From c6191cea564fd8298ab2de1ad886d8b653d889c0 Mon Sep 17 00:00:00 2001 From: No Author Date: Wed, 23 Feb 2000 23:01:34 +0000 Subject: [PATCH] This commit was manufactured by cvs2svn to create tag 'APACHE_1_3_12'. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/tags/1.3@84665 13f79535-47bb-0310-9956-ffa450edef68 --- APACHE_1_3_12/.cvsignore | 3 + APACHE_1_3_12/ABOUT_APACHE | 240 + APACHE_1_3_12/Announcement | 78 + APACHE_1_3_12/INSTALL | 543 ++ APACHE_1_3_12/KEYS | 664 ++ APACHE_1_3_12/LICENSE | 59 + APACHE_1_3_12/Makefile.tmpl | 612 ++ APACHE_1_3_12/README | 63 + APACHE_1_3_12/README.NT | 91 + APACHE_1_3_12/README.configure | 288 + APACHE_1_3_12/RULES.CVS | 13 + APACHE_1_3_12/STATUS | 577 ++ APACHE_1_3_12/WARNING-NT.TXT | 8 + APACHE_1_3_12/cgi-bin/printenv | 13 + APACHE_1_3_12/cgi-bin/test-cgi | 31 + APACHE_1_3_12/conf/.cvsignore | 4 + APACHE_1_3_12/conf/access.conf-dist | 8 + APACHE_1_3_12/conf/access.conf-dist-win | 8 + APACHE_1_3_12/conf/highperformance.conf-dist | 52 + APACHE_1_3_12/conf/httpd.conf-dist | 924 +++ APACHE_1_3_12/conf/httpd.conf-dist-win | 806 ++ APACHE_1_3_12/conf/httpd.conf-dist.nw | 814 ++ APACHE_1_3_12/conf/magic | 371 + APACHE_1_3_12/conf/mime.types | 373 + APACHE_1_3_12/conf/srm.conf-dist | 8 + APACHE_1_3_12/conf/srm.conf-dist-win | 8 + APACHE_1_3_12/config.layout | 192 + APACHE_1_3_12/configure | 1594 ++++ APACHE_1_3_12/htdocs/apache_pb.gif | Bin 0 -> 2326 bytes APACHE_1_3_12/htdocs/index.html.ca | 51 + APACHE_1_3_12/htdocs/index.html.cz | 51 + APACHE_1_3_12/htdocs/index.html.de | 61 + APACHE_1_3_12/htdocs/index.html.dk | 47 + APACHE_1_3_12/htdocs/index.html.ee | 53 + APACHE_1_3_12/htdocs/index.html.en | 38 + APACHE_1_3_12/htdocs/index.html.es | 51 + APACHE_1_3_12/htdocs/index.html.fr | 53 + APACHE_1_3_12/htdocs/index.html.it | 38 + APACHE_1_3_12/htdocs/index.html.ja.jis | 42 + APACHE_1_3_12/htdocs/index.html.lu | 37 + APACHE_1_3_12/htdocs/index.html.nl | 54 + APACHE_1_3_12/htdocs/index.html.po.iso-pl | 54 + APACHE_1_3_12/htdocs/index.html.pt | 42 + APACHE_1_3_12/htdocs/index.html.pt-br | 55 + APACHE_1_3_12/htdocs/index.html.se | 43 + APACHE_1_3_12/htdocs/manual/LICENSE | 59 + APACHE_1_3_12/htdocs/manual/bind.html | 135 + APACHE_1_3_12/htdocs/manual/cgi_path.html | 93 + .../htdocs/manual/content-negotiation.html | 588 ++ APACHE_1_3_12/htdocs/manual/custom-error.html | 177 + APACHE_1_3_12/htdocs/manual/dns-caveats.html | 189 + APACHE_1_3_12/htdocs/manual/dso.html | 393 + APACHE_1_3_12/htdocs/manual/ebcdic.html | 497 ++ APACHE_1_3_12/htdocs/manual/env.html | 64 + APACHE_1_3_12/htdocs/manual/expand.pl | 104 + APACHE_1_3_12/htdocs/manual/footer.html | 6 + APACHE_1_3_12/htdocs/manual/handler.html | 195 + APACHE_1_3_12/htdocs/manual/header.html | 6 + .../htdocs/manual/images/custom_errordocs.gif | Bin 0 -> 23291 bytes APACHE_1_3_12/htdocs/manual/images/home.gif | Bin 0 -> 1465 bytes APACHE_1_3_12/htdocs/manual/images/index.gif | Bin 0 -> 1540 bytes .../htdocs/manual/images/mod_rewrite_fig1.fig | 60 + .../htdocs/manual/images/mod_rewrite_fig1.gif | Bin 0 -> 3525 bytes .../htdocs/manual/images/mod_rewrite_fig2.fig | 50 + .../htdocs/manual/images/mod_rewrite_fig2.gif | Bin 0 -> 2553 bytes APACHE_1_3_12/htdocs/manual/images/sub.gif | Bin 0 -> 6083 bytes APACHE_1_3_12/htdocs/manual/index.html | 65 + APACHE_1_3_12/htdocs/manual/install-tpf.html | 334 + APACHE_1_3_12/htdocs/manual/install.html | 270 + APACHE_1_3_12/htdocs/manual/invoking.html | 220 + APACHE_1_3_12/htdocs/manual/keepalive.html | 103 + APACHE_1_3_12/htdocs/manual/location.html | 68 + APACHE_1_3_12/htdocs/manual/man-template.html | 108 + APACHE_1_3_12/htdocs/manual/misc/API.html | 1153 +++ APACHE_1_3_12/htdocs/manual/misc/FAQ-A.html | 298 + APACHE_1_3_12/htdocs/manual/misc/FAQ-B.html | 447 + APACHE_1_3_12/htdocs/manual/misc/FAQ-C.html | 273 + APACHE_1_3_12/htdocs/manual/misc/FAQ-D.html | 396 + APACHE_1_3_12/htdocs/manual/misc/FAQ-E.html | 598 ++ APACHE_1_3_12/htdocs/manual/misc/FAQ-F.html | 524 ++ APACHE_1_3_12/htdocs/manual/misc/FAQ-G.html | 371 + APACHE_1_3_12/htdocs/manual/misc/FAQ-H.html | 265 + APACHE_1_3_12/htdocs/manual/misc/FAQ-I.html | 238 + APACHE_1_3_12/htdocs/manual/misc/FAQ.html | 111 + .../htdocs/manual/misc/HTTP_Features.tsv | 142 + .../htdocs/manual/misc/client_block_api.html | 87 + .../htdocs/manual/misc/compat_notes.html | 126 + .../htdocs/manual/misc/custom_errordocs.html | 431 + .../htdocs/manual/misc/descriptors.html | 155 + .../htdocs/manual/misc/fin_wait_2.html | 324 + APACHE_1_3_12/htdocs/manual/misc/footer.html | 8 + APACHE_1_3_12/htdocs/manual/misc/header.html | 6 + APACHE_1_3_12/htdocs/manual/misc/howto.html | 209 + APACHE_1_3_12/htdocs/manual/misc/index.html | 151 + .../manual/misc/known_client_problems.html | 305 + APACHE_1_3_12/htdocs/manual/misc/nopgp.html | 90 + .../htdocs/manual/misc/perf-bsd44.html | 254 + .../htdocs/manual/misc/perf-dec.html | 285 + APACHE_1_3_12/htdocs/manual/misc/perf-hp.html | 122 + .../htdocs/manual/misc/perf-tuning.html | 871 ++ APACHE_1_3_12/htdocs/manual/misc/perf.html | 175 + .../htdocs/manual/misc/rewriteguide.html | 1906 +++++ .../htdocs/manual/misc/security_tips.html | 231 + .../htdocs/manual/misc/vif-info.html | 399 + .../htdocs/manual/misc/windoz_keepalive.html | 50 + APACHE_1_3_12/htdocs/manual/mod/core.html | 3366 ++++++++ .../htdocs/manual/mod/directive-dict.html | 265 + .../htdocs/manual/mod/directives.html | 231 + APACHE_1_3_12/htdocs/manual/mod/footer.html | 8 + APACHE_1_3_12/htdocs/manual/mod/header.html | 6 + APACHE_1_3_12/htdocs/manual/mod/index.html | 124 + .../htdocs/manual/mod/mod_access.html | 316 + .../htdocs/manual/mod/mod_actions.html | 132 + .../htdocs/manual/mod/mod_alias.html | 405 + APACHE_1_3_12/htdocs/manual/mod/mod_asis.html | 68 + APACHE_1_3_12/htdocs/manual/mod/mod_auth.html | 214 + .../htdocs/manual/mod/mod_auth_anon.html | 317 + .../htdocs/manual/mod/mod_auth_db.html | 220 + .../htdocs/manual/mod/mod_auth_dbm.html | 210 + .../htdocs/manual/mod/mod_auth_digest.html | 416 + .../htdocs/manual/mod/mod_autoindex.html | 851 ++ .../htdocs/manual/mod/mod_browser.html | 120 + .../htdocs/manual/mod/mod_cern_meta.html | 143 + APACHE_1_3_12/htdocs/manual/mod/mod_cgi.html | 216 + .../htdocs/manual/mod/mod_cookies.html | 59 + .../htdocs/manual/mod/mod_digest.html | 80 + APACHE_1_3_12/htdocs/manual/mod/mod_dir.html | 103 + APACHE_1_3_12/htdocs/manual/mod/mod_dld.html | 108 + APACHE_1_3_12/htdocs/manual/mod/mod_dll.html | 151 + APACHE_1_3_12/htdocs/manual/mod/mod_env.html | 137 + .../htdocs/manual/mod/mod_example.html | 168 + .../htdocs/manual/mod/mod_expires.html | 327 + .../htdocs/manual/mod/mod_headers.html | 121 + APACHE_1_3_12/htdocs/manual/mod/mod_imap.html | 329 + .../htdocs/manual/mod/mod_include.html | 443 + APACHE_1_3_12/htdocs/manual/mod/mod_info.html | 113 + .../htdocs/manual/mod/mod_isapi.html | 73 + .../htdocs/manual/mod/mod_log_agent.html | 77 + .../htdocs/manual/mod/mod_log_common.html | 118 + .../htdocs/manual/mod/mod_log_config.html | 456 ++ .../htdocs/manual/mod/mod_log_referer.html | 117 + APACHE_1_3_12/htdocs/manual/mod/mod_mime.html | 598 ++ .../htdocs/manual/mod/mod_mime_magic.html | 275 + .../htdocs/manual/mod/mod_mmap_static.html | 142 + .../htdocs/manual/mod/mod_negotiation.html | 201 + .../htdocs/manual/mod/mod_proxy.html | 1162 +++ .../htdocs/manual/mod/mod_rewrite.html | 1867 +++++ .../htdocs/manual/mod/mod_setenvif.html | 398 + APACHE_1_3_12/htdocs/manual/mod/mod_so.html | 164 + .../htdocs/manual/mod/mod_speling.html | 122 + .../htdocs/manual/mod/mod_status.html | 131 + .../htdocs/manual/mod/mod_unique_id.html | 180 + .../htdocs/manual/mod/mod_userdir.html | 123 + .../htdocs/manual/mod/mod_usertrack.html | 199 + .../htdocs/manual/mod/mod_vhost_alias.html | 307 + APACHE_1_3_12/htdocs/manual/multilogs.html | 134 + APACHE_1_3_12/htdocs/manual/netware.html | 278 + .../htdocs/manual/new_features_1_0.html | 131 + .../htdocs/manual/new_features_1_1.html | 228 + .../htdocs/manual/new_features_1_2.html | 210 + .../htdocs/manual/new_features_1_3.html | 693 ++ .../htdocs/manual/process-model.html | 68 + APACHE_1_3_12/htdocs/manual/readme-tpf.html | 208 + .../htdocs/manual/search/manual-index.cgi | 246 + APACHE_1_3_12/htdocs/manual/sections.html | 170 + APACHE_1_3_12/htdocs/manual/sourcereorg.html | 300 + APACHE_1_3_12/htdocs/manual/stopping.html | 183 + APACHE_1_3_12/htdocs/manual/suexec.html | 518 ++ APACHE_1_3_12/htdocs/manual/suexec_1_2.html | 191 + APACHE_1_3_12/htdocs/manual/unixware.html | 62 + .../htdocs/manual/upgrading_to_1_3.html | 302 + .../htdocs/manual/vhosts/details.html | 373 + .../htdocs/manual/vhosts/details_1_2.html | 396 + .../htdocs/manual/vhosts/examples.html | 512 ++ .../htdocs/manual/vhosts/fd-limits.html | 59 + .../htdocs/manual/vhosts/footer.html | 8 + .../htdocs/manual/vhosts/header.html | 6 + APACHE_1_3_12/htdocs/manual/vhosts/host.html | 172 + APACHE_1_3_12/htdocs/manual/vhosts/index.html | 65 + .../htdocs/manual/vhosts/ip-based.html | 141 + APACHE_1_3_12/htdocs/manual/vhosts/mass.html | 403 + .../htdocs/manual/vhosts/name-based.html | 164 + .../htdocs/manual/vhosts/vhosts-in-depth.html | 396 + .../htdocs/manual/vhosts/virtual-host.html | 208 + APACHE_1_3_12/htdocs/manual/windows.html | 572 ++ APACHE_1_3_12/icons/README | 158 + APACHE_1_3_12/icons/a.gif | Bin 0 -> 246 bytes APACHE_1_3_12/icons/alert.black.gif | Bin 0 -> 242 bytes APACHE_1_3_12/icons/alert.red.gif | Bin 0 -> 247 bytes APACHE_1_3_12/icons/apache_pb.gif | Bin 0 -> 2326 bytes APACHE_1_3_12/icons/back.gif | Bin 0 -> 216 bytes APACHE_1_3_12/icons/ball.gray.gif | Bin 0 -> 233 bytes APACHE_1_3_12/icons/ball.red.gif | Bin 0 -> 205 bytes APACHE_1_3_12/icons/binary.gif | Bin 0 -> 246 bytes APACHE_1_3_12/icons/binhex.gif | Bin 0 -> 246 bytes APACHE_1_3_12/icons/blank.gif | Bin 0 -> 148 bytes APACHE_1_3_12/icons/bomb.gif | Bin 0 -> 308 bytes APACHE_1_3_12/icons/box1.gif | Bin 0 -> 251 bytes APACHE_1_3_12/icons/box2.gif | Bin 0 -> 268 bytes APACHE_1_3_12/icons/broken.gif | Bin 0 -> 247 bytes APACHE_1_3_12/icons/burst.gif | Bin 0 -> 235 bytes APACHE_1_3_12/icons/c.gif | Bin 0 -> 242 bytes APACHE_1_3_12/icons/comp.blue.gif | Bin 0 -> 251 bytes APACHE_1_3_12/icons/comp.gray.gif | Bin 0 -> 246 bytes APACHE_1_3_12/icons/compressed.gif | Bin 0 -> 1038 bytes APACHE_1_3_12/icons/continued.gif | Bin 0 -> 214 bytes APACHE_1_3_12/icons/dir.gif | Bin 0 -> 225 bytes APACHE_1_3_12/icons/down.gif | Bin 0 -> 163 bytes APACHE_1_3_12/icons/dvi.gif | Bin 0 -> 238 bytes APACHE_1_3_12/icons/f.gif | Bin 0 -> 236 bytes APACHE_1_3_12/icons/folder.gif | Bin 0 -> 225 bytes APACHE_1_3_12/icons/folder.open.gif | Bin 0 -> 242 bytes APACHE_1_3_12/icons/folder.sec.gif | Bin 0 -> 243 bytes APACHE_1_3_12/icons/forward.gif | Bin 0 -> 219 bytes APACHE_1_3_12/icons/generic.gif | Bin 0 -> 221 bytes APACHE_1_3_12/icons/generic.red.gif | Bin 0 -> 220 bytes APACHE_1_3_12/icons/generic.sec.gif | Bin 0 -> 249 bytes APACHE_1_3_12/icons/hand.right.gif | Bin 0 -> 217 bytes APACHE_1_3_12/icons/hand.up.gif | Bin 0 -> 223 bytes APACHE_1_3_12/icons/icon.sheet.gif | Bin 0 -> 11977 bytes APACHE_1_3_12/icons/image1.gif | Bin 0 -> 274 bytes APACHE_1_3_12/icons/image2.gif | Bin 0 -> 309 bytes APACHE_1_3_12/icons/image3.gif | Bin 0 -> 286 bytes APACHE_1_3_12/icons/index.gif | Bin 0 -> 268 bytes APACHE_1_3_12/icons/layout.gif | Bin 0 -> 276 bytes APACHE_1_3_12/icons/left.gif | Bin 0 -> 172 bytes APACHE_1_3_12/icons/link.gif | Bin 0 -> 249 bytes APACHE_1_3_12/icons/movie.gif | Bin 0 -> 243 bytes APACHE_1_3_12/icons/p.gif | Bin 0 -> 237 bytes APACHE_1_3_12/icons/patch.gif | Bin 0 -> 251 bytes APACHE_1_3_12/icons/pdf.gif | Bin 0 -> 249 bytes APACHE_1_3_12/icons/pie0.gif | Bin 0 -> 188 bytes APACHE_1_3_12/icons/pie1.gif | Bin 0 -> 198 bytes APACHE_1_3_12/icons/pie2.gif | Bin 0 -> 198 bytes APACHE_1_3_12/icons/pie3.gif | Bin 0 -> 191 bytes APACHE_1_3_12/icons/pie4.gif | Bin 0 -> 193 bytes APACHE_1_3_12/icons/pie5.gif | Bin 0 -> 189 bytes APACHE_1_3_12/icons/pie6.gif | Bin 0 -> 186 bytes APACHE_1_3_12/icons/pie7.gif | Bin 0 -> 185 bytes APACHE_1_3_12/icons/pie8.gif | Bin 0 -> 173 bytes APACHE_1_3_12/icons/portal.gif | Bin 0 -> 254 bytes APACHE_1_3_12/icons/ps.gif | Bin 0 -> 244 bytes APACHE_1_3_12/icons/quill.gif | Bin 0 -> 267 bytes APACHE_1_3_12/icons/right.gif | Bin 0 -> 172 bytes APACHE_1_3_12/icons/screw1.gif | Bin 0 -> 258 bytes APACHE_1_3_12/icons/screw2.gif | Bin 0 -> 263 bytes APACHE_1_3_12/icons/script.gif | Bin 0 -> 242 bytes APACHE_1_3_12/icons/small/README.txt | 6 + APACHE_1_3_12/icons/small/back.gif | Bin 0 -> 129 bytes APACHE_1_3_12/icons/small/binary.gif | Bin 0 -> 134 bytes APACHE_1_3_12/icons/small/binhex.gif | Bin 0 -> 131 bytes APACHE_1_3_12/icons/small/blank.gif | Bin 0 -> 55 bytes APACHE_1_3_12/icons/small/broken.gif | Bin 0 -> 139 bytes APACHE_1_3_12/icons/small/burst.gif | Bin 0 -> 128 bytes APACHE_1_3_12/icons/small/comp1.gif | Bin 0 -> 130 bytes APACHE_1_3_12/icons/small/comp2.gif | Bin 0 -> 131 bytes APACHE_1_3_12/icons/small/compressed.gif | Bin 0 -> 128 bytes APACHE_1_3_12/icons/small/continued.gif | Bin 0 -> 114 bytes APACHE_1_3_12/icons/small/dir.gif | Bin 0 -> 132 bytes APACHE_1_3_12/icons/small/dir2.gif | Bin 0 -> 122 bytes APACHE_1_3_12/icons/small/doc.gif | Bin 0 -> 191 bytes APACHE_1_3_12/icons/small/forward.gif | Bin 0 -> 125 bytes APACHE_1_3_12/icons/small/generic.gif | Bin 0 -> 116 bytes APACHE_1_3_12/icons/small/generic2.gif | Bin 0 -> 127 bytes APACHE_1_3_12/icons/small/generic3.gif | Bin 0 -> 113 bytes APACHE_1_3_12/icons/small/image.gif | Bin 0 -> 126 bytes APACHE_1_3_12/icons/small/image2.gif | Bin 0 -> 138 bytes APACHE_1_3_12/icons/small/index.gif | Bin 0 -> 145 bytes APACHE_1_3_12/icons/small/key.gif | Bin 0 -> 187 bytes APACHE_1_3_12/icons/small/movie.gif | Bin 0 -> 134 bytes APACHE_1_3_12/icons/small/patch.gif | Bin 0 -> 182 bytes APACHE_1_3_12/icons/small/ps.gif | Bin 0 -> 184 bytes APACHE_1_3_12/icons/small/rainbow.gif | Bin 0 -> 3811 bytes APACHE_1_3_12/icons/small/sound.gif | Bin 0 -> 130 bytes APACHE_1_3_12/icons/small/sound2.gif | Bin 0 -> 119 bytes APACHE_1_3_12/icons/small/tar.gif | Bin 0 -> 132 bytes APACHE_1_3_12/icons/small/text.gif | Bin 0 -> 128 bytes APACHE_1_3_12/icons/small/transfer.gif | Bin 0 -> 124 bytes APACHE_1_3_12/icons/small/unknown.gif | Bin 0 -> 131 bytes APACHE_1_3_12/icons/small/uu.gif | Bin 0 -> 125 bytes APACHE_1_3_12/icons/sound1.gif | Bin 0 -> 248 bytes APACHE_1_3_12/icons/sound2.gif | Bin 0 -> 221 bytes APACHE_1_3_12/icons/sphere1.gif | Bin 0 -> 285 bytes APACHE_1_3_12/icons/sphere2.gif | Bin 0 -> 264 bytes APACHE_1_3_12/icons/tar.gif | Bin 0 -> 219 bytes APACHE_1_3_12/icons/tex.gif | Bin 0 -> 251 bytes APACHE_1_3_12/icons/text.gif | Bin 0 -> 229 bytes APACHE_1_3_12/icons/transfer.gif | Bin 0 -> 242 bytes APACHE_1_3_12/icons/unknown.gif | Bin 0 -> 245 bytes APACHE_1_3_12/icons/up.gif | Bin 0 -> 164 bytes APACHE_1_3_12/icons/uu.gif | Bin 0 -> 236 bytes APACHE_1_3_12/icons/uuencoded.gif | Bin 0 -> 236 bytes APACHE_1_3_12/icons/world1.gif | Bin 0 -> 228 bytes APACHE_1_3_12/icons/world2.gif | Bin 0 -> 261 bytes APACHE_1_3_12/logs/.cvsignore | 1 + APACHE_1_3_12/src/.cvsignore | 21 + APACHE_1_3_12/src/.gdbinit | 28 + APACHE_1_3_12/src/Apache.dsp | 109 + APACHE_1_3_12/src/Apache.mak | 230 + APACHE_1_3_12/src/ApacheCore.def | 362 + APACHE_1_3_12/src/ApacheCore.dsp | 405 + APACHE_1_3_12/src/ApacheCore.mak | 2558 ++++++ APACHE_1_3_12/src/ApacheCoreOS2.def | 368 + APACHE_1_3_12/src/ApacheNW.mcp.gz | Bin 0 -> 76780 bytes APACHE_1_3_12/src/BUILD.NOTES | 37 + APACHE_1_3_12/src/CHANGES | 7269 +++++++++++++++++ APACHE_1_3_12/src/Configuration.tmpl | 438 + APACHE_1_3_12/src/Configure | 2411 ++++++ APACHE_1_3_12/src/INDENT | 140 + APACHE_1_3_12/src/INSTALL | 169 + APACHE_1_3_12/src/Makefile.nt | 158 + APACHE_1_3_12/src/Makefile.tmpl | 134 + APACHE_1_3_12/src/Makefile_win32.txt | 136 + APACHE_1_3_12/src/Makefile_win32_debug.txt | 136 + APACHE_1_3_12/src/PORTING | 381 + APACHE_1_3_12/src/README | 147 + APACHE_1_3_12/src/README.EBCDIC | 99 + APACHE_1_3_12/src/ap/.cvsignore | 2 + APACHE_1_3_12/src/ap/.indent.pro | 54 + APACHE_1_3_12/src/ap/Makefile.tmpl | 78 + APACHE_1_3_12/src/ap/ap.dsp | 122 + APACHE_1_3_12/src/ap/ap.mak | 610 ++ APACHE_1_3_12/src/ap/ap_base64.c | 272 + APACHE_1_3_12/src/ap/ap_checkpass.c | 111 + APACHE_1_3_12/src/ap/ap_cpystrn.c | 93 + APACHE_1_3_12/src/ap/ap_execve.c | 390 + APACHE_1_3_12/src/ap/ap_fnmatch.c | 238 + APACHE_1_3_12/src/ap/ap_getpass.c | 196 + APACHE_1_3_12/src/ap/ap_md5c.c | 583 ++ APACHE_1_3_12/src/ap/ap_sha1.c | 383 + APACHE_1_3_12/src/ap/ap_signal.c | 83 + APACHE_1_3_12/src/ap/ap_slack.c | 116 + APACHE_1_3_12/src/ap/ap_snprintf.c | 1186 +++ APACHE_1_3_12/src/buildmark.c | 70 + APACHE_1_3_12/src/helpers/CutRule | 8 + APACHE_1_3_12/src/helpers/GuessCodeset | 15 + APACHE_1_3_12/src/helpers/GuessOS | 340 + APACHE_1_3_12/src/helpers/MakeEtags | 39 + APACHE_1_3_12/src/helpers/MakeLint | 31 + APACHE_1_3_12/src/helpers/PrintPath | 105 + APACHE_1_3_12/src/helpers/TestCompile | 232 + APACHE_1_3_12/src/helpers/binbuild.sh | 300 + APACHE_1_3_12/src/helpers/buildinfo.sh | 160 + APACHE_1_3_12/src/helpers/checkheader.sh | 35 + APACHE_1_3_12/src/helpers/dummy.c | 12 + APACHE_1_3_12/src/helpers/find-dbm-lib | 54 + APACHE_1_3_12/src/helpers/findcpp.sh | 73 + APACHE_1_3_12/src/helpers/fmn.sh | 49 + APACHE_1_3_12/src/helpers/fp2rp | 13 + APACHE_1_3_12/src/helpers/getuid.sh | 65 + APACHE_1_3_12/src/helpers/install.sh | 112 + APACHE_1_3_12/src/helpers/mfhead | 8 + APACHE_1_3_12/src/helpers/mkdir.sh | 35 + APACHE_1_3_12/src/helpers/mkshadow.sh | 110 + APACHE_1_3_12/src/helpers/ppl.sh | 55 + APACHE_1_3_12/src/helpers/slo.sh | 178 + APACHE_1_3_12/src/include/.cvsignore | 1 + APACHE_1_3_12/src/include/.indent.pro | 54 + APACHE_1_3_12/src/include/alloc.h | 405 + APACHE_1_3_12/src/include/ap.h | 192 + APACHE_1_3_12/src/include/ap_compat.h | 428 + APACHE_1_3_12/src/include/ap_config.h | 1444 ++++ APACHE_1_3_12/src/include/ap_ctype.h | 90 + APACHE_1_3_12/src/include/ap_md5.h | 130 + APACHE_1_3_12/src/include/ap_mmn.h | 257 + APACHE_1_3_12/src/include/ap_sha1.h | 102 + APACHE_1_3_12/src/include/buff.h | 236 + APACHE_1_3_12/src/include/compat.h | 9 + APACHE_1_3_12/src/include/conf.h | 9 + APACHE_1_3_12/src/include/explain.h | 44 + APACHE_1_3_12/src/include/fnmatch.h | 64 + APACHE_1_3_12/src/include/hsregex.h | 89 + APACHE_1_3_12/src/include/http_conf_globals.h | 125 + APACHE_1_3_12/src/include/http_config.h | 414 + APACHE_1_3_12/src/include/http_core.h | 319 + APACHE_1_3_12/src/include/http_log.h | 162 + APACHE_1_3_12/src/include/http_main.h | 174 + APACHE_1_3_12/src/include/http_protocol.h | 223 + APACHE_1_3_12/src/include/http_request.h | 117 + APACHE_1_3_12/src/include/http_vhost.h | 95 + APACHE_1_3_12/src/include/httpd.h | 1186 +++ APACHE_1_3_12/src/include/multithread.h | 69 + APACHE_1_3_12/src/include/rfc1413.h | 71 + APACHE_1_3_12/src/include/scoreboard.h | 207 + APACHE_1_3_12/src/include/util_date.h | 85 + APACHE_1_3_12/src/include/util_md5.h | 80 + APACHE_1_3_12/src/include/util_script.h | 91 + APACHE_1_3_12/src/include/util_uri.h | 128 + APACHE_1_3_12/src/lib/.cvsignore | 1 + APACHE_1_3_12/src/lib/expat-lite/.cvsignore | 1 + APACHE_1_3_12/src/lib/expat-lite/CHANGES | 65 + .../src/lib/expat-lite/Makefile.tmpl | 26 + APACHE_1_3_12/src/lib/expat-lite/asciitab.h | 62 + APACHE_1_3_12/src/lib/expat-lite/dllmain.c | 40 + APACHE_1_3_12/src/lib/expat-lite/expat.html | 73 + APACHE_1_3_12/src/lib/expat-lite/hashtable.c | 151 + APACHE_1_3_12/src/lib/expat-lite/hashtable.h | 69 + APACHE_1_3_12/src/lib/expat-lite/iasciitab.h | 63 + APACHE_1_3_12/src/lib/expat-lite/latin1tab.h | 62 + APACHE_1_3_12/src/lib/expat-lite/nametab.h | 150 + APACHE_1_3_12/src/lib/expat-lite/utf8tab.h | 63 + APACHE_1_3_12/src/lib/expat-lite/xmldef.h | 70 + APACHE_1_3_12/src/lib/expat-lite/xmlparse.c | 3256 ++++++++ APACHE_1_3_12/src/lib/expat-lite/xmlparse.def | 41 + APACHE_1_3_12/src/lib/expat-lite/xmlparse.dsp | 124 + APACHE_1_3_12/src/lib/expat-lite/xmlparse.h | 482 ++ APACHE_1_3_12/src/lib/expat-lite/xmlparse.mak | 289 + APACHE_1_3_12/src/lib/expat-lite/xmlrole.c | 1113 +++ APACHE_1_3_12/src/lib/expat-lite/xmlrole.h | 111 + APACHE_1_3_12/src/lib/expat-lite/xmltok.c | 1527 ++++ APACHE_1_3_12/src/lib/expat-lite/xmltok.def | 15 + APACHE_1_3_12/src/lib/expat-lite/xmltok.dsp | 160 + APACHE_1_3_12/src/lib/expat-lite/xmltok.h | 307 + APACHE_1_3_12/src/lib/expat-lite/xmltok.mak | 261 + .../src/lib/expat-lite/xmltok_impl.c | 1746 ++++ .../src/lib/expat-lite/xmltok_impl.h | 71 + APACHE_1_3_12/src/lib/expat-lite/xmltok_ns.c | 96 + APACHE_1_3_12/src/main/.cvsignore | 13 + APACHE_1_3_12/src/main/.indent.pro | 54 + APACHE_1_3_12/src/main/Makefile.tmpl | 165 + APACHE_1_3_12/src/main/alloc.c | 2707 ++++++ APACHE_1_3_12/src/main/buff.c | 1639 ++++ APACHE_1_3_12/src/main/gen_test_char.c | 62 + APACHE_1_3_12/src/main/gen_test_char.dsp | 105 + APACHE_1_3_12/src/main/gen_test_char.mak | 236 + APACHE_1_3_12/src/main/gen_uri_delims.c | 31 + APACHE_1_3_12/src/main/gen_uri_delims.dsp | 105 + APACHE_1_3_12/src/main/gen_uri_delims.mak | 204 + APACHE_1_3_12/src/main/http_config.c | 1646 ++++ APACHE_1_3_12/src/main/http_core.c | 3266 ++++++++ APACHE_1_3_12/src/main/http_log.c | 786 ++ APACHE_1_3_12/src/main/http_main.c | 7075 ++++++++++++++++ APACHE_1_3_12/src/main/http_protocol.c | 2886 +++++++ APACHE_1_3_12/src/main/http_request.c | 1375 ++++ APACHE_1_3_12/src/main/http_vhost.c | 948 +++ APACHE_1_3_12/src/main/rfc1413.c | 266 + APACHE_1_3_12/src/main/util.c | 2186 +++++ APACHE_1_3_12/src/main/util_date.c | 321 + APACHE_1_3_12/src/main/util_md5.c | 229 + APACHE_1_3_12/src/main/util_script.c | 1159 +++ APACHE_1_3_12/src/main/util_uri.c | 599 ++ APACHE_1_3_12/src/modules/.cvsignore | 1 + APACHE_1_3_12/src/modules/README | 34 + APACHE_1_3_12/src/modules/example/.cvsignore | 3 + APACHE_1_3_12/src/modules/example/.indent.pro | 54 + .../src/modules/example/Makefile.tmpl | 15 + APACHE_1_3_12/src/modules/example/README | 53 + .../src/modules/example/mod_example.c | 1149 +++ .../src/modules/experimental/.cvsignore | 3 + .../src/modules/experimental/.indent.pro | 54 + .../src/modules/experimental/Makefile.tmpl | 23 + .../modules/experimental/mod_auth_digest.c | 2019 +++++ .../modules/experimental/mod_mmap_static.c | 395 + APACHE_1_3_12/src/modules/extra/.cvsignore | 7 + APACHE_1_3_12/src/modules/extra/.indent.pro | 54 + APACHE_1_3_12/src/modules/extra/Makefile.tmpl | 6 + APACHE_1_3_12/src/modules/proxy/.cvsignore | 12 + APACHE_1_3_12/src/modules/proxy/.indent.pro | 55 + .../src/modules/proxy/ApacheModuleProxy.dsp | 133 + .../src/modules/proxy/ApacheModuleProxy.mak | 549 ++ APACHE_1_3_12/src/modules/proxy/Makefile.OS2 | 6 + .../src/modules/proxy/Makefile.libdir | 4 + APACHE_1_3_12/src/modules/proxy/Makefile.tmpl | 113 + APACHE_1_3_12/src/modules/proxy/mod_proxy.c | 965 +++ APACHE_1_3_12/src/modules/proxy/mod_proxy.h | 320 + APACHE_1_3_12/src/modules/proxy/proxy_cache.c | 1200 +++ .../src/modules/proxy/proxy_connect.c | 288 + APACHE_1_3_12/src/modules/proxy/proxy_ftp.c | 1285 +++ APACHE_1_3_12/src/modules/proxy/proxy_http.c | 546 ++ APACHE_1_3_12/src/modules/proxy/proxy_util.c | 1292 +++ APACHE_1_3_12/src/modules/standard/.cvsignore | 6 + .../src/modules/standard/.indent.pro | 54 + .../src/modules/standard/Makefile.OS2 | 115 + .../src/modules/standard/Makefile.tmpl | 256 + .../src/modules/standard/mod_access.c | 410 + .../src/modules/standard/mod_actions.c | 290 + .../src/modules/standard/mod_alias.c | 418 + APACHE_1_3_12/src/modules/standard/mod_asis.c | 145 + APACHE_1_3_12/src/modules/standard/mod_auth.c | 333 + .../src/modules/standard/mod_auth_anon.c | 322 + .../src/modules/standard/mod_auth_db.c | 355 + .../src/modules/standard/mod_auth_db.module | 35 + .../src/modules/standard/mod_auth_dbm.c | 335 + .../src/modules/standard/mod_autoindex.c | 1774 ++++ .../src/modules/standard/mod_cern_meta.c | 405 + APACHE_1_3_12/src/modules/standard/mod_cgi.c | 609 ++ .../src/modules/standard/mod_digest.c | 399 + APACHE_1_3_12/src/modules/standard/mod_dir.c | 246 + APACHE_1_3_12/src/modules/standard/mod_env.c | 270 + .../src/modules/standard/mod_expires.c | 519 ++ .../src/modules/standard/mod_headers.c | 273 + APACHE_1_3_12/src/modules/standard/mod_imap.c | 919 +++ .../src/modules/standard/mod_include.c | 2559 ++++++ APACHE_1_3_12/src/modules/standard/mod_info.c | 703 ++ .../src/modules/standard/mod_log_agent.c | 188 + .../src/modules/standard/mod_log_config.c | 1180 +++ .../src/modules/standard/mod_log_referer.c | 229 + APACHE_1_3_12/src/modules/standard/mod_mime.c | 736 ++ .../src/modules/standard/mod_mime_magic.c | 2474 ++++++ .../src/modules/standard/mod_negotiation.c | 2748 +++++++ .../src/modules/standard/mod_rewrite.c | 4293 ++++++++++ .../src/modules/standard/mod_rewrite.h | 499 ++ .../src/modules/standard/mod_setenvif.c | 423 + APACHE_1_3_12/src/modules/standard/mod_so.c | 360 + .../src/modules/standard/mod_speling.c | 566 ++ .../src/modules/standard/mod_status.c | 777 ++ .../src/modules/standard/mod_unique_id.c | 400 + .../src/modules/standard/mod_userdir.c | 349 + .../src/modules/standard/mod_usertrack.c | 393 + .../src/modules/standard/mod_vhost_alias.c | 482 ++ APACHE_1_3_12/src/modules/test/.cvsignore | 3 + APACHE_1_3_12/src/modules/test/.indent.pro | 54 + APACHE_1_3_12/src/modules/test/Makefile.tmpl | 18 + APACHE_1_3_12/src/modules/test/README | 3 + APACHE_1_3_12/src/modules/test/mod_rndchunk.c | 179 + .../src/modules/test/mod_test_util_uri.c | 354 + APACHE_1_3_12/src/os/.indent.pro | 54 + APACHE_1_3_12/src/os/bs2000/.cvsignore | 1 + APACHE_1_3_12/src/os/bs2000/Makefile.tmpl | 84 + APACHE_1_3_12/src/os/bs2000/bs2login.c | 296 + APACHE_1_3_12/src/os/bs2000/ebcdic.c | 182 + APACHE_1_3_12/src/os/bs2000/ebcdic.h | 11 + APACHE_1_3_12/src/os/bs2000/os-inline.c | 31 + APACHE_1_3_12/src/os/bs2000/os.c | 104 + APACHE_1_3_12/src/os/bs2000/os.h | 51 + APACHE_1_3_12/src/os/mpeix/Makefile.tmpl | 50 + APACHE_1_3_12/src/os/mpeix/README | 5 + APACHE_1_3_12/src/os/mpeix/dlopen.c | 216 + APACHE_1_3_12/src/os/mpeix/gettimeofday.c | 116 + APACHE_1_3_12/src/os/mpeix/mpe_dl_stub.c | 1 + APACHE_1_3_12/src/os/mpeix/os-inline.c | 1 + APACHE_1_3_12/src/os/mpeix/os.c | 1 + APACHE_1_3_12/src/os/mpeix/os.h | 147 + APACHE_1_3_12/src/os/netware/Apache.def | 4 + APACHE_1_3_12/src/os/netware/ApacheCore.imp | 347 + APACHE_1_3_12/src/os/netware/ApacheCoreNW.def | 4 + .../src/os/netware/ApacheModuleAuthAnon.def | 2 + .../src/os/netware/ApacheModuleCERNMeta.def | 1 + .../src/os/netware/ApacheModuleDigest.def | 1 + .../src/os/netware/ApacheModuleExpires.def | 1 + .../src/os/netware/ApacheModuleHeaders.def | 1 + .../src/os/netware/ApacheModuleInfo.def | 2 + .../src/os/netware/ApacheModuleProxy.def | 1 + .../src/os/netware/ApacheModuleRewrite.def | 1 + .../src/os/netware/ApacheModuleSpeling.def | 2 + .../src/os/netware/ApacheModuleStatus.def | 1 + .../src/os/netware/ApacheModuleUserTrack.def | 1 + APACHE_1_3_12/src/os/netware/getopt.c | 161 + APACHE_1_3_12/src/os/netware/getopt.h | 10 + APACHE_1_3_12/src/os/netware/main_nlm.c | 10 + APACHE_1_3_12/src/os/netware/mod_nlm.c | 148 + APACHE_1_3_12/src/os/netware/modules.c | 70 + APACHE_1_3_12/src/os/netware/multithread.c | 102 + APACHE_1_3_12/src/os/netware/os.c | 124 + APACHE_1_3_12/src/os/netware/os.h | 143 + APACHE_1_3_12/src/os/netware/precomp.h | 11 + APACHE_1_3_12/src/os/netware/test_char.h | 21 + APACHE_1_3_12/src/os/netware/uri_delims.h | 16 + APACHE_1_3_12/src/os/os2/.cvsignore | 1 + APACHE_1_3_12/src/os/os2/Makefile.tmpl | 57 + APACHE_1_3_12/src/os/os2/os-inline.c | 34 + APACHE_1_3_12/src/os/os2/os.c | 63 + APACHE_1_3_12/src/os/os2/os.h | 52 + APACHE_1_3_12/src/os/os2/util_os2.c | 96 + APACHE_1_3_12/src/os/os390/Makefile.tmpl | 72 + APACHE_1_3_12/src/os/os390/README.os390 | 86 + APACHE_1_3_12/src/os/os390/ebcdic.c | 173 + APACHE_1_3_12/src/os/os390/ebcdic.h | 6 + APACHE_1_3_12/src/os/os390/os-inline.c | 31 + APACHE_1_3_12/src/os/os390/os.c | 103 + APACHE_1_3_12/src/os/os390/os.h | 40 + APACHE_1_3_12/src/os/os390/xebcdic.sh | 202 + APACHE_1_3_12/src/os/tpf/Makefile.tmpl | 42 + APACHE_1_3_12/src/os/tpf/TPFExport | 9 + APACHE_1_3_12/src/os/tpf/cgetop.c | 151 + APACHE_1_3_12/src/os/tpf/ebcdic.c | 170 + APACHE_1_3_12/src/os/tpf/ebcdic.h | 7 + APACHE_1_3_12/src/os/tpf/os-inline.c | 31 + APACHE_1_3_12/src/os/tpf/os.c | 664 ++ APACHE_1_3_12/src/os/tpf/os.h | 138 + APACHE_1_3_12/src/os/tpf/samples/linkdll.jcl | 155 + APACHE_1_3_12/src/os/tpf/samples/loadset.jcl | 41 + APACHE_1_3_12/src/os/unix/.cvsignore | 1 + APACHE_1_3_12/src/os/unix/Makefile.tmpl | 47 + APACHE_1_3_12/src/os/unix/os-aix-dso.c | 668 ++ APACHE_1_3_12/src/os/unix/os-inline.c | 31 + APACHE_1_3_12/src/os/unix/os.c | 184 + APACHE_1_3_12/src/os/unix/os.h | 150 + APACHE_1_3_12/src/os/win32/.cvsignore | 27 + .../src/os/win32/ApacheModuleAuthAnon.dsp | 113 + .../src/os/win32/ApacheModuleAuthAnon.mak | 241 + .../src/os/win32/ApacheModuleAuthDigest.dsp | 97 + .../src/os/win32/ApacheModuleAuthDigest.mak | 246 + .../src/os/win32/ApacheModuleCERNMeta.dsp | 113 + .../src/os/win32/ApacheModuleCERNMeta.mak | 239 + .../src/os/win32/ApacheModuleDigest.dsp | 113 + .../src/os/win32/ApacheModuleDigest.mak | 242 + .../src/os/win32/ApacheModuleExpires.dsp | 113 + .../src/os/win32/ApacheModuleExpires.mak | 234 + .../src/os/win32/ApacheModuleHeaders.dsp | 113 + .../src/os/win32/ApacheModuleHeaders.mak | 232 + .../src/os/win32/ApacheModuleInfo.dsp | 112 + .../src/os/win32/ApacheModuleInfo.mak | 211 + .../src/os/win32/ApacheModuleRewrite.dsp | 117 + .../src/os/win32/ApacheModuleRewrite.mak | 255 + .../src/os/win32/ApacheModuleSpeling.dsp | 113 + .../src/os/win32/ApacheModuleSpeling.mak | 236 + .../src/os/win32/ApacheModuleStatus.dsp | 113 + .../src/os/win32/ApacheModuleStatus.mak | 274 + .../src/os/win32/ApacheModuleUserTrack.dsp | 113 + .../src/os/win32/ApacheModuleUserTrack.mak | 235 + APACHE_1_3_12/src/os/win32/ApacheOS.dsp | 86 + APACHE_1_3_12/src/os/win32/ApacheOS.mak | 164 + APACHE_1_3_12/src/os/win32/MakeModuleMak.cpp | 59 + APACHE_1_3_12/src/os/win32/MakeModuleMak.mak | 195 + APACHE_1_3_12/src/os/win32/Module.mak.tmpl | 230 + APACHE_1_3_12/src/os/win32/apache.ico | Bin 0 -> 766 bytes APACHE_1_3_12/src/os/win32/apache.rc | 84 + APACHE_1_3_12/src/os/win32/getopt.c | 170 + APACHE_1_3_12/src/os/win32/getopt.h | 10 + .../src/os/win32/installer/README.TXT | 6 + .../src/os/win32/installer/apache.iwz | 995 +++ .../os/win32/installer/installdll/install.c | 666 ++ .../os/win32/installer/installdll/install.def | 6 + .../os/win32/installer/installdll/install.dsp | 107 + .../os/win32/installer/installdll/install.mak | 297 + .../installer/installdll/test/resource.h | 26 + .../os/win32/installer/installdll/test/test.c | 269 + .../win32/installer/installdll/test/test.def | 2 + .../win32/installer/installdll/test/test.dsp | 121 + .../os/win32/installer/installdll/test/test.h | 4 + .../win32/installer/installdll/test/test.ico | Bin 0 -> 766 bytes .../win32/installer/installdll/test/test.mak | 229 + .../win32/installer/installdll/test/test.rc | 155 + APACHE_1_3_12/src/os/win32/main_win32.c | 16 + APACHE_1_3_12/src/os/win32/mod_dll.c | 190 + APACHE_1_3_12/src/os/win32/mod_isapi.c | 569 ++ APACHE_1_3_12/src/os/win32/modules.c | 72 + APACHE_1_3_12/src/os/win32/multithread.c | 258 + APACHE_1_3_12/src/os/win32/os.c | 7 + APACHE_1_3_12/src/os/win32/os.h | 197 + APACHE_1_3_12/src/os/win32/passwd.c | 16 + APACHE_1_3_12/src/os/win32/passwd.h | 8 + APACHE_1_3_12/src/os/win32/readdir.c | 80 + APACHE_1_3_12/src/os/win32/readdir.h | 36 + APACHE_1_3_12/src/os/win32/registry.c | 471 ++ APACHE_1_3_12/src/os/win32/registry.h | 8 + APACHE_1_3_12/src/os/win32/resource.h | 17 + APACHE_1_3_12/src/os/win32/service.c | 431 + APACHE_1_3_12/src/os/win32/service.h | 17 + APACHE_1_3_12/src/os/win32/util_win32.c | 677 ++ APACHE_1_3_12/src/regex/.cvsignore | 6 + APACHE_1_3_12/src/regex/COPYRIGHT | 20 + APACHE_1_3_12/src/regex/Makefile.tmpl | 147 + APACHE_1_3_12/src/regex/README | 32 + APACHE_1_3_12/src/regex/WHATSNEW | 92 + APACHE_1_3_12/src/regex/cclass.h | 31 + APACHE_1_3_12/src/regex/cname.h | 102 + APACHE_1_3_12/src/regex/debug.c | 243 + APACHE_1_3_12/src/regex/engine.c | 1020 +++ APACHE_1_3_12/src/regex/engine.ih | 37 + APACHE_1_3_12/src/regex/main.c | 516 ++ APACHE_1_3_12/src/regex/mkh | 77 + APACHE_1_3_12/src/regex/regcomp.c | 1585 ++++ APACHE_1_3_12/src/regex/regcomp.ih | 50 + APACHE_1_3_12/src/regex/regerror.c | 124 + APACHE_1_3_12/src/regex/regerror.ih | 14 + APACHE_1_3_12/src/regex/regex.3 | 502 ++ APACHE_1_3_12/src/regex/regex.7 | 233 + APACHE_1_3_12/src/regex/regex.dsp | 114 + APACHE_1_3_12/src/regex/regex.mak | 266 + APACHE_1_3_12/src/regex/regex2.h | 146 + APACHE_1_3_12/src/regex/regexec.c | 141 + APACHE_1_3_12/src/regex/regfree.c | 38 + APACHE_1_3_12/src/regex/split.c | 318 + APACHE_1_3_12/src/regex/tests | 475 ++ APACHE_1_3_12/src/regex/utils.h | 22 + APACHE_1_3_12/src/support/.cvsignore | 11 + APACHE_1_3_12/src/support/.indent.pro | 54 + APACHE_1_3_12/src/support/Makefile.tmpl | 82 + APACHE_1_3_12/src/support/README | 62 + APACHE_1_3_12/src/support/SHA1/README.sha1 | 34 + .../src/support/SHA1/convert-sha1.pl | 36 + .../src/support/SHA1/htpasswd-sha1.pl | 22 + .../src/support/SHA1/ldif-sha1.example | 19 + APACHE_1_3_12/src/support/ab.8 | 215 + APACHE_1_3_12/src/support/ab.c | 1130 +++ APACHE_1_3_12/src/support/apachectl | 229 + APACHE_1_3_12/src/support/apachectl.8 | 133 + APACHE_1_3_12/src/support/apxs.8 | 464 ++ APACHE_1_3_12/src/support/apxs.pl | 655 ++ APACHE_1_3_12/src/support/dbmmanage | 189 + APACHE_1_3_12/src/support/dbmmanage.1 | 171 + APACHE_1_3_12/src/support/htdigest.1 | 97 + APACHE_1_3_12/src/support/htdigest.c | 300 + APACHE_1_3_12/src/support/htdigest.dsp | 103 + APACHE_1_3_12/src/support/htdigest.mak | 297 + APACHE_1_3_12/src/support/htdigest.mcp.gz | Bin 0 -> 10565 bytes APACHE_1_3_12/src/support/htpasswd.1 | 225 + APACHE_1_3_12/src/support/htpasswd.c | 589 ++ APACHE_1_3_12/src/support/htpasswd.dsp | 119 + APACHE_1_3_12/src/support/htpasswd.mak | 550 ++ APACHE_1_3_12/src/support/htpasswd.mcp.gz | Bin 0 -> 10067 bytes APACHE_1_3_12/src/support/httpd.8 | 211 + APACHE_1_3_12/src/support/httpd.exp | 415 + APACHE_1_3_12/src/support/log_server_status | 118 + APACHE_1_3_12/src/support/logresolve.8 | 87 + APACHE_1_3_12/src/support/logresolve.c | 351 + APACHE_1_3_12/src/support/logresolve.pl | 264 + APACHE_1_3_12/src/support/phf_abuse_log.cgi | 21 + APACHE_1_3_12/src/support/rotatelogs.8 | 83 + APACHE_1_3_12/src/support/rotatelogs.c | 82 + APACHE_1_3_12/src/support/split-logfile | 103 + APACHE_1_3_12/src/support/suexec.8 | 70 + APACHE_1_3_12/src/support/suexec.c | 593 ++ APACHE_1_3_12/src/support/suexec.h | 143 + APACHE_1_3_12/src/test/.cvsignore | 11 + APACHE_1_3_12/src/test/.indent.pro | 54 + APACHE_1_3_12/src/test/README | 3 + APACHE_1_3_12/src/test/check_chunked | 42 + APACHE_1_3_12/src/test/cls.c | 166 + APACHE_1_3_12/src/test/rename/Makefile | 21 + APACHE_1_3_12/src/test/rename/README | 59 + APACHE_1_3_12/src/test/rename/apapi.h | 259 + APACHE_1_3_12/src/test/rename/apapi.h.mk | 82 + APACHE_1_3_12/src/test/rename/apapi_compat.h | 525 ++ .../src/test/rename/apapi_compat.h.mk | 90 + APACHE_1_3_12/src/test/rename/compat.h | 393 + APACHE_1_3_12/src/test/rename/compat.h.mk | 59 + APACHE_1_3_12/src/test/rename/csubst/Makefile | 34 + APACHE_1_3_12/src/test/rename/csubst/csubst.c | 131 + APACHE_1_3_12/src/test/rename/csubst/lexer.c | 2235 +++++ APACHE_1_3_12/src/test/rename/csubst/lexer.l | 226 + APACHE_1_3_12/src/test/rename/csubst/tokens.h | 41 + APACHE_1_3_12/src/test/rename/csubst/util.c | 137 + APACHE_1_3_12/src/test/rename/csubst/util.h | 11 + APACHE_1_3_12/src/test/rename/rename.cf | 400 + .../src/test/rename/rename.cf.clean-api | 456 ++ .../src/test/rename/rename.cf.update | 55 + APACHE_1_3_12/src/test/rename/rename.pl | 89 + APACHE_1_3_12/src/test/tcpdumpscii.txt | 50 + APACHE_1_3_12/src/test/test-writev.c | 85 + APACHE_1_3_12/src/test/test_date.c | 180 + APACHE_1_3_12/src/test/test_find.c | 62 + APACHE_1_3_12/src/test/test_limits.c | 200 + APACHE_1_3_12/src/test/test_parser.c | 59 + APACHE_1_3_12/src/test/test_select.c | 30 + APACHE_1_3_12/src/test/time-sem.c | 572 ++ APACHE_1_3_12/src/test/vhtest/README | 53 + APACHE_1_3_12/src/test/vhtest/bin/test1 | 29 + APACHE_1_3_12/src/test/vhtest/bin/test1d | 29 + APACHE_1_3_12/src/test/vhtest/bin/test2 | 45 + APACHE_1_3_12/src/test/vhtest/bin/test2d | 45 + APACHE_1_3_12/src/test/vhtest/bin/test3 | 18 + APACHE_1_3_12/src/test/vhtest/bin/test4 | 13 + APACHE_1_3_12/src/test/vhtest/bin/test5 | 31 + APACHE_1_3_12/src/test/vhtest/bin/test6 | 0 APACHE_1_3_12/src/test/vhtest/bin/vhget | 74 + .../src/test/vhtest/conf/common.conf | 24 + APACHE_1_3_12/src/test/vhtest/conf/mime.types | 103 + APACHE_1_3_12/src/test/vhtest/conf/test1.conf | 28 + .../src/test/vhtest/conf/test1d.conf | 33 + APACHE_1_3_12/src/test/vhtest/conf/test2.conf | 35 + .../src/test/vhtest/conf/test2d.conf | 45 + APACHE_1_3_12/src/test/vhtest/conf/test3.conf | 34 + APACHE_1_3_12/src/test/vhtest/conf/test4.conf | 18 + APACHE_1_3_12/src/test/vhtest/conf/test5.conf | 44 + APACHE_1_3_12/src/test/vhtest/conf/test6.conf | 42 + .../test/vhtest/docroot/default1/vhost.txt | 1 + .../test/vhtest/docroot/default2/vhost.txt | 1 + .../test/vhtest/docroot/default3/vhost.txt | 1 + .../src/test/vhtest/docroot/main/vhost.txt | 1 + .../src/test/vhtest/docroot/vhost1/vhost.txt | 1 + .../src/test/vhtest/docroot/vhost2/vhost.txt | 1 + .../src/test/vhtest/docroot/vhost3/vhost.txt | 1 + .../src/test/vhtest/docroot/vhost4/vhost.txt | 1 + .../src/test/vhtest/docroot/vhost5/vhost.txt | 1 + APACHE_1_3_12/src/test/vhtest/logs/.cvsignore | 1 + APACHE_1_3_12/src/test/vhtest/runtest | 42 + APACHE_1_3_12/src/test/zb.c | 567 ++ 780 files changed, 194896 insertions(+) create mode 100644 APACHE_1_3_12/.cvsignore create mode 100644 APACHE_1_3_12/ABOUT_APACHE create mode 100644 APACHE_1_3_12/Announcement create mode 100644 APACHE_1_3_12/INSTALL create mode 100644 APACHE_1_3_12/KEYS create mode 100644 APACHE_1_3_12/LICENSE create mode 100644 APACHE_1_3_12/Makefile.tmpl create mode 100644 APACHE_1_3_12/README create mode 100644 APACHE_1_3_12/README.NT create mode 100644 APACHE_1_3_12/README.configure create mode 100644 APACHE_1_3_12/RULES.CVS create mode 100644 APACHE_1_3_12/STATUS create mode 100644 APACHE_1_3_12/WARNING-NT.TXT create mode 100644 APACHE_1_3_12/cgi-bin/printenv create mode 100644 APACHE_1_3_12/cgi-bin/test-cgi create mode 100644 APACHE_1_3_12/conf/.cvsignore create mode 100644 APACHE_1_3_12/conf/access.conf-dist create mode 100644 APACHE_1_3_12/conf/access.conf-dist-win create mode 100644 APACHE_1_3_12/conf/highperformance.conf-dist create mode 100644 APACHE_1_3_12/conf/httpd.conf-dist create mode 100644 APACHE_1_3_12/conf/httpd.conf-dist-win create mode 100644 APACHE_1_3_12/conf/httpd.conf-dist.nw create mode 100644 APACHE_1_3_12/conf/magic create mode 100644 APACHE_1_3_12/conf/mime.types create mode 100644 APACHE_1_3_12/conf/srm.conf-dist create mode 100644 APACHE_1_3_12/conf/srm.conf-dist-win create mode 100644 APACHE_1_3_12/config.layout create mode 100755 APACHE_1_3_12/configure create mode 100644 APACHE_1_3_12/htdocs/apache_pb.gif create mode 100644 APACHE_1_3_12/htdocs/index.html.ca create mode 100644 APACHE_1_3_12/htdocs/index.html.cz create mode 100644 APACHE_1_3_12/htdocs/index.html.de create mode 100644 APACHE_1_3_12/htdocs/index.html.dk create mode 100644 APACHE_1_3_12/htdocs/index.html.ee create mode 100644 APACHE_1_3_12/htdocs/index.html.en create mode 100644 APACHE_1_3_12/htdocs/index.html.es create mode 100644 APACHE_1_3_12/htdocs/index.html.fr create mode 100644 APACHE_1_3_12/htdocs/index.html.it create mode 100644 APACHE_1_3_12/htdocs/index.html.ja.jis create mode 100644 APACHE_1_3_12/htdocs/index.html.lu create mode 100644 APACHE_1_3_12/htdocs/index.html.nl create mode 100644 APACHE_1_3_12/htdocs/index.html.po.iso-pl create mode 100644 APACHE_1_3_12/htdocs/index.html.pt create mode 100755 APACHE_1_3_12/htdocs/index.html.pt-br create mode 100644 APACHE_1_3_12/htdocs/index.html.se create mode 100644 APACHE_1_3_12/htdocs/manual/LICENSE create mode 100644 APACHE_1_3_12/htdocs/manual/bind.html create mode 100644 APACHE_1_3_12/htdocs/manual/cgi_path.html create mode 100644 APACHE_1_3_12/htdocs/manual/content-negotiation.html create mode 100644 APACHE_1_3_12/htdocs/manual/custom-error.html create mode 100644 APACHE_1_3_12/htdocs/manual/dns-caveats.html create mode 100644 APACHE_1_3_12/htdocs/manual/dso.html create mode 100644 APACHE_1_3_12/htdocs/manual/ebcdic.html create mode 100644 APACHE_1_3_12/htdocs/manual/env.html create mode 100755 APACHE_1_3_12/htdocs/manual/expand.pl create mode 100644 APACHE_1_3_12/htdocs/manual/footer.html create mode 100644 APACHE_1_3_12/htdocs/manual/handler.html create mode 100644 APACHE_1_3_12/htdocs/manual/header.html create mode 100644 APACHE_1_3_12/htdocs/manual/images/custom_errordocs.gif create mode 100644 APACHE_1_3_12/htdocs/manual/images/home.gif create mode 100644 APACHE_1_3_12/htdocs/manual/images/index.gif create mode 100644 APACHE_1_3_12/htdocs/manual/images/mod_rewrite_fig1.fig create mode 100644 APACHE_1_3_12/htdocs/manual/images/mod_rewrite_fig1.gif create mode 100644 APACHE_1_3_12/htdocs/manual/images/mod_rewrite_fig2.fig create mode 100644 APACHE_1_3_12/htdocs/manual/images/mod_rewrite_fig2.gif create mode 100644 APACHE_1_3_12/htdocs/manual/images/sub.gif create mode 100644 APACHE_1_3_12/htdocs/manual/index.html create mode 100644 APACHE_1_3_12/htdocs/manual/install-tpf.html create mode 100644 APACHE_1_3_12/htdocs/manual/install.html create mode 100644 APACHE_1_3_12/htdocs/manual/invoking.html create mode 100644 APACHE_1_3_12/htdocs/manual/keepalive.html create mode 100644 APACHE_1_3_12/htdocs/manual/location.html create mode 100644 APACHE_1_3_12/htdocs/manual/man-template.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/API.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/FAQ-A.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/FAQ-B.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/FAQ-C.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/FAQ-D.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/FAQ-E.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/FAQ-F.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/FAQ-G.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/FAQ-H.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/FAQ-I.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/FAQ.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/HTTP_Features.tsv create mode 100644 APACHE_1_3_12/htdocs/manual/misc/client_block_api.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/compat_notes.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/custom_errordocs.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/descriptors.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/fin_wait_2.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/footer.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/header.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/howto.html create mode 100755 APACHE_1_3_12/htdocs/manual/misc/index.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/known_client_problems.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/nopgp.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/perf-bsd44.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/perf-dec.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/perf-hp.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/perf-tuning.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/perf.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/rewriteguide.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/security_tips.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/vif-info.html create mode 100644 APACHE_1_3_12/htdocs/manual/misc/windoz_keepalive.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/core.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/directive-dict.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/directives.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/footer.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/header.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/index.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_access.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_actions.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_alias.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_asis.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_auth.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_auth_anon.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_auth_db.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_auth_dbm.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_auth_digest.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_autoindex.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_browser.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_cern_meta.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_cgi.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_cookies.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_digest.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_dir.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_dld.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_dll.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_env.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_example.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_expires.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_headers.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_imap.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_include.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_info.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_isapi.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_log_agent.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_log_common.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_log_config.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_log_referer.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_mime.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_mime_magic.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_mmap_static.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_negotiation.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_proxy.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_rewrite.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_setenvif.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_so.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_speling.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_status.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_unique_id.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_userdir.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_usertrack.html create mode 100644 APACHE_1_3_12/htdocs/manual/mod/mod_vhost_alias.html create mode 100644 APACHE_1_3_12/htdocs/manual/multilogs.html create mode 100644 APACHE_1_3_12/htdocs/manual/netware.html create mode 100644 APACHE_1_3_12/htdocs/manual/new_features_1_0.html create mode 100644 APACHE_1_3_12/htdocs/manual/new_features_1_1.html create mode 100644 APACHE_1_3_12/htdocs/manual/new_features_1_2.html create mode 100644 APACHE_1_3_12/htdocs/manual/new_features_1_3.html create mode 100644 APACHE_1_3_12/htdocs/manual/process-model.html create mode 100644 APACHE_1_3_12/htdocs/manual/readme-tpf.html create mode 100755 APACHE_1_3_12/htdocs/manual/search/manual-index.cgi create mode 100644 APACHE_1_3_12/htdocs/manual/sections.html create mode 100644 APACHE_1_3_12/htdocs/manual/sourcereorg.html create mode 100644 APACHE_1_3_12/htdocs/manual/stopping.html create mode 100644 APACHE_1_3_12/htdocs/manual/suexec.html create mode 100644 APACHE_1_3_12/htdocs/manual/suexec_1_2.html create mode 100644 APACHE_1_3_12/htdocs/manual/unixware.html create mode 100644 APACHE_1_3_12/htdocs/manual/upgrading_to_1_3.html create mode 100644 APACHE_1_3_12/htdocs/manual/vhosts/details.html create mode 100644 APACHE_1_3_12/htdocs/manual/vhosts/details_1_2.html create mode 100644 APACHE_1_3_12/htdocs/manual/vhosts/examples.html create mode 100644 APACHE_1_3_12/htdocs/manual/vhosts/fd-limits.html create mode 100644 APACHE_1_3_12/htdocs/manual/vhosts/footer.html create mode 100644 APACHE_1_3_12/htdocs/manual/vhosts/header.html create mode 100644 APACHE_1_3_12/htdocs/manual/vhosts/host.html create mode 100644 APACHE_1_3_12/htdocs/manual/vhosts/index.html create mode 100644 APACHE_1_3_12/htdocs/manual/vhosts/ip-based.html create mode 100644 APACHE_1_3_12/htdocs/manual/vhosts/mass.html create mode 100644 APACHE_1_3_12/htdocs/manual/vhosts/name-based.html create mode 100644 APACHE_1_3_12/htdocs/manual/vhosts/vhosts-in-depth.html create mode 100644 APACHE_1_3_12/htdocs/manual/vhosts/virtual-host.html create mode 100644 APACHE_1_3_12/htdocs/manual/windows.html create mode 100644 APACHE_1_3_12/icons/README create mode 100644 APACHE_1_3_12/icons/a.gif create mode 100644 APACHE_1_3_12/icons/alert.black.gif create mode 100644 APACHE_1_3_12/icons/alert.red.gif create mode 100644 APACHE_1_3_12/icons/apache_pb.gif create mode 100644 APACHE_1_3_12/icons/back.gif create mode 100644 APACHE_1_3_12/icons/ball.gray.gif create mode 100644 APACHE_1_3_12/icons/ball.red.gif create mode 100644 APACHE_1_3_12/icons/binary.gif create mode 100644 APACHE_1_3_12/icons/binhex.gif create mode 100644 APACHE_1_3_12/icons/blank.gif create mode 100644 APACHE_1_3_12/icons/bomb.gif create mode 100644 APACHE_1_3_12/icons/box1.gif create mode 100644 APACHE_1_3_12/icons/box2.gif create mode 100644 APACHE_1_3_12/icons/broken.gif create mode 100644 APACHE_1_3_12/icons/burst.gif create mode 100644 APACHE_1_3_12/icons/c.gif create mode 100644 APACHE_1_3_12/icons/comp.blue.gif create mode 100644 APACHE_1_3_12/icons/comp.gray.gif create mode 100644 APACHE_1_3_12/icons/compressed.gif create mode 100644 APACHE_1_3_12/icons/continued.gif create mode 100644 APACHE_1_3_12/icons/dir.gif create mode 100644 APACHE_1_3_12/icons/down.gif create mode 100644 APACHE_1_3_12/icons/dvi.gif create mode 100644 APACHE_1_3_12/icons/f.gif create mode 100644 APACHE_1_3_12/icons/folder.gif create mode 100644 APACHE_1_3_12/icons/folder.open.gif create mode 100644 APACHE_1_3_12/icons/folder.sec.gif create mode 100644 APACHE_1_3_12/icons/forward.gif create mode 100644 APACHE_1_3_12/icons/generic.gif create mode 100644 APACHE_1_3_12/icons/generic.red.gif create mode 100644 APACHE_1_3_12/icons/generic.sec.gif create mode 100644 APACHE_1_3_12/icons/hand.right.gif create mode 100644 APACHE_1_3_12/icons/hand.up.gif create mode 100644 APACHE_1_3_12/icons/icon.sheet.gif create mode 100644 APACHE_1_3_12/icons/image1.gif create mode 100644 APACHE_1_3_12/icons/image2.gif create mode 100644 APACHE_1_3_12/icons/image3.gif create mode 100644 APACHE_1_3_12/icons/index.gif create mode 100644 APACHE_1_3_12/icons/layout.gif create mode 100644 APACHE_1_3_12/icons/left.gif create mode 100644 APACHE_1_3_12/icons/link.gif create mode 100644 APACHE_1_3_12/icons/movie.gif create mode 100644 APACHE_1_3_12/icons/p.gif create mode 100644 APACHE_1_3_12/icons/patch.gif create mode 100644 APACHE_1_3_12/icons/pdf.gif create mode 100644 APACHE_1_3_12/icons/pie0.gif create mode 100644 APACHE_1_3_12/icons/pie1.gif create mode 100644 APACHE_1_3_12/icons/pie2.gif create mode 100644 APACHE_1_3_12/icons/pie3.gif create mode 100644 APACHE_1_3_12/icons/pie4.gif create mode 100644 APACHE_1_3_12/icons/pie5.gif create mode 100644 APACHE_1_3_12/icons/pie6.gif create mode 100644 APACHE_1_3_12/icons/pie7.gif create mode 100644 APACHE_1_3_12/icons/pie8.gif create mode 100644 APACHE_1_3_12/icons/portal.gif create mode 100644 APACHE_1_3_12/icons/ps.gif create mode 100644 APACHE_1_3_12/icons/quill.gif create mode 100644 APACHE_1_3_12/icons/right.gif create mode 100644 APACHE_1_3_12/icons/screw1.gif create mode 100644 APACHE_1_3_12/icons/screw2.gif create mode 100644 APACHE_1_3_12/icons/script.gif create mode 100644 APACHE_1_3_12/icons/small/README.txt create mode 100644 APACHE_1_3_12/icons/small/back.gif create mode 100644 APACHE_1_3_12/icons/small/binary.gif create mode 100644 APACHE_1_3_12/icons/small/binhex.gif create mode 100644 APACHE_1_3_12/icons/small/blank.gif create mode 100644 APACHE_1_3_12/icons/small/broken.gif create mode 100644 APACHE_1_3_12/icons/small/burst.gif create mode 100644 APACHE_1_3_12/icons/small/comp1.gif create mode 100644 APACHE_1_3_12/icons/small/comp2.gif create mode 100644 APACHE_1_3_12/icons/small/compressed.gif create mode 100644 APACHE_1_3_12/icons/small/continued.gif create mode 100644 APACHE_1_3_12/icons/small/dir.gif create mode 100644 APACHE_1_3_12/icons/small/dir2.gif create mode 100644 APACHE_1_3_12/icons/small/doc.gif create mode 100644 APACHE_1_3_12/icons/small/forward.gif create mode 100644 APACHE_1_3_12/icons/small/generic.gif create mode 100644 APACHE_1_3_12/icons/small/generic2.gif create mode 100644 APACHE_1_3_12/icons/small/generic3.gif create mode 100644 APACHE_1_3_12/icons/small/image.gif create mode 100644 APACHE_1_3_12/icons/small/image2.gif create mode 100644 APACHE_1_3_12/icons/small/index.gif create mode 100644 APACHE_1_3_12/icons/small/key.gif create mode 100644 APACHE_1_3_12/icons/small/movie.gif create mode 100644 APACHE_1_3_12/icons/small/patch.gif create mode 100644 APACHE_1_3_12/icons/small/ps.gif create mode 100644 APACHE_1_3_12/icons/small/rainbow.gif create mode 100644 APACHE_1_3_12/icons/small/sound.gif create mode 100644 APACHE_1_3_12/icons/small/sound2.gif create mode 100644 APACHE_1_3_12/icons/small/tar.gif create mode 100644 APACHE_1_3_12/icons/small/text.gif create mode 100644 APACHE_1_3_12/icons/small/transfer.gif create mode 100644 APACHE_1_3_12/icons/small/unknown.gif create mode 100644 APACHE_1_3_12/icons/small/uu.gif create mode 100644 APACHE_1_3_12/icons/sound1.gif create mode 100644 APACHE_1_3_12/icons/sound2.gif create mode 100644 APACHE_1_3_12/icons/sphere1.gif create mode 100644 APACHE_1_3_12/icons/sphere2.gif create mode 100644 APACHE_1_3_12/icons/tar.gif create mode 100644 APACHE_1_3_12/icons/tex.gif create mode 100644 APACHE_1_3_12/icons/text.gif create mode 100644 APACHE_1_3_12/icons/transfer.gif create mode 100644 APACHE_1_3_12/icons/unknown.gif create mode 100644 APACHE_1_3_12/icons/up.gif create mode 100644 APACHE_1_3_12/icons/uu.gif create mode 100644 APACHE_1_3_12/icons/uuencoded.gif create mode 100644 APACHE_1_3_12/icons/world1.gif create mode 100644 APACHE_1_3_12/icons/world2.gif create mode 100644 APACHE_1_3_12/logs/.cvsignore create mode 100644 APACHE_1_3_12/src/.cvsignore create mode 100644 APACHE_1_3_12/src/.gdbinit create mode 100644 APACHE_1_3_12/src/Apache.dsp create mode 100644 APACHE_1_3_12/src/Apache.mak create mode 100644 APACHE_1_3_12/src/ApacheCore.def create mode 100644 APACHE_1_3_12/src/ApacheCore.dsp create mode 100644 APACHE_1_3_12/src/ApacheCore.mak create mode 100644 APACHE_1_3_12/src/ApacheCoreOS2.def create mode 100644 APACHE_1_3_12/src/ApacheNW.mcp.gz create mode 100644 APACHE_1_3_12/src/BUILD.NOTES create mode 100644 APACHE_1_3_12/src/CHANGES create mode 100644 APACHE_1_3_12/src/Configuration.tmpl create mode 100755 APACHE_1_3_12/src/Configure create mode 100644 APACHE_1_3_12/src/INDENT create mode 100644 APACHE_1_3_12/src/INSTALL create mode 100644 APACHE_1_3_12/src/Makefile.nt create mode 100644 APACHE_1_3_12/src/Makefile.tmpl create mode 100644 APACHE_1_3_12/src/Makefile_win32.txt create mode 100644 APACHE_1_3_12/src/Makefile_win32_debug.txt create mode 100644 APACHE_1_3_12/src/PORTING create mode 100644 APACHE_1_3_12/src/README create mode 100644 APACHE_1_3_12/src/README.EBCDIC create mode 100644 APACHE_1_3_12/src/ap/.cvsignore create mode 100644 APACHE_1_3_12/src/ap/.indent.pro create mode 100644 APACHE_1_3_12/src/ap/Makefile.tmpl create mode 100644 APACHE_1_3_12/src/ap/ap.dsp create mode 100644 APACHE_1_3_12/src/ap/ap.mak create mode 100644 APACHE_1_3_12/src/ap/ap_base64.c create mode 100644 APACHE_1_3_12/src/ap/ap_checkpass.c create mode 100644 APACHE_1_3_12/src/ap/ap_cpystrn.c create mode 100644 APACHE_1_3_12/src/ap/ap_execve.c create mode 100644 APACHE_1_3_12/src/ap/ap_fnmatch.c create mode 100644 APACHE_1_3_12/src/ap/ap_getpass.c create mode 100644 APACHE_1_3_12/src/ap/ap_md5c.c create mode 100644 APACHE_1_3_12/src/ap/ap_sha1.c create mode 100644 APACHE_1_3_12/src/ap/ap_signal.c create mode 100644 APACHE_1_3_12/src/ap/ap_slack.c create mode 100644 APACHE_1_3_12/src/ap/ap_snprintf.c create mode 100644 APACHE_1_3_12/src/buildmark.c create mode 100755 APACHE_1_3_12/src/helpers/CutRule create mode 100755 APACHE_1_3_12/src/helpers/GuessCodeset create mode 100755 APACHE_1_3_12/src/helpers/GuessOS create mode 100755 APACHE_1_3_12/src/helpers/MakeEtags create mode 100644 APACHE_1_3_12/src/helpers/MakeLint create mode 100755 APACHE_1_3_12/src/helpers/PrintPath create mode 100755 APACHE_1_3_12/src/helpers/TestCompile create mode 100755 APACHE_1_3_12/src/helpers/binbuild.sh create mode 100755 APACHE_1_3_12/src/helpers/buildinfo.sh create mode 100755 APACHE_1_3_12/src/helpers/checkheader.sh create mode 100644 APACHE_1_3_12/src/helpers/dummy.c create mode 100644 APACHE_1_3_12/src/helpers/find-dbm-lib create mode 100755 APACHE_1_3_12/src/helpers/findcpp.sh create mode 100755 APACHE_1_3_12/src/helpers/fmn.sh create mode 100755 APACHE_1_3_12/src/helpers/fp2rp create mode 100755 APACHE_1_3_12/src/helpers/getuid.sh create mode 100755 APACHE_1_3_12/src/helpers/install.sh create mode 100755 APACHE_1_3_12/src/helpers/mfhead create mode 100755 APACHE_1_3_12/src/helpers/mkdir.sh create mode 100755 APACHE_1_3_12/src/helpers/mkshadow.sh create mode 100755 APACHE_1_3_12/src/helpers/ppl.sh create mode 100755 APACHE_1_3_12/src/helpers/slo.sh create mode 100644 APACHE_1_3_12/src/include/.cvsignore create mode 100644 APACHE_1_3_12/src/include/.indent.pro create mode 100644 APACHE_1_3_12/src/include/alloc.h create mode 100644 APACHE_1_3_12/src/include/ap.h create mode 100644 APACHE_1_3_12/src/include/ap_compat.h create mode 100644 APACHE_1_3_12/src/include/ap_config.h create mode 100644 APACHE_1_3_12/src/include/ap_ctype.h create mode 100644 APACHE_1_3_12/src/include/ap_md5.h create mode 100644 APACHE_1_3_12/src/include/ap_mmn.h create mode 100644 APACHE_1_3_12/src/include/ap_sha1.h create mode 100644 APACHE_1_3_12/src/include/buff.h create mode 100644 APACHE_1_3_12/src/include/compat.h create mode 100644 APACHE_1_3_12/src/include/conf.h create mode 100644 APACHE_1_3_12/src/include/explain.h create mode 100644 APACHE_1_3_12/src/include/fnmatch.h create mode 100644 APACHE_1_3_12/src/include/hsregex.h create mode 100644 APACHE_1_3_12/src/include/http_conf_globals.h create mode 100644 APACHE_1_3_12/src/include/http_config.h create mode 100644 APACHE_1_3_12/src/include/http_core.h create mode 100644 APACHE_1_3_12/src/include/http_log.h create mode 100644 APACHE_1_3_12/src/include/http_main.h create mode 100644 APACHE_1_3_12/src/include/http_protocol.h create mode 100644 APACHE_1_3_12/src/include/http_request.h create mode 100644 APACHE_1_3_12/src/include/http_vhost.h create mode 100644 APACHE_1_3_12/src/include/httpd.h create mode 100644 APACHE_1_3_12/src/include/multithread.h create mode 100644 APACHE_1_3_12/src/include/rfc1413.h create mode 100644 APACHE_1_3_12/src/include/scoreboard.h create mode 100644 APACHE_1_3_12/src/include/util_date.h create mode 100644 APACHE_1_3_12/src/include/util_md5.h create mode 100644 APACHE_1_3_12/src/include/util_script.h create mode 100644 APACHE_1_3_12/src/include/util_uri.h create mode 100644 APACHE_1_3_12/src/lib/.cvsignore create mode 100644 APACHE_1_3_12/src/lib/expat-lite/.cvsignore create mode 100644 APACHE_1_3_12/src/lib/expat-lite/CHANGES create mode 100644 APACHE_1_3_12/src/lib/expat-lite/Makefile.tmpl create mode 100644 APACHE_1_3_12/src/lib/expat-lite/asciitab.h create mode 100644 APACHE_1_3_12/src/lib/expat-lite/dllmain.c create mode 100644 APACHE_1_3_12/src/lib/expat-lite/expat.html create mode 100644 APACHE_1_3_12/src/lib/expat-lite/hashtable.c create mode 100644 APACHE_1_3_12/src/lib/expat-lite/hashtable.h create mode 100644 APACHE_1_3_12/src/lib/expat-lite/iasciitab.h create mode 100644 APACHE_1_3_12/src/lib/expat-lite/latin1tab.h create mode 100644 APACHE_1_3_12/src/lib/expat-lite/nametab.h create mode 100644 APACHE_1_3_12/src/lib/expat-lite/utf8tab.h create mode 100644 APACHE_1_3_12/src/lib/expat-lite/xmldef.h create mode 100644 APACHE_1_3_12/src/lib/expat-lite/xmlparse.c create mode 100644 APACHE_1_3_12/src/lib/expat-lite/xmlparse.def create mode 100644 APACHE_1_3_12/src/lib/expat-lite/xmlparse.dsp create mode 100644 APACHE_1_3_12/src/lib/expat-lite/xmlparse.h create mode 100644 APACHE_1_3_12/src/lib/expat-lite/xmlparse.mak create mode 100644 APACHE_1_3_12/src/lib/expat-lite/xmlrole.c create mode 100644 APACHE_1_3_12/src/lib/expat-lite/xmlrole.h create mode 100644 APACHE_1_3_12/src/lib/expat-lite/xmltok.c create mode 100644 APACHE_1_3_12/src/lib/expat-lite/xmltok.def create mode 100644 APACHE_1_3_12/src/lib/expat-lite/xmltok.dsp create mode 100644 APACHE_1_3_12/src/lib/expat-lite/xmltok.h create mode 100644 APACHE_1_3_12/src/lib/expat-lite/xmltok.mak create mode 100644 APACHE_1_3_12/src/lib/expat-lite/xmltok_impl.c create mode 100644 APACHE_1_3_12/src/lib/expat-lite/xmltok_impl.h create mode 100644 APACHE_1_3_12/src/lib/expat-lite/xmltok_ns.c create mode 100644 APACHE_1_3_12/src/main/.cvsignore create mode 100644 APACHE_1_3_12/src/main/.indent.pro create mode 100644 APACHE_1_3_12/src/main/Makefile.tmpl create mode 100644 APACHE_1_3_12/src/main/alloc.c create mode 100644 APACHE_1_3_12/src/main/buff.c create mode 100644 APACHE_1_3_12/src/main/gen_test_char.c create mode 100644 APACHE_1_3_12/src/main/gen_test_char.dsp create mode 100644 APACHE_1_3_12/src/main/gen_test_char.mak create mode 100644 APACHE_1_3_12/src/main/gen_uri_delims.c create mode 100644 APACHE_1_3_12/src/main/gen_uri_delims.dsp create mode 100644 APACHE_1_3_12/src/main/gen_uri_delims.mak create mode 100644 APACHE_1_3_12/src/main/http_config.c create mode 100644 APACHE_1_3_12/src/main/http_core.c create mode 100644 APACHE_1_3_12/src/main/http_log.c create mode 100644 APACHE_1_3_12/src/main/http_main.c create mode 100644 APACHE_1_3_12/src/main/http_protocol.c create mode 100644 APACHE_1_3_12/src/main/http_request.c create mode 100644 APACHE_1_3_12/src/main/http_vhost.c create mode 100644 APACHE_1_3_12/src/main/rfc1413.c create mode 100644 APACHE_1_3_12/src/main/util.c create mode 100644 APACHE_1_3_12/src/main/util_date.c create mode 100644 APACHE_1_3_12/src/main/util_md5.c create mode 100644 APACHE_1_3_12/src/main/util_script.c create mode 100644 APACHE_1_3_12/src/main/util_uri.c create mode 100644 APACHE_1_3_12/src/modules/.cvsignore create mode 100644 APACHE_1_3_12/src/modules/README create mode 100644 APACHE_1_3_12/src/modules/example/.cvsignore create mode 100644 APACHE_1_3_12/src/modules/example/.indent.pro create mode 100644 APACHE_1_3_12/src/modules/example/Makefile.tmpl create mode 100644 APACHE_1_3_12/src/modules/example/README create mode 100644 APACHE_1_3_12/src/modules/example/mod_example.c create mode 100644 APACHE_1_3_12/src/modules/experimental/.cvsignore create mode 100644 APACHE_1_3_12/src/modules/experimental/.indent.pro create mode 100644 APACHE_1_3_12/src/modules/experimental/Makefile.tmpl create mode 100644 APACHE_1_3_12/src/modules/experimental/mod_auth_digest.c create mode 100644 APACHE_1_3_12/src/modules/experimental/mod_mmap_static.c create mode 100644 APACHE_1_3_12/src/modules/extra/.cvsignore create mode 100644 APACHE_1_3_12/src/modules/extra/.indent.pro create mode 100644 APACHE_1_3_12/src/modules/extra/Makefile.tmpl create mode 100644 APACHE_1_3_12/src/modules/proxy/.cvsignore create mode 100644 APACHE_1_3_12/src/modules/proxy/.indent.pro create mode 100644 APACHE_1_3_12/src/modules/proxy/ApacheModuleProxy.dsp create mode 100644 APACHE_1_3_12/src/modules/proxy/ApacheModuleProxy.mak create mode 100644 APACHE_1_3_12/src/modules/proxy/Makefile.OS2 create mode 100644 APACHE_1_3_12/src/modules/proxy/Makefile.libdir create mode 100644 APACHE_1_3_12/src/modules/proxy/Makefile.tmpl create mode 100644 APACHE_1_3_12/src/modules/proxy/mod_proxy.c create mode 100644 APACHE_1_3_12/src/modules/proxy/mod_proxy.h create mode 100644 APACHE_1_3_12/src/modules/proxy/proxy_cache.c create mode 100644 APACHE_1_3_12/src/modules/proxy/proxy_connect.c create mode 100644 APACHE_1_3_12/src/modules/proxy/proxy_ftp.c create mode 100644 APACHE_1_3_12/src/modules/proxy/proxy_http.c create mode 100644 APACHE_1_3_12/src/modules/proxy/proxy_util.c create mode 100644 APACHE_1_3_12/src/modules/standard/.cvsignore create mode 100644 APACHE_1_3_12/src/modules/standard/.indent.pro create mode 100644 APACHE_1_3_12/src/modules/standard/Makefile.OS2 create mode 100644 APACHE_1_3_12/src/modules/standard/Makefile.tmpl create mode 100644 APACHE_1_3_12/src/modules/standard/mod_access.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_actions.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_alias.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_asis.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_auth.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_auth_anon.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_auth_db.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_auth_db.module create mode 100644 APACHE_1_3_12/src/modules/standard/mod_auth_dbm.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_autoindex.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_cern_meta.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_cgi.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_digest.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_dir.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_env.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_expires.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_headers.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_imap.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_include.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_info.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_log_agent.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_log_config.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_log_referer.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_mime.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_mime_magic.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_negotiation.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_rewrite.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_rewrite.h create mode 100644 APACHE_1_3_12/src/modules/standard/mod_setenvif.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_so.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_speling.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_status.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_unique_id.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_userdir.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_usertrack.c create mode 100644 APACHE_1_3_12/src/modules/standard/mod_vhost_alias.c create mode 100644 APACHE_1_3_12/src/modules/test/.cvsignore create mode 100644 APACHE_1_3_12/src/modules/test/.indent.pro create mode 100644 APACHE_1_3_12/src/modules/test/Makefile.tmpl create mode 100644 APACHE_1_3_12/src/modules/test/README create mode 100644 APACHE_1_3_12/src/modules/test/mod_rndchunk.c create mode 100644 APACHE_1_3_12/src/modules/test/mod_test_util_uri.c create mode 100644 APACHE_1_3_12/src/os/.indent.pro create mode 100644 APACHE_1_3_12/src/os/bs2000/.cvsignore create mode 100644 APACHE_1_3_12/src/os/bs2000/Makefile.tmpl create mode 100644 APACHE_1_3_12/src/os/bs2000/bs2login.c create mode 100644 APACHE_1_3_12/src/os/bs2000/ebcdic.c create mode 100644 APACHE_1_3_12/src/os/bs2000/ebcdic.h create mode 100644 APACHE_1_3_12/src/os/bs2000/os-inline.c create mode 100644 APACHE_1_3_12/src/os/bs2000/os.c create mode 100644 APACHE_1_3_12/src/os/bs2000/os.h create mode 100644 APACHE_1_3_12/src/os/mpeix/Makefile.tmpl create mode 100644 APACHE_1_3_12/src/os/mpeix/README create mode 100644 APACHE_1_3_12/src/os/mpeix/dlopen.c create mode 100644 APACHE_1_3_12/src/os/mpeix/gettimeofday.c create mode 100644 APACHE_1_3_12/src/os/mpeix/mpe_dl_stub.c create mode 100644 APACHE_1_3_12/src/os/mpeix/os-inline.c create mode 100644 APACHE_1_3_12/src/os/mpeix/os.c create mode 100644 APACHE_1_3_12/src/os/mpeix/os.h create mode 100644 APACHE_1_3_12/src/os/netware/Apache.def create mode 100644 APACHE_1_3_12/src/os/netware/ApacheCore.imp create mode 100644 APACHE_1_3_12/src/os/netware/ApacheCoreNW.def create mode 100644 APACHE_1_3_12/src/os/netware/ApacheModuleAuthAnon.def create mode 100644 APACHE_1_3_12/src/os/netware/ApacheModuleCERNMeta.def create mode 100644 APACHE_1_3_12/src/os/netware/ApacheModuleDigest.def create mode 100644 APACHE_1_3_12/src/os/netware/ApacheModuleExpires.def create mode 100644 APACHE_1_3_12/src/os/netware/ApacheModuleHeaders.def create mode 100644 APACHE_1_3_12/src/os/netware/ApacheModuleInfo.def create mode 100644 APACHE_1_3_12/src/os/netware/ApacheModuleProxy.def create mode 100644 APACHE_1_3_12/src/os/netware/ApacheModuleRewrite.def create mode 100644 APACHE_1_3_12/src/os/netware/ApacheModuleSpeling.def create mode 100644 APACHE_1_3_12/src/os/netware/ApacheModuleStatus.def create mode 100644 APACHE_1_3_12/src/os/netware/ApacheModuleUserTrack.def create mode 100644 APACHE_1_3_12/src/os/netware/getopt.c create mode 100644 APACHE_1_3_12/src/os/netware/getopt.h create mode 100644 APACHE_1_3_12/src/os/netware/main_nlm.c create mode 100644 APACHE_1_3_12/src/os/netware/mod_nlm.c create mode 100644 APACHE_1_3_12/src/os/netware/modules.c create mode 100644 APACHE_1_3_12/src/os/netware/multithread.c create mode 100644 APACHE_1_3_12/src/os/netware/os.c create mode 100644 APACHE_1_3_12/src/os/netware/os.h create mode 100644 APACHE_1_3_12/src/os/netware/precomp.h create mode 100644 APACHE_1_3_12/src/os/netware/test_char.h create mode 100644 APACHE_1_3_12/src/os/netware/uri_delims.h create mode 100644 APACHE_1_3_12/src/os/os2/.cvsignore create mode 100644 APACHE_1_3_12/src/os/os2/Makefile.tmpl create mode 100644 APACHE_1_3_12/src/os/os2/os-inline.c create mode 100644 APACHE_1_3_12/src/os/os2/os.c create mode 100644 APACHE_1_3_12/src/os/os2/os.h create mode 100644 APACHE_1_3_12/src/os/os2/util_os2.c create mode 100644 APACHE_1_3_12/src/os/os390/Makefile.tmpl create mode 100644 APACHE_1_3_12/src/os/os390/README.os390 create mode 100644 APACHE_1_3_12/src/os/os390/ebcdic.c create mode 100644 APACHE_1_3_12/src/os/os390/ebcdic.h create mode 100644 APACHE_1_3_12/src/os/os390/os-inline.c create mode 100644 APACHE_1_3_12/src/os/os390/os.c create mode 100644 APACHE_1_3_12/src/os/os390/os.h create mode 100755 APACHE_1_3_12/src/os/os390/xebcdic.sh create mode 100644 APACHE_1_3_12/src/os/tpf/Makefile.tmpl create mode 100644 APACHE_1_3_12/src/os/tpf/TPFExport create mode 100644 APACHE_1_3_12/src/os/tpf/cgetop.c create mode 100644 APACHE_1_3_12/src/os/tpf/ebcdic.c create mode 100644 APACHE_1_3_12/src/os/tpf/ebcdic.h create mode 100644 APACHE_1_3_12/src/os/tpf/os-inline.c create mode 100644 APACHE_1_3_12/src/os/tpf/os.c create mode 100644 APACHE_1_3_12/src/os/tpf/os.h create mode 100644 APACHE_1_3_12/src/os/tpf/samples/linkdll.jcl create mode 100644 APACHE_1_3_12/src/os/tpf/samples/loadset.jcl create mode 100644 APACHE_1_3_12/src/os/unix/.cvsignore create mode 100644 APACHE_1_3_12/src/os/unix/Makefile.tmpl create mode 100644 APACHE_1_3_12/src/os/unix/os-aix-dso.c create mode 100644 APACHE_1_3_12/src/os/unix/os-inline.c create mode 100644 APACHE_1_3_12/src/os/unix/os.c create mode 100644 APACHE_1_3_12/src/os/unix/os.h create mode 100644 APACHE_1_3_12/src/os/win32/.cvsignore create mode 100644 APACHE_1_3_12/src/os/win32/ApacheModuleAuthAnon.dsp create mode 100644 APACHE_1_3_12/src/os/win32/ApacheModuleAuthAnon.mak create mode 100644 APACHE_1_3_12/src/os/win32/ApacheModuleAuthDigest.dsp create mode 100644 APACHE_1_3_12/src/os/win32/ApacheModuleAuthDigest.mak create mode 100644 APACHE_1_3_12/src/os/win32/ApacheModuleCERNMeta.dsp create mode 100644 APACHE_1_3_12/src/os/win32/ApacheModuleCERNMeta.mak create mode 100644 APACHE_1_3_12/src/os/win32/ApacheModuleDigest.dsp create mode 100644 APACHE_1_3_12/src/os/win32/ApacheModuleDigest.mak create mode 100644 APACHE_1_3_12/src/os/win32/ApacheModuleExpires.dsp create mode 100644 APACHE_1_3_12/src/os/win32/ApacheModuleExpires.mak create mode 100644 APACHE_1_3_12/src/os/win32/ApacheModuleHeaders.dsp create mode 100644 APACHE_1_3_12/src/os/win32/ApacheModuleHeaders.mak create mode 100644 APACHE_1_3_12/src/os/win32/ApacheModuleInfo.dsp create mode 100644 APACHE_1_3_12/src/os/win32/ApacheModuleInfo.mak create mode 100644 APACHE_1_3_12/src/os/win32/ApacheModuleRewrite.dsp create mode 100644 APACHE_1_3_12/src/os/win32/ApacheModuleRewrite.mak create mode 100644 APACHE_1_3_12/src/os/win32/ApacheModuleSpeling.dsp create mode 100644 APACHE_1_3_12/src/os/win32/ApacheModuleSpeling.mak create mode 100644 APACHE_1_3_12/src/os/win32/ApacheModuleStatus.dsp create mode 100644 APACHE_1_3_12/src/os/win32/ApacheModuleStatus.mak create mode 100644 APACHE_1_3_12/src/os/win32/ApacheModuleUserTrack.dsp create mode 100644 APACHE_1_3_12/src/os/win32/ApacheModuleUserTrack.mak create mode 100755 APACHE_1_3_12/src/os/win32/ApacheOS.dsp create mode 100755 APACHE_1_3_12/src/os/win32/ApacheOS.mak create mode 100644 APACHE_1_3_12/src/os/win32/MakeModuleMak.cpp create mode 100644 APACHE_1_3_12/src/os/win32/MakeModuleMak.mak create mode 100644 APACHE_1_3_12/src/os/win32/Module.mak.tmpl create mode 100755 APACHE_1_3_12/src/os/win32/apache.ico create mode 100755 APACHE_1_3_12/src/os/win32/apache.rc create mode 100644 APACHE_1_3_12/src/os/win32/getopt.c create mode 100644 APACHE_1_3_12/src/os/win32/getopt.h create mode 100644 APACHE_1_3_12/src/os/win32/installer/README.TXT create mode 100644 APACHE_1_3_12/src/os/win32/installer/apache.iwz create mode 100644 APACHE_1_3_12/src/os/win32/installer/installdll/install.c create mode 100644 APACHE_1_3_12/src/os/win32/installer/installdll/install.def create mode 100644 APACHE_1_3_12/src/os/win32/installer/installdll/install.dsp create mode 100644 APACHE_1_3_12/src/os/win32/installer/installdll/install.mak create mode 100644 APACHE_1_3_12/src/os/win32/installer/installdll/test/resource.h create mode 100644 APACHE_1_3_12/src/os/win32/installer/installdll/test/test.c create mode 100644 APACHE_1_3_12/src/os/win32/installer/installdll/test/test.def create mode 100644 APACHE_1_3_12/src/os/win32/installer/installdll/test/test.dsp create mode 100644 APACHE_1_3_12/src/os/win32/installer/installdll/test/test.h create mode 100644 APACHE_1_3_12/src/os/win32/installer/installdll/test/test.ico create mode 100644 APACHE_1_3_12/src/os/win32/installer/installdll/test/test.mak create mode 100644 APACHE_1_3_12/src/os/win32/installer/installdll/test/test.rc create mode 100644 APACHE_1_3_12/src/os/win32/main_win32.c create mode 100644 APACHE_1_3_12/src/os/win32/mod_dll.c create mode 100644 APACHE_1_3_12/src/os/win32/mod_isapi.c create mode 100644 APACHE_1_3_12/src/os/win32/modules.c create mode 100644 APACHE_1_3_12/src/os/win32/multithread.c create mode 100755 APACHE_1_3_12/src/os/win32/os.c create mode 100755 APACHE_1_3_12/src/os/win32/os.h create mode 100644 APACHE_1_3_12/src/os/win32/passwd.c create mode 100644 APACHE_1_3_12/src/os/win32/passwd.h create mode 100644 APACHE_1_3_12/src/os/win32/readdir.c create mode 100644 APACHE_1_3_12/src/os/win32/readdir.h create mode 100755 APACHE_1_3_12/src/os/win32/registry.c create mode 100755 APACHE_1_3_12/src/os/win32/registry.h create mode 100755 APACHE_1_3_12/src/os/win32/resource.h create mode 100644 APACHE_1_3_12/src/os/win32/service.c create mode 100644 APACHE_1_3_12/src/os/win32/service.h create mode 100644 APACHE_1_3_12/src/os/win32/util_win32.c create mode 100644 APACHE_1_3_12/src/regex/.cvsignore create mode 100644 APACHE_1_3_12/src/regex/COPYRIGHT create mode 100644 APACHE_1_3_12/src/regex/Makefile.tmpl create mode 100644 APACHE_1_3_12/src/regex/README create mode 100644 APACHE_1_3_12/src/regex/WHATSNEW create mode 100644 APACHE_1_3_12/src/regex/cclass.h create mode 100644 APACHE_1_3_12/src/regex/cname.h create mode 100644 APACHE_1_3_12/src/regex/debug.c create mode 100644 APACHE_1_3_12/src/regex/engine.c create mode 100644 APACHE_1_3_12/src/regex/engine.ih create mode 100644 APACHE_1_3_12/src/regex/main.c create mode 100644 APACHE_1_3_12/src/regex/mkh create mode 100644 APACHE_1_3_12/src/regex/regcomp.c create mode 100644 APACHE_1_3_12/src/regex/regcomp.ih create mode 100644 APACHE_1_3_12/src/regex/regerror.c create mode 100644 APACHE_1_3_12/src/regex/regerror.ih create mode 100644 APACHE_1_3_12/src/regex/regex.3 create mode 100644 APACHE_1_3_12/src/regex/regex.7 create mode 100644 APACHE_1_3_12/src/regex/regex.dsp create mode 100644 APACHE_1_3_12/src/regex/regex.mak create mode 100644 APACHE_1_3_12/src/regex/regex2.h create mode 100644 APACHE_1_3_12/src/regex/regexec.c create mode 100644 APACHE_1_3_12/src/regex/regfree.c create mode 100644 APACHE_1_3_12/src/regex/split.c create mode 100644 APACHE_1_3_12/src/regex/tests create mode 100644 APACHE_1_3_12/src/regex/utils.h create mode 100644 APACHE_1_3_12/src/support/.cvsignore create mode 100644 APACHE_1_3_12/src/support/.indent.pro create mode 100644 APACHE_1_3_12/src/support/Makefile.tmpl create mode 100644 APACHE_1_3_12/src/support/README create mode 100644 APACHE_1_3_12/src/support/SHA1/README.sha1 create mode 100755 APACHE_1_3_12/src/support/SHA1/convert-sha1.pl create mode 100755 APACHE_1_3_12/src/support/SHA1/htpasswd-sha1.pl create mode 100644 APACHE_1_3_12/src/support/SHA1/ldif-sha1.example create mode 100644 APACHE_1_3_12/src/support/ab.8 create mode 100644 APACHE_1_3_12/src/support/ab.c create mode 100755 APACHE_1_3_12/src/support/apachectl create mode 100644 APACHE_1_3_12/src/support/apachectl.8 create mode 100644 APACHE_1_3_12/src/support/apxs.8 create mode 100644 APACHE_1_3_12/src/support/apxs.pl create mode 100644 APACHE_1_3_12/src/support/dbmmanage create mode 100644 APACHE_1_3_12/src/support/dbmmanage.1 create mode 100644 APACHE_1_3_12/src/support/htdigest.1 create mode 100644 APACHE_1_3_12/src/support/htdigest.c create mode 100644 APACHE_1_3_12/src/support/htdigest.dsp create mode 100644 APACHE_1_3_12/src/support/htdigest.mak create mode 100644 APACHE_1_3_12/src/support/htdigest.mcp.gz create mode 100644 APACHE_1_3_12/src/support/htpasswd.1 create mode 100644 APACHE_1_3_12/src/support/htpasswd.c create mode 100644 APACHE_1_3_12/src/support/htpasswd.dsp create mode 100644 APACHE_1_3_12/src/support/htpasswd.mak create mode 100644 APACHE_1_3_12/src/support/htpasswd.mcp.gz create mode 100644 APACHE_1_3_12/src/support/httpd.8 create mode 100644 APACHE_1_3_12/src/support/httpd.exp create mode 100755 APACHE_1_3_12/src/support/log_server_status create mode 100644 APACHE_1_3_12/src/support/logresolve.8 create mode 100644 APACHE_1_3_12/src/support/logresolve.c create mode 100644 APACHE_1_3_12/src/support/logresolve.pl create mode 100755 APACHE_1_3_12/src/support/phf_abuse_log.cgi create mode 100644 APACHE_1_3_12/src/support/rotatelogs.8 create mode 100644 APACHE_1_3_12/src/support/rotatelogs.c create mode 100644 APACHE_1_3_12/src/support/split-logfile create mode 100644 APACHE_1_3_12/src/support/suexec.8 create mode 100644 APACHE_1_3_12/src/support/suexec.c create mode 100644 APACHE_1_3_12/src/support/suexec.h create mode 100644 APACHE_1_3_12/src/test/.cvsignore create mode 100644 APACHE_1_3_12/src/test/.indent.pro create mode 100644 APACHE_1_3_12/src/test/README create mode 100755 APACHE_1_3_12/src/test/check_chunked create mode 100644 APACHE_1_3_12/src/test/cls.c create mode 100644 APACHE_1_3_12/src/test/rename/Makefile create mode 100644 APACHE_1_3_12/src/test/rename/README create mode 100644 APACHE_1_3_12/src/test/rename/apapi.h create mode 100755 APACHE_1_3_12/src/test/rename/apapi.h.mk create mode 100644 APACHE_1_3_12/src/test/rename/apapi_compat.h create mode 100755 APACHE_1_3_12/src/test/rename/apapi_compat.h.mk create mode 100644 APACHE_1_3_12/src/test/rename/compat.h create mode 100755 APACHE_1_3_12/src/test/rename/compat.h.mk create mode 100644 APACHE_1_3_12/src/test/rename/csubst/Makefile create mode 100644 APACHE_1_3_12/src/test/rename/csubst/csubst.c create mode 100644 APACHE_1_3_12/src/test/rename/csubst/lexer.c create mode 100644 APACHE_1_3_12/src/test/rename/csubst/lexer.l create mode 100644 APACHE_1_3_12/src/test/rename/csubst/tokens.h create mode 100644 APACHE_1_3_12/src/test/rename/csubst/util.c create mode 100644 APACHE_1_3_12/src/test/rename/csubst/util.h create mode 100644 APACHE_1_3_12/src/test/rename/rename.cf create mode 100644 APACHE_1_3_12/src/test/rename/rename.cf.clean-api create mode 100755 APACHE_1_3_12/src/test/rename/rename.cf.update create mode 100755 APACHE_1_3_12/src/test/rename/rename.pl create mode 100644 APACHE_1_3_12/src/test/tcpdumpscii.txt create mode 100644 APACHE_1_3_12/src/test/test-writev.c create mode 100644 APACHE_1_3_12/src/test/test_date.c create mode 100644 APACHE_1_3_12/src/test/test_find.c create mode 100644 APACHE_1_3_12/src/test/test_limits.c create mode 100644 APACHE_1_3_12/src/test/test_parser.c create mode 100644 APACHE_1_3_12/src/test/test_select.c create mode 100644 APACHE_1_3_12/src/test/time-sem.c create mode 100644 APACHE_1_3_12/src/test/vhtest/README create mode 100644 APACHE_1_3_12/src/test/vhtest/bin/test1 create mode 100644 APACHE_1_3_12/src/test/vhtest/bin/test1d create mode 100644 APACHE_1_3_12/src/test/vhtest/bin/test2 create mode 100644 APACHE_1_3_12/src/test/vhtest/bin/test2d create mode 100644 APACHE_1_3_12/src/test/vhtest/bin/test3 create mode 100644 APACHE_1_3_12/src/test/vhtest/bin/test4 create mode 100644 APACHE_1_3_12/src/test/vhtest/bin/test5 create mode 100644 APACHE_1_3_12/src/test/vhtest/bin/test6 create mode 100755 APACHE_1_3_12/src/test/vhtest/bin/vhget create mode 100644 APACHE_1_3_12/src/test/vhtest/conf/common.conf create mode 100644 APACHE_1_3_12/src/test/vhtest/conf/mime.types create mode 100644 APACHE_1_3_12/src/test/vhtest/conf/test1.conf create mode 100644 APACHE_1_3_12/src/test/vhtest/conf/test1d.conf create mode 100644 APACHE_1_3_12/src/test/vhtest/conf/test2.conf create mode 100644 APACHE_1_3_12/src/test/vhtest/conf/test2d.conf create mode 100644 APACHE_1_3_12/src/test/vhtest/conf/test3.conf create mode 100644 APACHE_1_3_12/src/test/vhtest/conf/test4.conf create mode 100644 APACHE_1_3_12/src/test/vhtest/conf/test5.conf create mode 100644 APACHE_1_3_12/src/test/vhtest/conf/test6.conf create mode 100644 APACHE_1_3_12/src/test/vhtest/docroot/default1/vhost.txt create mode 100644 APACHE_1_3_12/src/test/vhtest/docroot/default2/vhost.txt create mode 100644 APACHE_1_3_12/src/test/vhtest/docroot/default3/vhost.txt create mode 100644 APACHE_1_3_12/src/test/vhtest/docroot/main/vhost.txt create mode 100644 APACHE_1_3_12/src/test/vhtest/docroot/vhost1/vhost.txt create mode 100644 APACHE_1_3_12/src/test/vhtest/docroot/vhost2/vhost.txt create mode 100644 APACHE_1_3_12/src/test/vhtest/docroot/vhost3/vhost.txt create mode 100644 APACHE_1_3_12/src/test/vhtest/docroot/vhost4/vhost.txt create mode 100644 APACHE_1_3_12/src/test/vhtest/docroot/vhost5/vhost.txt create mode 100644 APACHE_1_3_12/src/test/vhtest/logs/.cvsignore create mode 100755 APACHE_1_3_12/src/test/vhtest/runtest create mode 100644 APACHE_1_3_12/src/test/zb.c diff --git a/APACHE_1_3_12/.cvsignore b/APACHE_1_3_12/.cvsignore new file mode 100644 index 0000000000..8da1527b45 --- /dev/null +++ b/APACHE_1_3_12/.cvsignore @@ -0,0 +1,3 @@ +Makefile +config.status +src.* diff --git a/APACHE_1_3_12/ABOUT_APACHE b/APACHE_1_3_12/ABOUT_APACHE new file mode 100644 index 0000000000..0a3e114be8 --- /dev/null +++ b/APACHE_1_3_12/ABOUT_APACHE @@ -0,0 +1,240 @@ + + The Apache HTTP Server Project + + http://www.apache.org/ + + February 1999 + +The Apache Project is a collaborative software development effort aimed +at creating a robust, commercial-grade, featureful, and freely-available +source code implementation of an HTTP (Web) server. The project is +jointly managed by a group of volunteers located around the world, using +the Internet and the Web to communicate, plan, and develop the server and +its related documentation. These volunteers are known as the Apache Group. +In addition, hundreds of users have contributed ideas, code, and +documentation to the project. This file is intended to briefly describe +the history of the Apache Group, recognize the many contributors, and +explain how you can join the fun too. + +In February of 1995, the most popular server software on the Web was the +public domain HTTP daemon developed by Rob McCool at the National Center +for Supercomputing Applications, University of Illinois, Urbana-Champaign. +However, development of that httpd had stalled after Rob left NCSA in +mid-1994, and many webmasters had developed their own extensions and bug +fixes that were in need of a common distribution. A small group of these +webmasters, contacted via private e-mail, gathered together for the purpose +of coordinating their changes (in the form of "patches"). Brian Behlendorf +and Cliff Skolnick put together a mailing list, shared information space, +and logins for the core developers on a machine in the California Bay Area, +with bandwidth and diskspace donated by HotWired and Organic Online. +By the end of February, eight core contributors formed the foundation +of the original Apache Group: + + Brian Behlendorf Roy T. Fielding Rob Hartill + David Robinson Cliff Skolnick Randy Terbush + Robert S. Thau Andrew Wilson + +with additional contributions from + + Eric Hagberg Frank Peters Nicolas Pioch + +Using NCSA httpd 1.3 as a base, we added all of the published bug fixes +and worthwhile enhancements we could find, tested the result on our own +servers, and made the first official public release (0.6.2) of the Apache +server in April 1995. By coincidence, NCSA restarted their own development +during the same period, and Brandon Long and Beth Frank of the NCSA Server +Development Team joined the list in March as honorary members so that the +two projects could share ideas and fixes. + +The early Apache server was a big hit, but we all knew that the codebase +needed a general overhaul and redesign. During May-June 1995, while +Rob Hartill and the rest of the group focused on implementing new features +for 0.7.x (like pre-forked child processes) and supporting the rapidly growing +Apache user community, Robert Thau designed a new server architecture +(code-named Shambhala) which included a modular structure and API for better +extensibility, pool-based memory allocation, and an adaptive pre-forking +process model. The group switched to this new server base in July and added +the features from 0.7.x, resulting in Apache 0.8.8 (and its brethren) +in August. + +After extensive beta testing, many ports to obscure platforms, a new set +of documentation (by David Robinson), and the addition of many features +in the form of our standard modules, Apache 1.0 was released on +December 1, 1995. + +Less than a year after the group was formed, the Apache server passed +NCSA's httpd as the #1 server on the Internet. + +The survey by Netcraft (http://www.netcraft.com/survey/) shows that Apache +is today more widely used than all other web servers combined. + + ============================================================================ + +Current Apache Group in alphabetical order as of 14 February 1999: + + Brian Behlendorf O'Reilly and Associates, California + Ken Coar IBM Corporation, Research Triangle Park, NC, USA + Mark J. Cox C2Net Europe, UK + Lars Eilebrecht Cable & Wireless ECRC, Munich, Germany + Ralf S. Engelschall Munich, Germany. + Roy T. Fielding UC Irvine, California + Dean Gaudet Critical Path, California + Rob Hartill Internet Movie DB, UK + Ben Hyde Gensym, Massachusetts + Jim Jagielski jaguNET ISP, Maryland + Alexei Kosut Stanford University, California + Martin Kraemer Munich, Germany + Ben Laurie Freelance Consultant, UK + Doug MacEachern Critical Path, California + Aram W. Mirzadeh Qosina Corporation, New York + Sameer Parekh C2Net, California + Cliff Skolnick Freelance, California + Marc Slemko Canada + Bill Stoddard IBM Corp., Research Triangle Park, NC + Paul Sutton C2Net Europe, UK + Randy Terbush Covalent Technologies, Nebraska + Dirk-Willem van Gulik Freelance Consultant, Italy + +Apache Emeritae (old group members now off doing other things) + + Chuck Murcko The Topsail Group, Pennsylvania + David Robinson Cambridge University, UK + Robert S. Thau MIT, Massachusetts + Andrew Wilson Freelance Consultant, UK + +Other major contributors + + Howard Fear (mod_include), Florent Guillaume (language negotiation), + Koen Holtman (rewrite of mod_negotiation), + Kevin Hughes (creator of all those nifty icons), + Rasmus Lerdorf (mod_info, mod_php, mod_php3), + Brandon Long and Beth Frank (NCSA Server Development Team, post-1.3), + Ambarish Malpani (Beginning of the NT port), + Rob McCool (original author of the NCSA httpd 1.3), + Paul Richards (convinced the group to use remote CVS after 1.0), + Garey Smiley (OS/2 port), Henry Spencer (author of the regex library). + +Many 3rd-party modules, frequently used and recommended, are also +freely-available and linked from the related projects page: +, and their authors frequently +contribute ideas, patches, and testing. In particular, Doug MacEachern +(mod_perl) and Rasmus Lerdorf (mod_php). + +Hundreds of people have made individual contributions to the Apache +project. Patch contributors are listed in the src/CHANGES file. +Frequent contributors have included Petr Lampa, Tom Tromey, James H. +Cloos Jr., Ed Korthof, Nathan Neulinger, Jason S. Clary, Jason A. Dour, +Michael Douglass, Tony Sanders, Brian Tao, Michael Smith, Adam Sussman, +Nathan Schrenk, Matthew Gray, and John Heidemann. + + ============================================================================ + +How to become involved in the Apache project + +There are several levels of contributing. If you just want to send +in an occasional suggestion/fix, then you can just use the bug reporting +form at . You can also subscribe +to the announcements mailing list (apache-announce@apache.org) which we +use to broadcast information about new releases, bugfixes, and upcoming +events. There's a lot of information about the development process (much +of it in serious need of updating) to be found at . + +If you'd like to become an active contributor to the Apache project (the +group of volunteers who vote on changes to the distributed server), then +you need to start by subscribing to the new-httpd@apache.org mailing list. +One warning though: traffic is high, 1000 to 1500 messages/month. +To subscribe to the list, send "subscribe new-httpd" in the body of +a message to . We recommend reading the list for +a while before trying to jump in to development. + + NOTE: The developer mailing list (new-httpd@apache.org) is not + a user support forum; it is for people actively working on development + of the server code and documentation, and for planning future + directions. If you have user/configuration questions, send them + to the USENET newsgroup "comp.infosystems.www.servers.unix". + +There is a core group of contributors (informally called the "core") +which was formed from the project founders and is augmented from time +to time when core members nominate outstanding contributors and the +rest of the core members agree. The core group focus is more on +"business" issues and limited-circulation things like security problems +than on mainstream code development. The term "The Apache Group" +technically refers to this core of project contributors. + +The Apache project is a meritocracy -- the more work you have done, the more +you are allowed to do. The group founders set the original rules, but +they can be changed by vote of the active members. There is a group +of people who have logins on our server (hyperreal.com) and access to the +CVS repository. Everyone has access to the CVS snapshots. Changes to +the code are proposed on the mailing list and usually voted on by active +members -- three +1 (yes votes) and no -1 (no votes, or vetoes) are needed +to commit a code change during a release cycle; docs are usually committed +first and then changed as needed, with conflicts resolved by majority vote. + +Our primary method of communication is our mailing list. Approximately 40 +messages a day flow over the list, and are typically very conversational in +tone. We discuss new features to add, bug fixes, user problems, developments +in the web server community, release dates, etc. The actual code development +takes place on the developers' local machines, with proposed changes +communicated using a patch (output of a unified "diff -u oldfile newfile" +command), and committed to the source repository by one of the core +developers using remote CVS. Anyone on the mailing list can vote on a +particular issue, but we only count those made by active members or people +who are known to be experts on that part of the server. Vetoes must be +accompanied by a convincing explanation. + +New members of the Apache Group are added when a frequent contributor is +nominated by one member and unanimously approved by the voting members. +In most cases, this "new" member has been actively contributing to the +group's work for over six months, so it's usually an easy decision. + +The above describes our past and current (as of April 1998) guidelines, +which will probably change over time as the membership of the group +changes and our development/coordination tools improve. + + ============================================================================ + +Why Apache Is Free + +Apache exists to provide a robust and commercial-grade reference +implementation of the HTTP protocol. It must remain a platform upon which +individuals and institutions can build reliable systems, both for +experimental purposes and for mission-critical purposes. We believe the +tools of online publishing should be in the hands of everyone, and +software companies should make their money providing value-added services +such as specialized modules and support, amongst other things. We realize +that it is often seen as an economic advantage for one company to "own" a +market - in the software industry that means to control tightly a +particular conduit such that all others must pay. This is typically done +by "owning" the protocols through which companies conduct business, at the +expense of all those other companies. To the extent that the protocols of +the World Wide Web remain "unowned" by a single company, the Web will +remain a level playing field for companies large and small. Thus, +"ownership" of the protocol must be prevented, and the existence of a +robust reference implementation of the protocol, available absolutely for +free to all companies, is a tremendously good thing. + +Furthermore, Apache is an organic entity; those who benefit from it +by using it often contribute back to it by providing feature enhancements, +bug fixes, and support for others in public newsgroups. The amount of +effort expended by any particular individual is usually fairly light, but +the resulting product is made very strong. This kind of community can +only happen with freeware -- when someone pays for software, they usually +aren't willing to fix its bugs. One can argue, then, that Apache's +strength comes from the fact that it's free, and if it were made "not +free" it would suffer tremendously, even if that money were spent on a +real development team. + +We want to see Apache used very widely -- by large companies, small +companies, research institutions, schools, individuals, in the intranet +environment, everywhere -- even though this may mean that companies who +could afford commercial software, and would pay for it without blinking, +might get a "free ride" by using Apache. We would even be happy if some +commercial software companies completely dropped their own HTTP server +development plans and used Apache as a base, with the proper attributions +as described in the LICENSE file. + +Thanks for using Apache! + + ============================================================================ +Roy Fielding, June 1997 diff --git a/APACHE_1_3_12/Announcement b/APACHE_1_3_12/Announcement new file mode 100644 index 0000000000..dfd664deac --- /dev/null +++ b/APACHE_1_3_12/Announcement @@ -0,0 +1,78 @@ +Apache 1.3.12 Released +====================== + +The Apache Software Foundation and The Apache Server Project are +pleased to announce the release of version 1.3.12 of the Apache HTTP server. + +The primary changes in this version of Apache are those related to +the ``cross site scripting'' security alerts described at + + http://www.cert.org/advisories/CA-2000-02.html + - and - + http://www.apache.org/info/css-security/index.html + +Specifically, charset handling has been improved and reinforced +(including a new directive: AddDefaultCharset) and server generated +pages properly escape ``userland'' input. + +A complete listing with detailed descriptions is provided in the +src/CHANGES file. + +We consider Apache 1.3.12 to be the best version of Apache available and +we strongly recommend that users of older versions, especially of the +1.1.x and 1.2.x family, upgrade as soon as possible. No further releases +will be made in the 1.2.x family. + + +Apache 1.3.12 is available for download from + + http://www.apache.org/dist/ + +Please see the CHANGES_1.3 file in the same directory for a full +list of changes. + +Binary distributions are available from + + http://www.apache.org/dist/binaries/ + +As of Apache 1.3.12 binary distributions contain all standard Apache +modules as shared objects (if supported by the platform) and include +full source code. Installation is easily done by executing the +included install script. See the README.bindist and INSTALL.bindist +files for a complete explanation. Please note that the binary +distributions are only provided for your convenience and current +distributions for specific platforms are not always available. + +The source and binary distributions are also available via any of the +mirrors listed at + + http://www.apache.org/mirrors/ + +For an overview of new features in 1.3 please see + + http://www.apache.org/docs/new_features_1_3.html + +In general, Apache 1.3 offers several substantial improvements +over version 1.2, including better performance, reliability and a +wider range of supported platforms, including Windows 95/98 and NT +(which fall under the "Win32" label). + +Apache is the most popular web server in the known universe; over +half of the servers on the Internet are running Apache or one of +its variants. + +IMPORTANT NOTE FOR WIN32 USERS: Over the years, many users have +come to trust Apache as a secure and stable server. It must +be realized that the current Win32 code has not yet reached the +levels of the Unix version, but is of acceptable quality. Any +Win32 stability or security problems do not impact, in any way, +Apache on other platforms. With the continued donation of time +and resources by individuals and companies, we hope that the Win32 +version of Apache will grow stronger through the 1.3.x release cycle. + + +Thank you for using Apache. +-- +See you at ApacheCon 2000 in Orlanda, Florida, March 8-10, 2000. + http://www.Apachecon.com/ + diff --git a/APACHE_1_3_12/INSTALL b/APACHE_1_3_12/INSTALL new file mode 100644 index 0000000000..b485c7d4f9 --- /dev/null +++ b/APACHE_1_3_12/INSTALL @@ -0,0 +1,543 @@ + + APACHE INSTALLATION + + NOTE: Windows users please read the documents README.NT and + http://www.apache.org/docs/windows.html, (or the + htdocs/manual/windows.html file included with Apache). + The following applies only to Unix users. + + Introduction + ============ + + Like all good things, there are two ways to configure, compile, and install + Apache. You can go for the 3-minute installation process using the APACI + process described below; or, you can opt for the same mechanism used in + previous versions of Apache, as described in the file 'src/INSTALL'. Each + mechanism has its benefits and drawbacks - APACI is newer and a little more + raw, but it gets you up and running the least amount of time, whereas the + "Configuration.tmpl" mechanism may be more familiar and give you some more + flexibility to the power user. We'd be very interested in your comments and + feedback regarding each approach. + + + Installing the Apache 1.3 HTTP server with APACI + ================================================ + + 1. Overview for the impatient + -------------------------- + + $ ./configure --prefix=PREFIX + $ make + $ make install + $ PREFIX/bin/apachectl start + + NOTE: PREFIX is not the string "PREFIX". Instead use the Unix + filesystem path under which Apache should be installed. For + instance use "/usr/local/apache" for PREFIX above. + + 2. Requirements + ------------ + + The following requirements exist for building Apache: + + o Disk Space: + + Make sure you have approximately 12 MB of temporary free disk space + available. After installation Apache occupies approximately 3 MB of + disk space (the actual required disk space depends on the amount of + compiled in third party modules, etc). + + o ANSI-C Compiler: + + Make sure you have an ANSI-C compiler installed. The GNU C compiler + (GCC) from the Free Software Foundation (FSF) is recommended (version + 2.7.2 is fine). If you don't have GCC then at least make sure your + vendors compiler is ANSI compliant. You can find the homepage of GNU + at http://www.gnu.org/ and the GCC distribution under + http://www.gnu.org/order/ftp.html . + + o Perl 5 Interpreter [OPTIONAL]: + + For some of the support scripts like `apxs' or `dbmmanage' (which are + written in Perl) the Perl 5 interpreter is required (versions 5.003 + and 5.004 are fine). If no such interpreter is found by APACI's + `configure' script this is no harm. Of course, you still can build + and install Apache 1.3. Only those support scripts cannot be used. If + you have multiple Perl interpreters installed (perhaps a Perl 4 from + the vendor and a Perl 5 from your own), then it is recommended to use + the --with-perl option (see below) to make sure the correct one is + selected by APACI. + + o Dynamic Shared Object (DSO) support [OPTIONAL]: + + To provide maximum flexibility Apache now is able to load modules + under runtime via the DSO mechanism by using the pragmatic + dlopen()/dlsym() system calls. These system calls are not available + under all operating systems therefore you cannot use the DSO mechanism + on all platforms. And Apache currently has only limited built-in + knowledge on how to compile shared objects because this is heavily + platform-dependent. The current state is this: + + o Out-of-the-box supported platforms are: + - Linux - SunOS - UnixWare - Mac OS X Server + - FreeBSD - Solaris - AIX - Mac OS + - OpenBSD - IRIX - SCO - OpenStep/Mach + - NetBSD - HPUX - ReliantUNIX - DYNIX/ptx + - BSDI - Digital Unix - DGUX + + o Entirely unsupported platforms are: + - Ultrix + + If your system is not on these lists but has the dlopen-style + interface, you either have to provide the appropriate compiler and + linker flags (see CFLAGS_SHLIB, LDFLAGS_SHLIB and LDFLAGS_SHLIB_EXPORT + below) manually or at least make sure a Perl 5 interpreter is + installed from which Apache can guess the options. + + For more in-depth information about DSO support in Apache 1.3 please + read the document htdocs/manual/dso.html carefully. Especially the + section entitled "Advantages & Disadvantages" because using the DSO + mechanism can have strange side-effects if you are not carefully. BE + WARNED! + + 3. Configuring the source tree + --------------------------- + + NOTE: Although we'll often advise you to read the src/Configuration.tmpl + file parts to better understand the various options in this + section, there is _AT NO TIME_ any need to _EDIT_ this file. The + _COMPLETE_ configuration takes place via command line arguments and + local shell variables for the ./configure script. The + src/Configuration.tmpl file is just a _READ-ONLY_ resource, here. + + Introduction: + + The next step is to configure the Apache source tree for your particular + platform and personal requirements. The most important setup here is the + location prefix where Apache is to be installed later, because Apache has + to be configured for this location to work correctly. But there are a lot + of other options available for your pleasure. + + For a short impression of what possibilities you have, here is a typical + example which compiles Apache for the installation tree /sw/pkg/apache + with a particular compiler and flags plus the two additional modules + mod_rewrite and mod_proxy for later loading through the DSO mechanism: + + $ CC="pgcc" OPTIM="-O2" \ + ./configure --prefix=/sw/pkg/apache \ + --enable-module=rewrite --enable-shared=rewrite \ + --enable-module=proxy --enable-shared=proxy + + The complete reference of all configuration possibilities follows. For + more real-life configuration examples please check out the file + README.configure. + + Reference: + + $ [CC=...] [CFLAGS_SHLIB=...] [TARGET=...] + [OPTIM=...] [LD_SHLIB=...] + [CFLAGS=...] [LDFLAGS_SHLIB=...] + [INCLUDES=...] [LDFLAGS_SHLIB_EXPORT=...] + [LDFLAGS=...] [RANLIB=...] + [LIBS=...] [DEPS=...] + ./configure + [--quiet] [--prefix=DIR] [--enable-rule=NAME] + [--verbose] [--exec-prefix=PREFIX] [--disable-rule=NAME] + [--shadow[=DIR]] [--bindir=EPREFIX] [--add-module=FILE] + [--show-layout] [--sbindir=DIR] [--activate-module=FILE] + [--help] [--libexecdir=DIR] [--enable-module=NAME] + [--mandir=DIR] [--disable-module=NAME] + [--sysconfdir=DIR] [--enable-shared=NAME] + [--datadir=DIR] [--disable-shared=NAME] + [--includedir=DIR] [--permute-module=N1:N2] + [--localstatedir=DIR] + [--runtimedir=DIR] [--enable-suexec] + [--logfiledir=DIR] [--suexec-caller=UID] + [--proxycachedir=DIR] [--suexec-docroot=DIR] + [--with-layout=[FILE:]ID] [--suexec-logfile=FILE] + [--suexec-userdir=DIR] + [--with-perl=FILE] [--suexec-uidmin=UID] + [--without-support] [--suexec-gidmin=GID] + [--without-confadjust] [--suexec-safepath=PATH] + [--without-execstrip] + [--server-uid=UID] + [--server-gid=GID] + + Use the CC, OPTIM, CFLAGS, INCLUDES, LDFLAGS, LIBS, CFLAGS_SHLIB, + LD_SHLIB, LDFLAGS_SHLIB, LDFLAGS_SHLIB_EXPORT, RANLIB, DEPS and TARGET + environment variables to override the corresponding default entries in + the src/Configuration.tmpl file (see there for more information about + their usage). + + Note: The syntax ``KEY=VALUE ./configure ...'' (one single line!) is + the GNU Autoconf compatible way of specifying defines and can + be used with Bourne shell compatible shells only (sh, bash, + ksh). If you use a different type of shell either use ``env + KEY=VALUE ./configure ...'' when the `env' command is available + on your system or use ``setenv KEY VALUE; ./configure ...'' if + you use one of the C-shell variants (csh, tcsh). + + Note: The above parameter names are the canonical ones used in + Autoconf-style interfaces. But because src/Configuration.tmpl + uses the prefix EXTRA_ for some variables (e.g. EXTRA_CFLAGS) + these variants are accepted for backward-compatibility reasons, + too. But please use the canonical Autoconf-style names and + don't rely on this. + + Use the --prefix=PREFIX and --exec-prefix=EPREFIX options to configure + Apache to use a particular installation prefix. The default is + PREFIX=/usr/local/apache and EPREFIX=PREFIX. + + Use the --bindir=DIR, --sbindir=DIR, --libexecdir=DIR, --mandir=DIR, + --sysconfdir=DIR, --datadir=DIR, --includedir=DIR, --localstatedir=DIR, + --runtimedir=DIR, --logfiledir=DIR and proxycachedir=DIR option to change + the paths for particular subdirectories of the installation tree. + Defaults are bindir=EPREFIX/bin, sbindir=EPREFIX/sbin, + libexecdir=EPREFIX/libexec, mandir=PREFIX/man, sysconfdir=PREFIX/etc, + datadir=PREFIX/share, includedir=PREFIX/include, + localstatedir=PREFIX/var, runtimedir=PREFIX/var/run, + logfiledir=PREFIX/var/log and proxycachedir=PREFIX/var/proxy. + + Note: To reduce the pollution of shared installation locations + (like /usr/local/ or /etc) with Apache files to a minimum the + string ``/apache'' is automatically appended to 'libexecdir', + 'sysconfdir', 'datadir', 'localstatedir' and 'includedir' if + (and only if) the following points apply for each path + individually: + + 1. the path doesn't already contain the word ``apache'' + 2. the path was not directly customized by the user + + Keep in mind that per default these paths are derived from + 'prefix' and 'exec-prefix', so usually its only a matter + whether these paths contain ``apache'' or not. Although the + defaults were defined with experience in mind you always should + make sure the paths fit your situation by checking the finally + chosen paths via the --layout option. + + Use the --with-layout=[F:]ID option to select a particular installation + path base-layout. You always _HAVE_ to select a base-layout. There are + currently two layouts pre-defined in the file config.layout: `Apache' for + the classical Apache path layout and `GNU' for a path layout conforming + to the GNU `standards' document. When you want to use your own custom + layout FOO, either add a corresponding "..." section + to config.layout and use --with-layout=FOO or place it into your own + file, say config.mypaths, and use --with-layout=config.mypaths:FOO. + + Use the --show-layout option to check the final installation path layout + while fiddling with the options above. + + Use the --enable-rule=NAME and --disable-rule=NAME options to enable or + disable a particular Rule from the Apache src/Configuration.tmpl file. The + defaults (yes=enabled, no=disabled) can either be seen when running + `./configure --help' or manually looked up in the src/Configuration.tmpl + file. + + Use the --add-module=FILE option to copy a module source file to the + Apache src/modules/extra/ directory and on-the-fly add an entry for it in + the configuration file. FILE has to be a valid path to a C source file + outside the Apache source tree, for instance /path/to/mod_foo.c, or a + path to an already existing C source code file in src/modules/extra/, such + as src/modules/extra/mod_foo.c, in which case no copying will be done. + The added module this is way is automatically activated and enabled. Use + this option to automatically include a simple third-party module to the + Apache build process. + + Use the --activate-module=FILE option to add an entry for an existing + module object or library file into the configuration file on-the-fly. + FILE has to be a valid path beginning with "src/modules/", and the + corresponding file has to have been copied to this location in the Apache + source tree before running configure. The module is automatically + enabled. Use this option to automatically include a complex third-party + module to the Apache build process where, for instance a module like + mod_perl or mod_php3 consisting of more than one file which are created + by a third-party configuration scheme. + + Use the --enable-module=NAME and --disable-module=NAME options to enable + or disable a particular already distributed module from the Apache + src/Configuration.tmpl file. The correct module names (no `mod_' prefix!) + and defaults (yes=enabled, no=disabled) can be seen when running + `./configure --help'. There are two special NAME variants: `all' for + enabling or disabling all modules and `most' for enabling or disabling + only these modules which are useable on all platforms (currently this is + `all' minus the modules `auth_db', `log_agent', `log_referer', `example', + `so' and `mmap_static'). For a compact overview of available modules see + the following list (remove the `mod_' prefix to get the NAME). + + _________________________________________________________________________ + LIST OF AVAILABLE MODULES + + Environment creation + (+) mod_env .......... Set environment variables for CGI/SSI scripts + (+) mod_setenvif ..... Set environment variables based on HTTP headers + (-) mod_unique_id .... Generate unique identifiers for request + Content type decisions + (+) mod_mime ......... Content type/encoding determination (configured) + (-) mod_mime_magic ... Content type/encoding determination (automatic) + (+) mod_negotiation .. Content selection based on the HTTP Accept* headers + URL mapping + (+) mod_alias ........ Simple URL translation and redirection + (-) mod_rewrite ...... Advanced URL translation and redirection + (+) mod_userdir ...... Selection of resource directories by username + (-) mod_speling ...... Correction of misspelled URLs + Directory Handling + (+) mod_dir .......... Directory and directory default file handling + (+) mod_autoindex .... Automated directory index file generation + Access Control + (+) mod_access ....... Access Control (user, host, network) + (+) mod_auth ......... HTTP Basic Authentication (user, passwd) + (-) mod_auth_dbm ..... HTTP Basic Authentication via Unix NDBM files + (-) mod_auth_db ...... HTTP Basic Authentication via Berkeley-DB files + (-) mod_auth_anon .... HTTP Basic Authentication for Anonymous-style users + (-) mod_digest ....... HTTP Digest Authentication + HTTP response + (-) mod_headers ...... Arbitrary HTTP response headers (configured) + (-) mod_cern_meta .... Arbitrary HTTP response headers (CERN-style files) + (-) mod_expires ...... Expires HTTP responses + (+) mod_asis ......... Raw HTTP responses + Scripting + (+) mod_include ...... Server Side Includes (SSI) support + (+) mod_cgi .......... Common Gateway Interface (CGI) support + (+) mod_actions ...... Map CGI scripts to act as internal `handlers' + Internal Content Handlers + (+) mod_status ....... Content handler for server run-time status + (-) mod_info ......... Content handler for server configuration summary + Request Logging + (+) mod_log_config ... Customizable logging of requests + (-) mod_log_agent .... Specialized HTTP User-Agent logging (deprecated) + (-) mod_log_referer .. Specialized HTTP Referrer logging (deprecated) + (-) mod_usertrack .... Logging of user click-trails via HTTP Cookies + Miscellaneous + (+) mod_imap ......... Server-side Image Map support + (-) mod_proxy ........ Caching Proxy Module (HTTP, HTTPS, FTP) + (-) mod_so ........... Dynamic Shared Object (DSO) bootstrapping + Experimental + (-) mod_mmap_static .. Caching of frequently served pages via mmap() + Development + (-) mod_example ...... Apache API demonstration (developers only) + _________________________________________________________________________ + (+) = enabled per default [disable with --disable-module] + (-) = disabled per default [enable with --enable-module ] + + + Use the --enable-shared=NAME and --disable-shared=NAME options to enable + or disable the shared object support for a particular module from the + Apache src/Configuration.tmpl file. The defaults (yes=enabled, + no=disabled) can be seen when running `./configure --help'. There are two + special NAME variants: `max' for enabling or disabling DSO on all modules + except the bootstrapping `so' module and `remain' for enabling or + disabling DSO for only those modules which are still not enabled (which + this way implicitly enables them itself). + + Note 1: The --enable-shared option DOES NOT AUTOMATICALLY enable the + module because there are variants like `--enable-shared=max' + which should not imply `--enable-module=all'. + + Note 2: Per default the DSO mechanism is globally disabled, i.e. no + modules are build as shared objects. + + Note 3: The usage of any --enable-shared option automatically implies + a --enable-module=so option because the bootstrapping module + mod_so is always needed for DSO support. + + Note 4: When you later want to extend your Apache installation via + third-party modules through the DSO+APXS mechanism make sure + that you at least compile with mod_so included, even when no + distributed modules are build as shared objects. This can be + achieved by explicitly using --enable-module=so. + + Note 5: Some platforms require --enable-rule=SHARED_CORE for + the DSO mechanism to work, i.e. when you want to use + --enable-shared for some modules on these platforms you also + have to enable the SHARED_CORE rule. For more details please + read the document `htdocs/manual/dso.html'. + + Use the --permute-module=N1:N2 option to permutate the AddModule lines of + modules mod_N1 and mod_N2 in the Configuration file. This way one can + give modules different priorities. Two special and important variants + are supported for the option argument: first BEGIN:N which permutes + module mod_N 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 + N:END which permutes mod_N with the end of the module list, i.e. it + `moves' the module to the end of the list (gives it highest priority). + + Use the --with-perl=FILE option to select a particular Perl interpreter + executable to be used with Apache. Per default APACI tries to find it + automatically. But if multiple Perl instances exist on your system you + have to select the correct one manually. + + Use the --without-support option to explicitly disable the build and + installation of support tools from the src/support/ area. This can be + useful when you have compilation problems with one or more of these not + programs on your platform or if you just don't need them. + + Use the --without-confadjust option to explicitly disable some built + user/situation dependent adjustments to the config files (Group, Port, + ServerAdmin, ServerName, etc.). This is usually only interesting for + vendor package maintainers who wants to force the keeping of defaults. + + Use the --without-execstrip option to disable the stripping of + executables on installation. This can be important on some platforms in + combination with --enable-rule=SHARED_CORE or when Apache was built with + debugging symbols which shouldn't be lost. + + Use the --enable-suexec option to enable the suEXEC feature by building + and installing the "suexec" support program. Use --suexec-caller=UID to + set the allowed caller user id, --suexec-userdir=DIR to set the user + subdirectory, --suexec-docroot=DIR to set the suexec root directory, + --suexec-uidmin=UID/--suexec-gidmin=GID to set the minimal allowed + UID/GID, --suexec-logfile=FILE to set the logfile and + --suexec-safepath=PATH to set the safe shell PATH for the suEXEC + feature. At least one --suexec-xxxxx option has to be provided together + with the --enable-suexec option to let APACI accept your request for + using the suEXEC feature. + + CAUTION: FOR DETAILS ABOUT THE SUEXEC FEATURE WE HIGHLY RECOMMEND YOU TO + FIRST READ THE DOCUMENT htdocs/manual/suexec.html BEFORE USING + THE ABOVE OPTIONS. + + USING THE SUEXEC FEATURE PROPERLY CAN REDUCE CONSIDERABLY THE + SECURITY RISKS INVOLVED WITH ALLOWING USERS TO DEVELOP AND RUN + PRIVATE CGI OR SSI PROGRAMS. HOWEVER, IF SUEXEC IS IMPROPERLY + CONFIGURED, IT CAN CAUSE ANY NUMBER OF PROBLEMS AND POSSIBLY + CREATE NEW HOLES IN YOUR COMPUTER'S SECURITY. IF YOU AREN'T + FAMILIAR WITH MANAGING SETUID ROOT PROGRAMS AND THE SECURITY + ISSUES THEY PRESENT, WE HIGHLY RECOMMEND THAT YOU NOT CONSIDER + USING SUEXEC AND KEEP AWAY FROM THESE OPTIONS! + + Use the --shadow option to let APACI create a shadow source tree of the + sources for building. This is useful when you want to build for different + platforms in parallel (usually through a NFS, AFS or DFS mounted + filesystem). You may specify a directory to the --shadow option into + which the shadow tree will be created. + + Use the --quiet option to disable all configuration verbose messages. + + Use the --verbose option to enable additional verbose messages. + + Use the --server-uid option to specify the user ID you want the server to run + as. If not specified the server will run as user nobody. If the user ID + specified is different than the ID of the user starting the server, you need to + start the server as root. + + Use the --server-gid option to specify the group ID you want the server user ID to + be a member of. If not specified, the group ID will be #-1. + + 4. Building the package + -------------------- + + Now you can build the various parts which form the Apache package by + simply running the command + + $ make + + Please be patient here, this takes approximately 2 minutes to complete + under a Pentium-166/FreeBSD-2.2 system, dependend on the amount of + modules you have enabled. + + 5. Installing the package + ---------------------- + + Now its time to install the package under the configured installation + PREFIX (see --prefix option above) by running: + + $ make install + + For the paranoid hackers under us: The above command really installs under + prefix _only_, i.e. no other stuff from your system is touched. Even if + you upgrade an existing installation your configuration files in + PREFIX/etc/ are preserved. + + Note for package authors: + + To simplify rolling a package tarball from the installed files APACI + provides a way to override the installation root for the install step. + Additionally you can get rid of the user message at the end of the + installation process by using the `install-quiet' target. Example: + + $ make install-quiet root=/tmp/apache-root + + Notes for specific platforms: + + NOTE: Please note that for re-installing Apache on AIX you should use the + command `slibclean' before using `make install' to really unload + any old versions of the DSO's that might still be cached by the + dynamic loader. + + 6. Testing the package + ------------------- + + Now you can fire up your Apache HTTP server by immediately running + + $ PREFIX/bin/apachectl start + + and then you should be able to request your first document via URL + http://localhost/ (when you built and installed Apache as root or at + least used the --without-confadjust option) or http://localhost:8080/ + (when you built and installed Apache as a regular user). Then stop the + server again by running: + + $ PREFIX/bin/apachectl stop + + 7. Customizing the package + ----------------------- + + Finally you can customize your Apache HTTP server by editing the + configuration files under PREFIX/etc/. + + $ vi PREFIX/etc/httpd.conf + $ vi PREFIX/etc/access.conf + $ vi PREFIX/etc/srm.conf + + Have a look at the Apache manual under htdocs/manual/ or + http://www.apache.org/docs/ for a complete reference of available + configuration directives. + + 8. Preparing the system + -------------------- + + Proper operation of a public HTTP server requires at least the following: + + 1. A correctly working TCP/IP layer, since HTTP is implemented on top of + TCP/IP. Although modern Unix platforms have good networking layers, + always make sure you have all official vendor patches referring to the + network layer applied. + + 2. Accurate time keeping, since elements of the HTTP protocol are + expressed as the time of day. So, it's time to investigate setting + some time synchronization facility on your system. Usually the ntpdate + or xntpd programs are used for this purpose which are based on the + Network Time Protocol (NTP). See the Usenet newsgroup + comp.protocols.time.ntp and the NTP homepage at + http://www.eecis.udel.edu/~ntp/ for more details about NTP software + and public time servers. + + 9. Contacts + -------- + + o If you want to be informed about new code releases, bug fixes, + security fixes, general news and information about the Apache server + subscribe to the apache-announce mailing list as described under + http://www.apache.org/announcelist.html + + o If you want freely available support for running Apache please join the + Apache user community by subscribing at least to the following USENET + newsgroup: + comp.infosystems.www.servers.unix + + o If you want commercial support for running Apache please contact + one of the companies and contractors which are listed at + http://www.apache.org/info/support.cgi + + o If you have a concrete bug report for Apache please go to the + Apache Group Bug Database and submit your report: + http://www.apache.org/bug_report.html + + o If you want to participate in actively developing Apache please + subscribe to the `new-httpd' mailing list as described at + http://dev.apache.org/mailing-lists + + Thanks for running Apache. + The Apache Group + http://www.apache.org/ + diff --git a/APACHE_1_3_12/KEYS b/APACHE_1_3_12/KEYS new file mode 100644 index 0000000000..5482538d68 --- /dev/null +++ b/APACHE_1_3_12/KEYS @@ -0,0 +1,664 @@ +This file contains the PGP keys of various Apache developers. +Please don't use them for email unless you have to. Their main +purpose is code signing. + +Apache users: pgp < KEYS +Apache developers: pgp -kxa and append it to this file. + + +Type Bits/KeyID Date User ID +pub 1024/2719AF35 1995/05/13 Ben Laurie + Ben Laurie + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.3ia + +mQCNAi+0jQEAAAEEAK7oX0FeNncaHfa1v+V7SMUviAm8qB8orWG0zvja4ZtSrHVg +/PMwppUh44t5ERA9lltRBdHu30+YSh8a1dYt1XOD83nknzj9rhtpFAPqyywlLVhN +VY3PVLyMbULw27aEAGc+StFqrDoUQ0+j9QU/YH/IyVN9rBaJyhsIDEUnGa81AAUR +tB5CZW4gTGF1cmllIDxiZW5AYWxncm91cC5jby51az6JARUDBRAyb2Doc3AsNzyk +Yh0BARa6CACUBnsP9Vb+T/PvNYKVQBIODz+90tz5GozWwCVfPVSaRd8Dz+oF1sFs +YCz/KuxqBhL5PkiCuSMfOVlPA5nirjoktMF/af5saZqhPr5rvr67Z1OzZnVDvWe4 +DhFrn8EoLrY5YNJhUwfINnZqyKaQu8TW6p4caLkTCW0KM+4ztTe74xRG9NeE+K0+ +0RMpAF3jEY36LGRjq6miazt2bVZQDTl6CuWE+gAaFlX2ojV7e1xdxVvpBIEc34MP +g9ORJ0evx1QilMt1VyGcS/pe4IQgjdJqjU/4fzqFZkT2nntQMbV9kQyNe2+qfqP7 +giTryIanmBAfd3oOCTsRz2VKPfdhCqCRiQB1AwUQMRdzEEyr2GZv4ALJAQEuhAL6 +A8I84BR+87uNAHD0ZJkTM73WdyMEGvAKBvrZK/g0VLYj0NtgkSuRJfrXnGkuh27I +ZrjfL952Q/mXgMtHhJHJ9YfenGFWSEDHnolNzKOzTQJpE01IZ3nWv7ezA9N1LZVC +iQCVAgUQMROrdRsIDEUnGa81AQEUNgQAlvyjt534RDQd2AYGoZriaFzjaL7dTCRH +4b1zxuWBNWf3pI4W0iwU02Q5rEWEmY5DLl6/ie+vcQKOWSqXVgnM/s6EARdKEN56 +d6PzkwszgfEybDYrcAxReJcTCcV8ItJer/iqpBLgtaxyUpI77NvKcDGHp6BgYpnv +1lNkH0FISK+JAJUDBRAwtzlWdGx7qH+PTVkBARFWA/99NTCMihlOZS7LmHDVic/q +H1K1DVdMcv0iL39+7Pq4+AA/ET8dWIgcjaIreSqAZTpjwU1pMPaWgecDD1rEMCYX +R+JoofLJ24BLcSlpXJ/gWMifYNxqdDeMRkw/aW/kaXQJWIz+oDYNuOyi5VvB6faF +6Lm7P5cw1mX0I5rYc3woh7QoQmVuIExhdXJpZSA8YmVuQGdvbnpvLmJlbi5hbGdy +b3VwLmNvLnVrPokAlQIFEDEXgCUbCAxFJxmvNQEBiL8D/3MLjfHGvuByqP1VFQrF +QeMNd2aIQuC7ys3lkDvrLkkPJQANua0/MdDaZk6F5pCGcTmmmaJOjcOcCheD7FU5 +w9zxkQGR3Swr3opFHSr/CkEl83jRy3oq1MFydWoGajQjIr/c23X8zr+XntPyO6VX +q5He4RrTiXeAEFBzz+J+R+EQ +=zh1u +-----END PGP PUBLIC KEY BLOCK----- + + +Type Bits KeyID Created Expires Algorithm Use +sec+ 1024 0xA99F75DD 1997-01-24 ---------- RSA Sign & Encrypt +uid Rodent of Unusual Size +uid Rodent of Unusual Size +uid Rodent of Unusual Size +uid Rodent of Unusual Size +uid Rodent of Unusual Size + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: PGPfreeware 5.0i for non-commercial use + +mQCNAzLpIyUAAAEEAN9KC8CxTeozPYJjsnhFpJ14d4Hhf2M6OTgqPQFRHOswM/3j +B7IW0s+HwVyQ5/SjIlo+8ur9X7yaj1FS2GQmKD1x9LKeHRAoosBIs33okRtoeDRy +ufTaTyQTwLklxClWm3JEef4xZioun1mtWbpz0yVEOCSZcRvtnJrNPMCpn3XdAAUR +tCtSb2RlbnQgb2YgVW51c3VhbCBTaXplIDxLZW4uQ29hckBHb2x1eC5Db20+iQCV +AwUQNiiZ2JrNPMCpn3XdAQGlgwP+JLlZvNV/fJ2azKIwjibDa4n2LUDxa7ofKboU +QL+D7FD24zQcmzmkBQm/BL/FSUtxZasJkvdVbU98N3G4h3C4AyErfQOFcrepyGAB +M88onQ1DbQ6tiUA3gw9gIB+2l1C5R8wBOtlwoRJM4GFvjjtRp+KaQqvN3f+lLMMt +hKYB70mJAJUDBRAz3QWlms08wKmfdd0BAQMfBAC1c+9gr7ELthxwzYGTB7LiBk+p +UABsPG/hT9z/cTGN8YQbK6VXV74sPAaeyD/t56xFUI9CRktZCinXp2cxvbNTe3Q0 +MLtD/PlCSRsgwsEIoM+1An1S3qOXWiGBXoXl/DgRzz9GVnB04m5/SP9XLE4Tmz+1 +X/Gu4TJnRjZZxN4xoYkAPwMFEDb44af9b4jGIdCnGxECiFUAnR3RORpXVyclwFEl +euOwoynPQbY6AJ9H5rwHnz4gkE+AVp95++HmyeDkYIkAlQMFEDb45Ogxpj2W7BQL +gQEBaS4D/R+EzfuRPiX5LgV7C70xtplIgS1iK+h0ddkPAr3P3zPxY0AEOjM81hiz +Ol2Kf0TUMhhcLqO0UjNK9EyIHpO+Bf7pQoV050XYvcIwzNyVez5VCbDM7JA+vVeG +/Pb+O/tPyEs7peSpdJAP4Kbg4Eu4b6+1QTLKrBCTWkEuNHABOuzDiQCVAwUQNzs2 +CairDeBjG1dJAQGb7AQAzHChrwaosl01sLcmlItrsqmzSFL5hbLor9Wh8UjVeYxX +FMVgTQGs/AwN1B0W8PApOsz8mg0pSJm8VPHv+pc4Z9eNhUokfUsRJ4LHjREpr3Gh ++5LoZ53nk1f62VQSOCxOOJ50cAH2rqv/ym9EVCaZ7evfHIR7/KH5+sVpcs14c/20 +KFJvZGVudCBvZiBVbnVzdWFsIFNpemUgPGNvYXJAQXBhY2hlLk9yZz6JAJUDBRA2 +KJmIms08wKmfdd0BAT3yBADEDHAn++77n7bLA/u9QYM2LBQHnXdw5Is8YGHpHcNZ +VDA8CtRTOdub8rhe9qgsid/jEry0hT9Sygfx/ry5ntjmF12ltnxBDPdZuU2DaHaI +h/zBUAv0hyaQeAXEYiV9J75GrDkTj5Jrrnd623uyIRoMZPKYb+oqsZ4HjIe/w+CD +fokAPwMFEDb44bT9b4jGIdCnGxECzDAAoNR8md7KvzarecOh/6NpTb5r8JXJAJ0a +JtTzsoNXpLaVwSMiGdm5ts2qOYkAlQMFEDb45PYxpj2W7BQLgQEBxKID/11Dft+U +eLddkIDFjaJGrIOfQ11y+QlJWaQ2Him/qNzNP8w8ZJ/meAb4PMSeQOI3PVKulf8v +Mp3Z0Jh2irfn1ycqsui4kDe6azvd5PultRKTRljtwVIDuqsrVMVq/zNAC2bN6CUn +kkdZ2O7a5qIkDDYnyRzAEwKhJxleWrXYHiIhiQCVAwUQNzs2GqirDeBjG1dJAQHc +YgP/eRCEQW5DJ6JQol5HQ26UnjBfQGdXsRvpT6gFNCDy/Nv+b886WC9j99T3IU+A +ztXfOPfPh7oU/2yC0VOmSaZS9SQ/PuuFdNhMggR8Q7goWothdBsMOUyO3iYrQCRn +V3mLNsOT+/gpSt9diLujs7SpiQeHZmQaNMQUrJPBp7tTbsa0LVJvZGVudCBvZiBV +bnVzdWFsIFNpemUgPENvYXJAUmFsZWlnaC5JQk0uQ29tPokAlQMFEDYoommazTzA +qZ913QEBZzMD/3F9tSh8IOiA+zaBsxCsbH2RP3RIERhxaeU+r85yPXzvVmWdh5iE +loxI64ucwAJl70Btp1hGBVXBdaFqYf53S4C8LD3yLGYj16Y9Sw+6KJ+TxF7yZZBX +6Rw6ohuMTjkW2xlgXL9bKpMenY5KX8ly6DA9+uWGsxbirqx6Vj8AEESSiQA/AwUQ +Nvjhv/1viMYh0KcbEQI04wCfcrpxqgqoy0oaupHCgVoI+MGA6LkAoJzV0/kcC3IW +WhAbFLZ8DAmn0OnyiQCVAwUQNvjlADGmPZbsFAuBAQFfWAP/U7/1XFenZrzKuVXa +onrEn1Td8Iv85VROuAODPD/bX2N5eCIbQIAzQClns1KqT3lpFIpmpagm9Njkr4/h +G4agwnUliNCLZ9eIJIejh8MXZE9NfGoKitCrozxywmqlDKSJRBF3od8pJRGTVZF+ +8aqLaLCIJAaKmp3SSbPJDZZISO+0LVJvZGVudCBvZiBVbnVzdWFsIFNpemUgPEtl +bi5Db2FyQE1lZXBab3IuQ29tPokAlQMFEDexh0+azTzAqZ913QEByLkD/Rt0Wjm1 +i94iNsaCFrN7Oi9CxZ6Bb/0aytDRxA8tGBJvS6nlafOhfULzgPpId8kn1T7cW8LD +ALMAJKm71jYu1Nl89FfSiZpxJyRS5ox6EwTaWoUxhU5zsXB+F/ue5gAM2wlslxbx +rE9m/KK7HrdEFag4VYcDixii5V1sw4kHa2NftCVSb2RlbnQgb2YgVW51c3VhbCBT +aXplIDxLZW5AQ29hci5Pcmc+iQCVAwUQN7Gd35rNPMCpn3XdAQHcoQQArrWwFNeS +A5Yu1nEXevfStfkSUQqzA6qsREPgrczIOgsCfDR/RA/1P7GcxiOvY5mtckuvgkP0 +A9atWkCFX4A0UzerKAKaSirUd/V6Dm8w3hOR/e66I/rbQifZoV/KqvofRsxESV4U ++uXoBsleePwhpmDarpx1BlMJrjwhDDmGaVY= +=FPho +-----END PGP PUBLIC KEY BLOCK----- + +Type Bits/KeyID Date User ID +pub 768/A0BB71C1 1997/06/03 Jim Jagielski + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.3 + +mQBtAzOUkNMAAAEDANZdTUJQPwrFI9526Qf+DEWL8dXgfhWW8o6CzewdcCoHYEpu +9CiOMD3f9bgo1VozOPceGzCu/9FF2hMLUvVsTAZkzC3rre5TtPo/vOf5HJ+ac9M7 +aqxW+gRu2/90oLtxwQAFEbQfSmltIEphZ2llbHNraSA8amltQGphZ3VORVQuY29t +PokAdQMFEDOUkNRu2/90oLtxwQEB8iEC/i9Qo55TlT8bRpcqeM3lzNDqzU9cqKRf +9X8pGJIVE5m2JPm99qPLs8RPeepLChi8ZZ+2hSfb7ldQhvVLgNqQqLpsjGtJjJOU +C+MrKDeSk2WAicg6Uo0FWCsEHxrssw139A== +=pwim +-----END PGP PUBLIC KEY BLOCK----- + +Type Bits KeyID Created Expires Algorithm Use +sec 1024 0x08C975E5 1999-04-14 ---------- DSS Sign & Encrypt +sub 2048 0x4CCDB430 1999-04-14 ---------- Diffie-Hellman +uid Jim Jagielski + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: PGPfreeware 5.5.3i + +mQGiBDcUl9QRBADl5tF8kOD0uddlnl9qsaG70/hwujGTsSXATnqoLseTsWORoVXf +oBklokEAGmT2+Cl8XIXZ31Wh+GaJ3CTbEv8Ok1vapOt+ltPgOKzZEB4uP25EbhC2 +LWf+lUoafcd2Xi0KBV4fqXqEEuDGP1TAdZ6k7NVqgpjvbJ5TdqL0LrWOOwCg/0b4 ++/p/avQr+uZRU2rdmYu/b/0D/2LnjcEqUjsslh2e9m0OgAu+gnYAmQH6Dbnp+iKl +jffWPChwIMFZd/7FnGOzYDzoqnzTFyA4VE5PHWL61V2lpHJWB21K9D6rbEcx0iYB +AHHxZQEmxSBU6PmGnbF+2P7vC0Jz9gZ5dCbjtGboYxd00/XQlZwCs8jHueTpSfx9 +n7dYBACFpW+v2pSlG0ReiS6Ult3gaGWiw81D0nFVvCp5BlxgQDymyF1MS6FbCj/g +FGILosMhlsIHTFaC0DD0LSXyN1rm0ykPvi+vULIlKNJwW7fCi+33j1Azx+zfMNeO +T5vqAfF6cvsZ6qPb9CcYvU4jEKvkovA1U3jMFehqcGkTV5sfvbQeSmltIEphZ2ll +bHNraSA8amltQGFwYWNoZS5vcmc+iQBLBBARAgALBQI3FJfUBAsDAgEACgkQizpg +HwjJdeU/8ACg3mtYerA7QN/8Okp2IgGr+ge4yKgAn09RX5UR8DyZ1/Q8OFasE6T6 +Tg2UuQINBDcUl9UQCAD2Qle3CH8IF3KiutapQvMF6PlTETlPtvFuuUs4INoBp1aj +FOmPQFXz0AfGy0OplK33TGSGSfgMg71l6RfUodNQ+PVZX9x2Uk89PY3bzpnhV5JZ +zf24rnRPxfx2vIPFRzBhznzJZv8V+bv9kV7HAarTW56NoKVyOtQa8L9GAFgr5fSI +/VhOSdvNILSd5JEHNmszbDgNRR0PfIizHHxbLY7288kjwEPwpVsYjY67VYy4XTjT +NP18F1dDox0YbN4zISy1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6ypUM2Zafq9AK +UJsCRtMIPWakXUGfnHy9iUsiGSa6q6Jew1XpMgs7AAICCACEhzcRGEc3y3/4YNaG +89FmtIRpFU5zoaZxxDrmUiS1HdhqFykv8ozaTyjfImCuhq8i6DG15oGudxPma7Ey +sCcA/qmQEBVrXFK2DYTFW3UnPyqiE822plo0d45u1csKzPvGpHYVGC4HOEKCghRy +/54nH0fsKV3VSlIXAhRG3LIstzAtslrSYELW1Lov53GK+YZpRDJTbLAxjIYB8kEY +hiQYzHm/cbBeRpjG9BpoBQh54dNOj22CU8HC4KvZSnDcLAzmDyrQFXFfffvJtQ7+ +HH2iIWKMFOjpRHh2ZK6uhJb03Yo/v+admKs1HSEFdV5VJUCkqymhKT0OiWnXmNHq +QUfliQBGBBgRAgAGBQI3FJfVAAoJEIs6YB8IyXXlME4AniogMeV3YLNf6C1Y2+k8 +F3rt0S/OAKDHF+wfxLDzCxsoQbwesIUAKgb7Hg== +=mrXV +-----END PGP PUBLIC KEY BLOCK----- + +Type Bits/KeyID Date User ID +pub 2048/DD919C31 1996/12/24 sameer@c2.net + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.3ia + +mQENAzK/QZIAAAEIALrsEjuGlt6wkHy8fx2wPSkH7paAqJHDCbO1W/GMVs41BsH1 +xpyBi9lOtUXHsDC8Obx/TES4/xVPSsFKPQLa9Q/OsxjXmEPBvQ5PZdOXJ5zmRMI1 +1cfUp2s8w6i+IS68IWRKdPMshGWFGar1YUPM1UpVME7U+uGD3wgdC4DrVJHzS5Eh +gEDyQ9FPb+8CpsRO3AvUPzsZGG8Iy/9GiLzmaJG34zZ5fv5X7sr89xiWJ21ehk+X +ePO9kvq+nzfOCCK6a3GZD4g3KJX/Pm3oKeaXeL8WSCCPzpNbtRJk3ofeN7Zm1K0L +yChPiyui+OO063/WASv52bxUIlmzbX82a92RnDEABRG0DXNhbWVlckBjMi5uZXSJ +ARUDBRAyv0GTbX82a92RnDEBAfqVB/9GSzADIVqY0faFOLN6+E3qqg3hPRLBvjgC +5cvTlwT7W64zI+aiSZuN+xAXq+3lnKtmzn45F3hD7gBxRPJbSKsObn2zU4UcqW/o +qoiYEnO9EhoBomwPUbVy8C00CWvDLfeF4L5r+2oXgilTsCojSaWJX0QoPCwRQao1 +YwZ6CqAA78vdbBNkmA0WrPsVqwd3ijgFapcX671AqiT+pDbvK646I6uGPXJzN3ZU +vFuDim9D2uNk9CfvPhKGscr4qqP40TnNn5fjSsmrFyFxYsdwo7I4TFpnsEPOw226 +GU+TR7zdwnByP72AxPEBJ/F22LwNyreuph+fRpWCnCf+9gVW9Heh +=jS5Z +-----END PGP PUBLIC KEY BLOCK----- + + =========================== +Rob Hartill + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.2 + +mQCNAzG6VfMAAAEEAOvtvphFG/D02vGLENBl5OVPgEJgP9E1xhUgKTZnJstv30kD +h1IqeIBkEAy5bpKapCbvvxukyQErhB0efTi2v5yTAlz5pVjgWM5Sa8CyTXJmXPHH +EuOfy1DqaiQSmZ6KWX0ygw3gKDZMiNMf06UURLLYtRlGKSYY3WVj2u2UCmS9AAUR +tB5Sb2JlcnQgSGFydGlsbCA8cm9iaEBpbWRiLmNvbT6JAJUDBRAx5eIAZWPa7ZQK +ZL0BAU2XBACXfopMzC8kW3KEqq+N9W9fkGNgy//8XqQ77FmfPQPbO4X7Zn3cyO46 +MxvPP+92zSyN3dyj/xWZYoRLwll+ync9d4KUFwKw45DALAvz1CKHMOpQPD7dIWdE +9poJQrcbKeOqLcGZTu/hY90gWBUZ++9umR8X8lyh/WEgcUolfgYHew== +=upYh +-----END PGP PUBLIC KEY BLOCK----- + +Type Bits/KeyID Date User ID +pub 1024/631B5749 1996/06/21 Randy Terbush + Randy Terbush + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.3ia + +mQCNAzHLBS8AAAEEANGFXb9o0NPVfVjSLvQh1j3fN6cMeVNA5BGUJ6HZGP/NDxTE +i8hwejJqakkU4ux/g6Kqckrx3h8WR7OXZZ+R8CsA0bg9Sr42ndEQCUISgArg+lXZ +gRUniARPPA7tamTSq8v1mnxqy9s26Ht2rAG2D6IiK/7v0JlezKirDeBjG1dJAAUR +tCFSYW5keSBUZXJidXNoIDxyYW5keUB6eXp6eXZhLmNvbT6JAJUDBRAxywUwqKsN +4GMbV0kBAegnA/sH63WyfwMFmn3nWe8T/5IXO/QkMYoMGLS1i7IxMY9O8BVvKQM+ +oxEcJdFAG7zPZkpgKzTBxmExz5hMZ9hwJ42XhrslWoP7JVvADJcdthrUAYW9W+jx +GcDYAW3qW5DpKsQchfvXq9QOBDxP+Kbbe2B8xGEyGUhLkacISFTrIhhQSrQiUmFu +ZHkgVGVyYnVzaCA8cmFuZHlAY292YWxlbnQubmV0PokAlQMFEDXwEhioqw3gYxtX +SQEBnaED/1AJCYW7jKCtBaZZLhp5TRtYSQxBMTmT2b4bDE4mbTb0VtDgpfrp5yOu +xTtJxiQ53jIenv58qYLMhVBUsuMjWjnTVtNF6531n0T6v/K0ByNmUqKwStH/8qLX +i+I4VWinALYcSOZDxranDey+1oVyw0NpvJMFFEhF0fmPRlSpaq5c +=x5FB +-----END PGP PUBLIC KEY BLOCK----- + +Type Bits/KeyID Date User ID +pub 1024/49A563D9 1997/02/24 Mark Cox + Mark Cox + Mark Cox + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.3ia + +mQCNAzMRY/IAAAEEAOloTOU0f4w7FDRMM6kA/6XazXxJ/HH8dsmb6E7RuYfVlXsd +kCwxUBOkyW+AYhkHbYUwnB5qBoFUyLrbLGuwKHW1KnAwgbeZLTH5nqQLpA0RLGVZ +v3tzImKUdyyxBphZWC4IeEgUbl9cc+piOsEJ8QzF7gnqwWo/Ku6tTP1JpWPZAAUR +tBdNYXJrIENveCA8bWFya0Bhd2UuY29tPokAlQMFEDQvYTHurUz9SaVj2QEB/hMD +/ix6pAa+4ZgFQNRAc7fC+I4uGWvXoI8N8wtgiJi//8Kc1vjtvTylLPKVBDsy1ihs +bVOjD3NUEkH95TNI3QhVeCwJPl2e3GgFl253hj8Jai9snHj75pXjQXq0NxQ/JRSr +EAqrFM7+yRLPs7zDwsMoc2Ox5emq4joVa3syZUEwW7LxtBZNYXJrIENveCA8bWNv +eEBjMi5uZXQ+iQCVAwUQNHKlBO6tTP1JpWPZAQEA8QP9HSjVMLohfOVO0tHcLRDB +eDfnRnBxgTeF7P2u8qB+eOeLqBzHNmE/gROWuZXOpkxeCqT0GG3oXqmSEmVOtDsJ +K92sKvtTdJOAGq95UQI3t1Ix6iNHkVJfo11RkJyU2iL6XFR1953nS33xKGdbU6v7 +5KVCu3JTe1kDEDOyMVDdRmW0GU1hcmsgQ294IDxtYXJrQHVrd2ViLmNvbT6JAJUD +BRAzEWPy7q1M/UmlY9kBAfN5A/43SdANs/NZ6ouyxAvKEWSPDnNkHI3rSPynbn7o +kSrtFeCQ3Vwe0B0fkszBEAZ9zbnx/s/1LKnriUfyzhdZhJfkZfxgDwy6s6smagYW +smz/LFaeDzG3Ej20VSe6ghseqcPscJL06PUg13LJC4LFlgYcCDEeGl81Nm37fe0x +IUhlNA== +=k8vP +-----END PGP PUBLIC KEY BLOCK----- + +Type Bits/KeyID Date User ID +pub 1024/2F90A69D 1997/02/24 Paul Sutton + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.3ia + +mQCNAzMRsB0AAAEEAKj2XYYEGcZhT69x4gskQ3xz+KMTLn7gKSqqcyyeinJ0ZjLl +6AJjb1/68nGsF+IIY+IJS+5smq8do1qpC3UZcmw423Sg8F71GeqDO4HZXOAOieVy +rpVs6S5TaXlJOcrC7zZCx+iql97+xJFjUGkkS7j/jIkx1AajzMNkSr0vkKadAAUR +tBxQYXVsIFN1dHRvbiA8cGF1bEB1a3dlYi5jb20+iQCVAwUQMxGwHcNkSr0vkKad +AQGrigP9F43zbiOigYel+JCMiB0HK/UdqSrf3xWxHIKWKNhQNjhnyeF+jKQwFld6 +7KQYsqZIpHsWLWmSk0AmKQOUIw+DxclDxBL2dT4p+CjgTgIAcbvPpahWkBAw/E+c +EGTiYbe+Y3sHJhhP+d0TOLmsETG9tpi7gFZ6FfNcWPxFMdxGrf4= +=0jQW +-----END PGP PUBLIC KEY BLOCK----- + +Type bits/keyID Date User ID +pub 1024/BA20321D 1997/06/05 Chuck Murcko + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.2 + +mQCNAzOW7moAAAEEAMYZlNOxWCjLR/PosadbG+xsrB2unid2LiYoakTFiDIBaZjx +bu6hNmVZPYfKOXQcqrCu0EY3uVLP/L89bST5pfIZOzz8GTm33zrETgfzpXYyFdbX +eZ5vc6aa3+7zmI7h/aU567P9ruB2C/RBLl1A59wmPRRVvjEIAkI4bAO6IDIdAAUR +tCBDaHVjayBNdXJja28gPGNodWNrQHRvcHNhaWwub3JnPg== +=vUdL +-----END PGP PUBLIC KEY BLOCK----- + +Type Bits/KeyID Date User ID +pub 1024/26BB437D 1997/04/28 Ralf S. Engelschall + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.3ia + +mQCNAzNko/QAAAEEANZ2kpN/oMkz4tqzxvKPZws/XwsD0Y+E5/y7P2DIw4uHS/4N +syQbgkdrZhPBlXDv68DQioHXWsb904qyr7iZB1LC5ItK9MgqlK+Z2mvPqsGbHM8J ++oYib8kf2zJ6HvrYrP7NYB0tN9YYum2ICtx+hIi6aKGXdB1ATA5erwYmu0N9AAUR +tClSYWxmIFMuIEVuZ2Vsc2NoYWxsIDxyc2VAZW5nZWxzY2hhbGwuY29tPokAlQMF +EDNko/QOXq8GJrtDfQEBKVoD/2K/+4pcwhxok+FkuLwC5Pnuh/1oeOYHiKYwx0Z3 +p09RLvDtNldr6VD+aL9JltxdPTARzZ8M50UqoF9jMr25GifheFYhilww41OVZA3e +cLXlLgda1+t0vWs3Eg/i2b0arQQDaIq7PeRdjdEDgwnG4xBaqaAqfgxwOXJ+LPWF +hiXZ +=K7lL +-----END PGP PUBLIC KEY BLOCK----- + +Type bits/keyID Date User ID +pub 1024/45B91DF1 1996/03/02 Doug MacEachern + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.2 + +mQCNAzE4lesAAAEEAKJYS1vL2iB3owwiZdCxp3JyvSNaC7h1p2jQXcJvY10gqyZm +VffDwFoSvJM1JdCx3o1mb3JpZ2OTV4SrDDkzcSpTXelgyh7k9O3HB7oG6pHTML9g +Dq9ZKydShMIvIJos7KuLWoM/eeeejtkv7r/gWsGHAyKbT8fs3r7nlmxFuR3xAAUX +tB9Eb3VnIE1hY0VhY2hlcm4gPGRvdWdtQG9zZi5vcmc+ +=yaR9 +-----END PGP PUBLIC KEY BLOCK----- + +Type Bits/KeyID Date User ID +pub 1023/163751F5 1997/08/18 Dean Gaudet + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.3a + +mQCNAzP30QgAAAED/1k8hPKsJj8Il/TfhP1JIRGwnXuzfQ/etv+MZJMzeNeKa8OX +Kw0d4e1S/KdJ+AZwWQp3ZMDoX2ghZ79X4DDDLEAc/Fmy0Gg8t89CP+xJk7b4EHjk +F7HX69BRJp3On4aRTXRND3WviqEmn5ppzbBkTenF9WWudLRbqrc4NnoWN1H1AAUR +tCBEZWFuIEdhdWRldCA8ZGdhdWRldEBhcmN0aWMub3JnPokAlQMFEDP30Qm3ODZ6 +FjdR9QEB9VQD/0+zumFj1zzYZ1+bS9Az36gijDUb8rlEVf/lBShx4VEvha8fsRRy +vkwnmJyupYvGtrSIYAwB0VK+GZPZa7XfZvUCM83AZY9vGpE0LwW2Vcz9kWZdJ0t+ +B7zJElmBUrmj9aW6ICmSNbOBwVo1Y7hg6lPSFFMOOECFpT1WuTXXYpNA +=KWcF +-----END PGP PUBLIC KEY BLOCK----- + + +Type bits/keyID Date User ID +pub 1024/EE65E321 1998/10/22 Martin Kraemer +sig BB1D9F6D ct magazine CERTIFICATE +sig E2449019 Martin Kraemer +sig EE65E321 Martin Kraemer +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.2 + +mQCNAzYvawcAAAEEAO/lLOQVYsUS+l7yan+Rzr0ehfWRqlgeNsV4DQ0xTuQewD9K +5lm7ujRwutxlNaf5dXjE24mlsiRN8KDp+fKwm7Wtqv490xmhzS/6y8ekwB02P4fi +/JJNX1PbLS0cL6+bz2dFqLDhh03Ovz3G16Y9he5mrJ2PNOWa9Dfj9F/uZeMhAAUR +tCJNYXJ0aW4gS3JhZW1lciA8bWFydGluQGFwYWNoZS5vcmc+iQCVAwUQNkcAbUS4 +3da7HZ9tAQFUnAP+PrKa3YFKp9XTrANmORex4kOyNpM1adS8zM6bTcHyIkH4WitB +b2nRbqOdOuSwbh655aSStluIxY66CValeL+6E7MCEqQ/UlzzMVmdbMyWSYwDlkV3 +gQkg3vE6bgFlWlLLr2HnkllY3ISEChDWh8x7fRKLy+8ZBGW89ZXOGkhIb9mJAJUD +BRA2L2ueKwLDReJEkBkBAbeGBACKM1FCmQC583/IHyw7rDlvnsZKeKvdbbLGSnmJ +NWOyf4VgkC8OCKmwPnWLOOIK44/JsT2Yonih2r+04FBqYo6SsMgBqOBJqKktHvtx +bD3VfUUkkV8kZ4ituecWTx0zj1Oa0QiCiv8HHvdsmQB0mj07mWQz1CamXPSwHYn+ +t+fJOIkAlQMFEDYva2c34/Rf7mXjIQEBcNQEAOrt4+o2LwcCiJp3bOF9WZMirpMQ +QJISqXBnom3r2eB+k1a/Jig1sePSzPxneW9EgWIrWg0EfK+u2kMgvTJynDUux9zL +4qnECmZT+ESEm+P8rPKeecOfUHgDjQlTUCneOX5p0TbdvJm+TcJVjXjoVrYv6hZg +InYw+jlvF5e/sdI8 +=03LU +-----END PGP PUBLIC KEY BLOCK----- + + +Type Bits/KeyID Date User ID +pub 1024/EC140B81 1997/04/10 Dirk-Willem van Gulik + Dirk-Willem van Gulik + Dirk-Willem van Gulik + Dirk-Willem van Gulik + Dirk-Willem van Gulik + Dirk-Willem van Gulik + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.3i + +mQCNAzNNOsMAAAEEAJmwazRhNJB4mQkvp0rrxLkeOAxR9fGBXgJNa6HHdLv7YHwx +mwMorHYDCAMypO1yuznNTaMVT1z3cS+yqhOkTVxwNI1mxW6Zts1kOJB9pWuU33sk +sUuCkLHXMgyvP9cms6gcYgB5g3UP6M/aQ4T017+Gk/7crlH87DGmPZbsFAuBAAUR +tCxEaXJrLVdpbGxlbSB2YW4gR3VsaWsgPGRpcmt4QHdlYndlYXZpbmcub3JnPokA +lQMFEDRZ5+0xpj2W7BQLgQEB/KAD/1xniFNLHp+jxIVrEL6HcI06QZUYPvRuarWq +3aI2gdeXej59Ry96MOo2MU3MsuQ+wW+6gEJAuyCp2jyYfzF/8winNcFWc738s/hX +fRYCJe4bvtMcnhBV7GAlTgyw00fcrnaJaQ811+QwKnZvXXWb+QuoXC4ddTon25w4 +XHLjtDZHtCxEaXJrLVdpbGxlbSB2YW4gR3VsaWsgPERpcmsudmFuR3VsaWtAanJj +Lml0PokAlQMFEDNNOsMxpj2W7BQLgQEBzW8EAItAEaeuIzPIVlKOk1LnHlYc4FyW +aiNJC2+rRmftYu2bIp/JFuXu3xC0U0byyHu0p+Y1pcAnt2YrqmYUfM0d2cx1b4+L +8RQR4SGKhq9jWKS3icfKoyMnGiD2CeI8/Xx8V6b8Xg0QqsdlS0kz//qGCDWMz0vi +oxzasVEvFjqAse03tCtEaXJrLVdpbGxlbSB2YW4gR3VsaWsgPGRpcmt4QHdlYndl +YXZpbmcubmw+iQCVAwUQNFnn1DGmPZbsFAuBAQE0vAP/aOb/rXsE256tpi0+CRp6 +cd9b1oBmw894UK+Cf4DeNHWehPWJog4y0eNFUcAMdLIdubDzc6Kfxw5QyJt2EAXr +05XuJ2DJdG24S/aPzGq+6VzL7Nq7pylXuhrACTgeesaceEpUd/NeOCOyzNR7i8qM +zbGFtU7fH1ipfJjN6fXLo5K0JERpcmstV2lsbGVtIHZhbiBHdWxpayA8ZGlya3hA +ZGRzLm5sPokAlQMFEDRZ58Expj2W7BQLgQEBGRwD/jdUjCJXFcAbjx3Y2pWUkR7C +hwJTohM2TvhFp80Ffbhh1xT961XGuHL5l41fRAIg9FEHjQKNVfXeisLH68Qh73cF +5xuNE6c1x1VSqfDLl9fXZ6TA35qt0G599T67jmVai4F/LjHWDI1O6UvPRuZE3O7m +eRaCfbPLAJ1ztFujtS3btClEaXJrLVdpbGxlbSB2YW4gR3VsaWsgPGRpcmt4QGJp +Z2Zvb3QuY29tPokAlQMFEDRZ56Qxpj2W7BQLgQEBvOED/1LhhPP5OkeCCEMVnmyZ +jZexzv6XOH2I5qH0iuozsI987sSK+zfv8O0wEBwjUOQqBuzlvjKImYQ/oqR89egQ +AinPc4z1b3kgeGyqrmtea6ScmpKufcWUBbhH0qsXF41eU3ArKY4kB9znV+/PacCe +VrOD8roFaxIDZ2nW9FS0mriOtC5EaXJrLVdpbGxlbSB2YW4gR3VsaWsgPGRpcmt4 +QHRlY2hub2xvZ2lzdC5jb20+iQCVAwUQNFnnjTGmPZbsFAuBAQEaHwP/Q2Rs6MIu +z8all/xildFOPfRAX73InwBeInr1O4UU4l6yWRvuLkg+m6O8eJSHo21SNZBCu9gM +FoQsd0jVOitUr8+w2WkypBlJo5wl1nCw/1sLU4AxtBb0jyADvJzxFCeje/FkxEvs +6Y3eLxpJRBylbg6KFOsmSY46DyGc49B6cZo= +=xUw/ +-----END PGP PUBLIC KEY BLOCK----- + +Type Bits KeyID Created Expires Algorithm Use +sec+ 1024 0xF08E012A 1998-02-19 ---------- DSS Sign & Encrypt +sub 2048 0xD8F8125A 1998-02-19 ---------- Diffie-Hellman +uid Dean Gaudet +uid Dean Gaudet +uid Dean Gaudet + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: PGPfreeware 5.0i for non-commercial use + +mQGiBDTsCJkRBADJmDUiJL0xUaxg0yw7+VqqFUL6sjWxZeZ7kQZs4dyN3R1ilBUG +KmOXE6qSfb6Pi0qEmgCz1K7g1KaglMRrpANY4h1CjziEVmTH5s3ocxe77w2uaou1 +gHJERIqQuC4/z0DwFqq61ZVf5dUQTD8OmfOwG4pFs51Si9WS03ueVEFQFwCg/9Z2 +j6UzCLyUABpWeV1v4m0w82kEAK96GyKDcT20TymKJnMKuwya+ZwqrULH3Sdi2Mwi +1GOH7aomG2fK4D2yxWx5xTiYhmYNnRoopgu/Kv5a4x43tOKS3zeADMnHIw9dMSn9 +4Kba8vfKbZnlOgt9veV+iWZv7N2aS2z7w/i53Y6LAlV1hAIMvGJ3zLfmShZs0LDI +Ya18A/wNcdJazUk9mLGIoycCYOk5YhWL9sCaCBdmdfDPu++rLnqROSWkmfYkOTt+ +pG9SPnvv3XrX/SEwM8gYfpbZwrFDJFI9W63lc9hdSosFD+8xiRl6h2gKRwWvc1Ry +xIt3+gUrZxovNxBOv98BoSf/j3lkldU+ZjDGlCplRHSndxlN/bQgRGVhbiBHYXVk +ZXQgPGRnYXVkZXRAYXJjdGljLm9yZz6JAEsEEBECAAsFAjTsCJkECwMBAgAKCRB9 +bb/R8I4BKqqzAKDc/4H9iOXJxVE0yCEHeTQ2gAHfhgCg7VSq7eNhiJhBgblQav/R +XOhaHj20JkRlYW4gR2F1ZGV0IDxkZ2F1ZGV0LWRqZzIwQGFyY3RpYy5vcmc+iQBL +BBARAgALBQI07AjSBAsDAQIACgkQfW2/0fCOASoWOACfb+8OVvy6FCqN2MxdCqp6 +gffNbYgAoOxlTa4NjCUUO9dfLFFYpDfGrRy7tCBEZWFuIEdhdWRldCA8ZGdhdWRl +dEBhcGFjaGUub3JnPokASwQQEQIACwUCNOwI/gQLAwECAAoJEH1tv9HwjgEqiC8A +oJDu1HTuGOfChFSJJ31XvV8tnlo5AKCFceck4veIMP8pDC0f5UBGGC3mZLkCDQQ0 +7AiZEAgA9kJXtwh/CBdyorrWqULzBej5UxE5T7bxbrlLOCDaAadWoxTpj0BV89AH +xstDqZSt90xkhkn4DIO9ZekX1KHTUPj1WV/cdlJPPT2N286Z4VeSWc39uK50T8X8 +dryDxUcwYc58yWb/Ffm7/ZFexwGq01uejaClcjrUGvC/RgBYK+X0iP1YTknbzSC0 +neSRBzZrM2w4DUUdD3yIsxx8Wy2O9vPJI8BD8KVbGI2Ou1WMuF040zT9fBdXQ6Md +GGzeMyEstSr/POGxKUAYEY18hKcKctaGxAMZyAcpesqVDNmWn6vQClCbAkbTCD1m +pF1Bn5x8vYlLIhkmuquiXsNV6TILOwACAggAhb3cBmR67H4+9Rj4FeTwJ8kflX6I +pp2AeXXZiffiPVBv5cGzGn2RkGPAZqbp2AkrCb4TrJH//1GPdR8VmPeEGsm6u0uT +0M404l/4IW1FFQ4JBpTENPn4NYBHkKBNkPcls/ip0lSjlmLGVQVOtDOaFD7n44xV +hT4WpptCripg/5kymDmK9c8hv6rPUvNoVrDdWR4//MCvNAZvGq2bZGdFTyd5Tn6D +AmwbvL/UwgiDnm95qBBfCZtmGkkFaoOePtBevWFaviFZM2pErPRcjY8A/1cZsycj +JPMFYqBKGDIk76ulDSjU0Q8dqhCEDf0o2oQEg6msjDtetVFEDw9yJe0AGIkAPwMF +GDTsCJl9bb/R8I4BKhECBKgAoNRtRaRMdYNwajSO7056eKazCGSDAKDShamaRjAe +ThQ1KefmJKyzfcosZQ== +=25Cv +-----END PGP PUBLIC KEY BLOCK----- + + +Type Bits/KeyID Date User ID +pub 999/F88341D9 1994/11/08 Lars Eilebrecht + Lars Eilebrecht + Lars Eilebrecht + Lars Eilebrecht + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.3ia + +mQCKAi6+wOsAAAED53PJgrIYS7iHbZn0ycrnzS03fwvwsDpoAVouoqqBSVNoVXH+ +lL+8HzX/fADvNyk1lYi5kTiYR2meKB1p0qpvj4bQ8ZEmcBemhV0FbESJ4CxIgy6V +euxOD3v9gauyf1u4lkfyLIsCepuJqpkH+aOviE9VhTcE/D6Pt/L4g0HZAAURtCRM +YXJzIEVpbGVicmVjaHQgPGxhcnNAaHlwZXJyZWFsLm9yZz6JAJUDBRA3pN73pBlG +R0SoBbUBAahrA/9/Pyd+R/2vz0is/Tuu6aniMYb5O09OWypVtJ+1QB0Hr2pTB7MR +Spb8ljpMTT+Mv+hE9RZm0lxwW6OgYbosrDCwpw39Tfs89UjFJMmCj+UyThmpt52k +g3MkcRD7C7J0w+RVV+EPs67vLya3wKRRXKa5i3I1RlznleiJwxxGAgaxOokAlAMF +EzeoM6P9LZCSqJB7JQEB9XYD9R+ZzFmtJuclCbKR7zZcB/5lqpbmuDRMStAaBIq7 +KZ019tbuyj8RGdc04UFBAVL31pwHl2hrBTsCw0ZsVudvRg1ufn9KwNQnmO4j9fbE +fYJ1gNDgTaf0zMZ5KdKAhNtw0Wx8tAntvqjcxM//h4lSMn8HWiYlRqNFSxRT0nGT +CxqJAJMDBRA3peHbT37mpPWwmrUBAXpIA+kBT2YJm3tep61cxMn64OlY+i/OOt05 +Of+fcJwPwD4q0hxXCeWMYSueDvavvJG4+42T1O8xLPCeR6cqe8PBtXlRbyY4b6cI +mFRuOsFlqEtpXNmJ9AY2KIU8bhZBuzckS6oXGxbM40PiXsIwREib3J5OY6G4YG23 +8LpTheINpKmJAJUDBRA3nOBupMNFzIvCD00BAXGEA/98Rkn6Ncn9BgFUJlLskcsw +Bn45IJhIJtLYIqyjSWZY9iGPU41txPPcqi2k2atn03ThUufQc4V1R6pnLZwijeoA +pd3AuXv7o0wRj/zi9lrhpQpE5L/9YzJ+uGkHTMjMBSks74IR87QVebdMxSvFYBPK +QbwAVohgOBdZyNYyiCn3SokBFQMFEDecWF2urbkCPI45bQEBc40IAJ7NUAL5a5Bh +qUDf60pLZlYonowEbAnnkT+0pnp70JD1w4+bi1dSa/iboU4Kedf9tqGnPlC6LhN+ +uPWSyJcZ4AxkyhBPoezUdpKDYxezLbSlnsWPpjSHo2iYani7uSDFjppTq5vmmkPW +lW2NuI9DvXtDS6UnHJa31CqvVl60vmuyQyceI75UK/Qe4kZRgfFQsLrCWpiw6fLu +KB9NWm5wVt09ZN4U3Zo7eSNVZfSSqzkPKgXR21yD79Qs66PxjM+SH6PrbD6UEtkW +llB42nzdiQ/8MGNCFLgnaYqUkLe58Y2oicWy7OxC+wWPxuvCW64TF8uGkDlF8ors +J5DTX6c57HqJAJUDBRA3ovk3JBRJVbhWhOUBAWmRA/92NqJsbkEExxDNrAeQB5Y0 +draruR6h4BTWreJtFH4WitgnqOvU8ylveGLMLiv/cZKRmZuDaBncoQ+mdCMOeZNB +qW0xGKS4nm+rTw7LlG0DjyO/fDTe8LXdQBxR5hDcm+ynfH/Q16x2Nov7DO9NBvkq +vvp/nj2KzGH8wrgsHFzOkIkBFQIFEzeOINlR6m16P5LTsQEBE2cH/00BLuWwe/bX +DqL9+qxsx+Ko53cuJj6ZLwc7UU/YKEW4/9q7EVG3slfbl4aPWWURH5XCpn0iDpKc +fEvgsbGe6yEoxpDQkj2fTnU9z1B7aitb2u/a1NMhdgNBOHvU0p9dVlaanqsGG0zV +KE2yxZOa5R7H27PESjK2vT0NxljuUV0zV65oQgb3zT8a1DNnpvbVcPskTSrPiecm +p8B3sH0OdG9mCAEfO2QDLcg9+XDOH7M1BvH/x6eo3ccj4TUAIx0GCz3LsEenAxkw +18Bgdu25jhBcjdgNj1yvEbD/+vc6iL3HkuPbDt2jtc25QVRNPYtMDPVOXCzRovAJ +WOEMaLb74hiJAJUCBRA3jiC/xEaR6Lw5pc0BAZshBACeTZNGRkwDJC4BKFan90qG +RCAxkzFCVxyFjetBqwkeFsWM4E1dKxPoObjR0lrsXt+IbxZ0xUQB6yquCyIWZvyl +v4y77ZxBfklHQwOZimA1rinxgOsZozdAJY5OztaScc5fKEDmMGlbc8Kn0UL7k3+p +FOF+XuMktL3ZUt9nyEbU0YkBFQMFEDeOS7Cec+sKTVjuUQEB4I0H/Aw3vqOo4y12 +XODHVnRiRcZ4fRunqF5KsqHdBuf3Bh8fH99iwlIV6rj7Rdod9OjE10ARCvoxiaYj +Ev+DF88+xam77IkDks0IGU3ou+c2RjPI9h189FWG8q5m04ZcHtvo3GnGvmgaD5wd +setAM/xg4279gktoUi/o/Xi6DpJ0mx0VBOuTVwnVEKoCUWJtWrOjVEF4teSrI8n4 +Mb+Y/Cche/iu8l3t9fnny90RfOg1r6jSJi7wy9XSgVangSCjWlrn/gbYmsH7wb2B +9BUfsiEu2HAZVAIGuOZeU0nqDl4Z91aMK8scVBKBHmeST7dYB6KqXyQaGmDDsxU2 +5ks5GBPChuOJARUDBRA3jOyQaxYS8X0sCakBAd2hCAChV00lh5v4uicK+hHrL6uz +FI0KgtehTYBLC21EW++q3g4UtVw5bg4ksGgM0cN3T2O3VJ+OIeYp2aW0DUTGVymF +SZ7Ezt+J+YTq1PeDVpqWI16z/qvyGCJwNLWU39QnX9gYPTfoB0bYTCqnp1CZ6l/n +E4skqiryJCyoy/icDBsErz8WkPS7R5mJlNtmO9T0WSh6w6AXQrsKKorl1p/dcyYM +Fr+ggJ7fq1xzufnUdRi+S8rWQbIqcgIKIrGrSaHqKkf4zIHn1QBJO5HomHmLT5pp +d6SUbXCnTFDk05uSmZHT4g4/wyqhxkWlGtyTMjDluboRUIFXR3Q1cvBMiZII0r4S +iQCVAwUQN4uW+cmGeh06atyFAQFuigP6AltjOGhRcEg5rc3wrSZqk6fpVucw9qhh +QKPv5aBTWtIJdIQy1mls00V4QjPW2PFGWpQJSl0ZXTLIgrr/rlBQRziJ8WFMmLhE +c/TH1ZUSfC3P2YMd9rWxIA6Nk4c7qDmR7bYE6cvndRCEws5NCmvpigY+30tVXBU5 +bK1zgVmR/E+JARUDBRM3ieTK4clqXikoFOUBAUjKB/9FstalvSqDeMHbcYdRiC5x +AyDA5fU6ZY1keaTSQY9qPCVfHji87wbJge2kmIxA+ldpQQQB7t3z7ktPV25o29dk +aZpRHllDfzGd7heJPBC0DXEIXu3XZRUG19Baxt2VZ8JA/v/bzL1o/i/sLTEvDk4q +OeB6LZrvRcK7COFYlSByZXmWcbZGV39qzykG+NxrfXqOwz4NZqebewj3e0cQ/cGv +csRnh2IsMMfWXDOfioUgLsYQzuVP9imGhRtYzkIf0vf5A+YRBBXLvrAmp3qpJqLm +D0pSYYGXxwbGEfLqXa2lbjDToRfDvyGfFtgen1AfgaUIKiqRVTRCvxf9ZuvQXiac +iQCSAwUQN4UudD6Pt/L4g0HZAQGagQPjBZRiXtA4UeXk+J1zYjYKf6dq//K9Fi7z +9U4obGoY0e0k1OcOGWEa5DWhl3vftOaiWejmU4gXveYcdVCly6fNoX1T8EAmu2Dt +/qFxyZ8RSWb+ncTqYGM1PFVWmvJBmDfz4zg88gNLnIfxzYravVCvBpaSRjhouBPY +BegjWUu0IUxhcnMgRWlsZWJyZWNodCA8c2Z4QHVuaXgtYWcub3JnPokAlQMFEzeo +M+39LZCSqJB7JQEBpE8D/AunAbzd6eYOmNwVXWh6krunrxduJrLPMwBye0H2g1nH +Vvhoo9q17Drfl72Lo/Ku2Gs19TVp+KLNk6vcol8ULAdQYftPhIUF8Hf2D2dARMlv +jLr+fQoYYRS1GX9OoEN4G8PntE0P2aGplVuf45mUpEFaPYwW22FjFykBw7SFp/7i +iQA/AwUQN4pfglbmlud7DA+mEQI0xgCfdPIVdT687G5021a/3W0GWJF65JQAnRba +oZFy2n6HDJobnSOyEHHHI5E4iQEVAwUQN5TIi66tuQI8jjltAQELnQf+OcWrzHw8 +C+StgCtQmRJpMFEC6iSfnuBTAp09LFIWdXzuGI/xxyfDGAWdUBwH8mMhO7wqJ1Mx +suptpeGpk+bif13Im6G61DJU0gtZypfe/r6cvG1DojE1esU+4sP78ZD1+bWBjkSb +NE/YT6gqiftok/TsKvm8Ry9WwRHvRZBMQ3Y0ETtDzAQAojY74Ct6TdGz2rp2CDXj +6zY0dt5NnHfdPjNFwCgiIGgvSwzwfyXgOB2fap7aHwqdEKZcwSjjpNolSmH/lxlR +IrERjxGqEWGqDEDtP3q6xC6MmNq94002/hbUfLGnmZg7DT4h62ZW162XAVl8+qWV +cmNTlRyg4NRz9YkBFQIFEzeJ+2pR6m16P5LTsQEBnlUH/ROK2rG+VFiE1o5oipaH +oHMJAPmGCfnBlEBMPxLbRa20BEWVbQu6t8oTxhpVEXL7pCcsZIIZ01o+tiAbRAPj +kOkTXTqi5qkHOAqqglneBr6BnbZnNiCRxKdhtJPqZJ6BbPY8xhEw0VvvAfvpjT3m +SbskaRVhyi1q7BAn24JgiGKq/4uxw7wZ3Ew1i1nT5SlE+KfEuPk+nJz8e1nTTmFL +pgk/9U283uXm+8OH14Xlsz+/xFfo8h8Tu8jsNvOhyA+ScgfVP8HAEdnbqDSqReOy +PcgJL+10f7iwG2jZjYLHHOZZmSlrk5zgZK5XRSiBQlif7kQO3gk6uGmVRh0AZvHL +nfKJAJUCBRA3ifqcxEaR6Lw5pc0BAZ5JA/9oB8luDaIxEDGe3nqccMtSSgAyCeEw +YukeN0cZU/R9k3lsV/QpzsVJ4LSTFvb7gH/zNdYGOq93NMYD5AFVAr2mXC/znwWt +HD+kxUXEMksSWU8hasnm90Q4MIPmlp2kTRuF7gg8e+wPGB/wkGWdc9d4R6bRPrtu +mTHvKOsAvqieKIkAlQMFEDYpHBmazTzAqZ913QEBKhID/1nDIBaKVck0xaxXQp/J +R4dnsKwUD38pCLEu2lIfyKPitotqyvqu6txJySt346JAo9AbT9NJdIAQ/uy5q1Xp +dNMsQUcluapyFNlcxJqnDEVYYvF0b5u4KI65XFuminhmgrPbFv4a117J4Ov7/+AU +v7BsSqVkxd+/CDMELFw4z+1liQCSAwUQM80O2D6Pt/L4g0HZAQHGlwPnbvChyY3a +MfEKSYiYgP5gxUXyDVGKPcITL6gsBmKI1ZJHGPaVZMeGxVle3MXnf4APv2smqsWF +lQLH5bq8bjq4sy67f9WmcR+rZCwPR3rMhS9IMUjGzL+ziSfK+B8x5dzMeZvu+MZs +azI/2aqMDI3sxRyqAEEA0fgdf0JJE3y0IUxhcnMgRWlsZWJyZWNodCA8bGFyc0Bh +cGFjaGUub3JnPokAlQMFEzeoNAP9LZCSqJB7JQEBoyYD+wXn4TqjNwDe+7JGRng/ +4TXtjYnzCrdeoEmc3b5LCtv4MadCSOfeBvDA7ZwXcEooKXvd/M4B4o6QA4SqUcJU +5pDqdgP7nFD3IRzx/8XRy+OODciAPHrmZUelNIQ2S3vMkjpjjUf0/lQ1jVWiGllm +lxCNe7+O+q+iCJOVsN64Er72iQCSAwUQN4UuKD6Pt/L4g0HZAQFWvQPmPTlwE9If +rBcb6afTEb6hWewTcwLZckphgwNjcuDBccv193gl8MOhPG+wFv2c+jKwndV19NvH +eB0r1HE0+lYqLxQI0DTGZTVGDfyQBJMKBOMLOdB5Qk12gNOXC7F8Ulhx9w/LlBs3 +1MRsl3e6TY5JyzclPP8qNSI1DhBBBzS0LUxhcnMgRWlsZWJyZWNodCA8TGFycy5F +aWxlYnJlY2h0QHVuaXgtYWcub3JnPokAlQMFEzeoNBb9LZCSqJB7JQEBWagD/RFh +QOAq9BlODMwwHaWhJfA7lc7aG/kLVhUoMwLWfP6WJ26BP4A1nr/zgxs8YfPVoO6j +gQNW7umWrVLVEfSjhFNFvQ83qa7Uj0PZ5quw2IwaPhL8a0WVF68TNp4idZKbtd8z +NJ9rYBJp++kXUUNsAAH5p86he3tT6SEee7YNtNYTiQA/AwUQN4pfkVbmlud7DA+m +EQJw3ACaAvmnV6/Zb1fJATLrKUC2BrZcEaAAoP2dC+NFgYGECMLpAnZVaU61Zz6G +iQEVAwUQN5TIi66tuQI8jjltAQFtfAf/Xx7ao4FjWI0Vhs2rF8B0oi3Mfoq8DV2x +nSh/8kaBdcrqJNx2k+ra+X9FhOmbAtUSuGEFGKSfhfG01TGKAxLRTohQp6zKCAcu +tc9jeHAYoC9X5CYH9iixOq1YmLzzmgQi/m4yUnaY7f2OOpgCdHYKqgofUHRvjBEV +2lw/kg9iIv1ngXTOeIXEVDjpV3+l63grj0pU/lucjfLDTH3+36dsmN57xcM/RXFy +DoDtCholTVEqkZasqxh8GU4Y+H+CLFwJBuumw2yw+JKmVZ3FP7Fy1Cki+I+fxSwC +AXVZXSMtnJCa2hn4m9hVHSesFQ0lVAauxI9sj1/R0ldqIzd10Tt1u4kBFQIFEzeJ ++3tR6m16P5LTsQEBSS0H/RD6hglWcvD6Pp4M+/vDNe0VEdw2e/ZafV4Yf80vd97r +/CCVqJny3DuRxj1NBZ2oKJ2NKQlKYoJbc7e420N1EXWRWgTOMxAks4pj7AcNPlMp +6Yqg0BMk9M2n8cmJXZcJWcJH+++oisbqf1y3WBkCVNV2q3Ad5nnHeotBqmjbpHNg +zcuJuWGfW8aDRW4722BuxxkNYOStFVXYevoUg7PU8Xwg06/0abogmQhD59Og7Pzh +M2Tm5tBR4dssCMfx8ppog5iF5utJBU0QCAtDKzSuEH4HVNUsiJcTvqleTn3q/BUa +KLUJ6ObQfJfsSFAowX4hfeSLCcdt1b7pLHouQoMXO8OJAJUCBRA3ifq6xEaR6Lw5 +pc0BAZMoA/0YuMwfDWhn6VO7kH5RUl/sdNBl5wSMbDfe3nDW+/KV41yOX+ISzI1v ++Dosy5qGaV2HUntJm3rXknDqnoDNdnGTaKyma6Z77fs7RUo80ZnYhSzSYWEAnzLN +MBldwyHZI/NRbmAvsfOeyQ06nFNy2il70+WpEZBP5Caaxz7LpXN8zIkAkgMFEDPN +DAU+j7fy+INB2QEBrfUD50++xHDXNa/IwOnZpDCohrAiLbCIWXnqVh+mTBZaOx1+ +24rQcd76B6TRonW8vAkWWuK+ugS6QXUloreRL+hva79M0hngwpaN+FuQlbjRjuAI +oJQk/OHqEPDWdh9zg31cqfC5uJFV1baKDUdWgplQ30B3TfibfSMwcTOpds7gtDFM +YXJzIGBTRlgnIEVpbGVicmVjaHQgPFNGWEB1bml4LWFnLnVuaS1zaWVnZW4uZGU+ +iQCVAwUTN6g0J/0tkJKokHslAQEqTwP9GdKy8Xl/DIJsQMKJ/w1ZsOyuqZL6fH3e +xZC31Y8X6Dk8XN2Rw0KkO2PjMNpXsjd0fp59X9swTD/hf1gRIr7Uvh/p2nXfyBSD +r4/VUHpK7tx7IB3ZolIZVvtm67+H8vfHKk9XEFgFF14+aVvKHojXZ3tsRt6Wm78n +nJ43gdVyHr6JAHUDBRAzEfV1S1wlNB5o8N0BAX7QAwC3iuW6C34zc8We4NVTx8Op +OkMElBEsIjyQphkyE+X/eNWIR6qIYMDeZBkfVw8VggiQKkHxb28YYmb9M7uB70Ox +WC1Szts8Ga1bzn0dufY7xgxaT6kQatXHMUzV7r39muOJAJUCBRAw+R5/voJFl2Zs +ya0BAVlWA/0eFxcSJrCcc6WspLfB5eJKUDVmFh3eWnvNUBZWv73yKZQanlVq9vfa +VGztcQbeBBT4uWsmvAhsF7PLkbByp97u9dY3064tZiqYjAVrdePQbFJOZRQpxPYF +aOVMWHKTNr29SOQynqP/Pw7mM9RUIV8DsRqgaiK/oIENXze0NL+as4kBFQMFEDEs +VXTwiYRjAFcYEQEBWnwH/jmcYmaqYHgN4jGc2zq9e7+GIy/yeDd6Ya3MvLLIdK5k +wWzR1jn0UdMsxpQF3rKQki8wZ0kDKYdjF3NwJedSyuM+PO4gEMabuZP2Sq4OWoWS +O1+aJL4k3EY5l5KW216frDLOid2Tjo8TtbVsrUl1uf95SsG482lEZW1GwQPUEEhg +GD57MGfgjykTblLJNhCN8uA1lY7mmznAnjcuEy3wfVCGPNaF31zsk/othcGdH9W3 +n3mbrjyAhkCMZRBYtx3d4QxAIDSfB7vQulwAp2Ink+3VWLZWB9eFE5OvwiypG1jY +XfyOUkDD24oyits1OVN7z3KJQNVGpUgXJH7Q0Nok5pmJAJUDBRAw+UGLHilwjxqE +mVEBAchWA/46j8drvA9WkMyh72akvT1GErDzE4J9dBUf7adnPQoetH/gUPenzlAs +5kbfeCKtYjGbCdKE8iy3+sH/zHW9S4b7Bn+61xQE4duTlKT8daj1FrLUk6B0p9Pm +X/HtQdKejyfenbiOq4pqHPDSqaTsEpkb6gA9wEwiqTIjksFnvfpgWYkAVQMFEDD5 +fUoJNGLsuYI5PQEBF9gCAJQqYY+CSP8r6HWCJaQtjDzrPoX072jD1YUgmWdBFX2Y +E2aS0F0A4lKJWAb0xyZ4wWcl2aM5Z/3X+DAR0IClsJiJAFUCBRAw+UT5PjTM7Dn4 +WRsBAeRKAgCDTEFmWZ/tdq9pxUnAknH+U2iqZvmOjHxLL1YNLa73hCe+Im2xQ6PA +AWdoOhYM3w8QDG8TbFEGjK4YdE2kgvRMiQCVAgUQMPjujh3Ztnhw/dexAQH49QP+ +P3GBBGu4zfPqbZsWSrH2dMTj9ncbD54nA0+FUdejBzeq5Fa7aO/Nl0okcd2VLHfU +Y1Jnx2QN5h6CSBqOiURVTnso4NyxAEkkn2a+GBZIbrZ39JQ5STnhCoaryMP3Ujuz +A8HS8YTqgBb/VMwJaTpuBi8fadTetcQ5dXSGBJ2PXDiJAJUCBRAw+UJ8hWrdG2nW +nOkBAQgjBACletAHnVmcl1qJHMFiG1vzy4DUwofCS9b4o1xpwb09j7gNC+/6wlz4 +W29tAK66vj+sWxhcYuNolonnlNk+czeSJTzm0+nD3kViZMT52kn/GQ992NWpZnLo +YWDFHO5ZC+8qkqNSfE0VQksY0OFtPkA1BSBL64oG+UnHe82BxjqqEokAVQIFEDD4 +zdqb2lGD8IQbEQEBjYUB/2eiJQSOIXRm/LXnpTIGNpH9yKtPDQcssoCQCOPB6k3t +HCiFugT3AZCajKKCbUSU1+kZLfH0SnvyDxnhxqslt3iJAO4DBRAw4VEeit1k1hLN +dSkBAU55BsEBICTJPEh0ftogZjiUNsfpL+C1Zj6fIXWiggXX7yQ5q0qbhIKwVhSP +Tw6UsBezViz6hEj51qOXXfGHsp82M92goiFwDlAdKxvLboxdXUp/5BVAjKoKr2zz +lN7Er+rVZRAiAIeuxkzR5+tSCISzNChuL/XpaNC5P0qVsEUTyWVv5bUAQKY7Ufo7 +hToquvOvnhPZCgQiJgiLYQXhP3H+iX8LkuPtbovjJpJKq5zvPtO23Y25Fk0s0y95 +ddr/7TNqfBcKqbONcvt5yBDs6uyLH+MwY38NmSnl2xF6tDNMYXJzIGBTRlgnIEVp +bGVicmVjaHQgPFNGWEBhcHBsMi5ocnoudW5pLXNpZWdlbi5kZT6JAJUDBRM3qDQ5 +/S2QkqiQeyUBAdsdA/0WrlL1R5qp2xRjRwSQpnORCm53cIEVEvm43L9MsSKRXbJc +YmWorKIqjUKkazywiOmuz8BJU30NM29z7zoLizMuM2AVGrabnaK8Xg7LECBMtAJD +coSLTlKczVKAL84pfqs9HVKzTDwL1RA/6N4pgvbVQmPFS0TTyemiC03kiCM2tIkA +lQIFEDD5Hv6+gkWXZmzJrQEBD9QD/iIIvOUqyKRBWjHgJD7zoskxDQH/YVhJu59z +oCEOJGwXFPLlT3cemeMCaVLa5XvoDnLYWZ/bfI5nFd9vF9GwwbmP8/x39Z3N2xKf +JpD8eH5inu5AwtIskfXjmcZhSfDgv2XpAaFigz3wIBt+XbkPRxJJxfqD5oJ1ys0q +Ne0U6jjyiQEVAwUQMSxVrvCJhGMAVxgRAQHLVgf/cW6FlzmOeIvJ/3yB7vhSOlpi +vnY00iKnzzCpWLOasaC4NPazhqNIewBa01KSuamIicYkzXk8MeaTq5EaQfJyA+Nt +dWSm/3/ivKWoO4KaqJbVPnxaDnB2KBH+2mq0BJ4rS4i2jVZuopbtMAHV+lQUHaVH +826YaFPa+425A/H+Oaqn2EdkL80fpIJsACsudYPDGCKS3zcMjspVK1cXqNRDzIOZ +8I/XtyNEJpw1yRGft4jrn4lj9jU4y0v6sFOt6jpuvAmyRN/pebwjYJw1Ye697MMk +n0nEafH55Et+XfdBOYNm3Sb/J2g8j2JVVhN6JKuFYyM1kvK13Rky3SiLPUzD94kA +lQIFEDD5QqqFat0badac6QEB6HsD/RooPR6pFnSisCerTlPhSvDI2gl2HUMFw0CZ +J5JKVlj5GFDZp5jl0yhgCFCweFuE7RUgMOkvGeEoEPZeyipacsrVIcO26aCQyerL +TQd6JTgOuCEeEvkjBwiqOrVNSEPM5TWPzQc7Q7IDtKTsCT+xNGtO6Pi2+ArZaodZ +Ttp4tXkCiQBVAgUQMPjOC5vaUYPwhBsRAQHdVAH/eIgCk6fo3/Mvxu7IESdDLM/o +zh14yvZz6FvC/VKtSp51goqsV5jI9wKANIjonLeO7GJubjO+lqHvsEVsGQ+wpIkA +7gMFEDDhUjOK3WTWEs11KQEBgTUGwQGH8Ic7zNaUlRmYm5J8R375iP8CrJ/xILbE +T69VsR2aDG2MA2z8NBBkV1ARrAC2YWa9sO91yCyf3NAI6I1oqtbv/09Im/s0bTu6 +6dWrqRAiuTB3Ou+gHJ0fc85gTWcBd9/xS/mNlZb1/ZXjkBaYdl0Bzm72c3+HqZjH +zT3nlxVY5HCi15J4iDgCuCPzeo1r8QgGmsbP7fD+0Hka7tlXb87WxPZt+nkjGS9x +mLrNHw5/vJpcN4+fzevzhTQD8IcsUr0QcZUH9jZpm6xWpibPF5z7FzXTorguf+W0 +M0xhcnMgYFNGWCcgRWlsZWJyZWNodCA8U0ZYQGFwcGwxLmhyei51bmktc2llZ2Vu +LmRlPokAlQMFEzeoNFL9LZCSqJB7JQEB8hcD/jiiaI17W2zC2gtJuqZq0tBAOWJG +1e7Q7NcadfGQpEj4iceT5pTOK64mvyXWhMUUq9vEq8SPNowk1s6830uQyAQftco5 +xZ+RuT5ZYqPx3faku5Q16HRaBeJQEfxys14SEMP7K8fiuP4iHLmXLwThPE0EsUA0 +VTaVptaQwwto5ruIiQCVAgUQMPke2r6CRZdmbMmtAQGOzAP/U3CbvKhXqyPupOIp +pb1LcNAPcspe3B6IN1gXSWn3rUhaS7IG6vhpgE1E5ArzbMVCoo0p+yb4Ve743oBh +DbMRQkRSRP1FCCayt9TWrTrtmij51yTlPbO4f7+SqYX23bwa/iOPFVOK3oL3Y0SF +yK6007jyQrfYFPaaBfbDu12zobiJARUDBRAxLFW88ImEYwBXGBEBAVQqB/9jgON6 +jXz5kB+vQEqXXg/b10orenw4tyepeHqO4F9NGJacUm2tB8Yf3DelC+mLZFG4NlNN +DOE7h46raDmDL0zK1TWG0tFWlXAGeaaMtFbPRYaqvjLhlQtuDeFrk2x8Gml2AcqT +lj4Gm28gv/ftkGTO2SIFd+zRltzd9lHhtJTXEM4T4dLQGh87G5up9msJm8CMwILk +0nhHXcfzGdiDo0pAICo594I5VaQadz8ErtUCsxeMLyj/2dAPNjZ9E8g0+cJvh//g ++6fA6sTNrrMvFd+A2tpAnX1ug9v+j0MGW805aSr2BKZWdMSSqsQy2Jd3fUoBT8tU +JEf/vSbHtdmQXn83iQBVAwUQMPl9jgk0Yuy5gjk9AQFbSQH/Sz0CprAeon/Ss72O +wyGTe+4c2DBUXgOgpMvkQMg5ERNxwB/hRlUmj4nOaNjFzV/ZGTCQyST831p8pmZw +1JjO14kAVQIFEDD5RRk+NMzsOfhZGwEBqHsCAIhZH8c235XbRsO54I72aHAaKurk +TtMlT4L3FP7cF5lebLL8BHu1Yl0qcLqVoYMucySjcJav9dEoP6sLTnSc2yuJAJUC +BRAw+O7dHdm2eHD917EBAXRrA/9xfAgFoQCPgP9KHMydrc1D8QzhpOeIAd1Ugfh3 +pSHZHAMKhi3ofAQ/XXF8HAjpsNaVCF1SAPMY5eY7ErG/9e2Li+Ic7A7UqqNG0c7I +N/iEj+i7anRue1cxnnJW/RZqTJbuRh3srFNth38JMp7wcH7zCSPyHWlvfUkmhfNa +yCbBeIkAlQIFEDD5QtiFat0badac6QEBBTAD/0BSoVCxdb2QyLlGighOJBtHKe6c ++HZqpp1We4tmgCHGnXpz4RBilzhCLqMs8FV6Yd1Lg9by8l6AXWkm0NnhV8s3DCQj +GPtjSFTwDgFwdQh8V04RHtLBtb+LtBNTy7e80d+aAih2/X0PusXETOqo/EwdGkiz +z8g4b0vfNzeRXyudiQBVAgUQMPjOLJvaUYPwhBsRAQGDqQIA2P2avbSBxhFnh4N+ +e5NKRK+2O8qjHQS0z5ScACCKHFSrm80JkMR6iFlJkFH+namS1xK75x2TlsEUe3OR +o1O3zYkAVQIFEC/S7ZyZNU6jaP3/TQEB25sCAJyZCXeC915C4DbNKaoc2sIRd2aM +giW05ZzxYUI8mMO3pzZwF2a7Cg5iSdZYYMwpe9OWHqU+AhXHd+GWGhvHEUqJAJUC +BRAv0z5HRrGJ++Deqm0BAXu0A/sHvzL3eBqiMMwLw3B+I0qHuXlwGHQ40D5bWDc7 +tgsTlbtn986Dgfek66OepTsfc2wKGYPG0EpAgiJlemc2Dg23cXvrm3wQ+syaONAn +hrr7wId+ZeZ81Jao8x2OAlbjKQydRqwaGAXVnx+U02R8fmB9b0avxRwKWAqprnG+ +SELlzIkAVQMFEC/TO8pDBndHH+0DOwEBWzQB/3VwSMfehk8hrJ1JnE9SMXVITen3 +c2djoDeYplHW+R7AbqxGpVrgw7iXDzDwBTuB7au/C6kXfB4XVn0MbZtq4aaJAJUC +BRAv0zhK5cuGDKtEoMkBAf+9BACMYzfvQzBwh+a1D17/SPSfO1DBDXx1cwD50zI0 +eIatz4kLvW7nOPHCY7tHVW/tlIBp/0+yUX/XXzBLp8WD0E/4s7lPgPjjAwlN+Iwy +/fRDhJ/Gf0Nf03eJjMvU9MeaUI58JBCq8LjnVdtxcQKqapYcSogjz//jD+H3KuX/ +kX+5eYkAVQIFEC/SVx/9mEr5stbwpQEBz+sB/2uYnno7jRBUPzTf5tTXNKJITXH4 +VRG35x4CyjOqj21oWhEgZdNrwymzBK3IAuckqnIOQYSdN9F0BFVC1wTNgmeJAFUC +BRAv0kO/ERkJHPqUz38BAbbHAf4hAAlkS+V00fN6KR7PXxPHLXYScn2T7NrauM9W +eVfv614hjdU07WGiZSDCqOg4elmR0aB052a586CVPdGquTkViQCVAgUQL9G37UlJ +piwTnZDhAQHNRgQAyidzdQU2MaifwX+iZzQ88Det8fYhLobfUU3p9FqtbU/CTsJa +XHfCAebqA73F9XmUOMEn6VWZuYvP/UxmGDrjp4VFu6C0Fhs5fATrOY2soGFyFW55 +U43PBY8gDwFm1HYvDoKKQA6EqCXid2Dw87xRSDyCHRVQoZM8MrQwpHtkKkaJAFUC +BRAv0hc+eYwYDHu3XYkBAakgAf9muXXpQvDf+CXtPXURudsD1PcuNe4PhMbcgZ4R +XfPXBtGnbbvI3XZrc9tq8QomPWZ9atlpPz1e3WyZgFojBfhqiQCVAgUQLxgZ6khf +qy8j2SvjAQGc7QP/VHgeVQzjcJSPF2KfNyKM4nFE17uJ5emnvE2f1K4mi0NV4IsN +EVKmYXYQVvQoPKhfZtjXzE9P2xa0gxi/heKBIHB+5H5Kn4nUIt0/7POYhltkFz7c +bnEzqeKm9oqXUOSFKUup51bh2aDWsqAI5dgod3MdRxqd40TiuShaVXAbmuGJAJUC +BRAuzX6/HilwjxqEmVEBAfBcA/wIosNYUsnsVzclnQye4/Fbv0z2dFDAvZMj9V3i +UJRKIM5R0S+NTjkwuYuBT7g5k095doFIuQ3jPw9STEYQS9J4IUTu7ThU2rUYnZoL +58dUXO5ZunQux7OoNKebrG8HHPjTIRpmeRe7f7rqRdlX8TgE0iQJoHlXapfGsEiD +QPXSIIkAlAIFEC7Htq4PRy9bNNdNwQEBM1UD+NT5tNSqeVl2t/oqAK/6EM6zpU7n +fxwTFA2wGXvHzYONunxDm3bVgRXwuIU3WKa4tiodeoMQe3uq2ug1oFheCdHbhCMj +e6t6X6RgyJtlbEaurfzYLZqlF5oQOZDWq0TM/6Rd7FprADMoyjxUpYydeNBgEtmi +G5Sp9yIT0Ds5AXWJAEUCBRAuvsWtldOLUWZxqVUBAU4tAX9YK5N9ywRzvPVYrkEx +CW0KCc2+7PSGKY0/YXE+XiDmure7yLTd2o9u5XB+vFLPL6Y= +=Duku +-----END PGP PUBLIC KEY BLOCK----- diff --git a/APACHE_1_3_12/LICENSE b/APACHE_1_3_12/LICENSE new file mode 100644 index 0000000000..6ac6538b3c --- /dev/null +++ b/APACHE_1_3_12/LICENSE @@ -0,0 +1,59 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + + + diff --git a/APACHE_1_3_12/Makefile.tmpl b/APACHE_1_3_12/Makefile.tmpl new file mode 100644 index 0000000000..7d028fce18 --- /dev/null +++ b/APACHE_1_3_12/Makefile.tmpl @@ -0,0 +1,612 @@ +## ==================================================================== +## Copyright (c) 1998-1999 The Apache Group. 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 acknowledgment: +## "This product includes software developed by the Apache Group +## for use in the Apache HTTP server project (http://www.apache.org/)." +## +## 4. The names "Apache Server" and "Apache Group" must not be used to +## endorse or promote products derived from this software without +## prior written permission. For written permission, please contact +## apache@apache.org. +## +## 5. Products derived from this software may not be called "Apache" +## nor may "Apache" appear in their names without prior written +## permission of the Apache Group. +## +## 6. Redistributions of any form whatsoever must retain the following +## acknowledgment: +## "This product includes software developed by the Apache Group +## for use in the Apache HTTP server project (http://www.apache.org/)." +## +## THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY +## EXPRESSED 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 APACHE GROUP OR +## ITS 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. +## ==================================================================== +## +## This software consists of voluntary contributions made by many +## individuals on behalf of the Apache Group and was originally based +## on public domain software written at the National Center for +## Supercomputing Applications, University of Illinois, Urbana-Champaign. +## For more information on the Apache Group and the Apache HTTP server +## project, please see . +## + +## +## Makefile -- Apache Autoconf-style Interface (APACI) +## top-level control Makefile for out-of-the-box +## build and installation procedure. +## +## Written by Ralf S. Engelschall +## + +## ================================================================== +## Options +## ================================================================== + +# safe environment +SHELL = @SHELL@ + +# what platform are we on +PLATFORM = @PLATFORM@ + +# paths to the source tree parts +TOP = . +SRC = @SRC@ +MKF = @MKF@ +AUX = @AUX@ + +# build tools +CP = cp +LN = ln +RM = rm -f +MKDIR = $(TOP)/$(AUX)/mkdir.sh +INSTALL = $(TOP)/$(AUX)/install.sh -c +IFLAGS_PROGRAM = @IFLAGS_PROGRAM@ +IFLAGS_CORE = @IFLAGS_CORE@ +IFLAGS_DSO = @IFLAGS_DSO@ +IFLAGS_SCRIPT = @IFLAGS_SCRIPT@ +IFLAGS_DATA = @IFLAGS_DATA@ +INSTALL_PROGRAM = $(INSTALL) $(IFLAGS_PROGRAM) +INSTALL_CORE = $(INSTALL) $(IFLAGS_CORE) +INSTALL_DSO = $(INSTALL) $(IFLAGS_DSO) +INSTALL_SCRIPT = $(INSTALL) $(IFLAGS_SCRIPT) +INSTALL_DATA = $(INSTALL) $(IFLAGS_DATA) +PERL = @PERL@ +TAR = @TAR@ +TAROPT = @TAROPT@ + +# installation name of Apache webserver +TARGET = @TARGET@ + +# installation root +# (overrideable by package maintainers for +# rolling packages without bristling the system) +root = + +# installation paths +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +mandir = @mandir@ +sysconfdir = @sysconfdir@ +datadir = @datadir@ +iconsdir = @iconsdir@ +htdocsdir = @htdocsdir@ +cgidir = @cgidir@ +includedir = @includedir@ +localstatedir = @localstatedir@ +runtimedir = @runtimedir@ +logfiledir = @logfiledir@ +proxycachedir = @proxycachedir@ + +libexecdir_relative = @libexecdir_relative@ + +# suexec details (optional) +suexec = @suexec@ +suexec_caller = @suexec_caller@ +suexec_docroot = @suexec_docroot@ +suexec_logexec = @suexec_logexec@ +suexec_userdir = @suexec_userdir@ +suexec_uidmin = @suexec_uidmin@ +suexec_gidmin = @suexec_gidmin@ +suexec_safepath = @suexec_safepath@ +suexec_umask = @suexec_umask@ + +# some substituted configuration parameters +conf_user = @conf_user@ +conf_group = @conf_group@ +conf_port = @conf_port@ +conf_serveradmin = @conf_serveradmin@ +conf_servername = @conf_servername@ + +# usage of src/support stuff +build-support = @build_support@ +install-support = @install_support@ +clean-support = @clean_support@ +distclean-support = @distclean_support@ + +# forwarding arguments +MFWD = root=$(root) + +## ================================================================== +## Targets +## ================================================================== + +# default target +all: build + +## ------------------------------------------------------------------ +## Build Target +## ------------------------------------------------------------------ + +# build the package +build: + @echo "===> $(SRC)" + @$(MAKE) -f $(TOP)/$(MKF) $(MFLAGS) $(MFWD) build-std + @if [ "x$(build-support)" != "x" ]; then \ + $(MAKE) -f $(TOP)/$(MKF) $(MFLAGS) $(MFWD) $(build-support); \ + fi + @touch $(TOP)/$(SRC)/.apaci.build.ok + @echo "<=== $(SRC)" + +# the non-verbose variant for package maintainers +build-quiet: + @$(MAKE) -f $(TOP)/$(MKF) $(MFLAGS) $(MFWD) QUIET=1 build + +# build the standard stuff +build-std: + @case "x$(PLATFORM)" in \ + x*390*) _C89_STEPS="0xffffffff"; export _C89_STEPS;; \ + esac; \ + cd $(TOP)/$(SRC); $(MAKE) $(MFLAGS) SDP=$(SRC)/ all + +# build the additional support stuff +build-support: + @echo "===> $(SRC)/support"; \ + case "x$(PLATFORM)" in \ + x*390*) _C89_STEPS="0xffffffff"; export _C89_STEPS;; \ + esac; \ + cd $(TOP)/$(SRC)/support; $(MAKE) $(MFLAGS) all || exit 1; \ + if [ ".$(suexec)" = .1 ]; then \ + $(MAKE) $(MFLAGS) \ + EXTRA_CFLAGS='\ + -DHTTPD_USER=\"$(suexec_caller)\" \ + -DUID_MIN=$(suexec_uidmin) \ + -DGID_MIN=$(suexec_gidmin) \ + -DUSERDIR_SUFFIX=\"$(suexec_userdir)\" \ + -DLOG_EXEC=\"$(suexec_logexec)\" \ + -DDOC_ROOT=\"$(suexec_docroot)\" \ + -DSAFE_PATH=\"$(suexec_safepath)\" \ + $(suexec_umask)' \ + suexec; \ + fi + @echo "<=== $(SRC)/support" + +## ------------------------------------------------------------------ +## Installation Targets +## ------------------------------------------------------------------ + +# indirection step to avoid conflict with INSTALL document +# on case-insenstive filesystems, for instance on OS/2 +install: install-all + +# the install target for installing the complete Apache +# package. This is implemented by running subtargets for the +# separate parts of the installation process. +install-all: + @if [ ! -f $(TOP)/$(SRC)/.apaci.build.ok ]; then \ + $(MAKE) -f $(TOP)/$(MKF) $(MFLAGS) $(MFWD) build; \ + else \ + :; \ + fi + @$(MAKE) -f $(TOP)/$(MKF) $(MFLAGS) $(MFWD) \ + install-mktree install-programs $(install-support) \ + install-include install-data install-config + -@$(RM) $(SRC)/.apaci.install.tmp + -@$(RM) $(SRC)/.apaci.install.conf + -@if [ ".$(QUIET)" != .1 ]; then \ + if [ ".$(TARGET)" = .httpd ]; then \ + apachectl='apachectl'; \ + else \ + apachectl="$(TARGET)ctl"; \ + fi; \ + echo "+--------------------------------------------------------+"; \ + echo "| You now have successfully built and installed the |"; \ + echo "| Apache 1.3 HTTP server. To verify that Apache actually |"; \ + echo "| works correctly you now should first check the |"; \ + echo "| (initially created or preserved) configuration files |"; \ + echo "| |"; \ + echo "| $(sysconfdir)/$(TARGET).conf"; \ + echo "| |"; \ + echo "| and then you should be able to immediately fire up |"; \ + echo "| Apache the first time by running: |"; \ + echo "| |"; \ + echo "| $(sbindir)/$${apachectl} start"; \ + echo "| |"; \ + echo "| Thanks for using Apache. The Apache Group |"; \ + echo "| http://www.apache.org/ |"; \ + echo "+--------------------------------------------------------+"; \ + fi + +# the non-verbose variant for package maintainers +install-quiet: + @$(MAKE) -f $(TOP)/$(MKF) $(MFLAGS) $(MFWD) QUIET=1 install-all + +# create the installation tree +install-mktree: + @echo "===> [mktree: Creating Apache installation tree]" + $(MKDIR) $(root)$(bindir) + $(MKDIR) $(root)$(sbindir) + $(MKDIR) $(root)$(libexecdir) + $(MKDIR) $(root)$(mandir)/man1 + $(MKDIR) $(root)$(mandir)/man8 + $(MKDIR) $(root)$(sysconfdir) + $(MKDIR) $(root)$(htdocsdir) + $(MKDIR) $(root)$(iconsdir) + $(MKDIR) $(root)$(cgidir) + $(MKDIR) $(root)$(includedir) + $(MKDIR) $(root)$(includedir)/xml + $(MKDIR) $(root)$(runtimedir) + $(MKDIR) $(root)$(logfiledir) + $(MKDIR) $(root)$(proxycachedir) + -@if [ "x`$(AUX)/getuid.sh`" = "x0" ]; then \ + echo "chown $(conf_user) $(root)$(proxycachedir)"; \ + chown $(conf_user) $(root)$(proxycachedir); \ + echo "chgrp $(conf_group) $(root)$(proxycachedir)"; \ + chgrp "$(conf_group)" $(root)$(proxycachedir); \ + fi + @echo "<=== [mktree]" + +# install the server program and optionally corresponding +# shared object files. +install-programs: + @echo "===> [programs: Installing Apache $(TARGET) program and shared objects]" + -@if [ ".`grep '^[ ]*AddModule.*mod_so\.o' $(TOP)/$(SRC)/Configuration.apaci`" != . ]; then \ + echo "$(INSTALL_CORE) $(TOP)/$(SRC)/$(TARGET) $(root)$(sbindir)/$(TARGET)"; \ + $(INSTALL_CORE) $(TOP)/$(SRC)/$(TARGET) $(root)$(sbindir)/$(TARGET); \ + SHLIB_EXPORT_FILES="`grep '^SHLIB_EXPORT_FILES=' $(TOP)/$(SRC)/Makefile | sed -e 's:^.*=::'`"; \ + if [ ".$${SHLIB_EXPORT_FILES}" != . ]; then \ + $(CP) $(TOP)/$(SRC)/support/httpd.exp $(root)$(libexecdir)/; \ + chmod 644 $(root)$(libexecdir)/httpd.exp; \ + fi; \ + else \ + echo "$(INSTALL_PROGRAM) $(TOP)/$(SRC)/$(TARGET) $(root)$(sbindir)/$(TARGET)"; \ + $(INSTALL_PROGRAM) $(TOP)/$(SRC)/$(TARGET) $(root)$(sbindir)/$(TARGET); \ + fi + -@if [ ".`grep 'SUBTARGET=target_shared' $(TOP)/$(SRC)/Makefile`" != . ]; then \ + SHLIB_SUFFIX_NAME="`grep '^SHLIB_SUFFIX_NAME=' $(TOP)/$(SRC)/Makefile | sed -e 's:^.*=::'`"; \ + SHLIB_SUFFIX_LIST="`grep '^SHLIB_SUFFIX_LIST=' $(TOP)/$(SRC)/Makefile | sed -e 's:^.*=::'`"; \ + echo "$(INSTALL_CORE) $(TOP)/$(SRC)/lib$(TARGET).ep $(root)$(libexecdir)/lib$(TARGET).ep"; \ + $(INSTALL_CORE) $(TOP)/$(SRC)/lib$(TARGET).ep $(root)$(libexecdir)/lib$(TARGET).ep; \ + echo "$(INSTALL_DSO) $(TOP)/$(SRC)/lib$(TARGET).$${SHLIB_SUFFIX_NAME} $(root)$(libexecdir)/lib$(TARGET).$${SHLIB_SUFFIX_NAME}"; \ + $(INSTALL_DSO) $(TOP)/$(SRC)/lib$(TARGET).$${SHLIB_SUFFIX_NAME} $(root)$(libexecdir)/lib$(TARGET).$${SHLIB_SUFFIX_NAME}; \ + if [ ".$${SHLIB_SUFFIX_LIST}" != . ]; then \ + echo "$(RM) $(libexecdir)/lib$(TARGET).$${SHLIB_SUFFIX_NAME}.*"; \ + $(RM) $(libexecdir)/lib$(TARGET).$${SHLIB_SUFFIX_NAME}.*; \ + for suffix in $${SHLIB_SUFFIX_LIST} ""; do \ + [ ".$${suffix}" = . ] && continue; \ + echo "$(LN) $(root)$(libexecdir)/lib$(TARGET).$${SHLIB_SUFFIX_NAME} $(root)$(libexecdir)/lib$(TARGET).$${SHLIB_SUFFIX_NAME}.$${suffix}"; \ + $(LN) $(root)$(libexecdir)/lib$(TARGET).$${SHLIB_SUFFIX_NAME} $(root)$(libexecdir)/lib$(TARGET).$${SHLIB_SUFFIX_NAME}.$${suffix}; \ + done; \ + fi; \ + fi + $(INSTALL_DATA) $(TOP)/$(SRC)/support/httpd.8 $(root)$(mandir)/man8/$(TARGET).8 + -@$(RM) $(SRC)/.apaci.install.conf; touch $(SRC)/.apaci.install.conf + -@if [ ".`grep '^[ ]*SharedModule' $(TOP)/$(SRC)/Configuration.apaci`" != . ]; then \ + for mod in `egrep '^[ ]*SharedModule' $(TOP)/$(SRC)/Configuration.apaci |\ + sed -e 's/^[ ]*SharedModule[ ]*//'`; do \ + file=`echo $${mod} | sed -e 's;^.*/\([^/]*\);\1;'`; \ + echo "$(INSTALL_DSO) $(TOP)/$(SRC)/$${mod} $(root)$(libexecdir)/$${file}"; \ + $(INSTALL_DSO) $(TOP)/$(SRC)/$${mod} $(root)$(libexecdir)/$${file}; \ + name=`$(TOP)/$(AUX)/fmn.sh $(TOP)/$(SRC)/$${mod}`; \ + echo dummy | awk '{ printf("LoadModule %-18s %s\n", modname, modpath); }' \ + modname="$${name}" modpath="$(libexecdir_relative)$${file}" >>$(SRC)/.apaci.install.conf; \ + done; \ + echo "" >>$(SRC)/.apaci.install.conf; \ + echo "# Reconstruction of the complete module list from all available modules" >>$(SRC)/.apaci.install.conf; \ + echo "# (static and shared ones) to achieve correct module execution order." >>$(SRC)/.apaci.install.conf; \ + echo "# [WHENEVER YOU CHANGE THE LOADMODULE SECTION ABOVE UPDATE THIS, TOO]" >>$(SRC)/.apaci.install.conf; \ + echo "ClearModuleList" >>$(SRC)/.apaci.install.conf; \ + egrep "^[ ]*(Add|Shared)Module" $(SRC)/Configuration.apaci |\ + sed -e 's:SharedModule:AddModule:' \ + -e 's:modules/[^/]*/::' \ + -e 's:[ ]lib: mod_:' \ + -e 's:\.[soam].*$$:.c:' >>$(SRC)/.apaci.install.conf; \ + fi + @echo "<=== [programs]" + +# install the support programs and scripts +install-support: + @echo "===> [support: Installing Apache support programs and scripts]" + $(INSTALL_PROGRAM) $(TOP)/$(SRC)/support/ab $(root)$(sbindir)/ab + $(INSTALL_DATA) $(TOP)/$(SRC)/support/ab.8 $(root)$(mandir)/man8/ab.8 + @if [ ".$(TARGET)" = .httpd ]; then \ + apachectl='apachectl'; \ + else \ + apachectl="$(TARGET)ctl"; \ + fi; \ + echo "$(INSTALL_SCRIPT) $(TOP)/$(SRC)/support/apachectl[*] $(root)$(sbindir)/$${apachectl}"; \ + sed -e 's;PIDFILE=.*;PIDFILE=$(runtimedir)/$(TARGET).pid;' \ + -e 's;HTTPD=.*;HTTPD=$(sbindir)/$(TARGET);' \ + < $(TOP)/$(SRC)/support/apachectl > $(TOP)/$(SRC)/.apaci.install.tmp && \ + $(INSTALL_SCRIPT) $(TOP)/$(SRC)/.apaci.install.tmp $(root)$(sbindir)/$${apachectl}; \ + echo "$(INSTALL_DATA) $(TOP)/$(SRC)/support/apachectl.8 $(root)$(mandir)/man8/$${apachectl}.8"; \ + $(INSTALL_DATA) $(TOP)/$(SRC)/support/apachectl.8 $(root)$(mandir)/man8/$${apachectl}.8 + $(INSTALL_PROGRAM) $(TOP)/$(SRC)/support/htpasswd $(root)$(bindir)/htpasswd + $(INSTALL_DATA) $(TOP)/$(SRC)/support/htpasswd.1 $(root)$(mandir)/man1/htpasswd.1 + $(INSTALL_PROGRAM) $(TOP)/$(SRC)/support/htdigest $(root)$(bindir)/htdigest + $(INSTALL_DATA) $(TOP)/$(SRC)/support/htdigest.1 $(root)$(mandir)/man1/htdigest.1 + @echo "$(INSTALL_SCRIPT) $(TOP)/$(SRC)/support/dbmmanage[*] $(root)$(bindir)/dbmmanage"; \ + sed -e 's;^#!/.*;#!$(PERL);' \ + < $(TOP)/$(SRC)/support/dbmmanage > $(TOP)/$(SRC)/.apaci.install.tmp && \ + $(INSTALL_SCRIPT) $(TOP)/$(SRC)/.apaci.install.tmp $(root)$(bindir)/dbmmanage + $(INSTALL_DATA) $(TOP)/$(SRC)/support/dbmmanage.1 $(root)$(mandir)/man1/dbmmanage.1 + $(INSTALL_PROGRAM) $(TOP)/$(SRC)/support/logresolve $(root)$(sbindir)/logresolve + $(INSTALL_DATA) $(TOP)/$(SRC)/support/logresolve.8 $(root)$(mandir)/man8/logresolve.8 + $(INSTALL_PROGRAM) $(TOP)/$(SRC)/support/rotatelogs $(root)$(sbindir)/rotatelogs + $(INSTALL_DATA) $(TOP)/$(SRC)/support/rotatelogs.8 $(root)$(mandir)/man8/rotatelogs.8 + @echo "$(INSTALL_SCRIPT) $(TOP)/$(SRC)/support/apxs[*] $(root)$(sbindir)/apxs"; \ + sed -e 's;^#!/.*;#!$(PERL);' \ + -e 's;\@prefix\@;$(prefix);' \ + -e 's;\@sbindir\@;$(sbindir);' \ + -e 's;\@libexecdir\@;$(libexecdir);' \ + -e 's;\@includedir\@;$(includedir);' \ + -e 's;\@sysconfdir\@;$(sysconfdir);' \ + < $(TOP)/$(SRC)/support/apxs > $(TOP)/$(SRC)/.apaci.install.tmp && \ + $(INSTALL_SCRIPT) $(TOP)/$(SRC)/.apaci.install.tmp $(root)$(sbindir)/apxs + $(INSTALL_DATA) $(TOP)/$(SRC)/support/apxs.8 $(root)$(mandir)/man8/apxs.8 + -@if [ ".$(suexec)" = .1 ]; then \ + echo "$(INSTALL_PROGRAM) $(TOP)/$(SRC)/support/suexec $(root)$(sbindir)/suexec"; \ + $(INSTALL_PROGRAM) $(TOP)/$(SRC)/support/suexec $(root)$(sbindir)/suexec; \ + echo "chown root $(root)$(sbindir)/suexec"; \ + chown root $(root)$(sbindir)/suexec; \ + echo "chmod 4711 $(root)$(sbindir)/suexec"; \ + chmod 4711 $(root)$(sbindir)/suexec; \ + echo "$(INSTALL_DATA) $(TOP)/$(SRC)/support/suexec.8 $(root)$(mandir)/man8/suexec.8"; \ + $(INSTALL_DATA) $(TOP)/$(SRC)/support/suexec.8 $(root)$(mandir)/man8/suexec.8; \ + fi + @echo "<=== [support]" + +# install the support programs and scripts for binary distribution +install-binsupport: + @echo "===> [support: Installing Apache support programs and scripts for binary distribution]" + $(INSTALL_PROGRAM) $(TOP)/$(SRC)/support/ab $(root)$(sbindir)/ab + $(INSTALL_DATA) $(TOP)/$(SRC)/support/ab.8 $(root)$(mandir)/man8/ab.8 + @if [ ".$(TARGET)" = .httpd ]; then \ + apachectl='apachectl'; \ + else \ + apachectl="$(TARGET)ctl"; \ + fi; \ + echo "$(INSTALL_SCRIPT) $(TOP)/$(SRC)/support/apachectl[*] $(root)$(sbindir)/$${apachectl}"; \ + sed -e 's;PIDFILE=.*;PIDFILE=$(runtimedir)/$(TARGET).pid;' \ + -e 's;HTTPD=.*;HTTPD=$(sbindir)/$(TARGET);' \ + < $(TOP)/$(SRC)/support/apachectl > $(TOP)/$(SRC)/.apaci.install.tmp && \ + $(INSTALL_SCRIPT) $(TOP)/$(SRC)/.apaci.install.tmp $(root)$(sbindir)/$${apachectl}; \ + echo "$(INSTALL_DATA) $(TOP)/$(SRC)/support/apachectl.8 $(root)$(mandir)/man8/$${apachectl}.8"; \ + $(INSTALL_DATA) $(TOP)/$(SRC)/support/apachectl.8 $(root)$(mandir)/man8/$${apachectl}.8 + $(INSTALL_PROGRAM) $(TOP)/$(SRC)/support/htpasswd $(root)$(bindir)/htpasswd + $(INSTALL_DATA) $(TOP)/$(SRC)/support/htpasswd.1 $(root)$(mandir)/man1/htpasswd.1 + $(INSTALL_PROGRAM) $(TOP)/$(SRC)/support/htdigest $(root)$(bindir)/htdigest + $(INSTALL_DATA) $(TOP)/$(SRC)/support/htdigest.1 $(root)$(mandir)/man1/htdigest.1 + @echo "$(INSTALL_SCRIPT) $(TOP)/$(SRC)/support/dbmmanage[*] $(root)$(bindir)/dbmmanage"; \ + $(INSTALL_SCRIPT) $(TOP)/$(SRC)/support/dbmmanage $(root)$(bindir)/dbmmanage + $(INSTALL_DATA) $(TOP)/$(SRC)/support/dbmmanage.1 $(root)$(mandir)/man1/dbmmanage.1 + $(INSTALL_PROGRAM) $(TOP)/$(SRC)/support/logresolve $(root)$(sbindir)/logresolve + $(INSTALL_DATA) $(TOP)/$(SRC)/support/logresolve.8 $(root)$(mandir)/man8/logresolve.8 + $(INSTALL_PROGRAM) $(TOP)/$(SRC)/support/rotatelogs $(root)$(sbindir)/rotatelogs + $(INSTALL_DATA) $(TOP)/$(SRC)/support/rotatelogs.8 $(root)$(mandir)/man8/rotatelogs.8 + @echo "$(INSTALL_SCRIPT) $(TOP)/$(SRC)/support/apxs[*] $(root)$(sbindir)/apxs"; \ + $(INSTALL_SCRIPT) $(TOP)/$(SRC)/support/apxs $(root)$(sbindir)/apxs + $(INSTALL_DATA) $(TOP)/$(SRC)/support/apxs.8 $(root)$(mandir)/man8/apxs.8 + -@if [ ".$(suexec)" = .1 ]; then \ + echo "$(INSTALL_PROGRAM) $(TOP)/$(SRC)/support/suexec $(root)$(sbindir)/suexec"; \ + $(INSTALL_PROGRAM) $(TOP)/$(SRC)/support/suexec $(root)$(sbindir)/suexec; \ + echo "chown root $(root)$(sbindir)/suexec"; \ + chown root $(root)$(sbindir)/suexec; \ + echo "chmod 4711 $(root)$(sbindir)/suexec"; \ + chmod 4711 $(root)$(sbindir)/suexec; \ + echo "$(INSTALL_DATA) $(TOP)/$(SRC)/support/suexec.8 $(root)$(mandir)/man8/suexec.8"; \ + $(INSTALL_DATA) $(TOP)/$(SRC)/support/suexec.8 $(root)$(mandir)/man8/suexec.8; \ + fi + @echo "<=== [support]" + +# install the Apache C header files +install-include: + @echo "===> [include: Installing Apache C header files]" + $(CP) $(TOP)/$(SRC)/include/*.h $(root)$(includedir)/ + $(CP) $(TOP)/$(SRC)/lib/expat-lite/*.h $(root)$(includedir)/xml/ + @osdir=`grep '^OSDIR=' $(TOP)/$(SRC)/Makefile.config | sed -e 's:^OSDIR=.*/os/:os/:'`; \ + echo "$(CP) $(TOP)/$(SRC)/$${osdir}/os.h $(root)$(includedir)/"; \ + $(CP) $(TOP)/$(SRC)/$${osdir}/os.h $(root)$(includedir)/; \ + echo "$(CP) $(TOP)/$(SRC)/$${osdir}/os-inline.c $(root)$(includedir)/"; \ + $(CP) $(TOP)/$(SRC)/$${osdir}/os-inline.c $(root)$(includedir)/ + chmod 644 $(root)$(includedir)/*.h $(root)$(includedir)/xml/*.h + @echo "<=== [include]" + +# create an initial document root containing the Apache manual, +# icons and distributed CGI scripts. +install-data: + @echo "===> [data: Installing initial data files]" + -@if [ -f $(root)$(htdocsdir)/index.html ] || [ -f $(root)$(htdocsdir)/index.html.en ]; then \ + echo "[PRESERVING EXISTING DATA SUBDIR: $(root)$(htdocsdir)/]"; \ + else \ + echo "Copying tree $(TOP)/htdocs/ -> $(root)$(htdocsdir)/"; \ + (cd $(TOP)/htdocs/ && $(TAR) $(TAROPT) - *) |\ + (cd $(root)$(htdocsdir)/ && $(TAR) -xf -); \ + find $(root)$(htdocsdir)/ -type d -exec chmod a+rx {} \; ; \ + find $(root)$(htdocsdir)/ -type f -exec chmod a+r {} \; ; \ + fi + -@if [ -f $(root)$(cgidir)/printenv ]; then \ + echo "[PRESERVING EXISTING DATA SUBDIR: $(root)$(cgidir)/]"; \ + else \ + for script in printenv test-cgi; do \ + cat $(TOP)/cgi-bin/$${script} |\ + sed -e 's;^#!/.*perl;#!$(PERL);' \ + > $(TOP)/$(SRC)/.apaci.install.tmp; \ + echo "$(INSTALL_DATA) $(TOP)/conf/$${script}[*] $(root)$(cgidir)/$${script}"; \ + $(INSTALL_DATA) $(TOP)/$(SRC)/.apaci.install.tmp $(root)$(cgidir)/$${script}; \ + done; \ + fi + @echo "Copying tree $(TOP)/icons/ -> $(root)$(iconsdir)/"; \ + (cd $(TOP)/icons/ && $(TAR) $(TAROPT) - *) |\ + (cd $(root)$(iconsdir)/ && $(TAR) -xf -); \ + find $(root)$(iconsdir)/ -type d -exec chmod a+rx {} \; ;\ + find $(root)$(iconsdir)/ -type f -exec chmod a+r {} \; + @echo "<=== [data]" + +# create the initial configuration by providing default files +# and initial config files while preserving existing ones. +install-config: + @echo "===> [config: Installing Apache configuration files]" + -@for conf in httpd.conf access.conf srm.conf; do \ + if [ .$$conf = .httpd.conf ]; then \ + target_conf="$(TARGET).conf"; \ + else \ + target_conf="$$conf"; \ + fi; \ + if [ ".$(TARGET)" = .httpd ]; then \ + target_prefix=""; \ + else \ + target_prefix="$(TARGET)_"; \ + fi; \ + (echo "##"; \ + echo "## $${target_conf} -- Apache HTTP server configuration file"; \ + echo "##"; \ + echo ""; \ + cat $(TOP)/conf/$${conf}-dist ) |\ + sed -e '/# LoadModule/r $(TOP)/$(SRC)/.apaci.install.conf' \ + -e 's;@@ServerRoot@@/htdocs;$(htdocsdir);' \ + -e 's;@@ServerRoot@@/icons;$(iconsdir);' \ + -e 's;@@ServerRoot@@/cgi-bin;$(cgidir);' \ + -e 's;@@ServerRoot@@/proxy;$(proxycachedir);' \ + -e 's;@@ServerRoot@@;$(prefix);g' \ + -e 's;httpd\.conf;$(TARGET).conf;' \ + -e 's;logs/accept\.lock;$(runtimedir)/$(TARGET).lock;' \ + -e 's;logs/apache_runtime_status;$(runtimedir)/$(TARGET).scoreboard;' \ + -e 's;logs/httpd\.pid;$(runtimedir)/$(TARGET).pid;' \ + -e "s;logs/access_log;$(logfiledir)/$${target_prefix}access_log;" \ + -e "s;logs/error_log;$(logfiledir)/$${target_prefix}error_log;" \ + -e "s;logs/referer_log;$(logfiledir)/$${target_prefix}referer_log;" \ + -e "s;logs/agent_log;$(logfiledir)/$${target_prefix}agent_log;" \ + -e 's;conf/magic;$(sysconfdir)/magic;' \ + -e 's;conf/mime\.types;$(sysconfdir)/mime.types;' \ + -e 's;User nobody;User $(conf_user);' \ + -e 's;Group #-1;Group $(conf_group);' \ + -e 's;Port 80;Port $(conf_port);' \ + -e 's;ServerAdmin you@your.address;ServerAdmin $(conf_serveradmin);' \ + -e 's;ServerName new.host.name;ServerName $(conf_servername);' \ + > $(TOP)/$(SRC)/.apaci.install.tmp && \ + echo "$(INSTALL_DATA) $(TOP)/conf/$${conf}-dist[*] $(root)$(sysconfdir)/$${target_conf}.default"; \ + $(INSTALL_DATA) $(TOP)/$(SRC)/.apaci.install.tmp $(root)$(sysconfdir)/$${target_conf}.default; \ + if [ ! -f "$(root)$(sysconfdir)/$${target_conf}" ]; then \ + echo "$(INSTALL_DATA) $(TOP)/conf/$${conf}-dist[*] $(root)$(sysconfdir)/$${target_conf}"; \ + $(INSTALL_DATA) $(TOP)/$(SRC)/.apaci.install.tmp $(root)$(sysconfdir)/$${target_conf}; \ + else \ + echo "[PRESERVING EXISTING CONFIG FILE: $(root)$(sysconfdir)/$${target_conf}]"; \ + fi; \ + done + -@for conf in mime.types magic; do \ + echo "$(INSTALL_DATA) $(TOP)/conf/$${conf} $(root)$(sysconfdir)/$${conf}.default"; \ + $(INSTALL_DATA) $(TOP)/conf/$${conf} $(root)$(sysconfdir)/$${conf}.default; \ + if [ ! -f "$(root)$(sysconfdir)/$${conf}" ]; then \ + echo "$(INSTALL_DATA) $(TOP)/conf/$${conf} $(root)$(sysconfdir)/$${conf}"; \ + $(INSTALL_DATA) $(TOP)/conf/$${conf} $(root)$(sysconfdir)/$${conf}; \ + else \ + echo "[PRESERVING EXISTING CONFIG FILE: $(root)$(sysconfdir)/$${conf}]"; \ + fi; \ + done + @echo "<=== [config]" + + +## ------------------------------------------------------------------ +## Cleanup Targets +## ------------------------------------------------------------------ + +# cleanup the source tree by removing anything which was +# created by the build target +clean: + @echo "===> $(SRC)" + @$(MAKE) -f $(TOP)/$(MKF) $(MFLAGS) $(MFWD) clean-std $(clean-support) + @echo "<=== $(SRC)" + @$(RM) $(TOP)/$(SRC)/.apaci.build.ok + +# clean the standard stuff +clean-std: + @cd $(TOP)/$(SRC); $(MAKE) $(MFLAGS) SDP=$(SRC)/ clean + +# clean additional support stuff +clean-support: + @echo "===> $(SRC)/support"; \ + cd $(TOP)/$(SRC)/support; $(MAKE) $(MFLAGS) clean; \ + if [ ".$(suexec)" = .1 ]; then \ + echo "$(RM) suexec"; \ + $(RM) suexec; \ + fi; \ + echo "<=== $(SRC)/support" + +# cleanup the source tree by removing anything which was +# created by the configure step and the build target. +# When --shadow is used we just remove the complete shadow tree. +distclean: + @if [ ".$(SRC)" = .src ]; then \ + $(MAKE) -f $(TOP)/$(MKF) $(MFLAGS) $(MFWD) distclean-normal; \ + else \ + $(MAKE) -f $(TOP)/$(MKF) $(MFLAGS) $(MFWD) distclean-shadow; \ + fi + +distclean-normal: + @echo "===> $(SRC)" + @$(MAKE) -f $(TOP)/$(MKF) $(MFLAGS) $(MFWD) distclean-std $(distclean-support) + @echo "<=== $(SRC)" + -$(RM) $(SRC)/Configuration.apaci + -$(RM) $(SRC)/apaci + @$(RM) $(SRC)/.apaci.build.ok + -$(RM) Makefile + -$(RM) config.status + +# clean the standard stuff +distclean-std: + @cd $(TOP)/$(SRC); $(MAKE) $(MFLAGS) SDP=$(SRC)/ distclean + +distclean-support: + @echo "===> $(SRC)/support"; \ + cd $(TOP)/$(SRC)/support; $(MAKE) $(MFLAGS) distclean; \ + if [ ".$(suexec)" = .1 ]; then \ + echo "$(RM) suexec"; \ + $(RM) suexec; \ + fi; \ + echo "<=== $(SRC)/support" + +distclean-shadow: + $(RM) -r $(SRC) + $(RM) $(TOP)/$(MKF) + -@if [ ".`ls $(TOP)/src.* 2>/dev/null`" = . ]; then \ + echo "$(RM) Makefile"; \ + $(RM) Makefile; \ + fi + diff --git a/APACHE_1_3_12/README b/APACHE_1_3_12/README new file mode 100644 index 0000000000..604b8dff9c --- /dev/null +++ b/APACHE_1_3_12/README @@ -0,0 +1,63 @@ + + Apache + Version 1.3 (and up) + + What is it? + ----------- + + Apache is an HTTP server designed as a plug-in replacement for + the NCSA server version 1.3 (or 1.4). It fixes numerous bugs in + the NCSA server and includes many frequently requested new + features, and has an API which allows it to be extended to meet + users' needs more easily. + + The Latest Version + ------------------ + + Details of the latest version can be found on the Apache HTTP + server project page under http://www.apache.org/. + + Documentation + ------------- + + The documentation available as of the date of this release is + also included, in HTML format, in the htdocs/manual/ directory. + For the most up-to-date documentation can be found on + http://www.apache.org/docs/. + + Installation + ------------ + + From Apache version 1.3 and up you have two possibilities to + build and install the Apache package: The old commonly known + but manual way from Apache 1.2 and below and the new + out-of-the-box way through the new Apache Autoconf-style + Interface (APACI). For detailed instructions see the file + INSTALL in this directory. + + Licensing + --------- + + Please see the file called LICENSE. + + Acknowledgments + ---------------- + + We wish to acknowledge the following copyrighted works that + make up portions of the Apache software: + + Portions of this software were developed at the National Center + for Supercomputing Applications (NCSA) at the University of + Illinois at Urbana-Champaign. + + This software contains code derived from the RSA Data Security + Inc. MD5 Message-Digest Algorithm, including various + modifications by Spyglass Inc., Carnegie Mellon University, and + Bell Communications Research, Inc (Bellcore). + + This package contains software written and copyrighted by Henry + Spencer. Please see the file called src/regex/COPYRIGHT. + + The NT port was started with code provided to the Apache Group + by Ambarish Malpani of ValiCert, Inc. (http://www.valicert.com/). + diff --git a/APACHE_1_3_12/README.NT b/APACHE_1_3_12/README.NT new file mode 100644 index 0000000000..b398a8deef --- /dev/null +++ b/APACHE_1_3_12/README.NT @@ -0,0 +1,91 @@ + + Apache + Version 1.3 (and up) + + What is it? + ----------- + + Apache is an HTTP server, originally designed for Unix systems. This + is the version of Apache for Microsoft Windows NT, 98, and 95 + systems. Like the Unix version, it includes many frequently + requested new features, and has an API that allows it to be extended + to meet users' needs more easily. It also allows ISAPI extensions. + + + The Latest Version + ------------------ + + Details of the latest version can be found on the Apache HTTP + server project page under http://www.apache.org/. + + Documentation + ------------- + + The documentation available as of the date of this release is + also included, in HTML format, in the htdocs/manual/ directory. + For the most up-to-date documentation can be found on + http://www.apache.org/docs/. For Windows specific information, see + http://www.apache.org/docs/windows.html. + + WARNING + ------- + + Apache on Win32 has not yet been optimized for performance. Apache + still performs best, and is most reliable on Unix platforms. Over + time we will improve performance for Windows NT. Folks doing + comparative reviews of webserver performance are asked to compare + against Apache on a Unix platform such as Solaris, FreeBSD, or + Linux. + + Apache on Win32 should still be considered beta quality code. It + does not meet the normal standards of stability and security that + Unix releases do. + + Installation + ------------ + + If you have installed Apache as a pre-compiled binary, you can + now run the server by selecting "Start Apache as console app" + from the Start menu. You can configure Apache for your system + by editing the file conf/httpd.conf in the directory where you + installed Apache. + + See the http://www.apache.org/docs/windows.html for details of how + to run and configure Apache, or select the "Apache Documentation" + icon read the local copy installed with Apache. + + Known Problems + -------------- + + To get information about the current set of known problems, see the + online bug reporting database at + http://www.apache.org/bug_report.html. Bugs which affect Apache on + Windows and not Apache on Unix can be found under the category + "os-windows". + + Licensing + --------- + + Please see the file called LICENSE. + + Acknowledgments + ---------------- + + We wish to acknowledge the following copyrighted works that + make up portions of the Apache software: + + Portions of this software were developed at the National Center + for Supercomputing Applications (NCSA) at the University of + Illinois at Urbana-Champaign. + + This software contains code derived from the RSA Data Security + Inc. MD5 Message-Digest Algorithm, including various + modifications by Spyglass Inc., Carnegie Mellon University, and + Bell Communications Research, Inc (Bellcore). + + This package contains software written and copyrighted by Henry + Spencer. Please see the file called src/regex/COPYRIGHT. + + The NT port was started with code provided to the Apache Group + by Ambarish Malpani of ValiCert, Inc. (http://www.valicert.com/). + diff --git a/APACHE_1_3_12/README.configure b/APACHE_1_3_12/README.configure new file mode 100644 index 0000000000..4c2b4e7da1 --- /dev/null +++ b/APACHE_1_3_12/README.configure @@ -0,0 +1,288 @@ + + APACHE CONFIGURATION + + Apache 1.3 Autoconf-style Interface (APACI) + =========================================== + + APACI is an Autoconf-style interface for the Unix side of the Apache 1.3 + HTTP server source distribution. It is actually not GNU Autoconf-based, i.e. + the GNU Autoconf package itself is not used. Instead APACI just provides a + similar batch configuration interface and a corresponding out-of-the-box + build and installation procedure. + + The basic goal is to provide the following commonly known and expected + procedure for out-of-the-box building and installing a package like Apache: + + $ gunzip plus corresponding Makefile. and then + performs the complete build process inside this shadow tree. + + Dynamic Shared Object (DSO) support + ----------------------------------- + + Apache 1.3 supports building modules as shared objects on all major Unix + platforms (see section "Supported Platforms" in document + htdocs/manual/dso.html for details). APACI has a nice way of enabling the + building of DSO-based modules and automatically installing them: + + $ ./configure --prefix=/path/to/apache \ + --enable-module=rewrite \ + --enable-shared=rewrite + $ make + $ make install + + This builds and installs Apache with the default configuration except that + it adds the mod_rewrite module and automatically builds and installs it as a + DSO, so it is optionally available for loading under runtime. To make your + life even more easy APACI additionally inserts a corresponding `LoadModule' + line into the httpd.conf file in the installation phase. + + APACI also supports a variant of the --enable-shared option: + + $ ./configure --prefix=/path/to/apache \ + --enable-shared=max + $ make + $ make install + + This enables shared object building for the maximum of modules, i.e. all + enabled modules (--enable-module or the default set) except for mod_so + itself (the bootstrapping module for DSO support). So, to build a + full-powered Apache with maximum flexibility by building and installing most + of the modules, you can use: + + $ ./configure --prefix=/path/to/apache \ + --enable-module=most \ + --enable-shared=max + $ make + $ make install + + This first enables most of the modules (all modules except some problematic + ones like mod_auth_db which needs third party libraries not available on + every platform or mod_log_agent and mod_log_referer which are deprecated) + and then enables DSO support for all of them. This way you get all these + modules installed and you then can decide under runtime (via the + `LoadModule') directives which ones are actually used. Especially a very + useful for vendor package maintainers to provide a flexible Apache package. + + On-the-fly added additional/private module + ------------------------------------------ + + For Apache there are a lot of modules flying around on the net which solve + particular problems. For a good reference see the Apache Module Registory at + http://modules.apache.org/ and the Apache Group's contribution directory at + http://www.apache.org/dist/contrib/modules/. These modules usually come in a + file named mod_foo.c. APACI supports adding these sources on-the-fly to the + build process: + + $ ./configure --prefix=/path/to/apache \ + --add-module=/path/to/mod_foo.c + $ make + $ make install + + This automatically copies mod_foo.c to src/modules/extra/, activates it in + the configuration and builds Apache with it. A very useful way is to combine + this with the DSO support: + + $ ./configure --prefix=/path/to/apache \ + --add-module=/path/to/mod_foo.c \ + --enable-shared=foo + $ make + $ make install + + This builds and installs Apache with the default set of modules, but + additionally builds mod_foo as a DSO and adds a `LoadModule' line to the + httpd.conf file to activate it for loading under runtime. + + Apache and mod_perl + ------------------- + + The Apache/Perl integration project (http://perl.apache.org/) from Doug + MacEachern is a very powerful approach to integrate + a Perl 5 interpreter into the Apache HTTP server both for running Perl + programs and for programming Apache modules in Perl. The distribution + mod_perl-1.XX.tar.gz can be found on http://perl.apache.org/src/. Here is + how you can build and install Apache with mod_perl: + + $ gunzip with AllowOverride None, + which is something all sites should do in any case. + Status: Marc was looking at it. + + * Ronald Tschalär's patch to mod_proxy to allow other modules to + set headers too (needed by mod_auth_digest) + Message-ID: <199907080712.JAA28269@chill.innovation.ch> + Status: + +Documentation that needs writing: + + +Available Patches: + + * Andrew Ford's patch (1999/12/05) to add absolute times to mod_expires + Message-ID: + Status: Martin +1, Jim +1 + + * Raymond S Brand's path to mod_autoindex to fix the header/readme + include processing so the envariables are correct for the included + documents. (Actually, there are two variants in the patch message, + for two different ways of doing it.) + Message-ID: <384AA242.B93F8B5@rsbx.net> + Status: Martin +1(concept) + + * Jayaram's patch (10/27/99) to fix PR4856 + PR: 4856 It is found that UnSetEnv directive fails to unset the + environment variable in the server config context. + Status: + + * Jayaram's patch (10/27/99) for changes to mod_autoindex + + Problem 1: + ------------------------ + AddIcon (,) ^^DIRECTORY^^ + and + AddIcon (,) ^^BLANKICON^^ + should be able to set the alternate text and icon file for any directory/ + blankicon in a directory listing. This was not happening because the + alternate text for ^^DIRECTORY^^ and ^^BLANKICON^^ were hardcoded to + "DIR" and " " respectively. + + Problem 2: + ------------------------- + IndexIgnore should hide the files with this file- + extension in directory listings. This was NOT happening because the + total filename was being compared with the file-extension. + + Status: Martin +1(untested) + + * JJ Keijser's patch (99/10/06) to enable mod_info on Win32 + PR#: PR2415, PR1442 + Status: + + * JJ Keijser's patch (99/10/06) to: + - Run Apache as a service on Win95 (PR2208) + - Making sure that Apache is shut down when the system is shutdown. + (PR1643, PR2472) + - Use apache -i/-u to install/uninstalling Apache on Win95 + - Add ConsoleCtrlHandler to catch Ctrl-C in the Apache console window + - Make Apache shut down cleanly when run on Windows 95 (PR4125) + PR#: PR2472, PR4125, PR1643 (suspended) and PR2208 (suspended). + Status: Martin +1(untested) + + * Paul Reder's patch to fix Allow/Deny (.htaccess parsing) in + regex processing. + Message-ID: <37A88E34.FD09C658@raleigh.ibm.com> + PR: 3019, 3454 + Status: + + * David Harris' patch to add a function to report on the number + of bytes in a pool that are actually used. + Message-ID: <008e01bedead$781c9480$0500a8c0@delf> + Status: + + * Stipe Tolj's Cygwin32 port + PR#: 2936 + Status: Lars +1 (on concept), Martin +1 (on concept), Ken +1 (concept) + + * Salvador Ortiz Garcia ' patch to allow DirectoryIndex + to refer to URIs for non-static resources. + MID: + Status: Ken +1 (on concept), Lars +1 (on concept) + + * Ralf's [PATCH] to add EAPI (ctx, hook, mm, etc.) to the base package + Message-ID: <19990414134729.A93825@engelschall.com> + Status: Mark +1, Dean +1, BenH +1, + Randy +1 (please choose name other than "hook") + Doug +1 on concept (untested), Lars +1 on concept, + Martin +1 (untested), Fred +1, + Jim -1 (I really don't think it makes sense to + add this right now this late in the release cycle + for 1.3.10. I am +1 for 1.3.11) + Greg -0 for 1.3 series. + + * Brian Havard's patch to remove dependency of mod_auth_dbm on mod_auth. + (PR#2598) + Message-ID: <199905170830.SAA31549@silk.apana.org.au> + Status: Lars +1 (on concept), Ken +1 (on concept), Martin +1(untested) + + * Aidan Cully's patch to allow assignment of 'ownership' of resources + to either the server UID or the file's owner. + Message-ID: <37306CB4.8EA9D76C@Golux.Com> + Status: Ken +1, Dean +1, Randy +1, Lars +0, Jim +1 + + * Keith Wannamaker's NT multiple services patch + Message-ID: <85256730.0073D841.00@d54mta06.raleigh.ibm.com> + Status: Bill +1 (on concept), Lars +1 (on concept) + + * Jun-ichiro itojun Hagino's [PATCH] IPv6 enable patch + ftp://ftp.kame.net/pub/kame/misc/apache-139-v6-19991013a.diff.gz + Message-ID: <18586.916662926@coconut.itojun.org>, + <24384.944888872@coconut.itojun.org> + Status: Lars +1 (on concept), Dirkx +1 (tested), + Martin +1 (on concept, but patched apache does not + compile successfully on pre-IPv6-SVR4, + and possibly others), Jim -1 (not for 1.3.10) + Greg -0 for 1.3 series. + + * Jim Patterson's patch to make mod_info work on Win32 + Message-ID: PR#1442 + Status: Lars +1 (on concept), Ken +1 (concept) + + * Peter Greis' new '%m' CustomLog option: the time taken to serve the + request, in milli-seconds. + Message-ID: PR#2838 + Status: Jim +0 (as is, the patch requires rework since it needs + to be aware of NO_GETTIMEOFDAY and NO_TIMES as well as + implement a times() alternative. Not only that, but with + extended_status, we calculate this anyway). + + * Juan Gallego's patch to add CSH-style modifiers (:h, :r, :t, :e) + to mod_include's variable processing. + Mesage-ID: PR#3246, also available at + + Status: Ken, Greg: -0 for 1.3/+0 for 2.0 + Lars -0 for 1.3 + + * Eric Prud'hommeaux's mod_dir mods for file-level access control. + Message-ID: + Status: Jim -0 (The current behavior seems logical to me. If there + was more universal interest in changing it, then that would be + a different matter). + + * Eric Prud'hommeaux's mods for practical negotiation with + file level access control. + Message-ID: + Status: + + * Greg's XML Handling patch + Message-ID: <3764E070.381B1B8E@lyra.org> + Message-ID: <3760EC9C.1CB6398E@lyra.org> + Status: Greg -0 (will integrate into 2.0 rather than 1.3) + Martin +1 (on concept) + +In progress: + + * Doug MacEachern's libapr - Generic Apache Request Library (Alpha) + This package contains modules for manipulating client request data + via the Apache API with Perl and C. + Status: http://www.pobox.com/~dougm/libapr-0.20_01.tar.gz + + * David Harris' note of odd size memory allocations. Dean notes + that this is due to BLOCK_MIN_ALLOC. Should we reduce it to 1024? + Discussion in thread following message-ID below. + Message-ID: <00a001bedc00$fbc5af60$0500a8c0@delf> + Status: + + * Martin Kraemer's mod_ebcdic.c: a new module which will contain the + ebcdic related stuff (common to all ebcdic based os's) and will + allow for flexible configuration of the conversion rules. That + will replace the current hardwired heuristics. + Message-Id: none yet + Status: first prototype running, to be posted to list soon. + +Needs patch: + + * MaxRequestsPerChild doesn't count requests, only the + number of connections processed. + We can either 'fix' it by renaming the directive to + MaxConnectionsPerChild or really fix it to actually count + the number of requests. + Lars: I think we should really fix. + Ken: Definitely fix this, otherwise a massive series of + requests on the same connection is possible, which + defeats the purpose. + Jim: The main idea behind this is to avoid problems with + memory leaks. So it really doesn't matter which we + do, as long as there's a match between the directive + and what it does. Since it's easier, I'd say just + rename to MaxConnectionsPerChild but keep MaxRequestsPerChild + as an "alias" to that (maybe print a short "MaxRequestsPerChild + is depreciated" message when Apache starts). + + * get_path_info bug; ap_get_remote_host should be ap_vformatter instead. + See: + + * URI issues + - RFC2068 requires a server to recognize its own IP addr(s) in dot + notation, we do this fine if the user follows the dns-caveats + documentation... we should handle it in the case the user doesn't ever + supply a dot-notation address. + + * Problems dealing with .-rooted domain names such as "twinlark." versus + "twinlark.arctic.org.". See the thread containing + Message-ID: <19980203211817.06723@deejai.mch.sni.de> for more details. + In particular this affects the correctness of the proxy and the + vhost mechanism. + + * proxy_*_canon routines use r->proxyreq incorrectly. See + + + * work around a Navigator/Mozilla bug when mod_proxy is used + (broken images). + Message-ID: + Status: Lars' patch was vetoed. Roy and Dean think that it is + probably another buffer magic number error and should be + tested to find out and, if so, fixed like it was in core. + Dirkx: cannot reproduce this at all. + + * ap_escape_html() always duplicates the string, even when there is + no change and the caller would be happy to use the original. + What is needed is a separate interface for "don't need a dup" + situations, like just about everywhere we use it in bvputs and + bputs calls. + dirkx: -1 (as some of the modules from modules.apache.org seem + (rightly?) to assume that they can modify the returned escaped + string whilst relying on the passed string not to be damaged. + Martin: +1 (a "separate interface" is like in the case of + ap_table_setn() complementing ap_table_set(). It would not + interfere with any existing code). + + * Should we disallow requests with bogus characters in the method? + See + +Open issues: + + * Should we provide a way to force CustomError responses past IE's + 'prettify-if-less-than-N-bytes' bogosity? + + * there are still some PRs about inetd mode + Should we deprecate "ServerType inetd" if the next release is 1.4.0? + +1: Lars + -0: Martin (ISTR someone volunteered to "keep it working". I fear + some exotic platforms may require it) + + * general/3787: SERVER_PORT is always 80 if client comes to any port + => needs review by the protocol guys, I think. + + * Paul would like to see a 'gdbm' option because he uses + it a lot. + -0: Greg (volunteers; will add to 2.0 series rather than 1.3) + +1: Martin + + * Many people have asked for a DBM to be distributed with Apache to + isolate it from platform inconsistencies. SDBM (used by mod_ssl, + mod_dav, Perl, and others) should fit the bill and is public domain. + -0: Greg (volunteers; will add to 2.0 series rather than 1.3) + +1: Martin + + * Maybe a http_paths.h file? See + + +1: Brian, Paul, Ralf, Martin, Dirkx + +0: Jim (not for 1.3.0) + + * Release builds: Should we provide Configuration or not? + Should we 'make all suexec' in src/support? + +1: Brian, Jim, Dirkx, Ken +1 (possible suexec path issue, though) + + * root's environment is inherited by the Apache server. Jim & Ken + think we should recommend using 'env' to build the + appropriate environment. Marc and Alexei don't see any + big deal. Martin says that not every "env" has a -u flag. + + * Marc's socket options like source routing (kill them?) + Marc, Martin say Yes + + * Ken's PR#1053: an error when accessing a negotiated document + explicitly names the variant selected. Should it do so, or should + the original URI be referenced? + Martin: keep as is (helps identifying errors. IMO no privacy issue.) + + * Proposed API Changes: + + - r->content_language is for backwards compatibility... with modules + that may not link any longer without some minor editing. The new + field is r->content_languages. Heck it's not even mentioned in + apache-devsite/mmn.txt when we got content_languages (note the s!). + The proposal is to remove r->content_language: + Status: Paul +1, Ralf +1, Ken +1, Martin +1, Dirkx +1 (I could + not find ANY module which uses it and which (still) compiles + after the config change.) + + - child_exit() is redundant, it can be implemented via cleanups. It is + not "symmetric" in the sense that there is no exit API method to go + along with the init() API method. There is no need for an exit + method, there are already modules using cleanups to perform this (see + mod_mmap_static, and mod_php3 for example). The proposal is to + remove the child_exit() method and document cleanups as the method of + handling this need. + Status: Rasmus +1, Paul +1, Jim +1, + Martin +1, Ralf +1, Ken +1, + Dirkx +1 (with doc change) + + * Should we re-enable nagle now that we're non-buffering CGIs? See + various messages from Marc in March 98. + + * TZ should not be dealt with specially any longer now that we have + "PassEnv". See + + Jim: IMO it's too late in the game for this... I'm + sure this would cause some strange bug reports as + people's cgi-scripts no longer work correctly + ("It worked just fine before I upgraded to 1.3.0") + unless we warn people in big nasty letters to add + PassEnv TZ to their config files "just in case" + and hope they do it :) + Dirkx: Is not this the same issue about maintaining your 'env' ? + + * In ap_bclose() there's no test that (fb->fd != -1) -- so it's + possible that it'll do something completely bogus when it's + used for read-only things. - Dean Gaudet + + * Roy's HTTP/1.1 Wishlist items: + 1) byte range error handling + + * use of spawnvp in uncompress_child in mod_mime_magic - doesn't + use the new child_info structure, is this still safe? Needs to be + looked at. + + * suexec doesn't understand argv parameters; e.g. + + + + fails even when "ls" is in the same directory because suexec is trying + to stat a file called "ls -l". A patch for this is available at + + http://www.xnet.com/~emarshal/suexec.diff + + and it's not bad except that it doesn't handle programs with spaces in + the filename (think win32, or samba-mounted filesystems). There are + several PR's to this and I don't see for security reasons why we can't + accomodate it, though it does add complexity to suexec.c. + PR #1120 + Brian: +1 + +Win32 specific issues: + + Important + + * fix O(n^2) attack in mod_isapi.c ... i.e. recopy the code from + scan_script_headers_err_core. + + In progress: + + * Ben's ASP work... All agree it sounds cool. + + * DDA's adding a tray application to the Windoze version for ease of + status/management. + <01BCDB29.2C04DEB0@caravan.individual.com> + <01BCDB2A.F8C09010@caravan.individual.com> + Status: Ken +1, Sameer +1, Martin +1, Ben +1 (as long as + we get a single executable) + Paul: No like Win95 specific stuff + Ken: What's W95-specific about it? + + Help: + * There are several PRs reporting Apache looping and they each seem to + implicate CGI script processing. The first PR happened about the time + we migrated to using native Win32 function calls to create the child + process. I have tried to recreate the problem w/o success. It just now + occurs to me that there may be a race condition between when the new + process comes alive and the parent sending data to (or attempting to + read data from) the child process. CreateProcess() returns immediately, + before the new process is created. The parent may be attempting I/O + with the child before it's ready. TODO: investigate ways to cause the + parent to wait for the child process to become fully active before + proceeding with CGI I/O processing. + + * should trap ^C when running not-as-service and do proper shutdown + + * should have a pretty little icon for Apache on Win32 + (Resolved?! there's a tiny feather icon now!?!) + + * proxy module doesn't load on Win95. Why? Good question. PR#1462. + David Whitmarsh says it's because + you can't dynamically load a DLL that uses declspec(thread). He + supplied a patch. + MID: <36f6e9bb.16134842@smtp.dial.pipex.com> + + * Proxy cache garbage collection doesn't work. PR#1891 + + * chdir() for CGI scripts and mod_include #exec needs to be + re-implemented now that CreateProcess is being used. + + * process/thread model + - need dynamic thread creation/destruction, similar to + Unix process model + - can't use WaitForMultipleObjects in the same way we + do now, since that has a limit of 64(!) objects. Grr. + PR#1665 + + * some errors printed by CGIs to stderr don't end up making it + to the server log unless an extra debugging message is added + after they run? (PR#1725 indicates this may not be just Win32) + + * handle bugs that make it pop up errors on console, ie. segv + equiv? Can we do this? Need to make it robust. + + * install + - make installshield work + - config in cvs tree? + - install docs, etc.? + - location for install + + * the mutex should be critical-regions, since the current design + is creating a mess of SO calls that are unnecessary + + * we don't mmap on NT. Use TransmitFile? + + * CGIs + - docs on how they work w/scripts + - WTF is the buffering coming from? + - we don't have a way to make non-blocking files on NT! + + * performance + + * documentation: + - running the server without admin + - how CGIs work + - update README.NT + - short/long name handling + - better status page on current state of NT for users + + * http_main.c hell + - split into two files? + + * who should run the service? Who exactly is the "system account"? + + docs say: + + Localsystem is a very privileged account locally, so you shouldn't run + any shareware applications there. However, it has no network privileges + and cannot leave the machine via any NT-secured mechanism, including + file system, named pipes, DCOM, or secure RPC. + + and: + + A service that runs in the context of the LocalSystem account + inherits the security context of the SCM. It is not associated with + any logged-on user account and does not have credentials (domain + name, user name, and password) to be used for verification. This + has several implications: [... removed ...] + + + That _really_ sucks. Can we recommend running Apache as some + other user? + + * modules that need to be made to work on win32 + - mod_example isn't multithreadreded + - mod_unique_id (needs mt changes) + - mod_auth_db.c (do we want to even try this? We should have some + db of some sort... what else can we pick from under win32?) + - mod_auth_dbm.c + - mod_info.c (PR#1442 re exporting symbols for it...) + - mod_log_agent.c + - mod_log_referer.c + - mod_mime_magic.c (needs access to mod_mime API stage...) + + * do something to disable bogus warnings + + * rfc1413.c has static storage which won't work multithreaded + + * mod_include --> exec cgi, exec cmd, etc. don't work right. + Looks like a code path that isn't run anywhere else that has + something not quite right... A PR or two on it. + + * signal type handling + - how to rotate logs from command line? + (Point people to Andrew Ford's cronolog because it's "better" + than ours?) + + * Currently if you double click on the conf files or the + log files you get a useless dialog offering the set of all + executables, usually after a very long pause. Ought + to stuff .conf in the registry mapping it to text. + + * apparently either "BrowserMatch" or the "nokeepalive" variable + cause instability - see PR#1729. + + +Binaries (1.3.11): + + Platform Avail. Volunteer + ------------------------------------------------------------------------------ + alpha-dec-osf3.0 no Sameer Parekh + alpha-dec-osf4.0 no Lars Eilebrecht, Ken Coar, Randy Terbush + alpha-whatever-linux2 no Randy Terbush + armv4l-whatever-linux2 no Rasmus Lerdorf + hppa1.1-hp-hpux-10.x no Rob Hartill, Randy Terbush + i386-slackware-linux(a.out) no Sameer Parekh + i386-sun-solaris2.5 no Sameer Parekh + i386-sun-solaris2.6 no Randy Terbush + i386-sun-solaris2.7 no Cliff Skolnick + i386-unixware-svr4 no Sameer Parekh, Randy Terbush + i386-unknown-freebsd2.1 no Andrew Wilson, Brian Tao + i386-unknown-freebsd2.2.8 yes Jim Jagielski + i386-whatever-freebsd3.0 no Ken Coar + i386-whatever-freebsd3.0 no Dirk-Willem van Gulik + i686-pc-freebsd3.1 no Ralf S. Engelschall + i586-unknown-linux2 no Ralf S. Engelschall, Lars Eilebrecht, Randy Terbush + i686-unknown-linux2 no Lars Eilebrecht + i686-whatever-linux2 no Ken Coar, Randy Terbush + i386-unknown-linux(ELF) no Aram Mirzadeh, Michael Douglass + i386-unknown-netBSD-1.3.2 no Lars Eilebrecht, Randy Terbush + i386-unknown-sco3 no Ben Laurie + i386-unknown-sco5 no Ben Laurie + i386-siemens-sinix5.4 yes Martin Kraemer + i386-dg-dgux5.4R2.01 no Randy Terbush + x86-qnx-4.x no Randy Terbush + x86-bsdos-3.x no Randy Terbush + x86-bsdos-4.x no Randy Terbush + x86-openbsd-2.x no Randy Terbush + m68k-apple-aux3.1.1 no Jim Jagielski + m88k-dg-dgux5.4R2.01 no Sameer parekh + m88k-next-next no Rob Hartill + mips-dec-ultrix4.4 no Sameer Parekh + mips-unknown-linux no Lars Eilebrecht + mips-sgi-irix5.3 no Mark Imbrianco, Randy Terbush + mips-sgi-irix6.2 no Lars Eilebrecht, Randy Terbush + mips-sgi-irix6.4 no Lars Eilebrecht + mips-siemens-reliantunix5.4 yes Martin Kraemer + OS/2 yes Brian Havard + powerpc-apple-rhapsody5.6 yes Wilfredo Sanchez + rs6000-ibm-aix3.2.5 no Sameer Parekh + rs6000-ibm-aix4.1 no Lars Eilebrecht + rs6000-ibm-aix4.2 no Bill Stoddard + rs6000-ibm-aix4.3.x no Bill Stoddard, Randy Terbush + sparc-sun-solaris2.5 no Lars Eilebrecht, Randy Terbush + sparc-sun-solaris2.6 no Lars Eilebrecht + sparc-sun-solaris2.7 no Cliff Skolnick + sparc-sun-sunos4.1.3_U1 no Sameer Parekh + sparc-unknown-linux no Lars Eilebrecht, Randy Terbush diff --git a/APACHE_1_3_12/WARNING-NT.TXT b/APACHE_1_3_12/WARNING-NT.TXT new file mode 100644 index 0000000000..94320d3f37 --- /dev/null +++ b/APACHE_1_3_12/WARNING-NT.TXT @@ -0,0 +1,8 @@ +WARNING: The Win32 release of Apache should +still be considered beta quality code. +It does not meet the normal standards of +stability and security that Unix releases do. +There are numerous known bugs and +inconsistencies. There is also a much +greater chance of security holes being +present in the Win32 version of Apache. diff --git a/APACHE_1_3_12/cgi-bin/printenv b/APACHE_1_3_12/cgi-bin/printenv new file mode 100644 index 0000000000..207074361a --- /dev/null +++ b/APACHE_1_3_12/cgi-bin/printenv @@ -0,0 +1,13 @@ +#!/usr/local/bin/perl +## +## printenv -- demo CGI program which just prints its environment +## + +print "Content-type: text/plain\n\n"; +foreach $var (sort(keys(%ENV))) { + $val = $ENV{$var}; + $val =~ s|\n|\\n|g; + $val =~ s|"|\\"|g; + print "${var}=\"${val}\"\n"; +} + diff --git a/APACHE_1_3_12/cgi-bin/test-cgi b/APACHE_1_3_12/cgi-bin/test-cgi new file mode 100644 index 0000000000..a85631e3aa --- /dev/null +++ b/APACHE_1_3_12/cgi-bin/test-cgi @@ -0,0 +1,31 @@ +#!/bin/sh + +# disable filename globbing +set -f + +echo Content-type: text/plain +echo + +echo CGI/1.0 test script report: +echo + +echo argc is $#. argv is "$*". +echo + +echo SERVER_SOFTWARE = $SERVER_SOFTWARE +echo SERVER_NAME = $SERVER_NAME +echo GATEWAY_INTERFACE = $GATEWAY_INTERFACE +echo SERVER_PROTOCOL = $SERVER_PROTOCOL +echo SERVER_PORT = $SERVER_PORT +echo REQUEST_METHOD = $REQUEST_METHOD +echo HTTP_ACCEPT = "$HTTP_ACCEPT" +echo PATH_INFO = "$PATH_INFO" +echo PATH_TRANSLATED = "$PATH_TRANSLATED" +echo SCRIPT_NAME = "$SCRIPT_NAME" +echo QUERY_STRING = "$QUERY_STRING" +echo REMOTE_HOST = $REMOTE_HOST +echo REMOTE_ADDR = $REMOTE_ADDR +echo REMOTE_USER = $REMOTE_USER +echo AUTH_TYPE = $AUTH_TYPE +echo CONTENT_TYPE = $CONTENT_TYPE +echo CONTENT_LENGTH = $CONTENT_LENGTH diff --git a/APACHE_1_3_12/conf/.cvsignore b/APACHE_1_3_12/conf/.cvsignore new file mode 100644 index 0000000000..39efabf64d --- /dev/null +++ b/APACHE_1_3_12/conf/.cvsignore @@ -0,0 +1,4 @@ +access.conf +httpd.conf +srm.conf +highperformance.conf diff --git a/APACHE_1_3_12/conf/access.conf-dist b/APACHE_1_3_12/conf/access.conf-dist new file mode 100644 index 0000000000..a38b11bace --- /dev/null +++ b/APACHE_1_3_12/conf/access.conf-dist @@ -0,0 +1,8 @@ +# +# This is the default file for the AccessConfig directive in httpd.conf. +# It is processed after httpd.conf and srm.conf. +# +# To avoid confusion, it is recommended that you put all of your +# Apache server directives into the httpd.conf file and leave this +# one essentially empty. +# diff --git a/APACHE_1_3_12/conf/access.conf-dist-win b/APACHE_1_3_12/conf/access.conf-dist-win new file mode 100644 index 0000000000..a38b11bace --- /dev/null +++ b/APACHE_1_3_12/conf/access.conf-dist-win @@ -0,0 +1,8 @@ +# +# This is the default file for the AccessConfig directive in httpd.conf. +# It is processed after httpd.conf and srm.conf. +# +# To avoid confusion, it is recommended that you put all of your +# Apache server directives into the httpd.conf file and leave this +# one essentially empty. +# diff --git a/APACHE_1_3_12/conf/highperformance.conf-dist b/APACHE_1_3_12/conf/highperformance.conf-dist new file mode 100644 index 0000000000..d5a931359e --- /dev/null +++ b/APACHE_1_3_12/conf/highperformance.conf-dist @@ -0,0 +1,52 @@ +# Ha, you're reading this config file looking for the easy way out! +# "how do I make my apache server go really really fast??" +# Well you could start by reading the htdocs/manual/misc/perf-tuning.html +# page. But, we'll give you a head start. +# +# This config file is small, it is probably not what you'd expect on a +# full featured internet webserver with multiple users. But it's +# probably a good starting point for any folks interested in testing +# performance. +# +# To run this config you'll need to use something like: +# httpd -f @@ServerRoot@@/conf/highperformance.conf + +Port 80 +ServerRoot @@ServerRoot@@ +DocumentRoot @@ServerRoot@@/htdocs +MaxClients 150 +StartServers 5 +MinSpareServers 5 +MaxSpareServers 10 +# Assume no memory leaks at all +MaxRequestsPerChild 0 + +# this is a True Config File +# see http://www.apache.org/info/three-config-files.html +ResourceConfig /dev/null +AccessConfig /dev/null + +# it's always nice to know the server has started +ErrorLog logs/error_log + +# Some benchmarks require logging, which is a good requirement. Uncomment +# this if you need logging. +#TransferLog logs/access_log + +# Disable symlink protection and htaccess files, they chew far too much. + + AllowOverride none + Options FollowSymLinks + # If this was a real internet server you'd probably want to + # uncomment these: + #order deny,allow + #deny from all + + +# If this was a real internet server you'd probably want to uncomment this: +# +# order allow,deny +# allow from all +# + +# OK that's enough hints. Read the documentation if you want more. diff --git a/APACHE_1_3_12/conf/httpd.conf-dist b/APACHE_1_3_12/conf/httpd.conf-dist new file mode 100644 index 0000000000..bd22702a4e --- /dev/null +++ b/APACHE_1_3_12/conf/httpd.conf-dist @@ -0,0 +1,924 @@ +# +# Based upon the NCSA server configuration files originally by Rob McCool. +# +# This is the main Apache server configuration file. It contains the +# configuration directives that give the server its instructions. +# See for detailed information about +# the directives. +# +# Do NOT simply read the instructions in here without understanding +# what they do. They're here only as hints or reminders. If you are unsure +# consult the online docs. You have been warned. +# +# After this file is processed, the server will look for and process +# @@ServerRoot@@/conf/srm.conf and then @@ServerRoot@@/conf/access.conf +# unless you have overridden these with ResourceConfig and/or +# AccessConfig directives here. +# +# The configuration directives are grouped into three basic sections: +# 1. Directives that control the operation of the Apache server process as a +# whole (the 'global environment'). +# 2. Directives that define the parameters of the 'main' or 'default' server, +# which responds to requests that aren't handled by a virtual host. +# These directives also provide default values for the settings +# of all virtual hosts. +# 3. Settings for virtual hosts, which allow Web requests to be sent to +# different IP addresses or hostnames and have them handled by the +# same Apache server process. +# +# Configuration and logfile names: If the filenames you specify for many +# of the server's control files begin with "/" (or "drive:/" for Win32), the +# server will use that explicit path. If the filenames do *not* begin +# with "/", the value of ServerRoot is prepended -- so "logs/foo.log" +# with ServerRoot set to "/usr/local/apache" will be interpreted by the +# server as "/usr/local/apache/logs/foo.log". +# + +### Section 1: Global Environment +# +# The directives in this section affect the overall operation of Apache, +# such as the number of concurrent requests it can handle or where it +# can find its configuration files. +# + +# +# ServerType is either inetd, or standalone. Inetd mode is only supported on +# Unix platforms. +# +ServerType standalone + +# +# ServerRoot: The top of the directory tree under which the server's +# configuration, error, and log files are kept. +# +# NOTE! If you intend to place this on an NFS (or otherwise network) +# mounted filesystem then please read the LockFile documentation +# (available at ); +# you will save yourself a lot of trouble. +# +# Do NOT add a slash at the end of the directory path. +# +ServerRoot "@@ServerRoot@@" + +# +# The LockFile directive sets the path to the lockfile used when Apache +# is compiled with either USE_FCNTL_SERIALIZED_ACCEPT or +# USE_FLOCK_SERIALIZED_ACCEPT. This directive should normally be left at +# its default value. The main reason for changing it is if the logs +# directory is NFS mounted, since the lockfile MUST BE STORED ON A LOCAL +# DISK. The PID of the main server process is automatically appended to +# the filename. +# +#LockFile logs/accept.lock + +# +# PidFile: The file in which the server should record its process +# identification number when it starts. +# +PidFile logs/httpd.pid + +# +# ScoreBoardFile: File used to store internal server process information. +# Not all architectures require this. But if yours does (you'll know because +# this file will be created when you run Apache) then you *must* ensure that +# no two invocations of Apache share the same scoreboard file. +# +ScoreBoardFile logs/apache_runtime_status + +# +# In the standard configuration, the server will process this file, +# srm.conf, and access.conf in that order. The latter two files are +# now distributed empty, as it is recommended that all directives +# be kept in a single file for simplicity. The commented-out values +# below are the built-in defaults. You can have the server ignore +# these files altogether by using "/dev/null" (for Unix) or +# "nul" (for Win32) for the arguments to the directives. +# +#ResourceConfig conf/srm.conf +#AccessConfig conf/access.conf + +# +# Timeout: The number of seconds before receives and sends time out. +# +Timeout 300 + +# +# KeepAlive: Whether or not to allow persistent connections (more than +# one request per connection). Set to "Off" to deactivate. +# +KeepAlive On + +# +# MaxKeepAliveRequests: The maximum number of requests to allow +# during a persistent connection. Set to 0 to allow an unlimited amount. +# We recommend you leave this number high, for maximum performance. +# +MaxKeepAliveRequests 100 + +# +# KeepAliveTimeout: Number of seconds to wait for the next request from the +# same client on the same connection. +# +KeepAliveTimeout 15 + +# +# Server-pool size regulation. Rather than making you guess how many +# server processes you need, Apache dynamically adapts to the load it +# sees --- that is, it tries to maintain enough server processes to +# handle the current load, plus a few spare servers to handle transient +# load spikes (e.g., multiple simultaneous requests from a single +# Netscape browser). +# +# It does this by periodically checking how many servers are waiting +# for a request. If there are fewer than MinSpareServers, it creates +# a new spare. If there are more than MaxSpareServers, some of the +# spares die off. The default values are probably OK for most sites. +# +MinSpareServers 5 +MaxSpareServers 10 + +# +# Number of servers to start initially --- should be a reasonable ballpark +# figure. +# +StartServers 5 + +# +# Limit on total number of servers running, i.e., limit on the number +# of clients who can simultaneously connect --- if this limit is ever +# reached, clients will be LOCKED OUT, so it should NOT BE SET TOO LOW. +# It is intended mainly as a brake to keep a runaway server from taking +# the system with it as it spirals down... +# +MaxClients 150 + +# +# MaxRequestsPerChild: the number of requests each child process is +# allowed to process before the child dies. The child will exit so +# as to avoid problems after prolonged use when Apache (and maybe the +# libraries it uses) leak memory or other resources. On most systems, this +# isn't really needed, but a few (such as Solaris) do have notable leaks +# in the libraries. For these platforms, set to something like 10000 +# or so; a setting of 0 means unlimited. +# +# NOTE: This value does not include keepalive requests after the initial +# request per connection. For example, if a child process handles +# an initial request and 10 subsequent "keptalive" requests, it +# would only count as 1 request towards this limit. +# +MaxRequestsPerChild 0 + +# +# Listen: Allows you to bind Apache to specific IP addresses and/or +# ports, in addition to the default. See also the +# directive. +# +#Listen 3000 +#Listen 12.34.56.78:80 + +# +# BindAddress: You can support virtual hosts with this option. This directive +# is used to tell the server which IP address to listen to. It can either +# contain "*", an IP address, or a fully qualified Internet domain name. +# See also the and Listen directives. +# +#BindAddress * + +# +# Dynamic Shared Object (DSO) Support +# +# To be able to use the functionality of a module which was built as a DSO you +# have to place corresponding `LoadModule' lines at this location so the +# directives contained in it are actually available _before_ they are used. +# Please read the file README.DSO in the Apache 1.3 distribution for more +# details about the DSO mechanism and run `httpd -l' for the list of already +# built-in (statically linked and thus always available) modules in your httpd +# binary. +# +# Note: The order is which modules are loaded is important. Don't change +# the order below without expert advice. +# +# Example: +# LoadModule foo_module libexec/mod_foo.so + +# +# ExtendedStatus controls whether Apache will generate "full" status +# information (ExtendedStatus On) or just basic information (ExtendedStatus +# Off) when the "server-status" handler is called. The default is Off. +# +#ExtendedStatus On + +### Section 2: 'Main' server configuration +# +# The directives in this section set up the values used by the 'main' +# server, which responds to any requests that aren't handled by a +# definition. These values also provide defaults for +# any containers you may define later in the file. +# +# All of these directives may appear inside containers, +# in which case these default settings will be overridden for the +# virtual host being defined. +# + +# +# If your ServerType directive (set earlier in the 'Global Environment' +# section) is set to "inetd", the next few directives don't have any +# effect since their settings are defined by the inetd configuration. +# Skip ahead to the ServerAdmin directive. +# + +# +# Port: The port to which the standalone server listens. For +# ports < 1023, you will need httpd to be run as root initially. +# +Port 80 + +# +# If you wish httpd to run as a different user or group, you must run +# httpd as root initially and it will switch. +# +# User/Group: The name (or #number) of the user/group to run httpd as. +# . On SCO (ODT 3) use "User nouser" and "Group nogroup". +# . On HPUX you may not be able to use shared memory as nobody, and the +# suggested workaround is to create a user www and use that user. +# NOTE that some kernels refuse to setgid(Group) or semctl(IPC_SET) +# when the value of (unsigned)Group is above 60000; +# don't use Group #-1 on these systems! +# +User nobody +Group #-1 + +# +# ServerAdmin: Your address, where problems with the server should be +# e-mailed. This address appears on some server-generated pages, such +# as error documents. +# +ServerAdmin you@your.address + +# +# ServerName allows you to set a host name which is sent back to clients for +# your server if it's different than the one the program would get (i.e., use +# "www" instead of the host's real name). +# +# Note: You cannot just invent host names and hope they work. The name you +# define here must be a valid DNS name for your host. If you don't understand +# this, ask your network administrator. +# If your host doesn't have a registered DNS name, enter its IP address here. +# You will have to access it by its address (e.g., http://123.45.67.89/) +# anyway, and this will make redirections work in a sensible way. +# +#ServerName new.host.name + +# +# DocumentRoot: The directory out of which you will serve your +# documents. By default, all requests are taken from this directory, but +# symbolic links and aliases may be used to point to other locations. +# +DocumentRoot "@@ServerRoot@@/htdocs" + +# +# Each directory to which Apache has access, can be configured with respect +# to which services and features are allowed and/or disabled in that +# directory (and its subdirectories). +# +# First, we configure the "default" to be a very restrictive set of +# permissions. +# + + Options FollowSymLinks + AllowOverride None + + +# +# Note that from this point forward you must specifically allow +# particular features to be enabled - so if something's not working as +# you might expect, make sure that you have specifically enabled it +# below. +# + +# +# This should be changed to whatever you set DocumentRoot to. +# + + +# +# This may also be "None", "All", or any combination of "Indexes", +# "Includes", "FollowSymLinks", "ExecCGI", or "MultiViews". +# +# Note that "MultiViews" must be named *explicitly* --- "Options All" +# doesn't give it to you. +# + Options Indexes FollowSymLinks MultiViews + +# +# This controls which options the .htaccess files in directories can +# override. Can also be "All", or any combination of "Options", "FileInfo", +# "AuthConfig", and "Limit" +# + AllowOverride None + +# +# Controls who can get stuff from this server. +# + Order allow,deny + Allow from all + + +# +# UserDir: The name of the directory which is appended onto a user's home +# directory if a ~user request is received. +# + + UserDir public_html + + +# +# Control access to UserDir directories. The following is an example +# for a site where these directories are restricted to read-only. +# +# +# AllowOverride FileInfo AuthConfig Limit +# Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec +# +# Order allow,deny +# Allow from all +# +# +# Order deny,allow +# Deny from all +# +# + +# +# DirectoryIndex: Name of the file or files to use as a pre-written HTML +# directory index. Separate multiple entries with spaces. +# + + DirectoryIndex index.html + + +# +# AccessFileName: The name of the file to look for in each directory +# for access control information. +# +AccessFileName .htaccess + +# +# The following lines prevent .htaccess files from being viewed by +# Web clients. Since .htaccess files often contain authorization +# information, access is disallowed for security reasons. Comment +# these lines out if you want Web visitors to see the contents of +# .htaccess files. If you change the AccessFileName directive above, +# be sure to make the corresponding changes here. +# +# Also, folks tend to use names such as .htpasswd for password +# files, so this will protect those as well. +# + + Order allow,deny + Deny from all + + +# +# CacheNegotiatedDocs: By default, Apache sends "Pragma: no-cache" with each +# document that was negotiated on the basis of content. This asks proxy +# servers not to cache the document. Uncommenting the following line disables +# this behavior, and proxies will be allowed to cache the documents. +# +#CacheNegotiatedDocs + +# +# UseCanonicalName: (new for 1.3) With this setting turned on, whenever +# Apache needs to construct a self-referencing URL (a URL that refers back +# to the server the response is coming from) it will use ServerName and +# Port to form a "canonical" name. With this setting off, Apache will +# use the hostname:port that the client supplied, when possible. This +# also affects SERVER_NAME and SERVER_PORT in CGI scripts. +# +UseCanonicalName On + +# +# TypesConfig describes where the mime.types file (or equivalent) is +# to be found. +# + + TypesConfig conf/mime.types + + +# +# DefaultType is the default MIME type the server will use for a document +# if it cannot otherwise determine one, such as from filename extensions. +# If your server contains mostly text or HTML documents, "text/plain" is +# a good value. If most of your content is binary, such as applications +# or images, you may want to use "application/octet-stream" instead to +# keep browsers from trying to display binary files as though they are +# text. +# +DefaultType text/plain + +# +# The mod_mime_magic module allows the server to use various hints from the +# contents of the file itself to determine its type. The MIMEMagicFile +# directive tells the module where the hint definitions are located. +# mod_mime_magic is not part of the default server (you have to add +# it yourself with a LoadModule [see the DSO paragraph in the 'Global +# Environment' section], or recompile the server and include mod_mime_magic +# as part of the configuration), so it's enclosed in an container. +# This means that the MIMEMagicFile directive will only be processed if the +# module is part of the server. +# + + MIMEMagicFile conf/magic + + +# +# HostnameLookups: Log the names of clients or just their IP addresses +# e.g., www.apache.org (on) or 204.62.129.132 (off). +# The default is off because it'd be overall better for the net if people +# had to knowingly turn this feature on, since enabling it means that +# each client request will result in AT LEAST one lookup request to the +# nameserver. +# +HostnameLookups Off + +# +# ErrorLog: The location of the error log file. +# If you do not specify an ErrorLog directive within a +# container, error messages relating to that virtual host will be +# logged here. If you *do* define an error logfile for a +# container, that host's errors will be logged there and not here. +# +ErrorLog logs/error_log + +# +# LogLevel: Control the number of messages logged to the error_log. +# Possible values include: debug, info, notice, warn, error, crit, +# alert, emerg. +# +LogLevel warn + +# +# The following directives define some format nicknames for use with +# a CustomLog directive (see below). +# +LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined +LogFormat "%h %l %u %t \"%r\" %>s %b" common +LogFormat "%{Referer}i -> %U" referer +LogFormat "%{User-agent}i" agent + +# +# The location and format of the access logfile (Common Logfile Format). +# If you do not define any access logfiles within a +# container, they will be logged here. Contrariwise, if you *do* +# define per- access logfiles, transactions will be +# logged therein and *not* in this file. +# +CustomLog logs/access_log common + +# +# If you would like to have agent and referer logfiles, uncomment the +# following directives. +# +#CustomLog logs/referer_log referer +#CustomLog logs/agent_log agent + +# +# If you prefer a single logfile with access, agent, and referer information +# (Combined Logfile Format) you can use the following directive. +# +#CustomLog logs/access_log combined + +# +# Optionally add a line containing the server version and virtual host +# name to server-generated pages (error documents, FTP directory listings, +# mod_status and mod_info output etc., but not CGI generated documents). +# Set to "EMail" to also include a mailto: link to the ServerAdmin. +# Set to one of: On | Off | EMail +# +ServerSignature On + +# +# Aliases: Add here as many aliases as you need (with no limit). The format is +# Alias fakename realname +# + + + # + # Note that if you include a trailing / on fakename then the server will + # require it to be present in the URL. So "/icons" isn't aliased in this + # example, only "/icons/".. + # + Alias /icons/ "@@ServerRoot@@/icons/" + + + Options Indexes MultiViews + AllowOverride None + Order allow,deny + Allow from all + + + # + # ScriptAlias: This controls which directories contain server scripts. + # ScriptAliases are essentially the same as Aliases, except that + # documents in the realname directory are treated as applications and + # run by the server when requested rather than as documents sent to the client. + # The same rules about trailing "/" apply to ScriptAlias directives as to + # Alias. + # + ScriptAlias /cgi-bin/ "@@ServerRoot@@/cgi-bin/" + + # + # "@@ServerRoot@@/cgi-bin" should be changed to whatever your ScriptAliased + # CGI directory exists, if you have that configured. + # + + AllowOverride None + Options None + Order allow,deny + Allow from all + + + +# End of aliases. + +# +# Redirect allows you to tell clients about documents which used to exist in +# your server's namespace, but do not anymore. This allows you to tell the +# clients where to look for the relocated document. +# Format: Redirect old-URI new-URL +# + +# +# Directives controlling the display of server-generated directory listings. +# + + + # + # FancyIndexing is whether you want fancy directory indexing or standard + # + IndexOptions FancyIndexing + + # + # AddIcon* directives tell the server which icon to show for different + # files or filename extensions. These are only displayed for + # FancyIndexed directories. + # + AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip + + AddIconByType (TXT,/icons/text.gif) text/* + AddIconByType (IMG,/icons/image2.gif) image/* + AddIconByType (SND,/icons/sound2.gif) audio/* + AddIconByType (VID,/icons/movie.gif) video/* + + AddIcon /icons/binary.gif .bin .exe + AddIcon /icons/binhex.gif .hqx + AddIcon /icons/tar.gif .tar + AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv + AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip + AddIcon /icons/a.gif .ps .ai .eps + AddIcon /icons/layout.gif .html .shtml .htm .pdf + AddIcon /icons/text.gif .txt + AddIcon /icons/c.gif .c + AddIcon /icons/p.gif .pl .py + AddIcon /icons/f.gif .for + AddIcon /icons/dvi.gif .dvi + AddIcon /icons/uuencoded.gif .uu + AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl + AddIcon /icons/tex.gif .tex + AddIcon /icons/bomb.gif core + + AddIcon /icons/back.gif .. + AddIcon /icons/hand.right.gif README + AddIcon /icons/folder.gif ^^DIRECTORY^^ + AddIcon /icons/blank.gif ^^BLANKICON^^ + + # + # DefaultIcon is which icon to show for files which do not have an icon + # explicitly set. + # + DefaultIcon /icons/unknown.gif + + # + # AddDescription allows you to place a short description after a file in + # server-generated indexes. These are only displayed for FancyIndexed + # directories. + # Format: AddDescription "description" filename + # + #AddDescription "GZIP compressed document" .gz + #AddDescription "tar archive" .tar + #AddDescription "GZIP compressed tar archive" .tgz + + # + # ReadmeName is the name of the README file the server will look for by + # default, and append to directory listings. + # + # HeaderName is the name of a file which should be prepended to + # directory indexes. + # + # If MultiViews are amongst the Options in effect, the server will + # first look for name.html and include it if found. If name.html + # doesn't exist, the server will then look for name.txt and include + # it as plaintext if found. + # + ReadmeName README + HeaderName HEADER + + # + # IndexIgnore is a set of filenames which directory indexing should ignore + # and not include in the listing. Shell-style wildcarding is permitted. + # + IndexIgnore .??* *~ *# HEADER* README* RCS CVS *,v *,t + + +# End of indexing directives. + +# +# Document types. +# + + + # + # AddEncoding allows you to have certain browsers (Mosaic/X 2.1+) uncompress + # information on the fly. Note: Not all browsers support this. + # Despite the name similarity, the following Add* directives have nothing + # to do with the FancyIndexing customization directives above. + # + AddEncoding x-compress Z + AddEncoding x-gzip gz tgz + + # + # AddLanguage allows you to specify the language of a document. You can + # then use content negotiation to give a browser a file in a language + # it can understand. + # + # Note 1: The suffix does not have to be the same as the language + # keyword --- those with documents in Polish (whose net-standard + # language code is pl) may wish to use "AddLanguage pl .po" to + # avoid the ambiguity with the common suffix for perl scripts. + # + # Note 2: The example entries below illustrate that in quite + # some cases the two character 'Language' abbriviation is not + # identical to the two character 'Country' code for its country, + # E.g. 'Danmark/dk' versus 'Danish/da'. + # + # Note 3: In the case of 'ltz' we violate the RFC by using a three char + # specifier. But there is 'work in progress' to fix this and get + # the reference data for rfc1766 cleaned up. + # + # Danish (da) - Dutch (nl) - English (en) - Estonian (ee) + # French (fr) - German (de) - Greek-Modern (el) + # Italian (it) - Portugese (pt) - Luxembourgeois* (ltz) + # Spanish (es) - Swedish (sv) - Catalan (ca) - Czech(cz) + # Polish (pl) - Brazilian Portuguese (pt-br) - Japanese (ja) + # + AddLanguage da .dk + AddLanguage nl .nl + AddLanguage en .en + AddLanguage et .ee + AddLanguage fr .fr + AddLanguage de .de + AddLanguage el .el + AddLanguage it .it + AddLanguage ja .ja + AddCharset ISO-2022-JP .jis + AddLanguage pl .po + AddCharset ISO-8859-2 .iso-pl + AddLanguage pt .pt + AddLanguage pt-br .pt-br + AddLanguage ltz .lu + AddLanguage ca .ca + AddLanguage es .es + AddLanguage sv .se + AddLanguage cz .cz + + # LanguagePriority allows you to give precedence to some languages + # in case of a tie during content negotiation. + # + # Just list the languages in decreasing order of preference. We have + # more or less alphabetized them here. You probably want to change this. + # + + LanguagePriority en da nl et fr de el it ja pl pt pt-br ltz ca es sv + + + # + # AddType allows you to tweak mime.types without actually editing it, or to + # make certain files to be certain types. + # + # For example, the PHP 3.x module (not part of the Apache distribution - see + # http://www.php.net) will typically use: + # + #AddType application/x-httpd-php3 .php3 + #AddType application/x-httpd-php3-source .phps + # + # And for PHP 4.x, use: + # + #AddType application/x-httpd-php .php + #AddType application/x-httpd-php-source .phps + + AddType application/x-tar .tgz + + # + # AddHandler allows you to map certain file extensions to "handlers", + # actions unrelated to filetype. These can be either built into the server + # or added with the Action command (see below) + # + # If you want to use server side includes, or CGI outside + # ScriptAliased directories, uncomment the following lines. + # + # To use CGI scripts: + # + #AddHandler cgi-script .cgi + + # + # To use server-parsed HTML files + # + #AddType text/html .shtml + #AddHandler server-parsed .shtml + + # + # Uncomment the following line to enable Apache's send-asis HTTP file + # feature + # + #AddHandler send-as-is asis + + # + # If you wish to use server-parsed imagemap files, use + # + #AddHandler imap-file map + + # + # To enable type maps, you might want to use + # + #AddHandler type-map var + + +# End of document types. + +# +# Action lets you define media types that will execute a script whenever +# a matching file is called. This eliminates the need for repeated URL +# pathnames for oft-used CGI file processors. +# Format: Action media/type /cgi-script/location +# Format: Action handler-name /cgi-script/location +# + +# +# MetaDir: specifies the name of the directory in which Apache can find +# meta information files. These files contain additional HTTP headers +# to include when sending the document +# +#MetaDir .web + +# +# MetaSuffix: specifies the file name suffix for the file containing the +# meta information. +# +#MetaSuffix .meta + +# +# Customizable error response (Apache style) +# these come in three flavors +# +# 1) plain text +#ErrorDocument 500 "The server made a boo boo. +# n.b. the (") marks it as text, it does not get output +# +# 2) local redirects +#ErrorDocument 404 /missing.html +# to redirect to local URL /missing.html +#ErrorDocument 404 /cgi-bin/missing_handler.pl +# N.B.: You can redirect to a script or a document using server-side-includes. +# +# 3) external redirects +#ErrorDocument 402 http://some.other_server.com/subscription_info.html +# N.B.: Many of the environment variables associated with the original +# request will *not* be available to such a script. + +# +# Customize behaviour based on the browser +# + + + # + # The following directives modify normal HTTP response behavior. + # The first directive disables keepalive for Netscape 2.x and browsers that + # spoof it. There are known problems with these browser implementations. + # The second directive is for Microsoft Internet Explorer 4.0b2 + # which has a broken HTTP/1.1 implementation and does not properly + # support keepalive when it is used on 301 or 302 (redirect) responses. + # + BrowserMatch "Mozilla/2" nokeepalive + BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0 + + # + # The following directive disables HTTP/1.1 responses to browsers which + # are in violation of the HTTP/1.0 spec by not being able to grok a + # basic 1.1 response. + # + BrowserMatch "RealPlayer 4\.0" force-response-1.0 + BrowserMatch "Java/1\.0" force-response-1.0 + BrowserMatch "JDK/1\.0" force-response-1.0 + + + +# +# Allow server status reports, with the URL of http://servername/server-status +# Change the ".your_domain.com" to match your domain to enable. +# +# +# SetHandler server-status +# Order deny,allow +# Deny from all +# Allow from .your_domain.com +# + +# +# Allow remote server configuration reports, with the URL of +# http://servername/server-info (requires that mod_info.c be loaded). +# Change the ".your_domain.com" to match your domain to enable. +# +# +# SetHandler server-info +# Order deny,allow +# Deny from all +# Allow from .your_domain.com +# + +# +# There have been reports of people trying to abuse an old bug from pre-1.1 +# days. This bug involved a CGI script distributed as a part of Apache. +# By uncommenting these lines you can redirect these attacks to a logging +# script on phf.apache.org. Or, you can record them yourself, using the script +# support/phf_abuse_log.cgi. +# +# +# Deny from all +# ErrorDocument 403 http://phf.apache.org/phf_abuse_log.cgi +# + +# +# Proxy Server directives. Uncomment the following lines to +# enable the proxy server: +# +# + #ProxyRequests On + # + # + # Order deny,allow + # Deny from all + # Allow from .your_domain.com + # + + # + # Enable/disable the handling of HTTP/1.1 "Via:" headers. + # ("Full" adds the server version; "Block" removes all outgoing Via: headers) + # Set to one of: Off | On | Full | Block + # + #ProxyVia On + + # + # To enable the cache as well, edit and uncomment the following lines: + # (no cacheing without CacheRoot) + # + #CacheRoot "@@ServerRoot@@/proxy" + #CacheSize 5 + #CacheGcInterval 4 + #CacheMaxExpire 24 + #CacheLastModifiedFactor 0.1 + #CacheDefaultExpire 1 + #NoCache a_domain.com another_domain.edu joes.garage_sale.com + +# +# End of proxy directives. + +### Section 3: Virtual Hosts +# +# VirtualHost: If you want to maintain multiple domains/hostnames on your +# machine you can setup VirtualHost containers for them. +# Please see the documentation at +# for further details before you try to setup virtual hosts. +# You may use the command line option '-S' to verify your virtual host +# configuration. + +# +# If you want to use name-based virtual hosts you need to define at +# least one IP address (and port number) for them. +# +#NameVirtualHost 12.34.56.78:80 +#NameVirtualHost 12.34.56.78 + +# +# VirtualHost example: +# Almost any Apache directive may go into a VirtualHost container. +# +# +# ServerAdmin webmaster@host.some_domain.com +# DocumentRoot /www/docs/host.some_domain.com +# ServerName host.some_domain.com +# ErrorLog logs/host.some_domain.com-error_log +# CustomLog logs/host.some_domain.com-access_log common +# + +# +# diff --git a/APACHE_1_3_12/conf/httpd.conf-dist-win b/APACHE_1_3_12/conf/httpd.conf-dist-win new file mode 100644 index 0000000000..f7d99f8a7d --- /dev/null +++ b/APACHE_1_3_12/conf/httpd.conf-dist-win @@ -0,0 +1,806 @@ +# +# Based upon the NCSA server configuration files originally by Rob McCool. +# +# This is the main Apache server configuration file. It contains the +# configuration directives that give the server its instructions. +# See for detailed information about +# the directives. +# +# Do NOT simply read the instructions in here without understanding +# what they do. They're here only as hints or reminders. If you are unsure +# consult the online docs. You have been warned. +# +# After this file is processed, the server will look for and process +# @@ServerRoot@@/conf/srm.conf and then @@ServerRoot@@/conf/access.conf +# unless you have overridden these with ResourceConfig and/or +# AccessConfig directives here. +# +# The configuration directives are grouped into three basic sections: +# 1. Directives that control the operation of the Apache server process as a +# whole (the 'global environment'). +# 2. Directives that define the parameters of the 'main' or 'default' server, +# which responds to requests that aren't handled by a virtual host. +# These directives also provide default values for the settings +# of all virtual hosts. +# 3. Settings for virtual hosts, which allow Web requests to be sent to +# different IP addresses or hostnames and have them handled by the +# same Apache server process. +# +# Configuration and logfile names: If the filenames you specify for many +# of the server's control files begin with "/" (or "drive:/" for Win32), the +# server will use that explicit path. If the filenames do *not* begin +# with "/", the value of ServerRoot is prepended -- so "logs/foo.log" +# with ServerRoot set to "/usr/local/apache" will be interpreted by the +# server as "/usr/local/apache/logs/foo.log". +# +# NOTE: Where filenames are specified, you must use forward slashes +# instead of backslashes (e.g., "c:/apache" instead of "c:\apache"). +# If a drive letter is omitted, the drive on which Apache.exe is located +# will be used by default. It is recommended that you always supply +# an explicit drive letter in absolute paths, however, to avoid +# confusion. +# + +### Section 1: Global Environment +# +# The directives in this section affect the overall operation of Apache, +# such as the number of concurrent requests it can handle or where it +# can find its configuration files. +# + +# +# ServerType is either inetd, or standalone. Inetd mode is only supported on +# Unix platforms. +# +ServerType standalone + +# +# ServerRoot: The top of the directory tree under which the server's +# configuration, error, and log files are kept. +# +# Do NOT add a slash at the end of the directory path. +# +ServerRoot "@@ServerRoot@@" + +# +# PidFile: The file in which the server should record its process +# identification number when it starts. +# +PidFile logs/httpd.pid + +# +# ScoreBoardFile: File used to store internal server process information. +# Not all architectures require this. But if yours does (you'll know because +# this file will be created when you run Apache) then you *must* ensure that +# no two invocations of Apache share the same scoreboard file. +# +ScoreBoardFile logs/apache_status + +# +# In the standard configuration, the server will process httpd.conf, +# srm.conf, and access.conf in that order. The latter two files are +# now distributed empty, as it is recommended that all directives +# be kept in a single file for simplicity. The commented-out values +# below are the built-in defaults. You can have the server ignore +# these files altogether by using "/dev/null" (for Unix) or +# "nul" (for Win32) for the arguments to the directives. +# +#ResourceConfig conf/srm.conf +#AccessConfig conf/access.conf + +# +# Timeout: The number of seconds before receives and sends time out. +# +Timeout 300 + +# +# KeepAlive: Whether or not to allow persistent connections (more than +# one request per connection). Set to "Off" to deactivate. +# +KeepAlive On + +# +# MaxKeepAliveRequests: The maximum number of requests to allow +# during a persistent connection. Set to 0 to allow an unlimited amount. +# We reccomend you leave this number high, for maximum performance. +# +MaxKeepAliveRequests 100 + +# +# KeepAliveTimeout: Number of seconds to wait for the next request from the +# same client on the same connection. +# +KeepAliveTimeout 15 + +# +# Apache on Win32 always creates one child process to handle requests. If it +# dies, another child process is created automatically. Within the child +# process multiple threads handle incoming requests. The next two +# directives control the behaviour of the threads and processes. +# + +# +# MaxRequestsPerChild: the number of requests each child process is +# allowed to process before the child dies. The child will exit so +# as to avoid problems after prolonged use when Apache (and maybe the +# libraries it uses) leak memory or other resources. On most systems, this +# isn't really needed, but a few (such as Solaris) do have notable leaks +# in the libraries. For Win32, set this value to zero (unlimited) +# unless advised otherwise. +# +MaxRequestsPerChild 0 + +# +# Number of concurrent threads (i.e., requests) the server will allow. +# Set this value according to the responsiveness of the server (more +# requests active at once means they're all handled more slowly) and +# the amount of system resources you'll allow the server to consume. +# +ThreadsPerChild 50 + +# +# Listen: Allows you to bind Apache to specific IP addresses and/or +# ports, in addition to the default. See also the +# directive. +# +#Listen 3000 +#Listen 12.34.56.78:80 + +# +# BindAddress: You can support virtual hosts with this option. This directive +# is used to tell the server which IP address to listen to. It can either +# contain "*", an IP address, or a fully qualified Internet domain name. +# See also the and Listen directives. +# +#BindAddress * + +# +# Dynamic Shared Object (DSO) Support +# +# To be able to use the functionality of a module which was built as a DSO you +# have to place corresponding `LoadModule' lines at this location so the +# directives contained in it are actually available _before_ they are used. +# Please read the file README.DSO in the Apache 1.3 distribution for more +# details about the DSO mechanism and run `apache -l' for the list of already +# built-in (statically linked and thus always available) modules in your Apache +# binary. +# +# Note: The order in which modules are loaded is important. Don't change +# the order below without expert advice. +# +#LoadModule anon_auth_module modules/ApacheModuleAuthAnon.dll +#LoadModule cern_meta_module modules/ApacheModuleCERNMeta.dll +#LoadModule digest_module modules/ApacheModuleDigest.dll +#LoadModule expires_module modules/ApacheModuleExpires.dll +#LoadModule headers_module modules/ApacheModuleHeaders.dll +#LoadModule proxy_module modules/ApacheModuleProxy.dll +#LoadModule rewrite_module modules/ApacheModuleRewrite.dll +#LoadModule speling_module modules/ApacheModuleSpeling.dll +#LoadModule status_module modules/ApacheModuleStatus.dll +#LoadModule usertrack_module modules/ApacheModuleUserTrack.dll + +# +# ExtendedStatus controls whether Apache will generate "full" status +# information (ExtendedStatus On) or just basic information (ExtendedStatus +# Off) when the "server-status" handler is called. The default is Off. +# +#ExtendedStatus On + +### Section 2: 'Main' server configuration +# +# The directives in this section set up the values used by the 'main' +# server, which responds to any requests that aren't handled by a +# definition. These values also provide defaults for +# any containers you may define later in the file. +# +# All of these directives may appear inside containers, +# in which case these default settings will be overridden for the +# virtual host being defined. +# + +# +# If your ServerType directive (set earlier in the 'Global Environment' +# section) is set to "inetd", the next few directives don't have any +# effect since their settings are defined by the inetd configuration. +# Skip ahead to the ServerAdmin directive. +# + +# +# Port: The port to which the standalone server listens. +# +Port 80 + +# +# ServerAdmin: Your address, where problems with the server should be +# e-mailed. This address appears on some server-generated pages, such +# as error documents. +# +ServerAdmin you@your.address + +# +# ServerName allows you to set a host name which is sent back to clients for +# your server if it's different than the one the program would get (i.e., use +# "www" instead of the host's real name). +# +# Note: You cannot just invent host names and hope they work. The name you +# define here must be a valid DNS name for your host. If you don't understand +# this, ask your network administrator. +# If your host doesn't have a registered DNS name, enter its IP address here. +# You will have to access it by its address (e.g., http://123.45.67.89/) +# anyway, and this will make redirections work in a sensible way. +# +#ServerName new.host.name + +# +# DocumentRoot: The directory out of which you will serve your +# documents. By default, all requests are taken from this directory, but +# symbolic links and aliases may be used to point to other locations. +# +DocumentRoot "@@ServerRoot@@/htdocs" + +# +# Each directory to which Apache has access, can be configured with respect +# to which services and features are allowed and/or disabled in that +# directory (and its subdirectories). +# +# First, we configure the "default" to be a very restrictive set of +# permissions. +# + + Options FollowSymLinks + AllowOverride None + + +# +# Note that from this point forward you must specifically allow +# particular features to be enabled - so if something's not working as +# you might expect, make sure that you have specifically enabled it +# below. +# + +# +# This should be changed to whatever you set DocumentRoot to. +# + + +# +# This may also be "None", "All", or any combination of "Indexes", +# "Includes", "FollowSymLinks", "ExecCGI", or "MultiViews". +# +# Note that "MultiViews" must be named *explicitly* --- "Options All" +# doesn't give it to you. +# + Options Indexes FollowSymLinks MultiViews + +# +# This controls which options the .htaccess files in directories can +# override. Can also be "All", or any combination of "Options", "FileInfo", +# "AuthConfig", and "Limit" +# + AllowOverride None + +# +# Controls who can get stuff from this server. +# + Order allow,deny + Allow from all + + +# +# UserDir: The name of the directory which is appended onto a user's home +# directory if a ~user request is received. +# +# Under Win32, we do not currently try to determine the home directory of +# a Windows login, so a format such as that below needs to be used. See +# the UserDir documentation for details. +# +UserDir "@@ServerRoot@@/users/" + +# +# DirectoryIndex: Name of the file or files to use as a pre-written HTML +# directory index. Separate multiple entries with spaces. +# +DirectoryIndex index.html + +# +# AccessFileName: The name of the file to look for in each directory +# for access control information. +# +AccessFileName .htaccess + +# +# The following lines prevent .htaccess files from being viewed by +# Web clients. Since .htaccess files often contain authorization +# information, access is disallowed for security reasons. Comment +# these lines out if you want Web visitors to see the contents of +# .htaccess files. If you change the AccessFileName directive above, +# be sure to make the corresponding changes here. +# + + Order allow,deny + Deny from all + + +# +# CacheNegotiatedDocs: By default, Apache sends "Pragma: no-cache" with each +# document that was negotiated on the basis of content. This asks proxy +# servers not to cache the document. Uncommenting the following line disables +# this behavior, and proxies will be allowed to cache the documents. +# +#CacheNegotiatedDocs + +# +# UseCanonicalName: (new for 1.3) With this setting turned on, whenever +# Apache needs to construct a self-referencing URL (a URL that refers back +# to the server the response is coming from) it will use ServerName and +# Port to form a "canonical" name. With this setting off, Apache will +# use the hostname:port that the client supplied, when possible. This +# also affects SERVER_NAME and SERVER_PORT in CGI scripts. +# +UseCanonicalName On + +# +# TypesConfig describes where the mime.types file (or equivalent) is +# to be found. +# +TypesConfig conf/mime.types + +# +# DefaultType is the default MIME type the server will use for a document +# if it cannot otherwise determine one, such as from filename extensions. +# If your server contains mostly text or HTML documents, "text/plain" is +# a good value. If most of your content is binary, such as applications +# or images, you may want to use "application/octet-stream" instead to +# keep browsers from trying to display binary files as though they are +# text. +# +DefaultType text/plain + +# +# The mod_mime_magic module allows the server to use various hints from the +# contents of the file itself to determine its type. The MIMEMagicFile +# directive tells the module where the hint definitions are located. +# mod_mime_magic is not part of the default server (you have to add +# it yourself with a LoadModule [see the DSO paragraph in the 'Global +# Environment' section], or recompile the server and include mod_mime_magic +# as part of the configuration), so it's enclosed in an container. +# This means that the MIMEMagicFile directive will only be processed if the +# module is part of the server. +# + + MIMEMagicFile conf/magic + + +# +# HostnameLookups: Log the names of clients or just their IP addresses +# e.g., www.apache.org (on) or 204.62.129.132 (off). +# The default is off because it'd be overall better for the net if people +# had to knowingly turn this feature on, since enabling it means that +# each client request will result in AT LEAST one lookup request to the +# nameserver. +# +HostnameLookups Off + +# +# ErrorLog: The location of the error log file. +# If you do not specify an ErrorLog directive within a +# container, error messages relating to that virtual host will be +# logged here. If you *do* define an error logfile for a +# container, that host's errors will be logged there and not here. +# +ErrorLog logs/error.log + +# +# LogLevel: Control the number of messages logged to the error.log. +# Possible values include: debug, info, notice, warn, error, crit, +# alert, emerg. +# +LogLevel warn + +# +# The following directives define some format nicknames for use with +# a CustomLog directive (see below). +# +LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined +LogFormat "%h %l %u %t \"%r\" %>s %b" common +LogFormat "%{Referer}i -> %U" referer +LogFormat "%{User-agent}i" agent + +# +# The location and format of the access logfile (Common Logfile Format). +# If you do not define any access logfiles within a +# container, they will be logged here. Contrariwise, if you *do* +# define per- access logfiles, transactions will be +# logged therein and *not* in this file. +# +CustomLog logs/access.log common + +# +# If you would like to have agent and referer logfiles, uncomment the +# following directives. +# +#CustomLog logs/referer.log referer +#CustomLog logs/agent.log agent + +# +# If you prefer a single logfile with access, agent, and referer information +# (Combined Logfile Format) you can use the following directive. +# +#CustomLog logs/access.log combined + +# +# Optionally add a line containing the server version and virtual host +# name to server-generated pages (error documents, FTP directory listings, +# mod_status and mod_info output etc., but not CGI generated documents). +# Set to "EMail" to also include a mailto: link to the ServerAdmin. +# Set to one of: On | Off | EMail +# +ServerSignature On + +# +# Aliases: Add here as many aliases as you need (with no limit). The format is +# Alias fakename realname +# +# Note that if you include a trailing / on fakename then the server will +# require it to be present in the URL. So "/icons" isn't aliased in this +# example, only "/icons/".. +# +Alias /icons/ "@@ServerRoot@@/icons/" + +# +# ScriptAlias: This controls which directories contain server scripts. +# ScriptAliases are essentially the same as Aliases, except that +# documents in the realname directory are treated as applications and +# run by the server when requested rather than as documents sent to the client. +# The same rules about trailing "/" apply to ScriptAlias directives as to +# Alias. +# +ScriptAlias /cgi-bin/ "@@ServerRoot@@/cgi-bin/" + +# +# "@@ServerRoot@@/cgi-bin" should be changed to whatever your ScriptAliased +# CGI directory exists, if you have that configured. +# + + AllowOverride None + Options None + + +# +# Redirect allows you to tell clients about documents which used to exist in +# your server's namespace, but do not anymore. This allows you to tell the +# clients where to look for the relocated document. +# Format: Redirect old-URI new-URL +# + +# +# Directives controlling the display of server-generated directory listings. +# + +# +# FancyIndexing is whether you want fancy directory indexing or standard +# +IndexOptions FancyIndexing + +# +# AddIcon* directives tell the server which icon to show for different +# files or filename extensions. These are only displayed for +# FancyIndexed directories. +# +AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip + +AddIconByType (TXT,/icons/text.gif) text/* +AddIconByType (IMG,/icons/image2.gif) image/* +AddIconByType (SND,/icons/sound2.gif) audio/* +AddIconByType (VID,/icons/movie.gif) video/* + +AddIcon /icons/binary.gif .bin .exe +AddIcon /icons/binhex.gif .hqx +AddIcon /icons/tar.gif .tar +AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv +AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip +AddIcon /icons/a.gif .ps .ai .eps +AddIcon /icons/layout.gif .html .shtml .htm .pdf +AddIcon /icons/text.gif .txt +AddIcon /icons/c.gif .c +AddIcon /icons/p.gif .pl .py +AddIcon /icons/f.gif .for +AddIcon /icons/dvi.gif .dvi +AddIcon /icons/uuencoded.gif .uu +AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl +AddIcon /icons/tex.gif .tex +AddIcon /icons/bomb.gif core + +AddIcon /icons/back.gif .. +AddIcon /icons/hand.right.gif README +AddIcon /icons/folder.gif ^^DIRECTORY^^ +AddIcon /icons/blank.gif ^^BLANKICON^^ + +# +# DefaultIcon is which icon to show for files which do not have an icon +# explicitly set. +# +DefaultIcon /icons/unknown.gif + +# +# AddDescription allows you to place a short description after a file in +# server-generated indexes. These are only displayed for FancyIndexed +# directories. +# Format: AddDescription "description" filename +# +#AddDescription "GZIP compressed document" .gz +#AddDescription "tar archive" .tar +#AddDescription "GZIP compressed tar archive" .tgz + +# +# ReadmeName is the name of the README file the server will look for by +# default, and append to directory listings. +# +# HeaderName is the name of a file which should be prepended to +# directory indexes. +# +# The server will first look for name.html and include it if found. +# If name.html doesn't exist, the server will then look for name.txt +# and include it as plaintext if found. +# +ReadmeName README +HeaderName HEADER + +# +# IndexIgnore is a set of filenames which directory indexing should ignore +# and not include in the listing. Shell-style wildcarding is permitted. +# +IndexIgnore .??* *~ *# HEADER* README* RCS CVS *,v *,t + +# +# AddEncoding allows you to have certain browsers (Mosaic/X 2.1+) uncompress +# information on the fly. Note: Not all browsers support this. +# Despite the name similarity, the following Add* directives have nothing +# to do with the FancyIndexing customisation directives above. +# +AddEncoding x-compress Z +AddEncoding x-gzip gz tgz + +# +# AddLanguage allows you to specify the language of a document. You can +# then use content negotiation to give a browser a file in a language +# it can understand. +# +# Note 1: The suffix does not have to be the same as the language +# keyword --- those with documents in Polish (whose net-standard +# language code is pl) may wish to use "AddLanguage pl .po" to +# avoid the ambiguity with the common suffix for perl scripts. +# +# Note 2: The example entries below illustrate that in quite +# some cases the two character 'Language' abbriviation is not +# identical to the two character 'Country' code for it's country, +# E.g. 'Danmark/dk' versus 'Danish/da'. +# +# Note 3: In the case of 'ltz' we violate the RFC by using a three char +# specifier. But there is 'work in progress' to fix this and get +# the reference data for rfc1766 cleaned up. +# +# Danish (da) - Dutch (nl) - English (en) - Estonian (ee) +# French (fr) - German (de) - Greek-Modern (el) +# Italian (it) -Portugese (pt) - Luxembourgeois* (ltz) +# Spanish (es) - Swedish (sv) - Catalan (ca) - Czech(cz) +# +AddLanguage da .dk +AddLanguage nl .nl +AddLanguage en .en +AddLanguage et .ee +AddLanguage fr .fr +AddLanguage de .de +AddLanguage el .el +AddLanguage it .it +AddLanguage pt .pt +AddLanguage ltz .lu +AddLanguage ca .ca +AddLanguage es .es +AddLanguage sv .se +AddLanguage cz .cz + +# LanguagePriority allows you to give precedence to some languages +# in case of a tie during content negotiation. +# +# Just list the languages in decreasing order of preference. We have +# more or less alphabetized them here. You probably want to change this. +# +LanguagePriority en da nl et fr de el it pt ltz ca es sv + +# +# AddType allows you to tweak mime.types without actually editing it, or to +# make certain files to be certain types. +# +# For example, the PHP3 module (not part of the Apache distribution) +# will typically use: +# +#AddType application/x-httpd-php3 .phtml +#AddType application/x-httpd-php3-source .phps + +AddType application/x-tar .tgz + +# +# AddHandler allows you to map certain file extensions to "handlers", +# actions unrelated to filetype. These can be either built into the server +# or added with the Action command (see below) +# +# If you want to use server side includes, or CGI outside +# ScriptAliased directories, uncomment the following lines. +# +# To use CGI scripts: +# +#AddHandler cgi-script .cgi + +# +# To use server-parsed HTML files +# +#AddType text/html .shtml +#AddHandler server-parsed .shtml + +# +# Uncomment the following line to enable Apache's send-asis HTTP file +# feature +# +#AddHandler send-as-is asis + +# +# If you wish to use server-parsed imagemap files, use +# +#AddHandler imap-file map + +# +# To enable type maps, you might want to use +# +#AddHandler type-map var + +# +# Action lets you define media types that will execute a script whenever +# a matching file is called. This eliminates the need for repeated URL +# pathnames for oft-used CGI file processors. +# Format: Action media/type /cgi-script/location +# Format: Action handler-name /cgi-script/location +# + +# +# MetaDir: specifies the name of the directory in which Apache can find +# meta information files. These files contain additional HTTP headers +# to include when sending the document +# +#MetaDir .web + +# +# MetaSuffix: specifies the file name suffix for the file containing the +# meta information. +# +#MetaSuffix .meta + +# +# Customizable error response (Apache style) +# these come in three flavors +# +# 1) plain text +#ErrorDocument 500 "The server made a boo boo. +# n.b. the (") marks it as text, it does not get output +# +# 2) local redirects +#ErrorDocument 404 /missing.html +# to redirect to local URL /missing.html +#ErrorDocument 404 /cgi-bin/missing_handler.pl +# N.B.: You can redirect to a script or a document using server-side-includes. +# +# 3) external redirects +#ErrorDocument 402 http://some.other_server.com/subscription_info.html +# N.B.: Many of the environment variables associated with the original +# request will *not* be available to such a script. + +# +# The following directives disable keepalives and HTTP header flushes. +# The first directive disables it for Netscape 2.x and browsers which +# spoof it. There are known problems with these. +# The second directive is for Microsoft Internet Explorer 4.0b2 +# which has a broken HTTP/1.1 implementation and does not properly +# support keepalive when it is used on 301 or 302 (redirect) responses. +# +BrowserMatch "Mozilla/2" nokeepalive +BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0 + +# +# The following directive disables HTTP/1.1 responses to browsers which +# are in violation of the HTTP/1.0 spec by not being able to grok a +# basic 1.1 response. +# +BrowserMatch "RealPlayer 4\.0" force-response-1.0 +BrowserMatch "Java/1\.0" force-response-1.0 +BrowserMatch "JDK/1\.0" force-response-1.0 + +# +# Allow server status reports, with the URL of http://servername/server-status +# Change the ".your_domain.com" to match your domain to enable. +# +# +# SetHandler server-status +# Order deny,allow +# Deny from all +# Allow from .your_domain.com +# + +# +# Allow remote server configuration reports, with the URL of +# http://servername/server-info (requires that mod_info.c be loaded). +# Change the ".your_domain.com" to match your domain to enable. +# +# +# SetHandler server-info +# Order deny,allow +# Deny from all +# Allow from .your_domain.com +# + +# +# There have been reports of people trying to abuse an old bug from pre-1.1 +# days. This bug involved a CGI script distributed as a part of Apache. +# By uncommenting these lines you can redirect these attacks to a logging +# script on phf.apache.org. Or, you can record them yourself, using the script +# support/phf_abuse_log.cgi. +# +# +# Deny from all +# ErrorDocument 403 http://phf.apache.org/phf_abuse_log.cgi +# + +# +# Proxy Server directives. Uncomment the following line to +# enable the proxy server: +# +#ProxyRequests On + +# +# Enable/disable the handling of HTTP/1.1 "Via:" headers. +# ("Full" adds the server version; "Block" removes all outgoing Via: headers) +# Set to one of: Off | On | Full | Block +# +#ProxyVia On + +# +# To enable the cache as well, edit and uncomment the following lines: +# (no cacheing without CacheRoot) +# +#CacheRoot "@@ServerRoot@@/proxy" +#CacheSize 5 +#CacheGcInterval 4 +#CacheMaxExpire 24 +#CacheLastModifiedFactor 0.1 +#CacheDefaultExpire 1 +#NoCache a_domain.com another_domain.edu joes.garage_sale.com + +### Section 3: Virtual Hosts +# +# VirtualHost: If you want to maintain multiple domains/hostnames on your +# machine you can setup VirtualHost containers for them. +# Please see the documentation at +# for further details before you try to setup virtual hosts. +# You may use the command line option '-S' to verify your virtual host +# configuration. + +# +# If you want to use name-based virtual hosts you need to define at +# least one IP address (and port number) for them. +# +#NameVirtualHost 12.34.56.78:80 +#NameVirtualHost 12.34.56.78 + +# +# VirtualHost example: +# Almost any Apache directive may go into a VirtualHost container. +# +# +# ServerAdmin webmaster@host.some_domain.com +# DocumentRoot /www/docs/host.some_domain.com +# ServerName host.some_domain.com +# ErrorLog logs/host.some_domain.com-error_log +# CustomLog logs/host.some_domain.com-access_log common +# + +# +# diff --git a/APACHE_1_3_12/conf/httpd.conf-dist.nw b/APACHE_1_3_12/conf/httpd.conf-dist.nw new file mode 100644 index 0000000000..41cde7b057 --- /dev/null +++ b/APACHE_1_3_12/conf/httpd.conf-dist.nw @@ -0,0 +1,814 @@ +# +# Based upon the NCSA server configuration files originally by Rob McCool. +# +# This is the main Apache server configuration file. It contains the +# configuration directives that give the server its instructions. +# See for detailed information about +# the directives. +# +# Do NOT simply read the instructions in here without understanding +# what they do. They're here only as hints or reminders. If you are unsure +# consult the online docs. You have been warned. +# +# After this file is processed, the server will look for and process +# sys:/apache/conf/srm.conf and then sys:/apache/conf/access.conf +# unless you have overridden these with ResourceConfig and/or +# AccessConfig directives here. +# +# The configuration directives are grouped into three basic sections: +# 1. Directives that control the operation of the Apache server process as a +# whole (the 'global environment'). +# 2. Directives that define the parameters of the 'main' or 'default' server, +# which responds to requests that aren't handled by a virtual host. +# These directives also provide default values for the settings +# of all virtual hosts. +# 3. Settings for virtual hosts, which allow Web requests to be sent to +# different IP addresses or hostnames and have them handled by the +# same Apache server process. +# +# Configuration and logfile names: If the filenames you specify for many +# of the server's control files begin with "/" (or "drive:/" for Win32 and +# sys:/ for NetWare), the server will use that explicit path. If the +# filenames do *not* begin with "/", the value of ServerRoot is prepended +# -- so "logs/foo.log" with ServerRoot set to "/usr/local/apache" will be +# interpreted by the server as "/usr/local/apache/logs/foo.log". +# + +### Section 1: Global Environment +# +# The directives in this section affect the overall operation of Apache, +# such as the number of concurrent requests it can handle or where it +# can find its configuration files. +# + +# +# ServerType is either inetd, or standalone. Inetd mode is only supported on +# Unix platforms. +# +ServerType standalone + +# +# ServerRoot: The top of the directory tree under which the server's +# configuration, error, and log files are kept. +# +# NOTE! If you intend to place this on an NFS (or otherwise network) +# mounted filesystem then please read the LockFile documentation +# (available at ); +# you will save yourself a lot of trouble. +# +# Do NOT add a slash at the end of the directory path. +# +ServerRoot "sys:/apache" + +# +# PidFile: The file in which the server should record its process +# identification number when it starts. +# +PidFile logs/httpd.pid + +# +# ScoreBoardFile: File used to store internal server process information. +# Not all architectures require this. But if yours does (you'll know because +# this file will be created when you run Apache) then you *must* ensure that +# no two invocations of Apache share the same scoreboard file. +# +ScoreBoardFile logs/apache_status + +# +# In the standard configuration, the server will process this file, +# srm.conf, and access.conf in that order. The latter two files are +# now distributed empty, as it is recommended that all directives +# be kept in a single file for simplicity. The commented-out values +# below are the built-in defaults. You can have the server ignore +# these files altogether by using "/dev/null" (for Unix) or +# "nul" (for Win32) for the arguments to the directives. +# +#ResourceConfig conf/srm.conf +#AccessConfig conf/access.conf + +# +# Timeout: The number of seconds before receives and sends time out. +# +Timeout 300 + +# +# KeepAlive: Whether or not to allow persistent connections (more than +# one request per connection). Set to "Off" to deactivate. +# +KeepAlive On + +# +# MaxKeepAliveRequests: The maximum number of requests to allow +# during a persistent connection. Set to 0 to allow an unlimited amount. +# We recommend you leave this number high, for maximum performance. +# +MaxKeepAliveRequests 100 + +# +# KeepAliveTimeout: Number of seconds to wait for the next request from the +# same client on the same connection. +# +KeepAliveTimeout 15 + +# +# Number of concurrent threads (i.e., requests) the server will allow. +# Set this value according to the responsiveness of the server (more +# requests active at once means they're all handled more slowly) and +# the amount of system resources you'll allow the server to consume. +# +ThreadsPerChild 50 + +# +# When NetWare creates a thread you need to specify the stack size. +# You may need to increase this if you get stack overflows. +# ThreadStackSize 65536 + +ThreadStackSize 65536 + +# +# MaxRequestsPerChild: the number of requests each child process is +# allowed to process before the child dies. The child will exit so +# as to avoid problems after prolonged use when Apache (and maybe the +# libraries it uses) leak memory or other resources. On most systems, this +# isn't really needed, but a few (such as Solaris) do have notable leaks +# in the libraries. For these platforms, set to something like 10000 +# or so; a setting of 0 means unlimited. +# +# NOTE: This value does not include keepalive requests after the initial +# request per connection. For example, if a child process handles +# an initial request and 10 subsequent "keptalive" requests, it +# would only count as 1 request towards this limit. +# +MaxRequestsPerChild 0 + +# +# Listen: Allows you to bind Apache to specific IP addresses and/or +# ports, in addition to the default. See also the +# directive. +# +#Listen 3000 +#Listen 12.34.56.78:80 + + +# +# BindAddress: You can support virtual hosts with this option. This directive +# is used to tell the server which IP address to listen to. It can either +# contain "*", an IP address, or a fully qualified Internet domain name. +# See also the and Listen directives. +# +#BindAddress * + +# +# Dynamic Shared Object (DSO) Support +# +# To be able to use the functionality of a module which was built as a DSO you +# have to place corresponding `LoadModule' lines at this location so the +# directives contained in it are actually available _before_ they are used. +# Please read the file README.DSO in the Apache 1.3 distribution for more +# details about the DSO mechanism and run `httpd -l' for the list of already +# built-in (statically linked and thus always available) modules in your httpd +# binary. +# +# Note: The order is which modules are loaded is important. Don't change +# the order below without expert advice. + +# LoadModule anon_auth_module modules/authanon +# LoadModule cern_meta_module modules/cernmeta +# LoadModule digest_module modules/digest +# LoadModule expires_module modules/expires +# LoadModule headers_module modules/headers +# LoadModule proxy_module modules/proxy +# LoadModule rewrite_module modules/rewrite +# LoadModule speling_module modules/speling +# LoadModule status_module modules/status +# LoadModule info_module modules/info +# LoadModule usertrack_module modules/usrtrack + +# +# ExtendedStatus controls whether Apache will generate "full" status +# information (ExtendedStatus On) or just basic information (ExtendedStatus +# Off) when the "server-status" handler is called. The default is Off. +# +#ExtendedStatus On + +### Section 2: 'Main' server configuration +# +# The directives in this section set up the values used by the 'main' +# server, which responds to any requests that aren't handled by a +# definition. These values also provide defaults for +# any containers you may define later in the file. +# +# All of these directives may appear inside containers, +# in which case these default settings will be overridden for the +# virtual host being defined. +# + +# +# Port: The port to which the standalone server listens. For +# ports < 1023, you will need httpd to be run as root initially. +# +Port 80 + +# +# ServerAdmin: Your address, where problems with the server should be +# e-mailed. This address appears on some server-generated pages, such +# as error documents. +# +ServerAdmin someone@somewhere.com + +# +# ServerName allows you to set a host name which is sent back to clients for +# your server if it's different than the one the program would get (i.e., use +# "www" instead of the host's real name). +# +# Note: You cannot just invent host names and hope they work. The name you +# define here must be a valid DNS name for your host. If you don't understand +# this, ask your network administrator. +# If your host doesn't have a registered DNS name, enter its IP address here. +# You will have to access it by its address (e.g., http://123.45.67.89/) +# anyway, and this will make redirections work in a sensible way. +# +ServerName 123.45.67.89 + +# +# DocumentRoot: The directory out of which you will serve your +# documents. By default, all requests are taken from this directory, but +# symbolic links and aliases may be used to point to other locations. +# +DocumentRoot "sys:/apache/htdocs" + +# +# Each directory to which Apache has access, can be configured with respect +# to which services and features are allowed and/or disabled in that +# directory (and its subdirectories). +# +# First, we configure the "default" to be a very restrictive set of +# permissions. +# + + Options FollowSymLinks + AllowOverride None + + +# +# Note that from this point forward you must specifically allow +# particular features to be enabled - so if something's not working as +# you might expect, make sure that you have specifically enabled it +# below. +# + +# +# This should be changed to whatever you set DocumentRoot to. +# + +# +# This may also be "None", "All", or any combination of "Indexes", +# "Includes", "FollowSymLinks", "ExecCGI", or "MultiViews". +# +# Note that "MultiViews" must be named *explicitly* --- "Options All" +# doesn't give it to you. +# + Options Indexes FollowSymLinks + +# +# This controls which options the .htaccess files in directories can +# override. Can also be "All", or any combination of "Options", "FileInfo", +# "AuthConfig", and "Limit" +# + AllowOverride None + +# +# Controls who can get stuff from this server. +# + Order allow,deny + Allow from all + + +# +# UserDir: The name of the directory which is appended onto a user's home +# directory if a ~user request is received. +# +UserDir public_html +# +# Control access to UserDir directories. The following is an example +# for a site where these directories are restricted to read-only. +# +# +# AllowOverride FileInfo AuthConfig Limit +# Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec +# +# Order allow,deny +# Allow from all +# +# +# Order deny,allow +# Deny from all +# +# + +# +# DirectoryIndex: Name of the file or files to use as a pre-written HTML +# directory index. Separate multiple entries with spaces. +# +DirectoryIndex index.html + +# +# AccessFileName: The name of the file to look for in each directory +# for access control information. +# +#AccessFileName .htaccess + +# +# The following lines prevent .htaccess files from being viewed by +# Web clients. Since .htaccess files often contain authorization +# information, access is disallowed for security reasons. Comment +# these lines out if you want Web visitors to see the contents of +# .htaccess files. If you change the AccessFileName directive above, +# be sure to make the corresponding changes here. +# +# Also, folks tend to use names such as .htpasswd for password +# files, so this will protect those as well. +# + + Order allow,deny + Deny from all + + +# +# CacheNegotiatedDocs: By default, Apache sends "Pragma: no-cache" with each +# document that was negotiated on the basis of content. This asks proxy +# servers not to cache the document. Uncommenting the following line disables +# this behavior, and proxies will be allowed to cache the documents. +# +#CacheNegotiatedDocs + +# +# UseCanonicalName: (new for 1.3) With this setting turned on, whenever +# Apache needs to construct a self-referencing URL (a URL that refers back +# to the server the response is coming from) it will use ServerName and +# Port to form a "canonical" name. With this setting off, Apache will +# use the hostname:port that the client supplied, when possible. This +# also affects SERVER_NAME and SERVER_PORT in CGI scripts. +# +UseCanonicalName On + +# +# TypesConfig describes where the mime.types file (or equivalent) is +# to be found. +# +TypesConfig conf/mime.types + +# +# DefaultType is the default MIME type the server will use for a document +# if it cannot otherwise determine one, such as from filename extensions. +# If your server contains mostly text or HTML documents, "text/plain" is +# a good value. If most of your content is binary, such as applications +# or images, you may want to use "application/octet-stream" instead to +# keep browsers from trying to display binary files as though they are +# text. +# +DefaultType text/plain + +# +# The mod_mime_magic module allows the server to use various hints from the +# contents of the file itself to determine its type. The MIMEMagicFile +# directive tells the module where the hint definitions are located. +# mod_mime_magic is not part of the default server (you have to add +# it yourself with a LoadModule [see the DSO paragraph in the 'Global +# Environment' section], or recompile the server and include mod_mime_magic +# as part of the configuration), so it's enclosed in an container. +# This means that the MIMEMagicFile directive will only be processed if the +# module is part of the server. +# + + MIMEMagicFile conf/magic + + +# +# HostnameLookups: Log the names of clients or just their IP addresses +# e.g., www.apache.org (on) or 204.62.129.132 (off). +# The default is off because it'd be overall better for the net if people +# had to knowingly turn this feature on, since enabling it means that +# each client request will result in AT LEAST one lookup request to the +# nameserver. +# +HostnameLookups Off + +# +# ErrorLog: The location of the error log file. +# If you do not specify an ErrorLog directive within a +# container, error messages relating to that virtual host will be +# logged here. If you *do* define an error logfile for a +# container, that host's errors will be logged there and not here. +# +ErrorLog logs/error_log + +# +# LogLevel: Control the number of messages logged to the error_log. +# Possible values include: debug, info, notice, warn, error, crit, +# alert, emerg. +# +LogLevel warn + +# +# The following directives define some format nicknames for use with +# a CustomLog directive (see below). +# +LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined +LogFormat "%h %l %u %t \"%r\" %>s %b" common +LogFormat "%{Referer}i -> %U" referer +LogFormat "%{User-agent}i" agent + +# +# The location and format of the access logfile (Common Logfile Format). +# If you do not define any access logfiles within a +# container, they will be logged here. Contrariwise, if you *do* +# define per- access logfiles, transactions will be +# logged therein and *not* in this file. +# +#CustomLog logs/access_log common + +# +# If you would like to have agent and referer logfiles, uncomment the +# following directives. +# +#CustomLog logs/referer_log referer +#CustomLog logs/agent_log agent + +# +# If you prefer a single logfile with access, agent, and referer information +# (Combined Logfile Format) you can use the following directive. +# +#CustomLog logs/access_log combined + +# +# Optionally add a line containing the server version and virtual host +# name to server-generated pages (error documents, FTP directory listings, +# mod_status and mod_info output etc., but not CGI generated documents). +# Set to "EMail" to also include a mailto: link to the ServerAdmin. +# Set to one of: On | Off | EMail +# +ServerSignature On + +# +# Aliases: Add here as many aliases as you need (with no limit). The format is +# Alias fakename realname +# +# Note that if you include a trailing / on fakename then the server will +# require it to be present in the URL. So "/icons" isn't aliased in this +# example, only "/icons/".. +# +Alias /icons/ "sys:/apache/icons/" + + + Options Indexes MultiViews + AllowOverride None + Order allow,deny + Allow from all + + +# +# ScriptAlias: This controls which directories contain server scripts. +# ScriptAliases are essentially the same as Aliases, except that +# documents in the realname directory are treated as applications and +# run by the server when requested rather than as documents sent to the client. +# The same rules about trailing "/" apply to ScriptAlias directives as to +# Alias. +# +ScriptAlias /cgi-bin/ "sys:/apache/cgi-bin/" + +# +# "sys:/apache/cgi-bin" should be changed to whatever your ScriptAliased +# CGI directory exists, if you have that configured. +# + + AllowOverride None + Options None + Order allow,deny + Allow from all + + +# +# Redirect allows you to tell clients about documents which used to exist in +# your server's namespace, but do not anymore. This allows you to tell the +# clients where to look for the relocated document. +# Format: Redirect old-URI new-URL +# + +# +# Directives controlling the display of server-generated directory listings. +# + +# +# FancyIndexing is whether you want fancy directory indexing or standard +# +IndexOptions FancyIndexing + +# +# AddIcon* directives tell the server which icon to show for different +# files or filename extensions. These are only displayed for +# FancyIndexed directories. +# +AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip + +AddIconByType (TXT,/icons/text.gif) text/* +AddIconByType (IMG,/icons/image2.gif) image/* +AddIconByType (SND,/icons/sound2.gif) audio/* +AddIconByType (VID,/icons/movie.gif) video/* + +AddIcon /icons/binary.gif .bin .exe +AddIcon /icons/binhex.gif .hqx +AddIcon /icons/tar.gif .tar +AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv +AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip +AddIcon /icons/a.gif .ps .ai .eps +AddIcon /icons/layout.gif .html .shtml .htm .pdf +AddIcon /icons/text.gif .txt +AddIcon /icons/c.gif .c +AddIcon /icons/p.gif .pl .py +AddIcon /icons/f.gif .for +AddIcon /icons/dvi.gif .dvi +AddIcon /icons/uuencoded.gif .uu +AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl +AddIcon /icons/tex.gif .tex +AddIcon /icons/bomb.gif core + +AddIcon /icons/back.gif .. +AddIcon /icons/hand.right.gif README +AddIcon /icons/folder.gif ^^DIRECTORY^^ +AddIcon /icons/blank.gif ^^BLANKICON^^ + +# +# DefaultIcon is which icon to show for files which do not have an icon +# explicitly set. +# +DefaultIcon /icons/unknown.gif + +# +# AddDescription allows you to place a short description after a file in +# server-generated indexes. These are only displayed for FancyIndexed +# directories. +# Format: AddDescription "description" filename +# +#AddDescription "GZIP compressed document" .gz +#AddDescription "tar archive" .tar +#AddDescription "GZIP compressed tar archive" .tgz + +# +# ReadmeName is the name of the README file the server will look for by +# default, and append to directory listings. +# +# HeaderName is the name of a file which should be prepended to +# directory indexes. +# +# The server will first look for name.html and include it if found. +# If name.html doesn't exist, the server will then look for name.txt +# and include it as plaintext if found. +# +ReadmeName README +HeaderName HEADER + +# +# IndexIgnore is a set of filenames which directory indexing should ignore +# and not include in the listing. Shell-style wildcarding is permitted. +# +IndexIgnore .??* *~ *# HEADER* README* RCS CVS *,v *,t + +# +# AddEncoding allows you to have certain browsers (Mosaic/X 2.1+) uncompress +# information on the fly. Note: Not all browsers support this. +# Despite the name similarity, the following Add* directives have nothing +# to do with the FancyIndexing customization directives above. +# +AddEncoding x-compress Z +AddEncoding x-gzip gz tgz + +# +# AddLanguage allows you to specify the language of a document. You can +# then use content negotiation to give a browser a file in a language +# it can understand. Note that the suffix does not have to be the same +# as the language keyword --- those with documents in Polish (whose +# net-standard language code is pl) may wish to use "AddLanguage pl .po" +# to avoid the ambiguity with the common suffix for perl scripts. +# +AddLanguage en .en +AddLanguage fr .fr +AddLanguage de .de +AddLanguage da .da +AddLanguage el .el +AddLanguage it .it + +# +# LanguagePriority allows you to give precedence to some languages +# in case of a tie during content negotiation. +# Just list the languages in decreasing order of preference. +# +LanguagePriority en fr de + +# +# AddType allows you to tweak mime.types without actually editing it, or to +# make certain files to be certain types. +# +# For example, the PHP3 module (not part of the Apache distribution - see +# http://www.php.net) will typically use: +# +#AddType application/x-httpd-php3 .php3 +#AddType application/x-httpd-php3-source .phps + +AddType application/x-tar .tgz + +# +# AddHandler allows you to map certain file extensions to "handlers", +# actions unrelated to filetype. These can be either built into the server +# or added with the Action command (see below) +# +# If you want to use server side includes, or CGI outside +# ScriptAliased directories, uncomment the following lines. +# +# To use CGI scripts: +# +#AddHandler cgi-script .cgi + +# +# To use server-parsed HTML files +# +#AddType text/html .shtml +#AddHandler server-parsed .shtml + +# +# Uncomment the following line to enable Apache's send-asis HTTP file +# feature +# +#AddHandler send-as-is asis + +# +# If you wish to use server-parsed imagemap files, use +# +#AddHandler imap-file map + +# +# To enable type maps, you might want to use +# +#AddHandler type-map var + +# +# Action lets you define media types that will execute a script whenever +# a matching file is called. This eliminates the need for repeated URL +# pathnames for oft-used CGI file processors. +# Format: Action media/type /cgi-script/location +# Format: Action handler-name /cgi-script/location +# + +# +# MetaDir: specifies the name of the directory in which Apache can find +# meta information files. These files contain additional HTTP headers +# to include when sending the document +# +#MetaDir .web + +# +# MetaSuffix: specifies the file name suffix for the file containing the +# meta information. +# +#MetaSuffix .meta + +# +# Customizable error response (Apache style) +# these come in three flavors +# +# 1) plain text +#ErrorDocument 500 "The server made a boo boo. +# n.b. the (") marks it as text, it does not get output +# +# 2) local redirects +#ErrorDocument 404 /missing.html +# to redirect to local URL /missing.html +#ErrorDocument 404 /cgi-bin/missing_handler.pl +# N.B.: You can redirect to a script or a document using server-side-includes. +# +# 3) external redirects +#ErrorDocument 402 http://some.other_server.com/subscription_info.html +# N.B.: Many of the environment variables associated with the original +# request will *not* be available to such a script. + +# +# The following directives modify normal HTTP response behavior. +# The first directive disables keepalive for Netscape 2.x and browsers that +# spoof it. There are known problems with these browser implementations. +# The second directive is for Microsoft Internet Explorer 4.0b2 +# which has a broken HTTP/1.1 implementation and does not properly +# support keepalive when it is used on 301 or 302 (redirect) responses. +# +BrowserMatch "Mozilla/2" nokeepalive +BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0 + +# +# The following directive disables HTTP/1.1 responses to browsers which +# are in violation of the HTTP/1.0 spec by not being able to grok a +# basic 1.1 response. +# +BrowserMatch "RealPlayer 4\.0" force-response-1.0 +BrowserMatch "Java/1\.0" force-response-1.0 +BrowserMatch "JDK/1\.0" force-response-1.0 + +# +# Allow server status reports, with the URL of http://servername/server-status +# Change the ".your_domain.com" to match your domain to enable. +# +# +# SetHandler server-status +# Order deny,allow +# Deny from all +# Allow from .your_domain.com +# + +# +# Allow remote server configuration reports, with the URL of +# http://servername/server-info (requires that mod_info.c be loaded). +# Change the ".your_domain.com" to match your domain to enable. +# +# +# SetHandler server-info +# Order deny,allow +# Deny from all +# Allow from .your_domain.com +# + +# +# There have been reports of people trying to abuse an old bug from pre-1.1 +# days. This bug involved a CGI script distributed as a part of Apache. +# By uncommenting these lines you can redirect these attacks to a logging +# script on phf.apache.org. Or, you can record them yourself, using the script +# support/phf_abuse_log.cgi. +# +# +# Deny from all +# ErrorDocument 403 http://phf.apache.org/phf_abuse_log.cgi +# + +# +# Proxy Server directives. Uncomment the following lines to +# enable the proxy server: +# +# +#ProxyRequests On +# +# +# Order deny,allow +# Deny from all +# Allow from .your_domain.com +# + +# +# Enable/disable the handling of HTTP/1.1 "Via:" headers. +# ("Full" adds the server version; "Block" removes all outgoing Via: headers) +# Set to one of: Off | On | Full | Block +# +#ProxyVia On + +# +# To enable the cache as well, edit and uncomment the following lines: +# (no cacheing without CacheRoot) +# +#CacheRoot "sys:/apache/proxy" +#CacheSize 5 +#CacheGcInterval 4 +#CacheMaxExpire 24 +#CacheLastModifiedFactor 0.1 +#CacheDefaultExpire 1 +#NoCache a_domain.com another_domain.edu joes.garage_sale.com + +# +# End of proxy directives. + +### Section 3: Virtual Hosts +# +# VirtualHost: If you want to maintain multiple domains/hostnames on your +# machine you can setup VirtualHost containers for them. +# Please see the documentation at +# for further details before you try to setup virtual hosts. +# You may use the command line option '-S' to verify your virtual host +# configuration. + +# +# If you want to use name-based virtual hosts you need to define at +# least one IP address (and port number) for them. +# +#NameVirtualHost 123.45.67.89:8080 + + +# +# VirtualHost example: +# Almost any Apache directive may go into a VirtualHost container. +# +# +# ServerAdmin webmaster@host.some_domain.com +# DocumentRoot /www/docs/host.some_domain.com +# ServerName host.some_domain.com +# ErrorLog logs/host.some_domain.com-error_log +# CustomLog logs/host.some_domain.com-access_log common +# + +# +# + diff --git a/APACHE_1_3_12/conf/magic b/APACHE_1_3_12/conf/magic new file mode 100644 index 0000000000..885b793aec --- /dev/null +++ b/APACHE_1_3_12/conf/magic @@ -0,0 +1,371 @@ +# Magic data for mod_mime_magic Apache module (originally for file(1) command) +# The module is described in htdocs/manual/mod/mod_mime_magic.html +# +# The format is 4-5 columns: +# Column #1: byte number to begin checking from, ">" indicates continuation +# Column #2: type of data to match +# Column #3: contents of data to match +# Column #4: MIME type of result +# Column #5: MIME encoding of result (optional) + +#------------------------------------------------------------------------------ +# Localstuff: file(1) magic for locally observed files +# Add any locally observed files here. + +#------------------------------------------------------------------------------ +# end local stuff +#------------------------------------------------------------------------------ + +#------------------------------------------------------------------------------ +# Java + +0 short 0xcafe +>2 short 0xbabe application/java + +#------------------------------------------------------------------------------ +# audio: file(1) magic for sound formats +# +# from Jan Nicolai Langfeldt , +# + +# Sun/NeXT audio data +0 string .snd +>12 belong 1 audio/basic +>12 belong 2 audio/basic +>12 belong 3 audio/basic +>12 belong 4 audio/basic +>12 belong 5 audio/basic +>12 belong 6 audio/basic +>12 belong 7 audio/basic + +>12 belong 23 audio/x-adpcm + +# DEC systems (e.g. DECstation 5000) use a variant of the Sun/NeXT format +# that uses little-endian encoding and has a different magic number +# (0x0064732E in little-endian encoding). +0 lelong 0x0064732E +>12 lelong 1 audio/x-dec-basic +>12 lelong 2 audio/x-dec-basic +>12 lelong 3 audio/x-dec-basic +>12 lelong 4 audio/x-dec-basic +>12 lelong 5 audio/x-dec-basic +>12 lelong 6 audio/x-dec-basic +>12 lelong 7 audio/x-dec-basic +# compressed (G.721 ADPCM) +>12 lelong 23 audio/x-dec-adpcm + +# Bytes 0-3 of AIFF, AIFF-C, & 8SVX audio files are "FORM" +# AIFF audio data +8 string AIFF audio/x-aiff +# AIFF-C audio data +8 string AIFC audio/x-aiff +# IFF/8SVX audio data +8 string 8SVX audio/x-aiff + +# Creative Labs AUDIO stuff +# Standard MIDI data +0 string MThd audio/unknown +#>9 byte >0 (format %d) +#>11 byte >1 using %d channels +# Creative Music (CMF) data +0 string CTMF audio/unknown +# SoundBlaster instrument data +0 string SBI audio/unknown +# Creative Labs voice data +0 string Creative\ Voice\ File audio/unknown +## is this next line right? it came this way... +#>19 byte 0x1A +#>23 byte >0 - version %d +#>22 byte >0 \b.%d + +# [GRR 950115: is this also Creative Labs? Guessing that first line +# should be string instead of unknown-endian long...] +#0 long 0x4e54524b MultiTrack sound data +#0 string NTRK MultiTrack sound data +#>4 long x - version %ld + +# Microsoft WAVE format (*.wav) +# [GRR 950115: probably all of the shorts and longs should be leshort/lelong] +# Microsoft RIFF +0 string RIFF audio/unknown +# - WAVE format +>8 string WAVE audio/x-wav + +#------------------------------------------------------------------------------ +# c-lang: file(1) magic for C programs or various scripts +# + +# XPM icons (Greg Roelofs, newt@uchicago.edu) +# ideally should go into "images", but entries below would tag XPM as C source +0 string /*\ XPM image/x-xbm 7bit + +# this first will upset you if you're a PL/1 shop... (are there any left?) +# in which case rm it; ascmagic will catch real C programs +# C or REXX program text +0 string /* text/plain +# C++ program text +0 string // text/plain + +#------------------------------------------------------------------------------ +# compress: file(1) magic for pure-compression formats (no archives) +# +# compress, gzip, pack, compact, huf, squeeze, crunch, freeze, yabba, whap, etc. +# +# Formats for various forms of compressed data +# Formats for "compress" proper have been moved into "compress.c", +# because it tries to uncompress it to figure out what's inside. + +# standard unix compress +0 string \037\235 application/octet-stream x-compress + +# gzip (GNU zip, not to be confused with [Info-ZIP/PKWARE] zip archiver) +0 string \037\213 application/octet-stream x-gzip + +# According to gzip.h, this is the correct byte order for packed data. +0 string \037\036 application/octet-stream +# +# This magic number is byte-order-independent. +# +0 short 017437 application/octet-stream + +# XXX - why *two* entries for "compacted data", one of which is +# byte-order independent, and one of which is byte-order dependent? +# +# compacted data +0 short 0x1fff application/octet-stream +0 string \377\037 application/octet-stream +# huf output +0 short 0145405 application/octet-stream + +# Squeeze and Crunch... +# These numbers were gleaned from the Unix versions of the programs to +# handle these formats. Note that I can only uncrunch, not crunch, and +# I didn't have a crunched file handy, so the crunch number is untested. +# Keith Waclena +#0 leshort 0x76FF squeezed data (CP/M, DOS) +#0 leshort 0x76FE crunched data (CP/M, DOS) + +# Freeze +#0 string \037\237 Frozen file 2.1 +#0 string \037\236 Frozen file 1.0 (or gzip 0.5) + +# lzh? +#0 string \037\240 LZH compressed data + +#------------------------------------------------------------------------------ +# frame: file(1) magic for FrameMaker files +# +# This stuff came on a FrameMaker demo tape, most of which is +# copyright, but this file is "published" as witness the following: +# +0 string \ +# and Anna Shergold +# +0 string \14 byte 12 (OS/2 1.x format) +#>14 byte 64 (OS/2 2.x format) +#>14 byte 40 (Windows 3.x format) +#0 string IC icon +#0 string PI pointer +#0 string CI color icon +#0 string CP color pointer +#0 string BA bitmap array + + +#------------------------------------------------------------------------------ +# lisp: file(1) magic for lisp programs +# +# various lisp types, from Daniel Quinlan (quinlan@yggdrasil.com) +0 string ;; text/plain 8bit +# Emacs 18 - this is always correct, but not very magical. +0 string \012( application/x-elc +# Emacs 19 +0 string ;ELC\023\000\000\000 application/x-elc + +#------------------------------------------------------------------------------ +# mail.news: file(1) magic for mail and news +# +# There are tests to ascmagic.c to cope with mail and news. +0 string Relay-Version: message/rfc822 7bit +0 string #!\ rnews message/rfc822 7bit +0 string N#!\ rnews message/rfc822 7bit +0 string Forward\ to message/rfc822 7bit +0 string Pipe\ to message/rfc822 7bit +0 string Return-Path: message/rfc822 7bit +0 string Path: message/news 8bit +0 string Xref: message/news 8bit +0 string From: message/rfc822 7bit +0 string Article message/news 8bit +#------------------------------------------------------------------------------ +# msword: file(1) magic for MS Word files +# +# Contributor claims: +# Reversed-engineered MS Word magic numbers +# + +0 string \376\067\0\043 application/msword +0 string \333\245-\0\0\0 application/msword + +# disable this one because it applies also to other +# Office/OLE documents for which msword is not correct. See PR#2608. +#0 string \320\317\021\340\241\261 application/msword + + + +#------------------------------------------------------------------------------ +# printer: file(1) magic for printer-formatted files +# + +# PostScript +0 string %! application/postscript +0 string \004%! application/postscript + +# Acrobat +# (due to clamen@cs.cmu.edu) +0 string %PDF- application/pdf + +#------------------------------------------------------------------------------ +# sc: file(1) magic for "sc" spreadsheet +# +38 string Spreadsheet application/x-sc + +#------------------------------------------------------------------------------ +# tex: file(1) magic for TeX files +# +# XXX - needs byte-endian stuff (big-endian and little-endian DVI?) +# +# From + +# Although we may know the offset of certain text fields in TeX DVI +# and font files, we can't use them reliably because they are not +# zero terminated. [but we do anyway, christos] +0 string \367\002 application/x-dvi +#0 string \367\203 TeX generic font data +#0 string \367\131 TeX packed font data +#0 string \367\312 TeX virtual font data +#0 string This\ is\ TeX, TeX transcript text +#0 string This\ is\ METAFONT, METAFONT transcript text + +# There is no way to detect TeX Font Metric (*.tfm) files without +# breaking them apart and reading the data. The following patterns +# match most *.tfm files generated by METAFONT or afm2tfm. +#2 string \000\021 TeX font metric data +#2 string \000\022 TeX font metric data +#>34 string >\0 (%s) + +# Texinfo and GNU Info, from Daniel Quinlan (quinlan@yggdrasil.com) +#0 string \\input\ texinfo Texinfo source text +#0 string This\ is\ Info\ file GNU Info text + +# correct TeX magic for Linux (and maybe more) +# from Peter Tobias (tobias@server.et-inf.fho-emden.de) +# +0 leshort 0x02f7 application/x-dvi + +# RTF - Rich Text Format +0 string {\\rtf application/rtf + +#------------------------------------------------------------------------------ +# animation: file(1) magic for animation/movie formats +# +# animation formats, originally from vax@ccwf.cc.utexas.edu (VaX#n8) +# MPEG file +0 string \000\000\001\263 video/mpeg +# +# The contributor claims: +# I couldn't find a real magic number for these, however, this +# -appears- to work. Note that it might catch other files, too, +# so BE CAREFUL! +# +# Note that title and author appear in the two 20-byte chunks +# at decimal offsets 2 and 22, respectively, but they are XOR'ed with +# 255 (hex FF)! DL format SUCKS BIG ROCKS. +# +# DL file version 1 , medium format (160x100, 4 images/screen) +0 byte 1 video/unknown +0 byte 2 video/unknown + diff --git a/APACHE_1_3_12/conf/mime.types b/APACHE_1_3_12/conf/mime.types new file mode 100644 index 0000000000..0e6ccc4d11 --- /dev/null +++ b/APACHE_1_3_12/conf/mime.types @@ -0,0 +1,373 @@ +# This is a comment. I love comments. + +# This file controls what Internet media types are sent to the client for +# given file extension(s). Sending the correct media 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. For more information about Internet media types, +# please read RFC 2045, 2046, 2047, 2048, and 2077. The Internet media type +# registry is at . + +# MIME type Extension +application/EDI-Consent +application/EDI-X12 +application/EDIFACT +application/activemessage +application/andrew-inset ez +application/applefile +application/atomicmail +application/batch-smtp +application/cals-1840 +application/commonground +application/cybercash +application/dca-rft +application/dec-dx +application/eshop +application/http +application/hyperstudio +application/iges +application/index +application/index.cmd +application/index.obj +application/index.response +application/index.vnd +application/ipp +application/mac-binhex40 hqx +application/mac-compactpro cpt +application/macwriteii +application/marc +application/mathematica +application/mathematica-old +application/msword doc +application/news-message-id +application/news-transmission +application/ocsp-request +application/ocsp-response +application/octet-stream bin dms lha lzh exe class +application/oda oda +application/pdf pdf +application/pgp-encrypted +application/pgp-keys +application/pgp-signature +application/pkcs10 +application/pkcs7-mime +application/pkcs7-signature +application/pkix-cert +application/pkix-crl +application/pkixcmp +application/postscript ai eps ps +application/prs.alvestrand.titrax-sheet +application/prs.cww +application/prs.nprend +application/remote-printing +application/riscos +application/rtf rtf +application/sdp +application/set-payment +application/set-payment-initiation +application/set-registration +application/set-registration-initiation +application/sgml +application/sgml-open-catalog +application/slate +application/smil smi smil +application/vemmi +application/vnd.3M.Post-it-Notes +application/vnd.FloGraphIt +application/vnd.accpac.simply.aso +application/vnd.accpac.simply.imp +application/vnd.acucobol +application/vnd.anser-web-certificate-issue-initiation +application/vnd.anser-web-funds-transfer-initiation +application/vnd.audiograph +application/vnd.businessobjects +application/vnd.claymore +application/vnd.commerce-battelle +application/vnd.commonspace +application/vnd.comsocaller +application/vnd.cosmocaller +application/vnd.cups-postscript +application/vnd.cups-raster +application/vnd.cups-raw +application/vnd.cybank +application/vnd.dna +application/vnd.dpgraph +application/vnd.dxr +application/vnd.ecdis-update +application/vnd.ecowin.chart +application/vnd.ecowin.filerequest +application/vnd.ecowin.fileupdate +application/vnd.ecowin.series +application/vnd.ecowin.seriesrequest +application/vnd.ecowin.seriesupdate +application/vnd.enliven +application/vnd.epson.msf +application/vnd.epson.quickanime +application/vnd.epson.salt +application/vnd.epson.ssf +application/vnd.fdf +application/vnd.ffsns +application/vnd.framemaker +application/vnd.fujitsu.oasys +application/vnd.fujitsu.oasys2 +application/vnd.fujitsu.oasys3 +application/vnd.fujitsu.oasysgp +application/vnd.fujitsu.oasysprs +application/vnd.fujixerox.docuworks +application/vnd.fut-misnet +application/vnd.hp-HPGL +application/vnd.hp-PCL +application/vnd.hp-PCLXL +application/vnd.hp-hpid +application/vnd.hp-hps +application/vnd.ibm.MiniPay +application/vnd.ibm.modcap +application/vnd.intercon.formnet +application/vnd.intertrust.digibox +application/vnd.intertrust.nncp +application/vnd.intu.qbo +application/vnd.intu.qfx +application/vnd.is-xpr +application/vnd.japannet-directory-service +application/vnd.japannet-jpnstore-wakeup +application/vnd.japannet-payment-wakeup +application/vnd.japannet-registration +application/vnd.japannet-registration-wakeup +application/vnd.japannet-setstore-wakeup +application/vnd.japannet-verification +application/vnd.japannet-verification-wakeup +application/vnd.koan +application/vnd.lotus-1-2-3 +application/vnd.lotus-approach +application/vnd.lotus-freelance +application/vnd.lotus-notes +application/vnd.lotus-organizer +application/vnd.lotus-screencam +application/vnd.lotus-wordpro +application/vnd.mediastation.cdkey +application/vnd.meridian-slingshot +application/vnd.mif mif +application/vnd.minisoft-hp3000-save +application/vnd.mitsubishi.misty-guard.trustweb +application/vnd.mobius.daf +application/vnd.mobius.dis +application/vnd.mobius.msl +application/vnd.mobius.plc +application/vnd.mobius.txf +application/vnd.motorola.flexsuite +application/vnd.motorola.flexsuite.adsi +application/vnd.motorola.flexsuite.fis +application/vnd.motorola.flexsuite.gotap +application/vnd.motorola.flexsuite.kmr +application/vnd.motorola.flexsuite.ttc +application/vnd.motorola.flexsuite.wem +application/vnd.ms-artgalry +application/vnd.ms-asf +application/vnd.ms-excel xls +application/vnd.ms-powerpoint ppt +application/vnd.ms-project +application/vnd.ms-tnef +application/vnd.ms-works +application/vnd.music-niff +application/vnd.musician +application/vnd.netfpx +application/vnd.noblenet-directory +application/vnd.noblenet-sealer +application/vnd.noblenet-web +application/vnd.novadigm.EDM +application/vnd.novadigm.EDX +application/vnd.novadigm.EXT +application/vnd.osa.netdeploy +application/vnd.pg.format +application/vnd.pg.osasli +application/vnd.powerbuilder6 +application/vnd.powerbuilder6-s +application/vnd.powerbuilder7 +application/vnd.powerbuilder7-s +application/vnd.powerbuilder75 +application/vnd.powerbuilder75-s +application/vnd.previewsystems.box +application/vnd.publishare-delta-tree +application/vnd.rapid +application/vnd.seemail +application/vnd.shana.informed.formdata +application/vnd.shana.informed.formtemplate +application/vnd.shana.informed.interchange +application/vnd.shana.informed.package +application/vnd.street-stream +application/vnd.svd +application/vnd.swiftview-ics +application/vnd.triscape.mxs +application/vnd.truedoc +application/vnd.ufdl +application/vnd.uplanet.alert +application/vnd.uplanet.alert-wbxml +application/vnd.uplanet.bearer-choi-wbxml +application/vnd.uplanet.bearer-choice +application/vnd.uplanet.cacheop +application/vnd.uplanet.cacheop-wbxml +application/vnd.uplanet.channel +application/vnd.uplanet.channel-wbxml +application/vnd.uplanet.list +application/vnd.uplanet.list-wbxml +application/vnd.uplanet.listcmd +application/vnd.uplanet.listcmd-wbxml +application/vnd.uplanet.signal +application/vnd.vcx +application/vnd.visio +application/vnd.wap.wbxml +application/vnd.wap.wmlc +application/vnd.wap.wmlscriptc +application/vnd.webturbo +application/vnd.wrq-hp3000-labelled +application/vnd.wt.stf +application/vnd.xara +application/vnd.xfdl +application/vnd.yellowriver-custom-menu +application/wita +application/wordperfect5.1 +application/x-bcpio bcpio +application/x-cdlink vcd +application/x-chess-pgn pgn +application/x-compress +application/x-cpio cpio +application/x-csh csh +application/x-director dcr dir dxr +application/x-dvi dvi +application/x-futuresplash spl +application/x-gtar gtar +application/x-gzip +application/x-hdf hdf +application/x-javascript js +application/x-koan skp skd skt skm +application/x-latex latex +application/x-netcdf nc cdf +application/x-sh sh +application/x-shar shar +application/x-shockwave-flash swf +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/x400-bp +application/xml +application/zip zip +audio/32kadpcm +audio/basic au snd +audio/l16 +audio/midi mid midi kar +audio/mpeg mpga mp2 mp3 +audio/vnd.cns.anp1 +audio/vnd.cns.inf1 +audio/vnd.digital-winds +audio/vnd.lucent.voice +audio/vnd.nortel.vbk +audio/vnd.octel.sbc +audio/vnd.qcelp +audio/vnd.rhetorex.32kadpcm +audio/vnd.vmx.cvsd +audio/x-aiff aif aiff aifc +audio/x-pn-realaudio ram rm +audio/x-pn-realaudio-plugin rpm +audio/x-realaudio ra +audio/x-wav wav +chemical/x-pdb pdb xyz +image/bmp bmp +image/cgm +image/g3fax +image/gif gif +image/ief ief +image/jpeg jpeg jpg jpe +image/naplps +image/png png +image/prs.btif +image/prs.pti +image/tiff tiff tif +image/vnd.cns.inf2 +image/vnd.dwg +image/vnd.dxf +image/vnd.fastbidsheet +image/vnd.fpx +image/vnd.mix +image/vnd.net-fpx +image/vnd.svf +image/vnd.wap.wbmp +image/vnd.xiff +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/delivery-status +message/disposition-notification +message/external-body +message/http +message/news +message/partial +message/rfc822 +message/s-http +model/iges igs iges +model/mesh msh mesh silo +model/vnd.dwf +model/vnd.flatland.3dml +model/vnd.gtw +model/vrml wrl vrml +multipart/alternative +multipart/appledouble +multipart/byteranges +multipart/digest +multipart/encrypted +multipart/form-data +multipart/header-set +multipart/mixed +multipart/parallel +multipart/related +multipart/report +multipart/signed +multipart/voice-message +text/calendar +text/css css +text/directory +text/enriched +text/html html htm +text/plain asc txt +text/prs.lines.tag +text/rfc822-headers +text/richtext rtx +text/rtf rtf +text/sgml sgml sgm +text/tab-separated-values tsv +text/uri-list +text/vnd.abc +text/vnd.flatland.3dml +text/vnd.fly +text/vnd.fmi.flexstor +text/vnd.in3d.3dml +text/vnd.in3d.spot +text/vnd.latex-z +text/vnd.motorola.reflex +text/vnd.wap.wml +text/vnd.wap.wmlscript +text/x-setext etx +text/xml xml +video/mpeg mpeg mpg mpe +video/quicktime qt mov +video/vnd.motorola.video +video/vnd.motorola.videop +video/vnd.vivo +video/x-msvideo avi +video/x-sgi-movie movie +x-conference/x-cooltalk ice diff --git a/APACHE_1_3_12/conf/srm.conf-dist b/APACHE_1_3_12/conf/srm.conf-dist new file mode 100644 index 0000000000..394b6fa64d --- /dev/null +++ b/APACHE_1_3_12/conf/srm.conf-dist @@ -0,0 +1,8 @@ +# +# This is the default file for the ResourceConfig directive in httpd.conf. +# It is processed after httpd.conf but before access.conf. +# +# To avoid confusion, it is recommended that you put all of your +# Apache server directives into the httpd.conf file and leave this +# one essentially empty. +# diff --git a/APACHE_1_3_12/conf/srm.conf-dist-win b/APACHE_1_3_12/conf/srm.conf-dist-win new file mode 100644 index 0000000000..394b6fa64d --- /dev/null +++ b/APACHE_1_3_12/conf/srm.conf-dist-win @@ -0,0 +1,8 @@ +# +# This is the default file for the ResourceConfig directive in httpd.conf. +# It is processed after httpd.conf but before access.conf. +# +# To avoid confusion, it is recommended that you put all of your +# Apache server directives into the httpd.conf file and leave this +# one essentially empty. +# diff --git a/APACHE_1_3_12/config.layout b/APACHE_1_3_12/config.layout new file mode 100644 index 0000000000..142dfd67ec --- /dev/null +++ b/APACHE_1_3_12/config.layout @@ -0,0 +1,192 @@ +## +## config.layout -- APACI Pre-defined Installation Path Layouts +## +## Hints: +## - layouts can be loaded with APACI's --with-layout=ID option +## - when no --with-layout option is given, the default layout is `Apache' +## - a trailing plus character (`+') on paths is replaced with a +## `/' suffix where is the the argument from +## option --target (defaults to `httpd'). +## + +# Classical Apache path layout. + + prefix: /usr/local/apache + exec_prefix: $prefix + bindir: $exec_prefix/bin + sbindir: $exec_prefix/bin + libexecdir: $exec_prefix/libexec + mandir: $prefix/man + sysconfdir: $prefix/conf + datadir: $prefix + iconsdir: $datadir/icons + htdocsdir: $datadir/htdocs + cgidir: $datadir/cgi-bin + includedir: $prefix/include + localstatedir: $prefix + runtimedir: $localstatedir/logs + logfiledir: $localstatedir/logs + proxycachedir: $localstatedir/proxy + + +# GNU standards conforming path layout. +# See FSF's GNU project `make-stds' document for details. + + prefix: /usr/local + exec_prefix: $prefix + bindir: $exec_prefix/bin + sbindir: $exec_prefix/sbin + libexecdir: $exec_prefix/libexec + mandir: $prefix/man + sysconfdir: $prefix/etc+ + datadir: $prefix/share+ + iconsdir: $datadir/icons + htdocsdir: $datadir/htdocs + cgidir: $datadir/cgi-bin + includedir: $prefix/include+ + localstatedir: $prefix/var+ + runtimedir: $localstatedir/run + logfiledir: $localstatedir/log + proxycachedir: $localstatedir/proxy + + +# Apache binary distribution path layout + + prefix: /usr/local/apache + exec_prefix: + bindir: bin + sbindir: bin + libexecdir: libexec + mandir: man + sysconfdir: conf + datadir: + iconsdir: icons + htdocsdir: htdocs + cgidir: cgi-bin + includedir: include + localstatedir: + runtimedir: logs + logfiledir: logs + proxycachedir: proxy + + +# Apple's Mac OS X Server Layout + + prefix: /Local/Library/WebServer + exec_prefix: /usr/local + bindir: $exec_prefix/bin + sbindir: $exec_prefix/sbin + libexecdir: /Local/Library/Apache/Modules + mandir: $exec_prefix/share/man + sysconfdir: $prefix/Configuration + datadir: $prefix + iconsdir: /Local/Library/Apache/Icons + htdocsdir: $datadir/Documents + cgidir: $datadir/CGI-Executables + includedir: /Local/Library/Frameworks/Apache.framework/Versions/1.3/Headers + localstatedir: /var + runtimedir: $prefix/Logs + logfiledir: $prefix/Logs + proxycachedir: $prefix/ProxyCache + + +# RedHat 5.x layout + + prefix: /usr + exec_prefix: $prefix + bindir: $prefix/bin + sbindir: $prefix/sbin + libexecdir: $prefix/lib/apache + mandir: $prefix/man + sysconfdir: /etc/httpd/conf + datadir: /home/httpd + iconsdir: $datadir/icons + htdocsdir: $datadir/html + cgidir: $datadir/cgi-bin + includedir: $prefix/include/apache + localstatedir: /var + runtimedir: $localstatedir/run + logfiledir: $localstatedir/log/httpd + proxycachedir: $localstatedir/cache/httpd + + +# According to the /opt filesystem conventions + + prefix: /opt/apache + exec_prefix: $prefix + bindir: $exec_prefix/bin + sbindir: $exec_prefix/sbin + libexecdir: $exec_prefix/libexec + mandir: $prefix/man + sysconfdir: /etc$prefix + datadir: $prefix/share + iconsdir: $datadir/icons + htdocsdir: $datadir/htdocs + cgidir: $datadir/cgi-bin + includedir: $prefix/include + localstatedir: /var$prefix + runtimedir: $localstatedir/run + logfiledir: $localstatedir/logs + proxycachedir: $localstatedir/proxy + + +# BeOS layout... + + prefix: /boot/home/apache + exec_prefix: $prefix + bindir: $exec_prefix/bin + sbindir: $exec_prefix/bin + libexecdir: $exec_prefix/libexec + mandir: $prefix/man + sysconfdir: $prefix/conf + datadir: $prefix + iconsdir: $datadir/icons + htdocsdir: $datadir/htdocs + cgidir: $datadir/cgi-bin + includedir: $prefix/include + localstatedir: $prefix + runtimedir: $localstatedir/logs + logfiledir: $localstatedir/logs + proxycachedir: $localstatedir/proxy + + +# SuSE 6.x layout + + prefix: /usr + exec_prefix: $prefix + bindir: $prefix/bin + sbindir: $prefix/sbin + libexecdir: $prefix/lib/apache + mandir: $prefix/man + sysconfdir: /etc/httpd + datadir: /usr/local/httpd + iconsdir: $datadir/icons + htdocsdir: $datadir/htdocs + cgidir: $datadir/cgi-bin + includedir: $prefix/include/apache + localstatedir: /var + runtimedir: $localstatedir/run + logfiledir: $localstatedir/log/httpd + proxycachedir: $localstatedir/cache/httpd + + +# BSD/OS layout + + prefix: /var/www + exec_prefix: /usr/contrib + bindir: $exec_prefix/bin + sbindir: $exec_prefix/bin + libexecdir: $exec_prefix/libexec/apache + mandir: $exec_prefix/man + sysconfdir: $prefix/conf + datadir: $prefix + iconsdir: $datadir/icons + htdocsdir: $datadir/htdocs + cgidir: $datadir/cgi-bin + includedir: $exec_prefix/include/apache + localstatedir: /var + runtimedir: $localstatedir/run + logfiledir: $localstatedir/log/httpd + proxycachedir: $localstatedir/proxy + + diff --git a/APACHE_1_3_12/configure b/APACHE_1_3_12/configure new file mode 100755 index 0000000000..e3a886aab0 --- /dev/null +++ b/APACHE_1_3_12/configure @@ -0,0 +1,1594 @@ +#!/bin/sh +## ==================================================================== +## Copyright (c) 1998-1999 The Apache Group. 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 acknowledgment: +## "This product includes software developed by the Apache Group +## for use in the Apache HTTP server project (http://www.apache.org/)." +## +## 4. The names "Apache Server" and "Apache Group" must not be used to +## endorse or promote products derived from this software without +## prior written permission. For written permission, please contact +## apache@apache.org. +## +## 5. Products derived from this software may not be called "Apache" +## nor may "Apache" appear in their names without prior written +## permission of the Apache Group. +## +## 6. Redistributions of any form whatsoever must retain the following +## acknowledgment: +## "This product includes software developed by the Apache Group +## for use in the Apache HTTP server project (http://www.apache.org/)." +## +## THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY +## EXPRESSED 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 APACHE GROUP OR +## ITS 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. +## ==================================================================== +## +## This software consists of voluntary contributions made by many +## individuals on behalf of the Apache Group and was originally based +## on public domain software written at the National Center for +## Supercomputing Applications, University of Illinois, Urbana-Champaign. +## For more information on the Apache Group and the Apache HTTP server +## project, please see . +## + +## +## configure -- Apache Autoconf-style Interface (APACI) +## +## Initially written by Ralf S. Engelschall +## + +# default input separator chars: +DIFS=' +' + +## +## avoid brain dead shells on Ultrix and friends +## +if [ -f /bin/sh5 ]; then + if [ ".$APACI_SH5_UPGRADE_STEP" != .done ]; then + APACI_SH5_UPGRADE_STEP=done + export APACI_SH5_UPGRADE_STEP + exec /bin/sh5 $0 "$@" + fi +fi + +## +## the paths to the Apache source tree +## +top=. +mkf=Makefile +src=src +aux=src/helpers +sedsubst=src/.apaci.sedsubst +addconf=src/.apaci.addconf +tplconf=src/.apaci.tplconf +pldconf=src/.apaci.pldconf +configlayout=config.layout +configstatus=config.status +shadow='' + +## +## pre-determine runtime modes +## +help=no +quiet=no +verbose=no +case "$*" in + --help|*--help|*--help* ) + help=yes; quiet=yes + echo "[hang on a moment, generating help]" + echo "" + ;; + --quiet|*--quiet|*--quiet* ) + quiet=yes + ;; + --verbose|*--verbose|*--verbose*|-v|*-v|*-v* ) + verbose=yes + ;; + * ) + ;; +esac + +## +## determine platform id +## +PLATFORM="`$aux/GuessOS`" + +## +## display version information +## +if [ "x$quiet" = "xno" ]; then + APV=`cat $src/include/httpd.h |\ + grep "#define SERVER_BASEVERSION" |\ + sed -e 's/^[^"]*"//' -e 's/".*$//' -e 's/^Apache\///'` + echo "Configuring for Apache, Version $APV" +fi + +## +## important hint for the first-time users +## +if [ $# -eq 0 ]; then + echo " + Warning: Configuring Apache with default settings." + echo " + This is probably not what you really want." + echo " + Please read the README.configure and INSTALL files" + echo " + first or at least run '$0 --help' for" + echo " + a compact summary of available options." +fi + +## +## +## determine path to (optional) Perl interpreter +## +PERL=no-perl-on-this-system +perlpath="`$aux/PrintPath perl5 perl miniperl`" +if [ "x$perlpath" != "x" ]; then + PERL="$perlpath" +fi + +## +## look for deadly broken echo commands which interpret escape +## sequences `\XX' *per default*. For those we first try the -E option +## and if it then is still broken we give a warning message. +## If it works set the `Safe Echo Option' (SEO) variable. +## +SEO='' # CHANGE THIS VARIABLE HERE IF YOU HAVE PROBLEMS WITH ECHO! +bytes=`echo $SEO '\1' | wc -c | awk '{ printf("%s", $1); }'` +if [ "x$bytes" != "x3" ]; then + bytes=`echo -E '\1' | wc -c | awk '{ printf("%s", $1); }'` + if [ "x$bytes" != "x3" ]; then + echo " + Warning: Your 'echo' command is slightly broken." + echo " + It interprets escape sequences per default. We already" + echo " + tried 'echo -E' but had no real success. If errors occur" + echo " + please set the SEO variable in 'configure' manually to" + echo " + the required 'echo' options, i.e. those which force your" + echo " + 'echo' to not interpret escape sequences per default." + else + SEO='-E' + fi +fi + +## +## look for the best Awk we can find because some +## standard Awks are really braindead and cause +## problems for our scripts under some platforms. +## +AWK=awk +awkpath="`$aux/PrintPath nawk gawk awk`" +if [ "x$awkpath" != "x" ]; then + AWK="$awkpath" +fi + +## +## Look for a good Tar. If we don't find 'GNU tar' then make +## sure ours can handle the '-h' (don't copy symlink, copy +## the actual data) option. +## +TAR=tar +tarpath="`$aux/PrintPath gtar gnutar tar`" +if [ "x$tarpath" != "x" ]; then + TAR="$tarpath" +fi +case "`$TAR --version 2>/dev/null`" in + *GNU*) TAROPT="-hcf" ;; + *) if $TAR -hcf - Makefile.tmpl > /dev/null 2>&1 + then + TAROPT="-hcf" + else + TAROPT="-cf" + fi + ;; +esac + +## +## Request USTAR format for tar files on OS/390 +## Request that prelink step be used for 390 +## +case $PLATFORM in + *-IBM-OS390*) + TAROPT="${TAROPT}U" + ;; +esac + +## +## determine path to sh, it's not /bin/sh on ALL systems +## +SHELL=/bin/sh +if [ ! -f "$SHELL" ]; then + SHELL="`$aux/PrintPath sh`" + if [ "x$SHELL" = "x" ]; then + echo "configure:Error: Cannot determine path to Bourne-Shell" 1>&2 + exit 1 + fi +fi + +## +## determine default parameters +## + +# default paths +prefix=UNSET + +# layout configuration +with_layout=0 +show_layout=0 + +# suexec defaults +suexec=0 +suexec_ok=0 +suexec_docroot='$datadir/htdocs' +suexec_logexec='$logfiledir/suexec_log' +suexec_caller=www +suexec_userdir=public_html +suexec_uidmin=100 +suexec_gidmin=100 +suexec_safepath="/usr/local/bin:/usr/bin:/bin" +# if the umask is undefined, we don't change it +#suexec_umask=0755 + +# the installation flags +iflags_program="-m 755 -s" +iflags_core="-m 755" +iflags_dso="-m 755" +iflags_script="-m 755" +iflags_data="-m 644" + +# various other flags +support=1 +confadjust=1 +permute='' + +# determine rules +rules='' +rulelist='' +OIFS="$IFS" +IFS=' +' +for rule in `grep '^Rule' $src/Configuration.tmpl`; do + rule=`echo "$rule" | sed -e 's/^Rule[ ]*//'` + name=`echo "$rule" | sed -e 's/=.*$//'` + namelow=`echo "$name" | tr '[A-Z]' '[a-z]'` + arg=`echo "$rule" | sed -e 's/^.*=//'` + eval "rule_$namelow=$arg" + rules="$rules:$namelow" + rulelist="$rulelist:$name=$arg" +done +IFS="$OIFS" +rules=`echo $rules | sed -e 's/^://'` + +# determine modules +modules='' +modulelist='' +OIFS="$IFS" +IFS=' +' +for module in `egrep '^[# ]*(Add|Shared)Module' $src/Configuration.tmpl`; do + add=yes + share=no + if [ "x`echo $module | grep '^#'`" != "x" ]; then + add=no + fi + if [ "x`echo $module | grep 'SharedModule'`" != "x" ]; then + share=yes + fi + module=`echo "$module" |\ + sed -e 's%^.*/\(.*\)$%\1%' \ + -e 's/\.[oa]$//' \ + -e 's/\.module$//' \ + -e 's/^mod_//' \ + -e 's/^lib//'` + eval "module_$module=$add" + eval "shared_$module=$share" + modules="${modules}:$module" + modulelist="${modulelist}:$module=$add" + if [ "x$share" = "xyes" ]; then + modulelist="${modulelist}*" + fi +done +IFS="$OIFS" +modules=`echo $modules | sed -e 's/^://'` + +# backward compatibility for old src/Configuration.tmpl +# parameter names to the canonical Autoconf-style shell +# variable names. +OIFS="$IFS" +IFS="$DIFS" +for var in CFLAGS LDFLAGS LIBS INCLUDES DEPS; do + eval "val=\$EXTRA_$var" + if [ "x$val" != "x" ]; then + eval "$var=\$val" + eval "EXTRA_$var=\"\"; export EXTRA_$var" + echo " + Hint: please use $var instead of EXTRA_$var next time" + fi +done +IFS="$OIFS" + +## +## Platform-specific defaults +## +case $PLATFORM in + *-apple-rhapsody*) + default_layout="Mac OS X Server" + iflags_core="${iflags_core} -S \"-S\"" + iflags_dso="${iflags_dso} -S \"-S\"" + ;; + *-apple-macos*) + default_layout="Mac OS X Server" + iflags_core="${iflags_core} -S \"-S\"" + iflags_dso="${iflags_dso} -S \"-S\"" + ;; + *OS/2* ) + default_layout="Apache" + iflags_program="${iflags_program} -e .exe" + iflags_core="${iflags_core} -e .exe" + ;; + *MPE/iX* ) + default_layout="Apache" + iflags_program="-m 755" + ;; + *) + default_layout="Apache" + ;; +esac + +## +## support for the default layout +## +case "$*" in + *--with-layout=* ) + ;; + * ) + if [ "x$*" = "x" ]; then + set -- --with-layout="$default_layout" + else + set -- --with-layout="$default_layout" "$@" + fi + ;; +esac + +## +## Initialize server user ID and group ID variables +## +conf_user="" +conf_group="" + +## +## Iterate over the command line options the first time. +## +## This time we pre-process options which need high priority +## on the command line independent of their position, so they +## can be overridden by others. +## +apc_prev='' +OIFS1="$IFS" +IFS="$DIFS" +for apc_option +do + # if previous option needs an argument, assign it. + if [ "x$apc_prev" != "x" ]; then + eval "$apc_prev=\$apc_option" + apc_prev="" + continue + fi + # split out arguments + case "$apc_option" in + -*=*) apc_optarg=`echo "$apc_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) apc_optarg= ;; + esac + # pre-process only a few options now + case "$apc_option" in + --help | -h | -help ) + echo "Usage: configure [options]" + echo "Options: [defaults in brackets after descriptions]" + echo "General options:" + echo " --quiet, --silent do not print messages" + echo " --verbose, -v print even more messages" + echo " --shadow[=DIR] switch to a shadow tree (under DIR) for building" + echo "" + echo "Stand-alone options:" + echo " --help, -h print this message" + echo " --show-layout print installation path layout (check and debug)" + echo "" + echo "Installation layout options:" + echo " --with-layout=[F:]ID use installation path layout ID (from file F)" + echo " --target=TARGET install name-associated files using basename TARGET" + echo " --prefix=PREFIX install architecture-independent files in PREFIX" + echo " --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX" + echo " --bindir=DIR install user executables in DIR" + echo " --sbindir=DIR install sysadmin executables in DIR" + echo " --libexecdir=DIR install program executables in DIR" + echo " --mandir=DIR install manual pages in DIR" + echo " --sysconfdir=DIR install configuration files in DIR" + echo " --datadir=DIR install read-only data files in DIR" + echo " --iconsdir=DIR install read-only icon files in DIR" + echo " --htdocsdir=DIR install read-only document files in DIR" + echo " --cgidir=DIR install read-only cgi files in DIR" + echo " --includedir=DIR install includes files in DIR" + echo " --localstatedir=DIR install modifiable data files in DIR" + echo " --runtimedir=DIR install runtime data in DIR" + echo " --logfiledir=DIR install logfile data in DIR" + echo " --proxycachedir=DIR install proxy cache data in DIR" + echo "" + echo "Configuration options:" + echo " --enable-rule=NAME enable a particular Rule named 'NAME'" + echo " --disable-rule=NAME disable a particular Rule named 'NAME'" + $aux/ppl.sh $rulelist + echo " --add-module=FILE on-the-fly copy & activate a 3rd-party Module" + echo " --activate-module=FILE on-the-fly activate existing 3rd-party Module" + echo " --permute-module=N1:N2 on-the-fly permute module 'N1' with module 'N2'" + echo " --enable-module=NAME enable a particular Module named 'NAME'" + echo " --disable-module=NAME disable a particular Module named 'NAME'" + $aux/ppl.sh $modulelist + echo " --enable-shared=NAME enable build of Module named 'NAME' as a DSO" + echo " --disable-shared=NAME disable build of Module named 'NAME' as a DSO" + echo " --with-perl=FILE path to the optional Perl interpreter" + echo " --with-port=PORT set the port number for httpd.conf" + echo " --without-support disable the build and installation of support tools" + echo " --without-confadjust disable the user/situation adjustments in config" + echo " --without-execstrip disable the stripping of executables on installation" + echo " --server-uid=UID set the user ID the web server should run as [nobody]" + echo " --server-gid=GID set the group ID the web server UID is a memeber of [#-1]" + echo "" + echo "suEXEC options:" + echo " --enable-suexec enable the suEXEC feature" + echo " --suexec-caller=NAME set the suEXEC username of the allowed caller [$suexec_caller]" + echo " --suexec-docroot=DIR set the suEXEC root directory [PREFIX/share/htdocs]" + echo " --suexec-logfile=FILE set the suEXEC logfile [PREFIX/var/log/suexec_log]" + echo " --suexec-userdir=DIR set the suEXEC user subdirectory [$suexec_userdir]" + echo " --suexec-uidmin=UID set the suEXEC minimal allowed UID [$suexec_uidmin]" + echo " --suexec-gidmin=GID set the suEXEC minimal allowed GID [$suexec_gidmin]" + echo " --suexec-safepath=PATH set the suEXEC safe PATH [$suexec_safepath]" + echo " --suexec-umask=UMASK set the umask for the suEXEC'd script [server's umask]" + echo "" + echo "Deprecated options:" + echo " --layout backward compat only: use --show-layout" + echo " --compat backward compat only: use --with-layout=Apache" + exit 0 + ;; + --with-layout=*|--compat) + if [ "x$apc_option" = "x--compat" ]; then + apc_optarg="Apache" + fi + case $apc_optarg in + *:* ) + file=`echo $apc_optarg | sed -e 's/:.*//'` + name=`echo $apc_optarg | sed -e 's/.*://'` + ;; + * ) + name=$apc_optarg + file=$configlayout + ;; + esac + if [ ! -f "$file" ]; then + echo "configure:Error: Path layout definition file $file not found" 1>&2 + exit 1 + fi + sed -e "1,/[ ]*<[Ll]ayout[ ]*$name[ ]*>[ ]*/d" \ + -e '/[ ]*<\/Layout>[ ]*/,$d' \ + -e "s/^[ ]*//g" \ + -e "s/:[ ]*/=\'/g" \ + -e "s/[ ]*$/'/g" \ + $file >$pldconf + . $pldconf + OOIFS="$IFS" # most likely not needed: jmj + IFS="$DIFS" # ditto + for var in prefix exec_prefix bindir sbindir libexecdir mandir \ + sysconfdir datadir iconsdir htdocsdir cgidir includedir \ + localstatedir runtimedir logfiledir proxycachedir; do + eval "val=\"\$$var\"" + case $val in + *+ ) + val=`echo $val | sed -e 's;\+$;;'` + eval "$var=\"\$val\"" + eval "autosuffix_$var=yes" + ;; + * ) + eval "autosuffix_$var=no" + ;; + esac + done + IFS="$OOIFS" + rm -f $pldconf 2>/dev/null + if [ "x$prefix" = "xUNSET" ]; then + echo "configure:Error: Path layout definition not found or incorrect" 1>&2 + exit 1 + fi + if [ "x$quiet" = "xno" ]; then + echo " + using installation path layout: $name ($file)" + fi + name_layout=$name + with_layout=1 + ;; + *) + ;; + esac +done + +## +## Iterate over the command line options the second time. +## +## This time we parse the standard options. +## +addconf_created=0 +apc_prev='' +for apc_option +do + # if previous option needs an argument, assign it. + if [ "x$apc_prev" != "x" ]; then + eval "$apc_prev=\$apc_option" + apc_prev="" + continue + fi + # split out arguments + case "$apc_option" in + -*=*) apc_optarg=`echo "$apc_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) apc_optarg= ;; + esac + # accept only the most important GNU Autoconf-style options + case "$apc_option" in + --help|-h|-help|--with-layout=*|-compat) + # just ignore already parsed options + ;; + --quiet | --silent) + quiet=yes + ;; + --verbose | -v) + verbose=yes + ;; + --shadow*) + # if we use an external shadow tree, first shadow all of ourself + # to this tree and switch over to to it for internal (=platform) + # shadowing... + case "$apc_option" in + --shadow=*) + shadow="$apc_optarg" + if [ "x$quiet" = "xno" ]; then + echo " + creating external package shadow tree ($shadow)" + fi + rm -rf $shadow 2>/dev/null + $aux/mkshadow.sh . $shadow + for file in $mkf $sedsubst $addconf $tplconf $pldconf $configstatus; do + rm -f $shadow/$file 2>/dev/null + done + if [ "x$quiet" = "xno" ]; then + echo " + switching to external package shadow tree ($shadow)" + fi + cd $shadow + ;; + esac + # determine GNU platform triple + gnutriple=`$aux/GuessOS | sed -e 's:/:-:g' | $AWK '{ printf("%s",$1); }'` + # create Makefile wrapper (the first time only) + if [ "x`ls $top/src.* 2>/dev/null`" = "x" ]; then + if [ "x$quiet" = "xno" ]; then + echo " + creating Makefile (shadow wrapper)" + fi + echo "##" > Makefile + echo "## Apache Makefile (shadow wrapper)" >> Makefile + echo "##" >> Makefile + echo "" >> Makefile + if [ "x$shadow" != "x" ]; then + echo "SHADOW=$shadow" >> Makefile + else + echo "SHADOW=." >> Makefile + fi + # (the use of `awk' and not `$AWK' here is correct, because this + # Makefile is for platform bootstrapping, so don't hardcode paths) + echo "GNUTRIPLE=\`$aux/GuessOS | sed -e 's:/:-:g' | awk '{ printf(\"%s\",\$\$1); }'\`" >> Makefile + echo "" >> Makefile + echo "all build install install-quiet clean distclean:" >> Makefile + echo " @cd \$(SHADOW); \$(MAKE) -f Makefile.\$(GNUTRIPLE) \$(MFLAGS) \$@" >> Makefile + echo "" >> Makefile + fi + # set shadow paths + shadowmkf="Makefile.$gnutriple" + shadowsrc="src.$gnutriple" + shadowaux="src.$gnutriple/helpers" + shadowsedsubst="src.$gnutriple/.apaci.sedsubst" + shadowaddconf="src.$gnutriple/.apaci.addconf" + shadowtplconf="src.$gnutriple/.apaci.tplconf" + # (re)create shadow tree + if [ "x$quiet" = "xno" ]; then + echo " + creating internal platform shadow tree ($shadowsrc)" + fi + rm -rf $shadowsrc + $aux/mkshadow.sh $src $shadowsrc + # delegate us to the shadow paths + mkf=$shadowmkf + src=$shadowsrc + aux=$shadowaux + sedsubst=$shadowsedsubst + addconf=$shadowaddconf + tplconf=$shadowtplconf + ;; + --show-layout|--layout) + show_layout=1 + ;; + --target=*) + TARGET="$apc_optarg" + ;; + --prefix=*) + prefix="$apc_optarg" + autosuffix_prefix=no + ;; + --exec-prefix=*) + exec_prefix="$apc_optarg" + autosuffix_exec_prefix=no + ;; + --bindir=*) + bindir="$apc_optarg" + autosuffix_bindir=no + ;; + --sbindir=*) + sbindir="$apc_optarg" + autosuffix_sbindir=no + ;; + --libexecdir=*) + libexecdir="$apc_optarg" + autosuffix_libexecdir=no + ;; + --mandir=*) + mandir="$apc_optarg" + autosuffix_mandir=no + ;; + --sysconfdir=*) + sysconfdir="$apc_optarg" + autosuffix_sysconfdir=no + ;; + --datadir=*) + datadir="$apc_optarg" + autosuffix_datadir=no + ;; + --iconsdir=*) + iconsdir="$apc_optarg" + autosuffix_iconsdir=no + ;; + --htdocsdir=*) + htdocsdir="$apc_optarg" + autosuffix_htdocsdir=no + ;; + --cgidir=*) + cgidir="$apc_optarg" + autosuffix_cgidir=no + ;; + --includedir=*) + includedir="$apc_optarg" + autosuffix_includedir=no + ;; + --localstatedir=*) + localstatedir="$apc_optarg" + autosuffix_localstatedir=no + ;; + --runtimedir=*) + runtimedir="$apc_optarg" + autosuffix_runtimedir=no + ;; + --logfiledir=*) + logfiledir="$apc_optarg" + autosuffix_logfiledir=no + ;; + --proxycachedir=*) + proxycachedir="$apc_optarg" + autosuffix_proxycachedir=no + ;; + --add-module=*) + file="$apc_optarg" + if [ "x`echo $file | egrep '/?mod_[a-zA-Z0-9][a-zA-Z0-9_]*\.c$'`" = "x" ]; then + echo "configure:Error: Module filename doesn't match '/?mod_[a-zA-Z0-9][a-zA-Z0-9_]*\.c'" 1>&2 + exit 1 + fi + if [ ! -f $file ]; then + echo "configure:Error: Module source $file not found" 1>&2 + exit 1 + fi + modfilec=`echo $file | sed -e 's;^.*/;;'` + modfileo=`echo $file | sed -e 's;^.*/;;' -e 's;\.c$;.o;'` + if [ "x$file" != "x$src/modules/extra/$modfilec" ]; then + cp $file $src/modules/extra/$modfilec + fi + if [ "x$addconf_created" = "x0" ]; then + addconf_created=1 + rm -f $addconf 2>/dev/null + touch $addconf 2>/dev/null + fi + echo "" >>$addconf + echo "## On-the-fly added module" >>$addconf + echo "## (configure --add-module=$file)" >>$addconf + echo "AddModule modules/extra/$modfileo" >>$addconf + module=`echo "$modfileo" |\ + sed -e 's%^.*/\(.*\)$%\1%' \ + -e 's/\.[^.]*$//' \ + -e 's/^mod_//' \ + -e 's/^lib//'` + eval "module_$module=yes" + eval "shared_$module=no" + modules="${modules}:$module" + modulelist="${modulelist}:$module=yes" + if [ "x$quiet" = "xno" ]; then + echo " + on-the-fly added and activated $module module (modules/extra/$modfileo)" + fi + ;; + --activate-module=*) + file="$apc_optarg" + case $file in + src/modules/* ) ;; + *) echo "configure:Error: Module source already has to be below src/modules/ to be activated" 1>&2 + exit 1 + ;; + esac + modfile=`echo $file | sed -e 's;^src/;;'` + if [ "x$addconf_created" = "x0" ]; then + addconf_created=1 + rm -f $addconf 2>/dev/null + touch $addconf 2>/dev/null + fi + echo "" >>$addconf + echo "## On-the-fly activated module" >>$addconf + echo "## (configure --activate-module=$file)" >>$addconf + echo "AddModule $modfile" >>$addconf + module=`echo "$modfile" |\ + sed -e 's%^.*/\(.*\)$%\1%' \ + -e 's/\.[^.]*$//' \ + -e 's/^mod_//' \ + -e 's/^lib//'` + eval "module_$module=yes" + eval "shared_$module=no" + modules="${modules}:$module" + modulelist="${modulelist}:$module=yes" + if [ "x$quiet" = "xno" ]; then + echo " + activated $module module ($modfile)" + fi + ;; + --enable-*) + apc_feature=`echo $apc_option | sed -e 's/-*enable-//' -e 's/=.*//'` + apc_feature=`echo $apc_feature | sed 's/-/_/g'` + case "$apc_option" in + *=*) ;; + *) apc_optarg=yes ;; + esac + case "$apc_feature" in + rule ) + apc_optarg=`echo "$apc_optarg" | tr '[A-Z]' '[a-z]'` + apc_optarg_real=`echo "$apc_optarg" | tr '[a-z]' '[A-Z]'` + eval "exists=\$rule_${apc_optarg}" + if [ "x$exists" = "x" ]; then + echo "configure:Error: No such rule named '${apc_optarg_real}'" 1>&2 + exit 1 + fi + eval "rule_${apc_optarg}=yes" + ;; + module ) + case $apc_optarg in + all ) + OOIFS="$IFS" + IFS=':' + for module in $modules; do + eval "module_${module}=yes" + done + IFS="$OOIFS" + module_auth_digest=no # conflict with mod_digest + ;; + most ) + OOIFS="$IFS" + IFS=':' + for module in $modules; do + eval "module_${module}=yes" + done + IFS="$OOIFS" + module_auth_db=no # not all platforms have -ldb + module_mmap_static=no # not all platforms have mmap() + module_so=no # not all platforms have dlopen() + module_example=no # only for developers + module_auth_digest=no # conflict with mod_digest + module_log_agent=no # deprecated + module_log_referer=no # deprecated + ;; + * ) + eval "exists=\$module_${apc_optarg}" + if [ "x$exists" = "x" ]; then + echo "configure:Error: No such module named '${apc_optarg}'" 1>&2 + exit 1 + fi + eval "module_${apc_optarg}=yes" + ;; + esac + ;; + shared ) + case $apc_optarg in + max ) + OOIFS="$IFS" + IFS=':' + for module in $modules; do + eval "shared_${module}=yes" + done + IFS="$OOIFS" + shared_so=no # because of bootstrapping + ;; + remain ) + OOIFS="$IFS" + IFS=':' + for module in $modules; do + eval "add=\$module_${module}" + if [ "x$add" = "xno" ]; then + eval "module_${module}=yes" + eval "shared_${module}=yes" + fi + done + IFS="$OOIFS" + shared_so=no + ;; + * ) + eval "exists=\$module_${apc_optarg}" + if [ "x$exists" = "x" ]; then + echo "configure:Error: No such module named '${apc_optarg}'" 1>&2 + exit 1 + fi + eval "shared_${apc_optarg}=yes" + ;; + esac + ;; + suexec ) + suexec=1 + ;; + * ) + echo "configure:Error: invalid option '$apc_option'" 1>&2 + exit 1 + ;; + esac + ;; + --disable-*) + apc_feature=`echo $apc_option | sed -e 's/-*disable-//' -e 's/=.*//'` + apc_feature=`echo $apc_feature| sed 's/-/_/g'` + case "$apc_option" in + *=*) ;; + *) apc_optarg=yes ;; + esac + case "$apc_feature" in + rule ) + apc_optarg=`echo "$apc_optarg" | tr '[A-Z]' '[a-z]'` + apc_optarg_real=`echo "$apc_optarg" | tr '[a-z]' '[A-Z]'` + eval "exists=\$rule_${apc_optarg}" + if [ "x$exists" = "x" ]; then + echo "configure:Error: No such rule named '${apc_optarg_real}'" 1>&2 + exit 1 + fi + eval "rule_${apc_optarg}=no" + ;; + module ) + case $apc_optarg in + all ) + OOIFS="$IFS" + IFS=':' + for module in $modules; do + eval "module_${module}=no" + done + IFS="$OOIFS" + ;; + * ) + eval "exists=\$module_${apc_optarg}" + if [ "x$exists" = "x" ]; then + echo "configure:Error: No such module named '${apc_optarg}'" 1>&2 + exit 1 + fi + eval "module_${apc_optarg}=no" + ;; + esac + ;; + shared ) + case $apc_optarg in + all ) + OOIFS="$IFS" + IFS=':' + for module in $modules; do + eval "shared_${module}=no" + done + IFS="$OOIFS" + ;; + * ) + eval "exists=\$module_${apc_optarg}" + if [ "x$exists" = "x" ]; then + echo "configure:Error: No such module named '${apc_optarg}'" 1>&2 + exit 1 + fi + eval "shared_${apc_optarg}=no" + ;; + esac + ;; + * ) + echo "configure:Error: invalid option '$apc_option'" 1>&2 + exit 1 + ;; + esac + ;; + --permute-module=*:*) + mod1=`echo $apc_optarg | sed -e 's/:.*//'` + mod2=`echo $apc_optarg | sed -e 's/.*://'` + for mod in $mod1 $mod2; do + case $mod in + BEGIN|END) + ;; + *) eval "exists=\$module_${mod}" + if [ "x$exists" = "x" ]; then + echo "configure:Error: No such module named '${mod}'" 1>&2 + exit 1 + fi + ;; + esac + done + case $mod1:$mod2 in + BEGIN:END|*:BEGIN|END:*) + echo "configure:Error: Invalid combination of pseudo module identifiers" 1>&2 + exit 1 + ;; + esac + permute="${permute},${mod1}:${mod2}" + ;; + --with-perl=*) + PERL="$apc_optarg" + ;; + --with-port=*) + port="$apc_optarg" + ;; + --without-support) + support=0 + ;; + --without-confadjust) + confadjust=0 + ;; + --without-execstrip) + iflags_program=`echo "$iflags_program" | sed -e 's/-s//'` + ;; + --suexec-caller=*) + suexec_caller="$apc_optarg" + suexec_ok=1 + ;; + --suexec-docroot=*) + suexec_docroot="$apc_optarg" + suexec_ok=1 + ;; + --suexec-logfile=*) + suexec_logexec="$apc_optarg" + suexec_ok=1 + ;; + --suexec-userdir=*) + suexec_userdir="$apc_optarg" + suexec_ok=1 + ;; + --suexec-uidmin=*) + suexec_uidmin="$apc_optarg" + suexec_ok=1 + ;; + --suexec-gidmin=*) + suexec_gidmin="$apc_optarg" + suexec_ok=1 + ;; + --suexec-safepath=*) + suexec_safepath="$apc_optarg" + suexec_ok=1 + ;; + --suexec-umask=*) + suexec_umask_val="$apc_optarg" + suexec_umask="-DSUEXEC_UMASK=$apc_optarg" + suexec_ok=1 + ;; + --server-uid=*) + conf_user="$apc_optarg" + # protect the '#' against interpretation as comment + case x"${conf_user}" in + "#"*) conf_user="\\\\${conf_user}";; + "\\#"*)conf_user="\\${conf_user}";; + esac + ;; + --server-gid=*) + conf_group="$apc_optarg" + # protect the '#' against interpretation as comment + case x"${conf_group}" in + "#"*) conf_group="\\\\${conf_group}";; + "\\#"*)conf_group="\\${conf_group}";; + esac + ;; + * ) + echo "configure:Error: invalid option '$apc_option'" 1>&2 + exit 1 + ;; + esac +done +IFS="$OIFS1" +if [ "x$apc_prev" != "x" ]; then + echo "configure:Error: missing argument to --`echo $apc_prev | sed 's/_/-/g'`" 1>&2 + exit 1 +fi +if [ "x$addconf_created" = "x0" ]; then + rm -f $addconf 2>/dev/null + touch $addconf 2>/dev/null +fi + +## +## create a config status script for restoring +## the configuration via a simple shell script +## +rm -f $configstatus 2>/dev/null +echo "#!/bin/sh" >$configstatus +echo "##" >>$configstatus +echo "## $configstatus -- APACI auto-generated configuration restore script" >>$configstatus +echo "##" >>$configstatus +echo "## Use this shell script to re-run the APACI configure script for" >>$configstatus +echo "## restoring your configuration. Additional parameters can be supplied." >>$configstatus +echo "##" >>$configstatus +echo "" >>$configstatus +for var in CC CPP OPTIM CFLAGS CFLAGS_SHLIB LDFLAGS LD_SHLIB LDFLAGS_SHLIB \ + LDFLAGS_SHLIB_EXPORT LIBS INCLUDES RANLIB DEPS TARGET; do + eval "val=\"\$$var\"" + if [ "x$val" != "x" ]; then + echo "$var=$val" |\ + sed -e 's:\(["$\\]\):\\\1:g' \ + -e 's:\([A-Z]*=\):\1":' \ + -e 's:$:" \\:' >>$configstatus + fi +done +echo $SEO "./configure \\" >>$configstatus +for arg +do + echo "$arg" |\ + sed -e 's:\(["$\\]\):\\\1:g' \ + -e 's:^:":' \ + -e 's:$:" \\:' >>$configstatus +done +echo '"$@"' >>$configstatus +echo '' >>$configstatus +chmod a+x $configstatus + +## +## a few errors and warnings +## +if [ "x$suexec" = "x1" ]; then + if [ "x$suexec_ok" = "x0" ]; then + echo "configure:Error: You enabled the suEXEC feature via --enable-suexec but" + echo " without explicitly configuring it via at least one" + echo " --suexec-xxxxx option. Seems like you are still not" + echo " familiar with the suEXEC risks. Please read the INSTALL" + echo " and htdocs/manual/suexec.html documents first." + exit 1 + fi + if [ "x`$aux/getuid.sh`" != "x0" ]; then + echo " + Warning: You have enabled the suEXEC feature. Be aware that you need" 1>&2 + echo " + root privileges to complete the final installation step." 1>&2 + fi +fi +if [ "x$PERL" = "xno-perl-on-this-system" ]; then + if [ "x$quiet" = "xno" ]; then + echo " + Warning: no Perl interpreter detected for support scripts." + echo " + Perhaps you need to specify one with --with-perl=FILE." + fi +fi + +## +## target name +## +if [ "x$TARGET" != "x" ]; then + thetarget="$TARGET" +else + thetarget=httpd +fi + +## +## expand path variables and make sure +## they do not end with a backslash +## +OIFS="$IFS" +IFS="$DIFS" +for var in prefix exec_prefix bindir sbindir libexecdir mandir \ + sysconfdir datadir iconsdir htdocsdir cgidir includedir \ + localstatedir runtimedir logfiledir proxycachedir \ + suexec_docroot suexec_logexec ; do + eval "val=\"\$$var\""; + val=`echo $val | sed -e 's:\(.\)/*$:\1:'` + eval "$var=\"$val\"" + # expand value + eval "val=\$$var" + # automatically add target suffix to path when it's + # requested (path has a trailing plus in config.layout) and + # looks reasonable (i.e. when "apache" or target-name + # still not part of path) + eval "autosuffix=\$autosuffix_$var" + if [ "x$autosuffix" = "xyes" ]; then + addtarget=no + if [ "x`echo $val | grep apache`" = "x" ]; then + if [ "x`echo $val | grep $thetarget`" = "x" ]; then + addtarget=yes + fi + fi + if [ "x$addtarget" = "xyes" ]; then + eval "$var=\"\$$var/$thetarget\"" + fi + fi +done +IFS="$OIFS" + +## +## determine special configurable Makefile targets +## +if [ "x$support" = "x1" ]; then + build_support='build-support' + if [ "x$name_layout" = "xBinaryDistribution" ]; then + install_support='install-binsupport' + else + install_support='install-support' + fi + clean_support='clean-support' + distclean_support='distclean-support' +else + build_support='' + install_support='' + clean_support='' + distclean_support='' +fi + +## +## determine special configuration parameters +## +## The checks via /etc/passwd and /etc/group will obviously fail +## on platforms using NIS. But then you propably do not want a +## UID/GID as production oriented as a web server in NIS anyway. +## +if [ "x$port" != "x" ]; then + conf_port=$port +else + conf_port="80" +fi +conf_serveradmin="you@your.address" +conf_servername="new.host.name" +if [ "x$confadjust" = "x1" ]; then + if [ -f /etc/passwd ]; then + if [ "x$conf_user" = "x" ]; then + for uid in nobody www daemon demon http httpd; do + if [ "x`egrep \^${uid}: /etc/passwd`" != "x" ]; then + conf_user="$uid" + break + fi + done + fi + if [ "x$conf_group" = "x" ]; then + for gid in nobody nogroup www daemon demon http httpd; do + if [ "x`egrep \^${gid}: /etc/group`" != "x" ]; then + conf_group="$gid" + break + fi + done + fi + fi + if [ "x`$aux/getuid.sh`" != "x0" -a "x$port" = "x" ]; then + conf_port="8080" + fi + conf_serveradmin="`$aux/buildinfo.sh -n %u@%h%d`" + conf_servername="`$aux/buildinfo.sh -n %h%d`" +fi + +## +## Default server user id and group id if not specified on configure invocation and none +## of the ids in /etc/passwd or /etc/group worked. +## +if [ "x$conf_user" = "x" ]; then + conf_user="nobody" +fi +if [ "x$conf_group" = "x" ]; then + conf_group="\\\\#-1" +fi + +## +## determine prefix-relative paths for directories +## because Apache supports them for the -d and -f +## options, the LoadModule directive, etc. +## +## [we have to make sure that it ends with a slash +## or we cannot support the case where the relative +## path is just the emtpy one, i.e. ""] +## +runtimedir_relative=`echo $runtimedir | sed -e "s:^$prefix/*::" -e 's:\(.\)$:\1/:'` +logfiledir_relative=`echo $logfiledir | sed -e "s:^$prefix/*::" -e 's:\(.\)$:\1/:'` +sysconfdir_relative=`echo $sysconfdir | sed -e "s:^$prefix/*::" -e 's:\(.\)$:\1/:'` +libexecdir_relative=`echo $libexecdir | sed -e "s:^$prefix/*::" -e 's:\(.\)$:\1/:'` + +## +## check and debug +## +if [ "x$show_layout" = "x1" ]; then + echo "" + echo "Installation paths:" + echo " prefix: $prefix" + echo " exec_prefix: $exec_prefix" + echo " bindir: $bindir" + echo " sbindir: $sbindir" + echo " libexecdir: $libexecdir" + echo " mandir: $mandir" + echo " sysconfdir: $sysconfdir" + echo " datadir: $datadir" + echo " iconsdir: $iconsdir" + echo " htdocsdir: $htdocsdir" + echo " cgidir: $cgidir" + echo " includedir: $includedir" + echo " localstatedir: $localstatedir" + echo " runtimedir: $runtimedir" + echo " logfiledir: $logfiledir" + echo " proxycachedir: $proxycachedir" + echo "" + echo "Compilation paths:" + echo " HTTPD_ROOT: $prefix" + echo " SHARED_CORE_DIR: $libexecdir" + echo " DEFAULT_PIDLOG: ${runtimedir_relative}${thetarget}.pid" + echo " DEFAULT_SCOREBOARD: ${runtimedir_relative}${thetarget}.scoreboard" + echo " DEFAULT_LOCKFILE: ${runtimedir_relative}${thetarget}.lock" + echo " DEFAULT_XFERLOG: ${logfiledir_relative}access_log" + echo " DEFAULT_ERRORLOG: ${logfiledir_relative}error_log" + echo " TYPES_CONFIG_FILE: ${sysconfdir_relative}mime.types" + echo " SERVER_CONFIG_FILE: ${sysconfdir_relative}${thetarget}.conf" + echo " ACCESS_CONFIG_FILE: ${sysconfdir_relative}access.conf" + echo " RESOURCE_CONFIG_FILE: ${sysconfdir_relative}srm.conf" + echo "" + if [ "x$suexec" = "x1" ]; then + echo "suEXEC setup:" + echo " suexec binary: $sbindir/suexec" + echo " document root: $suexec_docroot" + echo " userdir suffix: $suexec_userdir" + echo " logfile: $suexec_logexec" + echo " safe path: $suexec_safepath" + echo " caller ID: $suexec_caller" + echo " minimum user ID: $suexec_uidmin" + echo " minimum group ID: $suexec_gidmin" + if [ "x$suexec_umask" != "x" ]; then + echo " umask: $suexec_umask_val" + else + echo " umask: running server's" + fi + echo "" + fi + exit 0 +fi + +## +## create Makefile from Makefile.tmpl +## +if [ "x$quiet" = "xno" ]; then + echo "Creating $mkf" +fi +sed $mkf \ +-e "s%@PLATFORM@%$PLATFORM%g" \ +-e "s%@PERL@%$PERL%g" \ +-e "s%@TAR@%$TAR%g" \ +-e "s%@TAROPT@%$TAROPT%g" \ +-e "s%@SRC@%$src%g" \ +-e "s%@MKF@%$mkf%g" \ +-e "s%@AUX@%$aux%g" \ +-e "s%@TARGET@%$thetarget%g" \ +-e "s%@IFLAGS_PROGRAM@%$iflags_program%g" \ +-e "s%@IFLAGS_CORE@%$iflags_core%g" \ +-e "s%@IFLAGS_DSO@%$iflags_dso%g" \ +-e "s%@IFLAGS_SCRIPT@%$iflags_script%g" \ +-e "s%@IFLAGS_DATA@%$iflags_data%g" \ +-e "s%@prefix@%$prefix%g" \ +-e "s%@exec_prefix@%$exec_prefix%g" \ +-e "s%@bindir@%$bindir%g" \ +-e "s%@sbindir@%$sbindir%g" \ +-e "s%@libexecdir@%$libexecdir%g" \ +-e "s%@libexecdir_relative@%$libexecdir_relative%g" \ +-e "s%@mandir@%$mandir%g" \ +-e "s%@sysconfdir@%$sysconfdir%g" \ +-e "s%@datadir@%$datadir%g" \ +-e "s%@iconsdir@%$iconsdir%g" \ +-e "s%@htdocsdir@%$htdocsdir%g" \ +-e "s%@cgidir@%$cgidir%g" \ +-e "s%@localstatedir@%$localstatedir%g" \ +-e "s%@includedir@%$includedir%g" \ +-e "s%@runtimedir@%$runtimedir%g" \ +-e "s%@logfiledir@%$logfiledir%g" \ +-e "s%@proxycachedir@%$proxycachedir%g" \ +-e "s%@suexec@%$suexec%g" \ +-e "s%@suexec_caller@%$suexec_caller%g" \ +-e "s%@suexec_docroot@%$suexec_docroot%g" \ +-e "s%@suexec_logexec@%$suexec_logexec%g" \ +-e "s%@suexec_userdir@%$suexec_userdir%g" \ +-e "s%@suexec_uidmin@%$suexec_uidmin%g" \ +-e "s%@suexec_gidmin@%$suexec_gidmin%g" \ +-e "s%@suexec_safepath@%$suexec_safepath%g" \ +-e "s%@suexec_umask@%$suexec_umask%g" \ +-e "s%@conf_user@%$conf_user%g" \ +-e "s%@conf_group@%$conf_group%g" \ +-e "s%@conf_port@%$conf_port%g" \ +-e "s%@conf_serveradmin@%$conf_serveradmin%g" \ +-e "s%@conf_servername@%$conf_servername%g" \ +-e "s%@build_support@%$build_support%g" \ +-e "s%@install_support@%$install_support%g" \ +-e "s%@clean_support@%$clean_support%g" \ +-e "s%@distclean_support@%$distclean_support%g" \ +-e "s%@SHELL@%$SHELL%g" + +## +## override default paths in $src/include/httpd.h +## via command line arguments for the compiler +## supplied by a little shell script named $src/apaci +## +echo "#!/bin/sh" >$src/apaci +echo "## USED AS A COMMAND LINE EXPANDER TO OVERRIDE PATHS" >>$src/apaci +echo "## WITHOUT DISTURBING THE KNOWN MAKE BUILD PROCESS DISPLAY" >>$src/apaci +echo "echo '-DHTTPD_ROOT=\"$prefix\"'" >>$src/apaci +echo "echo '-DSUEXEC_BIN=\"$sbindir/suexec\"'" >>$src/apaci +echo "echo '-DSHARED_CORE_DIR=\"$libexecdir\"'" >>$src/apaci +echo "echo '-DDEFAULT_PIDLOG=\"${runtimedir_relative}${thetarget}.pid\"'" >>$src/apaci +echo "echo '-DDEFAULT_SCOREBOARD=\"${runtimedir_relative}${thetarget}.scoreboard\"'" >>$src/apaci +echo "echo '-DDEFAULT_LOCKFILE=\"${runtimedir_relative}${thetarget}.lock\"'" >>$src/apaci +echo "echo '-DDEFAULT_XFERLOG=\"${logfiledir_relative}access_log\"'" >>$src/apaci +echo "echo '-DDEFAULT_ERRORLOG=\"${logfiledir_relative}error_log\"'" >>$src/apaci +echo "echo '-DTYPES_CONFIG_FILE=\"${sysconfdir_relative}mime.types\"'" >>$src/apaci +echo "echo '-DSERVER_CONFIG_FILE=\"${sysconfdir_relative}${thetarget}.conf\"'" >>$src/apaci +echo "echo '-DACCESS_CONFIG_FILE=\"${sysconfdir_relative}access.conf\"'" >>$src/apaci +echo "echo '-DRESOURCE_CONFIG_FILE=\"${sysconfdir_relative}srm.conf\"'" >>$src/apaci +chmod a+x $src/apaci +CFLAGS="$CFLAGS \\\`\$(SRCDIR)/apaci\\\`" + +## +## create $src/Configuration.apaci file +## +if [ "x$quiet" = "xno" ]; then + echo "Creating Configuration.apaci in $src" +fi +rm -f $sedsubst 2>/dev/null +touch $sedsubst + +# generate settings from imported environment variables +OIFS="$IFS" +IFS="$DIFS" +for var in CC CPP OPTIM CFLAGS CFLAGS_SHLIB LDFLAGS LD_SHLIB LDFLAGS_SHLIB \ + LDFLAGS_SHLIB_EXPORT LIBS INCLUDES RANLIB DEPS TARGET; do + eval "val=\"\$$var\""; + if [ "x$val" != "x" ]; then + case $var in + CFLAGS|LDFLAGS|LIBS|INCLUDES|DEPS) + echo $SEO "s%^#*\\(EXTRA_$var=\\).*%\\1$val%g" >>$sedsubst + ;; + *) + echo $SEO "s%^#*\\($var=\\).*%\\1$val%g" >>$sedsubst + ;; + esac + eval "$var=\"\"; export $var" + fi +done +IFS="$OIFS" + +# generate rule directives +OIFS="$IFS" +IFS=':' +for rule in $rules; do + name="`echo $rule | tr '[a-z]' '[A-Z]'`" + eval "val=\$rule_$rule" + echo $SEO "s%^\\(Rule $name=\\).*%\\1$val%g" >>$sedsubst + if [ "x$verbose" = "xyes" ]; then + echo " + Rule $name=$val" + fi +done +IFS="$OIFS" + +# consistency checks for shared object support +some_shares=0 +OIFS="$IFS" +IFS=':' +for module in $modules; do + eval "share=\$shared_$module" + if [ "x$share" = "xyes" ]; then + some_shares=1 + fi +done +IFS="$OIFS" +if [ "x$some_shares" = "x1" ]; then + if [ "x$module_so" = "xno" ]; then + module_so=yes + if [ "x$quiet" = "xno" ]; then + echo " + enabling mod_so for DSO support" + fi + fi +fi +if [ "x$shared_so" = "xyes" ]; then + shared_so=no + echo "configure:Error: Module mod_so cannot be made a DSO itself" 1>&2 + exit 1 +fi + +# module permutation support +if [ "x$permute" != "x" ]; then + sed -e '/## mod_mmap_static/,$d' $tplconf + OIFS="$IFS" + IFS=' +' + for line in `cat src/Configuration.tmpl $addconf | egrep '^[# ]*(Add|Shared)Module'`; do + name=`echo "$line" |\ + sed -e 's%^.*/\(.*\)$%\1%' \ + -e 's/\.[oa]$//' \ + -e 's/\.module$//' \ + -e 's/^mod_//' \ + -e 's/^lib//'` + echo "${name}:${line}" + done |\ + $AWK -F: ' + BEGIN { + n = 0; + } + { + module_pos[$1] = n; + module_list[n] = $1; + module_line[$1] = $2; + n++; + } + END { + pn = split(permute, perm, ","); + for (p = 1; p <= pn; p++) { + split(perm[p], m, ":") + m1 = m[1]; + m2 = m[2]; + if (m1 == "BEGIN") { + for (i = module_pos[m2]-1; i >= 0; i--) { + n1 = module_list[i]; + n2 = module_list[i+1]; + module_list[i] = n2; + module_list[i+1] = n1; + module_pos[n1] = i+1; + module_pos[n2] = i; + } + } + else if (m2 == "END") { + for (i = module_pos[m1]; i < n-1; i++) { + n1 = module_list[i]; + n2 = module_list[i+1]; + module_list[i] = n2; + module_list[i+1] = n1; + module_pos[n1] = i+1; + module_pos[n2] = i; + } + } + else { + p1 = module_pos[m1]; + p2 = module_pos[m2]; + n1 = module_list[p1]; + n2 = module_list[p2]; + module_list[p1] = n2; + module_list[p2] = n1; + module_pos[m1] = p2; + module_pos[m2] = p1; + } + } + for (i = 0; i < n; i++) { + name = module_list[i]; + printf("%s\n", module_line[name]); + } + } + ' "permute=$permute" >>$tplconf + IFS="$OIFS" +else + cat $src/Configuration.tmpl $addconf >$tplconf +fi + +# generate module directives +# (paths are modules/foo/mod_bar.ext and modules/foo/libbar.ext) +OIFS="$IFS" +IFS=':' +for module in $modules; do + eval "add=\$module_$module" + if [ "x$add" = "xyes" ]; then + echo $SEO "s%^.*\\(AddModule.*mod_$module\\..*\\)%\\1%g" >>$sedsubst + echo $SEO "s%^.*\\(AddModule.*lib$module\\..*\\)%\\1%g" >>$sedsubst + echo $SEO "s%^.*\\(SharedModule.*mod_$module\\..*\\)%\\1%g" >>$sedsubst + echo $SEO "s%^.*\\(SharedModule.*lib$module\\..*\\)%\\1%g" >>$sedsubst + m="yes" + else + echo $SEO "s%^.*\\(AddModule.*mod_$module\\..*\\)%# \\1%g" >>$sedsubst + echo $SEO "s%^.*\\(AddModule.*lib$module\\..*\\)%# \\1%g" >>$sedsubst + echo $SEO "s%^.*\\(SharedModule.*mod_$module\\..*\\)%# \\1%g" >>$sedsubst + echo $SEO "s%^.*\\(SharedModule.*lib$module\\..*\\)%# \\1%g" >>$sedsubst + m=no + fi + eval "share=\$shared_$module" + if [ "x$share" = "xyes" ]; then + echo $SEO "s%^\\(.*\\)AddModule\\(.*mod_$module\\.\\)[oam].*\\(.*\\)%\\1SharedModule\\2so\\3%g" >>$sedsubst + echo $SEO "s%^\\(.*\\)AddModule\\(.*lib$module\\.\\)[oam].*\\(.*\\)%\\1SharedModule\\2so\\3%g" >>$sedsubst + m="$m [shared]" + fi + if [ "x$verbose" = "xyes" ]; then + echo " + Module $module: $m" + fi +done +IFS="$OIFS" + +# 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" +case $PLATFORM in + *OS/2* ) + echo $SEO "s%/mod_\\(.\\{1,8\\}\\).*\\.so%/\\1\\.dll%" >>$sedsubst + echo $SEO "s%/\\(lib.*\\)\\.so$%/\\1.dll%" >>$sedsubst + ;; +esac + +# split sedsubst into chunks of 50 commands +# to workaround limits in braindead seds +files=`$AWK <$sedsubst ' + BEGIN { line=0; cnt=0; } + { + if (line % 50 == 0) { + file = sedsubst "." cnt; + printf("%s\n", file); + cnt++; + } + line++; + print $0 >file; + } +' "sedsubst=$sedsubst"` +OIFS="$IFS" +IFS="$DIFS" +substcmd="" +for file in $files; do + substcmd="${substcmd} sed -f $file |" +done +substcmd="${substcmd} cat" +IFS="$OIFS" + +# and finally translate the config template +# according to our defined configuration +eval "cat $tplconf | $substcmd >$src/Configuration.apaci" + +# cleanup +rm -f $sedsubst $sedsubst.[0-9] 2>/dev/null +rm -f $addconf 2>/dev/null +rm -f $tplconf 2>/dev/null + +## +## create all other Makefiles by running the proprietary +## $src/Configure script with our custom Configuration.apaci file +## +if [ "x$verbose" = "xyes" ]; then + vflag="-v"; +fi +if [ "x$quiet" = "xyes" ]; then + (cd $src; ./Configure ${vflag} -file Configuration.apaci >/dev/null); +else + (cd $src; ./Configure ${vflag} -file Configuration.apaci |\ + sed -e '/^Using config file:.*/d' \ + -e "s:Makefile in :Makefile in $src\\/:" \ + -e "s:Makefile\$:Makefile in $src:") +fi + +## +## final hints +## +if [ "x$quiet" = "xno" ]; then + if [ "x$shadow" != "x" ]; then + echo "Hint: You now have to build inside $shadow." + echo "This can be done either by running the canonical commands" + echo " \$ cd $shadow" + echo " \$ make" + echo " \$ make install" + echo "or by running this alternative commands" + echo " \$ make -f $shadow/Makefile" + echo " \$ make -f $shadow/Makefile install" + fi +fi + diff --git a/APACHE_1_3_12/htdocs/apache_pb.gif b/APACHE_1_3_12/htdocs/apache_pb.gif new file mode 100644 index 0000000000000000000000000000000000000000..3a1c139fc4247ec7e770fdaab961fb3692c953fb GIT binary patch literal 2326 zcmeH``#aS60)Ri?F~*GRoWb@r$c#H_jN6u#)66_>GY!UILM{ophO`}&oUt=FmBNTY z$`ICVA7j^+h#i;OQDc-ga!qS+8Gc0FW4f z)Bt1yAj_Q32!U{ zRIo-qQptb-t7{uBm(~px;>}n!KArWR1^>`Cf~is&A3~v0s8aF}M#nn9GGt0d7v`yb z*>S>eMWL(I627?MNllQ7BkqHq)M=1k z=&Ky&zXVh2hPE6DHG1$Mj#+!@W<|fAeonA2iB#Un#%N(&&W1dtI~9BfQ#)e2X=lF^XcGT}q=AoZ{H^5&_C+Pv zN&hQZTYONvvH2qVcG~jIh^yqZXMG0jauI~J<^%?yjPC{pb>Ylqd7Qgl5*ph^Ulf=T ztUu|ceZK)dM=IDKg~q~CZoH&Cb~-~Z=;&lvYG{6Kc>2z^;Sv327g?kssFZ=dw}0cH zdw$mEtN!A<`J8^&z3 zt~SwiD6S8)Rjrr!Kx<)&vBl1-$xbOvcBi~nxrDC!TBPace;L%k*DDqrZ4t4XvN(& zu%4H=wkn0>)>bWw*7qy^XgxfL8hEr{3=!aT@x^9eDj^ytk&Chl$kO(lBLUN|dQ6Gs zqR_gQC$$$-23%rt``_I(>C3A7dOXT9Z$frk_k~-Ys+P;@AA_2Pg%%8=^ZRrL+?~|f zW&~d`K5oo!G0s}dw|gtsI8gBY`D(2K(S?RiMa{{iIhO(d)G0SJjuwocN&dl=)Ns$! zkAoL^`msv}wXFIo9^Egsd~xDITuw=a{)ty}PeNiaZ{?=q1Ff-;&+#A?LvlJm+3a2z z0EU`idSaEFK|F|qEq^5hpn?C2d=DQ+H3YkO^OBqUex<5bLo z9(N*aTe0*iA?|UPIVvKLCc?9Ag1I16-HvOfbsA#dH4-dk3 zhnz>*3E(FdLU+yVpuPUsliM=aeNjZUS*@XX3Z53T6iR8-2uO=XFwVs0@AhefEv8q zeI*^7gje{cZVN8?oK%ZT=2#U=<_Ih7M^R~)Ja%@QBEHt-Nj+won-qIvXTfK$!wnkr z2MQ*#TaAN%Ohqz*uQYER7$<|Jgd}A|ZL~mb$%8Fh^ z{1s=ft;T@}n?u#1Sd8|0dAq@XlaA<)Sy)vu-xZB|?3vPJ`3#PxQkI=}-aLquKdtW{ zRsg5o;PBjI;EgPh^zTEWZ?enGho=a|_a2#rB5> + + + Pàgina de prova de l'instal·lació d'Apache + + + +

+ Funciona ! El servidor web Apache està instal·lat + en aquest lloc  ! +

+

+ Si veu aquesta pàgina, es que els propietaris d'aquest domini + acaben d'instal·lar satisfactòriament el + servidor web Apache. + Ara han d'afegir contingut en aquest directori i substituir aquesta pàgina, + o bè dirigir aquest servidor cap al contingut real. +

+
+
+ Si està veien aquesta pàgina i no es la que esperava, posis en + contacte amb + l'administrador web d'aquest lloc. + (Provi d'enviar un correu electrònic a <Webmaster@domain>.) + Encara que aquest lloc està utilitzant el programari Apache, es gairebé segur + que no tè res a veure amb el Grup Apache, per tant + no enviï cap correu electrònic als autors d'Apache referent a aquest lloc o al seu contingut. + Si es que ho fa, el seu missatge serà ignorat. +
+
+

+ La + documentació + d'Apache ha estat inclosa en aquesta distribució. +

+

+ L'administrador de web pot utilitzar lliurement la imatge d'aquí sota + en el servidor web equipat amb el programari Apache. + Gràcies per utilitzar Apache ! +

+
+ +
+ + diff --git a/APACHE_1_3_12/htdocs/index.html.cz b/APACHE_1_3_12/htdocs/index.html.cz new file mode 100644 index 0000000000..4cc98cbd1c --- /dev/null +++ b/APACHE_1_3_12/htdocs/index.html.cz @@ -0,0 +1,51 @@ + + + + + Testovací stránka instalace web serveru Apache + + + +

+ Funguje to! Na tomto serveru bì¾í Apache! +

+

+ Pokud vidíte tuto zprávu, správce tohoto poèítaèe právì úspì¹nì + nainstaloval Apache web server. + Teï je¹tì musí doplnit obsah a nahradit tuto standardní uvítací + stránku, nebo pøesmìrovat server na skuteènou domovskou stránku. +

+
+
+ Pokud vidíte tuto zprávu místo oèekávané domovské stránky, + kontaktujte, prosím, správce pøíslu¹ného web + serveru. (Zkuste poslat e-mail na adresu + <Webmaster@domain>.) + Pøesto¾e tento server pou¾ívá program Apache, témìø jistì nemá nic + spoleèného s Apache Group, proto prosím neposílejte e-maily o tomto + serveru nebo jeho obsahu autorùm Apache. Pokud to udìláte, budeme + va¹e zprávy ignorovat. +
+
+

+ Zde najdete + dokumentaci + Apache (anglicky) obsa¾enou v této distribuci. +

+

+ Následující logo mù¾e být pou¾ito bez omezení na web serveru s + programem Apache. Dìkujeme za pou¾ití Apache! +

+
+ +
+ + diff --git a/APACHE_1_3_12/htdocs/index.html.de b/APACHE_1_3_12/htdocs/index.html.de new file mode 100644 index 0000000000..a5420e933a --- /dev/null +++ b/APACHE_1_3_12/htdocs/index.html.de @@ -0,0 +1,61 @@ + + + + Testseite fuer die Apache-Installation auf dieser Web Site + + + + +

+ Es klappt! Der Apache Web-Server ist auf dieser Web-Site installiert! +

+

+ Wenn Sie diese Seite sehen, dann bedeutet das, dass die + Eigentümer dieser Domäne soeben einen neuen + Apache Web-Server + erfolgreich installiert haben. Jetzt muss noch der + richtige Web-Inhalt zugefügt und diese Platzhalter-Seite + ersetzt werden (oder der Web-Server für den Zugriff auf den + richtigen Inhalt umkonfiguriert werden). +

+
+
+ Wenn Sie diese Seite an Stelle einer anderen erwarteten Web-Site + sehen sollten, dann nehmen Sie bitte Kontakt mit dem + Eigentümer dieser Site auf (Versuchen Sie, eine EMail + an <Webmaster@domänenname> + zu senden)!
+

+ Obwohl der Eigentümer dieser Domäne die Apache + Web-Server Software verwendet, hat diese Web-Site ziemlich sicher + keinerlei Verbindung mit der Apache Software Foundation + (die diese Software kostenlos vertreibt). Es besteht also + keinerlei Veranlassung, eine EMail an + die Entwickler der Software zu senden. Sollten Sie das dennoch + tun, wird Ihre Mail stillschweigend + ignoriert. +

+
+

+ Die englische Online-Dokumentation für die + Apache Web-Server Software ist Bestandteil dieser + Software-Distribution. +

+

+ Dem WebMaster dieser Web-Site steht es frei, das + untenstehende "Powered by Apache"-Logo auf einem Apache-basierten + Web-Server zu verwenden.
+ Vielen Dank, dass Sie Apache gewählt haben! +

+
+ Powered by Apache! +
+ + diff --git a/APACHE_1_3_12/htdocs/index.html.dk b/APACHE_1_3_12/htdocs/index.html.dk new file mode 100644 index 0000000000..22b3931aac --- /dev/null +++ b/APACHE_1_3_12/htdocs/index.html.dk @@ -0,0 +1,47 @@ + + + + Prøveside for Apache installationen + + + +

+ Det virkede! Apache Webserveren er installeret på denne maskine! +

+

+ Hvis du kan se denne side, så har dem som ejer dette domæne lige + installeret Apache Webserveren. + Du må nu placere web sider i dette directory og fjerne denne side, eller + konfigurere serveren til at anvende et andet directory. +

+
+
+ Hvis du ser denne side istedet for en anden forventet side, kontakt + venligst administratoren for den server du prøver at kontakte. + (Prøv at sende mail til <Webmaster@domain>.) + Apachegruppen har ikke noget at gøre med denne site, så det vil ikke + hjælpe at sende mail to Apache udviklerne angående denne site. +
+
+

+ Apache- + documentationen + er inkluderet med denne distribution. +

+

+ Webmasteren af denne site må gerne bruge den følgende grafik + på en Apache-drevet webserver. Mange tak for at bruge Apache! +

+
+ +
+ + diff --git a/APACHE_1_3_12/htdocs/index.html.ee b/APACHE_1_3_12/htdocs/index.html.ee new file mode 100644 index 0000000000..879c30e381 --- /dev/null +++ b/APACHE_1_3_12/htdocs/index.html.ee @@ -0,0 +1,53 @@ + + + + Apache veebiserveri installatsiooni testlehekülg + + + + +

+ Kujuta pilti, käima läks! Apache veebiserver on installeeritud! +

+

+ Kui Sa näed seda lehekülge, siis selle domeeni omanikud on + edukalt hakkama saanud Apache veebiserveri + installeerimisega. Järgmiseks peaks nad selle lehekülje asendama + misiganes materjaliga, mida nad oma veebisaidis näidata tahavad, + või siis juhatama veebiserverile kätte tegeliku materjali + asukoha. +

+
+
+ Kui Sa ootasid siin leheküljel näha hoopis midagi muud, + siis palun võta ühendust selle veebisaidi + administraatoriga. (Võid näiteks kirjutada aadressil + <Webmaster@domain>.) Kuigi see veebisait + kasutab Apache tarkvara, pole ta peaaegu kindlasti mitte Apache Group'iga + mingil muul moel seotud. Seega, palun ära kirjuta selle saidi + asjus Apache autoritele. Kui sa seda teed, siis sinu kirja + ignoreeritakse. +
+
+

+ Ka Apache + dokumentatsioon + on selles distributsioonis olemas. +

+

+ Kohalik veebmeister võib vabalt kasutada allpool olevat + pilti oma Apache veebiserveril. Aitäh Apachet kasutamast! +

+
+ +
+ + diff --git a/APACHE_1_3_12/htdocs/index.html.en b/APACHE_1_3_12/htdocs/index.html.en new file mode 100644 index 0000000000..73f5eca36c --- /dev/null +++ b/APACHE_1_3_12/htdocs/index.html.en @@ -0,0 +1,38 @@ + + + + Test Page for Apache Installation + + + + + +

+If you can see this, it means that the installation of the Apache web server software on this system was successful. You may now add content to this directory and replace this page. + +


+ +

Seeing this instead of the website you expected?

+ +

+This page is here because the site administrator has changed the configuration of this web server. +Please contact the person responsible for maintaining this server with questions. The Apache Software Foundation, which wrote the web server software this site administrator is using, has nothing to do with maintaining this site and cannot help resolve configuration issues. + +


+ + +

+The Apache documentation has been included with this distribution. + +

+You are free to use the image below on an Apache-powered web server. Thanks for using Apache! + +

+ + diff --git a/APACHE_1_3_12/htdocs/index.html.es b/APACHE_1_3_12/htdocs/index.html.es new file mode 100644 index 0000000000..b5f81070b7 --- /dev/null +++ b/APACHE_1_3_12/htdocs/index.html.es @@ -0,0 +1,51 @@ + + + + Pagína para probar la instalación de Apache + + + +

+ ¡Funcionó! ¡El Servidor de Red Apache ha sido instalado en ese sitio! +

+

+ Si usted puede ver esta pagína, entonces los dueños de esta + maquína han instalado el Servidor de + Red Apache con exíto. Ahora deben añadir contenido a este directorio + y reemplazar esta pagína, ó apuntar este servidor al contenido real. +

+
+
+ Si usted esta leyendo esta pagína y no es lo que esperaba, por favor + contacte el administrador de este sitio. + (Trate de enviar correo electrónico a <Webmaster@domain>.) + Aunque este sitio esta utilizando el programa Apache es casi seguro + que no tiene ninguna conexión con el Apache Group, por eso favor de + no enviar correo sobre este sitio o su contenido a los autores de + Apache. Si lo hace, su mensaje sera + ignorado. +
+
+

+ La + documentación + de Apache ha sido incluida en esta distribución. +

+

+ El administrador del sitio esta invitado a usar la siguiente + imagen para indicar que su sitio es servido por Apache. + ¡Gracias por usar Apache! +

+
+ +
+ + diff --git a/APACHE_1_3_12/htdocs/index.html.fr b/APACHE_1_3_12/htdocs/index.html.fr new file mode 100644 index 0000000000..7ffa0979d6 --- /dev/null +++ b/APACHE_1_3_12/htdocs/index.html.fr @@ -0,0 +1,53 @@ + + + + Page de test de l'installation d'Apache + + + +

+ Ça fonctionne ! Le serveur web Apache est installé sur + ce site ! +

+

+ Si vous lisez cette page, c'est que les propriétaires de ce domaine + viennent d'installer le + serveur web Apache + avec succès. Ils doivent maintenant ajouter du contenu à ce + répertoire et remplacer cette page, ou bien faire pointer le serveur + vers l'endroit où se trouve le contenu réel du site. +

+
+
+ Si vous voyez cette page au lieu du site attendu, veuillez contacter + l'administrateur du site concerné. + (Essayez d'envoyer un email à + <Webmaster@domaine>.) + Bien que ce site utilise le logiciel Apache, il n'a certainement + rien à voir avec le Groupe Apache, par conséquent + veuillez ne pas envoyer d'email aux + auteurs d'Apache concernant ce site ou son contenu. Si vous le faites, + votre message sera ignoré. +
+
+

+ La + documentation + Apache est incluse dans cette distribution. +

+

+ Le webmaster de ce site peut librement utiliser l'image ci-dessous + sur un site web utilisant le logiciel Apache. Merci d'avoir choisi + Apache ! +

+
+ +
+ + diff --git a/APACHE_1_3_12/htdocs/index.html.it b/APACHE_1_3_12/htdocs/index.html.it new file mode 100644 index 0000000000..ab32d04a50 --- /dev/null +++ b/APACHE_1_3_12/htdocs/index.html.it @@ -0,0 +1,38 @@ + + + + + Pagina di prova dell'installazione di un sito Web con Apache + + + + +
+

+Funziona! Il Server Web Apache e' stato installato su questo sito Web!

+Se riuscite a vedere questa pagina, allora vuol dire che coloro che gestiscono +questo dominio hanno appena installato il software Web Server +Apache correttamente. Ora e' necessario aggiungere il vostro materiale +in questo direttorio e sostituire questa pagina di prova, oppure configurare +il server per far riferimento al vostro materiale se collocato altrove. +

+


+
Se state vedendo questa pagina invece del sito che pensavate, +vi preghiamo di contattare l'amministratore del sito in questione. +(Provate ad inviare un email a <Webmaster@domain>.)  +Nonostante questo sito stia utilizzando il software Apache, questo non +vi garantisce nessun tipo di contatto diretto al Gruppo Apache, quindi +vi preghiamo di non inviare email riguardanti questo sito o al materiale +in esso contenuto agli autori di Apache. Ogni messaggio del genere verra' +ignorato.
+ +
+
La documentazione relativa di Apache +e' inclusa nella distribuzione. +

Il Webmaster di questo sito e' libero di utilizzare l'immagine qui sotto +su qualsiasi Web server potenziato con Apache. Grazie per aver scelto Apache! +

+

+ + + diff --git a/APACHE_1_3_12/htdocs/index.html.ja.jis b/APACHE_1_3_12/htdocs/index.html.ja.jis new file mode 100644 index 0000000000..0a4e545261 --- /dev/null +++ b/APACHE_1_3_12/htdocs/index.html.ja.jis @@ -0,0 +1,42 @@ + + + + + Apache $B%$%s%9%H!<%k;~$N%F%9%H%Z!<%8(B + + + + + +

+$B$b$7$3$N%Z!<%8$,FI$a$?$N$G$"$l$P!"(BApache $B%&%'%V%5!<%P(B$B$N%$%s%9%H!<%k$,$3$N7W;;5!$GL5;v$K=*N;$7$?$3$H$r0UL#$7$^$9!#$"$J$?$O!"$3$N%G%#%l%/%H%j$KJ8=q$r2C$($?$j!"$3$N%Z!<%8$rCV$-$+$($k$3$H$,$G$-$^$9!#(B +

+
+ +

$B$"$J$?$NM=A[$KH?$7$F!"$3$N%Z!<%8$,8+$($F$$$k$G$7$g$&$+(B?

+ +

+$B$3$N%Z!<%8$O!"%5%$%H4IM}$B$3$N%5!<%P$r4IM}$9$k@UG$$r;}$C$F$$$kJ}$KO"Mm$r$H$C$F(B$B$/$@$5$$!#$3$N%5%$%H4IM} +


+ + +

+Apache $B$K4X$9$k(B$BJ8=q(B $B$O!"$3$N(B web $B%5!<%PG[I[J*$NCf$K4^$^$l$F$$$^$9!#(B +

+

+$B0J2<$N2hA|$O!"(BApache $B$rMxMQ$7$F$$$k(B web $B%5!<%P$G<+M3$K;H$&$3$H$,$G$-$^$9!#(BApache $B$r$4MxMQ$$$?$@$-!"$"$j$,$H$&$4$6$$$^$9(B! +

+
+ +
+ + diff --git a/APACHE_1_3_12/htdocs/index.html.lu b/APACHE_1_3_12/htdocs/index.html.lu new file mode 100644 index 0000000000..f068a83e77 --- /dev/null +++ b/APACHE_1_3_12/htdocs/index.html.lu @@ -0,0 +1,37 @@ + + + + + + Test Page for Apache Installation on Web Site + + + + +
+

+Et huet geklappt! Den Apache Web Server as op dëser 'Web Site' installeiert!

+Wann Dir die heiten Sait gesit, dann hun d'Proprietairen vun dëser 'domain' +elo just d'Apache Web server software +mat succés installeiert. Sie mussen allerdengs nach des Decksait +remplaceieren oder awer de Server op eng aner Sait mat dem richtigen contenu +em-dirigeieren. +
+
+
Wann Dir die heiten Sait anstell vun der site die Dir erwârt +hut gesitt, da contacteiert wannechglift den administrator vun dem betraffener +site. (Versicht én email no <Webmaster@domain> ze +schecken.) Obwuel den heiten site Apache software benotzt, as et +ball secher datt keng Verbindung mat der Apache Group existeiert, also scheckt +wannechglift keng email iwert desen site oder sein contenu zu den Apache +Autoren. Falls Dir dëst awer macht, get ären message  ignoreiert.
+ +
+

D'Apache documentation ass dëser Ausgab +beigefücht. +

Dem Webmaster vun dem heitenen site steht et zou dest Bild ob engem +Apache-powered Web server ze presenteieren. Merci dat Dir Apache benotzt! +

+ + + diff --git a/APACHE_1_3_12/htdocs/index.html.nl b/APACHE_1_3_12/htdocs/index.html.nl new file mode 100644 index 0000000000..b00747cd2a --- /dev/null +++ b/APACHE_1_3_12/htdocs/index.html.nl @@ -0,0 +1,54 @@ + + + + Test Pagina voor de Apache Installatie op deze Web Site + + + + +

+ Alles Werkt! De Apache Web Server is geinstalleerd op deze Web Site +

+

+ Mocht u deze pagina zien, dan betekent dat, dat de eigenaren van dit + domein zojuist een nieuwe Apache Web + Server hebben geinstalleerd. Nu moet men nog de echte inhoud gaan + toevoegen, en moet men deze pagina gaan vervangen door de echte web + site. +

+
+
+ Mocht u deze pagina zien, in plaats van de pagina of web site die u + verwachtte, neem dan contact op met de beheerder van + deze site. Bijvoorbeeld door een berichtje te sturen naar + <Webmaster@dit-domain>. +

+ Alhoewel deze web site gebruik maakt van de Apache Software is er + verder geen enkele relatie tussen de beheerders van deze web site en + de Apache Groep (die de web software geschreven heeft). Het heeft dus + absoluut + geen zin de web software auteurs een emailtje te sturen. Mocht u dat + toch doen, dan wordt uw bericht gewoon genegeerd. +

+
+

+ De + handleiding voor de apache web + server software maakt deel uit van deze distributie. +

+

+ Als beheerder of webmaster is het u toegestaan het onderstaande + plaatje vrijelijk te gebruiken op uw 'Apache Powered' web site. Bedankt + voor het kiezen voor, en gebruiken van, Apache! +

+
+ Klein 'Powered by Apache' Logotje +
+ + diff --git a/APACHE_1_3_12/htdocs/index.html.po.iso-pl b/APACHE_1_3_12/htdocs/index.html.po.iso-pl new file mode 100644 index 0000000000..18275b7216 --- /dev/null +++ b/APACHE_1_3_12/htdocs/index.html.po.iso-pl @@ -0,0 +1,54 @@ + + + + Strona kontrolna dla instalacji Apache na tej stronie + + + + + +

+ Uda³o siê! Serwer Apache jest zainstalowany na tej stronie! +

+

+ Je¶li widzisz t± stronê to znaczy ¿e w³a¶æiciel tej domeny + w³a¶nie z sukcesem zainstalowa³ serwera + Apache. + Teraz on musi t± strone zamienic na to na co przeznaczy³ domene + (albo nastawiæ serwer tak, ze bêdzie pokazywaæ to co powinien). +

+
+
+ Je¶li ta strona nie jest to, czego oczekiwa³e¶, to + skontaktuj siê z w³a¶æicielem tej strony (spróbuj wys³ac + mail do <webmaster@domena>)!
+

+ Chocia¿ w³a¶æiciel tej domeny u¿ywa serwera Apache, + strona ta nie ma nic wspólnego z Apache Software Foundation + (ktora rozdaje ten program za darmo). Dla tego + nie pisz email-ów do webmastera tej strony + je¶li masz pytania techniczne dotyczaj±ce serwera Apache. Mia³bys jednak + napisaæ mimo wszystko tak± mail, bêdzie ona ignorowana. +

+
+

+ Do tej dystrybucji nale¿y angielska + dokumentacja. +

+

+ Webmaster tej strony mo¿e, ale nie musi u¿ywac obrazek + "Powered by Apache" na tym serwerze. +
+ Dziêkujemy ze zecydowa³es siê na Apache! +

+
+ Powered by Apache! +
+ + diff --git a/APACHE_1_3_12/htdocs/index.html.pt b/APACHE_1_3_12/htdocs/index.html.pt new file mode 100644 index 0000000000..4e2645f5d8 --- /dev/null +++ b/APACHE_1_3_12/htdocs/index.html.pt @@ -0,0 +1,42 @@ + + + + Página de teste da instalação do Apache Web Server + + + + + + +

Se está a ver esta página significa que a instalação + do Apache Web Server foi efectuada + com sucesso. Pode agora adicionar conteúdo a esta directoria e substituir + esta página. +


+ +

Está a ver esta página em vez do website que + esperava?

+ +

Esta página está neste momento activa porque o administrador + deste site alterou a configuração do web server. Por favor contacte + a pessoa responsável pela manutenção deste servidor. + A Fundação Apache Software (Apache Software Foundation), apesar + de ter produzido o web server que o administrador deste site está a usar, + não tem qualquer tipo de responsabilidade pela manutenção + deste nem pode ajudar a resolver problemas de configuração. +


+ + +

A documentação foi incluída + juntamente com esta distribuição. +

A imagem abaixo pode ser usada livremente em qualquer site presente num servidor + com o Apache Web Server instalado. Obrigado por usar o Apache Web Server! +

+ + diff --git a/APACHE_1_3_12/htdocs/index.html.pt-br b/APACHE_1_3_12/htdocs/index.html.pt-br new file mode 100755 index 0000000000..72428d5a2a --- /dev/null +++ b/APACHE_1_3_12/htdocs/index.html.pt-br @@ -0,0 +1,55 @@ + + + + Pagina teste para a instalacao do Apache no Web Site + + + + +

+ Funcionou! O Apache Web Server esta instalado neste Web Site! +

+

+ Se conseguir ver esta pagina, entao as pessoas que possuem este + dominio acabaram + de instalar o software Apache Web + server + com sucesso. Agora tem de adicionar o conteudo a esta directoria + e substituir esta pagina "placeholder", ou apontar o servidor para o + seu conteudo real. +

+
+
+ Se esta a ver esta pagina em vez do site que esperava, por favor + contacte o administrador do site envolvido. + (Tente enviar um e-mail para + <Webmaster@domain>.) + Apesar de neste site estar a + correr o software Apache e quase certo que nao tem + outra ligacao com o Grupo Apache, por isso por favor nao envie + e-mails acerca deste + site ou do seu conteudo para os autores do Apache. Se o fizer, a + sua mensagem vai ser + ignorada. +
+
+

+ O Apache documentation + foi incluido com esta distribuicao. +

+

+ O Webmaster deste site e livre para utilizar a imagem abaixo num + Web server instalado com o Apache. Obrigado por utilizar o Apache! +

+
+ +
+ + diff --git a/APACHE_1_3_12/htdocs/index.html.se b/APACHE_1_3_12/htdocs/index.html.se new file mode 100644 index 0000000000..d9fcb2edb1 --- /dev/null +++ b/APACHE_1_3_12/htdocs/index.html.se @@ -0,0 +1,43 @@ + + + + Testsida för Apache-installationen + + + +

+ Det fungerade! Apache är installerad på denna maskin! +

+

+ Om du kan se denna sida så har ägaren till denna maskin installerat + webbserverprogramvaran Apache.
+ Denne måste nu placera webbsidor i detta bibliotek och ändra på denna sida, eller + peka servern mot ett annat bibliotek. +

+
+
+ Om du förväntat dig att se något helt annat här än denna sida, kontakta + vänligen administratören för den webbserver du försöker komma i kontakt med. + (Försök att skicka ett brev till <webmaster@domain>.) + Apache Software Foundation har inget med denna webbplats att göra, så det är ingen idé + att skicka mail till författarna av Apache rörande denna webbplats. +
+
+

+ Apache-dokumentationen är inkluderad i denna distribution. +

+

+ Administratören av denna webbplats får gärna använda följande bild till en webbplats som använder Apache.
+ Tack för att ni använder Apache! +

+
+ +
+ + diff --git a/APACHE_1_3_12/htdocs/manual/LICENSE b/APACHE_1_3_12/htdocs/manual/LICENSE new file mode 100644 index 0000000000..6ac6538b3c --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/LICENSE @@ -0,0 +1,59 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + + + diff --git a/APACHE_1_3_12/htdocs/manual/bind.html b/APACHE_1_3_12/htdocs/manual/bind.html new file mode 100644 index 0000000000..75bacbb253 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/bind.html @@ -0,0 +1,135 @@ + + +Setting which addresses and ports Apache uses + + + + + +

Setting which addresses and ports Apache uses

+ +
+ +When Apache starts, it connects to some port and address on the +local machine and waits for incoming requests. By default, it +listens to all addresses on the machine, and to the port +as specified by the Port directive in the server configuration. +However, it can be told to listen to more the one port, or to listen +to only selected addresses, or a combination. This is often combined +with the Virtual Host feature which determines how Apache +responds to different IP addresses, hostnames and ports.

+ +There are two directives used to restrict or specify which addresses +and ports Apache listens to. + +

    +
  • BindAddress is used to restrict the server to + listening to + a single address, and can be used to permit multiple Apache servers + on the same machine listening to different IP addresses. +
  • Listen can be used to make a single Apache server + listen + to more than one address and/or port. +
+ +

BindAddress

+Syntax: BindAddress [ * | IP-address + | hostname ]
+Default: BindAddress *
+Context: server config
+Status: Core

+ +Makes the server listen to just the specified address. If the argument +is *, the server listens to all addresses. The port listened to +is set with the Port directive. Only one BindAddress +should be used. + +

Listen

+Syntax: Listen [ port | IP-address:port ]
+Default: none
+Context: server config
+Status: Core

+ +Listen can be used instead of BindAddress and +Port. It tells the server to accept incoming requests on the +specified port or address-and-port combination. If the first format is +used, with a port number only, the server listens to the given port on +all interfaces, instead of the port given by the Port +directive. If an IP address is given as well as a port, the server +will listen on the given port and interface.

Multiple Listen +directives may be used to specify a number of addresses and ports to +listen to. The server will respond to requests from any of the listed +addresses and ports.

+ +For example, to make the server accept connections on both port +80 and port 8000, use: +

+   Listen 80
+   Listen 8000
+
+ +To make the server accept connections on two specified +interfaces and port numbers, use +
+   Listen 192.170.2.1:80
+   Listen 192.170.2.5:8000
+
+ +

How this works with Virtual Hosts

+ +BindAddress and Listen do not implement Virtual Hosts. They tell the +main server what addresses and ports to listen to. If no +<VirtualHost> directives are used, the server will behave the +same for all accepted requests. However, <VirtualHost> can be +used to specify a different behavior for one or more of the addresses +and ports. To implement a VirtualHost, the server must first be told +to listen to the address and port to be used. Then a +<VirtualHost> section should be created for a specified address +and port to set the behavior of this virtual host. Note that if the +<VirtualHost> is set for an address and port that the server is +not listening to, it cannot be accessed. + +

See also

+ +See also the documentation on +Virtual Hosts, +BindAddress directive, +Port directive, +DNS Issues +and +<VirtualHost> section. + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/cgi_path.html b/APACHE_1_3_12/htdocs/manual/cgi_path.html new file mode 100644 index 0000000000..2b7bd963b1 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/cgi_path.html @@ -0,0 +1,93 @@ + + +PATH_INFO Changes in the CGI Environment + + + + + +

PATH_INFO Changes in the CGI Environment

+ +
+ +

Overview

+ +

As implemented in Apache 1.1.1 and earlier versions, the method +Apache used to create PATH_INFO in the CGI environment was +counterintuitive, and could result in crashes in certain cases. In +Apache 1.2 and beyond, this behavior has changed. Although this +results in some compatibility problems with certain legacy CGI +applications, the Apache 1.2 behavior is still compatible with the +CGI/1.1 specification, and CGI scripts can be easily modified (see below). + +

The Problem

+ +

Apache 1.1.1 and earlier implemented the PATH_INFO and SCRIPT_NAME +environment variables by looking at the filename, not the URL. While +this resulted in the correct values in many cases, when the filesystem +path was overloaded to contain path information, it could result in +errant behavior. For example, if the following appeared in a config +file: +

+     Alias /cgi-ralph /usr/local/httpd/cgi-bin/user.cgi/ralph
+
+

In this case, user.cgi is the CGI script, the "/ralph" +is information to be passed onto the CGI. If this configuration was in +place, and a request came for "/cgi-ralph/script/", the +code would set PATH_INFO to "/ralph/script", and +SCRIPT_NAME to "/cgi-". Obviously, the latter is +incorrect. In certain cases, this could even cause the server to +crash.

+ +

The Solution

+ +

Apache 1.2 and later now determine SCRIPT_NAME and PATH_INFO by +looking directly at the URL, and determining how much of the URL is +client-modifiable, and setting PATH_INFO to it. To use the above +example, PATH_INFO would be set to "/script", and +SCRIPT_NAME to "/cgi-ralph". This makes sense and results +in no server behavior problems. It also permits the script to be +guaranteed that +"http://$SERVER_NAME:$SERVER_PORT$SCRIPT_NAME$PATH_INFO" +will always be an accessible URL that points to the current script, +something which was not necessarily true with previous versions of +Apache. + +

However, the "/ralph" +information from the Alias directive is lost. This is +unfortunate, but we feel that using the filesystem to pass along this +sort of information is not a recommended method, and a script making +use of it "deserves" not to work. Apache 1.2b3 and later, however, do +provide a workaround. + +

Compatibility with Previous Servers

+ +

It may be necessary for a script that was designed for earlier +versions of Apache or other servers to need the information that the +old PATH_INFO variable provided. For this purpose, Apache 1.2 (1.2b3 +and later) sets an additional variable, FILEPATH_INFO. This +environment variable contains the value that PATH_INFO would have had +with Apache 1.1.1.

+ +

A script that wishes to work with both Apache 1.2 and earlier +versions can simply test for the existence of FILEPATH_INFO, and use +it if available. Otherwise, it can use PATH_INFO. For example, in +Perl, one might use: +

+    $path_info = $ENV{'FILEPATH_INFO'} || $ENV{'PATH_INFO'};
+
+ +

By doing this, a script can work with all servers supporting the +CGI/1.1 specification, including all versions of Apache.

+ + + + + diff --git a/APACHE_1_3_12/htdocs/manual/content-negotiation.html b/APACHE_1_3_12/htdocs/manual/content-negotiation.html new file mode 100644 index 0000000000..7bfaee5afa --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/content-negotiation.html @@ -0,0 +1,588 @@ + + + +Apache Content Negotiation + + + + + +

Content Negotiation

+ +

+Apache's support for content negotiation has been updated to meet the +HTTP/1.1 specification. It can choose the best representation of a +resource based on the browser-supplied preferences for media type, +languages, character set and encoding. It is also implements a +couple of features to give more intelligent handling of requests from +browsers which send incomplete negotiation information.

+ +Content negotiation is provided by the +mod_negotiation module, +which is compiled in by default. + +


+ +

About Content Negotiation

+ +

+A resource may be available in several different representations. For +example, it might be available in different languages or different +media types, or a combination. One way of selecting the most +appropriate choice is to give the user an index page, and let them +select. However it is often possible for the server to choose +automatically. This works because browsers can send as part of each +request information about what representations they prefer. For +example, a browser could indicate that it would like to see +information in French, if possible, else English will do. Browsers +indicate their preferences by headers in the request. To request only +French representations, the browser would send + +

+  Accept-Language: fr
+
+ +

+Note that this preference will only be applied when there is a choice +of representations and they vary by language. +

+ +As an example of a more complex request, this browser has been +configured to accept French and English, but prefer French, and to +accept various media types, preferring HTML over plain text or other +text types, and preferring GIF or JPEG over other media types, but also +allowing any other media type as a last resort: + +

+  Accept-Language: fr; q=1.0, en; q=0.5
+  Accept: text/html; q=1.0, text/*; q=0.8, image/gif; q=0.6,
+        image/jpeg; q=0.6, image/*; q=0.5, */*; q=0.1
+
+ +Apache 1.2 supports 'server driven' content negotiation, as defined in +the HTTP/1.1 specification. It fully supports the Accept, +Accept-Language, Accept-Charset and Accept-Encoding request headers. +Apache 1.3.4 also supports 'transparent' content negotiation, which is +an experimental negotiation protocol defined in RFC 2295 and RFC 2296. +It does not offer support for 'feature negotiation' as defined in +these RFCs. +

+ +A resource is a conceptual entity identified by a URI +(RFC 2396). An HTTP server like Apache provides access to +representations of the resource(s) within its namespace, +with each representation in the form of a sequence of bytes with a +defined media type, character set, encoding, etc. Each resource may be +associated with zero, one, or more than one representation +at any given time. If multiple representations are available, +the resource is referred to as negotiable and each of its +representations is termed a variant. The ways in which the +variants for a negotiable resource vary are called the +dimensions of negotiation. + +

Negotiation in Apache

+ +

+In order to negotiate a resource, the server needs to be given +information about each of the variants. This is done in one of two +ways: + +

    +
  • Using a type map (i.e., a *.var file) which + names the files containing the variants explicitly, or +
  • Using a 'MultiViews' search, where the server does an implicit + filename pattern match and chooses from among the results. +
+ +

Using a type-map file

+ +

+A type map is a document which is associated with the handler +named type-map (or, for backwards-compatibility with +older Apache configurations, the mime type +application/x-type-map). Note that to use this feature, +you must have a handler set in the configuration that defines a +file suffix as type-map; this is best done with a + +

+  AddHandler type-map var
+
+ +in the server configuration file. See the comments in the sample config +file for more details.

+ +Type map files have an entry for each available variant; these entries +consist of contiguous HTTP-format header lines. Entries for +different variants are separated by blank lines. Blank lines are +illegal within an entry. It is conventional to begin a map file with +an entry for the combined entity as a whole (although this +is not required, and if present will be ignored). An example +map file is: + +

+  URI: foo
+
+  URI: foo.en.html
+  Content-type: text/html
+  Content-language: en
+
+  URI: foo.fr.de.html
+  Content-type: text/html;charset=iso-8859-2
+  Content-language: fr, de
+
+ +If the variants have different source qualities, that may be indicated +by the "qs" parameter to the media type, as in this picture (available +as jpeg, gif, or ASCII-art): + +
+  URI: foo
+
+  URI: foo.jpeg
+  Content-type: image/jpeg; qs=0.8
+
+  URI: foo.gif
+  Content-type: image/gif; qs=0.5
+
+  URI: foo.txt
+  Content-type: text/plain; qs=0.01
+
+

+ +qs values can vary in the range 0.000 to 1.000. Note that any variant with +a qs value of 0.000 will never be chosen. Variants with no 'qs' +parameter value are given a qs factor of 1.0. The qs parameter indicates +the relative 'quality' of this variant compared to the other available +variants, independent of the client's capabilities. For example, a jpeg +file is usually of higher source quality than an ascii file if it is +attempting to represent a photograph. However, if the resource being +represented is an original ascii art, then an ascii representation would +have a higher source quality than a jpeg representation. A qs value +is therefore specific to a given variant depending on the nature of +the resource it represents. + +

+The full list of headers recognized is: + +

+
URI: +
uri of the file containing the variant (of the given media + type, encoded with the given content encoding). These are + interpreted as URLs relative to the map file; they must be on + the same server (!), and they must refer to files to which the + client would be granted access if they were to be requested + directly. +
Content-Type: +
media type --- charset, level and "qs" parameters may be given. These + are often referred to as MIME types; typical media types are + image/gif, text/plain, or + text/html; level=3. +
Content-Language: +
The languages of the variant, specified as an Internet standard + language tag from RFC 1766 (e.g., en for English, + kr for Korean, etc.). +
Content-Encoding: +
If the file is compressed, or otherwise encoded, rather than + containing the actual raw data, this says how that was done. + Apache only recognizes encodings that are defined by an + AddEncoding directive. + This normally includes the encodings x-compress + for compress'd files, and x-gzip for gzip'd files. + The x- prefix is ignored for encoding comparisons. +
Content-Length: +
The size of the file. Specifying content + lengths in the type-map allows the server to compare file sizes + without checking the actual files. +
Description: +
A human-readable textual description of the variant. If Apache cannot + find any appropriate variant to return, it will return an error + response which lists all available variants instead. Such a variant + list will include the human-readable variant descriptions. +
+ +

Multiviews

+ +

+MultiViews is a per-directory option, meaning it can be set with +an Options directive within a <Directory>, +<Location> or <Files> +section in access.conf, or (if AllowOverride +is properly set) in .htaccess files. Note that +Options All does not set MultiViews; you +have to ask for it by name. + +

+The effect of MultiViews is as follows: if the server +receives a request for /some/dir/foo, if +/some/dir has MultiViews enabled, and +/some/dir/foo does not exist, then the server reads the +directory looking for files named foo.*, and effectively fakes up a +type map which names all those files, assigning them the same media +types and content-encodings it would have if the client had asked for +one of them by name. It then chooses the best match to the client's +requirements. + +

+MultiViews may also apply to searches for the file named by the +DirectoryIndex directive, if the server is trying to +index a directory. If the configuration files specify + +

+  DirectoryIndex index
+
+ +then the server will arbitrate between index.html +and index.html3 if both are present. If neither are +present, and index.cgi is there, the server will run it. + +

+If one of the files found when reading the directive is a CGI script, +it's not obvious what should happen. The code gives that case +special treatment --- if the request was a POST, or a GET with +QUERY_ARGS or PATH_INFO, the script is given an extremely high quality +rating, and generally invoked; otherwise it is given an extremely low +quality rating, which generally causes one of the other views (if any) +to be retrieved. + +

The Negotiation Methods

+ +After Apache has obtained a list of the variants for a given resource, +either from a type-map file or from the filenames in the directory, it +invokes one of two methods to decide on the 'best' variant to +return, if any. It is not necessary to know any of the details of how +negotiation actually takes place in order to use Apache's content +negotiation features. However the rest of this document explains the +methods used for those interested. +

+ +There are two negotiation methods: + +

    + +
  1. Server driven negotiation with the Apache +algorithm is used in the normal case. The Apache algorithm is +explained in more detail below. When this algorithm is used, Apache +can sometimes 'fiddle' the quality factor of a particular dimension to +achieve a better result. The ways Apache can fiddle quality factors is +explained in more detail below. + +
  2. Transparent content negotiation is used when the +browser specifically requests this through the mechanism defined in RFC +2295. This negotiation method gives the browser full control over +deciding on the 'best' variant, the result is therefore dependent on +the specific algorithms used by the browser. As part of the +transparent negotiation process, the browser can ask Apache to run the +'remote variant selection algorithm' defined in RFC 2296. + + +

    Dimensions of Negotiation

    + + + + + + + +
    Dimension +Notes +
    Media Type +Browser indicates preferences with the Accept header field. Each item +can have an associated quality factor. Variant description can also +have a quality factor (the "qs" parameter). +
    Language +Browser indicates preferences with the Accept-Language header field. +Each item can have a quality factor. Variants can be associated with none, one +or more than one language. +
    Encoding +Browser indicates preference with the Accept-Encoding header field. +Each item can have a quality factor. +
    Charset +Browser indicates preference with the Accept-Charset header field. +Each item can have a quality factor. +Variants can indicate a charset as a parameter of the media type. +
    + +

    Apache Negotiation Algorithm

    + +

    +Apache can use the following algorithm to select the 'best' variant +(if any) to return to the browser. This algorithm is not +further configurable. It operates as follows: + +

      +
    1. First, for each dimension of the negotiation, check the appropriate +Accept* header field and assign a quality to each +variant. If the Accept* header for any dimension implies that this +variant is not acceptable, eliminate it. If no variants remain, go +to step 4. + +
    2. Select the 'best' variant by a process of elimination. Each of the +following tests is applied in order. Any variants not selected at each +test are eliminated. After each test, if only one variant remains, +select it as the best match and proceed to step 3. If more than one +variant remains, move on to the next test. + +
        +
      1. Multiply the quality factor from the Accept header with the + quality-of-source factor for this variant's media type, and select + the variants with the highest value. + +
      2. Select the variants with the highest language quality factor. + +
      3. Select the variants with the best language match, using either the + order of languages in the Accept-Language header (if present), or else + else the order of languages in the LanguagePriority + directive (if present). + +
      4. Select the variants with the highest 'level' media parameter + (used to give the version of text/html media types). + +
      5. Select variants with the best charset media parameters, + as given on the Accept-Charset header line. Charset ISO-8859-1 + is acceptable unless explicitly excluded. Variants with a + text/* media type but not explicitly associated + with a particular charset are assumed to be in ISO-8859-1. + +
      6. Select those variants which have associated + charset media parameters that are not ISO-8859-1. + If there are no such variants, select all variants instead. + +
      7. Select the variants with the best encoding. If there are + variants with an encoding that is acceptable to the user-agent, + select only these variants. Otherwise if there is a mix of encoded + and non-encoded variants, select only the unencoded variants. + If either all variants are encoded or all variants are not encoded, + select all variants. + +
      8. Select the variants with the smallest content length. + +
      9. Select the first variant of those remaining. This will be either the + first listed in the type-map file, or when variants are read from + the directory, the one whose file name comes first when sorted using + ASCII code order. + +
      + +
    3. The algorithm has now selected one 'best' variant, so return + it as the response. The HTTP response header Vary is set to indicate the + dimensions of negotiation (browsers and caches can use this + information when caching the resource). End. + +
    4. To get here means no variant was selected (because none are acceptable + to the browser). Return a 406 status (meaning "No acceptable representation") + with a response body consisting of an HTML document listing the + available variants. Also set the HTTP Vary header to indicate the + dimensions of variance. + +
    + +

    Fiddling with Quality Values

    + +

    +Apache sometimes changes the quality values from what would be +expected by a strict interpretation of the Apache negotiation +algorithm above. This is to get a better result from the algorithm for +browsers which do not send full or accurate information. Some of the +most popular browsers send Accept header information which would +otherwise result in the selection of the wrong variant in many +cases. If a browser sends full and correct information these fiddles +will not be applied. +

    + +

    Media Types and Wildcards

    + +

    +The Accept: request header indicates preferences for media types. It +can also include 'wildcard' media types, such as "image/*" or "*/*" +where the * matches any string. So a request including: +

    +  Accept: image/*, */*
    +
    + +would indicate that any type starting "image/" is acceptable, +as is any other type (so the first "image/*" is redundant). Some +browsers routinely send wildcards in addition to explicit types they +can handle. For example: +
    +  Accept: text/html, text/plain, image/gif, image/jpeg, */*
    +
    + +The intention of this is to indicate that the explicitly +listed types are preferred, but if a different representation is +available, that is ok too. However under the basic algorithm, as given +above, the */* wildcard has exactly equal preference to all the other +types, so they are not being preferred. The browser should really have +sent a request with a lower quality (preference) value for *.*, such +as: +
    +  Accept: text/html, text/plain, image/gif, image/jpeg, */*; q=0.01
    +
    + +The explicit types have no quality factor, so they default to a +preference of 1.0 (the highest). The wildcard */* is given +a low preference of 0.01, so other types will only be returned if +no variant matches an explicitly listed type. +

    + +If the Accept: header contains no q factors at all, Apache sets +the q value of "*/*", if present, to 0.01 to emulate the desired +behavior. It also sets the q value of wildcards of the format +"type/*" to 0.02 (so these are preferred over matches against +"*/*". If any media type on the Accept: header contains a q factor, +these special values are not applied, so requests from browsers +which send the correct information to start with work as expected. + +

    Variants with no Language

    + +

    +If some of the variants for a particular resource have a language +attribute, and some do not, those variants with no language +are given a very low language quality factor of 0.001.

    + +The reason for setting this language quality factor for +variant with no language to a very low value is to allow +for a default variant which can be supplied if none of the +other variants match the browser's language preferences. + +For example, consider the situation with three variants: + +

      +
    • foo.en.html, language en +
    • foo.fr.html, language en +
    • foo.html, no language +
    + +

    +The meaning of a variant with no language is that it is +always acceptable to the browser. If the request Accept-Language +header includes either en or fr (or both) one of foo.en.html +or foo.fr.html will be returned. If the browser does not list +either en or fr as acceptable, foo.html will be returned instead. + +

    Extensions to Transparent Content Negotiation

    + +Apache extends the transparent content negotiation protocol (RFC 2295) +as follows. A new {encoding ..} element is used in +variant lists to label variants which are available with a specific +content-encoding only. The implementation of the +RVSA/1.0 algorithm (RFC 2296) is extended to recognize encoded +variants in the list, and to use them as candidate variants whenever +their encodings are acceptable according to the Accept-Encoding +request header. The RVSA/1.0 implementation does not round computed +quality factors to 5 decimal places before choosing the best variant. + +

    Note on hyperlinks and naming conventions

    + +

    +If you are using language negotiation you can choose between +different naming conventions, because files can have more than one +extension, and the order of the extensions is normally irrelevant +(see mod_mime documentation for details). +

    +A typical file has a MIME-type extension (e.g., html), +maybe an encoding extension (e.g., gz), and of course a +language extension (e.g., en) when we have different +language variants of this file. + +

    +Examples: +

      +
    • foo.en.html +
    • foo.html.en +
    • foo.en.html.gz +
    + +

    +Here some more examples of filenames together with valid and invalid +hyperlinks: +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FilenameValid hyperlinkInvalid hyperlink
    foo.html.enfoo
    + foo.html
    -
    foo.en.htmlfoofoo.html
    foo.html.en.gzfoo
    + foo.html
    foo.gz
    + foo.html.gz
    foo.en.html.gzfoofoo.html
    + foo.html.gz
    + foo.gz
    foo.gz.html.enfoo
    + foo.gz
    + foo.gz.html
    foo.html
    foo.html.gz.enfoo
    + foo.html
    + foo.html.gz
    foo.gz
    + +

    +Looking at the table above you will notice that it is always possible to +use the name without any extensions in an hyperlink (e.g., foo). +The advantage is that you can hide the actual type of a +document rsp. file and can change it later, e.g., from html +to shtml or cgi without changing any +hyperlink references. + +

    +If you want to continue to use a MIME-type in your hyperlinks (e.g. +foo.html) the language extension (including an encoding extension +if there is one) must be on the right hand side of the MIME-type extension +(e.g., foo.html.en). + + +

    Note on Caching

    + +

    +When a cache stores a representation, it associates it with the request URL. +The next time that URL is requested, the cache can use the stored +representation. But, if the resource is negotiable at the server, +this might result in only the first requested variant being cached and +subsequent cache hits might return the wrong response. To prevent this, +Apache normally marks all responses that are returned after content negotiation +as non-cacheable by HTTP/1.0 clients. Apache also supports the HTTP/1.1 +protocol features to allow caching of negotiated responses.

    + +For requests which come from a HTTP/1.0 compliant client (either a +browser or a cache), the directive CacheNegotiatedDocs can be +used to allow caching of responses which were subject to negotiation. +This directive can be given in the server config or virtual host, and +takes no arguments. It has no effect on requests from HTTP/1.1 clients. + + + + diff --git a/APACHE_1_3_12/htdocs/manual/custom-error.html b/APACHE_1_3_12/htdocs/manual/custom-error.html new file mode 100644 index 0000000000..09604ea972 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/custom-error.html @@ -0,0 +1,177 @@ + + + +Custom error responses + + + + + +

    Custom error responses

    + +
    + +
    Purpose + +
    Additional functionality. Allows webmasters to configure the response of + Apache to some error or problem. + +

    Customizable responses can be defined to be activated in the + event of a server detected error or problem. + +

    e.g. if a script crashes and produces a "500 Server Error" + response, then this response can be replaced with either some + friendlier text or by a redirection to another URL (local or + external). +

    + +

    Old behavior + +
    NCSA httpd 1.3 would return some boring old error/problem message + which would often be meaningless to the user, and would provide no + means of logging the symptoms which caused it.
    + +

    + +

    New behavior + +
    The server can be asked to; +
      +
    1. Display some other text, instead of the NCSA hard coded messages, or +
    2. redirect to a local URL, or +
    3. redirect to an external URL. +
    + +

    Redirecting to another URL can be useful, but only if some information + can be passed which can then be used to explain and/or log the + error/problem + more clearly. + +

    To achieve this, Apache will define new CGI-like environment + variables, e.g. + +

    +REDIRECT_HTTP_ACCEPT=*/*, image/gif, image/x-xbitmap, image/jpeg
    +REDIRECT_HTTP_USER_AGENT=Mozilla/1.1b2 (X11; I; HP-UX A.09.05 9000/712)
    +REDIRECT_PATH=.:/bin:/usr/local/bin:/etc
    +REDIRECT_QUERY_STRING=
    +REDIRECT_REMOTE_ADDR=121.345.78.123
    +REDIRECT_REMOTE_HOST=ooh.ahhh.com
    +REDIRECT_SERVER_NAME=crash.bang.edu
    +REDIRECT_SERVER_PORT=80
    +REDIRECT_SERVER_SOFTWARE=Apache/0.8.15
    +REDIRECT_URL=/cgi-bin/buggy.pl
    +
    + +

    note the REDIRECT_ prefix. + +

    At least REDIRECT_URL and REDIRECT_QUERY_STRING + will + be passed to the new URL (assuming it's a cgi-script or a cgi-include). + The + other variables will exist only if they existed prior to the + error/problem. + None of these will be set if your ErrorDocument is an + external redirect (i.e., anything starting with a + scheme name + like http:, even if it refers to the same host as the + server).

    + +

    Configuration + +
    Use of "ErrorDocument" is enabled for .htaccess files when the + "FileInfo" override is + allowed. + +

    Here are some examples... + +

    +ErrorDocument 500 /cgi-bin/crash-recover
    +ErrorDocument 500 "Sorry, our script crashed. Oh dear
    +ErrorDocument 500 http://xxx/
    +ErrorDocument 404 /Lame_excuses/not_found.html
    +ErrorDocument 401 /Subscription/how_to_subscribe.html +
    + +

    The syntax is, + +

    ErrorDocument +<3-digit-code> action + +

    where the action can be, + +

      +
    1. Text to be displayed. Prefix the text with a quote ("). Whatever + follows the quote is displayed. Note: the (") prefix isn't + displayed. + +
    2. An external URL to redirect to. + +
    3. A local URL to redirect to. + +
    +
    + +


    + +

    Custom error responses and redirects

    + +
    + +
    Purpose + +
    Apache's behavior to redirected URLs has been modified so that additional + environment variables are available to a script/server-include.

    + +

    Old behavior + +
    Standard CGI vars were made available to a script which has been + redirected to. No indication of where the redirection came from was + provided. + +

    + +

    New behavior +
    + +A new batch of environment variables will be initialized for use by a +script which has been redirected to. Each new variable will have the +prefix REDIRECT_. REDIRECT_ environment +variables are created from the CGI environment variables which existed +prior to the redirect, they are renamed with a REDIRECT_ +prefix, i.e., HTTP_USER_AGENT becomes +REDIRECT_HTTP_USER_AGENT. In addition to these new +variables, Apache will define REDIRECT_URL and +REDIRECT_STATUS to help the script trace its origin. +Both the original URL and the URL being redirected to can be logged in +the access log. + +
    +

    +If the ErrorDocument specifies a local redirect to a CGI script, the script +should include a "Status:" header field in its output +in order to ensure the propagation all the way back to the client +of the error condition that caused it to be invoked. For instance, a Perl +ErrorDocument script might include the following: +

    +
    +      :
    +    print  "Content-type: text/html\n";
    +    printf "Status: %s Condition Intercepted\n", $ENV{"REDIRECT_STATUS"};
    +      :
    +
    +

    +If the script is dedicated to handling a particular error condition, such as +404 Not Found, it can use the specific code and +error text instead. +

    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/dns-caveats.html b/APACHE_1_3_12/htdocs/manual/dns-caveats.html new file mode 100644 index 0000000000..cbf8a57a9d --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/dns-caveats.html @@ -0,0 +1,189 @@ + + +Issues Regarding DNS and Apache + + + + + +

    Issues Regarding DNS and Apache

    + +

    This page could be summarized with the statement: don't require +Apache to use DNS for any parsing of the configuration files. +If Apache has to use DNS to parse the configuration files then your +server may be subject to reliability problems (it might not boot), or +denial and theft of service attacks (including users able to steal hits +from other users). + +

    A Simple Example

    + +Consider this configuration snippet: + +
    +    <VirtualHost www.abc.dom>
    +    ServerAdmin webgirl@abc.dom
    +    DocumentRoot /www/abc
    +    </VirtualHost>
    +
    + +

    In order for Apache to function properly it absolutely needs +to have two pieces of information about each virtual host: the +ServerName +and at least one IP address that the server +responds to. This example does not include the IP address, so Apache +must use DNS to find the address of www.abc.dom. If for +some reason DNS is not available at the time your server is parsing its +config file, then this virtual host will not be configured. It +won't be able to respond to any hits to this virtual host (prior to +Apache version 1.2 the server would not even boot). + +

    Suppose that www.abc.dom has address 10.0.0.1. Then +consider this configuration snippet: + +

    +    <VirtualHost 10.0.0.1>
    +    ServerAdmin webgirl@abc.dom
    +    DocumentRoot /www/abc
    +    </VirtualHost>
    +
    + +

    Now Apache needs to use reverse DNS to find the ServerName +for this virtualhost. If that reverse lookup fails then it will partially +disable the virtualhost (prior to Apache version 1.2 the server would not +even boot). If the virtual host is name-based then it will effectively +be totally disabled, but if it is IP-based then it will mostly work. +However if Apache should ever have to generate a full URL for the server +which includes the server name then it will fail to generate a valid URL. + +

    Here is a snippet that avoids both of these problems. + +

    +    <VirtualHost 10.0.0.1>
    +    ServerName www.abc.dom
    +    ServerAdmin webgirl@abc.dom
    +    DocumentRoot /www/abc
    +    </VirtualHost>
    +
    + +

    Denial of Service

    + +

    There are (at least) two forms that denial of service can come in. +If you are running a version of Apache prior to version 1.2 then your +server will not even boot if one of the two DNS lookups mentioned above +fails for any of your virtual hosts. In some cases this DNS lookup may +not even be under your control. For example, if abc.dom +is one of your customers and they control their own DNS then they +can force your (pre-1.2) server to fail while booting simply by deleting the +www.abc.dom record. + +

    Another form is far more insidious. Consider this configuration +snippet: + +

    +    <VirtualHost www.abc.dom>
    +    ServerAdmin webgirl@abc.dom
    +    DocumentRoot /www/abc
    +    </VirtualHost>
    +
    + +
    +    <VirtualHost www.def.dom>
    +    ServerAdmin webguy@def.dom
    +    DocumentRoot /www/def
    +    </VirtualHost>
    +
    + +

    Suppose that you've assigned 10.0.0.1 to www.abc.dom and +10.0.0.2 to www.def.dom. Furthermore, suppose that +def.com has control of their own DNS. With this config +you have put def.com into a position where they can steal +all traffic destined to abc.com. To do so, all they have to +do is set www.def.dom to 10.0.0.1. +Since they control their own DNS you can't stop them from pointing the +www.def.com record wherever they wish. + +

    Requests coming in to 10.0.0.1 (including all those where users typed +in URLs of the form http://www.abc.dom/whatever) will all be +served by the def.com virtual host. To better understand why +this happens requires a more in-depth discussion of how Apache matches +up incoming requests with the virtual host that will serve it. A rough +document describing this is available. + +

    The "main server" Address

    + +

    The addition of name-based virtual host +support in Apache 1.1 requires Apache to know the IP address(es) of +the host that httpd is running on. To get this address it uses either +the global ServerName (if present) or calls the C function +gethostname (which should return the same as typing +"hostname" at the command prompt). Then it performs a DNS lookup on +this address. At present there is no way to avoid this lookup. + +

    If you fear that this lookup might fail because your DNS server is down +then you can insert the hostname in /etc/hosts (where you +probably already have it so that the machine can boot properly). Then +ensure that your machine is configured to use /etc/hosts +in the event that DNS fails. Depending on what OS you are using this +might be accomplished by editing /etc/resolv.conf, or maybe +/etc/nsswitch.conf. + +

    If your server doesn't have to perform DNS for any other reason +then you might be able to get away with running Apache with the +HOSTRESORDER environment variable set to "local". This all +depends on what OS and resolver libraries you are using. It also affects +CGIs unless you use mod_env +to control the environment. It's best to consult the man pages or FAQs +for your OS. + +

    Tips to Avoid these problems

    + +
      +
    • use IP addresses in <VirtualHost> +
    • use IP addresses in Listen +
    • use IP addresses in BindAddress +
    • ensure all virtual hosts have an explicit ServerName +
    • create a <VirtualHost _default_:*> server that + has no pages to serve +
    + +

    Appendix: Future Directions

    + +

    The situation regarding DNS is highly undesirable. For Apache +1.2 we've attempted to make the server at least continue booting +in the event of failed DNS, but it might not be the best we +can do. In any event requiring the use of explicit IP addresses in +configuration files is highly undesirable in today's Internet where renumbering + is a necessity. + +

    A possible work around to the theft of service attack described above +would be to perform a reverse DNS lookup on the ip address returned by +the forward lookup and compare the two names. In the event of a mismatch +the virtualhost would be disabled. This would require reverse DNS to be +configured properly (which is something that most admins are familiar with +because of the common use of "double-reverse" DNS lookups by FTP servers +and TCP wrappers). + +

    In any event it doesn't seem possible to reliably boot a virtual-hosted +web server when DNS has failed unless IP addresses are used. Partial +solutions such as disabling portions of the configuration might be worse +than not booting at all depending on what the webserver is supposed +to accomplish. + +

    As HTTP/1.1 is deployed and browsers and proxies start issuing the +Host header it will become possible to avoid the use of +IP-based virtual hosts entirely. In this event a webserver has no requirement +to do DNS lookups during configuration. But as of March 1997 these +features have not been deployed widely enough to be put into use on +critical webservers. + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/dso.html b/APACHE_1_3_12/htdocs/manual/dso.html new file mode 100644 index 0000000000..66e6fc9841 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/dso.html @@ -0,0 +1,393 @@ + + +Apache 1.3 Dynamic Shared Object (DSO) support + + + + +

    + + +
    + +

    +Apache 1.3
    +Dynamic Shared Object (DSO)
    +Support +

    + +
    Originally written by
    +Ralf S. Engelschall <rse@apache.org>, April 1998
    + +
    + +

    Background

    + +

    On modern Unix derivatives there exists a nifty mechanism usually called +dynamic linking/loading of Dynamic Shared Objects (DSO) which +provides a way to build a piece of program code in a special format for +loading it at run-time into the address space of an executable program. + +

    This loading can usually be done in two ways: Automatically by a system +program called ld.so when an executable program is started or +manually from within the executing program via a programmatic system interface +to the Unix loader through the system calls dlopen()/dlsym(). + +

    In the first way the DSO's are usually called shared libraries or +DSO libraries and named libfoo.so or +libfoo.so.1.2. They reside in a system directory (usually +/usr/lib) and the link to the executable program is established +at build-time by specifying -lfoo to the linker command. This +hard-codes library references into the executable program file so that at +start-time the Unix loader is able to locate libfoo.so in +/usr/lib, in paths hard-coded via linker-options like +-R or in paths configured via the environment variable +LD_LIBRARY_PATH. It then resolves any (yet unresolved) symbols in +the executable program which are available in the DSO. + +

    Symbols in the executable program are usually not referenced by the DSO +(because it's a reusable library of general code) and hence no further +resolving has to be done. The executable program has no need to do anything on +its own to use the symbols from the DSO because the complete resolving is done +by the Unix loader. (In fact, the code to invoke ld.so is part of +the run-time startup code which is linked into every executable program which +has been bound non-static). The advantage of dynamic loading of common library +code is obvious: the library code needs to be stored only once, in a system +library like libc.so, saving disk space for every program. + +

    In the second way the DSO's are usually called shared objects or +DSO files and can be named with an arbitrary extension (although the +canonical name is foo.so). These files usually stay inside a +program-specific directory and there is no automatically established link to +the executable program where they are used. Instead the executable program +manually loads the DSO at run-time into its address space via +dlopen(). At this time no resolving of symbols from the DSO for +the executable program is done. But instead the Unix loader automatically +resolves any (yet unresolved) symbols in the DSO from the set of symbols +exported by the executable program and its already loaded DSO libraries +(especially all symbols from the ubiquitous libc.so). This way +the DSO gets knowledge of the executable program's symbol set as if it had +been statically linked with it in the first place. + +

    Finally, to take advantage of the DSO's API the executable program has to +resolve particular symbols from the DSO via dlsym() for later use +inside dispatch tables etc. In other words: The executable program has to +manually resolve every symbol it needs to be able to use it. The advantage of +such a mechanism is that optional program parts need not be loaded (and thus +do not spend memory) until they are needed by the program in question. When +required, these program parts can be loaded dynamically to extend the base +program's functionality. + +

    Although this DSO mechanism sounds straightforward there is at least one +difficult step here: The resolving of symbols from the executable program for +the DSO when using a DSO to extend a program (the second way). Why? Because +"reverse resolving" DSO symbols from the executable program's symbol set is +against the library design (where the library has no knowledge about the +programs it is used by) and is neither available under all platforms nor +standardized. In practice the executable program's global symbols are often +not re-exported and thus not available for use in a DSO. Finding a way to +force the linker to export all global symbols is the main problem one has to +solve when using DSO for extending a program at run-time. + +

    Practical Usage

    + +

    The shared library approach is the typical one, because it is what the DSO +mechanism was designed for, hence it is used for nearly all types of libraries +the operating system provides. On the other hand using shared objects for +extending a program is not used by a lot of programs. + +

    As of 1998 there are only a few software packages available which use the +DSO mechanism to actually extend their functionality at run-time: Perl 5 (via +its XS mechanism and the DynaLoader module), Netscape Server, etc. Starting +with version 1.3, Apache joined the crew, because Apache already uses a module +concept to extend its functionality and internally uses a dispatch-list-based +approach to link external modules into the Apache core functionality. So, +Apache is really predestined for using DSO to load its modules at run-time. + +

    As of Apache 1.3, the configuration system supports two optional features +for taking advantage of the modular DSO approach: compilation of the Apache +core program into a DSO library for shared usage and compilation of the +Apache modules into DSO files for explicit loading at run-time. + +

    Implementation

    + +

    The DSO support for loading individual Apache modules is based on a module +named mod_so.c which has to be +statically compiled into the Apache core. It is the only module besides +http_core.c which cannot be put into a DSO itself +(bootstrapping!). Practically all other distributed Apache modules then can +then be placed into a DSO by individually enabling the DSO build for them via +configure's --enable-shared option (see top-level +INSTALL file) or by changing the AddModule command +in your src/Configuration into a SharedModule +command (see src/INSTALL file). After a module is compiled into +a DSO named mod_foo.so you can use mod_so's LoadModule command in your +httpd.conf file to load this module at server startup or restart. + +

    To simplify this creation of DSO files for Apache modules (especially for +third-party modules) a new support program named apxs (APache +eXtenSion) is available. It can be used to build DSO based modules +outside of the Apache source tree. The idea is simple: When +installing Apache the configure's make install +procedure installs the Apache C header files and puts the platform-dependent +compiler and linker flags for building DSO files into the apxs +program. This way the user can use apxs to compile his Apache +module sources without the Apache distribution source tree and without having +to fiddle with the platform-dependent compiler and linker flags for DSO +support. + +

    To place the complete Apache core program into a DSO library (only required +on some of the supported platforms to force the linker to export the apache +core symbols -- a prerequisite for the DSO modularization) the rule +SHARED_CORE has to be enabled via configure's +--enable-rule=SHARED_CORE option (see top-level +INSTALL file) or by changing the Rule command in +your Configuration file to Rule SHARED_CORE=yes (see +src/INSTALL file). The Apache core code is then placed into a DSO +library named libhttpd.so. Because one cannot link a DSO against +static libraries on all platforms, an additional executable program named +libhttpd.ep is created which both binds this static code and +provides a stub for the main() function. Finally the +httpd executable program itself is replaced by a bootstrapping +code which automatically makes sure the Unix loader is able to load and start +libhttpd.ep by providing the LD_LIBRARY_PATH to +libhttpd.so. + +

    Supported Platforms

    + +

    Apache's src/Configure script currently has only limited but +adequate built-in knowledge on how to compile DSO files, because as already +mentioned this is heavily platform-dependent. Nevertheless all major Unix +platforms are supported. The definitive current state (May 1999) is this: + +

    +

      +
    • Out-of-the-box supported platforms:
      +(actually tested versions in parenthesis) + +
      +o  FreeBSD            (2.1.5, 2.2.x, 3.x, 4.x)
      +o  OpenBSD            (2.x)
      +o  NetBSD             (1.3.1)
      +o  BSDI               (3.x, 4.x)
      +o  Linux              (Debian/1.3.1, RedHat/4.2)
      +o  Solaris            (2.4, 2.5, 2.6, 2.7)
      +o  SunOS              (4.1.3)
      +o  Digital UNIX       (4.0)
      +o  IRIX               (5.3, 6.2)
      +o  HP/UX              (10.20)
      +o  UnixWare           (2.01, 2.1.2)
      +o  SCO                (5.0.4)
      +o  AIX                (3.2, 4.1.5, 4.2, 4.3)
      +o  ReliantUNIX/SINIX  (5.43)
      +o  SVR4               (-)
      +o  Mac OS X Server    (1.0)
      +o  Mac OS             (10.0 preview 1)
      +o  OpenStep/Mach      (4.2)
      +o  DGUX               (??)
      +o  NetWare            (5.1)
      +
      + +

      +

    • Explicitly unsupported platforms: + +
      +o  Ultrix             (no dlopen-style interface under this platform)
      +
      + +
    + +

    Usage Summary

    + +

    To give you an overview of the DSO features of Apache 1.3, here is a short +and concise summary: + +

      + +
    1. Placing the Apache core code (all the stuff which usually forms the +httpd binary) into a DSO libhttpd.so, an executable +program libhttpd.ep and a bootstrapping executable program +httpd (Notice: this is only required on some of the supported +platforms to force the linker to export the Apache core symbols, which in turn +is a prerequisite for the DSO modularization): + +

      +

        +
      • Build and install via configure (preferred): +
        +
        +$ ./configure --prefix=/path/to/install
        +              --enable-rule=SHARED_CORE ...
        +$ make install
        +
        +
        + +
      • Build and install manually: +
        +
        +- Edit src/Configuration:
        +  << Rule SHARED_CORE=default
        +  >> Rule SHARED_CORE=yes
        +  << EXTRA_CFLAGS= 
        +  >> EXTRA_CFLAGS= -DSHARED_CORE_DIR=\"/path/to/install/libexec\"
        +$ make 
        +$ cp src/libhttpd.so* /path/to/install/libexec/
        +$ cp src/libhttpd.ep  /path/to/install/libexec/
        +$ cp src/httpd        /path/to/install/bin/
        +
        +
        +
      + +
    2. Build and install a distributed Apache module, say +mod_foo.c, into its own DSO mod_foo.so: + +

      +

        +
      • Build and install via configure (preferred): +
        +
        +$ ./configure --prefix=/path/to/install
        +        --enable-shared=foo
        +$ make install
        +
        +
        + +
      • Build and install manually: +
        +
        +- Edit src/Configuration:
        +  << AddModule    modules/xxxx/mod_foo.o
        +  >> SharedModule modules/xxxx/mod_foo.so
        +$ make
        +$ cp src/xxxx/mod_foo.so /path/to/install/libexec
        +- Edit /path/to/install/etc/httpd.conf
        +  >> LoadModule foo_module /path/to/install/libexec/mod_foo.so
        +
        +
        +
      + +
    3. Build and install a third-party Apache module, say +mod_foo.c, into its own DSO mod_foo.so + +

      +

        +
      • Build and install via configure (preferred): +
        +
        +$ ./configure --add-module=/path/to/3rdparty/mod_foo.c 
        +        --enable-shared=foo
        +$ make install
        +
        +
        + +
      • Build and install manually: +
        +
        +$ cp /path/to/3rdparty/mod_foo.c /path/to/apache-1.3/src/modules/extra/
        +- Edit src/Configuration:
        +  >> SharedModule modules/extra/mod_foo.so
        +$ make
        +$ cp src/xxxx/mod_foo.so /path/to/install/libexec
        +- Edit /path/to/install/etc/httpd.conf
        +  >> LoadModule foo_module /path/to/install/libexec/mod_foo.so
        +
        +
        +
      + +

      +

    4. Build and install a third-party Apache module, say +mod_foo.c, into its own DSO mod_foo.so outside +of the Apache source tree: + +

      +

        +
      • Build and install via apxs: +
        +
        +$ cd /path/to/3rdparty
        +$ apxs -c mod_foo.c
        +$ apxs -i -a -n foo mod_foo.so
        +
        +
        +
      + +
    + +

    Advantages & Disadvantages

    + +

    The above DSO based features of Apache 1.3 have the following advantages: + +

      +
    • The server package is more flexible at run-time because the actual server + process can be assembled at run-time via LoadModule + httpd.conf configuration commands instead of + Configuration AddModule commands at build-time. + For instance this way one is able to run different server instances + (standard & SSL version, minimalistic & powered up version + [mod_perl, PHP3], etc.) with only one Apache installation. +

      +

    • The server package can be easily extended with third-party modules even + after installation. This is at least a great benefit for vendor package + maintainers who can create a Apache core package and additional packages + containing extensions like PHP3, mod_perl, mod_fastcgi, etc. +

      +

    • Easier Apache module prototyping because with the DSO/apxs + pair you can both work outside the Apache source tree and only need an + apxs -i command followed by an apachectl + restart to bring a new version of your currently developed module + into the running Apache server. +
    + +

    DSO has the following disadvantages: + +

      +
    • The DSO mechanism cannot be used on every platform because not all + operating systems support dynamic loading of code into the address space + of a program. +

      +

    • The server is approximately 20% slower at startup time because of the + symbol resolving overhead the Unix loader now has to do. +

      +

    • The server is approximately 5% slower at execution time under some + platforms because position independent code (PIC) sometimes needs + complicated assembler tricks for relative addressing which are not + necessarily as fast as absolute addressing. +

      +

    • Because DSO modules cannot be linked against other DSO-based libraries + (ld -lfoo) on all platforms (for instance a.out-based + platforms usually don't provide this functionality while ELF-based + platforms do) you cannot use the DSO mechanism for all types of modules. + Or in other words, modules compiled as DSO files are restricted to only + use symbols from the Apache core, from the C library (libc) + and all other dynamic or static libraries used by the Apache core, or + from static library archives (libfoo.a) containing position + independent code. The only chances to use other code is to either make + sure the Apache core itself already contains a reference to it, loading + the code yourself via dlopen() or enabling the + SHARED_CHAIN rule while building Apache when your platform + supports linking DSO files against DSO libraries. +

      +

    • Under some platforms (many SVR4 systems) there is no way to force the + linker to export all global symbols for use in DSO's when linking the + Apache httpd executable program. But without the visibility of the Apache + core symbols no standard Apache module could be used as a DSO. The only + chance here is to use the SHARED_CORE feature because this + way the global symbols are forced to be exported. As a consequence the + Apache src/Configure script automatically enforces + SHARED_CORE on these platforms when DSO features are used in + the Configuration file or on the configure command line. +
    + + +
    + + diff --git a/APACHE_1_3_12/htdocs/manual/ebcdic.html b/APACHE_1_3_12/htdocs/manual/ebcdic.html new file mode 100644 index 0000000000..0e93aaa490 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/ebcdic.html @@ -0,0 +1,497 @@ + + + +The Apache EBCDIC Port + + + + + +

    Overview of the Apache EBCDIC Port

    + +

    + Version 1.3 of the Apache HTTP Server is the first version which + includes a port to a (non-ASCII) mainframe machine which uses + the EBCDIC character set as its native codeset.
    + (It is the SIEMENS family of mainframes running the + BS2000/OSD + operating system. This mainframe OS nowadays features a + SVR4-derived POSIX subsystem). +

    + +

    + The port was started initially to +

      +
    • prove the feasibility of porting + the Apache HTTP server + to this platform +
    • find a "worthy and capable" successor for the venerable + CERN-3.0 daemon + (which was ported a couple of years ago), and to +
    • prove that Apache's preforking process model can on this platform + easily outperform the accept-fork-serve model used by CERN by a + factor of 5 or more. +
    +

    + +

    + This document serves as a rationale to describe some of the design + decisions of the port to this machine. +

    + +

    Design Goals

    +

    + One objective of the EBCDIC port was to maintain enough backwards + compatibility with the (EBCDIC) CERN server to make the transition to + the new server attractive and easy. This required the addition of + a configurable method to define whether a HTML document was stored + in ASCII (the only format accepted by the old server) or in EBCDIC + (the native document format in the POSIX subsystem, and therefore + the only realistic format in which the other POSIX tools like grep + or sed could operate on the documents). The current solution to + this is a "pseudo-MIME-format" which is intercepted and + interpreted by the Apache server (see below). Future versions + might solve the problem by defining an "ebcdic-handler" for all + documents which must be converted. +

    + +

    Technical Solution

    +

    + Since all Apache input and output is based upon the BUFF data type + and its methods, the easiest solution was to add the conversion to + the BUFF handling routines. The conversion must be settable at any + time, so a BUFF flag was added which defines whether a BUFF object + has currently enabled conversion or not. This flag is modified at + several points in the HTTP protocol: +

      +
    • set before a request is received (because the + request and the request header lines are always in ASCII + format) + +
    • set/unset when the request body is + received - depending on the content type of the request body + (because the request body may contain ASCII text or a binary file) + +
    • set before a reply header is sent (because the + response header lines are always in ASCII format) + +
    • set/unset when the response body is + sent - depending on the content type of the response body + (because the response body may contain text or a binary file) +
    +

    + +

    Porting Notes

    +

    +

      +
    1. + The relevant changes in the source are #ifdef'ed into two + categories: +
      +
      #ifdef CHARSET_EBCDIC +
      Code which is needed for any EBCDIC based machine. This + includes character translations, differences in + contiguity of the two character sets, flags which + indicate which part of the HTTP protocol has to be + converted and which part doesn't etc. +
      #ifdef _OSD_POSIX +
      Code which is needed for the SIEMENS BS2000/OSD + mainframe platform only. This deals with include file + differences and socket implementation topics which are + only required on the BS2000/OSD platform. +
      +

    2. + +
    3. + The possibility to translate between ASCII and EBCDIC at the + socket level (on BS2000 POSIX, there is a socket option which + supports this) was intentionally not chosen, because + the byte stream at the HTTP protocol level consists of a + mixture of protocol related strings and non-protocol related + raw file data. HTTP protocol strings are always encoded in + ASCII (the GET request, any Header: lines, the chunking + information etc.) whereas the file transfer parts (i.e., GIF + images, CGI output etc.) should usually be just "passed through" + by the server. This separation between "protocol string" and + "raw data" is reflected in the server code by functions like + bgets() or rvputs() for strings, and functions like bwrite() + for binary data. A global translation of everything would + therefore be inadequate.
      + (In the case of text files of course, provisions must be made so + that EBCDIC documents are always served in ASCII) +

    4. + +
    5. + This port therefore features a built-in protocol level conversion + for the server-internal strings (which the compiler translated to + EBCDIC strings) and thus for all server-generated documents. + The hard coded ASCII escapes \012 and \015 which are + ubiquitous in the server code are an exception: they are + already the binary encoding of the ASCII \n and \r and must + not be converted to ASCII a second time. This exception is + only relevant for server-generated strings; and external + EBCDIC documents are not expected to contain ASCII newline characters. +

    6. + +
    7. + By examining the call hierarchy for the BUFF management + routines, I added an "ebcdic/ascii conversion layer" which + would be crossed on every puts/write/get/gets, and a + conversion flag which allowed enabling/disabling the + conversions on-the-fly. Usually, a document crosses this + layer twice from its origin source (a file or CGI output) to + its destination (the requesting client): file -> + Apache, and Apache -> client.
      + The server can now read the header + lines of a CGI-script output in EBCDIC format, and then find + out that the remainder of the script's output is in ASCII + (like in the case of the output of a WWW Counter program: the + document body contains a GIF image). All header processing is + done in the native EBCDIC format; the server then determines, + based on the type of document being served, whether the + document body (except for the chunking information, of + course) is in ASCII already or must be converted from EBCDIC. +

    8. + +
    9. + For Text documents (MIME types text/plain, text/html etc.), + an implicit translation to ASCII can be used, or (if the + users prefer to store some documents in raw ASCII form for + faster serving, or because the files reside on a NFS-mounted + directory tree) can be served without conversion. +
      + Example:
      + to serve files with the suffix .ahtml as a raw ASCII text/html + document without implicit conversion (and suffix .ascii + as ASCII text/plain), use the directives:
      +      AddType  text/x-ascii-html  .ahtml
      +      AddType  text/x-ascii-plain .ascii
      +      
      + Similarly, any text/XXXX MIME type can be served as "raw ASCII" by + configuring a MIME type "text/x-ascii-XXXX" for it using AddType. +

    10. + +
    11. + Non-text documents are always served "binary" without conversion. + This seems to be the most sensible choice for, .e.g., GIF/ZIP/AU + file types. This of course requires the user to copy them to the + mainframe host using the "rcp -b" binary switch. +

    12. + +
    13. + Server parsed files are always assumed to be in native (i.e., + EBCDIC) format as used on the machine, and are converted after + processing. +

    14. + +
    15. + For CGI output, the CGI script determines whether a conversion is + needed or not: by setting the appropriate Content-Type, text files + can be converted, or GIF output can be passed through unmodified. + An example for the latter case is the wwwcount program which we ported + as well. +

    16. +
    +

    + +

    Document Storage Notes

    +

    Binary Files

    +

    + All files with a Content-Type: which does not + start with text/ are regarded as binary files + by the server and are not subject to any conversion. + Examples for binary files are GIF images, gzip-compressed + files and the like. +

    +

    + When exchanging binary files between the mainframe host and a + Unix machine or Windows PC, be sure to use the ftp "binary" + (TYPE I) command, or use the + rcp -b command from the mainframe host + (the -b switch is not supported in unix rcp's). +

    + +

    Text Documents

    +

    + The default assumption of the server is that Text Files + (i.e., all files whose Content-Type: starts with + text/) are stored in the native character + set of the host, EBCDIC. +

    + +

    Server Side Included Documents

    +

    + SSI documents must currently be stored in EBCDIC only. No + provision is made to convert it from ASCII before processing. +

    + +

    Apache Modules' Status

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Module + Status + Notes +
    http_core + + + +
    mod_access + + + +
    mod_actions + + + +
    mod_alias + + + +
    mod_asis + + + +
    mod_auth + + + +
    mod_auth_anon + + + +
    mod_auth_db + ? + with own libdb.a +
    mod_auth_dbm + ? + with own libdb.a +
    mod_autoindex + + + +
    mod_cern_meta + ? + +
    mod_cgi + + + +
    mod_digest + + + +
    mod_dir + + + +
    mod_so + - + no shared libs +
    mod_env + + + +
    mod_example + - + (test bed only) +
    mod_expires + + + +
    mod_headers + + + +
    mod_imap + + + +
    mod_include + + + +
    mod_info + + + +
    mod_log_agent + + + +
    mod_log_config + + + +
    mod_log_referer + + + +
    mod_mime + + + +
    mod_mime_magic + ? + not ported yet +
    mod_negotiation + + + +
    mod_proxy + + + +
    mod_rewrite + + + untested +
    mod_setenvif + + + +
    mod_speling + + + +
    mod_status + + + +
    mod_unique_id + + + +
    mod_userdir + + + +
    mod_usertrack + ? + untested +
    + +

    Third Party Modules' Status

    + + + + + + + + + + + + + + + + +
    Module + Status + Notes +
    mod_jserv + - + JAVA still being ported. +
    mod_php3 + + + mod_php3 runs fine, with LDAP and GD and FreeType libraries +
    mod_put + ? + untested +
    mod_session + - + untested +
    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/env.html b/APACHE_1_3_12/htdocs/manual/env.html new file mode 100644 index 0000000000..962dbe90ae --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/env.html @@ -0,0 +1,64 @@ + + + +Special Purpose Environment Variables + + + + + +

    Special Purpose Environment Variables

    +

    +Interoperability problems have led to the introduction of +mechanisms to modify the way Apache behaves when talking to particular +clients. To make these mechanisms as flexible as possible, they +are invoked by defining environment variables, typically with +BrowserMatch, though +SetEnv and +PassEnv could also be used, for +example. +

    + +

    downgrade-1.0

    +

    +This forces the request to be treated as a HTTP/1.0 request even if it +was in a later dialect. +

    + +

    force-no-vary

    +

    +This causes any Vary fields to be removed from the response +header before it is sent back to the client. Some clients don't +interpret this field correctly (see the +known client problems +page); setting this variable can work around this problem. Setting +this variable also implies force-response-1.0. +

    + +

    force-response-1.0

    +

    +This forces an HTTP/1.0 response when set. It was originally implemented as a +result of a problem with AOL's proxies. Some clients may not behave correctly +when given an HTTP/1.1 response, and this can be used to interoperate with +them. +

    + +

    nokeepalive

    +

    +This disables KeepAlive when set. Because +of problems with Netscape 2.x and KeepAlive, we recommend the following +directive be used: +

    +
    +    BrowserMatch Mozilla/2 nokeepalive
    +
    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/expand.pl b/APACHE_1_3_12/htdocs/manual/expand.pl new file mode 100755 index 0000000000..d286149880 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/expand.pl @@ -0,0 +1,104 @@ +#!/usr/local/bin/perl5 + +# This is a very simple Perl script to expand server-side includes +# in the directory it is run, and direct subdirectories. It will +# work only on SSI directives of the form +# +# +# +# Filename must be relative to the directory the file appears in. +# +# Nov 30, 1996 - Alexei Kosut + +# ==================================================================== +# Copyright (c) 1996-1999 The Apache Group. 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 acknowledgment: +# "This product includes software developed by the Apache Group +# for use in the Apache HTTP server project (http://www.apache.org/)." +# +# 4. The names "Apache Server" and "Apache Group" must not be used to +# endorse or promote products derived from this software without +# prior written permission. +# +# 5. Products derived from this software may not be called "Apache" +# nor may "Apache" appear in their names without prior written +# permission of the Apache Group. +# +# 6. Redistributions of any form whatsoever must retain the following +# acknowledgment: +# "This product includes software developed by the Apache Group +# for use in the Apache HTTP server project (http://www.apache.org/)." +# +# THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY +# EXPRESSED 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 APACHE GROUP OR +# ITS 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. +# ==================================================================== +# +# This software consists of voluntary contributions made by many +# individuals on behalf of the Apache Group and was originally based +# on public domain software written at the National Center for +# Supercomputing Applications, University of Illinois, Urbana-Champaign. +# For more information on the Apache Group and the Apache HTTP server +# project, please see . + +# Put a list of dirs (except ..) into @dirs + +opendir DIR, "." or die "Could not open directory: $!"; +@dirs = grep !/^\.\.$/, (grep -d, readdir DIR); +closedir DIR; + +foreach $dir (@dirs) { + print "Entering directory $dir\n"; + opendir SUBDIR, "$dir" or die "Could not open subdir $dir: $!"; + foreach $file (grep /\.html$/, readdir SUBDIR) { + print "Expanding file $dir/$file\n"; + rename "$dir/$file", "$dir/${file}.old"; + open READ, "$dir/${file}.old" or die "Couldn't read $dir/$file: $!"; + open WRITE, ">$dir/$file" or die "Couldn't write $dir/$file: $!"; + while ($r = ) { + if ($r =~ //) { + ($pre, $include, $post) = ($`, $1, $'); + print WRITE $pre; + + open INC, "$dir/$include" or + print "Could not include file $dir/$include: $!"; + print WRITE while (); + close INC; + + print WRITE $post; + } + else { + print WRITE $r; + } + } + close READ; + close WRITE; + unlink "$dir/$file.old"; + } + closedir SUBDIR; +} + + diff --git a/APACHE_1_3_12/htdocs/manual/footer.html b/APACHE_1_3_12/htdocs/manual/footer.html new file mode 100644 index 0000000000..c82d24e722 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/footer.html @@ -0,0 +1,6 @@ +
    +

    + Apache HTTP Server Version 1.3 +

    + +Index diff --git a/APACHE_1_3_12/htdocs/manual/handler.html b/APACHE_1_3_12/htdocs/manual/handler.html new file mode 100644 index 0000000000..72f16fd170 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/handler.html @@ -0,0 +1,195 @@ + + + +Apache's Handler Use + + + + + +

    Apache's Handler Use

    + +

    What is a Handler

    + +

    A "handler" is an internal Apache representation of the action to be +performed when a file is called. Generally, files have implicit +handlers, based on the file type. Normally, all files are simply +served by the server, but certain file typed are "handled" +separately. For example, you may use a type of +"application/x-httpd-cgi" to invoke CGI scripts.

    + +

    Apache 1.1 adds the additional ability to use handlers +explicitly. Either based on filename extensions or on location, these +handlers are unrelated to file type. This is advantageous both because +it is a more elegant solution, but it also allows for both a type +and a handler to be associated with a file (See also +Files with Multiple Extensions) + +

    + +

    Handlers can either be built into the server or to a module, or +they can be added with the Action directive. The built-in +handlers in the standard distribution are as follows:

    + +
      +
    • default-handler: + Send the file using the default_handler(), which is the + handler used by default to handle static content. + (core) +
    • send-as-is: + Send file with HTTP headers as is. + (mod_asis) +
    • cgi-script: + Treat the file as a CGI script. + (mod_cgi) +
    • imap-file: + Imagemap rule file. + (mod_imap) +
    • server-info: + Get the server's configuration information + (mod_info) +
    • server-parsed: + Parse for server-side includes + (mod_include) +
    • server-status: + Get the server's status report + (mod_status) +
    • type-map: + Parse as a type map file for content negotiation + (mod_negotiation) +
    + +

    + +

    Directives

    + + +
    + +

    AddHandler

    + +Syntax: AddHandler handler-name extension extension...
    +Context: server config, virtual host, directory, .htaccess
    +Override: FileInfo
    +Status: Base
    +Module: mod_mime
    +Compatibility: AddHandler is only available in Apache +1.1 and later

    + +

    AddHandler maps the filename extensions extension to the +handler handler-name. This mapping is added to any already +in force, overriding any mappings that already exist for the same +extension. + +For example, to activate CGI scripts +with the file extension ".cgi", you might use: +

    +    AddHandler cgi-script cgi
    +
    + +

    Once that has been put into your srm.conf or httpd.conf file, any +file containing the ".cgi" extension will be treated as a +CGI program.

    + +

    + +See also: Files with +multiple extensions + +


    + +

    SetHandler

    + +Syntax: SetHandler handler-name
    +Context: directory, .htaccess
    +Status: Base
    +Module: mod_mime
    +Compatibility: SetHandler is only available in Apache +1.1 and later.

    + +

    When placed into an .htaccess file or a +<Directory> or <Location> +section, this directive forces all matching files to be parsed through +the handler given by handler-name. For example, if you had a +directory you wanted to be parsed entirely as imagemap rule files, +regardless of extension, you might put the following into an +.htaccess file in that directory: +

    +    SetHandler imap-file
    +
    + +

    Another example: if you wanted to have the server display a status +report whenever a URL of http://servername/status was +called, you might put the following into access.conf: +

    +    <Location /status>
    +    SetHandler server-status
    +    </Location>
    +
    +
    + +

    Programmer's Note

    + +

    In order to implement the handler features, an addition has been +made to the Apache API that you may wish to +make use of. Specifically, a new record has been added to the +request_rec structure:

    +
    +    char *handler
    +
    +

    If you wish to have your module engage a handler, you need only to +set r->handler to the name of the handler at any time +prior to the invoke_handler stage of the +request. Handlers are implemented as they were before, albeit using +the handler name instead of a content type. While it is not +necessary, the naming convention for handlers is to use a +dash-separated word, with no slashes, so as to not invade the media +type name-space.

    + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/header.html b/APACHE_1_3_12/htdocs/manual/header.html new file mode 100644 index 0000000000..c0959dc7aa --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/header.html @@ -0,0 +1,6 @@ +
    + [APACHE DOCUMENTATION] +

    + Apache HTTP Server Version 1.3 +

    +
    diff --git a/APACHE_1_3_12/htdocs/manual/images/custom_errordocs.gif b/APACHE_1_3_12/htdocs/manual/images/custom_errordocs.gif new file mode 100644 index 0000000000000000000000000000000000000000..d566c5d891e5c574267fe715fc10706c5702b790 GIT binary patch literal 23291 zcmbq(Wl$VV7w+PVyM`nLcMC2FL4pK#54N}mx4`0yJ1i31-95OwySoS1Gk!sySv-L!2t{gJ3BioDLsL`yXJ0O0)1{Ox-4`A@tRfY-PCO=AZE*gL9gRbz&MnB z9Qq&JH|ufe>znELIQ!eXH|5Q5eEfC%Kdf)%+i>5IgI)p9*SC2559lj9=#?G%%KrNL zA5hRM2>J?oeH-u_rdKHF^(_Q%2>!nl^M5V;_bmV@Fkg7Ee?VYRa7ZX5EIcAIDmo@M zE)S?=?}zb)E%hI>JG-Cl1Y=Q%I*y#`E0o|P?ggkMS+R6MMs}I7)P&C ztUFkpH=M+7Jd`$Qzf}m!8Sm(Zo%Ig?{cEp*YQX3Ke_WfFC64K?8B*?hxuuUf)0Id$Yvu3H*A^@G zeF~Ta*;W^%2L*}Ng2=LZ~8wWJhbLJF;c9sT7yr0YEr;}bi!=XPniz&@kaAiguXiDmr2`@ zf)pFrz;=csICvt~X6|>m$kfGxkFIn@+*t0$ znYD9dE15i<+qu6&WSSPUC%Kp6bLZ+Lm@{Z0DXXQGM2k8lzNkRWs5&^{PMr(5*t&Qz zqp_?e6N0wiP@ibUYSQSKf1E|c+P~5=VJM}U6xB7mnd*UjSd_nFd2Ce2q%33BKDWnU zn-)U&OqpUd1Y!C6jmPt>hXAIrOXw)iGiVzy#?Nn=1qgF|@xNH8Iv~ubt4+qm9RNRruf@{%jA5#~AbbWfa{+k%- ze#6K0JKv^Cur4>8o$-nC>ab`JN$>Wd&BJaqcX`tu%(|R3hxc3L!$EG6t-yjR_Eg7F zX~Ws$ab-X2(@E{T?bB)Fe)-c`>)qMYc?SyH^F19X2oZ3a^UVwkn^f$;RI`95m8cx1o|4j zL=Kdry~qS(3m~EVxd+l+4q5QEQsB9|iA#LT4pN9WBI+&dWs;eMXr3$}(-HKcnZbWr*Lu&`IlKA4b-ijZ_x$otLL8FtC&o-{C&(d;4$Mw7fn*RH z3oqJXB$t*2X4oUpRTAVTYe2lrC-qG|#v+3&mkP~d@T;j(jD_qDBeB+yc5`*CsTYXC zYH(QY@iHmJjf_U;q3i6>A;~Iti`muUhfH)#3}NdoaTEQp*wkg>0=X%xnzW>aHeT`u z#y;2E4=wY7GM_mikdRx2s7A{8mB@JXhr6X2r0FIG+(nt8F|D3XgP zRxKcdwHH9+i#11!)ioA?g|;^(2ACy6t&DTk(3{d_3MTFOp}Be=(K6eJ65ahHpcB?c zx!Y)o{@u`g`{PZ8FJ`F$%8!LEvfIiKxl$wI;e|ed+p6e@QWLr#i$mJC)ybo!KU?-& z$2@LpGBL}{C4VeUL2qjd<;pA_T-5^dl=F+1wM7?tkLGxH({3B zbMyOck=->8NR(6Hq4@#D0UtWvmpc`Nb?s=+HxF|&AhzP^9eLcfz>jnw_E@c8ge0}@ zzCTB-4*Q}+J6W$lmc`9bHLpAp6?92+AhG$-ZLyOS*QuKC({vb`aO>Lf`G%5KsyGzZ zinZ0gCTxf7;kowjmI$8ElG zKhrB~H9nI|$&^ntSNLOX47rStt{|vP*?uzNns>_hM#KKqqIi#ZKQ`RO>&j<#z%+Dh zS}`?-fm&$Am+>e6uufuG)M%KWDq>0lsd;S-9R?gVRVAE$5m!P=nyHOEXQ9xTLsnhu z;jTwTefF8-wWF7Y{5W62ub_O0l81C6R3-0hrLa6_1SsxOn+58 zrNsd^aSNa`IgvJY5i91Z2EJ3oz>dIBS&*^iV`tjg9;$TlhU5X^O8#2ywM*+6Vur_R z2~%C`zaKIns;f*!7PD`!7Aop%?=m~p4=M~!CqWJD0adKODqhNl0@m^I1N%5zr-irN z#|h!TV>#x$dk=so;a?`{)sBZe@|@^`p?Fw(wS?)Wl7R~=Ypm%3e@loG--!T>v4(C^qLN#bIJ$AJq+**L=K z=on~8vPdLuTi8+OQwAMersOm)vqkA=t?J*@hUD_1ZihAod1wQ)yG%Dc5a ztsXwNnlJr|I5E@SYFDun9PQRquQKk~j-_>EWR12N_FS35Bj{)tg>8a8m-4d8JzRgS z*fcA^hRS(7HVtj;#ctEqxzG65T%#1y5On7JuuTP>EAIOczRuP0dhV!=pDh?|9BCw7 zUp2s1hJS8cW=3VjPPW-IA`9ffo!bkP2wlxvEe>C;IgX}|?0>#AG*%0wqj8v@?wRUMQBmgNYneFk^H2<^sP{iNYAaoFMb8=VpD z-ANW~PHBX5P{2%@0oxPcYYBJrS%3ZzxGi5eh0prJ3x3p^j^Et^*L?$|lXak3{`!Ud zswBc68+|l2gLZNP%y#*^5Ch&Niik-CnUVxM(qmgDf3r?D0UHGVY7F+03U=1~cEA;6 zz7QOs88Ukj?0aBy4hjih2wCwB`75g9e-IL{8M;6bnwT64<->C6)xa&#$|Qkg^FeYo zA^C2Q!emHsBcyZzf<+WiLKs%f7gnnoR__+pm>kyZrd`(Sygbi-55@kQ=vM((*q9wbMi zO{fjH8RA^%43TJz6h>ZaM%}ta-6uyqHby-!M8Py8RXQSF-7K>Abted;&b!^y=&-K_ zFt8q?aY$qE_+tpPVu;*hRB)n|gTld;dhL9uaFzPIInlTs(W7oL^eM57O|i_2v8)fV z#nCbFp`q~xew5O{Gbv#_04B9XELtWhJ88Tqf4sO>{CBMw&ZZayQjaZ-xN%;%V&Aw{ zHDNpo0Gfq~e|8|oEf6!56YDU+-XVSvkk}xS*kh1rl#*yk8qX;$C?e(f@c~HY=0|KF z_nu$oR>Px)2zA02purD^sF*-kmy|dGOGy5gPzFdeNg*xiNUkS^b{(u%knm!SlHpKv)I7~?8PoE7% z&pk}3+(_GShwf-)6c)vB-5Ut@#n|zE!@I~(N(nw^021HF_a-TO?8&Upe1An@3sFq) zDT-bW1pGx!>$`JmL3ZvBO&l3S$6QKZDoRUPOvbZJ-(*N9gk+IwC;qKWClJWkBh99? zM3+v<$h}R}$P4zr$Y3T*V1dab)h$|82mfFPStW2ud;kIAd;vctV};0aP!il;^F3K> zGesCu5<|(Q7@=WJSwxmu*u`1np()aj$;uG!G_5R>Z5~OP^dFEs14yo}KzfdJo)Tj| z74$8~I~HW9*T-|rK+6ZSon#8gG?Q>Cl2Pk_qc+>Ux~QTx#I-f0B5G%jAi8by*w-}t zLf1|=W6Ur-%8Px>HD5~C(9Sc4=E*;%3`(bbgrvzG<)x8jDQFYqG8SP#v!aXhOD&<+ z(2UTa>~HiQVdg+*j}jtt6TNw7f5}`}ku~J8#8(CgUdq9@hocDvh>+#-dw8H&0wZM7 zqaKUWWy<0hi(wRKc~h2o8QNtUkTR8}vOLC=WtpNS%c3I2@*j`sWlQDkgZVaOCDlto zM>*L{9wjctC8M)Crh6s6w^jqLgSr)=M{EEOPjK~aAQse00&XN7bHk10Rmvl%qJ&7e5cs+$eW62*k6Fx9Ue1eoER>YVSGUSn z8P25^%$J7Ntqj(wE+q#aCaWG7>4nvYFV-h7r5O&_TMd`9=rquyR+P+HpJGJcz0%%QqZT8I8c2q*N#lDB3wLRpF5yDC7VD%qnE_#%?Se1!$Bqp^qC51KMCW(`$ z1UpCr-L;$X44Rja8#l!Oqcm`Bp*7K|3OTlp2AdjFTbgyCZo@%#WFh|Sju$tL z1v;(cgmAqQUl7^h&QX)AQ?W3cTBZcsW`?WVJmo!)wZrY3qmFgkQIlJdnzm|MW6;~^ zwAv0*+mBij=a&t$JZbEuN)ad8&hJ}wxT8o@{yw(+eO~?xd-@9??|>KTK-BF(_UZtp zb)dC&V61dtJ$K-ccj5_k5(vea5Vz(^>WxTslCN}rcI0iXS-nEfOWK%EAY8iLJYL;=Y25;8S_2Cje;T_*$a_SEdc<{mzI*jZd1+2`17x4! zWk&$=2D30~a!vpV z;UacvLxpLBPUOSw&%+&QeKjk-xzD{tUL!%JgJtYUD%S9-CnNIYBU3`7u$j{QXpE8^ zuVIbY;X!Nowdc{Xk)elo0L7D05|zH$w6UYsF$wq4qwTRDt-}M>@CssY`z>SR&!bSk zv6Gc?*z-6+Q$MW-s9twSUuhsIZT!(|{7!Zp%Vz8r1MrM7L7+ED#DW1Y{EhVecvAR; zitgA3#^_!+Ic>+73>p+;sE8i3VR?}c%cErqeL7UDg;09h%wn3@8@=qd+aqrjC1S!} zw^yxn$nF`Qs*IGTZH!Z{+|;U=aWyUeVMeJeo$n=Cxh&DiYF4XlCfRdZw;4k>eY$4C z^7rnvzx_~g_>iMDd}!%kICdnoh#A_|sT`Tv`JyQe%vrhgSr0i_hPzFR&dWTx=k$l+ z`4*fxqxa}p7z6Rv6aLY|EwX*0a=m4(Xd~7$80n<=dZQX`b-H0wZZGK#VGEya7TBbh zdU56oy%)g37$xZorIpjRi~0dxBW#M}>((=9n3KsdGe^v`bm>K1ZS&C#OIfQ+a;NhZ zEEu|avmKQy?SR$F_ke0lLBe_c=+z!2@=21b35?T;Ht+FYZBxI{8%&31_RD57^_KcE z>rJfI4Bo9@3eTSF6=@+X1)kRRmeoDT&FXl}cgWSzv25JfOslo5BeAYlwNCFlt=ecV zr|9;MJx^e_EjOHwZoi-HmfLWNSW6mAQ5ap9Kdn1VU-5>?mCHPG(YDtgTW)Q-*LR+7 zIu1{9lrOQ5Z5;^LQ)A7(p006!Xb}3a4I9~bzqgUtI#j~E7{@Xrn-;_IF!w^f^iF^6 z=jo)@oY<0Zr3<+*ATX;qMwq}G;eUWPO`jbg*72Q zW^Kv>G*90V9i4kd-zCU(+7jv;12mj01DD*%R*apWkwIIXv(p|fs8b{v**nD=sM zvbBIF^Ww{w z)mQnmMAnPy@_*N-r-rs0XdnNfV_&_q``3?k*2lUa+CDP?yCA_nXT<(@vhwflYylj7 zj{Bv5_R9sA-64L(wOqv+iNf^x*cG4f4dTx$IG-z%j2occh0ypJ()!Kkzhk17OrZv+dnt-rRig z$+sPZM{j%e8FR}qay>y{59F~O%6b-neHD*=b2@gX_Iv%Z{X|E5&+Yei zPuZQz+R2CCx8KM2rLZ5mGIn)-t~A&_ww&)dEZ?21t#|#sWIkOpe$5;Bb4B^(Id<)_ z?#F#^`AJ{Y^B3&>UWJ#?^^K2FBbKAXRM^V{r?b(2mRi5U3bbxreRk|iZxw}Lo99dU zHn5tr>r1x8gTMFsaF^mNz3b~o=dUZi0054Nrny^4a$)1Z!ofX|l!0Gbiy_2KtEg#k z@$dna3{8N2VuHdK$|zz9)do=DL=VA4p1KS?byBUYn2w&%$yey5n60JKEJ|BPR!Wm) zfu}-pdN#t^9>tKMVwMZC)S(}#KiXST`JA7OF1yag>{-4l{IvTW_0d;1ZTDhuth+ss(gEB6 z$%bIE;Y~|%7L26}c|MX4isWay2uo$F2I7&6!Zi~l{<@pk8xB(`T6+%VE}1LSZ4rfD z!qHY?)6#>5po~RB0nEePWxY(rVuhliDHjmlinTVc^I1Zs1F_a9bJTj#Jg2$k#51z) z&nWY>)h*skI_=^7H93C)U9ht_%S7W%H6+{$!ilM};jNOYI1E;lHq#XZ{;3W+~Lu)=IGAsDzO}rWkdh0a%*regljxZ!U%> zR@nbR`Gm%0h5uL+QB#d0f__@{B|XFl@&e*bbm0i}#ibFJE$qe-pw2?T#b#96#**GB z6c3aEgl-xx6Evt=Vw52eI;mnxt;;gXOM?B`L)WNc_Pm%?W!z_|v;$uywpg%saqS+rUaEf3v8bJL!n`riEL|pDUDdQAg ztWMe#!Y!$yRD>9!eT$+x5S?m;Tn}Aleg?!+p4Hr1V_Zf4vu3w znhSRLE|^_6s?XZdD?ay#yaSuKY)-t_;*ja`Z4`(u0%NjZtib!TF4&8q3SP*VHrabn z6;wLoJ&Csb(+_v(gQ0@MPy>;Zl`@ps-;RaY(ctx|!(1|Hab_@XFF{gk*x3MF+fQi@YHSi0rlJ0@fm;}%>|rX~{9$FL8eu8jxBaMB#z#SA+xv|X)AUfGYpaJ5iXcvCPzGVAimxT}D<_MuaG7gooro{hq&_gfk z08uWbB&;y+Wj1mM(>|dj{(I2N4t5APVx}S;H}B)hc8IXFrh2!2@SR2) zfRJbwnxb!4R6cukLy@&47a9DO4;OoDFSB#Wa%Rj2Q=A@W8_n&DUJ99zLD@$HZ-6;m z>SduQ;VlPRrWY7f96<3+H7w|>5os#D1nuY9OoI`@T;%tLeDkZ}A$toMP8k2vV2>Du zo>1m|j+dDCgcyU7ZUlJ*nE)9f(N3h#*5WHJ*Yq^^2a>@@CU~j<_|93*kmivOxZ9LT zF2D#?qRkPuDAaMcp&V4ey%K5WLx5+ba#Wt`H}04_nZ1Z(WEP4bCN+^}38T>%yCVbs z#VKxWgCcRRPzb_q=w!ISHp*SizVH(bu3Zbw5&#K!k< zYBTDu3x9V8K=hwKO?q=?PiCSKk_c1GU|tmUo0eB%m{xA%=z_Si6b+R`9*Ln&)L`}I z4M~{OF3Y=^;nZ^K?2B)7-eg_1S;fv}X(E46b=d0FcMjrhpe=iin13Dv#U zm~;#9uOb&&n#b z`5)kGI5wJo99;aGcLy>W93sr6DM6Lzy8_%}<-|O|M*Q&qpb4ik~dLk}MTsP5RxO`X`4NsNSe*6p4jq_OeAf+&D57IB^7U%NIkempiuWi^B^v3K7V4q9I zPM4Mki=f$`iA?2A1U!>b3J18c&%!K2b`FPHc$RdcGEw*#zjlsSZ09wTt0XFsl1-Mf z($c|2`vY1R`H4I~69(W5o#7cL$k`rJ`t2wbbIkR&P;$$|dF#899RDq|bpiY^K@tU` z;HsQ;ZrzX4 zZLFCdz!f%}707ocmXz0aKqTKVW8}qOsZ6WCL~mIq(9c8SE@naQzdZ77{#}`@aFa-@ zQgWTHCZBd7b3{7eWh(lAdYJ6(`(U&sKT7TT!)xzrPM66R$Em2MCoVtl@TnUDKoyS) zw6;b_MQY*io1%=uN_%UrV{0tq7`3N*w-)=&+A7zgb)q;!G*-_kbEnS!#8Pw@MO!iG z9XpRRZLml8_=A1Fs`puh3g_9J`{{)0yJS3EZEX6>*jTs@t&{1d(9idJ?{K=~6!~bv zzw%oKip6%a+CkVrl6NDo;VngT{O-2tcGkzMlduZZ@P2l9|7^C)4F!^KoyabA9*H`A zo8Gx%gHN{wh|R>%bMHPr3wYJb4rUT;2TGA~=Zge4{@VtM4XpHSS!}5S@joagw6jIvrgIu+)b%K)0)B3+VwkVss5(_WSOiaw2q_Y1U zMuGg2c6e2QZ^ZBuu`)?Ba3a2LUPOHCxR%lek{d|sTeAX&z70p{q66zD;07C16cDGLb#J-^AztFPHnAZg#{Er*e~=$UoE*V z&u&HF_mCh9zJNHz0F{6MhelK(2~rw2hn=Kf)3m;edx9B;Y}D$wnD=fQ)oOBgnsmI{ zKB~XNs?ZN}50;~^E#TJ4b2SQ`nDMfDFZ*EOZHv{fX9qeumT&he6 zHzhg5tgV$5Yj*kuYU%X%nIY_SVGl?r&S4DFu?f=Wf*^2O4S#y%IuHcZR;EBWj?KmhJ`3iMVE zzoIoHwb4@I_&9|JHY8oBBk@!Gn?drou5?L(T4{b3$rMqKnz16=F|-dsk9-O8MX}F7 zFkk}lbBc3BkjZtBNevGY9XF*vJlt16B>#gRry;$$t79E~Jh5gB>48BzQfQSDepg)( z{a}1DPAoNQl&^FY*gb*KJ#sS9##1x8Ch>#dXQVzc`Yuy=*$s$wu+$V-K zien^3p91f_NJ!}2LF8}PVr0Kmvg%+`U{P!l&?leIXVVO*GMf+>lnQ5nBq5gA!;XNc z?!V+rpRMBPf|$fBW&D(5`=Ww=g=_e;USGH#_>Cla0GRNU4V`_6nUzj29}GRbgA?S9 z_N4Un2RBa-q{Jbj>Y(p&v1d|swB!`N+V=YB?Cqds+>}I4K}keeZS0hcO?Q}% z1OZBL6I@pDX91&g2Qt070szUszTSnB#0ZtSDF~w4Gj5R9x*^8|ryblXo_~vM?*XZ8 zf^I*3#Nx>8HP2+zHjkUcGPLm7x5&xUw6T^>v@nKeS%CbRiD;7+aCJ%}H1`xE<%p~G z1P7tp^wE*iv%xHZIe`zBsE?T$cLArAVA=z6&VL+WBVyqVqcZwGU$b3C!MyCIX>N!? z`9!YS*_QpBdA}ZU58@QzDc^gz0Z~LF;87FFQS!w;xe06AGNBmfQv;bgINfJ_E>W|; zL;M}3;{_XYhi-G7AVpLhh!eGdIT z`141aVHvp~?TPpjp#j@WhH`{s>}v^sd>|D%83d0p?kzyd25E{SdZ?Q4Sv`nyD8_EN zh%UKqBw6rj+PP?^eou#G1<2TlVb%AUx^-k_X#$91odtKMR_=`s<)1V_6t+{Mh?zYI zwpA7@kSldKs^YA>U8%cXMNXJnUW$+D7?1?B@(aFFUBDIOuBxJ`&Y zi1m(y#=ca_as}*t?vk&?p0v%iHp3XI6i9japP8SO>ILe1D!qRTSk2eF;=xrtnB?#xhwpLA->_2TQUuh-Yu(U_NY!4mu93Q z)@fZg(SlCs{lkguqmSk>0z$sL9p>9$xU~M~YOJ_&Ql~BI$D8aSRX1uO$ zld{>@YCeh<%?S)-|E|ok4B;B6_@}K?y(AmOSS`s|q=hWF)7Y~9qa#iPY5zy75z`;) zK-I@$`n=)1?O-lt#ZUW!+MUZ4J31QZ;UPZaiiOkFd3j|o?~15Pa;sE27?@Gz)atXT z+i<1*-Qp2NgFgx;1=oe-ir$+vq#ZSX9a6~9>9J($XcrGM<&%Xmp0qjl zHa|F(Od-}S79;p6HSvwK(@wxIDI@nWXhcH(fQDriqs5L7;a|w)GMJj2w?c3`iBtKzYIVA zlI@q#5pYgb812zjvmO9ZAPs2PY)RraA`^i{27u%-qq&1_X^3#joHXnjpH3@s)U%RQS(XkG36;$e7!{G!3QP@6we;^>m4GS{C^Hf6bKP?5{*GY` zegMaq)`gL$V1J+(`+x)3kp*stkL`z#ZKVPC$WhOPP)}CIj&#R%F<|2zX&;AYBp=0d z4aj9wbxWju5pIJVe8>QD6RGE(l^INbWOfVlazsGrNan!`;_S-qGkv?}TG3T8e}9a=}Th=ENVpfmGg8G;Op0Mo<|}rx;k~ z*wf#=r|=849#O-nV4@Zdp2|In)+hq{B^iy#>~`auBfs;kV1);KC2y)oFD}PprRSiBB86#V~^hz8TiV16ri70ZFE=^@q1bMbJ46An2 z<#&fk3S{!S)$pzs!n3|jqZ?f$EDKbY@vxMzgZofg(G^PJv51I`pWah*FDo-;i>PM{ zv!fdm-Wvc%AZOe2&t;&J&F$`>onYz@GtFsW_HniuO ztg_|6*`NP`n406~aW>i7HqgFoCcUhTyx$3-*umFdh0WV+LOGE5*d5WkIPZ9VRU?=}|W(pSD` zY~abSUhD3NoNeHI+4*7n{;MxLM(i4=3RPgFqA(hQ{18xN0+Akv9gmZ#%n3mVAd7+1 z-DB00XQGiwu+S{*t|XU4i(Vj!Tn<@X9C&|VWV1iavO0iyJZv*13OgDVUIm{KjxHNk z3IA-vI{CY1xN;8$v_QBa5h&kz_X;H`Q(fwgTO zrf>lrWj~vN0A{6+?7{Wc{8eMfYiE7$H&OIqn^$LN$YU#q%;$uxi^t64{bk2GpOElk zMbw<76uzrCrf%Npu@8>%GEUS?9Qy+AG@}X-X?=NvGA>v)PE*GwDqgmp15}&Z$|xaz z{5PLYMBmFq?zd-NzOE6=!6^9gcJZ^DzvBI15ogGYa~fK^m0>MIhTO)=}w z1T&K2&8Fgw*8>v$r7d8(I0TD*{dWa3Yhagcs5l)MBbSjv+Eza2j)>_EQYd%|q%|}W z69Y3PRIf%yF~r+l;r+;yvgN4mNny5eOrU7sL6mB^n?6stDKA8LQi0bb$&3V2x z`pYKd-g2DD8Nn$VVNal=^c5K>EiD5M^j8QBP?Qb;Z8-u0CMJAcJ$zM7J<=Nkw;rRD4WqlKubXYKyJBQ?Y<%MX<=U=q zY;OI>wS`rv2=N5)NT15E001=p0y4MK|1N`q1fTE1NN8j(r4^~9LeTW#0}rR^RMK%| zxM&z>@ey;_m4_vc)mb82JYI?enUmS$Xnx4^_y1qAt#nQPXzJ`#Qw?uGI-2`+eC<2V zf$yQXEN2XITM83cGC@EkFe46x^m`(`Gag7iqnd=$JCO4=u$qYNXNNq| z5BG4Au@<+hqt)StiuJz>g@r2B{)L#oS-y~G}Gj}a&8Fj`|q5fP^RKJptxat zyn2$PZcP)7vaa*$_j%49n!*h*2G4=PPjK0l zF3f*wr1tRs(KJo3-ll!1+uQyPc%<`aiJSWhpD?99TsE; zF-FFQGXyR|25+bbAkhrSBF2nEIq4L$xH~j}w5F8&Qf%ifD~YSg``HK(D)bMdc_&e( zHH1?;%&&<9kdY6NWjc(Tcj+%GTyZ%*ZOAZMTo4dHtt3@6*B_vzd_Q!xQp>_zE#{mQ z9b7__-bkT<9?k4XRP~RW3nE5P< z_$d=ROrRvqWd=?@i4Q-cnB_)BN~LaohYGQ+)_EU}yIEo;cJ-e5z_OSk6O}d?M!e%Y zK1NuU^TWu4rJh8?tgByD!{%mohlFmx_?Eu2Sd}Hs6RG*RSwlQ}qK!%1#3dtNZc=oC zEBV5=`$o3)YEWg)vNVoZ%``-n#*E1T>idW&B(ual@Kch(XNumZk@mWf3N(^cbl`U; z<#Y<5F+M#tv#l^s1&M{rZVg?i^XKE2MD`_0cEFQGe-rpditD5ZMo#QNq_j6cmCuC7 zmzto*4amf@Ht0mQ493|AHTc3z55`i)M*HrtabhXXE)Amyb3yi8ACIMpSXhX1y}#14 z)fZubNI;}}TNaYAq%hq7K#b;9v;%tA`yRnvif1PEhyYh96ARnchX~j{?p8 z!C8@!yUBJt!30vdwH2p%@`rR7B_Vx+(X!v;(`H^;&m01)wJ5+rMM!lhOxi%$1G z;Ij{PMBwzMU;HF>m=<%0Pr~Hl-3Y_)j*GcT6HWe*66R)Rlw(K*bmBV`}bl~42c=DSc*Uf2`}9gdU7J$ zh$wBm*L&h{nL1H7XY!rTxhYa8xHF`G}0{fe5F#X&IW@Fhp2LiyZyuqDgs z|H1k?hhp|%i+N}gVmkw*{ltLJ+N_Ms{wWbuhsn}3aXNxQuQ@l<=%9nanNfM4o7TNk_tw9=_##t3X|e8{vtA|MGklJaO6hEaR__g1Wn`^G)*+ zw$A6!)r~I=jlIHFu1TJH9cZr2`+?;ygC#3_<-|=>H)kHbo@@6I;_CZ0X~m!XGoJ=8 zNuG|^`L=%OpS_WTd(tbwi^Hpa9)z9e5%!LxPjeMR4Xu#2ZKldF!<)$YcAR#0x6^m} z*yudv7+5Es{3BaE^?ZNX^9Oy7LzlmQvuc3H$gOjGl|4>lWM348Y=SWHIAj;Y?Aw0I#82DnoIzO& z$7IsPCT`0wgbgDfT~mf#(mB1iSJo6hFIMS#b9j|m9UbNiw2mf}#~rp>YD9UoSKB%T z*tMsdJ(3U4YNH%|?$_2oTT8RsBtlBS!EB$qPj7^=Sho;SxK_m|`i` zs4-XbetsNAulMn2cYVKa`RuE2{VVLgqH*yd%w@S$ceHj!t2XI3qNeX-0lS&2L$<52 zB#ptXnJ*5BpD%}xPQzEs5GPM3HDOas>F>XABn-!UjDIIede35F?fTt*m+hj(qCYT@ zMz)ld&|3mH;%VZa2lD}vF-Y!px=qczcl-dp+a zIOx+lN|N|&Y|-joBw7Od>=s;pcFY-Y&{>U1XdL6kG>vSj57Q2cJamq%Nd_M;*d8_7 z9(_0C*pIvz&?Kslq)?AWTm-N2VL2zey7EP;@kH1)MkqE$As>RoUCjTQ#&|o05^F_~ z!5AzXzel{Mw~(j@nG}YFnFjdpnT$0W`~_N{(NjfF>wsyT?IZHkqei~W)k|5Z97`Znm3MZ6o2(LdUR9jQ2thTmL4jw#5$Q;}nY zLrgN%6FtE9!uF#Cc1}>Xxt^!xjXRXZA!t@XokB{7$%Ep;kjDDj< z&W|SW)di~c^O@MtEJUd^IjY}mI9>n(?#-esYHe?x6#G$L2A`xqjT+gkGT!76_ha`z zD-CXJ9y#ns31+6~uWCMZJ7Nb(?oBhCi#5w#2Sud);5zKStn>}#JeiK+~$vx(( zH+xDwdJ6FQ^1J8hleyEO84%y+nRs|_slZ0Q0w zw0xT(YZBKub2J-wvO+)Nyi}fSQohg;lMuxPGg|s!PIE9Ny*=6kUffX>mqwAVU(tuk zqSDHu4>;s$5X=lRz#jpcWHN}KDwxHgc)_4RGBB9gEdhuW9MM>aoe=X=DgfCf2o6+I z<6+h=lh`GLnYUEbtyDUTQ=Da4ye8r=ei$U+j%D}=i5&#nXqEinGp`~m1(BrHH3zL| z$4D{+$`tW&Uo5LmOK69hwpv zcDZL;>|vH)WEVFOWmH%Bnwa<#sj^Yp@>$bzIUymB&oG}q6$PeKdB#(9;!!^Iwy`Eq zTxL*BGh99_Q%pNteR@>XyHw5kgvR7qJ#MY<{s zWd33rMkENXTd37}0Evav3`48aWvbnN6w{?PFdsK~JvDGFH&9xY`n_w+D=z00Yy^8Y zhW==z32S@=#&!3`yFS!wd4_9R)#El*Bp=twhxtAi_%=(FRcV3`O)Wp|#oG_Z|9CL` zL>v6wDl*C?y)h9Iq*Zs>XokWcotPRa{t#1#ZgnVC1KXErjJ0YEL9ZDKE9bRpWIt|= z9&Y{pgyH(5?Gt+2f=(kAPwd}R{UV(@h6AHOYDXT5#woqF?ATYbzGAqaXvJ6zBBXlrx#o*$l2$D zm-!95PCsXm-An!JGuTzy(&7B@*J-ioFEpy{pv#NY^gg5nwA`Vx(yaKl;(v}G5%2sE z-bzm1HF(_UYSl)(g2A2I2C-_TDQ)HP>@gdJRfv=KOD5OJK9|}acYG$V7}@xPgokl# z!2+e@c(e$3Dvk|wAK=7j4z@@Ne@Fx$cJ(&Kg^|@B1P+8V+i*4|$_Ylqd-X=T^(*XE zI1coBSamKfH+Vj^QhIeUwsiVG_4*1{7lwDP3^$kyHCd%bg?ZI$rVZm3B_pNvC#NR0 zhDX5j{)sts#zTY#uk-{~mM@0BOHHVChalgk_ViZCt@uq!*+kT(xE-b>G^Khs zrlb^(mRO7~p^f4T+BR8830c*IrdE6Cj0=`jQ>Qk}>(qP>8^4zw4oj^uldVB~Ujqxb zB}Pv>)=k~P&jUf(Paq|2-Wg>)+M_J`EXjbp+;~ky*K74&eMTleR}K$KhDzdmi0tuf33}4MVT{y@2G_-veZA~V3K3; zem+iPhCj*qpQq~AB{wF4T*uYtL%9t zvu!sEi4oR@mVVFEc}c5_l86f(`-|C_i`h>J&Jp(74S|jVOQmg6nV2qR@0ZKpFDfK; zYcno4>WPPznKrF1BV8{|A1=eXSon>+DP{#$1|qn9y)gz?S2V;5V+I$;gjdtSxk8ew z3pU=hHuIC5i6azV*XYZO!fU8qQ*h1Qw)@?_l4~a{t8YG3vhUvChMazlZ4wK22kPnc;

    NJBr8l*+>3!pZ>`f<1VQh5z!dWX991Pqv^fncj8Lo^}`!@J!yPhY&c=(sd8HIpRb z>i+~18tvtVj=h{+=4IfsuIpCz>!>+ymbrrWnCiyGVAuNV;#Na)KG}b2zr$WY-t1k* zT!rbL?%HKo&}eMl4()Df?9{esiCS;TsFZcPXVQ+z(U9Y}UG4^?S7U3o5lzMF#<{3F zz+%g5fp%a~mZ*{J?-BkhXKu!*m^ra~Eay?nbIBm^8rqJO1Ki{e^81DLLS5~{AREI8B_a865wN>F+B94`7c-U zfA*Ua|A6oU05CN;6@ZwixX9S(_y`#(IZ0V*d5M{+xyjk-`KdTC(9j@YdMY4FdRhP= z5ODg!Aj>dYTT46p@?vs0_3OK9GCVkF0*aihyv(f0Fj4|@xcd^IMWeO#qLr2PvVpb1 z#Z|`D#RVi%3?RZ#2v98uFgy5BvJNCa0x}p7GFWShpc3`~m|y@ffV@Qu1E^c@j$gHA z6f0W1{)jQ7#*K?ql|p68BP&<1Ox==2YnLu+)DA70GRuU)brU(-yopm2Om*<)F-Vbu zMv7}$Xk^i%C7e=lTzI++@GhRAcktvLlgFgT4+a5biby1=9g~2AUI^@`Xdyy)3X46> z2{*3XxpZxc1et2oM**!~#j+-F!97MkxbEpB<^@3;)g;GNhDnjp7NkyCgB1Y zg|)E+B`rE4;!BZM!sQN2)&NDBiQK(F!V5ytu*Fc=q~J{!OaTxhIc1b%&RZP4L*SKm z-ifCtM~0-=NJ_{c4B2DjJesF-E;#^IN!ur z&N)A9l*R`&DT->Uss^xUUaOdL+$qX2`6NqK%DHN;%-p)^7FleOVhWQv#~uD zrjRU9zak}GH*K01+PIt;%K;^q4NP#s1*c(cBxwji2E&z1VFVgWP0a5GXe9iS7h;Iv zg%pxVG0r$1Gh&7rXOw(0$|akuvKdU23v(!a;?=FJ;0{`=SuyYY2~6f~dK9o)1W~3? zB|5hqypjS%ri#gS#u+#1mf81`Pam6aIE)*8poYvBe~9 zX?H1Z0W9S-yr`y9qUDeU7l}J!?9wD)t?;wnwNZ7iM&4_v6pb>Gz zV=yuN7-M+BubgX-vw_=@paFLyXViV86ii65g!R~4AI0@&EUqo!uL}O>tT%?}R5=P0Pk*I7yAc?1BY&dtxF|=|CiMX=xmU zr7R7mMO^A`pZnY;BRmKRG-wQtj2L0afQJU+B{T~DXxJVd<(4-lTu-9hI~_Hxv`q39 zQbM_a=8rB4QYuYhTI9&)QsRe&^1J{GkmE)rIYYkz9_3!ta-tKLScaa|B8{o*4wsD8 z9m?Et5n{Z|P%oiIekv7TU+CRZA|Zwlmhps;U;+>lLM)XV-u!eEx-Qt2tUoBB91^X!&(9f zVT&DL{~AZY0u~Kn8^a`6o2o(3(D`GYwl4CEjS*}pbMPGG>r zi^Lel9l+pCl0P}*C`)+xI#lOC3wqGMx$}|58YKyx9K1gm}XYG%Z`F|$5Utu-?1 zTHiXT!a&4^n^dlBKDgu2ZgiFJ$n+ube(yCD(le2=@{x2r)eZjF|@Q^KG9S+BI)E%>iEWeGh!-{Qh^#18#AO)7;?WPWsPv zj`VvQ9p^HqcfUU#^qt2%*GB&~(Pf@>a`_s~PP#NNICLQ|3t|`(zxd2Q?sm7&yyQg3 zI>Cc}cazgy;8CAD-1{!{tZUojSob%;Pmc7AuN>ug2fMBf4)3Q|T<%Ms{MNzVc)KsY z>MK9G$}4~Ox6i%j`G)+^3vceyU!CeEN4?LlEq7|mJ5{4bG|mzoO(s_pQ4>FU+(qyA z%f~+F!VmlKHGl4?D?RL^Cw}CK-*e2vyy;r6e&c_RZjWQX>%iZB@-q*5>T}-J(06{} z#eZ{^>z(}S55D#OlP-JA8=vY2AD>spS6f3OnI*k26mJ)oaf+vO(?@y#wtkiOdeJ9( zT<3eM2Ym1cbUr74E;n@{cX&-#dhgbE+XjJ_ka`4Yc%J8YomYG)H-LmEdE-Zd0(f!> z7Ggr7EbM2Hb%mt$oo zE=-scNhpO2LWNZ*Y6!;8L)(p$HiY&(wte8x0 z$Y0R33>CPGJokC9D2m8Hiy1+R!nkp`c7#WGg|C=?@#c)1P>e`;jP8bS$!LsbQ8THYk)xjU%WG%UB8RR*t}kjIH>KrFf3PIF7#PfzPN3%t(ywSdIBOfyrQx zexnN82#^X_KF@TAjL47ew}W4IgGG0YR=0%lmx&3vcupsKGAM#9D1p!Cc`T@ks@H%! zn2eeDff8wpmnU$^XM-3hbuIXjBDirJ>5-fFa^%K=F$sTl$C59Zk*cSPF?f=&=#d2% zlm0&GbT$WhGe}LM-~da>luhXX-MCSQR**ZU3&S>S(!_oysdz5Ad^sp|jCXiJ$&g!T zf+snE)0c88c!D=~gJtQHCV7!yDSd7!d~}I#@V1p}>4MEDi(|=>c}b3YnQdc9mKkZ5 z!zY*&NSN>EfQH9?>Iar>>6Izhk1?Z^PU)0TX)}@-6H1mLOr|5931yl%e>FIn7WtSx zX_QxomVfz^1lXD{n1B!Yf)@Fejt85kc$=&FbaJViys2~Ex0kPpo6%>0vALUr*_f$G zoWi-4Y5AO5cbu#jn84X?$f=lHb(xsSl$vQ0dBy-*W*TT`m7Jz(&WL(U=bY4;{(}zr za`C5?>M4UF2cOJ2evyfgODL1%hFNp`qEY;5*sYt|fr_?8iga~!&JkNKPM zh@HO(g6s*SYDtR%sEq2Ef?3&oY>9pN2&DK}qx<-yDX5=zIgB$ZoLc#!YU!i9hM(v+ zZ4X*~SL%XGilnzV03q6)BWh&e$x+OqWPa9YmH3h%_U?*aoq%VU zaLSgII;o9mejB-g6}m_u%AMXBRvndQP?BSdMht06n)1hVIm&V_dZ9Q-gMpcW8LF!j zYMOwFtGB6;r?{ZFS*syOo4HD=%Brj~I;&Ypt15Yk3dwatxude#ke1r34{56_*>w&X zZWb7VFG`WS3YQ^es+ftYm1ao7;0v0jAzKz{`WcUpn2L{xC+V7*V!D|?SZZK+YG?Ol z^Gc)+TA70wjrb}g`r4H1`fD8(Y<*UqDta38T9R_Au%noN=W^hW(^l?Z5AC| zW^5aavMHOdUkauo`mu!bu#1=>7m{{-wswxDvN@}>9@4Q(iK_nlwTQSE5KmDhli&eI ziwH;S0T!XOO4|uYo3xJrwG=V6nXt5tP_>JYwOWg`P8$GT%LrTR2w4lZ7NHyEcCb79 zp)3og4y&p`+kgJYdz)~zUz-tiYqy+$w~(;6%+R->@VAK&xPnW#g*&#Du(x8%x12DP zl#sS+TdHguqCZQJ|2l+#8?|?<2!m_1l)$;j@VT16xuILPrMtL@Yr3JUwTx?x`UtsF z*0V0lOx{?cDj|f+aJ6^~wYgimOWV6&>$F{Kx`qq9T#L27o3y%%ym`C3#Y?urTfBnX zyj$zF&>Ov*yS&LOwPb6!%DcIF8wtysz1qvW<@>u)tNys?_@+gfmPq-!*eJQD%C9h_ zh+n8P%22kMo4e%8yVnc7y$iO@>%57pz546B`&+pE3%=6pyan991Ps1iOT5ghz<-Ot z-J8G&9K4bsz7c%D`rEx1%(>ypzI_Ru?^}p1E4vyMAxDOW0E@p148qKtz!^Nlb_>A* zyuia7!8LrtJnX28^{*i^E5(!=$^!M@+*+jKnhRqs~d6(}}{mT{yQtBhP!p#z!W^iQOv_Ye8+JN$4%VH zR4m7$tjC{R%65FZ#_PXxT*|Br%GWEzefzoLs*}anrHqWOUuu7OvBLTHwjQ+$mF&kK zjJ`O`$I%vw3&Ik7%zXUJ$BfJ~49&&7#G{IONIjz(FJI&KQ?bAOE)IlxOLrv60ZPYxy(o(pctFYAb z3n<^HXcThNHI%35>@GASQ*xB?beAf z)@8lbhvp=n`I(0zn(Fk{d(GFT8oxgap5n=7Qjo#_4-s{cY?G4=Bz1gPl5dlfx09hRMjo{0+aV6+>^^45(AmQr04icQc>6br;$u96Q zFY_}`>3?$R{s&L&5`X{_KmePb?IZu&vF_*HPVqn=+$b*r0)X)WK<-SR0Rh1Az+LGA z0Pi}Q@VQ&F>4)25R?=cVaGq3h*zwAsc=7Mh*duAOR0h_Abxw zY0vhX&-rNn>}swgnBMc7p7T3D0h^BP*-qTCe)XEZ_k5q{6X5s0{p(HN^igl<5}^CK zAMU}8_*T#O0ATeXAMcP4<7VI8lP>`k!2HZF?3Zus0U#^2k859bX3 z=@2mf=exiAzYXz<(B0jK4ZwkRb{8V4|TW|clp5>Dd z2muy@gbx4$hyo3Xhy#p|kdcy;l$Dm3my3yxn4O-VprN9pq@|{(sHv)}tfHETuZR$g zoRS0x0uu#&X9+ZFcq4-tonu>!TN00GAO7qFngg9sBUT*$DYr&x>PC5lIo5rK8M z5bfGUAOeAp#60~9MzUmtW(24SSjSQTH(90#SU_M-z`1gi+9i6olHWWC+6WQS$Ef~a zMTbZq4NS_ksne%Wqe_hg5vIghM-i=?U_loIW)Tof_&6+NCzEJTLP%LDZLn^qEC{lY z5|_G4IuY@dsL4@;uhN*611FEx)TB!fD_+dFv17$m8Nu~OX{-bZVm%_VEDD-uXq`Sg zQ}w{Y18)#;Udk(AuTRRIj6P17c((1^xO3~a6j@T%-G^DbF8rJ7qvF6_8BWf;x%1}= zd$WVCSU9}b$dw+aUaB_t@8H9WFHC;=_@>r-5^uo1z5Dm)Q3FIM;e-@cXyJtzW~kwY9Cqm8hZN4E*SU4&ooC{S zD5j|5iqyG7q9QEDDC3MY)@UOuE~=*ph&=Y_NG7S|l1w(~0+ zo_zM{=bwNED(Iku7Ha6Bh$gD&qKr1`=%bMOS`m}aW!rkr-_>8GHED(a}D cmTKy$sHUpws;su^>Z`EED(kGYni>cIJO8`nHUIzs literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/htdocs/manual/images/home.gif b/APACHE_1_3_12/htdocs/manual/images/home.gif new file mode 100644 index 0000000000000000000000000000000000000000..11299c1cb7ef6aed8ee4b159d733668de8662f22 GIT binary patch literal 1465 zcmW+#YfO^|6g_P}`hb?UfCU7!Ag=*RMW7WJEwIjlKme;k1}ab&2*DvZXLNHgz%i{n z3mR9Y7$rv8M5m%)l>+jRM?iElgAB@Rn)yW3VbpIQyFYGjZf@>9=j7ZC(Vxqt=^BXf zHG1$6}$N0HhEs1{h#YOn?T0#13OAoUz{88vFO7xf%Wan41F$ zvoRaJcqhiP)8UXvpx2|Nh3elp3tt)yQYqY^Tv(twRYGu5QmA5745xS7sN%vC{1a{s z7U)dSd_*{cTCosH56Iys5@GFHjE+L-f=rMsSmeS?r&Ew%e{enws>#Z~@)j zumIC+#{2h}RD+u0!rk4PIpKyfk1GCY3{@(^k);q8h6kaEb>Y6L*u-j1;`ym>=OC^CNoG6R#aAIEolu&@SI z9v=Ac0S6cyBTka2p5bF0qQfx|3Q>mmvzd7On8E;ZIamZp0a$d3K3w4Ja8uv?CFWrRB8irk+8diujrupK}iE_ zY@kvhGZRJ}+=V#;%wyR63m&$$;pIylg_y*4CvaEMkpMQILV`&FXyJUUgqK*1&`|8& z4XqX(9n`I0u?U_}PU8DO0!mMa1r!Co4}v79^72Aj8b}g!8YPH*Ff8;iKSh|WEf&(C z(cr`h*z&0TZGP~y0-Xco!zw2SazD(^L+%c_8{QP_{DWRay zqPC5P#YK=6AWJE`zSS(Lp2g!qr^CgI6n&x)1_HGAQ2eI7g!#{eSo^<)vRxus?#vc2+eTOvP+lpVZ!Fb7Xp_TZ}$yX4uG^@QEFF zco~b74x4EGT=SW}8s3B1FGN3@i@v=QY0yXi))o{zZvQb?bb3v{QCcKkn~PbjM$u?x|e0@l@=M028tTa{kh%sHFXdxbw5B@+uRf zLbgScD_L2eJ`owZ!g&4K)ATZpTy*VOfl1RSOX@8c7WAxXt?}J{%h}pGk+o6ia{QUz z;^6y7nz0oz_8e)L;bSmo>+=n!&C`_5K9cINoz>#L+btv3(IVtA4pZXeP z!q8hnq9bs->OPIf>C3PZn3}Kuk?}wmQR!vN-Fw$7z)jpE3HFC5=U#FK7LE*K1o zO^7<`VCbX0(zD%WI->b{S@oSgbeEk)Nfv8ob&B(6+z{}>FmH*;fy6SGG!wlpY{R&? zn0xbPdusfD_sLtamKk^=)G&cCj?2j;s*`)?b& z3j5o;9{pY@vT_cz6siQD5uWQ6`Y7wC>hU2@#@F|Lu;Oss%J__+(+aVruBm;cH#rjB L;Md}uqCn_>{mJyz literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/htdocs/manual/images/index.gif b/APACHE_1_3_12/htdocs/manual/images/index.gif new file mode 100644 index 0000000000000000000000000000000000000000..741c8939d77d2423d67beaaef8fe78aed13a94bb GIT binary patch literal 1540 zcma)5X;V`N6g^2EAqfEj3FHAmLln@6kxfB?HbDhZNdqfbC>Xlu)u%~i4fxr zzJ!Ylva@mP7Gz+zw_{`kMmA>_j_13=(h?F02v~kb=lD2<&y`h?98{sgmB3Y7|P-oTat3#t{+%}_+4$c(KApcmUwEFv-z zQkXL`K&NAD41LL%jpJryk+4|17MCw$Vge?%6%BNmEzZkPk^&wNT69%Zpr?mYaBGFx z2vR77uP>64s45aIBGWK5aSpx$Fc>H=$Fpa6{~i-r;BesXj$ONOAr>|uii*(O3=V;B zkzlgJbM#NBV6>%t*;#=sg?S1Xr!ZkcwKbR;r2Po9pC4}Apa6m=PeAfOa$!ON1AG$j zh6_Pp>QtnrqP`vf&K< z549Tm_oKBHeSMS{HZ?gXC;0n=57HGjc5obzg$HCZNX#%0V4HA7EJjceR;|MJ?a*pr zGEpUL#Eu9-{A4CRBah34rzb)~ariJ2p*5Q+h3BJaS2<8dY$GCY-~e<`mz1EY3jO^k zo)4KA%dtsDf&-efGxow99Ss==$;og-*v*@e5pX8JWMan->TKjp;NwTQ2~o8HCKZGb zSX)z@m74b=E)Fd%P{QvCHZy>6NCiy9$taeK5V8SezeUz8IGcF?-Sq!XUSE)3enHNf z1dSzHqB~u$VezHw^t#eUP4gzxutT0fms>j#+^N5MwsCda9aW;A_roSDIF{W-%W4<< zDe9IJ^V^)Fg%gf#8e7NfD){dmk4$i9+ z3Wpe@J|?#JZ;wr)%O>B3Wy1S4sR1nw$0VqiSa>Ith1sm_{3G2ep^>%Z_c_s9RVi!S zmW3Od3te~hF8^LNW7peLq~NGjR8P){yYT3AUrX8U684qS#d-3=r}mfb77*g~{xdST zq0#5G-!BvwPHC{gXqFHg@^6gU`rXBJ9o@8Pk$e;;{PdNFnVP8OfEo>nO1 z7mXPa z8}g=~3>^KF=R+TS?B~`#ta05FyyLE~Qmb1L%RCyJIDg4-`hx}DK{Q5a-=1j&PDfGN zb=%1CzwbBKK5gk7a(b1((%M*>HcMj|M(wyqZj|MUAev?HAi+p?Ve5Gc-)*d>$N*LF OiPzOh=dG1;1pN#BQV7)m literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/htdocs/manual/images/mod_rewrite_fig1.fig b/APACHE_1_3_12/htdocs/manual/images/mod_rewrite_fig1.fig new file mode 100644 index 0000000000..7c80fea3f1 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/images/mod_rewrite_fig1.fig @@ -0,0 +1,60 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +0 32 #efefef +0 33 #cfcfef +0 34 #bebebe +2 1 0 4 4 7 0 0 -1 0.000 0 0 -1 1 0 6 + 1 1 2.00 120.00 240.00 + 6675 5250 6900 5250 6900 4650 4950 4650 4950 4050 5475 4050 +2 1 0 4 4 7 0 0 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 6900 4050 7650 4050 +2 1 0 4 4 7 0 0 -1 0.000 0 0 -1 1 0 6 + 1 1 2.00 120.00 240.00 + 9375 4050 9900 4050 9900 4650 7200 4650 7200 5250 7650 5250 +2 1 0 4 9 7 0 0 -1 0.000 0 0 -1 1 0 4 + 1 1 2.00 120.00 240.00 + 9300 5250 9900 5250 9900 6300 6975 6300 +2 1 2 4 0 7 0 0 -1 7.500 1 1 -1 0 0 2 + 3900 2100 3900 1500 +2 1 2 4 0 7 0 0 -1 7.500 1 1 -1 0 0 2 + 3900 7950 3900 7350 +2 1 1 4 9 7 0 0 -1 10.000 0 0 -1 1 0 4 + 1 1 2.00 120.00 240.00 + 5625 6300 2700 6300 2700 7050 3225 7050 +2 1 0 4 9 7 0 0 -1 0.000 0 0 -1 1 0 4 + 1 1 2.00 120.00 240.00 + 5550 3000 2700 3000 2700 5250 3225 5250 +2 1 1 4 9 7 0 0 -1 10.000 0 0 -1 1 0 4 + 1 1 2.00 120.00 240.00 + 9225 2325 9900 2325 9900 3000 6975 3000 +2 1 0 4 9 7 0 0 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 4800 5250 5550 5250 +2 4 0 2 9 7 0 0 -1 0.000 0 0 7 0 0 5 + 6900 3300 5700 3300 5700 2700 6900 2700 6900 3300 +2 4 0 2 9 7 0 0 -1 0.000 0 0 7 0 0 5 + 6900 6600 5700 6600 5700 6000 6900 6000 6900 6600 +4 0 0 0 0 0 20 0.0000 4 195 1455 3300 5400 RewriteRule\001 +4 0 0 0 0 1 20 0.0000 4 210 1440 7800 4200 CondPattern\001 +4 0 0 0 0 1 20 0.0000 4 270 1110 5625 4200 TestString\001 +4 0 0 0 0 0 20 0.0000 4 195 1905 3300 4200 RewriteCond \001 +4 0 0 0 0 1 20 0.0000 4 210 1320 7800 5400 Substitution\001 +4 0 0 0 0 1 20 0.0000 4 195 825 5700 5400 Pattern\001 +4 0 0 0 0 0 20 0.0000 4 195 1455 3300 7200 RewriteRule\001 +4 0 0 0 0 0 20 0.0000 4 195 1455 3300 2400 RewriteRule\001 +4 0 0 0 0 1 20 0.0000 4 195 825 5700 7200 Pattern\001 +4 0 0 0 0 1 20 0.0000 4 210 1320 7800 7200 Substitution\001 +4 0 0 0 0 1 20 0.0000 4 210 1320 7800 2400 Substitution\001 +4 0 0 0 0 1 20 0.0000 4 195 825 5700 2400 Pattern\001 +4 0 9 0 0 18 12 0.0000 4 135 645 6000 2925 current\001 +4 0 9 0 0 18 12 0.0000 4 135 375 6075 3150 URL\001 +4 0 9 0 0 18 12 0.0000 4 135 825 5925 6225 rewritten\001 +4 0 9 0 0 18 12 0.0000 4 135 375 6075 6450 URL\001 diff --git a/APACHE_1_3_12/htdocs/manual/images/mod_rewrite_fig1.gif b/APACHE_1_3_12/htdocs/manual/images/mod_rewrite_fig1.gif new file mode 100644 index 0000000000000000000000000000000000000000..664ac1e7bb7a186d2c6157878cdadd5bfb7d3466 GIT binary patch literal 3525 zcmV;$4Lb5iNk%v~VXOgx0igf@000000I&Z50RR90EC2ui0IUIl0RRI2oR6u??GK}z zwAzca-n{z{hT=$;=82~2%C_zc$MQ_q_KoNI&iDQg3<`(DqVb4KDwoWr^9hYgr_`$T zip^@b+^+Wv4vWX+viXcotJmzd`wfrF=k&V$j?e4&{J#GW7$`VMSZH{Nn5ekO*y#8O z87VnQS!sERnW?$S+3EQS8ma{VAZi*%daBx%y6XB08!J0YTWfoZJJ_1b`?T8&tn?d9 zTx@)doUFXe+}t>uEKSD7VUw$V!fPAKs7Md zyD+KN9Q=3h;kSZ|nq;i_tyjVj)go#8aj#*#l1DDS3)(Z@%69kyPTY9&V!4&)rtBFx zuj2)w`FT#Zid9C@pqy*6bX(4r!i z`&oEWA8EOQzK;7h-_)wNdu5K?Iehubp{JLgo4RDqgZ`)Y*B;$$)*%+$dHscE#A{gb zR-kbH1*IQZjHxyr2lYAeQhMI0XB~uIWhh>7=EXn_fCXlz9*RV4IG20X@n;)YEyjqV zZzf#W#9BIHb|Q;WnUx=P*|kMtQ@s&q*LfQbkywavf%hMh?0vUnUk~7jP?lP5$z_*b zehFrnVvb2>nP#3T29{_Bqvo2uwCQFpaK?GdoOIS==bf|Usb?&FW&>ZKf(}Y(p@H_f zM*u!3is&7TF4|}vkNz-eq;FK(1E!X;q3H^pF7W53V|Z$>}`s%Bqu>#xc1iDTV{;D&&R{HCsu*yp8vByf1Y%|O9+Ux z-3#mecOiw7a5$cc3$nP<;RJq2<6evY1GyoR!%g|+e`u}&=de^Bx#tvsE~n^zl#IIR zpR0~*Af&ghHS4gSF8l0!yl#8wxx0e|zaD&_XPZ1tY z8sBI|GGg#PLSdr?;8?|v9qvbAnbL=N1Qhdf)ZUCxu8f|=>UjiK^T)Xn(x5qHnABbZJemex0KS7O!VPvHiOI4 zbn-}bfu$R3X+v_v206$;FM3iA0kfKH24|KF;HD2d zbRTN!D4cp3&Ii01OhUGDkjTWQh(1H1vfzgU==9q&4^*N+R+E+Z5vDd*iNt1}U>K-G z&pMFgA1Ap;K(B0NDE{eqOAToel@Xoi2I_gEdqydR`rKkX56Xbri1afU4FN$zN+EY@ z@jpEpr3d^;AbtrDV3 z8zUqoPBzGn7d>jJ2p9ykQema15Nyx@3k1VTK|6)@D+(rP1jQ<4rlFAR*%12!%R-@` zrqJvLAX@~_o=LR-!mJNSTPD-g7gL!zm2Ld9`Fd@01J4)Jd^-|4~*ahD_FpK zeC~oD3}HALIKmXJu!YgsV1Wo0zSMGWW%)}=5SMNs8x}F(JPe8wvkS$aP_Z)f`wAE1 zi^ZOhG0|w;2^${+#;(w@F?hTRA2$uhoDeeDh`b3Sr;WrW=5Qo{tO_Lq1Imq^@QRsi z3tW zla!qSrQ;asOrmg^adiU8P@2#pim{RgHdy&pneohVSpnZih{MM+D4kU zC~y|7O4MBX5~l_oW-smO?RJ@lk_OlKKV>uW6Rk7dx3zRr7OtcT<>%jfRx?lveoX$x z=KQBFdZe_y=I0URQ%D|_d92BZYX8EYstA5?*kuPLdhNN{4a+L37O=#vv&?H`#b)ux_e3j_lTMFt< z^_KH9>jUok*W=*KvL^!VYmc(nJUY4n><{pn|a8_Mtg$NqLd{;{RM z{N`_e3BW)9*f&SBU#$xJw>Fs)fcWPqKwyAMAb^pBGN!PAmeYXhLOF;NEuWQuNAQ4# z<2PoLH=vM#zXJiX5-Y+YEX+oNv~nR12PzWyI3ZXzD0nVp(<>ubfmgzUdgFpWGlF&_ zgC`h+sB(cu@PUH>gy7|aNkcY2$bl;u3PZ>^IruX#h=ep)D{q5bH~0;>6@*3Lgsw9< zOVfo2xP@_`g^1>Cd^0@jMl%9uf-2aCkoJZwvuWnShC1kmb_j=fh$Cf)Gyms@e+Y;s zBLiwkhi9mVokEClh=_Bjh%2**b+~SPScrj0iIo_L6S!J;!-JUP{)l0?J7e=UR%jt$ zn1}r50H7!}qWD?$w_{^ydmZ>JG02Ho=!#!xHFsl#jzfzM2#e^lgq`y^wHSdG&@o7J zhocjWyf}>B;E7ToiOeXBLGX;-(2P+aThZt{*Jz5RvW(l9UkK=pDv(^&_&=7|FyV-f z>8OscK#uF^9Pao9?Ff%BGml*$kM#&%_?QLvh>!fJkN*ge0V$9JNst9;kOygg{y2|$ za*P}W01t_J(ROnXnG_F69uygoS#W6?NrswMhZ1R#i}qO zhk~eW$~I857HZtlcxS*^AZ0@>`960DFwZ8FN0e+N$&o|;bdy2F1t>X`KzVFBDF@%i zX%N{*ocC3Kgpw3#ZVA^?Md=dlc9Ix*l~QSyLbW1Fxp-n3Z&In2V(D>M`4v{_lBIZ1 zZs|}?(jEXsC1@FQwqcepqD#`c!5cEh}o9Zv_B#TP1bahF$H$4 zL70&#cwos;;c-kSS5Ad#m|qEXgoSaU$(J5Sl51d^pmv!vQkgfUP8F`AC znin~4JV#Zl*_wQ}8h*zLE7h0!)_5NUk~TF=BJ^@|_f$%Gl;pv75wce`Wu4R+QyF&$ z&{=w;2~Kato!$v`MFM!8$#_o17KP`UHNsCEr+BO8iFncJ253p2huKnMr9p4WmV}8< zdP$yhX`5B4cR{%WnrV8Y*K~Ht9$^Wa26>6auilG?+ni*OG#mS)} zv7sL-q9aP8CHg%cYNDH&qEHp0E9#;z3ZpSvCMYVSEkL6+8k#t&qdUr@Jvt^g>Z3*( zq!TfuMQWr+`U*gbq-nLJa@C?unwwB6rBh0!RcfVIilteqrCZ9SUFxOoR{#JzTehj$ literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/htdocs/manual/images/mod_rewrite_fig2.fig b/APACHE_1_3_12/htdocs/manual/images/mod_rewrite_fig2.fig new file mode 100644 index 0000000000..facf410fc9 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/images/mod_rewrite_fig2.fig @@ -0,0 +1,50 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +0 32 #efefef +0 33 #cfcfef +0 34 #bebebe +2 1 2 4 0 7 0 0 -1 10.000 1 1 -1 0 0 2 + 4050 3750 4050 4425 +2 1 0 2 9 7 0 0 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 4950 4800 5550 4800 +2 1 0 2 9 7 0 0 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 4950 3600 5550 3600 +2 1 0 2 9 7 0 0 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 6600 5700 7725 5700 +2 1 0 2 9 7 0 0 -1 0.000 0 0 -1 1 0 6 + 1 1 2.00 120.00 240.00 + 6600 5550 6900 5550 6900 5100 4950 5100 4950 2850 5550 2850 +2 1 0 2 4 7 0 0 -1 0.000 0 0 -1 1 0 6 + 1 1 2.00 120.00 240.00 + 9525 4800 9750 4800 9750 5100 7200 5100 7200 5550 7725 5550 +2 1 0 2 4 7 0 0 -1 0.000 0 0 -1 1 0 6 + 1 1 2.00 120.00 240.00 + 9450 3000 9750 3000 9750 3225 5100 3225 5100 3450 5550 3450 +2 1 0 2 4 7 0 0 -1 0.000 0 0 -1 1 0 6 + 1 1 2.00 120.00 240.00 + 9450 3600 9750 3600 9750 3825 5100 3825 5100 4050 5550 4050 +2 1 0 2 4 7 0 0 -1 0.000 0 0 -1 1 0 6 + 1 1 2.00 120.00 240.00 + 9450 4200 9750 4200 9750 4425 5100 4425 5100 4650 5550 4650 +4 0 0 0 0 0 20 0.0000 4 195 1905 3300 4800 RewriteCond \001 +4 0 0 0 0 1 20 0.0000 4 210 1620 7800 4800 CondPatternN\001 +4 0 0 0 0 0 20 0.0000 4 195 1905 3300 3600 RewriteCond \001 +4 0 0 0 0 1 20 0.0000 4 210 1575 7800 3600 CondPattern2\001 +4 0 0 0 0 1 20 0.0000 4 270 1290 5625 4800 TestStringN\001 +4 0 0 0 0 1 20 0.0000 4 270 1245 5625 3600 TestString2\001 +4 0 0 0 0 0 20 0.0000 4 195 1905 3300 3000 RewriteCond \001 +4 0 0 0 0 1 20 0.0000 4 270 1245 5625 3000 TestString1\001 +4 0 0 0 0 1 20 0.0000 4 210 1575 7800 3000 CondPattern1\001 +4 0 0 0 0 1 20 0.0000 4 210 1320 7800 5700 Substitution\001 +4 0 0 0 0 1 20 0.0000 4 195 825 5700 5700 Pattern\001 +4 0 0 0 0 0 20 0.0000 4 195 1455 3300 5700 RewriteRule\001 diff --git a/APACHE_1_3_12/htdocs/manual/images/mod_rewrite_fig2.gif b/APACHE_1_3_12/htdocs/manual/images/mod_rewrite_fig2.gif new file mode 100644 index 0000000000000000000000000000000000000000..3ea8cb65a3f9f1682c6b52d3911f52d2434ad38f GIT binary patch literal 2553 zcmV*@J5W=b#yB~Kp0=~-bve892N4)}p(pW%2p5sZht~LD zI1%}hx8|otxH2g-xLK0vxppC@5V~NentIoI(rJ0{2OE+}BP-$wx*=Bz983yn zON(iU%aN>EEQsprz_yI0Q)?}KoO*nQ-CZ_4KxX`yc3=u2d>*X_(0`guqzqd@*%#-LfeXh5BVQWpLp z)QG8|NtFn{$$Q4mA4HAe4t}G#aHU6(6t}s=hq0PVmJMrKq`A|k!e|9O8l4z&!W#`S zjZ$>#(5cRsJn6|i1(K`QjsTk`MM>77$!02Ard6pHsnu+78$i8lc7VuF^ky0)tFtHF zr(QWty35d@Uzmf7Y8_lL2S2v}^FhUV^=(jScxmn>5x6qvpoM!Pb&QqLVZdksM=H$I z>f6||`_!fUG4I*j11X7%v6>pY2xh3(3xa*;o zNYwSdUv1ZB&wdX*)_krZ4vewXW?IWbBeN8I)p6nPzS&B?4Ba$!41htm$T)Y{DsLok!AXXP!Iasb`-s^66)wB?2mFp%M~m zXrkQ3=fOx@uY&%$*{vTrQ0I{>pr{8vB)Ijjp5X8oW+QCNZyu6c=x)f=Sie!59OmW78?Uq0#Q z-A_M>*2j0|B3IR1{j3WUtyZmwDmAPb*OzWZ(KlCd!!olPXD?x<)MZ`WCSOCy2xXtD zBJXyVst}vinMV{8xGT+dtvA`ugw^Np$GNUjU414?N3v`l^XJ|U-Mw}&ZPjtd6m(DJ z6=fj;N4r>Zw<*{1t;9aJ(R|1-mS1mQ3*BsPl^rbC)KrgcT-_5(HI>#v|5g>Q3aoBpX0Y3fE=(`y56f!k?an7cM1Y2Z z>89<%9O0m%5>UCP<%ld{q4w}rZ#fjfi|+vUI%bW2f9l`Je*0g%Phpa(w)!Vrq^ zK;-L{1y9HXM4@nnK~NzJU&sR&!f=MpVu1{4I70`L;D$JSp$#5&cs{ zYT@jNOnhJx6M&^AO3?#^;?n*Uuh<3#lnIMmM8^c;)kQ!3a6w;0P#6_8#t_^LgJ*0~ z8bMIOHp($7bF3p3?TE(>#4(Rt+#?@BK)p8k@sBNFBX(pkNJ5^-eBJ6mA{CheLyiju zkA&n2BzXe>G;%|hOadk^RLM@dsDz>{!Y2<^N+X=|L7_|~AW7-UAgr=&FKA^fYs5%I z`f7x{?4>V%3Cv(F(FvN=r3r6Y#~>n;iOO825u52uAwn~nIGiRmXK2l9zA&5GEP^J# zSxjy@;+s@?7XnT-%uMkmW9qbo!NR!*cxJ^gHB45ja8-zDopYBYWED8c87Y7YLT~j< z!9TkN&v44KJU)w6L;elAvYZ*|nCAo|*E}W(wrLbBv>95q?)j~FcCxUUeXSS_qn!ztLk!=+AD_Zz6^so0i)aBZQiC`j+k z*P9!?-z)_r-R~*Ey)V3Rf27Mu^G49eU|?}Kw+G83*MP`hFtU<|l;kJNfXQBPvXr$L z_+~zF2`O9&Z^NR0`=RE7#d1Vx) zpa1;+r88#{$%0-X#R_fcFCrR+hhDS=8|`QXLORm?n>3~6XX#6$FVmXV9;Z87n?$UQ1dKj$WxKWt%&lC&*2KeJ zg|Jc^3%8wSJbJ~>Es5hsvVku&bMOtThffzVrY3bjZp9qQL0cRG3m7&S2lxLF`)k|Z zf?Q-y{q1!w@@ujE{JG!dHe$z|&Vcqbv=aBY>W)J$AvZ9!qFH%?Ma*N^PF&p0-WiVv zzMQNZfxTa!4%O>=-_E_8*b=)>dpCpizhqA8omJk;HIvg6=s4YH_3mYv&UCJ#46a;f zD6N=H-t{KN>tGW*NzbkI=0cs4Ge);y`zlrYMtkMWtfc2gZs#07qC6*Y8&p!K)?pjTI?meG(PwMLdKh&2SzNe>a{NyWt`OI&=^Pdm> P=u3b4)UW=R3jhE+CPVN4 literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/htdocs/manual/images/sub.gif b/APACHE_1_3_12/htdocs/manual/images/sub.gif new file mode 100644 index 0000000000000000000000000000000000000000..93061c5ad7f011307c4188fbc5d134db19fbc8c0 GIT binary patch literal 6083 zcmaKNc~BGC_xAdZs(b)vW+xP(Py6C*@L zL<}GZDo$WT5k&(CqM{Qwz;y!Z;7)MG`HYh<)bIaaSJ$mu{q8&WoO9o+4h;|S79@R! z{J}RPFdB^*hQ-9hBqt|lW@f5Xs=B(m-rimW01N;Q0DJ%h0EhvI2Ot@MGypOI7)5{) z0dBs~z0wh%oa+5J*>tsZ}wSu(NnA8{$BjzT@^96j2&qa&_AU9Ji7GY`0$k=UASb)7PdXQX7zC&=(8>a1lhm-u{$P{?R0!ZqQWJsE zNm7$LVy5yY3~)IhCV7hfWQ{m&%7d6RFqSz*d{TXUJgDOWaSTwg0C&;`)zq%k%Bj`c zbyMK1rYS#C)27M92On^aV1Nra zO;ZK8$3TY>^ooIi16anXyfp?0DnaT1m>dGX6=cQ(ff3Y+05=tgjG!_TOwNSW3(`hG z?${K9$~YBsV*qymq;fFU*i^4fG2j?MS|t!=0=^NX8bPuV#IpeMZOT<_Ux;B?M~%Trt2>0ZRoql~YTTYy~j@iw9UPU_G0H<%$3@HkEM102u(29VeMj zzL;@pl>fhH^6+!M;~@Zyz;&u_>P`re$xA_=8KzNp<{;BtR`hAAyZ2yr;>xh*nw}!o zoRlYh&9#A$bztGl@RsA(%ba6Rt`OW+0H-Lkz6l7|Tf}tpRO#hO*}25eFRrKU`Ec0t zm;NmY5jPe-YJrVJge_GUX2Fnfy1l%vYT55gmls+^oICyS4_Qyl{**d2+irneD~zsz zE>*ug-PoPiRMA?0r+gCk)O5EMEt11#1o1(a*dnilm|U4e?Z4@3-?n?iTju=Lm$rYu z`|{N5doZyf(ao#r?Vu+4X307Q7&LSC@AJ+MbT4MuScH|IU!O2fK3Wx=w&mTyx$B2Y z94UW?Z)jZn=g#pO=G!HWQPu9@#*IN-m0fr~<41Ec>Cc(Io1ba8c8*c~%;g_vG{+w}i0l%c2xq!;8Q2?GMUE z3Y_a3Mhacey&5Uv^*TQCHtR+x?yUw}D(^~Me({_;kvX@#|CHX_D;Qg>gb*904o1_q9U$yg=efLT zIDRnYO=Cm7Pc60piO#`-tc`c<7{21@t7g#?tld=M2UzCT_AX|ae@9rm(BrN&Im+iE z)*ZpuKIx+HFW7e%d)`}ZcY991=Z%H#R~coI?texmM+q9S}PW$NdaKzfY0E zEV)^bu#;dOrvrpTTciP3$WkFpv^cHFCMPzl-*jW4uH#o3%hrzfIMy`x_Wr#6CDCeg zZa=9Y7yogOU5V?ez8kKV@b#NV<7^)~s6Nk&;MQM?DRNs01r{aso)*eS2!gl;*AzyfdnUpv9ih10gIc&+G(DB2VkPjc42_z!|CpYyvCdNqTXI(hDjNil!_!6V zSaSsv6)IfL?gp^z=BJRbF0;~?E;uzjUZKR>G-z=*lmV2b!ffhiy!8ujl1FZIQT!#C zS*{_t8WTGUqn^}Ef0|Wn8^Wm?w-=cd@s``X%FCe2?~fipMrCeE!Krmkjn%Pwhm zdo;=-FH^2s{m07>>U-^1Jb`x(<8YSf7Ku(^y|b0g#WFvf&kZ!xcYwc-Bv;@aB#H6* z-o6l@kNXo3cQFo1vz_{HkS}C+nQU>$wewDz_9gC7!B6{U`hv1seBG z>#3%m5?-6zXIfHMmt$4ENg)cnuov-@La*A0^UfvhB}k-}f2oP{9#xlY^0Z}M1a$>9 z!PP&VZZN-KzTo^KvZv6-hr{H%fL`oU5@oK=Sr@ z?0@LS{rV4S)K%Wyy}i=Blku&laXl$Bg-iGNgAvcAsyaKzJ2gr1d#0Td#?HFizSOg+ zYer9c0zWdvqK3K7Ql|*zN%i(wtX~n4|AQ zr^V-5qHdjDGw0+{N_CVGVj zph8{N`1M-v!HI}X%Fd>*v|7_}zumLK?i4IjcA?RY?-!rpc^|^77eLS%vO5ZKs8A%;jJKbqiS8rU$=wGe{G`e0jJr%Q2-JddgP13|&AW1WYID zp3~k;{HbuShCF2i<|{l7muW$G)~UBhRKOH0)T^esIKi83J?a%Y?$opln`IJ2&lxgCUAQ5LIgla!NcK$!epjuI{yZVFG?j(U z)nutwzZ;3`)qA_eRToC_vUhDV;B4J%_k^p={kQ76*9<6$yo_q<>b`w59`W+{uiArC z;>w(;0VJ2N0onPApif{4$J)67H!9@0}366FzqTJ zyQpscGULzm&}R*yF|1OvbjCI(B#T@=)@fR!#XI{YG1tc7Ec(R+sNc?PMuQ=D)+$qqv~7f0?O#*9_RjjB2cJ&Ax45yk zrF!q$O|_P9FcRlwK-T?-5d@yX)kxW-oA`Ld`0w$In~a%DP26N0sB91}k$=Y9kh4C< zc#D4QR-%#p(aaWgWV4oXj<>zlKiN^Ovj=cKmKw+&gWWW- z&U&6J8~18!ZdiG4qpiIlJA6S4K9-Fau-$ri)XQ?Z!w?-GOn=KZG010M*16r2(}pqb z6Lwe+$K<&N3`*%Aomc9%zgg_->Qnf^lWtY^>khkgZR&@4Sf)Zintci>7_WCjG)nSVBm*YEG_)uZ-)mOOE#fwVXiu;l9HA10f z4)Jb2Q7+lLg6XkVZ&S`fE_EaO414txNUec5!EiWQI9;KO31Pq8-(e?afOsC}LW8l=>{-{Gjv}M(3HAc@#+Oy1?A);D1J$Euw}T z**HhJ-;X5Nho=f!t_o?y36(1Bf-3T%D$3k$){Fx&f&-)^uuOO$?(l*5ZDuR90ZSy_ zHX=}X6?2a^nP@#AJA4pF6g36_7Yw$=U`!8RX@<_X!Y)G0Y8BIJ71;R@!x>g4@(-pg zFVDN+httjT)#G95>e=#XZajFF7P|U{ZYuS8s->++r%`w&A9!^5PCzTPt~HwA6pFcz zbMHDx_dKjPvwU767dM}WpRcp@Wgk{u|B0c4whq&u80drZXm`}K42Ewb=6l&dX_Y3& z={P5&!3_!a^EQj5@rr?MM`ioV-K8=s-io=$Wp-?MuJQh~F%9jZl6F_l*#5$QKx1{* zfYxs!S4hc)(tvU{c_J7z>85-9z4AX(@F4Ff?4!0%0wHX?SOKiD#EO{2j+eWKCG_na z+8scBAzyz_U1d6C)xayMk&>GX_RojOo%gJF8i<*S8aUb(h}G`@)R=b$z?#@u82rP- z#|&fWwMRavf8EApUDG9*dT*-LQ+D66IxQ)gxcA#m%x@D$g6^+c2SQfq2rIuGyF;vv zZ?7Yp&foVO@{>;EVzB->>@0+5N+CL%KE$Iv(1u!sP<`S=dFWZds)!?c=3H+L6F7kRd z2GP~@XL;-I%W3BA)JEV8^3ffu$ow?&0RvK``z=Sf*1#dH#Yl#6qFXO*wD8smQUK z@rHU)PJgw$TB`{9U5_^Lg6cKw5;^kA!BsniNQWay&LjOXJ>=YUBI%oh;|OsbmhqdO zR3;;BRUoAjvYbSDkVm-r<-kp*$Z|Ddu%gNKZTzlqLWlzI!NytZ;haOzRVI`!^Z8p& zlQ=@7##XvsO6$^YXqVC)kmJ2-3f6}fZ9q?G(c^41@`%Xdx}KAA zr&UM>K+MjPjGssfEmEK(Z#F|uu+atsdUEoZY@{eubOR5f@h~C=@X<%pEH53HBZGzW zEwEpo%V~@Z>iaax_SMvG1$7W(SvvZ*saZuy=ztUb zOAKV8#_w~v#PGA+br{cPdokE_3LEFlu43v}_l?i4FQaw6PHT~%$AzcLwe2I(zG}Al z|HOz&xyH~*Oammhb3`ddg0~W-Y>V1)LW+)%peDN35Lf6)>4pV)N@SGd#C*IZ?Y@2U z#mMvW?ekUWj$HafDSbpu|DfM(A~azF*bU&^c%8Cw)%r`t(SQ(GvulGZ-o-!-IB#`Y zkFvd}c>!mub!4pqZL_n^mtVeul6D$}q|WvwZePt4w8VtFo5yF_t&+t{VNMSjZwJooa(gb`*W1dPA7h+(r#*~*UjjIqj?lw*hdT^mciA9 zu%iOU$NK3%bjP!2MeD;w61@LMI}ZuI{2MO9fRjk@!AhI}D~^|#Fdo{jkzX#FDZNT`!)9vQ8%mdy z+OMQOQo7!s#~tycC&cL(de4*_vpE{wd>#%<7+6Ddi7?%7!Bu zc(HUF@`!vAkJc*D!f`ZXVQ4d;v?!2If;9)QK11>LR%KU0-Uif}Q!A(Ve4_N)bIQ~d zvD<@t&D6o{h1X%)%j_KkhMqV2KOO?Q!XfH0n_;E_QDx9b88j1vU3lrv>Nu`W_si4A zmw(tU2fM`vd@vjDD8WZ7aY~Z?(L*?q-cF*%d)wk_HA5#1k(-^U7u2EG^wdEkM!gnF z(elunDzr`M{FFvpoKC%$MY(6Dc)F2xxod+~eW`R6{e?EK2Qqo(X<|_Ntoe7g|M=`R z{{k~PR1Pm9mTTeV0KZ`-!PoX$tQ_xO+W*fWQlFlsHBfEy zX;0+zY|E&ZYTBO?>Q&oE@7y}Rb<7t>5WNOKs{^GrE3 zT>_i3eX>L0S-PC3J%FrBuvQYBdAZDIFBARwUOa-AayV825WfevBqq-^v|(l0GtIsg z>_-oHv@#F+Uvk=eHhok$`;!ntHMDY~iHTx&V-xLp?fl0^$>h&(6k|gyJ@iEnu{4l{ zPPuaD>+-7Q$~OKc1u0!xaA=5BBo*uXkkx-9$9SbxTBJhvrdn#-E~K>FwrW$9*sr2p zmw2{Y(^hWZ0lj}K8V3JPc(%paQk7m_Ny?6ixDNi2K*KxTfA7je@rM)Nm#{Ks#+vN1 z@Yu*BIhZY#teE3qX8kdI>D*fMv@Y zb}8NBaz1Xr-w^q|c>fT;KB-;RK(cGu>-@=p%_diS$751v8lbU**D`B2|{gCwI~ z=GlHh?7purT9gLavtjO)kLsLvdt2Z2e|V=;yW{aIKZW*P-e3O7GO)nU#zP^$yE5A2 ziT6_Xjp*Bk@jq@`otPN!;Vt{Y|7b576LCxg- + + +Apache 1.3 documentation + + + + + +

    Apache 1.3 User's Guide

    + +
    + +

    Release Notes

    + + +

    Apache Reference Manual

    + + + +

    Other Notes

    + + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/install-tpf.html b/APACHE_1_3_12/htdocs/manual/install-tpf.html new file mode 100644 index 0000000000..661edba885 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/install-tpf.html @@ -0,0 +1,334 @@ + + + +Installing Apache on TPF + + + +

    + Installing the Apache 1.3 HTTP Server on TPF +

    +
    +
    Download +  | Compilation +  | Installation +  | VisualAge ] +
    +
    +
    + +

    +This document outlines the steps needed to install Apache onto a TPF system. +

    +

    +You should first read +htdocs/manual/readme-tpf.html +for basic information on the port of Apache to TPF including required PUT level +and supported functions & modules. +

    +

    Download

    +Releases of the Apache server are compressed into a "tarball" file and stored on the Apache web site. +You will need to choose a version and download the corresponding tarball to your PC. +Additionally the source code from the tarball will need to be copied onto an MVS OS/390 Open Edition machine +(later referred to simply as "Open Edition") for compiling. +So here are all the details on how to get Apache and how to get it where it needs to be: +
      +
    1. Download + the gzipped Apache files (the "tarball") to your PC. + The file name on the web site will be something like apache_1.3.x.tar.gz. +
      TIP: Be sure to keep the .tar.gz extension + when choosing the name of the PC file. +

      +
    2. Decompress the tarball on your PC using WinZip or some other PC decompression tool. +
      TIP: If you are using WinZip verify that the + "TAR File Smart CR/LF Conversion" option (under Options, Configuration) is NOT checked.
      + This is what you can expect if you use WinZip: +
        +
      • open the tarball with WinZip (this can usually be done simply by double-clicking + on the downloaded tarball) +
      • you will be told that the archive contains one file (such as apache_1.3.x.tar) - + allow WinZip to decompress it to a temporary folder +
      • extract the archived files onto your PC - + you'll be using files from the conf, htdocs, and icons directories later in the install phase +
      +
      +
    3. FTP the tarball to your Open Edition machine using binary mode: +
        +
      • activate FTP in an MSDOS window: ftp your.open.edition.machine.com +
      • sign in +
      • set mode to binary: binary +
      • send the file to Open Edition:
        +    send c:\downloaded_filename.tar.gz open_edition_filename.tar.gz +
      • exit FTP: bye +
      +
      TIP: + Open Edition and UNIX file names are case sensitive. If you use an NFS client to transfer files + from your PC to Open Edition (instead of using FTP as described above) verify that the NFS drive will transfer the + file names with upper/lower case preserved.
      +
      +
    4. Decompress the gzipped file on Open Edition: gunzip open_edition_filename.tar.gz +
      Note that the .tar.gz file will be replaced by the gunzipped .tar archive file. +

      +
    5. Extract the archived files necessary for compiling Apache: +
        +
      • pax -rvkf open_edition_filename.tar -o from=ISO8859-1,to=IBM-1047 "*/src" +
      • switch to the source code subdirectory of the newly extracted apache directory: cd apache-1.3/src +
      • remove unnecessary subdirectories: + rm -r os/bs2000 os/mpeix os/netware os/os2 os/os390 os/win32 +
      +
    +
    +

    Compilation

    +

    +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, it is necessary to generate a short bit of +code (modules.c) which simply has a list of them. If you are using the Configure utility +and make, modules.c and other necessary files will be created for you automatically. +

    +

    +The provided scripts assume a c89 compiler and have only been tested on an +Open Edition environment. If you are using a platform other that +Open Edition you may need to modify src/os/tpf/TPFExport and src/Configure +to match your environment. +

    +TIP: +Editing files on your PC prior to moving them to Open Edition may result +in the loss/addition of unprintable characters. Files of concern include shell +scripts and src/Configuration. The most common problems are with +tab characters and CR/LF characters. Most editors will handle the CR/LF problem correctly +but none seem to handle tab characters. If you need to edit files prior to moving them to Open Edition, +edit them in a UNIX editor such as vi or emacs.
    +

    +Note that Open Edition commands in this section are shown in +bold, +are case sensitive, and must be made from the "src" directory. +

    +
      +
    1. Overlay src/Configuration with src/Configuration.tmpl: + cp Configuration.tmpl Configuration +

      +
    2. Edit src/Configuration. It contains the list and settings + of various "Rules" and an additional section at the bottom that determines + which modules to compile: +

      +
        +
      • Adjust the Rules and EXTRA_CFLAGS|LIBS|LDFLAGS|INCLUDES + if you feel so inclined. +

        +
      • Comment out (by preceding the line with a "#") lines corresponding + to those modules you DO NOT wish to include. +

        +
      • Uncomment (by removing the initial "#", if present) lines + corresponding to those optional modules you wish + to include or add new lines corresponding to any custom modules + you have written. + The htdocs/manual/readme-tpf.html + document lists the modules that have been tested on TPF. +
      +
      The modules placed in the Apache distribution are the ones that have been + 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. +

      +
    3. Set the TPF environment variables: + . os/tpf/TPFExport +
      + (The initial period and blank on the command are required to ensure + the environment variables exist beyond the scope of the shell script.) + This script will set the environment variables required to compile the + programs for TPF. Verify that the export variables are valid for your + installation, in particular, the system include file directories. The + system include files must reside on your Open Edition system in the + appropriate file structure similar to /usr/include and /usr/include/sys. + DO NOT modify the TPF=YES export variable. If this is + changed, the "Configure" script will not recognize TPF. +

      +
    4. Run the "Configure" script: + Configure +
      + This generates modules.c, include/ap_config_auto.h, and necessary Makefiles: +
      +      Using config file: Configuration
      +      Creating Makefile
      +       + configured for TPF platform
      +       + setting C compiler to c89
      +       + setting C pre-processor to c89 -E
      +       + checking for system header files
      +       + adding selected modules
      +       + checking sizeof various data types
      +      Creating Makefile in support
      +      Creating Makefile in regex
      +      Creating Makefile in os/tpf
      +      Creating Makefile in ap
      +      Creating Makefile in main
      +      Creating Makefile in modules/standard
      +      $ _
      +      
      + 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>
      +      et cetera
      +      
      + If you receive an error such as "Configure 146: FSUM7351 not found" + the most likely explanation is that one or more of the make related + files were edited on a non-UNIX platform, corrupting the end-of-line marks. + Verify that lines ending with "\" in the flagged file do not have trailing + spaces. Using the vi editor and the sample error above as an example... +

      +            pull up the flagged file:       vi Configure
      +            turn on punctuation:            :set list
      +            go to the line in question:     146G
      +               or find a line with a "\":   /\\
      + The end of line should display as "\$". If it is displayed as + "\ $" (with a blank between \ and $) then you should revert to the + distributed version of the file and make the site-specific + changes again using a UNIX compatible editor such as vi or emacs. + Then try the Configure command again. +
                  close the file:                 :q  (or :quit!)
      + +
    5. Edit include/ap_config.h if you would like the scoreboard kept in shared + memory instead of file or system heap.
      + The default behavior for Apache on all platforms except TPF is to use the + file system for maintaining the scoreboard (which holds current Apache children status). + The default behavior for Apache on TPF is to use system heap. Available with + PUT10 is the use of shared memory for the scoreboard in place of the file system. + This reduces file activity for the parent Apache ECB and improves performance. + To activate shared memory, uncomment or add the directive + #define USE_SHMGET_SCOREBOARD + and comment out or remove the directive #define USE_TPF_SCOREBOARD + both of which are in the TPF section in ap_config.h. + This change will only take effect after Apache is (re)compiled. +

      + If you prefer to use the file system instead of system heap or shared memory, ensure that both + USE_TPF_SCOREBOARD and USE_SHMGET_SCOREBOARD are commented out or removed. + This change will only take effect after Apache is (re)compiled. + +
       
      +
    6. Edit include/ap_config.h if you plan on using the ZINET DAEMON model instead of the NOLISTEN model.
      + The default behavior is to let Apache check the server status (active/inactive) with ZINET + and shut itself down when appropriate. The default behavior also includes checking Apache's activation number. + Available with PUT11 (PJ25761) ZINET can perform these functions instead of Apache by using the DAEMON model. + This model offers increased reliability and is preferred over the NOLISTEN model. + If Apache goes down while running under the NOLISTEN model ZINET will not reactivate it nor alert the operator. + To use the DAEMON model you must modify the default behavior of Apache by uncommenting or adding the directive + #define USE_TPF_DAEMON within the TPF section in ap_config.h. + This directive is also recommend when starting Apache from the command line (APAR PJ26515). + This change will only take effect after Apache is (re)compiled. +

      + + +
    7. Now compile the programs: make
      + Besides compiling, make also runs main/gen_test_char.c and main/gen_uri_delims.c + in order to create main/test_char.h and main/uri_delims.h respectively

      + If during compilation you get a warning about a missing 'regex.h', set + WANTHSREGEX=yes in the src/Configuration file and start back at the + Configure step. +
    + +  +

    Installation

    +
      +
    1. Link the compiled object files into a DLL. + Sample link JCL has been included as src/os/tpf/samples/linkdll.jcl. + You will need to modify this JCL: +
        +
      • Change the IDs, data set names, and libraries for your particular site. +
      • Add/remove mod_xxx.o files so they correspond to the + mod_xxx.o lines in your src/Configuration file. +
      +
      TIP: + Do NOT include gen_test_char.o or gen_uri_delims.o in the link JCL since these files are only + used during the make step. +

      +
    2. Create a loadset. Sample loadset JCL has been included as src/os/tpf/samples/loadset.jcl. + You will need to modify this JCL for your particular site. +

      +
    3. Load (ZOLDR LOAD) and activate (ZOLDR ACT) the loadset on your test system. +

      +
    4. Ensure that the program name you are using for Apache has RESTRICT and KEY0 authorization. + zdpat pppp (c-c) will display allocation information. + You can use zapat pppp restrict key0 (c-c) to alter the + authorization. + Note that if the program name is unallocated, you must have the loadset for it activated or you will receive + INVALID PROGRAM NAME from the zdpat/zapat entries. +

      +
    5. + Apache requires a configuration file to initialize itself during activation. + (Previously three configuration files were used.) + Copy the distribution version, /conf/httpd.conf-dist, to /conf/httpd.conf and then + edit the /conf/httpd.conf copy with your site specific information. +

      + General documentation for Apache is located at + http://www.apache.org/docs/ + and in the HTML pages included with the distribution (tarball) under the + /htdocs/manual directory. +

      +
    6. On TPF activate ZCLAW and update INETD using ZINET entries, the common case: +

      +
      +    ZINET ADD S-TFTP PGM-CTFT PORT-69 PROTOCOL-UDP MODEL-NOWAIT
      +
      +    ZINET ADD S-APACHE PGM-pppp MODEL-NOLISTEN
      +    or ZINET ADD S-APACHE PGM-pppp MODEL-DAEMON USER-root (see notes above regarding the DAEMON model)
      + Please refer to IBM Transaction Processing Facility Transmission Control + Protocol/Internet Protocol Version 4 Release 1 for more information + on ZCLAW, INETD, and TFTP. +

      +
    7. Prior to sending a request to your Apache server from a browser, + TFTP the configuration file, log, icons and web pages to your TPF system. + A typical directory structure for Apache is as follows: +
           /usr/local/apache/conf
      +     /usr/local/apache/logs
      +     /usr/local/apache/icons
      +     /usr/local/apache/htdocs
      + All gif, jpg, and zip files should be TFTP'd as binary; conf files and html pages should be TFTP'd as text. +
      The logs directory must exist in order to avoid an fopen error while running Apache. + If you're running a PUT10 or higher version of TPF make the directory using the + zfile mkdir /usr/local/apache/logs functional entry. + If you're running TPF version PUT09 TFTP an empty file into the logs subdirectory to create it. +

      +
    8. Start the server using the ZINET START S-APACHE command. +
    +  +

    Compiling with VisualAge TPF

    +

    + It is not required that make be used to compile Apache for TPF: + Individual programs may be compiled using IBM's VisualAge TPF product. + This is particularly useful when compiling selected programs for the Debug Tool. +

    + The following VisualAge compile settings are required: +

    +
      +
    • "DEFINE - Define preprocessor macro name(s)" must include + TPF, CHARSET_EBCDIC, _POSIX_SOURCE, and + USE_HSREGEX +

      +
    • "LSEARCH - Path for user include files" must include + ../src/include and ../src/os/tpf +

      +
    • "DLL - Generate DLL code" must be checked +

      +
    • "LONGNAME - Support long names" must be checked +
    +
    +
    top +  | Download +  | Compilation +  | Installation +  | VisualAge ] +
    + + + diff --git a/APACHE_1_3_12/htdocs/manual/install.html b/APACHE_1_3_12/htdocs/manual/install.html new file mode 100644 index 0000000000..b8f5047e00 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/install.html @@ -0,0 +1,270 @@ + + + +Compiling and Installing Apache + + + + + + +

    Compiling and Installing Apache 1.3

    + +This document covers compilation and installation of Apache on Unix +systems only. For compiling and installation on Windows, see Using Apache with Microsoft Windows and for +TPF see Installing the Apache 1.3 HTTP +Server on TPF. + +

    + +UnixWare users will want to consult build notes +for various UnixWare versions before compiling. + +

    Downloading Apache

    + +Information on the latest version of Apache can be found on the Apache +web server at http://www.apache.org/. This will +list the current release, any more recent beta-test release, together +with details of mirror web and anonymous ftp sites. + +

    + +If you downloaded a binary distribution, skip to Installing Apache. Otherwise read the next section +for how to compile the server. + +

    Compiling Apache

    + +Compiling Apache consists of three steps: Firstly select which Apache +modules you want to include into the server. Secondly create a +configuration for your operating system. Thirdly compile the +executable. +

    + +All configuration of Apache is performed in the src +directory of the Apache distribution. Change into this directory. + +

      +
    1. + Select modules to compile into Apache in the + Configuration file. Uncomment lines corresponding to + those optional modules you wish to include (among the AddModule lines + at the bottom of the file), or add new lines corresponding to + additional modules you have downloaded or written. (See API.html for preliminary docs on how to + write Apache modules). Advanced users can comment out some of the + default modules if they are sure they will not need them (be careful + though, since many of the default modules are vital for the correct + operation and security of the server). +

      + + You should also read the instructions in the Configuration + file to see if you need to set any of the Rule lines. + + +

    2. + Configure Apache for your operating system. Normally you can just + type run the Configure script as given below. However + if this fails or you have any special requirements (e.g., to include + an additional library required by an optional module) you might need + to edit one or more of the following options in the + Configuration file: + EXTRA_CFLAGS, LIBS, LDFLAGS, INCLUDES. +

      + + Run the Configure script: +

      +
      +    % Configure
      +    Using 'Configuration' as config file
      +     + configured for <whatever> platform
      +     + setting C compiler to <whatever> *
      +     + setting C compiler optimization-level 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
      +   
      +
      + + (*: Depending on Configuration and your system, Configure + might not print these lines. That's OK).

      + + This generates a Makefile for use in stage 3. It also creates a + Makefile in the support directory, for compilation of the optional + support programs. +

      + + (If you want to maintain multiple configurations, you can give a + option to Configure to tell it to read an alternative + Configuration file, such as Configure -file + Configuration.ai). +

      + +

    3. + Type 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. + +

    Installing Apache

    + +You will have a binary file called httpd in the +src directory. A binary distribution of Apache will +supply this file.

    + +The next step is to install the program and configure it. Apache is +designed to be configured and run from the same set of directories +where it is compiled. If you want to run it from somewhere else, make +a directory and copy the conf, logs and +icons directories into it. In either case you should +read the security tips +describing how to set the permissions on the server root directory.

    + +The next step is to edit the configuration files for the server. This +consists of setting up various directives in up to three +central configuration files. By default, these files are located in +the conf directory and are called srm.conf, +access.conf and httpd.conf. To help you get +started there are same files in the conf directory of the +distribution, called srm.conf-dist, +access.conf-dist and httpd.conf-dist. Copy +or rename these files to the names without the -dist. +Then edit each of the files. Read the comments in each file carefully. +Failure to setup these files correctly could lead to your server not +working or being insecure. You should also have an additional file in +the conf directory called mime.types. This +file usually does not need editing. + +

    + +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. + +

    + +In addition to these three files, the server behavior can be configured +on a directory-by-directory basis by using .htaccess +files in directories accessed by the server. + +

    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. + +

    Starting and Stopping the Server

    + +To start the server, simply run httpd. This will look for +httpd.conf in the location compiled into the code (by +default /usr/local/apache/conf/httpd.conf). If +this file is somewhere else, you can give the real +location with the -f argument. For example: + +
    +    /usr/local/apache/httpd -f /usr/local/apache/conf/httpd.conf
    +
    + +If all goes well this will return to the command prompt almost +immediately. This indicates that the server is now up and running. If +anything goes wrong during the initialization of the server you will +see an error message on the screen. + +If the server started ok, you can now use your browser to +connect to the server and read the documentation. If you are running +the browser on the same machine as the server and using the default +port of 80, a suitable URL to enter into your browser is + +
    +    http://localhost/
    +
    + +

    + +Note that when the server starts it will create a number of +child processes to handle the requests. If you started Apache +as the root user, the parent process will continue to run as root +while the children will change to the user as given in the httpd.conf +file. + +

    + +If when you run httpd it complained about being unable to +"bind" to an address, then either some other process is already using +the port you have configured Apache to use, or you are running httpd +as a normal user but trying to use a port below 1024 (such as the +default port 80). + +

    + +If the server is not running, read the error message displayed +when you run httpd. You should also check the server +error_log for additional information (with the default configuration, +this will be located in the file error_log in the +logs directory). + +

    + +If you want your server to continue running after a system reboot, you +should add a call to httpd to your system startup files +(typically rc.local or a file in an +rc.N directory). This will start Apache as root. +Before doing this ensure that your server is properly configured +for security and access restrictions. + +

    + +To stop Apache send the parent process a TERM signal. The PID of this +process is written to the file httpd.pid in the +logs directory (unless configured otherwise). Do not +attempt to kill the child processes because they will be renewed by +the parent. A typical command to stop the server is: + +

    +    kill -TERM `cat /usr/local/apache/logs/httpd.pid`
    +
    + +

    + +For more information about Apache command line options, configuration +and log files, see Starting Apache. For a +reference guide to all Apache directives supported by the distributed +modules, see the Apache directives. + +

    Compiling Support Programs

    + +In addition to the main httpd server which is compiled +and configured as above, Apache includes a number of support programs. +These are not compiled by default. The support programs are in the +support directory of the distribution. To compile +the support programs, change into this directory and type +
    +    make
    +
    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/invoking.html b/APACHE_1_3_12/htdocs/manual/invoking.html new file mode 100644 index 0000000000..02ee07659f --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/invoking.html @@ -0,0 +1,220 @@ + + + +Starting Apache + + + + + +

    Starting Apache

    + +

    Invoking Apache

    + +On Unix, the httpd program is usually run as a daemon +which executes continuously, handling requests. It is possible to +invoke Apache by the Internet daemon inetd each time a +connection to the HTTP service is made (use the ServerType directive) but this is +not recommended. + +

    + +On Windows, Apache is normally run as a service on Windows NT, or as a +console application on Windows 95. See also running Apache for Windows. + +

    Command line options

    +The following options are recognized on the httpd command line: +
    +
    -d serverroot +
    Set the initial value for the +ServerRoot variable to +serverroot. This can be overridden by the ServerRoot command +in the configuration file. The default is +/usr/local/apache on Unix, /apache on +Windows and /os2httpd on OS/2. + +
    -D name +
    Define a name for use in in +IfDefine directives. +This option can be used to optionally enable certain functionality in the +configuration file, or to use a common configuration for +several independent hosts, where host specific information is enclosed in +<IfDefine> sections. + +
    -f config +
    Execute the commands in the file config on startup. If +config does not begin with a /, then it is taken to be a +path relative to the ServerRoot. The +default is conf/httpd.conf. + +
    -C "directive" +
    Process the given apache "directive" (just as if it had been part of a +configuration file) before actually reading the regular configuration files. + +
    -c "directive" +
    Process the given apache "directive" after reading +all the regular configuration files. + +
    -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. + +
    -v +
    Print the version of httpd and its build date, and then exit. + +
    -V +
    Print the base version of httpd, its +build date, and a list of compile time settings which influence the +behavior and performance of the apache server (e.g., +-DUSE_MMAP_FILES), +then exit. + +
    -L +
    + +Give a list of directives together with expected arguments and places +where the directive is valid, then exit. (Apache 1.3.4 and +later. Earlier versions used -l instead). + + +
    -l +
    + +Give a list of all modules compiled into the server, then exit. +(Apache 1.3.4 and later. Earlier versions used -h instead).
    + +Give a list of directives together with expected arguments and places +where the directive is valid, then exit. (Apache 1.2 to 1.3.3. Later +versions use -L instead). + + + +
    -h +
    + +Print a list of the httpd options, then exit. (Apache 1.3.4 and +later. Earlier versions used -? instead).
    + +Give a list of all modules compiled into the server, then exit. (Up to +Apache 1.3.3. Later versions use -l instead).
    + + +
    -S +
    Show the settings as parsed from the config file (currently only +shows a breakdown of the vhost settings) but do not start the +server. (Up to Apache 1.3.3, this option also started the server). + +
    -t +
    Test the configuration file syntax (i.e., read all configuration files +and interpret them) but do not start the server. If the configuration contains +errors, display an error message and exit with a non-zero exit status, +otherwise display "Syntax OK" and terminate with a zero exit status. This +command checks to see if all DocumentRoot entries exist and are directories. +For sites with many vhosts, this is expensive; consider the -T +command instead. + +
    -T +
    Test the configuration file syntax (i.e., read all configuration files +and interpret them) but do not start the server. If the configuration contains +errors, display an error message and exit with a non-zero exit status, +otherwise display "Syntax OK" and terminate with a zero exit status. This +command does not perform any checking of the DocumentRoot entries. + +
    -k option +
    Windows only: signal Apache to restart or shutdown. option +is one of "shutdown" or "restart". (Apache 1.3.3 and later). + +
    -? +
    Print a list of the httpd options, and then exit (up to Apache +1.3.3. Later version use -h instead). + +
    + +

    Configuration files

    +The server will read three files for configuration directives. Any +directive may appear in any of these files. The the names of these +files are taken to be relative to the server root; this is set by the +ServerRoot directive, the +-d command line flag, or (on Windows only) the registry +(see Running Apache for Windows). + +Conventionally, the files are: +
    +
    conf/httpd.conf +
    Contains directives that control the operation of the server daemon. +The filename may be overridden with the -f command line flag. + +
    conf/srm.conf +
    Contains directives that control the specification of documents that +the server can provide to clients. The filename may be overridden with +the ResourceConfig directive. + +
    conf/access.conf +
    Contains directives that control access to documents. +The filename may be overridden with the +AccessConfig directive. +
    +However, these conventions need not be adhered to. +

    +The server also reads a file containing mime document types; the filename +is set by the TypesConfig +directive, +and is conf/mime.types by default. + +

    Log files

    +

    security warning

    +Anyone who can write to the directory where Apache is writing a +log file can almost certainly gain access to the uid that the server is +started as, which is normally root. Do NOT give people write +access to the directory the logs are stored in without being aware of +the consequences; see the security tips +document for details. +

    pid file

    + +On startup, Apache saves the process id of the parent httpd process to +the file logs/httpd.pid. This filename can be changed +with the PidFile directive. The +process-id is for use by the administrator in restarting and +terminating the daemon: on Unix, a HUP or USR1 signal causes the +daemon to re-read its configuration files and a TERM signal causes it +to die gracefully; on Windows, use the -k command line option instead. +For more information see the Stopping and +Restarting page. + +

    +If the process dies (or is killed) abnormally, then it will be necessary to +kill the children httpd processes. + +

    Error log

    + +The server will log error messages to a log file, by default +logs/error_log on Unix or logs/error.log on +Windows and OS/2. The filename can be set using the ErrorLog directive; different error +logs can be set for different virtual hosts. + +

    Transfer log

    + +The server will typically log each request to a transfer file, by +default logs/access_log on Unix or +logs/access.log on Windows and OS/2. The filename can be +set using a TransferLog directive +or additional log files created with the CustomLog directive; +different transfer logs can be set for different virtual hosts. + + + + diff --git a/APACHE_1_3_12/htdocs/manual/keepalive.html b/APACHE_1_3_12/htdocs/manual/keepalive.html new file mode 100644 index 0000000000..31f35327c4 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/keepalive.html @@ -0,0 +1,103 @@ + + +Apache Keep-Alive Support + + + + + +

    Apache Keep-Alive Support

    + +
    + +

    What is Keep-Alive?

    + +The Keep-Alive extension to HTTP, as defined by the +HTTP/1.1 draft, allows persistent connections. These +long-lived HTTP sessions allow multiple requests to be send over the +same TCP connection, and in some cases have been shown to result in an +almost 50% speedup in latency times for HTML documents with lots of +images. + +

    Enabling Keep-Alive Support

    + +Apache 1.1 comes with Keep-Alive support on by default, however there +are some directives you can use to modify Apache's behavior: + +

    Note: Apache 1.2 uses a different syntax for the KeepAlive directive.

    + +

    KeepAlive

    +Syntax: KeepAlive max-requests
    +Default: KeepAlive 5
    +Context: server config
    +Status: Core

    + +This directive enables Keep-Alive support. Set max-requests +to the maximum number of requests you want Apache to entertain per +connection. A limit is imposed to prevent a client from hogging your +server resources. Set this to 0 to disable support. + +

    KeepAliveTimeout

    +Syntax: KeepAliveTimeout seconds
    +Default: KeepAliveTimeout 15
    +Context: server config
    +Status: Core

    + +The number of seconds Apache will wait for a subsequent request before +closing the connection. Once a request has been received, the timeout +value specified by the Timeout directive +applies. + +

    When Keep-Alive Is Used

    + +In order for Keep-Alive support to be used, first the browser must +support it. Many current browsers, including Netscape Navigator 2.0, +and Spyglass Mosaic-based browsers (including Microsoft Internet +Explorer) do. Note, however, that some Windows 95-based browsers misbehave +with Keep-Alive-supporting servers; they may occasionally hang on a +connect. This has been observed with several Windows browsers, and occurs +when connecting to any Keep-Alive server, not just Apache. Netscape 3.0b5 +and later versions are known to work around this problem. + +

    However, Keep-Alive support only is active with files where the +length is known beforehand. This means that most CGI scripts, +server-side included files and directory listings will not use +the Keep-Alive protocol. While this should be completely transparent +to the end user, it is something the web-master may want to keep in mind.

    + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/location.html b/APACHE_1_3_12/htdocs/manual/location.html new file mode 100644 index 0000000000..2dddd2ee2c --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/location.html @@ -0,0 +1,68 @@ + + + +Access Control by URL + + + + + +

    Access Control by URL

    + +

    The <Location> Directive

    + +Syntax: <Location URL prefix>
    +Context: server config, virtual host
    +Status: core
    + +

    The <Location> directive provides for access control by +URL. It is comparable to the <Directory> directive, and +should be matched with a </Location> directive. Directives that +apply to the URL given should be listen +within. <Location> sections are processed in the +order they appear in the configuration file, after the +<Directory> sections and .htaccess files are +read.

    + +

    Note that, due to the way HTTP functions, URL prefix +should, save for proxy requests, be of the form /path/, +and should not include the http://servername. It doesn't +necessarily have to protect a directory (it can be an individual +file, or a number of files), and can include wild-cards. In a wild-card +string, `?' matches any single character, and `*' matches any +sequences of characters. + +

    This functionality is especially useful when combined with the +SetHandler +directive. For example, to enable status requests, but allow them only +from browsers at foo.com, you might use: + +

    +    <Location /status>
    +    SetHandler server-status
    +    order deny,allow
    +    deny from all
    +    allow from .foo.com
    +    </Location>
    +
    + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/man-template.html b/APACHE_1_3_12/htdocs/manual/man-template.html new file mode 100644 index 0000000000..805b0079e9 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/man-template.html @@ -0,0 +1,108 @@ + + + + Apache module mod_foobar + + + + + +

    Module mod_foobar

    + +
    Add this file as a link in mod/index.html
    + +

    + This module is contained in the mod_foobar.c file, and + is/is not compiled in by default. It provides for + the foobar feature. Any document with the mime type + foo/bar will be processed by this module. +

    + +
    Add the magic mime type to the list in +magic_types.html
    + +

    Summary

    +

    + General module documentation here. +

    + +

    Directives

    + + +
    Add these directives to the list in +directives.html
    + +
    +

    ADirective directive

    +

    + Syntax: ADirective some args +
    + Default: ADirective default value +
    + Context: context-list +
    + +

    context-list is where this directive can appear; +allowed: server config, virtual host, directory, .htaccess
    + + Override: override +
    + +
    required if the directive is allowed in .htaccess files; +the AllowOverride option that allows the directive.
    + + Status: status +
    + +
    Core if in core apache, Base if in one of the standard +modules, Extension if in an extension module (not compiled in by default) +or Experimental
    + + Module: mod_foobar +
    + Compatibility: compatibility notes + +
    + Describe any compatibility issues, such as "Only available in Apache + 1.2 or later," or "The Apache syntax for this directive is not + compatible with the NCSA directive of the same name." +
    +

    + +

    + The ADirective directive does something. +

    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/API.html b/APACHE_1_3_12/htdocs/manual/misc/API.html new file mode 100644 index 0000000000..bf0fb77d7a --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/API.html @@ -0,0 +1,1153 @@ + + +Apache API notes + + + + +

    Apache API notes

    + +These are some notes on the Apache API and the data structures you +have to deal with, etc. They are not yet nearly complete, but +hopefully, they will help you get your bearings. Keep in mind that +the API is still subject to change as we gain experience with it. +(See the TODO file for what might be coming). However, +it will be easy to adapt modules to any changes that are made. +(We have more modules to adapt than you do). +

    + +A few notes on general pedagogical style here. In the interest of +conciseness, all structure declarations here are incomplete --- the +real ones have more slots that I'm not telling you about. For the +most part, these are reserved to one component of the server core or +another, and should be altered by modules with caution. However, in +some cases, they really are things I just haven't gotten around to +yet. Welcome to the bleeding edge.

    + +Finally, here's an outline, to give you some bare idea of what's +coming up, and in what order: + +

    + +

    Basic concepts.

    + +We begin with an overview of the basic concepts behind the +API, and how they are manifested in the code. + +

    Handlers, Modules, and Requests

    + +Apache breaks down request handling into a series of steps, more or +less the same way the Netscape server API does (although this API has +a few more stages than NetSite does, as hooks for stuff I thought +might be useful in the future). These are: + +
      +
    • URI -> Filename translation +
    • Auth ID checking [is the user who they say they are?] +
    • Auth access checking [is the user authorized here?] +
    • Access checking other than auth +
    • Determining MIME type of the object requested +
    • `Fixups' --- there aren't any of these yet, but the phase is + intended as a hook for possible extensions like + SetEnv, which don't really fit well elsewhere. +
    • Actually sending a response back to the client. +
    • Logging the request +
    + +These phases are handled by looking at each of a succession of +modules, looking to see if each of them has a handler for the +phase, and attempting invoking it if so. The handler can typically do +one of three things: + +
      +
    • Handle the request, and indicate that it has done so + by returning the magic constant OK. +
    • Decline to handle the request, by returning the magic + integer constant DECLINED. In this case, the + server behaves in all respects as if the handler simply hadn't + been there. +
    • Signal an error, by returning one of the HTTP error codes. + This terminates normal handling of the request, although an + ErrorDocument may be invoked to try to mop up, and it will be + logged in any case. +
    + +Most phases are terminated by the first module that handles them; +however, for logging, `fixups', and non-access authentication +checking, all handlers always run (barring an error). Also, the +response phase is unique in that modules may declare multiple handlers +for it, via a dispatch table keyed on the MIME type of the requested +object. Modules may declare a response-phase handler which can handle +any request, by giving it the key */* (i.e., a +wildcard MIME type specification). However, wildcard handlers are +only invoked if the server has already tried and failed to find a more +specific response handler for the MIME type of the requested object +(either none existed, or they all declined).

    + +The handlers themselves are functions of one argument (a +request_rec structure. vide infra), which returns an +integer, as above.

    + +

    A brief tour of a module

    + +At this point, we need to explain the structure of a module. Our +candidate will be one of the messier ones, the CGI module --- this +handles both CGI scripts and the ScriptAlias config file +command. It's actually a great deal more complicated than most +modules, but if we're going to have only one example, it might as well +be the one with its fingers in every place.

    + +Let's begin with handlers. In order to handle the CGI scripts, the +module declares a response handler for them. Because of +ScriptAlias, it also has handlers for the name +translation phase (to recognize ScriptAliased URIs), the +type-checking phase (any ScriptAliased request is typed +as a CGI script).

    + +The module needs to maintain some per (virtual) +server information, namely, the ScriptAliases in effect; +the module structure therefore contains pointers to a functions which +builds these structures, and to another which combines two of them (in +case the main server and a virtual server both have +ScriptAliases declared).

    + +Finally, this module contains code to handle the +ScriptAlias command itself. This particular module only +declares one command, but there could be more, so modules have +command tables which declare their commands, and describe +where they are permitted, and how they are to be invoked.

    + +A final note on the declared types of the arguments of some of these +commands: a pool is a pointer to a resource pool +structure; these are used by the server to keep track of the memory +which has been allocated, files opened, etc., either to service a +particular request, or to handle the process of configuring itself. +That way, when the request is over (or, for the configuration pool, +when the server is restarting), the memory can be freed, and the files +closed, en masse, without anyone having to write explicit code to +track them all down and dispose of them. Also, a +cmd_parms structure contains various information about +the config file being read, and other status information, which is +sometimes of use to the function which processes a config-file command +(such as ScriptAlias). + +With no further ado, the module itself: + +

    +/* Declarations of handlers. */
    +
    +int translate_scriptalias (request_rec *);
    +int type_scriptalias (request_rec *);
    +int cgi_handler (request_rec *);
    +
    +/* Subsidiary dispatch table for response-phase handlers, by MIME type */
    +
    +handler_rec cgi_handlers[] = {
    +{ "application/x-httpd-cgi", cgi_handler },
    +{ NULL }
    +};
    +
    +/* Declarations of routines to manipulate the module's configuration
    + * info.  Note that these are returned, and passed in, as void *'s;
    + * the server core keeps track of them, but it doesn't, and can't,
    + * know their internal structure.
    + */
    +
    +void *make_cgi_server_config (pool *);
    +void *merge_cgi_server_config (pool *, void *, void *);
    +
    +/* Declarations of routines to handle config-file commands */
    +
    +extern char *script_alias(cmd_parms *, void *per_dir_config, char *fake,
    +                          char *real);
    +
    +command_rec cgi_cmds[] = {
    +{ "ScriptAlias", script_alias, NULL, RSRC_CONF, TAKE2,
    +    "a fakename and a realname"},
    +{ NULL }
    +};
    +
    +module cgi_module = {
    +   STANDARD_MODULE_STUFF,
    +   NULL,                     /* initializer */
    +   NULL,                     /* dir config creator */
    +   NULL,                     /* dir merger --- default is to override */
    +   make_cgi_server_config,   /* server config */
    +   merge_cgi_server_config,  /* merge server config */
    +   cgi_cmds,                 /* command table */
    +   cgi_handlers,             /* handlers */
    +   translate_scriptalias,    /* filename translation */
    +   NULL,                     /* check_user_id */
    +   NULL,                     /* check auth */
    +   NULL,                     /* check access */
    +   type_scriptalias,         /* type_checker */
    +   NULL,                     /* fixups */
    +   NULL,                     /* logger */
    +   NULL                      /* header parser */
    +};
    +
    + +

    How handlers work

    + +The sole argument to handlers is a request_rec structure. +This structure describes a particular request which has been made to +the server, on behalf of a client. In most cases, each connection to +the client generates only one request_rec structure.

    + +

    A brief tour of the request_rec

    + +The request_rec contains pointers to a resource pool +which will be cleared when the server is finished handling the +request; to structures containing per-server and per-connection +information, and most importantly, information on the request itself.

    + +The most important such information is a small set of character +strings describing attributes of the object being requested, including +its URI, filename, content-type and content-encoding (these being filled +in by the translation and type-check handlers which handle the +request, respectively).

    + +Other commonly used data items are tables giving the MIME headers on +the client's original request, MIME headers to be sent back with the +response (which modules can add to at will), and environment variables +for any subprocesses which are spawned off in the course of servicing +the request. These tables are manipulated using the +ap_table_get and ap_table_set routines.

    +

    + Note that the Content-type header value cannot be + set by module content-handlers using the ap_table_*() + routines. Rather, it is set by pointing the content_type + field in the request_rec structure to an appropriate + string. E.g., +
    +  r->content_type = "text/html";
    + 
    +
    +Finally, there are pointers to two data structures which, in turn, +point to per-module configuration structures. Specifically, these +hold pointers to the data structures which the module has built to +describe the way it has been configured to operate in a given +directory (via .htaccess files or +<Directory> sections), for private data it has +built in the course of servicing the request (so modules' handlers for +one phase can pass `notes' to their handlers for other phases). There +is another such configuration vector in the server_rec +data structure pointed to by the request_rec, which +contains per (virtual) server configuration data.

    + +Here is an abridged declaration, giving the fields most commonly used:

    + +

    +struct request_rec {
    +
    +  pool *pool;
    +  conn_rec *connection;
    +  server_rec *server;
    +
    +  /* What object is being requested */
    +
    +  char *uri;
    +  char *filename;
    +  char *path_info;
    +  char *args;           /* QUERY_ARGS, if any */
    +  struct stat finfo;    /* Set by server core;
    +                         * st_mode set to zero if no such file */
    +
    +  char *content_type;
    +  char *content_encoding;
    +
    +  /* 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).
    +   */
    +
    +  table *headers_in;
    +  table *headers_out;
    +  table *err_headers_out;
    +  table *subprocess_env;
    +
    +  /* Info about the request itself... */
    +
    +  int header_only;     /* HEAD request, as opposed to GET */
    +  char *protocol;      /* Protocol, as given to us, or HTTP/0.9 */
    +  char *method;        /* GET, HEAD, POST, etc. */
    +  int method_number;   /* M_GET, M_POST, etc. */
    +
    +  /* Info for logging */
    +
    +  char *the_request;
    +  int bytes_sent;
    +
    +  /* A flag which modules can set, to indicate that the data being
    +   * returned is volatile, and clients should be told not to cache it.
    +   */
    +
    +  int no_cache;
    +
    +  /* 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 */
    +
    +};
    +
    +
    + +

    Where request_rec structures come from

    + +Most request_rec structures are built by reading an HTTP +request from a client, and filling in the fields. However, there are +a few exceptions: + +
      +
    • If the request is to an imagemap, a type map (i.e., a + *.var file), or a CGI script which returned a + local `Location:', then the resource which the user requested + is going to be ultimately located by some URI other than what + the client originally supplied. In this case, the server does + an internal redirect, constructing a new + request_rec for the new URI, and processing it + almost exactly as if the client had requested the new URI + directly.

      + +

    • If some handler signaled an error, and an + ErrorDocument is in scope, the same internal + redirect machinery comes into play.

      + +

    • Finally, a handler occasionally needs to investigate `what + would happen if' some other request were run. For instance, + the directory indexing module needs to know what MIME type + would be assigned to a request for each directory entry, in + order to figure out what icon to use.

      + + Such handlers can construct a sub-request, using the + functions ap_sub_req_lookup_file, + ap_sub_req_lookup_uri, and + ap_sub_req_method_uri; these construct a new + request_rec structure and processes it as you + would expect, up to but not including the point of actually + sending a response. (These functions skip over the access + checks if the sub-request is for a file in the same directory + as the original request).

      + + (Server-side includes work by building sub-requests and then + actually invoking the response handler for them, via the + function ap_run_sub_req). +

    + +

    Handling requests, declining, and returning error + codes

    + +As discussed above, each handler, when invoked to handle a particular +request_rec, has to return an int to +indicate what happened. That can either be + +
      +
    • OK --- the request was handled successfully. This may or may + not terminate the phase. +
    • DECLINED --- no erroneous condition exists, but the module + declines to handle the phase; the server tries to find another. +
    • an HTTP error code, which aborts handling of the request. +
    + +Note that if the error code returned is REDIRECT, then +the module should put a Location in the request's +headers_out, to indicate where the client should be +redirected to.

    + +

    Special considerations for response + handlers

    + +Handlers for most phases do their work by simply setting a few fields +in the request_rec structure (or, in the case of access +checkers, simply by returning the correct error code). However, +response handlers have to actually send a request back to the client.

    + +They should begin by sending an HTTP response header, using the +function ap_send_http_header. (You don't have to do +anything special to skip sending the header for HTTP/0.9 requests; the +function figures out on its own that it shouldn't do anything). If +the request is marked header_only, that's all they should +do; they should return after that, without attempting any further +output.

    + +Otherwise, they should produce a request body which responds to the +client as appropriate. The primitives for this are ap_rputc +and ap_rprintf, for internally generated output, and +ap_send_fd, to copy the contents of some FILE * +straight to the client.

    + +At this point, you should more or less understand the following piece +of code, which is the handler which handles GET requests +which have no more specific handler; it also shows how conditional +GETs can be handled, if it's desirable to do so in a +particular response handler --- ap_set_last_modified checks +against the If-modified-since value supplied by the +client, if any, and returns an appropriate code (which will, if +nonzero, be USE_LOCAL_COPY). No similar considerations apply for +ap_set_content_length, but it returns an error code for +symmetry.

    + +

    +int default_handler (request_rec *r)
    +{
    +    int errstatus;
    +    FILE *f;
    +
    +    if (r->method_number != M_GET) return DECLINED;
    +    if (r->finfo.st_mode == 0) return NOT_FOUND;
    +
    +    if ((errstatus = ap_set_content_length (r, r->finfo.st_size))
    +	|| (errstatus = ap_set_last_modified (r, r->finfo.st_mtime)))
    +        return errstatus;
    +
    +    f = fopen (r->filename, "r");
    +
    +    if (f == NULL) {
    +        log_reason("file permissions deny server access",
    +                   r->filename, r);
    +        return FORBIDDEN;
    +    }
    +
    +    register_timeout ("send", r);
    +    ap_send_http_header (r);
    +
    +    if (!r->header_only) send_fd (f, r);
    +    ap_pfclose (r->pool, f);
    +    return OK;
    +}
    +
    + +Finally, if all of this is too much of a challenge, there are a few +ways out of it. First off, as shown above, a response handler which +has not yet produced any output can simply return an error code, in +which case the server will automatically produce an error response. +Secondly, it can punt to some other handler by invoking +ap_internal_redirect, which is how the internal redirection +machinery discussed above is invoked. A response handler which has +internally redirected should always return OK.

    + +(Invoking ap_internal_redirect from handlers which are +not response handlers will lead to serious confusion). + +

    Special considerations for authentication + handlers

    + +Stuff that should be discussed here in detail: + +
      +
    • Authentication-phase handlers not invoked unless auth is + configured for the directory. +
    • Common auth configuration stored in the core per-dir + configuration; it has accessors ap_auth_type, + ap_auth_name, and ap_requires. +
    • Common routines, to handle the protocol end of things, at least + for HTTP basic authentication (ap_get_basic_auth_pw, + which sets the connection->user structure field + automatically, and ap_note_basic_auth_failure, which + arranges for the proper WWW-Authenticate: header + to be sent back). +
    + +

    Special considerations for logging handlers

    + +When a request has internally redirected, there is the question of +what to log. Apache handles this by bundling the entire chain of +redirects into a list of request_rec structures which are +threaded through the r->prev and r->next +pointers. The request_rec which is passed to the logging +handlers in such cases is the one which was originally built for the +initial request from the client; note that the bytes_sent field will +only be correct in the last request in the chain (the one for which a +response was actually sent). + +

    Resource allocation and resource pools

    +

    +One of the problems of writing and designing a server-pool server is +that of preventing leakage, that is, allocating resources (memory, +open files, etc.), without subsequently releasing them. The resource +pool machinery is designed to make it easy to prevent this from +happening, by allowing resource to be allocated in such a way that +they are automatically released when the server is done with +them. +

    +

    +The way this works is as follows: the memory which is allocated, file +opened, etc., to deal with a particular request are tied to a +resource pool which is allocated for the request. The pool +is a data structure which itself tracks the resources in question. +

    +

    +When the request has been processed, the pool is cleared. At +that point, all the memory associated with it is released for reuse, +all files associated with it are closed, and any other clean-up +functions which are associated with the pool are run. When this is +over, we can be confident that all the resource tied to the pool have +been released, and that none of them have leaked. +

    +

    +Server restarts, and allocation of memory and resources for per-server +configuration, are handled in a similar way. There is a +configuration pool, which keeps track of resources which were +allocated while reading the server configuration files, and handling +the commands therein (for instance, the memory that was allocated for +per-server module configuration, log files and other files that were +opened, and so forth). When the server restarts, and has to reread +the configuration files, the configuration pool is cleared, and so the +memory and file descriptors which were taken up by reading them the +last time are made available for reuse. +

    +

    +It should be noted that use of the pool machinery isn't generally +obligatory, except for situations like logging handlers, where you +really need to register cleanups to make sure that the log file gets +closed when the server restarts (this is most easily done by using the +function ap_pfopen, which also +arranges for the underlying file descriptor to be closed before any +child processes, such as for CGI scripts, are execed), or +in case you are using the timeout machinery (which isn't yet even +documented here). However, there are two benefits to using it: +resources allocated to a pool never leak (even if you allocate a +scratch string, and just forget about it); also, for memory +allocation, ap_palloc is generally faster than +malloc. +

    +

    +We begin here by describing how memory is allocated to pools, and then +discuss how other resources are tracked by the resource pool +machinery. +

    +

    Allocation of memory in pools

    +

    +Memory is allocated to pools by calling the function +ap_palloc, which takes two arguments, one being a pointer to +a resource pool structure, and the other being the amount of memory to +allocate (in chars). Within handlers for handling +requests, the most common way of getting a resource pool structure is +by looking at the pool slot of the relevant +request_rec; hence the repeated appearance of the +following idiom in module code: +

    +
    +int my_handler(request_rec *r)
    +{
    +    struct my_structure *foo;
    +    ...
    +
    +    foo = (foo *)ap_palloc (r->pool, sizeof(my_structure));
    +}
    +
    +

    +Note that there is no ap_pfree --- +ap_palloced memory is freed only when the associated +resource pool is cleared. This means that ap_palloc does not +have to do as much accounting as malloc(); all it does in +the typical case is to round up the size, bump a pointer, and do a +range check. +

    +

    +(It also raises the possibility that heavy use of ap_palloc +could cause a server process to grow excessively large. There are +two ways to deal with this, which are dealt with below; briefly, you +can use malloc, and try to be sure that all of the memory +gets explicitly freed, or you can allocate a sub-pool of +the main pool, allocate your memory in the sub-pool, and clear it out +periodically. The latter technique is discussed in the section on +sub-pools below, and is used in the directory-indexing code, in order +to avoid excessive storage allocation when listing directories with +thousands of files). +

    +

    Allocating initialized memory

    +

    +There are functions which allocate initialized memory, and are +frequently useful. The function ap_pcalloc has the same +interface as ap_palloc, but clears out the memory it +allocates before it returns it. The function ap_pstrdup +takes a resource pool and a char * as arguments, and +allocates memory for a copy of the string the pointer points to, +returning a pointer to the copy. Finally ap_pstrcat is a +varargs-style function, which takes a pointer to a resource pool, and +at least two char * arguments, the last of which must be +NULL. It allocates enough memory to fit copies of each +of the strings, as a unit; for instance: +

    +
    +     ap_pstrcat (r->pool, "foo", "/", "bar", NULL);
    +
    +

    +returns a pointer to 8 bytes worth of memory, initialized to +"foo/bar". +

    +

    Commonly-used pools in the Apache Web server

    +

    +A pool is really defined by its lifetime more than anything else. There +are some static pools in http_main which are passed to various +non-http_main functions as arguments at opportune times. Here they are: +

    +
    +
    permanent_pool +
    +
    +
      +
    • never passed to anything else, this is the ancestor of all pools +
    • +
    +
    +
    pconf +
    +
    +
      +
    • subpool of permanent_pool +
    • +
    • created at the beginning of a config "cycle"; exists until the + server is terminated or restarts; passed to all config-time + routines, either via cmd->pool, or as the "pool *p" argument on + those which don't take pools +
    • +
    • passed to the module init() functions +
    • +
    +
    +
    ptemp +
    +
    +
      +
    • sorry I lie, this pool isn't called this currently in 1.3, I + renamed it this in my pthreads development. I'm referring to + the use of ptrans in the parent... contrast this with the later + definition of ptrans in the child. +
    • +
    • subpool of permanent_pool +
    • +
    • created at the beginning of a config "cycle"; exists until the + end of config parsing; passed to config-time routines via + cmd->temp_pool. Somewhat of a "bastard child" because it isn't + available everywhere. Used for temporary scratch space which + may be needed by some config routines but which is deleted at + the end of config. +
    • +
    +
    +
    pchild +
    +
    +
      +
    • subpool of permanent_pool +
    • +
    • created when a child is spawned (or a thread is created); lives + until that child (thread) is destroyed +
    • +
    • passed to the module child_init functions +
    • +
    • destruction happens right after the child_exit functions are + called... (which may explain why I think child_exit is redundant + and unneeded) +
    • +
    +
    +
    ptrans +
    +
    +
      +
    • should be a subpool of pchild, but currently is a subpool of + permanent_pool, see above +
    • +
    • cleared by the child before going into the accept() loop to receive + a connection +
    • +
    • used as connection->pool +
    • +
    +
    +
    r->pool +
    +
    +
      +
    • for the main request this is a subpool of connection->pool; for + subrequests it is a subpool of the parent request's pool. +
    • +
    • exists until the end of the request (i.e., + ap_destroy_sub_req, or + in child_main after process_request has finished) +
    • +
    • note that r itself is allocated from r->pool; i.e., + r->pool is + first created and then r is the first thing palloc()d from it +
    • +
    +
    +
    +

    +For almost everything folks do, r->pool is the pool to use. But you +can see how other lifetimes, such as pchild, are useful to some +modules... such as modules that need to open a database connection once +per child, and wish to clean it up when the child dies. +

    +

    +You can also see how some bugs have manifested themself, such as setting +connection->user to a value from r->pool -- in this case +connection exists +for the lifetime of ptrans, which is longer than r->pool (especially if +r->pool is a subrequest!). So the correct thing to do is to allocate +from connection->pool. +

    +

    +And there was another interesting bug in mod_include/mod_cgi. You'll see +in those that they do this test to decide if they should use r->pool +or r->main->pool. In this case the resource that they are registering +for cleanup is a child process. If it were registered in r->pool, +then the code would wait() for the child when the subrequest finishes. +With mod_include this could be any old #include, and the delay can be up +to 3 seconds... and happened quite frequently. Instead the subprocess +is registered in r->main->pool which causes it to be cleaned up when +the entire request is done -- i.e., after the output has been sent to +the client and logging has happened. +

    +

    Tracking open files, etc.

    +

    +As indicated above, resource pools are also used to track other sorts +of resources besides memory. The most common are open files. The +routine which is typically used for this is ap_pfopen, which +takes a resource pool and two strings as arguments; the strings are +the same as the typical arguments to fopen, e.g., +

    +
    +     ...
    +     FILE *f = ap_pfopen (r->pool, r->filename, "r");
    +
    +     if (f == NULL) { ... } else { ... }
    +
    +

    +There is also a ap_popenf routine, which parallels the +lower-level open system call. Both of these routines +arrange for the file to be closed when the resource pool in question +is cleared. +

    +

    +Unlike the case for memory, there are functions to close +files allocated with ap_pfopen, and ap_popenf, +namely ap_pfclose and ap_pclosef. (This is +because, on many systems, the number of files which a single process +can have open is quite limited). It is important to use these +functions to close files allocated with ap_pfopen and +ap_popenf, since to do otherwise could cause fatal errors on +systems such as Linux, which react badly if the same +FILE* is closed more than once. +

    +

    +(Using the close functions is not mandatory, since the +file will eventually be closed regardless, but you should consider it +in cases where your module is opening, or could open, a lot of files). +

    +

    Other sorts of resources --- cleanup functions

    +
    +More text goes here. Describe the the cleanup primitives in terms of +which the file stuff is implemented; also, spawn_process. +
    +

    +Pool cleanups live until clear_pool() is called: clear_pool(a) recursively +calls destroy_pool() on all subpools of a; then calls all the cleanups for a; +then releases all the memory for a. destroy_pool(a) calls clear_pool(a) +and then releases the pool structure itself. i.e., clear_pool(a) doesn't +delete a, it just frees up all the resources and you can start using it +again immediately. +

    +

    Fine control --- creating and dealing with sub-pools, with a note +on sub-requests

    + +On rare occasions, too-free use of ap_palloc() and the +associated primitives may result in undesirably profligate resource +allocation. You can deal with such a case by creating a +sub-pool, allocating within the sub-pool rather than the main +pool, and clearing or destroying the sub-pool, which releases the +resources which were associated with it. (This really is a +rare situation; the only case in which it comes up in the standard +module set is in case of listing directories, and then only with +very large directories. Unnecessary use of the primitives +discussed here can hair up your code quite a bit, with very little +gain).

    + +The primitive for creating a sub-pool is ap_make_sub_pool, +which takes another pool (the parent pool) as an argument. When the +main pool is cleared, the sub-pool will be destroyed. The sub-pool +may also be cleared or destroyed at any time, by calling the functions +ap_clear_pool and ap_destroy_pool, respectively. +(The difference is that ap_clear_pool frees resources +associated with the pool, while ap_destroy_pool also +deallocates the pool itself. In the former case, you can allocate new +resources within the pool, and clear it again, and so forth; in the +latter case, it is simply gone).

    + +One final note --- sub-requests have their own resource pools, which +are sub-pools of the resource pool for the main request. The polite +way to reclaim the resources associated with a sub request which you +have allocated (using the ap_sub_req_... functions) +is ap_destroy_sub_req, which frees the resource pool. +Before calling this function, be sure to copy anything that you care +about which might be allocated in the sub-request's resource pool into +someplace a little less volatile (for instance, the filename in its +request_rec structure).

    + +(Again, under most circumstances, you shouldn't feel obliged to call +this function; only 2K of memory or so are allocated for a typical sub +request, and it will be freed anyway when the main request pool is +cleared. It is only when you are allocating many, many sub-requests +for a single main request that you should seriously consider the +ap_destroy_... functions). + +

    Configuration, commands and the like

    + +One of the design goals for this server was to maintain external +compatibility with the NCSA 1.3 server --- that is, to read the same +configuration files, to process all the directives therein correctly, +and in general to be a drop-in replacement for NCSA. On the other +hand, another design goal was to move as much of the server's +functionality into modules which have as little as possible to do with +the monolithic server core. The only way to reconcile these goals is +to move the handling of most commands from the central server into the +modules.

    + +However, just giving the modules command tables is not enough to +divorce them completely from the server core. The server has to +remember the commands in order to act on them later. That involves +maintaining data which is private to the modules, and which can be +either per-server, or per-directory. Most things are per-directory, +including in particular access control and authorization information, +but also information on how to determine file types from suffixes, +which can be modified by AddType and +DefaultType directives, and so forth. In general, the +governing philosophy is that anything which can be made +configurable by directory should be; per-server information is +generally used in the standard set of modules for information like +Aliases and Redirects which come into play +before the request is tied to a particular place in the underlying +file system.

    + +Another requirement for emulating the NCSA server is being able to +handle the per-directory configuration files, generally called +.htaccess files, though even in the NCSA server they can +contain directives which have nothing at all to do with access +control. Accordingly, after URI -> filename translation, but before +performing any other phase, the server walks down the directory +hierarchy of the underlying filesystem, following the translated +pathname, to read any .htaccess files which might be +present. The information which is read in then has to be +merged with the applicable information from the server's own +config files (either from the <Directory> sections +in access.conf, or from defaults in +srm.conf, which actually behaves for most purposes almost +exactly like <Directory />).

    + +Finally, after having served a request which involved reading +.htaccess files, we need to discard the storage allocated +for handling them. That is solved the same way it is solved wherever +else similar problems come up, by tying those structures to the +per-transaction resource pool.

    + +

    Per-directory configuration structures

    + +Let's look out how all of this plays out in mod_mime.c, +which defines the file typing handler which emulates the NCSA server's +behavior of determining file types from suffixes. What we'll be +looking at, here, is the code which implements the +AddType and AddEncoding commands. These +commands can appear in .htaccess files, so they must be +handled in the module's private per-directory data, which in fact, +consists of two separate tables for MIME types and +encoding information, and is declared as follows: + +
    +typedef struct {
    +    table *forced_types;      /* Additional AddTyped stuff */
    +    table *encoding_types;    /* Added with AddEncoding... */
    +} mime_dir_config;
    +
    + +When the server is reading a configuration file, or +<Directory> section, which includes one of the MIME +module's commands, it needs to create a mime_dir_config +structure, so those commands have something to act on. It does this +by invoking the function it finds in the module's `create per-dir +config slot', with two arguments: the name of the directory to which +this configuration information applies (or NULL for +srm.conf), and a pointer to a resource pool in which the +allocation should happen.

    + +(If we are reading a .htaccess file, that resource pool +is the per-request resource pool for the request; otherwise it is a +resource pool which is used for configuration data, and cleared on +restarts. Either way, it is important for the structure being created +to vanish when the pool is cleared, by registering a cleanup on the +pool if necessary).

    + +For the MIME module, the per-dir config creation function just +ap_pallocs the structure above, and a creates a couple of +tables to fill it. That looks like this: + +

    +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);
    +
    +    return new;
    +}
    +
    + +Now, suppose we've just read in a .htaccess file. We +already have the per-directory configuration structure for the next +directory up in the hierarchy. If the .htaccess file we +just read in didn't have any AddType or +AddEncoding commands, its per-directory config structure +for the MIME module is still valid, and we can just use it. +Otherwise, we need to merge the two structures somehow.

    + +To do that, the server invokes the module's per-directory config merge +function, if one is present. That function takes three arguments: +the two structures being merged, and a resource pool in which to +allocate the result. For the MIME module, all that needs to be done +is overlay the tables from the new per-directory config structure with +those from the parent: + +

    +void *merge_mime_dir_configs (pool *p, void *parent_dirv, void *subdirv)
    +{
    +    mime_dir_config *parent_dir = (mime_dir_config *)parent_dirv;
    +    mime_dir_config *subdir = (mime_dir_config *)subdirv;
    +    mime_dir_config *new =
    +      (mime_dir_config *)ap_palloc (p, sizeof(mime_dir_config));
    +
    +    new->forced_types = ap_overlay_tables (p, subdir->forced_types,
    +                                        parent_dir->forced_types);
    +    new->encoding_types = ap_overlay_tables (p, subdir->encoding_types,
    +                                          parent_dir->encoding_types);
    +
    +    return new;
    +}
    +
    + +As a note --- if there is no per-directory merge function present, the +server will just use the subdirectory's configuration info, and ignore +the parent's. For some modules, that works just fine (e.g., for the +includes module, whose per-directory configuration information +consists solely of the state of the XBITHACK), and for +those modules, you can just not declare one, and leave the +corresponding structure slot in the module itself NULL.

    + +

    Command handling

    + +Now that we have these structures, we need to be able to figure out +how to fill them. That involves processing the actual +AddType and AddEncoding commands. To find +commands, the server looks in the module's command table. +That table contains information on how many arguments the commands +take, and in what formats, where it is permitted, and so forth. That +information is sufficient to allow the server to invoke most +command-handling functions with pre-parsed arguments. Without further +ado, let's look at the AddType command handler, which +looks like this (the AddEncoding command looks basically +the same, and won't be shown here): + +
    +char *add_type(cmd_parms *cmd, mime_dir_config *m, char *ct, char *ext)
    +{
    +    if (*ext == '.') ++ext;
    +    ap_table_set (m->forced_types, ext, ct);
    +    return NULL;
    +}
    +
    + +This command handler is unusually simple. As you can see, it takes +four arguments, two of which are pre-parsed arguments, the third being +the per-directory configuration structure for the module in question, +and the fourth being a pointer to a cmd_parms structure. +That structure contains a bunch of arguments which are frequently of +use to some, but not all, commands, including a resource pool (from +which memory can be allocated, and to which cleanups should be tied), +and the (virtual) server being configured, from which the module's +per-server configuration data can be obtained if required.

    + +Another way in which this particular command handler is unusually +simple is that there are no error conditions which it can encounter. +If there were, it could return an error message instead of +NULL; this causes an error to be printed out on the +server's stderr, followed by a quick exit, if it is in +the main config files; for a .htaccess file, the syntax +error is logged in the server error log (along with an indication of +where it came from), and the request is bounced with a server error +response (HTTP error status, code 500).

    + +The MIME module's command table has entries for these commands, which +look like this: + +

    +command_rec mime_cmds[] = {
    +{ "AddType", add_type, NULL, OR_FILEINFO, TAKE2,
    +    "a mime type followed by a file extension" },
    +{ "AddEncoding", add_encoding, NULL, OR_FILEINFO, TAKE2,
    +    "an encoding (e.g., gzip), followed by a file extension" },
    +{ NULL }
    +};
    +
    + +The entries in these tables are: + +
      +
    • The name of the command +
    • The function which handles it +
    • a (void *) pointer, which is passed in the + cmd_parms structure to the command handler --- + this is useful in case many similar commands are handled by the + same function. +
    • A bit mask indicating where the command may appear. There are + mask bits corresponding to each AllowOverride + option, and an additional mask bit, RSRC_CONF, + indicating that the command may appear in the server's own + config files, but not in any .htaccess + file. +
    • A flag indicating how many arguments the command handler wants + pre-parsed, and how they should be passed in. + TAKE2 indicates two pre-parsed arguments. Other + options are TAKE1, which indicates one pre-parsed + argument, FLAG, which indicates that the argument + should be On or Off, and is passed in + as a boolean flag, RAW_ARGS, which causes the + server to give the command the raw, unparsed arguments + (everything but the command name itself). There is also + ITERATE, which means that the handler looks the + same as TAKE1, but that if multiple arguments are + present, it should be called multiple times, and finally + ITERATE2, which indicates that the command handler + looks like a TAKE2, but if more arguments are + present, then it should be called multiple times, holding the + first argument constant. +
    • Finally, we have a string which describes the arguments that + should be present. If the arguments in the actual config file + are not as required, this string will be used to help give a + more specific error message. (You can safely leave this + NULL). +
    + +Finally, having set this all up, we have to use it. This is +ultimately done in the module's handlers, specifically for its +file-typing handler, which looks more or less like this; note that the +per-directory configuration structure is extracted from the +request_rec's per-directory configuration vector by using +the ap_get_module_config function. + +
    +int find_ct(request_rec *r)
    +{
    +    int i;
    +    char *fn = ap_pstrdup (r->pool, r->filename);
    +    mime_dir_config *conf = (mime_dir_config *)
    +             ap_get_module_config(r->per_dir_config, &mime_module);
    +    char *type;
    +
    +    if (S_ISDIR(r->finfo.st_mode)) {
    +        r->content_type = DIR_MAGIC_TYPE;
    +        return OK;
    +    }
    +
    +    if((i=ap_rind(fn,'.')) < 0) return DECLINED;
    +    ++i;
    +
    +    if ((type = ap_table_get (conf->encoding_types, &fn[i])))
    +    {
    +        r->content_encoding = type;
    +
    +        /* go back to previous extension to try to use it as a type */
    +
    +        fn[i-1] = '\0';
    +        if((i=ap_rind(fn,'.')) < 0) return OK;
    +        ++i;
    +    }
    +
    +    if ((type = ap_table_get (conf->forced_types, &fn[i])))
    +    {
    +        r->content_type = type;
    +    }
    +
    +    return OK;
    +}
    +
    +
    + +

    Side notes --- per-server configuration, virtual + servers, etc.

    + +The basic ideas behind per-server module configuration are basically +the same as those for per-directory configuration; there is a creation +function and a merge function, the latter being invoked where a +virtual server has partially overridden the base server configuration, +and a combined structure must be computed. (As with per-directory +configuration, the default if no merge function is specified, and a +module is configured in some virtual server, is that the base +configuration is simply ignored).

    + +The only substantial difference is that when a command needs to +configure the per-server private module data, it needs to go to the +cmd_parms data to get at it. Here's an example, from the +alias module, which also indicates how a syntax error can be returned +(note that the per-directory configuration argument to the command +handler is declared as a dummy, since the module doesn't actually have +per-directory config data): + +

    +char *add_redirect(cmd_parms *cmd, void *dummy, char *f, char *url)
    +{
    +    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->redirects);
    +
    +    if (!ap_is_url (url)) return "Redirect to non-URL";
    +
    +    new->fake = f; new->real = url;
    +    return NULL;
    +}
    +
    + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/FAQ-A.html b/APACHE_1_3_12/htdocs/manual/misc/FAQ-A.html new file mode 100644 index 0000000000..acaad45d9e --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/FAQ-A.html @@ -0,0 +1,298 @@ + + + + + + + + + + + + + + + + + + + + + Apache Server Frequently Asked Questions + + + + +

    Apache Server Frequently Asked Questions

    +

    + $Revision: 1.3 $ ($Date: 1999/12/31 23:11:17 $) +

    +

    + The latest version of this FAQ is always available from the main + Apache web site, at + <http://www.apache.org/docs/misc/FAQ.html>. +

    + + + + + + + + + + + + + + + +

    + If you are reading a text-only version of this FAQ, you may find numbers + enclosed in brackets (such as "[12]"). These refer to the list of + reference URLs to be found at the end of the document. These references + do not appear, and are not needed, for the hypertext version. +

    +

    The Questions

    +
      + + +
    1. Background +
        +
      1. What is Apache? +
      2. +
      3. Why was Apache created? +
      4. +
      5. How does The Apache Group's work relate to + other servers? +
      6. +
      7. Why the name "Apache"? +
      8. +
      9. OK, so how does Apache compare to other servers? +
      10. +
      11. How thoroughly tested is Apache? +
      12. +
      13. What are the future plans for Apache? +
      14. +
      15. Whom do I contact for support? +
      16. +
      17. Is there any more information on Apache? +
      18. +
      19. Where can I get Apache? +
      20. +
      +
    2. + + +
    + +
    + +

    The Answers

    + + +

    A. Background

    +
      +
    1. + What is Apache? + +

      + Apache was originally based on code and ideas found in the most + popular HTTP server of the time.. NCSA httpd 1.3 (early 1995). It has + since evolved into a far superior system which can rival (and probably + surpass) almost any other UNIX based HTTP server in terms of functionality, + efficiency and speed. +

      +

      + Since it began, it has been completely rewritten, and includes many new + features. Apache is, as of January 1997, the most popular WWW server on + the Internet, according to the + Netcraft Survey. +

      +
      +
    2. + +
    3. + Why was Apache created? + +

      + To address the concerns of a group of WWW providers and part-time httpd + programmers that httpd didn't behave as they wanted it to behave. + Apache is an entirely volunteer effort, completely funded by its + members, not by commercial sales. +

      +
      +
    4. + +
    5. + How does The Apache Group's work relate to other + server efforts, such as NCSA's? + +

      + We, of course, owe a great debt to NCSA and their programmers for + making the server Apache was based on. We now, however, have our own + server, and our project is mostly our own. The Apache Project is an + entirely independent venture. +

      +
      +
    6. + +
    7. + Why the name "Apache"? + +

      + A cute name which stuck. Apache is "A + PAtCHy server". It was + based on some existing code and a series of "patch files". +

      + +

      + For many developers it is also a reverant connotation to the Native + American Indian tribe of Apache, well-known for their + superior skills in warfare strategy and inexhaustible endurance. + Online information about the Apache Nation is tough to locate; we + suggest searching + Google, + Northernlight, + Infoseek, or + AllTheWeb. +

      +

      + In addition, http://www.indian.org/ and http://www.nativeweb.com/ are + two excellent resources for Native American information. +

      +
      +
    8. + +
    9. + OK, so how does Apache compare to other servers? + +

      + For an independent assessment, see + Web Compare's + comparison chart. +

      +

      + Apache has been shown to be substantially faster than many other + free servers. Although certain commercial servers have claimed to + surpass Apache's speed (it has not been demonstrated that any of these + "benchmarks" are a good way of measuring WWW server speed at any + rate), we feel that it is better to have a mostly-fast free server + than an extremely-fast server that costs thousands of dollars. Apache + is run on sites that get millions of hits per day, and they have + experienced no performance difficulties. +

      +
      +
    10. + +
    11. + How thoroughly tested is Apache? + +

      + Apache is run on over 3 million Internet servers (as of June 1999). It has + been tested thoroughly by both developers and users. The Apache Group + maintains rigorous standards before releasing new versions of their + server, and our server runs without a hitch on over one half of all + WWW servers available on the Internet. When bugs do show up, we + release patches and new versions as soon as they are available. +

      +

      + The Apache project's web site includes a page with a partial list of + sites running + Apache. +

      +
      +
    12. + +
    13. + What are the future plans for Apache? + +

      +

        +
      • to continue to be an "open source" no-charge-for-use HTTP server, +
      • +
      • to keep up with advances in HTTP protocol and web developments in + general, +
      • +
      • to collect suggestions for fixes/improvements from its users, +
      • +
      • to respond to needs of large volume providers as well as + occasional users. +
      • +
      +

      +
      +
    14. + +
    15. + Whom do I contact for support? + +

      + There is no official support for Apache. None of the developers want to + be swamped by a flood of trivial questions that can be resolved elsewhere. + Bug reports and suggestions should be sent via + the bug report page. + Other questions should be directed to the + comp.infosystems.www.servers.unix or comp.infosystems.www.servers.ms-windows + newsgroup (as appropriate for the platform you use), where some of the + Apache team lurk, in the company of many other httpd gurus who + should be able to help. +

      +

      + Commercial support for Apache is, however, available from a number + of third parties. +

      +
      +
    16. + +
    17. + Is there any more information available on + Apache? + +

      + Indeed there is. See the main + Apache web site. + There is also a regular electronic publication called + Apache Week + available. Links to relevant Apache Week articles are + included below where appropriate. There are also some + Apache-specific books available. +

      +
      +
    18. + +
    19. + Where can I get Apache? + +

      + You can find out how to download the source for Apache at the + project's + main web page. +

      +
      +
    20. +
    + + + + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/FAQ-B.html b/APACHE_1_3_12/htdocs/manual/misc/FAQ-B.html new file mode 100644 index 0000000000..ee1798a518 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/FAQ-B.html @@ -0,0 +1,447 @@ + + + + + + + + + + + + + + + + + + + + + Apache Server Frequently Asked Questions + + + + +

    Apache Server Frequently Asked Questions

    +

    + $Revision: 1.3 $ ($Date: 2000/01/30 15:47:42 $) +

    +

    + The latest version of this FAQ is always available from the main + Apache web site, at + <http://www.apache.org/docs/misc/FAQ.html>. +

    + + + + + + + + + + + + + + + +

    + If you are reading a text-only version of this FAQ, you may find numbers + enclosed in brackets (such as "[12]"). These refer to the list of + reference URLs to be found at the end of the document. These references + do not appear, and are not needed, for the hypertext version. +

    +

    The Questions

    +
      + + +
    1. General Technical Questions +
        +
      1. "Why can't I ...? Why won't ... + work?" What to do in case of problems +
      2. +
      3. How compatible is Apache with my existing + NCSA 1.3 setup? +
      4. +
      5. Is Apache Year 2000 compliant? +
      6. +
      7. How do I submit a patch to the Apache Group? +
      8. +
      9. Why has Apache stolen my favourite site's + Internet address? +
      10. +
      11. Why am I getting spam mail from the Apache site? +
      12. +
      13. May I include the Apache software on a CD or other + package I'm distributing? +
      14. +
      15. What's the best hardware/operating system/... How do + I get the most out of my Apache Web server? +
      16. +
      17. What are "regular expressions"? +
      18. +
      19. Why isn't there a binary for my platform?
      20. +
      +
    2. + + +
    + +
    + +

    The Answers

    + + + +

    B. General Technical Questions

    +
      + +
    1. + "Why can't I ...? Why won't ... work?" What to + do in case of problems + +

      + If you are having trouble with your Apache server software, you should + take the following steps: +

      +
        +
      1. Check the errorlog! +

        + Apache tries to be helpful when it encounters a problem. In many + cases, it will provide some details by writing one or messages to + the server error log. Sometimes this is enough for you to diagnose + & fix the problem yourself (such as file permissions or the like). + The default location of the error log is + /usr/local/apache/logs/error_log, but see the + ErrorLog + directive in your config files for the location on your server. +

        +
      2. +
      3. Check the + FAQ! +

        + The latest version of the Apache Frequently-Asked Questions list can + always be found at the main Apache web site. +

        +
      4. +
      5. Check the Apache bug database +

        + Most problems that get reported to The Apache Group are recorded in + the + bug database. + Please check the existing reports, open + and closed, before adding one. If you find + that your issue has already been reported, please don't add + a "me, too" report. If the original report isn't closed + yet, we suggest that you check it periodically. You might also + consider contacting the original submitter, because there may be an + email exchange going on about the issue that isn't getting recorded + in the database. +

        +
      6. +
      7. Ask in the comp.infosystems.www.servers.unix + or comp.infosystems.www.servers.ms-windows USENET + newsgroup (as appropriate for the platform you use). +

        + A lot of common problems never make it to the bug database because + there's already high Q&A traffic about them in the + comp.infosystems.www.servers.unix + newsgroup. Many Apache users, and some of the developers, can be + found roaming its virtual halls, so it is suggested that you seek + wisdom there. The chances are good that you'll get a faster answer + there than from the bug database, even if you don't see + your question already posted. +

        +
      8. +
      9. If all else fails, report the problem in the bug + database +

        + If you've gone through those steps above that are appropriate and + have obtained no relief, then please do let The Apache + Group know about the problem by + logging a bug report. +

        +

        + If your problem involves the server crashing and generating a core + dump, please include a backtrace (if possible). As an example, +

        +

        +

        +
        # cd ServerRoot
        + # dbx httpd core
        + (dbx) where
        +
        +
        +

        +

        + (Substitute the appropriate locations for your + ServerRoot and your httpd and + core files. You may have to use gdb + instead of dbx.) +

        +
      10. +
      +
      +
    2. + +
    3. + How compatible is Apache with my existing NCSA 1.3 + setup? + +

      + Apache attempts to offer all the features and configuration options + of NCSA httpd 1.3, as well as many of the additional features found in + NCSA httpd 1.4 and NCSA httpd 1.5. +

      +

      + NCSA httpd appears to be moving toward adding experimental features + which are not generally required at the moment. Some of the experiments + will succeed while others will inevitably be dropped. The Apache + philosophy is to add what's needed as and when it is needed. +

      +

      + Friendly interaction between Apache and NCSA developers should ensure + that fundamental feature enhancements stay consistent between the two + servers for the foreseeable future. +

      +
      +
    4. + +
    5. + Is Apache Year 2000 compliant? + +

      + Yes, Apache is Year 2000 compliant. +

      +

      + Apache internally never stores years as two digits. + On the HTTP protocol level RFC1123-style addresses are generated + which is the only format a HTTP/1.1-compliant server should + generate. To be compatible with older applications Apache + recognizes ANSI C's asctime() and + RFC850-/RFC1036-style date formats, too. + The asctime() format uses four-digit years, + but the RFC850 and RFC1036 date formats only define a two-digit year. + If Apache sees such a date with a value less than 70 it assumes that + the century is 20 rather than 19. +

      +

      + Although Apache is Year 2000 compliant, you may still get problems + if the underlying OS has problems with dates past year 2000 + (e.g., OS calls which accept or return year numbers). + Most (UNIX) systems store dates internally as signed 32-bit integers + which contain the number of seconds since 1st January 1970, so + the magic boundary to worry about is the year 2038 and not 2000. + But modern operating systems shouldn't cause any trouble + at all. +

      +

      + Users of Apache 1.2.x should upgrade to a current version of Apache 1.3 + (see year-2000 improvements in + Apache 1.3 for details). +

      +

      + The Apache HTTP Server project is an open-source software product of + the Apache Software Foundation. The project and the Foundation + cannot offer legal assurances regarding any suitability + of the software for your application. There are several commercial + Apache support organizations and derivative server products available + that may be able to stand behind the software and provide you with + any assurances you may require. You may find links to some of these + vendors at + <http://www.apache.org/info/support.cgi>. +

      +

      + The Apache HTTP server software is distributed with the following + disclaimer, found in the software license: +

      +
      +   THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
      +   EXPRESSED 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 APACHE GROUP OR
      +   ITS 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.
      +  
      +
      +
    6. + +
    7. + How do I submit a patch to the Apache Group? +

      + The Apache Group encourages patches from outside developers. There + are 2 main "types" of patches: small bugfixes and general + improvements. Bugfixes should be submitting using the Apache bug report page. + Improvements, modifications, and additions should follow the + instructions below. +

      +

      + In general, the first course of action is to be a member of the + new-httpd@apache.org mailing list. This indicates to + the Group that you are closely following the latest Apache + developments. Your patch file should be generated using either + 'diff -c' or 'diff -u' against + the latest CVS tree. To submit your patch, send email to + new-httpd@apache.org with a Subject: line + that starts with [PATCH] and includes a general + description of the patch. In the body of the message, the patch + should be clearly described and then included at the end of the + message. If the patch-file is long, you can note a URL to the file + instead of the file itself. Use of MIME enclosures/attachments + should be avoided. +

      +

      + Be prepared to respond to any questions about your patches and + possibly defend your code. If your patch results in a lot of + discussion, you may be asked to submit an updated patch that + incorporate all changes and suggestions. +

      +
      +
    8. + +
    9. Why has Apache stolen my favourite site's + Internet address? +

      + The simple answer is: "It hasn't." This misconception is usually + caused by the site in question having migrated to the Apache Web + server software, but not having migrated the site's content yet. When + Apache is installed, the default page that gets installed tells the + Webmaster the installation was successful. The expectation is that + this default page will be replaced with the site's real content. + If it doesn't, complain to the Webmaster, not to the Apache project -- + we just make the software and aren't responsible for what people + do (or don't do) with it. +

      +
      +
    10. + +
    11. Why am I getting spam mail from the + Apache site? +

      + The short answer is: "You aren't." Usually when someone thinks the + Apache site is originating spam, it's because they've traced the + spam to a Web site, and the Web site says it's using Apache. See the + previous FAQ entry for more details on this + phenomenon. +

      +

      + No marketing spam originates from the Apache site. The only mail + that comes from the site goes only to addresses that have been + requested to receive the mail. +

      +
      +
    12. + +
    13. May I include the Apache software on a + CD or other package I'm distributing? +

      + The detailed answer to this question can be found in the + Apache license, which is included in the Apache distribution in + the file LICENSE. You can also find it on the Web at + <http://www.apache.org/LICENSE.txt>. +

      +
      +
    14. + +
    15. + What's the best hardware/operating system/... How do + I get the most out of my Apache Web server? + +

      + Check out Dean Gaudet's + performance tuning page. +

      +
      +
    16. + +
    17. + What are "regular expressions"? +

      + Regular expressions are a way of describing a pattern - for example, "all + the words that begin with the letter A" or "every 10-digit phone number" + or even "Every sentence with two commas in it, and no capital letter Q". + Regular expressions (aka "regexp"s) are useful in Apache because they + let you apply certain attributes against collections of files or resources + in very flexible ways - for example, all .gif and .jpg files under + any "images" directory could be written as /.*\/images\/.*[jpg|gif]/. +

      +

      + The best overview around is probably the one which comes with Perl. + We implement a simple subset of Perl's regexp support, but it's + still a good way to learn what they mean. You can start by going + to the CPAN page on regular expressions, and branching out from + there. +

      +
      +
    18. + +
    19. + Why isn't there a binary for my platform? +

      + The developers make sure that the software builds and works + correctly on the platforms available to them; this does + not necessarily mean that your platform + is one of them. In addition, the Apache HTTP server project + is primarily source oriented, meaning that distributing + valid and buildable source code is the purpose of a release, + not making sure that there is a binary package for all of the + supported platforms. +

      +

      + If you don't see a kit for your platform listed in the + binary distribution area + (<URL:http://www.apache.org/dist/binaries/>), + it means either that the platform isn't available to any of + the developers, or that they just haven't gotten around to + preparing a binary for it. As this is a voluntary project, + they are under no obligation to do so. Users are encouraged + and expected to build the software themselves. +

      +

      + The sole exception to these practices is the Windows package. + Unlike most Unix and Unix-like platforms, Windows systems + do not come with a bundled software development environment, + so we do prepare binary kits for Windows when we make + a release. Again, however, it's a voluntary thing and only + a limited number of the developers have the capability to build + the InstallShield package, so the Windows release may lag + somewhat behind the source release. This lag should be + no more than a few days at most. +

      +
      +
    20. + +
    + + + + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/FAQ-C.html b/APACHE_1_3_12/htdocs/manual/misc/FAQ-C.html new file mode 100644 index 0000000000..3f226c08f8 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/FAQ-C.html @@ -0,0 +1,273 @@ + + + + + + + + + + + + + + + + + + + + + Apache Server Frequently Asked Questions + + + + +

    Apache Server Frequently Asked Questions

    +

    + $Revision: 1.1 $ ($Date: 1999/06/24 15:02:51 $) +

    +

    + The latest version of this FAQ is always available from the main + Apache web site, at + <http://www.apache.org/docs/misc/FAQ.html>. +

    + + + + + + + + + + + + + + + +

    + If you are reading a text-only version of this FAQ, you may find numbers + enclosed in brackets (such as "[12]"). These refer to the list of + reference URLs to be found at the end of the document. These references + do not appear, and are not needed, for the hypertext version. +

    +

    The Questions

    +
      + + +
    1. Building Apache +
        +
      1. Why do I get an error about an undefined + reference to "__inet_ntoa" or other + __inet_* symbols? +
      2. +
      3. Why won't Apache compile with my + system's cc? +
      4. +
      5. Why do I get complaints about redefinition + of "struct iovec" when compiling under Linux? +
      6. +
      7. I'm using gcc and I get some compilation errors, + what is wrong? +
      8. +
      9. I'm using RedHat Linux 5.0, or some other + glibc-based Linux system, and I get errors with the + crypt function when I attempt to build Apache 1.2. +
      10. +
      +
    2. + + +
    + +
    + +

    The Answers

    + + + +

    C. Building Apache

    +
      + +
    1. + Why do I get an error about an undefined reference to + "__inet_ntoa" or other + __inet_* symbols? + +

      + If you have installed BIND-8 + then this is normally due to a conflict between your include files + and your libraries. BIND-8 installs its include files and libraries + /usr/local/include/ and /usr/local/lib/, while + the resolver that comes with your system is probably installed in + /usr/include/ and /usr/lib/. If + your system uses the header files in /usr/local/include/ + before those in /usr/include/ but you do not use the new + resolver library, then the two versions will conflict. +

      +

      + To resolve this, you can either make sure you use the include files + and libraries that came with your system or make sure to use the + new include files and libraries. Adding -lbind to the + EXTRA_LDFLAGS line in your Configuration + file, then re-running Configure, should resolve the + problem. (Apache versions 1.2.* and earlier use + EXTRA_LFLAGS instead.) +

      +

      + Note:As of BIND 8.1.1, the bind libraries and files are + installed under /usr/local/bind by default, so you + should not run into this problem. Should you want to use the bind + resolvers you'll have to add the following to the respective lines: +

      +

      +

      +
      EXTRA_CFLAGS=-I/usr/local/bind/include +
      + EXTRA_LDFLAGS=-L/usr/local/bind/lib +
      + EXTRA_LIBS=-lbind
      +
      +
      +

      +
      +
    2. + +
    3. + Why won't Apache compile with my system's + cc? + +

      + If the server won't compile on your system, it is probably due to one + of the following causes: +

      +
        +
      • The Configure script doesn't recognize your system + environment. +
        + This might be either because it's completely unknown or because + the specific environment (include files, OS version, et + cetera) isn't explicitly handled. If this happens, you may + need to port the server to your OS yourself. +
      • +
      • Your system's C compiler is garbage. +
        + Some operating systems include a default C compiler that is either + not ANSI C-compliant or suffers from other deficiencies. The usual + recommendation in cases like this is to acquire, install, and use + gcc. +
      • +
      • Your include files may be confused. +
        + In some cases, we have found that a compiler installation or system + upgrade has left the C header files in an inconsistent state. Make + sure that your include directory tree is in sync with the compiler and + the operating system. +
      • +
      • Your operating system or compiler may be out of + revision. +
        + Software vendors (including those that develop operating systems) + issue new releases for a reason; sometimes to add functionality, but + more often to fix bugs that have been discovered. Try upgrading + your compiler and/or your operating system. +
      • +
      +

      + The Apache Group tests the ability to build the server on many + different platforms. Unfortunately, we can't test all of the OS + platforms there are. If you have verified that none of the above + issues is the cause of your problem, and it hasn't been reported + before, please submit a + problem report. + Be sure to include complete details, such as the compiler + & OS versions and exact error messages. +

      +
      +
    4. + +
    5. + Why do I get complaints about redefinition + of "struct iovec" when + compiling under Linux? + +

      + This is a conflict between your C library includes and your kernel + includes. You need to make sure that the versions of both are matched + properly. There are two workarounds, either one will solve the problem: +

      +

      +

        +
      • Remove the definition of struct iovec from your C + library includes. It is located in /usr/include/sys/uio.h. + Or, +
      • +
      • Add -DNO_WRITEV to the EXTRA_CFLAGS + line in your Configuration and reconfigure/rebuild. + This hurts performance and should only be used as a last resort. +
      • +
      +

      +
      +
    6. + +
    7. I'm using gcc and I get some + compilation errors, what is wrong? +

      + GCC parses your system header files and produces a modified subset which + it uses for compiling. This behaviour ties GCC tightly to the version + of your operating system. So, for example, if you were running IRIX 5.3 + when you built GCC and then upgrade to IRIX 6.2 later, you will have to + rebuild GCC. Similarly for Solaris 2.4, 2.5, or 2.5.1 when you upgrade + to 2.6. Sometimes you can type "gcc -v" and it will tell you the version + of the operating system it was built against. +

      +

      + If you fail to do this, then it is very likely that Apache will fail + to build. One of the most common errors is with readv, + writev, or uio.h. This is not a + bug with Apache. You will need to re-install GCC. +

      +
      +
    8. + +
    9. + I'm using RedHat Linux 5.0, or some other + glibc-based Linux system, and I get errors with the + crypt function when I attempt to build Apache 1.2. + + +

      + glibc puts the crypt function into a separate + library. Edit your src/Configuration file and set this: +

      +
      +
      EXTRA_LIBS=-lcrypt +
      +
      +

      + Then re-run src/Configure and re-execute the make. +

      +
      +
    10. + +
    + + + + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/FAQ-D.html b/APACHE_1_3_12/htdocs/manual/misc/FAQ-D.html new file mode 100644 index 0000000000..a4062e92dd --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/FAQ-D.html @@ -0,0 +1,396 @@ + + + + + + + + + + + + + + + + + + + + + Apache Server Frequently Asked Questions + + + + +

    Apache Server Frequently Asked Questions

    +

    + $Revision: 1.5 $ ($Date: 1999/12/10 14:56:26 $) +

    +

    + The latest version of this FAQ is always available from the main + Apache web site, at + <http://www.apache.org/docs/misc/FAQ.html>. +

    + + + + + + + + + + + + + + + +

    + If you are reading a text-only version of this FAQ, you may find numbers + enclosed in brackets (such as "[12]"). These refer to the list of + reference URLs to be found at the end of the document. These references + do not appear, and are not needed, for the hypertext version. +

    +

    The Questions

    +
      + + +
    1. Error Log Messages and Problems Starting Apache +
        +
      1. Why do I get "setgid: Invalid + argument" at startup? +
      2. +
      3. Why am I getting "httpd: could not + set socket option TCP_NODELAY" in my error log? +
      4. +
      5. Why am I getting "connection + reset by peer" in my error log? +
      6. +
      7. The errorlog says Apache dumped core, + but where's the dump file? +
      8. +
      9. When I run it under Linux I get "shmget: + function not found", what should I do? +
      10. +
      11. Server hangs, or fails to start, and/or error log + fills with "fcntl: F_SETLKW: No record locks + available" or similar messages +
      12. +
      13. Why am I getting "Expected </Directory> + but saw </Directory>" when I try to start Apache? +
      14. +
      15. I'm using RedHat Linux and I have problems with httpd + dying randomly or not restarting properly +
      16. +
      17. I upgraded from an Apache version earlier + than 1.2.0 and suddenly I have problems with Apache dying randomly + or not restarting properly +
      18. +
      19. When I try to start Apache from a DOS + window, I get a message like "Cannot determine host name. + Use ServerName directive to set it manually." What does + this mean? +
      20. +
      21. When I try to start Apache for Windows, I get a message + like "Unable To Locate WS2_32.DLL...". What should I do? +
      22. +
      +
    2. + + +
    + +
    + +

    The Answers

    + + + +

    D. Error Log Messages and Problems Starting Apache

    +
      + +
    1. + Why do I get "setgid: Invalid + argument" at startup? + +

      + Your + Group + directive (probably in conf/httpd.conf) needs to name a + group that actually exists in the /etc/group file (or + your system's equivalent). This problem is also frequently seen when + a negative number is used in the Group directive + (e.g., "Group #-1"). Using a group name + -- not group number -- found in your system's group database should + solve this problem in all cases. +

      +
      +
    2. + +
    3. + Why am I getting "httpd: could not set socket + option TCP_NODELAY" in my error log? + +

      + This message almost always indicates that the client disconnected + before Apache reached the point of calling setsockopt() + for the connection. It shouldn't occur for more than about 1% of the + requests your server handles, and it's advisory only in any case. +

      +
      +
    4. + +
    5. + Why am I getting "connection reset by + peer" in my error log? + +

      + This is a normal message and nothing about which to be alarmed. It simply + means that the client canceled the connection before it had been + completely set up - such as by the end-user pressing the "Stop" + button. People's patience being what it is, sites with response-time + problems or slow network links may experiences this more than + high-capacity ones or those with large pipes to the network. +

      +
      +
    6. + +
    7. + The errorlog says Apache dumped core, but where's the dump + file? + +

      + In Apache version 1.2, the error log message + about dumped core includes the directory where the dump file should be + located. However, many Unixes do not allow a process that has + called setuid() to dump core for security reasons; + the typical Apache setup has the server started as root to bind to + port 80, after which it changes UIDs to a non-privileged user to + serve requests. +

      +

      + Dealing with this is extremely operating system-specific, and may + require rebuilding your system kernel. Consult your operating system + documentation or vendor for more information about whether your system + does this and how to bypass it. If there is a documented way + of bypassing it, it is recommended that you bypass it only for the + httpd server process if possible. +

      +

      + The canonical location for Apache's core-dump files is the + ServerRoot + directory. As of Apache version 1.3, the location can be set via + the + CoreDumpDirectory + directive to a different directory. Make sure that this directory is + writable by the user the server runs as (as opposed to the user the server + is started as). +

      +
      +
    8. + +
    9. + When I run it under Linux I get "shmget: + function not found", what should I do? + +

      + Your kernel has been built without SysV IPC support. You will have + to rebuild the kernel with that support enabled (it's under the + "General Setup" submenu). Documentation for kernel + building is beyond the scope of this FAQ; you should consult the Kernel + HOWTO, or the documentation provided with your distribution, or + a Linux + newsgroup/mailing list. As a last-resort workaround, you can + comment out the #define USE_SHMGET_SCOREBOARD + definition in the LINUX section of + src/conf.h and rebuild the server (prior to 1.3b4, + simply removing #define HAVE_SHMGET would have + sufficed). This will produce a server which is slower and less + reliable. +

      +
      +
    10. + +
    11. + Server hangs, or fails to start, and/or error log + fills with "fcntl: F_SETLKW: No record locks + available" or similar messages + + +

      + These are symptoms of a fine locking problem, which usually means that + the server is trying to use a synchronization file on an NFS filesystem. +

      +

      + Because of its parallel-operation model, the Apache Web server needs to + provide some form of synchronization when accessing certain resources. + One of these synchronization methods involves taking out locks on a file, + which means that the filesystem whereon the lockfile resides must support + locking. In many cases this means it can't be kept on an + NFS-mounted filesystem. +

      +

      + To cause the Web server to work around the NFS locking limitations, include + a line such as the following in your server configuration files: +

      +
      +
      LockFile /var/run/apache-lock +
      +
      +

      + The directory should not be generally writable (e.g., don't use + /var/tmp). + See the LockFile + documentation for more information. +

      +
      +
    12. + +
    13. Why am I getting "Expected + </Directory> but saw </Directory>" when + I try to start Apache? +

      + This is a known problem with certain versions of the AIX C compiler. + IBM are working on a solution, and the issue is being tracked by + problem report #2312. +

      +
      +
    14. + +
    15. + I'm using RedHat Linux and I have problems with httpd + dying randomly or not restarting properly + + +

      + RedHat Linux versions 4.x (and possibly earlier) RPMs contain + various nasty scripts which do not stop or restart Apache properly. + These can affect you even if you're not running the RedHat supplied + RPMs. +

      +

      + If you're using the default install then you're probably running + Apache 1.1.3, which is outdated. From RedHat's ftp site you can + pick up a more recent RPM for Apache 1.2.x. This will solve one of + the problems. +

      +

      + If you're using a custom built Apache rather than the RedHat RPMs + then you should rpm -e apache. In particular you want + the mildly broken /etc/logrotate.d/apache script to be + removed, and you want the broken /etc/rc.d/init.d/httpd + (or httpd.init) script to be removed. The latter is + actually fixed by the apache-1.2.5 RPMs but if you're building your + own Apache then you probably don't want the RedHat files. +

      +

      + We can't stress enough how important it is for folks, especially + vendors to follow the stopping Apache + directions given in our documentation. In RedHat's defense, + the broken scripts were necessary with Apache 1.1.x because the + Linux support in 1.1.x was very poor, and there were various race + conditions on all platforms. None of this should be necessary with + Apache 1.2 and later. +

      +
      +
    16. + +
    17. + I upgraded from an Apache version earlier + than 1.2.0 and suddenly I have problems with Apache dying randomly + or not restarting properly + + +

      + You should read the previous note about + problems with RedHat installations. It is entirely likely that your + installation has start/stop/restart scripts which were built for + an earlier version of Apache. Versions earlier than 1.2.0 had + various race conditions that made it necessary to use + kill -9 at times to take out all the httpd servers. + But that should not be necessary any longer. You should follow + the directions on how to stop + and restart Apache. +

      +

      As of Apache 1.3 there is a script + src/support/apachectl which, after a bit of + customization, is suitable for starting, stopping, and restarting + your server. +

      +
      +
    18. + +
    19. + When I try to start Apache from a DOS + window, I get a message like "Cannot determine host name. + Use ServerName directive to set it manually." What does + this mean? + +

      + It means what it says; the Apache software can't determine the + hostname of your system. Edit your conf\httpd.conf + file, look for the string "ServerName", and make sure there's an + uncommented directive such as +

      +
      +
      ServerName localhost
      +
      +

      + or +

      +
      +
      ServerName www.foo.com
      +
      +

      + in the file. Correct it if there one there with wrong information, or + add one if you don't already have one. +

      +

      + Also, make sure that your Windows system has DNS enabled. See the TCP/IP + setup component of the Networking or Internet Options control panel. +

      +

      + After verifying that DNS is enabled and that you have a valid hostname + in your ServerName directive, try to start the server + again. +

      +
      +
    20. +
    21. + When I try to start Apache for Windows, I get a message + like "Unable To Locate WS2_32.DLL...". What should I do? +

      + Short answer: You need to install Winsock 2, available from + http://www.microsoft.com/windows95/downloads/ +

      +

      + Detailed answer: Prior to version 1.3.9, Apache for Windows used Winsock 1.1. Beginning with + version 1.3.9, Apache began using Winsock 2 features (specifically, WSADuplicateSocket()). + WS2_32.DLL implements the Winsock 2 API. Winsock 2 ships with Windows NT 4.0 and Windows 98. + Some of the earlier releases of Windows 95 did not include Winsock 2. +

      +
      +
    22. + +
    + + + + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/FAQ-E.html b/APACHE_1_3_12/htdocs/manual/misc/FAQ-E.html new file mode 100644 index 0000000000..b0ef556ec4 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/FAQ-E.html @@ -0,0 +1,598 @@ + + + + + + + + + + + + + + + + + + + + + Apache Server Frequently Asked Questions + + + + +

    Apache Server Frequently Asked Questions

    +

    + $Revision: 1.4 $ ($Date: 1999/07/04 16:33:00 $) +

    +

    + The latest version of this FAQ is always available from the main + Apache web site, at + <http://www.apache.org/docs/misc/FAQ.html>. +

    + + + + + + + + + + + + + + + +

    + If you are reading a text-only version of this FAQ, you may find numbers + enclosed in brackets (such as "[12]"). These refer to the list of + reference URLs to be found at the end of the document. These references + do not appear, and are not needed, for the hypertext version. +

    +

    The Questions

    +
      + + +
    1. Configuration Questions +
        +
      1. Why can't I run more than <n> + virtual hosts? +
      2. +
      3. Can I increase FD_SETSIZE + on FreeBSD? +
      4. +
      5. Why doesn't my ErrorDocument + 401 work? +
      6. +
      7. Why does Apache send a cookie on every response? +
      8. +
      9. Why don't my cookies work, I even compiled in + mod_cookies? +
      10. +
      11. Why do my Java app[let]s give me plain text + when I request an URL from an Apache server? +
      12. +
      13. How do I get Apache to send a MIDI file so the + browser can play it? +
      14. +
      15. How do I add browsers and referrers to my logs? +
      16. +
      17. Why does accessing directories only work + when I include the trailing "/" + (e.g.http://foo.domain.com/~user/) but + not when I omit it + (e.g.http://foo.domain.com/~user)? +
      18. +
      19. Why doesn't mod_info list any + directives? +
      20. +
      21. I upgraded to Apache 1.3 and now my + virtual hosts don't work! +
      22. +
      23. I'm using RedHat Linux and my .htm files are + showing up as HTML source rather than being formatted! +
      24. +
      25. My .htaccess files are being + ignored. +
      26. +
      27. Why do I get a + "Forbidden" message whenever I try to + access a particular directory? +
      +
    2. + + +
    + +
    + +

    The Answers

    + + + +

    E. Configuration Questions

    +
      + +
    1. + Why can't I run more than <n> + virtual hosts? + +

      + You are probably running into resource limitations in your + operating system. The most common limitation is the + per-process limit on file descriptors, + which is almost always the cause of problems seen when adding + virtual hosts. Apache often does not give an intuitive error + message because it is normally some library routine (such as + gethostbyname()) which needs file descriptors and + doesn't complain intelligibly when it can't get them. +

      +

      + Each log file requires a file descriptor, which means that if you are + using separate access and error logs for each virtual host, each + virtual host needs two file descriptors. Each + Listen + directive also needs a file descriptor. +

      +

      + Typical values for <n> that we've seen are in + the neighborhood of 128 or 250. When the server bumps into the file + descriptor limit, it may dump core with a SIGSEGV, it might just + hang, or it may limp along and you'll see (possibly meaningful) errors + in the error log. One common problem that occurs when you run into + a file descriptor limit is that CGI scripts stop being executed + properly. +

      +

      + As to what you can do about this: +

      +
        +
      1. Reduce the number of + Listen + directives. If there are no other servers running on the machine + on the same port then you normally don't + need any Listen directives at all. By default Apache listens to + all addresses on port 80. +
      2. +
      3. Reduce the number of log files. You can use + mod_log_config + to log all requests to a single log file while including the name + of the virtual host in the log file. You can then write a + script to split the logfile into separate files later if + necessary. Such a script is provided with the Apache 1.3 distribution + in the src/support/split-logfile file. +
      4. +
      5. Increase the number of file descriptors available to the server + (see your system's documentation on the limit or + ulimit commands). For some systems, information on + how to do this is available in the + performance hints page. There is a specific + note for FreeBSD below. +

        + For Windows 95, try modifying your C:\CONFIG.SYS file to + include a line like +

        +
        +
        FILES=300 +
        +
        +

        + Remember that you'll need to reboot your Windows 95 system in order + for the new value to take effect. +

        +
      6. +
      7. "Don't do that" - try to run with fewer virtual hosts +
      8. +
      9. Spread your operation across multiple server processes (using + Listen + for example, but see the first point) and/or ports. +
      10. +
      +

      + Since this is an operating-system limitation, there's not much else + available in the way of solutions. +

      +

      + As of 1.2.1 we have made attempts to work around various limitations + involving running with many descriptors. + More information is available. +

      +
      +
    2. + +
    3. + Can I increase FD_SETSIZE on FreeBSD? + +

      + On versions of FreeBSD before 3.0, the FD_SETSIZE define + defaults to 256. This means that you will have trouble usefully using + more than 256 file descriptors in Apache. This can be increased, but + doing so can be tricky. +

      +

      + If you are using a version prior to 2.2, you need to recompile your + kernel with a larger FD_SETSIZE. This can be done by adding a + line such as: +

      +
      +
      options FD_SETSIZE nnn +
      +
      +

      + to your kernel config file. Starting at version 2.2, this is no + longer necessary. +

      +

      + If you are using a version of 2.1-stable from after 1997/03/10 or + 2.2 or 3.0-current from before 1997/06/28, there is a limit in + the resolver library that prevents it from using more file descriptors + than what FD_SETSIZE is set to when libc is compiled. To + increase this, you have to recompile libc with a higher + FD_SETSIZE. +

      +

      + In FreeBSD 3.0, the default FD_SETSIZE has been increased to + 1024 and the above limitation in the resolver library + has been removed. +

      +

      + After you deal with the appropriate changes above, you can increase + the setting of FD_SETSIZE at Apache compilation time + by adding "-DFD_SETSIZE=nnn" to the + EXTRA_CFLAGS line in your Configuration + file. +

      +
      +
    4. + +
    5. + Why doesn't my ErrorDocument 401 work? + +

      + You need to use it with a URL in the form + "/foo/bar" and not one with a method and + hostname such as "http://host/foo/bar". See the + ErrorDocument + documentation for details. This was incorrectly documented in the past. +

      +
      +
    6. + +
    7. + Why does Apache send a cookie on every response? + +

      + Apache does not automatically send a cookie on every + response, unless you have re-compiled it with the + mod_usertrack + module, and specifically enabled it with the + CookieTracking + directive. + This module has been in Apache since version 1.2. + This module may help track users, and uses cookies to do this. If + you are not using the data generated by mod_usertrack, do + not compile it into Apache. +

      +
      +
    8. + +
    9. + Why don't my cookies work, I even compiled in + mod_cookies? + + +

      + Firstly, you do not need to compile in + mod_cookies in order for your scripts to work (see the + previous question + for more about mod_cookies). Apache passes on your + Set-Cookie header fine, with or without this module. If + cookies do not work it will be because your script does not work + properly or your browser does not use cookies or is not set-up to + accept them. +

      +
      +
    10. + +
    11. + Why do my Java app[let]s give me plain text when I request + an URL from an Apache server? + +

      + As of version 1.2, Apache is an HTTP/1.1 (HyperText Transfer Protocol + version 1.1) server. This fact is reflected in the protocol version + that's included in the response headers sent to a client when + processing a request. Unfortunately, low-level Web access classes + included in the Java Development Kit (JDK) version 1.0.2 expect to see + the version string "HTTP/1.0" and do not correctly interpret + the "HTTP/1.1" value Apache is sending (this part of the + response is a declaration of what the server can do rather than a + declaration of the dialect of the response). The result + is that the JDK methods do not correctly parse the headers, and + include them with the document content by mistake. +

      +

      + This is definitely a bug in the JDK 1.0.2 foundation classes from Sun, + and it has been fixed in version 1.1. However, the classes in + question are part of the virtual machine environment, which means + they're part of the Web browser (if Java-enabled) or the Java + environment on the client system - so even if you develop + your classes with a recent JDK, the eventual users might + encounter the problem. + The classes involved are replaceable by vendors implementing the + Java virtual machine environment, and so even those that are based + upon the 1.0.2 version may not have this problem. +

      +

      + In the meantime, a workaround is to tell + Apache to "fake" an HTTP/1.0 response to requests that come + from the JDK methods; this can be done by including a line such as the + following in your server configuration files: +

      +

      +

      +
      BrowserMatch Java1.0 force-response-1.0 +
      + BrowserMatch JDK/1.0 force-response-1.0
      +
      +
      +

      +

      + More information about this issue can be found in the + Java and HTTP/1.1 + page at the Apache web site. +

      +
      +
    12. + +
    13. + How do I get Apache to send a MIDI file so the browser can + play it? + +

      + Even though the registered MIME type for MIDI files is + audio/midi, some browsers are not set up to recognize it + as such; instead, they look for audio/x-midi. There are + two things you can do to address this: +

      +
        +
      1. Configure your browser to treat documents of type + audio/midi correctly. This is the type that Apache + sends by default. This may not be workable, however, if you have + many client installations to change, or if some or many of the + clients are not under your control. +
      2. +
      3. Instruct Apache to send a different Content-type + header for these files by adding the following line to your server's + configuration files: +

        +

        +
        AddType audio/x-midi .mid .midi .kar +
        +
        +

        +

        + Note that this may break browsers that do recognize the + audio/midi MIME type unless they're prepared to also + handle audio/x-midi the same way. +

        +
      4. +
      +
      +
    14. + +
    15. + How do I add browsers and referrers to my logs? + +

      + Apache provides a couple of different ways of doing this. The + recommended method is to compile the + mod_log_config + module into your configuration and use the + CustomLog + directive. +

      +

      + You can either log the additional information in files other than your + normal transfer log, or you can add them to the records already being + written. For example: +

      +

      + + CustomLog logs/access_log "%h %l %u %t \"%r\" %s %b \"%{Referer}i\" \"%{User-Agent}i\"" + +

      +

      + This will add the values of the User-agent: and + Referer: headers, which indicate the client and the + referring page, respectively, to the end of each line in the access + log. +

      +

      + You may want to check out the Apache Week article + entitled: + "Gathering Visitor Information: Customizing Your + Logfiles". +

      +
      +
    16. + +
    17. + Why does accessing directories only work when I include + the trailing "/" + (e.g.http://foo.domain.com/~user/) + but not when I omit it + (e.g.http://foo.domain.com/~user)? + +

      + When you access a directory without a trailing "/", Apache needs + to send what is called a redirect to the client to tell it to + add the trailing slash. If it did not do so, relative URLs would + not work properly. When it sends the redirect, it needs to know + the name of the server so that it can include it in the redirect. + There are two ways for Apache to find this out; either it can guess, + or you can tell it. If your DNS is configured correctly, it can + normally guess without any problems. If it is not, however, then + you need to tell it. +

      +

      + Add a ServerName directive + to the config file to tell it what the domain name of the server is. +

      +
      +
    18. + +
    19. + Why doesn't mod_info list any directives? + +

      + The mod_info + module allows you to use a Web browser to see how your server is + configured. Among the information it displays is the list modules and + their configuration directives. The "current" values for + the directives are not necessarily those of the running server; they + are extracted from the configuration files themselves at the time of + the request. If the files have been changed since the server was last + reloaded, the display will will not match the values actively in use. + If the files and the path to the files are not readable by the user as + which the server is running (see the + User + directive), then mod_info cannot read them in order to + list their values. An entry will be made in the error log in + this event, however. +

      +
      +
    20. + +
    21. + I upgraded to Apache 1.3 and now my virtual hosts don't + work! + +

      + In versions of Apache prior to 1.3b2, there was a lot of confusion + regarding address-based virtual hosts and (HTTP/1.1) name-based + virtual hosts, and the rules concerning how the server processed + <VirtualHost> definitions were very complex and not + well documented. +

      +

      + Apache 1.3b2 introduced a new directive, + NameVirtualHost, + which simplifies the rules quite a bit. However, changing the rules + like this means that your existing name-based + <VirtualHost> containers probably won't work + correctly immediately following the upgrade. +

      +

      + To correct this problem, add the following line to the beginning of + your server configuration file, before defining any virtual hosts: +

      +
      +
      NameVirtualHost n.n.n.n +
      +
      +

      + Replace the "n.n.n.n" with the IP address to + which the name-based virtual host names resolve; if you have multiple + name-based hosts on multiple addresses, repeat the directive for each + address. +

      +

      + Make sure that your name-based <VirtualHost> blocks + contain ServerName and possibly ServerAlias + directives so Apache can be sure to tell them apart correctly. +

      +

      + Please see the + Apache + Virtual Host documentation for further details about configuration. +

      +
      +
    22. + +
    23. + I'm using RedHat Linux and my .htm files are showing + up as HTML source rather than being formatted! + + +

      + RedHat messed up and forgot to put a content type for .htm + files into /etc/mime.types. Edit /etc/mime.types, + find the line containing html and add htm to it. + Then restart your httpd server: +

      +
      +
      kill -HUP `cat /var/run/httpd.pid` +
      +
      +

      + Then clear your browsers' caches. (Many browsers won't + re-examine the content type after they've reloaded a page.) +

      +
      +
    24. + +
    25. + My .htaccess files are being ignored. +

      + This is almost always due to your + AllowOverride directive being set incorrectly for the directory in + question. If it is set to None then .htaccess files will + not even be looked for. If you do have one that is set, then be certain + it covers the directory you are trying to use the .htaccess file in. + This is normally accomplished by ensuring it is inside the proper + Directory container. +

      +
      +
    26. +
    27. + Why do I get a "Forbidden" message + whenever I try to access a particular directory? +

      + This message is generally caused because either +

      +
        +
      • The underlying file system permissions do not allow the + User/Group under which Apache is running to access the necessary + files; or +
      • The Apache configuration has some access restrictions in + place which forbid access to the files. +
      +

      + You can determine which case applies to your situation by checking the + error log. +

      +

      + In the case where file system permission are at fault, remember + that not only must the directory and files in question be readable, + but also all parent directories must be at least searchable by the + web server in order for the content to be accessible. +

      +
      +
    28. +
    + + + + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/FAQ-F.html b/APACHE_1_3_12/htdocs/manual/misc/FAQ-F.html new file mode 100644 index 0000000000..a4442a481e --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/FAQ-F.html @@ -0,0 +1,524 @@ + + + + + + + + + + + + + + + + + + + + + Apache Server Frequently Asked Questions + + + + +

    Apache Server Frequently Asked Questions

    +

    + $Revision: 1.2 $ ($Date: 1999/07/03 22:12:50 $) +

    +

    + The latest version of this FAQ is always available from the main + Apache web site, at + <http://www.apache.org/docs/misc/FAQ.html>. +

    + + + + + + + + + + + + + + + +

    + If you are reading a text-only version of this FAQ, you may find numbers + enclosed in brackets (such as "[12]"). These refer to the list of + reference URLs to be found at the end of the document. These references + do not appear, and are not needed, for the hypertext version. +

    +

    The Questions

    +
      + + +
    1. Dynamic Content (CGI and SSI) +
        +
      1. How do I enable CGI execution + in directories other than the ScriptAlias? +
      2. +
      3. What does it mean when my + CGIs fail with "Premature end of script + headers"? +
      4. +
      5. Why do I keep getting "Method Not + Allowed" for form POST requests? +
      6. +
      7. How can I get my script's output without + Apache buffering it? Why doesn't my server push work? +
      8. +
      9. Where can I find the "CGI + specification"? +
      10. +
      11. Why isn't FastCGI included with Apache any + more? +
      12. +
      13. How do I enable SSI (parsed HTML)? +
      14. +
      15. Why don't my parsed files get cached? +
      16. +
      17. How can I have my script output parsed? +
      18. +
      19. SSIs don't work for VirtualHosts and/or + user home directories +
      20. +
      21. How can I use ErrorDocument + and SSI to simplify customized error messages? +
      22. +
      23. Why is the environment variable + REMOTE_USER not set? +
      24. +
      +
    2. + + +
    + +
    + +

    The Answers

    + + + +

    F. Dynamic Content (CGI and SSI)

    +
      + +
    1. + How do I enable CGI execution in directories other than + the ScriptAlias? + +

      + Apache recognizes all files in a directory named as a + ScriptAlias + as being eligible for execution rather than processing as normal + documents. This applies regardless of the file name, so scripts in a + ScriptAlias directory don't need to be named + "*.cgi" or "*.pl" or + whatever. In other words, all files in a ScriptAlias + directory are scripts, as far as Apache is concerned. +

      +

      + To persuade Apache to execute scripts in other locations, such as in + directories where normal documents may also live, you must tell it how + to recognize them - and also that it's okay to execute them. For + this, you need to use something like the + AddHandler + directive. +

      +

      +

        +
      1. In an appropriate section of your server configuration files, add + a line such as +

        +

        +
        AddHandler cgi-script .cgi +
        +
        +

        +

        + The server will then recognize that all files in that location (and + its logical descendants) that end in ".cgi" + are script files, not documents. +

        +
      2. +
      3. Make sure that the directory location is covered by an + Options + declaration that includes the ExecCGI option. +
      4. +
      +

      +

      + In some situations, you might not want to actually + allow all files named "*.cgi" to be executable. + Perhaps all you want is to enable a particular file in a normal directory to + be executable. This can be alternatively accomplished + via mod_rewrite + and the following steps: +

      +

      +

        +
      1. Locally add to the corresponding .htaccess file a ruleset + similar to this one: +

        +

        +
        RewriteEngine on +
        + RewriteBase /~foo/bar/ +
        + RewriteRule ^quux\.cgi$ - [T=application/x-httpd-cgi]
        +
        +
        +

        +
      2. +
      3. Make sure that the directory location is covered by an + Options + declaration that includes the ExecCGI and + FollowSymLinks option. +
      4. +
      +

      +
      +
    2. + +
    3. + What does it mean when my CGIs fail with + "Premature end of script headers"? + +

      + It means just what it says: the server was expecting a complete set of + HTTP headers (one or more followed by a blank line), and didn't get + them. +

      +

      + The most common cause of this problem is the script dying before + sending the complete set of headers, or possibly any at all, to the + server. To see if this is the case, try running the script standalone + from an interactive session, rather than as a script under the server. + If you get error messages, this is almost certainly the cause of the + "premature end of script headers" message. Even if the CGI + runs fine from the command line, remember that the environment and + permissions may be different when running under the web server. The + CGI can only access resources allowed for the User and + Group specified in + your Apache configuration. In addition, the environment will not be + the same as the one provided on the command line, but it can be + adjusted using the directives provided by mod_env. +

      +

      + The second most common cause of this (aside from people not + outputting the required headers at all) is a result of an interaction + with Perl's output buffering. To make Perl flush its buffers + after each output statement, insert the following statements around + the print or write statements that send your + HTTP headers: +

      +

      +

      +
      {
      +  local ($oldbar) = $|;
      +  $cfh = select (STDOUT);
      +  $| = 1;
      +  #
      +  # print your HTTP headers here
      +  #
      +  $| = $oldbar;
      +  select ($cfh);
      + }
      +
      +
      +

      +

      + This is generally only necessary when you are calling external + programs from your script that send output to stdout, or if there will + be a long delay between the time the headers are sent and the actual + content starts being emitted. To maximize performance, you should + turn buffer-flushing back off (with $| = 0 or the + equivalent) after the statements that send the headers, as displayed + above. +

      +

      + If your script isn't written in Perl, do the equivalent thing for + whatever language you are using (e.g., for C, call + fflush() after writing the headers). +

      +

      + Another cause for the "premature end of script headers" + message are the RLimitCPU and RLimitMEM directives. You may + get the message if the CGI script was killed due to a + resource limit. +

      +

      + In addition, a configuration problem in suEXEC, mod_perl, or another third party + module can often interfere with the execution of your CGI and cause + the "premature end of script headers" message. +

      +
      +
    4. + +
    5. + Why do I keep getting "Method Not Allowed" for + form POST requests? + +

      + This is almost always due to Apache not being configured to treat the + file you are trying to POST to as a CGI script. You can not POST + to a normal HTML file; the operation has no meaning. See the FAQ + entry on CGIs outside ScriptAliased + directories for details on how to configure Apache to treat the + file in question as a CGI. +

      +
      +
    6. + +
    7. + How can I get my script's output without Apache buffering + it? Why doesn't my server push work? + +

      + As of Apache 1.3, CGI scripts are essentially not buffered. Every time + your script does a "flush" to output data, that data gets relayed on to + the client. Some scripting languages, for example Perl, have their own + buffering for output - this can be disabled by setting the $| + special variable to 1. Of course this does increase the overall number + of packets being transmitted, which can result in a sense of slowness for + the end user. +

      +

      Prior to 1.3, you needed to use "nph-" scripts to accomplish + non-buffering. Today, the only difference between nph scripts and + normal scripts is that nph scripts require the full HTTP headers to + be sent. +

      +
      +
    8. + +
    9. + Where can I find the "CGI specification"? + +

      + The Common Gateway Interface (CGI) specification can be found at + the original NCSA site + < + http://hoohoo.ncsa.uiuc.edu/cgi/interface.html>. + This version hasn't been updated since 1995, and there have been + some efforts to update it. +

      +

      + A new draft is being worked on with the intent of making it an informational + RFC; you can find out more about this project at + <http://web.golux.com/coar/cgi/>. +

      +
      +
    10. + +
    11. + Why isn't FastCGI included with Apache any more? + +

      + The simple answer is that it was becoming too difficult to keep the + version being included with Apache synchronized with the master copy + at the + FastCGI web site. When a new version of Apache was released, the + version of the FastCGI module included with it would soon be out of date. +

      +

      + You can still obtain the FastCGI module for Apache from the master + FastCGI web site. +

      +
      +
    12. + +
    13. + How do I enable SSI (parsed HTML)? + +

      + SSI (an acronym for Server-Side Include) directives allow static HTML + documents to be enhanced at run-time (e.g., when delivered to + a client by Apache). The format of SSI directives is covered + in the mod_include manual; + suffice it to say that Apache supports not only SSI but + xSSI (eXtended SSI) directives. +

      +

      + Processing a document at run-time is called parsing it; hence + the term "parsed HTML" sometimes used for documents that + contain SSI instructions. Parsing tends to be extremely + resource-consumptive, and is not enabled by default. It can also + interfere with the cachability of your documents, which can put a + further load on your server. (see the + next question for more information about this.) +

      +

      + To enable SSI processing, you need to +

      +
        +
      • Build your server with the + mod_include + module. This is normally compiled in by default. +
      • +
      • Make sure your server configuration files have an + Options + directive which permits Includes. +
      • +
      • Make sure that the directory where you want the SSI documents to + live is covered by the "server-parsed" content handler, + either explicitly or in some ancestral location. That can be done + with the following + AddHandler + directive: +

        +

        +
        AddHandler server-parsed .shtml +
        +
        +

        +

        + This indicates that all files ending in ".shtml" in that + location (or its descendants) should be parsed. Note that using + ".html" will cause all normal HTML files to be parsed, + which may put an inordinate load on your server. +

        +
      • +
      +

      + For additional information, see the Apache Week article on + Using Server Side Includes. +

      +
      +
    14. + +
    15. + Why don't my parsed files get cached? + +

      + Since the server is performing run-time processing of your SSI + directives, which may change the content shipped to the client, it + can't know at the time it starts parsing what the final size of the + result will be, or whether the parsed result will always be the same. + This means that it can't generate Content-Length or + Last-Modified headers. Caches commonly work by comparing + the Last-Modified of what's in the cache with that being + delivered by the server. Since the server isn't sending that header + for a parsed document, whatever's doing the caching can't tell whether + the document has changed or not - and so fetches it again to be on the + safe side. +

      +

      + You can work around this in some cases by causing an + Expires header to be generated. (See the + mod_expires + documentation for more details.) Another possibility is to use the + XBitHack Full + mechanism, which tells Apache to send (under certain circumstances + detailed in the XBitHack directive description) a + Last-Modified header based upon the last modification + time of the file being parsed. Note that this may actually be lying + to the client if the parsed file doesn't change but the SSI-inserted + content does; if the included content changes often, this can result + in stale copies being cached. +

      +
      +
    16. + +
    17. + How can I have my script output parsed? + +

      + So you want to include SSI directives in the output from your CGI + script, but can't figure out how to do it? + The short answer is "you can't." This is potentially + a security liability and, more importantly, it can not be cleanly + implemented under the current server API. The best workaround + is for your script itself to do what the SSIs would be doing. + After all, it's generating the rest of the content. +

      +

      + This is a feature The Apache Group hopes to add in the next major + release after 1.3. +

      +
      +
    18. + +
    19. + SSIs don't work for VirtualHosts and/or + user home directories. + +

      + This is almost always due to having some setting in your config file that + sets "Options Includes" or some other setting for your DocumentRoot + but not for other directories. If you set it inside a Directory + section, then that setting will only apply to that directory. +

      +
      +
    20. + +
    21. + How can I use ErrorDocument + and SSI to simplify customized error messages? + +

      + Have a look at this document. + It shows in example form how you can a combination of XSSI and + negotiation to tailor a set of ErrorDocuments to your + personal taste, and returning different internationalized error + responses based on the client's native language. +

      +
      +
    22. + +
    23. + Why is the environment variable + REMOTE_USER not set? + +

      + This variable is set and thus available in SSI or CGI scripts if and + only if the requested document was protected by access + authentication. For an explanation on how to implement these restrictions, + see + Apache Week's + articles on + Using User Authentication + or + DBM User Authentication. +

      +

      + Hint: When using a CGI script to receive the data of a HTML FORM + notice that protecting the document containing the FORM is not + sufficient to provide REMOTE_USER to the CGI script. You have + to protect the CGI script, too. Or alternatively only the CGI script (then + authentication happens only after filling out the form). +

      +
      +
    24. + +
    + + + + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/FAQ-G.html b/APACHE_1_3_12/htdocs/manual/misc/FAQ-G.html new file mode 100644 index 0000000000..4461ff424f --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/FAQ-G.html @@ -0,0 +1,371 @@ + + + + + + + + + + + + + + + + + + + + + Apache Server Frequently Asked Questions + + + + +

    Apache Server Frequently Asked Questions

    +

    + $Revision: 1.1 $ ($Date: 1999/06/24 15:02:52 $) +

    +

    + The latest version of this FAQ is always available from the main + Apache web site, at + <http://www.apache.org/docs/misc/FAQ.html>. +

    + + + + + + + + + + + + + + + +

    + If you are reading a text-only version of this FAQ, you may find numbers + enclosed in brackets (such as "[12]"). These refer to the list of + reference URLs to be found at the end of the document. These references + do not appear, and are not needed, for the hypertext version. +

    +

    The Questions

    +
      + + +
    1. Authentication and Access Restrictions +
        +
      1. Why isn't restricting access by host or domain name + working correctly? +
      2. +
      3. How do I set up Apache to require + a username and password to access certain documents? +
      4. +
      5. How do I set up Apache to allow access + to certain documents only if a site is either a local site + or the user supplies a password and username? +
      6. +
      7. Why does my authentication give + me a server error? +
      8. +
      9. Do I have to keep the (mSQL) + authentication information on the same machine? +
      10. +
      11. Why is my mSQL authentication terribly slow? +
      12. +
      13. Can I use my /etc/passwd file + for Web page authentication? +
      14. +
      +
    2. + + +
    + +
    + +

    The Answers

    + + +

    G. Authentication and Access Restrictions

    +
      + +
    1. + Why isn't restricting access by host or domain name + working correctly? + +

      + Two of the most common causes of this are: +

      +
        +
      1. An error, inconsistency, or unexpected mapping in the DNS + registration +
        + This happens frequently: your configuration restricts access to + Host.FooBar.Com, but you can't get in from that host. + The usual reason for this is that Host.FooBar.Com is + actually an alias for another name, and when Apache performs the + address-to-name lookup it's getting the real name, not + Host.FooBar.Com. You can verify this by checking the + reverse lookup yourself. The easiest way to work around it is to + specify the correct host name in your configuration. +
      2. +
      3. Inadequate checking and verification in your + configuration of Apache +
        + If you intend to perform access checking and restriction based upon + the client's host or domain name, you really need to configure + Apache to double-check the origin information it's supplied. You do + this by adding the -DMAXIMUM_DNS clause to the + EXTRA_CFLAGS definition in your + Configuration file. For example: +

        +

        +
        EXTRA_CFLAGS=-DMAXIMUM_DNS +
        +
        +

        +

        + This will cause Apache to be very paranoid about making sure a + particular host address is really assigned to the name it + claims to be. Note that this can incur a significant + performance penalty, however, because of all the name resolution + requests being sent to a nameserver. +

        +
      4. +
      +
      +
    2. + +
    3. + How do I set up Apache to require a username and + password to access certain documents? + +

      + There are several ways to do this; some of the more popular + ones are to use the mod_auth, + mod_auth_db, or + mod_auth_dbm modules. +

      +

      + For an explanation on how to implement these restrictions, see + Apache Week's + articles on + Using User Authentication + or + DBM User Authentication. +

      +
      +
    4. + +
    5. + How do I set up Apache to allow access to certain + documents only if a site is either a local site or + the user supplies a password and username? + +

      + Use the Satisfy directive, + in particular the Satisfy Any directive, to require + that only one of the access restrictions be met. For example, + adding the following configuration to a .htaccess + or server configuration file would restrict access to people who + either are accessing the site from a host under domain.com or + who can supply a valid username and password: +

      +

      +

      +
      deny from all +
      + allow from .domain.com +
      + AuthType Basic +
      + AuthUserFile /usr/local/apache/conf/htpasswd.users +
      + AuthName "special directory" +
      + require valid-user +
      + satisfy any
      +
      +
      +

      +

      + See the user authentication + question and the mod_access + module for details on how the above directives work. +

      +
      +
    6. + +
    7. + Why does my authentication give me a server error? + +

      + Under normal circumstances, the Apache access control modules will + pass unrecognized user IDs on to the next access control module in + line. Only if the user ID is recognized and the password is validated + (or not) will it give the usual success or "authentication + failed" messages. +

      +

      + However, if the last access module in line 'declines' the validation + request (because it has never heard of the user ID or because it is not + configured), the http_request handler will give one of + the following, confusing, errors: +

      +
        +
      • check access +
      • +
      • check user. No user file? +
      • +
      • check access. No groups file? +
      • +
      +

      + This does not mean that you have to add an + 'AuthUserFile /dev/null' line as some magazines suggest! +

      +

      + The solution is to ensure that at least the last module is authoritative + and CONFIGURED. By default, mod_auth is + authoritative and will give an OK/Denied, but only if it is configured + with the proper AuthUserFile. Likewise, if a valid group + is required. (Remember that the modules are processed in the reverse + order from that in which they appear in your compile-time + Configuration file.) +

      +

      + A typical situation for this error is when you are using the + mod_auth_dbm, mod_auth_msql, + mod_auth_mysql, mod_auth_anon or + mod_auth_cookie modules on their own. These are by + default not authoritative, and this will pass the + buck on to the (non-existent) next authentication module when the + user ID is not in their respective database. Just add the appropriate + 'XXXAuthoritative yes' line to the configuration. +

      +

      + In general it is a good idea (though not terribly efficient) to have the + file-based mod_auth a module of last resort. This allows + you to access the web server with a few special passwords even if the + databases are down or corrupted. This does cost a + file open/seek/close for each request in a protected area. +

      +
      +
    8. + +
    9. + Do I have to keep the (mSQL) authentication information + on the same machine? + +

      + Some organizations feel very strongly about keeping the authentication + information on a different machine than the webserver. With the + mod_auth_msql, mod_auth_mysql, and other SQL + modules connecting to (R)DBMses this is quite possible. Just configure + an explicit host to contact. +

      +

      + Be aware that with mSQL and Oracle, opening and closing these database + connections is very expensive and time consuming. You might want to + look at the code in the auth_* modules and play with the + compile time flags to alleviate this somewhat, if your RDBMS licences + allow for it. +

      +
      +
    10. + +
    11. + Why is my mSQL authentication terribly slow? + +

      + You have probably configured the Host by specifying a FQHN, + and thus the libmsql will use a full blown TCP/IP socket + to talk to the database, rather than a fast internal device. The + libmsql, the mSQL FAQ, and the mod_auth_msql + documentation warn you about this. If you have to use different + hosts, check out the mod_auth_msql code for + some compile time flags which might - or might not - suit you. +

      +
      +
    12. + +
    13. + Can I use my /etc/passwd file + for Web page authentication? + +

      + Yes, you can - but it's a very bad idea. Here are + some of the reasons: +

      +
        +
      • The Web technology provides no governors on how often or how + rapidly password (authentication failure) retries can be made. That + means that someone can hammer away at your system's + root password using the Web, using a dictionary or + similar mass attack, just as fast as the wire and your server can + handle the requests. Most operating systems these days include + attack detection (such as n failed passwords for the same + account within m seconds) and evasion (breaking the + connection, disabling the account under attack, disabling + all logins from that source, et cetera), but the + Web does not. +
      • +
      • An account under attack isn't notified (unless the server is + heavily modified); there's no "You have 19483 login + failures" message when the legitimate owner logs in. +
      • +
      • Without an exhaustive and error-prone examination of the server + logs, you can't tell whether an account has been compromised. + Detecting that an attack has occurred, or is in progress, is fairly + obvious, though - if you look at the logs. +
      • +
      • Web authentication passwords (at least for Basic authentication) + generally fly across the wire, and through intermediate proxy + systems, in what amounts to plain text. "O'er the net we + go/Caching all the way;/O what fun it is to surf/Giving my password + away!" +
      • +
      • Since HTTP is stateless, information about the authentication is + transmitted each and every time a request is made to the + server. Essentially, the client caches it after the first + successful access, and transmits it without asking for all + subsequent requests to the same server. +
      • +
      • It's relatively trivial for someone on your system to put up a + page that will steal the cached password from a client's cache + without them knowing. Can you say "password grabber"? +
      • +
      +

      + If you still want to do this in light of the above disadvantages, the + method is left as an exercise for the reader. It'll void your Apache + warranty, though, and you'll lose all accumulated UNIX guru points. +

      +
      +
    14. +
    + + + + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/FAQ-H.html b/APACHE_1_3_12/htdocs/manual/misc/FAQ-H.html new file mode 100644 index 0000000000..3369ec9c3d --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/FAQ-H.html @@ -0,0 +1,265 @@ + + + + + + + + + + + + + + + + + + + + + Apache Server Frequently Asked Questions + + + + +

    Apache Server Frequently Asked Questions

    +

    + $Revision: 1.1 $ ($Date: 1999/06/24 15:02:52 $) +

    +

    + The latest version of this FAQ is always available from the main + Apache web site, at + <http://www.apache.org/docs/misc/FAQ.html>. +

    + + + + + + + + + + + + + + + +

    + If you are reading a text-only version of this FAQ, you may find numbers + enclosed in brackets (such as "[12]"). These refer to the list of + reference URLs to be found at the end of the document. These references + do not appear, and are not needed, for the hypertext version. +

    +

    The Questions

    +
      + + +
    1. URL Rewriting +
        +
      1. Where can I find mod_rewrite rulesets + which already solve particular URL-related problems? +
      2. +
      3. Where can I find any published information + about URL-manipulations and mod_rewrite? +
      4. +
      5. Why is mod_rewrite so difficult to learn + and seems so complicated? +
      6. +
      7. What can I do if my RewriteRules don't work + as expected? +
      8. +
      9. Why don't some of my URLs get + prefixed with DocumentRoot when using mod_rewrite? +
      10. +
      11. How can I make all my URLs case-insensitive + with mod_rewrite? +
      12. +
      13. Why are RewriteRules in my VirtualHost + parts ignored? +
      14. +
      15. How can I use strings with whitespaces + in RewriteRule's ENV flag? +
      16. +
      +
    2. + + +
    + +
    + +

    The Answers

    + + + +

    H. URL Rewriting

    +
      + +
    1. + Where can I find mod_rewrite rulesets which already solve + particular URL-related problems? + +

      + There is a collection of + Practical Solutions for URL-Manipulation + where you can + find all typical solutions the author of + mod_rewrite + currently knows of. If you have more + interesting rulesets which solve particular problems not currently covered in + this document, send it to + Ralf S. Engelschall + for inclusion. The + other webmasters will thank you for avoiding the reinvention of the wheel. +

      +
      +
    2. + +
    3. + Where can I find any published information about + URL-manipulations and mod_rewrite? + +

      + There is an article from + Ralf S. Engelschall + about URL-manipulations based on + mod_rewrite + in the "iX Multiuser Multitasking Magazin" issue #12/96. The + german (original) version + can be read online at + <http://www.heise.de/ix/artikel/9612149/>, + the English (translated) version can be found at + <http://www.heise.de/ix/artikel/E/9612149/>. +

      +
      +
    4. + +
    5. + Why is mod_rewrite so difficult to learn and seems so + complicated? + +

      + Hmmm... there are a lot of reasons. First, mod_rewrite itself is a powerful + module which can help you in really all aspects of URL + rewriting, so it can be no trivial module per definition. To accomplish + its hard job it uses software leverage and makes use of a powerful regular + expression + library by Henry Spencer which is an integral part of Apache since its + version 1.2. And regular expressions itself can be difficult to newbies, + while providing the most flexible power to the advanced hacker. +

      +

      + On the other hand mod_rewrite has to work inside the Apache API environment + and needs to do some tricks to fit there. For instance the Apache API as of + 1.x really was not designed for URL rewriting at the .htaccess + level of processing. Or the problem of multiple rewrites in sequence, which + is also not handled by the API per design. To provide this features + mod_rewrite has to do some special (but API compliant!) handling which leads + to difficult processing inside the Apache kernel. While the user usually + doesn't see anything of this processing, it can be difficult to find + problems when some of your RewriteRules seem not to work. +

      +
      +
    6. + +
    7. + What can I do if my RewriteRules don't work as expected? + + +

      + Use "RewriteLog somefile" and + "RewriteLogLevel 9" and have a precise look at the + steps the rewriting engine performs. This is really the only one and best + way to debug your rewriting configuration. +

      +
      +
    8. + +
    9. Why don't some of my URLs + get prefixed with DocumentRoot when using mod_rewrite? + +

      + If the rule starts with /somedir/... make sure that + really no /somedir exists on the filesystem if you + don't want to lead the URL to match this directory, i.e., + there must be no root directory named somedir on the + filesystem. Because if there is such a directory, the URL will not + get prefixed with DocumentRoot. This behaviour looks ugly, but is + really important for some other aspects of URL rewriting. +

      +
      +
    10. + +
    11. + How can I make all my URLs case-insensitive with mod_rewrite? + + +

      + You can't! The reason is: First, case translations for arbitrary + length URLs cannot be done via regex patterns and + corresponding substitutions. One need a per-character pattern like + sed/Perl tr|..|..| feature. Second, just making URLs + always upper or lower case will not resolve the complete problem of + case-INSENSITIVE URLs, because actually the URLs had to be rewritten + to the correct case-variant residing on the filesystem because in + later processing Apache needs to access the file. And Unix + filesystem is always case-SENSITIVE. +

      +

      + But there is a module named mod_speling.c (yes, it is named + this way!) out there on the net. Try this one. +

      +
      +
    12. + +
    13. + Why are RewriteRules in my VirtualHost parts ignored? + +

      + Because you have to enable the engine for every virtual host explicitly due + to security concerns. Just add a "RewriteEngine on" to your + virtual host configuration parts. +

      +
      +
    14. + +
    15. + How can I use strings with whitespaces in RewriteRule's ENV + flag? + +

      + There is only one ugly solution: You have to surround the complete + flag argument by quotation marks ("[E=...]"). Notice: + The argument to quote here is not the argument to the E-flag, it is + the argument of the Apache config file parser, i.e., the + third argument of the RewriteRule here. So you have to write + "[E=any text with whitespaces]". +

      +
      +
    16. + +
    + + + + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/FAQ-I.html b/APACHE_1_3_12/htdocs/manual/misc/FAQ-I.html new file mode 100644 index 0000000000..f5c8976d81 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/FAQ-I.html @@ -0,0 +1,238 @@ + + + + + + + + + + + + + + + + + + + + + Apache Server Frequently Asked Questions + + + + +

    Apache Server Frequently Asked Questions

    +

    + $Revision: 1.5 $ ($Date: 2000/02/11 22:11:33 $) +

    +

    + The latest version of this FAQ is always available from the main + Apache web site, at + <http://www.apache.org/docs/misc/FAQ.html>. +

    + + + + + + + + + + + + + + + +

    + If you are reading a text-only version of this FAQ, you may find numbers + enclosed in brackets (such as "[12]"). These refer to the list of + reference URLs to be found at the end of the document. These references + do not appear, and are not needed, for the hypertext version. +

    +

    The Questions

    +
      + + +
    1. Features +
        +
      1. Does or will Apache act as a Proxy server? +
      2. +
      3. What are "multiviews"? +
      4. +
      5. Why can't I publish to my Apache server + using PUT on Netscape Gold and other programs? +
      6. +
      7. Why doesn't Apache include SSL? +
      8. +
      9. How can I attach a footer to my documents + without using SSI? +
      10. +
      11. Does Apache include a search engine? +
      12. +
      13. How can I rotate my log files? +
      14. +
      +
    2. + + +
    + +
    + +

    The Answers

    + + + +

    I. Features

    +
      + +
    1. + Does or will Apache act as a Proxy server? + +

      + Apache version 1.1 and above comes with a + proxy module. + If compiled in, this will make Apache act as a caching-proxy server. +

      +
      +
    2. + +
    3. + What are "multiviews"? + +

      + "Multiviews" is the general name given to the Apache + server's ability to provide language-specific document variants in + response to a request. This is documented quite thoroughly in the + content negotiation + description page. In addition, Apache Week carried an + article on this subject entitled + "Content Negotiation Explained". +

      +
      +
    4. + +
    5. + Why can't I publish to my Apache server using PUT on + Netscape Gold and other programs? + +

      + Because you need to install and configure a script to handle + the uploaded files. This script is often called a "PUT" handler. + There are several available, but they may have security problems. + Using FTP uploads may be easier and more secure, at least for now. + For more information, see the Apache Week article + Publishing Pages with PUT. +

      +
      +
    6. + +
    7. + Why doesn't Apache include SSL? + +

      + SSL (Secure Socket Layer) data transport requires encryption, and many + governments have restrictions upon the import, export, and use of + encryption technology. If Apache included SSL in the base package, + its distribution would involve all sorts of legal and bureaucratic + issues, and it would no longer be freely available. Also, some of + the technology required to talk to current clients using SSL is + patented by RSA Data Security, + who restricts its use without a license. +

      +

      + Some SSL implementations of Apache are available, however; see the + "related projects" + page at the main Apache web site. +

      +

      + You can find out more about this topic in the Apache Week + article about + Apache and Secure Transactions. +

      +
      +
    8. +
    9. + How can I attach a footer to my documents + without using SSI? + +

      + You can make arbitrary changes to static documents by configuring an + + Action which launches a CGI script. The CGI is then + responsible for setting a content-type and delivering the requested + document (the location of which is passed in the + PATH_TRANSLATED environment variable), along with + whatever footer is needed. +

      +

      + Busy sites may not want to run a CGI script on every request, and + should consider using an Apache module to add the footer. There are + several third party modules available through the Apache Module Registry which + will add footers to documents. These include mod_trailer, PHP + (php3_auto_append_file), mod_layout, and mod_perl + (Apache::Sandwich). +

      +
      +
    10. +
    11. + Does Apache include a search engine? + +

      Apache does not include a search engine, but there are many good + commercial and free search engines which can be used easily with + Apache. Some of them are listed on the Web Site Search + Tools page. Open source search engines that are often used with + Apache include ht://Dig and SWISH-E. +

      +
      +
    12. +
    13. + How can I rotate my log files? + +

      The simple answer: by piping the transfer log into an appropriate + log file rotation utility.

      +

      The longer answer: In the src/support/ directory, you will find a + utility called rotatelogs which can be used like this:

      +   TransferLog "|/path/to/rotatelogs /path/to/logs/access_log 86400"
      +  
      to enable daily rotation of the log files.
      + A more sophisticated solution of a logfile rotation utility is + available under the name cronolog from Andrew Ford's site at + http://www.ford-mason.co.uk/resources/cronolog/. It can automatically + create logfile subdirectories based on time and date, and can have a + constant symlink point to the rotating logfiles. (As of version 1.6.1, + cronolog is available under the Apache License). + Use it like this:
      +   CustomLog "|/path/to/cronolog --symlink=/usr/local/apache/logs/access_log /usr/local/apache/logs/%Y/%m/access_log" combined
      +  

      +
      +
    14. +
    + + + + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/FAQ.html b/APACHE_1_3_12/htdocs/manual/misc/FAQ.html new file mode 100644 index 0000000000..b9a926f84a --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/FAQ.html @@ -0,0 +1,111 @@ + + + + Apache Server Frequently Asked Questions + + + + + +

    Apache Server Frequently Asked Questions

    +

    + $Revision: 1.145 $ ($Date: 1999/06/24 15:02:53 $) +

    +

    + The latest version of this FAQ is always available from the main + Apache web site, at + <http://www.apache.org/docs/misc/FAQ.html>. +

    + + + + + + + + + + + + + + + +

    + If you are reading a text-only version of this FAQ, you may find numbers + enclosed in brackets (such as "[12]"). These refer to the list of + reference URLs to be found at the end of the document. These references + do not appear, and are not needed, for the hypertext version. +

    +

    The Questions

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + + + + + + + + +
    + +
    + +

    The Answers

    + + + + + + + + + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/HTTP_Features.tsv b/APACHE_1_3_12/htdocs/manual/misc/HTTP_Features.tsv new file mode 100644 index 0000000000..893403d898 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/HTTP_Features.tsv @@ -0,0 +1,142 @@ +This tab-separated-value file is for use as a checklist +for features against , +since two independently developed and interoperable +implementations are needed for each feature. For each entry, + ? means not filled-in + - means not applicable + n means no + y means yes + Y means yes with the addition of a module that uses feature + +The contents should be placed in the form at +by someone who wants to be the contact for the Apache Group. + +Section Feature Implemented Tested +8.1 Persistent Connections y y +8.2.3 Automatic retrying of requests - - +8.2.4 Use of the 100 (Continue) status n n +9.2 OPTIONS y y +9.3 GET y y +9.4 HEAD y y +9.5 POST y y +9.6 PUT Y y +9.7 DELETE Y y +9.8 TRACE y y +9.9 CONNECT y y +10.1.1 100 Continue y y +10.1.2 101 Switching Protocols Y n +10.2.1 200 OK y y +10.2.2 201 Created y y +10.2.3 202 Accepted y y +10.2.4 203 Non-Authoritative Information y y +10.2.5 204 No Content y y +10.2.6 205 Reset Content y y +10.2.7 206 Partial Content y y +10.3.1 300 Multiple Choices y y +10.3.2 301 Moved Permanently y y +10.3.3 302 Found y y +10.3.4 303 See Other y y +10.3.5 304 Not Modified y y +10.3.6 305 Use Proxy y n +10.3.7 307 Temporary Redirect n n +10.4.1 400 Bad Request y y +10.4.2 401 Unauthorized y y +10.4.3 402 Payment Required Y n +10.4.4 403 Forbidden y y +10.4.5 404 Not Found y y +10.4.6 405 Method Not Allowed y y +10.4.7 406 Not Acceptable y y +10.4.8 407 Proxy Authentication Required y y +10.4.9 408 Request Timeout y y +10.4.10 409 Conflict Y n +10.4.11 410 Gone y y +10.4.12 411 Length Required y y +10.4.13 412 Precondition Failed y y +10.4.14 413 Request Entity Too Large y y +10.4.15 414 Request-URI Too Long y y +10.4.16 415 Unsupported Media Type y n +10.4.17 416 Requested range not satisfiable n n +10.4.18 417 Expectation Failed n n +10.5.1 500 Internal Server Error y y +10.5.2 501 Not Implemented y y +10.5.3 502 Bad Gateway y y +10.5.4 503 Service Unavailable y y +10.5.5 504 Gateway Timeout y y +10.5.6 505 HTTP Version Not Supported Y n +13.3.3 Strong entity tags y y +13.3.3 Weak entity tags y y +14.1 Accept y y +14.2 Accept-Charset y y +14.3 Accept-Encoding n n +14.4 Accept-Language y y +14.5 Accept-Ranges y y +14.6 Age - - +14.7 Allow y y +14.8 Authorization y y +14.9 Cache-Control y y +14.10 Connection y y +14.11 Content-Encoding y y +14.12 Content-Language y y +14.13 Content-Length y y +14.14 Content-Location Y n +14.15 Content-MD5 y n +14.16 Content-Range y y +14.17 Content-Type y y +14.18 Date y y +14.19 ETag y y +14.20 Expect n n +14.21 Expires y y +14.22 From - - +14.23 Host y y +14.24 If-Modified-Since y y +14.25 If-Match y y +14.26 If-None-Match y y +14.27 If-Range y y +14.28 If-Unmodified-Since y y +14.29 Last-Modified y y +14.30 Location y y +14.31 Max-Forwards n n +14.32 Pragma y y +14.33 Proxy-Authenticate y y +14.34 Proxy-Authorization y y +14.35 Range y y +14.36 Referer y y +14.37 Retry-After y y +14.38 Server y y +14.39 TE n n +14.40 Trailer n n +14.41 Transfer-Encoding y y +14.42 Upgrade Y n +14.43 User-Agent - - +14.44 Vary y y +14.45 Via n n +14.46 Warning Y n +14.47 WWW-Authenticate y y +===== ===================================== +Same for : + +A 2 Basic Authentication y y +A 3.2.1 WWW-Authenticate Digest y n +A 3.2.1 qop-options auth n n +A 3.2.1 qop-options auth-int n n +A 3.2.2 Authorization Digest y n +A 3.2.2 request qop auth n n +A 3.2.2 request qop auth-int n n +A 3.2.3 Authentication-Info Digest n n +A 3.2.3 response qop auth n n +A 3.2.3 response qop auth-int n n +A 4.1 Proxy-Authenticate Basic y y +A 4.2 Proxy-Authenticate Digest y n +A 4.2 Proxy qop-options auth n n +A 4.2 Proxy qop-options auth-int n n +A 4.2 Proxy Authorization Digest y n +A 4.2 Proxy request qop auth n n +A 4.2 Proxy request qop auth-int n n +A 4.2 Proxy Authentication-Info Digest n n +A 4.2 Proxy response qop auth n n +A 4.2 Proxy response qop auth-int n n + + +NOTES: +100 Continue sent on all bodied requests, as per RFC 2068. +Accept-Encoding does not allow q-values, as per RFC 2068. diff --git a/APACHE_1_3_12/htdocs/manual/misc/client_block_api.html b/APACHE_1_3_12/htdocs/manual/misc/client_block_api.html new file mode 100644 index 0000000000..c451d19fd9 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/client_block_api.html @@ -0,0 +1,87 @@ + + + +Reading Client Input in Apache 1.2 + + + + + +

    Reading Client Input in Apache 1.2

    + +
    + +

    Apache 1.1 and earlier let modules handle POST and PUT requests by +themselves. The module would, on its own, determine whether the +request had an entity, how many bytes it was, and then called a +function (read_client_block) to get the data. + +

    However, HTTP/1.1 requires several things of POST and PUT request +handlers that did not fit into this module, and all existing modules +have to be rewritten. The API calls for handling this have been +further abstracted, so that future HTTP protocol changes can be +accomplished while remaining backwards-compatible.

    + +
    + +

    The New API Functions

    + +
    +   int ap_setup_client_block (request_rec *, int read_policy);
    +   int ap_should_client_block (request_rec *);
    +   long ap_get_client_block (request_rec *, char *buffer, int buffer_size);
    +
    + +
      +
    1. Call ap_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 possibly accept input, call + ap_should_client_block(). + This will tell the module whether or not to read input. If it is 0, + the module should assume that the input is of a non-entity type + (e.g., a GET request). A nonzero response indicates that the module + should proceed (to step 3). + 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 ap_get_client_block in a loop. Pass it a + buffer and its + size. It will put data into the buffer (not necessarily the full + buffer, in the case of chunked inputs), 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. + +
    + +

    As an example, please look at the code in +mod_cgi.c. This is properly written to the new API +guidelines.

    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/compat_notes.html b/APACHE_1_3_12/htdocs/manual/misc/compat_notes.html new file mode 100644 index 0000000000..719ee93ea9 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/compat_notes.html @@ -0,0 +1,126 @@ + + + +Apache HTTP Server: Notes about Compatibility with NCSA's Server + + + + +

    Compatibility Notes with NCSA's Server

    + +
    + +While Apache is for the most part a drop-in replacement for NCSA's +httpd, there are a couple gotcha's to watch out for. These are mostly +due to the fact that the parser for config and access control files +was rewritten from scratch, so certain liberties the earlier servers +took may not be available here. These are all easily fixable. If you +know of other non-fatal problems that belong here, let us know. + +

    Please also check the known +client problems page. + +

      +
    1. As of Apache 1.3.1, methods named in a + <Limit> + section must be listed in upper-case. Lower- or mixed-case + method names will result in a configuration error. +

      +

      +
    2. + +
    3. The basic mod_auth AuthGroupFile-specified group file + format allows commas between user names - Apache does not. + +

      +

    4. If you follow the NCSA guidelines for setting up access + restrictions based on client domain, you may well have added + entries for, AuthType, AuthName, AuthUserFile or + AuthGroupFile. None of these are + needed (or appropriate) for restricting access based on client + domain. When Apache sees AuthType it (reasonably) + assumes you are using some authorization type based on username + and password. Please remove AuthType, it's + unnecessary even for NCSA. + +

      +

    5. OldScriptAlias is no longer supported. + +

      +

    6. exec cgi="" produces reasonable malformed + header responses when used to invoke non-CGI scripts.
      + The NCSA code ignores the missing header. (bad idea) +
      Solution: write CGI to the CGI spec and use + include virtual, or use exec cmd="" instead. + +

      +

    7. Icons for FancyIndexing broken - well, no, they're not broken, + we've just upgraded the icons from flat .xbm files to pretty and + much smaller .gif files, courtesy of Kevin Hughes at EIT. If you are using the same + srm.conf from an old distribution, make sure you add the new AddIcon, AddIconByType, + and DefaultIcon + directives. + +

      +

    8. Apache versions before 1.2b1 will ignore the last line of configuration + files if the last line does not have a trailing newline. This affects + configuration files (httpd.conf, access.conf and srm.conf), and + htpasswd and htgroup files. + +

      +

    9. Apache does not permit commas delimiting the methods in <Limit>. + +

      +

    10. Apache's <VirtualHost> treats all addresses as + "optional" (i.e., the server should continue booting if it can't + resolve the address). Whereas in NCSA the default is to fail + booting unless an added optional keyword is included. + +

      +

    11. Apache does not implement OnDeny use + ErrorDocument + instead. + +

      +

    12. Apache (as of 1.3) always performs the equivalent of + HostnameLookups minimal. minimal is not an + option to + HostnameLookups. + +

      +

    13. To embed spaces in directive arguments NCSA used a backslash + before the space. Apache treats backslashes as normal characters. To + embed spaces surround the argument with double-quotes instead. + +

      +

    14. Apache does not implement the NCSA referer + directive. See + PR#968 for a few brief suggestions on alternative ways to + implement the same thing under Apache. + +

      +

    15. Apache does not allow ServerRoot settings inside a VirtualHost + container. There is only one global ServerRoot in Apache; any desired + changes in paths for virtual hosts need to be made with the explicit + directives, eg. DocumentRoot, TransferLog, etc. + +
    + +More to come when we notice them.... + + + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/custom_errordocs.html b/APACHE_1_3_12/htdocs/manual/misc/custom_errordocs.html new file mode 100644 index 0000000000..47d50a19aa --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/custom_errordocs.html @@ -0,0 +1,431 @@ + + + +International Customized Server Error Messages + + + + + + +

    Using XSSI and ErrorDocument to configure +customized international server error responses

    +

    +

    Index

    + +
    +

    Introduction

    +This document describes an easy way to provide your apache WWW server +with a set of customized error messages which take advantage of +Content Negotiation +and eXtended Server Side Includes (XSSI) +to return error messages generated by the server in the client's +native language. +

    +

    +By using XSSI, all +customized messages +can share a homogenous and consistent style and layout, and maintenance work +(changing images, changing links) is kept to a minimum because all layout +information can be kept in a single file.
    +Error documents can be shared across different servers, or even hosts, +because all varying information is inserted at the time the error document +is returned on behalf of a failed request. +

    +

    +Content Negotiation then selects the appropriate language version of a +particular error message text, honoring the language preferences passed +in the client's request. (Users usually select their favorite languages +in the preferences options menu of today's browsers). When an error +document in the client's primary language version is unavailable, the +secondary languages are tried or a default (fallback) version is used. +

    +

    +You have full flexibility in designing your error documents to +your personal taste (or your company's conventions). For demonstration +purposes, we present a simple generic error document scheme. +For this hypothetic server, we assume that all error messages... +

      +
    • possibly are served by different virtual hosts (different host name, + different IP address, or different port) on the server machine, +
    • show a predefined company logo in the right top of the message + (selectable by virtual host), +
    • print the error title first, followed by an explanatory text and + (depending on the error context) help on how to resolve the error, +
    • have some kind of standardized background image, +
    • display an apache logo and a feedback email address at the bottom + of the error message. +
    +

    + +

    +An example of a "document not found" message for a german client might +look like this:
    +[Needs graphics capability to display]
    +All links in the document as well as links to the server's administrator +mail address, and even the name and port of the serving virtual host +are inserted in the error document at "run-time", i.e., when the error +actually occurs. +

    + +

    Creating an ErrorDocument directory

    + +For this concept to work as easily as possible, we must take advantage +of as much server support as we can get: +
      +
    1. By defining the MultiViews option, + we enable the language selection of the most appropriate language + alternative (content negotiation). +
    2. By setting the + LanguagePriority + directive we define a set of default fallback languages in the situation + where the client's browser did not express any preference at all. +
    3. By enabling Server Side Includes + (and disallowing execution of cgi scripts for security reasons), + we allow the server to include building blocks of the error message, + and to substitute the value of certain environment variables into the + generated document (dynamic HTML) or even to conditionally include + or omit parts of the text. +
    4. The AddHandler and + AddType directives are useful + for automatically XSSI-expanding all files with a .shtml + suffix to text/html. +
    5. By using the Alias directive, + we keep the error document directory outside of the document tree + because it can be regarded more as a server part than part of + the document tree. +
    6. The <Directory>-Block + restricts these "special" settings to the error document directory + and avoids an impact on any of the settings for the regular document tree. +
    7. For each of the error codes to be handled (see RFC2068 for an exact + description of each error code, or look at + src/main/http_protocol.c + if you wish to see apache's standard messages), an + ErrorDocument + in the aliased /errordocs directory is defined. + Note that we only define the basename of the document here + because the MultiViews option will select the best candidate + based on the language suffixes and the client's preferences. + Any error situation with an error code not handled by a + custom document will be dealt with by the server in the standard way + (i.e., a plain error message in english). +
    8. Finally, the AllowOverride + directive tells apache that it is not necessary to look for + a .htaccess file in the /errordocs directory: a minor speed + optimization. +
    +The resulting httpd.conf configuration would then look +similar to this: (Note that you can define your own error +messages using this method for only part of the document tree, +e.g., a /~user/ subtree. In this case, the configuration could as well +be put into the .htaccess file at the root of the subtree, and +the <Directory> and </Directory> directives -but not +the contained directives- must be omitted.) +
    +  LanguagePriority en fr de 
    +  Alias  /errordocs  /usr/local/apache/errordocs
    +  <Directory /usr/local/apache/errordocs>
    +   AllowOverride none
    +   Options MultiViews IncludesNoExec FollowSymLinks
    +   AddType text/html .shtml
    +   AddHandler server-parsed .shtml
    +  </Directory>
    +  #    "400 Bad Request",
    +  ErrorDocument  400  /errordocs/400
    +  #    "401 Authorization Required",
    +  ErrorDocument  401  /errordocs/401
    +  #    "403 Forbidden",
    +  ErrorDocument  403  /errordocs/403
    +  #    "404 Not Found",
    +  ErrorDocument  404  /errordocs/404
    +  #    "500 Internal Server Error",
    +  ErrorDocument  500  /errordocs/500
    +
    +The directory for the error messages (here: +/usr/local/apache/errordocs/) must then be created with the +appropriate permissions (readable and executable by the server uid or gid, +only writable for the administrator). + +

    Naming the individual error document files

    + +By defining the MultiViews option, the server was told to +automatically scan the directory for matching variants (looking at language +and content type suffixes) when a requested document was not found. +In the configuration, we defined the names for the error documents to be +just their error number (without any suffix). +

    +The names of the individual error documents are now determined like this +(I'm using 403 as an example, think of it as a placeholder for any of +the configured error documents): +

      +
    • No file errordocs/403 should exist. Otherwise, it would be found and + served (with the DefaultType, usually text/plain), all negotiation + would be bypassed. +
    • For each language for which we have an internationalized version + (note that this need not be the same set of languages for each + error code - you can get by with a single language version until + you actually have translated versions), a document + errordocs/403.shtml.lang is created and + filled with the error text in that language (see + below). +
    • One fallback document called errordocs/403.shtml is + created, usually by creating a symlink to the default language + variant (see below). +
    + +

    The common header and footer files

    + +By putting as much layout information in two special "include files", +the error documents can be reduced to a bare minimum. +

    +One of these layout files defines the HTML document header +and a configurable list of paths to the icons to be shown in the resulting +error document. These paths are exported as a set of XSSI environment +variables and are later evaluated by the "footer" special file. +The title of the current error (which is +put into the TITLE tag and an H1 header) is simply passed in from the main +error document in a variable called title.
    +By changing this file, the layout of all generated error +messages can be changed in a second. +(By exploiting the features of XSSI, you can easily define different +layouts based on the current virtual host, or even based on the +client's domain name). +

    +The second layout file describes the footer to be displayed at the bottom +of every error message. In this example, it shows an apache logo, the current +server time, the server version string and adds a mail reference to the +site's webmaster. +

    +For simplicity, the header file is simply called head.shtml +because it contains server-parsed content but no language specific +information. The footer file exists once for each language translation, +plus a symlink for the default language.

    +Example: for English, French and German versions +(default english)
    +foot.shtml.en,
    +foot.shtml.fr,
    +foot.shtml.de,
    +foot.shtml symlink to foot.shtml.en

    +Both files are included into the error document by using the +directives <!--#include virtual="head" --> +and <!--#include virtual="foot" --> +respectively: the rest of the magic occurs in mod_negotiation and +in mod_include. +

    + +See the listings below to see an actual HTML +implementation of the discussed example. + + +

    Creating ErrorDocuments in different languages +

    + +After all this preparation work, little remains to be said about the +actual documents. They all share a simple common structure: +
    +<!--#set var="title" value="error description title" -->
    +<!--#include virtual="head" -->
    +   explanatory error text
    +<!--#include virtual="foot" -->
    +
    +In the listings section, you can see an example +of a [400 Bad Request] error document. Documents as simple as that +certainly cause no problems to translate or expand. + +

    The fallback language

    + +Do we need a special handling for languages other than those we have +translations for? We did set the LanguagePriority, didn't we?! +

    +Well, the LanguagePriority directive is for the case where the client does +not express any language priority at all. But what +happens in the situation where the client wants one +of the languages we do not have, and none of those we do have? +

    +Without doing anything, the Apache server will usually return a +[406 no acceptable variant] error, listing the choices from which the client +may select. But we're in an error message already, and important error +information might get lost when the client had to choose a language +representation first. +

    +So, in this situation it appears to be easier to define a fallback language +(by copying or linking, e.g., the english version to a language-less version). +Because the negotiation algorithm prefers "more specialized" variants over +"more generic" variants, these generic alternatives will only be chosen +when the normal negotiation did not succeed. +

    +A simple shell script to do it (execute within the errordocs/ dir): +

    +  for f in *.shtml.en
    +  do
    +     ln -s $f `basename $f .en`
    +  done
    +
    + +

    +

    + +

    Customizing Proxy Error Messages

    + +

    + As of Apache-1.3, it is possible to use the ErrorDocument + mechanism for proxy error messages as well (previous versions always + returned fixed predefined error messages). +

    +

    + Most proxy errors return an error code of [500 Internal Server Error]. + To find out whether a particular error document was invoked on behalf + of a proxy error or because of some other server error, and what the reason + for the failure was, you can check the contents of the new + ERROR_NOTES CGI environment variable: + if invoked for a proxy error, this variable will contain the actual proxy + error message text in HTML form. +

    +

    + The following excerpt demonstrates how to exploit the ERROR_NOTES + variable within an error document: +

    +
    + <!--#if expr="\"$REDIRECT_ERROR_NOTES\" = \"\"" -->
    +  <p>
    +   The server encountered an unexpected condition
    +   which prevented it from fulfilling the request. 
    +  </p>
    +  <p>
    +   <A HREF="mailto:<!--#echo var="SERVER_ADMIN" -->"
    +    SUBJECT="Error message [<!--#echo var="REDIRECT_STATUS" -->] <!--#echo var="title" --> for <!--#echo var="REQUEST_URI" -->">
    +   Please forward this error screen to <!--#echo var="SERVER_NAME" -->'s
    +   WebMaster</A>; it includes useful debugging information about
    +   the Request which caused the error.
    +   <pre><!--#printenv --></pre>
    +  </p>
    + <!--#else -->
    +  <!--#echo var="REDIRECT_ERROR_NOTES" -->
    + <!--#endif -->
    +
    + +

    HTML listing of the discussed example

    + +So, to summarize our example, here's the complete listing of the +400.shtml.en document. You will notice that it contains +almost nothing but the error text (with conditional additions). +Starting with this example, you will find it easy to add more error +documents, or to translate the error documents to different languages. +
    +<!--#set var="title" value="Bad Request"
    +--><!--#include virtual="head" --><P>
    +   Your browser sent a request that this server could not understand:
    +   <BLOCKQUOTE>
    +     <STRONG><!--#echo var="REQUEST_URI" --></STRONG>
    +   </BLOCKQUOTE>
    +   The request could not be understood by the server due to malformed
    +   syntax. The client should not repeat the request without
    +   modifications.
    +   </P>
    +   <P>
    +   <!--#if expr="\"$HTTP_REFERER\" != \"\"" -->
    +    Please inform the owner of
    +    <A HREF="<!--#echo var="HTTP_REFERER" -->">the referring page</A> about 
    +    the malformed link.
    +   <!--#else -->
    +    Please check your request for typing errors and retry.
    +   <!--#endif -->
    +   </P>
    +<!--#include virtual="foot" -->
    +

    + +Here is the complete head.shtml file (the funny line +breaks avoid empty lines in the document after XSSI processing). Note the +configuration section at top. That's where you configure the images and logos +as well as the apache documentation directory. Look how this file displays +two different logos depending on the content of the virtual host name +($SERVER_NAME), and that an animated apache logo is shown if the browser +appears to support it (the latter requires server configuration lines +of the form
    BrowserMatch "^Mozilla/[2-4]" anigif
    +for browser types which support animated GIFs). +
    +<!--#if expr="\"$SERVER_NAME\" = /.*\.mycompany\.com/" 
    +--><!--#set var="IMG_CorpLogo"
    +            value="http://$SERVER_NAME:$SERVER_PORT/errordocs/CorpLogo.gif" 
    +--><!--#set var="ALT_CorpLogo" value="Powered by Linux!" 
    +--><!--#else
    +--><!--#set var="IMG_CorpLogo"
    +            value="http://$SERVER_NAME:$SERVER_PORT/errordocs/PrivLogo.gif" 
    +--><!--#set var="ALT_CorpLogo" value="Powered by Linux!" 
    +--><!--#endif
    +--><!--#set var="IMG_BgImage" value="http://$SERVER_NAME:$SERVER_PORT/errordocs/BgImage.gif" 
    +--><!--#set var="DOC_Apache" value="http://$SERVER_NAME:$SERVER_PORT/Apache/" 
    +--><!--#if expr="$anigif" 
    +--><!--#set var="IMG_Apache" value="http://$SERVER_NAME:$SERVER_PORT/icons/apache_anim.gif" 
    +--><!--#else
    +--><!--#set var="IMG_Apache" value="http://$SERVER_NAME:$SERVER_PORT/icons/apache_pb.gif" 
    +--><!--#endif
    +--><!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
    +<HTML>
    + <HEAD>
    +  <TITLE>
    +   [<!--#echo var="REDIRECT_STATUS" -->] <!--#echo var="title" -->
    +  </TITLE>
    + </HEAD>
    + <BODY BGCOLOR="white" BACKGROUND="<!--#echo var="IMG_BgImage" -->"><UL>
    +  <H1 ALIGN="center">
    +   [<!--#echo var="REDIRECT_STATUS" -->] <!--#echo var="title" -->
    +   <IMG SRC="<!--#echo var="IMG_CorpLogo" -->"
    +        ALT="<!--#echo var="ALT_CorpLogo" -->" ALIGN=right>
    +  </H1>
    +  <HR><!-- ======================================================== -->
    +  <DIV>
    +

    + and this is the foot.shtml.en file: +
    +
    +  </DIV>
    +  <HR>
    +  <DIV ALIGN="right"><SMALL><SUP>Local Server time:
    +      <!--#echo var="DATE_LOCAL" -->
    +  </SUP></SMALL></DIV>
    +  <DIV ALIGN="center">
    +    <A HREF="<!--#echo var="DOC_Apache" -->">
    +    <IMG SRC="<!--#echo var="IMG_Apache" -->" BORDER=0 ALIGN="bottom"
    +         ALT="Powered by <!--#echo var="SERVER_SOFTWARE" -->"></A><BR>
    +    <SMALL><SUP><!--#set var="var"
    +     value="Powered by $SERVER_SOFTWARE -- File last modified on $LAST_MODIFIED"
    +    --><!--#echo var="var" --></SUP></SMALL>
    +  </DIV>
    +  <ADDRESS>If the indicated error looks like a misconfiguration, please inform
    +   <A HREF="mailto:<!--#echo var="SERVER_ADMIN" -->"
    +      SUBJECT="Feedback about Error message [<!--#echo var="REDIRECT_STATUS" 
    +        -->] <!--#echo var="title" -->, req=<!--#echo var="REQUEST_URI" -->">
    +   <!--#echo var="SERVER_NAME" -->'s WebMaster</A>.
    +  </ADDRESS>
    + </UL></BODY>
    +</HTML>
    +

    + + +

    More welcome!

    + +If you have tips to contribute, send mail to martin@apache.org + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/descriptors.html b/APACHE_1_3_12/htdocs/manual/misc/descriptors.html new file mode 100644 index 0000000000..dadb7cc78d --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/descriptors.html @@ -0,0 +1,155 @@ + + + +Descriptors and Apache + + + + + +

    Descriptors and Apache

    + +

    A descriptor, also commonly called a file handle is +an object that a program uses to read or write an open file, or open +network socket, or a variety of other devices. It is represented +by an integer, and you may be familiar with stdin, +stdout, and stderr which are descriptors 0, +1, and 2 respectively. +Apache needs a descriptor for each log file, plus one for each +network socket that it listens on, plus a handful of others. Libraries +that Apache uses may also require descriptors. Normal programs don't +open up many descriptors at all, and so there are some latent problems +that you may experience should you start running Apache with many +descriptors (i.e., with many virtual hosts). + +

    The operating system enforces a limit on the number of descriptors +that a program can have open at a time. There are typically three limits +involved here. One is a kernel limitation, depending on your operating +system you will either be able to tune the number of descriptors available +to higher numbers (this is frequently called FD_SETSIZE). Or you +may be stuck with a (relatively) low amount. The second limit is called +the hard resource limit, and it is sometimes set by root in an +obscure operating system file, but frequently is the same as the kernel +limit. The third limit is called the soft +resource limit. The soft limit is always less than or equal to +the hard limit. For example, the hard limit may be 1024, but the soft +limit only 64. Any user can raise their soft limit up to the hard limit. +Root can raise the hard limit up to the system maximum limit. The soft +limit is the actual limit that is used when enforcing the maximum number +of files a process can have open. + +

    To summarize: + +

    +  #open files  <=  soft limit  <=  hard limit  <=  kernel limit
    +
    + +

    You control the hard and soft limits using the limit (csh) +or ulimit (sh) directives. See the respective man pages +for more information. For example you can probably use +ulimit -n unlimited to raise your soft limit up to the +hard limit. You should include this command in a shell script which +starts your webserver. + +

    Unfortunately, it's not always this simple. As mentioned above, +you will probably run into some system limitations that will need to be +worked around somehow. Work was done in version 1.2.1 to improve the +situation somewhat. Here is a partial list of systems and workarounds +(assuming you are using 1.2.1 or later): + +

    + +
    BSDI 2.0 +
    Under BSDI 2.0 you can build Apache to support more descriptors + by adding -DFD_SETSIZE=nnn to + EXTRA_CFLAGS (where nnn is the number of descriptors + you wish to support, keep it less than the hard limit). But it + will run into trouble if more than approximately 240 Listen + directives are used. This may be cured by rebuilding your kernel + with a higher FD_SETSIZE. +

    + +

    FreeBSD 2.2, BSDI 2.1+ +
    Similar to the BSDI 2.0 case, you should define + FD_SETSIZE and rebuild. But the extra + Listen limitation doesn't exist. +

    + +

    Linux +
    By default Linux has a kernel maximum of 256 open descriptors + per process. There are several patches available for the + 2.0.x series which raise this to 1024 and beyond, and you + can find them in the "unofficial patches" section of the Linux Information HQ. + None of these patches are perfect, and an entirely different + approach is likely to be taken during the 2.1.x development. + Applying these patches will raise the FD_SETSIZE used to compile + all programs, and unless you rebuild all your libraries you should + avoid running any other program with a soft descriptor limit above + 256. As of this writing the patches available for increasing + the number of descriptors do not take this into account. On a + dedicated webserver you probably won't run into trouble. +

    + +

    Solaris through 2.5.1 +
    Solaris has a kernel hard limit of 1024 (may be lower in earlier + versions). But it has a limitation that files using + the stdio library cannot have a descriptor above 255. + Apache uses the stdio library for the ErrorLog directive. + When you have more than approximately 110 virtual hosts + (with an error log and an access log each) you will need to + build Apache with -DHIGH_SLACK_LINE=256 added to + EXTRA_CFLAGS. You will be limited to approximately + 240 error logs if you do this. +

    + +

    AIX +
    AIX version 3.2?? appears to have a hard limit of 128 descriptors. + End of story. Version 4.1.5 has a hard limit of 2000. +

    + +

    Others +
    If you have details on another operating system, please submit + it through our Bug + Report Page. +

    + +

    + +

    In addition to the problems described above there are problems with +many libraries that Apache uses. The most common example is the bind +DNS resolver library that is used by pretty much every unix, which +fails if it ends up with a descriptor above 256. We suspect there +are other libraries that similar limitations. So the code as of 1.2.1 +takes a defensive stance and tries to save descriptors less than 16 +for use while processing each request. This is called the low +slack line. + +

    Note that this shouldn't waste descriptors. If you really are pushing +the limits and Apache can't get a descriptor above 16 when it wants +it, it will settle for one below 16. + +

    In extreme situations you may want to lower the low slack line, +but you shouldn't ever need to. For example, lowering it can +increase the limits 240 described above under Solaris and BSDI 2.0. +But you'll play a delicate balancing game with the descriptors needed +to serve a request. Should you want to play this game, the compile +time parameter is LOW_SLACK_LINE and there's a tiny +bit of documentation in the header file httpd.h. + +

    Finally, if you suspect that all this slack stuff is causing you +problems, you can disable it. Add -DNO_SLACK to +EXTRA_CFLAGS and rebuild. But please report it to +our Bug +Report Page so that +we can investigate. + + + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/fin_wait_2.html b/APACHE_1_3_12/htdocs/manual/misc/fin_wait_2.html new file mode 100644 index 0000000000..e1e313d75c --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/fin_wait_2.html @@ -0,0 +1,324 @@ + + + +Connections in FIN_WAIT_2 and Apache + + + + + + + + +

    Connections in the FIN_WAIT_2 state and Apache

    +
      +
    1. What is the FIN_WAIT_2 state?

      +Starting with the Apache 1.2 betas, people are reporting many more +connections in the FIN_WAIT_2 state (as reported by +netstat) than they saw using older versions. When the +server closes a TCP connection, it sends a packet with the FIN bit +sent to the client, which then responds with a packet with the ACK bit +set. The client then sends a packet with the FIN bit set to the +server, which responds with an ACK and the connection is closed. The +state that the connection is in during the period between when the +server gets the ACK from the client and the server gets the FIN from +the client is known as FIN_WAIT_2. See the TCP RFC for the +technical details of the state transitions.

      + +The FIN_WAIT_2 state is somewhat unusual in that there is no timeout +defined in the standard for it. This means that on many operating +systems, a connection in the FIN_WAIT_2 state will stay around until +the system is rebooted. If the system does not have a timeout and +too many FIN_WAIT_2 connections build up, it can fill up the space +allocated for storing information about the connections and crash +the kernel. The connections in FIN_WAIT_2 do not tie up an httpd +process.

      + +

    2. But why does it happen?

      + +There are numerous reasons for it happening, some of them may not +yet be fully clear. What is known follows.

      + +

      Buggy clients and persistent connections

      + +Several clients have a bug which pops up when dealing with +persistent connections (aka keepalives). +When the connection is idle and the server closes the connection +(based on the +KeepAliveTimeout), the client is programmed so that the client does +not send back a FIN and ACK to the server. This means that the +connection stays in the FIN_WAIT_2 state until one of the following +happens:

      +

        +
      • The client opens a new connection to the same or a different + site, which causes it to fully close the older connection on + that socket. +
      • The user exits the client, which on some (most?) clients + causes the OS to fully shutdown the connection. +
      • The FIN_WAIT_2 times out, on servers that have a timeout + for this state. +

      +If you are lucky, this means that the buggy client will fully close the +connection and release the resources on your server. However, there +are some cases where the socket is never fully closed, such as a dialup +client disconnecting from their provider before closing the client. +In addition, a client might sit idle for days without making another +connection, and thus may hold its end of the socket open for days +even though it has no further use for it. +This is a bug in the browser or in its operating system's +TCP implementation.

      + +The clients on which this problem has been verified to exist:

      +

        +
      • Mozilla/3.01 (X11; I; FreeBSD 2.1.5-RELEASE i386) +
      • Mozilla/2.02 (X11; I; FreeBSD 2.1.5-RELEASE i386) +
      • Mozilla/3.01Gold (X11; I; SunOS 5.5 sun4m) +
      • MSIE 3.01 on the Macintosh +
      • MSIE 3.01 on Windows 95 +

      + +This does not appear to be a problem on: +

        +
      • Mozilla/3.01 (Win95; I) +
      +

      + +It is expected that many other clients have the same problem. What a +client should do is periodically check its open +socket(s) to see if they have been closed by the server, and close their +side of the connection if the server has closed. This check need only +occur once every few seconds, and may even be detected by a OS signal +on some systems (e.g., Win95 and NT clients have this capability, but +they seem to be ignoring it).

      + +Apache cannot avoid these FIN_WAIT_2 states unless it +disables persistent connections for the buggy clients, just +like we recommend doing for Navigator 2.x clients due to other bugs. +However, non-persistent connections increase the total number of +connections needed per client and slow retrieval of an image-laden +web page. Since non-persistent connections have their own resource +consumptions and a short waiting period after each closure, a busy server +may need persistence in order to best serve its clients.

      + +As far as we know, the client-caused FIN_WAIT_2 problem is present for +all servers that support persistent connections, including Apache 1.1.x +and 1.2.

      + +

      A necessary bit of code introduced in 1.2

      + +While the above bug is a problem, it is not the whole problem. +Some users have observed no FIN_WAIT_2 problems with Apache 1.1.x, +but with 1.2b enough connections build up in the FIN_WAIT_2 state to +crash their server. + +The most likely source for additional FIN_WAIT_2 states +is a function called lingering_close() which was added +between 1.1 and 1.2. This function is necessary for the proper +handling of persistent connections and any request which includes +content in the message body (e.g., PUTs and POSTs). +What it does is read any data sent by the client for +a certain time after the server closes the connection. The exact +reasons for doing this are somewhat complicated, but involve what +happens if the client is making a request at the same time the +server sends a response and closes the connection. Without lingering, +the client might be forced to reset its TCP input buffer before it +has a chance to read the server's response, and thus understand why +the connection has closed. +See the appendix for more details.

      + +The code in lingering_close() appears to cause problems +for a number of factors, including the change in traffic patterns +that it causes. The code has been thoroughly reviewed and we are +not aware of any bugs in it. It is possible that there is some +problem in the BSD TCP stack, aside from the lack of a timeout +for the FIN_WAIT_2 state, exposed by the lingering_close +code that causes the observed problems.

      + +

    3. What can I do about it?
    4. + +There are several possible workarounds to the problem, some of +which work better than others.

      + +

      Add a timeout for FIN_WAIT_2

      + +The obvious workaround is to simply have a timeout for the FIN_WAIT_2 state. +This is not specified by the RFC, and could be claimed to be a +violation of the RFC, but it is widely recognized as being necessary. +The following systems are known to have a timeout: +

      +

        +
      • FreeBSD versions starting at + 2.0 or possibly earlier. +
      • NetBSD version 1.2(?) +
      • OpenBSD all versions(?) +
      • BSD/OS 2.1, with the + + K210-027 patch installed. +
      • Solaris as of around version + 2.2. The timeout can be tuned by using ndd to + modify tcp_fin_wait_2_flush_interval, but the + default should be appropriate for most servers and improper + tuning can have negative impacts. +
      • Linux 2.0.x and + earlier(?) +
      • HP-UX 10.x defaults to + terminating connections in the FIN_WAIT_2 state after the + normal keepalive timeouts. This does not + refer to the persistent connection or HTTP keepalive + timeouts, but the SO_LINGER socket option + which is enabled by Apache. This parameter can be adjusted + by using nettune to modify parameters such as + tcp_keepstart and tcp_keepstop. + In later revisions, there is an explicit timer for + connections in FIN_WAIT_2 that can be modified; contact HP + support for details. +
      • SGI IRIX can be patched to + support a timeout. For IRIX 5.3, 6.2, and 6.3, + use patches 1654, 1703 and 1778 respectively. If you + have trouble locating these patches, please contact your + SGI support channel for help. +
      • NCR's MP RAS Unix 2.xx and + 3.xx both have FIN_WAIT_2 timeouts. In 2.xx it is non-tunable + at 600 seconds, while in 3.xx it defaults to 600 seconds and + is calculated based on the tunable "max keep alive probes" + (default of 8) multiplied by the "keep alive interval" (default + 75 seconds). +
      • Sequent's ptx/TCP/IP for + DYNIX/ptx has had a FIN_WAIT_2 timeout since around + release 4.1 in mid-1994. +
      +

      +The following systems are known to not have a timeout: +

      +

        +
      • SunOS 4.x does not and + almost certainly never will have one because it as at the + very end of its development cycle for Sun. If you have kernel + source should be easy to patch. +
      +

      +There is a +patch available for adding a timeout to the FIN_WAIT_2 state; it +was originally intended for BSD/OS, but should be adaptable to most +systems using BSD networking code. You need kernel source code to be +able to use it. If you do adapt it to work for any other systems, +please drop me a note at marc@apache.org. +

      +

      Compile without using lingering_close()

      + +It is possible to compile Apache 1.2 without using the +lingering_close() function. This will result in that +section of code being similar to that which was in 1.1. If you do +this, be aware that it can cause problems with PUTs, POSTs and +persistent connections, especially if the client uses pipelining. +That said, it is no worse than on 1.1, and we understand that keeping your +server running is quite important.

      + +To compile without the lingering_close() function, add +-DNO_LINGCLOSE to the end of the +EXTRA_CFLAGS line in your Configuration file, +rerun Configure and rebuild the server. +

      +

      Use SO_LINGER as an alternative to +lingering_close()

      + +On most systems, there is an option called SO_LINGER that +can be set with setsockopt(2). It does something very +similar to lingering_close(), except that it is broken +on many systems so that it causes far more problems than +lingering_close. On some systems, it could possibly work +better so it may be worth a try if you have no other alternatives.

      + +To try it, add -DUSE_SO_LINGER -DNO_LINGCLOSE to the end of the +EXTRA_CFLAGS line in your Configuration +file, rerun Configure and rebuild the server.

      + +NOTE: Attempting to use SO_LINGER and +lingering_close() at the same time is very likely to do +very bad things, so don't.

      + +

      Increase the amount of memory used for storing connection state

      +
      +
      BSD based networking code: +
      BSD stores network data, such as connection states, +in something called an mbuf. When you get so many connections +that the kernel does not have enough mbufs to put them all in, your +kernel will likely crash. You can reduce the effects of the problem +by increasing the number of mbufs that are available; this will not +prevent the problem, it will just make the server go longer before +crashing.

      + +The exact way to increase them may depend on your OS; look +for some reference to the number of "mbufs" or "mbuf clusters". On +many systems, this can be done by adding the line +NMBCLUSTERS="n", where n is the number of +mbuf clusters you want to your kernel config file and rebuilding your +kernel.

      +

      + +

      Disable KeepAlive

      +

      If you are unable to do any of the above then you should, as a last +resort, disable KeepAlive. Edit your httpd.conf and change "KeepAlive On" +to "KeepAlive Off". + +

    5. Feedback
    6. + +If you have any information to add to this page, please contact me at +marc@apache.org.

      + +

    7. Appendix
    8. +

      +Below is a message from Roy Fielding, one of the authors of HTTP/1.1. + +

      Why the lingering close functionality is necessary with HTTP

      + +The need for a server to linger on a socket after a close is noted a couple +times in the HTTP specs, but not explained. This explanation is based on +discussions between myself, Henrik Frystyk, Robert S. Thau, Dave Raggett, +and John C. Mallery in the hallways of MIT while I was at W3C.

      + +If a server closes the input side of the connection while the client +is sending data (or is planning to send data), then the server's TCP +stack will signal an RST (reset) back to the client. Upon +receipt of the RST, the client will flush its own incoming TCP buffer +back to the un-ACKed packet indicated by the RST packet argument. +If the server has sent a message, usually an error response, to the +client just before the close, and the client receives the RST packet +before its application code has read the error message from its incoming +TCP buffer and before the server has received the ACK sent by the client +upon receipt of that buffer, then the RST will flush the error message +before the client application has a chance to see it. The result is +that the client is left thinking that the connection failed for no +apparent reason.

      + +There are two conditions under which this is likely to occur: +

        +
      1. sending POST or PUT data without proper authorization +
      2. sending multiple requests before each response (pipelining) + and one of the middle requests resulting in an error or + other break-the-connection result. +
      +

      +The solution in all cases is to send the response, close only the +write half of the connection (what shutdown is supposed to do), and +continue reading on the socket until it is either closed by the +client (signifying it has finally read the response) or a timeout occurs. +That is what the kernel is supposed to do if SO_LINGER is set. +Unfortunately, SO_LINGER has no effect on some systems; on some other +systems, it does not have its own timeout and thus the TCP memory +segments just pile-up until the next reboot (planned or not).

      + +Please note that simply removing the linger code will not solve the +problem -- it only moves it to a different and much harder one to detect. +

    + + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/footer.html b/APACHE_1_3_12/htdocs/manual/misc/footer.html new file mode 100644 index 0000000000..7fe745dcfd --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/footer.html @@ -0,0 +1,8 @@ +
    + +

    + Apache HTTP Server Version 1.3 +

    + +Index +Home diff --git a/APACHE_1_3_12/htdocs/manual/misc/header.html b/APACHE_1_3_12/htdocs/manual/misc/header.html new file mode 100644 index 0000000000..5662300029 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/header.html @@ -0,0 +1,6 @@ +
    + [APACHE DOCUMENTATION] +

    + Apache HTTP Server Version 1.3 +

    +
    diff --git a/APACHE_1_3_12/htdocs/manual/misc/howto.html b/APACHE_1_3_12/htdocs/manual/misc/howto.html new file mode 100644 index 0000000000..9ce92a41ba --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/howto.html @@ -0,0 +1,209 @@ + + + + + +Apache HOWTO documentation + + + + + +

    Apache HOWTO documentation

    + +How to: + + +
    +

    How to redirect an entire server or directory to a +single URL

    + +

    There are two chief ways to redirect all requests for an entire +server to a single location: one which requires the use of +mod_rewrite, and another which uses a CGI script. + +

    First: if all you need to do is migrate a server from one name to +another, simply use the Redirect directive, as supplied +by mod_alias: + +

    +  Redirect / http://www.apache.org/
    +
    + +

    Since Redirect will forward along the complete path, +however, it may not be appropriate - for example, when the directory +structure has changed after the move, and you simply want to direct people +to the home page. + +

    The best option is to use the standard Apache module +mod_rewrite. +If that module is compiled in, the following lines + +

    RewriteEngine On
    +RewriteRule /.* http://www.apache.org/ [R]
    +
    + +This will send an HTTP 302 Redirect back to the client, and no matter +what they gave in the original URL, they'll be sent to +"http://www.apache.org". + +The second option is to set up a ScriptAlias pointing to +a CGI script which outputs a 301 or 302 status and the +location +of the other server.

    + +

    By using a CGI script you can intercept various requests +and +treat them specially, e.g., you might want to intercept +POST +requests, so that the client isn't redirected to a script on the other +server which expects POST information (a redirect will lose the POST +information.) You might also want to use a CGI script if you don't +want to compile mod_rewrite into your server. + +

    Here's how to redirect all requests to a script... In the server +configuration file, +

    ScriptAlias / /usr/local/httpd/cgi-bin/redirect_script/
    +
    + +and here's a simple perl script to redirect requests: + +
    +#!/usr/local/bin/perl
    +
    +print "Status: 302 Moved Temporarily\r\n" .
    +      "Location: http://www.some.where.else.com/\r\n" .
    +      "\r\n";
    +
    +

    + +
    + +

    How to reset your log files

    + +

    Sooner or later, you'll want to reset your log files (access_log and +error_log) because they are too big, or full of old information you don't +need.

    + +

    access.log typically grows by 1Mb for each 10,000 requests.

    + +

    Most people's first attempt at replacing the logfile is to just move the +logfile or remove the logfile. This doesn't work.

    + +

    Apache will continue writing to the logfile at the same offset as before the +logfile moved. This results in a new logfile being created which is just +as big as the old one, but it now contains thousands (or millions) of null +characters.

    + +

    The correct procedure is to move the logfile, then signal Apache to tell +it to reopen the logfiles.

    + +

    Apache is signaled using the SIGHUP (-1) signal. +e.g. +

    +mv access_log access_log.old
    +kill -1 `cat httpd.pid` +
    +

    + +

    Note: httpd.pid is a file containing the +process id +of the Apache httpd daemon, Apache saves this in the same directory as the log +files.

    + +

    Many people use this method to replace (and backup) their logfiles on a +nightly or weekly basis.

    +
    + +

    How to stop or restrict robots

    + +

    Ever wondered why so many clients are interested in a file called +robots.txt which you don't have, and never did have?

    + +

    These clients are called robots (also known as crawlers, +spiders and other cute name) - special automated clients which +wander around the web looking for interesting resources.

    + +

    Most robots are used to generate some kind of web index which +is then used by a search engine to help locate information.

    + +

    robots.txt provides a means to request that robots limit their +activities at the site, or more often than not, to leave the site alone.

    + +

    When the first robots were developed, they had a bad reputation for +sending hundreds/thousands of requests to each site, often resulting +in the site being overloaded. Things have improved dramatically since +then, thanks to +Guidelines for Robot Writers, but even so, some robots may exhibit +unfriendly behavior which the webmaster isn't willing to tolerate, and +will want to stop.

    + +

    Another reason some webmasters want to block access to robots, is to +stop them indexing dynamic information. Many search engines will use the +data collected from your pages for months to come - not much use if your +serving stock quotes, news, weather reports or anything else that will be +stale by the time people find it in a search engine.

    + +

    If you decide to exclude robots completely, or just limit the areas +in which they can roam, create a robots.txt file; refer +to the robot information pages provided by Martijn Koster for the syntax.

    + +
    +

    How to proxy SSL requests through + your non-SSL Apache server +
    + (submitted by David Sedlock) +

    +

    +SSL uses port 443 for requests for secure pages. If your browser just +sits there for a long time when you attempt to access a secure page +over your Apache proxy, then the proxy may not be configured to handle +SSL. You need to instruct Apache to listen on port 443 in addition to +any of the ports on which it is already listening: +

    +
    +    Listen 80
    +    Listen 443
    +
    +

    +Then set the security proxy in your browser to 443. That might be it! +

    +

    +If your proxy is sending requests to another proxy, then you may have +to set the directive ProxyRemote differently. Here are my settings: +

    +
    +    ProxyRemote http://nicklas:80/ http://proxy.mayn.franken.de:8080
    +    ProxyRemote http://nicklas:443/ http://proxy.mayn.franken.de:443
    +
    +

    +Requests on port 80 of my proxy nicklas are forwarded to +proxy.mayn.franken.de:8080, while requests on port 443 are +forwarded to proxy.mayn.franken.de:443. +If the remote proxy is not set up to +handle port 443, then the last directive can be left out. SSL requests +will only go over the first proxy. +

    +

    +Note that your Apache does NOT have to be set up to serve secure pages +with SSL. Proxying SSL is a different thing from using it. +

    + + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/index.html b/APACHE_1_3_12/htdocs/manual/misc/index.html new file mode 100755 index 0000000000..7d1013b2bd --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/index.html @@ -0,0 +1,151 @@ + + + + Apache Miscellaneous Documentation + + + + + +

    Apache Miscellaneous Documentation

    + +

    + Below is a list of additional documentation pages that apply to the + Apache web server development project. +

    +
    +
    API +
    +
    Description of Apache's Application Programming Interface. +
    +
    FAQ +
    +
    Frequently-Asked Questions concerning the Apache project and server. +
    +
    Reading Client Input in Apache 1.2 +
    +
    Describes differences between Apache 1.1 and 1.2 in how modules + read information from the client. +
    +
    Compatibility with NCSA +
    +
    Notes about Apache's compatibility with the NCSA server. +
    +
    How to use XSSI and Negotiation + for custom ErrorDocuments +
    +
    Describes a solution which uses XSSI and negotiation + to custom-tailor the Apache ErrorDocuments to taste, adding the + advantage of returning internationalized versions of the error + messages depending on the client's language preferences. +
    +
    File Descriptor use in Apache +
    Describes how Apache uses file descriptors and talks about various + limits imposed on the number of descriptors available by various + operating systems. +
    +
    FIN_WAIT_2 +
    +
    A description of the causes of Apache processes going into the + FIN_WAIT_2 state, and what you can do about it. +
    +
    "How-To" +
    +
    Instructions about how to accomplish some commonly-desired server + functionality changes. +
    +
    HTTP Features list
    +
    A tab-separate table of HTTP features implemented and tested in Apache. +
    +
    Known Client Problems +
    +
    A list of problems in HTTP clients which can be mitigated by Apache. +
    +
    No PGP +
    +
    Why we took PEM and PGP support out of the base Apache distribution. +
    +
    Performance Notes (BSD 4.4) +
    +
    Some notes about ways to improve/optimize Apache performance on + BSD 4.4 systems. +
    +
    Performance Notes (Digital UNIX) +
    +
    Extracts of USENET postings describing how to optimize Apache + performance on Digital UNIX systems. +
    +
    Performance Notes (HPUX) +
    +
    Email from an HP engineer on how to optimize HP-UX 10.20. +
    +
    Performance Notes (General) +
    +
    Some generic notes about how to improve the performance of your + machine/OS. +
    +
    Performance Notes -- Apache Tuning +
    +
    Notes about how to (run-time and compile-time) configure + Apache for highest performance. Notes explaining why Apache does + some things, and why it doesn't do other things (which make it + slower/faster). +
    +
    Security Tips +
    +
    Some "do"s - and "don't"s - for keeping your + Apache web site secure. +
    +
    Virtual Hosts (IP-based) +
    +
    Excerpts and notes about configuring and using Apache IP-based virtual + hosts. +
    +
    Windows Bug with Web Keepalive +
    +
    A brief description of a known problem with Microsoft Windows and + web sites accessed using keepalive connections. +
    +
    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/known_client_problems.html b/APACHE_1_3_12/htdocs/manual/misc/known_client_problems.html new file mode 100644 index 0000000000..4d41fc7707 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/known_client_problems.html @@ -0,0 +1,305 @@ + + + +Apache HTTP Server Project + + + + + +

    Known Problems in Clients

    + +

    Over time the Apache Group has discovered or been notified of problems +with various clients which we have had to work around, or explain. +This document describes these problems and the workarounds available. +It's not arranged in any particular order. Some familiarity with the +standards is assumed, but not necessary. + +

    For brevity, Navigator will refer to Netscape's Navigator +product (which in later versions was renamed "Communicator" and +various other names), and MSIE will refer to Microsoft's +Internet Explorer product. All trademarks and copyrights belong to +their respective companies. We welcome input from the various client +authors to correct inconsistencies in this paper, or to provide us with +exact version numbers where things are broken/fixed. + +

    For reference, +RFC1945 +defines HTTP/1.0, and +RFC2068 +defines HTTP/1.1. Apache as of version 1.2 is an HTTP/1.1 server (with an +optional HTTP/1.0 proxy). + +

    Various of these workarounds are triggered by environment variables. +The admin typically controls which are set, and for which clients, by using +mod_browser. Unless otherwise +noted all of these workarounds exist in versions 1.2 and later. + +

    Trailing CRLF on POSTs

    + +

    This is a legacy issue. The CERN webserver required POST +data to have an extra CRLF following it. Thus many +clients send an extra CRLF that +is not included in the Content-Length of the request. +Apache works around this problem by eating any empty lines which +appear before a request. + +

    Broken keepalive

    + +

    Various clients have had broken implementations of keepalive +(persistent connections). In particular the Windows versions of +Navigator 2.0 get very confused when the server times out an +idle connection. The workaround is present in the default config files: +

    +BrowserMatch Mozilla/2 nokeepalive +
    +Note that this matches some earlier versions of MSIE, which began the +practice of calling themselves Mozilla in their user-agent +strings just like Navigator. + +

    MSIE 4.0b2, which claims to support HTTP/1.1, does not properly +support keepalive when it is used on 301 or 302 (redirect) +responses. Unfortunately Apache's nokeepalive code +prior to 1.2.2 would not work with HTTP/1.1 clients. You must apply +this patch to version 1.2.1. Then add this to your config: +

    +BrowserMatch "MSIE 4\.0b2;" nokeepalive +
    + +

    Incorrect interpretation of +HTTP/1.1 in response

    + +

    To quote from section 3.1 of RFC1945: +

    +HTTP uses a "<MAJOR>.<MINOR>" numbering scheme to indicate versions +of the protocol. The protocol versioning policy is intended to allow +the sender to indicate the format of a message and its capacity for +understanding further HTTP communication, rather than the features +obtained via that communication. +
    +Since Apache is an HTTP/1.1 server, it indicates so as part of its +response. Many client authors mistakenly treat this part of the response +as an indication of the protocol that the response is in, and then refuse +to accept the response. + +

    The first major indication of this problem was with AOL's proxy servers. +When Apache 1.2 went into beta it was the first wide-spread HTTP/1.1 +server. After some discussion, AOL fixed their proxies. In +anticipation of similar problems, the force-response-1.0 +environment variable was added to Apache. When present Apache will +indicate "HTTP/1.0" in response to an HTTP/1.0 client, +but will not in any other way change the response. + +

    The pre-1.1 Java Development Kit (JDK) that is used in many clients +(including Navigator 3.x and MSIE 3.x) exhibits this problem. As do some +of the early pre-releases of the 1.1 JDK. We think it is fixed in the +1.1 JDK release. In any event the workaround: +

    +BrowserMatch Java/1.0 force-response-1.0
    +BrowserMatch JDK/1.0 force-response-1.0 +
    + +

    RealPlayer 4.0 from Progressive Networks also exhibits this problem. +However they have fixed it in version 4.01 of the player, but version +4.01 uses the same User-Agent as version 4.0. The +workaround is still: +

    +BrowserMatch "RealPlayer 4.0" force-response-1.0 +
    + +

    Requests use HTTP/1.1 but responses must be +in HTTP/1.0

    + +

    MSIE 4.0b2 has this problem. Its Java VM makes requests in HTTP/1.1 +format but the responses must be in HTTP/1.0 format (in particular, it +does not understand chunked responses). The workaround +is to fool Apache into believing the request came in HTTP/1.0 format. +

    +BrowserMatch "MSIE 4\.0b2;" downgrade-1.0 force-response-1.0 +
    +This workaround is available in 1.2.2, and in a +patch against 1.2.1. + +

    Boundary problems with header parsing

    + +

    All versions of Navigator from 2.0 through 4.0b2 (and possibly later) +have a problem if the trailing CRLF of the response header starts at +offset 256, 257 or 258 of the response. A BrowserMatch for this would +match on nearly every hit, so the workaround is enabled automatically +on all responses. The workaround implemented detects when this condition would +occur in a response and adds extra padding to the header to push the +trailing CRLF past offset 258 of the response. + +

    Multipart responses and Quoted Boundary +Strings

    + +

    On multipart responses some clients will not accept quotes (") +around the boundary string. The MIME standard recommends that +such quotes be used. But the clients were probably written based +on one of the examples in RFC2068, which does not include quotes. +Apache does not include quotes on its boundary strings to workaround +this problem. + +

    Byterange requests

    + +

    A byterange request is used when the client wishes to retrieve a +portion of an object, not necessarily the entire object. There +was a very old draft which included these byteranges in the URL. +Old clients such as Navigator 2.0b1 and MSIE 3.0 for the MAC +exhibit this behaviour, and +it will appear in the servers' access logs as (failed) attempts to +retrieve a URL with a trailing ";xxx-yyy". Apache does not attempt +to implement this at all. + +

    A subsequent draft of this standard defines a header +Request-Range, and a response type +multipart/x-byteranges. The HTTP/1.1 standard includes +this draft with a few fixes, and it defines the header +Range and type multipart/byteranges. + +

    Navigator (versions 2 and 3) sends both Range and +Request-Range headers (with the same value), but does not +accept a multipart/byteranges response. The response must +be multipart/x-byteranges. As a workaround, if Apache +receives a Request-Range header it considers it "higher +priority" than a Range header and in response uses +multipart/x-byteranges. + +

    The Adobe Acrobat Reader plugin makes extensive use of byteranges and +prior to version 3.01 supports only the multipart/x-byterange +response. Unfortunately there is no clue that it is the plugin +making the request. If the plugin is used with Navigator, the above +workaround works fine. But if the plugin is used with MSIE 3 (on +Windows) the workaround won't work because MSIE 3 doesn't give the +Range-Request clue that Navigator does. To workaround this, +Apache special cases "MSIE 3" in the User-Agent and serves +multipart/x-byteranges. Note that the necessity for this +with MSIE 3 is actually due to the Acrobat plugin, not due to the browser. + +

    Netscape Communicator appears to not issue the non-standard +Request-Range header. When an Acrobat plugin prior to +version 3.01 is used with it, it will not properly understand byteranges. +The user must upgrade their Acrobat reader to 3.01. + +

    Set-Cookie header is +unmergeable

    + +

    The HTTP specifications say that it is legal to merge headers with +duplicate names into one (separated by commas). Some browsers +that support Cookies don't like merged headers and prefer that each +Set-Cookie header is sent separately. When parsing the +headers returned by a CGI, Apache will explicitly avoid merging any +Set-Cookie headers. + +

    Expires headers and GIF89A +animations

    + +

    Navigator versions 2 through 4 will erroneously re-request +GIF89A animations on each loop of the animation if the first +response included an Expires header. This happens +regardless of how far in the future the expiry time is set. There +is no workaround supplied with Apache, however there are hacks for 1.2 +and for 1.3. + +

    POST without +Content-Length

    + +

    In certain situations Navigator 3.01 through 3.03 appear to incorrectly +issue a POST without the request body. There is no +known workaround. It has been fixed in Navigator 3.04, Netscapes +provides some +information. +There's also + +some information about the actual problem. + +

    JDK 1.2 betas lose parts of responses.

    + +

    The http client in the JDK1.2beta2 and beta3 will throw away the first part of +the response body when both the headers and the first part of the body are sent +in the same network packet AND keep-alive's are being used. If either condition +is not met then it works fine. + +

    See also Bug-ID's 4124329 and 4125538 at the java developer connection. + +

    If you are seeing this bug yourself, you can add the following BrowserMatch +directive to work around it: + +

    +BrowserMatch "Java1\.2beta[23]" nokeepalive +
    + +

    We don't advocate this though since bending over backwards for beta software +is usually not a good idea; ideally it gets fixed, new betas or a final release +comes out, and no one uses the broken old software anymore. In theory. + +

    Content-Type change +is not noticed after reload

    + +

    Navigator (all versions?) will cache the content-type +for an object "forever". Using reload or shift-reload will not cause +Navigator to notice a content-type change. The only +work-around is for the user to flush their caches (memory and disk). By +way of an example, some folks may be using an old mime.types +file which does not map .htm to text/html, +in this case Apache will default to sending text/plain. +If the user requests the page and it is served as text/plain. +After the admin fixes the server, the user will have to flush their caches +before the object will be shown with the correct text/html +type. + +

    MSIE Cookie problem with expiry date in +the year 2000

    + +

    MSIE versions 3.00 and 3.02 (without the Y2K patch) do not handle +cookie expiry dates in the year 2000 properly. Years after 2000 and +before 2000 work fine. This is fixed in IE4.01 service pack 1, and in +the Y2K patch for IE3.02. Users should avoid using expiry dates in the +year 2000. + +

    Lynx incorrectly asking for transparent +content negotiation

    + +

    The Lynx browser versions 2.7 and 2.8 send a "negotiate: trans" header +in their requests, which is an indication the browser supports transparent +content negotiation (TCN). However the browser does not support TCN. +As of version 1.3.4, Apache supports TCN, and this causes problems with +these versions of Lynx. As a workaround future versions of Apache will +ignore this header when sent by the Lynx client. + +

    MSIE 4.0 mishandles Vary response header

    + +

    MSIE 4.0 does not handle a Vary header properly. The Vary header is +generated by mod_rewrite in apache 1.3. The result is an error from MSIE +saying it cannot download the requested file. There are more details +in PR#4118. +

    +

    +A workaround is to add the following to your server's configuration +files: +

    +
    +    BrowserMatch "MSIE 4\.0" force-no-vary
    +
    +

    +(This workaround is only available with releases after +1.3.6 of the Apache Web server.) +

    + + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/nopgp.html b/APACHE_1_3_12/htdocs/manual/misc/nopgp.html new file mode 100644 index 0000000000..41b6a678a5 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/nopgp.html @@ -0,0 +1,90 @@ + + + +Why We Took PEM Out of Apache + + + + + +

    Why We Took PEM Out of Apache

    + +On May 17th, 1995, we were asked by a representative of NCSA to remove +any copies of NCSA httpd prior to 1.4.1 from our web site. They +were mandated by the NSA to inform us that redistribution of pre-1.4.1 +code violated the same laws that make distributing Phill Zimmerman's +PGP package to other countries illegal. There was no +encryption in NCSA's httpd, only hooks to publicly available libraries +of PEM code. By the NSA's rules, even hooks to this type of +application is illegal. + +

    + +Because Apache is based on NCSA code, and we had basically not touched +that part of the software, we were informed that Apache was also +illegal to distribute to foreign countries, and advised (not mandated) +by NCSA to remove it. So, we removed both the copies of the NCSA +httpd we had, and all versions of Apache previous to 0.6.5. + +

    + +The Apache members are strong advocates of the right to digital +privacy, so the decision to submit to the NSA and remove the code was +not an easy one. Here are some elements in our rationale: + +

      + +
    • The PEM code in httpd was not widely used. No major site relied +upon its use, so its loss is not a blow to encryption and security on +the world wide web. There are other efforts designed to give much +more flexible security - SSL and SHTTP - so this wasn't a function +whose absence would really be missed on a functional level. + +
    • We didn't feel like being just a couple more martyrs in a fight +being fought very well by many other people. Rather than have the +machine that supports the project confiscated or relocated to South +Africa, etc., we think there are more efficient methods to address the +issue. + +
    + +It kind of sickens us that we had to do it, but so be it. + +

    + +Patches that re-implement the PEM code may be available at a foreign +site soon. If it does show up, we'll point to it - that can't be illegal! + +

    + +Finally, here is a compendium of pointers to sites related to +encryption and export law. We can't promise this list will be up to +date, so send us mail when you see a problem or want a link added. +Thanks. + +

    + +Brian, +brian@hyperreal.com + + + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/perf-bsd44.html b/APACHE_1_3_12/htdocs/manual/misc/perf-bsd44.html new file mode 100644 index 0000000000..c5e978c2b9 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/perf-bsd44.html @@ -0,0 +1,254 @@ + + + +Running a High-Performance Web Server for BSD + + + + + + + +

    Running a High-Performance Web Server for BSD

    + +Like other OS's, the listen queue is often the first limit +hit. The +following are comments from "Aaron Gifford <agifford@InfoWest.COM>" +on how to fix this on BSDI 1.x, 2.x, and FreeBSD 2.0 (and earlier): + +

    + +Edit the following two files: +

    /usr/include/sys/socket.h
    + /usr/src/sys/sys/socket.h
    +In each file, look for the following: +
    +    /*
    +     * Maximum queue length specifiable by listen.
    +     */
    +    #define SOMAXCONN       5
    +
    + +Just change the "5" to whatever appears to work. I bumped the two +machines I was having problems with up to 32 and haven't noticed the +problem since. + +

    + +After the edit, recompile the kernel and recompile the Apache server +then reboot. + +

    + +FreeBSD 2.1 seems to be perfectly happy, with SOMAXCONN +set to 32 already. + +

    + + +Addendum for very heavily loaded BSD servers
    +
    +from Chuck Murcko <chuck@telebase.com> + +

    + +If you're running a really busy BSD Apache server, the following are useful +things to do if the system is acting sluggish:

    + +

      + +
    • Run vmstat to check memory usage, page/swap rates, etc. + +
    • Run netstat -m to check mbuf usage + +
    • Run fstat to check file descriptor usage + +
    + +These utilities give you an idea what you'll need to tune in your kernel, +and whether it'll help to buy more RAM. + +Here are some BSD kernel config parameters (actually BSDI, but pertinent to +FreeBSD and other 4.4-lite derivatives) from a system getting heavy usage. +The tools mentioned above were used, and the system memory was increased to +48 MB before these tuneups. Other system parameters remained unchanged. + +

    + +

    +maxusers        256
    +
    + +Maxusers drives a lot of other kernel parameters: + +
      + +
    • Maximum # of processes + +
    • Maximum # of processes per user + +
    • System wide open files limit + +
    • Per-process open files limit + +
    • Maximum # of mbuf clusters + +
    • Proc/pgrp hash table size + +
    + +The actual formulae for these derived parameters are in +/usr/src/sys/conf/param.c. +These calculated parameters can also be overridden (in part) by specifying +your own values in the kernel configuration file: + +
    +# Network options. NMBCLUSTERS defines the number of mbuf clusters and
    +# defaults to 256. This machine is a server that handles lots of traffic,
    +# so we crank that value.
    +options         NMBCLUSTERS=4096        # mbuf clusters at 4096
    +
    +#
    +# Misc. options
    +#
    +options         CHILD_MAX=512           # maximum number of child processes
    +options         OPEN_MAX=512            # maximum fds (breaks RPC svcs)
    +
    + +

    + +In many cases, NMBCLUSTERS must be set much larger than would appear +necessary at first glance. The reason for this is that if the browser +disconnects in mid-transfer, the socket fd associated with that particular +connection ends up in the TIME_WAIT state for several minutes, during +which time its mbufs are not yet freed. Another reason is that, on server +timeouts, some connections end up in FIN_WAIT_2 state forever, because +this state doesn't time out on the server, and the browser never sent +a final FIN. For more details see the +FIN_WAIT_2 page. + +

    + +Some more info on mbuf clusters (from sys/mbuf.h): +

    +/*
    + * Mbufs are of a single size, MSIZE (machine/machparam.h), which
    + * includes overhead.  An mbuf may add a single "mbuf cluster" of size
    + * MCLBYTES (also in machine/machparam.h), which has no additional overhead
    + * and is used instead of the internal data area; this is done when
    + * at least MINCLSIZE of data must be stored.
    + */
    +
    + +

    + +CHILD_MAX and OPEN_MAX are set to allow up to 512 child processes (different +than the maximum value for processes per user ID) and file descriptors. +These values may change for your particular configuration (a higher OPEN_MAX +value if you've got modules or CGI scripts opening lots of connections or +files). If you've got a lot of other activity besides httpd on the same +machine, you'll have to set NPROC higher still. In this example, the NPROC +value derived from maxusers proved sufficient for our load. + +

    + +To increase the size of the listen() queue, you need to +adjust the value of SOMAXCONN. SOMAXCONN is not derived from maxusers, +so you'll always need to increase that yourself. We use a value guaranteed +to be larger than Apache's default for the listen() of 128, currently. +The actual value for SOMAXCONN is set in sys/socket.h. +The best way to adjust this parameter is run-time, rather than changing +it in this header file and thus hardcoding a value in the kernel and +elsewhere. To do this, edit /etc/rc.local and add the +following line: +

    +    /usr/sbin/sysctl -w kern.somaxconn=256
    +
    + +

    + +We used 256 but you can tune it for your own setup. In +many cases, however, even the default value of 128 (for +later versions of FreeBSD) is OK. + +

    + +Caveats + +

    + +Be aware that your system may not boot with a kernel that is configured +to use more resources than you have available system RAM. +ALWAYS +have a known bootable kernel available when tuning your system this way, +and use the system tools beforehand to learn if you need to buy more +memory before tuning. + +

    + +RPC services will fail when the value of OPEN_MAX is larger than 256. +This is a function of the original implementations of the RPC library, +which used a byte value for holding file descriptors. BSDI has partially +addressed this limit in its 2.1 release, but a real fix may well await +the redesign of RPC itself. + +

    + +Finally, there's the hard limit of child processes configured in Apache. + +

    + +For versions of Apache later than 1.0.5 you'll need to change the +definition for HARD_SERVER_LIMIT in httpd.h and +recompile if you need to run more than the default 150 instances of httpd. + +

    + +From conf/httpd.conf-dist: + +

    +# Limit on total number of servers running, i.e., limit on the number
    +# of clients who can simultaneously connect --- if this limit is ever
    +# reached, clients will be LOCKED OUT, so it should NOT BE SET TOO LOW.
    +# It is intended mainly as a brake to keep a runaway server from taking
    +# Unix with it as it spirals down...
    +
    +MaxClients 150
    +
    + +Know what you're doing if you bump this value up, and make sure you've +done your system monitoring, RAM expansion, and kernel tuning beforehand. +Then you're ready to service some serious hits! + +

    + +Thanks to Tony Sanders and Chris Torek at BSDI for their +helpful suggestions and information. + +

    + +"M. Teterin" <mi@ALDAN.ziplink.net> writes:

    +

    It really does help if your kernel and frequently used utilities +are fully optimized. Rebuilding the FreeBSD kernel on an AMD-133 +(486-class CPU) web-server with
    + -m486 -fexpensive-optimizations -fomit-frame-pointer -O2
    +helped reduce the number of "unable" errors, because the CPU was +often maxed out.
    +

    + +


    + +

    More welcome!

    + +If you have tips to contribute, send mail to +apache@apache.org + + + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/perf-dec.html b/APACHE_1_3_12/htdocs/manual/misc/perf-dec.html new file mode 100644 index 0000000000..2b9cc9cc5e --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/perf-dec.html @@ -0,0 +1,285 @@ + + + +Performance Tuning Tips for Digital Unix + + + + +

    Performance Tuning Tips for Digital Unix

    + +Below is a set of newsgroup posts made by an engineer from DEC in +response to queries about how to modify DEC's Digital Unix OS for more +heavily loaded web sites. Copied with permission. + +
    + +

    Update

    +From: Jeffrey Mogul <mogul@pa.dec.com>
    +Date: Fri, 28 Jun 96 16:07:56 MDT
    + +
      +
    1. The advice given in the README file regarding the + "tcbhashsize" variable is incorrect. The largest value + this should be set to is 1024. Setting it any higher + will have the perverse result of disabling the hashing + mechanism. + +
    2. Patch ID OSF350-146 has been superseded by +
      + Patch ID OSF350-195 for V3.2C
      + Patch ID OSF360-350195 for V3.2D +
      + Patch IDs for V3.2E and V3.2F should be available soon. + There is no known reason why the Patch ID OSF360-350195 + won't work on these releases, but such use is not officially + supported by Digital. This patch kit will not be needed for + V3.2G when it is released. +
    +
    + + +
    +From           mogul@pa.dec.com (Jeffrey Mogul)
    +Organization   DEC Western Research
    +Date           30 May 1996 00:50:25 GMT
    +Newsgroups     comp.unix.osf.osf1
    +Message-ID     <4oirch$bc8@usenet.pa.dec.com>
    +Subject        Re: Web Site Performance
    +References     1
    +
    +
    +
    +In article <skoogDs54BH.9pF@netcom.com> skoog@netcom.com (Jim Skoog) writes:
    +>Where are the performance bottlenecks for Alpha AXP running the
    +>Netscape Commerce Server 1.12 with high volume internet traffic?
    +>We are evaluating network performance for a variety of Alpha AXP
    +>runing DEC UNIX 3.2C, which run DEC's seal firewall and behind
    +>that Alpha 1000 and 2100 webservers.
    +
    +Our experience (running such Web servers as altavista.digital.com
    +and www.digital.com) is that there is one important kernel tuning
    +knob to adjust in order to get good performance on V3.2C.  You
    +need to patch the kernel global variable "somaxconn" (use dbx -k
    +to do this) from its default value of 8 to something much larger.
    +
    +How much larger?  Well, no larger than 32767 (decimal).  And
    +probably no less than about 2048, if you have a really high volume
    +(millions of hits per day), like AltaVista does.
    +
    +This change allows the system to maintain more than 8 TCP
    +connections in the SYN_RCVD state for the HTTP server.  (You
    +can use "netstat -An |grep SYN_RCVD" to see how many such
    +connections exist at any given instant).
    +
    +If you don't make this change, you might find that as the load gets
    +high, some connection attempts take a very long time.  And if a lot
    +of your clients disconnect from the Internet during the process of
    +TCP connection establishment (this happens a lot with dialup
    +users), these "embryonic" connections might tie up your somaxconn
    +quota of SYN_RCVD-state connections.  Until the kernel times out
    +these embryonic connections, no other connections will be accepted,
    +and it will appear as if the server has died.
    +
    +The default value for somaxconn in Digital UNIX V4.0 will be quite
    +a bit larger than it has been in previous versions (we inherited
    +this default from 4.3BSD).
    +
    +Digital UNIX V4.0 includes some other performance-related changes
    +that significantly improve its maximum HTTP connection rate.  However,
    +we've been using V3.2C systems to front-end for altavista.digital.com
    +with no obvious performance bottlenecks at the millions-of-hits-per-day
    +level.
    +
    +We have some Webstone performance results available at
    +        http://www.digital.com/info/alphaserver/news/webff.html
    +
    +[The document referenced above is no longer at that URL -- Ed.]
    +
    +I'm not sure if these were done using V4.0 or an earlier version
    +of Digital UNIX, although I suspect they were done using a test
    +version of V4.0.
    +
    +-Jeff
    +
    +
    + +---------------------------------------------------------------------------- + +From mogul@pa.dec.com (Jeffrey Mogul) +Organization DEC Western Research +Date 31 May 1996 21:01:01 GMT +Newsgroups comp.unix.osf.osf1 +Message-ID <4onmmd$mmd@usenet.pa.dec.com> +Subject Digital UNIX V3.2C Internet tuning patch info + +---------------------------------------------------------------------------- + +Something that probably few people are aware of is that Digital +has a patch kit available for Digital UNIX V3.2C that may improve +Internet performance, especially for busy web servers. + +This patch kit is one way to increase the value of somaxconn, +which I discussed in a message here a day or two ago. + +I've included in this message the revised README file for this +patch kit below. Note that the original README file in the patch +kit itself may be an earlier version; I'm told that the version +below is the right one. + +Sorry, this patch kit is NOT available for other versions of Digital +UNIX. Most (but not quite all) of these changes also made it into V4.0, +so the description of the various tuning parameters in this README +file might be useful to people running V4.0 systems. + +This patch kit does not appear to be available (yet?) from + http://www.service.digital.com/html/patch_service.html +so I guess you'll have to call Digital's Customer Support to get it. + +-Jeff + +DESCRIPTION: Digital UNIX Network tuning patch + + Patch ID: OSF350-146 + + SUPERSEDED PATCHES: OSF350-151, OSF350-158 + + This set of files improves the performance of the network + subsystem on a system being used as a web server. There are + additional tunable parameters included here, to be used + cautiously by an informed system administrator. + +TUNING + + To tune the web server, the number of simultaneous socket + connection requests are limited by: + + somaxconn Sets the maximum number of pending requests + allowed to wait on a listening socket. The + default value in Digital UNIX V3.2 is 8. + This patch kit increases the default to 1024, + which matches the value in Digital UNIX V4.0. + + sominconn Sets the minimum number of pending connections + allowed on a listening socket. When a user + process calls listen with a backlog less + than sominconn, the backlog will be set to + sominconn. sominconn overrides somaxconn. + The default value is 1. + + The effectiveness of tuning these parameters can be monitored by + the sobacklog variables available in the kernel: + + sobacklog_hiwat Tracks the maximum pending requests to any + socket. The initial value is 0. + + sobacklog_drops Tracks the number of drops exceeding the + socket set backlog limit. The initial + value is 0. + + somaxconn_drops Tracks the number of drops exceeding the + somaxconn limit. When sominconn is larger + than somaxconn, tracks the number of drops + exceeding sominconn. The initial value is 0. + + TCP timer parameters also affect performance. Tuning the following + require some knowledge of the characteristics of the network. + + tcp_msl Sets the tcp maximum segment lifetime. + This is the maximum lifetime in half + seconds that a packet can be in transit + on the network. This value, when doubled, + is the length of time a connection remains + in the TIME_WAIT state after a incoming + close request is processed. The unit is + specified in 1/2 seconds, the initial + value is 60. + + tcp_rexmit_interval_min + Sets the minimum TCP retransmit interval. + For some WAN networks the default value may + be too short, causing unnecessary duplicate + packets to be sent. The unit is specified + in 1/2 seconds, the initial value is 1. + + tcp_keepinit This is the amount of time a partially + established connection will sit on the listen + queue before timing out (e.g., if a client + sends a SYN but never answers our SYN/ACK). + Partially established connections tie up slots + on the listen queue. If the queue starts to + fill with connections in SYN_RCVD state, + tcp_keepinit can be decreased to make those + partial connects time out sooner. This should + be used with caution, since there might be + legitimate clients that are taking a while + to respond to SYN/ACK. The unit is specified + in 1/2 seconds, the default value is 150 + (ie. 75 seconds). + + The hashlist size for the TCP inpcb lookup table is regulated by: + + tcbhashsize The number of hash buckets used for the + TCP connection table used in the kernel. + The initial value is 32. For best results, + should be specified as a power of 2. For + busy Web servers, set this to 2048 or more. + + The hashlist size for the interface alias table is regulated by: + + inifaddr_hsize The number of hash buckets used for the + interface alias table used in the kernel. + The initial value is 32. For best results, + should be specified as a power of 2. + + ipport_userreserved The maximum number of concurrent non-reserved, + dynamically allocated ports. Default range + is 1025-5000. The maximum value is 65535. + This limits the numer of times you can + simultaneously telnet or ftp out to connect + to other systems. + + tcpnodelack Don't delay acknowledging TCP data; this + can sometimes improve performance of locally + run CAD packages. Default is value is 0, + the enabled value is 1. + + Digital UNIX version: + + V3.2C +Feature V3.2C patch V4.0 +======= ===== ===== ==== +somaxconn X X X +sominconn - X X +sobacklog_hiwat - X - +sobacklog_drops - X - +somaxconn_drops - X - +tcpnodelack X X X +tcp_keepidle X X X +tcp_keepintvl X X X +tcp_keepcnt - X X +tcp_keepinit - X X +TCP keepalive per-socket - - X +tcp_msl - X - +tcp_rexmit_interval_min - X - +TCP inpcb hashing - X X +tcbhashsize - X X +interface alias hashing - X X +inifaddr_hsize - X X +ipport_userreserved - X - +sysconfig -q inet - - X +sysconfig -q socket - - X + +
    + + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/perf-hp.html b/APACHE_1_3_12/htdocs/manual/misc/perf-hp.html new file mode 100644 index 0000000000..ca902a09fe --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/perf-hp.html @@ -0,0 +1,122 @@ + + + +Running a High-Performance Web Server on HPUX + + + + +  + + +

    Running a High-Performance Web Server for HPUX

    + +
    +Date: Wed, 05 Nov 1997 16:59:34 -0800
    +From: Rick Jones <raj@cup.hp.com>
    +Reply-To: raj@cup.hp.com
    +Organization: Network Performance
    +Subject: HP-UX tuning tips
    +
    + +Here are some tuning tips for HP-UX to add to the tuning page. + +

    + +For HP-UX 9.X: Upgrade to 10.20
    +For HP-UX 10.[00|01|10]: Upgrade to 10.20 + +

    + +For HP-UX 10.20: + +

    + +Install the latest cumulative ARPA Transport Patch. This will allow you +to configure the size of the TCP connection lookup hash table. The +default is 256 buckets and must be set to a power of two. This is +accomplished with adb against the *disc* image of the kernel. The +variable name is tcp_hash_size. + +Notice that it's critically important that you use "W" to write a 32 bit +quantity, not "w" to write a 16 bit value when patching the disc image because +the tcp_hash_size variable is a 32 bit quantity. + +

    + +How to pick the value? Examine the output of + +ftp://ftp.cup.hp.com/dist/networking/tools/connhist and see how many +total TCP connections exist on the system. You probably want that number +divided by the hash table size to be reasonably small, say less than 10. +Folks can look at HP's SPECweb96 disclosures for some common settings. +These can be found at +http://www.specbench.org/. If an HP-UX system was +performing at 1000 SPECweb96 connections per second, the TIME_WAIT time +of 60 seconds would mean 60,000 TCP "connections" being tracked. + +

    + +Folks can check their listen queue depths with + +ftp://ftp.cup.hp.com/dist/networking/misc/listenq. + +

    + +If folks are running Apache on a PA-8000 based system, they should +consider "chatr'ing" the Apache executable to have a large page size. +This would be "chatr +pi L <BINARY>." The GID of the running executable +must have MLOCK privileges. Setprivgrp(1m) should be consulted for +assigning MLOCK. The change can be validated by running Glance and +examining the memory regions of the server(s) to make sure that they +show a non-trivial fraction of the text segment being locked. + +

    + +If folks are running Apache on MP systems, they might consider writing a +small program that uses mpctl() to bind processes to processors. A +simple pid % numcpu algorithm is probably sufficient. This might even go +into the source code. + +

    + +If folks are concerned about the number of FIN_WAIT_2 connections, they +can use nettune to shrink the value of tcp_keepstart. However, they +should be careful there - certainly do not make it less than oh two to +four minutes. If tcp_hash_size has been set well, it is probably OK to +let the FIN_WAIT_2's take longer to timeout (perhaps even the default +two hours) - they will not on average have a big impact on performance. + +

    + +There are other things that could go into the code base, but that might +be left for another email. Feel free to drop me a message if you or +others are interested. + +

    + +sincerely, + +

    + +rick jones
    + +http://www.cup.hp.com/netperf/NetperfPage.html + +


    + +

    + Apache HTTP Server Version 1.3 +

    + +Index +Home + + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/perf-tuning.html b/APACHE_1_3_12/htdocs/manual/misc/perf-tuning.html new file mode 100644 index 0000000000..58ca489f61 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/perf-tuning.html @@ -0,0 +1,871 @@ + + + + Apache Performance Notes + + + +

    Apache Performance Notes

    + +

    Author: Dean Gaudet + +

    Introduction

    +

    Apache is a general webserver, which is designed to be correct first, and +fast second. Even so, its performance is quite satisfactory. Most +sites have less than 10Mbits of outgoing bandwidth, which Apache can +fill using only a low end Pentium-based webserver. In practice sites +with more bandwidth require more than one machine to fill the bandwidth +due to other constraints (such as CGI or database transaction overhead). +For these reasons the development focus has been mostly on correctness +and configurability. + +

    Unfortunately many folks overlook these facts and cite raw performance +numbers as if they are some indication of the quality of a web server +product. There is a bare minimum performance that is acceptable, beyond +that extra speed only caters to a much smaller segment of the market. +But in order to avoid this hurdle to the acceptance of Apache in some +markets, effort was put into Apache 1.3 to bring performance up to a +point where the difference with other high-end webservers is minimal. + +

    Finally there are the folks who just plain want to see how fast something +can go. The author falls into this category. The rest of this document +is dedicated to these folks who want to squeeze every last bit of +performance out of Apache's current model, and want to understand why +it does some things which slow it down. + +

    Note that this is tailored towards Apache 1.3 on Unix. Some of it applies +to Apache on NT. Apache on NT has not been tuned for performance yet, +in fact it probably performs very poorly because NT performance requires +a different programming model. + +

    Hardware and Operating System Issues

    + +

    The single biggest hardware issue affecting webserver performance +is RAM. A webserver should never ever have to swap, swapping increases +the latency of each request beyond a point that users consider "fast +enough". This causes users to hit stop and reload, further increasing +the load. You can, and should, control the MaxClients +setting so that your server does not spawn so many children it starts +swapping. + +

    Beyond that the rest is mundane: get a fast enough CPU, a fast enough +network card, and fast enough disks, where "fast enough" is something +that needs to be determined by experimentation. + +

    Operating system choice is largely a matter of local concerns. But +a general guideline is to always apply the latest vendor TCP/IP patches. +HTTP serving completely breaks many of the assumptions built into Unix +kernels up through 1994 and even 1995. Good choices include +recent FreeBSD, and Linux. + +

    Run-Time Configuration Issues

    + +

    HostnameLookups

    +

    Prior to Apache 1.3, HostnameLookups defaulted to On. +This adds latency +to every request because it requires a DNS lookup to complete before +the request is finished. In Apache 1.3 this setting defaults to Off. +However (1.3 or later), if you use any allow from domain or +deny from domain directives then you will pay for a +double reverse DNS lookup (a reverse, followed by a forward to make sure +that the reverse is not being spoofed). So for the highest performance +avoid using these directives (it's fine to use IP addresses rather than +domain names). + +

    Note that it's possible to scope the directives, such as within +a <Location /server-status> section. In this +case the DNS lookups are only performed on requests matching the +criteria. Here's an example which disables +lookups except for .html and .cgi files: + +

    +HostnameLookups off
    +<Files ~ "\.(html|cgi)$>
    +    HostnameLookups on
    +</Files>
    +
    + +But even still, if you just need DNS names +in some CGIs you could consider doing the +gethostbyname call in the specific CGIs that need it. + +

    FollowSymLinks and SymLinksIfOwnerMatch

    +

    Wherever in your URL-space you do not have an +Options FollowSymLinks, or you do have an +Options SymLinksIfOwnerMatch Apache will have to +issue extra system calls to check up on symlinks. One extra call per +filename component. For example, if you had: + +

    +DocumentRoot /www/htdocs
    +<Directory />
    +    Options SymLinksIfOwnerMatch
    +</Directory>
    +
    + +and a request is made for the URI /index.html. +Then Apache will perform lstat(2) on /www, +/www/htdocs, and /www/htdocs/index.html. The +results of these lstats are never cached, +so they will occur on every single request. If you really desire the +symlinks security checking you can do something like this: + +
    +DocumentRoot /www/htdocs
    +<Directory />
    +    Options FollowSymLinks
    +</Directory>
    +<Directory /www/htdocs>
    +    Options -FollowSymLinks +SymLinksIfOwnerMatch
    +</Directory>
    +
    + +This at least avoids the extra checks for the DocumentRoot +path. Note that you'll need to add similar sections if you have any +Alias or RewriteRule paths outside of your +document root. For highest performance, and no symlink protection, +set FollowSymLinks everywhere, and never set +SymLinksIfOwnerMatch. + +

    AllowOverride

    + +

    Wherever in your URL-space you allow overrides (typically +.htaccess files) Apache will attempt to open +.htaccess for each filename component. For example, + +

    +DocumentRoot /www/htdocs
    +<Directory />
    +    AllowOverride all
    +</Directory>
    +
    + +and a request is made for the URI /index.html. Then +Apache will attempt to open /.htaccess, +/www/.htaccess, and /www/htdocs/.htaccess. +The solutions are similar to the previous case of Options +FollowSymLinks. For highest performance use +AllowOverride None everywhere in your filesystem. + +

    Negotiation

    + +

    If at all possible, avoid content-negotiation if you're really +interested in every last ounce of performance. In practice the +benefits of negotiation outweigh the performance penalties. There's +one case where you can speed up the server. Instead of using +a wildcard such as: + +

    +DirectoryIndex index
    +
    + +Use a complete list of options: + +
    +DirectoryIndex index.cgi index.pl index.shtml index.html
    +
    + +where you list the most common choice first. + +

    Process Creation

    + +

    Prior to Apache 1.3 the MinSpareServers, +MaxSpareServers, and StartServers settings +all had drastic effects on benchmark results. In particular, Apache +required a "ramp-up" period in order to reach a number of children +sufficient to serve the load being applied. After the initial +spawning of StartServers children, only one child per +second would be created to satisfy the MinSpareServers +setting. So a server being accessed by 100 simultaneous clients, +using the default StartServers of 5 would take on +the order 95 seconds to spawn enough children to handle the load. This +works fine in practice on real-life servers, because they aren't restarted +frequently. But does really poorly on benchmarks which might only run +for ten minutes. + +

    The one-per-second rule was implemented in an effort to avoid +swamping the machine with the startup of new children. If the machine +is busy spawning children it can't service requests. But it has such +a drastic effect on the perceived performance of Apache that it had +to be replaced. As of Apache 1.3, +the code will relax the one-per-second rule. It +will spawn one, wait a second, then spawn two, wait a second, then spawn +four, and it will continue exponentially until it is spawning 32 children +per second. It will stop whenever it satisfies the +MinSpareServers setting. + +

    This appears to be responsive enough that it's +almost unnecessary to twiddle the MinSpareServers, +MaxSpareServers and StartServers knobs. When +more than 4 children are spawned per second, a message will be emitted +to the ErrorLog. If you see a lot of these errors then +consider tuning these settings. Use the mod_status output +as a guide. + +

    Related to process creation is process death induced by the +MaxRequestsPerChild setting. By default this is 0, which +means that there is no limit to the number of requests handled +per child. If your configuration currently has this set to some +very low number, such as 30, you may want to bump this up significantly. +If you are running SunOS or an old version of Solaris, limit this +to 10000 or so because of memory leaks. + +

    When keep-alives are in use, children will be kept busy +doing nothing waiting for more requests on the already open +connection. The default KeepAliveTimeout of +15 seconds attempts to minimize this effect. The tradeoff +here is between network bandwidth and server resources. +In no event should you raise this above about 60 seconds, as +most of the benefits are lost. + +

    Compile-Time Configuration Issues

    + +

    mod_status and ExtendedStatus On

    + +

    If you include mod_status +and you also set ExtendedStatus On when building and running +Apache, then on every request Apache will perform two calls to +gettimeofday(2) (or times(2) depending +on your operating system), and (pre-1.3) several extra calls to +time(2). This is all done so that the status report +contains timing indications. For highest performance, set +ExtendedStatus off (which is the default). + +

    accept Serialization - multiple sockets

    + +

    This discusses a shortcoming in the Unix socket API. +Suppose your +web server uses multiple Listen statements to listen on +either multiple ports or multiple addresses. In order to test each +socket to see if a connection is ready Apache uses select(2). +select(2) indicates that a socket has zero or +at least one connection waiting on it. Apache's model includes +multiple children, and all the idle ones test for new connections at the +same time. A naive implementation looks something like this +(these examples do not match the code, they're contrived for +pedagogical purposes): + +

    +    for (;;) {
    +	for (;;) {
    +	    fd_set accept_fds;
    +
    +	    FD_ZERO (&accept_fds);
    +	    for (i = first_socket; i <= last_socket; ++i) {
    +		FD_SET (i, &accept_fds);
    +	    }
    +	    rc = select (last_socket+1, &accept_fds, NULL, NULL, NULL);
    +	    if (rc < 1) continue;
    +	    new_connection = -1;
    +	    for (i = first_socket; i <= last_socket; ++i) {
    +		if (FD_ISSET (i, &accept_fds)) {
    +		    new_connection = accept (i, NULL, NULL);
    +		    if (new_connection != -1) break;
    +		}
    +	    }
    +	    if (new_connection != -1) break;
    +	}
    +	process the new_connection;
    +    }
    +
    + +But this naive implementation has a serious starvation problem. Recall +that multiple children execute this loop at the same time, and so multiple +children will block at select when they are in between +requests. All those blocked children will awaken and return from +select when a single request appears on any socket +(the number of children which awaken varies depending on the operating +system and timing issues). +They will all then fall down into the loop and try to accept +the connection. But only one will succeed (assuming there's still only +one connection ready), the rest will be blocked in +accept. +This effectively locks those children into serving requests from that +one socket and no other sockets, and they'll be stuck there until enough +new requests appear on that socket to wake them all up. +This starvation problem was first documented in +PR#467. There +are at least two solutions. + +

    One solution is to make the sockets non-blocking. In this case the +accept won't block the children, and they will be allowed +to continue immediately. But this wastes CPU time. Suppose you have +ten idle children in select, and one connection arrives. +Then nine of those children will wake up, try to accept the +connection, fail, and loop back into select, accomplishing +nothing. Meanwhile none of those children are servicing requests that +occurred on other sockets until they get back up to the select +again. Overall this solution does not seem very fruitful unless you +have as many idle CPUs (in a multiprocessor box) as you have idle children, +not a very likely situation. + +

    Another solution, the one used by Apache, is to serialize entry into +the inner loop. The loop looks like this (differences highlighted): + +

    +    for (;;) {
    +	accept_mutex_on ();
    +	for (;;) {
    +	    fd_set accept_fds;
    +
    +	    FD_ZERO (&accept_fds);
    +	    for (i = first_socket; i <= last_socket; ++i) {
    +		FD_SET (i, &accept_fds);
    +	    }
    +	    rc = select (last_socket+1, &accept_fds, NULL, NULL, NULL);
    +	    if (rc < 1) continue;
    +	    new_connection = -1;
    +	    for (i = first_socket; i <= last_socket; ++i) {
    +		if (FD_ISSET (i, &accept_fds)) {
    +		    new_connection = accept (i, NULL, NULL);
    +		    if (new_connection != -1) break;
    +		}
    +	    }
    +	    if (new_connection != -1) break;
    +	}
    +	accept_mutex_off ();
    +	process the new_connection;
    +    }
    +
    + +The functions +accept_mutex_on and accept_mutex_off +implement a mutual exclusion semaphore. Only one child can have the +mutex at any time. There are several choices for implementing these +mutexes. The choice is defined in src/conf.h (pre-1.3) or +src/include/ap_config.h (1.3 or later). Some architectures +do not have any locking choice made, on these architectures it is unsafe +to use multiple Listen directives. + +
    +
    USE_FLOCK_SERIALIZED_ACCEPT +
    This method uses the flock(2) system call to lock a +lock file (located by the LockFile directive). + +
    USE_FCNTL_SERIALIZED_ACCEPT +
    This method uses the fcntl(2) system call to lock a +lock file (located by the LockFile directive). + +
    USE_SYSVSEM_SERIALIZED_ACCEPT +
    (1.3 or later) This method uses SysV-style semaphores to implement the +mutex. Unfortunately SysV-style semaphores have some bad side-effects. +One is that it's possible Apache will die without cleaning up the semaphore +(see the ipcs(8) man page). The other is that the semaphore +API allows for a denial of service attack by any CGIs running under the +same uid as the webserver (i.e., all CGIs unless you use something +like suexec or cgiwrapper). For these reasons this method is not used +on any architecture except IRIX (where the previous two are prohibitively +expensive on most IRIX boxes). + +
    USE_USLOCK_SERIALIZED_ACCEPT +
    (1.3 or later) This method is only available on IRIX, and uses +usconfig(2) to create a mutex. While this method avoids +the hassles of SysV-style semaphores, it is not the default for IRIX. +This is because on single processor IRIX boxes (5.3 or 6.2) the +uslock code is two orders of magnitude slower than the SysV-semaphore +code. On multi-processor IRIX boxes the uslock code is an order of magnitude +faster than the SysV-semaphore code. Kind of a messed up situation. +So if you're using a multiprocessor IRIX box then you should rebuild your +webserver with -DUSE_USLOCK_SERIALIZED_ACCEPT on the +EXTRA_CFLAGS. + +
    USE_PTHREAD_SERIALIZED_ACCEPT +
    (1.3 or later) This method uses POSIX mutexes and should work on +any architecture implementing the full POSIX threads specification, +however appears to only work on Solaris (2.5 or later), and even then +only in certain configurations. If you experiment with this you should +watch out for your server hanging and not responding. Static content +only servers may work just fine. +
    + +

    If your system has another method of serialization which isn't in the +above list then it may be worthwhile adding code for it (and submitting +a patch back to Apache). + +

    Another solution that has been considered but never implemented is +to partially serialize the loop -- that is, let in a certain number +of processes. This would only be of interest on multiprocessor boxes +where it's possible multiple children could run simultaneously, and the +serialization actually doesn't take advantage of the full bandwidth. +This is a possible area of future investigation, but priority remains +low because highly parallel web servers are not the norm. + +

    Ideally you should run servers without multiple Listen +statements if you want the highest performance. But read on. + +

    accept Serialization - single socket

    + +

    The above is fine and dandy for multiple socket servers, but what +about single socket servers? In theory they shouldn't experience +any of these same problems because all children can just block in +accept(2) until a connection arrives, and no starvation +results. In practice this hides almost the same "spinning" behaviour +discussed above in the non-blocking solution. The way that most TCP +stacks are implemented, the kernel actually wakes up all processes blocked +in accept when a single connection arrives. One of those +processes gets the connection and returns to user-space, the rest spin in +the kernel and go back to sleep when they discover there's no connection +for them. This spinning is hidden from the user-land code, but it's +there nonetheless. This can result in the same load-spiking wasteful +behaviour that a non-blocking solution to the multiple sockets case can. + +

    For this reason we have found that many architectures behave more +"nicely" if we serialize even the single socket case. So this is +actually the default in almost all cases. Crude experiments under +Linux (2.0.30 on a dual Pentium pro 166 w/128Mb RAM) have shown that +the serialization of the single socket case causes less than a 3% +decrease in requests per second over unserialized single-socket. +But unserialized single-socket showed an extra 100ms latency on +each request. This latency is probably a wash on long haul lines, +and only an issue on LANs. If you want to override the single socket +serialization you can define SINGLE_LISTEN_UNSERIALIZED_ACCEPT +and then single-socket servers will not serialize at all. + +

    Lingering Close

    + +

    As discussed in +draft-ietf-http-connection-00.txt section 8, +in order for an HTTP server to reliably implement the protocol +it needs to shutdown each direction of the communication independently +(recall that a TCP connection is bi-directional, each half is independent +of the other). This fact is often overlooked by other servers, but +is correctly implemented in Apache as of 1.2. + +

    When this feature was added to Apache it caused a flurry of +problems on various versions of Unix because of a shortsightedness. +The TCP specification does not state that the FIN_WAIT_2 state has a +timeout, but it doesn't prohibit it. On systems without the timeout, +Apache 1.2 induces many sockets stuck forever in the FIN_WAIT_2 state. +In many cases this can be avoided by simply upgrading to the latest +TCP/IP patches supplied by the vendor, in cases where the vendor has +never released patches (i.e., SunOS4 -- although folks with a source +license can patch it themselves) we have decided to disable this feature. + +

    There are two ways of accomplishing this. One is the +socket option SO_LINGER. But as fate would have it, +this has never been implemented properly in most TCP/IP stacks. Even +on those stacks with a proper implementation (i.e., Linux 2.0.31) this +method proves to be more expensive (cputime) than the next solution. + +

    For the most part, Apache implements this in a function called +lingering_close (in http_main.c). The +function looks roughly like this: + +

    +    void lingering_close (int s)
    +    {
    +	char junk_buffer[2048];
    +
    +	/* shutdown the sending side */
    +	shutdown (s, 1);
    +
    +	signal (SIGALRM, lingering_death);
    +	alarm (30);
    +
    +	for (;;) {
    +	    select (s for reading, 2 second timeout);
    +	    if (error) break;
    +	    if (s is ready for reading) {
    +		read (s, junk_buffer, sizeof (junk_buffer));
    +		/* just toss away whatever is here */
    +	    }
    +	}
    +
    +	close (s);
    +    }
    +
    + +This naturally adds some expense at the end of a connection, but it +is required for a reliable implementation. As HTTP/1.1 becomes more +prevalent, and all connections are persistent, this expense will be +amortized over more requests. If you want to play with fire and +disable this feature you can define NO_LINGCLOSE, but +this is not recommended at all. In particular, as HTTP/1.1 pipelined +persistent connections come into use lingering_close +is an absolute necessity (and + +pipelined connections are faster, so you +want to support them). + +

    Scoreboard File

    + +

    Apache's parent and children communicate with each other through +something called the scoreboard. Ideally this should be implemented +in shared memory. For those operating systems that we either have +access to, or have been given detailed ports for, it typically is +implemented using shared memory. The rest default to using an +on-disk file. The on-disk file is not only slow, but it is unreliable +(and less featured). Peruse the src/main/conf.h file +for your architecture and look for either USE_MMAP_SCOREBOARD or +USE_SHMGET_SCOREBOARD. Defining one of those two (as +well as their companions HAVE_MMAP and HAVE_SHMGET +respectively) enables the supplied shared memory code. If your system has +another type of shared memory, edit the file src/main/http_main.c +and add the hooks necessary to use it in Apache. (Send us back a patch +too please.) + +

    Historical note: The Linux port of Apache didn't start to use +shared memory until version 1.2 of Apache. This oversight resulted +in really poor and unreliable behaviour of earlier versions of Apache +on Linux. + +

    DYNAMIC_MODULE_LIMIT

    + +

    If you have no intention of using dynamically loaded modules +(you probably don't if you're reading this and tuning your +server for every last ounce of performance) then you should add +-DDYNAMIC_MODULE_LIMIT=0 when building your server. +This will save RAM that's allocated only for supporting dynamically +loaded modules. + +

    Appendix: Detailed Analysis of a Trace

    + +Here is a system call trace of Apache 1.3 running on Linux. The run-time +configuration file is essentially the default plus: + +
    +<Directory />
    +    AllowOverride none
    +    Options FollowSymLinks
    +</Directory>
    +
    + +The file being requested is a static 6K file of no particular content. +Traces of non-static requests or requests with content negotiation +look wildly different (and quite ugly in some cases). First the +entire trace, then we'll examine details. (This was generated by +the strace program, other similar programs include +truss, ktrace, and par.) + +
    +accept(15, {sin_family=AF_INET, sin_port=htons(22283), sin_addr=inet_addr("127.0.0.1")}, [16]) = 3
    +flock(18, LOCK_UN)                      = 0
    +sigaction(SIGUSR1, {SIG_IGN}, {0x8059954, [], SA_INTERRUPT}) = 0
    +getsockname(3, {sin_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("127.0.0.1")}, [16]) = 0
    +setsockopt(3, IPPROTO_TCP1, [1], 4)     = 0
    +read(3, "GET /6k HTTP/1.0\r\nUser-Agent: "..., 4096) = 60
    +sigaction(SIGUSR1, {SIG_IGN}, {SIG_IGN}) = 0
    +time(NULL)                              = 873959960
    +gettimeofday({873959960, 404935}, NULL) = 0
    +stat("/home/dgaudet/ap/apachen/htdocs/6k", {st_mode=S_IFREG|0644, st_size=6144, ...}) = 0
    +open("/home/dgaudet/ap/apachen/htdocs/6k", O_RDONLY) = 4
    +mmap(0, 6144, PROT_READ, MAP_PRIVATE, 4, 0) = 0x400ee000
    +writev(3, [{"HTTP/1.1 200 OK\r\nDate: Thu, 11"..., 245}, {"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 6144}], 2) = 6389
    +close(4)                                = 0
    +time(NULL)                              = 873959960
    +write(17, "127.0.0.1 - - [10/Sep/1997:23:39"..., 71) = 71
    +gettimeofday({873959960, 417742}, NULL) = 0
    +times({tms_utime=5, tms_stime=0, tms_cutime=0, tms_cstime=0}) = 446747
    +shutdown(3, 1 /* send */)               = 0
    +oldselect(4, [3], NULL, [3], {2, 0})    = 1 (in [3], left {2, 0})
    +read(3, "", 2048)                       = 0
    +close(3)                                = 0
    +sigaction(SIGUSR1, {0x8059954, [], SA_INTERRUPT}, {SIG_IGN}) = 0
    +munmap(0x400ee000, 6144)                = 0
    +flock(18, LOCK_EX)                      = 0
    +
    + +

    Notice the accept serialization: + +

    +flock(18, LOCK_UN)                      = 0
    +...
    +flock(18, LOCK_EX)                      = 0
    +
    + +These two calls can be removed by defining +SINGLE_LISTEN_UNSERIALIZED_ACCEPT as described earlier. + +

    Notice the SIGUSR1 manipulation: + +

    +sigaction(SIGUSR1, {SIG_IGN}, {0x8059954, [], SA_INTERRUPT}) = 0
    +...
    +sigaction(SIGUSR1, {SIG_IGN}, {SIG_IGN}) = 0
    +...
    +sigaction(SIGUSR1, {0x8059954, [], SA_INTERRUPT}, {SIG_IGN}) = 0
    +
    + +This is caused by the implementation of graceful restarts. When the +parent receives a SIGUSR1 it sends a SIGUSR1 +to all of its children (and it also increments a "generation counter" +in shared memory). Any children that are idle (between connections) +will immediately die +off when they receive the signal. Any children that are in keep-alive +connections, but are in between requests will die off immediately. But +any children that have a connection and are still waiting for the first +request will not die off immediately. + +

    To see why this is necessary, consider how a browser reacts to a closed +connection. If the connection was a keep-alive connection and the request +being serviced was not the first request then the browser will quietly +reissue the request on a new connection. It has to do this because the +server is always free to close a keep-alive connection in between requests +(i.e., due to a timeout or because of a maximum number of requests). +But, if the connection is closed before the first response has been +received the typical browser will display a "document contains no data" +dialogue (or a broken image icon). This is done on the assumption that +the server is broken in some way (or maybe too overloaded to respond +at all). So Apache tries to avoid ever deliberately closing the connection +before it has sent a single response. This is the cause of those +SIGUSR1 manipulations. + +

    Note that it is theoretically possible to eliminate all three of +these calls. But in rough tests the gain proved to be almost unnoticeable. + +

    In order to implement virtual hosts, Apache needs to know the +local socket address used to accept the connection: + +

    +getsockname(3, {sin_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("127.0.0.1")}, [16]) = 0
    +
    + +It is possible to eliminate this call in many situations (such as when +there are no virtual hosts, or when Listen directives are +used which do not have wildcard addresses). But no effort has yet been +made to do these optimizations. + +

    Apache turns off the Nagle algorithm: + +

    +setsockopt(3, IPPROTO_TCP1, [1], 4)     = 0
    +
    + +because of problems described in +a +paper by John Heidemann. + +

    Notice the two time calls: + +

    +time(NULL)                              = 873959960
    +...
    +time(NULL)                              = 873959960
    +
    + +One of these occurs at the beginning of the request, and the other occurs +as a result of writing the log. At least one of these is required to +properly implement the HTTP protocol. The second occurs because the +Common Log Format dictates that the log record include a timestamp of the +end of the request. A custom logging module could eliminate one of the +calls. Or you can use a method which moves the time into shared memory, +see the patches section below. + +

    As described earlier, ExtendedStatus On causes two +gettimeofday calls and a call to times: + +

    +gettimeofday({873959960, 404935}, NULL) = 0
    +...
    +gettimeofday({873959960, 417742}, NULL) = 0
    +times({tms_utime=5, tms_stime=0, tms_cutime=0, tms_cstime=0}) = 446747
    +
    + +These can be removed by setting ExtendedStatus Off (which +is the default). + +

    It might seem odd to call stat: + +

    +stat("/home/dgaudet/ap/apachen/htdocs/6k", {st_mode=S_IFREG|0644, st_size=6144, ...}) = 0
    +
    + +This is part of the algorithm which calculates the +PATH_INFO for use by CGIs. In fact if the request had been +for the URI /cgi-bin/printenv/foobar then there would be +two calls to stat. The first for +/home/dgaudet/ap/apachen/cgi-bin/printenv/foobar +which does not exist, and the second for +/home/dgaudet/ap/apachen/cgi-bin/printenv, which does exist. +Regardless, at least one stat call is necessary when +serving static files because the file size and modification times are +used to generate HTTP headers (such as Content-Length, +Last-Modified) and implement protocol features (such +as If-Modified-Since). A somewhat more clever server +could avoid the stat when serving non-static files, +however doing so in Apache is very difficult given the modular structure. + +

    All static files are served using mmap: + +

    +mmap(0, 6144, PROT_READ, MAP_PRIVATE, 4, 0) = 0x400ee000
    +...
    +munmap(0x400ee000, 6144)                = 0
    +
    + +On some architectures it's slower to mmap small +files than it is to simply read them. The define +MMAP_THRESHOLD can be set to the minimum +size required before using mmap. By default +it's set to 0 (except on SunOS4 where experimentation has +shown 8192 to be a better value). Using a tool such as lmbench you +can determine the optimal setting for your environment. + +

    You may also wish to experiment with MMAP_SEGMENT_SIZE +(default 32768) which determines the maximum number of bytes that +will be written at a time from mmap()d files. Apache only resets the +client's Timeout in between write()s. So setting this +large may lock out low bandwidth clients unless you also increase the +Timeout. + +

    It may even be the case that mmap isn't +used on your architecture, if so then defining USE_MMAP_FILES +and HAVE_MMAP might work (if it works then report back to us). + +

    Apache does its best to avoid copying bytes around in memory. The +first write of any request typically is turned into a writev +which combines both the headers and the first hunk of data: + +

    +writev(3, [{"HTTP/1.1 200 OK\r\nDate: Thu, 11"..., 245}, {"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 6144}], 2) = 6389
    +
    + +When doing HTTP/1.1 chunked encoding Apache will generate up to four +element writevs. The goal is to push the byte copying +into the kernel, where it typically has to happen anyhow (to assemble +network packets). On testing, various Unixes (BSDI 2.x, Solaris 2.5, +Linux 2.0.31+) properly combine the elements into network packets. +Pre-2.0.31 Linux will not combine, and will create a packet for +each element, so upgrading is a good idea. Defining NO_WRITEV +will disable this combining, but result in very poor chunked encoding +performance. + +

    The log write: + +

    +write(17, "127.0.0.1 - - [10/Sep/1997:23:39"..., 71) = 71
    +
    + +can be deferred by defining BUFFERED_LOGS. In this case +up to PIPE_BUF bytes (a POSIX defined constant) of log entries +are buffered before writing. At no time does it split a log entry +across a PIPE_BUF boundary because those writes may not +be atomic. (i.e., entries from multiple children could become mixed together). +The code does it best to flush this buffer when a child dies. + +

    The lingering close code causes four system calls: + +

    +shutdown(3, 1 /* send */)               = 0
    +oldselect(4, [3], NULL, [3], {2, 0})    = 1 (in [3], left {2, 0})
    +read(3, "", 2048)                       = 0
    +close(3)                                = 0
    +
    + +which were described earlier. + +

    Let's apply some of these optimizations: +-DSINGLE_LISTEN_UNSERIALIZED_ACCEPT -DBUFFERED_LOGS and +ExtendedStatus Off. Here's the final trace: + +

    +accept(15, {sin_family=AF_INET, sin_port=htons(22286), sin_addr=inet_addr("127.0.0.1")}, [16]) = 3
    +sigaction(SIGUSR1, {SIG_IGN}, {0x8058c98, [], SA_INTERRUPT}) = 0
    +getsockname(3, {sin_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("127.0.0.1")}, [16]) = 0
    +setsockopt(3, IPPROTO_TCP1, [1], 4)     = 0
    +read(3, "GET /6k HTTP/1.0\r\nUser-Agent: "..., 4096) = 60
    +sigaction(SIGUSR1, {SIG_IGN}, {SIG_IGN}) = 0
    +time(NULL)                              = 873961916
    +stat("/home/dgaudet/ap/apachen/htdocs/6k", {st_mode=S_IFREG|0644, st_size=6144, ...}) = 0
    +open("/home/dgaudet/ap/apachen/htdocs/6k", O_RDONLY) = 4
    +mmap(0, 6144, PROT_READ, MAP_PRIVATE, 4, 0) = 0x400e3000
    +writev(3, [{"HTTP/1.1 200 OK\r\nDate: Thu, 11"..., 245}, {"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 6144}], 2) = 6389
    +close(4)                                = 0
    +time(NULL)                              = 873961916
    +shutdown(3, 1 /* send */)               = 0
    +oldselect(4, [3], NULL, [3], {2, 0})    = 1 (in [3], left {2, 0})
    +read(3, "", 2048)                       = 0
    +close(3)                                = 0
    +sigaction(SIGUSR1, {0x8058c98, [], SA_INTERRUPT}, {SIG_IGN}) = 0
    +munmap(0x400e3000, 6144)                = 0
    +
    + +That's 19 system calls, of which 4 remain relatively easy to remove, +but don't seem worth the effort. + +

    Appendix: Patches Available

    + +There are + +several performance patches available for 1.3. But they may +be slightly out of date by the time Apache 1.3.0 has been released, +it shouldn't be difficult for someone with a little C knowledge to +update them. In particular: + +
      +
    • A +patch to remove all time(2) system calls. +
    • A +patch to remove various system calls from mod_include, +these calls are used by few sites but required for backwards compatibility. +
    • A +patch which integrates the above two plus a few other speedups at the +cost of removing some functionality. +
    + +

    Appendix: The Pre-Forking Model

    + +

    Apache (on Unix) is a pre-forking model server. The +parent process is responsible only for forking child +processes, it does not serve any requests or service any network +sockets. The child processes actually process connections, they serve +multiple connections (one at a time) before dying. +The parent spawns new or kills off old +children in response to changes in the load on the server (it does so +by monitoring a scoreboard which the children keep up to date). + +

    This model for servers offers a robustness that other models do +not. In particular, the parent code is very simple, and with a high +degree of confidence the parent will continue to do its job without +error. The children are complex, and when you add in third party +code via modules, you risk segmentation faults and other forms of +corruption. Even should such a thing happen, it only affects one +connection and the server continues serving requests. The parent +quickly replaces the dead child. + +

    Pre-forking is also very portable across dialects of Unix. +Historically this has been an important goal for Apache, and it continues +to remain so. + +

    The pre-forking model comes under criticism for various +performance aspects. Of particular concern are the overhead +of forking a process, the overhead of context switches between +processes, and the memory overhead of having multiple processes. +Furthermore it does not offer as many opportunities for data-caching +between requests (such as a pool of mmapped files). +Various other models exist and extensive analysis can be found in the + papers +of the JAWS project. In practice all of these costs vary drastically +depending on the operating system. + +

    Apache's core code is already multithread aware, and Apache version +1.3 is multithreaded on NT. There have been at least two other experimental +implementations of threaded Apache, one using the 1.3 code base on DCE, +and one using a custom user-level threads package and the 1.0 code base, +neither are available publically. There is also an experimental port of +Apache 1.3 to +Netscape's Portable Run Time, which +is available +(but you're encouraged to join the +new-httpd mailing list +if you intend to use it). +Part of our redesign for version 2.0 +of Apache will include abstractions of the server model so that we +can continue to support the pre-forking model, and also support various +threaded models. + + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/perf.html b/APACHE_1_3_12/htdocs/manual/misc/perf.html new file mode 100644 index 0000000000..73bd5b5b20 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/perf.html @@ -0,0 +1,175 @@ + + + +Hints on Running a High-Performance Web Server + + + + + +

    Hints on Running a High-Performance Web Server

    + +Running Apache on a heavily loaded web server, one often encounters +problems related to the machine and OS configuration. "Heavy" is +relative, of course - but if you are seeing more than a couple hits +per second on a sustained basis you should consult the pointers on +this page. In general the suggestions involve how to tune your kernel +for the heavier TCP load, hardware/software conflicts that arise, etc. + + + +
    + +

    +A/UX (Apple's UNIX) +

    + +If you are running Apache on A/UX, a page that gives some helpful +performance hints (concerning the listen() queue and using +virtual hosts) +can be found here + +


    + +

    +BSD-based (BSDI, FreeBSD, etc) +

    + +Quick and +detailed +performance tuning hints for BSD-derived systems. + +


    + +

    +Digital UNIX +

    + + + +


    + +

    +Linux +

    + +There are no known problems with heavily loaded systems running Linux +kernels 2.0.32 or later. Earlier kernels have some problems, and an +upgrade to the latest 2.0.x is a good idea to eliminate various security +and denial of service attacks. + +


    + +

    +Solaris 2.4 +

    + +The Solaris 2.4 TCP implementation has a few inherent limitations that +only became apparent under heavy loads. This has been fixed to some +extent in 2.5 (and completely revamped in 2.6), but for now consult +the following URL for tips on how to expand the capabilities if you +are finding slowdowns and lags are hurting performance. + +

    + +Other links: + +

    + +


    + +

    +SunOS 4.x +

    + +More information on tuning SOMAXCONN on SunOS can be found at + +http://www.islandnet.com/~mark/somaxconn.html. + +


    + +

    +SVR4 +

    + +Some SVR4 versions waste three system calls on every +gettimeofday() call. Depending on the syntactic +form of the TZ environment variable, these +systems have several different algorithms to determine the +local time zone (presumably compatible with +something). The following example uses the central european +time zone to demonstrate this: +
    +
    TZ=:MET +
    This form delegates the knowledge of the time zone + information to an external compiled zoneinfo file + (à la BSD).
    + Caveat: Each time the gettimeofday() + function is called, the external zone info is read in + again (at least on some SVR4 systems). That results in + three wasted system calls with every apache request + served.
    +     open("/usr/lib/locale/TZ/MET", O_RDONLY) = 3
    +     read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 7944) = 778
    +     close(3)                                = 0
    + +
    TZ=MET-1MDT,M3.5.0/02:00:00,M10.5.0/03:00:00 +
    This syntax form (à la SYSV) contains all the + knowledge about time zone beginning and ending times in + its external representation. It has to be parsed each + time it is evaluated, resulting in a slight computing + overhead, but it requires no system call. Though the + table lookup à la BSD is the more sophisticated + technical solution, the bad SVR4 implementation makes + this the preferred syntax on systems which otherwise + access the external zone info file repeatedly. +
    +You should use the truss utility on a +single-process apache server (started with the -X +debugging switch) to determine whether your system can profit +from the second form of the TZ environment +variable. If it does, you could integrate the setting of the +preferred TZ syntax into the httpd startup +script, which is usually simply a copy of (or symbolic link +to) the apachectl utility script, or into the +system's /etc/TIMEZONE script. + +


    + +

    More welcome!

    + +If you have tips to contribute, send mail to apache@apache.org + + + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/rewriteguide.html b/APACHE_1_3_12/htdocs/manual/misc/rewriteguide.html new file mode 100644 index 0000000000..0f469bd8b0 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/rewriteguide.html @@ -0,0 +1,1906 @@ + + +Apache 1.3 URL Rewriting Guide + + + + +
    + + +
    + +

    +Apache 1.3
    +URL Rewriting Guide
    +

    + +
    Originally written by
    +Ralf S. Engelschall <rse@apache.org>
    +December 1997
    + +
    + +

    +This document supplements the mod_rewrite reference documentation. It describes +how one can use Apache's mod_rewrite to solve typical URL-based problems +webmasters are usually confronted with in practice. I give detailed +descriptions on how to solve each problem by configuring URL rewriting +rulesets. + +

    Introduction to mod_rewrite

    + +The Apache module mod_rewrite is a killer one, i.e. it is a really +sophisticated module which provides a powerful way to do URL manipulations. +With it you can nearly do all types of URL manipulations you ever dreamed +about. The price you have to pay is to accept complexity, because +mod_rewrite's major drawback is that it is not easy to understand and use for +the beginner. And even Apache experts sometimes discover new aspects where +mod_rewrite can help. +

    +In other words: With mod_rewrite you either shoot yourself in the foot the +first time and never use it again or love it for the rest of your life because +of its power. This paper tries to give you a few initial success events to +avoid the first case by presenting already invented solutions to you. + +

    Practical Solutions

    + +Here come a lot of practical solutions I've either invented myself or +collected from other peoples solutions in the past. Feel free to learn the +black magic of URL rewriting from these examples. + +

    +
    +ATTENTION: Depending on your server-configuration it can be necessary to +slightly change the examples for your situation, e.g. adding the [PT] flag +when additionally using mod_alias and mod_userdir, etc. Or rewriting a ruleset +to fit in .htaccess context instead of per-server context. Always try +to understand what a particular ruleset really does before you use it. It +avoid problems. +
    + +

    URL Layout

    + +

    +

    Canonical URLs

    +

    + +

    +
    Description: +
    +On some webservers there are more than one URL for a resource. Usually there +are canonical URLs (which should be actually used and distributed) and those +which are just shortcuts, internal ones, etc. Independed which URL the user +supplied with the request he should finally see the canonical one only. + +

    +

    Solution: +
    +We do an external HTTP redirect for all non-canonical URLs to fix them in the +location view of the Browser and for all subsequent requests. In the example +ruleset below we replace /~user by the canonical /u/user and +fix a missing trailing slash for /u/user. + +

    +RewriteRule   ^/~([^/]+)/?(.*)    /u/$1/$2  [R]
    +RewriteRule   ^/([uge])/([^/]+)$  /$1/$2/   [R]
    +
    + +

    + +

    +

    Canonical Hostnames

    +

    + +

    +
    Description: +
    +... + +

    +

    Solution: +
    + +

    +RewriteCond %{HTTP_HOST}   !^fully\.qualified\.domain\.name [NC]
    +RewriteCond %{HTTP_HOST}   !^$
    +RewriteCond %{SERVER_PORT} !^80$
    +RewriteRule ^/(.*)         http://fully.qualified.domain.name:%{SERVER_PORT}/$1 [L,R]
    +RewriteCond %{HTTP_HOST}   !^fully\.qualified\.domain\.name [NC]
    +RewriteCond %{HTTP_HOST}   !^$
    +RewriteRule ^/(.*)         http://fully.qualified.domain.name/$1 [L,R]
    +
    + +

    + +

    +

    Moved DocumentRoot

    +

    + +

    +
    Description: +
    +Usually the DocumentRoot of the webserver directly relates to the URL +``/''. But often this data is not really of top-level priority, it is +perhaps just one entity of a lot of data pools. For instance at our Intranet +sites there are /e/www/ (the homepage for WWW), /e/sww/ (the +homepage for the Intranet) etc. Now because the data of the DocumentRoot stays +at /e/www/ we had to make sure that all inlined images and other +stuff inside this data pool work for subsequent requests. + +

    +

    Solution: +
    +We just redirect the URL / to /e/www/. While is seems +trivial it is actually trivial with mod_rewrite, only. Because the typical +old mechanisms of URL Aliases (as provides by mod_alias and friends) +only used prefix matching. With this you cannot do such a redirection +because the DocumentRoot is a prefix of all URLs. With mod_rewrite it is +really trivial: + +

    +RewriteEngine on
    +RewriteRule   ^/$  /e/www/  [R]
    +
    + +

    + +

    +

    Trailing Slash Problem

    +

    + +

    +
    Description: +
    +Every webmaster can sing a song about the problem of the trailing slash on +URLs referencing directories. If they are missing, the server dumps an error, +because if you say /~quux/foo instead of +/~quux/foo/ then the server searches for a file named +foo. And because this file is a directory it complains. Actually +is tries to fix it themself in most of the cases, but sometimes this mechanism +need to be emulated by you. For instance after you have done a lot of +complicated URL rewritings to CGI scripts etc. + +

    +

    Solution: +
    +The solution to this subtle problem is to let the server add the trailing +slash automatically. To do this correctly we have to use an external redirect, +so the browser correctly requests subsequent images etc. If we only did a +internal rewrite, this would only work for the directory page, but would go +wrong when any images are included into this page with relative URLs, because +the browser would request an in-lined object. For instance, a request for +image.gif in /~quux/foo/index.html would become +/~quux/image.gif without the external redirect! +

    +So, to do this trick we write: + +

    +RewriteEngine  on
    +RewriteBase    /~quux/
    +RewriteRule    ^foo$  foo/  [R]
    +
    + +

    +The crazy and lazy can even do the following in the top-level +.htaccess file of their homedir. But notice that this creates some +processing overhead. + +

    +RewriteEngine  on
    +RewriteBase    /~quux/
    +RewriteCond    %{REQUEST_FILENAME}  -d
    +RewriteRule    ^(.+[^/])$           $1/  [R]
    +
    + +

    + +

    +

    Webcluster through Homogeneous URL Layout

    +

    + +

    +
    Description: +
    +We want to create a homogenous and consistent URL layout over all WWW servers +on a Intranet webcluster, i.e. all URLs (per definition server local and thus +server dependent!) become actually server independed! What we want is +to give the WWW namespace a consistent server-independend layout: no URL +should have to include any physically correct target server. The cluster +itself should drive us automatically to the physical target host. + +

    +

    Solution: +
    +First, the knowledge of the target servers come from (distributed) external +maps which contain information where our users, groups and entities stay. +The have the form + +

    +user1  server_of_user1
    +user2  server_of_user2
    +:      :
    +

    + +We put them into files map.xxx-to-host. Second we need to instruct +all servers to redirect URLs of the forms + +

    +/u/user/anypath
    +/g/group/anypath
    +/e/entity/anypath
    +

    + +to + +

    +http://physical-host/u/user/anypath
    +http://physical-host/g/group/anypath
    +http://physical-host/e/entity/anypath
    +

    + +when the URL is not locally valid to a server. The following ruleset does +this for us by the help of the map files (assuming that server0 is a default +server which will be used if a user has no entry in the map): + +

    +RewriteEngine on
    +
    +RewriteMap      user-to-host   txt:/path/to/map.user-to-host
    +RewriteMap     group-to-host   txt:/path/to/map.group-to-host
    +RewriteMap    entity-to-host   txt:/path/to/map.entity-to-host
    +
    +RewriteRule   ^/u/([^/]+)/?(.*)   http://${user-to-host:$1|server0}/u/$1/$2
    +RewriteRule   ^/g/([^/]+)/?(.*)  http://${group-to-host:$1|server0}/g/$1/$2
    +RewriteRule   ^/e/([^/]+)/?(.*) http://${entity-to-host:$1|server0}/e/$1/$2
    +
    +RewriteRule   ^/([uge])/([^/]+)/?$          /$1/$2/.www/
    +RewriteRule   ^/([uge])/([^/]+)/([^.]+.+)   /$1/$2/.www/$3\
    +
    + +

    + +

    +

    Move Homedirs to Different Webserver

    +

    + +

    +
    Description: +
    +A lot of webmaster aksed for a solution to the following situation: They +wanted to redirect just all homedirs on a webserver to another webserver. +They usually need such things when establishing a newer webserver which will +replace the old one over time. + +

    +

    Solution: +
    +The solution is trivial with mod_rewrite. On the old webserver we just +redirect all /~user/anypath URLs to +http://newserver/~user/anypath. + +

    +RewriteEngine on
    +RewriteRule   ^/~(.+)  http://newserver/~$1  [R,L]
    +
    + +

    + +

    +

    Structured Homedirs

    +

    + +

    +
    Description: +
    +Some sites with thousend of users usually use a structured homedir layout, +i.e. each homedir is in a subdirectory which begins for instance with the +first character of the username. So, /~foo/anypath is +/home/f/foo/.www/anypath while /~bar/anypath is +/home/b/bar/.www/anypath. + +

    +

    Solution: +
    +We use the following ruleset to expand the tilde URLs into exactly the above +layout. + +

    +RewriteEngine on
    +RewriteRule   ^/~(([a-z])[a-z0-9]+)(.*)  /home/$2/$1/.www$3
    +
    + +

    + +

    +

    Filesystem Reorganisation

    +

    + +

    +
    Description: +
    +This really is a hardcore example: a killer application which heavily uses +per-directory RewriteRules to get a smooth look and feel on the Web +while its data structure is never touched or adjusted. + +Background: net.sw is my archive of freely available Unix +software packages, which I started to collect in 1992. It is both my hobby and +job to to this, because while I'm studying computer science I have also worked +for many years as a system and network administrator in my spare time. Every +week I need some sort of software so I created a deep hierarchy of +directories where I stored the packages: + +

    +drwxrwxr-x   2 netsw  users    512 Aug  3 18:39 Audio/
    +drwxrwxr-x   2 netsw  users    512 Jul  9 14:37 Benchmark/
    +drwxrwxr-x  12 netsw  users    512 Jul  9 00:34 Crypto/
    +drwxrwxr-x   5 netsw  users    512 Jul  9 00:41 Database/
    +drwxrwxr-x   4 netsw  users    512 Jul 30 19:25 Dicts/
    +drwxrwxr-x  10 netsw  users    512 Jul  9 01:54 Graphic/
    +drwxrwxr-x   5 netsw  users    512 Jul  9 01:58 Hackers/
    +drwxrwxr-x   8 netsw  users    512 Jul  9 03:19 InfoSys/
    +drwxrwxr-x   3 netsw  users    512 Jul  9 03:21 Math/
    +drwxrwxr-x   3 netsw  users    512 Jul  9 03:24 Misc/
    +drwxrwxr-x   9 netsw  users    512 Aug  1 16:33 Network/
    +drwxrwxr-x   2 netsw  users    512 Jul  9 05:53 Office/
    +drwxrwxr-x   7 netsw  users    512 Jul  9 09:24 SoftEng/
    +drwxrwxr-x   7 netsw  users    512 Jul  9 12:17 System/
    +drwxrwxr-x  12 netsw  users    512 Aug  3 20:15 Typesetting/
    +drwxrwxr-x  10 netsw  users    512 Jul  9 14:08 X11/
    +

    + +In July 1996 I decided to make this archive public to the world via a +nice Web interface. "Nice" means that I wanted to +offer an interface where you can browse directly through the archive hierarchy. +And "nice" means that I didn't wanted to change anything inside this hierarchy +- not even by putting some CGI scripts at the top of it. Why? Because the +above structure should be later accessible via FTP as well, and I didn't +want any Web or CGI stuff to be there. + +

    +

    Solution: +
    +The solution has two parts: The first is a set of CGI scripts which create all +the pages at all directory levels on-the-fly. I put them under +/e/netsw/.www/ as follows: + +

    +-rw-r--r--   1 netsw  users    1318 Aug  1 18:10 .wwwacl
    +drwxr-xr-x  18 netsw  users     512 Aug  5 15:51 DATA/
    +-rw-rw-rw-   1 netsw  users  372982 Aug  5 16:35 LOGFILE
    +-rw-r--r--   1 netsw  users     659 Aug  4 09:27 TODO
    +-rw-r--r--   1 netsw  users    5697 Aug  1 18:01 netsw-about.html
    +-rwxr-xr-x   1 netsw  users     579 Aug  2 10:33 netsw-access.pl
    +-rwxr-xr-x   1 netsw  users    1532 Aug  1 17:35 netsw-changes.cgi
    +-rwxr-xr-x   1 netsw  users    2866 Aug  5 14:49 netsw-home.cgi
    +drwxr-xr-x   2 netsw  users     512 Jul  8 23:47 netsw-img/
    +-rwxr-xr-x   1 netsw  users   24050 Aug  5 15:49 netsw-lsdir.cgi
    +-rwxr-xr-x   1 netsw  users    1589 Aug  3 18:43 netsw-search.cgi
    +-rwxr-xr-x   1 netsw  users    1885 Aug  1 17:41 netsw-tree.cgi
    +-rw-r--r--   1 netsw  users     234 Jul 30 16:35 netsw-unlimit.lst
    +

    + +The DATA/ subdirectory holds the above directory structure, i.e. the +real net.sw stuff and gets automatically updated via +rdist from time to time. + +The second part of the problem remains: how to link these two structures +together into one smooth-looking URL tree? We want to hide the DATA/ +directory from the user while running the appropriate CGI scripts for the +various URLs. + +Here is the solution: first I put the following into the per-directory +configuration file in the Document Root of the server to rewrite the announced +URL /net.sw/ to the internal path /e/netsw: + +

    +RewriteRule  ^net.sw$       net.sw/        [R]
    +RewriteRule  ^net.sw/(.*)$  e/netsw/$1
    +
    + +

    +The first rule is for requests which miss the trailing slash! The second rule +does the real thing. And then comes the killer configuration which stays in +the per-directory config file /e/netsw/.www/.wwwacl: + +

    +Options       ExecCGI FollowSymLinks Includes MultiViews 
    +
    +RewriteEngine on
    +
    +#  we are reached via /net.sw/ prefix
    +RewriteBase   /net.sw/
    +
    +#  first we rewrite the root dir to 
    +#  the handling cgi script
    +RewriteRule   ^$                       netsw-home.cgi     [L]
    +RewriteRule   ^index\.html$            netsw-home.cgi     [L]
    +
    +#  strip out the subdirs when
    +#  the browser requests us from perdir pages
    +RewriteRule   ^.+/(netsw-[^/]+/.+)$    $1                 [L]
    +
    +#  and now break the rewriting for local files
    +RewriteRule   ^netsw-home\.cgi.*       -                  [L]
    +RewriteRule   ^netsw-changes\.cgi.*    -                  [L]
    +RewriteRule   ^netsw-search\.cgi.*     -                  [L]
    +RewriteRule   ^netsw-tree\.cgi$        -                  [L]
    +RewriteRule   ^netsw-about\.html$      -                  [L]
    +RewriteRule   ^netsw-img/.*$           -                  [L]
    +
    +#  anything else is a subdir which gets handled
    +#  by another cgi script
    +RewriteRule   !^netsw-lsdir\.cgi.*     -                  [C]
    +RewriteRule   (.*)                     netsw-lsdir.cgi/$1
    +
    + +

    +Some hints for interpretation: +

      +
    1. Notice the L (last) flag and no substitution field ('-') in the + forth part +
    2. Notice the ! (not) character and the C (chain) flag + at the first rule in the last part +
    3. Notice the catch-all pattern in the last rule +
    + +
    + +

    +

    NCSA imagemap to Apache mod_imap

    +

    + +

    +
    Description: +
    +When switching from the NCSA webserver to the more modern Apache webserver a +lot of people want a smooth transition. So they want pages which use their old +NCSA imagemap program to work under Apache with the modern +mod_imap. The problem is that there are a lot of +hyperlinks around which reference the imagemap program via +/cgi-bin/imagemap/path/to/page.map. Under Apache this +has to read just /path/to/page.map. + +

    +

    Solution: +
    +We use a global rule to remove the prefix on-the-fly for all requests: + +

    +RewriteEngine  on
    +RewriteRule    ^/cgi-bin/imagemap(.*)  $1  [PT]
    +
    + +

    + +

    +

    Search pages in more than one directory

    +

    + +

    +
    Description: +
    +Sometimes it is neccessary to let the webserver search for pages in more than +one directory. Here MultiViews or other techniques cannot help. + +

    +

    Solution: +
    +We program a explicit ruleset which searches for the files in the directories. + +

    +RewriteEngine on
    +
    +#   first try to find it in custom/...
    +#   ...and if found stop and be happy:
    +RewriteCond         /your/docroot/dir1/%{REQUEST_FILENAME}  -f
    +RewriteRule  ^(.+)  /your/docroot/dir1/$1  [L]
    +
    +#   second try to find it in pub/...
    +#   ...and if found stop and be happy:
    +RewriteCond         /your/docroot/dir2/%{REQUEST_FILENAME}  -f
    +RewriteRule  ^(.+)  /your/docroot/dir2/$1  [L]
    +
    +#   else go on for other Alias or ScriptAlias directives,
    +#   etc.
    +RewriteRule   ^(.+)  -  [PT]
    +
    + +

    + +

    +

    Set Environment Variables According To URL Parts

    +

    + +

    +
    Description: +
    +Perhaps you want to keep status information between requests and use the URL +to encode it. But you don't want to use a CGI wrapper for all pages just to +strip out this information. + +

    +

    Solution: +
    +We use a rewrite rule to strip out the status information and remember it via +an environment variable which can be later dereferenced from within XSSI or +CGI. This way a URL /foo/S=java/bar/ gets translated to +/foo/bar/ and the environment variable named STATUS is set +to the value "java". + +

    +RewriteEngine on
    +RewriteRule   ^(.*)/S=([^/]+)/(.*)    $1/$3 [E=STATUS:$2]
    +
    + +

    + +

    +

    Virtual User Hosts

    +

    + +

    +
    Description: +
    +Assume that you want to provide www.username.host.domain.com +for the homepage of username via just DNS A records to the same machine and +without any virtualhosts on this machine. + +

    +

    Solution: +
    +For HTTP/1.0 requests there is no solution, but for HTTP/1.1 requests which +contain a Host: HTTP header we can use the following ruleset to rewrite +http://www.username.host.com/anypath internally to +/home/username/anypath: + +

    +RewriteEngine on
    +RewriteCond   %{HTTP_HOST}                 ^www\.[^.]+\.host\.com$
    +RewriteRule   ^(.+)                        %{HTTP_HOST}$1          [C]
    +RewriteRule   ^www\.([^.]+)\.host\.com(.*) /home/$1$2
    +
    + +

    + +

    +

    Redirect Homedirs For Foreigners

    +

    + +

    +
    Description: +
    +We want to redirect homedir URLs to another webserver +www.somewhere.com when the requesting user does not stay in the local +domain ourdomain.com. This is sometimes used in virtual host +contexts. + +

    +

    Solution: +
    +Just a rewrite condition: + +

    +RewriteEngine on
    +RewriteCond   %{REMOTE_HOST}  !^.+\.ourdomain\.com$
    +RewriteRule   ^(/~.+)         http://www.somewhere.com/$1 [R,L]
    +
    + +

    + +

    +

    Redirect Failing URLs To Other Webserver

    +

    + +

    +
    Description: +
    +A typical FAQ about URL rewriting is how to redirect failing requests on +webserver A to webserver B. Usually this is done via ErrorDocument +CGI-scripts in Perl, but there is also a mod_rewrite solution. But notice that +this is less performant than using a ErrorDocument CGI-script! + +

    +

    Solution: +
    +The first solution has the best performance but less flexibility and is less +error safe: + +

    +RewriteEngine on
    +RewriteCond   /your/docroot/%{REQUEST_FILENAME} !-f
    +RewriteRule   ^(.+)                             http://webserverB.dom/$1
    +
    + +

    +The problem here is that this will only work for pages inside the +DocumentRoot. While you can add more Conditions (for instance to also handle +homedirs, etc.) there is better variant: + +

    +RewriteEngine on
    +RewriteCond   %{REQUEST_URI} !-U
    +RewriteRule   ^(.+)          http://webserverB.dom/$1
    +
    + +

    +This uses the URL look-ahead feature of mod_rewrite. The result is that this +will work for all types of URLs and is a safe way. But it does a performance +impact on the webserver, because for every request there is one more internal +subrequest. So, if your webserver runs on a powerful CPU, use this one. If it +is a slow machine, use the first approach or better a ErrorDocument +CGI-script. + +

    + +

    +

    Extended Redirection

    +

    + +

    +
    Description: +
    +Sometimes we need more control (concerning the character escaping mechanism) +of URLs on redirects. Usually the Apache kernels URL escape function also +escapes anchors, i.e. URLs like "url#anchor". You cannot use this directly on +redirects with mod_rewrite because the uri_escape() function of Apache would +also escape the hash character. How can we redirect to such a URL? + +

    +

    Solution: +
    +We have to use a kludge by the use of a NPH-CGI script which does the redirect +itself. Because here no escaping is done (NPH=non-parseable headers). First +we introduce a new URL scheme xredirect: by the following per-server +config-line (should be one of the last rewrite rules): + +

    +RewriteRule ^xredirect:(.+) /path/to/nph-xredirect.cgi/$1 \
    +            [T=application/x-httpd-cgi,L]
    +
    + +

    +This forces all URLs prefixed with xredirect: to be piped through the +nph-xredirect.cgi program. And this program just looks like: + +

    +
    +#!/path/to/perl
    +##
    +##  nph-xredirect.cgi -- NPH/CGI script for extended redirects
    +##  Copyright (c) 1997 Ralf S. Engelschall, All Rights Reserved. 
    +##
    +
    +$| = 1;
    +$url = $ENV{'PATH_INFO'};
    +
    +print "HTTP/1.0 302 Moved Temporarily\n";
    +print "Server: $ENV{'SERVER_SOFTWARE'}\n";
    +print "Location: $url\n";
    +print "Content-type: text/html\n";
    +print "\n";
    +print "<html>\n";
    +print "<head>\n";
    +print "<title>302 Moved Temporarily (EXTENDED)</title>\n";
    +print "</head>\n";
    +print "<body>\n";
    +print "<h1>Moved Temporarily (EXTENDED)</h1>\n";
    +print "The document has moved <a HREF=\"$url\">here</a>.<p>\n";
    +print "</body>\n";
    +print "</html>\n";
    +
    +##EOF##
    +
    +
    + +

    +This provides you with the functionality to do redirects to all URL schemes, +i.e. including the one which are not directly accepted by mod_rewrite. For +instance you can now also redirect to news:newsgroup via + +

    +RewriteRule ^anyurl  xredirect:news:newsgroup
    +
    + +

    +Notice: You have not to put [R] or [R,L] to the above rule because the +xredirect: need to be expanded later by our special "pipe through" +rule above. + +

    + +

    +

    Archive Access Multiplexer

    +

    + +

    +
    Description: +
    +Do you know the great CPAN (Comprehensive Perl Archive Network) under http://www.perl.com/CPAN? This does a +redirect to one of several FTP servers around the world which carry a CPAN +mirror and is approximately near the location of the requesting client. +Actually this can be called an FTP access multiplexing service. While CPAN +runs via CGI scripts, how can a similar approach implemented via mod_rewrite? + +

    +

    Solution: +
    +First we notice that from version 3.0.0 mod_rewrite can also use the "ftp:" +scheme on redirects. And second, the location approximation can be done by a +rewritemap over the top-level domain of the client. With a tricky chained +ruleset we can use this top-level domain as a key to our multiplexing map. + +

    +RewriteEngine on
    +RewriteMap    multiplex                txt:/path/to/map.cxan
    +RewriteRule   ^/CxAN/(.*)              %{REMOTE_HOST}::$1                 [C]
    +RewriteRule   ^.+\.([a-zA-Z]+)::(.*)$  ${multiplex:$1|ftp.default.dom}$2  [R,L]
    +
    + +

    +##
    +##  map.cxan -- Multiplexing Map for CxAN
    +##
    +
    +de        ftp://ftp.cxan.de/CxAN/
    +uk        ftp://ftp.cxan.uk/CxAN/
    +com       ftp://ftp.cxan.com/CxAN/
    + :
    +##EOF##
    +
    + +

    + +

    +

    Time-Dependend Rewriting

    +

    + +

    +
    Description: +
    +When tricks like time-dependend content should happen a lot of webmasters +still use CGI scripts which do for instance redirects to specialized pages. +How can it be done via mod_rewrite? + +

    +

    Solution: +
    +There are a lot of variables named TIME_xxx for rewrite conditions. +In conjunction with the special lexicographic comparison patterns <STRING, +>STRING and =STRING we can do time-dependend redirects: + +

    +RewriteEngine on
    +RewriteCond   %{TIME_HOUR}%{TIME_MIN} >0700
    +RewriteCond   %{TIME_HOUR}%{TIME_MIN} <1900
    +RewriteRule   ^foo\.html$             foo.day.html
    +RewriteRule   ^foo\.html$             foo.night.html
    +
    + +

    +This provides the content of foo.day.html under the URL +foo.html from 07:00-19:00 and at the remaining time the contents of +foo.night.html. Just a nice feature for a homepage... + +

    + +

    +

    Backward Compatibility for YYYY to XXXX migration

    +

    + +

    +
    Description: +
    +How can we make URLs backward compatible (still existing virtually) after +migrating document.YYYY to document.XXXX, e.g. after translating a bunch of +.html files to .phtml? + +

    +

    Solution: +
    +We just rewrite the name to its basename and test for existence of the new +extension. If it exists, we take that name, else we rewrite the URL to its +original state. + +

    +#   backward compatibility ruleset for 
    +#   rewriting document.html to document.phtml
    +#   when and only when document.phtml exists
    +#   but no longer document.html
    +RewriteEngine on
    +RewriteBase   /~quux/
    +#   parse out basename, but remember the fact
    +RewriteRule   ^(.*)\.html$              $1      [C,E=WasHTML:yes]
    +#   rewrite to document.phtml if exists
    +RewriteCond   %{REQUEST_FILENAME}.phtml -f
    +RewriteRule   ^(.*)$ $1.phtml                   [S=1]
    +#   else reverse the previous basename cutout
    +RewriteCond   %{ENV:WasHTML}            ^yes$
    +RewriteRule   ^(.*)$ $1.html
    +
    + +

    + +

    Content Handling

    + +

    +

    From Old to New (intern)

    +

    + +

    +
    Description: +
    +Assume we have recently renamed the page bar.html to +foo.html and now want to provide the old URL for backward +compatibility. Actually we want that users of the old URL even not recognize +that the pages was renamed. + +

    +

    Solution: +
    +We rewrite the old URL to the new one internally via the following rule: + +

    +RewriteEngine  on
    +RewriteBase    /~quux/
    +RewriteRule    ^foo\.html$  bar.html
    +
    + +

    + +

    +

    From Old to New (extern)

    +

    + +

    +
    Description: +
    +Assume again that we have recently renamed the page bar.html to +foo.html and now want to provide the old URL for backward +compatibility. But this time we want that the users of the old URL get hinted +to the new one, i.e. their browsers Location field should change, too. + +

    +

    Solution: +
    +We force a HTTP redirect to the new URL which leads to a change of the +browsers and thus the users view: + +

    +RewriteEngine  on
    +RewriteBase    /~quux/
    +RewriteRule    ^foo\.html$  bar.html  [R]
    +
    + +

    + +

    +

    Browser Dependend Content

    +

    + +

    +
    Description: +
    +At least for important top-level pages it is sometimes necesarry to provide +the optimum of browser dependend content, i.e. one has to provide a maximum +version for the latest Netscape variants, a minimum version for the Lynx +browsers and a average feature version for all others. + +

    +

    Solution: +
    +We cannot use content negotiation because the browsers do not provide their +type in that form. Instead we have to act on the HTTP header "User-Agent". +The following condig does the following: If the HTTP header "User-Agent" +begins with "Mozilla/3", the page foo.html is rewritten to +foo.NS.html and and the rewriting stops. If the browser is "Lynx" or +"Mozilla" of version 1 or 2 the URL becomes foo.20.html. All other +browsers receive page foo.32.html. This is done by the following +ruleset: + +

    +RewriteCond %{HTTP_USER_AGENT}  ^Mozilla/3.*
    +RewriteRule ^foo\.html$         foo.NS.html          [L]
    +
    +RewriteCond %{HTTP_USER_AGENT}  ^Lynx/.*         [OR]
    +RewriteCond %{HTTP_USER_AGENT}  ^Mozilla/[12].*
    +RewriteRule ^foo\.html$         foo.20.html          [L]
    +
    +RewriteRule ^foo\.html$         foo.32.html          [L]
    +
    + +

    + +

    +

    Dynamic Mirror

    +

    + +

    +
    Description: +
    +Assume there are nice webpages on remote hosts we want to bring into our +namespace. For FTP servers we would use the mirror program which +actually maintains an explicit up-to-date copy of the remote data on the local +machine. For a webserver we could use the program webcopy which acts +similar via HTTP. But both techniques have one major drawback: The local copy +is always just as up-to-date as often we run the program. It would be much +better if the mirror is not a static one we have to establish explicitly. +Instead we want a dynamic mirror with data which gets updated automatically +when there is need (updated data on the remote host). + +

    +

    Solution: +
    +To provide this feature we map the remote webpage or even the complete remote +webarea to our namespace by the use of the Proxy Throughput feature +(flag [P]): + +

    +RewriteEngine  on
    +RewriteBase    /~quux/
    +RewriteRule    ^hotsheet/(.*)$  http://www.tstimpreso.com/hotsheet/$1  [P]
    +
    + +

    +RewriteEngine  on
    +RewriteBase    /~quux/
    +RewriteRule    ^usa-news\.html$   http://www.quux-corp.com/news/index.html  [P]
    +
    + +

    + +

    +

    Reverse Dynamic Mirror

    +

    + +

    +
    Description: +
    +... + +

    +

    Solution: +
    + +

    +RewriteEngine on
    +RewriteCond   /mirror/of/remotesite/$1           -U 
    +RewriteRule   ^http://www\.remotesite\.com/(.*)$ /mirror/of/remotesite/$1
    +
    + +

    + +

    +

    Retrieve Missing Data from Intranet

    +

    + +

    +
    Description: +
    +This is a tricky way of virtually running a corporates (external) Internet +webserver (www.quux-corp.dom), while actually keeping and maintaining +its data on a (internal) Intranet webserver +(www2.quux-corp.dom) which is protected by a firewall. The +trick is that on the external webserver we retrieve the requested data +on-the-fly from the internal one. + +

    +

    Solution: +
    +First, we have to make sure that our firewall still protects the internal +webserver and that only the external webserver is allowed to retrieve data +from it. For a packet-filtering firewall we could for instance configure a +firewall ruleset like the following: + +

    +ALLOW Host www.quux-corp.dom Port >1024 --> Host www2.quux-corp.dom Port 80  
    +DENY  Host *                 Port *     --> Host www2.quux-corp.dom Port 80
    +
    + +

    +Just adjust it to your actual configuration syntax. Now we can establish the +mod_rewrite rules which request the missing data in the background through the +proxy throughput feature: + +

    +RewriteRule ^/~([^/]+)/?(.*)          /home/$1/.www/$2
    +RewriteCond %{REQUEST_FILENAME}       !-f
    +RewriteCond %{REQUEST_FILENAME}       !-d
    +RewriteRule ^/home/([^/]+)/.www/?(.*) http://www2.quux-corp.dom/~$1/pub/$2 [P]
    +
    + +

    + +

    +

    Load Balancing

    +

    + +

    +
    Description: +
    +Suppose we want to load balance the traffic to www.foo.com over +www[0-5].foo.com (a total of 6 servers). How can this be done? + +

    +

    Solution: +
    +There are a lot of possible solutions for this problem. We will discuss first +a commonly known DNS-based variant and then the special one with mod_rewrite: + +
      +
    1. DNS Round-Robin + +

      +The simplest method for load-balancing is to use the DNS round-robin feature +of BIND. Here you just configure www[0-9].foo.com as usual in your +DNS with A(address) records, e.g. + +

      +www0   IN  A       1.2.3.1
      +www1   IN  A       1.2.3.2
      +www2   IN  A       1.2.3.3
      +www3   IN  A       1.2.3.4
      +www4   IN  A       1.2.3.5
      +www5   IN  A       1.2.3.6
      +
      + +

      +Then you additionally add the following entry: + +

      +www    IN  CNAME   www0.foo.com.
      +       IN  CNAME   www1.foo.com.
      +       IN  CNAME   www2.foo.com.
      +       IN  CNAME   www3.foo.com.
      +       IN  CNAME   www4.foo.com.
      +       IN  CNAME   www5.foo.com.
      +       IN  CNAME   www6.foo.com.
      +
      + +

      +Notice that this seems wrong, but is actually an intended feature of BIND and +can be used in this way. However, now when www.foo.com gets resolved, +BIND gives out www0-www6 - but in a slightly permutated/rotated order +every time. This way the clients are spread over the various servers. + +But notice that this not a perfect load balancing scheme, because DNS resolve +information gets cached by the other nameservers on the net, so once a client +has resolved www.foo.com to a particular wwwN.foo.com, all +subsequent requests also go to this particular name wwwN.foo.com. But +the final result is ok, because the total sum of the requests are really +spread over the various webservers. + +

      +

    2. DNS Load-Balancing + +

      +A sophisticated DNS-based method for load-balancing is to use the program +lbnamed which can be found at http://www.stanford.edu/~schemers/docs/lbnamed/lbnamed.html. +It is a Perl 5 program in conjunction with auxilliary tools which provides a +real load-balancing for DNS. + +

      +

    3. Proxy Throughput Round-Robin + +

      +In this variant we use mod_rewrite and its proxy throughput feature. First we +dedicate www0.foo.com to be actually www.foo.com by using a +single + +

      +www    IN  CNAME   www0.foo.com.
      +
      + +

      +entry in the DNS. Then we convert www0.foo.com to a proxy-only +server, i.e. we configure this machine so all arriving URLs are just pushed +through the internal proxy to one of the 5 other servers (www1-www5). +To accomplish this we first establish a ruleset which contacts a load +balancing script lb.pl for all URLs. + +

      +RewriteEngine on
      +RewriteMap    lb      prg:/path/to/lb.pl
      +RewriteRule   ^/(.+)$ ${lb:$1}           [P,L]
      +
      + +

      +Then we write lb.pl: + +

      +#!/path/to/perl
      +##
      +##  lb.pl -- load balancing script
      +##
      +
      +$| = 1;
      +
      +$name   = "www";     # the hostname base
      +$first  = 1;         # the first server (not 0 here, because 0 is myself) 
      +$last   = 5;         # the last server in the round-robin
      +$domain = "foo.dom"; # the domainname
      +
      +$cnt = 0;
      +while (<STDIN>) {
      +    $cnt = (($cnt+1) % ($last+1-$first));
      +    $server = sprintf("%s%d.%s", $name, $cnt+$first, $domain);
      +    print "http://$server/$_";
      +}
      +
      +##EOF##
      +
      + +

      +A last notice: Why is this useful? Seems like www0.foo.com still is +overloaded? The answer is yes, it is overloaded, but with plain proxy +throughput requests, only! All SSI, CGI, ePerl, etc. processing is completely +done on the other machines. This is the essential point. + +

      +

    4. Hardware/TCP Round-Robin + +

      +There is a hardware solution available, too. Cisco has a beast called +LocalDirector which does a load balancing at the TCP/IP level. Actually this +is some sort of a circuit level gateway in front of a webcluster. If you have +enough money and really need a solution with high performance, use this one. + +

    + +
    + +

    +

    Reverse Proxy

    +

    + +

    +
    Description: +
    +... + +

    +

    Solution: +
    + +

    +##
    +##  apache-rproxy.conf -- Apache configuration for Reverse Proxy Usage
    +##
    +
    +#   server type
    +ServerType           standalone
    +Port                 8000
    +MinSpareServers      16
    +StartServers         16
    +MaxSpareServers      16
    +MaxClients           16
    +MaxRequestsPerChild  100
    +
    +#   server operation parameters
    +KeepAlive            on
    +MaxKeepAliveRequests 100
    +KeepAliveTimeout     15
    +Timeout              400
    +IdentityCheck        off
    +HostnameLookups      off
    +
    +#   paths to runtime files
    +PidFile              /path/to/apache-rproxy.pid
    +LockFile             /path/to/apache-rproxy.lock
    +ErrorLog             /path/to/apache-rproxy.elog
    +CustomLog            /path/to/apache-rproxy.dlog "%{%v/%T}t %h -> %{SERVER}e URL: %U"
    +
    +#   unused paths
    +ServerRoot           /tmp
    +DocumentRoot         /tmp
    +CacheRoot            /tmp
    +RewriteLog           /dev/null
    +TransferLog          /dev/null
    +TypesConfig          /dev/null
    +AccessConfig         /dev/null
    +ResourceConfig       /dev/null
    +
    +#   speed up and secure processing
    +<Directory />
    +Options -FollowSymLinks -SymLinksIfOwnerMatch
    +AllowOverwrite None
    +</Directory>
    +
    +#   the status page for monitoring the reverse proxy
    +<Location /rproxy-status>
    +SetHandler server-status
    +</Location>
    +
    +#   enable the URL rewriting engine
    +RewriteEngine        on
    +RewriteLogLevel      0
    +
    +#   define a rewriting map with value-lists where
    +#   mod_rewrite randomly chooses a particular value
    +RewriteMap     server  rnd:/path/to/apache-rproxy.conf-servers
    +
    +#   make sure the status page is handled locally
    +#   and make sure no one uses our proxy except ourself
    +RewriteRule    ^/apache-rproxy-status.*  -  [L]
    +RewriteRule    ^(http|ftp)://.*          -  [F]
    +
    +#   now choose the possible servers for particular URL types
    +RewriteRule    ^/(.*\.(cgi|shtml))$  to://${server:dynamic}/$1  [S=1]
    +RewriteRule    ^/(.*)$               to://${server:static}/$1  
    +
    +#   and delegate the generated URL by passing it 
    +#   through the proxy module
    +RewriteRule    ^to://([^/]+)/(.*)    http://$1/$2   [E=SERVER:$1,P,L]
    +
    +#   and make really sure all other stuff is forbidden 
    +#   when it should survive the above rules...
    +RewriteRule    .*                    -              [F]
    +
    +#   enable the Proxy module without caching
    +ProxyRequests        on
    +NoCache              *
    +
    +#   setup URL reverse mapping for redirect reponses
    +ProxyPassReverse  /  http://www1.foo.dom/
    +ProxyPassReverse  /  http://www2.foo.dom/
    +ProxyPassReverse  /  http://www3.foo.dom/
    +ProxyPassReverse  /  http://www4.foo.dom/
    +ProxyPassReverse  /  http://www5.foo.dom/
    +ProxyPassReverse  /  http://www6.foo.dom/
    +
    + +

    +##
    +##  apache-rproxy.conf-servers -- Apache/mod_rewrite selection table
    +##
    +
    +#   list of backend servers which serve static
    +#   pages (HTML files and Images, etc.)
    +static    www1.foo.dom|www2.foo.dom|www3.foo.dom|www4.foo.dom
    +
    +#   list of backend servers which serve dynamically 
    +#   generated page (CGI programs or mod_perl scripts)
    +dynamic   www5.foo.dom|www6.foo.dom
    +
    + +

    + +

    +

    New MIME-type, New Service

    +

    + +

    +
    Description: +
    +On the net there are a lot of nifty CGI programs. But their usage is usually +boring, so a lot of webmaster don't use them. Even Apache's Action handler +feature for MIME-types is only appropriate when the CGI programs don't need +special URLs (actually PATH_INFO and QUERY_STRINGS) as their input. + +First, let us configure a new file type with extension .scgi +(for secure CGI) which will be processed by the popular cgiwrap +program. The problem here is that for instance we use a Homogeneous URL Layout +(see above) a file inside the user homedirs has the URL +/u/user/foo/bar.scgi. But cgiwrap needs the URL in the form +/~user/foo/bar.scgi/. The following rule solves the problem: + +

    +RewriteRule ^/[uge]/([^/]+)/\.www/(.+)\.scgi(.*) ...
    +... /internal/cgi/user/cgiwrap/~$1/$2.scgi$3  [NS,T=application/x-http-cgi]
    +
    + +

    +Or assume we have some more nifty programs: +wwwlog (which displays the access.log for a URL subtree and +wwwidx (which runs Glimpse on a URL subtree). We have to +provide the URL area to these programs so they know on which area +they have to act on. But usually this ugly, because they are all the +times still requested from that areas, i.e. typically we would run +the swwidx program from within /u/user/foo/ via +hyperlink to + +

    +/internal/cgi/user/swwidx?i=/u/user/foo/
    +

    + +which is ugly. Because we have to hard-code both the location of the +area and the location of the CGI inside the hyperlink. When we have to +reorganise or area, we spend a lot of time changing the various hyperlinks. + +

    +

    Solution: +
    +The solution here is to provide a special new URL format which automatically +leads to the proper CGI invocation. We configure the following: + +

    +RewriteRule   ^/([uge])/([^/]+)(/?.*)/\*  /internal/cgi/user/wwwidx?i=/$1/$2$3/
    +RewriteRule   ^/([uge])/([^/]+)(/?.*):log /internal/cgi/user/wwwlog?f=/$1/$2$3
    +
    + +

    +Now the hyperlink to search at /u/user/foo/ reads only + +

    +HREF="*"
    +

    + +which internally gets automatically transformed to + +

    +/internal/cgi/user/wwwidx?i=/u/user/foo/
    +

    + +The same approach leads to an invocation for the access log CGI +program when the hyperlink :log gets used. + +

    + +

    +

    From Static to Dynamic

    +

    + +

    +
    Description: +
    +How can we transform a static page foo.html into a dynamic variant +foo.cgi in a seemless way, i.e. without notice by the browser/user. + +

    +

    Solution: +
    +We just rewrite the URL to the CGI-script and force the correct MIME-type so +it gets really run as a CGI-script. This way a request to +/~quux/foo.html internally leads to the invokation of +/~quux/foo.cgi. + +

    +RewriteEngine  on
    +RewriteBase    /~quux/
    +RewriteRule    ^foo\.html$  foo.cgi  [T=application/x-httpd-cgi]
    +
    + +

    + +

    +

    On-the-fly Content-Regeneration

    +

    + +

    +
    Description: +
    +Here comes a really esoteric feature: Dynamically generated but statically +served pages, i.e. pages should be delivered as pure static pages (read from +the filesystem and just passed through), but they have to be generated +dynamically by the webserver if missing. This way you can have CGI-generated +pages which are statically served unless one (or a cronjob) removes the static +contents. Then the contents gets refreshed. + +

    +

    Solution: +
    +This is done via the following ruleset: + +

    +RewriteCond %{REQUEST_FILENAME}   !-s
    +RewriteRule ^page\.html$          page.cgi   [T=application/x-httpd-cgi,L]
    +
    + +

    +Here a request to page.html leads to a internal run of a +corresponding page.cgi if page.html is still missing or has +filesize null. The trick here is that page.cgi is a usual CGI script +which (additionally to its STDOUT) writes its output to the file +page.html. Once it was run, the server sends out the data of +page.html. When the webmaster wants to force a refresh the contents, +he just removes page.html (usually done by a cronjob). + +

    + +

    +

    Document With Autorefresh

    +

    + +

    +
    Description: +
    +Wouldn't it be nice while creating a complex webpage if the webbrowser would +automatically refresh the page every time we write a new version from within +our editor? Impossible? + +

    +

    Solution: +
    +No! We just combine the MIME multipart feature, the webserver NPH feature and +the URL manipulation power of mod_rewrite. First, we establish a new URL +feature: Adding just :refresh to any URL causes this to be refreshed +every time it gets updated on the filesystem. + +

    +RewriteRule   ^(/[uge]/[^/]+/?.*):refresh  /internal/cgi/apache/nph-refresh?f=$1
    +
    + +

    +Now when we reference the URL + +

    +/u/foo/bar/page.html:refresh
    +

    + +this leads to the internal invocation of the URL + +

    +/internal/cgi/apache/nph-refresh?f=/u/foo/bar/page.html
    +

    + +The only missing part is the NPH-CGI script. Although one would usually say +"left as an exercise to the reader" ;-) I will provide this, too. + +

    +#!/sw/bin/perl
    +##
    +##  nph-refresh -- NPH/CGI script for auto refreshing pages
    +##  Copyright (c) 1997 Ralf S. Engelschall, All Rights Reserved. 
    +##
    +$| = 1;
    +
    +#   split the QUERY_STRING variable
    +@pairs = split(/&/, $ENV{'QUERY_STRING'});
    +foreach $pair (@pairs) {
    +    ($name, $value) = split(/=/, $pair);
    +    $name =~ tr/A-Z/a-z/;
    +    $name = 'QS_' . $name;
    +    $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
    +    eval "\$$name = \"$value\"";
    +}
    +$QS_s = 1 if ($QS_s eq '');
    +$QS_n = 3600 if ($QS_n eq '');
    +if ($QS_f eq '') {
    +    print "HTTP/1.0 200 OK\n";
    +    print "Content-type: text/html\n\n";
    +    print "&lt;b&gt;ERROR&lt;/b&gt;: No file given\n";
    +    exit(0);
    +}
    +if (! -f $QS_f) {
    +    print "HTTP/1.0 200 OK\n";
    +    print "Content-type: text/html\n\n";
    +    print "&lt;b&gt;ERROR&lt;/b&gt;: File $QS_f not found\n";
    +    exit(0);
    +}
    +
    +sub print_http_headers_multipart_begin {
    +    print "HTTP/1.0 200 OK\n";
    +    $bound = "ThisRandomString12345";
    +    print "Content-type: multipart/x-mixed-replace;boundary=$bound\n";
    +    &print_http_headers_multipart_next;
    +}
    +
    +sub print_http_headers_multipart_next {
    +    print "\n--$bound\n";
    +}
    +
    +sub print_http_headers_multipart_end {
    +    print "\n--$bound--\n";
    +}
    +
    +sub displayhtml {
    +    local($buffer) = @_;
    +    $len = length($buffer);
    +    print "Content-type: text/html\n";
    +    print "Content-length: $len\n\n";
    +    print $buffer;
    +}
    +
    +sub readfile {
    +    local($file) = @_;
    +    local(*FP, $size, $buffer, $bytes);
    +    ($x, $x, $x, $x, $x, $x, $x, $size) = stat($file);
    +    $size = sprintf("%d", $size);
    +    open(FP, "&lt;$file");
    +    $bytes = sysread(FP, $buffer, $size);
    +    close(FP);
    +    return $buffer;
    +}
    +
    +$buffer = &readfile($QS_f);
    +&print_http_headers_multipart_begin;
    +&displayhtml($buffer);
    +
    +sub mystat {
    +    local($file) = $_[0];
    +    local($time);
    +
    +    ($x, $x, $x, $x, $x, $x, $x, $x, $x, $mtime) = stat($file);
    +    return $mtime;
    +}
    +
    +$mtimeL = &mystat($QS_f);
    +$mtime = $mtime;
    +for ($n = 0; $n &lt; $QS_n; $n++) {
    +    while (1) {
    +        $mtime = &mystat($QS_f);
    +        if ($mtime ne $mtimeL) {
    +            $mtimeL = $mtime;
    +            sleep(2);
    +            $buffer = &readfile($QS_f);
    +            &print_http_headers_multipart_next;
    +            &displayhtml($buffer);
    +            sleep(5);
    +            $mtimeL = &mystat($QS_f);
    +            last;
    +        }
    +        sleep($QS_s);
    +    }
    +}
    +
    +&print_http_headers_multipart_end;
    +
    +exit(0);
    +
    +##EOF##
    +
    + +
    + +

    +

    Mass Virtual Hosting

    +

    + +

    +
    Description: +
    +The <VirtualHost> feature of Apache is nice and works great +when you just have a few dozens virtual hosts. But when you are an ISP and +have hundreds of virtual hosts to provide this feature is not the best choice. + +

    +

    Solution: +
    +To provide this feature we map the remote webpage or even the complete remote +webarea to our namespace by the use of the Proxy Throughput feature +(flag [P]): + +

    +##
    +##  vhost.map 
    +## 
    +www.vhost1.dom:80  /path/to/docroot/vhost1
    +www.vhost2.dom:80  /path/to/docroot/vhost2
    +     :
    +www.vhostN.dom:80  /path/to/docroot/vhostN
    +
    + +

    +##
    +##  httpd.conf
    +##
    +    :
    +#   use the canonical hostname on redirects, etc.
    +UseCanonicalName on
    +
    +    :
    +#   add the virtual host in front of the CLF-format
    +CustomLog  /path/to/access_log  "%{VHOST}e %h %l %u %t \"%r\" %>s %b"
    +    :
    +
    +#   enable the rewriting engine in the main server
    +RewriteEngine on
    +
    +#   define two maps: one for fixing the URL and one which defines
    +#   the available virtual hosts with their corresponding
    +#   DocumentRoot.
    +RewriteMap    lowercase    int:tolower
    +RewriteMap    vhost        txt:/path/to/vhost.map
    +
    +#   Now do the actual virtual host mapping
    +#   via a huge and complicated single rule:
    +#
    +#   1. make sure we don't map for common locations
    +RewriteCond   %{REQUEST_URL}  !^/commonurl1/.*
    +RewriteCond   %{REQUEST_URL}  !^/commonurl2/.*
    +    :
    +RewriteCond   %{REQUEST_URL}  !^/commonurlN/.*
    +#
    +#   2. make sure we have a Host header, because
    +#      currently our approach only supports 
    +#      virtual hosting through this header
    +RewriteCond   %{HTTP_HOST}  !^$
    +#
    +#   3. lowercase the hostname
    +RewriteCond   ${lowercase:%{HTTP_HOST}|NONE}  ^(.+)$
    +#
    +#   4. lookup this hostname in vhost.map and
    +#      remember it only when it is a path 
    +#      (and not "NONE" from above)
    +RewriteCond   ${vhost:%1}  ^(/.*)$
    +#
    +#   5. finally we can map the URL to its docroot location 
    +#      and remember the virtual host for logging puposes
    +RewriteRule   ^/(.*)$   %1/$1  [E=VHOST:${lowercase:%{HTTP_HOST}}]
    +    : 
    +
    + +

    + +

    Access Restriction

    + +

    +

    Blocking of Robots

    +

    + +

    +
    Description: +
    +How can we block a really annoying robot from retrieving pages of a specific +webarea? A /robots.txt file containing entries of the "Robot +Exclusion Protocol" is typically not enough to get rid of such a robot. + +

    +

    Solution: +
    +We use a ruleset which forbids the URLs of the webarea +/~quux/foo/arc/ (perhaps a very deep directory indexed area where the +robot traversal would create big server load). We have to make sure that we +forbid access only to the particular robot, i.e. just forbidding the host +where the robot runs is not enough. This would block users from this host, +too. We accomplish this by also matching the User-Agent HTTP header +information. + +

    +RewriteCond %{HTTP_USER_AGENT}   ^NameOfBadRobot.*      
    +RewriteCond %{REMOTE_ADDR}       ^123\.45\.67\.[8-9]$
    +RewriteRule ^/~quux/foo/arc/.+   -   [F]
    +
    + +

    + +

    +

    Blocked Inline-Images

    +

    + +

    +
    Description: +
    +Assume we have under http://www.quux-corp.de/~quux/ some pages with inlined +GIF graphics. These graphics are nice, so others directly incorporate them via +hyperlinks to their pages. We don't like this practice because it adds useless +traffic to our server. + +

    +

    Solution: +
    +While we cannot 100% protect the images from inclusion, we +can at least restrict the cases where the browser sends +a HTTP Referer header. + +

    +RewriteCond %{HTTP_REFERER} !^$                                  
    +RewriteCond %{HTTP_REFERER} !^http://www.quux-corp.de/~quux/.*$ [NC]
    +RewriteRule .*\.gif$        -                                    [F]
    +
    + +

    +RewriteCond %{HTTP_REFERER}         !^$                                  
    +RewriteCond %{HTTP_REFERER}         !.*/foo-with-gif\.html$
    +RewriteRule ^inlined-in-foo\.gif$   -                        [F]
    +
    + +

    + +

    +

    Host Deny

    +

    + +

    +
    Description: +
    +How can we forbid a list of externally configured hosts from using our server? + +

    +

    Solution: +
    + +For Apache >= 1.3b6: + +

    +RewriteEngine on
    +RewriteMap    hosts-deny  txt:/path/to/hosts.deny
    +RewriteCond   ${hosts-deny:%{REMOTE_HOST}|NOT-FOUND} !=NOT-FOUND [OR]
    +RewriteCond   ${hosts-deny:%{REMOTE_ADDR}|NOT-FOUND} !=NOT-FOUND
    +RewriteRule   ^/.*  -  [F]
    +

    + +For Apache <= 1.3b6: + +

    +RewriteEngine on
    +RewriteMap    hosts-deny  txt:/path/to/hosts.deny
    +RewriteRule   ^/(.*)$ ${hosts-deny:%{REMOTE_HOST}|NOT-FOUND}/$1
    +RewriteRule   !^NOT-FOUND/.* - [F]
    +RewriteRule   ^NOT-FOUND/(.*)$ ${hosts-deny:%{REMOTE_ADDR}|NOT-FOUND}/$1 
    +RewriteRule   !^NOT-FOUND/.* - [F]
    +RewriteRule   ^NOT-FOUND/(.*)$ /$1
    +
    + +

    +##
    +##  hosts.deny 
    +##
    +##  ATTENTION! This is a map, not a list, even when we treat it as such.
    +##             mod_rewrite parses it for key/value pairs, so at least a
    +##             dummy value "-" must be present for each entry.
    +##
    +
    +193.102.180.41 -
    +bsdti1.sdm.de  -
    +192.76.162.40  -
    +
    + +

    + +

    +

    Proxy Deny

    +

    + +

    +
    Description: +
    +How can we forbid a certain host or even a user of a special host from using +the Apache proxy? + +

    +

    Solution: +
    +We first have to make sure mod_rewrite is below(!) mod_proxy in the +Configuration file when compiling the Apache webserver. This way it +gets called _before_ mod_proxy. Then we configure the following for a +host-dependend deny... + +

    +RewriteCond %{REMOTE_HOST} ^badhost\.mydomain\.com$ 
    +RewriteRule !^http://[^/.]\.mydomain.com.*  - [F]
    +
    + +

    ...and this one for a user@host-dependend deny: + +

    +RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST}  ^badguy@badhost\.mydomain\.com$
    +RewriteRule !^http://[^/.]\.mydomain.com.*  - [F]
    +
    + +

    + +

    +

    Special Authentication Variant

    +

    + +

    +
    Description: +
    +Sometimes a very special authentication is needed, for instance a +authentication which checks for a set of explicitly configured users. Only +these should receive access and without explicit prompting (which would occur +when using the Basic Auth via mod_access). + +

    +

    Solution: +
    +We use a list of rewrite conditions to exclude all except our friends: + +

    +RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} !^friend1@client1.quux-corp\.com$ 
    +RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} !^friend2@client2.quux-corp\.com$ 
    +RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} !^friend3@client3.quux-corp\.com$ 
    +RewriteRule ^/~quux/only-for-friends/      -                                 [F]
    +
    + +

    + +

    +

    Referer-based Deflector

    +

    + +

    +
    Description: +
    +How can we program a flexible URL Deflector which acts on the "Referer" HTTP +header and can be configured with as many referring pages as we like? + +

    +

    Solution: +
    +Use the following really tricky ruleset... + +

    +RewriteMap  deflector txt:/path/to/deflector.map
    +
    +RewriteCond %{HTTP_REFERER} !=""
    +RewriteCond ${deflector:%{HTTP_REFERER}} ^-$
    +RewriteRule ^.* %{HTTP_REFERER} [R,L]
    +
    +RewriteCond %{HTTP_REFERER} !=""
    +RewriteCond ${deflector:%{HTTP_REFERER}|NOT-FOUND} !=NOT-FOUND
    +RewriteRule ^.* ${deflector:%{HTTP_REFERER}} [R,L]
    +
    + +

    ... +in conjunction with a corresponding rewrite map: + +

    +##
    +##  deflector.map
    +##
    +
    +http://www.badguys.com/bad/index.html    -
    +http://www.badguys.com/bad/index2.html   -
    +http://www.badguys.com/bad/index3.html   http://somewhere.com/
    +
    + +

    +This automatically redirects the request back to the referring page (when "-" +is used as the value in the map) or to a specific URL (when an URL is +specified in the map as the second argument). + +

    + +

    Other

    + +

    +

    External Rewriting Engine

    +

    + +

    +
    Description: +
    +A FAQ: How can we solve the FOO/BAR/QUUX/etc. problem? There seems no solution +by the use of mod_rewrite... + +

    +

    Solution: +
    +Use an external rewrite map, i.e. a program which acts like a rewrite map. It +is run once on startup of Apache receives the requested URLs on STDIN and has +to put the resulting (usually rewritten) URL on STDOUT (same order!). + +

    +RewriteEngine on
    +RewriteMap    quux-map       prg:/path/to/map.quux.pl
    +RewriteRule   ^/~quux/(.*)$  /~quux/${quux-map:$1}
    +
    + +

    +#!/path/to/perl
    +
    +#   disable buffered I/O which would lead 
    +#   to deadloops for the Apache server
    +$| = 1;
    +
    +#   read URLs one per line from stdin and
    +#   generate substitution URL on stdout
    +while (<>) {
    +    s|^foo/|bar/|;
    +    print $_;
    +}
    +
    + +

    +This is a demonstration-only example and just rewrites all URLs +/~quux/foo/... to /~quux/bar/.... Actually you can program +whatever you like. But notice that while such maps can be used also by +an average user, only the system administrator can define it. + +

    + + +
    + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/security_tips.html b/APACHE_1_3_12/htdocs/manual/misc/security_tips.html new file mode 100644 index 0000000000..d0961d9cf9 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/security_tips.html @@ -0,0 +1,231 @@ + + + +Apache HTTP Server: Security Tips + + + + + +

    Security Tips for Server Configuration

    + +
    + +

    Some hints and tips on security issues in setting up a web server. Some of +the suggestions will be general, others specific to Apache. + +


    + +

    Permissions on ServerRoot Directories

    +

    In typical operation, Apache is started by the root +user, and it switches to the user defined by the User directive to serve hits. +As is the case with any command that root executes, you must take care +that it is protected from modification by non-root users. Not only +must the files themselves be writeable only by root, but so must the +directories, and parents of all directories. For example, if you +choose to place ServerRoot in /usr/local/apache then it is +suggested that you create that directory as root, with commands +like these: + +

    +    mkdir /usr/local/apache
    +    cd /usr/local/apache
    +    mkdir bin conf logs
    +    chown 0 . bin conf logs
    +    chgrp 0 . bin conf logs
    +    chmod 755 . bin conf logs
    +
    + +It is assumed that /, /usr, and /usr/local are only modifiable by root. +When you install the httpd executable, you should ensure that it is +similarly protected: + +
    +    cp httpd /usr/local/apache/bin
    +    chown 0 /usr/local/apache/bin/httpd
    +    chgrp 0 /usr/local/apache/bin/httpd
    +    chmod 511 /usr/local/apache/bin/httpd
    +
    + +

    You can create an htdocs subdirectory which is modifiable by other +users -- since root never executes any files out of there, and shouldn't +be creating files in there. + +

    If you allow non-root users to modify any files that root either +executes or writes on then you open your system to root compromises. +For example, someone could replace the httpd binary so that the next +time you start it, it will execute some arbitrary code. If the logs +directory is writeable (by a non-root user), someone +could replace a log file with a symlink to some other system file, +and then root might overwrite that file with arbitrary data. If the +log files themselves are writeable (by a non-root user), then someone +may be able to overwrite the log itself with bogus data. +

    +


    +

    Server Side Includes

    +

    Server side includes (SSI) can be configured so that users can execute +arbitrary programs on the server. That thought alone should send a shiver +down the spine of any sys-admin.

    + +One solution is to disable that part of SSI. To do that you use the +IncludesNOEXEC option to the Options +directive.

    + +


    + +

    Non Script Aliased CGI

    +

    Allowing users to execute CGI scripts in any directory +should only +be considered if; +

      +
    1. You trust your users not to write scripts which will deliberately or +accidentally expose your system to an attack. +
    2. You consider security at your site to be so feeble in other areas, as to +make one more potential hole irrelevant. +
    3. You have no users, and nobody ever visits your server. +

    +


    + +

    Script Alias'ed CGI

    +

    Limiting CGI to special directories gives the admin +control over +what goes into those directories. This is inevitably more secure than +non script aliased CGI, but only if users with write access to the +directories are trusted or the admin is willing to test each new CGI +script/program for potential security holes.

    + +Most sites choose this option over the non script aliased CGI approach.

    + +


    +

    CGI in general

    +

    Always remember that you must trust the writers of the CGI script/programs +or your ability to spot potential security holes in CGI, whether they were +deliberate or accidental.

    + +All the CGI scripts will run as the same user, so they have potential to +conflict (accidentally or deliberately) with other scripts e.g. +User A hates User B, so he writes a script to trash User B's CGI +database. One program which can be used to allow scripts to run +as different users is suEXEC which is +included with Apache as of 1.2 and is called from special hooks in +the Apache server code. Another popular way of doing this is with +CGIWrap.

    + +


    + + +

    Stopping users overriding system wide settings...

    +

    To run a really tight ship, you'll want to stop users from setting +up .htaccess files which can override security features +you've configured. Here's one way to do it...

    + +In the server configuration file, put +

    +<Directory />
    +AllowOverride None
    +Options None
    +allow from all
    +</Directory>
    +
    + +Then setup for specific directories

    + +This stops all overrides, Includes and accesses in all directories apart +from those named.

    +


    +

    + Protect server files by default +

    +

    +One aspect of Apache which is occasionally misunderstood is the feature +of default access. That is, unless you take steps to change it, if the +server can find its way to a file through normal URL mapping rules, it +can serve it to clients. +

    +

    +For instance, consider the following example: +

    +
      +
    1. # cd /; ln -s / public_html +
    2. +
    3. Accessing http://localhost/~root/ +
    4. +
    +

    +This would allow clients to walk through the entire filesystem. To work +around this, add the following block to your server's configuration: +

    +
    + <Directory />
    +     Order deny,allow
    +     Deny from all
    + </Directory>
    +
    +

    +This will forbid default access to filesystem locations. Add +appropriate +<Directory> +blocks to allow access only +in those areas you wish. For example, +

    +
    + <Directory /usr/users/*/public_html>
    +     Order deny,allow
    +     Allow from all
    + </Directory>
    + <Directory /usr/local/httpd>
    +     Order deny,allow
    +     Allow from all
    + </Directory>
    +
    +

    +Pay particular attention to the interactions of +<Location> +and +<Directory> +directives; for instance, even if <Directory /> +denies access, a <Location /> directive might +overturn it. +

    +

    +Also be wary of playing games with the +UserDir +directive; setting it to something like "./" +would have the same effect, for root, as the first example above. +If you are using Apache 1.3 or above, we strongly recommend that you +include the following line in your server configuration files: +

    +
    +
    UserDir disabled root +
    +
    + +
    +

    Please send any other useful security tips to The Apache Group +by filling out a +problem report. +If you are confident you have found a security bug in the Apache +source code itself, please let us +know. + +

    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/vif-info.html b/APACHE_1_3_12/htdocs/manual/misc/vif-info.html new file mode 100644 index 0000000000..f9d6d5d043 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/vif-info.html @@ -0,0 +1,399 @@ + + +Configuring Multiple IP Addresses + + + + +

    Configuring Multiple IP Addresses

    + +
    +This material is originally from John Ioannidis (ji@polaris.ctr.columbia.edu)
    +I have condensed it some and applied some corrections for SunOS 4.1.x
    +courtesy of Chuck Smoko (csmoko@relay.nswc.navy.mil).
    +
    +Bob Baggerman  (bob@bizweb.com)
    +12 Jan 94
    +
    +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
    +John Ionnidis writes:
    +
    +This is a topic that comes up once in a while on comp.protocols.tcp-ip
    +and other newsgroups. The question is, how to get a machine with one
    +network interface to respond to more than one IP addresses.
    +
    +I have a solution than might suit you.  For my doctoral work (there's
    +a paper about it in this year's ('91) SIGCOMM, also available for
    +anonymous FTP from cs.columbia.edu:/pub/ji/sigcomm*.ps.Z), I've
    +developed what I call the "Virtual Interface" (VIF). To the networking
    +code, it looks like an interface. It gets ifattach()ed when you open
    +the /dev/vif* device, and then you can ifconfig it as you like. It
    +does not have an if_input procedure; it only has an if_output. Packets
    +that it receives (from higher-level protocols) which have its
    +IP address, it simply loops back (like any well-behaved if driver).
    +Packets that it receives that are destined for some other address, it
    +encapsulates in an encapsulation protocol I call IPIP (IP-within-IP,
    +protocol number IPPROTO_IPIP == 94), and sends it to another machine
    +that groks that encapsulation protocol. This feature you won't need,
    +but here's how to have multiple IP addresses on a machine with a
    +single real interface:
    +
    +Let's say your primary interface's IP address is 198.3.2.1, and you
    +also want it to respond to addresses 198.4.3.2 and 198.5.4.3 (note
    +that these are three distinct class C addresses in three distinct
    +class C nets). Here are the ifconfigs:
    +
    +  ifconfig le0 198.3.2.1 up -trailers   # config primary interface
    +
    +  ifconfig vif0 198.4.3.2 up            # config first virtual interface
    +  route delete net 198.4.3 198.4.3.2    # delete spurious route
    +  route add host 198.4.3.2 198.4.3.2 0  # add route for this i/f
    +
    +  ifconfig vif1 198.5.4.3 up            # config second virtual interface
    +  route delete net 198.5.4 198.5.4.3    # delete spurious route
    +  route add host 198.5.4.3 198.5.4.3 0  # add route for this i/f
    +
    +The route deletes are needed because the ifconfig creates a default
    +route to the interface's network, which can cause problems; all that's
    +needed is the (host) route to the interface's address.
    +
    +Now, get le0's ethernet address (say, 8:0:20:3:2:1), and add the
    +following static ARP entries:
    +
    +  arp -s 198.4.3.2 8:0:20:3:2:1 pub
    +  arp -s 198.5.4.3 8:0:20:3:2:1 pub
    +
    +This will cause any ARP requests for the VIF addresses to be replied
    +with your machine's ethernet address.
    +
    +Now, make sure your default route is to your segment's gateway,
    +through the real interface. Finally, make sure your routers and/or
    +hosts on the same segment as yours know that 198.4.3.2 and 198.5.4.3
    +are on that cable.
    +
    +Here's what you've accomplished.
    +
    +ARP requests for any of your host's addresses will be replied to with
    +the host's ethernet address (the real one, because that's what it is,
    +the virtual ones because of the public static arp entries). Packets
    +reaching your host with any of these addresses will be accepted by the
    +ip_input routine because they match the address of one of the host's
    +interfaces. Packets leaving your host can have any of its addresses
    +(real and virtual).
    +
    +The code for vif follows. To use it, put the stuff in netinet/if_vif.c
    +and netinet/if_vif.h, configure your kernel with the number of
    +virtual interfaces you want using a line like:
    +
    +pseudo-device   vif4            # Virtual IP interface
    +
    +in your configuration file, and the line
    +
    +netinet/if_vif.c        optional vif device-driver
    +
    +in the "files" file. Also, add the appropriate entries in conf.c, so
    +that you can access the if_attach() routine when you open the device:
    +
    +
    +-------------------------- conf.c------------------------------------------
    +
    +add this in the appropriate place in the headers of conf.c:
    +
    +--------------------
    +#include "vif.h"
    +#if NVIF > 0
    +int     vifopen(), vifclose(), vifread(), vifwrite(), vifselect(), vifioctl();
    +#else
    +#define vifopen         nodev
    +#define vifclose        nodev
    +#define vifread         nodev
    +#define vifwrite        nodev
    +#define vifselect       nodev
    +#define vifioctl        nodev
    +#endif
    +--------------------
    +
    +then, way down in the definition for cdevsw[]:
    +
    +--------------------
    +        vifopen,        vifclose,       vifread,        vifwrite,       /*14*/
    +        vifioctl,       nodev,          nodev,          0,
    +        0,      nodev,
    +--------------------
    +
    +Make sure you remember the correct major device number, 14 in this case!
    +
    +---------------------------------------------------------------------------
    +
    +Finally, here's the code. It has the tunneling pieces removed (you
    +need more code to use that anyway), and it comes from a Mach 2.6
    +kernel; it should compile on any Berkeley-derived unix with minor
    +changes (most likely only in the includes).
    +
    +---------------------netinet/if_vif.h--------------------------------------
    +typedef struct
    +{
    +        struct ifnet    vif_if;
    +        struct ifnet    *vif_sif;       /* slave interface */
    +        int             vif_flags;
    +} vif_softc_t;
    +
    +#define VIFMTU  (1024+512)
    +---------------------------------------------------------------------------
    +
    +and
    +
    +---------------------netinet/if_vif.c--------------------------------------
    +/*
    + * Virtual IP interface module.
    + */
    +
    +#include "param.h"
    +#include "../sys/systm.h"
    +#include "../sys/mbuf.h"
    +#include "../sys/socket.h"
    +#include "../sys/errno.h"
    +#include "../sys/ioctl.h"
    +
    +#include "../net/if.h"
    +#include "../net/netisr.h"
    +#include "../net/route.h"
    +
    +#ifdef  INET
    +#include "../netinet/in.h"
    +#include "../netinet/in_systm.h"
    +#include "../netinet/in_var.h"
    +#include "../netinet/ip.h"
    +#endif
    +
    +#include "in_pcb.h"
    +#include "vif.h"
    +
    +typedef struct
    +{
    +        struct ifnet    vif_if;
    +        struct ifnet    *vif_sif;       /* slave interface */
    +        int             vif_flags;
    +} vif_softc_t;
    +
    +#define VIFMTU  (1024+512)
    +
    +vif_softc_t vif_softc[NVIF];
    +
    +int vifs_inited = 0;
    +
    +
    +vifattach()
    +{
    +        register int i;
    +        register struct ifnet *ifp;
    +        int     vifoutput(), vififioctl();
    +
    +        for (i=0; i<NVIF; i++)
    +        {
    +                ifp = &vif_softc[i].vif_if;
    +                ifp->if_name = "vif";
    +                ifp->if_unit = i;
    +                ifp->if_mtu = VIFMTU;
    +                ifp->if_flags = IFF_LOOPBACK | IFF_NOARP;
    +                ifp->if_ioctl = vififioctl;
    +                ifp->if_output = vifoutput;
    +                if_attach(ifp);
    +        }
    +}
    +
    +vifopen(dev, flag)
    +int dev, flag;
    +{
    +        int unit;
    +
    +        if (!vifs_inited)
    +        {
    +                vifattach();
    +                vifs_inited = 1;
    +                printf("vif initialized\n");
    +        }
    +
    +        unit = minor(dev);
    +        if ((unit < 0) || (unit >= NVIF))
    +        {
    +                return ENXIO;
    +        }
    +
    +        return 0;
    +}
    +
    +vifclose(dev, flag)
    +int dev, flag;
    +{
    +        return 0;
    +}
    +
    +vifread()
    +{
    +        return ENXIO;
    +}
    +
    +vifwrite()
    +{
    +        return ENXIO;
    +}
    +
    +vifselect()
    +{
    +        return ENXIO;
    +}
    +
    +vifoutput(ifp, m0, dst)
    +        struct ifnet *ifp;
    +        register struct mbuf *m0;
    +        struct sockaddr *dst;
    +{
    +        int s;
    +        register struct ifqueue *ifq;
    +        struct mbuf *m;
    +        struct sockaddr_in *din;
    +
    +        if (dst->sa_family != AF_INET)
    +        {
    +                printf("%s%d: can't handle af%d\n",
    +                       ifp->if_name, ifp->if_unit,
    +                       dst->sa_family);
    +                m_freem(m0);
    +                return (EAFNOSUPPORT);
    +        }
    +
    +        din = (struct sockaddr_in *)dst;
    +
    +        if (din->sin_addr.s_addr == IA_SIN(ifp->if_addrlist)->sin_addr.s_addr)
    +        {
    +                /* printf("%s%d: looping\n", ifp->if_name, ifp->if_unit); */
    +
    +                /*
    +                 * Place interface pointer before the data
    +                 * for the receiving protocol.
    +                 */
    +                if (m0->m_off <= MMAXOFF &&
    +                    m0->m_off >= MMINOFF + sizeof(struct ifnet *)) {
    +                        m0->m_off -= sizeof(struct ifnet *);
    +                        m0->m_len += sizeof(struct ifnet *);
    +                } else {
    +                        MGET(m, M_DONTWAIT, MT_HEADER);
    +                        if (m == (struct mbuf *)0)
    +                          return (ENOBUFS);
    +                        m->m_off = MMINOFF;
    +                        m->m_len = sizeof(struct ifnet *);
    +                        m->m_next = m0;
    +                        m0 = m;
    +                }
    +                *(mtod(m0, struct ifnet **)) = ifp;
    +                s = splimp();
    +                ifp->if_opackets++;
    +                ifq = &ipintrq;
    +                if (IF_QFULL(ifq)) {
    +                        IF_DROP(ifq);
    +                        m_freem(m0);
    +                        splx(s);
    +                        return (ENOBUFS);
    +                }
    +                IF_ENQUEUE(ifq, m0);
    +                schednetisr(NETISR_IP);
    +                ifp->if_ipackets++;
    +                splx(s);
    +                return (0);
    +        }
    +
    +        return EHOSTUNREACH;
    +}
    +
    +/*
    + * Process an ioctl request.
    + */
    +/* ARGSUSED */
    +vififioctl(ifp, cmd, data)
    +        register struct ifnet *ifp;
    +        int cmd;
    +        caddr_t data;
    +{
    +        int error = 0;
    +
    +        switch (cmd) {
    +
    +        case SIOCSIFADDR:
    +                ifp->if_flags |= IFF_UP;
    +                /*
    +                 * Everything else is done at a higher level.
    +                 */
    +                break;
    +
    +        default:
    +                error = EINVAL;
    +        }
    +        return (error);
    +}
    +
    +vifioctl(dev, cmd, arg, mode)
    +dev_t dev;
    +int cmd;
    +caddr_t arg;
    +int mode;
    +{
    +        int unit;
    +
    +        unit = minor(dev);
    +        if ((unit < 0) || (unit >= NVIF))
    +          return ENXIO;
    +
    +        return EINVAL;
    +}
    +----------------------------------------------------------------------------
    +
    +To use it, compile your kernel, and reboot. Then create the vif
    +device:
    +
    +# mknod /dev/vif c 14 0
    +
    +(or whatever major number it ended up being), and echo something into
    +it:
    +
    +# echo > /dev/vif
    +
    +This will cause the device to be opened, which will if_attach the
    +interfaces. If you feel like playing with the code, you may want to
    +kmem_alloc() the vif_softc structure at open time, and use the minor
    +number of the device to tell it how many interfaces to create.
    +
    +Now you can go ahead and ifconfig etc.
    +
    +I'll be happy to answer minor questions, and hear about success and
    +failure stories, but I cannot help you if you don't already know how
    +to hack kernels.
    +
    +Good luck!
    +
    +/ji
    +
    +In-Real-Life: John "Heldenprogrammer" Ioannidis
    +E-Mail-To: ji@cs.columbia.edu
    +V-Mail-To: +1 212 854 8120
    +P-Mail-To: 450 Computer Science \n Columbia University \n New York, NY 10027
    +
    + +

    + +Note: there is also a commercial-product-turned-freeware +called "Col. Patch" which does this as a loadable kernel module +for SunOS 4.1.3_U1. + +

    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/misc/windoz_keepalive.html b/APACHE_1_3_12/htdocs/manual/misc/windoz_keepalive.html new file mode 100644 index 0000000000..b8a556a804 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/misc/windoz_keepalive.html @@ -0,0 +1,50 @@ + + + +MS Windows Netscape 3.0b4 KeepAlive problem solved + + + + +

    HTTP/1.1 KeepAlive problems with Netscape 3.0

    + +
    +Date: Mon, 1 Jul 1996 16:03:06 -0700 (PDT)
    +From: Alexei Kosut <akosut@organic.com>
    +To: Apache Group
    +Subject: Re: keepalive and windoze
    +
    +Good news and good news (of a sort)..
    +
    +I was able to snag a Windows 95 machine here at Organic, and tried out
    +some things:
    +
    +1) On Netscape 3.0b4, I was able to reproduce the bug, each and every
    +time. It's really simple: go to the Network Setup panel. Set it to
    +"Connect Every Time" and only let it have 1 connection at once (this may
    +not be necessary, but it's helpful). Then load an image that's
    +kept-alive. Then wait until the connection times out (this depends on the
    +server - 10-30 seconds, except for MIIS, which never times out, near as I
    +can tell). Then hit reload. It will hang. (actually, once it crashed).
    +
    +2) This happens with all forms of server. Apache 1.1, Netscape 2.0,
    +Spyglass 1.2, NCSA 1.5 (although, as stated, I couldn't test MIIS).
    +
    +3) Netscape 3.0b5 does, indeed, *not* have this bug. At least, I couldn't
    +get it to perform such. Yipee.
    +
    +So, we just put up a note on the web page. Make sure we say that all the
    +servers have the bug, it's a Windows bug, and Netscape Navigator 3.0b5
    +works around it. That way, no one can yell at us. Yes?
    +
    +-- Alexei Kosut <akosut@organic.com>            The Apache HTTP Server
    +   http://www.nueva.pvt.k12.ca.us/~akosut/      http://www.apache.org/
    +
    + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/core.html b/APACHE_1_3_12/htdocs/manual/mod/core.html new file mode 100644 index 0000000000..749e7092c3 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/core.html @@ -0,0 +1,3366 @@ + + + +Apache Core Features + + + + + + +

    Apache Core Features

    +

    +These configuration parameters control the core Apache features, and are +always available. +

    +

    Directives

    + +
    + +

    AccessConfig directive

    + +Syntax: AccessConfig filename
    +Default: AccessConfig conf/access.conf
    +Context: server config, virtual host
    +Status: core

    + +The server will read this file for more directives after reading the +ResourceConfig file. Filename is +relative to the ServerRoot. +This feature can be disabled using: +

    AccessConfig /dev/null
    +Historically, this file only contained +<Directory> sections; in fact it can now +contain any server directive allowed in the server config context. +


    + +

    AccessFileName directive

    + +Syntax: AccessFileName filename filename ...
    +Default: AccessFileName .htaccess
    +Context: server config, virtual host
    +Status: core
    +Compatibility: AccessFileName can accept more than +one filename only in Apache 1.3 and later

    + +When returning a document to the client the server looks for the first existing +access control file from this list of names in every directory of the path to +the document, if access control files are enabled for that directory. + +For example: +

    AccessFileName .acl
    +before returning the document /usr/local/web/index.html, the +server will read /.acl, /usr/.acl, /usr/local/.acl and /usr/local/web/.acl +for directives, unless they have been disabled with +
    +<Directory />
    +AllowOverride None
    +</Directory>


    + +

    AddDefaultCharset directive

    +Syntax: +AddDefaultCharset Off / On / charset
    +Context: +all
    +Status: +core
    +Default: +AddDefaultCharset Off
    +Compatibility: + AddDefaultCharset is only available in Apache 1.3.12 and +later

    +This directive specifies the name of the character set that will be added +to any response that does not have any parameter on the content +type in the HTTP headers. This will override any character set specified +in the body of the document via a META tag. A setting +of AddDefaultCharset Off disables this functionality. +AddDefaultCharset On enables Apache's internal +default charset of iso-8859-1 as required by the +directive. You can also specify an alternate charset to be used; +e.g. AddDefaultCharset utf-8. +


    + +

    AddModule directive

    + +Syntax: AddModule module module ...
    +Context: server config
    +Status: core
    +Compatibility: AddModule is only available in +Apache 1.2 and later

    + +The server can have modules compiled in which are not actively in use. +This directive can be used to enable the use of those modules. The +server comes with a pre-loaded list of active modules; this list can +be cleared with the ClearModuleList +directive.


    + +

    AllowOverride directive

    + +Syntax: AllowOverride override override ...
    +Default: AllowOverride All
    +Context: directory
    +Status: core

    + +When the server finds an .htaccess file (as specified by +AccessFileName) it needs to know which +directives declared in that file can override earlier access information.

    + +Override can be set to None, in which case the server +will not read the file, All in which case the server will +allow all the directives, or one or more of the following: +

    +
    AuthConfig +
    + +Allow use of the authorization directives +(AuthDBMGroupFile, +AuthDBMUserFile, +AuthGroupFile, +AuthName, AuthType, +AuthUserFile, +require, etc.). +
    FileInfo +
    + +Allow use of the directives controlling document types +(AddEncoding, +AddLanguage, +AddType, +DefaultType, +ErrorDocument, +LanguagePriority, etc.). +
    Indexes +
    + +Allow use of the directives controlling directory indexing +(AddDescription, +AddIcon, +AddIconByEncoding, +AddIconByType, +DefaultIcon, +DirectoryIndex, +FancyIndexing, +HeaderName, +IndexIgnore, +IndexOptions, +ReadmeName, etc.). +
    Limit +
    + +Allow use of the directives controlling host access (allow, deny and order). +
    Options +
    + +Allow use of the directives controlling specific directory features +(Options and +XBitHack). +


    + +

    AuthName directive

    + +Syntax: AuthName auth-domain
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: core

    + +This directive sets the name of the authorization realm for a directory. +This realm is given to the client so that the user knows which username and +password to send. AuthName takes a single argument; +if the realm name contains spaces, it must be enclosed in quotation marks. +It must be accompanied by AuthType and +require directives, and directives such as +AuthUserFile and +AuthGroupFile to work.


    + +

    AuthType directive

    + +Syntax: AuthType type
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: core

    + +This directive selects the type of user authentication for a directory. +Only Basic and Digest are currently implemented. + +It must be accompanied by AuthName and +require directives, and directives such as +AuthUserFile and +AuthGroupFile to work.


    + +

    BindAddress directive

    + +Syntax: BindAddress saddr
    +Default: BindAddress *
    +Context: server config
    +Status: core

    + +A Unix® http server can either listen for connections to every +IP address of the server machine, or just one IP address of the server +machine. Saddr can be + +

    +
  3. * +
  4. An IP address +
  5. A fully-qualified Internet domain name +
  6. +If the value is *, then the server will listen for connections on +every IP address, otherwise it will only listen on the IP address +specified.

    + +Only one BindAddress directive can be used. For more +control over which address and ports Apache listens to, use the +Listen directive instead of +BindAddress.

    + +BindAddress can be used as an alternative method for +supporting virtual hosts using +multiple independent servers, instead of using <VirtualHost> sections. + +

    See Also: +DNS Issues
    +See Also: +Setting which addresses and ports Apache uses

    + +
    + +

    BS2000Account directive

    + +Syntax: BS2000Account account
    +Default: none
    +Context: server config
    +Status: core
    +Compatibility: BS2000Account is only available for +BS2000 machines, as of Apache 1.3 and later.

    + +The BS2000Account directive is available for BS2000 hosts +only. It must be used to define the account number for the non-privileged +apache server user (which was configured using the +User directive). +This is required by the BS2000 POSIX subsystem (to change the underlying +BS2000 task environment by performing a sub-LOGON) to prevent CGI scripts +from accessing resources of the privileged account which started the +server, usually SYSROOT.
    +Only one BS2000Account directive can be used.

    + +

    See Also: +Apache EBCDIC port

    + +
    + +

    ClearModuleList directive

    + +Syntax: ClearModuleList
    +Context: server config
    +Status: core
    +Compatibility: ClearModuleList is only available in +Apache 1.2 and later

    + +The server comes with a built-in list of active modules. This +directive clears the list. It is assumed that the list will then be +re-populated using the AddModule directive.


    + +

    ContentDigest directive

    + +Syntax: ContentDigest on|off
    +Default: ContentDigest off
    +Context: server config, virtual host, directory, +.htaccess
    +Override: Options
    +Status: experimental
    +Compatibility: ContentDigest is only available in +Apache 1.1 and later

    + +This directive enables the generation of Content-MD5 headers +as defined in RFC1864 respectively RFC2068.

    + +MD5 is an algorithm for computing a "message digest" (sometimes called +"fingerprint") of arbitrary-length data, with a high degree of confidence +that any alterations in the data will be reflected in alterations in the +message digest.

    + +The Content-MD5 header provides an end-to-end message +integrity check (MIC) of the entity-body. A proxy or client may check this +header for detecting accidental modification of the entity-body +in transit. +Example header: +

       Content-MD5: AuLb7Dp1rqtRtxz2m9kRpA==

    + +Note that this can cause performance problems on your server +since the message digest is computed on every request +(the values are not cached).

    + +Content-MD5 is only sent for documents served by the +core, and not by any module. For example, SSI documents, output from +CGI scripts, and byte range responses do not have this header. + +


    + +

    CoreDumpDirectory directive

    + +Syntax: CoreDumpDirectory directory
    +Default: the same location as ServerRoot
    +Context: server config
    +Status: core

    + +This controls the directory to which Apache attempts to switch before +dumping core. The default is in the ServerRoot +directory, however since this should not be writable by the user +the server runs as, core dumps won't normally get written. If you +want a core dump for debugging, you can use this directive to place +it in a different location.


    + +

    DefaultType directive

    + +Syntax: DefaultType MIME-type
    +Default: DefaultType text/html
    +Context: server config, virtual host, directory, +.htaccess
    +Override: FileInfo
    +Status: core

    + +There will be times when the server is asked to provide a document +whose type cannot be determined by its MIME types mappings.

    + +The server must inform the client of the content-type of the document, so in +the event of an unknown type it uses the DefaultType. For +example: +

    DefaultType image/gif
    +would be appropriate for a directory which contained many gif images +with filenames missing the .gif extension.


    + +

    <Directory> directive

    + +Syntax: <Directory directory> + ... </Directory>
    +Context: server config, virtual host
    +Status: Core.

    + +<Directory> and </Directory> are used to enclose a group of +directives which will apply only to the named directory and sub-directories +of that directory. Any directive which is allowed in a directory +context may be used. Directory is either the full path to a directory, +or a wild-card string. In a wild-card string, `?' matches any single character, +and `*' matches any sequences of characters. As of Apache 1.3, you +may also use `[]' character ranges like in the shell. Also as of Apache 1.3 +none of the wildcards match a `/' character, which more closely mimics the +behaviour of Unix shells. +Example: +

    +   <Directory /usr/local/httpd/htdocs>
    +   Options Indexes FollowSymLinks
    +   </Directory>
    +
    + +

    Apache 1.2 and above: +Extended regular expressions can also be used, with the addition of the +~ character. For example:

    + +
    +   <Directory ~ "^/www/.*/[0-9]{3}">
    +
    + +would match directories in /www/ that consisted of three numbers. + +

    If multiple (non-regular expression) directory sections match the +directory (or its parents) containing +a document, then the directives are applied in the order of shortest match +first, interspersed with the directives from the +.htaccess files. For example, with +

    +<Directory />
    +AllowOverride None
    +</Directory>

    +<Directory /home/*>
    +AllowOverride FileInfo
    +</Directory>
    +for access to the document /home/web/dir/doc.html the +steps are: + +
  7. Apply directive AllowOverride None (disabling +.htaccess files). +
  8. Apply directive AllowOverride FileInfo (for directory +/home/web). +
  9. Apply any FileInfo directives in /home/web/.htaccess +
  10. + +

    +Regular expression directory sections are handled slightly differently +by Apache 1.2 and 1.3. In Apache 1.2 they are interspersed with the normal +directory sections and applied in the order they appear in the configuration +file. They are applied only once, and apply when the shortest match +possible occurs. In Apache 1.3 regular expressions are not considered +until after all of the normal sections have been applied. Then all of +the regular expressions are tested in the order they appeared in the +configuration file. For example, with +

    +<Directory ~ abc$>
    +... directives here ...
    +</Directory>
    +
    +Suppose that the filename being accessed is +/home/abc/public_html/abc/index.html. The server +considers each of /, /home, /home/abc, +/home/abc/public_html, and /home/abc/public_html/abc +in that order. In Apache 1.2, when +/home/abc is considered, the regular expression will match +and be applied. In Apache 1.3 the regular expression isn't considered +at all at that point in the tree. It won't be considered until after +all normal <Directory>s and .htaccess files have +been applied. Then the regular expression will +match on /home/abc/public_html/abc and be applied. + +

    + + +Note that the default Apache access for <Directory /> is +Allow from All. This means that Apache will serve any file +mapped from an URL. It is recommended that you change this with a block +such as + +

    + <Directory />
    +     Order Deny,Allow
    +     Deny from All
    + </Directory>
    +
    +

    + +and then override this for directories you want accessible. +See the +Security Tips +page for more details. + +

    + +The directory sections typically occur in the access.conf file, but they +may appear in any configuration file. <Directory> directives cannot +nest, and cannot appear in a <Limit> or +<LimitExcept> section. +

    + +See also: How Directory, +Location and Files sections work for an explanation of how these +different sections are combined when a request is received + +


    + +

    <DirectoryMatch>

    +Syntax: <DirectoryMatch regex> + ... </DirectoryMatch>
    +Context: server config, virtual host
    +Status: Core.
    +Compatibility: Available in Apache 1.3 and later + +

    <DirectoryMatch> and </DirectoryMatch> are used to enclose a +group of +directives which will apply only to the named directory and sub-directories +of that directory, the same as <Directory>. However, it takes as an +argument a regular expression. For example:

    + +
    +   <DirectoryMatch "^/www/.*/[0-9]{3}">
    +
    + +

    would match directories in /www/ that consisted of three numbers.

    + +

    See Also: +<Directory> for a description of how +regular expressions are mixed in with normal <Directory>s. +
    +See also: How Directory, +Location and Files sections work for an explanation of how these +different sections are combined when a request is received + +


    + +

    DocumentRoot directive

    + +Syntax: DocumentRoot directory-filename
    +Default: DocumentRoot +/usr/local/apache/htdocs
    +Context: server config, virtual host
    +Status: core

    + +This directive sets the directory from which httpd will serve files. +Unless matched by a directive like Alias, the server appends the path +from the requested URL to the document root to make the path to the +document. Example: +

    DocumentRoot /usr/web
    +then an access to http://www.my.host.com/index.html refers +to /usr/web/index.html. + +

    There appears to be a bug in mod_dir which causes problems when the +DocumentRoot has a trailing slash (i.e., "DocumentRoot /usr/web/") so +please avoid that. + +


    + +

    ErrorDocument directive

    + +Syntax: ErrorDocument error-code document
    +Context: server config, virtual host, directory, +.htaccess
    +Status: core
    +Override: FileInfo
    +Compatibility: The directory and .htaccess contexts +are only available in Apache 1.1 and later.

    + +In the event of a problem or error, Apache can be configured to do +one of four things, + +

      +
    1. output a simple hardcoded error message +
    2. output a customized message +
    3. redirect to a local URL to handle the problem/error +
    4. redirect to an external URL to handle the problem/error +
    + +

    The first option is the default, while options 2-4 are configured +using the ErrorDocument directive, which is followed by +the HTTP response code and a message or URL. + +

    Messages in this context begin with a single quote +("), which does not form part of the message itself. +Apache will sometimes offer additional information regarding the +problem/error. + +

    URLs can begin with a slash (/) for local URLs, or be a full +URL which the client can resolve. Examples: +

    +ErrorDocument 500 http://foo.example.com/cgi-bin/tester
    +ErrorDocument 404 /cgi-bin/bad_urls.pl
    +ErrorDocument 401 /subscription_info.html
    +ErrorDocument 403 "Sorry can't allow you access today +
    + +

    Note that when you specify an ErrorDocument that +points to a remote URL (ie. anything with a method such as "http" in +front of it) Apache will send a redirect to the client to tell it +where to find the document, even if the document ends up being +on the same server.. This has several implications, the +most important being that if you use an "ErrorDocument 401" +directive then it must refer to a local document. This results +from the nature of the HTTP basic authentication scheme. + +

    See Also: documentation of customizable +responses.


    + +

    ErrorLog directive

    + +Syntax: ErrorLog filename|syslog[:facility] +
    +Default: ErrorLog logs/error_log (Unix)
    +Default: ErrorLog logs/error.log + (Windows and OS/2)
    +Context: server config, virtual host
    +Status: core

    + +The error log directive sets the name of the file to which the server will log +any errors it encounters. If the filename does not begin with a slash (/) +then it is assumed to be relative to the ServerRoot. +If the filename begins with a pipe (|) then it is assumed to be a command to +spawn to handle the error log. + +

    Apache 1.3 and above: +Using syslog instead of a filename enables logging via syslogd(8) +if the system supports it. The default is to use syslog facility +local7, but you can override this by using the +syslog:facility syntax where facility can be +one of the names usually documented in syslog(1). + +

    +SECURITY: See the +security tips +document for details on why your security could be compromised if +the directory where logfiles are stored is writable by anyone other +than the user that starts the server. + +

    See also: LogLevel +


    + +

    <Files> directive

    +Syntax: <Files filename> +... </Files>
    +Context: server config, virtual host, .htaccess
    +Status: core
    +Compatibility: only available in Apache +1.2 and above.

    + +

    The <Files> directive provides for access control by +filename. It is comparable to the <Directory> directive and +<Location> directives. It +should be matched with a </Files> directive. The +directives given within this section will be applied to any +object with a basename (last component of filename) matching +the specified filename. +<Files> sections are processed in the +order they appear in the configuration file, after the +<Directory> sections and .htaccess files are +read, but before <Location> sections. Note that +<Files> can be nested inside <Directory> +sections to restrict the portion of the filesystem they +apply to.

    + +

    The filename argument should include a filename, or a +wild-card string, where `?' matches any single character, and `*' matches any +sequences of characters. Extended regular expressions can also be used, +with the addition of +the ~ character. For example:

    + +
    +   <Files ~ "\.(gif|jpe?g|png)$">
    +
    + +would match most common Internet graphics formats. In Apache 1.3 and +later, <FilesMatch> is preferred, +however. + +

    Note that unlike <Directory> and <Location> sections, +<Files> sections can be used inside .htaccess +files. This allows users to control access to their own files, at a +file-by-file level. + +

    + +See also: How Directory, +Location and Files sections work for an explanation of how these +different sections are combined when a request is received + +


    + +

    <FilesMatch>

    +Syntax: <FilesMatch regex> +... </FilesMatch>
    +Context: server config, virtual host, .htaccess
    +Status: core
    +Compatibility: only available in Apache +1.3 and above.

    + +

    The <FilesMatch> directive provides for access control by +filename, just as the <Files> directive +does. However, it accepts a regular expression. For example:

    + +
    +   <FilesMatch "\.(gif|jpe?g|png)$">
    +
    + +

    would match most common Internet graphics formats.

    + +See also: How Directory, +Location and Files sections work for an explanation of how these +different sections are combined when a request is received + +
    + +

    Group directive

    + +Syntax: Group unix-group
    +Default: Group #-1
    +Context: server config, virtual host
    +Status: core

    + +The Group directive sets the group under which the server will answer requests. +In order to use this directive, the stand-alone server must be run initially +as root. Unix-group is one of: +

    +
    A group name +
    Refers to the given group by name. +
    # followed by a group number. +
    Refers to a group by its number. +
    + +It is recommended that you set up a new group specifically for running the +server. Some admins use user nobody, but this is not always +possible or desirable.

    + +Note: if you start the server as a non-root user, it will fail to change +to the specified group, and will instead continue to run as the group of the +original user.

    + +Special note: Use of this directive in <VirtualHost> requires a +properly configured suEXEC wrapper. +When used inside a <VirtualHost> in this manner, only the group +that CGIs are run as is affected. Non-CGI requests are still processed +as the group specified in the main Group directive.

    + +SECURITY: See User for a discussion of the security +considerations.


    + +

    HostNameLookups directive

    + +Syntax: HostNameLookups on | off | double
    +Default: HostNameLookups off
    +Context: server config, virtual host, directory
    +Status: core
    +Compatibility: double available only in +Apache +1.3 and above.
    +Compatibility: Default was on prior to +Apache 1.3.

    + +This directive enables DNS lookups so that host names can be logged (and +passed to CGIs/SSIs in REMOTE_HOST). +The value double refers to doing double-reverse DNS. +That is, after a reverse lookup is performed, a forward lookup is then +performed on that result. At least one of the ip addresses in the forward +lookup must match the original address. (In "tcpwrappers" terminology +this is called PARANOID.)

    + +Regardless of the setting, when mod_access +is used for controlling access by hostname, a double reverse lookup +will be performed. This is necessary for security. Note that the +result of this double-reverse isn't generally available unless +you set HostnameLookups double. For example, if only +HostnameLookups on and a request is made to an object that +is protected by hostname restrictions, regardless of whether the +double-reverse fails or not, CGIs will still be passed the single-reverse +result in REMOTE_HOST.

    + +The default for this directive was previously on in +versions of Apache prior to 1.3. It was changed to off +in order to save the network traffic for those sites that don't truly +need the reverse lookups done. It is also better for the end users +because they don't have to suffer the extra latency that a lookup +entails. +Heavily loaded sites should leave this directive off, since DNS +lookups can take considerable amounts of time. The utility logresolve, +provided in the /support directory, can be used to look up host names +from logged IP addresses offline.


    + +

    IdentityCheck directive

    + +Syntax: IdentityCheck boolean
    +Default: IdentityCheck off
    +Context: server config, virtual host, directory
    +Status: core

    + +This directive enables RFC1413-compliant logging of the remote user name +for each connection, where the client machine runs identd or something similar. +This information is logged in the access log. Boolean is either +on or off.

    + +The information should not be trusted in any way except for rudimentary usage +tracking.

    + +Note that this can cause serious latency problems accessing your server +since every request requires one of these lookups to be performed. When +firewalls are involved each lookup might possibly fail and add 30 seconds +of latency to each hit. So in general this is not very useful on public +servers accessible from the Internet. +


    + +

    <IfDefine> directive

    +Syntax: <IfDefine [!]parameter-name> ... +</IfDefine>
    +Default: None
    +Context: all
    +Status: Core
    +Compatibility: <IfDefine> is only available in +1.3.1 and later.

    + +

    + +The <IfDefine test>...</IfDefine> +section is used to mark directives that are conditional. The +directives within an IfDefine section are only +processed if the test is true. If test +is false, everything between the start and end markers +is ignored.

    + +The test in the <IfDefine> section directive +can be one of two forms: + +

      +
    • parameter-name +
    • !parameter-name +
    + +

    In the former case, the directives between the start and end markers are +only processed if the parameter named parameter-name is defined. +The second format reverses the test, and only processes the directives if +parameter-name is not defined. + +

    The parameter-name argument is a define as given on the +httpd command line via -Dparameter-, at the +time the server was started. + +

    <IfDefine> sections are nest-able, which can be used to implement +simple multiple-parameter tests. + +Example: + +

    +  $ httpd -DReverseProxy ...
    +
    +  # httpd.conf
    +  <IfDefine ReverseProxy>
    +  LoadModule rewrite_module libexec/mod_rewrite.so
    +  LoadModule proxy_module   libexec/libproxy.so
    +  </IfDefine>
    +
    + +


    + +

    <IfModule> directive

    +Syntax: <IfModule [!]module-name> + ... +</IfModule>
    +Default: None
    +Context: all
    +Status: Core
    +Compatibility: IfModule is only available in 1.2 and +later.

    + +

    + +The <IfModule test>...</IfModule> +section is used to mark directives that are conditional. The +directives within an IfModule section are only +processed if the test is true. If test +is false, everything between the start and end markers +is ignored.

    + +The test in the <IfModule> section directive +can be one of two forms: + +

      +
    • module name +
    • !module name +
    + +

    In the former case, the directives between the start and end markers +are only processed if the module named module name is compiled +in to Apache. The second format reverses the test, and only processes +the directives if module name is not compiled in. + +

    The module name argument is a module name as given as the file +name of the module, at the time it was compiled. For example, +mod_rewrite.c. + +

    <IfModule> sections are nest-able, which can be used to implement +simple multiple-module tests. + +


    + +

    Include directive

    +Syntax: Include filename
    +Context: server config
    +Status: Core
    +Compatibility: Include is only available in Apache 1.3 +and later. +

    +This directive allows inclusion of other configuration files from within the +server configuration files. + +


    + +

    KeepAlive directive

    +Syntax: (Apache 1.1) KeepAlive max-requests
    +Default: (Apache 1.1) KeepAlive 5
    +Syntax: (Apache 1.2) KeepAlive on/off
    +Default: (Apache 1.2) KeepAlive On
    +Context: server config
    +Status: Core
    +Compatibility: KeepAlive is only available in Apache +1.1 and later.

    + +This directive enables +Keep-Alive +support. + +

    Apache 1.1: Set max-requests +to the maximum number of requests you want Apache to entertain per +request. A limit is imposed to prevent a client from hogging your +server resources. Set this to 0 to disable support. + +

    Apache 1.2 and later: Set to "On" to enable +persistent connections, "Off" to disable. See also the MaxKeepAliveRequests directive.


    + +

    KeepAliveTimeout directive

    +Syntax: KeepAliveTimeout seconds
    +Default: KeepAliveTimeout 15
    +Context: server config
    +Status: Core
    +Compatibility: KeepAliveTimeout is only available in +Apache 1.1 and later.

    + +The number of seconds Apache will wait for a subsequent request before +closing the connection. Once a request has been received, the timeout +value specified by the Timeout directive +applies. +


    + +

    <Limit> directive

    + +Syntax: + <Limit method method ... > ... </Limit>
    +Context: any
    +Status: core

    + +Access controls are normally effective for all access +methods, and this is the usual desired behaviour. In the +general case, access control directives should not be placed within a +<limit> section. + +

    The purpose of the <Limit> directive is to restrict the effect +of the access controls to the nominated HTTP methods. For all other +methods, the access restrictions that are enclosed in the +<Limit> bracket will have no effect. The +following example applies the access control only to the methods POST, +PUT, and DELETE, leaving all other methods unprotected: + +

    +<Limit POST PUT DELETE>
    +require valid-user
    +</Limit>
    + +The method names listed can be one or more of: GET, POST, PUT, DELETE, +CONNECT, OPTIONS, TRACE, PATCH, PROPFIND, PROPPATCH, MKCOL, COPY, +MOVE, LOCK, and UNLOCK. The method name is +case-sensitive. If GET is used it will also restrict HEAD +requests. + +


    + +

    <LimitExcept> directive

    + +Syntax: + <LimitExcept method method ... > ... </LimitExcept>
    +Context: any
    +Status: core
    +Compatibility: Available in Apache 1.3.5 and later

    + +<LimitExcept> and </LimitExcept> are used to enclose a group of +access control directives which will then apply to any HTTP access method +not listed in the arguments; i.e., it is the opposite of a +<Limit> section and can be used to control both +standard and nonstandard/unrecognized methods. See the documentation for +<Limit> for more details. + +


    + +

    LimitRequestBody directive

    + +Syntax: LimitRequestBody number
    +Default: LimitRequestBody 0
    +Context: server config, virtual host, directory, +.htaccess
    +Status: core
    +Compatibility: LimitRequestBody is only available in +Apache 1.3.2 and later. +

    + +Number is a long integer from 0 (meaning unlimited) to 2147483647 +(2GB). The default value is defined by the compile-time constant +DEFAULT_LIMIT_REQUEST_BODY (0 as distributed). +

    + +The LimitRequestBody directive allows the user to set a +limit on the allowed size of an HTTP request message body within +the context in which the directive is given (server, per-directory, +per-file or per-location). If the client request exceeds that limit, +the server will return an error response instead of servicing the request. +The size of a normal request message body will vary greatly depending +on the nature of the resource and the methods allowed on that resource. +CGI scripts typically use the message body for passing form information +to the server. Implementations of the PUT method will require a value +at least as large as any representation that the server wishes +to accept for that resource. +

    + +This directive gives the server administrator greater control over abnormal +client request behavior, which may be useful for avoiding some forms +of denial-of-service attacks. +

    + +


    + +

    LimitRequestFields directive

    + +Syntax: LimitRequestFields number
    +Default: LimitRequestFields 100
    +Context: server config
    +Status: core
    +Compatibility: LimitRequestFields is only available in +Apache 1.3.2 and later. +

    + +Number is an integer from 0 (meaning unlimited) to 32767. +The default value is defined by the compile-time constant +DEFAULT_LIMIT_REQUEST_FIELDS (100 as distributed). +

    + +The LimitRequestFields directive allows the server administrator to modify +the limit on the number of request header fields allowed in an HTTP request. +A server needs this value to be larger than the number of fields that a +normal client request might include. The number of request header fields +used by a client rarely exceeds 20, but this may vary among different +client implementations, often depending upon the extent to which a user +has configured their browser to support detailed content negotiation. +Optional HTTP extensions are often expressed using request header fields. +

    + +This directive gives the server administrator greater control over abnormal +client request behavior, which may be useful for avoiding some forms +of denial-of-service attacks. The value should be increased if normal +clients see an error response from the server that indicates too many +fields were sent in the request.

    + +


    + +

    LimitRequestFieldsize directive

    + +Syntax: LimitRequestFieldsize number
    +Default: LimitRequestFieldsize 8190
    +Context: server config
    +Status: core
    +Compatibility: LimitRequestFieldsize is only available in +Apache 1.3.2 and later. +

    + +Number is an integer size in bytes from 0 to the value of the +compile-time constant DEFAULT_LIMIT_REQUEST_FIELDSIZE +(8190 as distributed). +

    + +The LimitRequestFieldsize directive allows the server administrator to reduce +the limit on the allowed size of an HTTP request header field below the +normal input buffer size compiled with the server. A server needs this +value to be large enough to hold any one header field from a normal client +request. The size of a normal request header field will vary greatly +among different client implementations, often depending upon the extent +to which a user has configured their browser to support detailed +content negotiation. +

    + +This directive gives the server administrator greater control over abnormal +client request behavior, which may be useful for avoiding some forms +of denial-of-service attacks. Under normal conditions, the value should +not be changed from the default.

    + +


    + +

    LimitRequestLine directive

    + +Syntax: LimitRequestLine number
    +Default: LimitRequestLine 8190
    +Context: server config
    +Status: core
    +Compatibility: LimitRequestLine is only available in +Apache 1.3.2 and later. +

    + +Number is an integer size in bytes from 0 to the value of the +compile-time constant DEFAULT_LIMIT_REQUEST_LINE +(8190 as distributed). +

    + +The LimitRequestLine directive allows the server administrator to reduce +the limit on the allowed size of a client's HTTP request-line below the +normal input buffer size compiled with the server. Since the request-line +consists of the HTTP method, URI, and protocol version, the +LimitRequestLine directive places a restriction on the length of a +request-URI allowed for a request on the server. A server needs this +value to be large enough to hold any of its resource names, including +any information that might be passed in the query part of a GET request. +

    + +This directive gives the server administrator greater control over abnormal +client request behavior, which may be useful for avoiding some forms +of denial-of-service attacks. Under normal conditions, the value should +not be changed from the default.

    + +


    + +

    Listen directive

    +Syntax: +Listen [IP address:]port number
    +Context: server config
    +Status: core
    +Compatibility: Listen is only available in Apache +1.1 and later.

    + +

    The Listen directive instructs Apache to listen to more than one IP +address or port; by default it responds to requests on all IP +interfaces, but only on the port given by the Port directive.

    + +Listen can be used instead of BindAddress and Port. It tells +the server to accept incoming requests on the specified port or +address-and-port combination. If the first format is used, with a port +number only, the server listens to the given port on all interfaces, +instead of the port given by the Port directive. If an IP +address is given as well as a port, the server will listen on the +given port and interface.

    + +Note that you may still require a Port directive so +that URLs that Apache generates that point to your server still +work.

    + +Multiple Listen directives may be used +to specify a number of addresses and ports to listen to. The server +will respond to requests from any of the listed addresses and +ports. +

    + +For example, to make the server accept connections on both port +80 and port 8000, use: +

    +   Listen 80
    +   Listen 8000
    +
    + +To make the server accept connections on two specified +interfaces and port numbers, use +
    +   Listen 192.170.2.1:80
    +   Listen 192.170.2.5:8000
    +
    + +

    See Also: +DNS Issues
    +See Also: +Setting which addresses and ports Apache uses
    +See Also: +Known Bugs +

    +
    + +

    ListenBacklog directive

    +Syntax: ListenBacklog backlog
    +Default: ListenBacklog 511
    +Context: server config
    +Status: Core
    +Compatibility: ListenBacklog is only available in Apache +versions after 1.2.0. + +

    The maximum length of the queue of pending connections. Generally no +tuning is needed or desired, however on some systems it is desirable +to increase this when under a TCP SYN flood attack. See +the backlog parameter to the listen(2) system call. + +

    This will often be limited to a smaller number by the operating +system. This varies from OS to OS. Also note that many OSes do not +use exactly what is specified as the backlog, but use a number based on +(but normally larger than) what is set. +


    + +

    <Location> directive

    + +Syntax: <Location URL> +... </Location>
    +Context: server config, virtual host
    +Status: core
    +Compatibility: Location is only available in Apache +1.1 and later.

    + +

    The <Location> directive provides for access control by +URL. It is similar to the <Directory> directive, and +starts a subsection which is terminated with a </Location> +directive. <Location> sections are processed in the +order they appear in the configuration file, after the +<Directory> sections and .htaccess files are +read, and after the <Files> sections.

    + +

    Note that URLs do not have to line up with the filesystem at all, +it should be emphasized that <Location> operates completely outside +the filesystem. + +

    For all origin (non-proxy) requests, the URL to be matched is +of the form /path/, and you should not include any +http://servername prefix. For proxy requests, the URL +to be matched is of the form scheme://servername/path, +and you must include the prefix. + +

    The URL may use wildcards In a wild-card string, `?' matches any +single character, and `*' matches any sequences of characters. + +

    Apache 1.2 and above: +Extended regular expressions can also be used, with the addition of +the ~ character. + +For example:

    + +
    +   <Location ~ "/(extra|special)/data">
    +
    + +

    would match URLs that contained the substring "/extra/data" or +"/special/data". In Apache 1.3 and above, a new directive +<LocationMatch> exists which +behaves identical to the regex version of +<Location>. + +

    The Location functionality is especially useful when +combined with the SetHandler directive. For example, +to enable status requests, but allow them only +from browsers at foo.com, you might use: + +

    +    <Location /status>
    +    SetHandler server-status
    +    order deny,allow
    +    deny from all
    +    allow from .foo.com
    +    </Location>
    +
    + +

    Apache 1.3 and above note about / (slash): The slash +character has special +meaning depending on where in a URL it appears. People may be used +to its behaviour in the filesystem where multiple adjacent slashes are +frequently collapsed to a single slash (i.e., /home///foo +is the same as /home/foo). In URL-space this is not +necessarily true. The <LocationMatch> directive +and the regex version of <Location> require you +to explicitly specify multiple slashes if that is your intention. +For example, <LocationMatch ^/abc> would match the +request URL /abc but not the request URL //abc. +The (non-regex) <Location> directive behaves +similarly when used for proxy requests. But when (non-regex) +<Location> is used for non-proxy requests it will +implicitly match multiple slashes with a single slash. For example, +if you specify <Location /abc/def> and the request +is to /abc//def then it will match. + +

    +See also: How Directory, +Location and Files sections work for an explanation of how these +different sections are combined when a request is received + +


    + +

    <LocationMatch>

    + +Syntax: <LocationMatch regex> +... </LocationMatch>
    +Context: server config, virtual host
    +Status: core
    +Compatibility: LocationMatch is only available in +Apache 1.3 and later.

    + +

    The <LocationMatch> directive provides for access control by +URL, in an identical manner to <Location>. However, it takes a regular +expression as an argument instead of a simple string. For example:

    + +
    +   <LocationMatch "/(extra|special)/data">
    +
    + +

    would match URLs that contained the substring "/extra/data" or +"/special/data".

    + +See also: How Directory, +Location and Files sections work for an explanation of how these +different sections are combined when a request is received + +
    + +

    LockFile directive

    +Syntax: LockFile filename
    +Default: LockFile logs/accept.lock
    +Context: server config
    +Status: core

    + +The LockFile directive sets the path to the lockfile used when +Apache is compiled with either USE_FCNTL_SERIALIZED_ACCEPT or +USE_FLOCK_SERIALIZED_ACCEPT. This directive should normally be +left at its default value. The main reason for changing it is if +the logs directory is NFS mounted, since the lockfile +must be stored on a local disk. The PID of the main +server process is automatically appended to the filename.

    + +SECURITY: It is best to avoid putting this file in a +world writable directory such as /var/tmp because someone +could create a denial of service attack and prevent the server from +starting by creating a lockfile with the same name as the one the +server will try to create.

    + +


    + +

    LogLevel directive

    +Syntax: LogLevel level
    +Default: LogLevel error
    +Context: server config, virtual host
    +Status: core
    +Compatibility: LogLevel is only available in 1.3 or +later. + +

    LogLevel adjusts the verbosity of the messages recorded in the +error logs (see ErrorLog directive). +The following levels are available, in order of +decreasing significance: + +

    +
    Level + Description +
    Example +
    emerg + Emergencies - system is unusable. +
    "Child cannot open lock file. Exiting" +
    alert + Action must be taken immediately. +
    "getpwuid: couldn't determine user name from uid" +
    crit + Critical Conditions. +
    "socket: Failed to get a socket, exiting child" +
    error + Error conditions. +
    "Premature end of script headers" +
    warn + Warning conditions. +
    "child process 1234 did not exit, sending another SIGHUP" +
    notice + Normal but significant condition. +
    "httpd: caught SIGBUS, attempting to dump core in ..." +
    info + Informational. +
    "Server seems busy, (you may need to increase StartServers, or + Min/MaxSpareServers)..." +
    debug + Debug-level messages +
    "Opening config file ..." +
    + +

    When a particular level is specified, messages from all other levels +of higher significance will be reported as well. E.g., when +LogLevel info is specified, then messages with log levels of +notice and warn will also be posted. +

    +Using a level of at least crit is recommended. +


    + +

    MaxClients directive

    + +Syntax: MaxClients number
    +Default: MaxClients 256
    +Context: server config
    +Status: core

    + +

    The MaxClients directive sets the limit on the number of simultaneous +requests that can be supported; not more than this number of child server +processes will be created. To configure more than 256 clients, you must +edit the HARD_SERVER_LIMIT entry in httpd.h and recompile. + +

    Any connection attempts over the MaxClients limit will normally +be queued, up to a number based on the +ListenBacklog directive. Once a child process is freed at the +end of a different request, the connection will then be serviced. + +


    + +

    MaxKeepAliveRequests directive

    +Syntax: MaxKeepAliveRequests number
    +Default: MaxKeepAliveRequests 100
    +Context: server config
    +Status: core
    +Compatibility: Only available in Apache +1.2 and later. + +

    The MaxKeepAliveRequests directive limits the number of requests +allowed per connection when KeepAlive is +on. If it is set to "0", unlimited requests will be +allowed. We recommend that this setting be kept to a high value for +maximum server performance.


    + +

    MaxRequestsPerChild directive

    + +Syntax: MaxRequestsPerChild number
    +Default: MaxRequestsPerChild 0
    +Context: server config
    +Status: core

    + +The MaxRequestsPerChild directive sets the limit on the number of requests +that an individual child server process will handle. After MaxRequestsPerChild +requests, the child process will die. If MaxRequestsPerChild is 0, then +the process will never expire.

    + +Setting MaxRequestsPerChild to a non-zero limit has two beneficial effects: +

      +
    • it limits the amount of memory that process can consume by (accidental) +memory leakage; +
    • by giving processes a finite lifetime, it helps reduce the +number of processes when the server load reduces. +
    + +

    This directive has no effect on Win32. + +

    NOTE: For KeepAlive requests, only the first +request is counted towards this limit. In effect, it changes the +behavior to limit the number of connections per child. + +


    + +

    MaxSpareServers directive

    + +Syntax: MaxSpareServers number
    +Default: MaxSpareServers 10
    +Context: server config
    +Status: core

    + +The MaxSpareServers directive sets the desired maximum number of idle +child server processes. An idle process is one which is not handling +a request. If there are more than MaxSpareServers idle, then the parent +process will kill off the excess processes.

    + +Tuning of this parameter should only be necessary on very busy sites. +Setting this parameter to a large number is almost always a bad idea.

    + +This directive has no effect when used with the Apache Web server on a +Microsoft Windows platform. + +

    + +See also MinSpareServers and +StartServers.


    + +

    MinSpareServers directive

    + +Syntax: MinSpareServers number
    +Default: MinSpareServers 5
    +Context: server config
    +Status: core

    + +The MinSpareServers directive sets the desired minimum number of idle +child server processes. An idle process is one which is not handling +a request. If there are fewer than MinSpareServers idle, then the parent +process creates new children at a maximum rate of 1 per second.

    + +Tuning of this parameter should only be necessary on very busy sites. +Setting this parameter to a large number is almost always a bad idea.

    + +This directive has no effect on Microsoft Windows. + +

    + +See also MaxSpareServers and +StartServers.


    + +

    NameVirtualHost directive

    + +Syntax: NameVirtualHost addr[:port]
    +Context: server config
    +Status: core
    +Compatibility: NameVirtualHost is only available in +Apache 1.3 and later

    + +The NameVirtualHost directive is a required directive if you want to configure +name-based virtual hosts.

    + +Although addr can be hostname it is recommended that you always use +an IP address, e.g. + +

    NameVirtualHost 111.22.33.44
    + +With the NameVirtualHost directive you specify the address to which your +name-based virtual host names resolve. If you have multiple name-based +hosts on multiple addresses, repeat the directive for each address.

    + +Note: the "main server" and any _default_ servers will never +be served for a request to a NameVirtualHost IP Address (unless for some +reason you specify NameVirtualHost but then don't define any VirtualHosts +for that address).

    + +Optionally you can specify a port number on which the name-based +virtual hosts should be used, e.g. + +

    NameVirtualHost 111.22.33.44:8080
    + +See also: +Apache Virtual Host documentation +
    +

    Options directive

    + +Syntax: Options [+|-]option [+|-]option ...
    +Context: server config, virtual host, directory, +.htaccess
    +Override: Options
    +Status: core

    + +The Options directive controls which server features are available in +a particular directory. +

    +option can be set to None, in which case none of +the extra features are enabled, or one or more of the following: +

    +
    All +
    All options except for MultiViews. This is the default setting. +
    ExecCGI +
    + +Execution of CGI scripts is permitted. +
    FollowSymLinks +
    + +The server will follow symbolic links in this directory. +
    +Note: even though the server follows the symlink it +does not +change the pathname used to match against <Directory> +sections. +
    +Note: this option gets ignored if set inside a +<Location> section. + +
    Includes +
    + +Server-side includes are permitted. +
    IncludesNOEXEC +
    + +Server-side includes are permitted, but the #exec command and +#include of CGI scripts are disabled. +
    Indexes +
    + +If a URL which maps to a directory is requested, and the there is no +DirectoryIndex (e.g., index.html) in that directory, then the server will +return a formatted listing of the directory. +
    MultiViews +
    + +Content negotiated MultiViews are +allowed. +
    SymLinksIfOwnerMatch +
    + +The server will only follow symbolic links for which the target +file or directory is owned by the same user id as the link. +
    +Note: this option gets ignored if set inside a +<Location> section. +
    + +Normally, if multiple Options could apply to a directory, +then the most specific one is taken complete; the options are not +merged. However if all the options on the Options +directive are preceded by a + or - symbol, the options are +merged. Any options preceded by a + are added to the options +currently in force, and any options preceded by a - are removed from +the options currently in force.

    + +For example, without any + and - symbols: + +

    +<Directory /web/docs>
    +Options Indexes FollowSymLinks
    +</Directory>
    +<Directory /web/docs/spec>
    +Options Includes
    +</Directory> +
    +then only Includes will be set for the /web/docs/spec +directory. However if the second Options directive uses the + +and - symbols:

    + +

    +<Directory /web/docs>
    +Options Indexes FollowSymLinks
    +</Directory>
    +<Directory /web/docs/spec>
    +Options +Includes -Indexes
    +</Directory> +
    +then the options FollowSymLinks and Includes +are set for the /web/docs/spec directory.

    + +Note: Using -IncludesNOEXEC or +-Includes +disables server-side includes completely regardless of the previous setting.

    + +The default in the absence of any other settings is All.

    +


    + +

    PidFile directive

    + +Syntax: PidFile filename
    +Default: PidFile logs/httpd.pid
    +Context: server config
    +Status: core

    + +The PidFile directive sets the file to which the server records the +process id of the daemon. If the filename does not begin with a slash (/) +then it is assumed to be relative to the ServerRoot. +The PidFile is only used in standalone mode.

    + +It is often useful to be able to send the server a signal, so that it closes +and then reopens its ErrorLog and TransferLog, and +re-reads its configuration files. This is done by sending a SIGHUP (kill -1) +signal to the process id listed in the PidFile.

    + +The PidFile is subject to the same warnings about log file placement and +security. + +


    + +

    Port directive

    + +Syntax: Port number
    +Default: Port 80
    +Context: server config
    +Status: core

    + +Number is a number from 0 to 65535; some port numbers +(especially below +1024) are reserved for particular protocols. See /etc/services +for a list of some defined ports; the standard port for the http protocol +is 80.

    + +The Port directive has two behaviors, the first of which is necessary for +NCSA backwards compatibility (and which is confusing in the context of +Apache).

    + +

      +
    • +In the absence of any Listen or +BindAddress directives specifying a port number, +a Port directive given in the "main server" +(i.e., outside any <VirtualHost> section) +sets the network port on which the server listens. +If there are any Listen or BindAddress directives specifying +:number then Port has no effect on what address the server +listens at. + +
    • The Port directive +sets the SERVER_PORT environment variable (for +CGI and SSI), +and is used when the server must generate a URL that refers to itself +(for example when creating an external redirect to itself). This +behaviour is modified by +UseCanonicalName. +
    + +In no event does a Port setting affect +what ports a VirtualHost responds on, the +VirtualHost directive itself is used for that.

    + +The primary behaviour of Port should be considered to be similar to that of +the ServerName directive. The ServerName +and Port together specify what you consider to be the canonical +address of the server. +(See also UseCanonicalName.)

    + +Port 80 is one of Unix's special ports. All ports numbered +below 1024 are reserved for system use, i.e., regular (non-root) users cannot +make use of them; instead they can only use higher port numbers. +To use port 80, you must start the server from the root account. +After binding to the port and before accepting requests, Apache will change +to a low privileged user as set by the User directive.

    + +If you cannot use port 80, choose any other unused port. Non-root users +will have to choose a port number higher than 1023, such as 8000.

    + +SECURITY: if you do start the server as root, be sure +not to set User to root. If you run the server as +root whilst handling connections, your site may be open to a major security +attack.


    + +

    require directive

    + +Syntax: require entity-name entity entity...
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: core

    + +This directive selects which authenticated users can access a directory. +The allowed syntaxes are: +

      +
    • require user userid userid ...

      +Only the named users can access the directory.

      +

    • require group group-name group-name ...

      +Only users in the named groups can access the directory.

      +

    • require valid-user

      +All valid users can access the directory. +

    +

    +Require must be accompanied by AuthName and +AuthType directives, and directives such as +AuthUserFile and +AuthGroupFile (to define users and +groups) in order to work correctly. Example: +

    +AuthType Basic
    +AuthName "Restricted Directory"
    +AuthUserFile /web/users
    +AuthGroupFile /web/groups
    +require group admin
    +
    + +Access controls which are applied in this way are effective for +all methods. This is what is normally +desired. If you wish to apply access controls only to +specific methods, while leaving other methods unprotected, then place +the require statement into a <Limit> section

    +

    See also Satisfy and mod_access. +


    + +

    ResourceConfig directive

    + +Syntax: ResourceConfig filename
    +Default: ResourceConfig conf/srm.conf
    +Context: server config, virtual host
    +Status: core

    + +The server will read this file for more directives after reading the +httpd.conf file. Filename is relative to the +ServerRoot. +This feature can be disabled using: +

    ResourceConfig /dev/null
    +Historically, this file contained most directives except for server +configuration directives and <Directory> +sections; in fact it can now contain any server directive allowed in the +server config context.

    + +See also AccessConfig.


    + +

    RLimitCPU directive

    + +Syntax: RLimitCPU # or 'max' + [# or 'max'] +
    +Default: Unset; uses operating system defaults +
    +Context: server config, virtual host
    +Status: core
    +Compatibility: RLimitCPU is only available in Apache 1.2 +and later

    + +Takes 1 or 2 parameters. The first parameter sets the soft resource limit +for all processes and the second parameter sets the maximum resource limit. +Either parameter can be a number, or max to indicate to the server +that the limit should be set to the maximum allowed by the operating system +configuration. Raising the maximum resource limit requires that the server +is running as root, or in the initial startup phase.

    + +This applies to processes forked off from Apache children servicing requests, +not the Apache children themselves. This includes CGI scripts and SSI +exec commands, but not any processes forked off from the Apache parent +such as piped logs.

    + +CPU resource limits are expressed in seconds per process.

    + +See also RLimitMEM or +RLimitNPROC.


    + +

    RLimitMEM directive

    + +Syntax: RLimitMEM # or 'max' + [# or 'max']
    +Default: Unset; uses operating system defaults +
    +Context: server config, virtual host
    +Status: core
    +Compatibility: RLimitMEM is only available in Apache 1.2 +and later

    + +Takes 1 or 2 parameters. The first parameter sets the soft resource limit for +all processes and the second parameter sets the maximum resource limit. Either +parameter can be a number, or max to indicate to the server that the +limit should be set to the maximum allowed by the operating system +configuration. Raising the maximum resource limit requires that the +server is running as root, or in the initial startup phase.

    + +This applies to processes forked off from Apache children servicing requests, +not the Apache children themselves. This includes CGI scripts and SSI +exec commands, but not any processes forked off from the Apache parent +such as piped logs.

    + +Memory resource limits are expressed in bytes per process.

    + +See also RLimitCPU or +RLimitNPROC.


    + +

    RLimitNPROC directive

    + +Syntax: RLimitNPROC # or 'max' + [# or 'max']
    +Default: Unset; uses operating system defaults +
    +Context: server config, virtual host
    +Status: core
    +Compatibility: RLimitNPROC is only available in Apache +1.2 and later

    + +Takes 1 or 2 parameters. The first parameter sets the soft resource limit +for all processes and the second parameter sets the maximum resource limit. +Either parameter can be a number, or max to indicate to the server +that the limit should be set to the maximum allowed by the operating system +configuration. Raising the maximum resource limit requires that the server +is running as root, or in the initial startup phase.

    + +This applies to processes forked off from Apache children servicing requests, +not the Apache children themselves. This includes CGI scripts and SSI +exec commands, but not any processes forked off from the Apache parent +such as piped logs.

    + +Process limits control the number of processes per user.

    + +Note: If CGI processes are not running under userids other +than the +web server userid, this directive will limit the number of processes that the +server itself can create. Evidence of this situation will be indicated by +cannot fork messages in the error_log.

    + +See also RLimitMEM or +RLimitCPU. + +


    + +

    Satisfy directive

    + +Syntax: Satisfy 'any' or 'all'
    +Default: Satisfy all
    +Context: directory, .htaccess
    +Status: core
    +Compatibility: Satisfy is only available in Apache 1.2 +and later

    + +Access policy if both allow and require used. The parameter can be +either 'all' or 'any'. This directive is only useful +if access to a particular area is being restricted by both +username/password and client host address. In this case the +default behavior ("all") is to require that the client passes the +address access restriction and enters a valid username and +password. With the "any" option the client will be granted access if +they either pass the host restriction or enter a valid username and +password. This can be used to password restrict an area, but to let +clients from particular addresses in without prompting for a password. +

    +See also require and +mod_access. + +


    + +

    ScoreBoardFile directive

    + +Syntax: ScoreBoardFile filename
    +Default: ScoreBoardFile logs/apache_status +
    +Context: server config
    +Status: core

    + +The ScoreBoardFile directive is required on some architectures to place +a file that the server will use to communicate between its children and +the parent. The easiest way to find out if your architecture requires +a scoreboard file is to run Apache and see if it creates the file named +by the directive. If your architecture requires it then you must ensure +that this file is not used at the same time by more than one invocation +of Apache.

    + +If you have to use a ScoreBoardFile then you may see improved speed by +placing it on a RAM disk. But be careful that you heed the same warnings +about log file placement and +security.

    + +Apache 1.2 and above:

    + +Linux 1.x users might be able to add +-DHAVE_SHMGET -DUSE_SHMGET_SCOREBOARD to +the EXTRA_CFLAGS in your Configuration. This +might work with some 1.x installations, but won't work with all of +them. (Prior to 1.3b4, HAVE_SHMGET would have sufficed.)

    + +SVR4 users should consider adding +-DHAVE_SHMGET -DUSE_SHMGET_SCOREBOARD to the +EXTRA_CFLAGS in your Configuration. This +is believed to work, but we were unable to test it in time for 1.2 +release. (Prior to 1.3b4, HAVE_SHMGET would have sufficed.)

    + +See Also: +Stopping and Restarting Apache

    + +


    + +

    ScriptInterpreterSource directive

    + +Syntax: ScriptInterpreterSource 'registry' or 'script'
    +Default: ScriptInterpreterSource script +
    +Context: directory, .htaccess
    +Status: core (Windows only)

    + +This directive is used to control how Apache 1.3.5 and later finds the interpreter +used to run CGI scripts. The default technique is to use the interpreter pointed to by +the #! line in the script. Setting ScriptInterpreterSource registry will cause the +Windows Registry to be searched using the script file extension (e.g., .pl) as a search key. +


    + +

    SendBufferSize directive

    + +Syntax: SendBufferSize bytes
    +Context: server config
    +Status: core

    + +The server will set the TCP buffer size to the number of bytes +specified. Very useful to increase past standard OS defaults on high +speed high latency (i.e., 100ms or so, such as transcontinental +fast pipes) +


    + +

    ServerAdmin directive

    + +Syntax: ServerAdmin email-address
    +Context: server config, virtual host
    +Status: core

    + +The ServerAdmin sets the e-mail address that the server includes in any +error messages it returns to the client.

    + +It may be worth setting up a dedicated address for this, e.g. +

    ServerAdmin www-admin@foo.bar.com
    +as users do not always mention that they are talking about the server!


    + +

    ServerAlias directive

    + +Syntax: ServerAlias host1 host2 ...
    +Context: virtual host
    +Status: core
    +Compatibility: ServerAlias is only available in Apache +1.1 and later.

    + +The ServerAlias directive sets the alternate names for a host, for use +with +name-based virtual hosts. + +

    See also: +Apache Virtual Host documentation + +


    + +

    ServerName directive

    + +Syntax: ServerName fully-qualified domain name +
    +Context: server config, virtual host
    +Status: core

    + +The ServerName directive sets the hostname of the server; this is +used when creating redirection URLs. If it is not specified, then the +server attempts to deduce it from its own IP address; however this may +not work reliably, or may not return the preferred hostname. For example: +

    ServerName www.example.com
    +would be used if the canonical (main) name of the actual machine +were simple.example.com.

    + +If you are using name-based +virtual hosts, the ServerName inside a +<VirtualHost> +section specifies what hostname must appear in the request's +Host: header to match this virtual host.

    + +

    See Also:
    +DNS Issues
    +Apache virtual host documentation
    +UseCanonicalName
    +NameVirtualHost
    +ServerAlias
    +

    +
    + +

    ServerPath directive

    + +Syntax: ServerPath pathname
    +Context: virtual host
    +Status: core
    +Compatibility: ServerPath is only available in Apache +1.1 and later.

    + +The ServerPath directive sets the legacy URL pathname for a host, for +use with name-based virtual hosts. + +

    See also: +Apache Virtual Host documentation + +


    + +

    ServerRoot directive

    + +Syntax: ServerRoot directory-filename
    +Default: ServerRoot /usr/local/apache
    +Context: server config
    +Status: core

    + +The ServerRoot directive sets the directory in which the server lives. +Typically it will contain the subdirectories conf/ and +logs/. Relative paths for other configuration files are taken +as relative to this directory.

    + +See also the -d option to httpd.

    +See also the security tips +for information on how to properly set permissions on the ServerRoot.

    + +


    + +

    ServerSignature directive

    + +Syntax: ServerSignature Off | On | EMail
    +Default: ServerSignature Off
    +Context: server config, virtual host, directory, +.htaccess
    +Status: core
    +Compatibility: ServerSignature is only available in +Apache +1.3 and later.

    + +The ServerSignature directive allows the configuration of a trailing +footer line under server-generated documents (error messages, +mod_proxy ftp directory listings, mod_info output, ...). The reason +why you would want to enable such a footer line is that in a chain +of proxies, the user often has no possibility to tell which of the +chained servers actually produced a returned error message.
    +The Off setting, which is the default, suppresses the +error line (and is therefore compatible with the behavior of +Apache-1.2 and below). The On setting simply adds a +line with the server version number and ServerName of the serving virtual host, and +the EMail setting additionally creates a "mailto:" +reference to the ServerAdmin of the +referenced document. + +


    + +

    ServerTokens directive

    + +Syntax: ServerTokens Minimal|OS|Full
    +Default: ServerTokens Full
    +Context: server config
    +Status: core
    +Compatibility: ServerTokens is only available + in Apache 1.3 and later + +

    +This directive controls whether Server response header +field which is sent back to clients includes a description of the generic +OS-type of the server as well as information about compiled-in modules. +

    +
    +
    ServerTokens Min[imal] +
    +
    Server sends (e.g.): Server: Apache/1.3.0 +
    +
    ServerTokens OS +
    +
    Server sends (e.g.): Server: Apache/1.3.0 (Unix) +
    +
    ServerTokens Full (or not specified) +
    +
    Server sends (e.g.): Server: Apache/1.3.0 (Unix) PHP/3.0 + MyMod/1.2 +
    +
    +

    +This setting applies to the entire server, and cannot be enabled or +disabled on a virtualhost-by-virtualhost basis. +

    + +
    + +

    ServerType directive

    + +Syntax: ServerType type
    +Default: ServerType standalone
    +Context: server config
    +Status: core

    + +The ServerType directive sets how the server is executed by the system. +Type is one of +

    +
    inetd +
    The server will be run from the system process inetd; the command to start +the server is added to /etc/inetd.conf +
    standalone +
    The server will run as a daemon process; the command to start the server +is added to the system startup scripts. (/etc/rc.local or +/etc/rc3.d/....) +
    + +Inetd is the lesser used of the two options. For each http +connection received, a new copy of the server is started from scratch; +after the connection is complete, this program exits. There is a high price to +pay per connection, but for security reasons, some admins prefer this option. +Inetd mode is no longer recommended and does not always +work properly. Avoid it if at all possible. +

    + +Standalone is the most common setting for ServerType since +it is far more efficient. The server is started once, and services all +subsequent connections. If you intend running Apache to serve a busy site, +standalone will probably be your only option.

    +


    +

    StartServers directive

    + +Syntax: StartServers number
    +Default: StartServers 5
    +Context: server config
    +Status: core

    + +The StartServers directive sets the number of child server processes created +on startup. As the number of processes is dynamically controlled depending +on the load, there is usually little reason to adjust this parameter.

    + +

    When running under Microsoft Windows, this directive has no effect. + There is always one child which handles all requests. Within the + child requests are handled by separate threads. The + ThreadsPerChild directive controls + the maximum number of child threads handling requests, which will + have a similar effect to the setting of StartServers + on Unix. + +

    + +See also MinSpareServers and +MaxSpareServers.


    + +

    ThreadsPerChild

    +Syntax: ThreadsPerChild number
    +Default: ThreadsPerChild 50
    +Context: server config
    +Status: core (Windows, NetWare)
    +Compatibility: Available only with Apache 1.3 and later +with Windows + +

    This directive tells the server how many threads it should use. This + is the maximum number of connections the server can handle at once; be + sure and set this number high enough for your site if you get a lot of + hits. + +

    This directive has no effect on Unix systems. Unix users should look + at StartServers and MaxRequestsPerChild.

    + +
    + +

    ThreadStackSize

    +Syntax: ThreadStackSize number
    +Default: ThreadStackSize 65536
    +Context: server config
    +Status: core (NetWare)
    +Compatibility: Available only with Apache 1.3 and later +with NetWare + +

    This directive tells the server what stack size to use for each of the + running threads. If you ever get a stack overflow you will need to bump + this number to a higher setting. + +

    This directive has no effect on other systems. +


    + + + + + + +

    TimeOut directive

    + +Syntax: TimeOut number
    +Default: TimeOut 300
    +Context: server config
    +Status: core

    + +The TimeOut directive currently defines the amount of time Apache will +wait for three things: + +

      +
    1. The total amount of time it takes to receive a GET request. +
    2. The amount of time between receipt of TCP packets on a POST or + PUT request. +
    3. The amount of time between ACKs on transmissions of TCP packets + in responses. +
    + +We plan on making these separately configurable at some point down the +road. The timer used to default to 1200 before 1.2, but has been +lowered to 300 which is still far more than necessary in most +situations. It is not set any lower by default because there may +still be odd places in the code where the timer is not reset when +a packet is sent. + +


    + +

    UseCanonicalName directive

    + + +Syntax: UseCanonicalName on|off|dns
    + +Default: UseCanonicalName on
    + +Context: server config, virtual host, directory
    + +Override: Options
    + +Compatibility: UseCanonicalName is only available in +Apache 1.3 and later

    + +In many situations Apache has to construct a self-referential +URL. That is, a URL which refers back to the same server. +With UseCanonicalName on (and in all versions prior to +1.3) Apache will use the ServerName and Port directives to construct a canonical name for the +server. This name is used in all self-referential URLs, and for the +values of SERVER_NAME and SERVER_PORT in CGIs. + +

    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). These values are the same that are used to +implement name based virtual +hosts, and are available with the same clients. The CGI variables +SERVER_NAME and SERVER_PORT will be constructed +from the client supplied values as well. + +

    An example where this may be useful is on an intranet server where +you have users connecting to the machine using short names such as +www. You'll notice that if the users type a shortname, +and a URL which is a directory, such as http://www/splat, +without the trailing slash then Apache will redirect them to +http://www.domain.com/splat/. If you have authentication +enabled, this will cause the user to have to reauthenticate twice (once +for www and once again for www.domain.com). +But if UseCanonicalName is set off, then Apache will redirect +to http://www/splat/. + +

    There is a third option, UseCanonicalName DNS, which +is intended for use with mass IP-based virtual hosting to support +ancient clients that do not provide a Host: header. With +this option Apache does a reverse DNS lookup on the server IP address +that the client connected to in order to work out self-referential URLs. + +

    Warning: if CGIs make assumptions about the values of +SERVER_NAME they may be broken by this option. The client +is essentially free to give whatever value they want as a hostname. +But if the CGI is only using SERVER_NAME to construct +self-referential URLs then it should be just fine. + +

    See also: +ServerName, +Port + +


    + +

    User directive

    + +Syntax: User unix-userid
    +Default: User #-1
    +Context: server config, virtual host
    +Status: core

    + +The User directive sets the userid as which the server will answer requests. +In order to use this directive, the standalone server must be run initially +as root. Unix-userid is one of: +

    +
    A username +
    Refers to the given user by name. +
    # followed by a user number. +
    Refers to a user by their number. +
    + +The user should have no privileges which result in it being able to access +files which are not intended to be visible to the outside world, and +similarly, the user should not be able to execute code which is not +meant for httpd requests. It is recommended that you set up a new user and +group specifically for running the server. Some admins use user +nobody, but this is not always possible or desirable. +For example mod_proxy's cache, when enabled, must be accessible to this user +(see the CacheRoot +directive).

    + +Notes: If you start the server as a non-root user, it will fail to change +to the lesser privileged user, and will instead continue to run as +that original user. If you do start the server as root, then it is normal +for the parent process to remain running as root.

    + +Special note: Use of this directive in <VirtualHost> requires a +properly configured suEXEC wrapper. +When used inside a <VirtualHost> in this manner, only the user +that CGIs are run as is affected. Non-CGI requests are still processed +with the user specified in the main User directive.

    + +SECURITY: Don't set User (or Group) to +root unless you know exactly what you are doing, and what the +dangers are.


    + +

    <VirtualHost> directive

    + +Syntax: <VirtualHost addr[:port] + ...> ... +</VirtualHost>
    +Context: server config
    +Status: Core.
    +Compatibility: Non-IP address-based Virtual Hosting only +available in Apache 1.1 and later.
    +Compatibility: Multiple address support only available in +Apache 1.2 and later.

    + +<VirtualHost> and </VirtualHost> are used to enclose a group of +directives which will apply only to a particular virtual host. +Any directive which is allowed in a virtual host context may be used. +When the server receives a request for a document on a particular virtual +host, it uses the configuration directives enclosed in the <VirtualHost> +section. Addr can be +

    +
  11. The IP address of the virtual host +
  12. A fully qualified domain name for the IP address of the virtual host. +
  13. Example: +
    + +<VirtualHost 10.1.2.3>
    +ServerAdmin webmaster@host.foo.com
    +DocumentRoot /www/docs/host.foo.com
    +ServerName host.foo.com
    +ErrorLog logs/host.foo.com-error_log
    +TransferLog logs/host.foo.com-access_log
    +</VirtualHost> +
    + +Each VirtualHost must correspond to a different IP address, different port +number or a +different host name for the server, in the latter case the server +machine must be configured to accept IP packets for multiple +addresses. (If the machine does not have multiple network interfaces, +then this can be accomplished with the ifconfig alias +command (if your OS supports it), or with kernel patches like VIF (for SunOS(TM) 4.1.x)).

    + +The special name _default_ can be specified in which case +this virtual host will match any IP address that is not explicitly listed +in another virtual host. In the absence of any _default_ virtual host +the "main" server config, consisting of all those definitions outside +any VirtualHost section, is used when no match occurs.

    + +You can specify a :port to change the port that is matched. +If unspecified then it defaults to the same port as the most recent +Port statement of the main server. You +may also specify :* to match all ports on that address. +(This is recommended when used with _default_.)

    + +SECURITY: See the +security tips +document for details on why your security could be compromised if +the directory where logfiles are stored is writable by anyone other +than the user that starts the server. + +

    NOTE: The use of <VirtualHost> does +not affect what addresses Apache listens on. You may +need to ensure that Apache is listening on the correct addresses using +either BindAddress or Listen. + +

    See also: +Apache Virtual Host documentation
    +See also: +Warnings about DNS and Apache
    +See also: +Setting which addresses and ports Apache uses
    +See also: How Directory, +Location and Files sections work for an explanation of how these +different sections are combined when a request is received +

    + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/directive-dict.html b/APACHE_1_3_12/htdocs/manual/mod/directive-dict.html new file mode 100644 index 0000000000..03a9c3f67e --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/directive-dict.html @@ -0,0 +1,265 @@ + + + + Definitions of terms used to describe Apache directives + + + + + +

    Terms Used to Describe Apache Directives

    + +

    + Each Apache configuration directive is described using a common format + that looks like this: +

    +
    +
    Syntax: directive-name some args +
    + Default: + directive-name default-value +
    + Context: context-list +
    + Override: override +
    + Status: status +
    + Module: module-name +
    + Compatibility: compatibility notes +
    +
    +

    + Each of the directive's attributes, complete with possible values + where possible, are described in this document. +

    + +

    Directive Terms

    + + +
    +

    Syntax

    +

    + This indicates the format of the directive as it would appear in a + configuration file. This syntax is extremely directive-specific, so + refer to the text of the directive's description for details. +

    + +
    +

    Default

    +

    + If the directive has a default value (i.e., if you omit it + from your configuration entirely, the Apache Web server will behave as + though you set it to a particular value), it is described here. If + there is no default value, this section should say + "None". +

    + +
    +

    Context

    +

    + This indicates where in the server's configuration files the directive + is legal. It's a comma-separated list of one or more of the following + values: +

    +
    +
    server config +
    +
    This means that the directive may be used in the server + configuration files (e.g., httpd.conf, + srm.conf, and access.conf), but + not within any <VirtualHost> or + <Directory> containers. It is not allowed in + .htaccess files at all. +

    +

    +
    +
    virtual host +
    +
    This context means that the directive may appear inside + <VirtualHost> containers in the server + configuration files. +

    +

    +
    +
    directory +
    +
    A directive marked as being valid in this context may be used + inside <Directory>, + <Location>, and <Files> + containers in the server configuration files, subject to the + restrictions outlined in How Directory, + Location and Files sections work. +

    +

    +
    +
    .htaccess +
    +
    If a directive is valid in this context, it means that it can + appear inside per-directory .htaccess files. + It may not be processed, though depending upon the + overrides + currently active. +

    +

    +
    +
    +

    + The directive is only allowed within the designated context; + if you try to use it elsewhere, you'll get a configuration error that + will either prevent the server from handling requests in that context + correctly, or will keep the server from operating at all -- + i.e., the server won't even start. +

    +

    + The valid locations for the directive are actually the result of a + Boolean OR of all of the listed contexts. In other words, a directive + that is marked as being valid in "server config, + .htaccess" can be used in the httpd.conf file + and in .htaccess files, but not within any + <Directory> or <VirtualHost> containers. +

    + +
    +

    Override

    +

    + This directive attribute indicates which configuration override must + be active in order for the directive to be processed when it appears + in a .htaccess file. If the directive's + context + doesn't permit it to appear in .htaccess files, this + attribute should say "Not applicable". +

    +

    + Overrides are activated by the + AllowOverride + directive, and apply to a particular scope (such as a directory) and + all descendants, unless further modified by other + AllowOverride directives at lower levels. The + documentation for that directive also lists the possible override + names available. +

    + +
    +

    Status

    +

    + This indicates how tightly bound into the Apache Web server the + directive is; in other words, you may need to recompile the server + with an enhanced set of modules in order to gain access to the + directive and its functionality. Possible values for this attribute + are: +

    +
    +
    Core +
    +
    If a directive is listed as having "Core" status, that + means it is part of the innermost portions of the Apache Web server, + and is always available. +

    +

    +
    +
    Base +
    +
    A directive labeled as having "Base" status is + supported by one of the standard Apache modules which is compiled + into the server by default, and is therefore normally available + unless you've taken steps to remove the module from your configuration. +

    +

    +
    +
    Extension +
    +
    A directive with "Extension" status is provided by one + of the modules included with the Apache server kit, but the module + isn't normally compiled into the server. To enable the directive + and its functionality, you will need to change the server build + configuration files and re-compile Apache. +

    +

    +
    +
    Experimental +
    +
    "Experimental" status indicates that the directive is + available as part of the Apache kit, but you're on your own if you + try to use it. The directive is being documented for completeness, + and is not necessarily supported. The module which provides the + directive may or may not be compiled in by default; check the top of + the page which describes the directive and its module to see if it + remarks on the availability. +

    +

    +
    +
    + +
    +

    Module

    +

    + This quite simply lists the name of the source module which defines + the directive. +

    + +
    +

    Compatibility

    +

    + If the directive wasn't part of the original Apache version 1 + distribution, the version in which it was introduced should be listed + here. If the directive has the same name as one from the NCSA HTTPd + server, any inconsistencies in behaviour between the two should also + be mentioned. Otherwise, this attribute should say "No + compatibility issues." +

    + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/directives.html b/APACHE_1_3_12/htdocs/manual/mod/directives.html new file mode 100644 index 0000000000..84c6b704cd --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/directives.html @@ -0,0 +1,231 @@ + + + +Apache directives + + + + + +

    Apache Directives

    +

    +Each Apache directive available in the standard Apache distribution is +listed here. They are described using a consistent format, and there is +a dictionary +of the terms used in their descriptions available. +

    + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/footer.html b/APACHE_1_3_12/htdocs/manual/mod/footer.html new file mode 100644 index 0000000000..7fe745dcfd --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/footer.html @@ -0,0 +1,8 @@ +
    + +

    + Apache HTTP Server Version 1.3 +

    + +Index +Home diff --git a/APACHE_1_3_12/htdocs/manual/mod/header.html b/APACHE_1_3_12/htdocs/manual/mod/header.html new file mode 100644 index 0000000000..5662300029 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/header.html @@ -0,0 +1,6 @@ +
    + [APACHE DOCUMENTATION] +

    + Apache HTTP Server Version 1.3 +

    +
    diff --git a/APACHE_1_3_12/htdocs/manual/mod/index.html b/APACHE_1_3_12/htdocs/manual/mod/index.html new file mode 100644 index 0000000000..cb344fd670 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/index.html @@ -0,0 +1,124 @@ + + + +Apache modules + + + + + +

    Apache modules

    + +

    +Below is a list of all of the modules that come as part of the +Apache distribution. See also the complete alphabetical list of +all Apache directives. +

    + +
    +
    Core +
    Core Apache features. +
    mod_access +
    Host based access control. +
    mod_actions Apache 1.1 and later. +
    Filetype/method-based script execution +
    mod_alias +
    Aliases and redirects. +
    mod_asis +
    The .asis file handler. +
    mod_auth +
    User authentication using text files. +
    mod_auth_anon +
    Anonymous user authentication, FTP-style. +
    mod_auth_db +
    User authentication using Berkeley DB files. +
    mod_auth_dbm +
    User authentication using DBM files. +
    mod_auth_digest +
    MD5 authentication (experimental) +
    mod_autoindex +
    Automatic directory listings. +
    mod_browser Apache 1.2.* only +
    Set environment variables based on User-Agent strings. Replaced by + mod_setenvif in Apache 1.3 and up +
    mod_cern_meta +
    Support for HTTP header metafiles. +
    mod_cgi +
    Invoking CGI scripts. +
    mod_cookies up to Apache 1.1.1 +
    Support for Netscape-like cookies. Replaced in Apache 1.2 by +mod_usertrack +
    mod_digest +
    MD5 authentication +
    mod_dir +
    Basic directory handling. +
    mod_dld Apache 1.2.* and earlier +
    Start-time linking with the GNU libdld. Replaced in Apache 1.3 by mod_so +
    mod_dll Apache 1.3b1 to 1.3b5 only +
    Replaced in 1.3b6 by mod_so +
    mod_env +
    Passing of environments to CGI scripts +
    mod_example Apache 1.2 and up +
    Demonstrates Apache API +
    mod_expires Apache 1.2 and up +
    Apply Expires: headers to resources +
    mod_headers Apache 1.2 and up +
    Add arbitrary HTTP headers to resources +
    mod_imap +
    The imagemap file handler. +
    mod_include +
    Server-parsed documents. +
    mod_info +
    Server configuration information +
    mod_isapi +
    Windows ISAPI Extension support +
    mod_log_agent +
    Logging of User Agents. +
    mod_log_common up to Apache 1.1.1 +
    Standard logging in the Common Logfile Format. Replaced by the +mod_log_config module in Apache 1.2 and up +
    mod_log_config +
    User-configurable logging replacement for mod_log_common. +
    mod_log_referer +
    Logging of document references. +
    mod_mime +
    Determining document types using file extensions. +
    mod_mime_magic +
    Determining document types using "magic numbers". +
    mod_mmap_static +
    Mapping files into memory for faster serving. +
    mod_negotiation +
    Content negotiation. +
    mod_proxy +
    Caching proxy abilities +
    mod_rewrite Apache 1.2 and up +
    Powerful URI-to-filename mapping using regular expressions +
    mod_setenvif Apache 1.3 and up +
    Set environment variables based on client information +
    mod_so Apache 1.3 and up +
    Experimental support for loading modules (DLLs on Windows) at runtime +
    mod_speling Apache 1.3 and up +
    Automatically correct minor typos in URLs +
    mod_status +
    Server status display +
    mod_userdir +
    User home directories. +
    mod_unique_id Apache 1.3 and up +
    Generate unique request identifier for every request +
    mod_usertrack Apache 1.2 and up +
    User tracking using Cookies (replacement for mod_cookies.c) +
    mod_vhost_alias Apache 1.3.7 and up +
    Support for dynamically configured mass virtual hosting +
    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_access.html b/APACHE_1_3_12/htdocs/manual/mod/mod_access.html new file mode 100644 index 0000000000..81c7e8d3db --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_access.html @@ -0,0 +1,316 @@ + + + +Apache module mod_access + + + + + + +

    Module mod_access

    +

    +This module is contained in the mod_access.c file, and +is compiled in by default. It provides access control based on client +hostname or IP address. +

    + + +
    +
    See also Satisfy + and require. +
    +
    + + +

    allow directive

    +

    + +Syntax: allow from host host ...
    +Context: directory, .htaccess
    +Override: Limit
    +Status: Base
    +Module: mod_access +

    +

    +The allow directive affects which hosts can access a given directory. +Host is one of the following: +

    +
    +
    all +
    All hosts are allowed access +
    A (partial) domain-name +
    Hosts whose names match, or end in, this string are allowed access. +
    A full IP address +
    An IP address of a host allowed access +
    A partial IP address +
    The first 1 to 3 bytes of an IP address, for subnet restriction. +
    A network/netmask pair (Apache 1.3 and later) +
    A network a.b.c.d, and a netmask w.x.y.z. For more fine-grained subnet + restriction. (i.e., 10.1.0.0/255.255.0.0) +
    A network/nnn CIDR specification (Apache 1.3 and later) +
    Similar to the previous case, except the netmask consists of nnn + high-order 1 bits. (i.e., 10.1.0.0/16 is the same as 10.1.0.0/255.255.0.0) +
    +

    +Example: +

    +
    allow from .ncsa.uiuc.edu
    +

    +All hosts in the specified domain are allowed access. +

    +

    +Note that this compares whole components; bar.edu +would not match foobar.edu. +

    +

    +See also deny, order, and +BrowserMatch. +

    + +

    +Syntax: allow from + env=variablename
    +Context: directory, .htaccess
    +Override: Limit
    +Status: Base
    +Module: mod_access
    +Compatibility: Apache 1.2 and above +

    +

    +The allow from env directive controls access to a directory by the +existence (or non-existence) of an environment variable. +

    +

    +Example: +

    +
    +BrowserMatch ^KnockKnock/2.0 let_me_in
    +<Directory /docroot>
    +    order deny,allow
    +    deny from all
    +    allow from env=let_me_in
    +</Directory>
    +
    +In this case browsers with the user-agent string KnockKnock/2.0 will +be allowed access, and all others will be denied. +

    +See also deny from env +and order. +

    +
    + +

    deny directive

    +

    + +Syntax: deny from host host ...
    +Context: directory, .htaccess
    +Override: Limit
    +Status: Base
    +Module: mod_access +

    +

    +The deny directive affects which hosts can access a given directory. +Host is one of the following: +

    +
    +
    all +
    all hosts are denied access +
    A (partial) domain-name +
    host whose name is, or ends in, this string are denied access. +
    A full IP address +
    An IP address of a host denied access +
    A partial IP address +
    The first 1 to 3 bytes of an IP address, for subnet restriction. +
    A network/netmask pair (Apache 1.3 and later) +
    A network a.b.c.d, and a netmask w.x.y.z. For more fine-grained subnet + restriction. (i.e., 10.1.0.0/255.255.0.0) +
    A network/nnn CIDR specification (Apache 1.3 and later) +
    Similar to the previous case, except the netmask consists of nnn + high-order 1 bits. (i.e., 10.1.0.0/16 is the same as 10.1.0.0/255.255.0.0) +
    +

    +Example: +

    +
    deny from 16
    +

    +All hosts in the specified network are denied access. +

    +

    +Note that this compares whole components; bar.edu +would not match foobar.edu. +

    +

    +See also allow and order. +

    + +

    +Syntax: deny from + env=variablename
    +Context: directory, .htaccess
    +Override: Limit
    +Status: Base
    +Module: mod_access
    +Compatibility: Apache 1.2 and above +

    +

    +The deny from env directive controls access to a directory by the +existence (or non-existence) of an environment variable. +

    +

    +Example: +

    +
    +BrowserMatch ^BadRobot/0.9 go_away
    +<Directory /docroot>
    +    order allow,deny
    +    allow from all
    +    deny from env=go_away
    +</Directory>
    +
    +In this case browsers with the user-agent string BadRobot/0.9 will +be denied access, and all others will be allowed. + +

    +See also allow from env +and order. +

    +
    + +

    order directive

    +

    + +Syntax: order ordering
    +Default: order deny,allow
    +Context: directory, .htaccess
    +Override: Limit
    +Status: Base
    +Module: mod_access +

    +

    +The order directive controls the order in which allow and +deny directives are evaluated. Ordering is one +of +

    +
    +
    deny,allow +
    the deny directives are evaluated before the allow directives. (The +initial state is OK.) +
    allow,deny +
    the allow directives are evaluated before the deny directives. (The +initial state is FORBIDDEN.) +
    mutual-failure +
    Only those hosts which appear on the allow list and do not appear +on the deny list are granted access. (The initial state is irrelevant.) +
    +

    +Keywords may only be separated by a comma; no whitespace is allowed between +them. +Note that in all cases every allow and deny +statement is evaluated, there is no "short-circuiting". +

    +

    +Example: +

    +
    + order deny,allow
    + deny from all
    + allow from .ncsa.uiuc.edu
    +
    +

    +Hosts in the ncsa.uiuc.edu domain are allowed access; all other hosts are +denied access. +

    + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_actions.html b/APACHE_1_3_12/htdocs/manual/mod/mod_actions.html new file mode 100644 index 0000000000..05d7969bde --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_actions.html @@ -0,0 +1,132 @@ + + + +Module mod_actions + + + + + +

    Module mod_actions

    +

    +This module is contained in the mod_actions.c file, and +is compiled in by default. It provides for +executing CGI scripts based on media type or request method. It is not +present in versions prior to Apache 1.1. +

    +

    Summary

    +

    +This module lets you run CGI scripts whenever a file of a certain type +is requested. This makes it much easier to execute scripts that +process files. +

    +

    Directives

    + + +
    + +

    Action directive

    +

    +Syntax: Action action-type cgi-script
    +Context: server config, virtual host, directory, + .htaccess
    +Override: FileInfo
    +Status: Base
    +Module: mod_actions
    +Compatibility: Action is only available in Apache 1.1 +and later +

    +

    +This directive adds an action, which will activate cgi-script when +action-type is triggered by the request. The action-type can +be either a handler or a MIME content type. It +sends the URL and file path of the requested document using the standard CGI +PATH_INFO and PATH_TRANSLATED environment variables. +

    +
    + +

    Script directive

    +

    +Syntax: Script method cgi-script
    +Context: server config, virtual host, directory
    +Status: Base
    +Module: mod_actions
    +Compatibility: Script is only available in Apache 1.1 +and later; arbitrary method use is only available with 1.3.10 and later +

    + +

    +This directive adds an action, which will activate cgi-script when +a file is requested using the method of method. It sends the +URL and file path of the requested document using the standard +CGI PATH_INFO and PATH_TRANSLATED environment variables. +

    +
    +Prior to Apache 1.3.10, method can only be +one of GET, POST, PUT, or +DELETE. As of 1.3.10, any arbitrary method name +may be used. Method names are case-sensitive, so +Script PUT and Script put +have two entirely different effects. +
    +

    +Note that the Script command defines default actions only. If a CGI +script is called, or some other resource that is capable of handling +the requested method internally, it will do so. Also note that Script +with a method of GET will only be called if there are +query arguments present (e.g., foo.html?hi). Otherwise, the request +will proceed normally. +

    +

    +Examples: +

    +
    +    Script GET /cgi-bin/search     #e.g. for <ISINDEX>-style searching
    +    Script PUT /~bob/put.cgi
    +
    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_alias.html b/APACHE_1_3_12/htdocs/manual/mod/mod_alias.html new file mode 100644 index 0000000000..0826842cde --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_alias.html @@ -0,0 +1,405 @@ + + + +Apache module mod_alias + + + + + + +

    Module mod_alias

    +

    +This module is contained in the mod_alias.c file, and +is compiled in by default. It provides for mapping different parts of the +host filesystem in the the document tree, and for URL redirection. +

    + +

    Directives

    + +
    + + +

    Alias directive

    +

    + +Syntax: Alias url-path directory-filename
    +Context: server config, virtual host
    +Status: Base
    +Module: mod_alias +

    +

    +The Alias directive allows documents to be stored in the local filesystem +other than under the DocumentRoot. +URLs with a (%-decoded) path beginning with url-path will be +mapped to local files beginning with directory-filename. +

    +Example: +

    +
    Alias /image /ftp/pub/image
    +

    +A request for http://myserver/image/foo.gif would cause the server to +return the file /ftp/pub/image/foo.gif. +

    +

    +Note that if you include a trailing / on the url-path then the +server will require a trailing / in order to expand the alias. That is, +if you use Alias /icons/ /usr/local/apache/icons/ then +the url /icons will not be aliased. +

    +

    +Note that you may need to specify additional +<Directory> sections +which cover the destination of aliases. Aliasing occurs +before <Directory> sections are checked, so only +the destination of aliases are affected. (Note however +<Location> +sections are run through once before aliases are performed, so they +will apply.) +

    +See also ScriptAlias. +

    +
    + +

    AliasMatch

    +

    +Syntax: AliasMatch regex directory-filename
    +Context: server config, virtual host
    +Status: Base
    +Module: mod_alias
    +Compatibility: Available in Apache 1.3 and later +

    + +

    This directive is equivalent to Alias, but +makes use of standard regular expressions, instead of simple prefix +matching. The supplied regular expression is matched against the URL, +and if it matches, the server will substitute any parenthesized +matches into the given string and use it as a filename. For example, +to activate the /icons directory, one might use: +

    +    AliasMatch ^/icons(.*) /usr/local/apache/icons$1
    +
    +

    + +
    + +

    Redirect directive

    +

    + +Syntax: Redirect [ status ] + url-path url
    +Context: server config, virtual host, directory, + .htaccess
    +Override: FileInfo
    +Status: Base
    +Module: mod_alias
    +Compatibility: The directory and .htaccess context's +are only available in versions 1.1 and later. The status +argument is only available in Apache 1.2 or later. +

    +

    +The Redirect directive maps an old URL into a new one. The new URL is returned +to the client which attempts to fetch it again with the new address. +Url-path a (%-decoded) path; any requests for documents beginning with +this path will be returned a redirect error to a new (%-encoded) url +beginning with url. +

    +

    +Example: +

    +
    Redirect /service +http://foo2.bar.com/service
    +

    +If the client requests http://myserver/service/foo.txt, it will be told to +access http://foo2.bar.com/service/foo.txt instead. +

    +

    +Note: Redirect directives take precedence over Alias +and ScriptAlias +directives, irrespective of their ordering in the configuration file. Also, +Url-path must be an absolute path, not a relative path, even +when used with .htaccess files or inside of <Directory> sections. +

    +

    +If no status argument is given, the redirect will be +"temporary" (HTTP status 302). This indicates to the client that the +resources is has moved temporarily. The status +argument can be used to return other HTTP status codes: +

    +

    +
    permanent +
    Returns a permanent redirect status (301) indicating that +the resource has moved permanently. +
    temp +
    Returns a temporary redirect status (302). This is the +default. +
    seeother +
    Returns a "See Other" status (303) indicating that +the resource has been replaced. +
    gone +
    Returns a "Gone" status (410) indicating that the resource +has been permanently removed. When this status is used the url +argument should be omitted. +
    +

    +Other status codes can be returned by giving the numeric status code +as the value of status. If the status is between 300 and 399, +the url argument must be present, otherwise it must be +omitted. Note that the status must be known to the Apache code (see +the function send_error_response in http_protocol.c). +

    +
    + +

    RedirectMatch

    +

    +Syntax: + RedirectMatch [status] regex url +
    +Context: server config, virtual host, directory, + .htaccess
    +Override: FileInfo
    +Status: Base
    +Module: mod_alias
    +Compatibility: Available in Apache 1.3 and later +

    + +

    This directive is equivalent to Redirect, but +makes use of standard regular expressions, instead of simple prefix +matching. The supplied regular expression is matched against the URL, +and if it matches, the server will substitute any parenthesized +matches into the given string and use it as a filename. For example, +to redirect all GIF files to like-named JPEG files on another server, +one might use: +

    +    RedirectMatch (.*)\.gif$ http://www.anotherserver.com$1.jpg
    +
    +

    + +
    + +

    RedirectTemp directive

    +

    + +Syntax: RedirectTemp url-path url
    +Context: server config, virtual host, directory, + .htaccess
    +Override: FileInfo
    +Status: Base
    +Module: mod_alias
    +Compatibility: This directive is only available in 1.2 +

    +

    +This directive makes the client know that the Redirect is only +temporary (status 302). Exactly equivalent to Redirect +temp. +

    +
    + +

    RedirectPermanent directive

    +

    + +Syntax: RedirectPermanent url-path url
    +Context: server config, virtual host, directory, + .htaccess
    +Override: FileInfo
    +Status: Base
    +Module: mod_alias
    +Compatibility: This directive is only available in 1.2 +

    +

    +This directive makes the client know that the Redirect is permanent +(status 301). Exactly equivalent to Redirect permanent. +

    +
    + +

    ScriptAlias directive

    +

    + +Syntax: ScriptAlias url-path directory-filename +
    +Context: server config, virtual host
    +Status: Base
    +Module: mod_alias +

    +

    +The ScriptAlias directive has the same behavior as the +Alias directive, except that in addition it +marks the target directory as containing CGI scripts. +URLs with a (%-decoded) path beginning with url-path will be +mapped to scripts beginning with directory-filename. +

    +Example: +

    +
    ScriptAlias /cgi-bin/ /web/cgi-bin/
    +

    +A request for http://myserver/cgi-bin/foo would cause the server to +run the script /web/cgi-bin/foo. +

    + +
    + +

    ScriptAliasMatch

    +

    +Syntax: ScriptAliasMatch + regex directory-filename
    +Context: server config, virtual host
    +Status: Base
    +Module: mod_alias
    +Compatibility: Available in Apache 1.3 and later +

    + +

    This directive is equivalent to ScriptAlias, but +makes use of standard regular expressions, instead of simple prefix +matching. The supplied regular expression is matched against the URL, +and if it matches, the server will substitute any parenthesized +matches into the given string and use it as a filename. For example, +to activate the standard /cgi-bin, one might use: +

    +    ScriptAliasMatch ^/cgi-bin(.*) /usr/local/apache/cgi-bin$1
    +
    +

    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_asis.html b/APACHE_1_3_12/htdocs/manual/mod/mod_asis.html new file mode 100644 index 0000000000..3ca8e7e906 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_asis.html @@ -0,0 +1,68 @@ + + + +Apache module mod_asis + + + + + + +

    Module mod_asis

    + +This module is contained in the mod_asis.c file, and +is compiled in by default. It provides for .asis files. Any +document with mime type httpd/send-as-is will be processed by +this module. + + +

    Purpose

    +To allow file types to be defined such that Apache sends them without +adding HTTP headers.

    + +This can be used to send any kind of data from the server, including redirects +and other special HTTP responses, without requiring a cgi-script or an nph +script. +

    Usage

    +In the server configuration file, define a new mime type called +httpd/send-as-is e.g. +
    AddType httpd/send-as-is asis
    +this defines the .asis file extension as being of the new +httpd/send-as-is mime type. The contents of any file with a +.asis extension will then be sent by Apache to the client with +almost no changes. Clients will need HTTP headers to be attached, so do not +forget them. A Status: header is also required; the data should be the +3-digit HTTP response code, followed by a textual message.

    + +Here's an example of a file whose contents are sent as is so as to +tell the client that a file has redirected. +

    +Status: 301 Now where did I leave that URL
    +Location: http://xyz.abc.com/foo/bar.html
    +Content-type: text/html
    +
    +<HTML>
    +<HEAD>
    +<TITLE>Lame excuses'R'us</TITLE>
    +</HEAD>
    +<BODY>
    +<H1>Fred's exceptionally wonderful page has moved to
    +<A HREF="http://xyz.abc.com/foo/bar.html">Joe's</A> site.
    +</H1>
    +</BODY>
    +</HTML> +
    +Notes: the server always adds a Date: and Server: header to the data returned +to the client, so these should not be included in the file. +The server does not add a Last-Modified header; it probably should. +

    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_auth.html b/APACHE_1_3_12/htdocs/manual/mod/mod_auth.html new file mode 100644 index 0000000000..a3f85d54be --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_auth.html @@ -0,0 +1,214 @@ + + + +Apache module mod_auth + + + + + + +

    Module mod_auth

    + +This module is contained in the mod_auth.c file, and +is compiled in by default. It provides for user authentication using +textual files. + + + +
  14. AuthGroupFile +
  15. AuthUserFile +
  16. AuthAuthoritative +
  17. +
    + + +

    AuthGroupFile

    + +Syntax: AuthGroupFile filename
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Base
    +Module: mod_auth

    + +The AuthGroupFile directive sets the name of a textual file containing the list +of user groups for user authentication. Filename is the path +to the group file. If it is not absolute (i.e., if it +doesn't begin with a slash), it is treated as relative to the ServerRoot. +

    +Each line of the group file contains a groupname followed by a colon, followed +by the member usernames separated by spaces. Example: +

    mygroup: bob joe anne
    +Note that searching large text files is very inefficient; +AuthDBMGroupFile should +be used instead.

    + +Security: make sure that the AuthGroupFile is stored outside the +document tree of the web-server; do not put it in the directory that +it protects. Otherwise, clients will be able to download the AuthGroupFile.

    + +See also AuthName, +AuthType and +AuthUserFile.


    + +

    AuthUserFile

    + +Syntax: AuthUserFile filename
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Base
    +Module: mod_auth

    + +The AuthUserFile directive sets the name of a textual file containing +the list of users and passwords for user +authentication. Filename is the path to the user +file. If it is not absolute (i.e., if it doesn't begin with a +slash), it is treated as relative to the ServerRoot. +

    Each line of the user file file contains a username followed +by a colon, followed by the crypt() encrypted password. The behavior +of multiple occurrences of the same user is undefined. +

    +The utility htpasswd which is installed as part of the +binary distribution, or which can be found in src/support, +is used to maintain this password file. See the man +page for more details. In short +

    +

    + htpasswd -c Filename username
    + Create a password file 'Filename' with 'username' + as the initial ID. It will prompt for the password. + htpasswd Filename username2
    + Adds or modifies in password file 'Filename' the 'username'. +
    +

    Note that +searching large text files is very inefficient; +AuthDBMUserFile should be +used instead. +

    + +Security: make sure that the AuthUserFile is stored outside the +document tree of the web-server; do not put it in the directory that +it protects. Otherwise, clients will be able to download the AuthUserFile.

    + +See also AuthName, +AuthType and +AuthGroupFile.

    +


    +

    AuthAuthoritative

    + +Syntax: AuthAuthoritative < + on(default) | off >
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Base
    +Module: mod_auth

    + +Setting the AuthAuthoritative directive explicitly to 'off' +allows for both authentication and authorization to be passed on to +lower level modules (as defined in the Configuration and +modules.c files) if there is no userID or +rule matching the supplied userID. If there is a userID and/or +rule specified; the usual password and access checks will be applied +and a failure will give an Authorization Required reply. + +

    + +So if a userID appears in the database of more than one module; or if +a valid require directive applies to more than one module; then the +first module will verify the credentials; and no access is passed on; +regardless of the AuthAuthoritative setting. + +

    + +A common use for this is in conjunction with one of the database +modules; such as mod_auth_db.c, mod_auth_dbm.c, +mod_auth_msql.c, and mod_auth_anon.c. These modules +supply the bulk of the user credential checking; but a few +(administrator) related accesses fall through to a lower level with a +well protected AuthUserFile. + +

    + +Default: By default; control is not passed on; and an + unknown +userID or rule will result in an Authorization Required reply. Not +setting it thus keeps the system secure; and forces an NCSA compliant +behaviour. + +

    + +Security: Do consider the implications of allowing a user to allow +fall-through in his .htaccess file; and verify that this is really +what you want; Generally it is easier to just secure a single +.htpasswd file, than it is to secure a database such as mSQL. Make +sure that the AuthUserFile is stored outside the document tree of the +web-server; do not put it in the directory that it +protects. Otherwise, clients will be able to download the +AuthUserFile. + +

    +See also AuthName, +AuthType and +AuthGroupFile.

    + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_auth_anon.html b/APACHE_1_3_12/htdocs/manual/mod/mod_auth_anon.html new file mode 100644 index 0000000000..b4708cb95d --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_auth_anon.html @@ -0,0 +1,317 @@ + + + +Apache module mod_auth_anon.c + + + + +

    Module mod_auth_anon

    + +This module is contained in the mod_auth_anon.c file and +is not compiled in by default. It is only available in Apache 1.1 and +later. It allows "anonymous" user access to authenticated areas. + +

    Summary

    + +It does access control in a manner similar to anonymous-ftp sites; i.e. +have a 'magic' user id 'anonymous' and the email address as a password. +These email addresses can be logged. +

    +Combined with other (database) access control methods, this allows for +effective user tracking and customization according to a user profile +while still keeping the site open for 'unregistered' users. One advantage +of using Auth-based user tracking is that, unlike magic-cookies and +funny URL pre/postfixes, it is completely browser independent and it +allows users to share URLs. +

    + +Directives / +Example / +Compile time options / +

    + +

    Directives

    + + +
    + +

    Anonymous directive

    + +Syntax: Anonymous user user ...
    +Default: none
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Extension
    +Module: mod_auth_anon

    + + A list of one or more 'magic' userIDs which are allowed access + without password verification. The userIDs are space separated. + It is possible to use the ' and " quotes to allow a space in + a userID as well as the \ escape character. +

    + Please note that the comparison is case-IN-sensitive. +
    + I strongly suggest that the magic username 'anonymous' + is always one of the allowed userIDs. +

    + Example:
    + + Anonymous anonymous "Not Registered" 'I don\'t know' +

    + This would allow the user to enter without password verification + by using the userId's 'anonymous', 'AnonyMous','Not Registered' and + 'I Don't Know'. +


    + +

    Anonymous_Authoritative directive

    +Syntax: Anonymous_Authoritative on | off
    +Default: Anonymous_Authoritative off
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Extension
    +Module: mod_auth_anon

    + + When set 'on', there is no + fall-through to other authorization methods. So if a + userID does not match the values specified in the + Anonymous directive, access is denied. +

    + Be sure you know what you are doing when you decide to switch + it on. And remember that it is the linking order of the modules + (in the Configuration / Make file) which details the order + in which the Authorization modules are queried. +


    + +

    Anonymous_LogEmail directive

    +Syntax: Anonymous_LogEmail on | off
    +Default: Anonymous_LogEmail on
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Extension
    +Module: mod_auth_anon

    + + When set 'on', the default, the 'password' entered (which hopefully + contains a sensible email address) is logged in the error log. +


    + +

    Anonymous_MustGiveEmail directive

    + +Syntax: Anonymous_MustGiveEmail on + | off
    +Default: Anonymous_MustGiveEmail on
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Extension
    +Module: mod_auth_anon

    + + Specifies whether the user must specify an email + address as the password. This prohibits blank passwords. +


    + +

    Anonymous_NoUserID directive

    +Syntax: Anonymous_NoUserID on | off
    +Default: Anonymous_NoUserID off
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Extension
    +Module: mod_auth_anon

    + + When set 'on', users can leave + the userID (and perhaps the password field) empty. This + can be very convenient for MS-Explorer users who can + just hit return or click directly on the OK button; which + seems a natural reaction. + +


    + +

    Anonymous_VerifyEmail directive

    +Syntax: Anonymous_VerifyEmail on | off
    +Default: Anonymous_VerifyEmail off
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Extension
    +Module: mod_auth_anon

    + + When set 'on' the 'password' entered is + checked for at least one '@' and a '.' to encourage users to enter + valid email addresses (see the above Auth_LogEmail). + +


    +

    Example

    + +The example below (when combined with the Auth directives +of a htpasswd-file based (or GDM, mSQL etc.) base access +control system allows users in as 'guests' with the +following properties: +
      +
    • +It insists that the user enters a userId. (Anonymous_NoUserId) +
    • +It insists that the user enters a password. +(Anonymous_MustGiveEmail) +
    • +The password entered must be a valid email address, ie. contain at least one +'@' and a '.'. (Anonymous_VerifyEmail) +
    • +The userID must be one of anonymous guest www test welcome +and comparison is not case sensitive. +
    • +And the Email addresses entered in the passwd field are logged to +the error log file +(Anonymous_LogEmail) +
    +

    +Excerpt of access.conf: +

    +Anonymous_NoUserId off
    +Anonymous_MustGiveEmail on
    +Anonymous_VerifyEmail on
    +Anonymous_LogEmail on
    +Anonymous anonymous guest www test welcome

    +

    +AuthName "Use 'anonymous' & Email address for guest entry"
    +AuthType basic +

    +# An AuthUserFile/AuthDBUserFile/AuthDBMUserFile
    +# directive must be specified, or use
    +# Anonymous_Authoritative for public access.
    +# In the .htaccess for the public directory, add:
    +<Files *>
    +order deny,allow
    +allow from all
    +

    +require valid-user
    +</Files>
    +

    + +
    +

    Compile Time Options

    + +Currently there are no Compile options. + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_auth_db.html b/APACHE_1_3_12/htdocs/manual/mod/mod_auth_db.html new file mode 100644 index 0000000000..2df31ba261 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_auth_db.html @@ -0,0 +1,220 @@ + + + +Apache module mod_auth_db + + + + + +

    Module mod_auth_db

    + +This module is contained in the mod_auth_db.c file, and +is not compiled in by default. It provides for user authentication using +Berkeley DB files. It is an alternative to DBM +files for those systems which support DB and not DBM. It is only +available in Apache 1.1 and later. + +

    +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 DB. 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. + +

    +
  18. AuthDBGroupFile +
  19. AuthDBUserFile +
  20. AuthDBAuthoritative +
  21. +
    + + +

    AuthDBGroupFile

    + +Syntax: AuthDBGroupFile filename
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Extension
    +Module: mod_auth_db

    + +The AuthDBGroupFile directive sets the name of a DB file containing the list +of user groups for user authentication. Filename is the absolute path +to the group file.

    + +The group file is keyed on the username. The value for a user is a +comma-separated list of the groups to which the users belongs. There must +be no whitespace within the value, and it must never contain any colons.

    + +Security: make sure that the AuthDBGroupFile is stored outside the +document tree of the web-server; do not put it in the directory that +it protects. Otherwise, clients will be able to download the +AuthDBGroupFile unless otherwise protected.

    + +Combining Group and Password DB files: In some cases it is easier to +manage a single database which contains both the password and group +details for each user. This simplifies any support programs that need +to be written: they now only have to deal with writing to and locking +a single DBM file. This can be accomplished by first setting the group +and password files to point to the same DB file:

    + +

    +AuthDBGroupFile /www/userbase
    +AuthDBUserFile /www/userbase +
    + +The key for the single DB record is the username. The value consists of

    + +

    +Unix Crypt-ed Password : List of Groups [ : (ignored) ] +
    + +The password section contains the Unix crypt() password as before. This is +followed by a colon and the comma separated list of groups. Other data may +optionally be left in the DB file after another colon; it is ignored by the +authentication module.

    + +See also AuthName, +AuthType and +AuthDBUserFile.


    + +

    AuthDBUserFile

    + +Syntax: AuthDBUserFile filename
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Extension
    +Module: mod_auth_db

    + +The AuthDBUserFile directive sets the name of a DB file containing the list +of users and passwords for user authentication. Filename is the +absolute path to the user file.

    + +The user file is keyed on the username. The value for a user is the +crypt() encrypted password, optionally followed by a colon and +arbitrary data. The colon and the data following it will be ignored +by the server.

    + +Security: make sure that the AuthDBUserFile is stored outside the +document tree of the web-server; do not put it in the directory that +it protects. Otherwise, clients will be able to download the +AuthDBUserFile.

    + +Important compatibility note: The implementation of "dbmopen" in the +apache modules reads the string length of the hashed values from the +DB data structures, rather than relying upon the string being +NULL-appended. Some applications, such as the Netscape web server, +rely upon the string being NULL-appended, so if you are having trouble +using DB files interchangeably between applications this may be a +part of the problem.

    + +See also AuthName, +AuthType and +AuthDBGroupFile.

    +


    +

    AuthDBAuthoritative

    + +Syntax: AuthDBAuthoritative < + on(default) | off >
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Base
    +Module: mod_auth

    + +Setting the AuthDBAuthoritative directive explicitly to 'off' +allows for both authentication and authorization to be passed on +to lower level modules (as defined in the Configuration +and modules.c file if there is no userID or +rule matching the supplied userID. If there is a userID +and/or rule specified; the usual password and access checks will +be applied and a failure will give an Authorization Required reply. +

    +So if a userID appears in the database of more than one module; or +if a valid require directive applies to more than one module; then +the first module will verify the credentials; and no access is +passed on; regardless of the AuthAuthoritative setting.

    + +A common use for this is in conjunction with one of the basic auth +modules; such as mod_auth.c. +Whereas this DB module supplies the bulk of the user credential +checking; a few (administrator) related accesses fall through to +a lower level with a well protected .htpasswd file.

    + +Default: By default; control is not passed on; and an +unknown +userID or rule will result in an Authorization Required reply. Not +setting it thus keeps the system secure; and forces an NCSA compliant +behaviour.

    +Security: Do consider the implications of allowing a user to allow +fall-through in his .htaccess file; and verify that this is really +what you want; Generally it is easier to just secure a single +.htpasswd file, than it is to secure a database which might have +more access interfaces. + +

    +See also AuthName, +AuthType and +AuthDBGroupFile.

    + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_auth_dbm.html b/APACHE_1_3_12/htdocs/manual/mod/mod_auth_dbm.html new file mode 100644 index 0000000000..36218ef8ee --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_auth_dbm.html @@ -0,0 +1,210 @@ + + + +Apache module mod_auth_dbm + + + + + + +

    Module mod_auth_dbm

    + +This module is contained in the mod_auth_dbm.c file, and +is not compiled in by default. It provides for user authentication using +DBM files. + + + +
  22. AuthDBMGroupFile +
  23. AuthDBMUserFile +
  24. AuthDBMAuthoritative +
  25. +
    + + +

    AuthDBMGroupFile

    + +Syntax: AuthDBMGroupFile filename
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Extension
    +Module: mod_auth_dbm

    + +The AuthDBMGroupFile directive sets the name of a DBM file containing the list +of user groups for user authentication. Filename is the absolute path +to the group file.

    + +The group file is keyed on the username. The value for a user is a +comma-separated list of the groups to which the users belongs. There must +be no whitespace within the value, and it must never contain any colons.

    + +Security: make sure that the AuthDBMGroupFile is stored outside the +document tree of the web-server; do not put it in the directory that +it protects. Otherwise, clients will be able to download the +AuthDBMGroupFile unless otherwise protected.

    + +Combining Group and Password DBM files: In some cases it is easier to +manage a single database which contains both the password and group +details for each user. This simplifies any support programs that need +to be written: they now only have to deal with writing to and locking +a single DBM file. This can be accomplished by first setting the group +and password files to point to the same DBM:

    + +

    +AuthDBMGroupFile /www/userbase
    +AuthDBMUserFile /www/userbase +
    + +The key for the single DBM is the username. The value consists of

    + +

    +Unix Crypt-ed Password : List of Groups [ : (ignored) ] +
    + +The password section contains the Unix crypt() password as before. This is +followed by a colon and the comma separated list of groups. Other data may +optionally be left in the DBM file after another colon; it is ignored by the +authentication module. This is what www.telescope.org uses for its combined +password and group database.

    + +See also AuthName, +AuthType and +AuthDBMUserFile.


    + +

    AuthDBMUserFile

    + +Syntax: AuthDBMUserFile filename
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Extension
    +Module: mod_auth_dbm

    + +The AuthDBMUserFile directive sets the name of a DBM file containing the list +of users and passwords for user authentication. Filename is the +absolute path to the user file.

    + +The user file is keyed on the username. The value for a user is the +crypt() encrypted password, optionally followed by a colon and +arbitrary data. The colon and the data following it will be ignored +by the server.

    + +Security: make sure that the AuthDBMUserFile is stored outside the +document tree of the web-server; do not put it in the directory that +it protects. Otherwise, clients will be able to download the +AuthDBMUserFile.

    + +Important compatibility note: The implementation of "dbmopen" in the +apache modules reads the string length of the hashed values from the +DBM data structures, rather than relying upon the string being +NULL-appended. Some applications, such as the Netscape web server, +rely upon the string being NULL-appended, so if you are having trouble +using DBM files interchangeably between applications this may be a +part of the problem.

    + +See also AuthName, +AuthType and +AuthDBMGroupFile.

    + +


    +

    AuthDBMAuthoritative

    + +Syntax: AuthDBMAuthoritative < on(default) | off >
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Base
    +Module: mod_auth

    + +Setting the AuthDBMAuthoritative directive explicitly to 'off' +allows for both authentication and authorization to be passed on +to lower level modules (as defined in the Configuration +and modules.c file if there is no userID or +rule matching the supplied userID. If there is a userID +and/or rule specified; the usual password and access checks will +be applied and a failure will give an Authorization Required reply. +

    +So if a userID appears in the database of more than one module; or +if a valid require directive applies to more than one module; then +the first module will verify the credentials; and no access is +passed on; regardless of the AuthAuthoritative setting.

    + +A common use for this is in conjunction with one of the basic auth +modules; such as mod_auth.c. +Whereas this DBM module supplies the bulk of the user credential +checking; a few (administrator) related accesses fall through to +a lower level with a well protected .htpasswd file.

    + +Default: By default; control is not passed on; and an unknown +userID or rule will result in an Authorization Required reply. Not +setting it thus keeps the system secure; and forces an NCSA compliant +behaviour.

    + +Security: Do consider the implications of allowing a user to allow +fall-through in his .htaccess file; and verify that this is really +what you want; Generally it is easier to just secure a single +.htpasswd file, than it is to secure a database which might have +more access interfaces. + +

    +See also AuthName, +AuthType and +AuthDBMGroupFile.

    + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_auth_digest.html b/APACHE_1_3_12/htdocs/manual/mod/mod_auth_digest.html new file mode 100644 index 0000000000..97fc96f1b4 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_auth_digest.html @@ -0,0 +1,416 @@ + + + +Apache module mod_auth_digest + + + + + +

    Module mod_auth_digest

    + +This module is contained in the mod_auth_digest.c file, and is +not compiled in by default. It is only available in Apache 1.3.8 and +later. It provides for user authentication using MD5 Digest +Authentication. + +

    Note this is an updated version of mod_digest. However, it has not been +extensively tested and is therefore marked experimental. If you use this +module, you must make sure to not use mod_digest (because they +share some of the same configuration directives). + + +

    +
  26. AuthDigestFile +
  27. AuthDigestGroupFile +
  28. AuthDigestQop +
  29. AuthDigestNonceLifetime +
  30. AuthDigestNonceFormat +
  31. AuthDigestNcCheck +
  32. AuthDigestAlgorithm +
  33. AuthDigestDomain +
  34. Using Digest Authentication +
  35. +
    + + +

    AuthDigestFile

    +Syntax: AuthDigestFile filename
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Base
    +Module: mod_auth_digest
    + +

    The AuthDigestFile directive sets the name of a textual file containing +the list of users and encoded passwords for digest authentication. +Filename is the absolute path to the user file. + +

    The digest file uses a special format. Files in this format can be +created using the "htdigest" utility found in the support/ subdirectory of +the Apache distribution. + +


    + +

    AuthDigestGroupFile

    +Syntax: AuthDigestGroupFile filename
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Base
    +Module: mod_auth_digest
    +Compatibility: Available in Apache 1.3.8 and later + +

    The AuthDigestGroupFile directive sets the name of a textual file +containing the list of groups and their members (user names). +Filename is the absolute path to the group file. + +

    Each line of the group file contains a groupname followed by a colon, +followed by the member usernames separated by spaces. Example: +

    mygroup: bob joe anne
    +Note that searching large text files is very inefficient. + +

    Security: make sure that the AuthGroupFile is stored outside the +document tree of the web-server; do not put it in the directory +that it protects. Otherwise, clients will be able to download the +AuthGroupFile. + +


    + +

    AuthDigestQop

    +Syntax: AuthDigestQop none | 1*{ auth | auth-int }
    +Default: AuthDigestQop auth
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Base
    +Module: mod_auth_digest
    +Compatibility: Available in Apache 1.3.8 and later + +

    The AuthDigestQop directive determines the quality-of-protection to use. +auth will only do authentication (username/password); +auth-int is authentication plus integrity checking (an MD5 hash +of the entity is also computed and checked); none will cause the +module to use the old RFC-2069 digest algorithm (which does not include +integrity checking). Both auth and auth-int may be +specified, in which the case the browser will choose which of these to +use. none should only be used if the browser for some reason +does not like the challenge it receives otherwise. + +

    auth-int is not implemented yet. + +


    + +

    AuthDigestNonceLifetime

    +Syntax: AuthDigestNonceLifetime <time>
    +Default: AuthDigestNonceLifetime 300
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Base
    +Module: mod_auth_digest
    +Compatibility: Available in Apache 1.3.8 and later + +

    The AuthDigestNonceLifetime directive controls how long the server +nonce is valid. When the client contacts the server using an expired +nonce the server will send back a 401 with stale=true. If +<time> is greater than 0 then it specifies the number of +seconds the nonce is valid; this should probably never be set to less +than 10 seconds. If <time> is less than 0 then the nonce +never expires. + + + +


    +

    AuthDigestNonceFormat

    +Syntax: AuthDigestNonceFormat ???
    +Default: AuthDigestNonceFormat ???
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Base
    +Module: mod_auth_digest
    +Compatibility: Available in Apache 1.3.8 and later + +

    Not implemented yet. + + +


    +

    AuthDigestNcCheck

    +Syntax: AuthDigestNcCheck On/Off
    +Default: AuthDigestNcCheck Off
    +Context: server config
    +Override: Not applicable
    +Status: Base
    +Module: mod_auth_digest
    +Compatibility: Available in Apache 1.3.8 and later + +

    Not implemented yet. + + +


    +

    AuthDigestAlgorithm

    +Syntax: AuthDigestAlgorithm MD5 | MD5-sess
    +Default: AuthDigestAlgorithm MD5
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Base
    +Module: mod_auth_digest
    +Compatibility: Available in Apache 1.3.8 and later + +

    The AuthDigestAlgorithm directive selects the algorithm used to calculate +the challenge and response hashes. + +

    MD5-sess is not correctly implemented yet. + + +


    +

    AuthDigestDomain

    +Syntax: AuthDigestDomain URI URI ...
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Base
    +Module: mod_auth_digest
    +Compatibility: Available in Apache 1.3.8 and later + +

    The AuthDigestDomain directive allows you to specify one or more URIs +which are in the same protection space (i.e. use the same realm and +username/password info). The specified URIs are prefixes, i.e. the client +will assume that all URIs "below" these are also protected by the same +username/password. The URIs may be either absolute URIs (i.e. inluding a +scheme, host, port, etc) or relative URIs. + +

    This directive should always be specified and contain at least +the (set of) root URI(s) for this space. Omitting to do so will cause the +client to send the Authorization header for every request sent to +this server. Apart from increasing the size of the request, it may also +have a detrimental effect on performance if "AuthDigestNcCheck" is on. + +

    The URIs specified can also point to different servers, in which case +clients (which understand this) will then share username/password info +across multiple servers without prompting the user each time. + + +


    + +

    Using Digest Authentication

    + +

    Using MD5 Digest authentication is very simple. Simply set up +authentication normally, using "AuthType Digest" and "AuthDigestFile" +instead of the normal "AuthType Basic" and "AuthUserFile"; also, +replace any "AuthGroupFile" with "AuthDigestGroupFile". Then add a +"AuthDigestDomain" directive containing at least the root URI(s) for +this protection space. Example: + +

    +  <Location /private/>
    +  AuthType Digest
    +  AuthName "private area"
    +  AuthDigestDomain /private/ http://mirror.my.dom/private2/
    +  AuthDigestFile /web/auth/.digest_pw
    +  require valid-user
    +  </Location>
    +
    + +

    Note: MD5 authentication provides a more secure +password system than Basic authentication, but only works with supporting +browsers. As of this writing (July 1999), the only major browsers which +support digest authentication are Internet Explorer 5.0 and +Amaya. Therefore, we do not +recommend using this feature on a large Internet site. However, for +personal and intra-net use, where browser users can be controlled, it is +ideal. + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_autoindex.html b/APACHE_1_3_12/htdocs/manual/mod/mod_autoindex.html new file mode 100644 index 0000000000..b39ed5c0f8 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_autoindex.html @@ -0,0 +1,851 @@ + + + +Apache module mod_autoindex + + + + + +

    Module mod_autoindex

    + +This module is contained in the mod_autoindex.c file, and +is compiled in by default. It provides for automatic directory indexing. + +

    Summary

    +The index of a directory can come from one of two sources: +
      +
    • A file written by the user, typically called index.html. +The DirectoryIndex directive sets +the name of this file. +This is controlled by mod_dir. +
    • Otherwise, a listing generated by the server. The other directives +control the format of this listing. The AddIcon, +AddIconByEncoding and +AddIconByType are used to set a list of +icons to display for various file types; for each file listed, the +first icon listed that matches the file is displayed. These +are controlled by mod_autoindex. +
    +The two functions are separated so that you can completely remove +(or replace) automatic index generation should you want to. +

    +If +FancyIndexing +is enabled, or the FancyIndexing keyword is present on the +IndexOptions +directive, the column headers are links that control the +order of the display. If you select a header link, the +listing will be regenerated, sorted by the values in that +column. Selecting the same header repeatedly toggles +between ascending and descending order. +

    +

    +Note that when the display is sorted by "Size", +it's the actual size of the files that's used, +not the displayed value - so a 1010-byte file will +always be displayed before a 1011-byte file (if in ascending +order) even though they both are shown as "1K". +

    + + +

    Directives

    + + +
  36. AddAlt +
  37. AddAltByEncoding +
  38. AddAltByType +
  39. AddDescription +
  40. AddIcon +
  41. AddIconByEncoding +
  42. AddIconByType +
  43. DefaultIcon +
  44. FancyIndexing +
  45. HeaderName +
  46. IndexIgnore +
  47. IndexOptions +
  48. IndexOrderDefault +
  49. ReadmeName +
  50. +
    + +

    AddAlt

    + +Syntax: AddAlt string file file...
    +Context: server config, virtual host, directory, + .htaccess
    +Override: Indexes
    +Status: Base
    +Module: mod_autoindex

    + +This sets the alternate text to display for a file, instead of an icon, for +FancyIndexing. File is a file +extension, partial filename, wild-card expression or full filename for files +to describe. String is enclosed in double quotes +("). This alternate text is displayed if the client is +image-incapable or has image loading disabled. + +


    +

    AddAltByEncoding

    + +Syntax: AddAltByEncoding string MIME-encoding + MIME-encoding...
    +Context: server config, virtual host, directory, + .htaccess
    +Override: Indexes
    +Status: Base
    +Module: mod_autoindex

    + +This sets the alternate text to display for a file, instead of an icon, for +FancyIndexing. MIME-encoding is a +valid content-encoding, such as x-compress. +String is enclosed in double quotes +("). This alternate text is displayed if the client is +image-incapable or has image loading disabled. + +


    +

    AddAltByType

    + +Syntax: AddAltByType string MIME-type MIME-type + ...
    +Context: server config, virtual host, directory, + .htaccess
    +Override: Indexes
    +Status: Base
    +Module: mod_autoindex

    + +This sets the alternate text to display for a file, instead of an icon, for +FancyIndexing. MIME-type is a +valid content-type, such as text/html. +String is enclosed in double quotes +("). This alternate text is displayed if the client is +image-incapable or has image loading disabled. + +


    + +

    AddDescription

    + +Syntax: AddDescription string file file...
    +Context: server config, virtual host, directory, + .htaccess
    +Override: Indexes
    +Status: Base
    +Module: mod_autoindex

    + +This sets the description to display for a file, for +FancyIndexing. File is a file +extension, partial filename, wild-card expression or full filename for files +to describe. String is enclosed in double quotes +("). Example: +

    AddDescription "The planet Mars" /web/pics/mars.gif +
    +

    +The description field is 23 bytes wide. 7 more bytes may be +added if the directory is covered by an +IndexOptions SuppressSize, and 19 bytes may be +added if IndexOptions SuppressLastModified is +in effect. The widest this column can be is therefore 49 bytes. +

    +As of Apache 1.3.10, the +DescriptionWidth +IndexOptions keyword allows you to adjust this width +to any arbitrary size. +
    +Caution: Descriptive text defined with AddDescription +may contain HTML markup, such as tags and character entities. If the +width of the description column should happen to truncate a tagged +element (such as cutting off the end of a bolded phrase), the results +may affect the rest of the directory listing. +

    +
    + +

    AddIcon

    + +Syntax: AddIcon icon name name ...
    +Context: server config, virtual host, directory, + .htaccess
    +Override: Indexes
    +Status: Base
    +Module: mod_autoindex

    + +This sets the icon to display next to a file ending in name for +FancyIndexing. Icon is either a +(%-escaped) relative URL to the icon, or of the format +(alttext,url) where alttext is the text tag given +for an icon for non-graphical browsers.

    + +Name is either ^^DIRECTORY^^ for directories, ^^BLANKICON^^ for +blank lines (to format the list correctly), a file extension, a wildcard +expression, a partial filename or a complete filename. Examples: +

    +AddIcon (IMG,/icons/image.xbm) .gif .jpg .xbm
    +AddIcon /icons/dir.xbm ^^DIRECTORY^^
    +AddIcon /icons/backup.xbm *~ +
    +AddIconByType should be used in preference to +AddIcon, when possible.


    + +

    AddIconByEncoding

    + +Syntax: AddIconByEncoding icon MIME-encoding + MIME-encoding ...
    +Context: server config, virtual host, directory, + .htaccess
    +Override: Indexes
    +Status: Base
    +Module: mod_autoindex

    + +This sets the icon to display next to files with +MIME-encoding for FancyIndexing. +Icon is either a (%-escaped) relative URL to the icon, or of the +format (alttext,url) where alttext is the text tag +given for an icon for non-graphical browsers.

    + +Mime-encoding is a wildcard expression matching required the +content-encoding. Examples: +

    +AddIconByEncoding /icons/compress.xbm x-compress +


    + +

    AddIconByType

    + +Syntax: AddIconByType icon MIME-type MIME-type + ...
    +Context: server config, virtual host, directory, + .htaccess
    +Override: Indexes
    +Status: Base
    +Module: mod_autoindex

    + +This sets the icon to display next to files of type MIME-type for +FancyIndexing. Icon is either a +(%-escaped) relative URL to the icon, or of the format +(alttext,url) where alttext is the text tag given +for an icon for non-graphical browsers.

    +Mime-type is a wildcard expression matching required the mime types. +Examples: +

    +AddIconByType (IMG,/icons/image.xbm) image/* +


    + +

    DefaultIcon

    + +Syntax: DefaultIcon url
    +Context: server config, virtual host, directory, + .htaccess
    +Override: Indexes
    +Status: Base
    +Module: mod_autoindex

    + +The DefaultIcon directive sets the icon to display for files when no +specific icon is known, for FancyIndexing. +Url is a (%-escaped) relative URL to the icon. Examples: +

    +DefaultIcon /icon/unknown.xbm +


    + +

    FancyIndexing

    + +Syntax: FancyIndexing boolean
    +Context: server config, virtual host, directory, + .htaccess
    +Override: Indexes
    +Status: Base
    +Module: mod_autoindex +

    +The FancyIndexing directive sets the FancyIndexing option for a directory. +Boolean can be on or off. The +IndexOptions directive should be used in +preference. +

    +
    + Note that in versions of Apache prior to 1.3.2, the + FancyIndexing and + IndexOptions directives will override each other. You + should use IndexOptions FancyIndexing in preference + to the standalone FancyIndexing directive. + As of Apache 1.3.2, a standalone FancyIndexing directive + is combined with any IndexOptions directive already + specified for the current scope. +
    +
    + +

    HeaderName

    + +Syntax: HeaderName filename
    +Context: server config, virtual host, directory, + .htaccess
    +Override: Indexes
    +Status: Base
    +Module: mod_autoindex +
    + Compatibility: some features only available after + 1.3.6; see text + +

    +The HeaderName directive sets the name of the file that will be inserted +at the top of the index listing. Filename is the name of the file +to include. +

    +
    Apache 1.3.6 and earlier: +The module first attempts to include filename.html +as an HTML document, otherwise it will try to include filename as +plain text. Filename is treated as a filesystem path relative +to the directory being indexed. In no case is SSI processing done. +Example: +
    HeaderName HEADER
    +when indexing the directory /web, the server will first look for +the HTML file /web/HEADER.html and include it if found, otherwise +it will include the plain text file /web/HEADER, if it exists. +
    +
    Apache versions after 1.3.6: +Filename is treated as a URI path relative to the one used +to access the directory being indexed, and must resolve to a document +with a major content type of "text" (e.g., +text/html, text/plain, etc.). +This means that filename may refer to a CGI script if the +script's actual file type (as opposed to its output) is marked as +text/html such as with a directive like: +
    +    AddType text/html .cgi
    +
    +Content negotiation +will be performed if the MultiViews +option is enabled. +If filename resolves to a static text/html document +(not a CGI script) and the +Includes option is enabled, +the file will be processed for server-side includes (see the +mod_include documentation). +
    +

    +See also ReadmeName. +


    + +

    IndexIgnore

    + +Syntax: IndexIgnore file file ...
    +Context: server config, virtual host, directory, + .htaccess
    +Override: Indexes
    +Status: Base
    +Module: mod_autoindex

    + +The IndexIgnore directive adds to the list of files to hide when listing +a directory. File is a file extension, partial filename, +wildcard expression or full filename for files to ignore. Multiple +IndexIgnore directives add to the list, rather than the replacing the list +of ignored files. By default, the list contains `.'. Example: +

    +IndexIgnore README .htaccess *~ +


    + +

    IndexOptions

    + +Syntax: IndexOptions option option ... + (Apache 1.3.2 and earlier) +
    +Syntax: IndexOptions [+|-]option [+|-]option + ... + (Apache 1.3.3 and later) +
    +Context: server config, virtual host, directory, + .htaccess
    +Override: Indexes
    +Status: Base
    +Module: mod_autoindex +
    +Compatibility: '+/-' syntax and merging of multiple + IndexOptions directives is only available with + Apache 1.3.3 and later; the FoldersFirst and + DescriptionWidth options are only + available with Apache 1.3.10 and later +

    + +The IndexOptions directive specifies the behavior of the directory indexing. +Option can be one of +

    +
    DescriptionWidth=[n | *] + (Apache 1.3.10 and later) +
    +The DescriptionWidth keyword allows you to specify the +width of the description column in characters. If the keyword value +is '*', then the column is automatically sized to the +length of the longest filename in the display. +See the section on AddDescription +for dangers inherent in truncating descriptions.
    +
    FancyIndexing +
    +This turns on fancy indexing of directories. +
    + Note that in versions of Apache prior to 1.3.2, the + FancyIndexing and + IndexOptions directives will override each other. You + should use IndexOptions FancyIndexing in preference + to the standalone FancyIndexing directive. + As of Apache 1.3.2, a standalone FancyIndexing directive + is combined with any IndexOptions directive already + specified for the current scope. +
    +
    FoldersFirst + (Apache 1.3.10 and later)
    +
    +If this option is enabled, subdirectories in a FancyIndexed listing +will always appear first, followed by normal files in the +directory. The listing is basically broken into two components, +the files and the subdirectories, and each is sorted separately and +then displayed subdirectories-first. For instance, if the sort order +is descending by name, and FoldersFirst is enabled, +subdirectory Zed will be listed before subdirectory +Beta, which will be listed before normal files +Gamma and Alpha. +This option only has an effect if +FancyIndexing +is also enabled.
    +
    IconHeight[=pixels] (Apache 1.3 and later) +
    + +Presence of this option, when used with IconWidth, will cause the server +to include HEIGHT and WIDTH attributes in the +IMG tag for the file icon. This allows browser to +precalculate the page layout without having to wait until all the +images have been loaded. If no value is given for the option, it +defaults to the standard height of the icons supplied with the Apache +software. +
    IconsAreLinks +
    + +This makes the icons part of the anchor for the filename, for +fancy indexing. +
    IconWidth[=pixels] (Apache 1.3 and later) +
    + +Presence of this option, when used with IconHeight, will cause the server +to include HEIGHT and WIDTH attributes in the +IMG tag for the file icon. This allows browser to +precalculate the page layout without having to wait until all the +images have been loaded. If no value is given for the option, it +defaults to the standard width of the icons supplied with the Apache +software. +
    NameWidth=[n | *] (Apache 1.3.2 and later) +
    +The NameWidth keyword allows you to specify the width of the +filename column in bytes. If the keyword value is '*', +then the column is automatically sized to the length of the longest +filename in the display. +
    ScanHTMLTitles +
    +This enables the extraction of the title from HTML documents for fancy +indexing. If the file does not have a description given by +AddDescription then httpd will read the +document for the value of the TITLE tag. This is CPU and disk intensive. +
    SuppressColumnSorting +
    + +If specified, Apache will not make the column headings in a FancyIndexed +directory listing into links for sorting. The default behaviour is +for them to be links; selecting the column heading will sort the directory +listing by the values in that column. +Only available in Apache 1.3 and later. +
    SuppressDescription +
    + +This will suppress the file description in fancy indexing listings. +
    SuppressHTMLPreamble + (Apache 1.3 and later) +
    + +If the directory actually contains a file specified by the +HeaderName +directive, the module usually includes the contents of the file +after a standard HTML preamble (<HTML>, <HEAD>, et +cetera). The SuppressHTMLPreamble option disables this behaviour, +causing the module to start the display with the header file contents. +The header file must contain appropriate HTML instructions in this case. +If there is no header file, the preamble is generated as usual. +
    SuppressLastModified +
    + +This will suppress the display of the last modification date, in fancy +indexing listings. +
    SuppressSize +
    + +This will suppress the file size in fancy indexing listings. +
    +

    +There are some noticeable differences in the behaviour of this +directive in recent (post-1.3.0) versions of Apache. +

    +
    +
    Apache 1.3.2 and earlier:
    +
    +

    +The default is that no options are enabled. If multiple IndexOptions +could apply to a directory, then the most specific one is taken complete; +the options are not merged. For example: +

    +<Directory /web/docs>
    +    IndexOptions FancyIndexing
    +</Directory>
    +<Directory /web/docs/spec>
    +    IndexOptions ScanHTMLTitles
    +</Directory>
    +
    +then only ScanHTMLTitles will be set for the /web/docs/spec +directory. +

    +
    +
    Apache 1.3.3 and later:
    +
    +

    +Apache 1.3.3 introduced some significant changes in the handling of +IndexOptions directives. In particular, +

    +
      +
    • Multiple IndexOptions directives for a single + directory are now merged together. The result of the example above + will now be the equivalent of + IndexOptions FancyIndexing ScanHTMLTitles. +
    • +
    • The addition of the incremental syntax (i.e., prefixing + keywords with '+' or '-'). +
    • +
    +

    +Whenever a '+' or '-' prefixed keyword is encountered, it is applied +to the current IndexOptions settings (which may have been +inherited from an upper-level directory). However, whenever an unprefixed +keyword is processed, it clears all inherited options and any incremental +settings encountered so far. Consider the following example: +

    +
    IndexOptions +ScanHTMLTitles -IconsAreLinks FancyIndexing +
    +IndexOptions +SuppressSize +
    +
    +

    +The net effect is equivalent to +IndexOptions FancyIndexing +SuppressSize, because +the unprefixed FancyIndexing discarded the incremental +keywords before it, but allowed them to start accumulating again +afterward. +

    +

    +To unconditionally set the IndexOptions for a +particular directory, clearing the inherited settings, specify +keywords without either '+' or '-' prefixes. +

    +
    +
    + +
    + +

    IndexOrderDefault

    + +Syntax: IndexOrderDefault + Ascending|Descending Name|Date|Size|Description +
    +Context: server config, virtual host, directory, + .htaccess +
    +Override: Indexes +
    +Status: Base +
    +Module: mod_autoindex +
    +Compatibility: IndexOrderDefault is only available in +Apache 1.3.4 and later. + +

    +The IndexOrderDefault directive is used in combination with +the FancyIndexing +index option. By default, fancyindexed directory listings are displayed in ascending order by filename; the IndexOrderDefault allows +you to change this initial display order. +

    +

    +IndexOrderDefault takes two arguments. The first must be either +Ascending or Descending, indicating the direction +of the sort. The second argument must be one of the keywords +Name, Date, Size, or +Description, and identifies the primary key. The secondary +key is always the ascending filename. +

    +

    +You can force a directory listing to only be displayed in a particular +order by combining this directive with the +SuppressColumnSorting index option; this will prevent +the client from requesting the directory listing in a different order. +

    + +
    + +

    ReadmeName

    + +Syntax: ReadmeName filename
    +Context: server config, virtual host, directory, + .htaccess
    +Override: Indexes
    +Status: Base
    +Module: mod_autoindex +
    + Compatibility: some features only available after + 1.3.6; see text + +

    +The ReadmeName directive sets the name of the file that will be appended +to the end of the index listing. Filename is the name of the file +to include, and is taken to be relative to the location being indexed. +

    +
    +The filename argument is treated as a stub filename +in Apache 1.3.6 and earlier, and as a relative URI in later versions. +Details of how it is handled may be found under the description of +the HeaderName directive, which uses the +same mechanism and changed at the same time as ReadmeName. +
    +

    See also HeaderName.

    + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_browser.html b/APACHE_1_3_12/htdocs/manual/mod/mod_browser.html new file mode 100644 index 0000000000..866f15a074 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_browser.html @@ -0,0 +1,120 @@ + + + +Apache module mod_browser + + + + + +

    Module mod_browser

    + +This module is contained in the mod_browser.c file, and +is compiled in by default. It provides for setting environment +variables based on the browser. This module is part of Apache 1.2.* +only. From Apache 1.3 onwards mod_setenvif provides the functionality +of this module. + +

    Summary

    + +

    This module allows you to set environment variables based on the name of +the browser accessing your document, based on the User-Agent +header field. This is especially useful when combined with a conditional +HTML language such as XSSI or PHP, and +can provide for simple browser-based negotiation of HTML features.

    + +

    Directives

    + + +
    + +

    BrowserMatch

    +Syntax: BrowserMatch regex attr1 attr2...
    +Context: server config
    +Status: base
    +Module: mod_browser
    +Compatibility: Apache 1.2 and above

    + +The BrowserMatch directive defines environment variables based on the +User-Agent +header. The first argument should be a POSIX.2 extended regular +expression (similar to an egrep-style regex). The rest of the arguments +give names of variables to set. These take the form of either +"varname", "!varname" or +"varname=value". In the first form, the value will be set +to "1". The second will remove the given variable if already defined, +and the third will set the variable to the value given by value. If a User-Agent +string matches more than one entry, they will +be merged. Entries are processed in the order they appear, and later +entries can override earlier ones. + +

    For example:

    +
    +    BrowserMatch ^Mozilla forms jpeg=yes browser=netscape
    +    BrowserMatch "^Mozilla/[2-3]" tables agif frames javascript
    +    BrowserMatch MSIE !javascript
    +
    + +

    BrowserMatchNoCase

    +Syntax: BrowserMatchNoCase regex attr1 attr2...
    +Context: server config
    +Status: base
    +Module: mod_browser
    +Compatibility: Apache 1.2 and above + +

    The BrowserMatchNoCase directive is semantically identical to + the BrowserMatch + directive. However, it provides for case-insensitive matching. For + example:

    +
    +    BrowserMatchNoCase mac platform=macintosh
    +    BrowserMatchNoCase win platform=windows
    +
    + + +

    + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_cern_meta.html b/APACHE_1_3_12/htdocs/manual/mod/mod_cern_meta.html new file mode 100644 index 0000000000..0ac5282421 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_cern_meta.html @@ -0,0 +1,143 @@ + + + +Module mod_cern_meta + + + + + +

    Apache module mod_cern_meta

    + +This module is contained in the mod_cern_meta.c file, and +is not compiled in by default. It provides for CERN httpd metafile +semantics. It is only available in Apache 1.1 and later. + +

    Summary

    + +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. + +

    More information on the +CERN metafile semantics is available. + +

    Directives

    + + +
    + +

    MetaFiles

    +Syntax: MetaFiles on/off
    +Default: MetaFiles off
    +Context: per-directory config
    +Status: Base
    +Module: mod_cern_meta
    +Compatibility: MetaFiles is only available in Apache 1.3 +and later.

    + +Turns on/off Meta file processing on a per-directory basis. This option was introduced in Apache 1.3. + +

    MetaDir

    +Syntax: MetaDir directory name
    +Default: MetaDir .web
    +Context: (Apache prior to 1.3) server config
    +Context: (Apache 1.3) per-directory config
    +Status: Base
    +Module: mod_cern_meta
    +Compatibility: MetaDir is only available in Apache 1.1 +and later.

    + +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. Set to "." to look in the same directory as the +file. + +

    MetaSuffix

    +Syntax: MetaSuffix suffix
    +Default: MetaSuffix .meta
    +Context: (Apache prior to 1.3) server config
    +Context: (Apache 1.3) per-directory config
    +Status: Base
    +Module: mod_cern_meta
    +Compatibility: MetaSuffix is only available in Apache 1.1 +and later.

    + +Specifies the file name suffix for the file containing the +meta information. For example, the default values for the two +directives will cause a request to +DOCUMENT_ROOT/somedir/index.html to look in +DOCUMENT_ROOT/somedir/.web/index.html.meta and will use +its contents to generate additional MIME header information. + +

    + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_cgi.html b/APACHE_1_3_12/htdocs/manual/mod/mod_cgi.html new file mode 100644 index 0000000000..1d5df58f60 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_cgi.html @@ -0,0 +1,216 @@ + + + +Apache module mod_cgi + + + + + + +

    Module mod_cgi

    + +This module is contained in the mod_cgi.c file, and +is compiled in by default. It provides for execution of CGI scripts. +Any file with mime type application/x-httpd-cgi will be +processed by this module. + + + +

    Summary

    +Any file that has the mime type application/x-httpd-cgi +or handler cgi-script (Apache 1.1 or later) +will be treated as a CGI script, and run by the server, with its output +being returned to the client. Files acquire this type either by +having a name containing an extension defined by the +AddType directive, or by being in +a ScriptAlias directory.

    + +When the server invokes a CGI script, it will add a variable called +DOCUMENT_ROOT to the environment. This variable will contain the +value of the DocumentRoot +configuration variable. + +

    CGI Environment variables

    +The server will set the CGI environment variables as described in the +CGI specification, with the +following provisions: +
    +
    REMOTE_HOST +
    This will only be set if HostnameLookups +is set to on (it is off by default), and if a reverse DNS +lookup of the accessing host's address indeed finds a host name. +
    REMOTE_IDENT +
    This will only be set if +IdentityCheck is set to on +and the accessing host supports the ident protocol. Note that the contents +of this variable cannot be relied upon because it can easily be faked, and if +there is a proxy between the client and the server, it is usually +totally useless. +
    REMOTE_USER +
    This will only be set if the CGI script is subject to authentication. +
    +

    + +


    + +

    CGI Debugging

    + +Debugging CGI scripts has traditionally been difficult, mainly because +it has +not +been possible to study the output (standard output and error) for +scripts +which are failing to run properly. These directives, included in +Apache 1.2 and later, provide +more detailed logging of errors when they occur. + +
    + +

    CGI Logfile Format

    + +When configured, the CGI error log logs any CGI which does not execute +properly. Each CGI script which fails to operate causes several lines +of information to be logged. The first two lines are always of the +format: + +
    +  %% [time] request-line
    +  %% HTTP-status CGI-script-filename
    +
    + +If the error is that CGI script cannot be run, the log file will +contain +an extra two lines: + +
    +  %%error
    +  error-message
    +
    + +Alternatively, if the error is the result of the script returning +incorrect header information (often due to a bug in the script), the +following information is logged: + +
    +  %request
    +  All HTTP request headers received
    +  POST or PUT entity (if any)
    +  %response
    +  All headers output by the CGI script
    +  %stdout
    +  CGI standard output
    +  %stderr
    +  CGI standard error
    +
    + +(The %stdout and %stderr parts may be missing if the script did not +output +anything on standard output or standard error). + +
    + +

    Directives

    + +

    ScriptLog

    + +Syntax: ScriptLog filename
    +Default: none
    +Context: server config
    +Status: mod_cgi +

    + +The ScriptLog directive sets the CGI script error logfile. +If no ScriptLog is given, no error log is created. If given, any +CGI errors are logged into the filename given as argument. If this +is a relative file or path it is taken relative to the server root. + +

    This log will be opened as the user the child processes run as, +ie. the user specified in the main User +directive. This means that either the directory the script log is +in needs to be writable by that user or the file needs to be manually +created and set to be writable by that user. If you place the +script log in your main logs directory, do NOT +change the directory permissions to make it writable by the user +the child processes run as.

    + +

    Note that script logging is meant to be a debugging feature when +writing CGI scripts, and is not meant to be activated continuously on +running servers. It is not optimized for speed or efficiency, and may +have security problems if used in a manner other than that for which +it was designed.

    + +

    ScriptLogLength

    + +Syntax: ScriptLogLength size
    +Default: 10385760
    +Context: server config
    +Status: mod_cgi +

    + +ScriptLogLength can be used to limit the size of the CGI +script logfile. Since the logfile logs a lot of information per CGI +error (all request headers, all script output) it can grow to be a big +file. To prevent problems due to unbounded growth, this directive can +be used to set an maximum file-size for the CGI logfile. If the file +exceeds this size, no more information will be written to it. + +

    ScriptLogBuffer

    + +Syntax: ScriptLogBuffer size
    +Default: 1024
    +Context: server config
    +Status: mod_cgi +

    + +The size of any PUT or POST entity body that is logged to the file is +limited, to prevent the log file growing too big too quickly if large +bodies are being received. By default, up to 1024 bytes are logged, +but this can be changed with this directive. + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_cookies.html b/APACHE_1_3_12/htdocs/manual/mod/mod_cookies.html new file mode 100644 index 0000000000..6eb44aa04d --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_cookies.html @@ -0,0 +1,59 @@ + + + +Apache module mod_cookies + + + + + +

    Module mod_cookies

    + +This module is obsolete. As of version +1.2 of Apache, it has been replaced with +mod_usertrack. + +

    This module is contained in the mod_cookies.c file, and +is not compiled in by default. It provides for Netscape(TM) cookies. +There is no documentation available for this module. + + +

    +
  51. CookieLog +
  52. +
    + + +

    CookieLog

    + +Syntax: CookieLog filename
    +Context: server config, virtual host
    +Status: Experimental
    +Module: mod_cookies

    + +The CookieLog directive sets the filename for logging of cookies. +The filename is relative to the ServerRoot. +

    + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_digest.html b/APACHE_1_3_12/htdocs/manual/mod/mod_digest.html new file mode 100644 index 0000000000..f5803cca51 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_digest.html @@ -0,0 +1,80 @@ + + + +Apache module mod_digest + + + + + +

    Module mod_digest

    + +This module is contained in the mod_digest.c file, and is +not compiled in by default. It is only available in Apache 1.1 and +later. It provides for user authentication using MD5 Digest +Authentication. + + + +
  53. AuthDigestFile +
  54. +
    + + +

    AuthDigestFile

    +Syntax: AuthDigestFile filename
    +Context: directory, .htaccess
    +Override: AuthConfig
    +Status: Base
    +Module: mod_digest

    + +

    The AuthDigestFile directive sets the name of a textual file containing +the list +of users and encoded passwords for digest authentication. +Filename +is the absolute path to the user file.

    +

    The digest file uses a special format. Files in this format can be +created using the "htdigest" utility found in the support/ subdirectory of +the Apache distribution.

    + +
    + +

    Using Digest Authentication

    + +

    Using MD5 Digest authentication is very simple. Simply set up +authentication normally. However, use "AuthType Digest" and +"AuthDigestFile" instead of the normal "AuthType Basic" and +"AuthUserFile". Everything else should remain the same.

    + +

    MD5 authentication provides a more secure password system, but only +works with supporting browsers. As of this writing (July 1996), the +majority of browsers do not support digest authentication. Therefore, we +do not recommend using this feature on a large Internet site. However, for +personal and intra-net use, where browser users can be controlled, it is +ideal.

    + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_dir.html b/APACHE_1_3_12/htdocs/manual/mod/mod_dir.html new file mode 100644 index 0000000000..f150aa2e11 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_dir.html @@ -0,0 +1,103 @@ + + + +Apache module mod_dir + + + + + +

    Module mod_dir

    + +This module is contained in the mod_dir.c file, and +is compiled in by default. It provides for "trailing slash" redirects and +serving directory index files. + +

    Summary

    +The index of a directory can come from one of two sources: +
      +
    • A file written by the user, typically called index.html. +The DirectoryIndex directive sets +the name of this file. +This is controlled by mod_dir. +
    • Otherwise, a listing generated by the server. This is provided by +mod_autoindex. +
    +The two functions are separated so that you can completely remove +(or replace) automatic index generation should you want to. +

    A "trailing slash" redirect is issued when the server receives a +request for a URL http://servername/foo/dirname where +dirname is a directory. Directories require a trailing +slash, so mod_dir issues a redirect to +http://servername/foo/dirname/. + +

    Directives

    + + +
  55. DirectoryIndex +
  56. +
    + +

    DirectoryIndex

    + +Syntax: DirectoryIndex local-url local-url ...
    +Default: DirectoryIndex index.html
    +Context: server config, virtual host, directory, .htaccess
    +Override: Indexes
    +Status: Base
    +Module: mod_dir

    + +The DirectoryIndex directive sets the list of resources to look for, +when the client requests an index of the directory by specifying a / +at the end of the a directory name. Local-url is the +(%-encoded) URL of a document on the server relative to the requested +directory; it is usually the name of a file in the directory. Several +URLs may be given, in which case the server will return the first one +that it finds. If none of the resources exist and the +Indexes option is set, the server will generate its own +listing of the directory. +

    + +Example: +

    +DirectoryIndex index.html +
    +then a request for http://myserver/docs/ would return +http://myserver/docs/index.html if it exists, or would list +the directory if it did not.

    + +Note that the documents do not need to be relative to the directory; +

    +DirectoryIndex index.html index.txt /cgi-bin/index.pl
    +would cause the CGI script /cgi-bin/index.pl to be executed +if neither index.html or index.txt existed in +a directory.


    + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_dld.html b/APACHE_1_3_12/htdocs/manual/mod/mod_dld.html new file mode 100644 index 0000000000..1d0e7919a2 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_dld.html @@ -0,0 +1,108 @@ + + + +Apache module mod_dld + + + + + +

    Module mod_dld

    + +This module is obsolete. As of version +1.3 of Apache, it has been replaced with +mod_so. + +This module is contained in the mod_dld.c file, and is not +compiled in by default. It provides for loading of executable code +and modules into the server at start-up time, using the GNU dld library. + +

    Summary

    + +The optional dld module is a proof-of-concept piece of code which +loads other modules into the server as it is configuring itself (the +first time only; for now, rereading the config files cannot affect the +state of loaded modules), using the GNU dynamic linking library, DLD. +It isn't compiled into the server by default, since not everyone has +DLD, but it works when I try it. (Famous last words.)

    + +Note that for some reason, LoadFile /lib/libc.a seems to be +required for just about everything.

    + +Note: that DLD needs to read the symbol table out of the server binary +when starting up; these commands will fail if the server can't find +its own binary when it starts up, or if that binary is stripped.

    + + +

    Directives

    + +
    + + +

    LoadFile

    + +Syntax: LoadFile filename filename ...
    +Context: server config
    +Status: Experimental
    +Module: mod_dld

    + +The LoadFile directive links in the named object files or libraries when +the server is started; this is used to load additional code which +may be required for some module to work. Filename is relative +to ServerRoot.


    + +

    LoadModule

    + +Syntax: LoadModule module filename
    +Context: server config
    +Status: Experimental
    +Module: mod_dld

    + +The LoadModule directive links in the object file or library filename +and adds the module structure named module to the list of active +modules. Module is the name of the external variable of type +module in the file. Example: +

    +LoadModule ai_backcompat_module modules/mod_ai_backcompat.o
    +LoadFile /lib/libc.a +
    +loads the module in the modules subdirectory of the ServerRoot.

    + + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_dll.html b/APACHE_1_3_12/htdocs/manual/mod/mod_dll.html new file mode 100644 index 0000000000..882ef32e28 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_dll.html @@ -0,0 +1,151 @@ + + + +Apache module mod_dll + + + + + +

    Module mod_dll

    + +This module is obsolete. As of version +1.3b6 of Apache, it has been replaced with +mod_so. + +

    +This module is contained in the mod_dll.c file, and is +compiled in by default for Windows. It provides for loading of executable code +and modules into the server at start-up time, when they are contained in +Win32 DLLs.

    + +

    Summary

    + +

    The DLL module +loads other modules into the server as it is configuring itself (the +first time only, rereading the config files cannot affect the +state of loaded modules), when these modules are compiled into DLL files.

    + +

    This module is included with Apache 1.3 and later, and is available + only when using Microsoft Windows.

    + +

    Creating DLL Modules

    + +

    The Apache module API is unchanged between the Unix and Windows + versions. Many modules will run on Windows with no or little change + from Unix, although others rely on aspects of the Unix architecture + which are not present in Windows, and will not work.

    + +

    When a module does work, it can be added to the server in one of two + ways. As with Unix, it can be compiled into the server. Because Apache + for Windows does not have the Configure program of Apache + for Unix, the module's source file must be added to the ApacheCore + project file, and its symbols must be added to the + nt\modules.c file.

    + +

    The second way is to compile the module as a DLL, a shared library + that can be loaded into the server at runtime, using the + LoadModule + directive. These module DLLs can be distributed and run on any Apache + for Windows installation, without recompilation of the server.

    + +

    To create a module DLL, a small change is necessary to the module's + source file: The module record must be exported from the DLL (which + will be created later; see below). To do this, add the + MODULE_VAR_EXPORT (defined in the Apache header files) to + your module's module record definition. For example, if your module + has:

    +
    +    module foo_module;
    +
    +

    Replace the above with:

    +
    +    module MODULE_VAR_EXPORT foo_module;
    +
    +

    Note that this will only be activated on Windows, so the module can + continue to be used, unchanged, with Unix if needed. Also, if you are + familiar with .DEF files, you can export the module + record with that method instead.

    + +

    Now, create a DLL containing your module. You will need to link this + against the ApacheCore.lib export library that is created when the + ApacheCore.dll shared library is compiled. You may also have to change + the compiler settings to ensure that the Apache header files are + correctly located.

    + +

    This should create a DLL version of your module. Now simply place it + in the server root, and use the LoadModule directive to + load it.

    + +

    Directives

    + +
    + + +

    LoadFile

    +Syntax: LoadFile filename filename ...
    +Context: server config
    +Status: Core (Windows)
    +Module: mod_dll

    + +The LoadFile directive links in the named object files or libraries when +the server is started; this is used to load additional code which +may be required for some module to work. Filename is relative +to ServerRoot.


    + +

    LoadModule

    +Syntax: LoadModule module filename
    +Context: server config
    +Status: Core (Windows)
    +Module: mod_dll

    + +The LoadModule directive links in the object file or library filename +and adds the module structure named module to the list of active +modules. Module is the name of the external variable of type +module in the file. Example: + +

    +LoadModule status_module modules/ApacheModuleStatus.dll
    +
    +loads the ApacheModuleStatus.dll module in the modules subdirectory of the +ServerRoot.

    + + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_env.html b/APACHE_1_3_12/htdocs/manual/mod/mod_env.html new file mode 100644 index 0000000000..abe1fbf795 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_env.html @@ -0,0 +1,137 @@ + + + +Apache module mod_env + + + + + +

    Apache module mod_env

    + +This module is contained in the mod_env.c file, and +is compiled in by default. It provides for +passing environment variables to CGI/SSI scripts. Is is only available +in Apache 1.1 and later. + +

    Summary

    + +This module allows Apache's CGI and SSI environment to inherit +environment variables from the shell which invoked the httpd process. +CERN web-servers are able to do this, so this module is especially +useful to web-admins who wish to migrate from CERN to Apache without +rewriting all their scripts + +

    Directives

    + + +
    + +

    PassEnv

    +Syntax: PassEnv variable variable ...
    +Context: server config, virtual host
    +Status: Base
    +Module: mod_env
    +Compatibility: PassEnv is only available in +Apache 1.1 and later.

    + +Specifies one or more environment variables to pass to CGI scripts +from the server's own environment. Example: +

    +    PassEnv LD_LIBRARY_PATH
    +
    + +
    + +

    SetEnv

    +Syntax: SetEnv variable value
    +Context: server config, virtual host
    +Status: Base
    +Module: mod_env
    +Compatibility: SetEnv is only available in +Apache 1.1 and later.

    + +Sets an environment variable, which is then passed on to CGI +scripts. Example: +

    +    SetEnv SPECIAL_PATH /foo/bin
    +
    + +
    + +

    UnsetEnv

    +Syntax: UnsetEnv variable variable ...
    +Context: server config, virtual host
    +Status: Base
    +Module: mod_env
    +Compatibility: UnsetEnv is only available in +Apache 1.1 and later.

    + +Removes one or more environment variables from those passed on to +CGI scripts. Example: +

    +    UnsetEnv LD_LIBRARY_PATH
    +
    + + + +

    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_example.html b/APACHE_1_3_12/htdocs/manual/mod/mod_example.html new file mode 100644 index 0000000000..3cee4b97a8 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_example.html @@ -0,0 +1,168 @@ + + + + Apache module mod_example + + + + +

    Module mod_example

    +

    + This module is contained in the modules/mod_example.c file, and + is not compiled in by default. It illustrates many of + the aspects of the + Apache 1.2 API + and, when used, demonstrates the manner in which module callbacks are + triggered by the server. +

    +

    Summary

    +

    + 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 syntaxes. 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 "AddModule modules/example/mod_example" line near + the bottom of + the src/Configuration file. If there isn't one, add + it; it should look like this: +
      +     AddModule modules/example/mod_example.o
      +    
      +
    2. +
    3. 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. +
    4. +
    5. Make the server (run "make" in the src + directory). +
    6. +
    +

    + To add another module of your own: +

    +
      +
    1. mkdir src/modules/mymodule +
    2. +
    3. cp src/modules/example/* src/modules/mymodule +
    4. +
    5. Modify the files in the new directory. +
    6. +
    7. Follow steps [1] through [3] above, with appropriate changes. +
    8. +
    +

    + Using the mod_example Module +

    +

    + 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. +

    +

    Directives

    +

    +

    +

    +
    +

    + Example +

    +

    + Syntax: Example +
    + Default: None +
    + Context: server config, virtual host, directory, + .htaccess +
    + Override: Options +
    + Status: Extension +
    + Module: mod_example +
    + Compatibility: Example is only + available in Apache 1.2 and later. +

    +

    + The Example directive just sets a demonstration flag which the + example module's content handler displays. It takes no arguments. If you + browse to an URL to which the example content-handler applies, you will get + a display of the routines within the module and how and in what order they + were called to service the document request. The effect of this directive + one can observe under the point "Example directive declared + here: YES/NO". +

    + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_expires.html b/APACHE_1_3_12/htdocs/manual/mod/mod_expires.html new file mode 100644 index 0000000000..141a969598 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_expires.html @@ -0,0 +1,327 @@ + + + + Apache module mod_expires + + + + +

    Module mod_expires

    +

    + This module is contained in the mod_expires.c file, and + is not compiled in by default. It provides for the + generation of Expires headers according to user-specified + criteria. +

    +

    Summary

    +

    + This module controls the setting of the Expires HTTP + header in server responses. The expiration date can set to be + relative to either the time the source file was last modified, or to + the time of the client access. +

    +

    + The Expires HTTP header is an instruction to the client + about the document's validity and persistence. If cached, the document + may be fetched from the cache rather than from the source until this + time has passed. After that, the cache copy is considered + "expired" and invalid, and a new copy must be obtained from + the source. +

    +

    Directives

    +

    +

    +
  57. ExpiresActive +
  58. +
  59. ExpiresByType +
  60. +
  61. ExpiresDefault +
  62. +
    +
    +

    + ExpiresActive directive +

    + +

    + Syntax: ExpiresActive boolean +
    + Context: server config, virtual host, directory, + .htaccess +
    + Override: Indexes +
    + Status: Extension +
    + Module: mod_expires +

    +

    + This directive enables or disables the generation of the + Expires header for the document realm in question. (That + is, if found in an .htaccess file, for instance, it + applies only to documents generated from that directory.) If set to + Off, no Expires header will be + generated for any document in the realm (unless overridden at a lower + level, such as an .htaccess file overriding a server + config file). If set to On, the header will be + added to served documents according to the criteria defined by the + ExpiresByType + and + ExpiresDefault + directives (q.v.). +

    +

    + Note that this directive does not guarantee that an + Expires header will be generated. If the criteria aren't + met, no header will be sent, and the effect will be as though this + directive wasn't even specified. +

    +
    +

    + ExpiresByType directive +

    + +

    + Syntax: ExpiresByType MIME-type + <code>seconds +
    + Context: server config, virtual host, directory, + .htaccess +
    + Override: Indexes +
    + Status: Extension +
    + Module: mod_expires +

    +

    + This directive defines the value of the Expires header + generated for documents of the specified type (e.g., + text/html). The second argument sets the number of + seconds that will be added to a base time to construct the expiration + date. +

    +

    + The base time is either the last modification time of the file, or the + time of the client's access to the document. Which should be used is + specified by the <code> field; + M means that the file's last modification time should + be used as the base time, and A means the client's + access time should be used. +

    +

    + The difference in effect is subtle. If M is used, all current + copies of the document in all caches will expire at the same time, + which can be good for something like a weekly notice that's always + found at the same URL. If A is used, the date of expiration + is different for each client; this can be good for image files that + don't change very often, particularly for a set of related documents + that all refer to the same images (i.e., the images will be + accessed repeatedly within a relatively short timespan). +

    +

    + Example: +

    +

    +

    +   ExpiresActive On                  # enable expirations
    +   ExpiresByType image/gif A2592000  # expire GIF images after a month
    +                                     #  in the client's cache
    +   ExpiresByType text/html M604800   # HTML documents are good for a
    +                                     #  week from the time they were
    +                                     #  changed, period
    +  
    +

    +

    + Note that this directive only has effect if ExpiresActive + On has been specified. It overrides, for the specified MIME + type only, any expiration date set by the + ExpiresDefault + directive. +

    +

    + You can also specify the expiration time calculation using an + alternate syntax, + described later in this document. +

    +
    +

    + ExpiresDefault directive +

    + +

    + Syntax: ExpiresDefault <code>seconds +
    + Context: server config, virtual host, directory, + .htaccess +
    + Override: Indexes +
    + Status: Extension +
    + Module: mod_expires +

    +

    + This directive sets the default algorithm for calculating the + expiration time for all documents in the affected realm. It can be + overridden on a type-by-type basis by the + ExpiresByType + directive. See the description of that directive for details about + the syntax of the argument, and the + alternate syntax + description as well. +

    +
    +

    + Alternate Interval Syntax +

    +

    + The + ExpiresDefault + and + ExpiresByType + 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: +

    + +
  63. access +
  64. +
  65. now (equivalent to 'access') +
  66. +
  67. modification +
  68. +
    +

    + The 'plus' keyword is optional. <num> should be an + integer value [acceptable to atoi()], and <type> + is one of: +

    + +
  69. years +
  70. +
  71. months +
  72. +
  73. weeks +
  74. +
  75. days +
  76. +
  77. hours +
  78. +
  79. minutes +
  80. +
  81. seconds +
  82. +
    +

    + 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"
    +
    +
    +

    + Note that if you use a modification date based setting, the Expires + header will not be added to content that does + not come from a file on disk. This is due to the fact that there is + no modification time for such content. + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_headers.html b/APACHE_1_3_12/htdocs/manual/mod/mod_headers.html new file mode 100644 index 0000000000..3d6e4f656e --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_headers.html @@ -0,0 +1,121 @@ + + + +Apache module mod_headers + + + + + +

    Module mod_headers

    + +The optional headers module allows for the customization of HTTP +response headers. Headers can be merged, replaced or removed. The +directives described in this document are only available if Apache is +compiled with mod_headers.c. + +
    + +

    Directive

    + + +
    + +

    Header

    +Syntax: Header [ set | append | add ] + header value
    +Syntax: Header unset header
    +Context: server config, virtual host, access.conf, + .htaccess
    +Status: optional
    +Module: mod_header

    + +This directive can replace, merge or remove HTTP response headers. The +action it performs is determined by the first argument. This can be one +of the following values: + +

      +
    • set
      + The response header is set, replacing any previous header with this name + +
    • append
      + The response header is appended to any existing header of the same + name. When a new value is merged onto an existing header it is + separated from the existing header with a comma. This is the HTTP standard + way of giving a header multiple values. + +
    • add
      + The response header is added to the existing set of headers, even if + this header already exists. This can result in two (or more) headers + having the same name. This can lead to unforeseen consequences, and in + general "append" should be used instead. + +
    • unset
      + The response header of this name is removed, if it exists. If there are + multiple headers of the same name, all will be removed. +
    + +This argument is followed by a header name, which can include the +final colon, but it is not required. Case is ignored. For +add, append and set a value is given as the third argument. If this +value contains spaces, it should be surrounded by double quotes. +For unset, no value should be given. + +

    Order of Processing

    + +The Header directive can occur almost anywhere within the server +configuration. It is valid in the main server config and virtual host +sections, inside <Directory>, <Location> and <Files> +sections, and within .htaccess files. +

    +The Header directives are processed in the following order: +

      +
    1. main server +
    2. virtual host +
    3. <Directory> sections and .htaccess +
    4. <Location> +
    5. <Files> +
    + +Order is important. These two headers have a different effect if reversed: +
    +Header append Author "John P. Doe"
    +Header unset Author
    +
    + +This way round, the Author header is not set. If reversed, the Author +header is set to "John P. Doe". +

    + +The Header directives are processed just before the response is sent +by its handler. These means that some headers that are added just +before the response is sent cannot be unset or overridden. This +includes headers such as "Date" and "Server". +

    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_imap.html b/APACHE_1_3_12/htdocs/manual/mod/mod_imap.html new file mode 100644 index 0000000000..a68d069649 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_imap.html @@ -0,0 +1,329 @@ + + + +Apache module mod_imap + + + + + +

    Module mod_imap

    + +This module is contained in the mod_imap.c file, and is +compiled in by default. It provides for .map files, +replacing the functionality of the imagemap CGI +program. Any directory or document type configured to use the handler +imap-file (using either AddHandler or SetHandler) will be +processed by this module. + +

    Summary

    + +This module is in the default Apache distribution. The following directive will +activate files ending with .map as imagemap files: + +
    AddHandler imap-file map
    + +Note that the following is still supported: + +
    AddType application/x-httpd-imap map
    + +However, we are trying to phase out "magic MIME types" so we are deprecating +this method. + +

    New Features

    +The imagemap module adds some new features that were not +possible with previously distributed imagemap programs.

    + +

      +
    • URL references relative to the Referer: information. +
    • Default <BASE> assignment through a new map directive +base. +
    • No need for imagemap.conf file. +
    • Point references. +
    • Configurable generation of imagemap menus. +
    +

    + +

    Configuration Directives

    + + + +

    + +

    ImapMenu

    +Syntax: ImapMenu {none, formatted, semiformatted, + unformatted}
    +Context: server config, virtual host, directory, .htaccess
    +Override: Indexes
    +Module: mod_imap.c
    +Compatibility: ImapMenu is only available in Apache +1.1 and later.

    + +The ImapMenu directive determines the action taken if an imagemap file +is called without valid coordinates. +

    +
    none +
    If ImapMenu is + none, no menu is generated, and the default + action is performed. +
    formatted +
    A formatted menu is the simplest menu. Comments + in the imagemap file are ignored. A level one header is + printed, then an hrule, then the links each on a separate line. + The menu has a consistent, plain look close to that of + a directory listing. +
    semiformatted +
    In the semiformatted menu, comments are printed + where they occur in the imagemap file. Blank lines are turned + into HTML breaks. No header or hrule is printed, but otherwise + the menu is the same as a formatted menu. +
    unformatted +
    Comments are printed, blank lines are ignored. Nothing is + printed that does not appear in the imagemap file. All breaks + and headers must be included as comments in the imagemap file. + This gives you the most flexibility over the appearance of your + menus, but requires you to treat your map files as HTML instead + of plaintext. +
    + +

    + +

    ImapDefault

    +Syntax: ImapDefault {error, nocontent, + map, referer, URL}
    +Context: server config, virtual host, directory, .htaccess
    +Override: Indexes
    +Module: mod_imap.c
    +Compatibility: ImapDefault is only available in Apache +1.1 and later.

    + + +The ImapDefault directive sets the default default used in +the imagemap files. Its value is overridden by a default +directive within the imagemap file. If not present, the +default action is nocontent, which means +that a 204 No Content is sent to the client. In this +case, the client should continue to display the original page. + +

    + +

    ImapBase

    +Syntax: ImapBase {map, referer, URL}
    +Context: server config, virtual host, directory, .htaccess
    +Override: Indexes
    +Module: mod_imap.c
    +Compatibility: ImapBase is only available in Apache +1.1 and later.

    + +The ImapBase directive sets the default base used in +the imagemap files. Its value is overridden by a base +directive within the imagemap file. If not present, the +base defaults to http://servername/. + +


    +

    + +

    Imagemap File

    +The lines in the imagemap files can have one of several formats: +
    +directive value [x,y ...]
    +directive value "Menu text" [x,y ...]
    +directive value x,y ... "Menu text"
    +
    +The directive is one of base, default, +poly, circle, rect, or +point. The value is an absolute or relative URL, or one +of the special values listed below. The coordinates are +x,y pairs separated by whitespace. The quoted text is +used as the text of the link if a imagemap menu is generated. Lines +beginning with '#' are comments. + +

    Imagemap File Directives

    +There are six directives allowed in the imagemap file. The directives +can come in any order, but are processed in the order they are found +in the imagemap file. +
    +
    base Directive +
    Has the effect of <BASE HREF="value">. The + non-absolute URLs of the map-file are taken relative to this value. + The base directive overrides ImapBase as set in a + .htaccess file or in the server configuration files. In the absence + of an ImapBase configuration directive, base defaults to + http://server_name/.
    + base_uri is synonymous with base. Note that + a trailing slash on the URL is significant. +

    +

    default Directive +
    The action taken if the coordinates given do not fit any of the + poly, circle or rect + directives, and there are no point directives. Defaults + to nocontent in the absence of an ImapDefault + configuration setting, causing a status code of 204 No + Content to be returned. The client should keep the same + page displayed. +

    +

    poly Directive +
    Takes three to one-hundred points, and is obeyed if the user selected + coordinates fall within the polygon defined by these points. +

    +

    circle +
    Takes the center coordinates of a circle and a point on the circle. Is + obeyed if the user selected point is with the circle. +

    +

    rect Directive +
    Takes the coordinates of two opposing corners of a rectangle. Obeyed + if the point selected is within this rectangle. +

    +

    point Directive +
    Takes a single point. The point directive closest to the user + selected point is obeyed if no other directives are satisfied. + Note that default will not be followed if a + point directive is present and valid coordinates are + given. +
    + + + +

    Values

    +The values for each of the directives can any of the following: +
    +
    a URL +
    The URL can be relative or absolute URL. Relative URLs can + contain '..' syntax and will be resolved relative to the + base value.
    + base itself will not resolved according to the current + value. A statement base mailto: will work properly, though. +

    +

    map +
    Equivalent to the URL of the imagemap file itself. No + coordinates are sent with this, so a menu will be generated + unless ImapMenu is set to 'none'. +

    +

    menu +
    Synonymous with map. +

    +

    referer +
    Equivalent to the URL of the referring document. + Defaults to http://servername/ if no Referer: + header was present. +

    +

    nocontent +
    Sends a status code of 204 No Content, + telling the client to keep the same page displayed. Valid for + all but base. +

    +

    error +
    Fails with a 500 Server Error. Valid for all but + base, but sort of silly for anything but + default. +
    + +

    Coordinates

    +
    +
    0,0 200,200 +
    A coordinate consists of an x and a y value + separated by a comma. The coordinates are separated from each other + by whitespace. To accommodate the way Lynx handles imagemaps, should a + user select the coordinate 0,0, it is as if + no coordinate had been selected. +
    + +

    Quoted Text

    +
    +
    "Menu Text" +
    After the value or after the coordinates, the line optionally may + contain text within double quotes. This string is used as the + text for the link if a menu is generated:
    + <a HREF="http://foo.com/">Menu text</a>
    + If no quoted text is present, the name of the link will be used + as the text:
    + <a HREF="http://foo.com/">http://foo.com</a>
    + It is impossible to escape double quotes within this text. +
    + +
    + +

    Example Mapfile

    +
    +#Comments are printed in a 'formatted' or 'semiformatted' menu.
    +#And can contain html tags. <hr>
    +base referer
    +poly map "Could I have a menu, please?" 0,0 0,10 10,10 10,0
    +rect .. 0,0 77,27 "the directory of the referer"
    +circle http://www.inetnebr.com/lincoln/feedback/ 195,0 305,27
    +rect another_file "in same directory as referer" 306,0 419,27
    +point http://www.zyzzyva.com/ 100,100
    +point http://www.tripod.com/ 200,200
    +rect mailto:nate@tripod.com 100,150 200,0 "Bugs?"
    +
    +

    + +

    Referencing your mapfile

    +
    +<A HREF="/maps/imagemap1.map">
    +<IMG ISMAP SRC="/images/imagemap1.gif">
    +</A> +

    + + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_include.html b/APACHE_1_3_12/htdocs/manual/mod/mod_include.html new file mode 100644 index 0000000000..678720dde2 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_include.html @@ -0,0 +1,443 @@ + + + +Apache module mod_include + + + + + +

    Module mod_include

    + +This module is contained in the mod_include.c file, and +is compiled in by default. It provides for server-parsed html +documents. Several directives beyond the original NCSA definition were +introduced in Apache 1.2 - these are flagged below with the phrase +"Apache 1.2 and above". Of particular significance are the new flow +control directives documented at the bottom. + +

    Enabling Server-Side Includes

    + +Any document with handler of "server-parsed" will be parsed by this +module, if the Includes option is set. If documents +containing server-side include directives are given the extension +.shtml, the following directives will make Apache parse them and +assign the resulting document the mime type of text/html: + +
    +AddType text/html .shtml
    +AddHandler server-parsed .shtml
    +
    + +The following directive must be given for the directories containing +the shtml files (typically in a <Directory> section, +but this directive is also valid .htaccess files if AllowOverride +Options is set): + +
    +Options +Includes
    +
    + +Alternatively the XBitHack +directive can be used to parse normal (text/html) files, +based on file permissions.

    + +For backwards compatibility, documents with mime type +text/x-server-parsed-html or +text/x-server-parsed-html3 will also be parsed +(and the resulting output given the mime type text/html). + +

    Basic Elements

    + +The document is parsed as an HTML document, with special commands embedded +as SGML comments. A command has the syntax: + +
    +<!--#element attribute=value attribute=value ... + --> +
    + +The value will often be enclosed in double quotes; many commands only allow +a single attribute-value pair. Note that the comment terminator +(-->) should be preceded by whitespace to ensure that it +isn't considered part of an SSI token. +

    +The allowed elements are:

    + +

    + +
    config +
    +This command controls various aspects of the parsing. The valid attributes +are: +
    +
    errmsg +
    The value is a message that is sent back to the client if an error occurs +whilst parsing the document. +
    sizefmt +
    The value sets the format to be used which displaying the size of a file. +Valid values are bytes for a count in bytes, or +abbrev for a count in Kb or Mb as appropriate. +
    timefmt +
    The value is a string to be used by the strftime(3) library +routine when printing dates. +
    + + +
    echo +
    +This command prints one of the include variables, defined below. +If the variable is unset, it is printed as (none). +Any dates printed are subject to the currently configured timefmt. + +Attributes: +
    +
    var +
    The value is the name of the variable to print. +
    encoding +
    Specifies how Apache should encode special characters contained +in the variable before outputting them. If set to "none", no encoding +will be done. If set to "url", then URL encoding (also known as +%-encoding; this is appropriate for use within URLs in links, etc.) +will be performed. At the start of an echo element, +the default is set to "entity", resulting in entity encoding (which +is appropriate in the context of a block-level HTML element, eg. +a paragraph of text). This can be changed by adding an +encoding attribute, which will remain in effect until +the next encoding attribute is encountered or the +element ends, whichever comes first. Note that the +encoding attribute must precede the corresponding +var attribute to be effective, and that only special +characters as defined in the ISO-8859-1 character encoding will be +encoded. This encoding process may not have the desired result if +a different character encoding is in use. +Apache 1.3.12 and above; previous versions do no encoding. + +
    + +
    exec +
    +The exec command executes a given shell command or CGI script. +The IncludesNOEXEC Option disables this command +completely. The valid attributes are: +
    +
    cgi +
    +The value specifies a (%-encoded) URL relative path to the CGI script. +If the path does not begin with a (/), then it is taken to be relative to +the current document. The document referenced by this path is invoked +as a CGI script, even if the server would not normally recognize it as +such. However, the directory containing the script must be enabled for +CGI scripts (with ScriptAlias +or the ExecCGI Option).

    +The CGI script is given the PATH_INFO and query string (QUERY_STRING) of the +original request from the client; these cannot be specified in the URL path. +The include variables will be available to the script in addition to the +standard CGI environment.

    +If the script returns a Location: header instead of output, then this +will be translated into an HTML anchor.

    +The include virtual element should be used in preference to +exec cgi. +

    cmd +
    The server will execute the given string using /bin/sh. +The include variables are available to the command. +
    + +
    fsize +
    +This command prints the size of the specified file, subject to the +sizefmt format specification. Attributes: +
    +
    file +
    The value is a path relative to the directory containing the current +document being parsed. +
    virtual +
    The value is a (%-encoded) URL-path relative to the current document being +parsed. If it does not begin with a slash (/) then it is taken to be relative +to the current document. +
    + +
    flastmod +
    +This command prints the last modification date of the specified file, +subject to the timefmt format specification. The attributes are +the same as for the fsize command. + +
    include +
    +This command inserts the text of another document or file into the parsed +file. Any included file is subject to the usual access control. If the +directory containing the parsed file has the +Option +IncludesNOEXEC set, and the including the document would cause a program +to be executed, then it will not be included; this prevents the execution of +CGI scripts. Otherwise CGI scripts are invoked as normal using the complete +URL given in the command, including any query string. + +

    + +An attribute defines the location of the document; the inclusion is done for +each attribute given to the include command. The valid attributes are: +

    +
    file +
    The value is a path relative to the directory containing the current +document being parsed. It cannot contain ../, nor can it be an +absolute path. The virtual attribute should always be used +in preference to this one. +
    virtual +
    The value is a (%-encoded) URL relative to the current document being +parsed. The URL cannot contain a scheme or hostname, only a path and +an optional query string. If it does not begin with a slash (/) then it +is taken to be relative to the current document. +
    +A URL is constructed from the attribute, and the output the server +would return if the URL were accessed by the client is included in the parsed +output. Thus included files can be nested. + +
    printenv +
    This prints out a listing of all existing variables and their values. + Starting with Apache 1.3.12, special characters are entity encoded (see the + echo element for details) before being + output. No attributes. +
    For example: <!--#printenv --> +
    Apache 1.2 and above. + +
    set +
    This sets the value of a variable. Attributes: +
    +
    var +
    The name of the variable to set. +
    value +
    The value to give a variable. +
    +For example: + <!--#set var="category" value="help" --> +
    Apache 1.2 and above. + +
    + +

    Include Variables

    + +In addition to the variables in the standard CGI environment, these are +available for the echo command, for if and +elif, and to any program invoked by the document. + +
    +
    DATE_GMT +
    The current date in Greenwich Mean Time. +
    DATE_LOCAL +
    The current date in the local time zone. +
    DOCUMENT_NAME +
    The filename (excluding directories) of the document requested by the +user. +
    DOCUMENT_URI +
    The (%-decoded) URL path of the document requested by the user. Note that +in the case of nested include files, this is not then URL for the +current document. +
    LAST_MODIFIED +
    The last modification date of the document requested by the user. +
    +

    + +

    Variable Substitution

    +

    Variable substitution is done within quoted strings in most cases + where they may reasonably occur as an argument to an SSI directive. + This includes the + config, + exec, + flastmod, + fsize, + include, and + set + directives, as well as the arguments to conditional operators. + You can insert a literal dollar sign into the string using backslash + quoting: + +

    +    <!--#if expr="$a = \$test" -->
    +
    + +

    If a variable reference needs to be substituted in the middle of a + character sequence that might otherwise be considered a valid + identifier in its own right, it can be disambiguated by enclosing + the reference in braces, à la shell substitution: + +

    +    <!--#set var="Zed" value="${REMOTE_HOST}_${REQUEST_METHOD}" -->
    +
    + +

    This will result in the Zed variable being set to + "X_Y" if REMOTE_HOST is + "X" and REQUEST_METHOD is + "Y". + +

    EXAMPLE: the below example will print "in foo" if the DOCUMENT_URI is +/foo/file.html, "in bar" if it is /bar/file.html and "in neither" +otherwise: +

    +    <!--#if expr="\"$DOCUMENT_URI\" = \"/foo/file.html\"" -->
    +    in foo
    +    <!--#elif expr="\"$DOCUMENT_URI\" = \"/bar/file.html\"" -->
    +    in bar
    +    <!--#else -->
    +    in neither
    +    <!--#endif -->
    +
    + +

    Flow Control Elements

    + +These are available in Apache 1.2 and above. The basic flow control +elements are: + +
    +    <!--#if expr="test_condition" -->
    +    <!--#elif expr="test_condition" -->
    +    <!--#else -->
    +    <!--#endif -->
    +
    + +

    The if element works like an + if statement in a programming language. The test condition + is evaluated and if the result is true, then the text until + the next elif, else. + or endif element is included in the + output stream. + +

    The elif or else + statements are be used the put text into the output stream + if the original test_condition was false. These elements + are optional. + +

    The endif element ends the + if element and is required. + +

    test_condition is one of the following: + +

    + +
    string
    true if string is not empty + +
    string1 = string2 +
    + string1 != string2 +
    + string1 < string2 +
    + string1 <= string2 +
    + string1 > string2 +
    + string1 >= string2 + +
    Compare string1 with string 2. If string2 has the form /string/ + then it is compared as a regular expression. + Regular expressions have the same syntax as those found in the + Unix egrep command. + +
    ( test_condition ) +
    true if test_condition is true +
    ! test_condition +
    true if test_condition is false +
    test_condition1 && test_condition2 +
    true if both test_condition1 and + test_condition2 are true +
    test_condition1 || test_condition2 +
    true if either test_condition1 or + test_condition2 is true +
    + +

    "=" and "!=" bind more tightly than "&&" and + "||". + "!" binds most tightly. Thus, the following are equivalent: + +

    +    <!--#if expr="$a = test1 && $b = test2" -->
    +    <!--#if expr="($a = test1) && ($b = test2)" -->
    +
    + +

    Anything that's not recognized as a variable or an operator is + treated as a string. Strings can also be quoted: 'string'. + Unquoted strings can't contain whitespace (blanks and tabs) + because it is used to separate tokens such as variables. If + multiple strings are found in a row, they are concatenated using + blanks. So, + +

    +     string1    string2  results in string1 string2
    +    'string1    string2' results in string1    string2
    +
    + +
    +

    Directives

    + +
    + + +

    XBitHack

    + +Syntax: XBitHack status
    +Default: XBitHack off
    +Context: server config, virtual host, directory, .htaccess
    +Override: Options
    +Status: Base
    +Module: mod_include

    + +The XBitHack directives controls the parsing of ordinary html documents. +This directive only affects files associated with the MIME type +text/html. +Status can have the following values: +

    +
    off +
    No special treatment of executable files. +
    on +
    Any file that has the user-execute bit set will be treated as a +server-parsed html document. +
    full +
    As for on but also test the group-execute bit. If it +is set, then set the Last-modified date of the returned file to be the +last modified time of the file. If it is not set, then no last-modified date +is sent. Setting this bit allows clients and proxies to cache the result of +the request. +

    Note: you would not want to use this, for example, when you +#include a CGI that produces different output on each hit +(or potentially depends on the hit). +

    +

    + +


    +

    Using Server Side Includes for ErrorDocuments

    + +There is a document which +describes how to use the features of mod_include to offer internationalized +customized server error documents. +

    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_info.html b/APACHE_1_3_12/htdocs/manual/mod/mod_info.html new file mode 100644 index 0000000000..8afa84dc41 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_info.html @@ -0,0 +1,113 @@ + + + +Apache module mod_info + + + + + +

    Module mod_info

    + +This module is contained in the mod_info.c file. It +provides a comprehensive overview of the server configuration +including all installed modules and directives in the configuration +files. This module is not compiled into the +server by default. It is only available in Apache 1.1 and later. To +enable it, add the following line to the server build Configuration +file, and rebuild the server: + +
    +AddModule modules/standard/mod_info.o
    +
    + +

    Directives

    + + +
    +

    +To configure it, add the following to your access.conf file. + +

    +<Location /server-info>
    +SetHandler server-info
    +</Location>
    +
    + +You may wish to add a +<Limit> +clause inside the +location +directive to limit access to your server configuration information.

    +Once configured, the server information is obtained by accessing +http://your.host.dom/server-info

    +

    + + Note that the configuration files are read by the module at run-time, + and therefore the display may not reflect the running + server's active configuration if the files have been changed since the + server was last reloaded. Also, the configuration files must be + readable by the user as which the server is running (see the + User + directive), or else the directive settings will not be listed. +

    + It should also be noted that if mod_info is compiled into + the server, its handler capability is available in all + configuration files, including per-directory files + (e.g., .htaccess). This may have + security-related ramifications for your site. +

    +
    +
    + +
    + +

    AddModuleInfo

    +Syntax: AddModuleInfo module-name string
    +Context: server config, virtual host
    +Status: base
    +Module: mod_browser
    +Compatibility: Apache 1.3 and above

    + +This allows the content of string to be shown as +HTML interpreted, +Additional Information for the module module-name. +Example: +

    +
    +AddModuleInfo mod_auth.c 'See <A HREF="http://www.apache.org/docs/mod/mod_auth.html">http://www.apache.org/docs/mod/mod_auth.html</A>'
    +
    +
    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_isapi.html b/APACHE_1_3_12/htdocs/manual/mod/mod_isapi.html new file mode 100644 index 0000000000..61c9ba6728 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_isapi.html @@ -0,0 +1,73 @@ + + + +Apache module mod_isapi + + + + + + +

    Module mod_isapi

    + +

    This module is contained in the mod_isapi.c file, and is + compiled in by default. It provides support for ISAPI Extensions when + running under Microsoft Windows. Any document with a handler of + isapi-isa will be processed by this module. + +

    Purpose

    + +

    This module implements the ISAPI + Extension API. It allows Internet Server Applications (i.e., ISAPI + Extensions) to be used with Apache for Windows. + +

    Usage

    + +

    In the server configuration file, add a handler called + isapi-isa, and map it to files with a .DLL + extension. In other words:

    +
    +    AddHandler isapi-isa dll
    +
    +

    Now simply place the ISA DLLs into your document root, and they will + be loaded when their URLs are accessed.

    + +

    ISAPI Extensions are governed by the same restrictions as CGI + scripts. That is, Options ExecCGI must be active in the + directory that contains the ISA.

    + +

    Notes

    + +

    Apache's ISAPI implementation conforms to all of the ISAPI 2.0 + specification, except for the "Microsoft-specific" extensions dealing + with asynchronous I/O. Apache's I/O model does not allow asynchronous + reading and writing in a manner that the ISAPI could access. If an ISA + tries to access async I/O, a message will be place in the error log, + to help with debugging. + +

    Some servers, like Microsoft IIS, load the ISA into the server, and + keep it loaded until memory usage is too high, and it is + unloaded. Apache currently loads and unloads the ISA for each + request. This is inefficient, but Apache's request model makes this + method the only method that currently works. A future release may use + a more effective loading method. + +

    Apache 1.3a1 currently limits POST and PUT input to 48k per + request. This is to work around a problem with the ISAPI implementation + that could result in a denial of service attack. It is expected that + support for larger uploads will be added soon. + +

    Also, remember that while Apache supports ISAPI Extensions, it does + not support ISAPI Filters. Support for filters may be added at a later + date, but no support is planned at this time.

    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_log_agent.html b/APACHE_1_3_12/htdocs/manual/mod/mod_log_agent.html new file mode 100644 index 0000000000..2084889074 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_log_agent.html @@ -0,0 +1,77 @@ + + + +Module mod_log_agent + + + + + +

    Module mod_log_agent

    + +This module is contained in the mod_log_agent.c file, and is not +compiled in by default. It provides for logging of the client user agents. +mod_log_agent is deprecated. Use mod_log_config +instead. + + +
    + + +

    AgentLog

    + +Syntax: AgentLog file-pipe
    +Default: AgentLog logs/agent_log
    +Context: server config, virtual host
    +Status: Extension
    +Module: mod_log_agent

    + +The AgentLog directive sets the name of the file to which the server will +log the UserAgent header of incoming requests. File-pipe is one +of +

    A filename +
    A filename relative to the ServerRoot. +
    `|' followed by a command +
    A program to receive the agent log information on its standard input. +Note the a new program will not be started for a VirtualHost if it inherits +the AgentLog from the main server. +
    +Security: if a program is used, then it will be +run under the user who started httpd. This will be root if the server +was started by root; be sure that the program is secure.

    + +Security: See the security tips document for +details on why your security could be compromised if the directory +where logfiles are stored is writable by anyone other than the user +that starts the server.

    + +This directive is provided for compatibility with NCSA 1.4.

    + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_log_common.html b/APACHE_1_3_12/htdocs/manual/mod/mod_log_common.html new file mode 100644 index 0000000000..3936d5c932 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_log_common.html @@ -0,0 +1,118 @@ + + + +Apache module mod_log_common + + + + + +

    Module mod_log_common

    + +This module is contained in the mod_log_common.c file, +and is compiled in by default. It provides for logging of the requests +made to the server using the Common Logfile Format. This module has +been replaced by mod_log_config in Apache 1.2 + +

    Log file format

    +The log file contains a separate line for each request. A line is composed +of several tokens separated by spaces: +
    +host ident authuser date request status bytes +
    +If a token does not have a value then it is represented by a hyphen (-). +The meanings and values of these tokens are as follows: +
    +
    host +
    The fully-qualified domain name of the client, or its IP number if the +name is not available. +
    ident +
    If IdentityCheck is enabled and the +client machine runs identd, then this is the identity information reported +by the client. +
    authuser +
    If the request was for an password protected document, then this is +the userid used in the request. +
    date +
    The date and time of the request, in the following format: +
    date = [day/month/year:hour:minute:second zone]
    +day = 2*digit
    +month = 3*letter
    +year = 4*digit
    +hour = 2*digit
    +minute = 2*digit
    +second = 2*digit
    +zone = (`+' | `-') 4*digit
    +
    request +
    The request line from the client, enclosed in double quotes +("). +
    status +
    The three digit status code returned to the client. +
    bytes +
    The number of bytes in the object returned to the client, not including +any headers. +
    + + +

    Directives

    + +
    + + +

    TransferLog

    + +Syntax: TransferLog file-pipe
    +Default: TransferLog logs/transfer_log
    +Context: server config, virtual host
    +Status: Base
    +Module: mod_log_common

    + +The TransferLog directive sets the name of the file to which the server will +log the incoming requests. File-pipe is one +of +

    A filename +
    A filename relative to the ServerRoot. +
    `|' followed by a command +
    A program to receive the agent log information on its standard input. +Note the a new program will not be started for a VirtualHost if it inherits +the TransferLog from the main server. See, just as an example, +cronolog. + +
    +Security: if a program is used, then it will be +run under the user who started httpd. This will be root if the server +was started by root; be sure that the program is secure.

    + +Security: See the security tips document for +details on why your security could be compromised if the directory +where logfiles are stored is writable by anyone other than the user +that starts the server.

    + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_log_config.html b/APACHE_1_3_12/htdocs/manual/mod/mod_log_config.html new file mode 100644 index 0000000000..d3d9d5106f --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_log_config.html @@ -0,0 +1,456 @@ + + + +Apache module mod_log_config + + + + + +

    Module mod_log_config

    +

    +This module is contained in the mod_log_config.c file, +and is compiled in by default in Apache 1.2. mod_log_config replaces +mod_log_common in Apache 1.2. Prior to version 1.2, mod_log_config was +an optional module. It provides for logging of the requests made to +the server, using the Common Log Format or a user-specified format. +

    + +

    Summary

    +

    +Three directives are provided by this module: TransferLog +to create a log file, LogFormat to set a custom format, +and CustomLog to define a log file and format in one go. +The TransferLog and CustomLog directives can +be used multiple times in each server to cause each request to be +logged to multiple files. +

    + +

    Compatibility notes

    + +
      +
    • This module is based on mod_log_config distributed with +previous Apache releases, now updated to handle multiple logs. +There is now no need to re-configure Apache to use configuration log +formats. + +
    • The module also implements the CookieLog directive, +used to log user-tracking information created by mod_usertrack. The use of +CookieLog is deprecated, and a CustomLog +should be defined to log user-tracking information instead. + +
    • As of Apache 1.3.5, this module allows conditional logging +based upon the setting of environment variables. That is, +you can control whether a request should be logged or not +based upon whether an arbitrary environment variable is +defined or not. This is settable on a per-logfile +basis. + +
    • Beginning with Apache 1.3.5, the mod_log_config module has +also subsumed the RefererIgnore functionality from +mod_log_referer. The effect +of RefererIgnore can be achieved by combinations of +SetEnvIf directives +and conditional CustomLog definitions. + +
    + +

    Log File Formats

    + +Unless told otherwise with LogFormat the log files created by +TransferLog will be in standard "Common Log Format" +(CLF). The contents of each line in a CLF file are explained +below. Alternatively, the log file can be customized (and if multiple +log files are used, each can have a different format). Custom formats +are set with LogFormat and CustomLog. + +

    Common Log Format

    + +The Common Log Format (CLF) file contains a separate line for each +request. A line is composed of several tokens separated by spaces: + +
    +host ident authuser date request status bytes +
    +If a token does not have a value then it is represented by a hyphen (-). +The meanings and values of these tokens are as follows: +
    +
    host +
    The fully-qualified domain name of the client, or its IP number if the +name is not available. +
    ident +
    If IdentityCheck is enabled and the +client machine runs identd, then this is the identity information reported +by the client. +
    authuser +
    If the request was for an password protected document, then this is +the userid used in the request. +
    date +
    The date and time of the request, in the following format: +
    date = [day/month/year:hour:minute:second zone]
    +day = 2*digit
    +month = 3*letter
    +year = 4*digit
    +hour = 2*digit
    +minute = 2*digit
    +second = 2*digit
    +zone = (`+' | `-') 4*digit
    +
    request +
    The request line from the client, enclosed in double quotes +("). +
    status +
    The three digit status code returned to the client. +
    bytes +
    The number of bytes in the object returned to the client, not including +any headers. +
    + +

    Custom Log Formats

    + +The format argument to the LogFormat and +CustomLog is a string. This string is logged to the log +file for each request. It can contain literal characters copied into +the log files, and `%' directives which are replaced in the log file +by the values as follows: + +
    +%...a:          Remote IP-address
    +%...A:          Local IP-address
    +%...B:          Bytes sent, excluding HTTP headers.
    +%...b:          Bytes sent, excluding HTTP headers. In CLF format
    +		i.e. a '-' rather than a 0 when no bytes are 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 server.
    +%...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 canonical Port of the server serving the request
    +%...P:          The process ID of the child that serviced the request.
    +%...q		The query string (prepended with a ? if a query string exists,
    +		otherwise an empty string)
    +%...r:          First line of request
    +%...s:          Status.  For requests that got internally redirected, this is
    +                the status of the *original* request --- %...>s for the last.
    +%...t:          Time, in common log format time format (standard english format)
    +%...{format}t:  The time, in the form given by format, which should
    +                be in strftime(3) format. (potentially localised)
    +%...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 canonical ServerName of the server serving the request.
    +%...V:          The server name according to the UseCanonicalName setting.
    +
    + +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. + +

    + +Note that the common log format is defined by the string "%h %l +%u %t \"%r\" %s %b", which can be used as the basis for +extending for format if desired (e.g., to add extra fields at the end). +NCSA's extended/combined log format would be "%h %l %u %t \"%r\" %s %b \"%{Referer}i\" \"%{User-agent}i\"". + +

    + +Note that the canonical ServerName +and Port of the server serving the request +are used for %v and %p respectively. This +happens regardless of the +UseCanonicalName setting because +otherwise log analysis programs would have to duplicate the entire +vhost matching algorithm in order to decide what host really served +the request. + +

    Using Multiple Log Files

    + +The TransferLog and CustomLog directives can +be given more than once to log requests to multiple log files. Each +request will be logged to all the log files defined by either of these +directives. + +

    Use with Virtual Hosts

    + +If a <VirtualHost> section does not contain any +TransferLog or CustomLog directives, the +logs defined for the main server will be used. If it does +contain one or more of these directives, requests serviced by +this virtual host will only be logged in the log files defined +within its definition, not in any of the main server's log files. +See the examples below. +

    + +

    Security Considerations

    + +See the security tips +document for details on why your security could be compromised if the +directory where logfiles are stored is writable by anyone other than +the user that starts the server. +

    +

    Directives

    + + +
    + + +

    CookieLog

    + +Syntax: CookieLog filename
    +Context: server config, virtual host
    +Module: mod_cookies
    +Compatibility: Only available in Apache 1.2 and above

    + +The CookieLog directive sets the filename for logging of cookies. +The filename is relative to the ServerRoot. This directive is included +only for compatibility with +mod_cookies, and is deprecated. +

    + +


    +

    CustomLog

    +Syntax: CustomLog file-pipe + format-or-nickname
    +Context: server config, virtual host
    +Status: Base
    +Compatibility: Nickname only available in Apache 1.3 + or later +
    +Module: mod_log_config +

    +The first argument is the filename to which log records should be +written. This is used +exactly like the argument to +TransferLog; +that is, it is either a full path or relative to the current +server root. +

    +

    +The format argument specifies a format for each line of the log file. +The options available for the format are exactly the same as for +the argument of the LogFormat directive. If the format +includes any spaces (which it will do in almost all cases) it +should be enclosed in double quotes. +

    +

    +Instead of an actual format string, you can use a format nickname defined with +the +LogFormat +directive. +

    + +
    +

    CustomLog (conditional)

    +Syntax: CustomLog file-pipe + format-or-nickname + env=[!]environment-variable
    +Context: server config, virtual host
    +Status: Base
    +Compatibility: Only available in Apache 1.3.5 + or later +
    +Module: mod_log_config +

    + +The behaviour of this form of the CustomLog directive is almost +identical to the standard CustomLog +directive. The difference is that the 'env=' clause controls +whether a particular request will be logged in the specified file or +not. If the specified environment variable is set for the +request (or is not set, in the case of a 'env=!name' +clause), then the request will be logged. +

    +

    +Environment variables can be set on a per-request basis +using the mod_setenvif and/or +mod_rewrite modules. For example, +if you don't want to record requests for all GIF images on +your server in a separate logfile but not your main log, you +can use: +

    +
    +    SetEnvIf Request_URI \.gif$ gif-image
    +    CustomLog gif-requests.log common env=gif-image
    +    CustomLog nongif-requests.log common env=!gif-image
    +
    + +
    +

    LogFormat

    + +Syntax: LogFormat format [nickname] +
    +Default: LogFormat "%h %l %u %t \"%r\" +%s %b"
    +Context: server config, virtual host
    +Status: Base
    +Compatibility: Nickname only available in Apache 1.3 + or later +
    +Module: mod_log_config +

    +This sets the format of the default logfile named by the +TransferLog +directive . See the section on +Custom Log Formats for details on the format +arguments. +

    +

    +If you include a nickname for the format on the directive line, you can +use it in other LogFormat and +CustomLog +directives rather than repeating the entire format string. +

    +

    +A +LogFormat directive which defines a nickname does +nothing else -- that is, it only defines the nickname, +it doesn't actually apply the format and make it the default. +

    + +
    + +

    TransferLog

    + +Syntax: TransferLog file-pipe
    +Default: none
    +Context: server config, virtual host
    +Status: Base
    +Module: mod_log_config

    + +The TransferLog directive adds a log file in the format defined by the +most recent +LogFormat +directive, or Common Log Format if no other default format has been +specified. +File-pipe is one +of +

    A filename +
    A filename relative to the ServerRoot. +
    `|' followed by a command +
    A program to receive the agent log information on its standard input. +Note the a new program will not be started for a VirtualHost if it inherits +the TransferLog from the main server. +
    +Security: if a program is used, then it will be +run under the user who started httpd. This will be root if the server +was started by root; be sure that the program is secure.

    + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_log_referer.html b/APACHE_1_3_12/htdocs/manual/mod/mod_log_referer.html new file mode 100644 index 0000000000..017aecd801 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_log_referer.html @@ -0,0 +1,117 @@ + + + +Apache module mod_log_referer + + + + + +

    Module mod_log_referer

    + +This module is contained in the mod_log_referer.c file, and is not +compiled in by default. It provides for logging of the documents which +reference documents on the server. As of Apache 1.3.5 it is deprecated. +Use CustomLog +(conditional) instead. + +

    Log file format

    +The log file contains a separate line for each refer. Each line has the +format +
    uri -> document
    +where uri is the (%-escaped) URI for the document that references +the one requested by the client, and document is the (%-decoded) +local URL to the document being referred to. + + +

    Directives

    + +
    + + +

    RefererIgnore

    + +Syntax: RefererIgnore string string ...
    +Context: server config, virtual host
    +Status: Extension
    +Module: mod_log_referer

    + +The RefererIgnore directive adds to the list of strings to ignore in +Referer headers. If any of the strings in the list is contained in +the Referer header, then no referrer information will be logged for the +request. Example: +

    RefererIgnore www.ncsa.uiuc.edu
    +This avoids logging references from www.ncsa.uiuc.edu. +


    + + +

    RefererLog

    + +Syntax: RefererLog file-pipe
    +Default: RefererLog logs/referer_log
    +Context: server config, virtual host
    +Status: Extension
    +Module: mod_log_referer

    + +The RefererLog directive sets the name of the file to which the server will +log the Referer header of incoming requests. File-pipe is one +of +

    A filename +
    A filename relative to the ServerRoot. +
    `|' followed by a command +
    A program to receive the referrer log information on its standard input. +Note the a new program will not be started for a VirtualHost if it inherits +the RefererLog from the main server. +
    +Security: if a program is used, then it will be +run under the user who started httpd. This will be root if the server +was started by root; be sure that the program is secure.

    + +Security: See the security tips document for +details on why your security could be compromised if the directory +where logfiles are stored is writable by anyone other than the user +that starts the server.

    + +This directive is provided for compatibility with NCSA 1.4.

    + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_mime.html b/APACHE_1_3_12/htdocs/manual/mod/mod_mime.html new file mode 100644 index 0000000000..8cf486e213 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_mime.html @@ -0,0 +1,598 @@ + + + +Apache module mod_mime + + + + + +

    Module mod_mime

    + +This module is contained in the mod_mime.c file, and is +compiled in by default. It provides for determining the types of files +from the filename. + +

    Summary

    + +This module is used to determine various bits of "meta information" +about documents. This information relates to the content of the +document and is returned to the browser or used in content-negotiation +within the server. In addition, a "handler" can be set for a document, +which determines how the document will be processed within the server. + +

    + +The directives AddCharset, +AddEncoding, AddHandler, +AddLanguage and AddType +are all used to map file extensions onto the meta-information for that +file. Respectively they set the character set, content-encoding, handler, +content-language, and MIME-type (content-type) of documents. The +directive TypesConfig is used to specify a +file which also maps extensions onto MIME types. The directives ForceType and SetHandler are used to associated all the files +in a given location (e.g., a particular directory) onto a particular +MIME type or handler. + +

    + +Note that changing the type or encoding of a file does not change the +value of the Last-Modified header. Thus, previously cached +copies may still be used by a client or proxy, with the previous headers. + +

    Files with Multiple Extensions

    + +Files can have more than one extension, and the order of the +extensions is normally irrelevant. For example, if the file +welcome.html.fr maps onto content type text/html and +language French then the file welcome.fr.html will map +onto exactly the same information. The only exception to this is if an +extension is given which Apache does not know how to handle. In this +case it will "forget" about any information it obtained from +extensions to the left of the unknown extension. So, for example, if +the extensions fr and html are mapped to the appropriate language and +type but extension xxx is not assigned to anything, then the file +welcome.fr.xxx.html will be associated with content-type +text/html but no language. + +

    + +If more than one extension is given which maps onto the same type of +meta-information, then the one to the right will be used. For example, +if ".gif" maps to the MIME-type image/gif and ".html" maps to the +MIME-type text/html, then the file welcome.gif.html will +be associated with the MIME-type "text/html". + +

    + +Care should be taken when a file with multiple extensions gets +associated with both a MIME-type and a handler. This will usually +result in the request being by the module associated with the +handler. For example, if the .imap extension is mapped to +the handler "imap-file" (from mod_imap) and the .html +extension is mapped to the MIME-type "text/html", then the file +world.imap.html will be associated with both the +"imap-file" handler and "text/html" MIME-type. When it is processed, +the "imap-file" handler will be used, and so it will be treated as a +mod_imap imagemap file. + +

    Directives

    + +
    + +

    AddCharset

    +Syntax: AddCharset charset extension + [extension...]
    +Context: server config, virtual host, directory, .htaccess
    +Override: FileInfo
    +Status: Base
    +Module: mod_mime +
    +Compatibility: AddCharset is only available in Apache +1.3.10 and later + +

    +The AddCharset directive maps the given filename extensions to the +specified content charset. charset is the MIME charset +parameter of filenames containing extension. This mapping is +added to any already in force, overriding any mappings that already +exist for the same extension. +

    +

    +Example: +

    +    AddLanguage ja .ja
    +    AddCharset EUC-JP .euc
    +    AddCharset ISO-2022-JP .jis
    +    AddCharset SHIFT_JIS .sjis
    +
    + +

    +Then the document xxxx.ja.jis will be treated as being a +Japanese document whose charset is ISO-2022-JP (as will the document +xxxx.jis.ja). The AddCharset directive is useful for both +to inform the client about the character encoding of the document so +that the document can be interpreted and displayed appropriately, and +for content negotiation, where +the server returns one from several documents based on the client's +charset preference. +

    +

    +See also: mod_negotiation +

    + +
    + +

    AddEncoding

    + +Syntax: AddEncoding MIME-enc extension extension...
    +Context: server config, virtual host, directory, .htaccess
    +Override: FileInfo
    +Status: Base
    +Module: mod_mime

    + +The AddEncoding directive maps the given filename extensions to the +specified encoding type. MIME-enc is the MIME encoding to use +for documents containing the extension. This mapping is added +to any already in force, overriding any mappings that already exist +for the same extension. + +Example: +

    AddEncoding x-gzip gz
    AddEncoding x-compress Z +
    + +This will cause filenames containing the .gz extension to be marked as +encoded using the x-gzip encoding, and filenames containing the .Z +extension to be marked as encoded with x-compress.

    + +Old clients expect x-gzip and x-compress, +however the standard dictates that they're equivalent to gzip +and compress respectively. Apache does content encoding +comparisons by ignoring any leading x-. When responding +with an encoding Apache will use whatever form (i.e., x-foo +or foo) the client requested. If the client didn't +specifically request a particular form Apache will use the form given by +the AddEncoding directive. To make this long story short, +you should always use x-gzip and x-compress +for these two specific encodings. More recent encodings, such as +deflate should be specified without the x-. + +

    + +See also: Files with +multiple extensions + +


    + +

    AddHandler

    + +Syntax: AddHandler handler-name extension extension...
    +Context: server config, virtual host, directory, .htaccess
    +Override: FileInfo
    +Status: Base
    +Module: mod_mime
    +Compatibility: AddHandler is only available in Apache +1.1 and later

    + +

    AddHandler maps the filename extensions extension to the +handler handler-name. This +mapping is added to any already in force, overriding any mappings that +already exist for the same extension. + +For example, to activate CGI scripts +with the file extension ".cgi", you might use: +

    +    AddHandler cgi-script cgi
    +
    + +

    Once that has been put into your srm.conf or httpd.conf file, any +file containing the ".cgi" extension will be treated as a +CGI program.

    + +

    + +See also: Files with +multiple extensions + +


    + +

    AddLanguage

    + +Syntax: AddLanguage MIME-lang extension extension...
    +Context: server config, virtual host, directory, .htaccess
    +Override: FileInfo
    +Status: Base
    +Module: mod_mime + +

    +The AddLanguage directive maps the given filename extensions to the +specified content language. MIME-lang is the MIME language of +filenames containing extension. This mapping is added to any +already in force, overriding any mappings that already exist for the +same extension. +

    +

    +Example:

    +AddEncoding x-compress Z
    AddLanguage en .en
    AddLanguage fr +.fr
    +

    +

    +Then the document xxxx.en.Z will be treated as being a +compressed English document (as will the document +xxxx.Z.en). Although the content language is reported to +the client, the browser is unlikely to use this information. The +AddLanguage directive is more useful for +content negotiation, where +the server returns one from several documents based on the client's +language preference. +

    +

    +If multiple language assignments are made for the same extension, +the last one encountered is the one that is used. That is, for the +case of: +

    +
    +    AddLanguage en .en
    +    AddLanguage en-uk .en
    +    AddLanguage en-us .en
    +
    +

    +documents with the extension ".en" would be treated as +being "en-us". +

    +

    +See also: Files with +multiple extensions +
    +See also: mod_negotiation +

    + +
    + +

    AddType

    + +Syntax: AddType MIME-type extension extension...
    +Context: server config, virtual host, directory, .htaccess
    +Override: FileInfo
    +Status: Base
    +Module: mod_mime

    + +The AddType directive maps the given filename extensions onto the +specified content type. MIME-enc is the MIME type to use for +filenames containing extension. This mapping is added to any +already in force, overriding any mappings that already exist for the +same extension. This directive can be used to add mappings +not listed in the MIME types file (see the TypesConfig directive). + +Example: +

    +AddType image/gif GIF +
    +It is recommended that new MIME types be added using the AddType directive +rather than changing the TypesConfig file.

    +Note that, unlike the NCSA httpd, this directive cannot be used to set the +type of particular files.

    + +

    + +See also: Files with +multiple extensions + +


    + +

    DefaultLanguage

    + +Syntax: DefaultLanguage MIME-lang
    +Context: server config, virtual host, directory, .htaccess
    +Override: FileInfo
    +Status: Base
    +Module: mod_mime
    +Compatibility: DefaultLanguage is only available in Apache +1.3.4 and later.

    + +The DefaultLanguage directive tells Apache that all files in the +directive's scope (e.g., all files covered by the current +<Directory> container) that don't have an explicit +language extension (such as .fr or .de as +configured by AddLanguage) should be considered to be in +the specified MIME-lang language. This allows entire +directories to be marked as containing Dutch content, for instance, +without having to rename each file. Note that unlike using extensions +to specify languages, DefaultLanguage can only specify a +single language. + +

    + +If no DefaultLanguage directive is in force, and a file +does not have any language extensions as configured by +AddLanguage, then that file will be considered to have no +language attribute. + +

    + +See also: mod_negotiation +
    +See also: Files with +multiple extensions + +


    + +

    ForceType

    + +Syntax: ForceType media type
    +Context: directory, .htaccess
    +Status: Base
    +Module: mod_mime
    +Compatibility: ForceType is only available in Apache +1.1 and later.

    + +

    When placed into an .htaccess file or a +<Directory> or <Location> section, +this directive forces all matching files to be served +as the content type given by media type. For example, if you +had a directory full of GIF files, but did not want to label them all with +".gif", you might want to use: +

    +    ForceType image/gif
    +
    +

    Note that this will override any filename extensions that might determine +the media type.


    + +

    RemoveHandler

    + +Syntax: RemoveHandler extension extension...
    +Context: directory, .htaccess
    +Status: Base
    +Module: mod_mime
    +Compatibility: RemoveHandler is only available in Apache +1.3.4 and later.

    + +

    +The RemoveHandler directive removes any +handler associations for files with the given extensions. +This allows .htaccess files in subdirectories to undo +any associations inherited from parent directories or the server +config files. An example of its use might be: +

    +
    +
    /foo/.htaccess:
    +
    AddHandler server-parsed .html
    +
    /foo/bar/.htaccess:
    +
    RemoveHandler .html
    +
    +

    +This has the effect of returning .html files in the +/foo/bar directory to being treated as normal +files, rather than as candidates for parsing (see the +mod_include module). +

    +
    + +

    SetHandler

    + +Syntax: SetHandler handler-name
    +Context: directory, .htaccess
    +Status: Base
    +Module: mod_mime
    +Compatibility: SetHandler is only available in Apache +1.1 and later.

    + +

    When placed into an .htaccess file or a +<Directory> or <Location> section, +this directive forces all matching files to be parsed through the +handler +given by handler-name. For example, if you had a +directory you wanted to be parsed entirely as imagemap rule files, +regardless of extension, you might put the following into an +.htaccess file in that directory: +

    +    SetHandler imap-file
    +
    + +

    Another example: if you wanted to have the server display a status +report whenever a URL of http://servername/status was +called, you might put the following into access.conf: +

    +    <Location /status>
    +    SetHandler server-status
    +    </Location>
    +
    +
    + +

    TypesConfig

    + +Syntax: TypesConfig filename
    +Default: TypesConfig conf/MIME.types
    +Context: server config
    +Status: Base
    +Module: mod_mime

    + +The TypesConfig directive sets the location of the MIME types configuration +file. Filename is relative to the +ServerRoot. This file sets the default list of +mappings from filename extensions to content types; changing this file is not +recommended. Use the AddType directive instead. The +file contains lines in the format of the arguments to an AddType command: +

    MIME-type extension extension ...
    +The extensions are lower-cased. Blank lines, and lines beginning with a hash +character (`#') are ignored.

    + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_mime_magic.html b/APACHE_1_3_12/htdocs/manual/mod/mod_mime_magic.html new file mode 100644 index 0000000000..a85e6b46b5 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_mime_magic.html @@ -0,0 +1,275 @@ + + + + Apache module mod_mime_magic + + + +

    + [APACHE DOCUMENTATION] +
    + +

    Module mod_mime_magic

    + + This module is contained in the mod_mime_magic.c file, and is + an optional extension to the Apache HTTPD server. + It can be used to determine the MIME type of a file by looking at a + few bytes of its contents, the same way the Unix file(1) command works. + To use mod_mime_magic you have to enable the following line in the + server build Configuration file: + +
    +      AddModule modules/standard/mod_mime_magic.o
    +  
    + + This should be listed before mod_mime in the build + Configuration file so that it will be used after mod_mime. + mod_mime_magic is intended as a "second line of defense" for cases + mod_mime cannot resolve. + +

    Summary

    + + This module is derived from a free version of the file(1) + command for Unix, + which uses "magic numbers" and other hints from a file's contents to + figure out what the contents are. + In the case of this module, + it tries to figure out the MIME type of the file. +

    + This module active only if the magic file is specified by the + MimeMagicFile directive. +

    + The contents of the file are plain ASCII text in 4-5 columns. + Blank lines are allowed but ignored. + Commented lines use a hash mark "#". + The remaining lines are parsed for the following columns: + + + + + + + + + + + + + + + + + + + + + +
    ColumnDescription
    1byte number to begin checking from +
    + ">" indicates a dependency upon the previous non-">" line
    2type of data to match + + + + + + + + + + + + +
    bytesingle character
    shortmachine-order 16-bit integer
    longmachine-order 32-bit integer
    stringarbitrary-length string
    datelong integer date + (seconds since Unix epoch/1970)
    beshortbig-endian 16-bit integer
    belongbig-endian 32-bit integer
    bedatebig-endian 32-bit integer date
    leshortlittle-endian 16-bit integer
    lelonglittle-endian 32-bit integer
    ledatelittle-endian 32-bit integer date
    +
    3contents of data to match
    4MIME type if matched
    5MIME encoding if matched (optional)
    + +

    + For example, the following magic file lines + would recognize some audio formats. + +

    +# Sun/NeXT audio data
    +0       string          .snd
    +>12     belong          1               audio/basic
    +>12     belong          2               audio/basic
    +>12     belong          3               audio/basic
    +>12     belong          4               audio/basic
    +>12     belong          5               audio/basic
    +>12     belong          6               audio/basic
    +>12     belong          7               audio/basic
    +>12     belong          23              audio/x-adpcm
    +
    + + Or these would recognize the difference between "*.doc" files containing + Microsoft Word or FrameMaker documents. (These are incompatible file + formats which use the same file suffix.) + +
    +# Frame
    +0       string          \<MakerFile     application/x-frame
    +0       string          \<MIFFile       application/x-frame
    +0       string          \<MakerDictionary       application/x-frame
    +0       string          \<MakerScreenFon        application/x-frame
    +0       string          \<MML           application/x-frame
    +0       string          \<Book          application/x-frame
    +0       string          \<Maker         application/x-frame
    +
    +# MS-Word
    +0       string          \376\067\0\043                  application/msword
    +0       string          \320\317\021\340\241\261        application/msword
    +0       string          \333\245-\0\0\0                 application/msword
    +
    + + An optional MIME encoding can be included as a fifth column. + For example, this can recognize gzipped files and set the encoding + for them. + +
    +# gzip (GNU zip, not to be confused with [Info-ZIP/PKWARE] zip archiver)
    +0       string          \037\213        application/octet-stream        x-gzip
    +
    + +

    Performance Issues

    + + This module is not for every system. If your system is barely keeping + up with its load or if you're performing a web server benchmark, + you may not want to enable this because the processing is not free. +

    + However, an effort was made to improve the performance of the original + file(1) code to make it fit in a busy web server. + It was designed for a server where there are thousands of users who + publish their own documents. + This is probably very common on intranets. + Many times, it's helpful + if the server can make more intelligent decisions about a file's + contents than the file name allows + ...even if just to reduce the "why doesn't my page work" calls + when users improperly name their own files. + You have to decide if the extra work suits your environment. +

    + When compiling an Apache server, this module should be at or near the + top of the list of modules in the Configuration file. The modules are + listed in increasing priority so that will mean this one is used only + as a last resort, just like it was designed to. + +

    Directives

    +

    +

    +

    +
    +

    + MimeMagicFile +

    +

    + Syntax: MimeMagicFile magic-file-name +
    + Default: none +
    + Context: server config, virtual host +
    + Status: Extension +
    + Module: mod_mime_magic +

    + + The MimeMagicFile directive can be used to enable this module, + the default file is distributed at conf/magic. + Non-rooted paths are relative to the ServerRoot. Virtual hosts + will use the same file as the main server unless a more specific setting + is used, in which case the more specific setting overrides the main server's + file. +

    +


    + +

    Notes

    + + The following notes apply to the mod_mime_magic module and are + included here for compliance with contributors' copyright restrictions + that require their acknowledgment. + +
    +/*
    + * 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.
    + *
    + */
    +
    + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_mmap_static.html b/APACHE_1_3_12/htdocs/manual/mod/mod_mmap_static.html new file mode 100644 index 0000000000..07ed6b7350 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_mmap_static.html @@ -0,0 +1,142 @@ + + + + Apache module mod_mmap_static + + + + +

    Module mod_mmap_static

    + +

    + This module is contained in the mod_mmap_static.c file, with + Apache 1.3 and later. It provides mmap()ing of a statically configured list + of frequently requested but not changed files. It is not compiled into the + server by default. To use mod_mmap_static you have to enable + the following line in the server build Configuration file: +

    +    AddModule  modules/experimental/mod_mmap_static.o
    +  
    +

    + +

    Summary

    +

    + This is an experimental module and should be used with + care. You can easily create a broken site using this module, read this + document carefully. + mod_mmap_static maps a list of statically configured files (via + MMapFile directives in the main server configuration) into + memory through the system call mmap(). This system + call is available on most modern Unix derivates, but not on all. There + are sometimes system-specific limits on the size and number of files that + can be mmap()d, experimentation is probably the easiest way to find out. +

    +

    + This mmap()ing is done once at server start or restart, only. So whenever + one of the mapped files changes on the filesystem you have to + restart the server by at least sending it a HUP or USR1 signal (see the + Stopping and Restarting documentation). 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. The reason why this modules doesn't take care of changes to the files + is that this check would need an extra stat() every time which + is a waste and against the intent of I/O reduction. +

    + +

    Directives

    + + +
    + +

    MMapFile

    +

    + Syntax: MMapFile filename ... +
    + Default: None +
    + Context: server-config +
    + Override: Not applicable +
    + Status: Experimental +
    + Module: mod_mmap_static +
    + Compatibility: Only available in Apache 1.3 or later + +

    + The MMapFile directive maps one or more files (given as + whitespace separated arguments) into memory at server startup time. They + are automatically unmapped on a server shutdown. When the files have changed + on the filesystem at least a HUP or USR1 signal should be send to the server + to re-mmap them. +

    + +

    + Be careful with the filename arguments: They have to literally + match the filesystem path Apache's URL-to-filename translation handlers + create. We cannot compare inodes or other stuff to match paths through + symbolic links etc. because that again would cost extra stat() + system calls which is not acceptable. This module may or may not work + with filenames rewritten by mod_alias or + mod_rewrite... it is an experiment after all. +

    + +

    + Notice: You cannot use this for speeding up CGI programs or other files + which are served by special content handlers. It can only be used for + regular files which are usually served by the Apache core content handler. +

    + + Example: + +
    +  MMapFile /usr/local/apache/htdocs/index.html
    +  
    + +

    + Note: don't bother asking for a for a MMapDir + directive which + recursively maps all the files in a directory. Use Unix the way it was + meant to be used. For example, see the + Include directive, and consider this command: +

    +  find /www/htdocs -type f -print \
    +  | sed -e 's/.*/mmapfile &/' > /www/conf/mmap.conf
    +  
    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_negotiation.html b/APACHE_1_3_12/htdocs/manual/mod/mod_negotiation.html new file mode 100644 index 0000000000..96222acb22 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_negotiation.html @@ -0,0 +1,201 @@ + + + +Apache module mod_negotiation + + + + + +

    Module mod_negotiation

    + +This module is contained in the mod_negotiation.c file, +and is compiled in by default. It provides for content negotiation. + +

    Summary

    +Content negotiation, or more accurately content selection, is the +selection of the document that best matches the clients +capabilities, from one of several available documents. +There are two implementations of this. +
      +
    • A type map (a file with the handler type-map) +which explicitly lists the files containing the variants. +
    • A MultiViews search (enabled by the MultiViews +Option, where the server does an implicit +filename pattern match, and choose from amongst the results. +
    + +

    Type maps

    +A type map has the same format as RFC822 mail headers. It contains document +descriptions separated by blank lines, with lines beginning with a hash +character ('#') treated as comments. A document description consists of +several header records; records may be continued on multiple lines if the +continuation lines start with spaces. The leading space will be deleted +and the lines concatenated. A header record consists of a keyword +name, which always ends in a colon, followed by a value. Whitespace is allowed +between the header name and value, and between the tokens of value. + +The headers allowed are: + +
    +
    Content-Encoding: +
    The encoding of the file. Apache only recognizes encodings that are +defined by an AddEncoding directive. +This normally includes the encodings x-compress for compress'd +files, and x-gzip for gzip'd files. The x- prefix +is ignored for encoding comparisons. +
    Content-Language: +
    The language of the variant, as an Internet standard language tag +(RFC 1766). An example is en, meaning English. +
    Content-Length: +
    The length of the file, in bytes. If this header is not present, then +the actual length of the file is used. +
    Content-Type: +
    The MIME media type of the document, with optional parameters. +Parameters are separated from the media type and from one another by a +semi-colon, with a syntax of name=value. Common parameters +include: +
    +
    level +
    an integer specifying the version of the media type. +For text/html this defaults to 2, otherwise 0. +
    qs +
    a floating-point number with a value in the range 0.0 to 1.0, + indicating the relative 'quality' of this variant + compared to the other available variants, independent of the client's + capabilities. For example, a jpeg file is usually of higher source + quality than an ascii file if it is attempting to represent a + photograph. However, if the resource being represented is ascii art, + then an ascii file would have a higher source quality than a jpeg file. + All qs values are therefore specific to a given resource. +
    +Example: +
    Content-Type: image/jpeg; qs=0.8
    +
    URI: +
    The path to the file containing this variant, relative to the map file. +
    + +

    MultiViews

    +A MultiViews search is enabled by the MultiViews +Option. +If the server receives a request for /some/dir/foo and +/some/dir/foo does not exist, then the server reads the +directory looking for all files named foo.*, and effectively +fakes up a type map which names all those files, assigning them the same media +types and content-encodings it would have if the client had asked for +one of them by name. It then chooses the best match to the client's +requirements, and returns that document.

    + + + +

    Directives

    + + +See also: +DefaultLanguage, +AddEncoding, +AddLanguage, +AddType, and +Option. + +
    + + +

    CacheNegotiatedDocs

    +Syntax: CacheNegotiatedDocs
    +Context: server config
    +Status: Base
    +Module: mod_negotiation
    +Compatibility: CacheNegotiatedDocs is only available +in Apache 1.1 and later.

    + +

    If set, this directive allows content-negotiated documents to be +cached by proxy servers. This could mean that clients behind those +proxys could retrieve versions of the documents that are not the best +match for their abilities, but it will make caching more +efficient. +

    + +This directive only applies to requests which come from HTTP/1.0 browsers. +HTTP/1.1 provides much better control over the caching of negotiated +documents, and this directive has no effect in responses to +HTTP/1.1 requests. + + + +

    LanguagePriority

    + +Syntax: LanguagePriority MIME-lang MIME-lang...
    +Context: server config, virtual host, directory, .htaccess
    +Override: FileInfo
    +Status: Base
    +Module: mod_negotiation

    + +The LanguagePriority sets the precedence of language variants for the case +where the client does not express a preference, when handling a +MultiViews request. The list of MIME-lang are in order of decreasing +preference. Example: + +

    LanguagePriority en fr de
    + +For a request for foo.html, where foo.html.fr +and foo.html.de both existed, but the browser did not express +a language preference, then foo.html.fr would be returned.

    + +

    + +Note that this directive only has an effect if a 'best' language +cannot be determined by any other means. Correctly implemented +HTTP/1.1 requests will mean this directive has no effect. + +

    + +See also: +DefaultLanguage and +AddLanguage + + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_proxy.html b/APACHE_1_3_12/htdocs/manual/mod/mod_proxy.html new file mode 100644 index 0000000000..6e9db4fdd9 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_proxy.html @@ -0,0 +1,1162 @@ + + + +Apache module mod_proxy + + + + + +

    Apache module mod_proxy

    + +This module is contained in the mod_proxy.c file for Apache 1.1.x, +or the modules/proxy subdirectory for Apache 1.2, and +is not compiled in by default. It provides for an HTTP +1.0 caching proxy +server. It is only available in Apache 1.1 and later. Common configuration +questions are addressed after the directive +descriptions. + +

    Note:

    +

    This module was experimental in Apache 1.1.x. As of Apache 1.2, mod_proxy +stability is greatly improved.

    + +

    Summary

    + +This module implements a proxy/cache for Apache. It implements +proxying capability for +FTP, +CONNECT (for SSL), +HTTP/0.9, and +HTTP/1.0. +The module can be configured to connect to other proxy modules for these +and other protocols. + +

    Directives

    + + +
    + +

    ProxyRequests

    +Syntax: ProxyRequests on/off
    +Default: ProxyRequests Off
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: ProxyRequests is only available in +Apache 1.1 and later.

    + +This allows or prevents Apache from functioning as a proxy +server. Setting ProxyRequests to 'off' does not disable use of the ProxyPass directive. + +


    + +

    ProxyRemote

    +Syntax: ProxyRemote <match> <remote-server>
    +Default: None
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: ProxyRemote is only available in +Apache 1.1 and later.

    + +This defines remote proxies to this proxy. <match> is either the +name of a URL-scheme that the remote server supports, or a partial URL +for which the remote server should be used, or '*' to indicate the +server should be contacted for all requests. <remote-server> is a +partial URL for the remote server. Syntax: + +

    +  <remote-server> = <protocol>://<hostname>[:port]
    +
    + +<protocol> is the protocol that should be used to communicate +with the remote server; only "http" is supported by this module. +

    +Example: +

    +  ProxyRemote http://goodguys.com/ http://mirrorguys.com:8000
    +  ProxyRemote * http://cleversite.com
    +  ProxyRemote ftp http://ftpproxy.mydomain.com:8080
    +
    + +In the last example, the proxy will forward FTP requests, encapsulated +as yet another HTTP proxy request, to another proxy which can handle +them. + +
    + +

    ProxyPass

    +Syntax: ProxyPass <path> <url>
    +Default: None
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: ProxyPass is only available in +Apache 1.1 and later.

    + +This directive allows remote servers to be mapped into the space of the local +server; the local server does not act as a proxy in the conventional sense, +but appears to be a mirror of the remote server. <path> is the name of +a local virtual path; <url> is a partial URL for the remote server. +

    +Suppose the local server has address http://wibble.org/; then +

    +   ProxyPass /mirror/foo/ http://foo.com/
    +
    +will cause a local request for the +<http://wibble.org/mirror/foo/bar> to be +internally converted into a proxy request to +<http://foo.com/bar>. + +
    + +

    ProxyPassReverse

    +Syntax: ProxyPassReverse <path> <url>
    +Default: None
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: ProxyPassReverse is only available in +Apache 1.3b6 and later.

    + +This directive lets Apache adjust the URL in the Location header on +HTTP redirect responses. For instance this is essential when Apache is used as +a reverse proxy to avoid by-passing the reverse proxy because of HTTP +redirects on the backend servers which stay behind the reverse proxy. +

    +<path> is the name of a local virtual path.
    +<url> is a partial URL for the remote server - the same way they are +used for the ProxyPass directive. +

    +Example:
    +Suppose the local server has address http://wibble.org/; then +

    +   ProxyPass         /mirror/foo/ http://foo.com/
    +   ProxyPassReverse  /mirror/foo/ http://foo.com/
    +
    +will not only cause a local request for the +<http://wibble.org/mirror/foo/bar> to be internally +converted into a proxy request to <http://foo.com/bar> (the +functionality ProxyPass provides here). It also takes care of +redirects the server foo.com sends: when http://foo.com/bar is +redirected by him to http://foo.com/quux Apache adjusts this to +http://wibble.org/mirror/foo/quux before forwarding the HTTP +redirect response to the client. +

    +Note that this ProxyPassReverse directive can also be used in +conjunction with the proxy pass-through feature ("RewriteRule ... +[P]") from +mod_rewrite because its doesn't depend on a corresponding +ProxyPass directive. + +


    + +

    AllowCONNECT

    +Syntax: AllowCONNECT <port list>
    +Default: AllowCONNECT 443 563
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: AllowCONNECT is only +available in Apache 1.3.2 and later.

    + +The AllowCONNECT directive specifies a list of port numbers +to which the proxy CONNECT method may connect. +Today's browsers use this method when a https connection +is requested and proxy tunneling over http is in effect.
    +By default, only the default https port (443) and the default +snews port (563) are enabled. Use the AllowCONNECT +directive to overrride this default and allow connections to the +listed ports only. + +


    + +

    ProxyBlock

    +Syntax: ProxyBlock <word/host/domain list>
    +Default: None
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: ProxyBlock is only available in +Apache 1.2 and later.

    + +The ProxyBlock directive specifies a list of words, hosts and/or domains, +separated by spaces. HTTP, HTTPS, and FTP document requests to sites whose +names contain matched words, hosts or domains are blocked by the +proxy server. The proxy module will also attempt to determine IP addresses of +list items which may be hostnames during startup, and cache them for match +test as well. Example: + +

    +  ProxyBlock joes-garage.com some-host.co.uk rocky.wotsamattau.edu
    +
    + +'rocky.wotsamattau.edu' would also be matched if referenced by IP address.

    + +Note that 'wotsamattau' would also be sufficient to match 'wotsamattau.edu'.

    + +Note also that + +

    +ProxyBlock *
    +
    + +blocks connections to all sites. + +
    + +

    ProxyReceiveBufferSize

    +Syntax: ProxyReceiveBufferSize <bytes>
    +Default: None
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: ProxyReceiveBufferSize is only available in +Apache 1.3 and later.

    + +The ProxyReceiveBufferSize directive specifies an explicit network buffer size +for outgoing HTTP and FTP connections, for increased throughput. It has to be +greater than 512 or set to 0 to indicate that the system's default buffer size +should be used. + +

    +Example: + +

    +  ProxyReceiveBufferSize 2048
    +
    + +
    + +

    NoProxy

    +Syntax: NoProxy { <Domain> + | <SubNet> + | <IpAddr> + | <Hostname> + }
    +Default: None
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: NoProxy is only available in +Apache 1.3 and later.

    + +This directive is only useful for Apache proxy servers within intranets. +The NoProxy directive specifies a list of subnets, IP addresses, hosts +and/or domains, separated by spaces. A request to a host which matches +one or more of these is always served directly, without forwarding to +the configured ProxyRemote proxy server(s). +

    +Example: + +

    +  ProxyRemote  *  http://firewall.mycompany.com:81
    +  NoProxy         .mycompany.com 192.168.112.0/21 
    +
    +The arguments to the NoProxy directive are one of the following type list: +
    + + +
    Domain +
    A Domain is a partially qualified DNS domain name, preceded + by a period. + It represents a list of hosts which logically belong to the same DNS + domain or zone (i.e., the suffixes of the hostnames are all ending in + Domain).
    + Examples: .com .apache.org.
    + To distinguish Domains from Hostnames (both + syntactically and semantically; a DNS domain can have a DNS A record, + too!), Domains are always written + with a leading period.
    + Note: Domain name comparisons are done without regard to the case, + and Domains are always assumed to be anchored in the root + of the DNS tree, therefore two domains .MyDomain.com and + .mydomain.com. (note the trailing period) are + considered equal. Since a domain comparison does not involve a DNS + lookup, it is much more efficient than subnet comparison. + + + +
    SubNet +
    A SubNet is a partially qualified internet address in + numeric (dotted quad) form, optionally followed by a slash and the + netmask, specified as the number of significant bits in the + SubNet. It is used to represent a subnet of hosts which can + be reached over a common network interface. In the absence of the + explicit net mask it is assumed that omitted (or zero valued) + trailing digits specify the mask. (In this case, the netmask can + only be multiples of 8 bits wide.)
    + Examples: +
    +
    192.168 or 192.168.0.0 +
    the subnet 192.168.0.0 with an implied netmask of 16 valid bits + (sometimes used in the netmask form 255.255.0.0) +
    192.168.112.0/21 +
    the subnet 192.168.112.0/21 with a netmask of 21 + valid bits (also used in the form 255.255.248.0) +
    + As a degenerate case, a SubNet with 32 valid bits is the + equivalent to an IPAddr, while a SubNet with zero + valid bits (e.g., 0.0.0.0/0) is the same as the constant + _Default_, matching any IP address. + + + +
    IPAddr +
    A IPAddr represents a fully qualified internet address in + numeric (dotted quad) form. Usually, this address represents a + host, but there need not necessarily be a DNS domain name + connected with the address.
    + Example: 192.168.123.7
    + Note: An IPAddr does not need to be resolved by the DNS + system, so it can result in more effective apache performance. +

    See Also: + DNS Issues

    + + + +
    Hostname +
    A Hostname is a fully qualified DNS domain name which can + be resolved to one or more IPAddrs via the DNS domain name service. + It represents a logical host (in contrast to + Domains, see + above) and must be resolvable to at least one IPAddr (or often to a list of hosts + with different IPAddr's).
    + Examples: prep.ai.mit.edu + www.apache.org.
    + Note: In many situations, it is more effective to specify an + IPAddr in place of a + Hostname since a DNS lookup + can be avoided. Name resolution in Apache can take a remarkable deal + of time when the connection to the name server uses a slow PPP + link.
    + Note: Hostname comparisons are done without regard to the case, + and Hostnames are always assumed to be anchored in the root + of the DNS tree, therefore two hosts WWW.MyDomain.com + and www.mydomain.com. (note the trailing period) are + considered equal.
    +

    See Also: +DNS Issues

    +
    + +
    + +

    ProxyDomain

    +Syntax: ProxyDomain <Domain>
    +Default: None
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: ProxyDomain is only available in +Apache 1.3 and later.

    + +This directive is only useful for Apache proxy servers within intranets. +The ProxyDomain directive specifies the default domain which the apache +proxy server will belong to. If a request to a host without a domain name +is encountered, a redirection response to the same host +with the configured Domain appended will be generated. +

    +Example: + +

    +  ProxyRemote  *  http://firewall.mycompany.com:81
    +  NoProxy         .mycompany.com 192.168.112.0/21 
    +  ProxyDomain     .mycompany.com
    +
    + +
    + +

    ProxyVia

    +Syntax: ProxyVia { off + | on + | full + | block + }
    +Default: ProxyVia off
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: ProxyVia is only available in +Apache 1.3.2 and later.

    + +This directive controls the use of the Via: HTTP header +by the proxy. Its intended use is to control the flow of of proxy +requests along a chain of proxy servers. +See RFC2068 (HTTP/1.1) for an explanation of Via: header lines.

      +
    • If set to off, which is the default, no special +processing is performed. If a request or reply contains a Via: header, +it is passed through unchanged. +
    • If set to on, each request and reply will get a Via: header +line added for the current host. +
    • If set to full, each generated Via: header line will +additionally have the Apache server version shown as a Via: comment field. +
    • If set to block, every proxy request will have all its +Via: header lines removed. No new Via: header will be generated. +
    + +
    + +

    CacheForceCompletion

    +Syntax: CacheForceCompletion <percentage>
    +Default: 90
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: CacheForceCompletion is only available in +Apache 1.3.1 and later.

    + +If an http transfer that is being cached is cancelled, the proxy module will +complete the transfer to cache if more than the percentage specified has +already been transferred.

    + +This is a percentage, and must be a number between 1 and 100, or 0 to use +the default. 100 will cause a document to be cached only if the transfer +was allowed to complete. A number between 60 and 90 is recommended. + +


    + +

    CacheRoot

    +Syntax: CacheRoot <directory>
    +Default: None
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: CacheRoot is only available in +Apache 1.1 and later.

    + +Sets the name of the directory to contain cache files; this must be +writable by the httpd server. +(see the User directive).
    +Setting CacheRoot enables proxy cacheing; without defining +a CacheRoot, proxy functionality will be available +if ProxyRequests are set to On, but no +cacheing will be available. + +


    + +

    CacheSize

    +Syntax: CacheSize <size>
    +Default: CacheSize 5
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: CacheSize is only available in +Apache 1.1 and later.

    + +Sets the desired space usage of the cache, in KB (1024-byte units). Although +usage may grow above this setting, the garbage collection will delete files +until the usage is at or below this setting.
    +Depending on the expected proxy traffic volume and CacheGcInterval, +use a value which is at least 20 to 40 % lower than the available space. + +


    + +

    CacheGcInterval

    +Syntax: CacheGcInterval <time>
    +Default: None
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: CacheGcinterval is only available in +Apache 1.1 and later.

    + +Check the cache every <time> hours, and delete files if the space +usage is greater than that set by CacheSize. Note that <time> accepts a +float value, you could for example use CacheGcInterval 1.5 to +check the cache every 90 minutes. (If unset, no garbage collection will +be performed, and the cache will grow indefinitely.) +Note also that the larger the CacheGcInterval, the more +extra space beyond the configured CacheSize will be +needed for the cache between garbage collections.
    + +


    + +

    CacheMaxExpire

    +Syntax: CacheMaxExpire <time>
    +Default: CacheMaxExpire 24
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: CacheMaxExpire is only available in +Apache 1.1 and later.

    + +Cachable HTTP documents will be retained for at most <time> hours without +checking the origin server. Thus documents can be at most <time> +hours out of date. This restriction is enforced even if an expiry date +was supplied with the document. + +


    + +

    CacheLastModifiedFactor

    +Syntax: CacheLastModifiedFactor <factor>
    +Default: CacheLastModifiedFactor 0.1
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: CacheLastModifiedFactor is only available in +Apache 1.1 and later.

    + +If the origin HTTP server did not supply an expiry date for the +document, then estimate one using the formula +

    +  expiry-period = time-since-last-modification * <factor>
    +
    +For example, if the document was last modified 10 hours ago, and +<factor> is 0.1, then the expiry period will be set to 10*0.1 = 1 hour. + +

    If the expiry-period would be longer than that set by CacheMaxExpire, +then the latter takes precedence. + +


    + +

    CacheDirLevels

    +Syntax: CacheDirLevels <levels>
    +Default: CacheDirLevels 3
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: CacheDirLevels is only available in +Apache 1.1 and later.

    + +CacheDirLevels sets the number of levels of subdirectories in the cache. +Cached data will be saved this many directory levels below CacheRoot. + +


    + +

    CacheDirLength

    +Syntax: CacheDirLength <length>
    +Default: CacheDirLength 1
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: CacheDirLength is only available in +Apache 1.1 and later.

    + +CacheDirLength sets the number of characters in proxy cache subdirectory names. + +


    + +

    CacheDefaultExpire

    +Syntax: CacheDefaultExpire <time>
    +Default: CacheDefaultExpire 1
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: CacheDefaultExpire is only available in +Apache 1.1 and later.

    + +If the document is fetched via a protocol that does not support expiry times, +then use <time> hours as the expiry time. +CacheMaxExpire does not +override this setting. + +


    + +

    NoCache

    +Syntax: NoCache <word/host/domain list>
    +Default: None
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Base
    +Module: mod_proxy
    +Compatibility: NoCache is only available in +Apache 1.1 and later.

    + +The NoCache directive specifies a list of words, hosts and/or domains, separated +by spaces. HTTP and non-passworded FTP documents from matched words, hosts or +domains are not cached by the proxy server. The proxy module will +also attempt to determine IP addresses of list items which may be hostnames +during startup, and cache them for match test as well. Example: + +

    +  NoCache joes-garage.com some-host.co.uk bullwinkle.wotsamattau.edu
    +
    + +'bullwinkle.wotsamattau.edu' would also be matched if referenced by IP +address.

    + +Note that 'wotsamattau' would also be sufficient to match 'wotsamattau.edu'.

    + +Note also that + +

    +NoCache *
    +
    + +disables caching completely.

    + +


    + +

    Common configuration topics

    + + + +

    Controlling access to your proxy

    + +You can control who can access your proxy via the normal <Directory> +control block using the following example:

    + +

    +<Directory proxy:*>
    +order deny,allow
    +deny from [machines you'd like *not* to allow by IP address or name]
    +allow from [machines you'd like to allow by IP address or name]
    +</Directory>
    +

    + +A <Files> block will also work, and is the only method known to work +for all possible URLs in Apache versions earlier than 1.2b10.

    + +

    Using Netscape hostname shortcuts

    + +There is an optional patch to the proxy module to allow Netscape-like +hostname shortcuts to be used. It's available from the +contrib/patches/1.2 directory on the Apache Web site.

    + +

    Why doesn't file type xxx download via FTP?

    + +You probably don't have that particular file type defined as +application/octet-stream in your proxy's mime.types configuration +file. A useful line can be

    + +

    +application/octet-stream        bin dms lha lzh exe class tgz taz
    +
    + +

    How can I force an FTP ASCII download of File xxx?

    + +In the rare situation where you must download a specific file using the FTP +ASCII transfer method (while the default transfer is in +binary mode), you can override mod_proxy's default by +suffixing the request with ;type=a to force an ASCII transfer.

    + +

    Why does Apache start more slowly when using the + proxy module?

    + +If you're using the ProxyBlock or NoCache +directives, hostnames' IP addresses are looked up and cached during +startup for later match test. This may take a few seconds (or more) +depending on the speed with which the hostname lookups occur.

    + +

    Can I use the Apache proxy module with my SOCKS proxy?

    + +Yes. Just build Apache with the rule SOCKS4=yes in your +Configuration file, and follow the instructions there. SOCKS5 +capability can be added in a similar way (there's no SOCKS5 +rule yet), so use the EXTRA_LDFLAGS definition, or build Apache +normally and run it with the runsocks wrapper provided with SOCKS5, +if your OS supports dynamically linked libraries.

    + +Some users have reported problems when using SOCKS version 4.2 on Solaris. +The problem was solved by upgrading to SOCKS 4.3.

    + +Remember that you'll also have to grant access to your Apache proxy machine by +permitting connections on the appropriate ports in your SOCKS daemon's +configuration.

    + +

    What other functions are useful for an intranet proxy server?

    + +

    An Apache proxy server situated in an intranet needs to forward external +requests through the company's firewall. However, when it has to access +resources within the intranet, it can bypass the firewall when accessing +hosts. The NoProxy directive is useful for specifying +which hosts belong to the intranet and should be accessed directly.

    + +

    Users within an intranet tend to omit the local domain name from their +WWW requests, thus requesting "http://somehost/" instead of +"http://somehost.my.dom.ain/". Some commercial proxy servers let them get +away with this and simply serve the request, implying a configured +local domain. When the ProxyDomain directive +is used and the server is configured for +proxy service, Apache can return a redirect response and send the client +to the correct, fully qualified, server address. This is the preferred method +since the user's bookmark files will then contain fully qualified hosts.

    + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_rewrite.html b/APACHE_1_3_12/htdocs/manual/mod/mod_rewrite.html new file mode 100644 index 0000000000..38301fb677 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_rewrite.html @@ -0,0 +1,1867 @@ + + + + + + +Apache module mod_rewrite + + + + +
    + + +
    +

    Module mod_rewrite
    URL Rewriting Engine

    + +This module is contained in the mod_rewrite.c file, with Apache +1.2 and later. It provides a rule-based rewriting engine to rewrite requested +URLs on the fly. It is not compiled into the server by default. To use +mod_rewrite you have to enable the following line in the server +build Configuration file: +
    +    AddModule  modules/standard/mod_rewrite.o
    +
    + +

    +


    + +
    +

    Summary

    + +
    +
    +
    +``The great thing about mod_rewrite is it gives you all the +configurability and flexibility of Sendmail. The downside to +mod_rewrite is that it gives you all the configurability and +flexibility of Sendmail.'' +
    +-- Brian Behlendorf
    +Apache Group +
    +
    +
    +
    + +
    +
    +
    +`` +Despite the tons of examples and docs, mod_rewrite +is voodoo. Damned cool voodoo, but still voodoo. +'' +
    +-- Brian Moore
    +bem@news.cmc.net +
    +
    +
    +
    + +Welcome to mod_rewrite, the Swiss Army Knife of URL manipulation! + +

    +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 rules and an unlimited number of attached rule conditions for each rule to +provide a really flexible and powerful URL manipulation mechanism. The URL +manipulations can depend on various tests, for instance server variables, +environment variables, HTTP headers, time stamps and even external database +lookups in various formats can be used to achieve a really granular URL +matching. + +

    +This module operates on the full URLs (including the path-info part) both in +per-server context (httpd.conf) and per-directory context +(.htaccess) and can even generate query-string parts on result. +The rewritten result can lead to internal sub-processing, external request +redirection or even to an internal proxy throughput. + +

    +But all this functionality and flexibility has its drawback: complexity. So +don't expect to understand this entire module in just one day. + +

    +This module was invented and 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 +
    + +

    +


    + +

    Table Of Contents

    + +

    +Internal Processing +

    +

    +Configuration Directives +

    +Miscellaneous + + +

    +


    + +
    +

    Internal Processing

    +
    + +

    +


    + +

    +The internal processing of this module is very complex but needs to be +explained once even to the average user to avoid common mistakes and to let +you exploit its full functionality. + +

    API Phases

    + +

    +First you have to understand that when Apache processes a HTTP request it does +this in phases. A hook for each of these phases is provided by the Apache API. +Mod_rewrite uses two of these hooks: the URL-to-filename translation hook +which is used after the HTTP request has been read but before any authorization +starts and the Fixup hook which is triggered after the authorization phases +and after the per-directory config files (.htaccess) have been +read, but before the content handler is activated. + +

    +So, after a request comes in and Apache has determined the corresponding +server (or virtual server) the rewriting engine starts processing of all +mod_rewrite directives from the per-server configuration in the +URL-to-filename phase. A few steps later when the final data directories are +found, the per-directory configuration directives of mod_rewrite are triggered +in the Fixup phase. In both situations mod_rewrite rewrites URLs either to new +URLs or to filenames, although there is no obvious distinction between them. +This is a usage of the API which was not intended to be this way when the API +was designed, but as of Apache 1.x this is the only way mod_rewrite can +operate. To make this point more clear remember the following two points: + +

      +
    1. Although mod_rewrite rewrites URLs to URLs, URLs to filenames and + even filenames to filenames, the API currently provides only a + URL-to-filename hook. In Apache 2.0 the two missing hooks will be + added to make the processing more clear. But this point has no + drawbacks for the user, it is just a fact which should be + remembered: Apache does more in the URL-to-filename hook than the + API intends for it. +

      +

    2. Unbelievably mod_rewrite provides URL manipulations in per-directory + context, i.e., within .htaccess files, + although these are reached a very long time after the URLs have + been translated to filenames. It has to be this way because + .htaccess files live in the filesystem, so processing + has already reached this stage. In other words: According to the + API phases at this time it is too late for any URL manipulations. + To overcome this chicken and egg problem mod_rewrite uses a trick: + When you manipulate a URL/filename in per-directory context + mod_rewrite first rewrites the filename back to its corresponding + URL (which is usually impossible, but see the RewriteBase + directive below for the trick to achieve this) and then initiates + a new internal sub-request with the new URL. This restarts + processing of the API phases. +

      + Again mod_rewrite tries hard to make this complicated step totally + transparent to the user, but you should remember here: While URL + manipulations in per-server context are really fast and efficient, + per-directory rewrites are slow and inefficient due to this chicken and + egg problem. But on the other hand this is the only way mod_rewrite can + provide (locally restricted) URL manipulations to the average user. +

    + +

    +Don't forget these two points! + +

    Ruleset Processing

    + +Now when mod_rewrite is triggered in these two API phases, it reads the +configured rulesets from its configuration structure (which itself was either +created on startup for per-server context or during the directory walk of the +Apache kernel for per-directory context). Then the URL rewriting engine is +started with the contained ruleset (one or more rules together with their +conditions). The operation of the URL rewriting engine itself is exactly the +same for both configuration contexts. Only the final result processing is +different. + +

    +The order of rules in the ruleset is important because the rewriting engine +processes them in a special (and not very obvious) order. The +rule is this: The rewriting engine loops through the ruleset rule by rule +(RewriteRule directives) and when a particular rule matches it +optionally loops through existing corresponding conditions +(RewriteCond directives). For historical reasons the conditions +are given first, and so the control flow is a little bit long-winded. See +Figure 1 for more details. + +

    +

    + + + + + + + +
    [Needs graphics capability to display]
    +Figure 1: The control flow through the rewriting ruleset +
    +
    + +

    +As you can see, first the URL is matched against the Pattern of each +rule. When it fails mod_rewrite immediately stops processing this rule and +continues with the next rule. If the Pattern matches, mod_rewrite +looks for corresponding rule conditions. If none are present, it just +substitutes the URL with a new value which is constructed from the string +Substitution and goes on with its rule-looping. But if conditions +exist, it starts an inner loop for processing them in the order that +they are listed. For conditions the logic is different: we don't match a +pattern against the current URL. Instead we first create a string +TestString by expanding variables, back-references, map lookups, +etc. and then we try to match CondPattern against it. If the +pattern doesn't match, the complete set of conditions and the corresponding +rule fails. If the pattern matches, then the next condition is processed +until no more conditions are available. If all conditions match, processing +is continued with the substitution of the URL with Substitution. + +

    Regex Back-Reference Availability

    + +One important thing here has to be remembered: Whenever you +use parentheses in Pattern or in one of the CondPattern +back-references are internally created which can be used with the +strings $N and %N (see below). These +are available for creating the strings Substitution and +TestCond. Figure 2 shows to which locations the back-references are +transfered for expansion. + +

    +

    + + + + + + + +
    [Needs graphics capability to display]
    +Figure 2: The back-reference flow through a rule +
    +
    + +

    +We know this was a crash course on mod_rewrite's internal processing. But +you will benefit from this knowledge when reading the following documentation +of the available directives. + +

    +


    + +
    +

    Configuration Directives

    +
    + +

    +


    + +

    RewriteEngine

    +Syntax: + RewriteEngine {on,off}
    +Default: + RewriteEngine off
    +Context: + server config, virtual host, directory, .htaccess
    +Override: FileInfo
    +Status: Extension
    +Module: mod_rewrite.c
    +Compatibility: Apache 1.2
    + +

    +The RewriteEngine directive enables or disables the runtime +rewriting engine. If it is set to off this module does no runtime +processing at all. It does not even update the SCRIPT_URx +environment variables. + +

    +Use this directive to disable the module instead of commenting out +all the RewriteRule directives! + +

    +Note that, by default, rewrite configurations are not inherited. +This means that you need to have a RewriteEngine on +directive for each virtual host in which you wish to use it. + +

    +


    +

    + +

    RewriteOptions

    +Syntax: RewriteOptions Option
    +Default: None
    +Context: server config, virtual host, directory, + .htaccess
    +Override: FileInfo
    +Status: Extension
    +Module: mod_rewrite.c
    +Compatibility: Apache 1.2
    + +

    +The RewriteOptions directive sets some special options for the +current per-server or per-directory configuration. The Option +strings can be one of the following: + +

      +
    • 'inherit'
      + This forces the current configuration to inherit the configuration of the + parent. In per-virtual-server context this means that the maps, + conditions and rules of the main server are inherited. In per-directory + context this means that conditions and rules of the parent directory's + .htaccess configuration are inherited. +
    + +

    +


    +

    + +

    RewriteLog

    +Syntax: RewriteLog Filename
    +Default: None
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Extension
    +Module: mod_rewrite.c
    +Compatibility: Apache 1.2
    + +

    +The RewriteLog directive sets the name of the file to which the +server logs any rewriting actions it performs. If the name does not begin +with a slash ('/') then it is assumed to be relative to the +Server Root. The directive should occur only once per server +config. + +

    + + +
    +Note: To disable the logging of rewriting actions it is +not recommended to set Filename +to /dev/null, because although the rewriting engine does +not then output to a logfile it still creates the logfile +output internally. This will slow down the server with no advantage +to the administrator! +To disable logging either remove or comment out the +RewriteLog directive or use RewriteLogLevel 0! +
    + +

    + + +
    +Security: See the Apache Security +Tips document for details on why your security could be compromised if the +directory where logfiles are stored is writable by anyone other than the user +that starts the server. +
    + +

    +Example: +

    +
    +RewriteLog "/usr/local/var/apache/logs/rewrite.log"
    +
    +
    + +

    +


    +

    + +

    RewriteLogLevel

    +Syntax: RewriteLogLevel Level
    +Default: RewriteLogLevel 0 +
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Extension
    +Module: mod_rewrite.c
    +Compatibility: Apache 1.2
    + +

    +The RewriteLogLevel directive sets the verbosity level of the +rewriting +logfile. The default level 0 means no logging, while 9 or more means +that practically all actions are logged. + +

    +To disable the logging of rewriting actions simply set Level to 0. +This disables all rewrite action logs. + +

    + + +
    +Notice: Using a high value for Level will slow down +your Apache server dramatically! Use the rewriting logfile at +a Level greater than 2 only for debugging! +
    + + +

    +Example: +

    +
    +RewriteLogLevel 3
    +
    +
    + +

    +


    +

    + +

    RewriteLock

    +Syntax: RewriteLock Filename
    +Default: None
    +Context: server config
    +Override: Not applicable
    +Status: Extension
    +Module: mod_rewrite.c
    +Compatibility: Apache 1.3
    + +

    +This directive sets the filename for a synchronization lockfile which +mod_rewrite needs to communicate with RewriteMap +programs. Set this lockfile to a local path (not on a NFS-mounted +device) when you want to use a rewriting map-program. It is not required for +other types of rewriting maps. + +

    +


    +

    + +

    RewriteMap

    +Syntax: RewriteMap MapName + MapType:MapSource
    +Default: not used per default
    +Context: server config, virtual host
    +Override: Not applicable
    +Status: Extension
    +Module: mod_rewrite.c
    +Compatibility: Apache 1.2 (partially), Apache 1.3
    + +

    +The RewriteMap directive defines a Rewriting Map +which can be used inside rule substitution strings by the mapping-functions +to insert/substitute fields through a key lookup. The source of this +lookup can be of various types. +

    + +The MapName is the name of the map and will +be used to specify a mapping-function for the substitution strings of a +rewriting rule via one of the following constructs: + +

    +${ MapName : LookupKey +}
    +${ MapName : LookupKey +| DefaultValue } +
    + +When such a construct occurs the map MapName +is consulted and the key LookupKey is looked-up. If the key is +found, the map-function construct is substituted by SubstValue. If +the key is not found then it is substituted by DefaultValue or +by the empty string if no DefaultValue was specified. + +

    +The following combinations for MapType and MapSource +can be used: + +

      +
    • Standard Plain Text
      + MapType: txt, MapSource: Unix filesystem path to valid regular + file +

      + This is the standard rewriting map feature where the MapSource is + a plain ASCII file containing either blank lines, comment lines (starting + with a '#' character) or pairs like the following - one per line. + +

      + MatchingKey SubstValue +
      + +

      + Example: +

      + + +
      +##
      +##  map.txt -- rewriting map
      +##
      +
      +Ralf.S.Engelschall    rse   # Bastard Operator From Hell
      +Mr.Joe.Average        joe   # Mr. Average
      +
      + +

      + + +
      +RewriteMap real-to-user txt:/path/to/file/map.txt
      +
      + +

      +

    • Randomized Plain Text
      + MapType: rnd, MapSource: Unix filesystem path to valid regular + file +

      + This is identical to the Standard Plain Text variant above but with a + special + post-processing feature: After looking up a value it is parsed according + to contained ``|'' characters which have the meaning of + ``or''. + In other words they indicate a set of alternatives from which the actual + returned value is chosen randomly. Although this sounds crazy and useless, + it + was actually designed for load balancing in a reverse proxy situation where + the looked up values are server names. + Example: +

      + + +
      +##
      +##  map.txt -- rewriting map
      +##
      +
      +static   www1|www2|www3|www4
      +dynamic  www5|www6
      +
      + +

      + + +
      +RewriteMap servers rnd:/path/to/file/map.txt
      +
      + +

      +

    • Hash File
      + MapType: dbm, MapSource: Unix filesystem path to valid + regular file +

      + Here the source is a binary NDBM format file containing the same contents + as a Plain Text format file, but in a special representation + which is optimized for really fast lookups. You can create such a file with + any NDBM tool or with the following Perl script: +

      + + +
      +#!/path/to/bin/perl
      +##
      +##  txt2dbm -- convert txt map to dbm format
      +##
      +
      +($txtmap, $dbmmap) = @ARGV;
      +open(TXT, "<$txtmap");
      +dbmopen(%DB, $dbmmap, 0644);
      +while (<TXT>) {
      +    next if (m|^s*#.*| or m|^s*$|);
      +    $DB{$1} = $2 if (m|^\s*(\S+)\s+(\S+)$|);
      +}
      +dbmclose(%DB);
      +close(TXT)
      +

      + + +
      $ txt2dbm map.txt map.db 
      +

      +

    • Internal Function
      + MapType: int, MapSource: Internal Apache function +

      + Here the source is an internal Apache function. Currently you cannot + create your own, but the following functions already exists: +

        +
      • toupper:
        + Converts the looked up key to all upper case. +
      • tolower:
        + Converts the looked up key to all lower case. +
      • escape:
        + Translates special characters in the looked up key to hex-encodings. +
      • unescape:
        + Translates hex-encodings in the looked up key back to special characters. +
      +

      +

    • External Rewriting Program
      + MapType: prg, MapSource: Unix filesystem path to valid + regular file +

      + Here the source is a program, not a map file. To create it you + can use the language of your choice, but the result has to be a + executable (i.e., either object-code or a script with the + magic cookie trick '#!/path/to/interpreter' as the + first line). +

      + This program is started once at startup of the Apache servers and then + communicates with the rewriting engine over its stdin and + stdout file-handles. For each map-function lookup it will + receive the key to lookup as a newline-terminated string on + stdin. It then has to give back the looked-up value as a + newline-terminated string on stdout or the four-character + string ``NULL'' if it fails (i.e., there is no + corresponding value + for the given key). A trivial program which will implement a 1:1 map + (i.e., key == value) could be: +

      + + +
      +#!/usr/bin/perl
      +$| = 1;
      +while (<STDIN>) {
      +    # ...put here any transformations or lookups...
      +    print $_;
      +}
      +
      +

      + But be very careful:
      +

        +
      1. ``Keep it simple, stupid'' (KISS), because + if this program hangs it will hang the Apache server + when the rule occurs. +
      2. Avoid one common mistake: never do buffered I/O on stdout! + This will cause a deadloop! Hence the ``$|=1'' in the + above example... +
      3. Use the RewriteLock directive to define a lockfile + mod_rewrite can use to synchronize the communication to the program. + By default no such synchronization takes place. +
      +
    + +The RewriteMap directive can occur more than once. For each +mapping-function use one RewriteMap directive to declare its +rewriting mapfile. While you cannot declare a map in +per-directory context it is of course possible to use +this map in per-directory context. + +

    + + +
    +Note: For plain text and DBM format files the looked-up +keys are cached in-core +until the mtime of the mapfile changes or the server does a +restart. This way you can have map-functions in rules which are used +for every request. This is no problem, because the +external lookup only happens once! +
    + +

    +


    +

    + +

    RewriteBase

    +Syntax: RewriteBase BaseURL
    +Default: default is the physical directory path +
    +Context: directory, .htaccess
    +Override: FileInfo
    +Status: Extension
    +Module: mod_rewrite.c
    +Compatibility: Apache 1.2
    + +

    +The RewriteBase directive explicitly sets the base URL for +per-directory rewrites. As you will see below, RewriteRule can be +used in per-directory config files (.htaccess). There it will act +locally, i.e., the local directory prefix is stripped at this stage of +processing and your rewriting rules act only on the remainder. At the end +it is automatically added back to the path. + +

    +When a substitution occurs for a new URL, this module has to re-inject the URL +into the server processing. To be able to do this it needs to know what the +corresponding URL-prefix or URL-base is. By default this prefix is the +corresponding filepath itself. But at most websites URLs are +NOT directly related to physical filename paths, so this +assumption will usually be wrong! There you have to use the +RewriteBase directive to specify the correct URL-prefix. + +

    + + +
    +Notice: If your webserver's URLs are not +directly related to physical file paths, you have to use +RewriteBase in every +.htaccess files where you want to use RewriteRule +directives. +
    + +

    +Example: + +

    + Assume the following per-directory config file: + +

    + + +
    +#
    +#  /abc/def/.htaccess -- per-dir config file for directory /abc/def
    +#  Remember: /abc/def is the physical path of /xyz, i.e., the server
    +#            has a 'Alias /xyz /abc/def' directive e.g.
    +#
    +
    +RewriteEngine On
    +
    +#  let the server know that we were reached via /xyz and not
    +#  via the physical path prefix /abc/def
    +RewriteBase   /xyz
    +
    +#  now the rewriting rules
    +RewriteRule   ^oldstuff\.html$  newstuff.html
    +
    + +

    +In the above example, a request to /xyz/oldstuff.html +gets correctly +rewritten to the physical file /abc/def/newstuff.html. + +

    + + +
    + +Note - For Apache hackers:
    +The following list gives detailed information about the internal +processing steps: + +

    +

    +Request:
    +  /xyz/oldstuff.html
    +
    +Internal Processing:
    +  /xyz/oldstuff.html     -> /abc/def/oldstuff.html  (per-server Alias)
    +  /abc/def/oldstuff.html -> /abc/def/newstuff.html  (per-dir    RewriteRule)
    +  /abc/def/newstuff.html -> /xyz/newstuff.html      (per-dir    RewriteBase)
    +  /xyz/newstuff.html     -> /abc/def/newstuff.html  (per-server Alias)
    +
    +Result:
    +  /abc/def/newstuff.html
    +
    + +This seems very complicated but is the correct Apache internal processing, +because the per-directory rewriting comes too late in the process. So, +when it occurs the (rewritten) request has to be re-injected into the Apache +kernel! BUT: While this seems like a serious overhead, it really isn't, because +this re-injection happens fully internally to the Apache server and the same +procedure is used by many other operations inside Apache. So, you can be +sure the design and implementation is correct. +
    +
    + +

    + + +

    +


    +

    + +

    RewriteCond

    +Syntax: RewriteCond TestString + CondPattern
    +Default: None
    +Context: server config, virtual host, directory, + .htaccess
    +Override: FileInfo
    +Status: Extension
    +Module: mod_rewrite.c
    +Compatibility: Apache 1.2 (partially), Apache 1.3
    + +

    +The RewriteCond directive defines a rule condition. Precede a +RewriteRule directive with one or more RewriteCond +directives. + +The following rewriting rule is only used if its pattern matches the current +state of the URI and if these additional conditions apply +too. + +

    +TestString is a string which can contains the following +expanded constructs in addition to plain text: + +

      +
    • RewriteRule backreferences: These are backreferences of + the form + +
      +$N +
      + +(0 <= N <= 9) which provide access to the grouped parts (parenthesis!) +of the pattern from the corresponding RewriteRule directive (the +one following the current bunch of RewriteCond directives). + +

      +

    • RewriteCond backreferences: These are backreferences of +the form + +
      +%N +
      + +(1 <= N <= 9) which provide access to the grouped parts (parentheses!) of +the pattern from the last matched RewriteCond directive in the +current bunch of conditions. + +

      +

    • Server-Variables: These are variables + of the form + +
      +%{ NAME_OF_VARIABLE } +
      + +where NAME_OF_VARIABLE can be a string +taken from the following list: + +

      + + + + + + + + + + + + + + + +
      +HTTP headers:

      + +HTTP_USER_AGENT
      +HTTP_REFERER
      +HTTP_COOKIE
      +HTTP_FORWARDED
      +HTTP_HOST
      +HTTP_PROXY_CONNECTION
      +HTTP_ACCEPT
      +
      +

      +connection & request:

      + +REMOTE_ADDR
      +REMOTE_HOST
      +REMOTE_USER
      +REMOTE_IDENT
      +REQUEST_METHOD
      +SCRIPT_FILENAME
      +PATH_INFO
      +QUERY_STRING
      +AUTH_TYPE
      +
      +

      +server internals:

      + +DOCUMENT_ROOT
      +SERVER_ADMIN
      +SERVER_NAME
      +SERVER_ADDR
      +SERVER_PORT
      +SERVER_PROTOCOL
      +SERVER_SOFTWARE
      +
      +

      +system stuff:

      + +TIME_YEAR
      +TIME_MON
      +TIME_DAY
      +TIME_HOUR
      +TIME_MIN
      +TIME_SEC
      +TIME_WDAY
      +TIME
      +
      +

      +specials:

      + +API_VERSION
      +THE_REQUEST
      +REQUEST_URI
      +REQUEST_FILENAME
      +IS_SUBREQ
      +
      +

      + +

      + + +
      +Notice: These variables all correspond to the similarly named +HTTP MIME-headers, C variables of the Apache server or struct tm +fields of the Unix system. +
      + +

    + +

    +Special Notes: + +

      +
    1. The variables SCRIPT_FILENAME and REQUEST_FILENAME contain the same +value, i.e., the value of the filename field of +the internal +request_rec structure of the Apache server. The first name is +just the +commonly known CGI variable name while the second is the consistent +counterpart to REQUEST_URI (which contains the value of the uri +field of request_rec). + +

      +

    2. There is the special format: %{ENV:variable} where +variable can be any environment variable. This is looked-up via +internal Apache structures and (if not found there) via getenv() +from the Apache server process. + +

      +

    3. There is the special format: %{HTTP:header} where +header can be any HTTP MIME-header name. This is looked-up +from the HTTP request. Example: %{HTTP:Proxy-Connection} +is the value of the HTTP header ``Proxy-Connection:''. + +

      +

    4. There is the special format %{LA-U:variable} for look-aheads +which perform an internal (URL-based) sub-request to determine the final value +of variable. Use this when you want to use a variable for rewriting +which is actually set later in an API phase and thus is not available at the +current stage. For instance when you want to rewrite according to the +REMOTE_USER variable from within the per-server context +(httpd.conf file) you have to use %{LA-U:REMOTE_USER} +because this variable is set by the authorization phases which come +after the URL translation phase where mod_rewrite operates. On the +other hand, because mod_rewrite implements its per-directory context +(.htaccess file) via the Fixup phase of the API and because the +authorization phases come before this phase, you just can use +%{REMOTE_USER} there. + +

      +

    5. There is the special format: %{LA-F:variable} which performs an +internal (filename-based) sub-request to determine the final value of +variable. Most of the time this is the same as LA-U above. +
    + +

    +CondPattern is the condition pattern, i.e., a regular +expression +which is applied to the current instance of the TestString, +i.e., TestString is evaluated and then matched against +CondPattern. + +

    +Remember: CondPattern is a standard +Extended Regular Expression with some additions: + +

      +
    1. You can prefix the pattern string with a '!' character +(exclamation mark) to specify a non-matching pattern. + +

      +

    2. +There are some special variants of CondPatterns. Instead of real +regular expression strings you can also use one of the following: +

      +

        +
      • '<CondPattern' (is lexically lower)
        +Treats the CondPattern as a plain string and compares it +lexically to TestString. True if +TestString is lexically lower than CondPattern. +

        +

      • '>CondPattern' (is lexically greater)
        +Treats the CondPattern as a plain string and compares it +lexically to TestString. True if +TestString is lexically greater than CondPattern. +

        +

      • '=CondPattern' (is lexically equal)
        +Treats the CondPattern as a plain string and compares it +lexically to TestString. True if +TestString is lexically equal to CondPattern, i.e the +two strings are exactly equal (character by character). +If CondPattern is just "" (two quotation marks) this +compares TestString to the empty string. +

        +

      • '-d' (is directory)
        +Treats the TestString as a pathname and +tests if it exists and is a directory. +

        +

      • '-f' (is regular file)
        +Treats the TestString as a pathname and +tests if it exists and is a regular file. +

        +

      • '-s' (is regular file with size)
        +Treats the TestString as a pathname and +tests if it exists and is a regular file with size greater than zero. +

        +

      • '-l' (is symbolic link)
        +Treats the TestString as a pathname and +tests if it exists and is a symbolic link. +

        +

      • '-F' (is existing file via subrequest)
        +Checks if TestString is a valid file and accessible via all the +server's currently-configured access controls for that path. This uses an +internal subrequest to determine the check, so use it with care because it +decreases your servers performance! +

        +

      • '-U' (is existing URL via subrequest)
        +Checks if TestString is a valid URL and accessible via all the +server's +currently-configured access controls for that path. This uses an internal +subrequest to determine the check, so use it with care because it decreases +your server's performance! +
      +

      + + +
      +Notice: +All of these tests can also be prefixed by an exclamation mark ('!') +to negate their meaning. +
      +

    + +

    +Additionally you can set special flags for CondPattern by appending + +

    +[flags] +
    + +as the third argument to the RewriteCond directive. Flags +is a comma-separated list of the following flags: + +
      +
    • 'nocase|NC' (no case)
      + This makes the test case-insensitive, i.e., there is + no difference between 'A-Z' and 'a-z' both in the expanded + TestString and the CondPattern. +

      +

    • 'ornext|OR' (or next condition)
      + Use this to combine rule conditions with a local OR instead of the + implicit AND. Typical example: +

      +

      +RewriteCond %{REMOTE_HOST}  ^host1.*  [OR]
      +RewriteCond %{REMOTE_HOST}  ^host2.*  [OR]
      +RewriteCond %{REMOTE_HOST}  ^host3.*
      +RewriteRule ...some special stuff for any of these hosts...
      +
      + Without this flag you would have to write the cond/rule three times. +
    + +

    +Example: +

    + +To rewrite the Homepage of a site according to the ``User-Agent:'' +header of the request, you can use the following: + +
    +RewriteCond  %{HTTP_USER_AGENT}  ^Mozilla.*
    +RewriteRule  ^/$                 /homepage.max.html  [L]
    +
    +RewriteCond  %{HTTP_USER_AGENT}  ^Lynx.*
    +RewriteRule  ^/$                 /homepage.min.html  [L]
    +
    +RewriteRule  ^/$                 /homepage.std.html  [L]
    +
    + +Interpretation: If you use Netscape Navigator as your browser (which identifies +itself as 'Mozilla'), then you get the max homepage, which includes +Frames, etc. If you use the Lynx browser (which is Terminal-based), then you +get the min homepage, which contains no images, no tables, etc. If you +use any other browser you get the standard homepage. +
    + +

    +


    +

    + +

    RewriteRule

    +Syntax: RewriteRule Pattern Substitution
    +Default: None
    +Context: server config, virtual host, directory, .htaccess
    +Override: FileInfo
    +Status: Extension
    +Module: mod_rewrite.c
    +Compatibility: Apache 1.2 (partially), Apache 1.3
    + +

    +The RewriteRule directive is the real rewriting workhorse. The +directive can occur more than once. Each directive then defines one single +rewriting rule. The definition order of these rules is +important, because this order is used when applying the rules at +run-time. + +

    +Pattern can be (for Apache +1.1.x a System V8 and for Apache 1.2.x and later a POSIX) regular expression which gets applied to the current +URL. Here ``current'' means the value of the URL when this rule gets +applied. This may not be the originally requested URL, because no +longer existingany number of rules may already have matched and made +alterations to it. + +

    +Some hints about the syntax of regular expressions: + +

    + + + + +
    +
    +Text:
    +  .           Any single character
    +  [chars]     Character class: One  of chars
    +  [^chars]    Character class: None of chars
    +  text1|text2 Alternative: text1 or text2
    +
    +Quantifiers:
    +  ?           0 or 1 of the preceding text
    +  *           0 or N of the preceding text (N > 0)
    +  +           1 or N of the preceding text (N > 1)
    +
    +Grouping:
    +  (text)      Grouping of text
    +              (either to set the borders of an alternative or
    +              for making backreferences where the Nth group can 
    +              be used on the RHS of a RewriteRule with $N)
    +
    +Anchors:
    +  ^           Start of line anchor
    +  $           End   of line anchor
    +
    +Escaping:
    +  \char       escape that particular char
    +              (for instance to specify the chars ".[]()" etc.)
    +
    +
    + +

    +For more information about regular expressions either have a look at your +local regex(3) manpage or its src/regex/regex.3 copy in the +Apache 1.3 distribution. If you are interested in more detailed +information about regular expressions and their variants (POSIX regex, Perl +regex, etc.) have a look at the following dedicated book on this topic: + +

    +Mastering Regular Expressions
    +Jeffrey E.F. Friedl
    +Nutshell Handbook Series
    +O'Reilly & Associates, Inc. 1997
    +ISBN 1-56592-257-3
    +
    + +

    +Additionally in mod_rewrite the NOT character ('!') is a possible +pattern prefix. This gives you the ability to negate a pattern; to say, for +instance: ``if the current URL does NOT match this +pattern''. This can be used for exceptional cases, where it is easier to +match the negative pattern, or as a last default rule. + +

    + + +
    +Notice: When using the NOT character to negate a pattern you cannot +have grouped wildcard parts in the pattern. This is impossible because when +the pattern does NOT match, there are no contents for the groups. In +consequence, if negated patterns are used, you cannot use $N in the +substitution string! +
    + +

    +Substitution of a rewriting rule is the string +which is substituted for (or replaces) the original URL for which +Pattern matched. Beside plain text you can use + +

      +
    1. back-references $N to the RewriteRule pattern +
    2. back-references %N to the last matched RewriteCond pattern +
    3. server-variables as in rule condition test-strings (%{VARNAME}) +
    4. mapping-function calls (${mapname:key|default}) +
    + +Back-references are $N (N=0..9) identifiers which +will be replaced by the contents of the Nth group of the matched +Pattern. The server-variables are the same as for the +TestString of a RewriteCond directive. The +mapping-functions come from the RewriteMap directive and are +explained there. These three types of variables are expanded in the order of +the above list. + +

    +As already mentioned above, all the rewriting rules are applied to the +Substitution (in the order of definition in the config file). The +URL is completely replaced by the Substitution and the +rewriting process goes on until there are no more rules unless explicitly +terminated by a L flag - see below. + +

    +There is a special substitution string named '-' which means: +NO substitution! Sounds silly? No, it is useful to provide rewriting +rules which only match some URLs but do no substitution, e.g., in +conjunction with the C (chain) flag to be able to have more than one +pattern to be applied before a substitution occurs. + +

    +One more note: You can even create URLs in the substitution string containing +a query string part. Just use a question mark inside the substitution string +to indicate that the following stuff should be re-injected into the +QUERY_STRING. When you want to erase an existing query string, end the +substitution string with just the question mark. + +

    + + +
    +Note: There is a special feature: When you prefix a substitution +field with http://thishost[:thisport] then +mod_rewrite automatically strips it out. This auto-reduction on +implicit external redirect URLs is a useful and important feature when +used in combination with a mapping-function which generates the hostname +part. Have a look at the first example in the example section below to +understand this. +
    + +

    + + +
    +Remember: An unconditional external redirect to your own server will +not work with the prefix http://thishost because of this feature. +To achieve such a self-redirect, you have to use the R-flag (see +below). +
    + +

    +Additionally you can set special flags for Substitution by appending + +

    +[flags] +
    + +as the third argument to the RewriteRule directive. Flags is a +comma-separated list of the following flags: + +
      +
    • 'redirect|R [=code]' (force redirect)
      + Prefix Substitution + with http://thishost[:thisport]/ (which makes the new URL a URI) to + force a external redirection. If no code is given a HTTP response + of 302 (MOVED TEMPORARILY) is used. If you want to use other response + codes in the range 300-400 just specify them as a number or use + one of the following symbolic names: temp (default), permanent, + seeother. + Use it for rules which should + canonicalize the URL and give it back to the client, e.g., translate + ``/~'' into ``/u/'' or always append a slash to + /u/user, etc.
      +

      + Note: When you use this flag, make sure that the + substitution field is a valid URL! If not, you are redirecting to an + invalid location! And remember that this flag itself only prefixes the + URL with http://thishost[:thisport]/, rewriting continues. + Usually you also want to stop and do the redirection immediately. To stop + the rewriting you also have to provide the 'L' flag. +

      +

    • 'forbidden|F' (force URL to be forbidden)
      + This forces the current URL to be forbidden, i.e., it immediately sends + back a HTTP response of 403 (FORBIDDEN). Use this flag in conjunction with + appropriate RewriteConds to conditionally block some URLs. +

      +

    • 'gone|G' (force URL to be gone)
      + This forces the current URL to be gone, i.e., it immediately sends back a + HTTP response of 410 (GONE). Use this flag to mark pages which no longer + exist as gone. +

      +

    • 'proxy|P' (force proxy)
      + This flag forces the substitution part to be internally forced as a proxy + request and immediately (i.e., rewriting rule processing stops here) put + through the proxy module. You have to make + sure that the substitution string is a valid URI (e.g., typically starting + with http://hostname) which can be handled by the + Apache proxy module. If not you get an error from the proxy module. Use + this flag to achieve a more powerful implementation of the ProxyPass directive, to map some + remote stuff into the namespace of the local server. +

      + Notice: To use this functionality make sure you have the proxy module + compiled into your Apache server program. If you don't know please check + whether mod_proxy.c is part of the ``httpd -l'' + output. If yes, this functionality is available to mod_rewrite. If not, + then you first have to rebuild the ``httpd'' program with + mod_proxy enabled. +

      +

    • 'last|L' (last rule)
      + Stop the rewriting process here and + don't apply any more rewriting rules. This corresponds to the Perl + last command or the break command from the C + language. Use this flag to prevent the currently rewritten URL from being + rewritten further by following rules. For + example, use it to rewrite the root-path URL ('/') to a real + one, e.g., '/e/www/'. +

      +

    • 'next|N' (next round)
      + Re-run the rewriting process (starting again with the first rewriting + rule). Here the URL to match is again not the original URL but the URL + from the last rewriting rule. This corresponds to the Perl + next command or the continue command from the C + language. Use this flag to restart the rewriting process, i.e., to + immediately go to the top of the loop.
      + But be careful not to create an infinite loop! +

      +

    • 'chain|C' (chained with next rule)
      + This flag chains the current rule with the next rule (which itself can + be chained with the following rule, etc.). This has the following + effect: if a rule matches, then processing continues as usual, i.e., the + flag has no effect. If the rule does not match, then all following + chained rules are skipped. For instance, use it to remove the + ``.www'' part inside a per-directory rule set when you let an + external redirect happen (where the ``.www'' part should not to + occur!). +

      +

    • 'type|T=MIME-type' (force MIME type)
      + Force the MIME-type of the target file to be MIME-type. For + instance, this can be used to simulate the mod_alias + directive ScriptAlias which internally forces all files inside + the mapped directory to have a MIME type of + ``application/x-httpd-cgi''. +

      +

    • 'nosubreq|NS' (used only if no internal sub-request)
      + This flag forces the rewriting engine to skip a rewriting rule if the + current request is an internal sub-request. For instance, sub-requests + occur internally in Apache when mod_include tries to find out + information about possible directory default files (index.xxx). + On sub-requests it is not always useful and even sometimes causes a failure to + if the complete set of rules are applied. Use this flag to exclude some rules.
      +

      + Use the following rule for your decision: whenever you prefix some URLs + with CGI-scripts to force them to be processed by the CGI-script, the + chance is high that you will run into problems (or even overhead) on sub-requests. + In these cases, use this flag. +

      +

    • 'nocase|NC' (no case)
      + This makes the Pattern case-insensitive, i.e., there is + no difference between 'A-Z' and 'a-z' when Pattern is matched + against the current URL. +

      +

    • 'qsappend|QSA' (query string + append)
      + This flag forces the rewriting engine to append a query + string part in the substitution string to the existing one instead of + replacing it. Use this when you want to add more data to the query string + via a rewrite rule. +

      +

    • 'passthrough|PT' (pass through to next handler)
      + This flag forces the rewriting engine to set the uri field + of the internal request_rec structure to the value + of the filename field. This flag is just a hack to be able + to post-process the output of RewriteRule directives by + Alias, ScriptAlias, Redirect, etc. directives + from other URI-to-filename translators. A trivial example to show the + semantics: + If you want to rewrite /abc to /def via the rewriting + engine of mod_rewrite and then /def to /ghi + with mod_alias: +
      +    RewriteRule ^/abc(.*)  /def$1 [PT]
      +    Alias       /def       /ghi
      +    
      + If you omit the PT flag then mod_rewrite + will do its job fine, i.e., it rewrites uri=/abc/... to + filename=/def/... as a full API-compliant URI-to-filename + translator should do. Then mod_alias comes and tries to do a + URI-to-filename transition which will not work. +

      + Note: You have to use this flag if you want to intermix directives + of different modules which contain URL-to-filename translators. The + typical example is the use of mod_alias and + mod_rewrite.. +

      + + +
      + + Note - For Apache hackers:
      + If the current Apache API had a + filename-to-filename hook additionally to the URI-to-filename hook then + we wouldn't need this flag! But without such a hook this flag is the + only solution. The Apache Group has discussed this problem and will + add such a hook in Apache version 2.0. +
      +
      +

      +

    • 'skip|S=num' (skip next rule(s))
      + This flag forces the rewriting engine to skip the next num rules + in sequence when the current rule matches. Use this to make pseudo + if-then-else constructs: The last rule of the then-clause becomes + skip=N where N is the number of rules in the else-clause. + (This is not the same as the 'chain|C' flag!) +

      +

    • 'env|E=VAR:VAL' (set environment variable)
      + This forces an environment variable named VAR to be set to the + value VAL, where VAL can contain regexp backreferences + $N and %N which will be expanded. You can use this flag + more than once to set more than one variable. The variables can be later + dereferenced in many situations, but usually from + within XSSI (via <!--#echo var="VAR"-->) or CGI (e.g. + $ENV{'VAR'}). Additionally you can dereference it in a + following RewriteCond pattern via %{ENV:VAR}. Use this to strip + but remember information from URLs. +
    + +

    + + +
    +Note: Never forget that Pattern is applied to a complete URL +in per-server configuration files. But in per-directory configuration +files, the per-directory prefix (which always is the same for a specific +directory!) is automatically removed for the pattern matching and +automatically added after the substitution has been done. This feature is +essential for many sorts of rewriting, because without this prefix stripping +you have to match the parent directory which is not always possible. +

    +There is one exception: If a substitution string starts with +``http://'' then the directory prefix will not be added and an +external redirect or proxy throughput (if flag P is used!) is forced! +

    + +

    + + +
    +Note: To enable the rewriting engine for per-directory configuration files +you need to set ``RewriteEngine On'' in these files and +``Option FollowSymLinks'' must be enabled. If your administrator has +disabled override of FollowSymLinks for a user's directory, then +you cannot use the rewriting engine. This restriction is needed for +security reasons. +
    + +

    +Here are all possible substitution combinations and their meanings: + +

    +Inside per-server configuration (httpd.conf)
    +for request ``GET /somepath/pathinfo'':

    + +

    + + + + +
    +
    +Given Rule                                      Resulting Substitution
    +----------------------------------------------  ----------------------------------
    +^/somepath(.*) otherpath$1                      not supported, because invalid!
    +
    +^/somepath(.*) otherpath$1  [R]                 not supported, because invalid!
    +
    +^/somepath(.*) otherpath$1  [P]                 not supported, because invalid!
    +----------------------------------------------  ----------------------------------
    +^/somepath(.*) /otherpath$1                     /otherpath/pathinfo
    +
    +^/somepath(.*) /otherpath$1 [R]                 http://thishost/otherpath/pathinfo
    +                                                via external redirection
    +
    +^/somepath(.*) /otherpath$1 [P]                 not supported, because silly!
    +----------------------------------------------  ----------------------------------
    +^/somepath(.*) http://thishost/otherpath$1      /otherpath/pathinfo
    +
    +^/somepath(.*) http://thishost/otherpath$1 [R]  http://thishost/otherpath/pathinfo
    +                                                via external redirection
    +
    +^/somepath(.*) http://thishost/otherpath$1 [P]  not supported, because silly!
    +----------------------------------------------  ----------------------------------
    +^/somepath(.*) http://otherhost/otherpath$1     http://otherhost/otherpath/pathinfo
    +                                                via external redirection
    +
    +^/somepath(.*) http://otherhost/otherpath$1 [R] http://otherhost/otherpath/pathinfo
    +                                                via external redirection
    +                                                (the [R] flag is redundant)
    +
    +^/somepath(.*) http://otherhost/otherpath$1 [P] http://otherhost/otherpath/pathinfo
    +                                                via internal proxy
    +
    +
    + +

    +Inside per-directory configuration for /somepath
    +(i.e., file .htaccess in dir /physical/path/to/somepath containing +RewriteBase /somepath)
    for +request ``GET /somepath/localpath/pathinfo'':

    + +

    + + + + +
    +
    +Given Rule                                      Resulting Substitution
    +----------------------------------------------  ----------------------------------
    +^localpath(.*) otherpath$1                      /somepath/otherpath/pathinfo
    +
    +^localpath(.*) otherpath$1  [R]                 http://thishost/somepath/otherpath/pathinfo
    +                                                via external redirection
    +
    +^localpath(.*) otherpath$1  [P]                 not supported, because silly!
    +----------------------------------------------  ----------------------------------
    +^localpath(.*) /otherpath$1                     /otherpath/pathinfo
    +
    +^localpath(.*) /otherpath$1 [R]                 http://thishost/otherpath/pathinfo
    +                                                via external redirection
    +
    +^localpath(.*) /otherpath$1 [P]                 not supported, because silly!
    +----------------------------------------------  ----------------------------------
    +^localpath(.*) http://thishost/otherpath$1      /otherpath/pathinfo
    +
    +^localpath(.*) http://thishost/otherpath$1 [R]  http://thishost/otherpath/pathinfo
    +                                                via external redirection
    +
    +^localpath(.*) http://thishost/otherpath$1 [P]  not supported, because silly!
    +----------------------------------------------  ----------------------------------
    +^localpath(.*) http://otherhost/otherpath$1     http://otherhost/otherpath/pathinfo
    +                                                via external redirection
    +
    +^localpath(.*) http://otherhost/otherpath$1 [R] http://otherhost/otherpath/pathinfo
    +                                                via external redirection
    +                                                (the [R] flag is redundant)
    +
    +^localpath(.*) http://otherhost/otherpath$1 [P] http://otherhost/otherpath/pathinfo
    +                                                via internal proxy
    +
    +
    + +

    +Example: +

    +

    +We want to rewrite URLs of the form +
    +/ Language +/~ Realname +/.../ File +
    +into +
    +/u/ Username +/.../ File +. Language +
    +

    +We take the rewrite mapfile from above and save it under +/path/to/file/map.txt. Then we only have to add the +following lines to the Apache server configuration file: + +

    +
    +RewriteLog   /path/to/file/rewrite.log
    +RewriteMap   real-to-user               txt:/path/to/file/map.txt
    +RewriteRule  ^/([^/]+)/~([^/]+)/(.*)$   /u/${real-to-user:$2|nobody}/$3.$1
    +
    +
    + +
    + +

    +


    + +
    +

    Miscellaneous

    +
    + +

    +


    + +

    Environment Variables

    + +This module keeps track of two additional (non-standard) CGI/SSI environment +variables named SCRIPT_URL and SCRIPT_URI. These contain +the logical Web-view to the current resource, while the standard CGI/SSI +variables SCRIPT_NAME and SCRIPT_FILENAME contain the +physical System-view. + +

    +Notice: These variables hold the URI/URL as they were initially +requested, i.e., before any rewriting. This is +important because the rewriting process is primarily used to rewrite logical +URLs to physical pathnames. + +

    +Example: + +

    +
    +SCRIPT_NAME=/sw/lib/w3s/tree/global/u/rse/.www/index.html
    +SCRIPT_FILENAME=/u/rse/.www/index.html
    +SCRIPT_URL=/u/rse/
    +SCRIPT_URI=http://en1.engelschall.com/u/rse/
    +
    +
    + +

    +


    + +

    Practical Solutions

    + +We also have an URL Rewriting +Guide available, which provides a collection of practical solutions +for URL-based problems. There you can find real-life rulesets and +additional information about mod_rewrite. + + +
    + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_setenvif.html b/APACHE_1_3_12/htdocs/manual/mod/mod_setenvif.html new file mode 100644 index 0000000000..868a1106ae --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_setenvif.html @@ -0,0 +1,398 @@ + + + + Apache module mod_setenvif + + + + +

    Module mod_setenvif

    +

    + This module is contained in the mod_setenvif.c file, and + is compiled in by default. It provides for + the ability to set environment variables based upon attributes of the + request. +

    +

    Summary

    +

    + The mod_setenvif module allows you to set environment + variables according to whether different aspects of the request match + regular expressions you specify. These envariables can be used by + other parts of the server to make decisions about actions to be taken. +

    +

    The directives are considered in the order they appear in the + configuration files. So more complex sequences can be used, such + as this example, which sets netscape if the browser + is mozilla but not MSIE. +

    +  BrowserMatch ^Mozilla netscape
    +  BrowserMatch MSIE !netscape
    +  
    +

    + +

    Directives

    + + +
    +

    The BrowserMatch Directive

    +

    + Syntax: BrowserMatch regex envar[=value] [...] +
    + Default: none +
    + Context: server config +
    + Override: none +
    + Status: Base +
    + Module: mod_setenvif +
    + Compatibility: Apache 1.2 and above (in Apache 1.2 + this directive was found in the now-obsolete mod_browser module) +

    +

    + The BrowserMatch directive defines environment variables based on the + User-Agent HTTP request header field. The first argument + should be a POSIX.2 extended regular expression (similar to an + egrep-style regex). The rest of the arguments give the + names of variables to set, and optionally values to which they should + be set. These take the form of +

    +
      +
    1. varname, or +
    2. +
    3. !varname, or +
    4. +
    5. varname=value +
    6. +
    +

    + In the first form, the value will be set to "1". The second + will remove the given variable if already defined, and the third will + set the variable to the value given by value. If a + User-Agent string matches more than one entry, they will + be merged. Entries are processed in the order in which they appear, + and later entries can override earlier ones. +

    +

    + For example: +

    +
    +    BrowserMatch ^Mozilla forms jpeg=yes browser=netscape
    +    BrowserMatch "^Mozilla/[2-3]" tables agif frames javascript
    +    BrowserMatch MSIE !javascript
    +  
    +

    + Note that the regular expression string is + case-sensitive. For cane-INsensitive matching, see + the + BrowserMatchNoCase + directive. +

    +

    + The BrowserMatch and BrowserMatchNoCase + directives are special cases of the + SetEnvIf + and + SetEnvIfNoCase + directives. The following two lines have the same effect: +

    +
    +   BrowserMatchNoCase Robot is_a_robot
    +   SetEnvIfNoCase User-Agent Robot is_a_robot
    +  
    + +
    +

    + + The BrowserMatchNoCase Directive + +

    +

    + Syntax: BrowserMatchNoCase regex envar[=value] + [...] +
    + Default: none +
    + Context: server config +
    + Override: none +
    + Status: Base +
    + Module: mod_setenvif +
    + Compatibility: Apache 1.2 and above (in Apache 1.2 + this directive was found in the now-obsolete mod_browser module) +

    +

    + The BrowserMatchNoCase directive is semantically identical to + the + BrowserMatch + directive. However, it provides for case-insensitive matching. For + example: +

    +
    +    BrowserMatchNoCase mac platform=macintosh
    +    BrowserMatchNoCase win platform=windows
    +  
    +

    + The BrowserMatch and BrowserMatchNoCase + directives are special cases of the + SetEnvIf + and + SetEnvIfNoCase + directives. The following two lines have the same effect: +

    +
    +   BrowserMatchNoCase Robot is_a_robot
    +   SetEnvIfNoCase User-Agent Robot is_a_robot
    +  
    + +
    +

    + + The SetEnvIf Directive + +

    +

    + Syntax: SetEnvIf attribute regex envar[=value] + [...] +
    + Default: none +
    + Context: server config +
    + Override: none +
    + Status: Base +
    + Module: mod_setenvif +
    + Compatibility: Apache 1.3 and above; the + Request_Protocol keyword and environment-variable matching are only + available with 1.3.7 and later +

    +

    + The SetEnvIf directive defines environment variables + based on attributes of the request. These attributes can be the + values of various HTTP request header fields (see + RFC2068 + for more information about these), or of other aspects of the request, + including the following: +

    +
      +
    • Remote_Host - the hostname (if available) of the + client making the request +
    • +
    • Remote_Addr - the IP address of the client making + the request +
    • +
    • Remote_User - the authenticated username (if + available) +
    • +
    • Request_Method - the name of the method being used + (GET, POST, et cetera) +
    • +
    • Request_Protocol - the name and version of the protocol + with which the request was made (e.g., "HTTP/0.9", "HTTP/1.1", + etc.) +
    • +
    • Request_URI - the portion of the URL following the + scheme and host portion +
    • +
    +

    + Some of the more commonly used request header field names include + Host, User-Agent, and Referer. +

    +

    + If the attribute name doesn't match any of the special keywords, + nor any of the request's header field names, it is tested as the name + of an environment variable in the list of those associated with the request. + This allows SetEnvIf directives to test against the result + of prior matches. +

    +
    + Only those environment variables defined by earlier + SetEnvIf[NoCase] directives are available for testing in + this manner. 'Earlier' means that they were defined at a broader scope + (such as server-wide) or previously in the current directive's + scope. +
    +

    + Example: +

    +
    +   SetEnvIf Request_URI "\.gif$" object_is_image=gif
    +   SetEnvIf Request_URI "\.jpg$" object_is_image=jpg
    +   SetEnvIf Request_URI "\.xbm$" object_is_image=xbm
    +        :
    +   SetEnvIf Referer www\.mydomain\.com intra_site_referral
    +        :
    +   SetEnvIf object_is_image xbm XBIT_PROCESSING=1
    +  
    +

    + The first three will set the envariable object_is_image if the + request was for an image file, and the fourth sets + intra_site_referral if the referring page was somewhere + on the www.mydomain.com Web site. +

    + +
    +

    + + The SetEnvIfNoCase Directive + +

    +

    + Syntax: SetEnvIfNoCase + attribute regex envar[=value] [...] +
    + Default: none +
    + Context: server config +
    + Override: none +
    + Status: Base +
    + Module: mod_setenvif +
    + Compatibility: Apache 1.3 and above +

    +

    + The SetEnvIfNoCase is semantically identical to the + SetEnvIf + directive, and differs only in that the regular expression matching is + performed in a case-insensitive manner. For example: +

    +
    +   SetEnvIfNoCase Host Apache\.Org site=apache
    +  
    +

    + This will cause the site envariable to be set to + "apache" if the HTTP request header field + Host: was included and contained Apache.Org, + apache.org, or any other combination. +

    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_so.html b/APACHE_1_3_12/htdocs/manual/mod/mod_so.html new file mode 100644 index 0000000000..6edd1a4fb3 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_so.html @@ -0,0 +1,164 @@ + + + +Apache module mod_so + + + + + +

    Module mod_so

    + +This module is contained in the mod_so.c file. It is +compiled in by default on Windows and is not compiled in by default on +Unix. It provides for loading of executable code and modules into the +server at start-up or restart time. On Unix, the loaded code typically +comes from shared object files (usually with .so +extension), whilst on Windows this module loads DLL +files. This module is only available in Apache 1.3 and up. + +

    + +In previous releases, the functionality of this module was provided +for Unix by mod_dld, and for Windows by mod_dll. On Windows, mod_dll +was used in beta release 1.3b1 through 1.3b5. mod_so combines these +two modules into a single module for all operating systems. + +

    Summary

    + +This is an experimental module. On selected operating systems it can be used +to load modules into Apache at runtime via the Dynamic +Shared Object (DSO) mechanism, rather than requiring a recompilation. + +

    Directives

    + +
    + + +

    LoadFile

    + +Syntax: LoadFile filename filename ...
    +Context: server config
    +Status: Base
    +Module: mod_so

    + +The LoadFile directive links in the named object files or libraries +when the server is started or restarted; this is used to load +additional code which may be required for some module to +work. Filename is either and absolute path or relative to ServerRoot.


    + +

    LoadModule

    + +Syntax: LoadModule module filename
    +Context: server config
    +Status: Base
    +Module: mod_so

    + +The LoadModule directive links in the object file or library filename +and adds the module structure named module to the list of active +modules. Module is the name of the external variable of type +module in the file. Example (Unix): +

    +LoadModule status_module modules/mod_status.so +
    + +

    + +Example (Windows): +

    +LoadModule status_module modules/ApacheModuleStatus.dll
    +
    + +loads the named module from the modules subdirectory of the +ServerRoot.

    + +


    + +

    Creating DLL Modules for Windows

    + +

    The Apache module API is unchanged between the Unix and Windows + versions. Many modules will run on Windows with no or little change + from Unix, although others rely on aspects of the Unix architecture + which are not present in Windows, and will not work.

    + +

    When a module does work, it can be added to the server in one of two + ways. As with Unix, it can be compiled into the server. Because Apache + for Windows does not have the Configure program of Apache + for Unix, the module's source file must be added to the ApacheCore + project file, and its symbols must be added to the + os\win32\modules.c file.

    + +

    The second way is to compile the module as a DLL, a shared library + that can be loaded into the server at runtime, using the + LoadModule + directive. These module DLLs can be distributed and run on any Apache + for Windows installation, without recompilation of the server.

    + +

    To create a module DLL, a small change is necessary to the module's + source file: The module record must be exported from the DLL (which + will be created later; see below). To do this, add the + MODULE_VAR_EXPORT (defined in the Apache header files) to + your module's module record definition. For example, if your module + has:

    +
    +    module foo_module;
    +
    +

    Replace the above with:

    +
    +    module MODULE_VAR_EXPORT foo_module;
    +
    +

    Note that this will only be activated on Windows, so the module can + continue to be used, unchanged, with Unix if needed. Also, if you are + familiar with .DEF files, you can export the module + record with that method instead.

    + +

    Now, create a DLL containing your module. You will need to link this + against the ApacheCore.lib export library that is created when the + ApacheCore.dll shared library is compiled. You may also have to change + the compiler settings to ensure that the Apache header files are + correctly located.

    + +

    This should create a DLL version of your module. Now simply place it + in the modules directory of your server root, and use + the LoadModule directive to + load it.

    + + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_speling.html b/APACHE_1_3_12/htdocs/manual/mod/mod_speling.html new file mode 100644 index 0000000000..3be9f8000b --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_speling.html @@ -0,0 +1,122 @@ + + + + Apache module mod_speling + + + + +

    Module mod_speling

    +

    + This module is contained in the mod_speling.c file, + and is not compiled in by default. + It attempts to correct misspellings of + URLs that users might have entered, by ignoring capitalization + and by allowing up to one misspelling.
    + This catches the majority of misspelled requests. An automatic + "spelling corrected" redirection is returned if only one matching + document was found, and a list of matches is returned if more than + one document with a sufficiently similar name is found. +

    + +

    Summary

    +

    + Requests to documents sometimes cannot be served by the core apache + server because the request was misspelled or miscapitalized. This + module addresses this problem by trying to find a matching document, + even after all other modules gave up. It does its work by comparing + each document name in the requested directory against the requested + document name without regard to case, and allowing + up to one misspelling (character insertion / omission + / transposition or wrong character). A list is built with all document + names which were matched using this strategy. +

    +

    + If, after scanning the directory, +

      +
    • no matching document was found, Apache will proceed as usual + and return a "document not found" error. +
    • only one document is found that "almost" matches the request, + then it is returned in the form of a redirection response. +
    • more than one document with a close match was found, then + the list of the matches is returned to the client, and the client + can select the correct candidate. +
    +

    + +

    Directives

    + + +
  83. CheckSpelling +
  84. + +
    +

    CheckSpelling

    + + Syntax: CheckSpelling on/off
    + Default: CheckSpelling Off
    + Context: server config, virtual host, + directory, .htaccess
    + Override: Options +
    + Status: Base
    + Module: mod_speling
    + Compatibility: CheckSpelling was available as a + separately + available module for Apache 1.1, but was limited to miscapitalizations. + As of Apache 1.3, it is part of the Apache distribution. Prior to + Apache 1.3.2, the CheckSpelling directive was only available + in the "server" and "virtual host" contexts. +

    + This directive enables or disables the spelling module. When enabled, + keep in mind that +

    +
      +
    • the directory scan which is necessary for the spelling + correction will have an impact on the server's performance + when many spelling corrections have to be performed at the same time. +
    • +
    • the document trees should not contain sensitive files which could + be matched inadvertently by a spelling "correction". +
    • +
    • the module is unable to correct misspelled user names + (as in http://my.host/~apahce/), just file names or + directory names. +
    • +
    • spelling corrections apply strictly to existing files, so a request for + the <Location /status> may get incorrectly treated + as the negotiated file "/stats.html". +
    • +
    + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_status.html b/APACHE_1_3_12/htdocs/manual/mod/mod_status.html new file mode 100644 index 0000000000..ccfabe1a83 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_status.html @@ -0,0 +1,131 @@ + + + + Apache module mod_status + + + + + +

    Module mod_status

    + +The Status Module is only available in Apache 1.1 and later.

    + +

    Function

    + +The Status module allows a server administrator to find out how well +their server is performing. A HTML page is presented that gives +the current server statistics in an easily readable form. If required +this page can be made to automatically refresh (given a compatible +browser). Another page gives a simple machine-readable list of the current +server state. +

    +The details given are: +

      +
    • The number of children serving requests +
    • The number of idle children +
    • The status of each child, the number of requests that child has +performed and the total number of bytes served by the child (*) +
    • A total number of accesses and byte count served (*) +
    • The time the server was started/restarted and the +time it has been running for +
    • Averages giving the number of requests per second, +the number of bytes served per second and the average number +of bytes per request (*) +
    • The current percentage CPU used by each child and in total by +Apache (*) +
    • The current hosts and requests being processed (*) +
    + +A compile-time option must be used to display the details marked "(*)" as +the instrumentation required for obtaining these statistics does not +exist within standard Apache. + +

    ExtendedStatus directive

    + +Syntax: ExtendedStatus On|Off
    +Default: ExtendedStatus Off
    +Context: server config
    +Status: Base
    + Module: mod_status
    +Compatibility: ExtendedStatus is only available + in Apache 1.3.2 and later. + +

    +This directive controls whether the server keeps track of extended +status information for each request. This is only useful if the status module +is enabled on the server. +

    +

    +This setting applies to the entire server, and cannot be enabled or +disabled on a virtualhost-by-virtualhost basis. +

    + +

    Enabling Status Support

    + +To enable status reports only for browsers from the foo.com +domain add this code to your access.conf configuration file +
    +    <Location /server-status>
    +    SetHandler server-status
    +
    +    order deny,allow
    +    deny from all
    +    allow from .foo.com
    +    </Location>
    +
    +

    +You can now access server statistics by using a Web browser to access the +page http://your.server.name/server-status +

    +Note that mod_status will only work when you are running Apache in +standalone mode and not +inetd mode. + +

    Automatic Updates

    +You can get the status page to update itself automatically if you have +a browser that supports "refresh". Access the page +http://your.server.name/server-status?refresh=N to refresh the +page every N seconds. +

    Machine Readable Status File

    +A machine-readable version of the status file is available by accessing the +page http://your.server.name/server-status?auto. This is useful +when automatically run, see the Perl program in the /support +directory of Apache, log_server_status. + +
    + + It should be noted that if mod_status is compiled into + the server, its handler capability is available in all + configuration files, including per-directory files + (e.g., .htaccess). This may have + security-related ramifications for your site. + +
    + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_unique_id.html b/APACHE_1_3_12/htdocs/manual/mod/mod_unique_id.html new file mode 100644 index 0000000000..c9c4d3afe9 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_unique_id.html @@ -0,0 +1,180 @@ + + + +Apache module mod_unique_id + + + + + +

    Module mod_unique_id

    + +This module provides a magic token for each request which is guaranteed +to be unique across "all" requests under very specific conditions. +The unique identifier is even unique across multiple machines in a +properly configured cluster of machines. The environment variable +UNIQUE_ID is set to the identifier for each request. +Unique identifiers are useful for various reasons which are beyond the +scope of this document. + +

    Theory

    + +

    +First a brief recap of how the Apache server works on Unix machines. +This feature currently isn't supported on Windows NT. On Unix machines, +Apache creates several children, the children process requests one at +a time. Each child can serve multiple requests in its lifetime. For the +purpose of this discussion, the children don't share any data +with each other. We'll refer to the children as httpd processes. + +

    +Your website has one or more machines under your administrative control, +together we'll call them a cluster of machines. Each machine can +possibly run multiple instances of Apache. All of these collectively +are considered "the universe", and with certain assumptions we'll +show that in this universe we can generate unique identifiers for each +request, without extensive communication between machines in the cluster. + +

    +The machines in your cluster should satisfy these requirements. +(Even if you have only one machine you should synchronize its clock +with NTP.) + +

      +
    • The machines' times are synchronized via NTP or other network time + protocol. + +
    • The machines' hostnames all differ, such that the module can do a + hostname lookup on the hostname and receive a different IP address + for each machine in the cluster. +
    + +

    +As far as operating system assumptions go, we assume that pids (process +ids) fit in 32-bits. If the operating system uses more than 32-bits +for a pid, the fix is trivial but must be performed in the code. + +

    +Given those assumptions, at a single point in time we can identify +any httpd process on any machine in the cluster from all other httpd +processes. The machine's IP address and the pid of the httpd process +are sufficient to do this. So in order to generate unique identifiers +for requests we need only distinguish between different points in time. + +

    +To distinguish time we will use a Unix timestamp (seconds since January +1, 1970 UTC), and a 16-bit counter. The timestamp has only one second +granularity, so the counter is used to represent up to 65536 values +during a single second. The quadruple ( ip_addr, pid, time_stamp, +counter ) is sufficient to enumerate 65536 requests per second per +httpd process. There are issues however with pid reuse over +time, and the counter is used to alleviate this issue. + +

    +When an httpd child is created, the counter is initialized with ( +current microseconds divided by 10 ) modulo 65536 (this formula was +chosen to eliminate some variance problems with the low order bits of +the microsecond timers on some systems). When a unique identifier is +generated, the time stamp used is the time the request arrived at the +web server. The counter is incremented every time an identifier is +generated (and allowed to roll over). + +

    +The kernel generates a pid for each process as it forks the process, and +pids are allowed to roll over (they're 16-bits on many Unixes, but newer +systems have expanded to 32-bits). So over time the same pid will be +reused. However unless it is reused within the same second, it does not +destroy the uniqueness of our quadruple. That is, we assume the system +does not spawn 65536 processes in a one second interval (it may even be +32768 processes on some Unixes, but even this isn't likely to happen). + +

    +Suppose that time repeats itself for some reason. That is, suppose that +the system's clock is screwed up and it revisits a past time (or it is +too far forward, is reset correctly, and then revisits the future time). +In this case we can easily show that we can get pid and time stamp reuse. +The choice of initializer for the counter is intended to help defeat this. +Note that we really want a random number to initialize the counter, +but there aren't any readily available numbers on most systems (i.e., you +can't use rand() because you need to seed the generator, and can't seed +it with the time because time, at least at one second resolution, has +repeated itself). This is not a perfect defense. + +

    +How good a defense is it? Well suppose that one of your machines serves +at most 500 requests per second (which is a very reasonable upper bound +at this writing, because systems generally do more than just shovel out +static files). To do that it will require a number of children which +depends on how many concurrent clients you have. But we'll be pessimistic +and suppose that a single child is able to serve 500 requests per second. +There are 1000 possible starting counter values such that two sequences +of 500 requests overlap. So there is a 1.5% chance that if time (at one +second resolution) repeats itself this child will repeat a counter value, +and uniqueness will be broken. This was a very pessimistic example, +and with real world values it's even less likely to occur. If your +system is such that it's still likely to occur, then perhaps you should +make the counter 32 bits (by editing the code). + +

    +You may be concerned about the clock being "set back" during summer +daylight savings. However this isn't an issue because the times used here +are UTC, which "always" go forward. Note that x86 based Unixes may need +proper configuration for this to be true -- they should be configured to +assume that the motherboard clock is on UTC and compensate appropriately. +But even still, if you're running NTP then your UTC time will be correct +very shortly after reboot. + +

    +The UNIQUE_ID environment variable is constructed by +encoding the 112-bit (32-bit IP address, 32 bit pid, 32 bit time stamp, +16 bit counter) quadruple using the alphabet [A-Za-z0-9@-] +in a manner similar to MIME base64 encoding, producing 19 characters. +The MIME base64 alphabet is actually [A-Za-z0-9+/] however ++ and / need to be specially encoded in URLs, +which makes them less desirable. All values are encoded in network +byte ordering so that the encoding is comparable across architectures of +different byte ordering. The actual ordering of the encoding is: time +stamp, IP address, pid, counter. This ordering has a purpose, but it +should be emphasized that applications should not dissect the encoding. +Applications should treat the entire encoded UNIQUE_ID as an +opaque token, which can be compared against other UNIQUE_IDs +for equality only. + +

    +The ordering was chosen such that it's possible to change the encoding +in the future without worrying about collision with an existing database +of UNIQUE_IDs. The new encodings should also keep the time +stamp as the first element, and can otherwise use the same alphabet and +bit length. Since the time stamps are essentially an increasing sequence, +it's sufficient to have a flag second in which all machines in the +cluster stop serving and request, and stop using the old encoding format. +Afterwards they can resume requests and begin issuing the new encodings. + +

    +This we believe is a relatively portable solution to this problem. It can +be extended to multithreaded systems like Windows NT, and can grow with +future needs. The identifiers generated have essentially an infinite +life-time because future identifiers can be made longer as required. +Essentially no communication is required between machines in the cluster +(only NTP synchronization is required, which is low overhead), and no +communication between httpd processes is required (the communication is +implicit in the pid value assigned by the kernel). In very specific +situations the identifier can be shortened, but more information needs +to be assumed (for example the 32-bit IP address is overkill for any +site, but there is no portable shorter replacement for it). + +


    + +

    Directives

    + +mod_unique_id has no directives. + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_userdir.html b/APACHE_1_3_12/htdocs/manual/mod/mod_userdir.html new file mode 100644 index 0000000000..570b1b042a --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_userdir.html @@ -0,0 +1,123 @@ + + + +Apache module mod_userdir + + + + + +

    Module mod_userdir

    + +This module is contained in the mod_userdir.c file, and +is compiled in by default. It provides for user-specific directories. + + + +
    + + +

    UserDir

    + +Syntax: UserDir directory/filename
    +Default: UserDir public_html
    +Context: server config, virtual host
    +Status: Base
    +Module: mod_userdir
    +Compatibility: All forms except the UserDir +public_html form are only available in Apache 1.1 or above. Use +of the enabled keyword, or disabled with a +list of usernames, is only available in Apache 1.3 and above.

    + +The UserDir directive sets the real directory in a user's home directory +to use when a request for a document for a user is received. +Directory/filename is one of the following: +

    +
      +
    • The name of a directory or a pattern such as those shown below. +
    • +
    • The keyword disabled. This turns off all + username-to-directory translations except those explicitly named with + the enabled keyword (see below). +
    • +
    • The keyword disabled followed by a space-delimited + list of usernames. Usernames that appear in such a list will + never have directory translation performed, even if they + appear in an enabled clause. +
    • +
    • The keyword enabled followed by a space-delimited list + of usernames. These usernames will have directory translation + performed even if a global disable is in effect, but not if they also + appear in a disabled clause. +
    • +
    +

    +If neither the enabled nor the disabled +keywords appear in the Userdir directive, the argument is +treated as a filename pattern, and is used to turn the name into a +directory specification. A request for +http://www.foo.com/~bob/one/two.html will be translated to: +

    +UserDir public_html     -> ~bob/public_html/one/two.html
    +UserDir /usr/web        -> /usr/web/bob/one/two.html
    +UserDir /home/*/www     -> /home/bob/www/one/two.html
    +
    +The following directives will send redirects to the client: +
    +UserDir http://www.foo.com/users -> http://www.foo.com/users/bob/one/two.html
    +UserDir http://www.foo.com/*/usr -> http://www.foo.com/bob/usr/one/two.html
    +UserDir http://www.foo.com/~*/   -> http://www.foo.com/~bob/one/two.html
    +
    +

    +
    + + Be careful when using this directive; for instance, + "UserDir ./" would map + "/~root" to + "/" - which is probably undesirable. If you are + running Apache 1.3 or above, it is strongly recommended that your + configuration include a + "UserDir disabled root" declaration. + See also + the + <Directory> + directive and the + Security Tips + page for more information. + +
    + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_usertrack.html b/APACHE_1_3_12/htdocs/manual/mod/mod_usertrack.html new file mode 100644 index 0000000000..87d81ac0f6 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_usertrack.html @@ -0,0 +1,199 @@ + + + +Apache module mod_usertrack + + + + + +

    Module mod_usertrack

    + +Previous releases of Apache have included a module which generates a +'clickstream' log of user activity on a site using cookies. This was +called the "cookies" module, mod_cookies. In Apache 1.2 and later this +module has been renamed the "user tracking" module, +mod_usertrack. This module has been simplified and new directives +added. + +
    + +

    Logging

    + +Previously, the cookies module (now the user tracking module) did its +own logging, using the CookieLog directive. In this release, +this module does no logging at all. Instead, a configurable log +format file should be used to log user click-streams. This is possible +because the logging module now allows multiple log files. The cookie itself is +logged by using the text %{cookie}n + +in the log file format. For example: +
    +CustomLog logs/clickstream "%{cookie}n %r %t"
    +
    + +For backward compatibility the configurable log module implements the +old CookieLog directive, but this should be upgraded to the +above CustomLog directive. + +

    Directives

    + + + +
    + +

    CookieExpires

    +Syntax: CookieExpires expiry-period
    +Context: server config, virtual host
    +Status: optional
    +Module: mod_usertrack

    + +When used, this directive sets an expiry time on the cookie generated +by the usertrack module. The expiry-period can be given either +as a number of seconds, or in the format such as "2 weeks 3 days 7 +hours". Valid denominations are: years, months, weeks, hours, minutes +and seconds. If the expiry time is in any format other than one +number indicating the number of seconds, it must be enclosed by +double quotes. + +

    If this directive is not used, cookies last only for the current +browser session.

    + +

    CookieName

    +Syntax: CookieName token +
    +Default: Apache +
    +Context: server config, virtual host, directory, +.htaccess
    +Status: optional
    +Module: mod_usertrack +
    +Compatibility: Apache 1.3.7 and later +

    +This directive allows you to change the name of the cookie this module +uses for its tracking purposes. By default the cookie is named +"Apache". +

    +

    +You must specify a valid cookie name; results are unpredictable if +you use a name containing unusual characters. Valid characters +include A-Z, a-z, 0-9, "_", and "-". +

    + +

    CookieTracking

    +Syntax: CookieTracking on | off
    +Context: server config, virtual host, directory, +.htaccess
    +Override: FileInfo
    +Status: optional
    +Module: mod_usertrack

    + +When the user track module is compiled in, and "CookieTracking on" is +set, Apache will start sending a user-tracking cookie for all new +requests. This directive can be used to turn this behavior on or off +on a per-server or per-directory basis. By default, compiling +mod_usertrack will not activate cookies. + +


    + +

    2-digit or 4-digit dates for cookies?

    + +(the following is from message +<022701bda43d$9d32bbb0$1201a8c0@christian.office.sane.com> in +the new-httpd archives) + +

    + +

    +From: "Christian Allen" <christian@sane.com>
    +Subject: Re: Apache Y2K bug in mod_usertrack.c
    +Date: Tue, 30 Jun 1998 11:41:56 -0400
    +
    +Did some work with cookies and dug up some info that might be useful.
    +
    +True, Netscape claims that the correct format NOW is four digit dates, and
    +four digit dates do in fact work... for Netscape 4.x (Communicator), that
    +is.  However, 3.x and below do NOT accept them.  It seems that Netscape
    +originally had a 2-digit standard, and then with all of the Y2K hype and
    +probably a few complaints, changed to a four digit date for Communicator.
    +Fortunately, 4.x also understands the 2-digit format, and so the best way to
    +ensure that your expiration date is legible to the client's browser is to
    +use 2-digit dates.
    +
    +However, this does not limit expiration dates to the year 2000; if you use
    +an expiration year of "13", for example, it is interpreted as 2013, NOT
    +1913!  In fact, you can use an expiration year of up to "37", and it will be
    +understood as "2037" by both MSIE and Netscape versions 3.x and up (not sure
    +about versions previous to those).  Not sure why Netscape used that
    +particular year as its cut-off point, but my guess is that it was in respect
    +to UNIX's 2038 problem.  Netscape/MSIE 4.x seem to be able to understand
    +2-digit years beyond that, at least until "50" for sure (I think they
    +understand up until about "70", but not for sure).
    +
    +Summary:  Mozilla 3.x and up understands two digit dates up until "37"
    +(2037).  Mozilla 4.x understands up until at least "50" (2050) in 2-digit
    +form, but also understands 4-digit years, which can probably reach up until
    +9999.  Your best bet for sending a long-life cookie is to send it for some
    +time late in the year "37".
    +
    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/mod/mod_vhost_alias.html b/APACHE_1_3_12/htdocs/manual/mod/mod_vhost_alias.html new file mode 100644 index 0000000000..d9331a5752 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/mod/mod_vhost_alias.html @@ -0,0 +1,307 @@ + + + +Apache module mod_vhost_alias + + + + +
    + [APACHE DOCUMENTATION] +

    + Apache HTTP Server Version 1.3 +

    +
    + +

    Module mod_vhost_alias

    + +

    +This module is contained in the mod_vhost_alias.c file +and is not compiled in by default. It provides support for +dynamically configured mass virtual +hosting. +

    + +

    Directory Name Interpolation

    + +

    +All the directives in this module interpolate a string into a +pathname. The interpolated string (henceforth called the "name") may +be either the server name (see the +UseCanonicalName +directive for details on how this is determined) or the IP address of +the virtual host on the server in dotted-quad format. The +interpolation is controlled by specifiers inspired by +printf which have a number of formats: +

    +
    %% +
    insert a % +
    %p +
    insert the port number of the virtual host +
    %N.M +
    insert (part of) the name +
    +

    + +

    +N and M are used to specify substrings of +the name. N selects from the dot-separated components of +the name, and M selects characters within whatever +N has selected. M is optional and defaults +to zero if it isn't present; the dot must be present if and only if +M is present. The interpretation is as follows: +

    +
    0 +
    the whole name +
    1 +
    the first part +
    2 +
    the second part +
    -1 +
    the last part +
    -2 +
    the penultimate part +
    2+ +
    the second and all subsequent parts +
    -2+ +
    the penultimate and all preceding parts +
    1+ and -1+ +
    the same as 0 +
    +If N or M is greater than the number of +parts available a single underscore is interpolated. +

    + +

    Examples

    + +

    +For simple name-based virtual hosts you might use the following +directives in your server configuration file: +

    +	UseCanonicalName	Off
    +	VirtualDocumentRoot	/usr/local/apache/vhosts/%0
    +
    +A request for http://www.example.com/directory/file.html +will be satisfied by the file +/usr/local/apache/vhosts/www.example.com/directory/file.html. +

    + +

    +For a very large number of virtual hosts it is a good idea to arrange +the files to reduce the size of the vhosts directory. To +do this you might use the following in your configuration file: +

    +	UseCanonicalName	Off
    +	VirtualDocumentRoot	/usr/local/apache/vhosts/%3+/%2.1/%2.2/%2.3/%2
    +
    +A request for http://www.example.isp.com/directory/file.html +will be satisfied by the file +/usr/local/apache/isp.com/e/x/a/example/directory/file.html. +A more even spread of files can be achieved by hashing from the end of +the name, for example: +
    +	VirtualDocumentRoot	/usr/local/apache/vhosts/%3+/%2.-1/%2.-2/%2.-3/%2
    +
    +The example request would come from +/usr/local/apache/vhosts/isp.com/e/l/p/example/directory/file.html. +Alternatively you might use: +
    +	VirtualDocumentRoot	/usr/local/apache/vhosts/%3+/%2.1/%2.2/%2.3/%2.4+
    +
    +The example request would come from +/usr/local/apache/vhosts/isp.com/e/x/a/mple/directory/file.html. +

    + +

    +For IP-based virtual hosting you might use the following in your +configuration file: +

    +	UseCanonicalName DNS
    +	VirtualDocumentRootIP	/usr/local/apache/vhost/%1/%2/%3/%4/docs
    +	VirtualScriptAliasIP	/usr/local/apache/vhost/%1/%2/%3/%4/cgi-bin
    +
    +A request for http://www.example.isp.com/directory/file.html +would be satisfied by the file +/usr/local/apache/10/20/30/40/docs/directory/file.html if +the IP address of www.example.com were 10.20.30.40. +A request for http://www.example.isp.com/cgi-bin/script.pl +would be satisfied by executing the program +/usr/local/apache/10/20/30/40/cgi-bin/script.pl. +

    + +

    +The LogFormat directives +%V and %A are useful in conjunction with +this module. +

    + +
    + +

    Directives

    + +
    + +

    VirtualDocumentRoot directive

    +

    +Syntax: VirtualDocumentRoot interpolated-directory
    +Default: None
    +Context: server config, virtual host
    +Status: Extension
    +Module: mod_vhost_alias
    +Compatibility: VirtualDocumentRoot is only available in 1.3.7 and later.

    +

    +The VirtualDocumentRoot directive allows you to determine +where Apache will find your documents based on the value of the server +name. The result of expanding interpolated-directory is used +as the root of the document tree in a similar manner to the +DocumentRoot +directive's argument. If interpolated-directory is +none then VirtaulDocumentRoot is turned off. +This directive cannot be used in the same context as +VirtualDocumentRootIP. +

    +
    + +

    VirtualDocumentRootIP directive

    +

    +Syntax: VirtualDocumentRootIP interpolated-directory
    +Default: None
    +Context: server config, virtual host
    +Status: Extension
    +Module: mod_vhost_alias
    +Compatibility: VirtualDocumentRootIP is only available in 1.3.7 and later.

    +

    +The VirtualDocumentRootIP directive is like the +VirtualDocumentRoot directive, +except that it uses the IP address of the server end of the connection +instead of the server name. +

    +
    + +

    VirtualScriptAlias directive

    +

    +Syntax: VirtualScriptAlias interpolated-directory
    +Default: None
    +Context: server config, virtual host
    +Status: Extension
    +Module: mod_vhost_alias
    +Compatibility: VirtualScriptAlias is only available in 1.3.7 and later.

    +

    +The VirtualScriptAlias directive allows you to determine +where Apache will find CGI scripts in a similar manner to +VirtualDocumentRoot +does for other documents. It matches requests for URIs starting +/cgi-bin/, much like +ScriptAlias /cgi-bin/ +would. +

    +
    + +

    VirtualScriptAliasIP directive

    +

    +Syntax: VirtualScriptAliasIP interpolated-directory
    +Default: None
    +Context: server config, virtual host
    +Status: Extension
    +Module: mod_vhost_alias
    +Compatibility: VirtualScriptAliasIP is only available in 1.3.7 and later.

    +

    +The VirtualScriptAliasIP directive is like the +VirtualScriptAlias directive, +except that it uses the IP address of the server end of the connection +instead of the server name. +

    +
    + +

    + Apache HTTP Server Version 1.3 +

    + +Index +Home + + + diff --git a/APACHE_1_3_12/htdocs/manual/multilogs.html b/APACHE_1_3_12/htdocs/manual/multilogs.html new file mode 100644 index 0000000000..f5601e1594 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/multilogs.html @@ -0,0 +1,134 @@ + + + +Apache Multiple Log Files + + + + + +

    Multiple Log Files

    + +It is now possible to specify multiple log files, each with a fully +customizable format. This is compatible with existing +configurations. Multiple log files are implemented as part of the mod_log_config module which as of +Apache 1.2 is the default log module. + +
    + +

    Using Multiple Log Files

    + +Multiple log files be created with either the TransferLog +or CustomLog directive. These directives can be +repeated to create more than one log file (in previous releases, +only one logfile could be given per server configuration). +The TransferLog directive creates a log file +in the standard "common log format", although this can be customized +with LogFormat. The syntax of these two +directives is the same as for the config log module in previous +Apache releases. +

    + +The real power of multiple log files come from the ability to +create log files in different formats. For example, as well +as a CLF transfer log, the server could log the user agent of +each client, or the referrer information, or any other aspect of +the request, such as the language preferences of the user. +

    + +The new CustomLog directive takes both a filename to log +to, and a log file format. + +


    + +Syntax: CustomLog filename "format"
    +Context: server config, virtual host
    +Status: base
    +Module: mod_log_config

    + +The first argument is the filename to log to. This is used +exactly like the argument to TransferLog, that is, +it is either a file as a full path or relative to the current +server root, or |programname. Be aware that anyone who can write to +the directory where a log file is written can gain access to the uid +that starts the server. See the +security tips document for details.

    + +The format argument specifies a format for each line of the log file. +The options available for the format are exactly the same as for +the argument of the LogFormat directive. If the format +includes any spaces (which it will do in almost all cases) it +should be enclosed in double quotes. +

    + +

    Use with Virtual Hosts

    + +If a <VirtualHost> section does not contain any +TransferLog or CustomLog directives, the +logs defined for the main server will be used. If it does +contain one or more of these directives, requests serviced by +this virtual host will only be logged in the log files defined +within its definition, not in any of the main server's log files. +See the examples below. +

    + +


    + +

    Examples

    + +To create a normal (CLF) format log file in logs/access_log, and a +log of user agents: + +
    +TransferLog logs/access_log
    +CustomLog   logs/agents     "%{user-agent}i"
    +
    + +To define a CLF transfer log and a referrer log which log +all accesses to both the main server and a virtual host: + +
    +TransferLog logs/access_log
    +CustomLog   logs/referer    "%{referer}i"
    +
    +<VirtualHost>
    +  DocumentRoot   /whatever
    +  ServerName     my.virtual.host
    +</VirtualHost>
    +
    + +Since no TransferLog or CustomLog directives appear inside the +<VirtualHost> section, any requests for this virtual host +will be logged in the main server's log files. If however the +directive + +
    +TransferLog logs/vhost_access_log
    +
    + +was added inside the virtual host definition, then accesses to this +virtual host will be logged in vhost_access_log file (in common +log format), and not in logs/access_log or logs/referer. + + + + diff --git a/APACHE_1_3_12/htdocs/manual/netware.html b/APACHE_1_3_12/htdocs/manual/netware.html new file mode 100644 index 0000000000..8add778b5f --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/netware.html @@ -0,0 +1,278 @@ + + + +Using Apache with Novell NetWare 5 + + + + + + +

    Using Apache With Novell NetWare 5

    + +

    This document explains how to install, configure and run + Apache 1.3 under Novell NetWare 5. Please note that at + this time, NetWare support is entirely experimental, and is + recommended only for experienced users. The Apache Group does not + guarantee that this software will work as documented, or even at + all. If you find any bugs, or wish to contribute in other ways, please + use our bug reporting + page.

    + +

    Warning: Apache on NetWare has not yet been optimized for performance. +Apache still performs best, and is most reliable on Unix platforms. Over +time we will improve NetWare performance. Folks doing comparative reviews +of webserver performance are asked to compare against Apache +on a Unix platform such as Solaris, FreeBSD, or Linux.

    + +

    + +Most of this document assumes that you are installing Apache from a +binary distribution. If you want to compile Apache yourself (possibly +to help with development, or to track down bugs), see the section on +Compiling Apache for NetWare below. + +


    + + + +
    + +

    Requirements

    + +Apache 1.3 is designed to run on NetWare 5.0 and 5.1. +

    + +If running on NetWare 5.0 you must install Service Pack 4. + +

    +

    + +Service pack 4 is available here. + +

    Downloading Apache for NetWare 5

    + +

    Information on the latest version of Apache can be found on the +Apache web server at http://www.apache.org/. This will +list the current release, any more recent alpha or beta-test releases, +together with details of mirror web and anonymous ftp sites.

    + +

    +

    Installing Apache for NetWare

    + +There is no Apache install program for NetWare currently. You will need +to compile apache and copy the files over to the server manually. An +install program will be posted at a later date. +

    +Follow these steps to install Apache on NetWare (assuming you will install to sys:/apache): + +

      +
    • Create a directory called Apache on a NetWare volume +
    • Copy Apache.nlm, Apachec.nlm, htdigest.nlm, and htpasswd.nlm to sys:/apache +
    • Create a directory under sys:/Apache called conf +
    • Copy all the *.conf-dist-nw files to the sys:/apache/conf directory + and rename them all as *.conf files +
    • Copy the mime.types and magic files to sys:/apache/conf directory +
    • Copy all files and subdirectories of \apache-1.3\htdocs to sys:/apache/htdocs and + rename the proper index file (index.html.en) to index.html +
    • Copy all files and subdirectories in \apache-1.3\icons to sys:/apache/icons +
    • Create the directory sys:/apache/logs on the server +
    • Create the directory sys:/apache/cgi-bin on the server +
    • Create the directory sys:/apache/modules and copy all nlm modules built into the + modules directory +
    • Edit the httpd.conf file setting ServerRoot and ServerName to reflect your correct + server settings +
    • Add sys:/apache to the search path. EXAMPLE: search add sys:\apache +
    + +

    Apache may be installed to other volumes besides the default sys volume. + +

    Running Apache for NetWare

    + +To start Apache just type apache at the console. This +will load apache in the OS address space. If you prefer to load +Apache in a protected address space you may specify the address space +with the load statement as follows: +

    +

    +    load address space = apache apache
    +
    +

    +This will load Apache into an address space called apache. Running multiple instances +of Apache concurrently on NetWare is possible by loading each instance into its own +protected address space. + +

    +After starting Apache it will be listening to port 80 (unless you +changed the Port, Listen or +BindAddress directives in the configuration files). +To connect to the server and access the default page, launch a browser +and enter the server's name or address. + +This should respond with a welcome page, and a link to the Apache +manual. If nothing happens or you get an error, look in the +error_log file in the logs directory. + +

    + +Once your basic installation is working, you should configure it +properly by editing the files in the conf directory. + +

    +To unload Apache running in the OS address space just type the +following at the console: +

    +    unload apache
    +
    +If apache is running in a protected address space specify the +address space in the unload statement: +
    +    unload address space = apache apache
    +
    + +

    +When working with Apache it is important to know how it will find the +configuration files. You can specify a configuration file on the command line +in two ways: + +

      +
    • -f specifies a path to a particular configuration file +
    +
        apache -f "vol:/my server/conf/my.conf"
    +
        apache -f test/test.conf
    + +In these cases, the proper ServerRoot should be set in the configuration file. + +

    + +If you don't specify a configuration file name with -f, Apache will +use the file name compiled into the server, usually "conf/httpd.conf". Invoking +Apache with the -V switch will display this value labeled as SERVER_CONFIG_FILE. +Apache will then determine its ServerRoot by trying the following, in this order: + +

      +
    • A ServerRoot directive via a -C switch. +
    • The -d switch on the command line. +
    • Current working directory +
    • The server root compiled into the server. +
    + +

    +The server root compiled into the server is usually "sys:/apache". +invoking apache with the -V switch will display this value +labeled as HTTPD_ROOT. + +

    Configuring Apache for NetWare

    + +Apache is configured by files in the conf +directory. These are the same as files used to configure the Unix +version, but there are a few different directives for Apache on +NetWare. See the Apache documentation for all the +available directives. + +

    + +The main differences in Apache for NetWare are: + +

      +
    • Because Apache for NetWare is multithreaded, it does not use a + separate process for each request, as Apache does with + Unix. Instead there are only threads running: a parent thread, and + a child which handles the requests. Within the child each request is + handled by a separate thread. +

      + + So the "process"-management directives are different: +

      MaxRequestsPerChild + - Like the Unix directive, this controls how many requests a + process will serve before exiting. However, unlike Unix, a + process serves all the requests at once, not just one, so if + this is set, it is recommended that a very high number is + used. The recommended default, MaxRequestsPerChild + 0, does not cause the process to ever exit. +

      ThreadsPerChild - + This directive is new, and tells the server how many threads it + should use. This is the maximum number of connections the server + can handle at once; be sure and set this number high enough for + your site if you get a lot of hits. The recommended default is + ThreadsPerChild 50. +

      ThreadStackSize - + This directive tells the server what size of stack to use for + the individual threads. The recommended default is + ThreadStackSize 65536. +

      +

    • The directives that accept filenames as arguments now must use + NetWare filenames instead of Unix ones. However, because Apache + uses Unix-style names internally, you must use forward slashes, not + backslashes. Volumes can be used; if omitted, the drive with the + Apache executable will be assumed.

      +
    • Apache for NetWare contains the ability to load modules at runtime, + without recompiling the server. If Apache is compiled normally, it + will install a number of optional modules in the + \Apache\modules directory. To activate these, or other + modules, the new LoadModule + directive must be used. For example, to active the status module, + use the following (in addition to the status-activating directives + in access.conf):

      +
      +    LoadModule status_module modules/status
      +
      +

      Information on creating loadable + modules is also available.

      +
    + +

    Compiling Apache for NetWare

    + +

    Compiling Apache requires MetroWerks CodeWarrior 5 to be properly + installed. + +

    First, unpack the Apache distribution into an appropriate + directory. Then go to the src subdirectory of the Apache + distribution and unzip ApacheNW.mcp.gz. You may use a + recent version of WinZip to accomplish this or gzip for Windows. The main + Metrowerks project file for Apache (ApacheNW.mcp) is now ready + to use. Just double click on it from within explorer and it should + automatically launch MetroWerks CodeWarrior. +

    + +

    All major pieces of Apache may be built using the ApacheNW.mcp project + file. This includes modules such as status, info, and proxy. In addition, + the following project files have been provided as well: +

       
    +       /apache-1.3/src/support/htpasswd.mcp.gz
    +       /apache-1.3/src/support/htdigest.mcp.gz
    +
    + +

    +htpasswd.mcp.gz and htdigest.mcp.gz will also need +to be unzipped before they can be used with MetroWerks CodeWarrior. + +

    Once Apache has been compiled, it needs to be installed in its server + root directory. The default is the sys:/Apache + directory.

    +

    +Before running the server you must fill out the conf directory. +Copy the *.conf-dist-nw from the distribution conf directory +and rename *.conf. Edit the ServerRoot entries to your +actual server root (for example "sys:/apache"). Copy over +the conf/magic and conf/mime.types files as well. + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/new_features_1_0.html b/APACHE_1_3_12/htdocs/manual/new_features_1_0.html new file mode 100644 index 0000000000..1b2199c115 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/new_features_1_0.html @@ -0,0 +1,131 @@ + + + +Apache extra features + + + + + +

    Overview of new features

    + +

    New Features with Apache 1.0

    + +

    New features with this release, as extensions of the Apache +functionality (see also more detailed CHANGES file) in +the source directory. Because the core code has changed so +significantly, there are certain liberties that earlier versions of +Apache (and the NCSA daemon) took that Apache 1.0 is pickier about - +please check the compatibility notes if +you have any problems. + +

      + +
    • API for server extensions --- see below for a brief sermon on +philosophy, or see src/API.html for an actual +overview. Most server functionality (including includes, CGI, and +most forms of access control) are actually implemented as +API-conformant modules; you can also do other neat stuff (we've +included a sample module, for instance, which one of us is using to +track click-trails using the Netscape +cookie mechanism, for visitors who come in through Netscape +clients). Modules can also be loaded +dynamically using GNU DLD. + +

      +The API is not yet quite stable (see src/TODO for some possible +changes), but anything done now will be easily adapted for future +versions --- after all, we have more modules to adapt than you do. + +

      + +

    • New Process Model - much less forking, no +fixed number of children. + +We found that many people were using values for "MaxServers" either +too high or too low, and were hanging themselves on it. The model we +adopted is still based on long-lived minimal-forking processes, but +instead of specifying one number of persistent processes, the +web-master specifies a maximum and minimum number of processes to be +"spare" - every couple of seconds the parent checks the actual number +of spare servers and adjusts accordingly. This should keep the number +of servers concurrently running relatively low while still ensuring +minimal forking. + +

      + +

    • <VirtualHost> (the configuration +directive for +multiple-homed servers) is more general now. Just about any srm.conf or +httpd.conf command can go in a <Virtualhost> section, with the +following specific exceptions: ServerType, UserId, GroupId, +StartServers, MaxRequestsPerChild, BindAddress, PidFile, TypesConfig, +ServerRoot. + +

      + +

    • Support for content negotiation of +languages through MultiViews +(*.fr, *.de, *.en suffixes), via the new AddLanguage and LanguagePriority +commands (code written by Florent Guillaume, guillaum@clipper.ens.fr). + +

      + +

    • Significant internal cleanups and rearrangements. The two externally + visible consequences of this are that just about all of the unchecked + fixed limits are gone, and that the server is somewhat pickier about + config file syntax (noting and complaining about extraneous command + arguments or other stuff at the end of command lines). + +

      + +

    • XBITHACK is a run-time option, and can be selectively enabled per + directory --- the -DXBITHACK compile-time option just changes the + default. The command which configures it is "XBitHack", which is + allowed everywhere "Options" is; this takes an argument --- + "XBitHack Off" turns it off; "XBitHack On" gets you the NCSA + -DXBITHACK behavior; and "XBitHack Full" gets you the Apache GXBIT + stuff on top of that. (-DXBITHACK makes "Full" the default; + otherwise, it defaults "Off"). + +

      + +

    • TransferLog can specify a program which gets the log entries piped to it, + a la 'TransferLog "| /var/www/my-perl-script -arg valu"' --- this should + give the same SIGTERM/pause/SIGKILL treatment to the logging process on + server restarts that a CGI script gets on an aborted request. NB the + server is counting on the logging process to work, and will probably hang + or worse if it dies. + +

      + +

    • Configurable logging module --- this + is a replacement for the standard plane-jane Common Log Format code, which + supports a LogFormat directive which allows you to control the formatting of + entries in the TransferLog, and add some new items if you like (in + particular, Referer and User-Agent). EXPERIMENTAL. +
    +


    + + +

    Other features of Apache

    + + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/new_features_1_1.html b/APACHE_1_3_12/htdocs/manual/new_features_1_1.html new file mode 100644 index 0000000000..478c919a60 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/new_features_1_1.html @@ -0,0 +1,228 @@ + + +New features with Apache 1.1 + + + + + +

    Overview of new features

    + +

    API Changes

    + +A few changes to the Apache API were made for 1.1. It is possible +that some third-party modules will no longer work with 1.1, though +we have made every effort to provide backwards-compatibility. If you +encounter a module that does not work with 1.1, please let us know. + + +

    New Features with Apache 1.1

    +

    New features with this release, as extensions of the Apache +functionality (see also more detailed CHANGES file in +the source directory.) Because the core code has changed so +significantly, there are certain liberties that earlier versions of +Apache (and the NCSA daemon) took that recent Apache versions are +pickier about - please check the compatibility notes if you have any +problems.

    +
    + +

    In addition to a number of bug fixes and internal performance +enhancements, Apache +1.1 has the following specific new user features:

    + +
      + +
    • Support for Keep-Alive Persistent +Connections
      Apache now has (optional) support for persistent +connections, as defined by the HTTP/1.1 draft. This protocol, +supported by a number of current HTTP servers and browsers (including +Netscape Navigator 2.0) has been shown to increase speed of document +transfer by up to 50% in certain cases. + +
    • New non-IP Intensive VirtualHost +Support
      +Apache's support for virtual hosts has been enhanced to be able to +use information sent by some new Web browsers to determine the server +being accessed, without requiring an additional IP address for each +host. + +
    • Listen to Multiple Addresses and +Ports
      +Using the new Listen directive, Apache can listen to more +than one port and IP address, using the same configuration set. + +
    • Status +Module
      +Apache now contains a module that gives the web-master accurate, +up-to-date information about the server's status and its resource +consumption. It also gives the current state of each server process +including the current URL being processed. For an example, check out +the status of the +www.apache.org server. + +
    • Server Information Module +This module gives a plethora of information about the other modules +installed, their directives, and their configurations. It is +extremely helpful in debugging configuration problems. For an +example, check out information about the +www.apache.org server. + +
    • Experimental Caching Proxy +Server
      +Apache can now act as +an HTTP proxy server, allowing clients behind firewalls to use the +server to access the outside world. In addition, it can cache +documents it proxies, speeding up access to frequently requested +documents. + +
    • URL-based Access Protection +
      +In addition to access checking and authorization by filename (with +<Directory>), +the new <Location> directive allows protection by +URL. + +
    • Filetype-based Script +"Actions"
      +You can now run CGI scripts whenever a file of a certain type is +requested. This makes it much easier to execute scripts that process +files. In addition, you can use the new Script directive to enable scripts +for files called with HTTP methods Apache does not natively support. + +
    • New "Handler" Directives
      +The new AddHandler and SetHandler directive +allows "handlers" to be defined for filename extensions or +directories. These handlers, which can either be built into Apache or +added with the Action directive, extend +Apache's range of usability, and almost entirely remove the "magic" +media types. + +
    • Customizable CGI Environment +Variables
      +New PassEnv and SetEnv directives allow you to +modify the environment variables passed to CGI scripts. + +
    • CERN Metafile Support +
      +Now emulates the CERN httpd's support for metafiles containing additional +HTTP headers to be supplied with a document. + +
    • Improved Imagemap Support +
      +The internal imagemap handling code has been rewritten and +reorganized, adding new handling of default, base and relative URLs, +and support for creating non-graphical menus for use with clients that +do not support imagemaps. + +
    • Improved UserDir +Directive +
      +Now supports the ability to point user's files (as specified by URLs +beginning with the "~" character) at directories other +than those specified by the Unix password file. + +
    • Minimal DNS Now Runtime Option
      +New HostnameLookups +server configuration directive can be used to turn On or +Off DNS lookups. This supersedes the -DMINIMAL_DNS +compile-time configuration option. This option can be set per-directory. + +
    • IdentityCheck Now Per-Directory Option +
      +The IdentityCheck directive, which controls the use of +ident to check the remote user name, can now be set per directory. The +ident support is also RFC 1413-compliant. + +
    • Redirect Now Usable in .htaccess Files +
      +The Redirect +directive can now be used in .htaccess files when the +FileInfo directive has been set on. This allows users to +redirect parts of their directories without requiring CGI scripts + +
    • ErrorDocument Now Usable in .htaccess Files +
      +The ErrorDocument +directive can now be used in .htaccess files when the +FileInfo directive has been set on. This allows users to +have different error messages for different sections of a site. + +
    • ForceType Directive +
      +This new directive, in <Directory> sections or +.htaccess files, allows you to override the filename extensions and +force a single content type. (e.g., ForceType +application/octet-stream) + +
    • File Owner Available to Included CGI Scripts +
      +Server-side includes that call CGI scripts will now set a +USER_NAME environment variable that contains the owner of +the file which included it. + +
    • Improved Icons +
      +Thanks to Kevin +Hughes, Apache's nifty color GIF icons for directory listings have +been updated. In addition, the Powered by Apache +(apache_pb.gif) logo has been included. + +
    + +
    + +

    New Authentication Modules

    + +

    Note: These modules are not +compiled into the server by default, as they require special support +on the host system. They must be enabled specifically in the +Configuration file.

    + +
      + +
    • Anonymous HTTP Logins +
      +New options allow you to allow, using Basic HTTP Authentication, +anonymous logins, like those of FTP. This allows you to collect email +addresses of people accessing your site. + +
    • Support for Digest +Authentication
      +Apache now supports digest authentication using RSA MD5 +encryption. When used with a supporting web browser, this provides a +more secure alternative to Basic authentication. + +
    • Support for Unix DB +Authentication - mod_auth_db.c
      In +addition to DBM support, Apache now +contains optional support for Berkeley DB databases. + +
    • mSQL Database +Authentication - mod_auth_msql.html
      +Support for the use of mSQL databases for user authentication via HTTP +is now supported. + +
    + +
    + +

    OS/2 Support

    + +

    Apache now includes support for OS/2, thanks to +Softlink Services.

    + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/new_features_1_2.html b/APACHE_1_3_12/htdocs/manual/new_features_1_2.html new file mode 100644 index 0000000000..ea15f14204 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/new_features_1_2.html @@ -0,0 +1,210 @@ + + +New features with Apache 1.2 + + + + + +

    Overview of new features

    + +

    API Changes

    + +

    Some non-compatible changes were made to the Apache API in order to +deal with HTTP/1.1 compatibility. It is possible that some modules +will no longer work (specifically, those that process input using the +POST or PUT methods). If you encounter a module that does not work, +please contact the author. A programmer's note on the subject is +available.

    + +

    Additionally, some changes were made to the CGI environment that +may cause some CGI scripts to work incorrectly. If you are +experiencing trouble with a CGI that worked fine under Apache 1.1.1, +please see our explanation of the changes.

    + +

    New Features with Apache 1.2

    +

    New features with this release, as extensions of the Apache +functionality. Because the core code has changed so +significantly, there are certain liberties that earlier versions of +Apache (and the NCSA daemon) took that recent Apache versions are +pickier about - please check the compatibility notes if you have any +problems.

    +
    + +

    In addition to a number of bug fixes and internal performance +enhancements, Apache +1.2 has the following specific new user features:

    + +
      + + +
    • HTTP/1.1 Compliance +[Documentation to be written]
      +Aside from the optional proxy module (which operates as HTTP/1.0), +Apache is conditionally compliant with the HTTP/1.1 proposed standard, +as approved by the IESG and the +IETF HTTP working group. +HTTP/1.1 provides a much-improved protocol, and +should allow for greater performance and efficiency when transferring +files. Apache does, however, still work great with HTTP/1.0 browsers. +We are very close to being unconditionally compliant; if you note any +deviance from the proposed standard, please report it as a bug. + +
    • eXtended Server Side Includes +(XSSI)
      +A new set of server-side include +directives allows the user to better create WWW pages. This includes +number of powerful new features, such as the ability to set variables +and use conditional HTML. + +
    • File-based and Regex-enabled +Directive Sections
      +The new +<Files> +section allows directives to be enabled based on full filename, not just +directory and URL. In +addition, <Files> sections can appear in +.htaccess files. <Files>, along with +<Directory> + and <Location>, can +also now be based on regular expressions, not just simple prefix +matching. + +
    • Browser-based Environment +Variables
      +Environment variables can now be set based on the +User-Agent string of the browser. Combined with XSSI, this allows you to write browser-based +conditional HTML documents. + +
    • SetUID CGI Execution
      + Apache now + supports the execution of CGI scripts as users other + than the server user. A number of security checks are built in + to try and make this as safe as possible. + +
    • URL Rewriting Module +
      +The optional mod_rewrite module is now included. This +module can provide powerful URL mapping, using regular +expressions. There's nothing this module can't do! + +
    • Enhanced, Configurable +Logging
      +The optional mod_log_config included with earlier +versions of Apache is now standard, and has been enhanced to allow +logging of much more detail about the transaction, and can be used to +open more than one log file at once +(each of which can have a different log format). If you have Apache +write any logs to a directory which is writable by anyone other than +the user that starts the server, see the +security tips document to be sure you aren't putting the security +of your server at risk. + + +
    • User Tracking (Cookies) +Revisions
      +The mod_cookies included with previous versions of Apache +has been renamed mod_usertrack, to more accurately +reflect its function (some people inadvertently thought it enabled +cookie support in Apache, which is not true - Apache supports the use +of cookies directly). It is also now possible to disable the +generation of cookies, even when + the cookie module is compiled in. Also, an expiry time can be set + on the cookies. + +
    • <VirtualHost> +Enhancements
      + The <VirtualHost> directive can now take more than one IP + address or hostname. This lets a single vhost handles requests + for multiple IPs or hostnames. Also the special section + <VirtualHost _default_> can be used to handle requests normally + left for the main server configuration. + +
    • CGI Debugging +Environment
      +ScriptLog allows you to now set up a log that records +all input and output to failed CGI scripts. This includes environment +variables, input headers, POST data, output, and more. This makes CGI +scripts much easier to debug. + +
    • Resource Limits for CGI +Scripts
      +New directives allow the limiting of resources used by CGI scripts +(e.g., max CPU time). This is helpful in preventing 'runaway' CGI +processes. + +
    • Redirect Directive Can Return +Alternate Status
      + The Redirect directive can return permanent or temporary redirects, + "Gone" or "See Other" HTTP status. For NCSA-compatibility, + RedirectTemp and RedirectPermanent are also implemented. + +
    • Simplified Compilation
      + The process of configuring Apache for compilation has been + simplified. + +
    • Add or Remove +Options
      + The Options directive can now add or remove options from + those currently in force, rather than always replacing them. + +
    • Command-line Help
      +The -h command-line option now lists all the available +directives. + +
    • Optional Headers Module to Set or +Remove HTTP Headers
      +The optional mod_headers module can be used to set custom +headers in the HTTP response. It can append to existing headers, +replace them, or remove headers from the response. + +
    • Conditional Config +Directives
      +A new <IfModule> section allows directives to be +enabled only if a given module is loaded into the server. + +
    • NCSA Satisfy authentication +directive now implemented
      +Satisfy allows for more flexible access control +configurations. + +
    • Better NCSA Compatibility
      +Apache directives are now more compatible with NCSA 1.5 to make +moving between servers easier. In particular, Apache now implements the +Satisfy, +MaxKeepAliveRequests, +RedirectPermanent and +RedirectTemp, +directives, and the following directives are now syntax-compatible with +NCSA: +AuthUserFile, +AuthGroupFile, +AuthDigestFile, +KeepAlive and +KeepAliveTimeout. + +
    • Optional proxy module
      +An improved FTP, HTTP, and CONNECT mode SSL proxy is included with +Apache 1.2. Some of the changes visible to users: +
      +
      - Improved FTP proxy supporting PASV mode +
      - ProxyBlock directive for excluding sites to proxy +
      - NoCache * directive for disabling proxy caching +
      - Numerous bug fixes +
      + +
    + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/new_features_1_3.html b/APACHE_1_3_12/htdocs/manual/new_features_1_3.html new file mode 100644 index 0000000000..cd3c8ab0c0 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/new_features_1_3.html @@ -0,0 +1,693 @@ + + +New features with Apache 1.3 + + + + + +

    Overview of New Features in Apache 1.3

    + +

    New features with this release, as extensions of the Apache +functionality. Because the core code has changed so +significantly, there are certain liberties that earlier versions of +Apache (and the NCSA daemon) took that recent Apache versions are +pickier about - please check the +compatibility notes if you have any +problems.

    + +

    If you're upgrading from Apache 1.2, you may wish to read +the upgrade notes. + +

    Enhancements: Core | +Performance | +Configuration | +Modules | +API | +Misc + +


    + +

    Core Enhancements:

    + +
    +
    Dynamic Shared Object (DSO) support +
    Apache modules may now be loaded at runtime; this means that + modules can be loaded into the server process space only when necessary, + thus overall memory usage by Apache will be significantly reduced. DSO + currently is supported on FreeBSD, OpenBSD, NetBSD, Linux, Solaris, SunOS, + Digital UNIX, IRIX, HP/UX, UnixWare, NetWare, AIX, ReliantUnix and generic + SVR4 platforms. + +
    Support for Windows NT/95 +
    Apache now experimentally supports the Windows NT and Windows 95 + operating systems. + +
    Support for NetWare 5.x +
    Apache now experimentally supports the NetWare 5.x operating systems. + +
    Re-organized + Sources +
    The source files for Apache have been re-organized. The main + difference for Apache users is that the "Module" lines in + Configuration have been replaced with "AddModule" + with a slightly different syntax. For module authors there are + some changes designed to make it easier for users to add their + module. + +
    Reliable Piped Logs +
    On almost all Unix architectures Apache now implements "reliable" + piped logs in mod_log_config. Where reliable + means that if the logging child dies for whatever reason, Apache + will recover and respawn it without having to restart the entire + server. Furthermore if the logging child becomes "stuck" and + isn't reading its pipe frequently enough Apache will also restart + it. This opens up more opportunities for log rotation, hit + filtering, real-time splitting of multiple vhosts into separate + logs, and asynchronous DNS resolving on the fly. +
    + +


    + +

    Performance Improvements

    + +
      +
    • IP-based virtual hosts are looked up via hash table. +
    • <Directory> parsing speedups. +
    • The critical path for static requests has fewer system calls. + This generally helps all requests. (45 syscalls for a static + request in 1.2 versus 22 in 1.3 in a well tuned + configuration). +
    • + ProxyReceiveBufferSize directive gives + mod_proxy's outgoing connections larger network + buffers, for increased throughput. +
    • The low level I/O routines use writev (where + available) to issue multiple writes with a single system call. + They also avoid copying memory into buffers as much as + possible. The result is less CPU time spent on transferring + large files. +
    • Static requests are served using mmap, which + means bytes are only copied from the disk buffer to the + network buffer directly by the kernel. The program never + copies bytes around, which reduces CPU time. (Only where + available/tested.) +
    • When presented with a load spike, the server quickly adapts by + spawning children at faster rates. +
    • The code which dispatches modules was optimized to avoid + repeatedly skipping over modules that don't implement certain + phases of the API. (This skipping showed up as 5% of the cpu + time on profiles of a server with the default module mix.) +
    • Revamp of the Unix scoreboard management code so that less + time is spent counting children in various states. Previously + a scan was performed for each hit, now it is performed only + once per second. This should be noticeable on servers running + with hundreds of children and high loads. +
    • New serialization choices improve performance on Linux, and + IRIX. +
    • mod_log_config can + be compile-time configured to buffer writes. +
    • Replaced strncpy() with + ap_cpystrn(), a routine which doesn't have to + zero-fill the entire result. This has dramatic effects on + mod_include speed. +
    • Additions to the internal "table" API (used for keeping lists + of key/value string pairs) provide for up to 20% performance + improvement in many situations. +
    + +

    See the new performance +documentation for more information. + +


    + +

    Configuration Enhancements

    + +
    +
    Unified Server Configuration Files
    +
    (Apache 1.3.4) The contents of the three + server configuration files (httpd.conf, + srm.conf, and access.conf) have + been merged into a single httpd.conf file. + The srm.conf and access.conf files + are now empty except for comments directing the Webmaster + to look in httpd.conf. In addition, the + merged httpd.conf file has been restructured + to allow directives to appear in a hopefully more + intuitive and meaningful order. +
    +
    Continuation Lines in config files
    +
    Directive lines in the server configuration files may now be + split onto multiple lines by using the canonical Unix continuation + mechanism, namely a '\' as the last non-blank character on the + line to indicate that the next line should be concatenated. +
    +
    Apache Autoconf-style Interface (APACI) +
    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.
    + Note: The default installation layout has changed + for Apache 1.3.4. See the files README.configure and + INSTALL for more information. + +
    APache eXtenSion (APXS) support tool +
    Now that Apache provides full support for loading modules under + runtime from dynamic shared object (DSO) files, a new support tool + apxs was created which provides off-source building, + installing and activating of those DSO-based modules. It + completely hides the platform-dependent DSO-build commands from + the user and provides an easy way to build modules outside the + Apache source tree. To achieve this APACI installs the Apache C + header files together with the apxs tool. + +
    Default Apache directory + path changed to /usr/local/apache/
    +
    The default directory for the apache ServerRoot changed from the + NCSA-compatible /usr/local/etc/httpd/ to + /usr/local/apache/. This change covers only the + default setting (and the documentation); it is of course possible + to override it using the -d + ServerRoot and -f httpd.conf switches when + starting apache. + +
    Improved HTTP/1.1-style Virtual Hosts +
    The new NameVirtualHost + directive is used to list IP address:port pairs on which + HTTP/1.1-style virtual hosting occurs. This is vhosting based on + the Host: header from the client. Previously this + address was implicitly the same as the "main address" of the + machine, and this caused no end of problems for users, and was not + powerful enough. Please see the Apache Virtual Host documentation for + further details on configuration. + +
    Include directive +
    The Include + directive includes other config files immediately at that point in + parsing. + +
    -S command line option for debugging vhost setup +
    If Apache is invoked with the -S command line option + it will dump out information regarding how it parsed the + VirtualHost sections. This is useful for folks + trying to debug their virtual host configuration. + +
    Control of HTTP methods +
    <LimitExcept> and + </LimitExcept> are used to enclose a group of access control + directives which will then apply to any HTTP access method not listed in + the arguments; i.e., it is the opposite of a section and can be + used to control both standard and nonstandard/unrecognized methods. +
    + +


    + +

    Module Enhancements

    + +
    +
    Improved mod_negotiation +
    +
    The optional content negotiation (MultiViews) module has been completely + overhauled for Apache 1.3.4, incorporating the latest HTTP/1.1 + revisions and the experimental Transparent Content Negotion features + of RFC 2295 and RFC 2296. + +
    NEW - Spelling correction + module
    +
    This optional module corrects frequently occurring spelling and + capitalization errors in document names requested from the server. + +
    NEW - Conditional setting of + environment variables
    +
    The addition of + + SetEnvIf and + + SetEnvIfNoCase. These allow you to set + environment variables for server and CGI use based upon attributes + of the request. + +
    NEW - "Magic" +MIME-typing +
    The optional mod_mime_magic has been + added. It uses "magic numbers" and other hints from a file's + contents to figure out what the contents are. It then uses this + information to set the file's media type, if it cannot be + determined by the file's extension. + +
    NEW - Unique Request + Identifiers +
    mod_unique_id can be included + to generate a unique identifier that distinguishes a hit from + every other hit. ("Unique" has some restrictions on it.) The + identifier is available in the environment variable + UNIQUE_ID. + +
    mod_proxy enhancements: +
      +
    • Easier and safer authentification for ftp proxy logins: + When no ftp user name and/or password is specified in the + URL, but the destination ftp server requires one, apache now + returns a "[401] Authorization Required" status. This status code + usually makes the client browser pop up an "Enter user name and + password" dialog, and the request is retried with the given user + authentification. That is slightly more secure than specifying + the authentication information as part of the request URL, + where it could be logged in plaintext by older proxy servers. +
    • The new AllowCONNECT directive allows configuration + of the port numbers to which the proxy CONNECT method may connect. + That allows proxying to https://some.server:8443/ which resulted + in an error message prior to Apache version 1.3.2. +
    • The proxy now supports the HTTP/1.1 "Via:" header as specified in + RFC2068. The new + ProxyVia + directive allows switching "Via:" support off or on, or + suppressing outgoing "Via:" header lines altogether for privacy + reasons. +
    • The "Max-Forwards:" TRACE header specified in HTTP/1.1 is now + supported. With it, you can trace the path of a request along a + chain of proxies (if they, too, support it). +
    • NoProxy and ProxyDomain + directives added to proxy, useful for intranets. +
    • New + ProxyPassReverse directive. It lets Apache adjust the + URL in the Location header on HTTP redirect + responses. +
    • Easier navigation in ftp server directory trees. +
    + +
    Enhanced + mod_include string comparisons
    +
    The string-based server-side include (SSI) flow-control directives + now include comparison for less-than (<), less-than-or-equal + (<=), greater-than (>), and greater-than-or-equal (>=). + Previously comparisons could only be made for equality or + inequality. + +
    ServerRoot relative auth filenames +
    Auth filenames for the various authentication modules are now + treated as relative to the ServerRoot if they are not full paths. + +
    Enhancements to directory + indexing: + +
      +
    • Code split:The mod_dir module has + been split in two, with mod_dir handling directory index + files, and mod_autoindex + creating directory listings. Thus allowing folks to remove the + indexing function from critical servers. + +
    • Sortable: Clicking on a column title will now sort + the listing in order by the values in that column. This feature can + be disabled using the SuppressColumnSorting IndexOptions + keyword. + +
    • + SuppressHTMLPreamble can be used if + your README.html file includes its own HTML header. + +
    • The + IndexOptions directive now allows + the use of incremental prefixes (+/- to add/remove the respective + keyword feature, as was already possible for the + Options directive) to its + keyword arguments. Multiple IndexOptions directives applying + to the same directory will now be merged. + +
    • IconHeight and + IconWidth + let you set height and width attributes to the + <IMG> tag in directory listings. + +
    • The new NameWidth keyword to the + IndexOptions + directive lets you set the number of columns for + "fancy" + directory listings. If set to an '*' asterisk, the name width + will be adjusted automatically. + +
    • The FancyIndexing directive now correctly has + the same impact as + IndexOptions FancyIndexing + without replacing the effect of any existing IndexOptions + directive. + +
    + +
    Less Buffering of CGI Script Output +
    In previous versions of Apache, the output from CGI scripts would + be internally buffered by the server, and wouldn't be forwarded to + the client until either the buffers were full or the CGI script + completed. As of Apache 1.3, the buffer to the client is flushed + any time it contains something and the server is waiting for more + information from the script. This allows CGI script to provide + partial status reports during long processing operations. + + +
    Regular Expression support for + Alias and Redirect +
    New AliasMatch, + ScriptAliasMatch, and + RedirectMatch + directives allow for the use of regular expression matching. + Additionally, new + <DirectoryMatch>, + <LocationMatch>, + and + <FilesMatch> + sections provide a new syntax for regular expression sectioning. + +
    AddModuleInfo + directive added to mod_info +
    Allows additional information to be listed along with a specified + module. + +
    Absence of any TransferLog disables + logging +
    If no TransferLog directive is given then no log is + written. This supports co-existence with other logging modules. + +
    Ability to name logging formats +
    The LogFormat + directive has been enhanced to allow you to give nicknames to + specific logging formats. You can then use these nicknames in + other LogFormat and CustomLog directives, rather than having to + spell out the complete log format string each time. + +
    Conditional logging +
    mod_log_config + now supports logging based upon environment variables. + mod_log_referer and mod_log_agent are now deprecated. + +
    mod_cern_meta configurable per-directory +
    mod_cern_meta is now + configurable on a per-directory basis. + +
    New map types for + RewriteMap + directive +
    The new map types `Randomized Plain Text' and `Internal Function' + were added to the RewriteMap directive of + mod_rewrite. They provide two new features: First, you now can + randomly choose a sub-value from a value which was looked-up in a + rewriting map (which is useful when choosing between backend + servers in a Reverse Proxy situation). Second, you now can + translate URL parts to fixed (upper or lower) case (which is + useful when doing mass virtual hosting by the help of + mod_rewrite). + +
    CIDR and Netmask access control +
    mod_access directives now + support CIDR (Classless Inter-Domain Routing) style prefixes, and + netmasks for greater control over IP access lists. + +
    +


    + +

    API Additions and Changes

    + +

    For all those module writers and code hackers: + +

    +
    child_init +
    A new phase for Apache's API is called once per "heavy-weight process," + before any requests are handled. This allows the module to set up + anything that need to be done once per processes. For example, + connections to databases. + +
    child_exit +
    A new phase called once per "heavy-weight process," when it is + terminating. Note that it can't be called in some fatal cases (such + as segfaults and kill -9). The child_init and + child_exit functions are passed a pool whose lifetime is + the same as the lifetime of the child (modulo completely fatal + events in which apache has no hope of recovering). In contrast, + the module init function is passed a pool whose lifetime + ends when the parent exits or restarts. + +
    child_terminate +
    Used in the child to indicate the child should exit after finishing + the current request. + +
    register_other_child +
    See http_main.h. This is used in the parent to register + a child for monitoring. The parent will report status to a supplied + callback function. This allows modules to create their own children + which are monitored along with the httpd children. + +
    piped_log +
    See http_log.h. This API provides the common code for + implementing piped logs. In particular it implements a reliable piped + log on architectures supporting it (i.e., Unix at the moment). + +
    scoreboard format changed +
    The scoreboard format is quite different. It is considered a + "private" interface in general, so it's only mentioned here as an FYI. + +
    set_last_modified split into three +
    The old function set_last_modified performed multiple + jobs including the setting of the Last-Modified header, the + ETag header, and processing conditional requests (such as + IMS). These functions have been split into three functions: + set_last_modified, set_etag, and + meets_conditions. The field mtime has been + added to request_rec to facilitate + meets_conditions. + +
    New error logging function: ap_log_error +
    All old logging functions are deprecated, we are in the process of + replacing them with a single function called ap_log_error. + This is still a work in progress. + +
    set_file_slot for config parsing +
    The set_file_slot routine provides a standard routine that + prepends ServerRoot to non-absolute paths. + +
    post_read_request module API +
    This request phase occurs immediately after reading the request (headers), + and immediately after creating an internal redirect. It is most useful + for setting environment variables to affect future phases. + +
    psocket, and popendir +
    The psocket and pclosesocket functions allow + for race-condition free socket creation with resource tracking. + Similarly popendir and pclosedir protect + directory reading. + +
    is_initial_req +
    Test if the request is the initial request (i.e., the one + coming from the client). + +
    kill_only_once +
    An option to ap_spawn_child functions which prevents Apache + from aggressively trying to kill off the child. + +
    alloc debugging code +
    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. + +
    ap_cpystrn +
    The new strncpy "lookalike", with slightly different + semantics is much faster than strncpy because it + doesn't have to zero-fill the entire buffer. + +
    table_addn, table_setn, + table_mergen +
    These new functions do not call pstrdup + on their arguments. This provides for big speedups. There is + also some debugging support to ensure code uses them properly. + See src/CHANGES for more information. + +
    construct_url +
    The function prototype for this changed from taking a + server_rec * to taking a request_rec *. + +
    get_server_name, get_server_port +
    These are wrappers which deal with the + UseCanonicalName directive + when retrieving the server name and port for a request. + +
    Change to prototype for ap_bspawn_child and + ap_call_exec +
    Added a child_info * to spawn function + (as passed to ap_bspawn_child) and to + ap_call_exec to allow children to work correctly on Win32. + We also cleaned up the nomenclature a bit, replacing + spawn_child_err with simply + ap_spawn_child and spawn_child_err_buff + with simply ap_bspawn_child. + +
    ap_add_version_component() +
    This API function allows for modules to add their own additional + server tokens which are printed on the on the Server: + header line. Previous 1.3beta versions had used a + SERVER_SUBVERSION compile-time #define + to perform this function. Whether the tokens are actually displayed + is controlled by the new ServerTokens directive. + +
    + +


    + +

    Miscellaneous Enhancements

    + +
    +
    Port to EBCDIC mainframe machine + running BS2000/OSD +
    As a premiere, this version of Apache comes with a beta version of + a port to a mainframe machine which uses the EBCDIC character set + as its native codeset (It is the SIEMENS family of mainframes + running the BS2000/OSD operating system on a IBM/390 + compatible processor. This mainframe OS nowadays features a + SVR4-like POSIX subsystem). + +
    AccessFileName + Enhancement +
    The AccessFileName directive can now take more than + one filename. This lets sites serving pages from network file + systems and more than one Apache web server, configure access + based on the server through which shared pages are being served. + +
    HostNameLookups now defaults to "Off" +
    The HostNameLookups + directive now defaults to "Off". This means that, unless explicitly + turned on, the server will not resolve IP addresses into names. This + was done to spare the Internet from unnecessary DNS traffic. + +
    Double-Reverse DNS enforced +
    The HostnameLookups + directive now supports double-reverse DNS. (Known as + PARANOID in the terminology of tcp_wrappers.) An IP + address passes a double-reverse DNS test if the forward map of the + reverse map includes the original IP. Regardless of the + HostnameLookups setting, mod_access access lists using DNS + names require all names to pass a double-reverse + DNS test. (Prior versions of Apache required a compile-time + switch to enable double-reverse DNS.) + +
    LogLevel and syslog support +
    Apache now has configurable error + logging levels and supports error logging via syslogd(8). + +
    Detaching from stdin/out/err +
    On boot Apache will now detach from stdin, stdout, and stderr. It + does not detach from stderr until it has successfully read the + config files. So you will see errors in the config file. This + should make it easier to start Apache via rsh or crontab. + +
    Year-2000 Improvements +
    The default timefmt string used by mod_include has been + modified to display the year using four digits rather than the + two-digit format used previously. The mod_autoindex + module has also been modified to display years using four digits + in FancyIndexed directory listings. + +
    Common routines Moving to a Separate Library +
    There are a number of functions and routines that have been + developed for the Apache project that supplement or supersede + library routines that differ from one operating system to another. + While most of these are used only by the Apache server itself, + some are referenced by supporting applications (such as + htdigest), and these other applications would fail to + build because the routines were built only into the server. These + routines are now being migrated to a separate subdirectory and + library so they can be used by other applications than just the + server. See the src/ap/ subdirectory. + +
    New + ServerSignature directive +
    This directive optionally adds a line containing the server + version and virtual host name to server-generated pages (error + documents, ftp directory listings, mod_info output etc.). This + makes it easier for users to tell which server produced the error + message, especially in a proxy chain (often found in intranet + environments). + +
    New + UseCanonicalName directive +
    This directive gives control over how Apache creates + self-referential URLs. Previously Apache would always use the ServerName and Port directives to construct a + "canonical" name for the server. With UseCanonicalName + off Apache will use the hostname and port supplied by the + client, if available. + +
    SERVER_VERSION definition abstracted, and server + build date added +
    In earlier versions, the Apache server version was available to + modules through the #defined value for + SERVER_VERSION. In order to keep this value + consistent when modules and the core server are compiled at + different times, this information is now available through the + core API routine ap_get_server_version(). The use of + the SERVER_VERSION symbol is deprecated. Also, + ap_get_server_built() returns a string representing + the time the core server was linked. + +
    Including the operating + system in the server identity
    +
    A new directive, ServerTokens, allows the Webmaster + to change the value of the Server response header + field which is sent back to clients. The ServerTokens + directive controls whether the server will include a non-specific + note in the server identity about the type of operating system on + which the server is running as well as included module information. + As of Apache 1.3, this additional information is included by default. + +
    + +
    Support for Netscape style SHA1 encrypted passwords
    +
    To facilitate migration or integration of BasicAuth password + schemes where the password is encrypted using SHA1 (as opposed + to apache's build in MD5 and/or the OS specific crypt(3) function + ) passwords prefixed with with {SHA1} are taken + as Base64 encoded SHA1 passwords. More information and + some utilities to convert Netscape ldap/ldif entries can be + found in support/SHA1. + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/process-model.html b/APACHE_1_3_12/htdocs/manual/process-model.html new file mode 100644 index 0000000000..74f7d4e6eb --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/process-model.html @@ -0,0 +1,68 @@ + + +Server Pool Management + + + + + +

    Server Pool Management

    + +
    +

    +We found that many people were using values for "MaxServers" either +too high or too low, and were hanging themselves on it. The model we +adopted is still based on long-lived minimal-forking processes, but +instead of specifying one number of persistent processes, the +web-master specifies a maximum and minimum number of processes to be +"spare" - every couple of seconds the parent checks the actual number +of spare servers and adjusts accordingly. This should keep the number +of servers concurrently running relatively low while still ensuring +minimal forking. + +

    + +We renamed the 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. + +

    + +The defaults for each variable are: + +

    +MinSpareServers         5
    +MaxSpareServers         10
    +StartServers            5
    +
    + +There is an absolute maximum number of simultaneous children defined +by a compile-time limit which defaults to 256 and a "MaxClients" +directive which specifies the number of simultaneous children that +will be allowed. MaxClients can be adjusted up to the compile-time +limit (HARD_SERVER_LIMIT, defined in httpd.h). If you need more +than 256 simultaneous children, you need to modify both HARD_SERVER_LIMIT +and MaxClients.

    + +In versions before 1.2, HARD_SERVER_LIMIT defaulted to 150.

    + +We do not recommend changing either of these values unless: + +

      +
    1. You know you have the server resources to handle more +
    2. You use the machine for other purposes and must limit the amount of memory +Apache uses +
    + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/readme-tpf.html b/APACHE_1_3_12/htdocs/manual/readme-tpf.html new file mode 100644 index 0000000000..9d1a82a279 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/readme-tpf.html @@ -0,0 +1,208 @@ + + + +The Apache TPF Port + + + +

    Overview of the Apache TPF Port

    +
    +
    Configuration Files +  | What's Available +  | Porting Notes ] +
    +
    +
    + +

    + This version of Apache includes changes allowing it to run on + IBM's EBCDIC-based + TPF + (Transaction Processing Facility) operating system. + Unless otherwise noted TPF version 4.1 PUT09 is required. +

    + Refer to htdocs/manual/install-tpf.html + for step-by-step installation instructions. +

    + As this is the first cut at making Apache run on TPF, + performance tuning has not been done. +

    + This port builds upon the EBCDIC changes + previously made to Apache. +
    +

    + +  +

    Apache Configuration Files

    +

    + The distributed configuration files (httpd.conf-dist and + mime.types, both located in the conf subdirectory) + work on TPF. Performance considerations may dictate setting KeepAlive to "Off" + (the default is "On") or lowering the Timeout value from the default + 300 seconds (5 minutes) in order to reduce the number of active ECBs on your system. +

    + +  +

    What's Available in this Version

    + + (The Apache organization provides + online documentation + describing the various modules and components of the server.) + +

    Components/modules tested on TPF:

    + +
      +
    • alloc.c +
    • ap_base64.c +
    • ap_checkpass.c +
    • ap_cpystrn.c +
    • ap_fnmatch.c +
    • ap_md5c.c +
    • ap_sha1.c +
    • ap_signal.c +
    • ap_slack.c +
    • ap_snprintf.c +
    • buff.c +
    • buildmark.c +
    • ebcdic.c +
    • gen_test.char.c +
    • gen_uri_delims.c +
    • htpasswd.c (requires PUT10) +
    • http_config.c +
    • http_core.c +
    • http_log.c +
    • http_main.c +
    • http_protocol.c +
    • http_request.c +
    • http_vhost.c +
    • logresolve.c (requires PUT10) +
    • mod_access.c (see note 1) +
    • mod_actions.c +
    • mod_alias.c +
    • mod_asis.c +
    • mod_auth.c +
    • mod_auth_anon.c +
    • mod_autoindex.c +
    • mod_cern_meta.c +
    • mod_cgi.c (requires PUT10) +
    • mod_digest.c +
    • mod_dir.c +
    • mod_env.c +
    • mod_example.c +
    • mod_expires.c +
    • mod_headers.c +
    • mod_imap.c +
    • mod_include.c (see note 2) +
    • mod_info.c +
    • mod_log_agent.c +
    • mod_log_config.c +
    • mod_log_referer.c +
    • mod_mime.c +
    • mod_mime_magic.c +
    • mod_negotiation.c +
    • mod_put.c + (third party module) +
    • mod_proxy.c +
    • mod_setenvif.c +
    • mod_speling.c +
    • mod_status.c +
    • mod_tpf_shm_static.c (third party module, requires PUT10) +
    • mod_unique_id.c (requires PUT10) +
    • mod_userdir.c +
    • mod_usertrack.c +
    • os.c +
    • os-inline.c +
    • proxy_cache.c +
    • proxy_connect.c +
    • proxy_ftp.c +
    • proxy_http.c +
    • proxy_util.c +
    • regular expression parser +
    • regular expression test tool (requires PUT10) +
    • rfc1413.c +
    • rotatelogs.c (requires PUT10) +
    • util.c +
    • util_date.c +
    • util_md5.c +
    • util_script.c +
    • util_uri.c +
    + Notes: +
      +
    1. Use of mod_access directives "allow from" & "deny from" + with host names (verses ip addresses) requires TPF version 4.1 PUT10 +
    2. CGI execution requires TPF version 4.1 PUT10 +
    + +

    Components/modules not yet supported on TPF:

    + +
      +
    • htdigest.c +
    • lib/expat-lite +
    • mod_auth_digest.c +
    • mod_rewrite.c +
    • mod_vhost_alias.c +
    + +

    Components/modules that don't apply or that probably won't ever be available on TPF:

    + +
      +
    • ab.c +
    • ap_getpass.c +
    • mod_auth_db.c +
    • mod_auth_dbm.c +
    • mod_auth_db.module +
    • mod_mmap_static.c +
    • mod_so.c +
    • suexec.c +
    + +  +

    Porting Notes

    +

    +

    Changes made due to differences between UNIX and + TPF's process models:

    +
      +
    • Signals: On TPF a signal that is sent to a process + remains unhandled until the process explicitly requests that signals + be handled using the tpf_process_signals() function. + Additionally, the default action for an alarm on TPF is to take + an OPR-7777 dump and exit. (On UNIX the default is the equivalent + of exit() with no dump taken.) + These differences necessitated a few modifications: +

      +
        +
      • bypass the use of ap_block_alarms() & + ap_unblock_alarms() +
      • add tpf_process_signals() calls +
      • add select() calls to prevent blocking. +
      +
      +
    + +

    Find that function...

    +

    Some simple functions & definitions initially needed to be added + on TPF, such as FD_SET(). + We've put these in src/os/tpf/os.h for now. +

    + +

    EBCDIC changes:

    +

    TPF-specific conversion tables between US-ASCII and + EBCDIC (character set IBM-1047 to be exact) were created + and put into ebcdic.c in the src/os/tpf directory. +

    + +

    Miscellaneous, minor changes:

    +

    Various minor changes (such as casting) were made due to + differences in how some functions are implemented on TPF. +

    + +
    +
    top +  | Configuration Files +  | What's Available +  | Porting Notes ] +
    + + + diff --git a/APACHE_1_3_12/htdocs/manual/search/manual-index.cgi b/APACHE_1_3_12/htdocs/manual/search/manual-index.cgi new file mode 100755 index 0000000000..033529937f --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/search/manual-index.cgi @@ -0,0 +1,246 @@ +#!/usr/local/bin/perl5 -w +# ==================================================================== +# Copyright (c) 1995-1997 The Apache Group. 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 acknowledgment: +# "This product includes software developed by the Apache Group +# for use in the Apache HTTP server project (http://www.apache.org/)." +# +# 4. The names "Apache Server" and "Apache Group" must not be used to +# endorse or promote products derived from this software without +# prior written permission. +# +# 5. Redistributions of any form whatsoever must retain the following +# acknowledgment: +# "This product includes software developed by the Apache Group +# for use in the Apache HTTP server project (http://www.apache.org/)." +# +# THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY +# EXPRESSED 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 APACHE GROUP OR +# ITS 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. +# ==================================================================== +# +# manual-index.cgi script +# originally written by Ken Coar in May 1997 +# +# This script either displays a form in order to find documents in which +# a word appears, or displays the results of such a search. It is +# called as a CGI script. +# +# [FILE]PATH_INFO is the prefix to add to to the files names found in +# the index (URL prefix, not filesystem prefix), and QUERY_STRING is the +# word to be found. +# +#*** +#*** +# You may need to tweak the following line to point to the correct +# location of the index file on your system (it's in the +# apache/htdocs/manual directory of the Apache distribution tree). +#*** +#*** +$INDEX = "/www/apache.org/manual-index-data"; + +#*** +#*** +# You shouldn't have to modify anything else. +#*** +#*** + +$HTML = ""; + +# +# If we have a FILEPATH_INFO or PATH_INFO, it's there to remap the +# documents to the manual root directory. If this script is already in +# that directory, this isn't needed. +# +$prefix = $ENV{'FILEPATH_INFO'} || $ENV{'PATH_INFO'}; +$prefix .= "/" if ($prefix && ($prefix !~ m:/$:)); + +# +# QUERY_STRING, if present, contains the word for which we are to +# search. We also use its [non]presence to determine wha we display. +# +$word = $ENV{'QUERY_STRING'}; + +# +# Make sure our HTTP header makes it to the server by causing Perl to do +# a fflush() after every write to STDOUT. +# +select (STDOUT); +$| = 1; +printf ("Content-type: text/html\n\n"); + +# +# Fine, now buffering can go back to normal. +# +$| = 0; + +# +# Set up the HTML page title +$title = "Apache Documentation Search"; +$title .= ": Results for \"$word\"" if ($word); + +# +# We'll re-use the HTML scalar several times; we use it with here +# documents for multi-line static HTML code. Lets' do the standard page +# header. +# +$HTML = < + + + $title + + + + +
    + +
    +

    + Apache Documentation Search +

    +

    + This script performs a very simple search across the Apache + documentation for any single case-insensitive word. No combinations, + wildcards, regular expressions, word-stubbing, or other fancy options + are supported; this is just to help you find topics quickly. Only + those pages which include the exact word you type will be + listed. +

    +

    + Documents containing the search word are not listed in any + sort of priority order. +

    + +EOHT + +printf ($HTML); + +# +# Now set up the next section, which is only displayed if we've been +# given a word to find. +# +$HTML = < +

    + Results of Search for $word +

    +EOHT + +# +# We enblock the next section so problems can drop out to the common +# closure code. +# +QUERY: + { + if ($word) { + # + # Try and open the index file; complain bitterly if we can't. + # + if (! open (INDEX, "<$INDEX")) { + printf ("Can't find documentation index!"); + last QUERY; + } + # + # Got it; display the search-results header. + # + printf ($HTML); + # + # Read the entire index in and turn it into an hash for the + # lookup. + # + @index = ; + close (INDEX); + chomp (@index); + foreach (@index) { + ($key, $files) = split (/:/, $_); + $Index{$key} = $files; + } + # + # The dictionary is all lowercase words. Smash our query value + # and try to find it. + # + $word = lc ($word); + if (! exists ($Index{$word})) { + printf ("

    \n Sorry, no matches found.\n

    \n"); + last QUERY; + } + # + # Found an entry, so turn the hash value (a comma-separated list + # of relative file names) into an array for display. + # Incidentally, tell the user how many there are. + # + @files = split (/,/, $Index{$word}); + printf ("

    Total of %d match", scalar (@files)); + # + # Be smart about plurals. + # + if (scalar (@files) != 1) { + printf ("es") ; + } + printf (" found.\n

    \n"); + # + # Right. Now display the files as they're listed. + # + printf ("
      \n"); + foreach (@files) { + printf ("
    1. "); + printf ("$_\n"); + printf ("
    2. \n"); + } + printf ("
    \n"); + # + # C'est tout! + # + } + } + +# +# Back to common code - the exit path. Display the page trailer. +# +$HTML = <Home +
    + + +EOHT + +printf ($HTML); +exit (0); diff --git a/APACHE_1_3_12/htdocs/manual/sections.html b/APACHE_1_3_12/htdocs/manual/sections.html new file mode 100644 index 0000000000..88f3329408 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/sections.html @@ -0,0 +1,170 @@ + + +How Directory, Location and Files sections work + + + + + +

    How Directory, Location and Files sections work

    + +The sections <Directory>, <Location> and <Files> can contain +directives which only apply to specified directories, URLs or files +respectively. Also htaccess files can be used inside a directory to +apply directives to that directory. This document explains how these +different sections differ and how they relate to each other when +Apache decides which directives apply for a particular directory or +request URL. + +

    Directives allowed in the sections

    + +Everything that is syntactically allowed in +<Directory> is also allowed in +<Location> (except a sub-<Files> +section). Semantically however some things, and the most +notable are AllowOverride and the two options +FollowSymLinks and SymLinksIfOwnerMatch, +make no sense in <Location>, +<LocationMatch> or <DirectoryMatch>. +The same for <Files> -- syntactically everything +is fine, but semantically some things are different. + +

    How the sections are merged

    + +The order of merging is: + +
      + +
    1. + + <Directory> (except regular expressions) and + .htaccess done simultaneously (with .htaccess overriding + <Directory>) + +
    2. + +
    3. + <DirectoryMatch>, and + <Directory> with regular expressions + +
    4. + +
    5. <Files> and <FilesMatch> done + simultaneously +
    6. + +
    7. <Location> and <LocationMatch> done + simultaneously +
    8. + +
    + +Apart from <Directory>, each group is processed in +the order that they appear in the configuration +files. <Directory> (group 1 above) is processed in +the order shortest directory component to longest. If multiple +<Directory> sections apply to the same directory +they they are processed in the configuration file order. The +configuration files are read in the order httpd.conf, srm.conf and +access.conf. Configurations included via the Include +directive will be treated as if they where inside the including file +at the location of the Include directive. + +

    + +Sections inside <VirtualHost> sections are applied +after the corresponding sections outside the virtual host +definition. This allows virtual hosts to override the main server +configuration. (Note: this only works correctly from 1.2.2 and 1.3a2 +onwards. Before those releases sections inside virtual hosts were +applied before the main server). + +

    Notes about using sections

    + +The general guidelines are: + +

    + +

      +
    • + If you are attempting to match objects at the filesystem level + then you must use <Directory> and/or + <Files>. +
    • + +
    • + If you are attempting to match objects at the URL level then you + must use <Location> +
    • +
    + +But a notable exception is: + +
      +
    • + proxy control is done via <Directory>. This is + a legacy mistake because the proxy existed prior to + <Location>. A future version of the config + language should probably switch this to + <Location>. +
    • +
    + +

    +Note about .htaccess parsing: +

    +
      +
    • + Modifying .htaccess parsing during Location doesn't do + anything because .htaccess parsing has already occurred. +
    + +

    +<Location> and symbolic links: +

    +
      +
    • + It is not possible to use "Options FollowSymLinks" + or "Options SymLinksIfOwnerMatch" inside a + <Location>, <LocationMatch> + or <DirectoryMatch> section + (the options are simply ignored). + Using the options in question is only possible inside a + <Directory> section (or a .htaccess file). +
    + +

    +<Files> and Options: +

    +
      +
    • + Apache won't check for it, but using an Options + directive inside a <Files> section has no effect. +
    + +

    +Another note: +

    + +
      +
    • + There is actually a + <Location>/<LocationMatch> + sequence performed just before the name translation phase (where + Aliases and DocumentRoots are used to + map URLs to filenames). The results of this sequence are + completely thrown away after the translation has completed. +
    • +
    + + + diff --git a/APACHE_1_3_12/htdocs/manual/sourcereorg.html b/APACHE_1_3_12/htdocs/manual/sourcereorg.html new file mode 100644 index 0000000000..c168afceb0 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/sourcereorg.html @@ -0,0 +1,300 @@ + + + +Source Re-organisation + + + + + +

    Source Re-organisation

    + +As of 1.3, the Apache source directories have been re-organised. This +re-organisation is designed to simplify the directory structure, +make it easier to add additional modules, and to give module authors +a way of specifying compile time options or distribute binary +modules. + +

    Summary of Changes

    + +The source changes are: +
      +
    • The non-module source files have moved from src into + src/main +
    • +
    • The module source files previously in src have moved + to src/modules/standard +
    • +
    • The support directory is now in src/support +
    • +
    • The existing symbol names used for global Apache function and variable + identifiers have been renamed in the source. This way namespace conflicts + are avoided when linking Apache with third-party libraries. See the file + src/include/compat.h both for the list of renamed symbol + names and for a way to get source backward compatibility in existing + third-party module sources. +
    • +
    + +In addition, the following enhancements have been made: + +
      +
    • OS abstractions can be added in the src/os directory. + Currently this contains information for unix, OS/2 and Windows 32 + platforms. +
    • +
    • Configuration syntax has been simplified for adding new + modules. Users no longer need to enter the module's structure name. + In addition, new modules can be located anywhere on the + file system, or typically in new or existing directories under + src/modules. +
    • +
    • Module authors can give simpler instructions for adding their modules + to Apache compilation. They can also now provide compile time information + required by Configure, such as additional libraries + required. +
    • +
    • Module authors can distribute pre-compiled (.a or .o) versions of their + modules if required, along with a "module definition file" which + contains the information required by Configure. +
    • +
    • All the sub-directories (main, modules/* and os/*) are built as + libraries. +
    • +
    • The new Apache Autoconf-style Interface (APACI) script named + configure replaced the old top-level Makefile + and src/helpers/InstallApache stuff. +
    • +
    + +

    Adding Modules

    + +Modules are added to Apache by adding a reference to them in +src/Configuration then running Configure and +make. In earlier version of Apache before 1.3, the +line added to Configuration looked like this: + +
    +  Module    status_module    mod_status.o
    +
    + +From 1.3 onwards, the AddModule line should be used +instead, and typically looks like this: + +
    +  AddModule    modules/standard/mod_status.o
    +
    + +The argument to AddModule is the path, relative to src, to +the module file's source or object file. + +

    + +Normally when adding a module you should follow the instructions of +the module author. However if the module comes as a single source +file, say mod_foo.c, then the recommended way to add the module to +Apache is as follows: + +

      +
    • Put mod_foo.c into the directory + src/modules/extra +
    • +
    • Go to the src directory and add the following line + to Configuration
      + AddModule modules/extra/mod_foo.o +
    • +
    • Run ./Configure
    • +
    • Run make
    • +
    + +

    New Facilities for Module Authors

    + +In previous releases of Apache, new modules were added to the +src directory, and if the module required any additional +compilation options (such as libraries) they would have to be added +to Configuration. Also the user would have to be +told the module's structure name to add on the Module line +of Configuration. + +

    + +From Apache 1.3 onwards, module authors can make use of these new features: + +

      +
    • Simplified Configuration command AddModule which only + requires a path to the module source or object file +
    • +
    • If the module requires compile time options (such as extra + libraries) these can be specified in the module file source + or an external "module definition file". +
    • +
    • If a module is distributed as binary (.o or .a) then an external + "module definition file" can also be distributed which gives + the information Configure needs to add the module, such as extra + libraries and the module's structure name. +
    • Modules can be installed anywhere on the file system, although a directory + under src/modules is recommended. +
    • +
    • If the module is in its own directory, Apache can automatically + create a Makefile to build the module given a file containing + the module's dependencies. +
    • +
    • For building a third-party module outside the + Apache source tree the new apxs support tool can be + used to compile the module into a dynamic + shared object (DSO), install it into the existing Apache + installation and optionally activating it in the Apache + httpd.conf file. The only requirement is that + Apache has DSO-support for the used platform and the module + mod_so was built into + the server binary httpd. +
    • +
    + +The rest of this document shows how to package modules for Apache 1.3 +and later and what to tell end-users of the module. + +

    Building a simple source distribution

    + +Consider a simple add-on module, distributed as a single file. For +example, say it is called mod_demo.c. The archive for this module +should consist of two files, in a suitable directory name. For +example: + +
      +
    • mod_demo/mod_demo.c +
    • mod_demo/Makefile.tmpl +
    + +(Of course end-user instructions, README's, etc can also be supplied +in the archive). The end user should be told to extract this archive +in the src/modules directory of their Apache source +tree. This will create a new directory +src/modules/mod_demo. Then they need to add the following +line to the Configuration file: + +
    +  AddModule  modules/mod_demo/mod_demo.o
    +
    + +then run Configure and make as normal. + +

    + +The mod_demo/Makefile.tmpl should contain the dependencies +of the module source. For example, a simple module which just interfaces to +some standard Apache module API functions might look this this: + +

    +  mod_demo.o: mod_demo.c $(INCDIR)/httpd.h $(INCDIR)/http_protocol.h
    +
    + +When the user runs Configure Apache will create a full +makefile to build this module. If this module also requires +some additional built-time options to be given, such as libraries, +see the next section. +

    + +If the module also comes with header files, these can be added to the +archive. If the module consists of multiple source files it can be +built into a library file using a supplied makefile. In this case, +distribute the makefile as mod_demo/Makefile and do +not include a mod_demo/Makefile.tmpl. If +Configure sees a Makefile.tmpl it assumes it +is safe to overwrite any existing Makefile. + +

    + +See the Apache src/modules/standard for an example of a +module directory where the makefile is created automatically from a +Makefile.tmpl file (note that this directory also shows how to +distribute multiple modules in a single directory). See +src/modules/proxy and src/modules/example +for examples of modules built using custom makefiles (to build a +library and an object file, respectively). + +

    Adding Compile time Information

    + +Apache source files (or module definition files, see below) can +contain information used by Configure to add compile-time +options such as additional libraries. For example, if mod_demo in the +example above also requires that Apache be linked against a DBM +library, then the following text could be inserted into the mod_demo.c +source: + +
    +/*
    + * 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: demo_module
    + * ConfigStart
    +    LIBS="$LIBS $DBM_LIB"
    +    if [ "X$DBM_LIB" != "X" ]; then
    +        echo " + using $DBM_LIB for mod_demo"
    +    fi
    + * ConfigEnd
    + * MODULE-DEFINITION-END
    + */
    +
    + +Note that this is contained inside a C language comment to hide it +from the compiler. Anything between the lines which contains +MODULE-DEFINITION-START and +MODULE-DEFINITION-END is used by Configure. +The Name: line gives the module's structure name. This is +not really necessary in this case since if not present +Configure will guess at a name based on the filename +(e.g., given "mod_demo" it will remove the leading "mod_" and append +"_module" to get a structure name. This works with all modules +distributed with Apache). + +

    + +The lines between ConfigStart and ConfigEnd +as executed by Configure and can be used to add +compile-time options and libraries. In this case it adds the DBM +library (from $DBM_LIB) to the standard compilation libraries ($LIB) +and displays a message. + +

    + +See the default distribution's mod_auth_dbm.c for an example of +an embedded module definition. + +

    Module Definition Information for Binary Distribitions

    + +If the module is to be distributed as binary (object or library) rather +than source, it is not possible to add the module definition +information to the source file. In this case it can be placed in a +separate file which has the same base name as the object or library +file, but with a .module extension. So, for example, if +the distributed module object file is mod_demo.o, the module +definition file should be called mod_demo.module. It contains the same +information as above, but does not need to be inside a C comment or +delimited with MODULE-DEFINITION-START etc. For example: + +
    +Name: demo_module
    +ConfigStart
    + LIBS="$LIBS $DBM_LIB"
    + if [ "X$DBM_LIB" != "X" ]; then
    +     echo " + using $DBM_LIB for mod_demo"
    + fi
    +ConfigEnd
    +
    + +See the default distribution's mod_auth_db.module for an example of +a separate module definition file. + + + + diff --git a/APACHE_1_3_12/htdocs/manual/stopping.html b/APACHE_1_3_12/htdocs/manual/stopping.html new file mode 100644 index 0000000000..783d1c0250 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/stopping.html @@ -0,0 +1,183 @@ + + + +Stopping and Restarting Apache + + + + + +

    Stopping and Restarting Apache

    + +

    This document covers stopping and restarting Apache on Unix +only. Windows users should see Signalling +Apache when running.

    + +

    You will notice many httpd executables running on your system, +but you should not send signals to any of them except the parent, whose +pid is in the PidFile. That is to +say you shouldn't ever need to send signals to any process except the +parent. There are three signals that you can send the parent: +TERM, HUP, and USR1, which will +be described in a moment. + +

    To send a signal to the parent you should issue a command such as: +

    +    kill -TERM `cat /usr/local/apache/logs/httpd.pid`
    +
    + +You can read about its progress by issuing: + +
    +    tail -f /usr/local/apache/logs/error_log
    +
    + +Modify those examples to match your +ServerRoot and +PidFile settings. + +

    As of Apache 1.3 we provide a script src/support/apachectl +which can be used to start, stop, and restart Apache. It may need a +little customization for your system, see the comments at the top of +the script. + +

    TERM Signal: stop now

    + +

    Sending the TERM signal to the parent causes it to +immediately attempt to kill off all of its children. It may take it +several seconds to complete killing off its children. Then the +parent itself exits. Any requests in progress are terminated, and no +further requests are served. + +

    HUP Signal: restart now

    + +

    Sending the HUP signal to the parent causes it to kill off +its children like in TERM but the parent doesn't exit. It +re-reads its configuration files, and re-opens any log files. +Then it spawns a new set of children and continues +serving hits. + +

    Users of the +status module +will notice that the server statistics are +set to zero when a HUP is sent. + +

    Note: If your configuration file has errors in it when +you issue a +restart then your parent will not restart, it will exit with an error. +See below for a method of avoiding this. + +

    USR1 Signal: graceful restart

    + +

    Note: prior to release 1.2b9 this code is quite unstable +and shouldn't be used at all. + +

    The USR1 signal causes the parent process to advise +the children to exit after their current request (or to exit immediately +if they're not serving anything). The parent re-reads its configuration +files and re-opens its log files. As each child dies off the parent +replaces it with a child from the new generation of the +configuration, which begins serving new requests immediately. + +

    This code is designed to always respect the +MaxClients, +MinSpareServers, +and MaxSpareServers settings. +Furthermore, it respects StartServers +in the following manner: if after one second at least StartServers new +children have not been created, then create enough to pick up the slack. +This is to say that the code tries to maintain both the number of children +appropriate for the current load on the server, and respect your wishes +with the StartServers parameter. + +

    Users of the +status module +will notice that the server statistics +are not set to zero when a USR1 is sent. The +code +was written to both minimize the time in which the server is unable to serve +new requests (they will be queued up by the operating system, so they're +not lost in any event) and to respect your tuning parameters. In order +to do this it has to keep the scoreboard used to keep track +of all children across generations. + +

    The status module will also use a G to indicate those +children which are still serving requests started before the graceful +restart was given. + +

    At present there is no way for a log rotation script using +USR1 to know for certain that all children writing the +pre-restart log have finished. We suggest that you use a suitable delay +after sending the USR1 signal before you do anything with the +old log. For example if most of your hits take less than 10 minutes to +complete for users on low bandwidth links then you could wait 15 minutes +before doing anything with the old log. + +

    Note: If your configuration file has errors in it when +you issue a +restart then your parent will not restart, it will exit with an error. +In the case of graceful +restarts it will also leave children running when it exits. (These are +the children which are "gracefully exiting" by handling their last request.) +This will cause problems if you attempt to restart the server -- it will +not be able to bind to its listening ports. Before doing a restart, you +can check the syntax of the configuration files with the -t +command line argument (see Starting +Apache). This still will not guarantee that the server will restart +correctly. To check the semantics of the configuration files as well +as the syntax, you can try starting httpd as a non-root user. If +there are no errors it will attempt to open its sockets and logs and +fail because it's not root (or because the currently running httpd +already has those ports bound). If it fails for any other reason then +it's probably a config file error and the error should be fixed before +issuing the graceful restart. + + +

    Appendix: signals and race conditions

    + +

    Prior to Apache 1.2b9 there were several race conditions +involving the restart and die signals (a simple description of race +condition is: a time-sensitive problem, as in if something happens at just +the wrong time it won't behave as expected). For those architectures that +have the "right" feature set we have eliminated as many as we can. +But it should be noted that there still do exist race conditions on +certain architectures. + +

    Architectures that use an on disk +ScoreBoardFile +have the potential to corrupt their scoreboards. This can result in +the "bind: Address already in use" (after HUP) or +"long lost child came home!" (after USR1). The former is +a fatal error, while the latter just causes the server to lose a scoreboard +slot. So it might be advisable to use graceful restarts, with +an occasional hard restart. These problems are very difficult to work +around, but fortunately most architectures do not require a scoreboard file. +See the ScoreBoardFile documentation for a method to determine if your +architecture uses it. + +

    NEXT and MACHTEN (68k only) have small race +conditions +which can cause a restart/die signal to be lost, but should not cause the +server to do anything otherwise problematic. + + +

    All architectures have a small race condition in each child involving +the second and subsequent requests on a persistent HTTP connection +(KeepAlive). It may exit after reading the request line but before +reading any of the request headers. There is a fix that was discovered +too late to make 1.2. In theory this isn't an issue because the KeepAlive +client has to expect these events because of network latencies and +server timeouts. In practice it doesn't seem to affect anything either +-- in a test case the server was restarted twenty times per second and +clients successfully browsed the site without getting broken images or +empty documents. + + + + diff --git a/APACHE_1_3_12/htdocs/manual/suexec.html b/APACHE_1_3_12/htdocs/manual/suexec.html new file mode 100644 index 0000000000..3d8623df04 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/suexec.html @@ -0,0 +1,518 @@ + + + +Apache suEXEC Support + + + + + +

    Apache suEXEC Support

    + +

    +

      +
    1. CONTENTS
    2. +
    3. What is suEXEC?
    4. +
    5. Before we begin.
    6. +
    7. suEXEC Security Model.
    8. +
    9. Configuring & Installing suEXEC
    10. +
    11. Enabling & Disabling suEXEC
    12. +
    13. Using suEXEC
    14. +
    15. Debugging suEXEC
    16. +
    17. Beware the Jabberwock: Warnings & + Examples
    18. +
    +

    + +

    What is suEXEC?

    +

    +The suEXEC feature -- introduced in Apache 1.2 -- provides +Apache users the ability to run CGI and SSI +programs under user IDs different from the user ID of the calling web-server. +Normally, when a CGI or SSI program executes, it runs as the same user who is +running the web server. +

    + +

    +Used properly, this feature can reduce considerably the security risks involved +with allowing users to develop and run private CGI or SSI programs. However, +if suEXEC is improperly configured, it can cause any number of problems and +possibly create new holes in your computer's security. If you aren't familiar +with managing setuid root programs and the security issues they present, we +highly recommend that you not consider using suEXEC. +

    + +

    +BACK TO CONTENTS +

    + +

    Before we begin.

    +

    +Before jumping head-first into this document, you should be aware of the +assumptions made on the part of the Apache Group and this document. +

    + +

    +First, it is assumed that you are using a UNIX derivate operating system that +is capable of setuid and setgid operations. +All command examples are given in this regard. Other platforms, if they are +capable of supporting suEXEC, may differ in their configuration. +

    + +

    +Second, it is assumed you are familiar with some basic concepts of your +computer's security and its administration. This involves an understanding +of setuid/setgid operations and the various effects they +may have on your system and its level of security. +

    + +

    +Third, it is assumed that you are using an unmodified +version of suEXEC code. All code for suEXEC has been carefully scrutinized and +tested by the developers as well as numerous beta testers. Every precaution +has been taken to ensure a simple yet solidly safe base of code. Altering this +code can cause unexpected problems and new security risks. It is +highly recommended you not alter the suEXEC code unless you +are well versed in the particulars of security programming and are willing to +share your work with the Apache Group for consideration. +

    + +

    +Fourth, and last, it has been the decision of the Apache Group to +NOT make suEXEC part of the default installation of Apache. +To this end, suEXEC configuration requires of the administrator careful +attention to details. After due consideration has been given to the various +settings for suEXEC, the administrator may install suEXEC through normal +installation methods. The values for these settings need to be carefully +determined and specified by the administrator to properly maintain system +security during the use of suEXEC functionality. It is through this detailed +process that the Apache Group hopes to limit suEXEC installation only to those +who are careful and determined enough to use it. +

    + +

    +Still with us? Yes? Good. Let's move on! +

    + +

    +BACK TO CONTENTS +

    + +

    suEXEC Security Model

    +

    +Before we begin configuring and installing suEXEC, we will first discuss +the security model you are about to implement. By doing so, you may +better understand what exactly is going on inside suEXEC and what precautions +are taken to ensure your system's security. +

    + +

    +suEXEC is based on a setuid "wrapper" program that is +called by the main Apache web server. This wrapper is called when an HTTP +request is made for a CGI or SSI program that the administrator has designated +to run as a userid other than that of the main server. When such a request +is made, Apache provides the suEXEC wrapper with the program's name and the +user and group IDs under which the program is to execute. +

    + +

    +The wrapper then employs the following process to determine success or +failure -- if any one of these conditions fail, the program logs the failure +and exits with an error, otherwise it will continue: +

      +
    1. Was the wrapper called with the proper number of + arguments? +
      + The wrapper will only execute if it is given the proper number of arguments. + The proper argument format is known to the Apache web server. If the + wrapper + is not receiving the proper number of arguments, it is either being hacked, + or + there is something wrong with the suEXEC portion of your Apache binary. +
      +
    2. +
    3. Is the user executing this wrapper a valid user of this + system? +
      + This is to ensure that the user executing the wrapper is truly a user of the + system. +
      +
    4. +
    5. Is this valid user allowed to run the wrapper? +
      + Is this user the user allowed to run this wrapper? Only one user (the + Apache user) is allowed to execute this program. +
      +
    6. +
    7. Does the target program have an unsafe hierarchical + reference? +
      + Does the target program contain a leading '/' or have a '..' backreference? + These are not allowed; the target program must reside within the Apache + webspace. +
      +
    8. +
    9. Is the target user name valid? +
      + Does the target user exist? +
      +
    10. +
    11. Is the target group name valid? +
      + Does the target group exist? +
      +
    12. +
    13. Is the target user NOT superuser? +
      + Presently, suEXEC does not allow 'root' to execute CGI/SSI programs. +
      +
    14. +
    15. Is the target userid ABOVE the minimum ID + number? +
      + The minimum user ID number is specified during configuration. This allows + you + to set the lowest possible userid that will be allowed to execute CGI/SSI + programs. This is useful to block out "system" accounts. +
      +
    16. +
    17. Is the target group NOT the superuser group? +
      + Presently, suEXEC does not allow the 'root' group to execute CGI/SSI + programs. +
      +
    18. +
    19. Is the target groupid ABOVE the minimum ID + number? +
      + The minimum group ID number is specified during configuration. This allows + you + to set the lowest possible groupid that will be allowed to execute CGI/SSI + programs. This is useful to block out "system" groups. +
      +
    20. +
    21. Can the wrapper successfully become the target user and + group? +
      + Here is where the program becomes the target user and group via setuid and + setgid + calls. The group access list is also initialized with all of the groups + of which + the user is a member. +
      +
    22. +
    23. Does the directory in which the program resides exist? +
      + If it doesn't exist, it can't very well contain files. +
      +
    24. +
    25. Is the directory within the Apache webspace? +
      + If the request is for a regular portion of the server, is the requested + directory + within the server's document root? If the request is for a UserDir, is + the requested + directory within the user's document root? +
      +
    26. +
    27. Is the directory NOT writable by anyone else? +
      + We don't want to open up the directory to others; only the owner user + may be able + to alter this directories contents. +
      +
    28. +
    29. Does the target program exist? +
      + If it doesn't exists, it can't very well be executed. +
      +
    30. +
    31. Is the target program NOT writable by anyone + else? +
      + We don't want to give anyone other than the owner the ability to + change the program. +
      +
    32. +
    33. Is the target program NOT setuid or setgid? +
      + We do not want to execute programs that will then change our UID/GID again. +
      +
    34. +
    35. Is the target user/group the same as the program's + user/group? +
      + Is the user the owner of the file? +
      +
    36. +
    37. Can we successfully clean the process environment to + ensure safe operations? +
      + suEXEC cleans the process' environment by establishing a safe + execution PATH (defined + during configuration), as well as only passing through those + variables whose names + are listed in the safe environment list (also created during + configuration). +
      +
    38. +
    39. Can we successfully become the target program and + execute? +
      + Here is where suEXEC ends and the target program begins. +
      +
    40. +
    +

    + +

    +This is the standard operation of the the suEXEC wrapper's security model. +It is somewhat stringent and can impose new limitations and guidelines for +CGI/SSI design, but it was developed carefully step-by-step with security +in mind. +

    + +

    +For more information as to how this security model can limit your possibilities +in regards to server configuration, as well as what security risks can be +avoided with a proper suEXEC setup, see the +"Beware the Jabberwock" +section of this document. +

    + +

    +BACK TO CONTENTS +

    + +

    Configuring & Installing suEXEC

    +

    +Here's where we begin the fun. If you use Apache 1.2 or prefer to configure +Apache 1.3 with the "src/Configure" script you have to edit +the suEXEC header file and install the binary in its proper location +manually. This procedure is described in an +extra document. +The following sections describe the configuration and installation +for Apache 1.3 with the AutoConf-style interface (APACI). +

    + +

    +APACI's suEXEC configuration options
    +

    +
    --enable-suexec +
    This option enables the suEXEC feature which is never installed or + activated by default. At least one --suexec-xxxxx option has to be + provided together with the --enable-suexec option to let APACI + accept your request for using the suEXEC feature. +
    --suexec-caller=UID +
    The username under which + Apache normally runs. + This is the only user allowed to execute this program. +
    --suexec-docroot=DIR +
    Define as the DocumentRoot set for Apache. + This will be the only hierarchy (aside from UserDirs) + that can be used for suEXEC behavior. + The default directory is the --datadir value with + the suffix "/htdocs", e.g. if you configure with + "--datadir=/home/apache" the directory + "/home/apache/htdocs" is used as document root for + the suEXEC wrapper. +
    --suexec-logfile=FILE +
    This defines the filename to which all suEXEC transactions and + errors are logged (useful for auditing and debugging purposes). + By default the logfile is named "suexec_log" and located in your + standard logfile directory (--logfiledir). +
    --suexec-userdir=DIR +
    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. + Default value is "public_html". +
    + If you have virtual hosts 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! +
    --suexec-uidmin=UID +
    Define this as the lowest UID allowed to be a target user + for suEXEC. For most systems, 500 or 100 is common. + Default value is 100. +
    --suexec-gidmin=GID +
    Define this as the lowest GID allowed to be a target group + for suEXEC. For most systems, 100 is common and therefore + used as default value. +
    --suexec-safepath=PATH +
    Define a safe PATH environment to pass to CGI executables. + Default value is "/usr/local/bin:/usr/bin:/bin". +
    +

    + +

    +Checking your suEXEC setup
    +Before you compile and install the suEXEC wrapper you can check +the configuration with the --layout option. +
    +Example output: +

    +    suEXEC setup:
    +            suexec binary: /usr/local/apache/sbin/suexec
    +            document root: /usr/local/apache/share/htdocs
    +           userdir suffix: public_html
    +                  logfile: /usr/local/apache/var/log/suexec_log
    +                safe path: /usr/local/bin:/usr/bin:/bin
    +                caller ID: www
    +          minimum user ID: 100
    +         minimum group ID: 100
    +
    +

    + +

    +Compiling and installing the suEXEC wrapper
    +If you have enabled the suEXEC feature with the --enable-suexec option +the suexec binary (together with Apache itself) is automatically built +if you execute the command "make". +
    +After all components have been built you can execute the command +"make install" to install them. +The binary image "suexec" is installed in the directory defined by +the --sbindir option. Default location is "/usr/local/apache/sbin/suexec". +
    +Please note that you need root privileges for +the installation step. In order for the wrapper to set the user ID, it +must be installed as owner root and must have the +setuserid execution bit set for file modes. +

    + +

    +BACK TO CONTENTS +

    + +

    Enabling & Disabling suEXEC

    +

    +Upon startup of Apache, it looks for the file "suexec" in the "sbin" +directory (default is "/usr/local/apache/sbin/suexec"). +If Apache finds a properly configured suEXEC wrapper, it will print +the following message to the error log: +

    +    [notice] suEXEC mechanism enabled (wrapper: /path/to/suexec)
    +
    +If you don't see this message at server startup, the server is most +likely not finding the wrapper program where it expects it, or the +executable is not installed setuid root. +
    +If you want to enable the suEXEC mechanism for the first time +and an Apache server is already running you must kill and restart Apache. +Restarting it with a simple HUP or USR1 signal will not be enough. +
    +If you want to disable suEXEC you should kill and restart Apache after +you have removed the "suexec" file. +

    + +

    +BACK TO CONTENTS +

    + +

    Using suEXEC

    +

    +Virtual Hosts:
    +One way to use the suEXEC wrapper is through the +User and +Group directives in +VirtualHost +definitions. By setting these directives to values different from the +main server user ID, all requests for CGI resources will be executed as +the User and Group defined for that +<VirtualHost>. If only one or +neither of these directives are specified for a +<VirtualHost> then the main +server userid is assumed. +

    +User directories:
    +The suEXEC wrapper can also be used to execute CGI programs as +the user to which the request is being directed. This is accomplished by +using the "~" character prefixing the user +ID for whom execution is desired. +The only requirement needed for this feature to work is for CGI +execution to be enabled for the user and that the script must meet the +scrutiny of the security checks above. + +

    +BACK TO CONTENTS +

    + +

    Debugging suEXEC

    +

    +The suEXEC wrapper will write log information to the file defined +with the --suexec-logfile option as indicated above. If you feel you have +configured and installed the wrapper properly, have a look at this log +and the error_log for the server to see where you may have gone astray. +

    + +

    +BACK TO CONTENTS +

    + +

    +Beware the Jabberwock: Warnings & Examples +

    +

    +NOTE! This section may not be complete. For the latest +revision of this section of the documentation, see the Apache Group's +Online Documentation +version. +

    + +

    +There are a few points of interest regarding the wrapper that can cause +limitations on server setup. Please review these before submitting any +"bugs" regarding suEXEC. +

      +
    • suEXEC Points Of Interest
    • +
    • Hierarchy limitations +
      + For security and efficiency reasons, all suexec requests must + remain within either a top-level document root for virtual + host requests, or one top-level personal document root for + userdir requests. For example, if you have four VirtualHosts + configured, you would need to structure all of your VHosts' + document roots off of one main Apache document hierarchy to + take advantage of suEXEC for VirtualHosts. (Example forthcoming.) +
      +
    • +
    • suEXEC's PATH environment variable +
      + This can be a dangerous thing to change. Make certain every + path you include in this define is a trusted + directory. You don't want to open people up to having someone + from across the world running a trojan horse on them. +
      +
    • +
    • Altering the suEXEC code +
      + Again, this can cause Big Trouble if you try + this without knowing what you are doing. Stay away from it + if at all possible. +
      +
    • +
    + +

    +BACK TO CONTENTS +

    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/suexec_1_2.html b/APACHE_1_3_12/htdocs/manual/suexec_1_2.html new file mode 100644 index 0000000000..05346ec7d0 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/suexec_1_2.html @@ -0,0 +1,191 @@ + + + +Apache suEXEC Support + + + + + +

    Configuring & Installing suEXEC

    +

    +This section describes the configuration and installation of +the suEXEC feature with the "src/Configure" script. +
    +(If you use Apache 1.3 you may want to use the Apache +AutoConf-style interface (APACI) which is described in the +main suEXEC document). +

    + +

    +EDITING THE SUEXEC HEADER FILE
    +- From the top-level of the Apache source tree, type:   +cd support [ENTER] +

    + +

    +Edit the suexec.h file and change the following macros to +match your local Apache installation. +

    + +

    +From support/suexec.h +

    +     /*
    +      * HTTPD_USER -- Define as the username under which Apache normally
    +      *               runs.  This is the only user allowed to execute
    +      *               this program.
    +      */
    +     #define HTTPD_USER "www"
    +
    +     /*
    +      * UID_MIN -- Define this as the lowest UID allowed to be a target user
    +      *            for suEXEC.  For most systems, 500 or 100 is common.
    +      */
    +     #define UID_MIN 100
    +
    +     /*
    +      * GID_MIN -- Define this as the lowest GID allowed to be a target group
    +      *            for suEXEC.  For most systems, 100 is common.
    +      */
    +     #define GID_MIN 100
    +
    +     /*
    +      * 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.
    +      */
    +     #define USERDIR_SUFFIX "public_html"
    +
    +     /*
    +      * LOG_EXEC -- Define this as a filename if you want all suEXEC
    +      *             transactions and errors logged for auditing and
    +      *             debugging purposes.
    +      */
    +     #define LOG_EXEC "/usr/local/apache/logs/cgi.log" /* Need me? */
    +
    +     /*
    +      * 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.
    +      */
    +     #define DOC_ROOT "/usr/local/apache/htdocs"
    +
    +     /*
    +      * SAFE_PATH -- Define a safe PATH environment to pass to CGI executables.
    +      *
    +      */
    +     #define SAFE_PATH "/usr/local/bin:/usr/bin:/bin"
    +
    +

    + +

    +COMPILING THE SUEXEC WRAPPER
    +You now need to compile the suEXEC wrapper. At the shell command prompt, +after compiling Apache, +type:  make suexec[ENTER]. +This should create the suexec wrapper executable. +

    + +

    +COMPILING APACHE FOR USE WITH SUEXEC
    +By default, Apache is compiled to look for the suEXEC wrapper in the following +location. +

    + +

    +From src/include/httpd.h +

    +     /* The path to the suExec wrapper, can be overridden in Configuration */
    +     #ifndef SUEXEC_BIN
    +     #define SUEXEC_BIN  HTTPD_ROOT "/sbin/suexec"
    +     #endif
    +
    +

    + +

    +If your installation requires location of the wrapper program in a different +directory, either add +-DSUEXEC_BIN=\"</your/path/to/suexec>\" +to your CFLAGS (or edit src/include/httpd.h) and recompile your Apache server. +See Compiling and Installing Apache +(and the INSTALL file in the source distribution) +for more info on this process. +

    + +

    +COPYING THE SUEXEC BINARY TO ITS PROPER LOCATION
    +Copy the suexec executable created in the +exercise above to the defined location for SUEXEC_BIN. +

    + +

    +cp suexec /usr/local/apache/sbin/suexec [ENTER] +

    + +

    +In order for the wrapper to set the user ID, it must be installed as owner +root and must have the setuserid execution bit +set for file modes. If you are not running a root +user shell, do so now and execute the following commands. +

    + +

    +chown root /usr/local/apache/sbin/suexec [ENTER] +
    +chmod 4711 /usr/local/apache/sbin/suexec [ENTER] +

    + +

    Enabling & Disabling suEXEC

    +

    +After properly installing the suexec wrapper +executable, you must kill and restart the Apache server. A simple +kill -1 `cat httpd.pid` will not be enough. +Upon startup of the web-server, if Apache finds a properly configured +suexec wrapper, it will print the following message to +the console (Apache 1.2): +

    +    Configuring Apache for use with suexec wrapper.
    +
    +If you use Apache 1.3 the following message is printed to the +error log: +
    +    [notice] suEXEC mechanism enabled (wrapper: /path/to/suexec)
    +
    +

    +

    +If you don't see this message at server startup, the server is most +likely not finding the wrapper program where it expects it, or the +executable is not installed setuid root. Check +your installation and try again. +

    + +

    +BACK TO MAIN PAGE +

    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/unixware.html b/APACHE_1_3_12/htdocs/manual/unixware.html new file mode 100644 index 0000000000..a77a3b5cd4 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/unixware.html @@ -0,0 +1,62 @@ + + + +Compiling Apache under UnixWare + + + + + + +

    Compiling Apache under UnixWare

    + +To compile a working copy of Apache under UnixWare, there are several other +steps you may need to take. These prevent such problems as zombie processes, +bind errors, and accept errors, to name a few. + +

    UnixWare 1.x

    + +Make sure that USE_FCNTL_SERIALIZE_ACCEPT is defined (if not +defined by Apache autoconfiguration). If using the UnixWare cc +compiler, and you still see accept() errors, don't use compiler optimization, +or get gcc. + +

    UnixWare 2.0.x

    + +SCO patch tf2163 is required +in order for Apache to work correctly on UnixWare 2.0.x. See +http://www.sco.com +for UnixWare patch information.

    + +In addition, make sure that USE_FCNTL_SERIALIZE_ACCEPT is defined (if not +defined by Apache autoconfiguration). To reduce instances of connections +in FIN_WAIT_2 state, you may also want to define NO_LINGCLOSE (Apache 1.2 +only). + +

    UnixWare 2.1.x

    + +SCO patch ptf3123 is required +in order for Apache to work correctly on UnixWare 2.1.x. See +http://www.sco.com +for UnixWare patch information.

    + +NOTE: Unixware 2.1.2 and later already have patch ptf3123 +included

    + +In addition, make sure that USE_FCNTL_SERIALIZE_ACCEPT is defined (if not +defined by Apache autoconfiguration). To reduce instances of connections +in FIN_WAIT_2 state, you may also want to define NO_LINGCLOSE (Apache 1.2 +only).

    + +Thanks to Joe Doupnik <JRD@cc.usu.edu> and Rich Vaughn +<rvaughn@aad.com> for additional info for UnixWare builds.

    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/upgrading_to_1_3.html b/APACHE_1_3_12/htdocs/manual/upgrading_to_1_3.html new file mode 100644 index 0000000000..395a4799fe --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/upgrading_to_1_3.html @@ -0,0 +1,302 @@ + + +Upgrading to 1.3 from 1.2 + + + + + +

    Upgrading to 1.3 from 1.2

    + +

    In order to assist folks upgrading we are now going to maintain a +document describing information critical to existing Apache users. Note +that it only lists differences between recent major releases, so +for example, folks using Apache 1.1 or earlier will have to figure out +what changed up to Apache 1.2 before this document can be considered +relevant. Old users could look at the src/CHANGES file +which tracks code changes. + +

    These are intended to be brief notes, and you should be able to find +more information in either the New Features +document, or in the src/CHANGES file. + +

    Compile-Time Configuration Changes

    + +
      +
    • The source code has been reorganized, + which affects anyone with custom modules or modifications. But also, + the Module directive has been changed to the + AddModule directive. + +
    • The Configuration variable EXTRA_LFLAGS has + been renamed EXTRA_LDFLAGS. + +
    • The -DMAXIMUM_DNS definition has been obsoleted by + changes to mod_access enforcing double-reverse DNS lookups + when necessary. + +
    • The -DSERVER_SUBVERSION=\"string\" compile-time option has + been replaced with the run-time API call + ap_add_version_component(). Compile-time modification of the + server identity by the configuration scripts is no longer supported. +
    • + +
    • mod_dir has been split into two pieces + mod_autoindex, and + mod_dir. + +
    • mod_browser has been + replaced by mod_setenvif. + +
    • IRIX systems with untrusted users who can write CGIs which execute + as the same uid as httpd should consider using suexec, + or adding -DUSE_FCNTL_SERIALIZED_ACCEPT to + EXTRA_CFLAGS. This is slower, more information is available + on the performance tuning + page. There is a mild denial of service attack possible with the + default config, but the default config is an order of magnitude faster. + +
    • mod_auth_msql has been removed from the distribution. + +
    • The new Apache Autoconf-style Interface (APACI) was added to + the top-level to provide a real out-of-the-box build and installation + procedure for the complete Apache package. +
    + +

    Run-Time Configuration Changes

    + +
      +
    • There have been numerous changes to the default config files. + Ensure that you compare your existing configuration files with the + new ones to ensure there aren't any undesired differences. In + particular: +
        +
      • As of Apache 1.3.0, the current config files apply different + Options and + AllowOverride settings to + various directories than were used in 1.2. +
      • +
      • As of the release following Apache 1.3.3, the three + config file templates have been merged into httpd.conf-dist + and the order of the directives changed. +
      • +
      +
    • As of 1.3.2, mod_expires + will add Expires headers to content that does not come from a file + on disk, unless you are using a modification time based setting. + Previously, it would never add an Expires header unless content came + from a file on disk. This could result in Expires headers being added + in places where they were not previously added. +
    • Standalone FancyIndexing directives + are now combined with the settings of any IndexOptions + directive already in effect, rather than replacing them. +
    • +
    • AuthName strings will need to be quoted + in .htaccess or server configuration files if they contain + blank characters (like spaces). For example, if you use + an AuthName directive like this: +

      +

      +     AuthName This and That
      +    
      +

      + you will need to change it to +

      +

      +     AuthName "This and That"
      +    
      +

      + This change was made for consistency in the config language. +
    • As of Apache 1.3.1, methods listed in <Limit> + directives must be uppercase. Method names, such as + GET, POST, and PUT are + defined as being case-sensitive. That is, a GET + request is different from a get request. Prior + to Apache 1.3.1, the <Limit> directive + parser incorrectly treated both of these as being the same. + Apache's built-in method limit processing currently only understands + uppercase method names, so if you've used clauses such as + "<Limit Get post>" in your configuration + files, you need to correct them to use uppercase names. +

      + Unrecognized method names in the server configuration files will + result in the server logging an error message and failing to start. + In .htaccess files, unknown methods will cause the + server to log an error to its error log and return an 'Internal + Server Error' page to the client. +

      +
    • +
    • The default Apache ServerRoot directory changed + from the NCSA-compatible /usr/local/etc/httpd/ to + /usr/local/apache/. This change covers only the default + setting (and the documentation); it is of course possible to override it + using the -d ServerRoot and -f httpd.conf switches + when starting apache. + +
    • Folks using HTTP/1.1-style virtual hosting will need to list the + ip:port pairs that are supposed to have HTTP/1.1-style virtual hosting + via the + NameVirtualHost directive (one directive per pair). + Previously this support was given implicitly on the "main server + address". Now it has to be explicitly listed so as to avoid many + problems that users had. + Please see the Apache Virtual Host + documentation for further details on configuration. + +
    • The precedence of virtual hosts has been reversed (applies mainly to + vhosts using HTTP/1.1 Host: headers, and the + ServerPath directive). Now + the earlier vhosts in the file have precedence over the later vhosts. + +
    • HostnameLookups defaults to Off. + +
    • REMOTE_HOST CGI variable changed. + In Apache 1.2 and earlier, the REMOTE_HOST environment + variable made available to CGI scripts was set to either the + full DNS name of the client, or else to the client's IP address + if the name was not known. This behaviour differed from that + specified by the CGI specification, which defines this variable as being + NULL if the name isn't known. In Apache 1.3, we have made this correction. + REMOTE_ADDR always contains the client's IP address, + but REMOTE_HOST is only defined when the server has + been able to determine the client's DNS name. +
    • + +
    • The undocumented + mod_access + syntax "allow user-agents" was removed. The replacement is the + more general "allow from env". + +
    • When using wildcards in pathnames (such as * and ?) they no longer + match / (slash). That is, they more closely behave how a UNIX shell + behaves. This affects <Directory> directives, + for example. + +
    • If no TransferLog directive is given then nothing will + be logged. + (Previously it would default to logs/access_log.) + +
    • Apache now has configurable error + logging levels, and the default eliminates some messages that + earlier versions always generated. + +
    • 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. + +
    • <Files> sections previously could take a full pathname, and + were matched against the full pathnames. This had some + inconsistencies, and was removed. To emulate this older behaviour + use a <Files> section nested inside a <Directory> + section. + +
    • <Location> matching behaviour with respect to slashes has + changed. See the <Location> + documentation for more info. + +
    + +

    Misc Changes

    + +
      +
    • ServerType inetd has been deprecated. It still exists, + but bugs are unlikely to be fixed. + +
    • httpd_monitor has been deprecated. The replacement is + to use mod_status and make a request to a URL such as + http://myhost/server-status?refresh=10. + +
    • + 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". + +

    • + dbmmanage has been overhauled. + +
    + +

    Third Party Modules

    + +

    The following changes between the 1.2 and 1.3 API may require slight +changes in third party modules not maintained by Apache. + +

      +
    • + To avoid symbol clashes with third-party code compiled into the server, the + general prefix `ap_' was globally applied to the following + classes of symbols: Apache provided general functions (e.g., + ap_cpystrn), public API functions (e.g., + palloc, + bgets) and private functions which can't be made static + (because of cross-object usage) but should be (e.g., + new_connection). For backward source compatibility with + Apache 1.2 a new header file named compat.h was created which + provides defines for the old symbol names. + You'll either have to #include compat.h or update the API + symbols you use. +
    • +
    • + Be sure and examine the source code + reorganization page to see whether any item there affects you. +
    • + +
    • Use of SERVER_VERSION definition. If third-party + modules reference the server version string using this symbol, + they should be corrected to obtain it by calling the new API routine + const char *ap_get_server_version(). +
    • + +
    • ap_construct_url prototype change. The second parameter + was previously a server_rec, it has been changed to + a request_rec. + +
    • The table datatype has been made an opaque type. + Code which assumes a table is the same as an + array_header will not compile. This is actually a + change to enforce the API the way it was intended, all versions + of Apache have had a table_elts() function which + is intended for code which needs to access the elements of + a table. The changes required for this are pretty easy, and + work with all versions of Apache. + +

      Suppose t is a table. Whenever code refers to + t->elts, replace it with something like this: + +

      +    array_header *arr = table_elts(t);
      +    table_entry *elts = (table_entry *)arr->elts;
      +
      + + Whenever code refers to t->nelts use + arr->nelts. Many examples can be found in + the standard modules, search for table_elts. +
    • + +
    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/vhosts/details.html b/APACHE_1_3_12/htdocs/manual/vhosts/details.html new file mode 100644 index 0000000000..f14bd088a5 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/vhosts/details.html @@ -0,0 +1,373 @@ + + +An In-Depth Discussion of Virtual Host Matching + + + + + +

    An In-Depth Discussion of Virtual Host Matching

    + +

    The virtual host code was completely rewritten in +Apache 1.3. +This document attempts to explain exactly what Apache does when +deciding what virtual host to serve a hit from. With the help of the +new NameVirtualHost +directive virtual host configuration should be a lot easier and safer +than with versions prior to 1.3. + +

    If you just want to make it work without understanding +how, here are some examples. + +

    Config File Parsing

    + +

    There is a main_server which consists of all +the definitions appearing outside of <VirtualHost> sections. +There are virtual servers, called vhosts, which are defined by +<VirtualHost> +sections. + +

    The directives +Port, +ServerName, +ServerPath, +and +ServerAlias +can appear anywhere within the definition of +a server. However, each appearance overrides the previous appearance +(within that server). + +

    The default value of the Port field for main_server +is 80. The main_server has no default ServerPath, or +ServerAlias. The default ServerName is +deduced from the servers IP address. + +

    The main_server Port directive has two functions due to legacy +compatibility with NCSA configuration files. One function is +to determine the default network port Apache will bind to. This +default is overridden by the existence of any +Listen directives. +The second function is to specify the port number which is used +in absolute URIs during redirects. + +

    Unlike the main_server, vhost ports do not affect what +ports Apache listens for connections on. + +

    Each address appearing in the VirtualHost directive +can have an optional port. If the port is unspecified it defaults to +the value of the main_server's most recent Port statement. +The special port * indicates a wildcard that matches any port. +Collectively the entire set of addresses (including multiple +A record +results from DNS lookups) are called the vhost's address set. + +

    Unless a NameVirtualHost +directive is used for a specific IP address the first vhost with +that address is treated as an IP-based vhost. + +

    If name-based vhosts should be used a NameVirtualHost +directive must appear with the IP address set to be used for the +name-based vhosts. In other words, you must specify the IP address that +holds the hostname aliases (CNAMEs) for your name-based vhosts via a +NameVirtualHost directive in your configuration file. + +

    Multiple NameVirtualHost directives can be used each +with a set of VirtualHost directives but only one +NameVirtualHost directive should be used for each +specific IP:port pair. + +

    The ordering of NameVirtualHost and +VirtualHost directives is not important which makes the +following two examples identical (only the order of the +VirtualHost directives for one address set +is important, see below): + +

    +                                |
    +  NameVirtualHost 111.22.33.44  | <VirtualHost 111.22.33.44>
    +  <VirtualHost 111.22.33.44>    | # server A
    +  # server A  		        | </VirtualHost>
    +  ... 			        | <VirtualHost 111.22.33.55>
    +  </VirtualHost>	        | # server C
    +  <VirtualHost 111.22.33.44>    | ...
    +  # server B  		        | </VirtualHost>
    +  ... 			        | <VirtualHost 111.22.33.44>
    +  </VirtualHost>	        | # server B
    +                                | ...
    +  NameVirtualHost 111.22.33.55  | </VirtualHost>
    +  <VirtualHost 111.22.33.55>    | <VirtualHost 111.22.33.55>
    +  # server C  		        | # server D
    +  ... 			        | ...
    +  </VirtualHost>	        | </VirtualHost>
    +  <VirtualHost 111.22.33.55>    |
    +  # server D  		        | NameVirtualHost 111.22.33.44
    +  ... 			        | NameVirtualHost 111.22.33.55
    +  </VirtualHost>	        |
    +                                |
    +
    + +

    (To aid the readability of your configuration you should prefer the +left variant.) + +

    After parsing the VirtualHost directive, the vhost server +is given a default Port equal to the port assigned to the +first name in its VirtualHost directive. + +

    The complete list of names in the VirtualHost directive +are treated just like a ServerAlias (but are not overridden by any +ServerAlias statement) if all names resolve to the same address +set. Note that subsequent Port statements for this vhost will not +affect the ports assigned in the address set. + +

    During initialization a list for each IP address +is generated and inserted into an hash table. If the IP address is +used in a NameVirtualHost directive the list contains +all name-based vhosts for the given IP address. If there are no +vhosts defined for that address the NameVirtualHost directive +is ignored and an error is logged. For an IP-based vhost the list in the +hash table is empty. + +

    Due to a fast hashing function the overhead of hashing an IP address +during a request is minimal and almost not existent. Additionally +the table is optimized for IP addresses which vary in the last octet. + +

    For every vhost various default values are set. In particular: + +

      +
    1. If a vhost has no + ServerAdmin, + ResourceConfig, + AccessConfig, + Timeout, + KeepAliveTimeout, + KeepAlive, + MaxKeepAliveRequests, + or + SendBufferSize + directive then the respective value is + inherited from the main_server. (That is, inherited from whatever + the final setting of that value is in the main_server.) + +
    2. The "lookup defaults" that define the default directory + permissions + for a vhost are merged with those of the main_server. This includes + any per-directory configuration information for any module. + +
    3. The per-server configs for each module from the main_server are + merged into the vhost server. +
    + +Essentially, the main_server is treated as "defaults" or a +"base" on which to build each vhost. +But the positioning of these main_server +definitions in the config file is largely irrelevant -- the entire +config of the main_server has been parsed when this final merging occurs. +So even if a main_server definition appears after a vhost definition +it might affect the vhost definition. + +

    If the main_server has no ServerName at this point, +then the hostname of the machine that httpd is running on is used +instead. We will call the main_server address set those IP +addresses returned by a DNS lookup on the ServerName of +the main_server. + +

    For any undefined ServerName fields, a name-based vhost +defaults to the address given first in the VirtualHost +statement defining the vhost. + +

    Any vhost that includes the magic _default_ wildcard +is given the same ServerName as the main_server. + + +

    Virtual Host Matching

    + +

    The server determines which vhost to use for a request as follows: + +

    Hash table lookup

    + +

    When the connection is first made by a client, the IP address to +which the client connected is looked up in the internal IP hash table. + +

    If the lookup fails (the IP address wasn't found) the request is +served from the _default_ vhost if there is such a vhost +for the port to which the client sent the request. If there is no +matching _default_ vhost the request is served from the +main_server. + +

    If the lookup succeeded (a corresponding list for the IP address was +found) the next step is to decide if we have to deal with an IP-based +or a name-base vhost. + +

    IP-based vhost

    + +

    If the entry we found has an empty name list then we have found an +IP-based vhost, no further actions are performed and the request is +served from that vhost. + +

    Name-based vhost

    + +

    If the entry corresponds to a name-based vhost the name list contains +one or more vhost structures. This list contains the vhosts in the same +order as the VirtualHost directives appear in the config +file. + +

    The first vhost on this list (the first vhost in the config file with +the specified IP address) has the highest priority and catches any request +to an unknown server name or a request without a Host: +header field. + +

    If the client provided a Host: header field the list is +searched for a matching vhost and the first hit on a ServerName +or ServerAlias is taken and the request is served from +that vhost. A Host: header field can contain a port number, but +Apache always matches against the real port to which the client sent +the request. + +

    If the client submitted a HTTP/1.0 request without Host: +header field we don't know to what server the client tried to connect and +any existing ServerPath is matched against the URI +from the request. The first matching path on the list is used and the +request is served from that vhost. + +

    If no matching vhost could be found the request is served from the +first vhost with a matching port number that is on the list for the IP +to which the client connected (as already mentioned before). + +

    Persistent connections

    +The IP lookup described above is only done once for a particular +TCP/IP session while the name lookup is done on every request +during a KeepAlive/persistent connection. In other words a client may +request pages from different name-based vhosts during a single +persistent connection. + + +

    Absolute URI

    + +

    If the URI from the request is an absolute URI, and its hostname and +port match the main server or one of the configured virtual hosts +and match the address and port to which the client sent the request, +then the scheme/hostname/port prefix is stripped off and the remaining +relative URI is served by the corresponding main server or virtual host. +If it does not match, then the URI remains untouched and the request is +taken to be a proxy request. + + +

    Observations

    + +
      + +
    • A name-based vhost can never interfere with an IP-base vhost and + vice versa. IP-based vhosts can only be reached through an IP address + of its own address set and never through any other address. + The same applies to name-based vhosts, they can only be reached + through an IP address of the corresponding address set which must + be defined with a NameVirtualHost directive. +

      + +

    • ServerAlias and ServerPath checks are never + performed for an IP-based vhost. +

      + +

    • The order of name-/IP-based, the _default_ + vhost and the NameVirtualHost directive within the config + file is not important. Only the ordering + of name-based vhosts for a specific address set is significant. The one + name-based vhosts that comes first in the configuration file has + the highest priority for its corresponding address set. +

      + +

    • For security reasons the port number given in a Host: + header field is never used during the matching process. Apache always + uses the real port to which the client sent the request. +

      + +

    • If a ServerPath directive exists which is a prefix of + another ServerPath directive that appears later in + the configuration file, then the former will always be matched + and the latter will never be matched. (That is assuming that no + Host: header field was available to disambiguate the two.) +

      + +

    • If two IP-based vhosts have an address in common, the vhost appearing + first in the config file is always matched. Such a thing might happen + inadvertently. The server will give a warning in the error + logfile when it detects this. +

      + +

    • A _default_ vhost catches a request only if there is no + other vhost with a matching IP address and a matching port + number for the request. The request is only caught if the port number + to which the client sent the request matches the port number of your + _default_ vhost which is your standard Port + by default. A wildcard port can be specified (i.e., + _default_:*) to catch requests to any available port. +

      + +

    • The main_server is only used to serve a request if the IP address + and port number to which the client connected is unspecified + and does not match any other vhost (including a _default_ + vhost). In other words the main_server only catches a request for an + unspecified address/port combination (unless there is a + _default_ vhost which matches that port). +

      + +

    • A _default_ vhost or the main_server is never + matched for a request with an unknown or missing Host: header + field if the client connected to an address (and port) which is used + for name-based vhosts, e.g., in a NameVirtualHost + directive. +

      + +

    • You should never specify DNS names in VirtualHost + directives because it will force your server to rely on DNS to boot. + Furthermore it poses a security threat if you do not control the + DNS for all the domains listed. + There's more information + available on this and the next two topics. +

      + +

    • ServerName should always be set for each vhost. Otherwise + A DNS lookup is required for each vhost. +

      + +

    + +

    Tips

    + +

    In addition to the tips on the DNS +Issues page, here are some further tips: + +

      + +
    • Place all main_server definitions before any VirtualHost + definitions. (This is to aid the readability of the configuration -- + the post-config merging process makes it non-obvious that definitions + mixed in around virtual hosts might affect all virtual hosts.) +

      + +

    • Group corresponding NameVirtualHost and + VirtualHost definitions in your configuration to ensure + better readability. +

      + +

    • Avoid ServerPaths which are prefixes of other + ServerPaths. If you cannot avoid this then you have to + ensure that the longer (more specific) prefix vhost appears earlier in + the configuration file than the shorter (less specific) prefix + (i.e., "ServerPath /abc" should appear after + "ServerPath /abc/def"). +

      + +

    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/vhosts/details_1_2.html b/APACHE_1_3_12/htdocs/manual/vhosts/details_1_2.html new file mode 100644 index 0000000000..23d8e919a1 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/vhosts/details_1_2.html @@ -0,0 +1,396 @@ + + +An In-Depth Discussion of VirtualHost Matching + + + + + +

    An In-Depth Discussion of VirtualHost Matching

    + +

    This is a very rough document that was probably out of date the moment +it was written. It attempts to explain exactly what the code does when +deciding what virtual host to serve a hit from. It's provided on the +assumption that something is better than nothing. The server version +under discussion is Apache 1.2. + +

    If you just want to "make it work" without understanding +how, there's a What Works section at the bottom. + +

    Config File Parsing

    + +

    There is a main_server which consists of all the definitions appearing +outside of VirtualHost sections. There are virtual servers, +called vhosts, which are defined by +VirtualHost +sections. + +

    The directives +Port, +ServerName, +ServerPath, +and +ServerAlias +can appear anywhere within the definition of +a server. However, each appearance overrides the previous appearance +(within that server). + +

    The default value of the Port field for main_server +is 80. The main_server has no default ServerName, +ServerPath, or ServerAlias. + +

    In the absence of any +Listen +directives, the (final if there +are multiple) Port directive in the main_server indicates +which port httpd will listen on. + +

    The Port and ServerName directives for +any server main or virtual are used when generating URLs such as during +redirects. + +

    Each address appearing in the VirtualHost directive +can have an optional port. If the port is unspecified it defaults to +the value of the main_server's most recent Port statement. +The special port * indicates a wildcard that matches any port. +Collectively the entire set of addresses (including multiple +A record +results from DNS lookups) are called the vhost's address set. + +

    The magic _default_ address has significance during +the matching algorithm. It essentially matches any unspecified address. + +

    After parsing the VirtualHost directive, the vhost server +is given a default Port equal to the port assigned to the +first name in its VirtualHost directive. The complete +list of names in the VirtualHost directive are treated +just like a ServerAlias (but are not overridden by any +ServerAlias statement). Note that subsequent Port +statements for this vhost will not affect the ports assigned in the +address set. + +

    +All vhosts are stored in a list which is in the reverse order that +they appeared in the config file. For example, if the config file is: + +

    +    <VirtualHost A>
    +    ...
    +    </VirtualHost>
    +
    +    <VirtualHost B>
    +    ...
    +    </VirtualHost>
    +
    +    <VirtualHost C>
    +    ...
    +    </VirtualHost>
    +
    + +Then the list will be ordered: main_server, C, B, A. Keep this in mind. + +

    +After parsing has completed, the list of servers is scanned, and various +merges and default values are set. In particular: + +

      +
    1. If a vhost has no + ServerAdmin, + ResourceConfig, + AccessConfig, + Timeout, + KeepAliveTimeout, + KeepAlive, + MaxKeepAliveRequests, + or + SendBufferSize + directive then the respective value is + inherited from the main_server. (That is, inherited from whatever + the final setting of that value is in the main_server.) + +
    2. The "lookup defaults" that define the default directory + permissions + for a vhost are merged with those of the main server. This includes + any per-directory configuration information for any module. + +
    3. The per-server configs for each module from the main_server are + merged into the vhost server. +
    + +Essentially, the main_server is treated as "defaults" or a +"base" on +which to build each vhost. But the positioning of these main_server +definitions in the config file is largely irrelevant -- the entire +config of the main_server has been parsed when this final merging occurs. +So even if a main_server definition appears after a vhost definition +it might affect the vhost definition. + +

    If the main_server has no ServerName at this point, +then the hostname of the machine that httpd is running on is used +instead. We will call the main_server address set those IP +addresses returned by a DNS lookup on the ServerName of +the main_server. + +

    Now a pass is made through the vhosts to fill in any missing +ServerName fields and to classify the vhost as either +an IP-based vhost or a name-based vhost. A vhost is +considered a name-based vhost if any of its address set overlaps the +main_server (the port associated with each address must match the +main_server's Port). Otherwise it is considered an IP-based +vhost. + +

    For any undefined ServerName fields, a name-based vhost +defaults to the address given first in the VirtualHost +statement defining the vhost. Any vhost that includes the magic +_default_ wildcard is given the same ServerName as +the main_server. Otherwise the vhost (which is necessarily an IP-based +vhost) is given a ServerName based on the result of a reverse +DNS lookup on the first address given in the VirtualHost +statement. + +

    + +

    Vhost Matching

    + + +

    Apache 1.3 differs from what is documented +here, and documentation still has to be written. + +

    +The server determines which vhost to use for a request as follows: + +

    find_virtual_server: When the connection is first made +by the client, the local IP address (the IP address to which the client +connected) is looked up in the server list. A vhost is matched if it +is an IP-based vhost, the IP address matches and the port matches +(taking into account wildcards). + +

    If no vhosts are matched then the last occurrence, if it appears, +of a _default_ address (which if you recall the ordering of the +server list mentioned above means that this would be the first occurrence +of _default_ in the config file) is matched. + +

    In any event, if nothing above has matched, then the main_server is +matched. + +

    The vhost resulting from the above search is stored with data +about the connection. We'll call this the connection vhost. +The connection vhost is constant over all requests in a particular TCP/IP +session -- that is, over all requests in a KeepAlive/persistent session. + +

    For each request made on the connection the following sequence of +events further determines the actual vhost that will be used to serve +the request. + +

    check_fulluri: If the requestURI is an absoluteURI, that +is it includes http://hostname/, then an attempt is made to +determine if the hostname's address (and optional port) match that of +the connection vhost. If it does then the hostname portion of the URI +is saved as the request_hostname. If it does not match, then the +URI remains untouched. Note: to achieve this address +comparison, +the hostname supplied goes through a DNS lookup unless it matches the +ServerName or the local IP address of the client's socket. + +

    parse_uri: If the URI begins with a protocol +(i.e., http:, ftp:) then the request is +considered a proxy request. Note that even though we may have stripped +an http://hostname/ in the previous step, this could still +be a proxy request. + +

    read_request: If the request does not have a hostname +from the earlier step, then any Host: header sent by the +client is used as the request hostname. + +

    check_hostalias: If the request now has a hostname, +then an attempt is made to match for this hostname. The first step +of this match is to compare any port, if one was given in the request, +against the Port field of the connection vhost. If there's +a mismatch then the vhost used for the request is the connection vhost. +(This is a bug, see observations.) + +

    +If the port matches, then httpd scans the list of vhosts starting with +the next server after the connection vhost. This scan does not +stop if there are any matches, it goes through all possible vhosts, +and in the end uses the last match it found. The comparisons performed +are as follows: + +

      +
    • Compare the request hostname:port with the vhost + ServerName and Port. + +
    • Compare the request hostname against any and all addresses given in + the VirtualHost directive for this vhost. + +
    • Compare the request hostname against the ServerAlias + given for the vhost. +
    + +

    +check_serverpath: If the request has no hostname +(back up a few paragraphs) then a scan similar to the one +in check_hostalias is performed to match any +ServerPath directives given in the vhosts. Note that the +last match is used regardless (again consider the ordering of +the virtual hosts). + +

    Observations

    + +
      + +
    • It is difficult to define an IP-based vhost for the machine's + "main IP address". You essentially have to create a bogus + ServerName for the main_server that does not match the + machine's IPs. +

      + +

    • During the scans in both check_hostalias and + check_serverpath no check is made that the vhost being + scanned is actually a name-based vhost. This means, for example, that + it's possible to match an IP-based vhost through another address. But + because the scan starts in the vhost list at the first vhost that + matched the local IP address of the connection, not all IP-based vhosts + can be matched. +

      + Consider the config file above with three vhosts A, B, C. Suppose + that B is a named-based vhost, and A and C are IP-based vhosts. If + a request comes in on B or C's address containing a header + "Host: A" then + it will be served from A's config. If a request comes in on A's + address then it will always be served from A's config regardless of + any Host: header. +

      + +
    • Unless you have a _default_ vhost, + it doesn't matter if you mix name-based vhosts in amongst IP-based + vhosts. During the find_virtual_server phase above no + named-based vhost will be matched, so the main_server will remain the + connection vhost. Then scans will cover all vhosts in the vhost list. +

      + If you do have a _default_ vhost, then you cannot place + named-based vhosts after it in the config. This is because on any + connection to the main server IPs the connection vhost will always be + the _default_ vhost since none of the name-based are + considered during find_virtual_server. +

      + +
    • You should never specify DNS names in VirtualHost + directives because it will force your server to rely on DNS to boot. + Furthermore it poses a security threat if you do not control the + DNS for all the domains listed. + There's more information + available on this and the next two topics. +

      + +

    • ServerName should always be set for each vhost. Otherwise + A DNS lookup is required for each vhost. +

      + +

    • A DNS lookup is always required for the main_server's + ServerName (or to generate that if it isn't specified + in the config). +

      + +

    • If a ServerPath directive exists which is a prefix of + another ServerPath directive that appears later in + the configuration file, then the former will always be matched + and the latter will never be matched. (That is assuming that no + Host header was available to disambiguate the two.) +

      + +

    • If a vhost that would otherwise be a name-vhost includes a + Port statement that doesn't match the main_server + Port then it will be considered an IP-based vhost. + Then find_virtual_server will match it (because + the ports associated with each address in the address set default + to the port of the main_server) as the connection vhost. Then + check_hostalias will refuse to check any other name-based + vhost because of the port mismatch. The result is that the vhost + will steal all hits going to the main_server address. +

      + +

    • If two IP-based vhosts have an address in common, the vhost appearing + later in the file is always matched. Such a thing might happen + inadvertently. If the config has name-based vhosts and for some reason + the main_server ServerName resolves to the wrong address + then all the name-based vhosts will be parsed as ip-based vhosts. + Then the last of them will steal all the hits. +

      + +

    • The last name-based vhost in the config is always matched for any hit + which doesn't match one of the other name-based vhosts. + +
    + +

    What Works

    + +

    In addition to the tips on the DNS +Issues page, here are some further tips: + +

      + +
    • Place all main_server definitions before any VirtualHost definitions. +(This is to aid the readability of the configuration -- the post-config +merging process makes it non-obvious that definitions mixed in around +virtualhosts might affect all virtualhosts.) +

      + +

    • Arrange your VirtualHosts such +that all name-based virtual hosts come first, followed by IP-based +virtual hosts, followed by any _default_ virtual host +

      + +

    • Avoid ServerPaths which are prefixes of other +ServerPaths. If you cannot avoid this then you have to +ensure that the longer (more specific) prefix vhost appears earlier in +the configuration file than the shorter (less specific) prefix +(i.e., "ServerPath /abc" should appear after +"ServerPath /abcdef"). +

      + +

    • Do not use port-based vhosts in the same server as +name-based vhosts. A loose definition for port-based is a vhost which +is determined by the port on the server (i.e., one server with +ports 8000, 8080, and 80 - all of which have different configurations). +

      + +

    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/vhosts/examples.html b/APACHE_1_3_12/htdocs/manual/vhosts/examples.html new file mode 100644 index 0000000000..46697bcec4 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/vhosts/examples.html @@ -0,0 +1,512 @@ + + +VirtualHost Examples + + + + + +

    Virtual Host examples for common setups

    + + +

    Base configuration

    + + + +

    Additional features

    + + + +
    + +

    IP-based vhosts only

    + +
      + +
    • Setup 1: + The server machine has two IP addresses (111.22.33.44 + and 111.22.33.55) + which resolve to the names server.domain.tld and + www.otherdomain.tld respectively. + The hostname www.domain.tld is an alias (CNAME) + for server.domain.tld and will represent the + main server. +

      + Server configuration: + + +

      +    ...
      +    Port 80
      +    DocumentRoot /www/domain
      +    ServerName www.domain.tld
      +
      +    <VirtualHost 111.22.33.55>
      +    DocumentRoot /www/otherdomain
      +    ServerName www.otherdomain.tld
      +    ...
      +    </VirtualHost>
      +    
      + www.otherdomain.tld can only be reached through the + address 111.22.33.55, while www.domain.tld + can only be reached through 111.22.33.44 + (which represents our main server). +
      +

      + +

    • Setup 2: + Same as setup 1, but we don't want to have a dedicated main server. +

      + Server configuration: + +

      +    ...
      +    Port 80
      +    ServerName server.domain.tld
      +    
      +    <VirtualHost 111.22.33.44>
      +    DocumentRoot /www/domain
      +    ServerName www.domain.tld
      +    ...
      +    </VirtualHost>
      +
      +    <VirtualHost 111.22.33.55>
      +    DocumentRoot /www/otherdomain
      +    ServerName www.otherdomain.tld
      +    ...
      +    </VirtualHost>
      +    
      + The main server can never catch a request, because all IP addresses + of our machine are in use for IP-based virtual hosts + (only localhost requests can hit the main server). +
      +

      + +

    • Setup 3: + The server machine has two IP addresses (111.22.33.44 + and 111.22.33.55) + which resolve to the names server.domain.tld and + www-cache.domain.tld respectively. + The hostname www.domain.tld is an alias (CNAME) + for server.domain.tld and will represent the + main server. + www-cache.domain.tld will become our proxy-cache + listening on port 8080, while the web server itself uses the default + port 80. +

      + Server configuration: + +

      +    ...
      +    Port 80
      +    Listen 111.22.33.44:80
      +    Listen 111.22.33.55:8080
      +    ServerName server.domain.tld
      +    
      +    <VirtualHost 111.22.33.44:80>
      +    DocumentRoot /www/domain
      +    ServerName www.domain.tld
      +    ...
      +    </VirtualHost>
      +
      +    <VirtualHost 111.22.33.55:8080>
      +    ServerName www-cache.domain.tld
      +    ...
      +      <Directory proxy:>
      +      order deny,allow
      +      deny from all
      +      allow from 111.22.33
      +      </Directory>
      +    </VirtualHost>
      +    
      + The main server can never catch a request, because all IP addresses + (apart from localhost) of our machine are in use for IP-based + virtual hosts. The web server can only be reached on the first address + through port 80 and the proxy only on the second address through port 8080. +
      +
    +
    + +

    Name-based vhosts only

    + +
      + +
    • Setup 1: + The server machine has one IP address (111.22.33.44) + which resolves to the name server.domain.tld. + There are two aliases (CNAMEs) www.domain.tld and + www.sub.domain.tld for the address 111.22.33.44. +

      + Server configuration: + +

      +    ...
      +    Port 80
      +    ServerName server.domain.tld
      +
      +    NameVirtualHost 111.22.33.44 
      +
      +    <VirtualHost 111.22.33.44>
      +    DocumentRoot /www/domain
      +    ServerName www.domain.tld
      +    ...
      +    </VirtualHost>
      +    
      +    <VirtualHost 111.22.33.44>
      +    DocumentRoot /www/subdomain
      +    ServerName www.sub.domain.tld
      +    ...
      +    </VirtualHost> 
      +    
      + Apart from localhost there are no unspecified + addresses/ports, therefore the main server only serves + localhost requests. Due to the fact + that www.domain.tld has the highest priority + it can be seen as the default or + primary server. +
      +

      + +

    • Setup 2: + The server machine has two IP addresses (111.22.33.44 + and 111.22.33.55) + which resolve to the names server1.domain.tld and + server2.domain.tld respectively. + The alias www.domain.tld should be used for the + main server which should also catch any unspecified addresses. + We want to use a virtual host for the alias + www.otherdomain.tld and one virtual host should + catch any request to hostnames of the form + *.sub.domain.tld with www.sub.domain.tld + as its server name. The address 111.22.33.55 should be + used for the virtual hosts. +

      + Server configuration: + +

      +    ...
      +    Port 80
      +    ServerName www.domain.tld
      +    DocumentRoot /www/domain
      +
      +    NameVirtualHost 111.22.33.55
      +
      +    <VirtualHost 111.22.33.55>
      +    DocumentRoot /www/otherdomain
      +    ServerName www.otherdomain.tld
      +    ...
      +    </VirtualHost>
      +   
      +    <VirtualHost 111.22.33.55>
      +    DocumentRoot /www/subdomain
      +    ServerName www.sub.domain.tld
      +    ServerAlias *.sub.domain.tld
      +    ...
      +    </VirtualHost> 
      +    
      + Any request to an address other than 111.22.33.55 + will be served from the main server. A request to + 111.22.33.55 with an unknown or no Host: + header will be served from www.otherdomain.tld. +
      +
    + +
    + +

    Mixed name-/IP-based vhosts

    + +
      + +
    • Setup: + The server machine has three IP addresses (111.22.33.44, + 111.22.33.55 and 111.22.33.66) + which resolve to the names server.domain.tld, + www.otherdomain1.tld and www.otherdomain2.tld + respectively. + The address 111.22.33.44 should we used for a couple + of name-based vhosts and the other addresses for IP-based vhosts. +

      + Server configuration: + +

      +    ...
      +    Port 80
      +    ServerName server.domain.tld
      +
      +    NameVirtualHost 111.22.33.44
      +
      +    <VirtualHost 111.22.33.44>
      +    DocumentRoot /www/domain
      +    ServerName www.domain.tld
      +    ...
      +    </VirtualHost>
      +   
      +    <VirtualHost 111.22.33.44>
      +    DocumentRoot /www/subdomain1
      +    ServerName www.sub1.domain.tld
      +    ...
      +    </VirtualHost> 
      +    
      +    <VirtualHost 111.22.33.44>
      +    DocumentRoot /www/subdomain2
      +    ServerName www.sub2.domain.tld
      +    ...
      +    </VirtualHost> 
      + 
      +    <VirtualHost 111.22.33.55>
      +    DocumentRoot /www/otherdomain1
      +    ServerName www.otherdomain1.tld
      +    ...
      +    </VirtualHost> 
      +    
      +    <VirtualHost 111.22.33.66>
      +    DocumentRoot /www/otherdomain2
      +    ServerName www.otherdomain2.tld
      +    ...
      +    </VirtualHost>     
      +    
      + +
    + +
    + +

    Port-based vhosts

    + +
      + +
    • Setup: + The server machine has one IP address (111.22.33.44) + which resolves to the name www.domain.tld. + If we don't have the option to get another address or alias + for our server we can use port-based vhosts if we need + a virtual host with a different configuration. +

      + Server configuration: + +

      +    ...
      +    Listen 80
      +    Listen 8080
      +    ServerName www.domain.tld
      +    DocumentRoot /www/domain
      +
      +    <VirtualHost 111.22.33.44:8080>
      +    DocumentRoot /www/domain2
      +    ...
      +    </VirtualHost>
      +    
      + A request to www.domain.tld on port 80 is served + from the main server and a request to port 8080 is served from + the virtual host. +
      +
    + +
    + +

    Using _default_ vhosts

    + +
      + +
    • Setup 1: + Catching every request to any unspecified IP address and port, + i.e., an address/port combination that is not used for any other + virtual host. +

      + Server configuration: + +

      +    ...
      +    <VirtualHost _default_:*>
      +    DocumentRoot /www/default
      +    ...
      +    </VirtualHost>
      +    
      + Using such a default vhost with a wildcard port effectively + prevents any request going to the main server.
      + A default vhost never serves a request that was sent to an + address/port that is used for name-based vhosts. If the request + contained an unknown or no Host: header it is + always served from the primary name-based vhost (the + vhost for that address/port appearing first in the configuration + file).
      + You can use + AliasMatch + or + RewriteRule + to rewrite any request to a single information page (or script). +
      +

      + +

    • Setup 2: + Same as setup 1, but the server listens on several ports and + we want to use a second _default_ vhost for port 80. +

      + Server configuration: + +

      +    ...
      +    <VirtualHost _default_:80>
      +    DocumentRoot /www/default80
      +    ...
      +    </VirtualHost>
      +    
      +    <VirtualHost _default_:*>
      +    DocumentRoot /www/default
      +    ...
      +    </VirtualHost>    
      +    
      + The default vhost for port 80 (which must appear before + any default vhost with a wildcard port) catches all requests that + were sent to an unspecified IP address. The main server is + never used to serve a request. +
      +

      + +

    • Setup 3: + We want to have a default vhost for port 80, but no other default vhosts. +

      + Server configuration: + +

      +    ...
      +    <VirtualHost _default_:80>
      +    DocumentRoot /www/default
      +    ...
      +    </VirtualHost>
      +    
      + A request to an unspecified address on port 80 is served from the + default vhost any other request to an unspecified address and port + is served from the main server. +
      + +
    + +
    + +

    Migrating a name-based vhost to an IP-based vhost

    + +
      + +
    • Setup: + The name-based vhost with the hostname + www.otherdomain.tld (from our name-based + example, setup 2) should get its own IP address. + To avoid problems with name servers or proxies who cached the old + IP address for the name-based vhost we want to provide both variants + during a migration phase.
      + The solution is easy, because we can simply add the new IP address + (111.22.33.66) to the VirtualHost directive. +

      + Server configuration: + +

      +    ...
      +    Port 80
      +    ServerName www.domain.tld
      +    DocumentRoot /www/domain
      +
      +    NameVirtualHost 111.22.33.55
      +
      +    <VirtualHost 111.22.33.55 111.22.33.66>
      +    DocumentRoot /www/otherdomain
      +    ServerName www.otherdomain.tld
      +    ...
      +    </VirtualHost>
      +   
      +    <VirtualHost 111.22.33.55>
      +    DocumentRoot /www/subdomain
      +    ServerName www.sub.domain.tld
      +    ServerAlias *.sub.domain.tld
      +    ...
      +    </VirtualHost>
      +    
      + The vhost can now be accessed through the new address (as an IP-based + vhost) and through the old address (as a name-based vhost). +
      + +
    + +
    + +

    Using the ServerPath directive

    + +
      + +
    • Setup: + We have a server with two name-based vhosts. In order to match the correct + virtual host a client must send the correct Host: header. + Old HTTP/1.0 clients do not send such a header and Apache has no clue + what vhost the client tried to reach (and serves the request from + the primary vhost). To provide as much backward compatibility + as possible we create a primary vhost which returns a single page + containing links with an URL prefix to the name-based virtual hosts. +

      + Server configuration: + +

      +    ...
      +    NameVirtualHost 111.22.33.44
      +
      +    <VirtualHost 111.22.33.44>
      +    # primary vhost
      +    DocumentRoot /www/subdomain
      +    RewriteEngine On
      +    RewriteRule ^/.* /www/subdomain/index.html
      +    ...
      +    </VirtualHost>
      +
      +    <VirtualHost 111.22.33.44>
      +    DocumentRoot /www/subdomain/sub1
      +    ServerName www.sub1.domain.tld
      +    ServerPath /sub1/
      +    RewriteEngine On
      +    RewriteRule ^(/sub1/.*) /www/subdomain$1 
      +    ...
      +    </VirtualHost>
      +
      +    <VirtualHost 111.22.33.44>
      +    DocumentRoot /www/subdomain/sub2
      +    ServerName www.sub2.domain.tld
      +    ServerPath /sub2/
      +    RewriteEngine On
      +    RewriteRule ^(/sub2/.*) /www/subdomain$1 
      +    ...
      +    </VirtualHost>
      +    
      + Due to the ServerPath + directive a request to the + URL http://www.sub1.domain.tld/sub1/ is always + served from the sub1-vhost.
      + A request to the URL http://www.sub1.domain.tld/ + is only served from the sub1-vhost if the client sent a correct + Host: header. + If no Host: header is sent the client gets the + information page from the primary host.
      + Please note that there is one oddity: A request to + http://www.sub2.domain.tld/sub1/ is also served from + the sub1-vhost if the client sent no Host: header.
      + The RewriteRule directives are used to make sure that + a client which sent a correct Host: header can use + both URL variants, i.e., with or without URL prefix. +
      + +
    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/vhosts/fd-limits.html b/APACHE_1_3_12/htdocs/manual/vhosts/fd-limits.html new file mode 100644 index 0000000000..6b9d0f93c4 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/vhosts/fd-limits.html @@ -0,0 +1,59 @@ + + + +Apache Server Virtual Host Support + + + + + +

    File Descriptor Limits

    + +

    +When using a large number of Virtual Hosts, Apache may run out of available +file descriptors (sometimes called file handles if each Virtual +Host specifies different log files. +The total number of file descriptors used by Apache is one for each distinct +error log file, one for every other log file directive, plus 10-20 for +internal use. Unix operating systems limit the number of file descriptors that +may be used by a process; the limit is typically 64, and may usually be +increased up to a large hard-limit. +

    +Although Apache attempts to increase the limit as required, this +may not work if: +

      +
    1. Your system does not provide the setrlimit() system call. +
    2. The setrlimit(RLIMIT_NOFILE) call does not function on your system + (such as Solaris 2.3) +
    3. The number of file descriptors required exceeds the hard limit. +
    4. Your system imposes other limits on file descriptors, such as a limit +on stdio streams only using file descriptors below 256. (Solaris 2) +
    + +In the event of problems you can: +
      +
    • Reduce the number of log files; don't specify log files in the VirtualHost +sections, but only log to the main log files. +
    • If you system falls into 1 or 2 (above), then increase the file descriptor +limit before starting Apache, using a script like +
      +#!/bin/sh
      +ulimit -S -n 100
      +exec httpd
      +
    +

    +Please see the +Descriptors and Apache +document containing further details about file descriptor problems and how +they can be solved on your operating system. +

    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/vhosts/footer.html b/APACHE_1_3_12/htdocs/manual/vhosts/footer.html new file mode 100644 index 0000000000..7fe745dcfd --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/vhosts/footer.html @@ -0,0 +1,8 @@ +
    + +

    + Apache HTTP Server Version 1.3 +

    + +Index +Home diff --git a/APACHE_1_3_12/htdocs/manual/vhosts/header.html b/APACHE_1_3_12/htdocs/manual/vhosts/header.html new file mode 100644 index 0000000000..5662300029 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/vhosts/header.html @@ -0,0 +1,6 @@ +
    + [APACHE DOCUMENTATION] +

    + Apache HTTP Server Version 1.3 +

    +
    diff --git a/APACHE_1_3_12/htdocs/manual/vhosts/host.html b/APACHE_1_3_12/htdocs/manual/vhosts/host.html new file mode 100644 index 0000000000..5788676af8 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/vhosts/host.html @@ -0,0 +1,172 @@ + + +Apache non-IP Virtual Hosts + + + + + +

    Apache non-IP Virtual Hosts

    + +See Also: +Virtual Host Support + +
    + +

    What is a Virtual Host

    + +

    The "Virtual Host" refers to the practice of maintaining more than +one server on one machine, as differentiated by their apparent +hostname. For example, it is often desirable for companies sharing a +web server to have their own domains, with web servers accessible as +www.company1.com and www.company2.com, +without requiring the user to know any extra path information.

    + +

    Apache was one of the first servers to support virtual hosts right +out of the box, but since the base HTTP (HyperText +Transport Protocol) standard does not allow any method for the server +to determine the hostname it is being addressed as, Apache's virtual +host support has required a separate IP address for each +server. Documentation on using this approach (which still works very +well) is available. + +

    While the approach described above works, with the available IP +address space growing smaller, and the number of domains increasing, +it is not the most elegant solution, and is hard to implement on some +machines. The HTTP/1.1 protocol contains a method for the +server to identify what name it is being addressed as. Apache 1.1 and +later support this approach as well as the traditional +IP-address-per-hostname method.

    + +

    The benefits of using the new virtual host support is a practically +unlimited number of servers, ease of configuration and use, and +requires no additional hardware or software. The main disadvantage is +that the user's browser must support this part of the protocol. The +latest versions of many browsers (including Netscape Navigator 2.0 and +later) do, but many browsers, especially older ones, do not. This can +cause problems, although a possible solution is addressed below.

    + +

    Using non-IP Virtual Hosts

    + +

    Using the new virtual hosts is quite easy, and superficially looks +like the old method. You simply add to one of the Apache configuration +files (most likely httpd.conf or srm.conf) +code similar to the following:

    +
    +    <VirtualHost www.apache.org>
    +    ServerName www.apache.org
    +    DocumentRoot /usr/web/apache
    +    </VirtualHost>
    +
    + +

    Of course, any additional directives can (and should) be placed +into the <VirtualHost> section. To make this work, +all that is needed is to make sure that the www.apache.org +DNS entry points to the same IP address as the main +server. Optionally, you could simply use that IP address in the +<VirtualHost> entry.

    + +

    Additionally, many servers may wish to be accessible by more than +one name. For example, the Apache server might want to be accessible +as apache.org, or ftp.apache.org, assuming +the IP addresses pointed to the same server. In fact, one might want it +so that all addresses at apache.org were picked up by the +server. This is possible with the ServerAlias +directive, placed inside the <VirtualHost> section. For +example:

    + +
    +    ServerAlias apache.org *.apache.org
    +
    + +

    Note that you can use * and ? as wild-card +characters.

    + +

    You also might need ServerAlias if you are serving local users who +do not always include the domain name. For example, if local users are +familiar with typing "www" or "www.physics" then you will need to add +ServerAlias www www.physics. It isn't possible for the +server to know what domain the client uses for their name resolution +because the client doesn't provide that information in the request.

    + +

    Security Considerations

    + +Apache allows all virtual hosts to be made accessible via the +Host: header through all IP interfaces, even those which +are configured to use different IP interfaces. For example, if the +configuration for www.foo.com contained a virtual host +section for www.bar.com, and www.bar.com was +a separate IP interface, such that +non-Host:-header-supporting browsers can use it, as +before with Apache 1.0. If a request is made to +www.foo.com and the request includes the header +Host: www.bar.com, a page from www.bar.com +will be sent. + +

    + +This is a security concern if you are controlling access to a +particular server based on IP-layer controls, such as from within a +firewall or router. Let's say www.bar.com in the above +example was instead an intra-net server called +private.foo.com, and the router used by foo.com only let +internal users access private.foo.com. Obviously, +Host: header functionality now allows someone who has +access to www.foo.com to get +private.foo.com, if they send a Host: +private.foo.com header. It is important to note that this +condition exists only if you only implement this policy at the IP +layer - all security controls used by Apache (i.e., allow, deny from, etc.) are +consistently respected. + +

    Compatibility with Older Browsers

    + +

    As mentioned earlier, a majority of browsers do not send the +required data for the new virtual hosts to work properly. These +browsers will always be sent to the main server's pages. There is a +workaround, albeit a slightly cumbersome one:

    + +

    To continue the www.apache.org example (Note: Apache's +web server does not actually function in this manner), we might use the +new ServerPath directive in the www.apache.org +virtual host, for example: + +

    +    ServerPath /apache
    +
    +

    What does this mean? It means that a request for any file beginning +with "/apache" will be looked for in the Apache +docs. This means that the pages can be accessed as +http://www.apache.org/apache/ for all browsers, although +new browsers can also access it as +http://www.apache.org/.

    + +

    In order to make this work, put a link on your main server's page +to http://www.apache.org/apache/ (Note: Do not use +http://www.apache.org/ - this would create an endless +loop). Then, in the virtual host's pages, be sure to use either purely +relative links (e.g., "file.html" or +"../icons/image.gif" or links containing the prefacing +/apache/ +(e.g., "http://www.apache.org/apache/file.html" or +"/apache/docs/1.1/index.html").

    + +

    This requires a bit of +discipline, but adherence to these guidelines will, for the most part, +ensure that your pages will work with all browsers, new and old. When +a new browser contacts http://www.apache.org/, they will +be directly taken to the Apache pages. Older browsers will be able to +click on the link from the main server, go to +http://www.apache.org/apache/, and then access the +pages.

    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/vhosts/index.html b/APACHE_1_3_12/htdocs/manual/vhosts/index.html new file mode 100644 index 0000000000..06fcf1d16f --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/vhosts/index.html @@ -0,0 +1,65 @@ + + + +Apache Virtual Host documentation + + + + + +

    Apache Virtual Host documentation

    + +

    The term Virtual Host refers to the practice of maintaining +more than one server on one machine, as differentiated by their apparent +hostname. For example, it is often desirable for companies sharing a +web server to have their own domains, with web servers accessible as +www.company1.com and www.company2.com, +without requiring the user to know any extra path information.

    + +

    Apache was one of the first servers to support IP-based +virtual hosts right out of the box. Versions 1.1 and later of +Apache support both, IP-based and name-based virtual hosts (vhosts). +The latter variant of virtual hosts is sometimes also called host-based or +non-IP virtual hosts.

    + +

    Below is a list of documentation pages which explain all details +of virtual host support in Apache version 1.3 and later.

    + +
    + +

    Virtual Host Support

    + + + +

    Configuration directives

    + + + +

    Folks trying to debug their virtual host configuration may find the +Apache -S command line switch useful. It will dump out a +description of how Apache parsed the configuration file. Careful +examination of the IP addresses and server names may help uncover +configuration mistakes. + + + + diff --git a/APACHE_1_3_12/htdocs/manual/vhosts/ip-based.html b/APACHE_1_3_12/htdocs/manual/vhosts/ip-based.html new file mode 100644 index 0000000000..0e17c824b8 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/vhosts/ip-based.html @@ -0,0 +1,141 @@ + + + +Apache IP-based Virtual Host Support + + + + + +

    Apache IP-based Virtual Host Support

    + +See also: +Name-based Virtual Hosts Support + +
    + +

    System requirements

    +As the term IP-based indicates, the server must have a +different IP address for each IP-based virtual host. +This can be achieved by the machine having several physical network connections, +or by use of virtual interfaces which are supported by most modern +operating systems (see system documentation for details, these are +frequently called "ip aliases", and the "ifconfig" command +is most commonly used to set them up). + +

    How to set up Apache

    +There are two ways of configuring apache to support multiple hosts. +Either by running a separate httpd daemon for each hostname, or by running a +single daemon which supports all the virtual hosts. +

    +Use multiple daemons when: +

      +
    • There are security partitioning issues, such as company1 does not want + anyone at company2 to be able to read their data except via the web. + In this case you would need two daemons, each running with different + User, + Group, + Listen, and + ServerRoot settings. +
    • You can afford the memory and + file descriptor requirements of + listening to every IP alias on the machine. It's only possible to + Listen + to the "wildcard" address, or to specific addresses. So if you have + a need to listen to a specific address for whatever reason, then you + will need to listen to all specific addresses. (Although one httpd + could listen to N-1 of the addresses, and another could listen to + the remaining address.) +
    +Use a single daemon when: +
      +
    • Sharing of the httpd configuration between virtual hosts is acceptable. +
    • The machine services a large number of requests, and so the performance + loss in running separate daemons may be significant. +
    + +

    Setting up multiple daemons

    +Create a separate httpd installation for each virtual host. +For each installation, use the +Listen directive in the configuration +file to select which IP address (or virtual host) that daemon services. +e.g. +
    +    Listen www.smallco.com:80
    +
    +It is recommended that you use an IP address instead of a hostname +(see DNS caveats). + +

    Setting up a single daemon with virtual hosts

    +For this case, a single httpd will service requests for the main server +and all the virtual hosts. +The VirtualHost directive in the + configuration file is used to set the values of +ServerAdmin, +ServerName, +DocumentRoot, +ErrorLog and +TransferLog or +CustomLog +configuration directives to different values for each virtual host. +e.g. +
    +    <VirtualHost www.smallco.com>
    +    ServerAdmin webmaster@mail.smallco.com
    +    DocumentRoot /groups/smallco/www
    +    ServerName www.smallco.com
    +    ErrorLog /groups/smallco/logs/error_log
    +    TransferLog /groups/smallco/logs/access_log
    +    </VirtualHost>
    +
    +    <VirtualHost www.baygroup.org>
    +    ServerAdmin webmaster@mail.baygroup.org
    +    DocumentRoot /groups/baygroup/www
    +    ServerName www.baygroup.org
    +    ErrorLog /groups/baygroup/logs/error_log
    +    TransferLog /groups/baygroup/logs/access_log
    +    </VirtualHost>
    +
    + +It is recommended that you use an IP address instead of a hostname +(see DNS caveats). + +

    + +Almost any configuration directive can be put +in the VirtualHost directive, with the exception of +ServerType, +StartServers, +MaxSpareServers, +MinSpareServers, +MaxRequestsPerChild, +BindAddress, +Listen, +PidFile, +TypesConfig, +ServerRoot, +NameVirtualHost +and a few other directives. +

    +User and +Group may be used inside a VirtualHost +directive if the suEXEC wrapper is used. +

    + +SECURITY: When specifying where to write log files, be aware +of some security risks which are present if anyone other than the +user that starts Apache has write access to the directory where they +are written. See the security +tips document for details. +

    + + + + + diff --git a/APACHE_1_3_12/htdocs/manual/vhosts/mass.html b/APACHE_1_3_12/htdocs/manual/vhosts/mass.html new file mode 100644 index 0000000000..df56093680 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/vhosts/mass.html @@ -0,0 +1,403 @@ + + +Dynamically configured mass virtual hosting + + + + + +

    Dynamically configured mass virtual hosting

    + +

    This document describes how to efficiently serve an arbitrary number +of virtual hosts with Apache 1.3. + + + +

    Contents:

    + + + +

    Motivation

    + +

    The techniques described here are of interest if your +httpd.conf contains many +<VirtualHost> sections that are substantially the +same, for example: +

    +NameVirtualHost 111.22.33.44
    +<VirtualHost 111.22.33.44>
    +	ServerName		           www.customer-1.com
    +	DocumentRoot		/www/hosts/www.customer-1.com/docs
    +	ScriptAlias  /cgi-bin/  /www/hosts/www.customer-1.com/cgi-bin
    +</VirtualHost>
    +<VirtualHost 111.22.33.44>
    +	ServerName		           www.customer-2.com
    +	DocumentRoot		/www/hosts/www.customer-2.com/docs
    +	ScriptAlias  /cgi-bin/  /www/hosts/www.customer-2.com/cgi-bin
    +</VirtualHost>
    +# blah blah blah
    +<VirtualHost 111.22.33.44>
    +	ServerName		           www.customer-N.com
    +	DocumentRoot		/www/hosts/www.customer-N.com/docs
    +	ScriptAlias  /cgi-bin/  /www/hosts/www.customer-N.com/cgi-bin
    +</VirtualHost>
    +
    +

    + +

    The basic idea is to replace all of the static +<VirtualHost> configuration with a mechanism that +works it out dynamically. This has a number of advantages: +

      +
    1. Your configuration file is smaller so Apache starts faster and + uses less memory. +
    2. Adding virtual hosts is simply a matter of creating the + appropriate directories in the filesystem and entries in the DNS - + you don't need to reconfigure or restart Apache. +
    +

    + +

    The main disadvantage is that you cannot have a different log file +for each virtual host; however if you have very many virtual hosts +then doing this is dubious anyway because it eats file descriptors. It +is better to log to a pipe or a fifo and arrange for the process at +the other end to distribute the logs to the customers (it can also +accumulate statistics, etc.).

    + + +

    Overview

    + +

    A virtual host is defined by two pieces of information: its IP +address, and the contents of the Host: header in the HTTP +request. The dynamic mass virtual hosting technique is based on +automatically inserting this information into the pathname of the file +that is used to satisfy the request. This is done most easily using +mod_vhost_alias, +but if you are using a version of Apache up to 1.3.6 then you must use +mod_rewrite. Both +of these modules are disabled by default; you must enable one of them +when configuring and building Apache if you want to use this technique.

    + +

    A couple of things need to be `faked' to make the dynamic virtual +host look like a normal one. The most important is the server name +which is used by Apache to generate self-referential URLs, etc. It +is configured with the ServerName directive, and it is +available to CGIs via the SERVER_NAME environment +variable. The actual value used at run time is controlled by the +UseCanonicalName +setting. With UseCanonicalName Off the server name +comes from the contents of the Host: header in the +request. With UseCanonicalName DNS it comes from a +reverse DNS lookup of the virtual host's IP address. The former +setting is used for name-based dynamic virtual hosting, and the latter +is used for IP-based hosting. If Apache cannot work out the server +name because there is no Host: header or the DNS lookup +fails then the value configured with ServerName is used +instead.

    + +

    The other thing to `fake' is the document root (configured +with DocumentRoot and available to CGIs via the +DOCUMENT_ROOT environment variable). This setting +is used by the core module when mapping URIs to filenames, but +when the server is configured to do dynamic virtual hosting that +job is taken over by another module. If any CGIs or SSI documents +make use of the DOCUMENT_ROOT environment variable +they will therefore get a misleading value; there isn't any way to +change DOCUMENT_ROOT dynamically.

    + + +

    Simple dynamic virtual hosts

    + +

    This extract from httpd.conf implements the virtual +host arrangement outlined in the Motivation +section above, but in a generic fashion using +mod_vhost_alias.

    + +
    +# get the server name from the Host: header
    +UseCanonicalName Off
    +
    +# this log format can be split per-virtual-host based on the first field
    +LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon
    +CustomLog logs/access_log vcommon
    +
    +# include the server name in the filenames used to satisfy requests
    +VirtualDocumentRoot /www/hosts/%0/docs
    +VirtualScriptAlias  /www/hosts/%0/cgi-bin
    +
    + +

    This configuration can be changed into an IP-based virtual hosting +solution by just turning UseCanonicalName Off into +UseCanonicalName DNS. The server name that is inserted +into the filename is then derived from the IP address of the virtual +host.

    + + +

    A virtually hosted homepages system

    + +

    This is an adjustment of the above system tailored for an ISP's +homepages server. Using a slightly more complicated configuration we +can select substrings of the server name to use in the filename so +that e.g. the documents for www.user.isp.com are found in +/home/user/. It uses a single cgi-bin +directory instead of one per virtual host.

    + +
    +# all the preliminary stuff is the same as above, then
    +
    +# include part of the server name in the filenames
    +VirtualDocumentRoot /www/hosts/%2/docs
    +
    +# single cgi-bin directory
    +ScriptAlias  /cgi-bin/  /www/std-cgi/
    +
    + +

    There are examples of more complicated +VirtualDocumentRoot settings in +the +mod_vhost_alias documentation.

    + + +

    Using more than one virtual hosting +system on the same server

    + +

    With more complicated setups you can use Apache's normal +<VirtualHost> directives to control the scope of +the various virtual hosting configurations. For example, you could +have one IP address for homepages customers and another for commercial +customers with the following setup. This can of course be combined +with conventional <VirtualHost> configuration +sections.

    + +
    +UseCanonicalName Off
    +
    +LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon
    +
    +<Directory /www/commercial>
    +	Options FollowSymLinks
    +	AllowOverride All
    +</Directory>
    +
    +<Directory /www/homepages>
    +	Options FollowSymLinks
    +	AllowOverride None
    +</Directory>
    +
    +<VirtualHost 111.22.33.44>
    +	ServerName www.commercial.isp.com
    +
    +	CustomLog logs/access_log.commercial vcommon
    +
    +	VirtualDocumentRoot /www/commercial/%0/docs
    +	VirtualScriptAlias  /www/commercial/%0/cgi-bin
    +</VirtualHost>
    +
    +<VirtualHost 111.22.33.45>
    +	ServerName www.homepages.isp.com
    +
    +	CustomLog logs/access_log.homepages vcommon
    +
    +	VirtualDocumentRoot /www/homepages/%0/docs
    +	ScriptAlias         /cgi-bin/ /www/std-cgi/
    +</VirtualHost>
    +
    + + +

    More efficient IP-based virtual hosting

    + +

    After the first example I noted that it is +easy to turn it into an IP-based virtual hosting setup. Unfortunately +that configuration is not very efficient because it requires a DNS +lookup for every request. This can be avoided by laying out the +filesystem according to the IP addresses themselves rather than the +corresponding names and changing the logging similarly. Apache will +then usually not need to work out the server name and so incur a DNS +lookup.

    + +
    +# get the server name from the reverse DNS of the IP address
    +UseCanonicalName DNS
    +
    +# include the IP address in the logs so they may be split
    +LogFormat "%A %h %l %u %t \"%r\" %s %b" vcommon
    +CustomLog logs/access_log vcommon
    +
    +# include the IP address in the filenames
    +VirtualDocumentRootIP /www/hosts/%0/docs
    +VirtualScriptAliasIP  /www/hosts/%0/cgi-bin
    +
    + + +

    Using older versions of Apache

    + +

    The examples above rely on mod_vhost_alias which +appeared after version 1.3.6. If you are using a version of Apache +without mod_vhost_alias then you can implement this +technique with mod_rewrite as illustrated below, but +only for Host:-header-based virtual hosts.

    + +

    In addition there are some things to beware of with logging. Apache +1.3.6 is the first version to include the %V log format +directive; in versions 1.3.0 - 1.3.3 the %v option did +what %V does; version 1.3.4 has no equivalent. In +all these versions of Apache the UseCanonicalName +directive can appear in .htaccess files which means that +customers can cause the wrong thing to be logged. Therefore the best +thing to do is use the %{Host}i directive which logs the +Host: header directly; note that this may include +:port on the end which is not the case for +%V.

    + + +

    Simple dynamic virtual hosts +using mod_rewrite

    + +

    This extract from httpd.conf does the same thing as +the first example. The first half is very +similar to the corresponding part above but with some changes for +backward compatibility and to make the mod_rewrite part +work properly; the second half configures mod_rewrite to +do the actual work.

    + +

    There are a couple of especially tricky bits: By default, +mod_rewrite runs before the other URI translation modules +(mod_alias etc.) so if they are used then +mod_rewrite must be configured to accommodate them. +Also, mome magic must be performed to do a per-dynamic-virtual-host +equivalent of ScriptAlias.

    + +
    +# get the server name from the Host: header
    +UseCanonicalName Off
    +
    +# splittable logs
    +LogFormat "%{Host}i %h %l %u %t \"%r\" %s %b" vcommon
    +CustomLog logs/access_log vcommon
    +
    +<Directory /www/hosts>
    +	# ExecCGI is needed here because we can't force
    +	# CGI execution in the way that ScriptAlias does
    +	Options FollowSymLinks ExecCGI
    +</Directory>
    +
    +# now for the hard bit
    +
    +RewriteEngine On
    +
    +# a ServerName derived from a Host: header may be any case at all
    +RewriteMap  lowercase  int:tolower
    +
    +## deal with normal documents first:
    +# allow Alias /icons/ to work - repeat for other aliases
    +RewriteCond  %{REQUEST_URI}  !^/icons/
    +# allow CGIs to work
    +RewriteCond  %{REQUEST_URI}  !^/cgi-bin/
    +# do the magic
    +RewriteRule  ^/(.*)$  /www/hosts/${lowercase:%{SERVER_NAME}}/docs/$1
    +
    +## and now deal with CGIs - we have to force a MIME type
    +RewriteCond  %{REQUEST_URI}  ^/cgi-bin/
    +RewriteRule  ^/(.*)$  /www/hosts/${lowercase:%{SERVER_NAME}}/cgi-bin/$1  [T=application/x-httpd-cgi]
    +
    +# that's it!
    +
    + + +

    A homepages system +using mod_rewrite

    + +

    This does the same thing as the +second example.

    + +
    +RewriteEngine on
    +
    +RewriteMap   lowercase  int:tolower
    +
    +# allow CGIs to work
    +RewriteCond  %{REQUEST_URI}  !^/cgi-bin/
    +
    +# check the hostname is right so that the RewriteRule works
    +RewriteCond  ${lowercase:%{SERVER_NAME}}  ^www\.[a-z-]+\.isp\.com$
    +
    +# concatenate the virtual host name onto the start of the URI
    +# the [C] means do the next rewrite on the result of this one
    +RewriteRule  ^(.+)  ${lowercase:%{SERVER_NAME}}$1  [C]
    +
    +# now create the real file name
    +RewriteRule  ^www\.([a-z-]+)\.isp\.com/(.*) /home/$1/$2
    +
    +# define the global CGI directory
    +ScriptAlias  /cgi-bin/  /www/std-cgi/
    +
    + + +

    Using a separate virtual host configuration file

    + +

    This arrangement uses more advanced mod_rewrite +features to get the translation from virtual host to document root +from a separate configuration file. This provides more flexibility but +requires more complicated configuration.

    + +

    The vhost.map file contains something like this: +

    +www.customer-1.com  /www/customers/1
    +www.customer-2.com  /www/customers/2
    +# ...
    +www.customer-N.com  /www/customers/N
    +
    +

    + +

    The http.conf contains this: +

    +RewriteEngine on
    +
    +RewriteMap   lowercase  int:tolower
    +
    +# define the map file
    +RewriteMap   vhost      txt:/www/conf/vhost.map
    +
    +# deal with aliases as above
    +RewriteCond  %{REQUEST_URI}               !^/icons/
    +RewriteCond  %{REQUEST_URI}               !^/cgi-bin/
    +RewriteCond  ${lowercase:%{SERVER_NAME}}  ^(.+)$
    +# this does the file-based remap
    +RewriteCond  ${vhost:%1}                  ^(/.*)$
    +RewriteRule  ^/(.*)$                      %1/docs/$1
    +
    +RewriteCond  %{REQUEST_URI}               ^/cgi-bin/
    +RewriteCond  ${lowercase:%{SERVER_NAME}}  ^(.+)$
    +RewriteCond  ${vhost:%1}                  ^(/.*)$
    +RewriteRule  ^/(.*)$                      %1/cgi-bin/$1
    +
    +

    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/vhosts/name-based.html b/APACHE_1_3_12/htdocs/manual/vhosts/name-based.html new file mode 100644 index 0000000000..238cf5c721 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/vhosts/name-based.html @@ -0,0 +1,164 @@ + + +Apache name-based Virtual Hosts + + + + + +

    Apache name-based Virtual Host Support

    + +See Also: +IP-based Virtual Host Support + +
    + +

    Name-based vs. IP-based virtual hosts

    + +

    While the approach with IP-based virtual hosts works very well, +it is not the most elegant solution, because a dedicated IP address +is needed for every virtual host and it is hard to implement on some +machines. The HTTP/1.1 protocol contains a method for the +server to identify what name it is being addressed as. Apache 1.1 and +later support this approach as well as the traditional +IP-address-per-hostname method.

    + +

    The benefits of using the new name-based virtual host support is a +practically unlimited number of servers, ease of configuration and use, and +requires no additional hardware or software. +The main disadvantage is that the client must support this part of the +protocol. The latest versions of most browsers do, but there are still +old browsers in use who do not. This can cause problems, although a possible +solution is addressed below.

    + +

    Using non-IP Virtual Hosts

    + +

    Using the new virtual hosts is quite easy, and superficially looks +like the old method. The notable difference between IP-based and +name-based virtual host configuration is the +NameVirtualHost +directive which specifies an IP address that should be used as a +target for name-based virtual hosts.

    + +

    For example, suppose that both www.domain.tld and +www.otherdomain.tld point at the IP address +111.22.33.44. Then you simply add to one of the Apache +configuration files (most likely httpd.conf or +srm.conf) code similar to the following:

    + + + +
    +    NameVirtualHost 111.22.33.44
    +
    +    <VirtualHost 111.22.33.44>
    +    ServerName www.domain.tld
    +    DocumentRoot /www/domain
    +    </VirtualHost>
    +
    +    <VirtualHost 111.22.33.44>
    +    ServerName www.otherdomain.tld
    +    DocumentRoot /www/otherdomain
    +    </VirtualHost>
    +
    + +

    Of course, any additional directives can (and should) be placed +into the <VirtualHost> section. To make this work, +all that is needed is to make sure that the names +www.domain.tld and www.otherdomain.tld +are pointing to the IP address 111.22.33.44

    + +

    Note: When you specify an IP address in a NameVirtualHost +directive then requests to that IP address will only ever be served +by matching <VirtualHost>s. The "main server" will +never be served from the specified IP address. +If you start to use virtual hosts you should stop to use the "main server" +as an independent server and rather use it as a place for +configuration directives that are common for all your virtual hosts. +In other words, you should add a <VirtualHost> section for +every server (hostname) you want to maintain on your server. + +

    Additionally, many servers may wish to be accessible by more than +one name. For example, the example server might want to be accessible +as domain.tld, or www2.domain.tld, assuming +the IP addresses pointed to the same server. In fact, one might want it +so that all addresses at domain.tld were picked up by the +server. This is possible with the +ServerAlias +directive, placed inside the <VirtualHost> section. For +example:

    + +
    +    ServerAlias domain.tld *.domain.tld
    +
    + +

    Note that you can use * and ? as wild-card +characters.

    + +

    You also might need ServerAlias if you are +serving local users who do not always include the domain name. +For example, if local users are +familiar with typing "www" or "www.foobar" then you will need to add +ServerAlias www www.foobar. It isn't possible for the +server to know what domain the client uses for their name resolution +because the client doesn't provide that information in the request. +The ServerAlias directive is generally a way to have different +hostnames pointing to the same virtual host. +

    + +

    Compatibility with Older Browsers

    + +

    As mentioned earlier, there are still some clients in use who +do not send the required data for the name-based virtual hosts to work +properly. These clients will always be sent the pages from the +first virtual host listed for that IP address (the +primary name-based virtual host).

    + +

    There is a possible workaround with the +ServerPath +directive, albeit a slightly cumbersome one:

    + +

    Example configuration: + +

    +    NameVirtualHost 111.22.33.44
    +
    +    <VirtualHost 111.22.33.44>
    +    ServerName www.domain.tld
    +    ServerPath /domain
    +    DocumentRoot /web/domain
    +    </VirtualHost>
    +
    + +

    What does this mean? It means that a request for any URI beginning +with "/domain" will be served from the virtual host +www.domain.tld This means that the pages can be accessed as +http://www.domain.tld/domain/ for all clients, although +clients sending a Host: header can also access it as +http://www.domain.tld/.

    + +

    In order to make this work, put a link on your primary virtual host's page +to http://www.domain.tld/domain/ +Then, in the virtual host's pages, be sure to use either purely +relative links (e.g., "file.html" or +"../icons/image.gif" or links containing the prefacing +/domain/ +(e.g., "http://www.domain.tld/domain/misc/file.html" or +"/domain/misc/file.html").

    + +

    This requires a bit of +discipline, but adherence to these guidelines will, for the most part, +ensure that your pages will work with all browsers, new and old.

    + +

    See also: ServerPath configuration +example

    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/vhosts/vhosts-in-depth.html b/APACHE_1_3_12/htdocs/manual/vhosts/vhosts-in-depth.html new file mode 100644 index 0000000000..23d8e919a1 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/vhosts/vhosts-in-depth.html @@ -0,0 +1,396 @@ + + +An In-Depth Discussion of VirtualHost Matching + + + + + +

    An In-Depth Discussion of VirtualHost Matching

    + +

    This is a very rough document that was probably out of date the moment +it was written. It attempts to explain exactly what the code does when +deciding what virtual host to serve a hit from. It's provided on the +assumption that something is better than nothing. The server version +under discussion is Apache 1.2. + +

    If you just want to "make it work" without understanding +how, there's a What Works section at the bottom. + +

    Config File Parsing

    + +

    There is a main_server which consists of all the definitions appearing +outside of VirtualHost sections. There are virtual servers, +called vhosts, which are defined by +VirtualHost +sections. + +

    The directives +Port, +ServerName, +ServerPath, +and +ServerAlias +can appear anywhere within the definition of +a server. However, each appearance overrides the previous appearance +(within that server). + +

    The default value of the Port field for main_server +is 80. The main_server has no default ServerName, +ServerPath, or ServerAlias. + +

    In the absence of any +Listen +directives, the (final if there +are multiple) Port directive in the main_server indicates +which port httpd will listen on. + +

    The Port and ServerName directives for +any server main or virtual are used when generating URLs such as during +redirects. + +

    Each address appearing in the VirtualHost directive +can have an optional port. If the port is unspecified it defaults to +the value of the main_server's most recent Port statement. +The special port * indicates a wildcard that matches any port. +Collectively the entire set of addresses (including multiple +A record +results from DNS lookups) are called the vhost's address set. + +

    The magic _default_ address has significance during +the matching algorithm. It essentially matches any unspecified address. + +

    After parsing the VirtualHost directive, the vhost server +is given a default Port equal to the port assigned to the +first name in its VirtualHost directive. The complete +list of names in the VirtualHost directive are treated +just like a ServerAlias (but are not overridden by any +ServerAlias statement). Note that subsequent Port +statements for this vhost will not affect the ports assigned in the +address set. + +

    +All vhosts are stored in a list which is in the reverse order that +they appeared in the config file. For example, if the config file is: + +

    +    <VirtualHost A>
    +    ...
    +    </VirtualHost>
    +
    +    <VirtualHost B>
    +    ...
    +    </VirtualHost>
    +
    +    <VirtualHost C>
    +    ...
    +    </VirtualHost>
    +
    + +Then the list will be ordered: main_server, C, B, A. Keep this in mind. + +

    +After parsing has completed, the list of servers is scanned, and various +merges and default values are set. In particular: + +

      +
    1. If a vhost has no + ServerAdmin, + ResourceConfig, + AccessConfig, + Timeout, + KeepAliveTimeout, + KeepAlive, + MaxKeepAliveRequests, + or + SendBufferSize + directive then the respective value is + inherited from the main_server. (That is, inherited from whatever + the final setting of that value is in the main_server.) + +
    2. The "lookup defaults" that define the default directory + permissions + for a vhost are merged with those of the main server. This includes + any per-directory configuration information for any module. + +
    3. The per-server configs for each module from the main_server are + merged into the vhost server. +
    + +Essentially, the main_server is treated as "defaults" or a +"base" on +which to build each vhost. But the positioning of these main_server +definitions in the config file is largely irrelevant -- the entire +config of the main_server has been parsed when this final merging occurs. +So even if a main_server definition appears after a vhost definition +it might affect the vhost definition. + +

    If the main_server has no ServerName at this point, +then the hostname of the machine that httpd is running on is used +instead. We will call the main_server address set those IP +addresses returned by a DNS lookup on the ServerName of +the main_server. + +

    Now a pass is made through the vhosts to fill in any missing +ServerName fields and to classify the vhost as either +an IP-based vhost or a name-based vhost. A vhost is +considered a name-based vhost if any of its address set overlaps the +main_server (the port associated with each address must match the +main_server's Port). Otherwise it is considered an IP-based +vhost. + +

    For any undefined ServerName fields, a name-based vhost +defaults to the address given first in the VirtualHost +statement defining the vhost. Any vhost that includes the magic +_default_ wildcard is given the same ServerName as +the main_server. Otherwise the vhost (which is necessarily an IP-based +vhost) is given a ServerName based on the result of a reverse +DNS lookup on the first address given in the VirtualHost +statement. + +

    + +

    Vhost Matching

    + + +

    Apache 1.3 differs from what is documented +here, and documentation still has to be written. + +

    +The server determines which vhost to use for a request as follows: + +

    find_virtual_server: When the connection is first made +by the client, the local IP address (the IP address to which the client +connected) is looked up in the server list. A vhost is matched if it +is an IP-based vhost, the IP address matches and the port matches +(taking into account wildcards). + +

    If no vhosts are matched then the last occurrence, if it appears, +of a _default_ address (which if you recall the ordering of the +server list mentioned above means that this would be the first occurrence +of _default_ in the config file) is matched. + +

    In any event, if nothing above has matched, then the main_server is +matched. + +

    The vhost resulting from the above search is stored with data +about the connection. We'll call this the connection vhost. +The connection vhost is constant over all requests in a particular TCP/IP +session -- that is, over all requests in a KeepAlive/persistent session. + +

    For each request made on the connection the following sequence of +events further determines the actual vhost that will be used to serve +the request. + +

    check_fulluri: If the requestURI is an absoluteURI, that +is it includes http://hostname/, then an attempt is made to +determine if the hostname's address (and optional port) match that of +the connection vhost. If it does then the hostname portion of the URI +is saved as the request_hostname. If it does not match, then the +URI remains untouched. Note: to achieve this address +comparison, +the hostname supplied goes through a DNS lookup unless it matches the +ServerName or the local IP address of the client's socket. + +

    parse_uri: If the URI begins with a protocol +(i.e., http:, ftp:) then the request is +considered a proxy request. Note that even though we may have stripped +an http://hostname/ in the previous step, this could still +be a proxy request. + +

    read_request: If the request does not have a hostname +from the earlier step, then any Host: header sent by the +client is used as the request hostname. + +

    check_hostalias: If the request now has a hostname, +then an attempt is made to match for this hostname. The first step +of this match is to compare any port, if one was given in the request, +against the Port field of the connection vhost. If there's +a mismatch then the vhost used for the request is the connection vhost. +(This is a bug, see observations.) + +

    +If the port matches, then httpd scans the list of vhosts starting with +the next server after the connection vhost. This scan does not +stop if there are any matches, it goes through all possible vhosts, +and in the end uses the last match it found. The comparisons performed +are as follows: + +

      +
    • Compare the request hostname:port with the vhost + ServerName and Port. + +
    • Compare the request hostname against any and all addresses given in + the VirtualHost directive for this vhost. + +
    • Compare the request hostname against the ServerAlias + given for the vhost. +
    + +

    +check_serverpath: If the request has no hostname +(back up a few paragraphs) then a scan similar to the one +in check_hostalias is performed to match any +ServerPath directives given in the vhosts. Note that the +last match is used regardless (again consider the ordering of +the virtual hosts). + +

    Observations

    + +
      + +
    • It is difficult to define an IP-based vhost for the machine's + "main IP address". You essentially have to create a bogus + ServerName for the main_server that does not match the + machine's IPs. +

      + +

    • During the scans in both check_hostalias and + check_serverpath no check is made that the vhost being + scanned is actually a name-based vhost. This means, for example, that + it's possible to match an IP-based vhost through another address. But + because the scan starts in the vhost list at the first vhost that + matched the local IP address of the connection, not all IP-based vhosts + can be matched. +

      + Consider the config file above with three vhosts A, B, C. Suppose + that B is a named-based vhost, and A and C are IP-based vhosts. If + a request comes in on B or C's address containing a header + "Host: A" then + it will be served from A's config. If a request comes in on A's + address then it will always be served from A's config regardless of + any Host: header. +

      + +
    • Unless you have a _default_ vhost, + it doesn't matter if you mix name-based vhosts in amongst IP-based + vhosts. During the find_virtual_server phase above no + named-based vhost will be matched, so the main_server will remain the + connection vhost. Then scans will cover all vhosts in the vhost list. +

      + If you do have a _default_ vhost, then you cannot place + named-based vhosts after it in the config. This is because on any + connection to the main server IPs the connection vhost will always be + the _default_ vhost since none of the name-based are + considered during find_virtual_server. +

      + +
    • You should never specify DNS names in VirtualHost + directives because it will force your server to rely on DNS to boot. + Furthermore it poses a security threat if you do not control the + DNS for all the domains listed. + There's more information + available on this and the next two topics. +

      + +

    • ServerName should always be set for each vhost. Otherwise + A DNS lookup is required for each vhost. +

      + +

    • A DNS lookup is always required for the main_server's + ServerName (or to generate that if it isn't specified + in the config). +

      + +

    • If a ServerPath directive exists which is a prefix of + another ServerPath directive that appears later in + the configuration file, then the former will always be matched + and the latter will never be matched. (That is assuming that no + Host header was available to disambiguate the two.) +

      + +

    • If a vhost that would otherwise be a name-vhost includes a + Port statement that doesn't match the main_server + Port then it will be considered an IP-based vhost. + Then find_virtual_server will match it (because + the ports associated with each address in the address set default + to the port of the main_server) as the connection vhost. Then + check_hostalias will refuse to check any other name-based + vhost because of the port mismatch. The result is that the vhost + will steal all hits going to the main_server address. +

      + +

    • If two IP-based vhosts have an address in common, the vhost appearing + later in the file is always matched. Such a thing might happen + inadvertently. If the config has name-based vhosts and for some reason + the main_server ServerName resolves to the wrong address + then all the name-based vhosts will be parsed as ip-based vhosts. + Then the last of them will steal all the hits. +

      + +

    • The last name-based vhost in the config is always matched for any hit + which doesn't match one of the other name-based vhosts. + +
    + +

    What Works

    + +

    In addition to the tips on the DNS +Issues page, here are some further tips: + +

      + +
    • Place all main_server definitions before any VirtualHost definitions. +(This is to aid the readability of the configuration -- the post-config +merging process makes it non-obvious that definitions mixed in around +virtualhosts might affect all virtualhosts.) +

      + +

    • Arrange your VirtualHosts such +that all name-based virtual hosts come first, followed by IP-based +virtual hosts, followed by any _default_ virtual host +

      + +

    • Avoid ServerPaths which are prefixes of other +ServerPaths. If you cannot avoid this then you have to +ensure that the longer (more specific) prefix vhost appears earlier in +the configuration file than the shorter (less specific) prefix +(i.e., "ServerPath /abc" should appear after +"ServerPath /abcdef"). +

      + +

    • Do not use port-based vhosts in the same server as +name-based vhosts. A loose definition for port-based is a vhost which +is determined by the port on the server (i.e., one server with +ports 8000, 8080, and 80 - all of which have different configurations). +

      + +

    + + + + diff --git a/APACHE_1_3_12/htdocs/manual/vhosts/virtual-host.html b/APACHE_1_3_12/htdocs/manual/vhosts/virtual-host.html new file mode 100644 index 0000000000..aa81fad91e --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/vhosts/virtual-host.html @@ -0,0 +1,208 @@ + + + +Apache Server Virtual Host Support + + + + + +

    Virtual Host Support

    + +See Also: +Non-IP based virtual hosts + +

    What are virtual hosts?

    +This is the ability of a single machine to be a web server for multiple +domains. For example, an Internet service provider might have a machine +called www.serve.com which provides Web space for several +organizations including, say, smallco and baygroup. +Ordinarily, these groups would be given parts of the Web tree on www.serve.com. +So smallco's home page would have the URL +
    +http://www.serve.com/smallco/ +
    +and baygroup's home page would have the URL +
    +http://www.serve.com/baygroup/ +
    +

    +For esthetic reasons, however, both organizations would rather their home +pages appeared under their own names rather than that of the service +provider's; but they do not want to set up their own Internet links and +servers. +

    +Virtual hosts are the solution to this problem. smallco and baygroup would +have their own Internet name registrations, www.smallco.com and +www.baygroup.org respectively. These hostnames would both +correspond to the service provider's machine (www.serve.com). Thus +smallco's home page would now have the URL +

    +http://www.smallco.com/ +
    +and baygroup's home page would would have the URL +
    +http://www.baygroup.org/ +
    + +

    System requirements

    +Due to limitations in the HTTP/1.0 protocol, the web server must have a +different IP address for each virtual host. This can be achieved +by the machine having several physical network connections, or by use +of a virtual interface on some operating +systems. + +

    How to set up Apache

    +There are two ways of configuring apache to support multiple hosts. +Either by running a separate httpd daemon for each hostname, or by running a +single daemon which supports all the virtual hosts. +

    +Use multiple daemons when: +

      +
    • The different virtual hosts need very different httpd configurations, such + as different values for: + ServerType, + User, + Group, + TypesConfig or + ServerRoot. +
    • The machine does not process a very high request rate. +
    +Use a single daemon when: +
      +
    • Sharing of the httpd configuration between virtual hosts is acceptable. +
    • The machine services a large number of requests, and so the performance + loss in running separate daemons may be significant. +
    + +

    Setting up multiple daemons

    +Create a separate httpd installation for each virtual host. +For each installation, use the +BindAddress directive in the +configuration +file to select which IP address (or virtual host) that daemon services. +E.g., +
    BindAddress www.smallco.com
    +This hostname can also be given as an IP address. + +

    Setting up a single daemon

    +For this case, a single httpd will service requests for all the virtual hosts. +The VirtualHost directive in the + configuration file is used to set the values of +ServerAdmin, +ServerName, +DocumentRoot, +ErrorLog and +TransferLog configuration +directives to different values for each virtual host. +E.g., +
    +<VirtualHost www.smallco.com>
    +ServerAdmin webmaster@mail.smallco.com
    +DocumentRoot /groups/smallco/www
    +ServerName www.smallco.com
    +ErrorLog /groups/smallco/logs/error_log
    +TransferLog /groups/smallco/logs/access_log
    +</VirtualHost>
    +
    +<VirtualHost www.baygroup.org>
    +ServerAdmin webmaster@mail.baygroup.org
    +DocumentRoot /groups/baygroup/www
    +ServerName www.baygroup.org
    +ErrorLog /groups/baygroup/logs/error_log
    +TransferLog /groups/baygroup/logs/access_log
    +</VirtualHost>
    +
    + +This VirtualHost hostnames can also be given as IP addresses. + +

    + +Almost ANY configuration directive can be put +in the VirtualHost directive, with the exception of +ServerType, +User, +Group, +StartServers, +MaxSpareServers, +MinSpareServers, +MaxRequestsPerChild, +BindAddress, +PidFile, +TypesConfig, and +ServerRoot. + +

    + +SECURITY: When specifying where to write log files, be aware +of some security risks which are present if anyone other than the +user that starts Apache has write access to the directory where they +are written. See the security +tips document for details. + +

    + +

    File Handle/Resource Limits:

    +When using a large number of Virtual Hosts, Apache may run out of available +file descriptors if each Virtual Host specifies different log files. +The total number of file descriptors used by Apache is one for each distinct +error log file, one for every other log file directive, plus 10-20 for +internal use. Unix operating systems limit the number of file descriptors that +may be used by a process; the limit is typically 64, and may usually be +increased up to a large hard-limit. +

    +Although Apache attempts to increase the limit as required, this +may not work if: +

      +
    1. Your system does not provide the setrlimit() system call. +
    2. The setrlimit(RLIMIT_NOFILE) call does not function on your system + (such as Solaris 2.3) +
    3. The number of file descriptors required exceeds the hard limit. +
    4. Your system imposes other limits on file descriptors, such as a limit +on stdio streams only using file descriptors below 256. (Solaris 2) +
    + +In the event of problems you can: +
      +
    • Reduce the number of log files; don't specify log files in the VirtualHost +sections, but only log to the main log files. +
    • If you system falls into 1 or 2 (above), then increase the file descriptor +limit before starting Apache, using a script like +
      +#!/bin/sh
      +ulimit -S -n 100
      +exec httpd
      +
    + +The have been reports that Apache may start running out of resources allocated +for the root process. This will exhibit itself as errors in the error log like +"unable to fork". There are two ways you can bump this up: + +
      +
    1. Have a csh script wrapper around httpd which sets the +"rlimit" to some large number, like 512. +
    2. Edit http_main.c to add calls to setrlimit() from main(), along the lines +of +
      +        struct rlimit rlp;
      +
      +        rlp.rlim_cur = rlp.rlim_max = 512;
      +        if (setrlimit(RLIMIT_NPROC, &rlp)) {
      +            fprintf(stderr, "setrlimit(RLIMIT_NPROC) failed.\n");
      +            exit(1);
      +        }
      +
      +(thanks to "Aaron Gifford <agifford@InfoWest.COM>" for the patch) +
    + +The latter will probably manifest itself in a later version of Apache. + + + + diff --git a/APACHE_1_3_12/htdocs/manual/windows.html b/APACHE_1_3_12/htdocs/manual/windows.html new file mode 100644 index 0000000000..a9989b0063 --- /dev/null +++ b/APACHE_1_3_12/htdocs/manual/windows.html @@ -0,0 +1,572 @@ + + + +Using Apache with Microsoft Windows + + + + + + +

    Using Apache With Microsoft Windows

    + +

    This document explains how to install, configure and run + Apache 1.3 under Microsoft Windows. Please note that at + this time, Windows support is entirely experimental, and is + recommended only for experienced users. The Apache Group does not + guarantee that this software will work as documented, or even at + all. If you find any bugs, or wish to contribute in other ways, please + use our bug reporting + page.

    + +

    Warning: Apache on NT has not yet been optimized for performance. +Apache still performs best, and is most reliable on Unix platforms. Over +time we will improve NT performance. Folks doing comparative reviews +of webserver performance are asked to compare against Apache +on a Unix platform such as Solaris, FreeBSD, or Linux.

    + +

    + +Most of this document assumes that you are installing Windows from a +binary distribution. If you want to compile Apache yourself (possibly +to help with development, or to track down bugs), see the section on +Compiling Apache for Windows below. + +


    + + + +
    + +

    Requirements

    + +Apache 1.3 is designed to run on Windows NT 4.0. The binary installer +will only work in Intel processors. Apache may also run on Windows 95, +Windows 98 and Windows NT 3.5.1, but these have not been tested. In +all cases TCP/IP networking must be installed. + +

    + +If running on Windows 95, using the "Winsock2" upgrade is recommended +but may not be necessary. If running on NT 4.0, installing Service Pack 2 +is recommended. + +

    + +Note: "Winsock 2" is required for Apache 1.3.7 and later. + +

    + +"Winsock 2" for Windows 95 is available here. + +

    Downloading Apache for Windows

    + +

    Information on the latest version of Apache can be found on the +Apache web server at http://www.apache.org/. This will +list the current release, any more recent alpha or beta-test releases, +together with details of mirror web and anonymous ftp sites.

    + +

    + +You should download the version of Apache for Windows with the +.exe extension. This is a single file containing Apache, +ready to install and run. There may also be a .zip file +containing the source code, to compile Apache yourself. (If there is +no .zip file, the source will be available in a +.tar.gz file but this will contain Unix line endings. You +will have to convert at least the .mak and +.dsp files to have DOS line endings before MSVC will +understand them). + +

    Installing Apache for Windows

    + +Run the Apache .exe file you downloaded above. This will +ask for: + +
      + +
    • the directory to install Apache into (the default is + \Program Files\Apache Group\Apache although you can + change this to any other directory) + +
    • the start menu name (default is "Apache Web Server") + +
    • the installation type. The "Typical" option installs + everything except the source code. The "Minimum" option does not + install the manuals or source code. Choose the "Custom" install if + you want to install the source code. + +
    + +

    + +During the installation, Apache will configure the files in the +conf directory for your chosen installation +directory. However if any of the files in this directory already exist +they will not be overwritten. Instead the new copy of +the corresponding file will be left with the extension +.default. So, for example, if +conf\httpd.conf already exists it will not be altered, +but the version which would have been installed will be left in +conf\httpd.conf.default. After the installation has +finished you should manually check to see what in new in the +.default file, and if necessary update your existing +configuration files. + +

    + +Also, if you already have a file called htdocs\index.html +then it will not be overwritten (no index.html.default +file will be installed either). This should mean it a safe to install +Apache over an existing installation (but you will have to stop the +existing server running before doing the installation, then start the +new one after the installation is finished). + +

    + +After installing Apache, you should edit the configuration files in +the conf directory as required. These files will be +configured during the install ready for Apache to be run from the +directory where it was installed, with the documents served from the +subdirectory htdocs. There are lots of other options +which should be set before you start really using Apache. However to +get started quickly the files should work as installed. + +

    Running Apache for Windows

    + +There are two ways you can run Apache: + +
      +
    • As a "service" (available on NT only). This is the best option if + you want Apache to automatically start when you machine boots, and to + keep Apache running when you log-off. + +
    • From a console window. This is the only option + available for + Windows 95 users. +
    + +To start Apache as a service, you first need to install it as a +service. Multiple Apache services can be installed, each with a +different name and configuration. To install the default Apache +service named "Apache", run the "Install Apache as Service (NT only)" +option from the Start menu. Once this is done you can start the "Apache" +service by opening the Services window (in the Control Panel), selecting Apache, +then clicking on Start. Apache will now be running in the background. You +can later stop Apache by clicking on Stop. As an alternative to using +the Services window, you can start and stop the "Apache" service from the control +line with + +
    +  NET START APACHE
    +  NET STOP APACHE
    +
    + +See Signalling Service Apache when Running +for more information on installing and controlling Apache services. + +

    + +To run Apache from a console window, select the "Start Apache as +console app" option from the Start menu (in Apache 1.3.4 and earlier, +this option was called "Apache Server"). This will open a console +window and start Apache running inside it. The window will remain +active until you stop Apache. To stop Apache running, either select +the "Shutdown Apache console app" icon option from the Start menu +(this is not available in Apache 1.3.4 or earlier), or see Signalling Console Apache when Running for how +to control Apache from the command line. + +

    + +After starting Apache running (either in a console window or as a +service) if will be listening to port 80 (unless you changed the +Port, Listen or BindAddress +directives in the configuration files). To connect to the server and +access the default page, launch a browser and enter this URL: + +

    +  http://localhost/
    +
    + +This should respond with a welcome page, and a link to the Apache +manual. If nothing happens or you get an error, look in the +error_log file in the logs directory. +If your host isn't connected to the net, you may have to use +this URL: + +
    +  http://127.0.0.1/
    +
    + +

    + +Once your basic installation is working, you should configure it +properly by editing the files in the conf directory. + +

    Configuring Apache for Windows

    + +Apache is configured by files in the conf +directory. These are the same as files used to configure the Unix +version, but there are a few different directives for Apache on +Windows. See the Apache documentation for all the +available directives. + +

    + +The main differences in Apache for Windows are: + +

      +
    • Because Apache for Windows is multithreaded, it does not use a + separate process for each request, as Apache does with + Unix. Instead there are usually only two Apache processes running: + a parent process, and a child which handles the requests. Within + the child each request is handled by a separate thread. +

      + + So the "process"-management directives are different: +

      MaxRequestsPerChild + - Like the Unix directive, this controls how many requests a + process will serve before exiting. However, unlike Unix, a + process serves all the requests at once, not just one, so if + this is set, it is recommended that a very high number is + used. The recommended default, MaxRequestsPerChild + 0, does not cause the process to ever exit. +

      ThreadsPerChild - + This directive is new, and tells the server how many threads it + should use. This is the maximum number of connections the server + can handle at once; be sure and set this number high enough for + your site if you get a lot of hits. The recommended default is + ThreadsPerChild 50.

      +
    • The directives that accept filenames as arguments now must use + Windows filenames instead of Unix ones. However, because Apache + uses Unix-style names internally, you must use forward slashes, not + backslashes. Drive letters can be used; if omitted, the drive with + the Apache executable will be assumed.

      +
    • Apache for Windows contains the ability to load modules at runtime, + without recompiling the server. If Apache is compiled normally, it + will install a number of optional modules in the + \Apache\modules directory. To activate these, or other + modules, the new LoadModule + directive must be used. For example, to active the status module, + use the following (in addition to the status-activating directives + in access.conf):

      +
      +    LoadModule status_module modules/ApacheModuleStatus.dll
      +
      +

      Information on creating loadable + modules is also available.

      +
    • Apache can also load ISAPI Extensions (i.e., Internet Server + Applications), such as those used by Microsoft's IIS, and other + Windows servers. More information + is available. +

    + +

    Running Apache for Windows as a Service

    + Note: The -n option to specify a service name is only available + with Apache 1.3.7 and later. Earlier versions of Apache only support + the default service name 'Apache'. + +

    + +You can install Apache as a Windows NT service as follows: + +

    +    apache -i -n "service name"
    +
    + +To install a service to use a particular configuration, specify the +configuration file when the service is installed: + +
    +    apache -i -n "service name" -f "\my server\conf\my.conf"
    +
    + +To remove an Apache service, use + +
    +    apache -u -n "service name"
    +
    + +The default "service name", if one is not specified, is "Apache". + +

    + +Once a service is installed, you can use the -n option, in conjunction +with other options, to refer to a service's configuration file. For example:
    + +To test a service's configuration file: +

    +    apache -n "service name" -t
    +
    + +To start a console Apache using a service's configuration file: +
    +    apache -n "service name"
    +
    + +

    Running Apache for Windows from the Command Line

    + +The Start menu icons and the NT Service manager can provide a simple +interface for administering Apache. But in some cases it is easier to +work from the command line. + +

    +When working with Apache it is important to know how it will find the +configuration files. You can specify a configuration file on the command line +in two ways: + +

      +
    • -f specifies a path to a particular configuration file +
    +
        apache -f "c:\my server\conf\my.conf"
    +
        apache -f test\test.conf
    +
      +
    • -n specifies the configuration file of an installed Apache service (Apache 1.3.7 and later) +
    +
        apache -n "service name"
    + +In these cases, the proper ServerRoot should be set in the configuration file. + +

    + +If you don't specify a configuration file name with -f or -n, Apache will +use the file name compiled into the server, usually "conf/httpd.conf". Invoking +Apache with the -V switch will display this value labeled as SERVER_CONFIG_FILE. +Apache will then determine its ServerRoot by trying the following, in this order: + +

      +
    • A ServerRoot directive via a -C switch. +
    • The -d switch on the command line. +
    • Current working directory +
    • A registry entry, created if you did a binary install. +
    • The server root compiled into the server. +
    + +

    +The server root compiled into the server is usually "/apache". +invoking apache with the -V switch will display this value +labeled as HTTPD_ROOT. + +

    +When invoked from the start menu, Apache is usually passed no arguments, +so using the registry entry is the preferred technique for console Apache. + +

    +During a binary installation, a registry key will have +been installed, for example: +

    +  HKEY_LOCAL_MACHINE\Software\Apache Group\Apache\1.3.4\ServerRoot
    +
    + +

    +This key is compiled into the server and can enable you to test +new versions without affecting the current version. Of course +you must take care not to install the new version on top of the +old version in the file system. + +

    +If you did not do a binary install then Apache will in some +scenarios complain that about the missing registry key. This +warning can be ignored if it otherwise was able to find its +configuration files. + +

    +The value of this key is the "ServerRoot" directory, containing the +conf directory. When Apache starts it will read the +httpd.conf file from this directory. If this file +contains a ServerRoot directive which is different from +the directory obtained from the registry key above, Apache will forget +the registry key and use the directory from the configuration file. +If you copy the Apache directory or configuration files to a new +location it is vital that you update the ServerRoot +directory in the httpd.conf file to the new location. + +

    +To run Apache from the command line as a console application, use the +following command: + +

    +    apache 
    +
    + +Apache will execute, and will remain running until it is stopped by pressing +control-C. + +

    Signalling Service Apache when running

    + +On Windows NT, multiple instances of Apache can be run as services. +Signal an Apache service to start, restart, or shutdown as follows: + +
    +    apache -n "service name" -k start
    +    apache -n "service name" -k restart
    +    apache -n "service name" -k shutdown
    +
    + +In addition, you can use the native NT NET command to +start and stop Apache services as follows: + +
    +    NET START "service name"
    +    NET STOP "service name"
    +
    + +

    Signalling Console Apache when running

    + +On Windows 95, Apache runs as a console application. You can tell a +running Apache to stop by opening another console window and running + +
    +    apache -k shutdown
    +
    +
    + Note: This option is only available with Apache 1.3.3 and + later. For earlier versions, you need to use Control-C in the + Apache console window to shut down the server. +
    + +

    +This should be used instead of pressing Control-C in the running +Apache console window, because it lets Apache end any current +transactions and cleanup gracefully. + +

    + +You can also tell Apache to restart. This makes it re-read the +configuration files. Any transactions in progress are allowed to +complete without interruption. To restart Apache, run + +

    +    apache -k restart
    +
    +
    + Note: This option is only available with Apache 1.3.3 and + later. For earlier versions, you need to use Control-C in the + Apache console window to shut down the server. +
    + +

    +Note for people familiar with the Unix version of Apache: these +commands provide a Windows equivalent to kill -TERM +pid and kill -USR1 pid. The command +line option used, -k, was chosen as a reminder of the +"kill" command used on Unix. + +

    Compiling Apache for Windows

    + +

    Compiling Apache requires Microsoft Visual C++ 5.0 to be properly + installed. It is easiest to compile with the command-line tools + (nmake, etc...). Consult the VC++ manual to determine how to install + them.

    + +

    First, unpack the Apache distribution into an appropriate + directory. Open a command-line prompt, and change to the + src subdirectory of the Apache distribution.

    + +

    The master Apache makefile instructions are contained in the + Makefile.nt file. To compile Apache on Windows NT, simply + use one of the following commands: +

      +
    • nmake /f Makefile.nt _apacher (release build) +
    • nmake /f Makefile.nt _apached (debug build) +
    + +

    (1.3.4 and later) To compile Apache on Windows 95, use one of +

      +
    • nmake /f Makefile_win32.txt (release build) +
    • nmake /f Makefile_win32_debug.txt (debug build) +
    + +

    These will both compile Apache. The latter will include debugging + information in the resulting files, making it easier to find bugs and + track down problems.

    + +

    Apache can also be compiled using VC++'s Visual Studio development + environment. Although compiling Apache in this manner is not as + simple, it makes it possible to easily modify the Apache source, or + to compile Apache if the command-line tools are not installed. + Project files (.DSP) are included for each of the + portions of Apache. To build Apache from the these projects files + you will need to build the following projects in this order: + +

      +
    1. os\win32\ApacheOS.dsp +
    2. regex\regex.dsp +
    3. ap\ap.dsp +
    4. main\gen_uri_delims.dsp +
    5. main\gen_test_char.dsp +
    6. ApacheCore.dsp +
    7. Apache.dsp +
    + + In addition, the src\os\win32 subdirectory contains + project files for the optional modules (see below).

    + +

    Once Apache has been compiled, it needs to be installed in its server + root directory. The default is the \Apache + directory, on the current hard drive.

    + +

    To install the files into the \Apache directory + automatically, use one the following nmake commands (see above):

    +
      +
    • nmake /f Makefile.nt installr INSTDIR=dir + (for release build) +
    • nmake /f Makefile.nt installd INSTDIR=dir + (for debug build) +
    +or, for Windows 95 (1.3.4 and later), use one of: +
      +
    • nmake /f Makefile_win32.txt install INSTDIR=dir + (for release build) +
    • nmake /f Makefile_win32_debug.txt install INSTDIR=dir + (for debug build) +
    + +The dir argument to INSTDIR gives the installation directory; it can +be omitted if Apache is to be installed into \Apache. + +

    This will install the following:

    + +
      +
    • dir\Apache.exe - Apache executable +
    • dir\ApacheCore.dll - Main Apache shared library +
    • dir\modules\ApacheModule*.dll - Optional Apache + modules (7 files) +
    • dir\conf - Empty configuration directory +
    • dir\logs - Empty logging directory +
    + +

    If you do not have nmake, or wish to install in a different directory, + be sure to use a similar naming scheme.

    + +

    +Before running the server you must fill out the conf directory. +Copy the *.conf-dist-win from the distribution conf directory +and rename *.conf. Edit the @@ServerRoot@@ entries to your +actual server root (for example "C:\apache"). Copy over +the conf/magic and conf/mime.types files as well. + + + + + diff --git a/APACHE_1_3_12/icons/README b/APACHE_1_3_12/icons/README new file mode 100644 index 0000000000..74b2970b9e --- /dev/null +++ b/APACHE_1_3_12/icons/README @@ -0,0 +1,158 @@ +Public Domain Icons + + These icons were originally made for Mosaic for X and have been + included in the NCSA httpd and Apache server distributions in the + past. They are in the public domain and may be freely included in any + application. The originals were done by Kevin Hughes + (kevinh@kevcom.com). + + Many thanks to Andy Polyakov for tuning the icon colors and adding a + few new images. If you'd like to contribute additions or ideas to + this set, please let me know. + + Almost all of these icons are 20x22 pixels in size. There are + alternative icons in the "small" directory that are 16x16 in size, + provided by Mike Brown (mike@hyperreal.org). + +Suggested Uses + +The following are a few suggestions, to serve as a starting point for ideas. +Please feel free to tweak and rename the icons as you like. + + a.gif + This might be used to represent PostScript or text layout + languages. + + alert.black.gif, alert.red.gif + These can be used to highlight any important items, such as a + README file in a directory. + + back.gif, forward.gif + These can be used as links to go to previous and next areas. + + ball.gray.gif, ball.red.gif + These might be used as bullets. + + binary.gif + This can be used to represent binary files. + + binhex.gif + This can represent BinHex-encoded data. + + blank.gif + This can be used as a placeholder or a spacing element. + + bomb.gif + This can be used to repreesnt core files. + + box1.gif, box2.gif + These icons can be used to represent generic 3D applications and + related files. + + broken.gif + This can represent corrupted data. + + burst.gif + This can call attention to new and important items. + + c.gif + This might represent C source code. + + comp.blue.gif, comp.red.gif + These little computer icons can stand for telnet or FTP + sessions. + + compressed.gif + This may represent compressed data. + + continued.gif + This can be a link to a continued listing of a directory. + + down.gif, up.gif, left.gif, right.gif + These can be used to scroll up, down, left and right in a + listing or may be used to denote items in an outline. + + dvi.gif + This can represent DVI files. + + f.gif + This might represent FORTRAN or Forth source code. + + folder.gif, folder.open.gif, folder.sec.gif + The folder can represent directories. There is also a version + that can represent secure directories or directories that cannot + be viewed. + + generic.gif, generic.sec.gif, generic.red.gif + These can represent generic files, secure files, and important + files, respectively. + + hand.right.gif, hand.up.gif + These can point out important items (pun intended). + + image1.gif, image2.gif, image3.gif + These can represent image formats of various types. + + index.gif + This might represent a WAIS index or search facility. + + layout.gif + This might represent files and formats that contain graphics as + well as text layout, such as HTML and PDF files. + + link.gif + This might represent files that are symbolic links. + + movie.gif + This can represent various movie formats. + + p.gif + This may stand for Perl or Python source code. + + pie0.gif ... pie8.gif + These icons can be used in applications where a list of + documents is returned from a search. The little pie chart images + can denote how relevant the documents may be to your search + query. + + patch.gif + This may stand for patches and diff files. + + portal.gif + This might be a link to an online service or a 3D world. + + ps.gif, quill.gif + These may represent PostScript files. + + screw1.gif, screw2.gif + These may represent CAD or engineering data and formats. + + script.gif + This can represent any of various interpreted languages, such as + Perl, python, TCL, and shell scripts, as well as server + configuration files. + + sound1.gif, sound2.gif + These can represent sound files. + + sphere1.gif, sphere2.gif + These can represent 3D worlds or rendering applications and + formats. + + tex.gif + This can represent TeX files. + + text.gif + This can represent generic (plain) text files. + + transfer.gif + This can represent FTP transfers or uploads/downloads. + + unknown.gif + This may represent a file of an unknown type. + + uuencoded.gif + This can stand for uuencoded data. + + world1.gif, world2.gif + These can represent 3D worlds or other 3D formats. diff --git a/APACHE_1_3_12/icons/a.gif b/APACHE_1_3_12/icons/a.gif new file mode 100644 index 0000000000000000000000000000000000000000..bb23d971f4ce99b43dcadc7179deab4e3f55d2fd GIT binary patch literal 246 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIn&tKm;nhW{__jT$ShV!EGkg|Qki)QB^jv- z1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf2nHIbDd^F&3SUp#HU#9hW!Rw()J9@9Pc4|E2W2srx z@ZjD%n_KH1+_viO4gW0IG)3`1D5IB^&A~|*Z0siQ)e*Jc?U}v(RZqm-rsn%xldEMP i9?8v^arV~QxusXc{Vzw0+BY`Y83|alcZ6{=SOWlx{aaiB literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/alert.black.gif b/APACHE_1_3_12/icons/alert.black.gif new file mode 100644 index 0000000000000000000000000000000000000000..eaecd2172a091ee2994c73f33e784e336b23b58b GIT binary patch literal 242 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIn&tKm;nhW{__jT$ShV!EGkg|Qki)QB^jv- z1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf2sTRBTd^F&3SUp#HU#9hW!Eiwp#*PQqrY@^+(mQa9 zIq>=_)6J=N(?l8rJU#@b9ZU?|#8k#|TH+FuDboTL$LCUaCvA&aeP+vAqk{>XuXw(F ebwjlD^Y4XGxPKmyi?175+0@L8L7oO3fUlDhC^y*iC%Jku8u-*YC%bA zZc=KIf}y3QDTCrq7DfgJW(FOg=?oy-8JM#&cJ29GAmOljuG+p#>+^!)qA83W53Y$i zRmV;6*!V8-#*VCuOa*@qH0ND;#mM2YBw&+P*rb-FJO^IOEcFdnw_3sy#i%{~=Eb~? osgHMN$4+)vHJp`EcP`!U`GY!UILM{ophO`}&oUt=FmBNTY z$`ICVA7j^+h#i;OQDc-ga!qS+8Gc0FW4f z)Bt1yAj_Q32!U{ zRIo-qQptb-t7{uBm(~px;>}n!KArWR1^>`Cf~is&A3~v0s8aF}M#nn9GGt0d7v`yb z*>S>eMWL(I627?MNllQ7BkqHq)M=1k z=&Ky&zXVh2hPE6DHG1$Mj#+!@W<|fAeonA2iB#Un#%N(&&W1dtI~9BfQ#)e2X=lF^XcGT}q=AoZ{H^5&_C+Pv zN&hQZTYONvvH2qVcG~jIh^yqZXMG0jauI~J<^%?yjPC{pb>Ylqd7Qgl5*ph^Ulf=T ztUu|ceZK)dM=IDKg~q~CZoH&Cb~-~Z=;&lvYG{6Kc>2z^;Sv327g?kssFZ=dw}0cH zdw$mEtN!A<`J8^&z3 zt~SwiD6S8)Rjrr!Kx<)&vBl1-$xbOvcBi~nxrDC!TBPace;L%k*DDqrZ4t4XvN(& zu%4H=wkn0>)>bWw*7qy^XgxfL8hEr{3=!aT@x^9eDj^ytk&Chl$kO(lBLUN|dQ6Gs zqR_gQC$$$-23%rt``_I(>C3A7dOXT9Z$frk_k~-Ys+P;@AA_2Pg%%8=^ZRrL+?~|f zW&~d`K5oo!G0s}dw|gtsI8gBY`D(2K(S?RiMa{{iIhO(d)G0SJjuwocN&dl=)Ns$! zkAoL^`msv}wXFIo9^Egsd~xDITuw=a{)ty}PeNiaZ{?=q1Ff-;&+#A?LvlJm+3a2z z0EU`idSaEFK|F|qEq^5hpn?C2d=DQ+H3YkO^OBqUex<5bLo z9(N*aTe0*iA?|UPIVvKLCc?9Ag1I16-HvOfbsA#dH4-dk3 zhnz>*3E(FdLU+yVpuPUsliM=aeNjZUS*@XX3Z53T6iR8-2uO=XFwVs0@AhefEv8q zeI*^7gje{cZVN8?oK%ZT=2#U=<_Ih7M^R~)Ja%@QBEHt-Nj+won-qIvXTfK$!wnkr z2MQ*#TaAN%Ohqz*uQYER7$<|Jgd}A|ZL~mb$%8Fh^ z{1s=ft;T@}n?u#1Sd8|0dAq@XlaA<)Sy)vu-xZB|?3vPJ`3#PxQkI=}-aLquKdtW{ zRsg5o;PBjI;EgPh^zTEWZ?enGho=a|_a2#rB5>8 zTBKlTX=%!!_>+Z^fq{`h2V@1vb_Ql|iCuU8DGPkc5-<+lz3AMXubFeq{lvP)Ggp6^Q($uOC~PM5!3Knu5hd8zzVA-2Z^g;lkQyz{qtht`EC{l FYXAcbPG|rC literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/ball.gray.gif b/APACHE_1_3_12/icons/ball.gray.gif new file mode 100644 index 0000000000000000000000000000000000000000..eb84268c4ccf0146e661f51e63fc7d958d39111f GIT binary patch literal 233 zcmZ?wbhEHb6k!l!c+9}?|Ns9pKy>EJ?%lg*&YaoN(UF#x78)9AY;4Sc4JiKe3(3eV zR!A%=Q2NWsw3(v(5*CkrD310#bD$U2a#7+72kPI#`~Yw`N*?)jcGYB&?6 zl*5^v5@j;O_zpaf^Qf7s_EE`__xyKmPTmvoe(9bH{5w=PbF!#4X}t_l`&F_3!G;Q* IP6h^R09S}j761SM literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/ball.red.gif b/APACHE_1_3_12/icons/ball.red.gif new file mode 100644 index 0000000000000000000000000000000000000000..a8425cb574b1e4250b8cd35656432245cf4b51c8 GIT binary patch literal 205 zcmZ?wbhEHb6k!l!IK;s49|&g7{BLZ0=KudR1_V(2=NFQZS*(y)RH6W+GV>HlGEx-^ zN|SOjlND0(a}zW3^c1{P%YYIdrRf=|#X1VvAYO(;YG#REa(=FkLU3w9NosCVYLSAW zrKKr@;!hSv1_ovZ9grm;+ZmW0EOy=bXK>1Mb*$?2=q7RLtBj2b0*O~xQ!1DFD^5{O pJnUyaTmRk(8|hQW8HD_tlL9-OLb*IseTr8`t-rA*Y$5}LH2|rsMHm18 literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/binary.gif b/APACHE_1_3_12/icons/binary.gif new file mode 100644 index 0000000000000000000000000000000000000000..9a15cbae04ccda7ee515f0e56360afc5a0dba7a5 GIT binary patch literal 246 zcmZ?wbhEHb6k!l!IK;s4|Ns9pKy>EJ%$YNdjg1*#K=GenNJeI{LSj*g0+7ngQz*$u zRVXM;%E?StNXgGl%*@kM@J=lQN_do}XQUSEC}e|p84jtLC3?yExjG8LsRbpexk;%- z3Wk=JrVNTdSr{1@7#VaxR)B10V9xZ|wdbROfWzv!D*Gb21Y#8#gjW{Ev9DOlxiI_H z)^#HHvm9UiDQlh^nDJt>gl6-T1rM0J@~%VW#e jit!gMUf+_g-~76GhV}Y)-JD*HO`g_*&g~t+oD9|gOVnOa literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/binhex.gif b/APACHE_1_3_12/icons/binhex.gif new file mode 100644 index 0000000000000000000000000000000000000000..62d0363108d2585b7574f1eafa0749ae48e15f5b GIT binary patch literal 246 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIWsLS&DhwO0R|NR`GsU;7Aqtcl_&tI%shpX zj8uh!(xjZsWQCOc+{Da0Jq7R7GN6P8 zTBKlTX=%!!_>+Z^fq{`h2V@1vb_V85k6n8{8VES7o~yDia@YFk=4>QQyf+b%kUIiE6v`j kq<41P{%f~vu3nm((IxdxXZmdxm!@WCGePSPUrq*V0OwX&D*ylh literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/blank.gif b/APACHE_1_3_12/icons/blank.gif new file mode 100644 index 0000000000000000000000000000000000000000..0ccf01e1983e40365a9ab9f373b6fc497c8603cd GIT binary patch literal 148 zcmZ?wbhEHb6k!l!SjfQe|Ns9p|Nk?9f#N^Ekc`Y?g~Xx~1t67~r%;lSs!&jxl#`jP zkdmL9n3<=i;GJ3ql<+7`&qyuSQOE}IG8|GfOZ1ZSb9EGgQwvH`bCXhw6bvmbO&Jt_ pvM@3*Ff!-Xz$Dz$zw-23{>5{)-0I$ZZ_jW3Hcv(dYXE)}F?;|3 literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/bomb.gif b/APACHE_1_3_12/icons/bomb.gif new file mode 100644 index 0000000000000000000000000000000000000000..270fdb1c064a678acb8764f49dfab1e4930a437c GIT binary patch literal 308 zcmZ?wbhEHb6k!l!c+9}?9|+DEp8*nQ&g|a3d*;lU9UUEMX=$OMp~l9>3>ZN1pI=Bu zX0bwIQHcVO%FI(J$w*ZwC{4=AOjbzA&rQtC(^K$HEdxq;l%{8-7V9WvgLoMZshK5u z$@#fD3c;xbC8@bdsYMEgmX@Xria%Kx85o!tbU=22T*biBZ*bCc`Hl#c1H12gmgUBI zw%rtC;M!28($IJJckPX3ES?w2x?Bo89EJ%$YNdjg1**8Z)FBGcYhH{__jT$ShV!EGkg| zQki)QB^jv-1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz!(9+VBLGdRGBLf2?gAUMi29WIx%y|;K?))=oQ+_D9Ws|kbwV3Cb!G;~l zr6S87EaNL&_a?hVeW3t@!}Ye?nKK^#j99avpyTG(I#$(nk_Jvoof)on^{`p)&3!-P v58tszhQ3zU#BLwgx4CO~=RuzOzlQVSzZ;^Bd|G^1EJ%$YNdjg1**8Z)FBGcYhH{__jT$ShV!EGkg| zQki)QB^jv-1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz!(9+VBLGdRGBLf2?gAUMi29WIx%=I3-_IxxDa9BN8WnZTCdBN+UN;`V5 zvvyudlx5MGf7Niu+lB8<68M>}CwT0+Sa%>{VugiRTa(75mo;unPcK^%`XY`u`0=&t zU!@MXG|VX05I^^VF*R2EaBhQ*t$*G8!m22pl=_-R+Zy(Sw)W(nhPLXS$-P|O(_IV& Nt>?_0!_UcJ4FEU+X8-^I literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/broken.gif b/APACHE_1_3_12/icons/broken.gif new file mode 100644 index 0000000000000000000000000000000000000000..9f8cbe9f7604077bbd3a2bc8bc3a5bb5f569b838 GIT binary patch literal 247 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIn&tKm;nhW{__jT$ShV!EGkg|Qki)QB^jv- z1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf2Sr)tYd^F&3SUp#HU#9hW!Rw()J9@9Pc4`>z_|O^T zk}LelhjUMZx0Uz%<6KNN%O7PlP1)n6a$s{L_l_mk)%DU^kLsajo literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/burst.gif b/APACHE_1_3_12/icons/burst.gif new file mode 100644 index 0000000000000000000000000000000000000000..fbdcf575f78a5ebbd3eeac5bbd9f963962ab664f GIT binary patch literal 235 zcmZ?wbhEHb6k!l!IK;s49|+DEpZWiPW*S3UTAH!3F#{MV{__jT$ShV!EGkg|Qki)Q zB^jv-1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXn zDYZz!(9+VBLGdRGBLf2ygAT}iknIf2aT>es{4+SUl4tW3o}3LYCJ5%-`ZlvqY)y_i zON{zvlk8Qc_r#nUUz;+oS7*8wAfNp1ThKa>J&QI6cbF|deBP(?&CiC}j@vi=I#{!y ctx@66$5l65-@mTg36FLd3o%#&030@6>Hq)$ literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/c.gif b/APACHE_1_3_12/icons/c.gif new file mode 100644 index 0000000000000000000000000000000000000000..7555b6c164fc1b4fd61b082d8077fa9d91df56f2 GIT binary patch literal 242 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIn&tKm;nhW{__jT$ShV!EGkg|Qki)QB^jv- z1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf2sTRBTd^F&3SUp#HU#9hWL3V*Bp^eh6>z=a~rmo~; z@m;PwF+98fv}{9yhQgnc16&t10u@Ug6@{;Ldlgz{Obt2`rF%DR+wn(!`wtpSjoH_A d@zm!TvfmF~E%;F4@aA{Bxj;^{Ha{nWH2?tDSDF9- literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/comp.blue.gif b/APACHE_1_3_12/icons/comp.blue.gif new file mode 100644 index 0000000000000000000000000000000000000000..f8d76a8c23f018497587e3f99b1ca6de51b3f31c GIT binary patch literal 251 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIWz6d|FpC;V`F26w3!SH42u8!LNYRo6%va| z6o6D_oCMz{sEjG@SutI|Fl`#I8I43{F+7+RH9?U^n~B&57a> z9SY`avJ)3cpWb!+X3wWT_Y&^C>j_NskYN&^eSY~d0}D@y<%x+OBE#9DLr=Z++8Ul6 x7HBJQ=EA9jH5MFGT$gJ@mp5m{0_#-#wxuc*35QMb=U457e-D7YXCOLU#$QD literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/comp.gray.gif b/APACHE_1_3_12/icons/comp.gray.gif new file mode 100644 index 0000000000000000000000000000000000000000..7664cd03649021707e088ea934495978fb0d2656 GIT binary patch literal 246 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIWz6de`8}~1{hHM=NFQZS*(y)RH6W+GV>Hl zGEx-^N|SOjlND0(a}zW3^c1{P%YYIdrRf=|#X1VvAYO(;YG#REa(=FkLU3w9NosCV zYLSAWrKKr@;!hSv1_nk39gr0u+ZmWMC3fBUXK*TF)m~Py1H0L0ZcY^U=uj|Uqn)@& z`t+`&H+w$)xtDP7U5{X*hYXYW?DNZyDNHgr!s_U-Hfnv#g)JxEX01=i4l~r{ICH)$ lVU2;d{qukWdt+~JZ}<_zu;TaoO4H0{QT5pN7)DM8YXGT7UX1_% literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/compressed.gif b/APACHE_1_3_12/icons/compressed.gif new file mode 100644 index 0000000000000000000000000000000000000000..39e732739f562920d69e21b9d5f766103225471e GIT binary patch literal 1038 zcmbu8%S)7D6vm%!Ft{kRtWAqgQ<5~hoFu0y(5j?VVxWbZa?#}6Rb z^C4&mE(8ey7I`1M2JeEG;9*JiK{cogDnVhj&IhN#x!@!?SgZIT8pH*WAfQr!56}P? zAOQ@hO=)Venboj4_SAdly?75B%ShF$^D16p6ihnx&Uq)^!Jt?x>cx2xFCZgZJ=DW_ zhzF;Vnqq_|C9#;}U}{sET5N_bWHFyp6;;@N9LvZ#b)pWoE-9E4ry?rg_Jm@s!YM?- z_2>sN*-bmRKOwjwsVPQiQnHjB987IWQw!#tr5W>yb1);hAICBhaRU0vbxFabgE-Jf zI!yz}#c~?WZD}R_ASSzM2bs7qHzYO12+dAnk%NP&O=;MPteR=YeBi}sB=_T3Mgsdd z%-8tdmW)qmHpf@7+Sq7wJ@(F8V>|2!@rI@pL)%Sa4ik>0`8n`PG>cNN~PuHj#2TU&K?b$PjISFN2mlgUm*z2muv zKiQEemq|xslYK+k{%BxyxHmh}7Dc}w4}4S#{SXahUj#9ESDbc zOOHnflF24it!!Ke)S!Xtuzwj6iq1sMV&VMamBiM~1Dk->?y_AKLvKGkd3CL_zUO(} z{{Gh4ox9inc{4lTIae9-XIHj->p*v3PgZ}I-!Gd(0R3W>2Z59 z@wZv>Co5WRejm!z{yeqNojm@2_0WZ-{JG+hhh&B-mUxe ZEb;5(orN8>^?I=Ddd=ePr!Oz#=sza7#nJ!( literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/continued.gif b/APACHE_1_3_12/icons/continued.gif new file mode 100644 index 0000000000000000000000000000000000000000..b0ffb7e0cc026c1e0c383a17044f5aabcf4b5d91 GIT binary patch literal 214 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIWsLS&DhwO0R|NR`GsU;7Aqtcl_&tI%shpX zj8uh!(xjZsWQCOc+{Da0Jq7R7GN6P8 zTBKlTX=%!!_>+Z^fq{`h2V@1vb_QloiCuU88JzN5z4yk{OJ&c!6gd(UCY?Un$r?Nn?=Lqvv3P#w6Kw&mW_iT|AE}uhs$W)G1T8yg@&WtvAFs%+oyn@vrAN+!2FgA&7LgdM$msG{jgj*VKw;b&W_&MNEp LeCV-eWUvMRho4eP literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/down.gif b/APACHE_1_3_12/icons/down.gif new file mode 100644 index 0000000000000000000000000000000000000000..a354c871cd0b1871aea54b437a9fcd88608b6945 GIT binary patch literal 163 zcmZ?wbhEHb6k!l!SjfQe|Ns9p|Nk?9f#N^Ekc`Y?g~Xx~1t67~r%;lSs!&jxl#`jP zkdmL9n3<=i;GJ3ql<+7`&qyuSQOE}IG8|GfOZ1ZSb9EGgQwvH`bCXhw6bvmbO&Jt_ zvM@3*Ff!-Xz@*gEzw-23{>5`lI=eR?ORw&$xvkW+XnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf2i59!|d^F&3SUp#HpXaXk2Sl>&JZ}wUn<}Oew2Ebh zy5WrhZnywi7`v{UmEc1RMWQW;i796*RD-1HnCY( abURyR&WU;9JD3;O#qV)F(-6+dU=09`UszZG literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/f.gif b/APACHE_1_3_12/icons/f.gif new file mode 100644 index 0000000000000000000000000000000000000000..fbe353c28223f727deb5144a964b67aa52081e42 GIT binary patch literal 236 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIn&tKm;nhW{__jT$ShV!EGkg|Qki)QB^jv- z1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf2@fN%Gd^F&3SUp#HU#9hW!Rw()I|5y1O%gw{Qrk-4 za}Co**45@VTn>y2mrF4=IdgU;Y~koUdn&jyIjm;NN)0XFePuTmPrrRp@1UjePH&g! XquWjAXkF)P`eAc{t#G$ICxbNr*wRvL literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/folder.gif b/APACHE_1_3_12/icons/folder.gif new file mode 100644 index 0000000000000000000000000000000000000000..48264601ae0655bbb5b5539e54ab9c4c52c0ca96 GIT binary patch literal 225 zcmZ?wbhEHb6k!l!IK;s49|+FOJoEqm%rs*lV1NO|e|{kunZ*i;MI{PADl<=^BqLR! zpfo8bGg%=eKQ}QmPfx)+wG1fXQJS8STCAgx4dP`uq-K`rCFkerCyg@&WtvAFs%+oyn@vrAN+!2FgA&7LgdM$msG{jgj*VKw;b&W_&MNEp LeCV-eWUvMRho4eP literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/folder.open.gif b/APACHE_1_3_12/icons/folder.open.gif new file mode 100644 index 0000000000000000000000000000000000000000..30979cb52855157110d56344ce09ff29ad726585 GIT binary patch literal 242 zcmZ?wbhEHblx7fPIK;s49|+FOJoEqm?%lg*rWpeP0~jd&^9#wyELKP?Dp3GZnRyB& z8L0{drAaxN$qFg?xrv#1dJ5jDWk3m!()5hfVjYES5HG_aHM2x7IX_oNAvm?5BsDiF zwMfCx($bVc@h1x-0|OI-4#<3v?F`JR8oTcNGdShBI#=y=&2-5G4yn89^Q6URrb|x} zc)e?b^5WuCck>TOH!hekVIgPfp~Qt9URLv4mOfysiDC|%v8Jjt&35m)a4xxmqX+dL h7rU*#p8HYSdByGb-X0k#`er{rBo}PktY8g<%qclAuwOB_X8^p_SNX;zKOU}>LQ3y^g zC`rvtN-a__w6rv3Q2fcl$iTqNpaV3W0c1M^bDG7jJO2z$dEVUl?ms=DL1^Wsd78 zTBKlTX=%!!_>+Z^fq{`h2V@1vb_QlYiCuU8wX}SU+2eAh_5B^k_ROg-0w+{X^b?$Q zKX`{e+d0=|9tjPPcd_Mu)Ml%7PAUBP*kHbKD+5<3&kBD{#@jg@+pgRzznQIiy36?2 ILXnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf20T#RVd^F&3SUp#HU#9hW!Rw()J9@9Pc4`>z_|O^T zk}LelhjUMZx0Uz%<6KNNmX9Z{SfkK*HucgE9k$hhnp--1%Xa$c7hcewUAg{5?%98; H3=Gx)qghVl literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/generic.red.gif b/APACHE_1_3_12/icons/generic.red.gif new file mode 100644 index 0000000000000000000000000000000000000000..94743981d931466fd6403a80dc4d1425b744822e GIT binary patch literal 220 zcmZ?wbhEHb6k!l!IK;s49|&g7{GXO~=KudR1_oneV+Jr#{O1>vky)&eSX80_q%!jq zN-|Ov3QCi5GLscj@^ce2^Yj$FQ_Fx79;N9Ssl_@9*&tqqLuzJ;UUGh}jzVy1K}l+E zQfiTcp{1oMgW^vXMg|6E1|5+3Aln(3{XKT=`CK62xLURGi22&%H?LKSN;oNN&RD)A zj7{+T9dF5syeno$->jSG&*;OMYO`?t3LV4QtJ8%g=XgyGN!I7?Roi$yd81>RNCW@e KDqbH325SH#15FnI literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/generic.sec.gif b/APACHE_1_3_12/icons/generic.sec.gif new file mode 100644 index 0000000000000000000000000000000000000000..88d5240c3c3ee7aba7e51be6e49516277cd2c024 GIT binary patch literal 249 zcmZ?wbhEHb6k!l!IK;s49|(+%&;0*CbLPx61_oneV+Jr#{O1>vky)&eSX80_q%!jq zN-|Ov3QCi5GLscj@^ce2^Yj$FQ_Fx79;N9Ssl_@9*&tqqLuzJ;UUGh}jzVy1K}l+E zQfiTcp{1oMgW^vXMg|5Z1|5+3Aln(3b0VTHIq;y*eT9 pbHuxO``>OATea-a%QUllYxjTS@>KR}wi0z>>0oj07UpEI1^}8@T=4(^ literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/hand.right.gif b/APACHE_1_3_12/icons/hand.right.gif new file mode 100644 index 0000000000000000000000000000000000000000..5cdbc7206da8856227e36b9d8f1fe5668e162607 GIT binary patch literal 217 zcmZ?wbhEHb6k!l!IK;s49|+FOJoEqm%rs*LB%t`uFC-(gSRt{fL;*-;<|&k9q$(7Y zCgo%%E2QM-CT8a8DR`%r0VO<2(=$?wbriBeybOob%o4ri{9GM{;M9VW)ZC=hA_YTB zOH&5LpDc_F3``6 z1P@2d%A8Z(d*Iop;+0_slQ(LVa73?qy!_*&UOA1|IbCl>b_(7P3tlzje1;bjgEav1 C5>Ye& literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/hand.up.gif b/APACHE_1_3_12/icons/hand.up.gif new file mode 100644 index 0000000000000000000000000000000000000000..85a5d683177b439d3bd52a5fbe4f4b88e6b36a51 GIT binary patch literal 223 zcmZ?wbhEHb6k!l!IK;s49|+FOJoEqm%rs*LB%t`uFC-(gSRt{fL;*-;<|&k9q$(7Y zCgo%%E2QM-CT8a8DR`%r0VO<2(=$?wbriBeybOob%o4ri{9GM{;M9VW)ZC=hA_YTB zOH&5LpDc_F3``6slVT^wp$^;wzNj zocQ$p=uWvS+vn$eP!`KQ9AC&Oq&a`zGo|*%R}=iZ3~#^S+H|7K?YGc(Np|IEzH%$YO0yStg0 z|CyPYnPxMYW&ntYh-S?HW@gN0W@ctHnPvb0RaI3pGcy30%mA4)0A`s0W-|aYW&i*H z000000000000000A^uKOXlZjGVRCdJX>%ZHZXk4MWgu{MVr*$+AY^ZCVQFqIAWLO- zX>K4$b!TX0b1WchWp-(9Xh3CYbS`6WZ7d*DWpH$5ZDM6|ATc>PH2@*`1OWg51^_Go z0002s0Sp2F1^=KSj$~<`XsWJk>%MR-&vb3yc&_h!@BhG{a7Zi~kI1BQ$!t2G(5Q4u zt=2Z94c57Jbq!xrSezYad1i2Vl`geKT`f9=ebeIhcKwyc$G&!dYcqgkSA#%-MR_EJ zbY5(ce3FzZifTQ2m_Le|mzyY`jYOh`k2s}nVOo2vOmdj8t*~ISaDH2Wa&@$Wxw&et zaItv0vw_03Yrtj4nY6aX!MDTJx6W+Pz;VRQjk~p}!n}Ud+}`9@(X!gs(&;wmd!S3L z!_cGCXWWkSp0UcT1>ENDp1@Ou_~rBGgPB2j0ng~G#*l?WbG{62B1jJsMo_%=Ed+Sz zBSU8MDF2eYgHKg`4SU=Sq&9D1xIlGG`8y;2=ty2+-&Wr1sp| z+*p&)L!mrrx{P;qE30!7D_W(xwO&_&{k)0{yOM2Ii3Qo>JQ%8~Lbr5L*(ICO;i{?@ z_kvA3w_^)}KT4SJ(V0TC+XE?^m?+L z6!wPC#e7FIzNGl)+46zyJRL1}NZw1QuxEfe0q3 z;QxXQHt67k5Jo8BgcMe2;f4KGpy7rbZumrpAZqwwh#g{RA`B#!=tPPfeh9#eFveH` z02Qnlgof zW;df2035)|0XgbeB>-Q2Rc4k-Sc#*PY$D;NnsA;O;{?UP8mALmk_adjf)XmKm75k}C73-@+NhMQRIq`o ztHP+}tF*$JgqxRUS}U!63h5~nUsV^Zi(nR8sH@19ha#bhqM59%ksi5#qRPH7C;uzV z4jV0uxfYOZGEa1xB6kav8$q>~4WMoT=*kePm|BoYZKKo{s%We?POC+^<+jVhwW#vj zFTMbD`=Y?p_Ufs>d@K;A0})Wb@ErpHFaV|#Ox%K-JPNEa3LN9;F~J9Kpf3RYetZJJ zgC3kR!3MiL@DyA|q=d-{0FVI06hOsc zS~9_E=DTzWxMJ$9)`5z!CAdkL%x}aRZf#Kk7hjyG+DwaTEYgzD7D8nrR z%Xe@4V$6B_ZORB^r`d$r3q*i+cdxYVb;gE|5bE4uPo1=^fgjMF#q0B@7uW% zZVFv-=C5>-_`I(;?s(6xR{oUNL*ofK>T=tAx~VkU&AR6=vI4c!rIXBe;Us7J`w{g< zzxeF5lf5{`xm!=X(MUf(grMgd@4XO4o?Lp;qYGaA=E;)|qw~Wf5q-U-LeC+u%jKCd z(NQ|e{M1nMU;2m_HA$h*a3PZx0{!>DvdxcL3*b)ecE<(EQIL0F;@MFk01+KYm=qBOS;l2CKPYajusCb|WR(1beV-JQI)LKe30 zRT2D@6fWnx6B6N6>36Rj6;~lLf$U(+YfCvO5 z!X{ZRpP^2Ylth>%O@+x!@@tc2Tcmn4?J zdh?s$45v89NzQVb^PK2Rr#jck&UU)D6TRqDBI=rl7XMT)dAFlv~7g4Cg7 z(T++{I)qs^w4{d#g)Ig$(|3^ODD5bYX;gs?*W`3C;_0bR%K;X&B!!@d>CHfd!kKRf zHKZtU2|QR6!^t=`7)ZSiQDU-FZZOhVB*@8i_q1qD}C!6l~NeO5+|*FsL5x*x>t~*^{|KSC}S2QSeWcpqlmTa zM7B{3u|(FOYJtmN;p)-CF0QhZb&O9;yHS&@X0*ymOkU#>oU@X|t*n)(T%Gb+wyIS! zdS%Q*(JGhRp47OZWUXgaJBHpib*Hjr4QYk*Q=HVaHvg!oZd`~_+sP1hAHjkyVE-`F zt@_3@-OWZZHj)tORx32=^^SS_%2}wm7rTjAk4q1Vp8b{@u!c9x;SPKF!ypc^h(}D~jj?D*7&ljPuoRI*~1b`_& z`N=Xwq@A41s1O>t%K)}ctg;B^ddx4yI=1qTNky&&h-r*Y)>Nh9%w`!jKs6O5-;C3A zWh^f)&Utps$2xW4)EqE%xTAn_Wz-iBP~M#+<5~HxHA|u9WBf`Ygd1c zp0h0EBmo3)&-Z%81fMOT> zOEqSYl+m;RHS2g}s$O-gU7cjJi3w$slysb-?L}7T`rEqZGy!cmV{Qw3P{uYkvPr$> z+8J4Da_ZLw=H2QHFs_oTVjQFI4R1GYduH;(HMj@9>typ0)n$A(z|Wm-b&tA2R+8B3 z$W(40ZeZT@&VaoUX7N?KdEePKq?5JGK}-{z;IG1)r{6tTG&TI#52w(nwnPDQ9j)T| z#`py^zHxI4@#4~MHNO{l;~bH^4vxc`4XLY9Y`L@}Qb6l)Fup56TDKlruIc|P=< z)0@#f@AoBN)n^(b(RPDQI=Gh}NM@nBhkpii${}uKoK^jCH|+G*HO{!ak6Y&l;5)zk zPT)HDi0sJ%L!wjt1|+uSI=&Bw*m>xGy#aVt=4H$*y{X!urAYjPcMvThgC5e(h0D7L}B( z@oJyDm$yCn2VDO8*uOmQ4di>YO|bKAM-%AzzGLCb9@68tclj$FePmjP+8c4RP!2CoNwwBlen zFnjj5e9&`hN~SNF=YJ-6f_j#ML8xsrNP|iUXf+5E=i(}jS0f%Ga!FVZ4g*G7xFuZJ zG&&d{8F+uwCwW%Lgk|V-Rg!XPb7vx$b%2J3@{@&KIEPx;H*F{&q=ZV9bV_L zrL=fJkcWCGh~Hy5$N~j~h)RYC9{Tpcsmx zIEtiLil%sqsF;eXxQeXUivOL^*`2#qcEQOXgH-I$FpWgUh?RM6E`I)P_J6;`XjkGs%SvEd7Nc2iUp5;P@V zo6!wTb&z_%4$e12#bJ=y)fYBZRWQ*D{&-9CH4bAnkrY$xALUmS& z63HFGCPNHbEclt9pO$!0HlinrKN|`}ly)-#5Ti00qyDu432>u0dZQ6mC^Ob@>$W2y zN={ywCVOLR;}%6hN(wW&qyb>0(37K3ngC8(HdOX&n@C6_Cw88f zMp^oVuE79I8lz~sr1u!5Zi=HVw*k0!rATlofAelLGc;J3K4udKT3UEtdPPpNJYpJ1 zO{Z{X8V>=$0F2tGjGCql;5Rn^4lk=(A7OKNKs>SM|xOzrp z3WrD9s`m)1u{x`lQK?OOt4tcHr0|B2sHwOUgt#*SpK5cXDz1!kE{h{QXM(DKWO0WE zM6OB*(0Z*5AgxE?rW+umigK;=>Mm(BKUG+#xbrnT7O>!YD;*exLUOQbsIVmpVN<#- zsA`5|c!gyXulm|x)@rdbIULD(%N%ZXeQCo9GUAqhM^$b$angwL9@I*YMz3bi%+ zME`xbhe?nt6Y#4WptYZ}ojL%ZhiZfz^mZ`&v@8w<-F#eT#ykOSXxiri+@oXu7(pTey=ExN*3-TR6L0Vuu4Nh8J48F&hJX zYr2WxsK6V%X;U`ATfFn?y51#A4SNHNh_zAXv6+OtJPW;)B)xagiHTS?F9x>Li@nQ> zQx6-VuXKqAO1@uYzRAj->bt(|+rIAmzVI8r@;kruTfg>uzxbQK`n$jU+rR$%zyAOn zzydtL1YE!de832tzzV#;3d~qyrdisEQ0y3v+zXHYRKe+(!J?I$BQ;+d+!3EZjiq22 z*VvqPb-^P{k00{}?GhgRR7>b61(+4X!-)*^7@P@JcsLAI9SM<88JZWlJ07W8cO_Lp z9Kt^Q8fj@W8>t;hTwMcMlMM-yw~>$;5yhQ(6HRQ8Ch1is5s>;w#m)6oRg9TeHB~Xi zRfsUe54^<~wZx?9eoVoZhQL{-30{@iSd#EqedU;m$zObI$8%g$by>(;xl~i>$870W zK&e!6C72_z7R&XN@kIuOxfjj%$2#d+;Z?^|0m*gj$6?8vGg()I`Ic&Fm;Z1HoCU>| z^`*)bESF4)Rg3k>Gl3Pi99i}?%YYe}yoH;FT*~4I8J=0oEdk0N0moWF%qB(0UpdHN zSzM4A%A-{ft8B`E?92U>%l0VDza^B`yippZ%a}aLy?m6^T+V_y&EjlYANiPiEKs&7 zT}8Z`+{MaL0nfg9#;(c36M4^93DCm~8n=0y-M|xFT+o_{mA2d&5i!IHEf)-(6u?1~ z5&g^)J({T5&y!Hh0(s0AtzXVD!4O=HH$%fg2|XW7lsEj2?pRAZDjgUs!7PEamM~aq zgH$tZ!Q_~o3&y}e9n?ZS)I?p>Mt#&sozzOb)HKs#PM|+ftv~Tu0sr6Xp7oTp5+Wim zlw(J>pIJ))U>(+CJpltSw6XH7OZL6rv;kqwoPp9IVT7e!ZJ}Q+)^<(SWu0Vbjbwnb z)7}BrZr#)+vek0^Wg1$ic750ClGk$v0DBFg6|w=08rY$50ER{YXqUc!7$R|fyM}$( zy_(o#z1WORI*+|(Aj-19vZ$2(6t9PNu(|=bvm%~C*q#k(&yu*J-PZflwUV~iFIo>w z>ely)trlh3k0;#F`mGqqBAwmXN~YOAFaf&_*x`GGjt#U7YG!GQuCKt_we;Gru%_4g ztxbB;wN0U|TBt)n-PH}&`t#e`U2g2{N`t$x_dTP=E!>gn*Z-M--1J9ai(0$^VBY(! z!@gqGTpgyn3j^-`-URSAXFcEa-QX`U-16$EgT>mcJxkO(Ew7Dl6}#M%qqf_KM1NCc zx~tm|9@hM`Eql$ZM!=@z-K5g(N;Imv{_O%XrUj4ZyA2Vq25!Aj)hf^Zxupx_J@DWy z{^C0nCTBA9Rx(ra*ux3IQ?gc_#;+g9m)M7_HUA8N(1WXR$PJTsDj=M+D zq&8mTt9#(*s^9pHfpO-pXq%=(Zk^+MhEYxgY5v}8K1FRlxRK}x~j^iYbF;R;I za$CMlOMPhm>7YL0qVBRs5UERA<5nK4YHD$h+vSIG=|hw0NAQ7v4yI0<>$+a(ZFlHO zP9CN{*)oi;HIBN*UUxFS2+BSIvz`R6W2(1KhIRev)K0qD-Rt2l;EaCW%TeW$J>2+2&v;F8V-!` zP2Mw~y>N&nwky{#?7gL|(UpLHK@O6N)~@x84P zB8jDHiIe#C0pB3`4c?e*gD?ANYbl z_=I2hhJW~opZI}4jTBVEChWuu6~T{Bn;UG>5d4LG5FR^z%cSM_@yK72-@&2ZUk^;2 zi%|N_Ow#|A!>fNd&nU;BZ=9(=oiI#bub@+F?87GI#%UaoxnGd>cvLB@#Fsf&Pj#5V zMaba7`=FK38Y%p;`I$y_{IB`YegXVqJXEWR#wvZuz0Ab%92nlu$E+Ftk#NXRY5vbh zl{<;d26f5koL`R-|3u0DZmG$^DVCw+(f{;i6zts2AYg2UNN#6Yo+xRyqw2OZO^@*H zu5kM5axEzIiCDSR5jRsRhfduJ$U{<}R%ebmr8ckLS~K~(MP=fzu*(FZ+v%!!O|<=b z-*db!C7#jw*pi*xmYa_nA6y_Hp`TsP)L`M=BA{87lqy%UZ0YhP%$PD~(yVFoCeEBXck=A% z^C!@tLWdG9YV;^lG!>RIZORm*)2K_KN_9%L>eHl7ur|fG<15&K3b|&rSOEaqv}(^* zxOi4AT()lE#s$#UEZwzswGMfk*X~}68x9-@yMyqCyAl27m5cW;;J_3a(|xOWBIUZ0 zF++}g`6I({ne}d#IJj_x)T&bhIGva?WXq5L`uz-XblTb#aii5exwq5axkHM*-P!lV z9T65VZ@!@Q3fl+Y?jT*-c!BKN3mk~t`#0JN;>S;5EPeX%wcslV5b)r=@ZlcI>`pJ= zG~(sXnYTuKz8`hf#rGX&+y7}dL2DHxwjgW(OkiLE3o58!gLz5FphT9r_ud0&T}UBE zJIn>yhoOy<-+uhL_8&a~LYG#F1wx2mSPedCV2v4emg8c*aR?uDUxg^*Y!-r*+zR^b z7vyU?zIXzRN9qV+0SKbyoQatD^&pp3R*7YW063Qxm`+x}0Gep3Rc1y~*4LSs&1ETx zYf6r}B5Yp)u;-p^Vz=D|fnLyEoD0lZ2yc8AdZ-(IEudg@&n*hunQ1bh=%j7B2_B}M z%9$LBDfU+wi|+&orKij>+QwOc?s-6X9a?q>*%#!SXRN0?=5BR zu+<8CkzwhwTJ4R++RF@L_2TIys`85aP`2U?YVHNuYB2CvwjwMjygC}%>z*9$x*&ZG zGYMA2f*Ceqr#BYRF+_E)rrM}Y_V^;7&oYc2pARQ|fCUTh`$TOC>s&6noEZvVyNNk< zvk-|gOY|McawamBBhTw>k|{nHZM@aKOptj9M^J$UHD3*&yq+Rm^sMc22<(1i({O57 zBzr6*UQ9RrbjhJE`R~g9x~=i6gqc^eHhANG9*hg=)>C#Of zNcTf^N}aN_>Hiq5Z2NA5h5#Sx5ec2@d+kmjP|J?{12vyLh9 z$yaYGpQpQDbIsUKiz}oj@Cv$5sTQIBN8l$O8gaHeCR|aGVyo)s+SIj_{1gl z&<6g3TmSaHs6B#+kw{?_V-&qu#xAyiEK#Y*8poK%InuF?cDy4V^Qgx?^0AM8{39R( zDab(*vXF*6Bq9^3$VD=;k&b*MBqJ%wNm8a5RA+fy%c6C`auXV(jl8A!)8OGSqp)98xBy1(QgMuE&?go4(C0MkIg54r0u|}VhBwCv&}t@apxrF!KJ#IOg#Kco_Cjbd zEB^t}fR19K!7PSF4~h&+kdzDKv}P!%5ejj}fD^}b20PXO3Pfz98#0xGN}*xXG2pZl zm&gZCS8CFE@-wKY$mvgSSPfTf0;T|QDpG3-k1^rPW@)v^**9&)AY*ltQqyv8)Bir}kATl!b9niU;_-K!Vm7-0PRtqkyM+a))%E+ zEkIg}h+`U}}^@l7D4fj}73Lo5$+$i{Z%QjSUIN zB{t2FeY`^l`)PX~&To@V^JIB~LBBUfr9<*UM&a!4SQ~!C$Z*Gm7 z^ZemRfBDXS{xhKYN#Kvcanp~}7y&{pYEd(qGXY~+ski)SIy+j-R;IL=EloyGUpaHM zmbEr-t!MU$XVjt=50urZ=(hP6(KdbbtG(>$O{==nxQ?lV>(%U7Kl`B3=Jd*ZJ?d2V z$Zshjck0Ad*5(Y_P+bg zZgpFG;P9rCylXvcg9{tK+9q|l)l6(|JImjY1~{?>9&mK0TjS1dcfmgnau_;@(DwFT zzLzm<+ff|P{`UB)Ieu=8V;bGkrui3P^YBo&oNrGmHw$x}aad28=>HyO^^`{*a%vOY z-8qL1p`&i-o|F0K1Wvi8hu&$e%RJd#S2{cl9%(dI=*%AEH;jvo^l`_T?evQI+mqgQ zrqfv#{^~EXv92YH>pkl;pF6YLRCK`~T_delIMi-FnJE^riql~{5FHOSITtz0mFM#1 zfn51&{|?)4E2EItXn3%*xao;McuYy(dDDZC^&EaZ>|-zc+0(xEw!b~@bFcf|^S<}K z|2^=7FZ|&Xzxc*KKJt^V{N*#h`Oben^rJ8R=~KV@*1taXv)_A=K9iz>b!Ksni8N_y zPyGH{rtHjL&Lc!NukVZ}G-v3`i`t@`?0jxv^FQ48^B=pDtN*M1C078}T^is6LtxZb zsS#RT6lguvMxmYp>Hw%iAOkJ9UIb$Rkd|lpm0LNLZ&B4Q)==Tp5?Y}V3IZA?p-G+L7RD7N zJRuXFl^N>Q5w2nV9Tq{&;aRbtIq~6QX_OS=As3cmBD|Gp8N(pHVROY{B>-YqIpR-2 zVlOOWAmrc=9-wR?U}#z3Ygtt%ves?wlQ!(2I#5cHW0^vSn;A`pDLE%C(tRm4M zB4(YSDOQ(dIg=s$6)o~0b$uT&E|+o%AXc#z{Mp|)pwlv@#Gy!+c4e3U`BpT>mM}U* zo9LpD*#ZHEp!R(uIEJG*jw3miqdA@?$oO$dhMW0olZ z1fXO_X4g<+L$|bKnz@*f6(w{nkN?kq=ecSX3t3(E(*pUgS$=R!qjC zOUlVp9$r?~!^e$YRpt+`YybkRKw(5#)p?j)o{yDrr3858SDsc)9@O;6iR9rN;&qV{Q^+=69OKXx(kKrX|W~PY^rdKkndfQtTMr;Zs zk3q?)*`{o60ByF~UfPy$vJbVLMcUY$=e6FPZD;8b=K{6mVK~}!VhfXa+toFkfkmg< zsbqCZWrDOM zj7fPm6nLHh&czFvego#}DxbiKZTYo)Otu zXoZqbh92jCrd@&>4|GBbU3TMwT4#?{fJ+k5hL-4za_5nLXOfbckhWw?-e^hoC}&iF z0^HA&dFXvI<-L5^qX?;$5-5@$W_~WIl8Wg9B~Xi=5Z^UiVhm_{y5~lqXt;D~dyZ+0 z!suF3sF})Uhwf+Iv8kKBDT#3eV-yBl)~TK5sf>E(qR!h~z8RL{%$l0ozD25Y5vqSV zsi1})qvENFiejg7D5UynpWW~;VtE4Oy5 zw|*{8lNa`1Fz!PpM4~vjLqN=l`$cRrPS!5Eq8##~L7n2pE}##R z;HsEHVriB;g%rqs6cmVG6$S$aN+SwhpaiCD3|807x}Yl#mdduG3u<7@!sO42EX)!u zGOC{@EMZjTqA${H$1)fNdF|4&;%srk z7_wB-R+QETVjcG2R)K9e4dT;QZ6k2)N_{OXN<$<#);6_mGWKm%;np7lE;b2n781$d zLha$I6=12YiYT@$UL-a0{Agn_3QsDExVlQ%Ua5---^e#%IAI3T(NnFeLN$fQi*GcT^rA}k= zzAyZGQE$cKF={M}(f_Zz_OJi`F8~Ly01q$$7q9^zaP__8d|`$0Deyd!#R69aRJ>U~ z`ecE@;~m+jP23{}tI(5GFrWGt2v??q$wonnutavmWn_o2j!+Z2elk7Q>kk|1b&QF_P%@+3>(-Z$1x?IjNjvXBCg=ER)faOd1R4axMd>ZhrA%s7f#&h=777 z0Bt}R1F|bCvuj#0HLG(7GnqRp=UA#rI+N8MMa!t@P_htbb3b>r3Cv1R^9>Lgbt02AV!yOvt6Y}Jbd)wUTzBb%7B(C| zHkCESU?`d;=QbuQ>0f`flgzVo$O>e)(T5FnLQ~H%vs`1hP<<{pB+n`AkajBHGgRC* z58QHog0@#jhhT5%Q7%BZgtv5iaF2y`Ry+6n*w0!6-EfmY45hXx_ysS^3VM5RT`Q!5 zaR209=eC!5+hue`g*Yi;$To+58-YJ6Yv<#{wYLEjYD>CyYj0|G+j1rEcA0j!TUV-O zL%14CI0=_(gdezFf;bYdaA$|nRK)3|hWL1^>07gSeVDx1=>ChF56IVpqcog%Q5PdSxWxs_izmS?$^Z#kEDxtD)A zn1{KTk2#r_xtX6iny0y%uQ{8yxtqUv{GM;7)uO)g7Qqsu!`|ySG^{VKFCXNq!cLNj z3_AOQVf(5?_tDecR>S!Upc^VWB>@x*qT*-i0m)+Q$7%u6E|pu|EIWN{(So}B-v5H} z?rf!xY|kFz3|5u`in=0p?O~Bss8^sR?QH9+dJXb}=dNuVHr3=#E$qhCAN&E{_5l;l zBCH#G>2|N>3L(~(ZT$iTD=hEv`XT3jIu{_~A?EGs0{i5$l@N*`Uv00p*A%ipqOZ^H z72@FdZf+)S5-2G9BrdzIUoEe{6jNcYwxl_#%ERpZLXQ2)|54U!y=YUVT4V7GGjSB-7`Ncp z+ylS`kUc`cN=pt3Vch-M^HJKXJ?pT&dYkdvv$b~!emw*V-9L=o-#r|~inkyPtYpC7 z>k)Mva^1ZJ;oHv~&(X^1$s+F=w=n+WLk#4jlio`{D#^U_kQX-%fTGX>aYF+xV|hg#!}NYLw{REbL#EqT{V*t#5}(5Uq82CwV?Dp z@$3BoWB`LFk^r$;Uq|UxK0l03aOa~L`fJnN_rCRGf1vyp-*-RjhyP0k*9PmrvNA*xy%}x zhXb_hy?DKgOy;IdtJmzddsLVlU!swF={m}M3*=o})bpoAv@v%GfHs)ZB=sZ(MTNDf z!WGsf76x^8Hc9yj8hQsuT1qOqk_S`N=ZDG?=<}*lSahg3yEU~76XkoAt9$u{*>zTi z8?3wxYU*6NtoqW^8sixpTg2?L=W~0F+GO=e{tFH&o;g;0aNNlZAOBbPY&sD=*YgdZ z9f*&JDA_AZA6abPrkK~^S%LU|M`=AbtrqsEMI?)3cwI7i^Xe*S_<1L;Z` z!79BBMw+;gn7U17YQnULGiQl9a^~=acT!)-n>uHmL@6>Hq+U#`5FNAu6EQLiAWAHX zHS5keheUYXmd}Wur&>Q91({T7l_)I9k%cPtK-FUq-$aX6g%|o3ror)DT{k| b@W92JKaW1W`t|JFyMGTqzWn*9LI40ePu4mb literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/image1.gif b/APACHE_1_3_12/icons/image1.gif new file mode 100644 index 0000000000000000000000000000000000000000..01e442bfa92332ec1c6f6a3a1310a41da8be5cb4 GIT binary patch literal 274 zcmZ?wbhEHb6k!l!c+9}?9|+DE|4&Oh1EkNKnF$1G493RB3^;(|KfjQS%wmPaq7nrl zm6@kdl98%VP@0sJnXHhKpPQJOr>EeZS_YKxC{52uE!I)U2Jtc+QZq~RlJj$Q6oOL= zN>X!^Qi~J}EiFwM6o0ZXGB7YR=zwelxr%`$x8Q`Q<}TB46{|}Ro;FH4vD|TwVqCRu z(oHG-o-GnG^BH|*TNeaW6tnVAVoo@j5?96H;J7r$On>@QlgzzoTd%A$K6Qt0Rl^Fa tT+{HAkBVmGwl?ql^5gHGE#Ge!M>NIeRkegTICnX-n>O`N&=O>@1_0HcVjBPe literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/image2.gif b/APACHE_1_3_12/icons/image2.gif new file mode 100644 index 0000000000000000000000000000000000000000..751faeea3644ec77fc2758b18522443c86e11e88 GIT binary patch literal 309 zcmZ?wbhEHb6k!l!c+9}?9|(+%&;0*?=FFLyGiRm&0Rw}vu`$EUGYm708H|BE6rlLe zFC-(gSRt{fL;*-;<|&k9q$(7YCgo%%E2QM-CT8a8DR`%r0VO<2(=$?wbriBeybOob z%o4ri{9GM{;M9VW)ZC=hA_YTBOH&5LpDc_F3``6AFlZ-6WvSM=7VP{@&>xS8Bwhc1-A7qQa*6llSbi$3t0`pjwvYB~D2%9p5teUK9 z!JHj-nw2N%{)ee19sAhWn7?J+(8*}hLs;X|rU4J$iGeWf`wdw5G*d!uZZa9_W^ ocG{GwRjPF}8>Y#Xb1hynfA)0M4)%aGYyBN0JvVI*5@fIj0DN?8ZvX%Q literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/image3.gif b/APACHE_1_3_12/icons/image3.gif new file mode 100644 index 0000000000000000000000000000000000000000..4f30484ff64db93ee44ed0a9ad7ee2ddee74b3ff GIT binary patch literal 286 zcmZ?wbhEHb6k!l!c+9}?9|(+%&;0*CbLPx61_oneV}_Y$7-kwX7z24&fZ{*Dkc`Y? zg~Xx~1t67~r%;lSs!&jxl#`jPkdmL9n3<=i;GJ3ql<+7`&qyuSQOE}IG8|GfOZ1ZS zb9EGgQwvH`bCXhw6bvmbO&Jt_vM@3*Ffr(WYy-K9fu(Z83D4y_B18`CzVBL=8|T?3 z8Cj-fRpz22to2}(%Yyfw7ys+~3he!($l^D4LHYfmjv4i)2j@WJuw z(xQEj48%`M?cSeKc2$dA;a$a_s7`|)|JgXI)5;nenzd@X8XG%`OT79!SOcd{3$T;) Lm^~+0kii-Nb17t& literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/index.gif b/APACHE_1_3_12/icons/index.gif new file mode 100644 index 0000000000000000000000000000000000000000..162478fb3a7f690884b1527488a27a9d34ab497b GIT binary patch literal 268 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIWz6de`8}~1{hHM=NFQZS*(y)RH6W+GV>Hl zGEx-^N|SOjlND0(a}zW3^c1{P%YYIdrRf=|#X1VvAYO(;YG#REa(=FkLU3w9NosCV zYLSAWrKKr@;!hSv1_nk39gr0u+ZmYaJ$CK+XdvLQdala8OzZQ4*F%+d^j>G}%y8WC zp)<%eSG-8|P1Cu@LU&KQy{J}XRik+(=tTM=GYuMB5h}jym8(tr{ zTHty08q@pqX@{qpFA8HkpSQf;)z`l$D#)_MC9vJG&E2N2-g4rU9X0k#`er{rBo}PktY8g<%qclAuwOB_X8^p_SNX;zKOU}>LQ3y^g zC`rvtN-a__w6rv3Q2fcl$iTqNpaZfI}mo*BX ubMM=^lVvk>^@~}aS-AV^f3&VBD9tXZudR+|59;m-w3jTH=pio1U=0AHb6^Gl literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/left.gif b/APACHE_1_3_12/icons/left.gif new file mode 100644 index 0000000000000000000000000000000000000000..279e6710d4961d7644ea2e3e39e6afd300147aa8 GIT binary patch literal 172 zcmZ?wbhEHb6k!l!SjfQe|Ns9p|Nk?9f#N^Ekc`Y?g~Xx~1t67~r%;lSs!&jxl#`jP zkdmL9n3<=i;GJ3ql<+7`&qyuSQOE}IG8|GfOZ1ZSb9EGgQwvH`bCXhw6bvmbO&Jt_ zvM@3*Ff!-Xz@**Nzw-3iM{+%$5nXSNI_AHs_0#Z5ammWC>ec*qNb!1QNo>>3 NI{94w6cGjnYXFzvI#mDw literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/link.gif b/APACHE_1_3_12/icons/link.gif new file mode 100644 index 0000000000000000000000000000000000000000..c5b6889a76d72a1f052d2885a725e7065344ee9b GIT binary patch literal 249 zcmZ?wbhEHb6k!l!IK;s49|(+%&;0*CbLPx61_oneV+Jr#{O1>vky)&eSX80_q%!jq zN-|Ov3QCi5GLscj@^ce2^Yj$FQ_Fx79;N9Ssl_@9*&tqqLuzJ;UUGh}jzVy1K}l+E zQfiTcp{1oMgW^vXMg|5Z1|5+3Aln(3b0T)_`4k}HuzIfQzD(=$g4aWpcJy9n?OYMK z<3neVTdwpcAKpI=-d5i4k8cuSl8s+i>=HJ`A>=Y=gWs~oHDEJ%$YOO($b8LjTyi|@tVo`|#kjl(c zD9K1wC@4+J$xK#A$0Aq je4J*Rr#@1aJXdjR@wJsoZ!aBYW^HV0ZfO+YWUvMRZ1!36 literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/p.gif b/APACHE_1_3_12/icons/p.gif new file mode 100644 index 0000000000000000000000000000000000000000..7b917b4e91e8004d40241f2c031016f3cb414caa GIT binary patch literal 237 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIn&tKm;nhW{__jT$ShV!EGkg|Qki)QB^jv- z1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf22^PEdd^F&3SUp#HU#9hWLHC{`p^eh6ea~4tRaf(| z_%3JAe*U`SyKG~C!;gtpQxXFgX({TuJQm*75*apCqqytJp{nC4Q*X#X Y_^R}pPJ1}};XQE`%{%V$b23;10Di_)fB*mh literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/patch.gif b/APACHE_1_3_12/icons/patch.gif new file mode 100644 index 0000000000000000000000000000000000000000..39bc90e7953103a7fb4d6dbbd3efcfc1cc8de759 GIT binary patch literal 251 zcmZ?wbhEHb6k!l!IK;s49|+RY&iwyBbLPx61_oneV+Jr#{O1>vky)&eSX80_q%!jq zN-|Ov3QCi5GLscj@^ce2^Yj$FQ_Fx79;N9Ssl_@9*&tqqLuzJ;UUGh}jzVy1K}l+E zQfiTcp{1oMgW^vXMg|5Z1|5+3Aln(3^CEWb`4k}HuzIfQzD(=$g4aWpcJy9n?OYMK z<3neVTdwpcAKpI=-eOD+8f(7P$v8QjjESn*)KFqotJLnbYDxf$LnDLk)v8Bb)9>m( q*HL9Yo3!quRNC&zr)@sV$^5d;vQo}swQXy+(HAuD>9yx%um%8r)mtS1 literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/pdf.gif b/APACHE_1_3_12/icons/pdf.gif new file mode 100644 index 0000000000000000000000000000000000000000..c88fd777c4b2a85b930eb4a6b68440c88536289a GIT binary patch literal 249 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIn&tKm;nhW{__jT$ShV!EGkg|Qki)QB^jv- z1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf2ITpM2d^F&3SUp#HpXaXk2Sl>&JZ}wU>twhgl(8#J z&4;IaU+5wAJaJ`3 kwKt!oQbM;s-=_PA@BRCyb&avi?yYTZ7J^Yx{G1Hd067U;U;qFB literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/pie0.gif b/APACHE_1_3_12/icons/pie0.gif new file mode 100644 index 0000000000000000000000000000000000000000..6f7a0ae7a703000c365896477c32f9f1434d14ca GIT binary patch literal 188 zcmZ?wbhEHb6k!l!SjfQe|Ns9p|Nk?9f#N^Ekc`Y?g~Xx~1t67~r%;lSs!&jxl#`jP zkdmL9n3<=i;GJ3ql<+7`&qyuSQOE}IG8|GfOZ1ZSb9EGgQwvH`bCXhw6bvmbO&Jt_ zvM@3*Ff!-Xz+~Oizw-23{>3JXu0=Fn+uq4rbVj_b$!S{Jq*b>ox4e@+uPSrG fY~A@idsi_sTAZ5D!6YVVJJJ1GWyGRRCI)K&$B{!c literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/pie1.gif b/APACHE_1_3_12/icons/pie1.gif new file mode 100644 index 0000000000000000000000000000000000000000..03aa6be71eb2efded05e937f1ad79549ca2d56bd GIT binary patch literal 198 zcmZ?wbhEHb6k!l!SjfQe|Ns9p|Nk?9f#N^Ekc`Y?g~Xx~1t67~r%;lSs!&jxl#`jP zkdmL9n3<=i;GJ3ql<+7`&qyuSQOE}IG8|GfOZ1ZSb9EGgQwvH`bCXhw6bvmbO&Jt_ zvM@3*Ff!-Xz~tJ~zw-23{>3JXu0=3z*v`4OaPFr@>FpEKG8&zNm_A7^cehR7 q{3odT-{ZSYE(_O7ykRZyxV`aZjoH-0n$0tdUlfJ#w+AvXSOWl+b4fP< literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/pie2.gif b/APACHE_1_3_12/icons/pie2.gif new file mode 100644 index 0000000000000000000000000000000000000000..b04c5e090868dbcea50043700d52179ba99e89a4 GIT binary patch literal 198 zcmZ?wbhEHb6k!l!SjfQe|Ns9p|Nk?9f#N^Ekc`Y?g~Xx~1t67~r%;lSs!&jxl#`jP zkdmL9n3<=i;GJ3ql<+7`&qyuSQOE}IG8|GfOZ1ZSb9EGgQwvH`bCXhw6bvmbO&Jt_ zvM@3*Ff!-Xz~tJ~zw-23{>3JXu0=3z*v`4OaPFtZ*%}klI+l54ZqwVk=`G`N qqqzCzcVC|^a=f79z@jnzl=39bRIB-cn#w!p?CVf&?+9dIum%8pzDGL% literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/pie3.gif b/APACHE_1_3_12/icons/pie3.gif new file mode 100644 index 0000000000000000000000000000000000000000..4db9d023eda78f499c5e5efb7d6739d0d450652d GIT binary patch literal 191 zcmZ?wbhEHb6k!l!SjfQe|Ns9p|Nk?9f#N^Ekc`Y?g~Xx~1t67~r%;lSs!&jxl#`jP zkdmL9n3<=i;GJ3ql<+7`&qyuSQOE}IG8|GfOZ1ZSb9EGgQwvH`bCXhw6bvmbO&Jt_ zvM@3*Ff!-Xz+~6czw-23{>3JXu0=3z*v`4OaPFtZ*%}klI+l54ZqwVk=`G`N iqqzCzcW*N`uLwVHCM7ial+@(%Il4wxJnexD4AuaG3PW-L literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/pie4.gif b/APACHE_1_3_12/icons/pie4.gif new file mode 100644 index 0000000000000000000000000000000000000000..93471fdd885b4e54a6ebcfb68fa98626f3d43d75 GIT binary patch literal 193 zcmZ?wbhEHb6k!l!SjfQe|Ns9p|Nk?9f#N^Ekc`Y?g~Xx~1t67~r%;lSs!&jxl#`jP zkdmL9n3<=i;GJ3ql<+7`&qyuSQOE}IG8|GfOZ1ZSb9EGgQwvH`bCXhw6bvmbO&Jt_ zvM@3*Ff!-Xz~s==zw-23{>3JXu0=3z*v`4OaPFtZ*%}klI+l54ZqwVk=`G`N kqqzCzv6IghDLmwE@Ojtg`DD^c7sH|;f6tbO23!o*02@O^$p8QV literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/pie5.gif b/APACHE_1_3_12/icons/pie5.gif new file mode 100644 index 0000000000000000000000000000000000000000..57aee93f0707a6fea58637c351c4ac1dae6459cf GIT binary patch literal 189 zcmZ?wbhEHb6k!l!SjfQe|Ns9p|Nk?9f#N^Ekc`Y?g~Xx~1t67~r%;lSs!&jxl#`jP zkdmL9n3<=i;GJ3ql<+7`&qyuSQOE}IG8|GfOZ1ZSb9EGgQwvH`bCXhw6bvmbO&Jt_ zvM@3*Ff!-Xz+}_Yzw-23{>3JXu0=3z*v`4OaPFtZ*%}klI+l54ZqwVk=`G`N gqqzCzdnff4?UOy9X2Yes-Xz+~Cezw-23{>3JXu0=3z*v`4OaPFtZ*%}klI+l54ZqwVk=`G`N dBfa+_^}iWi*Dq8}v{CBqS-80Up#c|zH2^Q-Xz+}3JXu0=3z*v`4OaPFkWM->GJsune#*ygc&t5eqP cin@0;&wnp$nZ|PQtB_G$pA6d$4F(2l04BFX#Q*>R literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/pie8.gif b/APACHE_1_3_12/icons/pie8.gif new file mode 100644 index 0000000000000000000000000000000000000000..59ddb34ce0f42f40fc010aa2bcf059d891fccadf GIT binary patch literal 173 zcmZ?wbhEHb6k!l!SjfQe|Ns9p|Nk?9f#N^Ekc`Y?g~Xx~1t67~r%;lSs!&jxl#`jP zkdmL9n3<=i;GJ3ql<+7`&qyuSQOE}IG8|GfOZ1ZSb9EGgQwvH`bCXhw6bvmbO&Jt_ zvM@3*Ff!-Xz@*dDzw-23{>3JXu4R1A-L;ud>%okkhl!IyUaie(+qXfR+ave> Q)*p2%lMkH{VP&ue01>A?od5s; literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/portal.gif b/APACHE_1_3_12/icons/portal.gif new file mode 100644 index 0000000000000000000000000000000000000000..0e6e506e004caddde40da13470f5b566c4ebd3e4 GIT binary patch literal 254 zcmZ?wbhEHb6k!l!IK;s49|+DEp8*m;Fw=PE%$df<#taM$ivRpVGBS%55{pU{fK+Cl zLP!lN`jBehsZAsfWYa7fK8(M!(H)lmpeEhtIN zO-e0NFtoHZWl;Rd!pOkD#GnH-odIM!19M@xy5abNeolJ^dKQ(i&E!y0oZhYAIz1P__bl`CXaRbu>JEQyKU^X{_%FW>4o vqif4-qpv>D{n{&YXnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf2=@z^8d^F&3SUp#HpXaXk2Sl>&JZ}wU>twhgl(8#J z&4;IaU+5wAJ;6lrj$UyQTKrXC=eAut`Q_@GqDYq{i?eZ? fuRb@A(YSxvky)&eSX80_ zq%!jqN-|Ov3QCi5GLscj@^ce2^Yj$FQ_Fx79;N9Ssl_@9*&tqqLuzJ;UUGh}jzVy1 zK}l+EQfiTcp{1oMgW^vXMg|5(1|6X33?SPXnCmij?fGaR;jntH+P+NdaQBLW*w$93 zLXW4dLa(j`>C2pYt0=I?YR#HS>z@C9sN+1ND~Ts;Qmd-42b05628YQhH#GTgelWA? zX*zt-Xz@**Nzw)%~qgf4szES6oR(^g_8+4;}QR+O8Rat3Y55;}UDY3n~ OBkprQ{}oXN25SJEJ%$YNdjg1*#K=GenNJeI{LSj*g0+7ngQz*$u zRVXM;%E?StNXgGl%*@kM@J=lQN_do}XQUSEC}e|p84jtLC3?yExjG8LsRbpexk;%- z3Wk=JrVNTdSr{1@7#VaxR)B10U@n!|b?2W!n^SiVYewRG7AFm!*eRWl9lSzTtP=4S z(YLfe5`E@s3_lC2EJ%$YNdjg1*#K=GenNJeI{LSj*g0+7ngQz*$u zRVXM;%E?StNXgGl%*@kM@J=lQN_do}XQUSEC}e|p84jtLC3?yExjG8LsRbpexk;%- z3Wk=JrVNTdSr{1@7#VaxR)B10V6O7mwdbROfWzv!D*H06&kJ4;Roc;eowd{9p;(CH zi7%4jOn=^)>HKMOOmxr@^Rrv9(Zj|os#X5-Q4yu|;5S>$t1~+pUK<~i5YtS$=vU@u yeU(L%F~&2zjqBi^) literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/script.gif b/APACHE_1_3_12/icons/script.gif new file mode 100644 index 0000000000000000000000000000000000000000..d8a853bc5828cf534c4c46a0efbf4b1d7d3c52fc GIT binary patch literal 242 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIn&tKm;nhW{__jT$ShV!EGkg|Qki)QB^jv- z1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf2sTRBTd^F&3SUp#HU#9hW!Rw()J3?6|OcFmLXwbvQ z;yXWN*R#T&@77%j8VV0WP6%GqkhE;|xp+C~4`X#h&eoZ4tM=c%ZhDQk{(Ri#ES<}4 d7Yj^x^9CF~_};qCSmD=yXLEt#WPVNtYXEP%SK9yp literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/small/README.txt b/APACHE_1_3_12/icons/small/README.txt new file mode 100644 index 0000000000..deb96702b7 --- /dev/null +++ b/APACHE_1_3_12/icons/small/README.txt @@ -0,0 +1,6 @@ + +These icons are provided as an alternative to the standard Apache +icon graphics. All graphics in this directory, with the exception +of rainbow.gif, are 16x16 pixels in size, rather than the 20x22 +dimension icons which are the normal defaults for Apache and are +in the parent directory of this one. diff --git a/APACHE_1_3_12/icons/small/back.gif b/APACHE_1_3_12/icons/small/back.gif new file mode 100644 index 0000000000000000000000000000000000000000..e331454726bbc19cdcdd3867ffcae217a0fde8f6 GIT binary patch literal 129 zcmZ?wbhEHb6krfwSoEJkQBl#*&@d`0s->l+r>Ez@fddR+p!k!8k%57gK?lSGsbyex zi`aFC_kd@D&y?=4?(Pes3MEI<1Y!g8G%~jxUU1@6RIiH;$6BEo^BN2cqBwk-7hXtI c(vnrUxMBN-xh<~83yn{BaU>KdGcs5M0L&38p8x;= literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/small/binary.gif b/APACHE_1_3_12/icons/small/binary.gif new file mode 100644 index 0000000000000000000000000000000000000000..995f79b9b10d5a49fd6e6d9f641d3bb65cfffa02 GIT binary patch literal 134 zcmV;10D1pMNk%w1VGsZi0HXf@|Ns9vIXP=4 o#kZK`47H){6`LuGH;j-%Jne!zs_mH6LPMOYA{Q)|S&IY!JF>VnX#fBK literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/small/binhex.gif b/APACHE_1_3_12/icons/small/binhex.gif new file mode 100644 index 0000000000000000000000000000000000000000..3d54a5458e6edfde1f60b8a35d549e3af1552ffd GIT binary patch literal 131 zcmV-}0DS*PNk%w1VGsZi0HXf@|Ns9vIXP=NV?p<;}t+_F|n1vIhdG61y)fInX+{xz%o-MD*`-pgKX5xCVZ_5 lPsPf~hJ=DqCWLWTOyuOYZ1$d>Ba9hs3e#^gj&X!xZAVnu4@CeN-d>06V1HFU9}> literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/small/burst.gif b/APACHE_1_3_12/icons/small/burst.gif new file mode 100644 index 0000000000000000000000000000000000000000..d882ceba9cbf05051d5081f2e102ebff5f24edac GIT binary patch literal 128 zcmZ?wbhEHb6krfwSoELaz<~priULty691oD&Y82+%PWWh3>1H|FoGC5AOfV8f!UQ~ z*PVX`hZb>6bP*BCs6S}H;Vd99C5S^ubKfnY9r=Gl6W4NkFT36}`PFx$95FVrz#Gvo Z(|nHUXljWp;?_Q1GLa!b)18UI8UVh_DDeOQ literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/small/comp1.gif b/APACHE_1_3_12/icons/small/comp1.gif new file mode 100644 index 0000000000000000000000000000000000000000..712f36afdb27370918ce1eb008be6073aba769e6 GIT binary patch literal 130 zcmV-|0Db>QNk%w1VGsZi0HXf@|NsA#l$5~0z$qaZT4Q55rOtD`-T(jqA^8LW00062 zEC2ui01yBW0009=D7xJKFt$LdB@lxJ4RqIg#Z8m literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/small/comp2.gif b/APACHE_1_3_12/icons/small/comp2.gif new file mode 100644 index 0000000000000000000000000000000000000000..7759eb11f95a4bb3803ca55eae6c3ff8fd100b96 GIT binary patch literal 131 zcmV-}0DS*PNk%w1VGsZi0HXf@|Ns9O7#M_vgsrWuz`(##T3U0)=KufzA^8LW000C4 zEC2ui01yBW0009>NV?qqFg8)DEpK4KIl+xqbkqNgD~s^aKww; lWe8G`jyjbQNm3FtI?)idj0B1>qD63^77l^1cw9^X06XYXE$jdQ literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/small/compressed.gif b/APACHE_1_3_12/icons/small/compressed.gif new file mode 100644 index 0000000000000000000000000000000000000000..d3b156072ac0b62c0248694d2d05791379e34927 GIT binary patch literal 128 zcmZ?wbhEHb6krfwSoELa|NsBl+1YdE%sFu2!277EYykl;1`tsE$->CMz|5cn;(*jL zFuPjpx+AC8q?t7P$~sH6D{%rMQ(HBiPS!|-)_OUXyj2ijRTh5h@?e)dzw#N~vZiai c6)G%M%rgTM8yr{}o0lx>>ev_S%EVv|0H!@EhyVZp literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/small/continued.gif b/APACHE_1_3_12/icons/small/continued.gif new file mode 100644 index 0000000000000000000000000000000000000000..e1c9f2cfa68034f0439e336d3b3903deb44a0883 GIT binary patch literal 114 zcmV-&0FD1gNk%w1VGsZi0HXf@|Ns9vIXP=|;7%PM|whF~X2*V%{U5E|8iMaEOD$ U0n_;{NXL`HRB1Y&&_@CQJD2_|n*aa+ literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/small/dir.gif b/APACHE_1_3_12/icons/small/dir.gif new file mode 100644 index 0000000000000000000000000000000000000000..7b37b099177d12b3f6ee7056c03d992b09e7fee1 GIT binary patch literal 132 zcmZ?wbhEHb6krfwSoELa|Gl;U@2op;;J}Urwc*~@+N!b)V4(Pug^_`Qi9rX%1F2&GNR2Uen0VOOkQ~&?~ literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/small/dir2.gif b/APACHE_1_3_12/icons/small/dir2.gif new file mode 100644 index 0000000000000000000000000000000000000000..425d6e4b77ceb7ba16ded08c4915c809acf69c12 GIT binary patch literal 122 zcmZ?wbhEHb6krfwSoELaz<~qrvy+Q06{i$?9a~$xbV@b@7%2W^VFWRBKmt>yewCRwrrVbz0%P@q&p!pQbR!HK;_&hjwjs0n_k|_ba-tRk+Il!xvcWvVE3&b1Cxh RG|&8^tTFrSX;&r&YXB6~L|Om< literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/small/forward.gif b/APACHE_1_3_12/icons/small/forward.gif new file mode 100644 index 0000000000000000000000000000000000000000..2997466eb4de77500cbe27060b1a590f251102ab GIT binary patch literal 125 zcmZ?wbhEHb6krfwSoEL4($X?JJG-Z+=fHsj=gysDfC0syEQ|~c%nUjp0gze-W+#hX zTmETtFwSL&2y5Nl=5irbM5W{Lcb21_)0{VRxK0$bkc%jd_Yl5)#{CVW($PnOg`QH9 VToX4n&1RWCdxjo&kqQHYH2_QCMz|5cn;(*jL zFuPc2E&As#5ERnD*ARJtfp=NqymCk7r3mVwz!V%Hr- z1E&XvCVaS5R(RiAy>mgUql=e;(y~pho8&ujXu&V@o)YW0l^; H!e9*mJvSwK literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/small/image.gif b/APACHE_1_3_12/icons/small/image.gif new file mode 100644 index 0000000000000000000000000000000000000000..dc3d95ced763c4a905d8ceee4b2550e2131fd42f GIT binary patch literal 126 zcmZ?wbhEHb6krfwSoELa|NsBl+1WikJqHdPcpnwjl5F_?nk54RgW^vXMg|6E1|1+9 zs8RsPcDC4c=iE~pb*_oUQ#(Fu98;_~oS3sjVNNUao_t9rW#;4UEG%bvrx?u3by&?> e&3OOfw2*gItqmas!g_N~w>q49yG@Lf!5RRR*e}ok literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/small/image2.gif b/APACHE_1_3_12/icons/small/image2.gif new file mode 100644 index 0000000000000000000000000000000000000000..a5c40f15508516b54f02ecb77b9995116dc11308 GIT binary patch literal 138 zcmV;50CoRINk%w1VGsZi0HXf@|NsBMz`*}fQUH4)0DHBJjFeJRS^xk5A^8LW00031 zEC2ui01yBW0009|7`oiPN}S-D%%k z#wa;mSK3`9k(pCGM`QUUra7VZmHVu_rmbdA-1QFo2l NCU4lW(}RJ*8UX)gL+=0p literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/small/movie.gif b/APACHE_1_3_12/icons/small/movie.gif new file mode 100644 index 0000000000000000000000000000000000000000..7b4a42e7a0eec8e4508903e9bd49cd966e966e21 GIT binary patch literal 134 zcmZ?wbhEHb6krfwSoEL4($X?JJG-Z+=fHsj=gysb{`@%u7%2W^VPs%nX3zogKx!G7 zy*+mMeAYkV+1#MabHG}Fse$nzdz^H8ru>rzC6{fBxi)IB^anlsy)r`O#>SQkwF`?k i-+B_~9;vx~3vcGG7n{Cov&^1%&M%y6veyh225SHs|1u2# literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/small/patch.gif b/APACHE_1_3_12/icons/small/patch.gif new file mode 100644 index 0000000000000000000000000000000000000000..100484e59822e79e22ab469fecd4a39052a66875 GIT binary patch literal 182 zcmZ?wbhEHb6krfw_{6|qX=$0Ao!!&ZbMD-^=g*)2|Nox>3>1H|FfuT(F)03%Nvc%v zO)M(O%+vEON=(g7EpqTp&d>|?^VD-mWzYes2AOpTmr2ad8N2S7sdgD9bMoA>*d;jA zG*oa~#%+fN-d&Iql96D6GMaovr)0~p+w&0R?vcik1 Ky{BB67_0$$w?x1I literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/small/rainbow.gif b/APACHE_1_3_12/icons/small/rainbow.gif new file mode 100644 index 0000000000000000000000000000000000000000..8216b89bade87b795a7345329da487735f3e07eb GIT binary patch literal 3811 zcmX9*2|QHo+ddH{AxoAlA=?Pq8Eb=SjP)JMn6Xa`Ml#0M*kcR^Nimp;vQxd3HA&gG zP{>{hMJ1K2r{2-6a=6k2nDoQqb?SX0=ifo1OVxD)*A%?C=kWsLqNg*gMnlaOlHxTOc20< zz!KXE2Y^c~F~0BUQJ^eB8vwL{tO*bUf-x+@CIAvQ*$SYR z&94POIgkkeEO$8&lw%=q08CD13E=<$2jOfb2w@M|2>=kr4#Qe70Dyr29t80$Py)OL z0M|f30t6+1A-3%hJN6ulhyTQ80pJ`vHvpD`bO4}(pdgD20D>TzRnZ`bW~%{~3v0mA zv*01tc8+DhIt0`L*dMDFWL=iM0o&SGAekKnAcHZio~?}mHvhk4U6}o-vkUuQ06YiD zR#Yp|w6yc|^G?~>CRdM`9LWn~Fzkx#EN)tel!*A>@%LA#thBFDynC1OFGZ_fOG~0j z!l%^-{rItQM+c;n+}(}pL!B8ob4Fl9fcS!_Ix*ok<#u}J^l9KV5Wg6ou)OkKXLS|x z2_w5MD;x4XL}g3Gb$3?|l#Bco8OimRiv;QDuEJaJL-d*ML~g28hWV*q<5t)GlCuv5 z5{tvD{H>44nNO^u4gt^CCpdzEn$wBT6^}*AbKTURC+jExgqY2c8ibWBh!_jr1VNSj+5_ zp*2yT57lD%aNQo+A+u1w3bd6cf9h*Kj}N4Y9(vfjaO$8D{5SmSd!yTmm$xdjBR`%f zA7q+8y&C;Rsj-OI^E8wG{nQXm#R^G{-G)!9xpyw+#2fN1siC_n%#W#pRSEN*f2n_u zY63767tK{LJ%x@aLn-7U^17ssd2DejTM&9ORZ8hPJnES9HQ?n&)E_NT zN6w(Z@?Om@K9^DLVOZ&?&PzDwnBKHkK0mM!^(x0OAzAmu^#taDf|c<`^D6<uj6|Y%%DOL(v@tY|+Aw)l?I3cCNKRBTjtCrVn_-h%?cGew=uk2$MXjYD} zA3OPIgpviV6oEt6a^d9`rd*sHS^x~zJFP&_BYGEu^UuMEc?4JW7kZMHf27t%y-gGM ziT~QtEq4DPzzR`Fp8*~W2Vc}^aIxPaB;Ts6 z`zI;F6U`CLu$0LnUGkrDmBthppe{Hka(XR2_Y-qGQLjhc0^Y)Dg!V4X1RdUn7b%LU$dF-mY_O zcAYZ~_vSHKH5T8VR66w0BG>F|gHOWR0p`Kiw?}=&0pDb9SGjFfD4sK(rYJD;%pONS zUqYA7u(voXcy}cUR1?wwAC-%>K#~s~p9gZB;DMF)){{hc{f84>Ji?iQ`YysRqFQxh ze)AFcC2kfVW13UQ7Qrg^^jCd-mS*U$X}Im7nO5$+`q-}_r;U2%KA;UuClLQ67<0aU z!woIx<5jgS^AyVa#89$a&-7S+{qET*F$ey7@@-3LF;SJGcG!zE0q|*VSN+G>oQa4c z7e4=!oHx818nC7B?WI>?))U2NqVM~Ae<4()&yA5hrrW*02|RqV7(U|JE#>p$YLV$T zIzINZhxn5>N>A;5j>YdS`|SVXJb0G4J0e(ZD%&mBU<;|swG{KfsY|t%3D|5DiYZ)I z*DEZ)`lnG`D{DgQXiOvLJ@u549VgwABV$Bot)Qs{=a=>K-KX7cXzp9pNBV~aA^(!? z0~#SSdcwW>W1A)6yix+*<-JXB5uwIEUfo%8>r+t9Ql*5rF5YB{+U|yyF@?QEU;4rN zvoaY{}F4+jl5k8=GIY!8}5^F~Xc5H8a(s8r+vNK0~+Q zM`rR`aCVQwC3@7aZ{FfLFUfR+v_#zAPLpz~;h8fMmRvwPZbjLYTpF^HT|?Y46Y@LD zbq;E!%GGjM|C2?@oJYO-lv>KIm1+pKt;L>EUeQPt-)?m3q=jo0at5C`7pL~(2XB?? zDj)yKoO97axc>7C{Ly#xrEV>9UrU(^ro_idBb0S&CxZzxqeq7~pkYsK>J;Oc#!uHD z2jv$}-G2IP=_z^<3xBV0N0qa6x*kbSWX33^9QAT@DaIfaBGNJ?M;i`)hV|&2;?7ym zTISQt?|rkmX_$3*Me*QIfsNwYJpQv#bG%@VEd5VLVH>TdTBEPQFAqhiD|9@O-d94N z+z1>|&NtZ=yc2J^<%oR!a`FX#CZ$&jQ){_;+S4{mnp`XT0Or(2d+eI~rS5~V@xW4G z{TRtSIHEvJeRBHe;~`sz+qYKLgQkx^xqN%(Qpzju@1&9OF?Yq-yW2y;#j_L0lFIhE z>3T}{m$TjmS z59mqmj}7HC70Y~kV=~BSf7nnj+ayI?+F*=7Gue40Y&M0gcw@32@O>Nlb*g64E`Db< zx2BgeZKX)^+`cj<}BrgL>P30~YbyOSQty`|}~>ic&$^6r{#F<>`7E8jvmyWfPj|A;@fc2;vGk+V63TQP~E z&+k46?>5l&-pAT;;7r~NNFs21T9;oR4>jEM3mL@CA{`el`G*%dhV(dwItv?Ax?3O( z0$m9493B=s29?utfIa+)?-n`R9Vm9egEgQgn+HU}Nn zW-}tb7>NW|QFBn~!jTB`;UaS%uBb6Xyo9A&(+7DJR=c4(9Xjcz&VlVx)X{aehw3J& zZHL4#GkU9&2GcJ}OzEm9Uk;k}+pEz7Yv}*+2raaR=JyL7f+iovB^yn-?>8s&wUH{$ zAtFT3$0fqJccK4sopWlAaj6XZFVM4;BM=ZL6VhXEV9E0OUJCux4yN-+zgIUb^b9@O%n(O@t^2cZhht_OD)T$9?VpQ0JBWbp~kgVMg>QEva_~YrS<4tsr)3M(+~T zfUb54hl`+J5cmJ}h)$ZNlf@}UVwqp3l$W^)u~<_4AZ2|m8Ga}xTsI|42Ytma#({>; z$_TjI7SJr}B+Nzq%bhK8j_P|Hse%G-1tAp*vIj-uI!^^f889g6);a}o#zd*hG#9Da zEA87?(!_k|$efm-_*}7*xEloyt2sqtzB&|Hd}bQJae?qSZE(={aK+V{bS=@9gqI(+ z0@I=*9^)lb6aR>ue><2Pf0xftC+S%s_Txu5SMW8%3SEb-B!3m9fc=XCs-an;*R$xM z$LBATDf&i**O%Nfe-M(j&XbOS?ujaS$L2^8kb-I09ObgNQ(+<$OAI YQf)BD<7dvMP-NGBf&PAQ3ILe=54mLULI3~& literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/small/sound.gif b/APACHE_1_3_12/icons/small/sound.gif new file mode 100644 index 0000000000000000000000000000000000000000..a7a89ffd9ed29c24e1759e48291cadb875f6562a GIT binary patch literal 130 zcmV-|0Db>QNk%w1VGsZi0HXf@|NsAUb92DJz}B3c_ZS$h0022kN&o-=A^8LW00062 zEC2ui01yBW0009=D7xJKa0M|0iNY9L?>oRm4WtwVAYcqvtDHa_pF~g>Zy?Whj|;FJ k&6i_@dN;{osSB_y&_-ah8I>H<4WSc3QKFczSdah!J59YUXaE2J literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/small/sound2.gif b/APACHE_1_3_12/icons/small/sound2.gif new file mode 100644 index 0000000000000000000000000000000000000000..07706e07b86d25525e8e7fcb8cd2d8b10c235d49 GIT binary patch literal 119 zcmZ?wbhEHb6krfwSoEL4($X?JJG-Z+=fHsj=gysDfC0syEQ|~c%nUjp0gze-W*duL zK7aHX7^e#>G_TrlZjM+_!c@ literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/small/tar.gif b/APACHE_1_3_12/icons/small/tar.gif new file mode 100644 index 0000000000000000000000000000000000000000..59c3ffb9a5f0dcbcc0052a6dc8b428f4b033d316 GIT binary patch literal 132 zcmV-~0DJ#ONk%w1VGsZi0HXf@|Ns9vIXP=H^|M=26Efy0jDoCS8nDw3MpHX8$hcs!0R5&$~~!7=6l literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/small/text.gif b/APACHE_1_3_12/icons/small/text.gif new file mode 100644 index 0000000000000000000000000000000000000000..66ceefbc8c46837738701f2ab48d202b4df62686 GIT binary patch literal 128 zcmV-`0Du2SNk%w1VGsZi0HXf@|Ns9vIXP=L7D<;z<5S%P>S%fZDrUCEXNey i3D;T)3BKR#h$NV?p<;}t+_F|o}`C)Qk76hx+MVW0-gHlm8q0>wI1hP+I5AqX7Z lsY3_=D?$QFWeCnFftzz@X-@K f4p@7|h&XnDYZz!(9+VBLGdRGBLf2ygAUMi29WIx%-I^d?))<_JM1*!l}uu2Kl{c)an9BQ z8Fjp~isqGPnlRppzAozM@n_rZ?DB^@TMqI1Z!lq-XpvS})uOfhlGZ1!vqC)g^DkYQ rbCHkPIiy`w;vU-;D{*7rCt7AIb`rH-)ly|T)gs(25}jS#oD9|g^MhHm literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/sound2.gif b/APACHE_1_3_12/icons/sound2.gif new file mode 100644 index 0000000000000000000000000000000000000000..48e6a7fb2faeb6ba254a87945246f5ca5980583b GIT binary patch literal 221 zcmZ?wbhEHb6k!l!IK;s4|Ns9pKy>EJ%$YOO($b8LjTyi|@tVo`|#kjl(c zD9K1wC@4+J$xK#A$~K Lz}Ywz1_o;YcDqp^ literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/sphere1.gif b/APACHE_1_3_12/icons/sphere1.gif new file mode 100644 index 0000000000000000000000000000000000000000..7067070da2786b9842212ff1ce2307fb404407ce GIT binary patch literal 285 zcmZ?wbhEHb6k!l!c+9}?9|&g7{BLZ0=KudQXU@!=IWvuc!PwZC0S8e0=NFQZS*(y) zRH6W+GV>HlGEx-^N|SOjlND0(a}zW3^c1{P%YYIdrRf=|#X1VvAYO(;YG#REa(=Fk zLU3w9NosCVYLSAWrKKr@;!hSv1_ovZ9gvM6S23_u6rAu}z1QM(uhlIPp`JtRT@DHy zZ8JL^S8aON%CRcz&DRnUR>3@1XNE@hlZ*^I1j}_C#yT z68XztxyIW*eK)gq&Gg$oObhE&HaxGaZep#g4-2m9Y;B7#>??2R@5{BXndV`dHEXt- HAcHjk`1fN- literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/sphere2.gif b/APACHE_1_3_12/icons/sphere2.gif new file mode 100644 index 0000000000000000000000000000000000000000..a9e462a377c8d451bd0c0d07a47035bd44caf57e GIT binary patch literal 264 zcmZ?wbhEHb6k!l!IK;s49|&g7{BLZ021L(HV_+~gHfCU8Q2gf?l95@gkXTfr0HiYW z6iPBu6$(m|ax#+@Qu1>XGxPKmyi?175+0@L8L7oO3fUlDhC^y*iC%Jku8u-*YC%bA zZc=KIf}y3QDTCrq7DfgJW(FOg=?oy-8JMdxcJ29GAmOljuG+p#>+^!wLzQ;)UT5um zk+|bSXOMfYd{L=zjsF9o(~1rvGBq{}GB`LmSXvkRdn%jF4af{C6R?=uy5ZaLzjm9G zwH8$Kxi4iXD)_78aNoVF=4GE7r)afPMP*}_m05#Wld*D7Z?_kl#}r$ALGzij95@-Q E0diYklmGw# literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/tar.gif b/APACHE_1_3_12/icons/tar.gif new file mode 100644 index 0000000000000000000000000000000000000000..4032c1bd3d407abddd0f0e8801e3091726574171 GIT binary patch literal 219 zcmZ?wbhEHb6k!l!_{6~Q|NsB}`}gnOy*n%{)ZE;h0R|NRxrAh77As^X=jSPa=sbmz zj8uh!(xjZsWQCOc+{Da0Jq1HcOH&2!)H0x~M`?OSYO#(&Hi(zukeXSdmz{U7WG~8yuhh5Zb<@7 z`xV^^pIq^?J6sl`b?E$;oi=gneQc#~{w%G2Eo$=bQcK8x IUrq*V0QdG)RsaA1 literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/tex.gif b/APACHE_1_3_12/icons/tex.gif new file mode 100644 index 0000000000000000000000000000000000000000..45e43233b845960c59aa8933251d6d745b324031 GIT binary patch literal 251 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIn&tKm;nhW{__jT$ShV!EGkg|Qki)QB^jv- z1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf2c^13&d^F&3SUp#HU#6xa!*tin>9Z0|^A1!l(>hWb zZ!PfsEZ4Gxo$}LGGYd#m9-20(LPaIeg)1oN=Z{6M>Y}HwOe>foy~6k})9y8|ETZxl nuQycuR$g`V{oCDj`rkkOugz?zPGxp)?{Kpc$nTBfWUvMReehfo literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/text.gif b/APACHE_1_3_12/icons/text.gif new file mode 100644 index 0000000000000000000000000000000000000000..4c623909fbfb54658f19186beec8d362f87e233b GIT binary patch literal 229 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIn&tKm;nhW{__jT$ShV!EGkg|Qki)QB^jv- z1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf25f;1ld^F&3SUp#HU#9hW!Rw()J9@9P7P`C+IwEjh zoojbq@AhdAxLane{lx8+w_BW5Lq@1~%@UylHdfUEOTOIP6XtsB<@c_)dDA0}cD??? QSNCCuzu3fEy_^iz0A2r7i2wiq literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/transfer.gif b/APACHE_1_3_12/icons/transfer.gif new file mode 100644 index 0000000000000000000000000000000000000000..33697dbb667a8c898bc501cedd8039a3e9e04272 GIT binary patch literal 242 zcmZ?wbhEHb6k!l!IK;s49|(+%&;0*CbLPx61_oneV+Jr#{O1>vky)&eSX80_q%!jq zN-|Ov3QCi5GLscj@^ce2^Yj$FQ_Fx79;N9Ssl_@9*&tqqLuzJ;UUGh}jzVy1K}l+E zQfiTcp{1oMgW^vXMg|5Z1|5+3Aln(3Q#G`%?loA)#Gq@m*=ucI?DJZ$h{7jq60EN$ z%~d?lR>S0McO~B8j-}Ir=et8&oIMkM8Y@liURvT6>$dvF%11Mo3W@nQRp?BsQ#|oZ hcdptv6Cq9pYXE?dSF`{C literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/unknown.gif b/APACHE_1_3_12/icons/unknown.gif new file mode 100644 index 0000000000000000000000000000000000000000..32b1ea23fb6f6195f1bb17adf9c3cb2cc29dfefa GIT binary patch literal 245 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIn&tKm;nhW{__jT$ShV!EGkg|Qki)QB^jv- z1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf285X-Xz@*&Mzw-23{>5{AIi%LijXHkMRw1HyNzyFOS#mnvM?d*oFAHE` Gum%9J?KeFD literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/uu.gif b/APACHE_1_3_12/icons/uu.gif new file mode 100644 index 0000000000000000000000000000000000000000..4387d529f69f77810347be63429d13ff38bcb2c1 GIT binary patch literal 236 zcmZ?wbhEHb6k!l!IK;s4|Ns9p|NqaNIn&tKm;nhW{__jT$ShV!EGkg|Qki)QB^jv- z1*J(jnaK(%`MHUid3p-osbxS3kJ9vv)M6clY!ENQAvLo^FF8L~MXnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf2@fN%Gd^F&3SUp#HpJvB@7K6@PEKNyM9n&%bmCrCe zcjss6%XbLBY-{hkn53brAS;k_~V>SO;rqEX_zty4nJbR|}ofI+Ll^r*| X^XnDYZz! z(9+VBLGdRGBLf2?gAT|RknIf2@fN%Gd^F&3SUp#HpJvB@7K6@PEKNyM9n&%bmCrCe zcjss6%XbLBY-{hkn53brAS;k_~V>SO;rqEX_zty4nJbR|}ofI+Ll^r*| X^XGxPKmyi?175+0@L8L7oO3fUlDhC^y*iC%Jku8u-*YC%bAZc=KIf}y3Q zDTCrq7DfgJMg|?A=?own8JLoL`d3=Lojq&DmV<08H)chf_{g}X9%4v)7BSC#N7g2- z#f}=s?(`k{vcq_8jpbY)WyV!4N-Aq^MwZQ4x?oEC?F~i2;bkXPZnEj*mSpYLJUDmD atT54C`TIV6aAK=hU_0K-zaxNw!5RQ*npTkj literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/icons/world2.gif b/APACHE_1_3_12/icons/world2.gif new file mode 100644 index 0000000000000000000000000000000000000000..e3203f7a881283a15f895af86b7727878592257a GIT binary patch literal 261 zcmZ?wbhEHb6k!l!IK;s4|Ns9pKy>EJ%$YM8W*Rf388d)^;y=HTjLc$%#G(=fAeEV? zP?C|VP*9qblbNiLlAoKHnWv}VomvKz@F-2sNG;Y;$OiE;98xn&^pf*)brgbA3rbRR zlTwQm3@t5985DoAFfuSOGU$NJ2ieZRTp_XR&O5bJ*Ohi!T+-@^=jL?!gy~R6SmeCA7ufyx{6*ATcJslr}Jelts + 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_12/src/Apache.dsp b/APACHE_1_3_12/src/Apache.dsp new file mode 100644 index 0000000000..bbb644ded9 --- /dev/null +++ b/APACHE_1_3_12/src/Apache.dsp @@ -0,0 +1,109 @@ +# Microsoft Developer Studio Project File - Name="Apache" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.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 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 ".\ApacheLa" +# PROP BASE Intermediate_Dir ".\ApacheLa" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir ".\ApacheR" +# PROP Intermediate_Dir ".\ApacheR" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /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 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:console /machine:I386 +# ADD LINK32 CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "Apache - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir ".\ApacheL0" +# PROP BASE Intermediate_Dir ".\ApacheL0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir ".\ApacheD" +# PROP Intermediate_Dir ".\ApacheD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /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 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:console /debug /machine:I386 +# ADD LINK32 CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:console /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "Apache - Win32 Release" +# Name "Apache - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=.\os\win32\main_win32.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# End Group +# 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 +# End Target +# End Project diff --git a/APACHE_1_3_12/src/Apache.mak b/APACHE_1_3_12/src/Apache.mak new file mode 100644 index 0000000000..b44f43e072 --- /dev/null +++ b/APACHE_1_3_12/src/Apache.mak @@ -0,0 +1,230 @@ +# 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=.\ApacheR +INTDIR=.\ApacheR +# Begin Custom Macros +OutDir=.\.\ApacheR +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\Apache.exe" + +!ELSE + +ALL : "$(OUTDIR)\Apache.exe" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\apache.res" + -@erase "$(INTDIR)\main_win32.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\Apache.exe" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ + /Fp"$(INTDIR)\Apache.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheR/ +CPP_SBRS=. + +.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) $< +<< + +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=CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:console\ + /incremental:no /pdb:"$(OUTDIR)\Apache.pdb" /machine:I386\ + /out:"$(OUTDIR)\Apache.exe" +LINK32_OBJS= \ + "$(INTDIR)\apache.res" \ + "$(INTDIR)\main_win32.obj" + +"$(OUTDIR)\Apache.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "Apache - Win32 Debug" + +OUTDIR=.\ApacheD +INTDIR=.\ApacheD +# Begin Custom Macros +OutDir=.\.\ApacheD +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\Apache.exe" + +!ELSE + +ALL : "$(OUTDIR)\Apache.exe" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\apache.res" + -@erase "$(INTDIR)\main_win32.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\Apache.exe" + -@erase "$(OUTDIR)\Apache.ilk" + -@erase "$(OUTDIR)\Apache.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\ + /Fp"$(INTDIR)\Apache.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheD/ +CPP_SBRS=. + +.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) $< +<< + +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=CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:console\ + /incremental:yes /pdb:"$(OUTDIR)\Apache.pdb" /debug /machine:I386\ + /out:"$(OUTDIR)\Apache.exe" +LINK32_OBJS= \ + "$(INTDIR)\apache.res" \ + "$(INTDIR)\main_win32.obj" + +"$(OUTDIR)\Apache.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + + +!IF "$(CFG)" == "Apache - Win32 Release" || "$(CFG)" == "Apache - Win32 Debug" +SOURCE=.\os\win32\main_win32.c + +"$(INTDIR)\main_win32.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=.\os\win32\apache.rc +DEP_RSC_APACH=\ + ".\os\win32\apache.ico"\ + + +!IF "$(CFG)" == "Apache - Win32 Release" + + +"$(INTDIR)\apache.res" : $(SOURCE) $(DEP_RSC_APACH) "$(INTDIR)" + $(RSC) /l 0x809 /fo"$(INTDIR)\apache.res" /i "os\win32" /d "NDEBUG" $(SOURCE) + + +!ELSEIF "$(CFG)" == "Apache - Win32 Debug" + + +"$(INTDIR)\apache.res" : $(SOURCE) $(DEP_RSC_APACH) "$(INTDIR)" + $(RSC) /l 0x809 /fo"$(INTDIR)\apache.res" /i "os\win32" /d "_DEBUG" $(SOURCE) + + +!ENDIF + + +!ENDIF + diff --git a/APACHE_1_3_12/src/ApacheCore.def b/APACHE_1_3_12/src/ApacheCore.def new file mode 100644 index 0000000000..8dfc8e78a7 --- /dev/null +++ b/APACHE_1_3_12/src/ApacheCore.def @@ -0,0 +1,362 @@ +; 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 diff --git a/APACHE_1_3_12/src/ApacheCore.dsp b/APACHE_1_3_12/src/ApacheCore.dsp new file mode 100644 index 0000000000..511e5feefe --- /dev/null +++ b/APACHE_1_3_12/src/ApacheCore.dsp @@ -0,0 +1,405 @@ +# Microsoft Developer Studio Project File - Name="ApacheCore" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.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 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 ".\ApacheCo" +# PROP BASE Intermediate_Dir ".\ApacheCo" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir ".\CoreR" +# PROP Intermediate_Dir ".\CoreR" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I ".\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /YX /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 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 os\win32\ApacheOSR\ApacheOS.lib regex\release\regex.lib ap\Release\ap.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ws2_32.lib /nologo /subsystem:windows /dll /machine:I386 + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir ".\ApacheC0" +# PROP BASE Intermediate_Dir ".\ApacheC0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir ".\CoreD" +# PROP Intermediate_Dir ".\CoreD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# 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 ".\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /FR /YX /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 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 os\win32\ApacheOSD\ApacheOS.lib regex\debug\regex.lib ap\Debug\ap.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ws2_32.lib /nologo /subsystem:windows /dll /debug /machine:I386 +# SUBTRACT LINK32 /map + +!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=.\buildmark.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\alloc.h +# End Source File +# Begin Source File + +SOURCE=.\include\ap.h +# End Source File +# Begin Source File + +SOURCE=.\include\ap_md5.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=.\include\fnmatch.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 "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" +# End Group +# Begin Group "Generated Files" + +# PROP Default_Filter "" +# 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_12/src/ApacheCore.mak b/APACHE_1_3_12/src/ApacheCore.mak new file mode 100644 index 0000000000..8b012c5122 --- /dev/null +++ b/APACHE_1_3_12/src/ApacheCore.mak @@ -0,0 +1,2558 @@ +# 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 + +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +OUTDIR=.\CoreR +INTDIR=.\CoreR +# Begin Custom Macros +OutDir=.\.\CoreR +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheCore.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheCore.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\alloc.obj" + -@erase "$(INTDIR)\buff.obj" + -@erase "$(INTDIR)\buildmark.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 "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheCore.dll" + -@erase "$(OUTDIR)\ApacheCore.exp" + -@erase "$(OUTDIR)\ApacheCore.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I ".\include" /D "NDEBUG" /D "WIN32" /D\ + "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /Fp"$(INTDIR)\ApacheCore.pch" /YX\ + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\CoreR/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheCore.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=os\win32\ApacheOSR\ApacheOS.lib regex\release\regex.lib\ + ap\Release\ap.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib ws2_32.lib /nologo /subsystem:windows /dll\ + /incremental:no /pdb:"$(OUTDIR)\ApacheCore.pdb" /machine:I386\ + /def:".\ApacheCore.def" /out:"$(OUTDIR)\ApacheCore.dll"\ + /implib:"$(OUTDIR)\ApacheCore.lib" +DEF_FILE= \ + ".\ApacheCore.def" +LINK32_OBJS= \ + "$(INTDIR)\alloc.obj" \ + "$(INTDIR)\buff.obj" \ + "$(INTDIR)\buildmark.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" + +"$(OUTDIR)\ApacheCore.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +OUTDIR=.\CoreD +INTDIR=.\CoreD +# Begin Custom Macros +OutDir=.\.\CoreD +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheCore.dll" "$(OUTDIR)\ApacheCore.bsc" + +!ELSE + +ALL : "$(OUTDIR)\ApacheCore.dll" "$(OUTDIR)\ApacheCore.bsc" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\alloc.obj" + -@erase "$(INTDIR)\alloc.sbr" + -@erase "$(INTDIR)\buff.obj" + -@erase "$(INTDIR)\buff.sbr" + -@erase "$(INTDIR)\buildmark.obj" + -@erase "$(INTDIR)\buildmark.sbr" + -@erase "$(INTDIR)\getopt.obj" + -@erase "$(INTDIR)\getopt.sbr" + -@erase "$(INTDIR)\http_config.obj" + -@erase "$(INTDIR)\http_config.sbr" + -@erase "$(INTDIR)\http_core.obj" + -@erase "$(INTDIR)\http_core.sbr" + -@erase "$(INTDIR)\http_log.obj" + -@erase "$(INTDIR)\http_log.sbr" + -@erase "$(INTDIR)\http_main.obj" + -@erase "$(INTDIR)\http_main.sbr" + -@erase "$(INTDIR)\http_protocol.obj" + -@erase "$(INTDIR)\http_protocol.sbr" + -@erase "$(INTDIR)\http_request.obj" + -@erase "$(INTDIR)\http_request.sbr" + -@erase "$(INTDIR)\http_vhost.obj" + -@erase "$(INTDIR)\http_vhost.sbr" + -@erase "$(INTDIR)\mod_access.obj" + -@erase "$(INTDIR)\mod_access.sbr" + -@erase "$(INTDIR)\mod_actions.obj" + -@erase "$(INTDIR)\mod_actions.sbr" + -@erase "$(INTDIR)\mod_alias.obj" + -@erase "$(INTDIR)\mod_alias.sbr" + -@erase "$(INTDIR)\mod_asis.obj" + -@erase "$(INTDIR)\mod_asis.sbr" + -@erase "$(INTDIR)\mod_auth.obj" + -@erase "$(INTDIR)\mod_auth.sbr" + -@erase "$(INTDIR)\mod_autoindex.obj" + -@erase "$(INTDIR)\mod_autoindex.sbr" + -@erase "$(INTDIR)\mod_cgi.obj" + -@erase "$(INTDIR)\mod_cgi.sbr" + -@erase "$(INTDIR)\mod_dir.obj" + -@erase "$(INTDIR)\mod_dir.sbr" + -@erase "$(INTDIR)\mod_env.obj" + -@erase "$(INTDIR)\mod_env.sbr" + -@erase "$(INTDIR)\mod_imap.obj" + -@erase "$(INTDIR)\mod_imap.sbr" + -@erase "$(INTDIR)\mod_include.obj" + -@erase "$(INTDIR)\mod_include.sbr" + -@erase "$(INTDIR)\mod_isapi.obj" + -@erase "$(INTDIR)\mod_isapi.sbr" + -@erase "$(INTDIR)\mod_log_config.obj" + -@erase "$(INTDIR)\mod_log_config.sbr" + -@erase "$(INTDIR)\mod_mime.obj" + -@erase "$(INTDIR)\mod_mime.sbr" + -@erase "$(INTDIR)\mod_negotiation.obj" + -@erase "$(INTDIR)\mod_negotiation.sbr" + -@erase "$(INTDIR)\mod_setenvif.obj" + -@erase "$(INTDIR)\mod_setenvif.sbr" + -@erase "$(INTDIR)\mod_so.obj" + -@erase "$(INTDIR)\mod_so.sbr" + -@erase "$(INTDIR)\mod_userdir.obj" + -@erase "$(INTDIR)\mod_userdir.sbr" + -@erase "$(INTDIR)\modules.obj" + -@erase "$(INTDIR)\modules.sbr" + -@erase "$(INTDIR)\multithread.obj" + -@erase "$(INTDIR)\multithread.sbr" + -@erase "$(INTDIR)\readdir.obj" + -@erase "$(INTDIR)\readdir.sbr" + -@erase "$(INTDIR)\registry.obj" + -@erase "$(INTDIR)\registry.sbr" + -@erase "$(INTDIR)\rfc1413.obj" + -@erase "$(INTDIR)\rfc1413.sbr" + -@erase "$(INTDIR)\service.obj" + -@erase "$(INTDIR)\service.sbr" + -@erase "$(INTDIR)\util.obj" + -@erase "$(INTDIR)\util.sbr" + -@erase "$(INTDIR)\util_date.obj" + -@erase "$(INTDIR)\util_date.sbr" + -@erase "$(INTDIR)\util_md5.obj" + -@erase "$(INTDIR)\util_md5.sbr" + -@erase "$(INTDIR)\util_script.obj" + -@erase "$(INTDIR)\util_script.sbr" + -@erase "$(INTDIR)\util_uri.obj" + -@erase "$(INTDIR)\util_uri.sbr" + -@erase "$(INTDIR)\util_win32.obj" + -@erase "$(INTDIR)\util_win32.sbr" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\ApacheCore.bsc" + -@erase "$(OUTDIR)\ApacheCore.dll" + -@erase "$(OUTDIR)\ApacheCore.exp" + -@erase "$(OUTDIR)\ApacheCore.ilk" + -@erase "$(OUTDIR)\ApacheCore.lib" + -@erase "$(OUTDIR)\ApacheCore.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I ".\include" /D "_DEBUG" /D "WIN32"\ + /D "_WINDOWS" /D "WIN32_LEAN_AND_MEAN" /FR"$(INTDIR)\\"\ + /Fp"$(INTDIR)\ApacheCore.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\CoreD/ +CPP_SBRS=.\CoreD/ +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheCore.bsc" +BSC32_SBRS= \ + "$(INTDIR)\alloc.sbr" \ + "$(INTDIR)\buff.sbr" \ + "$(INTDIR)\buildmark.sbr" \ + "$(INTDIR)\getopt.sbr" \ + "$(INTDIR)\http_config.sbr" \ + "$(INTDIR)\http_core.sbr" \ + "$(INTDIR)\http_log.sbr" \ + "$(INTDIR)\http_main.sbr" \ + "$(INTDIR)\http_protocol.sbr" \ + "$(INTDIR)\http_request.sbr" \ + "$(INTDIR)\http_vhost.sbr" \ + "$(INTDIR)\mod_access.sbr" \ + "$(INTDIR)\mod_actions.sbr" \ + "$(INTDIR)\mod_alias.sbr" \ + "$(INTDIR)\mod_asis.sbr" \ + "$(INTDIR)\mod_auth.sbr" \ + "$(INTDIR)\mod_autoindex.sbr" \ + "$(INTDIR)\mod_cgi.sbr" \ + "$(INTDIR)\mod_dir.sbr" \ + "$(INTDIR)\mod_env.sbr" \ + "$(INTDIR)\mod_imap.sbr" \ + "$(INTDIR)\mod_include.sbr" \ + "$(INTDIR)\mod_isapi.sbr" \ + "$(INTDIR)\mod_log_config.sbr" \ + "$(INTDIR)\mod_mime.sbr" \ + "$(INTDIR)\mod_negotiation.sbr" \ + "$(INTDIR)\mod_setenvif.sbr" \ + "$(INTDIR)\mod_so.sbr" \ + "$(INTDIR)\mod_userdir.sbr" \ + "$(INTDIR)\modules.sbr" \ + "$(INTDIR)\multithread.sbr" \ + "$(INTDIR)\readdir.sbr" \ + "$(INTDIR)\registry.sbr" \ + "$(INTDIR)\rfc1413.sbr" \ + "$(INTDIR)\service.sbr" \ + "$(INTDIR)\util.sbr" \ + "$(INTDIR)\util_date.sbr" \ + "$(INTDIR)\util_md5.sbr" \ + "$(INTDIR)\util_script.sbr" \ + "$(INTDIR)\util_uri.sbr" \ + "$(INTDIR)\util_win32.sbr" + +"$(OUTDIR)\ApacheCore.bsc" : "$(OUTDIR)" $(BSC32_SBRS) + $(BSC32) @<< + $(BSC32_FLAGS) $(BSC32_SBRS) +<< + +LINK32=link.exe +LINK32_FLAGS=os\win32\ApacheOSD\ApacheOS.lib regex\debug\regex.lib\ + ap\Debug\ap.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib ws2_32.lib /nologo /subsystem:windows /dll\ + /incremental:yes /pdb:"$(OUTDIR)\ApacheCore.pdb" /debug /machine:I386\ + /def:".\ApacheCore.def" /out:"$(OUTDIR)\ApacheCore.dll"\ + /implib:"$(OUTDIR)\ApacheCore.lib" +DEF_FILE= \ + ".\ApacheCore.def" +LINK32_OBJS= \ + "$(INTDIR)\alloc.obj" \ + "$(INTDIR)\buff.obj" \ + "$(INTDIR)\buildmark.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" + +"$(OUTDIR)\ApacheCore.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) $< +<< + + +!IF "$(CFG)" == "ApacheCore - Win32 Release" || "$(CFG)" ==\ + "ApacheCore - Win32 Debug" +SOURCE=.\main\alloc.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_ALLOC=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\alloc.obj" : $(SOURCE) $(DEP_CPP_ALLOC) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_ALLOC=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\alloc.obj" "$(INTDIR)\alloc.sbr" : $(SOURCE) $(DEP_CPP_ALLOC)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\buff.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_BUFF_=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\buff.obj" : $(SOURCE) $(DEP_CPP_BUFF_) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_BUFF_=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\buff.obj" "$(INTDIR)\buff.sbr" : $(SOURCE) $(DEP_CPP_BUFF_)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\buildmark.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_BUILD=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\buildmark.obj" : $(SOURCE) $(DEP_CPP_BUILD) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_BUILD=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\buildmark.obj" "$(INTDIR)\buildmark.sbr" : $(SOURCE)\ + $(DEP_CPP_BUILD) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\os\win32\getopt.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + + +"$(INTDIR)\getopt.obj" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + + +"$(INTDIR)\getopt.obj" "$(INTDIR)\getopt.sbr" : $(SOURCE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\http_config.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_HTTP_=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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_request.h"\ + ".\include\http_vhost.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\http_config.obj" : $(SOURCE) $(DEP_CPP_HTTP_) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_HTTP_=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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_request.h"\ + ".\include\http_vhost.h"\ + ".\include\httpd.h"\ + ".\include\util_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\http_config.obj" "$(INTDIR)\http_config.sbr" : $(SOURCE)\ + $(DEP_CPP_HTTP_) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\http_core.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_HTTP_C=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\http_core.obj" : $(SOURCE) $(DEP_CPP_HTTP_C) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_HTTP_C=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\http_core.obj" "$(INTDIR)\http_core.sbr" : $(SOURCE)\ + $(DEP_CPP_HTTP_C) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\http_log.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_HTTP_L=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\http_log.obj" : $(SOURCE) $(DEP_CPP_HTTP_L) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_HTTP_L=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\http_log.obj" "$(INTDIR)\http_log.sbr" : $(SOURCE) $(DEP_CPP_HTTP_L)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\http_main.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_HTTP_M=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\http_main.obj" : $(SOURCE) $(DEP_CPP_HTTP_M) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_HTTP_M=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\http_main.obj" "$(INTDIR)\http_main.sbr" : $(SOURCE)\ + $(DEP_CPP_HTTP_M) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\http_protocol.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_HTTP_P=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\http_protocol.obj" : $(SOURCE) $(DEP_CPP_HTTP_P) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_HTTP_P=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\http_protocol.obj" "$(INTDIR)\http_protocol.sbr" : $(SOURCE)\ + $(DEP_CPP_HTTP_P) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\http_request.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_HTTP_R=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\http_request.obj" : $(SOURCE) $(DEP_CPP_HTTP_R) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_HTTP_R=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\http_request.obj" "$(INTDIR)\http_request.sbr" : $(SOURCE)\ + $(DEP_CPP_HTTP_R) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\http_vhost.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_HTTP_V=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\http_vhost.obj" : $(SOURCE) $(DEP_CPP_HTTP_V) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_HTTP_V=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\http_vhost.obj" "$(INTDIR)\http_vhost.sbr" : $(SOURCE)\ + $(DEP_CPP_HTTP_V) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_access.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_A=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_access.obj" : $(SOURCE) $(DEP_CPP_MOD_A) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_A=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_access.obj" "$(INTDIR)\mod_access.sbr" : $(SOURCE)\ + $(DEP_CPP_MOD_A) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_actions.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_AC=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_actions.obj" : $(SOURCE) $(DEP_CPP_MOD_AC) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_AC=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_actions.obj" "$(INTDIR)\mod_actions.sbr" : $(SOURCE)\ + $(DEP_CPP_MOD_AC) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_alias.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_AL=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_alias.obj" : $(SOURCE) $(DEP_CPP_MOD_AL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_AL=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_alias.obj" "$(INTDIR)\mod_alias.sbr" : $(SOURCE)\ + $(DEP_CPP_MOD_AL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_asis.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_AS=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_asis.obj" : $(SOURCE) $(DEP_CPP_MOD_AS) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_AS=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_asis.obj" "$(INTDIR)\mod_asis.sbr" : $(SOURCE) $(DEP_CPP_MOD_AS)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_auth.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_AU=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\mod_auth.obj" : $(SOURCE) $(DEP_CPP_MOD_AU) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_AU=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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_uri.h"\ + ".\os\win32\os.h"\ + ".\os\win32\readdir.h"\ + + +"$(INTDIR)\mod_auth.obj" "$(INTDIR)\mod_auth.sbr" : $(SOURCE) $(DEP_CPP_MOD_AU)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_autoindex.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_AUT=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_autoindex.obj" : $(SOURCE) $(DEP_CPP_MOD_AUT) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_AUT=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_autoindex.obj" "$(INTDIR)\mod_autoindex.sbr" : $(SOURCE)\ + $(DEP_CPP_MOD_AUT) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_cgi.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_C=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_cgi.obj" : $(SOURCE) $(DEP_CPP_MOD_C) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_C=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_cgi.obj" "$(INTDIR)\mod_cgi.sbr" : $(SOURCE) $(DEP_CPP_MOD_C)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_dir.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_D=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_dir.obj" : $(SOURCE) $(DEP_CPP_MOD_D) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_D=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_dir.obj" "$(INTDIR)\mod_dir.sbr" : $(SOURCE) $(DEP_CPP_MOD_D)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_env.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_E=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_env.obj" : $(SOURCE) $(DEP_CPP_MOD_E) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_E=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_env.obj" "$(INTDIR)\mod_env.sbr" : $(SOURCE) $(DEP_CPP_MOD_E)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_imap.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_I=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_imap.obj" : $(SOURCE) $(DEP_CPP_MOD_I) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_I=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_imap.obj" "$(INTDIR)\mod_imap.sbr" : $(SOURCE) $(DEP_CPP_MOD_I)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_include.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_IN=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_include.obj" : $(SOURCE) $(DEP_CPP_MOD_IN) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_IN=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_include.obj" "$(INTDIR)\mod_include.sbr" : $(SOURCE)\ + $(DEP_CPP_MOD_IN) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\os\win32\mod_isapi.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_IS=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_isapi.obj" : $(SOURCE) $(DEP_CPP_MOD_IS) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_IS=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_isapi.obj" "$(INTDIR)\mod_isapi.sbr" : $(SOURCE)\ + $(DEP_CPP_MOD_IS) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_log_config.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_L=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_log_config.obj" : $(SOURCE) $(DEP_CPP_MOD_L) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_L=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_log_config.obj" "$(INTDIR)\mod_log_config.sbr" : $(SOURCE)\ + $(DEP_CPP_MOD_L) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_mime.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_M=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_mime.obj" : $(SOURCE) $(DEP_CPP_MOD_M) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_M=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_mime.obj" "$(INTDIR)\mod_mime.sbr" : $(SOURCE) $(DEP_CPP_MOD_M)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_negotiation.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_N=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_negotiation.obj" : $(SOURCE) $(DEP_CPP_MOD_N) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_N=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_negotiation.obj" "$(INTDIR)\mod_negotiation.sbr" : $(SOURCE)\ + $(DEP_CPP_MOD_N) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_setenvif.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_S=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_setenvif.obj" : $(SOURCE) $(DEP_CPP_MOD_S) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_S=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_setenvif.obj" "$(INTDIR)\mod_setenvif.sbr" : $(SOURCE)\ + $(DEP_CPP_MOD_S) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_so.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_SO=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_so.obj" : $(SOURCE) $(DEP_CPP_MOD_SO) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_SO=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_so.obj" "$(INTDIR)\mod_so.sbr" : $(SOURCE) $(DEP_CPP_MOD_SO)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\modules\standard\mod_userdir.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MOD_U=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_userdir.obj" : $(SOURCE) $(DEP_CPP_MOD_U) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MOD_U=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_userdir.obj" "$(INTDIR)\mod_userdir.sbr" : $(SOURCE)\ + $(DEP_CPP_MOD_U) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\os\win32\modules.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MODUL=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\modules.obj" : $(SOURCE) $(DEP_CPP_MODUL) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MODUL=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\modules.obj" "$(INTDIR)\modules.sbr" : $(SOURCE) $(DEP_CPP_MODUL)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\os\win32\multithread.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_MULTI=\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.h"\ + ".\include\ap_mmn.h"\ + ".\include\hsregex.h"\ + ".\include\multithread.h"\ + ".\os\win32\os.h"\ + + +"$(INTDIR)\multithread.obj" : $(SOURCE) $(DEP_CPP_MULTI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_MULTI=\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.h"\ + ".\include\ap_mmn.h"\ + ".\include\hsregex.h"\ + ".\include\multithread.h"\ + ".\os\win32\os.h"\ + + +"$(INTDIR)\multithread.obj" "$(INTDIR)\multithread.sbr" : $(SOURCE)\ + $(DEP_CPP_MULTI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\os\win32\readdir.c +DEP_CPP_READD=\ + ".\os\win32\readdir.h"\ + + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + + +"$(INTDIR)\readdir.obj" : $(SOURCE) $(DEP_CPP_READD) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + + +"$(INTDIR)\readdir.obj" "$(INTDIR)\readdir.sbr" : $(SOURCE) $(DEP_CPP_READD)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\os\win32\registry.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_REGIS=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\registry.obj" : $(SOURCE) $(DEP_CPP_REGIS) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_REGIS=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\registry.obj" "$(INTDIR)\registry.sbr" : $(SOURCE) $(DEP_CPP_REGIS)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\rfc1413.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_RFC14=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\rfc1413.obj" : $(SOURCE) $(DEP_CPP_RFC14) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_RFC14=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\rfc1413.obj" "$(INTDIR)\rfc1413.sbr" : $(SOURCE) $(DEP_CPP_RFC14)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\os\win32\service.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_SERVI=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\service.obj" : $(SOURCE) $(DEP_CPP_SERVI) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_SERVI=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\service.obj" "$(INTDIR)\service.sbr" : $(SOURCE) $(DEP_CPP_SERVI)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\util.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_UTIL_=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\util.obj" : $(SOURCE) $(DEP_CPP_UTIL_) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_UTIL_=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\util.obj" "$(INTDIR)\util.sbr" : $(SOURCE) $(DEP_CPP_UTIL_)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\util_date.c +DEP_CPP_UTIL_D=\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.h"\ + ".\include\ap_mmn.h"\ + ".\include\hsregex.h"\ + ".\include\util_date.h"\ + ".\os\win32\os.h"\ + + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + + +"$(INTDIR)\util_date.obj" : $(SOURCE) $(DEP_CPP_UTIL_D) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + + +"$(INTDIR)\util_date.obj" "$(INTDIR)\util_date.sbr" : $(SOURCE)\ + $(DEP_CPP_UTIL_D) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\util_md5.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_UTIL_M=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\util_md5.obj" : $(SOURCE) $(DEP_CPP_UTIL_M) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_UTIL_M=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\util_md5.obj" "$(INTDIR)\util_md5.sbr" : $(SOURCE) $(DEP_CPP_UTIL_M)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\util_script.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_UTIL_S=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\util_script.obj" : $(SOURCE) $(DEP_CPP_UTIL_S) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_UTIL_S=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\util_script.obj" "$(INTDIR)\util_script.sbr" : $(SOURCE)\ + $(DEP_CPP_UTIL_S) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\main\util_uri.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_UTIL_U=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\util_uri.obj" : $(SOURCE) $(DEP_CPP_UTIL_U) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_UTIL_U=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\util_uri.obj" "$(INTDIR)\util_uri.sbr" : $(SOURCE) $(DEP_CPP_UTIL_U)\ + "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\os\win32\util_win32.c + +!IF "$(CFG)" == "ApacheCore - Win32 Release" + +DEP_CPP_UTIL_W=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\util_win32.obj" : $(SOURCE) $(DEP_CPP_UTIL_W) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheCore - Win32 Debug" + +DEP_CPP_UTIL_W=\ + ".\include\alloc.h"\ + ".\include\ap.h"\ + ".\include\ap_config.h"\ + ".\include\ap_ctype.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"\ + + +"$(INTDIR)\util_win32.obj" "$(INTDIR)\util_win32.sbr" : $(SOURCE)\ + $(DEP_CPP_UTIL_W) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + + +!ENDIF + diff --git a/APACHE_1_3_12/src/ApacheCoreOS2.def b/APACHE_1_3_12/src/ApacheCoreOS2.def new file mode 100644 index 0000000000..6a3bdb3e51 --- /dev/null +++ b/APACHE_1_3_12/src/ApacheCoreOS2.def @@ -0,0 +1,368 @@ +; 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 diff --git a/APACHE_1_3_12/src/ApacheNW.mcp.gz b/APACHE_1_3_12/src/ApacheNW.mcp.gz new file mode 100644 index 0000000000000000000000000000000000000000..71751b7ca63a41a48dc181c477d2b36d19d6a304 GIT binary patch literal 76780 zcmce-Wmp`|+BKS>0fJlb;5I-A8ZLc*S(4+?%6Z>ciw_ekR@ErENrcmbvT_YT%R1~ zqMK4k&qH*M_j)9rs3D_RCchneitg=*PH7mPyN>r92w-g`Fd#_Ik;Lv9n8Nru^~V3C zC*$qm7c(;)uUJ1iGv zG?WTG`{^=4D|XGZRx-dd3QP)AVG@4gR;ok)MeGI})5pjalrA!FtV8X^&kaFlS`9*r zdksydcLP;sd<~>#A(5g_@0brw8cs}&7dsmA%|gQNQ7;*42rdZ@2^KXPXv{WEmj}E* z^gQn(y5t>0KOZ0&&^N_03o|P=tC&dTU!*ak=;x0-!lA&SDEx9j3PVP{VRSQnKYb#{ zOKI{e{Bw3VD1~bOWH`0BLt}D5NX>Qr&Mxm;;e(L|e(C&{Dz}LRNA4wlUEGA`!GM4A zqxyY<>lgTDfh*_)yCuq~_VzKb$HjH%Q-z;)h=#bU=cshBfWT7Hmzrz^H4{PNqb$fC zD^VW5min8)C6($m`jO}RBO5yp=Ph9wM@y%ub8t;hAv`(h&#VrkNYd`S^uZbeP*407Y2YdfT2au*AF_+Cdro%&nx*ULhI57du$x4JAj%4ol! z#BIJf>m#j!(@w+}F5#PgFIx<(d!9G-4GgbS z){4=55(;*`a!3{iiE5vCu}pVaUVG}RuN|~xE|{N5#4N@SmN8$69<)upPYC93{(bd! zi)l^mW6jnZ>rI=aVj^*ku6uM+s0mT5O#Z1(bPwCRkWyE?=l84MXqVPzv`y@U{nfi5 zG+b_%GGiBj^VAl>(Vk>(i(tdIU!#fb zs(O8&yaU$fTP!^L)GL+=hvYoJ8L4T%zQ`cyzB;R1QyhwX%a4RAe-&9ID>t9ISnf$v z=0$~jQy?WW`!+(H7shQaGKy~YQ%2niK2cF#{|TfK=4nEf*|roRH?hWYYYiJQ?qyQ( zQhCQsPSVB9nrh+@FAW3BGhyZLCNj!nsl{!&`b-EDDeFx|mYfET?@PgX`gO2P!OBAuNMc5Z3!}Z27b^8TFSuiJ%!G=MW_uEgL8MDWRK& z@PKvycPoy!I_;)DFFNZ`8DGI%l|-zU!>Aj*j`RJ~ur<~&g?9>2u-y*B^24YCHfwWG<0lj$rxJqb`L zA7?k{F%_|T?#L1kSIr46^dm2?{iMU-`IcZ!)mymU4N~&56025Ih(JgW265@}7;?(P z)^BDZKY#c7jVh$@s=JGwEiN%YsOr`@ZLxaNE~;Rf@}mo7a(T}+#Yar5XIW{qzvP}v zq`XEEjiHrl_S{(&N~>8*UTs?F^~s|Y^#!ICN9awjRUNQjD08tZ%#z1N_^@*te^lR! z^+qvje-%5BlvqDN5l6xW25F*MJji~h@zAb$))qnca1l%8@KqtTSaFwjW}lis zbMa!9L(~es+8{8{06^7>5r1BFDWeacSc<2n{?b#R-qs}_sF&AhdQ#YjE&4rFm8>(?TM482Fs<2$V<*r0 zfh}Fzm#GJ^Io) zO%_i=rca=k54$vcLV`7okzJ`X_ZP+2ksf-P8t|RNFxz zY96@*@|+GSI%PWSV4n~@0Et2cS8JxfzRS|)#jPF=46n4TYDtgy8Rvxz(Ghc8nlu}B zKzHrKlD|zyUx(BQ?ZA_C(I%fJwAdP6*O*P^n>Q?RU~`}@fFy2i4a8-n>n|T-hhYI$ zNhzbDEab6UF$H!zE5`?3kUg@sE0{Z_Bu03e-=}DiOvmu4$G0Zp1n^ulVC{kQ^_gv6 zQpJJy`$p8}Ybn@h%)6G5#*cDGJm+<5Jhu(&=NR26<{bu59I?w&_A#|a72w}pr)Yui z;jW(3k)&V050i;KC`+Np^0?w$(;>(kD)g998HteIGe0UfI*F(FD;t);Q|q{yMaFfM& zxDY;z&TB<)l;#swtd=Nbr|Y!d%JZucAsZ(_5?fr#SQF?&=3Cg-z{%&NI5ZW87tdPX zmBvl1%^iCC0S=-EC66Y8?%6Y<=z1&E_b+aX)eg;T_^QUv-|54li6Ha+zTB`7Xw7B# zz`je9Fp`s)4LDX8M5r}u-wmd5vwti*xay35`T9_&Ntfj8=IRn%t4??0!a_$<0%j!< zLP16B64+LO#j3>e%kHXLMj0-5?6$ixYj_QhOItrfpf*fCE_@r=k|Uu|x83(}+70+n z!U$pr)V&SRMcxppG19A=@vFt}gOF+w4o&vRe-b0ETow&|DQ0hS{285G1zH0Fw0}ETE(k+EOWQ4IIP4zKJlIK zGpC~&Ej&oTNvkT)h=dLd-(n=r%Gh$%{l}v37b;6ZUA}y=t^Q^BsQMrC_@Vp>K9!N< zc@-f$6YI9^9C!osG>#Z3V1ajVj{P{pGLHSEnj@JFRiUD zY!g3!RB(OsddWL-hCNqhJrT>R_`dW!hm!z(q1qFKEJ^hg{;3XnjFYsB}wXia*?bX~}A3%Bx{BxU^c>?1_xsmzTXdKQB%QAJuaE z#uF6Y!Fghq#1C(!cEyh#)OPDH3ge>}PI98E8OifCT2j};GtA5P97fsp?W^v&aqso1 zZ6(M`P1v-UVNKu&|8ZWt3jV>2MI`_C~ zue@y+-R0gQK1A5KO4F>-v5g|l$u#S41ljf3z9AG8m*3Tf7g@dS8DT}v zHBmMJ^l1hc-ddf-3H62d7F4saFX0Gv9qD|t(aifb6Rr?1cI3T1WwXNd_O{{9OO|HP zDE_zHRduqMV!PmWIc$L?DBZVm8Uo9Z`KHWtY5 zbM>7)`8<0{uFl6NhUHE$Ms}dA(B^0fPp_(wutF(Mudeqam`vwYu2IAkS)Y&nUJ({& z9p03T9-KDqw*s zkYy(+B376_F5A`%dQVp_NW_CmH(7l8g9YxCY6^EEy0p=(8?^77((jz26dIqN`QS?~ zSMRVH7J8UNUtWJ`GFi4|jaU(B9dlZ$ z;}7S6!DqXApYSLCWZ7`P7o0TzLDojbA;#O6`T!g&lNr0Wm_3pv^|jBhrGRMq|F`OjPLJCyx&tgJY%G!B@Q&KrIm4G zcUQ`$wsL!7cbM9^bQa4x!Ma^~E)R6mNgvNn-c!6Nx;Bmko6Et>o2$^?v5@nf$fdjN zL)%}9MB&|Q8<|utK+LRSK(ZApv2hu`>3)V&@da2xQ&3lit%K9SBCtZBLR@)A8S$Ou zsx6S2l4Ziv`G~YGB1wlOo!akH_l%?vux4Ko44(?qjh!1&&;=S+r)4yl%PnX)DniVG zXuV@)-&3V@23hQL`K)^&REBno1=8kQ9wkwPjZ1VgSqUYblRx)~XvRs!(_?Aw;%M$- zXfB|TC@4e*3V}c&%uq-<6k-E~>_Q=vP)G(8q6392Kp~Y-NG245fKGc*2pJUO0EHYt zArw$ZHWXq2g)BoM!cYho6cPZ1+(9Aem{EQWx-rGynv^Ja`eRAOUub}*I02$>I=yZ? zd(u7y;IXcW*oVyNMaw->{Gzgk7c1PCKJA3+bdq3v`H+8Z?{FYQ7*qc0_{NKl(?kSW z4YPUpy{kg8rl!_Je;+w#>ziicYUH7HAOpCEcHbu>Qw@c88y|J$cQ?%6`x9Q8VkYAzNe?3(OSC7 zzYng*v?0C1`P^8X78JBEO_%bQw5CK_F}TbNb%Xv{>(?ya4j%gp%$MV?=RiGsOqf5I*js;*p;N@z6# zgC16Cz(Gd0DJ*jgLR~4p4wZ`7skJRHj0AS4X-ERd|C(=L4yyg8^t2krm z6PKo%8X0UelDnUmJ5(45B;`M8Y&04!?-`?p5xzxy!S_3nswTdDdbSHFugTUjXN9En zS~hR#*E%K1Ks>0h?~*ley@Fc)0*<>M&z-(}YSQiDuz`x=i@#UBg<6DLa;g1F!cSOF z9=XIf>=AgKbbz6?Cq1BdP{Gj4G#3KavlQLbD}4%!{D7&v=8)-MKP?wTcU1TCDfJvk zUb8j9euPgYnUCNCsV%?8Ps?LOM)S@h>AQP~rQIxRR`!4VO+t37mIyj{=PNA65w)`O zL_4>;X+~!gUCE!l4TpGbTyT=$0hY}Z7xY;JUm$u|)qN64UsG#w)XgFmn^#vgNMcxn zi8BdxDLF}i8v)g?{L!b)_f54toc+}u(zyM-g=w{`joO$!nkm1 zWb+IUvffYz_BBeR!Z>@sCA~tpAmB+Ss1^L@`!TNM6SoNeebEOBZQ8E?_E$N4ozsr6 zbE92(|I1(f`K?K}#*ws5U-G_mjv&hH**M=0W~&|Yi)Dd8YTY22r9Ge6j-8x~+PvsB znRAs|Pv`21&4!i8`-iM0a)VXb!6TVnn-~qaS0#c_nw)py#g54zc6w$7zvOTpOD$g3 zOhU9VZH4WSKQc9c2|Nl|VrwBI?*jQKOWyBIRBDKzzC=vod=`H5;}7MrFy@!1;w)&-jP#?RmyYb=ayt7@S$toY_`FgNcCgMq|wF{J~jh?WF zZ`&JqDa!z#puj&V@YkxhK_YV321G-&TNMs&Y=lTN39sOKFmk~j;U=rxjtdK`F55jU zC)O4~;BRm(4ZAV?XIv>WPT3OPh_3)phxz7n!gOp10b!evE3>QLGTuJcw$kG}^14&S zgww6*pr0OQKwWhMs$R6YZ2 zEMUL=_c;7hZ|OLP^LYE$Ui?0Wth-oXnxVep-L)XdkdpuOVqF-CB#v>e3}D=iW3SWZ zuz)sqv_D7d)#dA^yE5^`ExJ=H^;xUKLY)Dr7Q#9>i?CAdd&8hs``&|}w)eHwv`xGG zFFL*0=Z=o&xbk# zsq`uVyVruUH{j24#v70J=984z;D*a4tPOS@BqBzWz`L1bE%Lx0Jb=3#9U@)L6Hf2U zwRJ-b;qE)1SrzVs{(NIbNaTf9h;hA&F*J&@Wrg&>FA0K}r9SvcW+5C#-Fr%M_7~2|En10u2j7)aXVcM&~N->xmNwv(ADj z!bXdGOFxHts{z_Yo;xzy$&8Ie%+otPZ-wy=BJ0TA=FX2uGx3Zst;j}$zL$05 z6u9Uw;D170>L_{6z?dEclCgc1Uy!f7*)yW_GJu)ir~2=U zRd`njF$ebQqZ6M|NNRtCuHm%?AoVNmMy2^N_F_PHxdF7n9%J%l*8<`2oiB`xqtc;8 zX;>=yu%4RGqITvk`;O>q133HZTvqKt#?c7h_@N{w0Bbz286%-gRzq?Oy^`)QD2b`Y zGPX-ax`X9y$20Og+b9Az9i8P4FJ`OLNg^Sn_)KF3ysn^=|5 zxb(*3_jE;Y_u!98XV-M%45eJQ9J0Gip*d>tL9)hU$aTLYX7F<=z01vWF8;AZ)XHGb zU1(!Yeo|F_!@~CzRPpK(nqnT8A1a{V-J9Pk*m>lOZ(tPO7ZHRZvwD@QL@#c*JIor~ zgD^S*X;aw8H1~P!>RR76snIpdH*36S#1EDnG|^t}1{LM+Fz(&P82B?)GF{j!F}qu6 z>(|bD&fmYV8S13j%;H29kBkT00jtZ->t*kLG^CNwd<(YYD>D<#h|OjSi~q~HH;A@6P(Pxql}Z9zFwGtd@t|MB}tDOZbPRlcm?%6Z+5-iE@m zN(;om;3VgbgGuhCyG7~95vS6XK|xuo>mrGGQ}x(MBvhWwo5L^bjh3?kJT-%F(amRm zD@V9%9-!9J)z2$FUdYx)b;DX+UEegIB7gO7_f?!bqDn3vfU}q z@aHEvOIhkE=*^!!MjeNL0Z8iYiq8s$(w%I;?b=+aRuid!Y)Y%Lv+<>T*;&i_N+wnv z>^ol;#Hn`bK{eO-jkQsh)5s0#^;N;&HWJN9hYgjgXmXl(eQM;!!ks-+gmv8{IaQ(x zvpY(?ns+;~n$s(S^^qd4jJ4s5OGV9tOUu*e#dE4hc5CWv-bSI&s8M#Nwgr{&Eae5 z;HiFSk#!4Pgz#Qi02AzvA^J2kV=69J+!yC5`ZOAAD)vE&JmRev+@EJ&Qj`u()~mV9 zrf0_67`~*|$eg9T@2;;37*s#3CO0JOS5@6{9!s;Fm!q~T~~giH`xAp4=I&HF>i z-s#0a-ArpNtITn!XYDxDCn?18lnecvL4T?dnl0)_Fpyb;tDR_kAc1(U zoHrffCuu1Z&sqhu-5~fEGC83LC%$Bb5G(xS1WCwu8W;#JW^*oIE-*_yDC)qluU^z! zV3Oq`=fUzMf1G3775An<@R#CKmX`@A$re@BW%*Dqf)?xTYB2!R&-)B%C89$%r zFb1S86!fqYpH31O64%$kL3uWQuGJ3CIEfFzGr&KO3pnhE$5;v+#(`~HT=WL^?9ux5 z%1|`hs`2hjQ8~|2OsB6>(0&vcdG{+;JPYvK(yVk@Z>2#MOVP_SpLcp{oFWeVI>S(_ z`+MCSn8!E`w19FJ;dZrWo3?=kUUL_EB)M`)yABbCzr)&dPdY}>sNcWgaQ$@+g?J+e zR9e?@$G1+MI7%qOJv9*LPo764)7TQ78jima4wJvm*)1WJ%T2h1XNT42=FI82nN^8B zeM~=rTLDQr^NK`Yap^rn*+RJ~5?nk2ZrQLH9X9)wLit%5sTiGsNPLs>icz%cP73~y z*W8P;P*NgpaCq63X>m+n*k{@YrM=FG7j*MwOnEHxMNF&ng&a))UX2)ZM;2ofehD@N7L3X8xw60EvI^(I(*x|(y1e@X(H{Mg12jM|;{Q|5FY zv=-JzOTz4ox$)w(6_nDyjPHWIn&(TdJIMIJEhAhn84%`^dWYqW&xJBdEDK-Hjiz6> z13^N|3G;FDBm&8NZJ^ctU3hDl>Gb3@V|)7iyR@eOsLj`qmk$Q<+B@N^C@0Erd|zB> z{?`x&&bLojQ*>+MICbI{>2wUzB}8#d$Uk~{(Vf;2a0G&s8#r`<>^z9##gME@-SS62m1D;cFI6JH>zt> zXjp$-G_oHN>NBqoRv#WBYdo z3wf4q;nau9#rQx5hzi;&a8KbfjNJASy~1;-8GSJ_Y)V!uf*SY?#%b!8qK}!*by4-T z5i9VCE>0fChYWm~{?V9(C!+-^DQ7L6>c0XTo}c%i1%461Ss#eWN1>5`vt7$VufEFQ zhaekE!(C3N+}G4HX{1Cb18aWzoVtOs!xETRp9UhqXudKNWQ3{E)uH7pb{D*@K8Vo& zT227@T8>YHC6;^5drAf({W!_civwqd-u2tyi=&De91CAlLb<-~5a6^$vL~kP$>G96n_%c1aO4~w=w6s<^n~1;G#7~?M=P*JhcLauo9^Z^RA%u ze!QkVO#@Aa*3$)J1-AU;IyH%T#ORIGeMfJoAW|diAQQolWTMh7dW{Cn{VFgLgtGR| z5TiG<{b?YU8`iZpl;xVgBVm0xMg@6IB9QM|85-5^gWqRd(sCfV7Is2AArrM>oN03! z1e)o;BAi4Oe|z{;TsH8~zE0wi7N(p7V78~^(9ivo_%5iydA@AE9I#LQ`uXo|eNN**jO%^)C&qlb_mvd_IUX2UEgPVeIQ%R(bs< z_>Y8eKG?~+OSDYEzzqjXTdL)uC@bXj3Ka11QCWl(jtfOQ#RZ9-ipPYlhYa5%J+dI) zg$wljt2n+1+C%0w$!SP5&6CHX-|_GIj13ryt53LYuTVQ5zZu7zxUuQ4z0mqjGH)mTR74%D|zF`46V;7o_L={aBv7e9HwxmB!g1!OTFhUSvORipINue{1O(2BFNh+d*CJC(VnG%VXw`E7mfiG3u6ORyA-4(0~EI`B4 zqB1}s!@Y9e)(1ogc{nbsG5JDR`q~1H6o@u@il|v*ZvVc$>2cT;3hVI!0akk0oxF1v}7^R==x$NQxzG6R;>Vj>p4!h#KC1_ZFo z=IXGP_y<_-zg`_C&88^jnBL+x{y03MzRt>FY~9e{DIb@Sc?)d!%|rkp#N{2Z)i*Pf zCSUyMf?7krTTxuRlEb*{gt-MgI)*?(7bxQGulAp(_ZMvv!YFzriIm}L`rwhFgyA?@ z_Jxc@r#O!m)aMJcu?FE&maKl8TnFQfdz*Q4Omij1wR`WJ$K#f+k~Yv z_peqOrteMcGd0DNTswD-&YQkvw9+^|-Op^gq^iJDwOB|lmveh+ZzS%`@%HF{f=#x0<+vPgIjl#yJBO)i1ZgwM>Gw=Zchcvl@($kf zru{d>8=E1Qt1euc=`Gbf>_h_NX6Pt>D9L}umn#S>n@CnFn3WQbtOVS>;WeHAmU%mM zTjlKYw{Hb0pPBq9K}0d@|xE)%$rsqPr?Io%bgf zTD3V`b1F3Z)%r0n@#{fdrJD_eh~f7)3|vhkKSrQauvMuB4D(GF)c$BoLh3Zntn$+K z7FQS9SVV!6J(IvDX0t;df!&%wG42~cM!Mv=HH1&pD&!ik-fB=ROkf}5yOisJWbQv) zcN0YZ2N3Fi`3ng3KA^Q)cCa*x91u>jWn#;lr3>b1y^c#2RG^$>8zzX&XN%_D$`p`^P9OE;6#FDl%fCA~GU=4?krIq2A7a z|EECA?adG?_4XPMUnL?LG6^n*`=vg9J*+-sd8Ce&xjAQfo(yf{Z3e+;#IJ}`U1M$Yj-d@;H-ORZ@gw96F&A+80=U@q9=|~iX+;Fa z-XiRH7LVxcD}(gppX4opXk}G%cWyR8i)$nZ@H=`xPSyGe?|=(xvs~l59cRlN?*fhc z2sZbU^UNX?_h1<|mjE+oursp|?#kRx=sLWFdPIsQEy|axcyj8)lWhMFrVUcalIq%| z0cnHa(4cce2+HhNN%Nf>AexETv>VeyfuKhO7B^D~-x5BFM&yL{`)W=iD_Y0y(71+8 z6szx!KcBt7=gd%ux&0Vy#%Z$Kts+3(J;>eYnp~u0bg0?}(C&ubVM)uwi8oZa`*_l% zf=h_JOZUUOFQ}TP=ZmDLzR372m9HkMg{Y@vT!?=&J4*=rhTn&P@AEVXO~JHK$$>u% zQ`IM`Ms@9GA>Z&9$NEfYcelmEXa}4%p2F1>B=#D91=&Rp0a5d$BTXB(qk4Uezkrqfs}I=O4@YUM#jE&8uuilM0XtdV(!w7(4b#CJ&-}4hb(?)-T5o;fl`oIQgkgB z1mEZ#Rd=p=?CWZvca+e4o!desI(BWWTDfe*C`9qUR!OFBOjvFqZ)7(bDjikI!jZ9sYhpcMCOR8n?O`Sz6Ct8vt%LcFv@0)5 z?gk}=5ZacIwA*CPHx()Nk`e=#bA|7I&du>#)|b%Y<#4b3k!g@&q!g%)bfXfV8|GD* zMK$p*)!njG=kmyKecp#SjSTis~-;XOR%Pn-Ce*aE!Qke5o=j&qLESf$uyiQkWf)M+hs~5dE zQ{ka@9T#l|m!*3|rhILLp;M@J@jIm}CWhz-zsOZP$Xm0k4okUon}?$;9la4N{0+e{uu}sZW|WeE8}oa$!`fPZyvAH; zO)n6&AN^#?nH_ogyEI+yf)JxTV3kjtJ<#s1^3vDgAeYDHsCvfOxkj^NrF1VCYj&0d zXBleaop!ULYA6S;V^rZOA90GyKWju2KAysy7*y}QbnpRFp5K-a1U9r1i%Yg%Br5tp(cagZQxT+m zeMpyCEq4*-k-ihp7lZ!!y+B78G4s}$=Znrv1AUo*I$@@|cNa4Ruez@qp^$l!Qoi}s z^gNo{NPCsLbamhXCXu+IG3-!R9N%8Z4XTvO7;yRX|DPrM(g+J=!IqL$oPVX|HK`jL zq!q?qe05u;J&}QcAQxJ1Mk2tCMQ%htGKy;q1T>YGUQ&;>`LNCCSpuiingX^qZ-FJ< zgHK0g5hr%FKc`IJ&&b-ZVdUtDnUD_$F(*1uBIwEmK~qM;dbh9gOvalZ(iHzsK`dQtkqg4B(`eo1h;?w>C+WNxo7QNzRc;F5md4d^7wROx8U}yxW;aK}BTr zNt~6md-_vub$3@KCnY>mGZOA@BK?j-?Zo-8R<{FUDj=_0IpL`?CYON-;*Q#ee^iRyahXZn>u^dxlBXT80|lU zzjYCl#wDTF*~)z1#%>{vqNg>95+LC)h8pOLjPunllAgVf6Ww_0R_5W*#}C)a2%M54v}EvzW*cz5`L-X6y}ojQY!;E{&aFeOBlH>4eeu}nAYaXQ698X?8==LKC5JB}h6$6RRmsnKHGQoC<jp`zhe2Mi7>j4iI%yLh#Ea zzIM+@Mq{_g+lo-BB-<#B2)S(pJ!*`J$HM^5Z*u>}gm-H&c@ctuw4U>Oz81dLF)hkA zn%sP^{HTsZ`JkmE&>tkrJU#Hn>PWRwE4l?Wn#xE4zk1pvdodOlNLIBPv|V|=@J;?2 zCzqHDD3r;9Uu1~#akUl4Bwei2+)KVrKcgH0wuqd@hA1CvdKvXNo6G&*$b;6PCP{mW zz}K95oS3s~?y3K8PTlrghNAi&C~Mmx-pIT3N13UX@(!s`)4Apbg^a@pt*dL@7?meS>L;7YWw#zrbyEHKp7oqW zbIil9DAH(t+O})IxW;>evWK^drryoFiXz7fY^70-X)_pHrrZKaaEq+D!&u(_OB(ze zPnFLJevW{D(!3AviOd6B>oMNH$n_fyrYqZ}B7JX^sYX7Yuy)FCA_$YoP1{F)iojF2 zST%+wlAI<(TbMj)LTrO`B)0tWn#8tcxv$w`P6=N>G$JIoB=@`&6R~z+6+?01|9hnC z)hc&&u%f*p)?Mk`m&gl4w%}>8iLCs$U7`?XBG?Zoq(mCnV3Mv+G#Y%XkG;B-etDyQ zzc@$GEMwp}oS=lOa;H98avKvqBYKjRPu$yluNlzYaxsBmG3M;J1hlJu9#4Drq1xMH zMLEHEx<=s6EOjM+sDMn3?N+dgpI#W1kB!nqN0Y-ifmRoV;`t0^Rij0-hlZX}P%c%l zdMD}ZN;T05s?xpgzo8X^Ao#;)^vpH^6aU1yF76R5hwTnzD<&W}BI2Zl`h)lpN!ppydc7QXvBTG|U z(8lgqcgAq?b;6X=u_+j%Lxd{Q`5z{v_cNQ?eKX4Qlb)JuV2iZf=a#n8U77zugtUzl z^0f!6&cqP9?2om8EWVTz!C#a$9`1hspoe9%FLO}cxnhOfQXgxikjDh>t*WExx~*z8 z9?p|p(ovBQQd}ucK@cDa=qOf(;Ix7i5%}>B_2J)@P?`US1-T7YKd{KU0oEqi<)Hmw z;R_D_>|fmK82ZD9123Uc(LO$SRcB7rg7s1hyYAEKLACxHld62NS)FY?ZC!t8^b3S) z!OH4)w~)8UTnOkNT|9yjxJ_&)oHW-{TY$$N%wwxFci;oFMY`x5-VSFjGDUYFVcFJw zl@QT+$u0r&K>bf#8DVSp!zSw4+_DFhR8W*90GWvR^){3o5vi1_@r-Z1Ft)lUQZXm)+5YkXmp$%q07bcQ3B zC)H>JeZzpL3UP%XMsVbe{$;({c*B4V_K@9=*-b>yd?HZ{leC!#W&}r$@Z#Lh&lhL- zFFx~-y)^u5d-Lk93Q;RA;+8YYWV>s`?S44Je*hX~^6j77((?rA{;C5hlmG4BY4b-5 z!vN{T;7MA&bqpV+mp`6c33&k0Mcut!2%CRAMeI$8OUt-^suRy|J5^*mRxJFnNnmT8 zaM&E!Xx!00=_S}{Kd^s068qdbY7YHhyJ|?>_WnPCibzW#2A|Dbst7FH{lNJw)0?i%o6T?jWiJN^q^1u>AA*@%Nu| z)wKZ4RNWx13nqijTyQ0u`=or zJ7$cge;E&X#yzQ>`Ne9CMu}fx@tb^GQ>R%We^f=-8h_)p6a6TT8`ao|cZ@?p;(M3U zAW=&=EN(GOV(vjUZcT4_#wYx2JX4V6e-QwKF4igRhz(*MHn0Fg+Teuc$JC<}x2U3L zL`7S%?7B7TlkBpMP)2Ri`PGYEmZQA4uV!w{tc=~~_Wr0sx_1N>WYe*n_*W?ziJWTw zs^d7x^*Ho6-HGjGBzxoeLz?jgG9>bu@A=@m_Zp3cL@fFprEWJ?GX<0u@q(Ueu_}EF8s2q!xu#lQ=o1w=VwP|sRHecr0W4mZr5dxBmzw7mr zV=Kg)2fh`~NDZxMze^$rHpwxBqv=-kbw5=WRptq%{B*ga>(av))#{JKKd>e9Z}Q0` zc?wAVTk=pwNBK>B8-jWO^$~M!wSB8Wff<--7ZI$To%RqauyE^tSi@`zCn!d}u6?Bt zjkr#Z`Oir%J&rP%eJoZ3a|#KrEf|;T-u$+VXKbIC@jce5fmyn0VDpp7hc?<&*v78l zXORP9cC{a32WiC=KKFwjk_gH%o#~j^`PoH;aiNqOLyRtB6xAFOt+6%{q#gN;Q0lBQ z=Fw!$@xb8U0m2|Jgh;rw_IjW4*w3WUE7miktW{)g=Bqq44L4i*N0dr;g^u8p|j z)-Dl!^FhLUwM93^J8gf&{9L)an z5#$olf!BcO0#*1IkhGW2}4>-QgfK&dDD&Pl4u)~-viOU%#Ebwff<7_t zO`BISlK0y|ML&c~u6+bC*b`&Li71~94NpDf7B6?@b8bwcekPgTrdyFf_>MKil#aAi zX9f*JlATEKHA`9}+G#&P$$%Tc7O`1MM?Q2xva?@yw<*#2+4Kz}rXTAWhd4)iav&o6 zGM(C3d+%QweU-ZB2BhoTf6TUGXi6)0Gu?x>rOp zt@N(*ON3`iV%>mb=jTM{%m_~k`W1JqJtq1UOsqYAiOw{VX{T7vD1F&BvS}*BHYvhA zoVG+~j}qZ;lARoh$Ff*^t?xRE0VT^Ad)j)k0@!~We@XI|^Z4m5p` z-Gq0!+kd1Sio2Bp+YKU3sO%J}^-AbDM}HY}Any+~8cuf^xD%CFNWx=K5P(RT8F{t= z=7h_>EZrtb%>FGjI^QKgSC5ku8$dEj9n^LF!7KJm>R2D*bL2pIC-^?pMMp-EvUiRA zw?zG9&yNn7;~CU|t^mG?8F*2b9uK=l&CauLY~_fF9yeB6tu zPN_nEn;-xIV#}7mSL#!TnXP>;uIC!rpEN@-)q)9z5KE#FvJLH1=N~C?$VK6|3XhSK z>3CfI^NemNXA5^FU7e3X736GbTue0h+TSKo^kDkvcKzOOEO zzjS_orGH2JcP+N`LU)K+96D-BqDQ8Rh&+hm0;6^RhaWL$9|9oIKTZIA_6~lRRPp~= z>9=R{B@L@qX6c2a!=&Y)9)+gdE$M%0{r)vo-y-&1_v;qqDvZ2UH~%A(Tep+ewVo`~ z1F%D{p4T{L6rbCukbH{n``B(}?KV2rDE0Go)1UEy=W-a8t~EP{&@oe!ic^ihPm2^? z)$Y?sMJi`OQzk!duN9hb>%xBc>$xdf1LC;1O#-(Ljc0Ik+BGk}jRPq^68HJ1KSLuj ztEEd+@T`ntTYBljk-MXZ;uwA0>5Fgh);h!TrCw+{E)Ii*7a@8wup}8Z()A@-9P+U4 za4O(574b_cJBT2}84xiBggrUtuSJ&=^h7RCFe&Y*NC2ah3OGM)%JRjFhxzP}gVfH8 znBRnX@$!sZ5!lj7dXwcNJr@i&5aUO|801`V_Dgm@!qqIDBd&`@^~YCZw8vLfkT6c3 zHkDgp_I`bml2sm!JIkdG#j?`*skR{Rzf*lyO1@%As{}Pq3|v9f{ZGW|UJ==@u*dA| zN@62=jlv$cOaJ0gny#iT{-(1yl>xEwzP{0YZK3opos&sYcqH2nu>@X=<^B`%ivy3~ zZ2$QFd2(-KdBW2DOD}LNK}Cj(`yxGtQuCh(gs73R9A_;JFM_3l@=2+mOq6~Q@v6G3o}h`eE5yg`PBL(<7|1mBpa5}KwsOtQ1_ z_6fotAN;{L{{Qgy=J8Oy|Nn6IWZx?yyRs!^olIG?CHqeHBKtNNgv3zxB`LBK5!rV& zLW=B5Vj5crGqMZ@_ciMM{(Qc_&-eZP-S^}1``v#y&dizXI%now=XJf7=ks|<07Jax zy)+hq{gumhudRg3#~LPNeZ=L-(ras)_%mhBcI8LogOuex4RfQ=J6qN@A8fz>8wsVC z-B}!vUMg2>-QUw2I9YFgiehV*w1@@J1n98{D2OLpT2(B{ayN$@JTWAXB_iBt$R#Rq5OS&2;PJ$TPok`jL?=IVN*`l{0#kJRH%uJj)kq@~xR8*2)Dh zG;XZ>bFN-o{pNrDpnIaF+P^KzD5WnzXn3_)7^{9OZo3GViGN7tIBa=5g?(~c@=7l3 zRcq82!3ke)EMXmF;rUi8^&1oc|9lLur_du<@UY=XzbEidxNr{+#w-hT>SlC<(2Rp? z*4<$)Us0?wHtH3#;6&E7O51tH!$MEP0D+)yW!wg;vYVe`kDmq2sxLQTs= z7_XU@{SpUEy^x~42NFX8%i36uDp2?wYJ6=f)+z-2gkf4&m)jSnv)+~rrbvh63GA;? z?IB>5(rH;qkBvuH6a~*zJio90$gQFs1RuhsSNVp{+;OmQ{FMkW-pJsK06uT|N&CBO z(cVJr;MV%dv0weEPia2Fent##U7j)#h`nO=w4i1`xfJO$)#m7V^b9x}_iP=S=I++g zG~MxXzTwleM}Odul}!^WvbC><6-j?7W&opf9^FIp7n|xelU@ZQpVAqOe8yog^1*vO zNX^^8TTFlH$j>Bx8LtvyaR}7;#ujbsm1rR(`#H_ zvhFY<8E#&djnUm$OV~Jd8m|EgbH7ivypHanG=azx_0nQVh`=vlL4qD}({=Fhj5dDS zXEwkyl*_C z7A5JD(9*_#43G$j26^pGLAY~r0*Nrvk9|77Z~xmifjVGY>~W;{B<}~ARdc2OE;_-3 zCdoek_4Mtp`MqSzYFg2PS9li!(*izDLI#SV%VuZZh>we#zWLMWen4sa z=!gBvW0YHU;Hq2I`9_`uHY-PK#`ZjXrtq*M(BBw($A1i#BgSeKS z7OCT?SY-ZH(FvWxok|o_E2qwYn=#=7X5~fml~|?4e#0$)j(*S=#l62V4FeTKkD*HJ zg+F5+O|Cb5J2xw(;%NRckQ!U2%*XSAJU-AAnWr2|~uK`sLw zHuSeF4ROouEyk@4qh2tz34cpUQX%qhF-2b<<#%!Tv{rZJRbYk8kL(5eirjPGTKOkp z?`4<;B}wG>wLuu8cRN4fRw0rhqlm)JBE2t7`e>?&tD+%0=Wav2%Ao(}R)yBF-Ed!dd+Au)hJIHCa zT%`4J=!_+?G{mZau%?ku(SQl6sc=yn?$zKGe%Ui*c>Qq=Igf(VI1}Qv&z|ynZYLL_ z7MJ<;9rp~xI`V5>zHGJp;f?z$pTrA&o~=B6`T6M*J@$qjO)ETqRttZ_bKw+Q0q!Nh zZ-^oNYA>4&EKFIPWOqmL{FJ$I<_Zw%;@oPo5aVB_+KX(slY;*6;c8rBWHN5xqNXuE zI!AMo;bw3QQC^P#@F#?u{xX}fm4BH{mzOQnqCYtlQvo1iNH3+KVr>XL|NY@`!t~yo zHc|Tfx@z7N2V`Xm;-{8a3a&FpSj8{Z2h=OjPiPmWkuHHAxm ztWp7+kA5^yn{*qW?`y*9cO}@GB#S4x?qTI!f&v%$cMPU-|Dz6-G3A&2C5yt`=fYR8 ziFv;P0t$g)Hs1Ny)sN$ltXEbt_5WpY5WwQF3V-daplnQ8t)P^-e*5nGwl}f;UU=or zYZ-`}%@}r>oTgy$+n<*weki=jT%>oZ)Ekj`)kS_QSSmr$YffsbV;6Fsw;|Ad!H~Aj z(X;+42xCLjQdcz;JkJ0}!6ALG_x6*pUj{kr*Z5akYt4C*9g0+oD=@2Ql6U{d%L>w1D6X%x&E$w0b{R97I@3g zckKyq)XDyfqkdpBAX!2w`m3%+c18Z(_uG7%o{@uLu@Zs1gP$JlEebO((Y4 zC^Kv0{FZ4>h^*d@^6YfDOiFZ9<7BQ9Z|dJ^`c$kf<)lf8SCghIuJCV8$_~elcb~@A znVj*OxqAx+4X#*ytI<1M8F#(F}5Uu?o-J zzrZAWL6KQm%TCJ%LHOSUo0D-M8!lJ%v#X8gbB|?Dyc_>LStzd|)TSawkSfGT9jfXy zUB#7L9{l3y_AKeCbJ@kv)w}O#-MizYUmkN-*wYFZYK?~2F0RGME^O&U?Z%!F4tZ$N znxOvK=3ARb0lBMxW-1m(btAY@oVIMRyQ%-YKc=i7( zZ$&rxQj~0sL*aS>YsyGphMk`G=C9UQYiBeoE1W$XHm$5jK7yjlW=^ZK(s>!XM(@tD z3^~yq($~nK$Gws*P>3-ujhK2FSEH` z^Is}!(+98_>;V4ZV7%w8lE|Tc9cR(!0F<(KBE+L(?96a#wKYSV&8qNoT%N(mnO%vJ z_pgW9-wKx!f3RxYdgB}aWon|PFvK}C{plWqSH_f)X;1ueS9w~A=$-MGCVlbhR8G6N zhtJaUR|MVi;dR>mt0^1phQa5E5G+ z&TohJFq@R!`)bJNo`K8s>k5alm_>;llYc{#O|W~%kcHNBpOXY4L5d*z_Q6Ml)dfX0 zhOc*F*4&z@-xtYOa+U70J^0t3M$04ieNVx!Pk$ps@U@C@^--Az^HPr@;!Q=2(rJ4> ze^u5kH+%B|d$*5oJ})S%&oe97+HK(B{;=2&&(AKm^;`5j=H^~_JH>sK-I^vT5j3n~;ZG1BqdoIyk-y~&3OQG!6_f7~R|@PC)?1l66M zcH7mWR3aVV=cj&SygHBCdn!1}P~*Y~F@oyf8=rOElCRN2l^JD+%GZhRNc&gcA7h`f z);G87MP<9mzYLz!y1z7JUX(O*8RY+(d=@)+9EJ3%m!hw#WL|WMVRmSMzWK>wAh{z~ z8_mU~&e%^TVB4fL<#gpVWz28?$GUfL!fhsL;maNP=<<_*!iAW99;`Zvg6Y6iuBxNe ziph0^+z#aL$S8D-{uf^vk=WZ^K0=y{ zf*7Q^q!xL_0|h%{r#(#*K5kciv23aAzBR^lI2|O&eK-=`kmZn7C8cv^IleIsHkyg{ z`%NwT^7;_{qovvO+;=r^noW#6C>10`7b_FvQNU!VTwJlMeVl@Rr%r9pG8O&YJRO-}|c zelp$vD53M;P0Y;~zx*t_PZz}_L10aOD)IV?E^038h?5-nC(3C5G4j)DR(XV`uL@mN zqQAAHp?d|YUo<(}C8GrRuWCF+zmc8*U>T|Ezc)a0zV<))xA8r9`{a&tK2S2tDd>hy z=Aq@9xvd)&UJAJLId`2N0dwQi zQc{&4S0-PP3*YLVU%KQYSyvsmZQ-Bq{lA-;W!Mgsi~V|Fip>gV4!}`p9}G)@>?ZHr<%ZW)Nn9iGmZJLR?Qd>WKIcki?c2aoUKLj# z)0w*Ou70(_*jyly{cY(Njb8h2#}E|>w+uau-H+}nt|qfWtH!Zo=!eY8zc3+1>1G;K z`wk@q)jy-m3#UOa`*lz(>J|8S{dTeFTY;EPCs*uHl$phd4&U>&fH8a-reM{nxG~(Z zRj)W&HYbHK>nM?>!Z+a$e#oa#%x=qjRl}TtN#K8o8^q@C+L>q-mgUcMIc$joDm}4E zW@fHH^{1K9g|hXNv8{UlO&wNT(Bwc5F;9FD%cv`6QLefg`uf3@(UkSCAZNKH>PlVQ z;w(l-Vh-X2$9ct-M5#%iyzb>>K;M4@FhLpjM#+r_y?B3X);)QX{Mub^rrP_<8Dd}@9mqjc|!_kGoTH8KXu*EPUB5I#uw9gs03#mxX)<}*vEqGf~YF% zt=iM3G84A;IR(cal<-huB;65SxuJ8ci-6sW6! zoC3KisJYlC2$Its z@$M{zU-Me`t)5%dHcI)BH!34=acDROSCwJBU{%I^VeCSDLfdoXn{y7u^33nPSrUqL z_oJ<-bxw5;>Sxg$L~^hj8>)9d3DED`=>Yk&ZxrbiX7~XGde*Ni=>0oD=|{nYWoIAc z!EDsn6*IUpY<2X<*@||JpqFN3*C@gLE|GG;+G6{fErD7IyFp#4an$fCy3>ZBM#2r$ zNO;D9h>4q}0pX}VIO<>gwKF!oG3t>fMh!I z!IQvraW8I>;h@}=Yp%SDWt%~9olb0KHG|CNYX9AcfRy`gRw@v9R3b}2a@j{C_OF92T_|b}HGZ#gd44F_8 zHhMjUiiH0V-?PFQN!m5t`bCwnUxz_2aK|i#|-;9_YsHNt3vx%BRBg zKF^{3{a2{g1TCUmZ^aqGI1rJDhfp0DfGb$!XHJM(x()j5-jp5*ZzDcNEGXv7cm9r? zVk-iUaTS3HomD&y)Iv~}<&H6i{U9lQg2E2dz-7eQxsGpeZv!MZLkXx7mG{$O5N zcqgac{rO$2!Z1+Ci@l2J^z;{rYqFc*UV{R}z~wa%X;nU~m4nl~id;SC{@ArUIB?~W z#jj9_OTTrCgdt4V2w)qgYyDsTs)E=$M2u#tM+2KCG^^y>sGm8x#k54(@%AF28X(>3df65XV#0(aPEp%J<9@ChROT|b%8t;uQI^RcTF`O z`Q(Ou^$ZLd!>b@~TmJD!HxU<{w_X6*O+Z97cH%Ft5*eHRCQ zHkw`dv0CEGvhO&iT}9Hj<+%JqdVLmVK=fB7GL`0|?x~b#x4&RGKmBGc!A;fw)=F_Q zJYPS|rLOg+Qg7ZbeG;Rs?fU(VXo#b6#(IF^%L&txR({r|G|1=Y7wberKK7pdDZ})? z07<>RCT3SP?#apHKbhZ_=%2rO%ixcCtzl>dv&t_?-&fZ{9!mn>2OD_t0#3rmej+|p zA8r_@b5p9Rr<(~6Ll@_+fjvG)|2d|^s{$aVtGG`Xc} zp{U{Y$d&vLmJ(gfhf9~}K3AgEy635Y5=o)nilT8hsG|oOZZXkDJsaxPNnWN{6#0D4 z<=Kkq!hdF{;@CGC44|T6olATF1#L>>-<$NCcKiP`+Vsh@=F)6}E4=3Q|Enu}pzC&_ z#$#_+{dJ_|FFQT1b~-VfTts8iwlG?{EEtFYrM!{@&}iTK)Id8w2gCMp%{tE7HHK$E zK4)0R^%tW)R8cJX>qX&RT>x9Y3^?BG%)Pr3_r8m8W#1+c&xQ>Q*{><<3hX%d@_E_$ zv6$V2pA{X%yvMR~xF-TSZ(QA% z9q?is_Z>#{f{(+!1IyZot}{E{={fLdj?DVqV*9-)QfM{(bu1Nu&VZxf zL4Alu71Ye}K%<4A+7jba1Yla!OOs$f&gVEcboS=iq$TP%m&>=t9@tmvvDGDmK)RmX z%OmLLm%s$mQ1!?EfG;%|Wjg_E=oWfki*?2cp!9Z1OeVxu6(oa20jg<9B(|wofmP!d z|C>NrwpS}A6CSSOX3S3ld`QLuZ>VJKFDtwTvuC4=V~lnB=eVu$Pl0@;_uZZAefZeY zX}Kvz!p{oxiW!Tj2t2L_Kr)N`w;QT$Czi^Z!^D;4gxwEy(P}0EzuXD3qGxgFGXake zFpnV+UL61pR^?QJLU`lL!A@49AmRSNRI{>To#wuu2_OfoFQ>VsoIl6F=ji&olffOz zN>rNxyLRzhU{8>;zx%!9#*diAYp62;p!FP~*K640GfalmJAe}o_7FZUWJRQI%;9b$ z5?6y;q=dJhPP!X@w#hT8`)FbU(Z`}lGQ&2rZ_4P~d_ae^z!Nq+eIGVn&R$7g9ETm=|?;KGl; zA}rQt19b8T^l1rBTKT&#Lcid`m41I0b#Sc$$0Psd8u(U^e}Dh{#N*2$G*g*bD)nlP zyaujBQIL|*d1N{6HS6(Nya-nzczog2;88?kS(gYu4K?Vq5%g(y{6+HDkAJP)sNdfu z2|RRK;FI97BK$z7e}Dg*yuU98G>dH=GMwP&ZZQ%%r?SMFiyoh4j&Kz^zi$G_ zQG*{B+(gjH$1E7tZ=}j~cLNT0Z7KV>5qE>%4$VcfzU739yw8_TbUBU;j~a}B7wn;x zQK`P2?seNnZuqD%_<8DC`GT_AX4@EVjewrr`VYOw#jT;^h29(wS0@-lcQP%JKHwzxiQ z!g#*8o--y7Ept(f2Fk(GrR#ZbmjPWY6AWHBfuR#Kr2bCVlY^y5IPMy%SSBt;a}6}# zL=xTu;uLNfpy3NV=sxFXbWHCa>O5<2(uWJQTejbY0es$}$xD|@j>EFX#y7Y?wDNP= zVd*|FL?~IggFgOxGOt zPbVw007Zr`ZW#~fi@)|XE>SVpz%H1#pQ`L=n;<@NjD?>*tc}Ep#8YQqSc%h1!i(sk zV{=Dkd&ZuAEQtuwx2j6G!1onz25=JIE73sNkT!H0A40X1u=_doH`Cg58vcqbROV8q zy9@U@+UW&g;iBHx?e-kQB@T>j>0cJ-fZ+Jz5BQ#i(K5SPaow=0jkijv_g}HK|<`4bO7B@NK?N+=1Eur3!BQP{pO1S7f<<;^SSFptM?gsp)o=anJC} zcm4RPAlCMg%PLWY+vuac?Maxiswe0iL=w6?_me(2!U|vkp@JH;qy!Qrl?ElbjYTt*05}@ z0;})q;vMA|0t!sN4q1D${TWVkQH!5uWq%Fsy!T!>v-e&0mrtkn0`_^py<$ME^(=^x4jjG>F-%>H-W`8Ya_89K1P2lg#J;q+Y;1vvsE;GHcC4lX422FcrskJua6 zn7b%E;kVC*$S6e5MhtH7f+Jv}SLgSo5pz7G{TM$u#|LzOvf#bEhX+H z!BXCMRK=?hUBu%AluPBSUwaCDT$Rnds2wmX?OY{}smP8lGI0PZl0_!--3B>u-zS%v zTB=5e?i75DxDe5$FEZMmQkzf!ba=++rhOlL?2s-jlkuD_jS)WuhUFkKHq=L*Bdk?= z(m&d@)#Sj?vESJQgk*AA1Qy8&@$}w7Ch_zp?v&jc3~q@Hq|dz?EabD&{s4^M??zJ- zAjT<<9)*qKBzH~w`Knfgus?M_guu3ivaVeWhC+f;a=5atX&6I-nEN?X9|2w!B*>t@ z^Q{{A7~xlXtG0Ff&oS`17^irR-gx?cPGG*A;;Xvoz+Uo0r+D;49vBlon4h|!wHKk+ ztlwuKOk$uXVB($PFQ=RX-I}@ebV@p&MBwb-=FzvMztdn2+8za{##ssGwt4P4vY6<% zdKxf{tgzL}d0igmhLfZ%OAkq^_8R;OUKfj~G;|wQdojdFjpFQRvQDx+DKh|xKmBU2 zf%02(jINJAKnVO0`Kv}p0M$z$oXdeXW-?oFckv$ef2b1QRyoNP`!H>vS2OPg*XryJ z4$m-Te7`KD1nCuasDcn;6En`+ZZo?6?<<|v`ehu(Q zv7-c4Ks{kv2IWhms9rU>J|q{jQ@IECqqG`T`FD}yKtDxz(pHqpW|qd{;W38#})`@nY$DfPycu}1(N*Gyx?g+7?IA(DnDH)yq#E`jR3yi8Rwm>sTb8_h zQ$gJ`s)~)|ZyL3P|L-*}f0YCO(1sx(7g~x3dI-k50AoTpQfOa_$9$zd&R1lx5cpde zEJ*f>T(FKrf*hHteB0q?#R2v^x~F(nvrNu2|NK_h?$<)ZDxZ+x?X)A^8hN2i;ZE^m zaa{sRit`N!-aU>uu83^^&5!+8?P|oBsrsMdc7@9SQ*pb_xY)5~E4JcNA3-?Q?8%Tx zcmK^1opF~RJ>l7ggYg3ybw9i8Etmc?Xm5^p-%!oaP7uf$NXb;uC+Zmrg zwF7Z%{nV-$ z$B!EOHuaJ_TeE<~hBna00P0^`hORA1*AlBMvQqY*HmV8!MGn=6vhF_xWh6qmYSWKP zALyNJNdPV^s9gQBGv^wTp{de6do@5yuBi5t&%z#=Lyh;s(|?piouoh6_jJud!lm$5 z@3kAkSkBpv$LR7sdW!4f+8UxnK(M!Robf48V*Rt(uN-B3x{KW%T7wh~GyYgqbD^YO zSvSDv2g9#Gb2fR`^qs$N0*zKGr-iP3g$G;~7+-Q<{#9e7yUG43!9yWKU)2z;We?%4 z4?jP?dQh3}cJ2N*-YfoouS>E4g}D&GdIahWjW+UtT$+P3)oCfAv|o0E?@SdGatI>6 zB_*$<0;6-a{tshIo^9`QkHl-gciz*BE&X>+Gv=|CNY+5CLlo>W)p6p|P2Y415PRwC zN{&NZ@(T+tW0@C1T!Z9CtEEe4jVD5|Uasx7rUNpaHcPgiNXt&RFG%y=Pd^>6P_M9n z@Kqk6?2&xIWwajqAkp2Jpa7~eQz)o#srMfVoyP%pZ<76E-#D69)&|}~ zpR`XF23%AHvXqZ_&-kt8D1jV^PSgcwlZ+~s`!Z5EHS_N?_fx5QBj(?qx)b>(=S|0@ zsV-OkLG+B<)o3kb?rQ>8O)`6Y+@jT%JLqQp{1%U8+;%*gqzhdtj}Pdj5Y2xt z=4v{1oJ;NAOe-?ML@B+UHvpJqTB;$e5^UvCO>N3{RA zkjVAiEN0*3+jBy64Wh$?sWSKPnVFKP*h<*Ee%-GNLtuXzp?QWHVvNKT2R@t)E$d+V zo|~8oBn$(c1 zBzj4M=zlYvUl3~`XoCO66uLW9_PR`=gztdLWu7NF!_n0PR4m~a*%toW34O^wjoPSD z^qS3^6J)VhFBN>g`Q4|qZq`(Ypq*&k3M>6A?zBq)Fk8y;NxL(tG&pyh?aGr)PKjR& zkn0NA4sK9kTGOAg=NfA!PhAiuQ@b@S>%UO{!n@zH{)2?xnF2^=XxrXSZ6tb~{X)66 ze_u<`+ZW#AK6ejaVRl6vo|%2`n_Q_^R5|mC+E|%1m6a~jgehKR>jQBwM54`GYHcRB zWz@RgxEk{UZ?&gjbfjyArkDzTb0d~j#g6kEi&~J<6rFu#nfix2i?%D#nH!Cbt%GU1 zlBNg7zhO>j{wxR1zvt2aX*EI10}?l#$MM&lE|u-hQm9QK_a2Cr>x(=Q9!C>_QSz?# zjZFC+D&bkOQwe=&SeR(pWBoS-)fxZ=CszeX_R$nNp+Ij7A{}DDIr|Hxf%6m>*2UKw z$GCgeoCi~1XO)^ir-)(?k4k2oiGFoSRpCwDw0)9Zs~cCnE9|Jc_IgEQ2RNB3zj3d< zEicOZ<0rY8%6(lmALL-PQ#5Ol=pVMge$s;vKF~3`QdgWPG$zOTB}fqNy2#v(W@l_O zJlb{P4!GIm+YNiDrMu877t8%E|4cQD^@Y-^WP7&%1G^Buf7sE7`1FvZXR# z@999SQ(!Mo0VI#De>06m<2m8A9bo7G=p-CRuc>JugN}(pi66dRt{is&qH8s$;RzX5ugqo5wE_{6z<-mHEdYz*7>av zu^?LfbaCUX;Hy8{@~_&AV{&)@OJbYJQ&BKe^7n42*^hKuiEnQJ@-d{ zOLFoN4t-d~<~D zpLc7tyxOCTQu@3!U-XwW*JrTI>wkl9DcoTk(b2r)*%)%)RoBdJ)pcoiz`5A({kJN< zrt<69_w%m5lxfPjenU^aMX{$BE&yTr|9gU(c>*>W-p;*R*-;_{O}MW7g&&K-hTkO9 zY^_I7AAhv8zDfnErAtb|Bag0oeDGO}F_rW+Tcb2X?3_+_V)h@2k~tB0PtTbW^=Ul5 zGp!w* zxDGOFr`yJZAu9MsH5EWaPS4P3t}CCmPS5>QdD*GcK})0WN3SUoX)!fQt2(o4;n) z&IRaS67dkqtFD!Ics1B;*q)!A}pcrR!djuOHvrZwtc^d)? zqY%&k9z`LJK}8aBJ}9!|hMb`F4MED|mW^n7-Qz|eFWx~Fh(7NAI6;7l1gVq=Hfo11 z6d9<2Y#(Qv6I($(`O+rXC*+0W>TW6lFdE2uHyo#=2`8Qv4HP;~@m>LWUy%OJpI3{X z6(ywO|G%Z4N6eE|K+rdOee`$XdzH*Vj;`!bd`%zV1JP%@J621S4&ucTmHHo@dxZ;S zic-@1ggZZ2no7BA6iSZ7GU_MOdZ{T28^tsQ3hHP+i_9%iAJO~L`!?xSm5cKrpFHZP zRj23Yv4Z;*yH%|xfYB~9wi5JwQvB^4_NFl}6f&5q)>sIXUmMTveNQZJL?@O*2Cp8M zF!EjcJ9#Yw@>d9wu{XznWNah&2P9)}8gni^BS^+By&^Q6oCTX@KF}I6XlM+{ia!1v zC}8B5X2J4><9)Qhf+qy@`hw6Dq}B#UXt^3VpzqI$M>IUGY7FZS zufEo8RIP0#V%Nayj9)_Y*x#4II-(em@)2qPZyV2Jb&^wiik4FeE&>z5lA%12W3tu3 ztbt#+vxuAni6DtM5)2wRx=L=!^$#ckNV#JVl`?O!uVaHJPB9Q&}f8a!)O*fr^yM+-$ibpsw9nfLQkrB7s z9U0u|4oR>IsBh8f;r@bP?Ewnx6BLxO?c{VaZhhBGmi6o-MRP?9>NIh)mG-v?I-=e# zwNT=8&7(ULZ(2{Ky;um1*b(52qO##apFwHZO2foF=|$c{ZV?+ZSW~2l-^?Z&qYouX z>j(%?8D4rQMZT`qOl8u_{90_V+>o0K#)(Zt?IKG%_L*i*xh2d{rHQ*vlW|?gTVoW_ z67|J&eA7fzHzDjm@t*`J{`+Bg(0Swo5y3wc-~9YIL!I_w=IWh^3wx|0?tPD55+{b0 ze5Dy(KA#iZUiH3-RK)$=Eu!AcIG2v9UpQ*m1#H)yGd);g6F->R%kWc-?j&iJ!YRLjd;7ECE}@;G zoVO~Lx!|N&4}*L)#`O~lF)%S0izhqoF50`ji++YqAq^)A6#thg~ z?hz=?0=?d`$Z$lfkPTxzn?e=sPi}qlCwYayc7!;O0yDf4sQ70i+=-7OVWK!jv`%|E z;}LP|W7w6m6}^a}u!{53bZ~wwH>xyRhqIujL@|{7C>5uQxr&T`P{AKU2|tHbL#-e} zNoTHGM63Q%MI%s|(M1p31*WOsv7gw1=6^&-9fMkX9a9A{(EJwwn*W;Z{tPpxS~GFj z0kfm)Kh9xVkkAL~ynQMWAy6zIh6E`e&c!E21XXT^;%vZe<3*}PaPccp;7?;eqq-2; zC!mDI64cS|?K%uc> za8Ck90S zUE0?fLrFv8aZuC_qAS;XiwJ9gi9!a2L3yUR@Df-(j381i49c&-g+BwXt{+@o=nXtM zP7@s(*2W{IShVJXRtKX0MPY6HVkDu0zeoC13NTB2ka0(#tLa2p*g2r!4!h%ig03Li|CCO?wChvqfVh|F&qJF z?Lka4C#IutHXi&~^INMShCk#ntw`Fb6GlCd2c`1?q+|5`L}QHm?QUp8)Iqdy#7gu! zF<5bg212+4a5QA<{+f92#riOqKZY0`h#{)t99L}WVwGcppT~}%R88p~(D8(@!{0#K zP%0aN$S1B$Sfe|1SSyrc!1E3(bY6!7TC*brt=18XfRfhHAJI)+?7isroCGXW!C!@c zkj}_O>&Dw^E4(@p)+mlTkKIQlG_$tbpr3e3hMdHTcqm)VqKZWXQKzv1C|Wc{dvEj% ziMZgQI4p8Ao*kcxYzm{}w>qKl7{-tDK*x5db#KrqB;m9%x*NC$#tiP4$-0aexZu>- zcNZqTnQ|OZv-YwSTsm-J9BDvsm=50|5j;tx|7&i)280G4(_GkI^l^h)LEEYqH8fvI zoXy=v1x$|_COaBRk*$IcMZHA`x<@rL_LF97HjCpRXjaVbMo`^Q77gVKs@B_}*$7f6 zOgw3x23{#bhl2LbHeA~~+JJ?Nb5C=@FL;u|&tR8Oz4QLS_Jq&^+rx$`wGY0^GRBTg zL$!UZqG?r4qruc5dyAa=8y+5#wr1f1F*Hb>aCg4L({LuR#zv;Y!5fmjBjh~Fe7=EX zMitJ3^FzCI_|rqFT9a|+7)vCtpYl;QOb~MoS%V64IPBQz*`t9&vENV>(K8deK_P;h zRA9{!O0nU#D(VMZiCq+UA#4t+Yp#Ya%FUP1P_|8IbRFp; zy>YlVf-T}#bUfK2lQp&2`H;J8s~PoQqEI~Oqc92vd8gbX9g9<(ic_SV8gNqB(@i?g zTW~rUDYg`q2&O(YhWK%ogFEPR9d^+x9d?NKP0sx*k+&$~1zU+AVZcZ!qs2Rt=QI;d ze;hIC5W9=CQ9&|b)))aK5vFjXK1`aomG~!L2x+q{Rvsl99ZKr14*5ymrX^#R( zR;co~8xWReaqM%b^Lo@n*054UdYH=`Fh-2lw0=x8WYh65n)*1Lq{lU^4k`etw5>do z0+YuaZaj@(pW7m~I^TNe-x`Nv_2Jg+v9qg4u%mdM58(HOXQZk$UJom z50SZv7n4!O`+Gcv-9~KF>fE*SP#&d331QuU6$$}X$Ov;8{l2{y%m5V$4(!c(qm?Kn z#1Xl|V;mFad)4#_t{cydV-BHMdtilN;l@33r0^?PVvGb*v%L%0JB3?T{;1jcn%l2h z-ZBT0!+Ee2sAT&Il58yt8TNxvFeMc+u9GQfXQ^S9kP?_P8$lgTjMh|#$z@Qm{KxIAr-c* zBfUFVTYCuiVFT#7CbT5 z8^wlbBRkU0YSIADvNTzn7K9yt3VQ=(j4*y+oxD#L@&f0GVc%$KcV`SG3yH12BL)mI z$LA4S+J_4dW>U9Aao4~swax?J zP{!15-Mw+*FbSuNF-B&GwWV#@umEFh9@duH^;#n~n_i9{e+}z}nL&t?9!20d!Kz0U zVMpq~nzcno8RUtj%@g6>1D-^L@>r1`W`H>hiew85O&q(5Ge)zuAEk~l;H1$xR|$_j z(UHy?8_wU9vwdaGAMuj-)LO%dpXXbto-5&{WYTeJ9-P>2GlKb|V548B5#w_sXJg=^ z2bmo~$J=)g*_J*}h`R1$5|LCLYCSGA%`sqgvw@99axNwOX`BhVuA{4G zmQukgEjhwNA-awv`=$k@0-~N0URBoAUPPZwq+mFjff|bDBFh%5h>WNnSI)6+cVdiJ zIPJ@YWyY9pjEDCNxRGY_wz0v>fiJMgU`?Ws4Hn=d+jtIES_AItRnPA{)i%h?2jT+L zGdGfji(85Yl1Xy+Q^&p9&ClbzRAsVp>0WSPDGvt5tnO z*1{ER7+++1L`C{ORcjc|67vMSJHuDOMz_J;51bG?7Oq+C)}3pnH1AulqGP%Nz}i3pi;76BkKH1c+8MfkV}% zf+xbcn)ZvRe!JKU#aW_FQ9EGZw280iVJNDyh(d3|nQ*+o1aL8hQXM{&sUTYw1HMuQ z#0}N&@QwH|9Cs3v4wk-a<7p)Yn38yOl3QPuD1TsKvAOoaxcL+TYSs13qWE|c_U-tk^f@GX( za3WYUShJB7z1YEofKur2h}~B^${wc#VHX`(@zEEh4Kgp%{0f}SXRz~k1hGmW=7N&C za|2tUiSD_v$vx*ERwtlvqL~I5TxPU)$5%$+ImF?7LCggWFJjc8&N)D03Y`*8C6{c0FL&rA&<< zd_@?CM}W{&smhHsYTlECOA*g3qll-K(ZDmws6yZwQc|jSgMgoN8RG?vBFkkuR4Rz5 z==fX7;7`jc+M{~+PQgh%JG?loO$8(3d9o<2R4hmoo{f_zs9Hs!>=5E)T!IxhFj%B} zxX$@QPIxYUn&sG-DVSQVgDekQxDJ2Z1D)iqGw{Y{&JHJfD6v8^js}xGw-esa!&$}H z6%CUFUe4S0#g8D^%xV@ha<)r;c#GWn{E8DM61fv*%+yBQdNV{EXN%5N8jxagrvPq_ z6-qOj?SVKyZMZnE0t37ObZtyOL)n^yQ^6P_t-~t>4$t9@(LGT)t9)7Ht!Xe?oE%u` zaEwWuZ07vVIXEvi736rhh-b9$ayV9WMSI;x$OHG}vB~d*IhkVShDAWV)SBjxJ0Q@K zzX9d`MUJ!(`ztZVMWi#R`UDA(+Vzq5X*s#iS3 z*e4J2B}7$pP#_x^$0@qa0r!fBasH?BeDo&9H;V_X{rSyn+zq7mKZ0;Nr452m0;wPS>jvC-Mn7jRx- z=`jSM2F5+mbu%tnM4K1y>Y&`y&A32(23;EL0UV1Ta4ZYV!{1MN>VoN(=9soF&T|5p zhhDV+O*$szLOcevSEnm*&ekV5bALwc>{UF8}L2@&z z#ECH*_7pReUzoqn#}CBjqqtI(Y@CYN8CwTAR(&rYyF04KgF znGioi{5tb{?0X%R_!=fCF%Wqofye`mbw=r$qt2N9DCV!_bM7fFbs{HIihC52D>0=h z7DT&(nE-FFZ$N}oPBJcdMuvwhl_T33>9r{VoSPvd7%U(Jt2Ic67znL8lQnuoP+svS zDGkKqqETc{26!&OtTg-+E{Ta%M&_-Ob*Ny?#k@W85)O&&!DwA);-{D|z?u59g0Xxb zppVjTb&_eOXsQrq0zU|G0&32|jI`CoMFSJoSQ4{7;tlEO1`-Pe&`+q7{fL3eEDRIC z7Gp?Pn`j;gk7=DhWU!d{RXJi=K^bBd#&Jl*N)zdW{8h3ok**7XSFvq@exMyU)*!Pw zfHp}5oZY*-40yF{*6N|6FHM`JNNYOoioZqx2am8e8;_tiJ&$M?G0>JPF&6+O7RMd| zVzmp16=O~1oJdGq!AKCq<*FtGFe?R&F3@54MKf7({)H-gjE$P{nZi*V@Z3>uSl(;U zQkIzj0qV{(1;jWir)Th^Is;r2fBNrH!FhWBT zmCIazvhHyeDY9x&l7{zf1nL<|79Pf4S$x@fH554v%ol<2G&z=#MKMzYM^WKjt?lf62i%SM^yr|8BY_n!gk8o&Gk24oT?3bT9Hr0x{Op|9u>*mnn`xXFgg6)X{N$k+ zLe5`eLMBWJ7a9id*-S2H$l?Bs(rSq31rLUxl}FljRt=1qMC*)xlw)G^)J|8NATq*- z@oCBSF%ZUbDn3)V1ndIV8B>88ZQ1kCIY)=3T&nS{2@p>{}g5qq~%j&F#|uzd@ktBdk3(DQt(t$ z5sRV(pc9IbPN6<~3`B%#U~q*}_~~}Y!l(k6VU8dgn_(nSc65%C!X&XC7~W)8@?9f5 zEm~jmr|b_WHJ#$vP{Da}O|vy(O=lo=(S+fFqEk*jp8%vp(XF98O~-;b4kGd*|=E;FQ8VE{-hv!BU$=}Aq5?P!7Sqky0SW8R&4gq9|+EK!!HML z18PMMsMQIQ4}|ZZP;K@V1lfJcLq_}fQ?It)O~@$ip<{rm=gSbL92${a>{ z=|XEMfI-VOW}a+qr2EqI?)yRdl-n0FhTw6P;50bE_@M(`nn#kM#Ij;z?G)2Afaw@7 zMfM~yCG{kI+~k6*Vtp|}$qN+x*YNy%Rw!=gw2<6Z61XC0_{_1CgB)a9Akxmjk?&y} zUxP4*FO>I~(1-{9s}JKXM1km$dJZ^DP?it92Y;ZBG)1Gr9 zP5iE?Ha9#|a|{y!+|~uLP0qd3#6u#M`31E}@t3jE7{l9Pq)^FmUYy)g zx}R>R#0V*l(jgHDI{c8RR9pk51_*6Yi8xn`*XqLnjUNI_g_v~^v6YLt5WASbDRJZu z&=^>k@|d2R>NGE6!C2=sq8SxUK?D(vK;#lNlhF1EwW~ z8@W5=&55tS%<08zJWgXbP(V%_SEfB?mfAgBZXMvHv3jz+m-4iV~587CRU<$ZeM0g7@7zu(= z>;QQPJ73lyEI(FUa@9brJdSb!t*kT234(yFH~dzOA(-HmfTSaLbk0Q-aM3{O>SmTD zZO92@W4{08cIi1hA`63=$>8 zcg6J)j0?D0Q5biWR1a{qAek4tn1QRs3c?*fWMzsWGRyiP9U5voj64`@0lmTPi z?>Eb^4DbnK|4?ej00`DuazsLyx~U!j6a*rExdEZPm8TB+WSRKm;07%Clf@Q>bqNd{tn4u6Cfe}`i2zGD%eC|=gIRdnB{tjMo znHSHfaYn#qG-QmXbrIQ&T?e+v0TGVF!45e%98Lo-c`b$Ky6z6!>){8AWjv;rtV z)FT6;9u1`Z$4wG=)9b;WXpwoG$R7fj@m=|?2O_@a?iC8i=@D;QI4LkLxKpNM{jv|X zN6sfGbytEa2>>7x06^$CKe00sI0XC59zl=Nh}jh^qwXpO%!UuBcSlT6+Aa$hYRrje zTjY6QdJh8u=NFZXySvwiiYABZbWi|8>j*QLY}kXJzW@Rs zqrEzy=DP|-(csmwVi=X=pm{xlYku^emvdL0W-mI$j|jNxn!r`>CLv_D{?yuv*Q^1SmglWTyP{_ckPrrb$e2JENr?%5 zG~!3e^8GX9U*J%aqqw{OJ*@m00ZuSrser!o4d^>ZaY;FY(bhS zTz{V8L&awXXM)iH((xAPx`RO1<+A{YL$>sh|2()>fH48&N>46`eEF$UCRiCJ4{{33 zlFLc`jPc|!g{9d{OBcWy{LG!G=Hp;;K;!X1I)02K_A|qa16er}$jZ?WKdJGN!MpJw zto5^)y-;Qh7YDMk2~vXzN)!T|5gE}l#tvpI#sWy3X@GLgVK`AqF`=SolVU$K4|JyE zy@ur}=JRmgdzY53mV;jfC>=LIfY2pT06|Hy1S7oHUK#2r<|x~f#z_b7=P!Z%JbpeK z>6{FlNM*!aNa`PcIbBWoE_ zhs+xDP(Xl@Br9+x1+scPKnOJ6vkllEBtP zG**Zaf~gbrS(>IHkbB0-T#e!9FtpxNFyc)GPq?&BxZ->+T1YN^ z$JC{00b@Ogtjl0ZALE_EPvUBbXTya9TSa9^{Sb04*pV&hInj0%w(`Q$G#^0kZYErC zChtlI7SA?{KYsTj8*|mdHNXvJK$OuAEQj4J5N63@IWZ^6fUa5KRdK{i7D)PGbv8T$ z78hOdczE*yNRx!`RW?QuK}C3VeC;e)Lrk_j9{+$+kT51Ykuo0@y*;3+7Jc^QVqnZK_CeT7%zZ-ov}DwWIsBV z1@0O*pkSfo^dMB#e2Qb(V_335>ViQ;F9a;@5+Jx-02EdzMddH8FAeq*aJG&Y-Ycbk zJtYCdl2g+>iXCt;X28MtK@_x3;6J_(j4KtvGFrgF7y$@b0T3dbbFe7D!FGZ0(+xOS z*&ir){*(a{#va!q=t2Q(bsr%7OvlzRbYGay$MIvflMT-@&Y%HuFv)<`-5*@$I%xog z%E>~2z$}x$P7Yv5408`4>12w^%_Q|WkUukqI*AX>@+8vC0scWfhzPuZR10zpj{pgS zNYHtP0*5t%q2N3aVgP}VE(nAgC<+)BsAcjzX#fdh2P6!Zq$?p-Mp1vUo_t)ug=)SS zN4BR8fJVxblXP6~Kp9$RfQZQq}!%E}U zKmMjDlRc7}uGo_8rk=e51nU@88W07s?CF51PYSS21$bxL$vCe)5PJUR85VRn>@h>J z0!y74V9*VOy^En6KUT{P3c|*I)IywNGWBm>V=0ivLIlKg%D3ztxwyOj+`u6V0m(mC z9mHaE8|$U~#od9vm1IP~TzCuN5pf~U0Q`McV1yLL2~zD=Q3TS4i+uJ!E$zS@g1@{p zgXz0nN~&Fgvj)n~7%^aBY&dZTik`aLVN!wOh9-n__=(BPdq{^oFE04@k>Jfpom_`$p{elR+wYwWb|NDJ0Noo0O#?=~jIl zqT|K|fb4S)W_;Lwz`=G&T(97%a5~`7_RQ>b0pjc*)gf>>;Ifskh7l9=fsP^qOc_~` zE?SV+69lv$D3Pnc2--3!@CC?nu|-A1G~@#V*&d{o?$bf?Wh26#4pQ}8!m-4-t!IQM*>rwtScVJxmOBOymqq>=KYfbRj>m<`w693 zFady-2|W02KvL+3Ocu-V7tdtcrHV2I4*#HMCj|Ig7C`;+ zBZlgCumOLI9{5{HkAua>LAIxht`k*MMk_JMDs;y*HJZk`UW_6FS%ototB^pAXTt7T z(XDzqG{m_I)Pt;^4i-EYmJ&1V=?saA2R=zLYBzQv`=Kh%cPXoqcUS{83GxbeNuw-W zyg^=}1xfT3xCl^xl92o#Pf4Op@qT+^zuN~?b1i_ZGoD=6Qw|0vkbg`7{Ol4(i=4)H z=RZ6boIee!e|;#DFbr521UOvf#AodtcaVgOfOf@Svd2U-`N@w};7vdV5kHuv1T#1f zPHbrt2^~3R1~Cv%PxsJfK!@(%Jdj}!4ai|PBR?(Boa=fBIlxm11sOJ*x3xssK0Hr= zg_3C`*8%+5#yA1#Dh#Cm?Weesvx8(cC!>xHy(DYB4t5v=5MM51zknFX9>hSKYYPS{FAIaHo-wY%!y{ZymD3P0MyESF{KlQUN8yB`byHz&A>}zp2 z{=&F&`&DM+54E5_6ECAW2ENz+uXQt$V2Nj;y6x_6?caaJkK8+tu&kKlKT{_wDR)T@DOzS3~ER)G+KHs+@P^5C-@%Kj1 z7*)PDN^miFynW3pLDm=gzn3OG{4tWAC)v`jIOi8z^rP3^5kFcl-_4yWRr`My!=H1= z3EJ7Z`A+ZK4#gy1G3nK8$V$!Y`mQlLsKgxguN~Xeqc~9Ub)LHD_$^HK?#|$k&S!TZLF5>UC`18(N{^%5X`H?%NXe&<%`pNf= z=qXpQisahUX(+FpBmTnoDP8#u;v2R9O5G13(r(v-G8AJDMH*9z)9*$-f^#(fk5$Rx zN5jVFC3W3kyPo}-Z={XAUw2AtL2uH2D?5~aaci1YJgT+Bx9lbIAil`F1ZLw^FT&TS z2^Ps*&hvyOQH*jAo&|mf;sHJ7!bYOg_H_;Vt{mbJQUn$GU zQ*g3}a-dW1mPZj-9}LzZPtHV|p5nohaGYA(uWj+6QXQ9qF|1F{~vRA5so8D8MT?>5$^%(n*;bwWH zb=BII!sE<{f$;v8eycRgwQc@)6pwJRME@4<$~_TVSf+aTGojG&vy0`w^>1|iN|6RW zpUS^1*dLsv+4IR^pUMBf8i75^SNz((dfVzX*=p#C^q`_v>PI`3lw7r&4xy-T$5{Of z(euClKQ*)vP{+AD0?xz}a}Um2Bx>Cj;I04rCiP#DnFp6A%$hLtr@!AcH$8bEK2Zu< z9$v2U25k#fLH9uqbvEyd*WPbGmuAd)m>S{b6dj1DzqzAND_IYJ`?TSuBX#are}|9N zZidn7&;8(2|37VS`7^ZFf9`|jDqvd`R9UUN4&{lg7dn46h#73ogKANc54Msj$JLHC z)4|)+49hoDE5}dFUBCIvzoXRL;vDpjY{Eq?Q+;JP{n2c>qaWr&X=IY;v?+ve=0zE z{>h}Zg^{a_fp@={Iq**@h8R2ehV`?o=l-4udx3718d)>@7+ek3$WYkVFERYWcYf$< z6pa7wen9-cnxOS-xc%SOjXu_PdXHwNWARdNIZPWgZ-i|LkI;FZej=CJe34#`Iq{X~ zT1cGD`kb0KcK?s$%*r!%uO&-e8F}mPF1Ia-sMsa*6KmMY?g}`|Oq7B?mc$bdoOBM4 zg6$F?(&?y6_31%`O7q-HTWuvuYM;_u@TP)2IX4dmZ@mq-Xgy5ieR<;*AyElbb*u|V zgU*<%0&__4ztEf@^@e3Rop{`G3Uti;HRtXEcI?vaI~XN}2R>cUQUBWB z$L0v?rx98}6*ZoXo1ltXY%o~lY9LUW7jj2&!r@-az(ug>e`z8C>`Mwx0`KG75Clyz zuY7o!5X_tUZ?y7{ zaEUK%Tm@Cs{#?}5G6HMQ!WlpnHLc`&uu;Y*{BH?T_>;1<8pz_t)$=7+H4som?Z18C zeHSd~v(Kxj@#!tlThQMERn++O#3(K3dne<6rb68J{~Z;SgV9PZ`|m^lR(t)q2-dCD zK;&|@CgZ_Ut^dk~{i~vua9+{uGwZ)PVO;mEPeD<#@qcyEBJ~=elPCVac8+0p%=lx3ZKs-d9zv{aLHY2vcf9a?GG|Gc+HQ+Rn zYaBk#0W=|?I@<4vrAsb1OF)$ZUZHH94nfj?Z}!=av+D z9ns+4fINI;+c)gCilDkd`e1 zGK6hQ5FLh~cB2krS-prRz6|w|*t*Y??Cq}7xARD8>0KS7lP`pKiwiA{(8qO9PSNc5 z!Y|XmCJ&K1i_+M-vWG;7Ao>w@H@Ghmc_&H7oU(50#LW@4Glnp4JwW>+G~Af8?s%Zd z(D{gMGND~=WC_BTZ227)ZJy{$Q%p9)(@d$oz_Rwpmu`lnnbXG`i94|ql!nRsIHK(k zzHT#p)jicz-G~$;6@6U1FVzf9v$T&1dI~YZFOFIi%UTht5GXA=urbk#bjvdFW?yX`C?a^UxyA?W>iv=bvKPxwM8wIldvEZoa`wBsVl+j+`e z1;z?gGndf4^^cq(CtT44wnO$kPXxF7bZ>pq98EiM2sOA&Nk&JZXfMRLyKB!G@d?Et z?^YN(4KeMu+fx?bNp`}$MULJ?sJQtdr+ViTz)vGTl-$xn7b9BS)o@+#r=-d>$_BY& zJW2fsYn_b{N7s#hAjqgLuTBMdifH;?_&;uY$>B75hw2Sy$=$!NZP4GRJQog zl?aF%J<`1AsFX&758P>z8)ayA^kp#m z-73c(Ss|E_H9ccVrL-FCAp%>P==o{NuPDq;Z!gi2rc(^b2{!LuMrMQaj3IXl(hT z84*JL0dc&f8gzCUyEEK&6m%Fhs zz9G2KU5HaRLQ*$@u8wGzv=|c9_si|1@0U9*m|)Q<4ag%rWX9F4JN0?W0wHNz9erxF ze_=}-&4nHT*Etl)7vD)7aUp~ojA|`}hI?jTS&SBC1Q!^64rm)N_QsJev06kCEQd`0 zMuok5bbKdWJ1e*`X6Q}?#GSrxKJHCIC&h_3-!De=H$*$QGcvKxbnTRfs$1%4S2z0} zF!(6iIl)k~LvMqL6WaSAeh$*keRvs+-gIz?qn@24Es_YLLyoO+go(RFPko#-bvxgo z@Rkd>)$al>jmMXgw_AQqx{TG)ofVgP#7m^XZU;`aE@>O$9rG#4naGif+2WyIi(SY4 z_6uuP?=zBHH(FUj=(gbKa`!rSNLn~|h@4Nf{-&OEoU_D_Yfpa?xr+X9L|=XWU=WL^ zI!qDgMi9W@1~5d?Om|4W#fwftWV-G4btObXPWTS#t?uYMB%bmfDr^~|{Sf1Bu6&NTM?krEU>Dhw-1{wuy=9?>J(qa3$Q2~bzW#~VC^I1zL1O9R%Lo7!Z}Bq3xzR6Y^tV6@^>j@nLI zAIQ_zZwqvGG&79NJfb^6sPy`$&nq}ZcfJycipi;aGvZRX2Rspd?o#ec`h+Ynvt`iD z2xs>K0yN@?m`}e+nMn0Iar-UZFEQeFTeQ?7kDlj#j-Yf;xMFlMVLk#ve*FqDu~kv3 zpxvtr=m^$?zi#ink5(RR} z6*RZWJlcvjFYvRccwShoH6pJU>G)EI^6%}h@t+WyeJ)kf&8M&W);?$NFhDb&bAZDj zP-~gP%(Gs=>DN$pdDv~o`r~tno$%+P3#=&>THk7~`Ko`83*out%r}6wT0DE=&`rh^B4^0J z%UVBqTYvHOoH@)PSzS^RubmWmps=d311V}k^R#UIzM zuL;1e-%DkR`m(8KPOElXz=LBz+O!55&oSs@@Ff#T<9>0uu*b~wHd9VpVeRZNjlt!7 zjn?#gqbnhIz7!CTx{C{OesVTl9D4$>Gsyg0&xsOO&oY%Am`u;8`kXNKr4QE~zIloDrLIT)%KcYg;yCItT=g$B zzttiSzE-g{wZ$HzzC1F%{(|x0y(>0c6D1>UsrgQZp07TqhAURakV)u7WmJG9@!e38|KOs1?SstO}RRn z_uaJ+Q&%XNr&-fH=tvG~E8-Zo%r|*CMqV=JQ1YqJY1q?gEYC?lto|9vv}MA6+tXnu z6a8DYdP>GY6iTW|flfmQPKLG*?8Y72QZxz&#RudQA__;12IR^>{WGo>g;LJZ6}p{U zZ2N^nzO#KkYmG7O4yX$TLHx{5QPQ*HJZy=xw&QmcpYdM%Dwx3*{DM-c)JgCWV}0#7g;68Con6Rms=CgXxy2Wbsq#sF&FBn&lMW*Q(R7-DeUou zzbEp(|*pIb24gEfp1Z+B=b?T5kR*k>eyMGg1agW~MQ7!nM2K+LMK!cy?B_cf9228^Jlm48oqW&h`oB zV~vKS?S7NhwZ#{{UX)pT8&dWP^d~HP)#L5}zDco?TvlG)BU?y{)Vg%N5_^nAHaF@J~J z6-(6s-at9O?m3S!bD?hQ6V<*GG~}SY%-sAgue4*tAOw*viz|}-tNdEXWi?`cNlP08 z(O&1?@kc19%{UA(i3V{8!Ey^tZ&BH_<+VQ@nH%-crfy9-aX{&sdMVQf%BDFClWO+r zJy?{hmW$U2D>;EZ9r?C@Uq&eZX6~|J{R=+(0B!alO7=ir)|W<}w_fUq+_%j8;e=HB zTE#VOlf?aUB+Thbq|B=E@MO#{6t;5vlpAWPSDLvb)wjU%QT?KJhAYi3#<6SJ`?tin z1u>P?Q(f^Pcb3(=QS#d|8H!F|$|VYkj};7TufX~iHVLB*B^Yc44|nw=8Em}$!z%TU5Qsjm*vNoOsKVJsuzl~yr=EL9xk z97hf?m&BH&gTCp-HdsmK^VbJBhq9%I^ImFou(C{8k>~5RYj(d$WPdX?>`69Y<^A?4 z_z~b9WvYZF(RPd^X(FkV-zFYt_6>IQ8{C|k-@dC4AlX#mL6wT{J-witpK}j`FJ_qw ze<{qU%GL?}!5|PXQ}rc2IQ+{K(LWU;SmDnF^?$0~hv&awVGm#x5&!tzX^^u7Ra-J3 zQPS5|VyGsA(HUEpm#NmQ31YJkymq(J=@YBdNJ@z*`E!ZB!s{#6_3n?tGdxvWe4bFZ3WL?7G%*qV@Hx~zOhK0CnFi>f8a3%xE^97VGtlPH%eH|i<*u2=ht z)^cmvo%bS%ufA4lHPxCby<#?rdLgPd0ei%CYUg9`b?wrr;dI0hOXBVr0mMjC6>WShrn%i8ln* zg|hVBYf?WLEF5o6mW2p^d2%OMSO=n>V?;G=lUDz=lF`g))gZgC4G(wmL$lQen}9mnr!? zlsJdmzr>%PTx6dTbh-R_-C{7sXV8r8IW+zn-873?OWEpcHxY|>iA}SvSK3#!?GPCe zH+uRs2jgcy>9EO_8^Ur2VR4?9)&t6Ji)=cKT2D2mDrtVQ(HwDF!)hM=CNhD=e$!+g z`_9@(`*eVW?>1A5e6itEq}~G$s+P-100y)G41@;pQ#)=C%K1&#+D5q*_i|t$~`cP5wL8c$3!Lk=8h= zw$zcfjJlLXO_}FR)0VN4*Q+F7i0eKaTZ79yqnKvm2A8C)7h7^oEn|hle3i)V;0=sL(?^o#?wy%HYwCX@{J^Nd+J4F{BW{@L%J!PxFoz;#LMN;5jK6b zzb|uTwI9h<{JhtzC~!?*HR;`4z`BIW`uU6eh6&?6tKgVB58ic%XB|bYJWIED-n%Xn z1m4Jh65GM?By?snUb*)u(|9|JeNjW#uO-Fdw@(|X-J1^89_+pAIGTrJ9T%n_OwG8` z_(k`;%43J9YNt_6*MK9mR<~Nayzg9!v6Ygg^Y=-iTKF;)$p^3P;CL^w+o~Y@d#Rft zLSvNPRa&-!(_mexFJ4*Ma8-Mho`3zC1oOMw`;R(0RBw3rCH-CWl3d!B9at%4Q@!iq zn)J7GOLk!F(~K+6>$eSkc-nQ;r8fTn7nc=%7rYqbO>4$EcwzKnz*)3g{hMWLp=+Gm zf+wehgGrmSwT99=JA!l{!>zv`vY$9sOx@eS)^0?HDxdI^6V8GVo**Yc>0>Iq@Id0G zRQ3;TCTB4Z=(H)hm4rE52y5k8Ve_ed zmaOBZ>=n7X7uIjkfp5(Yn*t^8L|zr4+1VisWz~YvN;>;nHQ%nHzfoFvh&$^*~{nM zL#^UrgU%aY4um!~Qa)~n7TB4Yrs_?n?oNm}I;=iMRfT+ct2JS>9LjE+^8VA^1?_CE zQl$bdlTA4s_YBDsRN%Vdtu9sTD@VJ z9{%OwrS70x4bf&y58&1!A_5&0!H6Yg}NezBMReZWjNKUhyP}Nf3S8m zm@{O>Fr}Lj_gbUwHm|N%gAZ=J75yq&ld7e8HmGUUDSWMaMV!)P#KBs2!h8H%Zj%A` zV2!AkN#VluPreuF%sHF=cr2lNTwPsZ{k~}Rwu@0~vDZ}2sMWG%N4xTbaCXsC2Hs)$ zNd^1)^)f+2?jf!4@xvz(sU^NbM>w8s;iI2gGo$6EZ`)5-%7hJ>*7!<2PPSG#@lr2> zGH1M*XGX%u+S-nkkmc6}BWxB<&iL&#CKX@&glhgk z%Qt#HY&q$x*AC`KTCVKc9Wh2$R!pSRoX)Ku6NMI^s1lpGbAT34lhQjC8r)1-4sSk) z9L}xo^eHsVPpio4t`t34?Cw;M)7z2YAeo+}CTy1m*BXsAKlv+TSi15V8kzHQv@XOV zTfSkaFm4eFXJ%Dr(I@`)WKJhx7^;<{AY4|+6p5O)`t%`qTOK`K?eO*6YloqkMu)F+ ztq!B#y1+JyPtsA1x}CeI(8pV}YppsWutn9mcJikK;jl@AKfkDK^W)l@7An6&rbf_ zA#-laW^>TX;fBM+uC~h5klXLeyLR1ncb(W{q&fBcDdX(Nsctf3|Dj&~Pi}4H`_rlo zQAgPgjgQlY)iS@2o>a#xo>uPiMed^2YXX9FkKAIbpS3U7>Ivy)<#(<4&wOpF-PJ0cU-_tkFx8zp5_n8NEP>Hg$ZVx{2%vFm(Ae`bhM9 zZcU(64gQg#xTh!Wl*!#YDK7e}6*RoQF!ZM6*Wl(w#)dk}>BSF__Ijqsnqt2755^C9 z8^UycNnH-^I@_o_q0=IE3;(d8@j~i?qJ?QB|7W(lx>pG?Q=wNXgB?kGC8ma3mBdSK zbygLV_DLvwY}ZmP3GDpJO^UL;og3-+WRLeGktpI>tNAu3-DBj^@so<7%U94k0}pSQ zedg%X=NBJf03{N%FFhu9rz6*8xZA!kkFA!O4sLEMe#rZJ`=)PA(TB;eScV_yWwq7taZB{)1__p@2krW%gmkU?jO%M zIuAbFbdDU1$h=dy>0s+x>-O}>ArJg1A}#vnDxowE*%pei?o(7z%pfV#8PWWr%=A+F zS)sxYLy&)mTgx0^MDAbps0c8)$IY$@QLzv!dbsgjdsL;qedWSA}Iy!)Kje6+gdwGUr@XUd<7);QYGy)z4c!uD71na|j}X zYRV+i$>*noysmG3tvz@nW~HAOqsbmayG*ba4@Nzn?Dpl~+GiP5XZmaI9-e%MUfU5v zPFAXf@jTiMm(SefA=x6ymxyoE^F?6D%-tIAjD0$x*_y63 z`NDSkA=oN^_eUv9z4byR)kA)ADBsWzgT>=2@482u%g0R9hXzTi z*{6psZ56v0hRbND^CAkP2NUbU*TxK3_vq;Cl_KbIGUjt#i&v&)EFUWE{DL)InK_!L z`ryTRpRBcv?KXMr5kvj_A>ZJQpQ#j0J^T#w)=HxA^5EWHd!4MsH%-7bO`7oJufp$X=XV-ip3ims zrkPMAu4H)EKbT8sk|Xa!@_WNdEv8Ra91O8jKi}z<$^9B-^h#B>sUp`aRPG)9!ph?? z@KW9&SFNaIw@eYclItKiY&*EOT?T!Hn~_(lcN&~PWo*VY2bu+|c~;{BZTAeHp6r)# z1hId3KI(j1wOV$@m-94F~*_=O9K6qb~snt1h z`fAh4*)=@EY9_jpea3@`fiJHgm~L{NrW&;5V;gQMZn7^7_qW`Udt*1d$?}P+zfl?6V2s~noHRzg zr=YwU$uY&7$eI-W#@*2qJ;h#~m+;Wc-NB4wnlX{}(Y@_wu1Y_rsi*Sd?xefjFnz=xj*{X|hoMaIPp3LD|4&#$l(56r9l>1du-(yHI|jkY+6_>S%?oBww3 z`i;Gk)~gLO3ky1)&u_wawL6;>{6h*CKvy%N%O{31R=hAKpHKw`ihW z{aw-8j@}15U((-><`oN{)35J2ET6Iz_E;bg6LdoeFIxAJ(OS)cySm{P^jO{S&{&PR zS6`YjA>L zBXdC_g@2^V^EQsitW9s`&@40a4%gaNlTO!KoW(}_cu}UZ_gBP7jAE%%*lk+a^k;EcF6k{Ee}wS1ee{ z7W#C69@Yw6-4-yc*Cdx|`6=Q?*mVgRDT-HsN90C1&wRiH|vTpQX*~1>Y$Cy>FBf!1}UrMWeJi zM);%scQKGJW(w)3A==w~nNKi{= zhndgSW<&c$az@&T$Y5xzDH5xb&+U4EF`AsOmsC76`ONxKa9Ps-+GEk{Jh1_JVJrQi zk_(Yq>aBi9QO?JkU;CX`^4LRbOhPRKoG%I1oGSU!bo=oJw=GkMDru`)0zmNDPjX5v4qAJva7sLQVW`@T}G zNS=w;EafaFb*q&c{$bfqX?vYzHGm!WVlWzIx{bAB<0n8G8Dox5><$crcz-b2#?Fe! zP)_t`R$krF$-MB_V!gflgY$%X=thmLKxmeI!t4tf)CIzCY1z7*sFcg{q23Z&GjK?jJ*JXQNeb|&>;cOKV(4kYuC|M z;M2pqCf8X53tF!mu|qSc+NiZ8SD>Z4XMCHy+m$&N6Cw@_B?412dpn0KS=u}eCH(JY z^hU;2N(nVtrOsMcvfO<*U?W4Wi+t4!Gp|HeNtdN+yJJhHM7Ya>iib7BpEti35~T{3 zNa;P5Uy``4ggQ|(ywX8l#pm)`E#o;i)j>*PjTOG!az&>i>dhXHxQ+O1vTd)8l6Z)s zN=<6~5i08Sa9o^o5r&$`kRg{TlM7~E@ps~+Flr8Rw?+Iz8s0#m>8ppL&3_x-iZ&yf z;FX~o`ovp38lIx>qK&Q28}jn#^*`cGP?=P<2%3_@-2?ylV?<_J*Bb$9Jf< zW4*Vi+SzxkdeRfVl-T_CmPDNP8y`k&o|>aR99+u}%^5Grx$MhZz{L#ue)^SUj*VrP z@m=$C*vk(h{U@Eeb6jo32(FfXUAjM%5HvRV&orZ&M|iz4ks) za6ZLV0;XCd?ZSuRB# zN<1l6)J}~nTBXfbjI&!BU7vKYWAeFoZJ(NSTCe;fXA@*?_cW6JlKi9vEpoMMypiZ{ zY84(w_1@6th2d({B33zX$L7_~mrg=z^L=v+JoMLB1{}3iC*HSgGI1@4{G@UctYm8y z8Q_<^boqXvy-P>U?>YOCGw0)`p9NDJ5~W=*>Q1I*>CoE8EuWwEZQsJ$qE&Ye?cGMxfe483>rB8P|{E(=8E8B+lZEQQF!TC4}*SA)y z%MBbt$`usZP~MDj12pl+-Ujr|KOft^`%m;(nNi4NY}rLSA9Rd*y@9)|r2z!ewz6X)i}PDml&vb8RnD zkUHFx803K(neM-jMz@rr@%ziDR@B(hZTUl@`%}A+o}Y3p!>9g%`ZpgbR+2hO zAgy_j`V>+}9Hb)%(h7mpUn5~`NoX??8bm^$g3M-z&84D92owp1B1X}tL+GS{uqj{E ztT$@folbP2lkDiT)+o|>`m7OsRyS-)gZ@i}PErb+J4Po;(us%Z#Qk)l0G-6GC9-OX z^w8NqwX>AaU$eEdgwS7OwWPt?+1}8Zj?iB%wWRvc*_v8nWi9b_EwN;6x-fJ$FLWj| zbS5QqDrt=rS34UKIu{iB%fFTcsU_a5oxN5&?G!p=TRUx4J8c#^XRtO4s+~O>I(w>? zs8CCksU=F(5=Clfg+ixxL#DPuNX#12YRC+=hO`heLkyYvSwk8Lnd=9341`Rzg^N7ug+G4kcva*3PR>`Lw=>#Oh2q4C4@}Jgv^A6Og*TX^{XNI)DS&G=C0Nd z9cqY|L#8cPi6%9qb0H+Hnpw4)S>>A9<2AEKYe-@tzYd1{+7m+LR}da^>yt|q1i&me-Q zVAZox)zcx>#DEo&Z}2bg6_Wc3$t8HkZe`lKns`2#XjDC|TRp8&J*`qbtyE1sR!x$u zCLNalA~yA9&lHAD_(CIKNQ8!Q!WSH&u9bj65gOha-3FoHGAQ_NEu2~#HWJzy>N9BJ zGbrjqnY%Sxd#eY2i|Bldsd#IA&70ru-GlUA1$z%_d#~V3iM{>bLoI+huiW=j-}rzxE}4-98jHRmr?CWJYvIWw~RDQK%(1fuy6TlfQ#nep*3r z@1?fYEq)&OXe0avwd5h0q)=1$qRM`0l;C<4muR;s_wLei9`|~GVx#skJxHYCXV|kr z@jb|_KZ8D5A5dgZqp0)le>82Qu8+8-OO3kqz)xO2#yXm){$TAeEkcSl;kmByY0I(r zbD*Yws)5ox;);9%_mg^X3pnVodl}2%mVHQelx-uc&|EmQUH%$(YObXkb;mV|c>D#+ z{ZL?Nl2Uy;(s?*#4lnOIT(dkGXF#J(P0Va8-%C22`_g-k68zh!=w$%42ESbOvp;&& zto*R&d-o{H@e09*9zi zMZufprXsr%v31MS$Tq%yU?^;?q2xnII92uc>L^;(drmVn_zwE+K1{&Olu*-KPO8c8B}(7; znIFNhqb&@|^oV#+{e#76-pfe8f*TsYrG9O%MTRJ}*#uCWmamU*T#O1ioN~n*99CQ7 zEB=5uh;MX{KB=(&H!493eT4{qTw8NT@&PkwtnsM+$q=~Rw|3O6lV!P{AC7~rt91x~ zTnUgT9`Bq`*9g+IOQye<{`LjRJ!xtSoW0en_2an=>UhbNR)qk{*C_Vk>KXVG(Ria) zhJMx+@41Ok9(3~@_E)gn6T^<)*{Rc$!lqA}+JE_Y+k$>fL&wa1>bKEnA;I|p<3tj_ zcb~6eyT}}*w%{(YWI@Y)=1y>;3#Ma6wI>bT$8|6e42Gs-J}BM#ar~bRj9>U?abgn= z8+O0H;)!<0Rq+EhryEmuRw*2e-G~f0@VwKjdc8ffu5e`9sjRS z^{dC|gL+oFKts$w;j-L{gRfpTK}1G9b-y>PqWAoBKXfsKuOg77P zpX{2^-;^^wi{1@=1Ze3{JyS!t?lS`?6@ApvK9u)B$VaFks|0c1%G0`PezL;ni^s-C z^p>q`v_bVi$hO@+pBCpvC(F@St4ioQ!0Cl4f8-kVg87Vnt3Q7idhK2l{pMCdXV@w^9;Qh+(p)aQ_%$1OC|8w;km-&Vbc_QNR!MshcOR*HA%ePHaj!ZjA>}#~y1&2h$ZU9p2Zof~222O!kM*hk3uKb*!3NhJ4exKKdtioesXC z9ymeV(U5Jj4?T?DQB8Y4J*#(|BXaCH@~cum=uekriLXiV$(2c^u`lvuM1N&++C&Cs zb-$sela%Y_%1wceZ@wSj6L`V=efxj9ljLg)5((VztVoo{m|dG!Xg;hl%Y*z=*c9eD z==1|vj(*NkEoXn^o^H#ewyjS;@W_2;#K36Jxm7<2_pE4MByz0^q7y(aYPh+eL!aLk z1$mCdzxUFb=x^`}eRe-gCD)vbq!iwR2%$B(Sz0*u;8(A}r+32qO7iB5ZZ}Sx>6nu| z^MiJFqraB@b~+d4aO%Ok$+(BhcXF|xdre`i{hvL(e#*t)WPvZ{YyAi$iRy)VYZ0yP zg|s>m14l(0?(HwGTa8@_KK3<4I=E!(*S%Il+1h&lMp6Bn`+rsK$@zKDq4B4qLhxHr zJy&AQxZ!xiPwfz0`~6<;w3hE@Yne`ohtys4b{d_ovn1w>7!KACuLRedcpt_KOfLU- zEvji{$m3L0e(H1}ShP-yczDpGD)N<`$@lVLBh`Sxr@`k=5re-Q?y2jFFVz~4cr|N0 zdSCvwu3<@bO%wUHbwqyQROrd3>GYaD-)w*5QO)452fYtYhMT zF(RZ1QnEk@WF6Mo+BcO@@4M1?BYyQBI6IdRI^TFRPU{2kF-q<1$DsP(_j*c$nwDN3 zZn>vXJNdZeFgGNbVb~cNWI%iw+$5b6lHWKP`nhrX!LW^2cIxE)^21+-tph5Pu*5sA!vp?>n zHyl%5mA=xtr8~NLU*G&!HPWWw?eN@vLqj>OT#s{ahx_gu>g@B9ar$t%z-R34^@$r& zdxkSTyx;uHzyI~*U#AQk?(13T{d)PA!)dA|ug7lR|03<>l)BICb=Q^qXz{;8DK^C0 zuY5=E9@Q`2>$G{HKzH>1!G;$CT85n~vj2rlcKkP9F}x;o`(M2mFL=5Agf}Gl^+@2- zATo304yj(2t@-?X+f9&}VcUrmaK6Dv=)k#Oj9?qg1rc!a7Cx}GUUn_m!>qnv`#U(m zaI#n{=HWfllwAD1SA)nH{GFHeQ%jmQCfS$q_mK5O@=98B@Xdv4)#el2lAj#uyRiC_ z*=j@dg%t1n#^KPw!RKYe_wLr;oC;nxND0yMPHVhS<@L%=tF!!`;fI@A54!F(oH+h+ zHu+wC`Aw$)>DHUC#)j_b*1s5h6ymRHUHsGjxt3({u*JP|$Z1VK!}=FLRi$r>i+oA* z?~%IqHDx;YwzSBLS)PA=(#=B<0S{1X|KL6PK-$;A;6HjLEklOdH4in8PuBc5?vd;> z7&xJKvq5vY`h@rM*?j-{JH<{nq`8G-(4)6o^j_BF7*?G~DV+22*LC;rarQTKE7rPx zkNIrc&|lZ_W{sOi!S&6RtFeC9U#Sd)rU^G#3CX@%nXJ4$e(lxl+0Nh3&Sw|=oVnX* zaPzQ}s>ZcVN5`(s_qQo-`TqTPJnD$g>U>>=8&ri}JgtsB-73+4&q~-(X*$@}u;;2_ zwT(@|lUeYy^L|f$y4^L9ycu%IW6zUWQ>nXh!gV4-$5V%-m8(p?2aD9nJ<{|zQGf7z z=#+x2;4%YOPC*_!jF*Id4o;X)U`dP9Sk6;eWQ!BYpn{Jr61DxH8Fd*Ro# z_+rR7_BgUX*{^PH?~Ble*yHtMs#ACT^a-*d1~%5YWA=WAV^b^V3@MKD^%}&tRmp0e zP5V6sMrx|_YJy#A9w~YWnb+4@)D7SzH3s)+3^LURDeC<3&nxED!towQ|9u?Tc{jj$ zHLzK#zOL)uc}<;Wtv+~8op?%}Df#);{_D%sYsPp*3?WQY9n>CyI)rZu#t`Sb;EK8QP-{Z8n{$HR>c8~5t3 zwpQJ>{yXFm7$;P}QoK4*-u}bxwxQAM9Tsl=!~QU|R%1o#P`cx~rD>BJwn;3BqL85b(+vk#cn zLduZ4Dd_{|c$CSDuw9M4`R8cBhPD*hJN3x78-0cU36l|TeYRP{K5?)!522omuuMpn zrkKhRr92+hRho1j4m(rK={#`Z$j>|&P)_BXNktR@&lW;^BL8DcSe}Ez&KNOhY{A9; zC%rWKP3dpN(6#-H-QO5$&!9CdQzq%at0M{l|GNBNCt^#K!;Td7rmx(P9&kytib=ly zc^CU)>9ru%^CZbRarm|W>qppvAi;N%VHSR{kK&Ao#{bro!R+-qR|zuxR9+=5cp?<` z+k>oRA^hdp-`!)a=F!I)aWuhq-(%bTVIP}UK$zH-*xze^P*GE^alI$#BtkC)T(aj5 z!z&?HVV>;tjFP;8)=)fAk4o5djAFQH3H06DXb+tu8+TU9TJG64x_>03$vk>L19sM^ zd$o_{LVFth)=6)7r>9^!r=QHORJDSU+t%eo+_)G?yGIF`BaTay#2w!w6DM{!h8Fm1 z3_I5XDB3i!G$^;=l?B7MkYjw<^R$%)IklDlY*XzPy?G>bEvy2W9Jy%am2DOS^k1DVEH ze8;1_9_Jwj$BbU1gVEk52!}&H(&OozI=P`JC$RK*5$D+*<#ak1c5`SPOORgPi4TF> zTyfs_i!`tu71W#KiXgja@S@QoM zTQK-Fl*bCTxo^xc3SEl5pF%Ks#Bnx9P84h%f1YM@gye0w_}h+2)VugLBVcAAK2k(6 zK%XJm%i&agne7wr=#WQKx0{Z=re;)Le!<34a#YGeN@(UD#qr`rW`sU&QYMEbH-q0zYSI6v z$9P(3jc1?^j~sAP0ZX(5kL(bhr+w((yvj+i)H>{>Hupgf9c4e3Gg^i1VW*XD1{-Og z(occ9r-}`IKQMe6Oa+Hh9~S6ctj{olpIK~RnoWUF5@EaIXy#+9W3Q*N4xUS~bNObc z^lh7tM^59968#^8)!LiX(bkZh3Zsm$+JRM`-yNI#+6<7=a%`>Mxl{UiobkNJrLo}k zJ2ty1x5@QMQSJVNQLK8eGfP5J&d!g|M5cNDbatPPwSzmu0O6%pt+|fx3biJ zygI@V?oWh_jr|c<1&eL`RTMN34jBa)TTc-JneTG22+JYlg17D4t_vP<8e ziE_BdM|^cKH9yT&Nu{$ti2ZnVka5=XcE@5rd5QSW`Wm^dGThQ4eRVR2v&p?v3NO{w zI{Z@7MYEG{TzSK^;Y9h5WG;iE_hl+yKu|r-;5N>Pw#jD^?dsCAm4_UU$@pgb3)4P9uh;$f6`>>*_1T7UuCh_c*iG(0SK1o2Ir?e~7|&*+uq*1EL>ZkhglO>UbwiC(?u!KmFb>(dQe zPxOjY3La~F2iFfbCxR5dT`6m^M33k7^i^6v*oMS!s8sa34Rj!|Me%g4!7^dx0nPUTJ@!L;6E(tJE@AtLgM%VR48mxfGsbb^h!b z=2CFZcpmZBhaN4ghQZ*{Kgz`F1J?`=_5hobCjH0t#+bJ^M1mOfQ>|-vEnTa%;e?0+L^IRwEiUTY$+{UB&w1rgX-pUxK)2#?f<&#uHn|E z%HJ;~zTL~Fw0=D2|IR{c0bacuFE?YyJLV5A+RG!TMfo}~^$V3i*#G?w3^R2LQNts^ zFXHOsk&^25IY|yiy`yn2U{1z`8G!L>5guW>!#^IXFskgfZ69E|6}o&H0c=#$9l-by zP~QRLw3N%ioE5g*hG_@vpf>U%$~36E>bvjEfjT^8Hq0SQXP02`s*UtM2J4-AB6ll) zTvWYcqLgU06nC&)u@HS6$3zrbwx36z6Z3>2kCet`2E19{&p3tXGmhUFbGh1l!Q3TK z)YfIwQa&{sTjc(I;dlR#=~Yev)GK7NK&ixL0YrYku{^)ENj}4K!r1J{<2mJS=Y@+h zj5MD0j1{P(FD>XXa#e1)e6UnVMP!h!KcUkqFJ5iF$g@8>S>SN^?K+6@CpXGC{)d{a zXR|$zg1h13(Jql1gr&C@u@;}x--efQsKYm0khikB5m+3-?>x-+%0HVN|D7aA8td+N z)|tnPm~X-~yKKR$8OrTo*xL1NSE)#GB~K(BJ@EOA{4>J1Uix^Rr>D(=IHQXNOH^t( zCEOvt+X`3;w8m9q$3(En8jj`pHvBQC>+DQkg_WnVec~cU9^X95xgmv=Ktw3BDZdbJ z!%I2j)@CJ#(9G_GWTn|&HtT-nnbOnkH0?FqQl9OC=X3`s!qTQAtNSb&wzdopjtY}< zmL!oXxjf=7rt(HzDWmdG6a3i)xt{U5# zvlQ2Ge&^nXmvgW-i5*&`yo;JF`ZaI2QaGl;L^uLV1urCOVnFefo36{GA z-1b4<@%6)OKO24FgOLh*zXHP)%W*lq$-+>bdGTN-Po?Bin0dkokNEEx zoAR;aO?bgAC6!)NK6EGL%%ZZzmIz?v%-)9A-`cflQ4(v&z6d58iBaIZ#Vb-95-9T= zE~D7%>US5+woW@Kh4$8{FJq|VN?>*U4&OAulamj9at9!H5}UZ20Zsh@6rH`KQu8w7 zS_k+q3=M>7nKISG{2Tt>QWj6BHG}--?TRzOC%{!!nj_$pl&TbRyUnm_LrZYY7%kz!4E7wBe?ycAYspCuNrVJhAiG%9LAR{=t<$C72InVo2!tz9S;x{zA~pKOqZ;X9OOe~V(V zwNb4xt+Htq84zIxTg2V+K#$_53MH&53G@uABbbm`VYfgJvMIx52up=&m3yGjDMevAn3%>WEH5>#B z36O;=w@3SFHi*CTWZTZ`FcxKZz?9VxU*nSmNDL<-*I}?b{26r5Eth_}L3^`?Aa0TQ zaKx{So?6nB+ZjPlW+JwdZ1V`+;g2|4y1XRYKmESOcINb^8&ob5<(#(QxivFC_`g4~ z*LuS3ks{xh*b`c|sS6GAgxGL%^GrV6=5NbJ61!;k@q#8JVcpcfqq6isPZ&1n3~wi1 zg5!gPkRr@A6VD%_E;65=VJ8gWe2qaBYFGx_39_8osZ>|?_52d6^w8z`N2N+ToeZ5g zn5_1Z-G6GxbW6qD&I)WCU!I1w=DpM5sSswlcgmog!?ax|^IbSHef_acUy^iKDqDl{ z`me2Tvm*vKc0*0^m-22pbn!;Dq!?`S@j_N`x}UsQ*qu_I2AvHBE_RHF_PB4!Q`|%M zKaqYIgk>vHp)aDf4-qnzOu86f-Z<{vIc4$ZG_J=vCm^Grob)$fmDH@O1l1E%CM$_j zjT4U&P0~1%3)Op$e?1>1-Vt}2+0@f5?vU91U}uNX^F|`$l*K(sob^IjkGKnFJs6pu z9roBt9AsI7qTVPua9SJ@ck{EPSjBSgg_Dfet!`ydV2j=%J1n8vK8EZ|Pt#e3NxJ}N zHm=(@e$QCcERqx(xy=P~(!rmz7S2r+Unie)#u_tp1ew}0jIrk0XN>j0^aG2k zJ7kwn&gMgzm*!Q;F6B89Ky`i+->nn7Zic2;DWxskBhU6NN0NP)5We4m)2&;i)D*Lx zY(2K7UnSs zSz%z3quiI7{y?@OH52!Y3YC2-*P^@sJC6o_xaBalgFdnws|gu-;U)njy6G32+_&S`kl5p;yU0bi-QaWk!(~+P5XnIANwMQLtJD5ThxTYaKGo88&d|eWpejXr30+brIa(Iwu=B9@~26`2%e;j&iYC=zNDU*ub>R8kgv3(`T5b>v!LX*i7AFp7P{+6$>)mu)wW0&y(jBPPX?h-L1KN~N>NsXv-x%NqiO2c-5e|fI;JDYK9W~+ zgo^DEd)pJP#8Ch4Z~jk0qPc?e?lbVHeBV~z9&CVe5hGlXYAI&VhZ+Bm?)0<;WwN*8 zGPHR;N%r$VEc`TZ)evnv?@PA(*{smC0OcQG@O~OAM&91>I0b%ZinAWK^8Khil6|Ys zy7HmKM`i9;X`Ho{xw8|w%6r3@C5e=2%n*YNGQI@el2ue`*Gi=<7~|gt4$@#blm(%o zR#PnEMIR$vrVrsWEqYd7Y=keHhI^;2Ttqmh2HE>pVz*ThXDx_Vqe*tmy`U@*nZEad zNlp|pJ?7}i(R|LLF*3bz>(pollp!rI*5+Dqe9#z2d%{@1{QiKxvc*R&Tu-X^snKW9 z##ni=-n7TBizjx0lG#;iiRA9b^Em5@9^d;`@@_2(7T}|4&#{P*5rz&mUe-%uw`~v3 zy6W+PhUXM7TV(pn*6#IYOu0TX{j#xGuyvxfJZ_=QyJvkbgZ(A~25PSSOdjhRoEq1x`v9db#ptZ4L zDE-*OS}g7G5>%E55}bV(Dz*f@kx8pw(?g_3m>(!r+RTqI&LR4C2KYkl`*wAZ>8HlK zN3Z>zJAh2rhVt7MVYcDs2jmIyk`SXT%0f`7%jT0+ljkD|*Om_aQ)v&vy7f0gsTO_p@pItC3)~9Ii+D78R)qzGsN;ky=3oEb+n( zaXoFe-8yNUJyFJr_OZF0Q5zVb^dAoQRgXTm4E^nKLXeWtkyK6J%aH z2$W1Zi*c+x;F!O4;~8Zk6jPpwB?V%ceR-}$suE!hxiH4R1DF%k%l;C46$!&#*Fm=n(qrIOnzNEG{jbR`FrBk zcA2R(S{EUc6eWf_W$JsY%?fh~w%ikBb6cA+S7NM)r;GNOllg@)Sm)BBc00_S%gfX` zv7SV-n8zXwc8E|Sl0lg5W~`5CNkFrq1t1eei*H7PBAI9elCSDuak%FsInI#G>gD{B zxZ#LldRB}5EK2h|$oNqRO?on;CFrnZ{_ZRaa{T*p_OGn&Il0BB&DNH^US8p-#O)jkv zi{Kq21n2+J_(R#qoQX5(-vS#Kb*H;f>8b7(ulFE2syDignCxD4m%t}Wo&&u08%u9v zA4Sd02zPWC08!Q1nk|evXztNS)dpSxh}Xi_y!fFrrr=SP7HM~J{P zu(e8{>WXJuuQKr^o(p$mfrbkQcLXP!+g2hb~-n&Wh!J~6+9 z0p@33?5#YR*8my!P38igLKYwz+zNM#`&vLHhc(vupLtdQ1uiv1TizEI)Y6&!&xvt% z3&7hxw*R|XEHQ&ur~4F)c)Koua_5y#18clgQq~dEtU*e*i{Zqg`j4sUQjpR{lKM3@1uC2UKQ8Z&gaH_wwKhPK@bDG}eHLRE1>Cd515A#~1JJ*nK?=b2j@g`%gw}4g zrF;DATbr&q0Fw#XnGpb(r}n?b6GwaRQZbj0TI^{tM`c5tV}TpI-P2|Oug@;Jp{`p5 zTUMZ7bW>NT09C#KIU-66068-fK+$D|!juN$7nQSkm`~!(ETC!}oeHqb5Q3Bi8-<63o5aB4Z>Wy*ns30Fj^Vf?opo@3-%NLI2T~3A;i_ z9yJDsusqOQG-OnvwgFFGg&b(kgFZ1Mm+{s6cl&zySU*NeWJS*hYeB^m@PDnhM$tE< zLFYX?Q?LPsOMLZ&ZDD8zwCghi{|!3VD){*b>gN-7t`S5N@Vn=q!XOM1PRRTsujo>F zMFmOul^ml!6Jzn~n$v}t2ZnBmrh{(;1I0(G)|Ga1(qCddS9~krI6=Wc2~YucHI}F@ zkar}k5KH?sp0syD)dGEt`8@34N9)7~=jJR6%r9N=fhA&eTIl5B8v=O}mSZ_|_CrNM z!112LlDHVwv*c|os!t@qXLG&~djCRVxX&gC@*DI@nISR^^@()}6Ufbo>q{u2)x{vN z)_&wTeQM0j%=dyX#VtFYvA6D)iUZDf+aGRu!7Lbk532-!#NIWB79}rZgV6IaGwD?F zYazzLyssn-^PHg95!6H}A;K<2sNv+!-KgG?c83c=WIw{XsdhkwK%OLB&vI@WrHA>H zY=~8>Sz^titAxz05}A&3xX8%%)J& zdVm$@efrfYMu(d*in=7Rewu;uj!N{1x4j_8*giF#&JqC!m@<5+Qytf0Q#{lxdiu%xAH0<(85o94Mm zzzOxUnY%m2)Cc1#g7M;c4|>d54gxL`BdB#c;^=4r#{t-#O~q?mcquX1v=AG_XilEf zbMX$}sqKRQvF4#YhVp!CS%s#PY0T|{V!?9N9VlcI^sh=8@WQR$8gxWw^D2l^W64EU z41#X|$5_`;RzrDW56E8O5l9@^;JXfruQ)?D#2BS?Q+56rSxcnP4AypxTAPxI3hiN- zTs$Cq(H#AhP?RnrYmeco;A!K=>GC!heDs{yWZ>iE1*}oy0>&a`%j^+n?oTN}EL1}0 zDQAgfg3>6J(8=OhD>Tol&oh7okQDb#+b|!E`J3cp=qNCXcePWNTy*bC*fza`ykJ5u z42S?%bpCJo#9U*ppC&a#i_qIK3vcx=m0CAvxKWK!T)K=77%4Nrs=)5NJi+=RL}j&i z3#!_;B|V}rhkPH>wlv$BUZn+u8dP782zI{#g+G_zA^bv#wxor@hbn(P(X@*fD z-%AijBV@Snika~Oe^-M|oMV8x24@b&}jli@%2v1!xH!LTHxPk;Kj&x|1Gtm?|fr|cScaCCdNyt-XF0?l+gWX!p z`7~xOHj>KB*TSB|!C)N;;pVgU7=?W=hG<+}3rjVy?0(T=0)oOyRA#BG^Z}W(rpk%$ zEcAhqZ+NA%NY5pYVU98VyBbR_rhLvBF)meG$)}$0p|IR;5fU#aI;qpgTerU^qx`{( zSwMd@!MjFSdhh^+6&#!%=AT$j#k9*ytd|Y7o+~A!v`enHH6vT3lmOF3AWp*x4f4)ldXF*5iT43kO7OlahImTJ_z^k+*S-zp z0kkY7><7yLnTSN3wzh4P&ddi)?Wn)~&kz>`Q7C#h46kfLGLxk)vR3Pbc;w&vs4<{hE()q}AsKr;R6?#q_@!k6rIdh* zkpv)}_WHyQ!iX@CnfikTJ&rF&y@~@|mN`O2K}U73H?y z6j&9kLewW;!;X)f<=*288*8CDEa)X6nT*&p&Z6Q<5cE}ha=qKg{wOfrx@;?#^Cyv-HvX^I-m>@P6(E6=0StRn-+%P3Z zY@#3=TVT3jLA=!r=3GM#;>e|#ov??=9T_8cgT%-g?r` zT%sXf4I~N5le}I`D6~JoN#|q{IOi|V_K7r~#FZguLbE>{_N=FAU7V%n&wF9x8 zBc>LuCk1OINLi950g7`MW}u;kTLckF_hpvKEhWA!k4q~hknX?*+Jct@#X`}6kb?&# z=sJ)2r-~xLa@LrkYl-~x7Dw_^IM4O*v`UBs0OQO#B1hz*Ka9x*8@R?8*GenTe+{{osRYf1;Rt&dPwu35D|K27J0;q@V4KKbVFV|vQrYlo z)9zUTSVpDB7T3-b$YS2{_7pSh%M<1ign>5D&YQ-)i>Kz$kvRo~qq^lx$-HZuBLT0< zWlqd7qVP21iJyH_KWYwSMygRE+|gDVd6%o8Wz0={H5BPP`6aLT!h7%P9cV*5eL=Q_;Jwmg+oA?cdR zc?7Jln)CPIvJ)~>_O;MFNL-8P*5>{HIG$B%{8uoNdc@@d7aqrxz z(PBv&Tv}#nN>NR*q@GI!FuvhFYaep`T^kg z$(PdmG02{X`iD6^FH2=q3`OpriTNN+k1F|Lb>S45gq+8;|4U2m!x||rV!(jyQ^i&e zFJdfmR;QmqyNZlayFL9j=g8ckjh&H&7ngu^m`DPMxecAGHXPw`kG5cTT0W|2sXzu` zvk?u+SL>8?UHlV;<=@#zB8(7^3JANmE6p|XQleyw2}@TK`@}(BC&v0|rU^pkYSiP# zs(>bEG1I?dqlOmPi}Ia`$834`Zczp?aB1d07^JaUO_t7)lY*#L|y>9QD$dCE$v=}t@X)8cUygj1~H*|Z?@|&<#Pv}!A3o?38|bx6%ITMw>5N~%pP(A29i~n zz<34-VG7hKY5btr8N(CA(+Z3~VC;Fasvm}E;NyFTPR#vH*fdH)(lUy%RiMl`GSmCe z&P~10%1E$LS2oNEZ@n1>mg(89&$LW#Il=sP5NQ^bQ91w8bD0%I7lHcx{c#mf+kEjZ zOnfBo>t9UKQMI2y#;;q0tFgEa!R3BV$NzftT5T`pEVUv`1>lB6L7W9+WZ!9^c<*Df zkXuEBWG>ORO5EGysLEfd;HBXm+Eg^;20-kp4#U+i*IJSwwwRMp36($LInnPv}_ApciqUt+-2~VAgp_o%y{WXFXg{#GR6}#2FG@j#M?{=V* zmc9Lps=!wdM@lhp{=4L1tXix?_{KJnA+1T=GM5%wOi;PXLm#PV&;@#Ih1;8`P4(+B zK~;2ZZe2uHZZ*#;b~8f@R?od;#v8^C6h*eP&r(_S#xSCDVt0Khfs2s*lER_+10=yY z4<__s=Pjea>0Tn7mz+7(nNZJg`7N8jf5Y)KqVCOh6$_V^o!lur$&Q~x#b~EccGw%n z15vYop>s-$&Eb$Y1%$9S<@9F+#AD{RK&j)}$#%{jFl2WM(wXOm@`?mgv0b6)Qb_Is zW=9G|RWpIaKVrrkWsND4L0~E-G$o?7h+}JCO0aseUCjCHQCit*c5q6K^;v;Q4d3Xf zFm4Da&q((+}(8h1(VxU}h40tnpgHJb>ciGJ+6o3FLLnZIM zb;6<<4zNzrbqI7M&(J=4Bi?A=Rt0uYp2GMhCAy7}2!k2}k5Zud9hsnSeav;w^*h=U zyB|bHdIILjzx5bw6vLD(zi+`3+i}IUo!T9i0EPXtv6k5Dt z4G>3~f1{bkp@*&W4ZG~%qGZpx+Z}U*E(bGI%1w)4%JP-u3>i=8L3w?^48m;y#TQpo zegr*Q4I-|plpZ=QZuyR3kyI4RTx@9@$ATVA1oxtP+!g2y~86Scr% zEvyL&i+9YN1~@BZd_ej%oaBY4!DX+b#UY;?yv?)hl*tsaNH8grnbnP@71~8^n5yBu zv&2cyyD6+wOG3bAlfSNbn!GF#-A_APw73`}Hk3-tjJttbmG0Z}y-GHqMu983dN1pe zQwZxUYHx2?M1LV2rPQ}&bCCQNC>70{{u3py?kr$xvrTV3<>V(}NYy@O0`Kpd~ zf{j%TL%1Gua9s1{3&+SR=+maK^MW!WaYriPk8w1yEa5W_7!N$qdl^4o(W&+gS=zcw zGrT36v+XyKU>^Q8)`&ru0xMFeipNHTWsI*Bs)4r#FR7tGzVaUV?1UWRD!A0l{q)WS zTRbVy7*Tb}d?aGIAVTk$YB_}oRRbnaCrvM!6Oh0wN?6uqfAVD{lW(H~`Fy1U^bT4Qo-qp26W!TrgINAfv|+pF5N24hZa)?xa^ICP#`s- z3lNH$z$13rH-vBv@oLG=bzsZ#!mQ&}1x{eEUr*Rag> zKh0~k$}u+{ptFrcKHBjX9@zmdv9tH0*0Hd-D6rC*lk-=}S{+ozH%%m=aVbJ{-5kS< z7KmAl2wlL4o#OaI?#0ux&IvV~fVYcUy4=s)nsV!7QhD;4d-n4^uyIDx z7}TMdRs+VkFv!QYlY%{-*azc-{=$xv_t+k&oR#yG02Ybl?02M5pjTQ9jIrgj#DmB< zActkd?WeFLQC5AMe5IltnZICsjCO(7d4CD+ApH9bZulx-*CQerrx{9Kr%hnzg=HuY zuo~`HA~)h?kp_R&eAzG{xGfGTumo7B^aa5^ z(h>fQ8Nau75J0S!lta;Groz8%c|$gM8vbJye<|@G*9*Lx;2?A;p8+dn#>asL_PlqF zC37^>Xv0>K=4D-!7#H)MbJ%No#wa40m#D)qYF&=r*gk>;S!c+2cL6~KzAD|m4AM_w zebW|9>xT{QFD3NqIHyTkjsf`G-$6keaiz%@^tcoFH}n?3?87m83>d?%qCwRVIYiT>X$9I)4yZ%mDm+Z?<^4rq-4?{eQK+hJ*w^BCf{oJT1knMPCBIDiSCXtkl`d z8N_;5J4J7NJJH0{z^WNJFOvFAGyT3zFtbYutKl{JxzIz-(7RwnHVyd)o4rPjb?DsP zbtfML;KYuURg)AbIJxP*SCchz4bmr|=RMfeeI@)(<6778Mncki7S-MT-&<+W?LUN+41( z`05fgLdYaAErSgq4H+TJ@Amiq%$+;;o^$4VzUO}DsNo&oVFEc@c=Ym&#&BcQ(#5et zEXBW^H}|5;Lu#G`=*wmx8v#L_&|`@vIKaLJ4ddw$RvTuK1yKHONF78gZ;|xu^qB!D zT6K>VI%(1u$goLzx}H;6Ty!4LJ_RskXH-tC4D0O{F)!fH$%T|sX*p=(xChvYG@pBX z4@3D+O1j5mJT+)hw^m8>p3=I7lXvgB2K8olux?6>E?J_UYSuDDywQ}%m5L6Sq(e~@ z`Fr09ALKu~-cx_?-h5;|y4NqPvPjk4b!>W=In^$6qNfag%#dN9$q0v^GJw`xW3W45 zf5)G)O&{(1wbhwhdUu^@t|bcuzuTmVXap-+9|;{-JK1On>ADQyALP8{_pal=+5s~v za>jSoY3~+AK;|9OA3RrAkGja1ahhCC%&%9aSjjf~JANYFO%NAo*Edb&KNB=LcIk+)x*!q`g}DcCEtdh8m=|?7Xt0 zv{UeA_*h??Bz+CQH!rGfclhym|3Ce(pQ)D@;6{Df;5M5U4$*t$!*+a|OY z?CLv=^z$b%>wK~e{~073`jjL{L(1lzk*im6lbUR!U<<@eFNd(4z$N%)dL#I=Jv4T* zmi6KD#Q3==*nMii1=;P10;dY(N|}2ZXB)U61P?4OT*vi3g>&UU3YXyfrZvLwR=A@U zdqJCokG`!gikw%M&MowF+nOmoT2AO1iRsH@DVDY9P+GJ0@%#51(M}W_B{a2f7vh?n2&f0u zL7QrJ>7luWp8wi1eJ#{RFeq6OFmaD7-1FB?<{hw!)i4CfV1R}{R_0&9=T8A7yn8gtVBMhh41M^M#^#J&Ke!Zn|wti>9i6?&&ip+_sU zMk3-WP@{_DflIsBp~2->jPH)Gm=(Ob={&rcOvt~AcMO@LV7rcIfX`xlqX=H5o{rGD z=FExii)hYxJ$~R9W|v)a%c|e2NBx37_Po72DxPzEm*hIf?2;ZdX0St({s>iHVR=i) zT$TCMh&m^eL%iJ#jP4~pq(CBdQKP4vx_@Akc!CpfgIw3$;UOvKBDyj|e3XaI&IA8A zvi}%4z^(F>U5qQS#8sBePKg{I>F?ib?@zGik+h)+?`n!ZL#kZCst7y?7r!tKa81$j zykkjiZsd^1BmK0&?qBwrh8?Iv)vf9tj`etpexZ?IOI;^YF~CmO3kVmhaUa3#;+sSj zUcN8vN?|8L`E)NDR31){o3IwFwsGp)xS^IAZI$ zT>1U%7aXS-UyTc%2$1fVY}`;vhnZb0*5KzI`-&d6E*{xQSe??7$u%7>OWv7;kh$4A zgf*;Fk`}TCAWwbYl*Aa6GKjslJqn<2RA^vI>dpkD7@MP;M}2MXe(#cp!ZMC}Z!Ypb z0R)Sj7bgp#)?82^k{A-a5OJwmw{R1(<*gN!ZIz2G`BFL$pIjHGzHXr|Y$H@y$4F~6?D6=^txw;qYvgc%PM%$4~LLMe!H z!-vB@QYlqJ9D5E$YrH@;P5k*KLFLPR1?ti}TdafTKIqYspZ?g0D020Be(o(*G)Fkx zFs(88+}ityT{(7HET$HVS>qC849JTFot2BrW8PnrV$W|iRB$|S|A8Tlk2%w?XNeHPyz%(;^)rn* zY~|}qQmjn7^wa%OJ8BhoCI7J5owX)dg`Vo)#PJfNtshgi*2?9M`Nu!2p}*alO+1}v zyNon`i)a<0HAefIwd29H+R~?yw)@;@vz}J!lgx(>HJ6Qx?j!wa6Ab19SUCVfPUy}t z`Zb)j)xyK(6%IAN;~CT+8{~e~OXzhtvXyB`>J?JyC=0Fyy2W|DezvDucHQ3)ds^uCcYAmzLuMnx zBwC04>zN7quStTO|4_-kmVAQ6T$NO8563ZHghshmOC4bUV*0^NViG|rZRAw`_&~9e zYbRc(HU2HeHN77D_O?Xn`B*M)Z)TmAXn6xr>#yX#vq)EbA!GA1Mq-@lnF_p@a3QX5 z8PZOPFPMwydISN zYgdgFvkkC^6B(xcZ#p-Q*3+IArgi7*hAuXTxGYj87Sz++#98g|f=&4r5n(e0Nzd#z!6j5lcn@(Kfjtr||i$2%p z0*6fLH!8mG0@XE?sL?G5i3J^TCL}_JIqH~O*cS|3d8266>~`HWt$-3b{TEbO9Sgyf zc@``CP~)4q?k*f=O-cl^r+bJ}F);9zLh;nsP5rzC?Aa$l?*woT7<5#hK(U=*|zdZ~+ zA{vUKbvbGf+;7EXs0iUA?THvUPt|#E*Pzv9{`B^kPo2H87l~Q?Q_Z27s-$owUTwVj z{k8MwM%W?YgFBwL98#Yk=pw-9zd`#tWTj&ZN4TRIpf55hAQM3KxYF{~hcLit`H)82-WKKsF?PeM)yy?a{g%$zyId4By?t)F z+pf*xGA@H}QLkTysvNn&L{Zi2a>*0d`$TJ8$y_hJGi>xr)5HoHcF8aEq=&ANh`=3- zxk08l*yuFx<=)}#_>hC%ktmCt?pPbVOE>#RLapUzgJv#8q_X)flh#o8`S>wF&>XcM z4l?bB51(XGuYIfQsmBfXP2+PzKFEm}ohtreZQ2TFN47BV35L~T8LG89$L+d>-W=!WT2OMhplegaBQJD%n;2b76e_!UFF@C(t(7-yAFRVOQNKv@`%e{?3I{ zl_^P&8j{D*QiHr37rMYyR?*ftlGx;m3u^rZs5AdEeqRV!^gf0)d3wlGhHZS5p}GRg zK(%R0Q+nHER8}-v+&_|`TBcjYzh~{$JnIY{-_rC^SU^}5=tJ4(lv$?64E|IV9)`E# zqF{#jUx@=x!V!`%pSNBBI&Mg;$@o-!0nnQqOKZ+Kv3P7PB_nWA5HjxL=rKwEGhC=R z-Y{BM6>l-KGf=H$I;48F} zO@=P;TefX>b4+0?4|6K6zs^J^(gCYj#cw%qo#>o$(}k8}HE;tv^K0?;gtu)yqMV>( zBvEOkG>3P+V3w#$3Zz$<4VOmmJdePQkK@7GezF*_$D}ElPq%&tf#MtH%cTD7RqW@e zJJ>!tQoK|hd=2*^Ko!Sb4V&uli$3v`#@cgqWQ#JBKh+?VesfU@@hh&UXD|bn3wkc` zTW+@2R_#HC{P3Psn;L~bqTZ3spW-PqeVg%)Fy?p@J but saw " + or + "Expected but saw " + + 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. + A set of PTF's which correct the problem are available from: + http://service.software.ibm.com/support/rs6000 + The PTF's are: U462005, U462006, U462007, and U462023 through + U462030. The PTF's have been tested and do indeed fix the problem. + diff --git a/APACHE_1_3_12/src/CHANGES b/APACHE_1_3_12/src/CHANGES new file mode 100644 index 0000000000..b4863aa728 --- /dev/null +++ b/APACHE_1_3_12/src/CHANGES @@ -0,0 +1,7269 @@ +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 , + 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 ] + + *) Avoid infinite looping in APACI's configure script + inside Ultrix' /bin/sh5 upgrade step. + [Jan Gallo , Ralf S. Engelschall] PR#4940 + + *) PORT: Add support for Amdahl UTS 4.3 and later. + [Dave Dykstra ] 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 , 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 , 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] + + *) Properly escape various messages output to the client from a number + of modules and places in the core code. [Marc Slemko] + + *) 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] + + *) 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 ] 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 ] + + *) Add back support for UseCanonicalName in containers + [Manoj Kasichainula] + + *) 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 ] PR#5397 + + *) Added SuSE and BSDI layouts to config.layout for convinience reasons. + [Sebastian Helms , Timur Bakeyev + ] 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 ] + + *) Improve OS390 port to work on older system releases + [Paul Gilmartin ] + + *) Enhance mod_mime with an AddCharset directive to properly handle + that negotiation dimension. + [Youichirou Koga ] + + *) OS: Added first cut at support for IBM's OS/390. + [Ovies Brabson ] + + *) 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 , 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 ] + + *) 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 + , Paul Gilmartin ] + + *) 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 ] 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 , solved by Martin + Kraemer, warnings fixed by Ovies Brabson ] + + *) 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 ] PR#4973 + + *) Fixed NEXT/OpenStep building by adding an fallback typedef for + rlim_t to ap_config.h. + [Mark Miller ] 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 ] PR#4974 + + *) Added support for Berkeley-DB/3.x to mod_auth_db. + [Steve Atkins , 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 ] PR#5292 + + *) Removed the variable name "template" from a prototype for SunOS4 + in ap_config.h to make C++ compiler happy, too. + [SAKAI Kiyotaka ] PR#5363 + + *) Added missing links to htdocs/manual/mod/directives.html + for AllowCONNECT and ProxyDomain. [Patrik Grip-Jansson + , Ralf S. Engelschall] PR#5319 + + *) Fixed typo in htdocs/manual/install.html. + [Chris Pepper ] 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 , 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 ] 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 , Ralf S. Engelschall] PR#5291 + + *) Made `tr' usage in top-level configure script more portable + by always using square brackets consistently. + [Masashi Kizaki ] 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 ] 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 ] + + *) Fixed QUERY_STRING handling for `RewriteRule ... [P]' + in per-directory context. + [Martin Zeh ] 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 ] 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 ] PR#3140 + + *) Overhauled ApacheBench (ab) manpage ab.8. + [Simon Baldwin ] PR#5139 + + *) Made sure ApacheBench (ab) performs no more requests than + specified on command line (option -n). + [Jim Cox ] PR#4839 + + *) Support DSOs properly on 32-bit HP-UX 11.0 + [Dilip Khandekar ] + + *) Fix problem with proxy configuration where globally set configuration + options were overridden inside virtual hosts. + [Graham Leggett ] + + *) Fix ProxyReceiveBufferSize where default value was left uninitialised. + [Graham Leggett ] + + *) 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 [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 ] + + *) Add some compile-time flags to the output when -V is used for TPF + [David McCreedy ] + + *) mod_auth_digest fixes: + - Use unix-io instead of stdio to read /dev/random (fixes problems + on FreeBSD) + [Kano ] PR#4967 + - Correctly unescape all parts of the request uri and the uri + attribute of the Authorization header before doing comparison + [Joe Orton , Ronald Tschalär] + - Fixes for MD5-sess + [Joe Orton ] + - 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 ] + + *) More TPF changes. Code reorganization for cleanliness, regex + changes for testing, as well as doc and build updates. + [David McCreedy and others at IBM] + + *) Add TPF processing for the socket read to the rfc1413 code. + [David McCreedy and others at IBM] + + *) Require the batch (-b) option and default to MD5 on TPF in htpasswd. + [David McCreedy and others at IBM] + + *) Move "handler not found" warning message to below the check + for a wildcard handler. [Dirk , 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 ] + + +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 , Roy Fielding] + + *) PORT: Improved compilation and DSO support on Sequent DYNIX/ptx. + [Ian Turner ] 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 ] + + *) Fix a memory leak where the module counts were getting messed + up across restarts. [David Harris ] + + *) CIDR addresses such as a.b.c.d/24 where d != 0 weren't handled + properly in mod_access. + ["Paul J. Reder" ] PR#4770 + + *) RewriteLock/RewriteMap didn't work properly with virtual hosts. + [Dmitry Khrustalev ] PR#3874 + + *) PORT: Support for compaq/tandem/com. + [Michael Ottati , 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 ] + + *) Change for EBCDIC platforms (TPF and BS2000) to correctly deal + with ASCII/EBCDIC conversions in "ident" query. + [David McCreedy ] + + *) 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). PR#3118 [Dean Gaudet, Roy Fielding, Ken Coar] + + *) 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 ] + + *) 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 ] 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 ] + + *) Add the new mass-vhost module (mod_vhost_alias.c) developed and + used by Demon Internet, Ltd. [Tony Finch ] + + *) 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 ] + + *) 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 ] + + *) 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 ] + + *) Added ceiling on file size for memory mapped files. + [John Giannandrea ] 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 , 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". PR#4524 [Ken Coar] + + *) 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 ] + + *) 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 ] 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 , 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 ] PR#3997 + + *) Fix sed regex for generating ap_config_auto.h in src/Configure. + [Jan Gallo ] 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 ] PR#4310 + + *) Always log months in english format for %t in mod_log_config. + [Petr Lampa ] 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 , Ken Coar] PR#1574, 3026, 3529, + 3569, 4256 + + *) When stat() fails, don't assume anything about the contents of + the struct stat. [Ed Korthof ] + + *) 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 configuration sections + [Salvador Ortiz Garcia ] + + *) 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 ] PR#2579 + + *) Add recognition of .tgz as a gzipped tarchive. + [Bertrand de Singly ] PR#2364 + + *) mod_include's fsize/flastmod should allow only relative paths, just + like "include file". [Jaroslav Benkovsky ] + + *) 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 , + Tim Costello ] PR#3178 + + *) Fix inconsistent error messages reported by mod_proxy. + [Graham Leggett ] + + *) 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 ] 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 ] + + *) 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 ] PR#4248 + + *) Add "opt" (SysV-style) layout to config.layout. [Raymond S Brand + ] + + *) 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 , Ralf S. Engelschall] PR#4269 + + *) Add support for standalone mode in TPF + [Joe Moenich ] + + *) Fix number of bytes copied by read_connection() in src/support/ab.c + [Jim Cox ] PR#4271 + + *) Fix special RewriteCond "-s" pattern matching. + [Bob Finch ] + + *) Fix value quoting in src/Configure script for ap_config_auto.h + [Paul Sutton ] + + *) Make sure RewriteLock can be used only in the global context, (i.e. + outside of any 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 + ] 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 ] 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 ] 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 ] 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 ] PR#4189 + + *) Add ap_vrprintf() function. [John Tobey ] 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 " and PR#3422 + [Peter 'Luna' Altberg , 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 ] + + *) 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 + + DefaultType gargle/blurb + + 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 ] 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 + ] + + *) PORT: AIX does not require the SHARED_CODE "hack" + [Ryan Bloom ] + + *) 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 ] 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 ] 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 ] 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 ] PR#3617 + + *) Make documentation and error messages of APACI's --activate-module=FILE + option more clear. [Jan Wolter ] 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 ] 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 , 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 ] + + *) Add support for \n and \t to mod_log_config, can be used to produce + more reliable logs with multiline entries. [Tony Finch ] + + *) Fixed a few compiler nits. [John Bley ] + + *) 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 , Jim Jagielski] + + *) OS/2 ap_os_canonical_filename()'s behaviour is improved: ap_assert() + is removed. This allows directives to work and + prevents invalid requests from killing the process. + [Brian Havard ] + + *) Reorganised FAQ document. + [Joshua Slive ] 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 ] + + *) 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 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 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 ] 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 ] 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 ] + + *) 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 ] + + *) Let src/Configure be aware of CFLAGS options starting with plus + signs as it's the case for the HP/UX compiler. + [Doug Yatcilla ] 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 ] 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 ] 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 ] 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 ] + + *) 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 ] 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 ] PR#3573 + + *) Correct some filename case assumptions from WIN32 to + CASE_BLIND_FILESYSTEM. [Brian Havard ] + + *) 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 ] + PR#3336 + + *) Update APXS manual page: some -q option arguments were missing + and another was incorrect. [Mark Anderson ] 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 ] + + *) 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 `/' where 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 ] 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 ] + + *) 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 , 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 .. 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 and + 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 ] + + *) ap_md5_binary() was using sprintf() rather than a table lookup + to convert binary bytes to hex digits. + [Ronald Tschalär ] PR#3409 + + *) Fix SEGV in TCN negotiation if no variants are acceptable. + [Martin Plechsmid ] 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 ] PR#3340 + + *) Document the `add' command of `dbmmanage' in `dbmmanage.1' manpage. + [David MacKenzie ] 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 and + others at IBM] + + *) Fix problems with handling of UNC names (e.g., \\host\path) + on Win32. [Ken Parzygnat ] + + *) Rework os_canonical_*() on Win32 so it's simpler, more + robust, and works. [Ken Parzygnat ] + PR#2555, 2915, 3064, 3232 + + *) Work around incomplete implementation of strftime on Win32. + [Manoj Kasichainula, Ken Parzygnat ] + + *) 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 + ] + + *) 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 + ] + + *) 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 ] + PR#3255 + + *) The config parser wasn't correctly noticing a missing '>' + on container start lines (e.g., it wouldn't spot + "] + PR#3279 + + *) Add a 'RemoveHandler' directive which will selectively remove + all handler associations for the specified file extensions. + [Ryan Bloom ] 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 ] 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 ] 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 ] PR#3171 + + *) PORT: DSO support for UnixWare 7 + [Ralf S. Engelschall, Ron Record ] + + *) 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 ] + + *) 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 ] 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 ] + + *) 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 , Marc Slemko] + PR#3130 + + *) PORT: DRS 6000 machine. [Paul Debleecker ] + + *) 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 ] 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 ] 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 , + 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 ] PR#3111 + + *) Fix stderr redirection under syslog-based error logging situation. + [Youichirou Koga ] PR#3095 + + *) Document `ErrorLog syslog:facility' variant of error logging. + [Youichirou Koga ] PR#3096 + + *) Fix http://localhost/ hints in top-level INSTALL document. + [Rob Jenson , 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 ] + + *) Fix problem with scripts and filehandle inheritance on Win32. + [Ken Parzygnat ] PR#2884, 2910 + + *) Win32 name canonicalisation could end up using the server's + working directory to fill in some blanks. [Ken Parzygnat + ] 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 ] 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 + ] + + *) 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 ] + + *) PORT: Fix sys/resource.h handling for Amdahl's UTS 2.1 + [Dave Dykstra ] PR#3054 + + *) Correct comment in mod_log_config.c about its internals. + [Elf Sternberg ] + + *) 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 , 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 ] + + *) 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 ] + + *) Delete PID file on clean shutdowns. + [Charles Randall ] PR#2947 + + *) Fix mod_auth_*.html documents: NSCA -> NCSA + [Youichirou Koga ] PR#2991 + + *) Fix INSTALL document: www.gnu.ai.mit.edu -> www.gnu.org + [Karl Berry ] PR#2994 + + *) Fix dbmmanage.1 manual page. + [Youichirou Koga ] PR#2992 + + *) Fix possible buffer overflow situation in suexec.c. + [Jeff Stewart ] 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 ] PR#2533 + + *) Fix documentation of ProxyPass/ProxyPassReverse according to the + trailing slash problem. [Jon Drukman ] 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 ] + + *) 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 ] + + *) 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 ] 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 ] 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 ] 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: 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 + 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 + ] 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 , 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 ] + + *) 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 ] 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 ] 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 ] 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 , 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 transfered. It works for HTTP transfers only. The + new configuration directive is called CacheForceCompletion. + [Glen Parker ] PR#2277 + + *) Add the "] + + *) 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 ] PR#2529 + + *) Add Dynamic Shared Object (DSO) support for SCO5 (OpenServer 5.0.x). + [Ronald Record ] 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 ] PR#2551 + + *) The 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 ] 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 ] 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 ] + + *) 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 ] 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 .. sections to the core module (with same spirit + as .. 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 instead of physically ones (e.g. ) + 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 ] + 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 ] 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 ] 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 ] 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 ] PR#2384 + + *) mod_log_config wouldn't let vhosts use log formats defined in the + main server. [Christof Damian ] 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 ] PR#1973 + + *) Change "Options None" to "Options FollowSymLinks" in the + 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 ] PR#2320 + + *) Fix symbol export list (src/support/httpd.exp) after recent + API changes in the child spawning area. + [Jens-Uwe Mager ] + + *) 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" ] PR#2332 + + *) PORT: Fix compilation failures on NEXTSTEP. + [Rex Dieter ] PR#2293, 2316 + + *) PORT: F_NDELAY is a typo, should have been FNDELAY. There's also + O_NDELAY on various systems. [Dave Dykstra ] PR#2313 + + *) PORT: helpers/GuessOS updates for various versions for NCR SVR4. + [juerg schreiner , + Bill Houle ] 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 , 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" ] + + *) PORT: QNX needed a #include ; and now it uses flock + serialized accept to handle multiple sockets. + [Rob Saccoccio ] PR#2295, 2296 + + *) Have NT properly set the directory for CGI scripts + (& other spawned children) + [W G Stoddard ] + + *) Propagate environment to CGI scripts correctly in Win32. + [W G Stoddard ] 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 ] 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 ] + + *) 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 ] + + *) 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 ] 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 ] 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 ] + + *) 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 , 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. and directories src. + [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 ] + 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 ] PR#2146 + + *) Make Apache header files, and some variables, C++ friendly. + [Michael Anderson's ] + + *) 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 ] PR#2165 + + *) PORT: Dynamic Shared Object (DSO) support for NetBSD. + [Jaromir Dolecek , 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 RedHat 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 RedHat) who build for the real prefix + via "configure --prefix=/" 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 ] PR#2082 + + *) AIX required sys/select.h in support/ab.c + [Jens Schleusener ] 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 ] + + *) 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 ] 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 ] 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 ] 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 ] 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 ] 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 ] + + *) 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 ] PR#1888 + + *) rputs() did not calculate r->sent_bodyct properly. + [Siegmund Stirnweiss ] 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 ] 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 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 ] + + *) 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 ] 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 ] 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 ] 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 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 + sections). [Ralf S. Engelschall, parts based on code from + Jay Soffian ] 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 + ] + + *) [PORT] Recognize FreeBSD versions so we can use the OS regex as well + as handling unsigned-chars for FreeBSD v3 and v2 [Andrey Chernov + 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 ] + + *) Fix multiple UserDir problem introduced during 1.3b4-dev. + [Dean Gaudet] PR#1850 + + *) ap_cpystrn() had an off-by-1 error. + [Charles Fu ] 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 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 ] PR#1816 + + *) mod_mime_magic error message should indicate the filename when + reads fail. ["M.D.Parker" ] PR#1827 + + *) Previously Apache would permit to end (and + similary for Location and Directory), now this is diagnosed as an + error. Improve error messages for mismatched sections (, + , , , ...). + [Dean Gaudet, Martin Kraemer] + + *) is not permitted within (because of the + semantic ordering). [Dean Gaudet] PR#379 + + *) with wildcards was broken by the change in wildcard + semantics (* does not match /). To fix this, now + apply only to the basename of the request filename. This + fixes some other inconsistencies in semantics + (such as 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 ] 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 ] + + *) 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 ] 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 , 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 + 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 ] + + *) 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 , 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@zeus.dialix.oz.au (Peter Wemm) + 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 ] 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 ] 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 ] PR#1613 + + *) Some linkers complain when .o files contain no functions. + [Keith Severson ] 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

    +     start-tag before the HTML preamble, rather than after the preamble
    +     but before the header file contents.  [John Van Essen ]
    +     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  (Soeren Ziehe)
    +     [robinton@amtrash.comlink.de (Soeren Ziehe), 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 ] 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
    +	 , 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 ] 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 ]
    +
    +  *) WIN32: Check for binaries by looking for the executable header
    +     instead of counting control characters.
    +	 [Jim Patterson ] 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 ]
    +
    +  *) 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 ]
    +
    +  *) WIN32: Allow spaces to prefix the interpreter in #! lines.
    +     [Ben Laurie] PR#1101
    +
    +  *) WIN32: Cure file leak in CGIs. [Peter Tillemans ] 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 ]
    +
    +  *) 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., ) 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 ]
    +
    +  *) 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 ]
    +
    +  *) 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 ]
    +     PR #1261
    +
    +  *) PORT: Update the LynxOS port.  [Marius Groeger ]
    +
    +  *) Fix logic error when issuing a mmap() failed message
    +     with a non-zero MMAP_THRESHOLD.
    +     [David Chambers ] 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] áÎÄÒÅÊ þÅÒÎÏ×" ] 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 ] 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 ]
    +
    +  *) Fix a year formatting bug in mod_usertrack.
    +     [Paul Eggert ] 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 ] 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 ] PR#1321
    +
    +  *) Default pathname has been changed everywhere to /usr/local/apache
    +     [Sameer ]
    +
    +  *) PORT: AIX now uses USE_FCNTL_SERIALIZED_ACCEPT.
    +	[David Bronder ] PR#849
    +
    +  *) PORT: i386 AIX does not have memmove.
    +     [David Schuler ] PR#1267
    +
    +  *) PORT: HPUX now defaults to using Spencer regex.
    +     [Philippe Vanhaesendonck ,
    +     Omar Del Rio ] PR#482, 1246
    +
    +  *) PORT: Some versions of NetBSD don't automatically define
    +	    __NetBSD__.  Workaround by defining NETBSD.
    +     [Chris Craft ] PR#977
    +
    +  *) PORT: UnixWare 2.x requires -lgen for syslog.
    +     [Hans Snijder ] PR#1249
    +
    +  *) PORT: ULTRIX appears to not have syslog.
    +     [Lars Eilebrecht ]
    +
    +  *) PORT: Basic Gemini port (treat it like unixware212).
    +     ["Pavel Yakovlev (Paul McHacker)" ]
    +
    +  *) 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 ,  etc. blocks, prohibiting global
    +     server settings in  blocks, flagging unhandled multiple
    +     arguments to ,  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 ] 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 ]
    +
    +  *) 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" ]
    +
    +  *) PORT: Support Unisys SVR4, whose uname returns mostly useless data.
    +     ["Kaufman, Steven E" ]
    +
    +  *) 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 ] 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 
    +      Acorn RISCiX: Stephen Borrill 
    +
    +  *) 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  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.  PR#817  [Marc Slemko]
    +
    +  *) 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. PR#260, PR#656, PR#699, PR#713,
    +     PR#812 [Lars Eilebrecht]
    +
    +  *) 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
    +
    +  *) Not listed. See <http://www.apache.org/docs/new_features_1_0.html>
    +
    +Changes with Apache 0.8.16
    +
    +  *) 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
    +
    +  *) 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
    +
    +  *) 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
    +
    +  *) 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
    +
    +  *) 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
    +
    +  *) 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
    +
    +  *) 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
    +
    +  *) 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]
    +
    +  *) 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
    +
    +  *) 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
    +
    +  *) 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
    +
    +  *) 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
    +
    +  *) 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]
    +
    +  *) 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
    +
    +  *) 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):
    +
    +  *) 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 0.6.1
    +
    +  *) 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 0.6.0
    +
    +  *) 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 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 0.5.2
    +
    +  *) 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 0.5.1: [Hopefully complete]                  10 Apr 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 0.4                                          02 Apr 1995
    +
    +  *) Patches by Brian Behlendorf, Andrew Wilson, Robert Thau,
    +     and Rob Hartill.
    +
    +Changes with 0.3                                          24 Mar 1995
    +
    +  *) Patches by Robert Thau, David Robinson, Rob Hartill, and
    +     Carlos Varela
    +
    +Changes with 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_12/src/Configuration.tmpl b/APACHE_1_3_12/src/Configuration.tmpl
    new file mode 100644
    index 0000000000..68cc2dfaf9
    --- /dev/null
    +++ b/APACHE_1_3_12/src/Configuration.tmpl
    @@ -0,0 +1,438 @@
    +# 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 James Clark's Expat package into Apache, for use by the
    +#  modules. The "default" is to include it if the lib/expat-lite/
    +#  directory is present. This rule will always be interpreted as "no"
    +#  if the directory is not present.
    +#
    +
    +Rule SOCKS4=no
    +Rule SOCKS5=no
    +Rule IRIXNIS=no
    +Rule IRIXN32=yes
    +Rule PARANOID=no
    +Rule EXPAT=default
    +
    +# 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_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_12/src/Configure b/APACHE_1_3_12/src/Configure
    new file mode 100755
    index 0000000000..4852805c9d
    --- /dev/null
    +++ b/APACHE_1_3_12/src/Configure
    @@ -0,0 +1,2411 @@
    +#!/bin/sh
    +## ====================================================================
    +## Copyright (c) 1995-1999 The Apache Group.  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 acknowledgment:
    +##    "This product includes software developed by the Apache Group
    +##    for use in the Apache HTTP server project (http://www.apache.org/)."
    +##
    +## 4. The names "Apache Server" and "Apache Group" must not be used to
    +##    endorse or promote products derived from this software without
    +##    prior written permission. For written permission, please contact
    +##    apache@apache.org.
    +##
    +## 5. Products derived from this software may not be called "Apache"
    +##    nor may "Apache" appear in their names without prior written
    +##    permission of the Apache Group.
    +##
    +## 6. Redistributions of any form whatsoever must retain the following
    +##    acknowledgment:
    +##    "This product includes software developed by the Apache Group
    +##    for use in the Apache HTTP server project (http://www.apache.org/)."
    +##
    +## THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    +## EXPRESSED 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 APACHE GROUP OR
    +## ITS 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.
    +## ====================================================================
    +##
    +## This software consists of voluntary contributions made by many
    +## individuals on behalf of the Apache Group and was originally based
    +## on public domain software written at the National Center for
    +## Supercomputing Applications, University of Illinois, Urbana-Champaign.
    +## For more information on the Apache Group and the Apache HTTP server
    +## project, please see <http://www.apache.org/>.
    +
    +# 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_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=1 -U__STR__ -DUSEBCOPY"
    +	DEF_WANTHSREGEX=no
    +	;;
    +    *-ibm-aix[1-2].*)
    +	OS='IBM AIX 1.x/2.x'
    +	CFLAGS="$CFLAGS -DAIX=1 -DNEED_RLIM_T -U__STR__"
    +	;;
    +    *-ibm-aix3.*)
    +	OS='IBM AIX 3.x'
    +	CFLAGS="$CFLAGS -DAIX=30 -DNEED_RLIM_T -U__STR__"
    +	;;
    +    *-ibm-aix4.1)
    +	OS='IBM AIX 4.1'
    +	CFLAGS="$CFLAGS -DAIX=41 -DNEED_RLIM_T -U__STR__"
    +	;;
    +    *-ibm-aix4.2)
    +	OS='IBM AIX 4.2'
    +	CFLAGS="$CFLAGS -DAIX=42 -U__STR__"
    +	LDFLAGS="$LDFLAGS -lm"
    +	;;
    +    *-ibm-aix4.3)
    +	OS='IBM AIX 4.3'
    +	CFLAGS="$CFLAGS -DAIX=43 -U__STR__"
    +	LDFLAGS="$LDFLAGS -lm"
    +	RULE_SHARED_CORE=no
    +	DEF_SHARED_CORE=no
    +	;;
    +    *-ibm-aix*)
    +	OS='IBM AIX'
    +	CFLAGS="$CFLAGS -DAIX=1 -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
    +	;;
    +    *-linux2)
    +	DEF_WANTHSREGEX=yes
    +	OS='Linux'
    +	CFLAGS="$CFLAGS -DLINUX=2"
    +	LIBS="$LIBS -lm"
    +	;;
    +    *-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
    +	    [234]*)
    +		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 -DMAC_OS_X_SERVER"
    +	DEF_WANTHSREGEX=yes
    +	;;
    +    *-apple-macos*)
    +	OS='Mac OS'
    +	CFLAGS="$CFLAGS -DMAC_OS"
    +	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"
    +	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"
    +	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"
    +       DEF_WANTHSREGEX=yes
    +       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 -DUSE_SYSVSEM_SERIALIZED_ACCEPT -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*)
    +	OS='BeOS';
    +	CFLAGS="$CFLAGS -DBEOS"
    +	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"
    +       ;;
    +    *) # 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://www.apache.org/bug_report.html. 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
    +
    +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' | tr '[a-z]' '[A-Z]'`"
    +    ./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
    +	    LIBS_SHLIB='$(OSDIR)/mpe_dl_stub.o'	
    +	    ;;
    +	*-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
    +	    ;;
    +	*-freebsd3*|*-freebsd4*)
    +		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*)
    +	    CFLAGS_SHLIB="-fPIC"
    +	    LDFLAGS_SHLIB="-Bforcearchive -Bshareable"
    +	    LDFLAGS_MOD_SHLIB=$LDFLAGS_SHLIB
    +	    LDFLAGS_SHLIB_EXPORT=""
    +	    SHLIB_SUFFIX_DEPTH=2
    +	    ;;
    +	*-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-macos* )
    +	    LD_SHLIB="cc"
    +	    CFLAGS_SHLIB=""
    +	    LDFLAGS_SHLIB='$(EXTRA_LDFLAGS) -bundle -undefined suppress'
    +	    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"
    +	    ;;
    +	 *-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"
    +	    ;;
    +	*-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
    +	    ;;
    +	*-ibm-aix*)
    +	    case $CC in
    +		*/gcc|gcc ) CFLAGS_SHLIB="-fpic" ;;
    +		*/cc|cc   ) CFLAGS_SHLIB="" ;;
    +	    esac
    +	    case $PLAT in
    +		*-ibm-aix4*)
    +		    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=""
    +            ;;
    +	*)
    +	    ##  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://www.apache.org/bug_report.html:"
    +		    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
    +	;;
    +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
    +	;;
    +
    +    *-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
    +	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.
    +
    +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
    +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.
    +##
    +if [ -d ./lib/expat-lite/ ]; then
    +    if [ "x$RULE_EXPAT" = "xdefault" ]; then
    +        RULE_EXPAT=yes
    +    fi
    +else
    +    if [ "$xRULE_EXPAT" = "xyes" ]; then
    +        echo "ERROR: RULE_EXPAT set to \"yes\" but is not available."
    +	exit 1
    +    else
    +        RULE_EXPAT=no
    +    fi
    +fi
    +if [ "x$RULE_EXPAT" = "xyes" ]; then
    +    EXPATLIB="lib/expat-lite/libexpat.a"
    +    APLIBDIRS="expat-lite $APLIBDIRS"
    +    CFLAGS="$CFLAGS -DUSE_EXPAT -I\$(SRCDIR)/lib/expat-lite"
    +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
    +	echo " + enabling generation of Apache core as DSO"
    +	#    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=12
    +	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 "LDFLAGS_SHLIB=$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
    +	*-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
    +##
    +## 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)
    +      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)' \$@) || exit 1;; \\
    +		              *) (cd \$\$i && \$(MAKE) \$(MFLAGS_STATIC) SDP='\$(SDP)' CC='\$(CC)' AUX_CFLAGS='\$(CFLAGS)' RANLIB='\$(RANLIB)' \$@) || 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_12/src/INDENT b/APACHE_1_3_12/src/INDENT
    new file mode 100644
    index 0000000000..9f02cc3b09
    --- /dev/null
    +++ b/APACHE_1_3_12/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_12/src/INSTALL b/APACHE_1_3_12/src/INSTALL
    new file mode 100644
    index 0000000000..a39d37f925
    --- /dev/null
    +++ b/APACHE_1_3_12/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.NT and
    +        http://www.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_12/src/Makefile.nt b/APACHE_1_3_12/src/Makefile.nt
    new file mode 100644
    index 0000000000..9d0dbab491
    --- /dev/null
    +++ b/APACHE_1_3_12/src/Makefile.nt
    @@ -0,0 +1,158 @@
    +# Makefile for Windows NT and Windows 95
    +
    +# 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.nt INSTDIR="d:\Program Files\Apache" installr
    +#
    +# Note: this does *NOT* change the compiled in default "server root"
    +
    +!IF "$(INSTDIR)" == ""
    +INSTDIR=\Apache
    +!MESSAGE Using default install directory \Apache
    +!ENDIF 
    +
    +default:	_apacher
    +
    +_release:
    +	set SHORT=R
    +	set LONG=Release
    +
    +_debug:
    +	set SHORT=D
    +	set LONG=Debug
    +
    +_apacher: _release _build
    +_apached: _debug   _build
    +installr: _release _build _install
    +installd: _debug   _build _install
    +_cleanr:  _release _clean
    +_cleand:  _debug   _clean
    +
    +clean:
    +	$(MAKE) /f Makefile.nt _cleanr
    +	$(MAKE) /f Makefile.nt _cleand
    +
    +installdll: _release _installdll
    +
    +_build:
    +#	echo LONG %LONG% SHORT %SHORT% x
    +	cd os\win32
    +	 nmake /nologo CFG="ApacheOS - Win32 %LONG%" -f ApacheOS.mak
    +	cd ..\..
    +	cd regex
    +	 nmake /nologo CFG="regex - Win32 %LONG%" -f regex.mak
    +	cd ..
    +	cd ap
    +	 nmake /nologo CFG="ap - Win32 %LONG%" -f ap.mak
    +	cd ..
    +	cd support
    +	 nmake /nologo CFG="htpasswd - Win32 %LONG%" -f htpasswd.mak
    +	 nmake /nologo CFG="htdigest - Win32 %LONG%" -f htdigest.mak
    +	cd ..
    +	cd lib/expat-lite
    +	 nmake /nologo CFG="xmlparse - Win32 %LONG%" -f xmlparse.mak
    +	cd ../..
    +	cd main
    +	 nmake /nologo CFG="gen_uri_delims - Win32 %LONG%" -f gen_uri_delims.mak
    +	 nmake /nologo CFG="gen_test_char - Win32 %LONG%" -f gen_test_char.mak
    +	cd ..
    +	 -del Core%SHORT%\buildmark.obj
    +	 nmake /nologo CFG="ApacheCore - Win32 %LONG%" -f ApacheCore.mak
    +	 nmake /nologo CFG="Apache - Win32 %LONG%" -f Apache.mak
    +	cd os\win32
    +	 set CFG=ApacheModuleStatus - Win32 %LONG%
    +	 nmake /nologo CFG="ApacheModuleStatus - Win32 %LONG%" -f ApacheModuleStatus.mak
    +#	 nmake /nologo CFG ""/nologo -f ApacheModuleStatus.mak"=ApacheModuleInfo - Win32 %LONG%" -f ApacheModuleInfo.mak
    +	 nmake /nologo CFG="ApacheModuleAuthAnon - Win32 %LONG%" -f ApacheModuleAuthAnon.mak
    +	 nmake /nologo CFG="ApacheModuleDigest - Win32 %LONG%" -f ApacheModuleDigest.mak
    +	 nmake /nologo CFG="ApacheModuleCERNMeta - Win32 %LONG%" -f ApacheModuleCERNMeta.mak
    +	 nmake /nologo CFG="ApacheModuleExpires - Win32 %LONG%" -f ApacheModuleExpires.mak
    +	 nmake /nologo CFG="ApacheModuleHeaders - Win32 %LONG%" -f ApacheModuleHeaders.mak
    +	 nmake /nologo CFG="ApacheModuleSpeling - Win32 %LONG%" -f ApacheModuleSpeling.mak
    +	 nmake /nologo CFG="ApacheModuleUserTrack - Win32 %LONG%" -f ApacheModuleUserTrack.mak
    +	 nmake /nologo CFG="ApacheModuleRewrite - Win32 %LONG%" -f ApacheModuleRewrite.mak
    +	cd ..\..
    +	cd modules\proxy
    +	 nmake /nologo CFG="ApacheModuleProxy - Win32 %LONG%" -f ApacheModuleProxy.mak
    +	cd ..\..
    +
    +_install:
    +	-mkdir $(INSTDIR)
    +	-mkdir $(INSTDIR)\modules
    +	-mkdir $(INSTDIR)\logs
    +	-mkdir $(INSTDIR)\conf
    +	-mkdir $(INSTDIR)\bin
    +	copy Apache%SHORT%\Apache.exe $(INSTDIR)
    +	copy Core%SHORT%\ApacheCore.dll $(INSTDIR)
    +	copy os\win32\ApacheModuleStatus%SHORT%\ApacheModuleStatus.dll $(INSTDIR)\modules
    +#       copy os\win32\ApacheModuleInfo%SHORT%\ApacheModuleInfo.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleAuthAnon%SHORT%\ApacheModuleAuthAnon.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleDigest%SHORT%\ApacheModuleDigest.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleCERNMeta%SHORT%\ApacheModuleCERNMeta.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleExpires%SHORT%\ApacheModuleExpires.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleHeaders%SHORT%\ApacheModuleHeaders.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleRewrite%SHORT%\ApacheModuleRewrite.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleSpeling%SHORT%\ApacheModuleSpeling.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleUserTrack%SHORT%\ApacheModuleUserTrack.dll $(INSTDIR)\modules
    +	copy modules\proxy\%LONG%\ApacheModuleProxy.dll $(INSTDIR)\modules
    +	copy support\%LONG%\htpasswd.exe $(INSTDIR)\bin
    +	copy support\%LONG%\htdigest.exe $(INSTDIR)\bin
    +
    +_clean:
    +	cd os\win32
    +	 nmake /nologo CFG="ApacheOS - Win32 %LONG%" -f ApacheOS.mak clean
    +	cd ..\..
    +	cd regex
    +	 nmake /nologo CFG="regex - Win32 %LONG%" -f regex.mak clean
    +	cd ..
    +	cd ap
    +	 nmake /nologo CFG="ap - Win32 %LONG%" -f ap.mak clean
    +	cd ..
    +	cd support
    +	 nmake /nologo CFG="htpasswd - Win32 %LONG%" -f htpasswd.mak clean
    +	 nmake /nologo CFG="htdigest - Win32 %LONG%" -f htdigest.mak clean
    +	cd ..
    +	cd lib/expat-lite
    +	 nmake /nologo CFG="xmlparse - Win32 %LONG%" -f xmlparse.mak clean
    +	cd ../..
    +	cd main
    +	 nmake /nologo CFG="gen_uri_delims - Win32 %LONG%" -f gen_uri_delims.mak clean
    +	 del uri_delims.h
    +	 nmake /nologo CFG="gen_test_char - Win32 %LONG%" -f gen_test_char.mak clean
    +	 del test_char.h
    +	cd ..
    +	 nmake /nologo CFG="ApacheCore - Win32 %LONG%" -f ApacheCore.mak clean
    +	 nmake /nologo CFG="Apache - Win32 %LONG%" -f Apache.mak clean
    +	cd os\win32
    +	 nmake /nologo CFG="ApacheModuleStatus - Win32 %LONG%" -f ApacheModuleStatus.mak clean
    +#	 nmake /nologo CFG="ApacheModuleInfo - Win32 %LONG%" -f ApacheModuleInfo.mak clean
    +	 nmake /nologo CFG="ApacheModuleAuthAnon - Win32 %LONG%" -f ApacheModuleAuthAnon.mak clean
    +	 nmake /nologo CFG="ApacheModuleDigest - Win32 %LONG%" -f ApacheModuleDigest.mak clean
    +	 nmake /nologo CFG="ApacheModuleCERNMeta - Win32 %LONG%" -f ApacheModuleCERNMeta.mak clean
    +	 nmake /nologo CFG="ApacheModuleExpires - Win32 %LONG%" -f ApacheModuleExpires.mak clean
    +	 nmake /nologo CFG="ApacheModuleHeaders - Win32 %LONG%" -f ApacheModuleHeaders.mak clean
    +	 nmake /nologo CFG="ApacheModuleSpeling - Win32 %LONG%" -f ApacheModuleSpeling.mak clean
    +	 nmake /nologo CFG="ApacheModuleUserTrack - Win32 %LONG%" -f ApacheModuleUserTrack.mak clean
    +	 nmake /nologo CFG="ApacheModuleRewrite - Win32 %LONG%" -f ApacheModuleRewrite.mak clean
    +	cd ..\..
    +	cd modules\proxy
    +	 nmake /nologo CFG="ApacheModuleProxy - Win32 %LONG%" -f ApacheModuleProxy.mak clean
    +	cd ..\..
    + 	cd os\win32\installer\installdll
    +	 nmake /nologo CFG="install - Win32 %LONG%" -f install.mak clean
    +	cd ..\..\..
    +
    +_installdll:
    + 	cd os\win32\installer\installdll
    +	 nmake /nologo CFG="install - Win32 %LONG%" -f install.mak
    +	cd ..\..\..
    diff --git a/APACHE_1_3_12/src/Makefile.tmpl b/APACHE_1_3_12/src/Makefile.tmpl
    new file mode 100644
    index 0000000000..1daf1b5938
    --- /dev/null
    +++ b/APACHE_1_3_12/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)' ) || exit 1;; \
    +		              *) ( cd $$i && $(MAKE) $(MFLAGS_STATIC) SDP='$(SDP)' CC='$(CC)' AUX_CFLAGS='$(CFLAGS)' RANLIB='$(RANLIB)') || 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)' || 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)' $@ ) || 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)' 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 os/unix/os.h include/ap_ctype.h \
    + include/hsregex.h include/httpd.h include/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 os/unix/os.h \
    + include/ap_ctype.h include/hsregex.h include/alloc.h include/buff.h \
    + include/ap.h include/util_uri.h include/http_config.h
    diff --git a/APACHE_1_3_12/src/Makefile_win32.txt b/APACHE_1_3_12/src/Makefile_win32.txt
    new file mode 100644
    index 0000000000..b64607daac
    --- /dev/null
    +++ b/APACHE_1_3_12/src/Makefile_win32.txt
    @@ -0,0 +1,136 @@
    +# Makefile for Windows NT and Windows 95
    +
    +# Targets are:
    +#   _apache    - build Apache in Release mode
    +#   install    - build and install a Release build
    +#   clean      - remove (most) files generated by a Release build
    +#
    +# The default installation directory is \Apache. This can be changed
    +# with the INSTDIR macro, for example:
    +#
    +#   nmake /f Makefile_win32.txt INSTDIR="d:\Program Files\Apache" install
    +#
    +# Note: this does *NOT* change the compiled in default "server root"
    +
    +!IF "$(INSTDIR)" == ""
    +INSTDIR=\Apache
    +!MESSAGE Using default install directory \Apache
    +!ENDIF 
    +
    +default:	_apache
    +
    +_apache: _build
    +
    +install: _build _install
    +
    +_build:
    +	cd os\win32
    +	 nmake /nologo CFG="ApacheOS - Win32 Release" -f ApacheOS.mak
    +	cd ..\..
    +	cd regex
    +	 nmake /nologo CFG="regex - Win32 Release" -f regex.mak
    +	cd ..
    +	cd ap
    +	 nmake /nologo CFG="ap - Win32 Release" -f ap.mak
    +	cd ..
    +	cd support
    +	 nmake /nologo CFG="htpasswd - Win32 Release" -f htpasswd.mak
    +	 nmake /nologo CFG="htdigest - Win32 Release" -f htdigest.mak
    +	cd ..
    +	cd lib/expat-lite
    +	 nmake /nologo CFG="xmlparse - Win32 Release" -f xmlparse.mak
    +	cd ../..
    +	cd main
    +	 nmake /nologo CFG="gen_uri_delims - Win32 Release" -f gen_uri_delims.mak
    +	 nmake /nologo CFG="gen_test_char - Win32 Release" -f gen_test_char.mak
    +	cd ..
    +	 -del CoreR\buildmark.obj
    +	 nmake /nologo CFG="ApacheCore - Win32 Release" -f ApacheCore.mak
    +	 nmake /nologo CFG="Apache - Win32 Release" -f Apache.mak
    +	cd os\win32
    +	 set CFG=ApacheModuleStatus - Win32 Release
    +	 nmake /nologo CFG="ApacheModuleStatus - Win32 Release" -f ApacheModuleStatus.mak
    +#	 nmake /nologo CFG ""/nologo -f ApacheModuleStatus.mak"=ApacheModuleInfo - Win32 Release" -f ApacheModuleInfo.mak
    +	 nmake /nologo CFG="ApacheModuleAuthAnon - Win32 Release" -f ApacheModuleAuthAnon.mak
    +	 nmake /nologo CFG="ApacheModuleDigest - Win32 Release" -f ApacheModuleDigest.mak
    +	 nmake /nologo CFG="ApacheModuleCERNMeta - Win32 Release" -f ApacheModuleCERNMeta.mak
    +	 nmake /nologo CFG="ApacheModuleExpires - Win32 Release" -f ApacheModuleExpires.mak
    +	 nmake /nologo CFG="ApacheModuleHeaders - Win32 Release" -f ApacheModuleHeaders.mak
    +	 nmake /nologo CFG="ApacheModuleSpeling - Win32 Release" -f ApacheModuleSpeling.mak
    +	 nmake /nologo CFG="ApacheModuleUserTrack - Win32 Release" -f ApacheModuleUserTrack.mak
    +	 nmake /nologo CFG="ApacheModuleRewrite - Win32 Release" -f ApacheModuleRewrite.mak
    +	cd ..\..
    +	cd modules\proxy
    +	 nmake /nologo CFG="ApacheModuleProxy - Win32 Release" -f ApacheModuleProxy.mak
    +	cd ..\..
    +
    +_install:
    +	-mkdir $(INSTDIR)
    +	-mkdir $(INSTDIR)\modules
    +	-mkdir $(INSTDIR)\logs
    +	-mkdir $(INSTDIR)\conf
    +	-mkdir $(INSTDIR)\bin
    +	copy ApacheR\Apache.exe $(INSTDIR)
    +	copy CoreR\ApacheCore.dll $(INSTDIR)
    +	copy os\win32\ApacheModuleStatusR\ApacheModuleStatus.dll $(INSTDIR)\modules
    +#       copy os\win32\ApacheModuleInfoR\ApacheModuleInfo.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleAuthAnonR\ApacheModuleAuthAnon.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleDigestR\ApacheModuleDigest.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleCERNMetaR\ApacheModuleCERNMeta.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleExpiresR\ApacheModuleExpires.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleHeadersR\ApacheModuleHeaders.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleRewriteR\ApacheModuleRewrite.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleSpelingR\ApacheModuleSpeling.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleUserTrackR\ApacheModuleUserTrack.dll $(INSTDIR)\modules
    +	copy modules\proxy\Release\ApacheModuleProxy.dll $(INSTDIR)\modules
    +	copy support\Release\htpasswd.exe $(INSTDIR)\bin
    +	copy support\Release\htdigest.exe $(INSTDIR)\bin
    +
    +clean:
    +	cd os\win32
    +	 nmake /nologo CFG="ApacheOS - Win32 Release" -f ApacheOS.mak clean
    +	cd ..\..
    +	cd regex
    +	 nmake /nologo CFG="regex - Win32 Release" -f regex.mak clean
    +	cd ..
    +	cd ap
    +	 nmake /nologo CFG="ap - Win32 Release" -f ap.mak clean
    +	cd ..
    +	cd support
    +	 nmake /nologo CFG="htpasswd - Win32 Release" -f htpasswd.mak clean
    +	 nmake /nologo CFG="htdigest - Win32 Release" -f htdigest.mak clean
    +	cd ..
    +	cd lib/expat-lite
    +	 nmake /nologo CFG="xmlparse - Win32 Release" -f xmlparse.mak clean
    +	cd ../..
    +	cd main
    +	 nmake /nologo CFG="gen_uri_delims - Win32 Release" -f gen_uri_delims.mak clean
    +	 del uri_delims.h
    +	 nmake /nologo CFG="gen_test_char - Win32 Release" -f gen_test_char.mak clean
    +	 del test_char.h
    +	cd ..
    +	 nmake /nologo CFG="ApacheCore - Win32 Release" -f ApacheCore.mak clean
    +	 nmake /nologo CFG="Apache - Win32 Release" -f Apache.mak clean
    +	cd os\win32
    +	 nmake /nologo CFG="ApacheModuleStatus - Win32 Release" -f ApacheModuleStatus.mak clean
    +#	 nmake /nologo CFG="ApacheModuleInfo - Win32 Release" -f ApacheModuleInfo.mak clean
    +	 nmake /nologo CFG="ApacheModuleAuthAnon - Win32 Release" -f ApacheModuleAuthAnon.mak clean
    +	 nmake /nologo CFG="ApacheModuleDigest - Win32 Release" -f ApacheModuleDigest.mak clean
    +	 nmake /nologo CFG="ApacheModuleCERNMeta - Win32 Release" -f ApacheModuleCERNMeta.mak clean
    +	 nmake /nologo CFG="ApacheModuleExpires - Win32 Release" -f ApacheModuleExpires.mak clean
    +	 nmake /nologo CFG="ApacheModuleHeaders - Win32 Release" -f ApacheModuleHeaders.mak clean
    +	 nmake /nologo CFG="ApacheModuleSpeling - Win32 Release" -f ApacheModuleSpeling.mak clean
    +	 nmake /nologo CFG="ApacheModuleUserTrack - Win32 Release" -f ApacheModuleUserTrack.mak clean
    +	 nmake /nologo CFG="ApacheModuleRewrite - Win32 Release" -f ApacheModuleRewrite.mak clean
    +	cd ..\..
    +	cd modules\proxy
    +	 nmake /nologo CFG="ApacheModuleProxy - Win32 Release" -f ApacheModuleProxy.mak clean
    +	cd ..\..
    + 	cd os\win32\installer\installdll
    +	 nmake /nologo CFG="install - Win32 Release" -f install.mak clean
    +	cd ..\..\..
    +
    +installdll:
    + 	cd os\win32\installer\installdll
    +	 nmake /nologo CFG="install - Win32 Release" -f install.mak
    +	cd ..\..\..
    diff --git a/APACHE_1_3_12/src/Makefile_win32_debug.txt b/APACHE_1_3_12/src/Makefile_win32_debug.txt
    new file mode 100644
    index 0000000000..220427fadf
    --- /dev/null
    +++ b/APACHE_1_3_12/src/Makefile_win32_debug.txt
    @@ -0,0 +1,136 @@
    +# Makefile for Windows NT and Windows 95
    +
    +# Targets are:
    +#   _apache    - build Apache in Debug mode
    +#   install    - build and install a Debug build
    +#   clean      - 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_win32_debug.txt INSTDIR="d:\Program Files\Apache" install
    +#
    +# Note: this does *NOT* change the compiled in default "server root"
    +
    +!IF "$(INSTDIR)" == ""
    +INSTDIR=\Apache
    +!MESSAGE Using default install directory \Apache
    +!ENDIF 
    +
    +default:	_apache
    +
    +_apache: _build
    +
    +install: _build _install
    +
    +_build:
    +	cd os\win32
    +	 nmake /nologo CFG="ApacheOS - Win32 Debug" -f ApacheOS.mak
    +	cd ..\..
    +	cd regex
    +	 nmake /nologo CFG="regex - Win32 Debug" -f regex.mak
    +	cd ..
    +	cd ap
    +	 nmake /nologo CFG="ap - Win32 Debug" -f ap.mak
    +	cd ..
    +	cd support
    +	 nmake /nologo CFG="htpasswd - Win32 Debug" -f htpasswd.mak
    +	 nmake /nologo CFG="htdigest - Win32 Debug" -f htdigest.mak
    +	cd ..
    +	cd lib/expat-lite
    +	 nmake /nologo CFG="xmlparse - Win32 Debug" -f xmlparse.mak
    +	cd ../..
    +	cd main
    +	 nmake /nologo CFG="gen_uri_delims - Win32 Debug" -f gen_uri_delims.mak
    +	 nmake /nologo CFG="gen_test_char - Win32 Debug" -f gen_test_char.mak
    +	cd ..
    +	 -del CoreD\buildmark.obj
    +	 nmake /nologo CFG="ApacheCore - Win32 Debug" -f ApacheCore.mak
    +	 nmake /nologo CFG="Apache - Win32 Debug" -f Apache.mak
    +	cd os\win32
    +	 set CFG=ApacheModuleStatus - Win32 Debug
    +	 nmake /nologo CFG="ApacheModuleStatus - Win32 Debug" -f ApacheModuleStatus.mak
    +#	 nmake /nologo CFG ""/nologo -f ApacheModuleStatus.mak"=ApacheModuleInfo - Win32 Debug" -f ApacheModuleInfo.mak
    +	 nmake /nologo CFG="ApacheModuleAuthAnon - Win32 Debug" -f ApacheModuleAuthAnon.mak
    +	 nmake /nologo CFG="ApacheModuleDigest - Win32 Debug" -f ApacheModuleDigest.mak
    +	 nmake /nologo CFG="ApacheModuleCERNMeta - Win32 Debug" -f ApacheModuleCERNMeta.mak
    +	 nmake /nologo CFG="ApacheModuleExpires - Win32 Debug" -f ApacheModuleExpires.mak
    +	 nmake /nologo CFG="ApacheModuleHeaders - Win32 Debug" -f ApacheModuleHeaders.mak
    +	 nmake /nologo CFG="ApacheModuleSpeling - Win32 Debug" -f ApacheModuleSpeling.mak
    +	 nmake /nologo CFG="ApacheModuleUserTrack - Win32 Debug" -f ApacheModuleUserTrack.mak
    +	 nmake /nologo CFG="ApacheModuleRewrite - Win32 Debug" -f ApacheModuleRewrite.mak
    +	cd ..\..
    +	cd modules\proxy
    +	 nmake /nologo CFG="ApacheModuleProxy - Win32 Debug" -f ApacheModuleProxy.mak
    +	cd ..\..
    +
    +_install:
    +	-mkdir $(INSTDIR)
    +	-mkdir $(INSTDIR)\modules
    +	-mkdir $(INSTDIR)\logs
    +	-mkdir $(INSTDIR)\conf
    +	-mkdir $(INSTDIR)\bin
    +	copy ApacheD\Apache.exe $(INSTDIR)
    +	copy CoreD\ApacheCore.dll $(INSTDIR)
    +	copy os\win32\ApacheModuleStatusD\ApacheModuleStatus.dll $(INSTDIR)\modules
    +#       copy os\win32\ApacheModuleInfoD\ApacheModuleInfo.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleAuthAnonD\ApacheModuleAuthAnon.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleDigestD\ApacheModuleDigest.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleCERNMetaD\ApacheModuleCERNMeta.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleExpiresD\ApacheModuleExpires.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleHeadersD\ApacheModuleHeaders.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleRewriteD\ApacheModuleRewrite.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleSpelingD\ApacheModuleSpeling.dll $(INSTDIR)\modules
    +	copy os\win32\ApacheModuleUserTrackD\ApacheModuleUserTrack.dll $(INSTDIR)\modules
    +	copy modules\proxy\Debug\ApacheModuleProxy.dll $(INSTDIR)\modules
    +	copy support\Debug\htpasswd.exe $(INSTDIR)\bin
    +	copy support\Debug\htdigest.exe $(INSTDIR)\bin
    +
    +clean:
    +	cd os\win32
    +	 nmake /nologo CFG="ApacheOS - Win32 Debug" -f ApacheOS.mak clean
    +	cd ..\..
    +	cd regex
    +	 nmake /nologo CFG="regex - Win32 Debug" -f regex.mak clean
    +	cd ..
    +	cd ap
    +	 nmake /nologo CFG="ap - Win32 Debug" -f ap.mak clean
    +	cd ..
    +	cd support
    +	 nmake /nologo CFG="htpasswd - Win32 Debug" -f htpasswd.mak clean
    +	 nmake /nologo CFG="htdigest - Win32 Debug" -f htdigest.mak clean
    +	cd ..
    +	cd lib/expat-lite
    +	 nmake /nologo CFG="xmlparse - Win32 Debug" -f xmlparse.mak clean
    +	cd ../..
    +	cd main
    +	 nmake /nologo CFG="gen_uri_delims - Win32 Debug" -f gen_uri_delims.mak clean
    +	 del uri_delims.h
    +	 nmake /nologo CFG="gen_test_char - Win32 Debug" -f gen_test_char.mak clean
    +	 del test_char.h
    +	cd ..
    +	 nmake /nologo CFG="ApacheCore - Win32 Debug" -f ApacheCore.mak clean
    +	 nmake /nologo CFG="Apache - Win32 Debug" -f Apache.mak clean
    +	cd os\win32
    +	 nmake /nologo CFG="ApacheModuleStatus - Win32 Debug" -f ApacheModuleStatus.mak clean
    +#	 nmake /nologo CFG="ApacheModuleInfo - Win32 Debug" -f ApacheModuleInfo.mak clean
    +	 nmake /nologo CFG="ApacheModuleAuthAnon - Win32 Debug" -f ApacheModuleAuthAnon.mak clean
    +	 nmake /nologo CFG="ApacheModuleDigest - Win32 Debug" -f ApacheModuleDigest.mak clean
    +	 nmake /nologo CFG="ApacheModuleCERNMeta - Win32 Debug" -f ApacheModuleCERNMeta.mak clean
    +	 nmake /nologo CFG="ApacheModuleExpires - Win32 Debug" -f ApacheModuleExpires.mak clean
    +	 nmake /nologo CFG="ApacheModuleHeaders - Win32 Debug" -f ApacheModuleHeaders.mak clean
    +	 nmake /nologo CFG="ApacheModuleSpeling - Win32 Debug" -f ApacheModuleSpeling.mak clean
    +	 nmake /nologo CFG="ApacheModuleUserTrack - Win32 Debug" -f ApacheModuleUserTrack.mak clean
    +	 nmake /nologo CFG="ApacheModuleRewrite - Win32 Debug" -f ApacheModuleRewrite.mak clean
    +	cd ..\..
    +	cd modules\proxy
    +	 nmake /nologo CFG="ApacheModuleProxy - Win32 Debug" -f ApacheModuleProxy.mak clean
    +	cd ..\..
    + 	cd os\win32\installer\installdll
    +	 nmake /nologo CFG="install - Win32 Debug" -f install.mak clean
    +	cd ..\..\..
    +
    +installdll:
    + 	cd os\win32\installer\installdll
    +	 nmake /nologo CFG="install - Win32 Debug" -f install.mak
    +	cd ..\..\..
    diff --git a/APACHE_1_3_12/src/PORTING b/APACHE_1_3_12/src/PORTING
    new file mode 100644
    index 0000000000..52103d24f1
    --- /dev/null
    +++ b/APACHE_1_3_12/src/PORTING
    @@ -0,0 +1,381 @@
    +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 semaphore
    +  between children entering accept().  A complete port should define one
    +  of these, many may work and it's worthwhile timing them.  Without these
    +  the server will not implement multiple Listen directives reliably.
    +
    +     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. Valid only on
    +       Win32 at present.
    +
    +      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_12/src/README b/APACHE_1_3_12/src/README
    new file mode 100644
    index 0000000000..9aefdcac47
    --- /dev/null
    +++ b/APACHE_1_3_12/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_12/src/README.EBCDIC b/APACHE_1_3_12/src/README.EBCDIC
    new file mode 100644
    index 0000000000..78a5acfaac
    --- /dev/null
    +++ b/APACHE_1_3_12/src/README.EBCDIC
    @@ -0,0 +1,99 @@
    +			    README.EBCDIC
    +
    +This version of Apache comes with a first-cut (working, but not
    +fully tested) port to a mainframe machine which uses the EBCDIC
    +character set as its native codeset (It is the SIEMENS family 
    +of mainframes running the BS2000 operating system. This
    +mainframe OS nowadays features a SVR4-like POSIX subsystem).
    +
    +The port was started initially to
    +- prove the feasibility
    +- find a "worthy and capable" successor for the CERN daemon (which
    +  was ported a couple of years ago), and to
    +- prove that Apache's preforking process model can on this platform
    +  easily outperform the accept-fork-serve model used by CERN by a
    +  factor of 5 or more.
    +
    +This document serves as a rationale to describe some of the design
    +decisions of the port to this machine.
    +
    +* The relevant changes in the source are #ifdef'ed into two
    +  categories:
    +  #ifdef CHARSET_EBCDIC     Code which is needed for any EBCDIC
    +			    based machine
    +  #ifdef _OSD_POSIX         Code which is needed for the BS2000
    +			    SIEMENS mainframe platform only.
    +
    +* The possibility to translate between ASCII and EBCDIC at the
    +  socket level (on BS2000 POSIX, there is a socket option which
    +  supports this) was intentionally not chosen, because the byte
    +  stream at the HTTP protocol level consists of a mixture of
    +  protocol related strings and non-protocol related raw file data.
    +  HTTP protocol strings are always encoded in ASCII (the GET
    +  request, any Header: lines, the chunking information etc.) whereas
    +  the file transfer parts (i.e., GIF images, CGI output etc.) should
    +  usually be just "passed thru" by the server. This separation
    +  between "protocol string" and "raw data" is reflected in the
    +  server code by functions like bgets() or rvputs() for strings, and
    +  functions like bwrite() for binary data. A global translation of
    +  everything would therefore be inadequate.
    +  (In the case of text files of course, provisions must be made so
    +  that the documents are always served in ASCII format)
    +
    +* This port therefore features a built-in protocol level conversion
    +  for the server-internal strings (which the compiler translated to
    +  EBCDIC strings) and server-generated documents. This presumes that
    +  hard coded ASCII escapes \012 and \015 will not exist in the server
    +  code; rather coders will use the CRLF, CR, and LF macros.
    +
    +* By examining the call hierarchy for the BUFF management routines,
    +  I added an "ebcdic/ascii conversion layer" which would be crossed
    +  on every puts/write/get/gets, and a conversion flag which allowed
    +  switching of the conversions on-the-fly. So it is now possible to
    +  read the header lines of a CGI-script output in EBCDIC format, and
    +  then find out that the remainder of the script's output is in
    +  ASCII (like in the output of a WWW Counter program). Likewise, the
    +  server always generates its header lines in EBCDIC (and with ASCII
    +  conversion enabled) and determines, based on the type of document
    +  being served, whether the document body (except for the chunking
    +  information, of course) is in ASCII already or is converted from
    +  EBCDIC.
    +
    +* For Text documents (MIME types text/plain, text/html etc.), an
    +  implicit translation to ASCII can be used, or (if the users prefer
    +  to store some documents in raw ASCII form for faster serving) can
    +  be served without conversion.
    +  Example:
    +      to serve files with the suffix .ahtml as a raw ASCII text/html
    +      document (and suffix .ascii as ASCII text/plain), use the
    +      directives:
    +    AddType  text/x-ascii-html  .ahtml
    +    AddType  text/x-ascii-plain .ascii
    +  Similarly, any text/XXXX MIME type can be served as "raw ASCII" by
    +  configuring a MIME type "text/x-ascii-XXXX" for it using AddType.
    +
    +* Non-text documents are always served "binary" without conversion.
    +  This seems to be the most sensible choice for, .e.g., GIF/ZIP/AU
    +  file types. This of course requires the user to copy them to the
    +  mainframe host using the "rcp -b" binary switch.
    +
    +* Server parsed files are always assumed to be in native (i.e.,
    +  EBCDIC) format as used on the machine, and are converted after
    +  processing.
    +
    +* For CGI output, the CGI script determines whether a conversion is
    +  needed or not: by setting the appropriate Content-Type, text files
    +  can be converted, or GIF output can be passed through unmodified.
    +  An example for the latter case is the wwwcount program which we ported
    +  as well.
    +
    +Notes:
    +    To use the mod_auth_db functionality, you will need a working libdb.a.
    +On the system where I did the port none was available, so I ported the
    +standard db-1.85.14 with little problems. Note however that you will need
    +a working perl5 as well if you want to use Apache's dbmmanage script to
    +maintain db user databases.
    +
    +See also the ebcdic.html document which is part of the apache documentation.
    +
    +			    Martin Kraemer, 1-Oct-1998
    diff --git a/APACHE_1_3_12/src/ap/.cvsignore b/APACHE_1_3_12/src/ap/.cvsignore
    new file mode 100644
    index 0000000000..964f0bd942
    --- /dev/null
    +++ b/APACHE_1_3_12/src/ap/.cvsignore
    @@ -0,0 +1,2 @@
    +Makefile
    +Debug
    diff --git a/APACHE_1_3_12/src/ap/.indent.pro b/APACHE_1_3_12/src/ap/.indent.pro
    new file mode 100644
    index 0000000000..a9fbe9f9a1
    --- /dev/null
    +++ b/APACHE_1_3_12/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_12/src/ap/Makefile.tmpl b/APACHE_1_3_12/src/ap/Makefile.tmpl
    new file mode 100644
    index 0000000000..a536ed7fd7
    --- /dev/null
    +++ b/APACHE_1_3_12/src/ap/Makefile.tmpl
    @@ -0,0 +1,78 @@
    +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
    +
    +.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)/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)/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)/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)/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)/alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
    + $(INCDIR)/util_uri.h
    diff --git a/APACHE_1_3_12/src/ap/ap.dsp b/APACHE_1_3_12/src/ap/ap.dsp
    new file mode 100644
    index 0000000000..9d9c3194f1
    --- /dev/null
    +++ b/APACHE_1_3_12/src/ap/ap.dsp
    @@ -0,0 +1,122 @@
    +# Microsoft Developer Studio Project File - Name="ap" - Package Owner=<4>
    +# Microsoft Developer Studio Generated Build File, Format Version 5.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 Scc_ProjName ""
    +# PROP Scc_LocalPath ""
    +CPP=cl.exe
    +
    +!IF  "$(CFG)" == "ap - 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 Target_Dir ""
    +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
    +# ADD CPP /nologo /MD /W3 /GX /O2 /I "../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /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)" == "ap - 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 Target_Dir ""
    +# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
    +# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /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 "ap - Win32 Release"
    +# Name "ap - Win32 Debug"
    +# Begin Group "Source Files"
    +
    +# PROP Default_Filter ""
    +# 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_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 ""
    +# End Group
    +# 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_checkpass.c
    +# End Source File
    +# Begin Source File
    +
    +SOURCE=.\ap_base64.c
    +# End Source File
    +# End Target
    +# End Project
    diff --git a/APACHE_1_3_12/src/ap/ap.mak b/APACHE_1_3_12/src/ap/ap.mak
    new file mode 100644
    index 0000000000..1d7c9671df
    --- /dev/null
    +++ b/APACHE_1_3_12/src/ap/ap.mak
    @@ -0,0 +1,610 @@
    +# 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=.\Release
    +INTDIR=.\Release
    +# Begin Custom Macros
    +OutDir=.\Release
    +# End Custom Macros
    +
    +!IF "$(RECURSE)" == "0" 
    +
    +ALL : "$(OUTDIR)\ap.lib"
    +
    +!ELSE 
    +
    +ALL : "$(OUTDIR)\ap.lib"
    +
    +!ENDIF 
    +
    +CLEAN :
    +	-@erase "$(INTDIR)\ap_cpystrn.obj"
    +	-@erase "$(INTDIR)\ap_fnmatch.obj"
    +	-@erase "$(INTDIR)\ap_md5c.obj"
    +	-@erase "$(INTDIR)\ap_signal.obj"
    +	-@erase "$(INTDIR)\ap_slack.obj"
    +	-@erase "$(INTDIR)\ap_snprintf.obj"
    +	-@erase "$(INTDIR)\ap_sha1.obj"
    +	-@erase "$(INTDIR)\ap_base64.obj"
    +	-@erase "$(INTDIR)\ap_checkpass.obj"
    +	-@erase "$(INTDIR)\vc50.idb"
    +	-@erase "$(OUTDIR)\ap.lib"
    +
    +"$(OUTDIR)" :
    +    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
    +
    +CPP=cl.exe
    +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "../include" /D "WIN32" /D "NDEBUG" /D\
    + "_WINDOWS" /Fp"$(INTDIR)\ap.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c 
    +CPP_OBJS=.\Release/
    +CPP_SBRS=.
    +
    +.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) $< 
    +<<
    +
    +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_cpystrn.obj" \
    +	"$(INTDIR)\ap_fnmatch.obj" \
    +	"$(INTDIR)\ap_md5c.obj" \
    +	"$(INTDIR)\ap_signal.obj" \
    +	"$(INTDIR)\ap_slack.obj" \
    +	"$(INTDIR)\ap_snprintf.obj" \
    +	"$(INTDIR)\ap_sha1.obj" \
    +	"$(INTDIR)\ap_base64.obj" \
    +	"$(INTDIR)\ap_checkpass.obj"
    +
    +"$(OUTDIR)\ap.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS)
    +    $(LIB32) @<<
    +  $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS)
    +<<
    +
    +!ELSEIF  "$(CFG)" == "ap - Win32 Debug"
    +
    +OUTDIR=.\Debug
    +INTDIR=.\Debug
    +# Begin Custom Macros
    +OutDir=.\Debug
    +# End Custom Macros
    +
    +!IF "$(RECURSE)" == "0" 
    +
    +ALL : "$(OUTDIR)\ap.lib"
    +
    +!ELSE 
    +
    +ALL : "$(OUTDIR)\ap.lib"
    +
    +!ENDIF 
    +
    +CLEAN :
    +	-@erase "$(INTDIR)\ap_cpystrn.obj"
    +	-@erase "$(INTDIR)\ap_fnmatch.obj"
    +	-@erase "$(INTDIR)\ap_md5c.obj"
    +	-@erase "$(INTDIR)\ap_signal.obj"
    +	-@erase "$(INTDIR)\ap_slack.obj"
    +	-@erase "$(INTDIR)\ap_snprintf.obj"
    +	-@erase "$(INTDIR)\ap_sha1.obj"
    +	-@erase "$(INTDIR)\ap_base64.obj"
    +	-@erase "$(INTDIR)\ap_checkpass.obj"
    +	-@erase "$(INTDIR)\vc50.idb"
    +	-@erase "$(OUTDIR)\ap.lib"
    +
    +"$(OUTDIR)" :
    +    if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
    +
    +CPP=cl.exe
    +CPP_PROJ=/nologo /MDd /W3 /GX /Z7 /Od /I "../include" /D "WIN32" /D "_DEBUG" /D\
    + "_WINDOWS" /Fp"$(INTDIR)\ap.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c 
    +CPP_OBJS=.\Debug/
    +CPP_SBRS=.
    +
    +.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) $< 
    +<<
    +
    +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_cpystrn.obj" \
    +	"$(INTDIR)\ap_fnmatch.obj" \
    +	"$(INTDIR)\ap_md5c.obj" \
    +	"$(INTDIR)\ap_signal.obj" \
    +	"$(INTDIR)\ap_slack.obj" \
    +	"$(INTDIR)\ap_snprintf.obj" \
    +	"$(INTDIR)\ap_sha1.obj" \
    +	"$(INTDIR)\ap_base64.obj" \
    +	"$(INTDIR)\ap_checkpass.obj"
    +
    +"$(OUTDIR)\ap.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS)
    +    $(LIB32) @<<
    +  $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS)
    +<<
    +
    +!ENDIF 
    +
    +
    +!IF "$(CFG)" == "ap - Win32 Release" || "$(CFG)" == "ap - Win32 Debug"
    +SOURCE=.\ap_cpystrn.c
    +
    +!IF  "$(CFG)" == "ap - Win32 Release"
    +
    +DEP_CPP_AP_CP=\
    +	"..\include\alloc.h"\
    +	"..\include\ap.h"\
    +	"..\include\ap_config.h"\
    +	"..\include\ap_ctype.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"\
    +	{$(INCLUDE)}"sys\stat.h"\
    +	{$(INCLUDE)}"sys\types.h"\
    +
    +NODEP_CPP_AP_CP=\
    +	"..\include\ap_config_auto.h"\
    +	"..\include\ebcdic.h"\
    +	"..\include\os.h"\
    +	"..\include\sfio.h"\
    +
    +
    +"$(INTDIR)\ap_cpystrn.obj" : $(SOURCE) $(DEP_CPP_AP_CP) "$(INTDIR)"
    +
    +
    +!ELSEIF  "$(CFG)" == "ap - Win32 Debug"
    +
    +DEP_CPP_AP_CP=\
    +	"..\include\alloc.h"\
    +	"..\include\ap.h"\
    +	"..\include\ap_config.h"\
    +	"..\include\ap_ctype.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"\
    +
    +
    +"$(INTDIR)\ap_cpystrn.obj" : $(SOURCE) $(DEP_CPP_AP_CP) "$(INTDIR)"
    +
    +
    +!ENDIF 
    +
    +SOURCE=.\ap_fnmatch.c
    +
    +!IF  "$(CFG)" == "ap - Win32 Release"
    +
    +DEP_CPP_AP_FN=\
    +	"..\include\ap_config.h"\
    +	"..\include\ap_ctype.h"\
    +	"..\include\ap_mmn.h"\
    +	"..\include\fnmatch.h"\
    +	"..\include\hsregex.h"\
    +	"..\os\win32\os.h"\
    +	{$(INCLUDE)}"sys\stat.h"\
    +	{$(INCLUDE)}"sys\types.h"\
    +
    +NODEP_CPP_AP_FN=\
    +	"..\include\ap_config_auto.h"\
    +	"..\include\os.h"\
    +
    +
    +"$(INTDIR)\ap_fnmatch.obj" : $(SOURCE) $(DEP_CPP_AP_FN) "$(INTDIR)"
    +
    +
    +!ELSEIF  "$(CFG)" == "ap - Win32 Debug"
    +
    +DEP_CPP_AP_FN=\
    +	"..\include\ap_config.h"\
    +	"..\include\ap_ctype.h"\
    +	"..\include\ap_mmn.h"\
    +	"..\include\fnmatch.h"\
    +	"..\include\hsregex.h"\
    +	"..\os\win32\os.h"\
    +
    +
    +"$(INTDIR)\ap_fnmatch.obj" : $(SOURCE) $(DEP_CPP_AP_FN) "$(INTDIR)"
    +
    +
    +!ENDIF 
    +
    +SOURCE=.\ap_signal.c
    +
    +!IF  "$(CFG)" == "ap - Win32 Release"
    +
    +DEP_CPP_AP_SI=\
    +	"..\include\alloc.h"\
    +	"..\include\ap.h"\
    +	"..\include\ap_config.h"\
    +	"..\include\ap_ctype.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"\
    +	{$(INCLUDE)}"sys\stat.h"\
    +	{$(INCLUDE)}"sys\types.h"\
    +
    +NODEP_CPP_AP_SI=\
    +	"..\include\ap_config_auto.h"\
    +	"..\include\ebcdic.h"\
    +	"..\include\os.h"\
    +	"..\include\sfio.h"\
    +
    +
    +"$(INTDIR)\ap_signal.obj" : $(SOURCE) $(DEP_CPP_AP_SI) "$(INTDIR)"
    +
    +
    +!ELSEIF  "$(CFG)" == "ap - Win32 Debug"
    +
    +DEP_CPP_AP_SI=\
    +	"..\include\alloc.h"\
    +	"..\include\ap.h"\
    +	"..\include\ap_config.h"\
    +	"..\include\ap_ctype.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"\
    +
    +
    +"$(INTDIR)\ap_signal.obj" : $(SOURCE) $(DEP_CPP_AP_SI) "$(INTDIR)"
    +
    +
    +!ENDIF 
    +
    +SOURCE=.\ap_slack.c
    +
    +!IF  "$(CFG)" == "ap - Win32 Release"
    +
    +DEP_CPP_AP_SL=\
    +	"..\include\alloc.h"\
    +	"..\include\ap.h"\
    +	"..\include\ap_config.h"\
    +	"..\include\ap_ctype.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"\
    +	{$(INCLUDE)}"sys\stat.h"\
    +	{$(INCLUDE)}"sys\types.h"\
    +
    +NODEP_CPP_AP_SL=\
    +	"..\include\ap_config_auto.h"\
    +	"..\include\ebcdic.h"\
    +	"..\include\os.h"\
    +	"..\include\sfio.h"\
    +
    +
    +"$(INTDIR)\ap_slack.obj" : $(SOURCE) $(DEP_CPP_AP_SL) "$(INTDIR)"
    +
    +
    +!ELSEIF  "$(CFG)" == "ap - Win32 Debug"
    +
    +DEP_CPP_AP_SL=\
    +	"..\include\alloc.h"\
    +	"..\include\ap.h"\
    +	"..\include\ap_config.h"\
    +	"..\include\ap_ctype.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"\
    +
    +
    +"$(INTDIR)\ap_slack.obj" : $(SOURCE) $(DEP_CPP_AP_SL) "$(INTDIR)"
    +
    +
    +!ENDIF 
    +
    +SOURCE=.\ap_snprintf.c
    +
    +!IF  "$(CFG)" == "ap - Win32 Release"
    +
    +DEP_CPP_AP_SN=\
    +	"..\include\alloc.h"\
    +	"..\include\ap.h"\
    +	"..\include\ap_config.h"\
    +	"..\include\ap_ctype.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"\
    +	{$(INCLUDE)}"sys\stat.h"\
    +	{$(INCLUDE)}"sys\types.h"\
    +
    +NODEP_CPP_AP_SN=\
    +	"..\include\ap_config_auto.h"\
    +	"..\include\ebcdic.h"\
    +	"..\include\os.h"\
    +	"..\include\sfio.h"\
    +
    +
    +"$(INTDIR)\ap_snprintf.obj" : $(SOURCE) $(DEP_CPP_AP_SN) "$(INTDIR)"
    +
    +
    +!ELSEIF  "$(CFG)" == "ap - Win32 Debug"
    +
    +DEP_CPP_AP_SN=\
    +	"..\include\alloc.h"\
    +	"..\include\ap.h"\
    +	"..\include\ap_config.h"\
    +	"..\include\ap_ctype.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"\
    +
    +
    +"$(INTDIR)\ap_snprintf.obj" : $(SOURCE) $(DEP_CPP_AP_SN) "$(INTDIR)"
    +
    +
    +!ENDIF 
    +
    +SOURCE=.\ap_md5c.c
    +
    +!IF  "$(CFG)" == "ap - Win32 Release"
    +
    +DEP_CPP_AP_MD=\
    +	"..\include\ap_config.h"\
    +	"..\include\ap_ctype.h"\
    +	"..\include\ap_md5.h"\
    +	"..\include\ap_mmn.h"\
    +	"..\include\hsregex.h"\
    +	"..\os\win32\os.h"\
    +	{$(INCLUDE)}"sys\stat.h"\
    +	{$(INCLUDE)}"sys\types.h"\
    +
    +NODEP_CPP_AP_MD=\
    +	"..\include\ap_config_auto.h"\
    +	"..\include\os.h"\
    +	".\ebcdic.h"\
    +
    +
    +"$(INTDIR)\ap_md5c.obj" : $(SOURCE) $(DEP_CPP_AP_MD) "$(INTDIR)"
    +
    +
    +!ELSEIF  "$(CFG)" == "ap - Win32 Debug"
    +
    +DEP_CPP_AP_MD=\
    +	"..\include\ap_config.h"\
    +	"..\include\ap_ctype.h"\
    +	"..\include\ap_md5.h"\
    +	"..\include\ap_mmn.h"\
    +	"..\include\hsregex.h"\
    +	"..\os\win32\os.h"\
    +
    +
    +"$(INTDIR)\ap_md5c.obj" : $(SOURCE) $(DEP_CPP_AP_MD) "$(INTDIR)"
    +
    +
    +!ENDIF 
    +
    +
    +SOURCE=.\ap_checkpass.c
    +
    +!IF  "$(CFG)" == "ap - Win32 Release"
    +
    +DEP_CPP_AP_CH=\
    +	"..\include\ap_config.h"\
    +	"..\include\ap_ctype.h"\
    +	"..\include\ap_mmn.h"\
    +	"..\include\hsregex.h"\
    +	"..\os\win32\os.h"\
    +	{$(INCLUDE)}"sys\stat.h"\
    +	{$(INCLUDE)}"sys\types.h"\
    +
    +NODEP_CPP_AP_CH=\
    +	"..\include\ap_config_auto.h"\
    +	"..\include\os.h"\
    +	".\ebcdic.h"\
    +
    +
    +"$(INTDIR)\ap_checkpass.obj" : $(SOURCE) $(DEP_CPP_AP_CH) "$(INTDIR)"
    +
    +
    +!ELSEIF  "$(CFG)" == "ap - Win32 Debug"
    +
    +DEP_CPP_AP_CH=\
    +	"..\include\ap_config.h"\
    +	"..\include\ap_ctype.h"\
    +	"..\include\ap_mmn.h"\
    +	"..\include\hsregex.h"\
    +	"..\os\win32\os.h"\
    +
    +
    +"$(INTDIR)\ap_checkpass.obj" : $(SOURCE) $(DEP_CPP_AP_CH) "$(INTDIR)"
    +
    +
    +!ENDIF 
    +
    +SOURCE=.\ap_sha1.c
    +
    +!IF  "$(CFG)" == "ap - Win32 Release"
    +
    +DEP_CPP_AP_SH=\
    +	"..\include\ap_config.h"\
    +	"..\include\ap_ctype.h"\
    +	"..\include\ap_sha1.h"\
    +	"..\include\ap_mmn.h"\
    +	"..\include\hsregex.h"\
    +	"..\os\win32\os.h"\
    +	{$(INCLUDE)}"sys\stat.h"\
    +	{$(INCLUDE)}"sys\types.h"\
    +
    +NODEP_CPP_AP_SH=\
    +	"..\include\ap_config_auto.h"\
    +	"..\include\os.h"\
    +	".\ebcdic.h"\
    +
    +
    +"$(INTDIR)\ap_sha1.obj" : $(SOURCE) $(DEP_CPP_AP_SH) "$(INTDIR)"
    +
    +
    +!ELSEIF  "$(CFG)" == "ap - Win32 Debug"
    +
    +DEP_CPP_AP_SH=\
    +	"..\include\ap_config.h"\
    +	"..\include\ap_ctype.h"\
    +	"..\include\ap_sha1.h"\
    +	"..\include\ap_mmn.h"\
    +	"..\include\hsregex.h"\
    +	"..\os\win32\os.h"\
    +
    +
    +"$(INTDIR)\ap_sha1.obj" : $(SOURCE) $(DEP_CPP_AP_SH) "$(INTDIR)"
    +
    +
    +!ENDIF 
    +
    +SOURCE=.\ap_base64.c
    +
    +!IF  "$(CFG)" == "ap - Win32 Release"
    +
    +DEP_CPP_AP_BA=\
    +	"..\include\ap_config.h"\
    +	"..\include\ap_ctype.h"\
    +	"..\include\ap_mmn.h"\
    +	"..\include\hsregex.h"\
    +	"..\os\win32\os.h"\
    +	{$(INCLUDE)}"sys\stat.h"\
    +	{$(INCLUDE)}"sys\types.h"\
    +
    +NODEP_CPP_AP_BA=\
    +	"..\include\ap_config_auto.h"\
    +	"..\include\os.h"\
    +	".\ebcdic.h"\
    +
    +
    +"$(INTDIR)\ap_base64.obj" : $(SOURCE) $(DEP_CPP_AP_BA) "$(INTDIR)"
    +
    +
    +!ELSEIF  "$(CFG)" == "ap - Win32 Debug"
    +
    +DEP_CPP_AP_BA=\
    +	"..\include\ap_config.h"\
    +	"..\include\ap_ctype.h"\
    +	"..\include\ap_mmn.h"\
    +	"..\include\hsregex.h"\
    +	"..\os\win32\os.h"\
    +
    +
    +"$(INTDIR)\ap_base64.obj" : $(SOURCE) $(DEP_CPP_AP_BA) "$(INTDIR)"
    +
    +
    +!ENDIF 
    +
    +!ENDIF 
    +
    diff --git a/APACHE_1_3_12/src/ap/ap_base64.c b/APACHE_1_3_12/src/ap/ap_base64.c
    new file mode 100644
    index 0000000000..82497d3f6f
    --- /dev/null
    +++ b/APACHE_1_3_12/src/ap/ap_base64.c
    @@ -0,0 +1,272 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +
    +/* 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 "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_12/src/ap/ap_checkpass.c b/APACHE_1_3_12/src/ap/ap_checkpass.c
    new file mode 100644
    index 0000000000..a4a597e2f1
    --- /dev/null
    +++ b/APACHE_1_3_12/src/ap/ap_checkpass.c
    @@ -0,0 +1,111 @@
    +/* ====================================================================
    + * Copyright (c) 1996-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + * 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_12/src/ap/ap_cpystrn.c b/APACHE_1_3_12/src/ap/ap_cpystrn.c
    new file mode 100644
    index 0000000000..a9813f4005
    --- /dev/null
    +++ b/APACHE_1_3_12/src/ap/ap_cpystrn.c
    @@ -0,0 +1,93 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +
    +#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_12/src/ap/ap_execve.c b/APACHE_1_3_12/src/ap/ap_execve.c
    new file mode 100644
    index 0000000000..346ce13466
    --- /dev/null
    +++ b/APACHE_1_3_12/src/ap/ap_execve.c
    @@ -0,0 +1,390 @@
    +/* ====================================================================
    + * Copyright (c) 1998-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +
    +/*
    + * 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_12/src/ap/ap_fnmatch.c b/APACHE_1_3_12/src/ap/ap_fnmatch.c
    new file mode 100644
    index 0000000000..e164167144
    --- /dev/null
    +++ b/APACHE_1_3_12/src/ap/ap_fnmatch.c
    @@ -0,0 +1,238 @@
    +/*
    + * 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_12/src/ap/ap_getpass.c b/APACHE_1_3_12/src/ap/ap_getpass.c
    new file mode 100644
    index 0000000000..0cd59f4c34
    --- /dev/null
    +++ b/APACHE_1_3_12/src/ap/ap_getpass.c
    @@ -0,0 +1,196 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +/*
    + * 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)
    +#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_12/src/ap/ap_md5c.c b/APACHE_1_3_12/src/ap/ap_md5c.c
    new file mode 100644
    index 0000000000..18e67ff022
    --- /dev/null
    +++ b/APACHE_1_3_12/src/ap/ap_md5c.c
    @@ -0,0 +1,583 @@
    +/*
    + * 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.
    + */
    +
    +/* ====================================================================
    + * Copyright (c) 1996-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +
    +/*
    + * 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 "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_12/src/ap/ap_sha1.c b/APACHE_1_3_12/src/ap/ap_sha1.c
    new file mode 100644
    index 0000000000..1658c3ff65
    --- /dev/null
    +++ b/APACHE_1_3_12/src/ap/ap_sha1.c
    @@ -0,0 +1,383 @@
    +/* ====================================================================
    + * Copyright (c) 1996-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + * 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 "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_12/src/ap/ap_signal.c b/APACHE_1_3_12/src/ap/ap_signal.c
    new file mode 100644
    index 0000000000..5420d5061b
    --- /dev/null
    +++ b/APACHE_1_3_12/src/ap/ap_signal.c
    @@ -0,0 +1,83 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +
    +#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_12/src/ap/ap_slack.c b/APACHE_1_3_12/src/ap/ap_slack.c
    new file mode 100644
    index 0000000000..4fff5e05c8
    --- /dev/null
    +++ b/APACHE_1_3_12/src/ap/ap_slack.c
    @@ -0,0 +1,116 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +
    +/*
    + * 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_12/src/ap/ap_snprintf.c b/APACHE_1_3_12/src/ap/ap_snprintf.c
    new file mode 100644
    index 0000000000..a50c4af380
    --- /dev/null
    +++ b/APACHE_1_3_12/src/ap/ap_snprintf.c
    @@ -0,0 +1,1186 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + * 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>
    +
    +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.c - IEEE floating point formatting routines for FreeBSD
    + * from GNU libc-4.6.27.  Modified to be thread safe.
    + */
    +
    +/*
    + *    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 (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.
    + */
    +#define FIX_PRECISION( adjust, precision, s, s_len )	\
    +    if ( adjust )					\
    +	while ( s_len < precision )			\
    +	{						\
    +	    *--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
    +		 *
    +		 * XXX: an unreasonable amount of precision may be specified
    +		 * resulting in overflow of num_buf. Currently we
    +		 * ignore this possibility.
    +		 */
    +		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
    +		 */
    +		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(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_12/src/buildmark.c b/APACHE_1_3_12/src/buildmark.c
    new file mode 100644
    index 0000000000..575b9731a0
    --- /dev/null
    +++ b/APACHE_1_3_12/src/buildmark.c
    @@ -0,0 +1,70 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +
    +#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()
    +{
    +    return server_built;
    +}
    diff --git a/APACHE_1_3_12/src/helpers/CutRule b/APACHE_1_3_12/src/helpers/CutRule
    new file mode 100755
    index 0000000000..ca4b1f8eab
    --- /dev/null
    +++ b/APACHE_1_3_12/src/helpers/CutRule
    @@ -0,0 +1,8 @@
    +#!/bin/sh
    +# 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_12/src/helpers/GuessCodeset b/APACHE_1_3_12/src/helpers/GuessCodeset
    new file mode 100755
    index 0000000000..b761efb315
    --- /dev/null
    +++ b/APACHE_1_3_12/src/helpers/GuessCodeset
    @@ -0,0 +1,15 @@
    +#!/bin/sh
    +# 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_12/src/helpers/GuessOS b/APACHE_1_3_12/src/helpers/GuessOS
    new file mode 100755
    index 0000000000..5ac4552a01
    --- /dev/null
    +++ b/APACHE_1_3_12/src/helpers/GuessOS
    @@ -0,0 +1,340 @@
    +#!/bin/sh
    +#
    +# 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 handling other OSes.  This
    +# is being done because TPF is sometimes compiled
    +# on OS/390.  When that is the case, if we don't
    +# handle TPF ahead of the other OSes, TPF will
    +# fall into the OS/390 case and this script would
    +# return an incorrect value for the platform.
    +#
    +# Apache is not compiled on the TPF platform
    +# therefore an environment variable is used
    +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"
    +
    +
    +# 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
    +			;;
    +		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-9].*)
    +	echo "${MACHINE}-whatever-linux2"; exit 0
    +	;;
    +
    +    Linux:1.*)
    +	echo "${MACHINE}-whatever-linux1"; 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:*)
    +	echo "${MACHINE}-whatever-openbsd"; 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;
    +	;;
    +
    +    Rhapsody:*:*:*)
    +	case "${MACHINE}" in
    +	    Power*) MACHINE=powerpc ;;
    +	esac
    +	echo "${MACHINE}-apple-rhapsody${RELEASE}"; exit 0
    +	;;
    +
    +    "Mac OS":*:*:*)
    +	MACHINE=`uname -p`
    +	echo "${MACHINE}-apple-macos${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;
    +        ;;
    +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_12/src/helpers/MakeEtags b/APACHE_1_3_12/src/helpers/MakeEtags
    new file mode 100755
    index 0000000000..25f6bdab17
    --- /dev/null
    +++ b/APACHE_1_3_12/src/helpers/MakeEtags
    @@ -0,0 +1,39 @@
    +#!/bin/sh
    +
    +# 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_12/src/helpers/MakeLint b/APACHE_1_3_12/src/helpers/MakeLint
    new file mode 100644
    index 0000000000..4ab6bba1c4
    --- /dev/null
    +++ b/APACHE_1_3_12/src/helpers/MakeLint
    @@ -0,0 +1,31 @@
    +#!perl
    +
    +# 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_12/src/helpers/PrintPath b/APACHE_1_3_12/src/helpers/PrintPath
    new file mode 100755
    index 0000000000..908d274008
    --- /dev/null
    +++ b/APACHE_1_3_12/src/helpers/PrintPath
    @@ -0,0 +1,105 @@
    +#!/bin/sh
    +# 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_12/src/helpers/TestCompile b/APACHE_1_3_12/src/helpers/TestCompile
    new file mode 100755
    index 0000000000..034c613ae5
    --- /dev/null
    +++ b/APACHE_1_3_12/src/helpers/TestCompile
    @@ -0,0 +1,232 @@
    +#!/bin/sh
    +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'
    +#
    +# 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 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>
    +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>
    +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
    +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
    +#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_12/src/helpers/binbuild.sh b/APACHE_1_3_12/src/helpers/binbuild.sh
    new file mode 100755
    index 0000000000..1e2f454ff0
    --- /dev/null
    +++ b/APACHE_1_3_12/src/helpers/binbuild.sh
    @@ -0,0 +1,300 @@
    +#!/bin/sh
    +#
    +# binbuild.sh - Builds an Apache binary distribution.
    +# Initially written by Lars Eilebrecht <lars@apache.org>.
    +#
    +# This script falls under the Apache License.
    +# See http://www.apache.org/docs/LICENSE
    +
    +OS=`src/helpers/GuessOS`
    +case "x$OS" in
    +  x*390*) CONFIGPARAM="--with-layout=BinaryDistribution --enable-module=most";;
    +      *) 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 \"comp.infosystems.www.servers.unix\"" && \
    +  echo "      or \"comp.infosystems.www.servers.ms-windows\" newsgroup" && \
    +  echo "      (as appropriate for the platform you use), where some of the" && \
    +  echo "      Apache team lurk, in the company of many other Apache gurus" && \
    +  echo "      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://www.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 644" && \
    +  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*390*) $TAR -cfU ../apache_$VER-$OS.tar -C .. apache_$VER;;
    +	    *) $TAR -cf ../apache_$VER-$OS.tar -C .. 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_12/src/helpers/buildinfo.sh b/APACHE_1_3_12/src/helpers/buildinfo.sh
    new file mode 100755
    index 0000000000..5c2a72d6b3
    --- /dev/null
    +++ b/APACHE_1_3_12/src/helpers/buildinfo.sh
    @@ -0,0 +1,160 @@
    +#!/bin/sh
    +##
    +##  buildinfo.sh -- Determine Build Information
    +##  Initially written by Ralf S. Engelschall <rse@apache.org>
    +##  for the Apache's Autoconf-style Interface (APACI) 
    +##
    +#
    +# This script falls under the Apache License.
    +# See http://www.apache.org/docs/LICENSE
    +
    +
    +#
    +#   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_12/src/helpers/checkheader.sh b/APACHE_1_3_12/src/helpers/checkheader.sh
    new file mode 100755
    index 0000000000..26cd176c68
    --- /dev/null
    +++ b/APACHE_1_3_12/src/helpers/checkheader.sh
    @@ -0,0 +1,35 @@
    +#!/bin/sh
    +##
    +##  checkheader.sh -- Check whether a C header file exists
    +##  Initially written by Ralf S. Engelschall for the Apache
    +##   configuration mechanism
    +##
    +#
    +# This script falls under the Apache License.
    +# See http://www.apache.org/docs/LICENSE
    +
    +
    +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_12/src/helpers/dummy.c b/APACHE_1_3_12/src/helpers/dummy.c
    new file mode 100644
    index 0000000000..cf938b8402
    --- /dev/null
    +++ b/APACHE_1_3_12/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_12/src/helpers/find-dbm-lib b/APACHE_1_3_12/src/helpers/find-dbm-lib
    new file mode 100644
    index 0000000000..3792d9301e
    --- /dev/null
    +++ b/APACHE_1_3_12/src/helpers/find-dbm-lib
    @@ -0,0 +1,54 @@
    +# 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 dbm dbm_open; then
    +		    DBM_LIB="-ldbm"
    +		elif ./helpers/TestCompile lib ndbm dbm_open; then
    +		    DBM_LIB="-lndbm"
    +		fi
    +		if [ "x$DBM_LIB" != "x" ]; then
    +		    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_12/src/helpers/findcpp.sh b/APACHE_1_3_12/src/helpers/findcpp.sh
    new file mode 100755
    index 0000000000..a870f7371a
    --- /dev/null
    +++ b/APACHE_1_3_12/src/helpers/findcpp.sh
    @@ -0,0 +1,73 @@
    +#!/bin/sh
    +##
    +##  findcpp.sh -- Find out how to _directly_ run the C Pre-Processor (CPP)
    +##  Initially written by Ralf S. Engelschall for the Apache configuration
    +##   mechanism
    +##
    +#
    +# This script falls under the Apache License.
    +# See http://www.apache.org/docs/LICENSE
    +
    +
    +#   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_12/src/helpers/fmn.sh b/APACHE_1_3_12/src/helpers/fmn.sh
    new file mode 100755
    index 0000000000..2900499da9
    --- /dev/null
    +++ b/APACHE_1_3_12/src/helpers/fmn.sh
    @@ -0,0 +1,49 @@
    +#!/bin/sh
    +##
    +##  fmn.sh -- find a modules (structure) name
    +##
    +##  Extracted from the Configure script for use with
    +##  Apache's Autoconf-style Interface (APACI).
    +##
    +#
    +# This script falls under the Apache License.
    +# See http://www.apache.org/docs/LICENSE
    +
    +
    +#   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_12/src/helpers/fp2rp b/APACHE_1_3_12/src/helpers/fp2rp
    new file mode 100755
    index 0000000000..68d5adb6d1
    --- /dev/null
    +++ b/APACHE_1_3_12/src/helpers/fp2rp
    @@ -0,0 +1,13 @@
    +#!/bin/sh
    +##
    +## 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_12/src/helpers/getuid.sh b/APACHE_1_3_12/src/helpers/getuid.sh
    new file mode 100755
    index 0000000000..42cdf0d6e5
    --- /dev/null
    +++ b/APACHE_1_3_12/src/helpers/getuid.sh
    @@ -0,0 +1,65 @@
    +#!/bin/sh
    +# 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
    +#
    +# This script falls under the Apache License.
    +# See http://www.apache.org/docs/LICENSE
    +
    +# 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_12/src/helpers/install.sh b/APACHE_1_3_12/src/helpers/install.sh
    new file mode 100755
    index 0000000000..f0d2a14e95
    --- /dev/null
    +++ b/APACHE_1_3_12/src/helpers/install.sh
    @@ -0,0 +1,112 @@
    +#!/bin/sh
    +##
    +##  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>
    +##
    +#
    +# This script falls under the Apache License.
    +# See http://www.apache.org/docs/LICENSE
    +
    +
    +#
    +#   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
    +
    +#  Add a possible extension (such as ".exe") to src and dst
    +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_12/src/helpers/mfhead b/APACHE_1_3_12/src/helpers/mfhead
    new file mode 100755
    index 0000000000..277c396246
    --- /dev/null
    +++ b/APACHE_1_3_12/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_12/src/helpers/mkdir.sh b/APACHE_1_3_12/src/helpers/mkdir.sh
    new file mode 100755
    index 0000000000..4cd33c5671
    --- /dev/null
    +++ b/APACHE_1_3_12/src/helpers/mkdir.sh
    @@ -0,0 +1,35 @@
    +#!/bin/sh
    +## 
    +##  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>
    +##
    +#
    +# This script falls under the Apache License.
    +# See http://www.apache.org/docs/LICENSE
    +
    +
    +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_12/src/helpers/mkshadow.sh b/APACHE_1_3_12/src/helpers/mkshadow.sh
    new file mode 100755
    index 0000000000..00b0e3a2a4
    --- /dev/null
    +++ b/APACHE_1_3_12/src/helpers/mkshadow.sh
    @@ -0,0 +1,110 @@
    +#!/bin/sh
    +##
    +##  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) 
    +##
    +#
    +# This script falls under the Apache License.
    +# See http://www.apache.org/docs/LICENSE
    +
    +
    +#   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_12/src/helpers/ppl.sh b/APACHE_1_3_12/src/helpers/ppl.sh
    new file mode 100755
    index 0000000000..e83ab4793f
    --- /dev/null
    +++ b/APACHE_1_3_12/src/helpers/ppl.sh
    @@ -0,0 +1,55 @@
    +#!/bin/sh
    +##
    +##  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)
    +##
    +#
    +# This script falls under the Apache License.
    +# See http://www.apache.org/docs/LICENSE
    +
    +
    +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_12/src/helpers/slo.sh b/APACHE_1_3_12/src/helpers/slo.sh
    new file mode 100755
    index 0000000000..e9d0e58813
    --- /dev/null
    +++ b/APACHE_1_3_12/src/helpers/slo.sh
    @@ -0,0 +1,178 @@
    +#!/bin/sh
    +##
    +##  slo.h -- (S)eparate (L)inker (O)ptions by library class
    +##  Initially written by Ralf S. Engelschall <rse@apache.org>
    +##
    +#
    +# This script falls under the Apache License.
    +# See http://www.apache.org/docs/LICENSE
    +
    +
    +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_12/src/include/.cvsignore b/APACHE_1_3_12/src/include/.cvsignore
    new file mode 100644
    index 0000000000..49eae948bd
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/.cvsignore
    @@ -0,0 +1 @@
    +ap_config_auto.h
    diff --git a/APACHE_1_3_12/src/include/.indent.pro b/APACHE_1_3_12/src/include/.indent.pro
    new file mode 100644
    index 0000000000..a9fbe9f9a1
    --- /dev/null
    +++ b/APACHE_1_3_12/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_12/src/include/alloc.h b/APACHE_1_3_12/src/include/alloc.h
    new file mode 100644
    index 0000000000..cec503ee67
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/alloc.h
    @@ -0,0 +1,405 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +
    +#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 "../os/win32/readdir.h"
    +#endif
    +
    +typedef struct pool pool;
    +typedef struct pool ap_pool;
    +
    +pool * ap_init_alloc(void);		/* Set up everything */
    +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(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...
    + */
    +
    +API_EXPORT(void) ap_register_cleanup(pool *p, void *data,
    +				  void (*plain_cleanup) (void *),
    +				  void (*child_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...
    + */
    +
    +#ifdef TPF
    +#define ap_block_alarms() (0)
    +#define ap_unblock_alarms() (0)
    +#else
    +API_EXPORT(void) ap_block_alarms(void);
    +API_EXPORT(void) ap_unblock_alarms(void);
    +#endif /* TPF */
    +
    +/* 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(void) ap_note_cleanups_for_file(pool *, FILE *);
    +API_EXPORT(void) ap_note_cleanups_for_fd(pool *, 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_kill_cleanups_for_socket(pool *p, int sock);
    +API_EXPORT(int) ap_psocket(pool *p, 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);
    +
    +/* 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_12/src/include/ap.h b/APACHE_1_3_12/src/include/ap.h
    new file mode 100644
    index 0000000000..da284cb4f3
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/ap.h
    @@ -0,0 +1,192 @@
    +/* ====================================================================
    + * Copyright (c) 1998-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + * 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);
    +
    +/* 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.
    + *
    + * In no event does ap_snprintf return a negative number.  It's not possible
    + * to distinguish between an output which was truncated, and an output which
    + * exactly filled the buffer.
    + */
    +API_EXPORT(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_12/src/include/ap_compat.h b/APACHE_1_3_12/src/include/ap_compat.h
    new file mode 100644
    index 0000000000..ec0c753bca
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/ap_compat.h
    @@ -0,0 +1,428 @@
    +/*
    +**  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_12/src/include/ap_config.h b/APACHE_1_3_12/src/include/ap_config.h
    new file mode 100644
    index 0000000000..f60be1c3b5
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/ap_config.h
    @@ -0,0 +1,1444 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +
    +#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)
    +#include "ap_config_auto.h"
    +#else
    +/* not available under WIN32, so provide important entries manually */
    +#undef HAVE_UNISTD_H
    +#endif
    +
    +/* Have to include sys/stat.h before ../os/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
    +
    +#ifdef WIN32
    +#include "../os/win32/os.h"
    +#else
    +#include "os.h"
    +#endif
    +
    +/* 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 USE_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
    +#define SHM_R 0400  /* Read permission */
    +#define SHM_W 0200  /* 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
    +
    +#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 USE_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)
    +#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
    +
    +#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
    +#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
    +
    +#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(HPUX) || defined(HPUX10)
    +#undef HAVE_GMTOFF
    +#define NO_KILLPG
    +#undef NO_SETSID
    +#define USE_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(HPUX11)
    +#ifndef _HPUX_SOURCE
    +#define _HPUX_SOURCE
    +#endif
    +#define HAVE_SHMGET
    +#define USE_SHMGET_SCOREBOARD
    +#undef  HAVE_GMTOFF
    +#define USE_FCNTL_SERIALIZED_ACCEPT
    +/* feeling brave?  want to try using POSIX mutexes? */
    +/* #define HAVE_MMAP */
    +/* #define USE_MMAP_SCOREBOARD */
    +/* #define USE_MMAP_FILES */
    +/* #define USE_PTHREAD_SERIALIZED_ACCEPT */
    +#define NO_KILLPG
    +#undef  NO_SETSID
    +#define HAVE_SYSLOG
    +
    +#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 USE_FCNTL_SERIALIZED_ACCEPT
    +#ifdef USEBCOPY
    +#define memmove(a,b,c) bcopy(b,a,c)
    +#endif
    +#if AIX >= 42
    +#define NET_SIZE_T size_t
    +#endif
    +
    +#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 USE_FLOCK_SERIALIZED_ACCEPT
    +#define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
    +
    +#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 USE_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(MAC_OS) || defined(MAC_OS_X_SERVER) /* Mac OS (>= 10.0) and Mac OS X Server (<= 5.x) */
    +#undef PLATFORM
    +#ifdef MAC_OS_X_SERVER
    +#define PLATFORM "Mac OS X Server"
    +#else
    +#define PLATFORM "Mac OS"
    +#endif
    +#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 USE_FLOCK_SERIALIZED_ACCEPT
    +#define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
    +/*
    + * If you are using APACI, (you probably should be on Mac OS) these
    + * values are set at configure time.
    + */
    +#ifndef HTTPD_ROOT
    +#define HTTPD_ROOT              "/Local/Library/WebServer"
    +#endif
    +#ifndef DOCUMENT_LOCATION
    +#define DOCUMENT_LOCATION       HTTPD_ROOT "/Documents"
    +#endif
    +#ifndef DEFAULT_XFERLOG
    +#define DEFAULT_XFERLOG         "Logs/Access"
    +#endif
    +#ifndef DEFAULT_ERRORLOG
    +#define DEFAULT_ERRORLOG        "Logs/Errors"
    +#endif
    +#ifndef DEFAULT_PIDLOG
    +#define DEFAULT_PIDLOG          "Logs/Process"
    +#endif
    +#ifndef DEFAULT_SCOREBOARD
    +#define DEFAULT_SCOREBOARD      "Logs/Status"
    +#endif
    +#ifndef DEFAULT_LOCKFILE
    +#define DEFAULT_LOCKFILE        "Logs/Lock"
    +#endif
    +#ifndef SERVER_CONFIG_FILE
    +#define SERVER_CONFIG_FILE      "Configuration/Server"
    +#endif
    +#ifndef RESOURCE_CONFIG_FILE
    +#define RESOURCE_CONFIG_FILE    "Configuration/Resources"
    +#endif
    +#ifndef TYPES_CONFIG_FILE
    +#define TYPES_CONFIG_FILE       "Configuration/MIME"
    +#endif
    +#ifndef ACCESS_CONFIG_FILE
    +#define ACCESS_CONFIG_FILE      "Configuration/Access"
    +#endif
    +#ifndef DEFAULT_USER_DIR
    +#define DEFAULT_USER_DIR        "Library/Web Documents"
    +#endif
    +#ifndef DEFAULT_USER
    +#define DEFAULT_USER            "www"
    +#endif
    +#ifndef DEFAULT_GROUP
    +#define DEFAULT_GROUP           "www"
    +#endif
    +#ifndef DEFAULT_PATH
    +#define DEFAULT_PATH            "/bin:/usr/bin:/usr/local/bin"
    +#endif
    +
    +#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
    +
    +/* flock is faster ... but hasn't been tested on 1.x systems */
    +/* PR#3531 indicates flock() may not be stable, probably depends on
    + * kernel version.  Go back to using fcntl, but provide a way for
    + * folks to tweak their Configuration to get flock.
    + */
    +#ifndef USE_FLOCK_SERIALIZED_ACCEPT
    +#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
    +
    +#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(SCO5)
    +
    +#define USE_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 USE_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 */
    +#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> */
    +#undef NEED_STRCASECMP
    +#undef NEED_STRNCASECMP
    +#undef bzero
    +#endif /*_OSD_POSIX*/
    +
    +#elif defined(UW)
    +#if UW < 700
    +#define USE_FCNTL_SERIALIZED_ACCEPT
    +#define NO_LINGCLOSE
    +#define NO_KILLPG
    +#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 USE_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 USE_FLOCK_SERIALIZED_ACCEPT
    +#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 USE_FLOCK_SERIALIZED_ACCEPT
    +#define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
    +#define HAVE_SYSLOG 1
    +#define SYS_SIGLIST sys_siglist
    +
    +#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 USE_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 USE_FCNTL_SERIALIZED_ACCEPT
    +#undef USE_FLOCK_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 USE_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 USE_OS2SEM_SERIALIZED_ACCEPT
    +#define SINGLE_LISTEN_UNSERIALIZED_ACCEPT
    +#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 USE_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 USE_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 USE_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)
    +#include <stddef.h>
    +
    +#define NO_WRITEV
    +#define NO_KILLPG
    +#define NEED_INITGROUPS
    +
    +#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 */
    +
    +#include <tpfeq.h>
    +#include <tpfio.h>
    +#include <sysapi.h>
    +#include <sysgtime.h>
    +#define PRIMECRAS 0x010000
    +#define JMP_BUF jmp_buf
    +#define HAVE_SHMGET
    +#undef  HAVE_SYS_RESOURCE_H
    +#define NEED_INITGROUPS
    +#define NEED_SIGNAL_INTERRUPT
    +#include <strings.h>
    +#ifndef __strings_h
    +#define NEED_STRCASECMP
    +#define NEED_STRNCASECMP
    +#endif
    +#define NEED_STRDUP
    +#define NO_DBM_REWRITEMAP
    +#define NO_GETTIMEOFDAY
    +#define NO_KILLPG
    +#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
    +#define NO_USE_SIGACTION
    +#define USE_LONGJMP
    +/*#define USE_SHMGET_SCOREBOARD*/
    +#define USE_TPF_ACCEPT
    +#define USE_TPF_CORE_SERIALIZED_ACCEPT
    +/*#define USE_TPF_DAEMON*/
    +#define USE_TPF_SCOREBOARD
    +#define USE_TPF_SELECT
    +#define S_IREAD S_IRUSR
    +#define S_IWRITE S_IWUSR
    +#define S_IEXEC S_IXUSR
    +#define crypt(buf,salt) ((char *)buf)
    +#undef  offsetof
    +#define offsetof(s_type,field) ((size_t)&(((s_type*)0)->field))
    +
    +#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 USE_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
    +
    +#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 Mac OS X Server, 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(MAC_OS) || defined(MAC_OS_X_SERVER)) && 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(TPF) && !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 TPF
    +#include <netinet/in.h>
    +#endif /* TPF */
    +#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(TPF)
    +#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(TPF) && defined(NSIG)
    +#undef NSIG
    +#endif
    +#include <errno.h>
    +#if !defined(QNX) && !defined(CONVEXOS11) && !defined(NEXT) && !defined(TPF) && !defined(NETWARE)
    +#include <memory.h>
    +#endif
    +
    +#ifdef NEED_PROCESS_H
    +#include <process.h>
    +#endif
    +
    +#ifdef WIN32
    +#include "../include/hsregex.h"
    +#elif 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
    +
    +#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)
    +#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 */
    +
    +#ifdef offsetof
    +#define XtOffsetOf(s_type,field) offsetof(s_type,field)
    +#else
    +#define XtOffsetOf(s_type,field) XtOffset(s_type*,field)
    +#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 *);
    +
    +long 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_12/src/include/ap_ctype.h b/APACHE_1_3_12/src/include/ap_ctype.h
    new file mode 100644
    index 0000000000..e0a6abcaa0
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/ap_ctype.h
    @@ -0,0 +1,90 @@
    +/* ====================================================================
    + * Copyright (c) 1998-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +
    +#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_12/src/include/ap_md5.h b/APACHE_1_3_12/src/include/ap_md5.h
    new file mode 100644
    index 0000000000..3ed74af15e
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/ap_md5.h
    @@ -0,0 +1,130 @@
    +/*
    + * 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.
    + */
    +
    +/* ====================================================================
    + * Copyright (c) 1996-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +
    +#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_12/src/include/ap_mmn.h b/APACHE_1_3_12/src/include/ap_mmn.h
    new file mode 100644
    index 0000000000..2cbef1d12a
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/ap_mmn.h
    @@ -0,0 +1,257 @@
    +/* ====================================================================
    + * Copyright (c) 1998-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +
    +#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()
    + */
    +
    +#define MODULE_MAGIC_COOKIE 0x41503133UL /* "AP13" */
    +
    +#ifndef MODULE_MAGIC_NUMBER_MAJOR
    +#define MODULE_MAGIC_NUMBER_MAJOR 19990320
    +#endif
    +#define MODULE_MAGIC_NUMBER_MINOR 7                     /* 0...n */
    +#define MODULE_MAGIC_NUMBER MODULE_MAGIC_NUMBER_MAJOR	/* backward compat */
    +
    +/* Useful for testing for features. */
    +#define 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 MODULE_MAGIC_AT_LEAST(19980812,2)
    +    ... use ap_overlap_tables()
    +#else
    +    ... alternative code which doesn't use ap_overlap_tables()
    +#endif
    +
    +*/
    +
    +#endif /* !APACHE_AP_MMN_H */
    diff --git a/APACHE_1_3_12/src/include/ap_sha1.h b/APACHE_1_3_12/src/include/ap_sha1.h
    new file mode 100644
    index 0000000000..42a4f5788b
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/ap_sha1.h
    @@ -0,0 +1,102 @@
    +/* ====================================================================
    + * Copyright (c) 1996-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + * 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_12/src/include/buff.h b/APACHE_1_3_12/src/include/buff.h
    new file mode 100644
    index 0000000000..27ccd1537b
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/buff.h
    @@ -0,0 +1,236 @@
    +/* ====================================================================
    + * Copyright (c) 1996-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +
    +#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
    +};
    +
    +#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(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);
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif	/* !APACHE_BUFF_H */
    diff --git a/APACHE_1_3_12/src/include/compat.h b/APACHE_1_3_12/src/include/compat.h
    new file mode 100644
    index 0000000000..7b0f193120
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/compat.h
    @@ -0,0 +1,9 @@
    +/*
    + *  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_12/src/include/conf.h b/APACHE_1_3_12/src/include/conf.h
    new file mode 100644
    index 0000000000..493365a21f
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/conf.h
    @@ -0,0 +1,9 @@
    +/*
    + *  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_12/src/include/explain.h b/APACHE_1_3_12/src/include/explain.h
    new file mode 100644
    index 0000000000..217e999b9f
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/explain.h
    @@ -0,0 +1,44 @@
    +
    +#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_12/src/include/fnmatch.h b/APACHE_1_3_12/src/include/fnmatch.h
    new file mode 100644
    index 0000000000..d4fecf6504
    --- /dev/null
    +++ b/APACHE_1_3_12/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_12/src/include/hsregex.h b/APACHE_1_3_12/src/include/hsregex.h
    new file mode 100644
    index 0000000000..1d76e5b41d
    --- /dev/null
    +++ b/APACHE_1_3_12/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)
    +#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_12/src/include/http_conf_globals.h b/APACHE_1_3_12/src/include/http_conf_globals.h
    new file mode 100644
    index 0000000000..e97e0356e1
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/http_conf_globals.h
    @@ -0,0 +1,125 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +
    +#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 int ap_standalone;
    +extern int ap_configtestonly;
    +extern int ap_docrootcheck;
    +extern uid_t ap_user_id;
    +extern char *ap_user_name;
    +extern 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 int ap_max_requests_per_child;
    +extern int ap_threads_per_child;
    +extern int ap_excess_requests_per_child;
    +extern struct in_addr ap_bind_address;
    +extern listen_rec *ap_listeners;
    +extern int ap_daemons_to_start;
    +extern int ap_daemons_min_free;
    +extern int ap_daemons_max_free;
    +extern int ap_daemons_limit;
    +extern MODULE_VAR_EXPORT int ap_suexec_enabled;
    +extern int ap_listenbacklog;
    +extern int ap_dump_settings;
    +extern API_VAR_EXPORT int ap_extended_status;
    +
    +extern char *ap_pid_fname;
    +extern char *ap_scoreboard_fname;
    +extern char *ap_lock_fname;
    +extern MODULE_VAR_EXPORT char *ap_server_argv0;
    +
    +extern enum server_token_type ap_server_tokens;
    +
    +/* 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 char ap_server_confname[MAX_STRING_LEN];
    +
    +/* for -C, -c and -D switches */
    +extern array_header *ap_server_pre_read_config;
    +extern array_header *ap_server_post_read_config;
    +extern 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 char ap_coredump_dir[MAX_STRING_LEN];
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif	/* !APACHE_HTTP_CONF_GLOBALS_H */
    diff --git a/APACHE_1_3_12/src/include/http_config.h b/APACHE_1_3_12/src/include/http_config.h
    new file mode 100644
    index 0000000000..e0c29306f8
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/http_config.h
    @@ -0,0 +1,414 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +
    +#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... */
    +
    +void ap_single_module_configure(pool *p, server_rec *s, module *m);
    +
    +/* For http_main.c... */
    +
    +server_rec *ap_read_config(pool *conf_pool, pool *temp_pool, char *config_name);
    +void ap_init_modules(pool *p, server_rec *s);
    +void ap_child_init_modules(pool *p, server_rec *s);
    +void ap_child_exit_modules(pool *p, server_rec *s);
    +void ap_setup_prelinked_modules(void);
    +void ap_show_directives(void);
    +void ap_show_modules(void);
    +
    +/* For http_request.c... */
    +
    +void *ap_create_request_config(pool *p);
    +CORE_EXPORT(void *) ap_create_per_dir_config(pool *p);
    +void *ap_merge_per_dir_configs(pool *p, void *base, void *new);
    +
    +/* For http_core.c... (<Directory> command and virtual hosts) */
    +
    +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 **);
    +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 */
    +
    +int ap_translate_name(request_rec *);
    +int ap_check_access(request_rec *);	/* check access on non-auth basis */
    +int ap_check_user_id(request_rec *);	/* obtain valid username from client auth */
    +int ap_check_auth(request_rec *);	/* check (validated) user is authorized here */
    +int ap_find_types(request_rec *);	/* identify MIME type */
    +int ap_run_fixups(request_rec *);	/* poke around for other metainfo, etc.... */
    +int ap_invoke_handler(request_rec *);
    +int ap_log_transaction(request_rec *r);
    +int ap_header_parse(request_rec *);
    +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_12/src/include/http_core.h b/APACHE_1_3_12/src/include/http_core.h
    new file mode 100644
    index 0000000000..81cd3c8be6
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/http_core.h
    @@ -0,0 +1,319 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +
    +#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
    +
    +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);
    +
    +/* 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(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 } 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.
    + */
    +
    +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;
    +
    +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;
    +
    +    /* 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    
    +    
    +} 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;
    +} core_server_config;
    +
    +/* for http_config.c */
    +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_12/src/include/http_log.h b/APACHE_1_3_12/src/include/http_log.h
    new file mode 100644
    index 0000000000..89356bc7ff
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/http_log.h
    @@ -0,0 +1,162 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +
    +#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__
    +
    +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(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(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 *);     
    +
    +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(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_12/src/include/http_main.h b/APACHE_1_3_12/src/include/http_main.h
    new file mode 100644
    index 0000000000..a0d014de78
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/http_main.h
    @@ -0,0 +1,174 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +
    +#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.
    + */
    +
    +void ap_start_shutdown(void);
    +void ap_start_restart(int);
    +API_EXPORT(void) ap_hard_timeout(char *, request_rec *);
    +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);
    +int ap_update_child_status(int child_num, int status, request_rec *r);
    +void ap_time_process_request(int child_num, int status);
    +unsigned int ap_set_callback_and_alarm(void (*fn) (int), int x);
    +API_EXPORT(int) ap_check_alarm(void);
    +
    +#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_12/src/include/http_protocol.h b/APACHE_1_3_12/src/include/http_protocol.h
    new file mode 100644
    index 0000000000..bf6155a7ce
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/http_protocol.h
    @@ -0,0 +1,223 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +
    +#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. */
    +
    +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);
    +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.
    + */
    +
    +void ap_set_sub_req_protocol(request_rec *rnew, const request_rec *r);
    +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);
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif	/* !APACHE_HTTP_PROTOCOL_H */
    diff --git a/APACHE_1_3_12/src/include/http_request.h b/APACHE_1_3_12/src/include/http_request.h
    new file mode 100644
    index 0000000000..4d83c543d6
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/http_request.h
    @@ -0,0 +1,117 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +
    +#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 */
    +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_12/src/include/http_vhost.h b/APACHE_1_3_12/src/include/http_vhost.h
    new file mode 100644
    index 0000000000..acdb6e2f42
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/http_vhost.h
    @@ -0,0 +1,95 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +
    +#ifndef APACHE_HTTP_VHOST_H
    +#define APACHE_HTTP_VHOST_H
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +/* called before any config is read */
    +void ap_init_vhost_config(pool *p);
    +
    +/* called after the config has been read */
    +void ap_fini_vhost_config(pool *p, server_rec *main_server);
    +
    +/* handle addresses in <VirtualHost> statement */
    +const char *ap_parse_vhost_addrs(pool *p, const char *hostname, server_rec *s);
    +
    +/* handle NameVirtualHost directive */
    +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 */
    +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.
    + */
    +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_12/src/include/httpd.h b/APACHE_1_3_12/src/include/httpd.h
    new file mode 100644
    index 0000000000..ac87478488
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/httpd.h
    @@ -0,0 +1,1186 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +
    +#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 "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)
    +#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))
    +#define ap_http_method(r)	"http"
    +#define ap_default_port(r)	DEFAULT_HTTP_PORT
    +
    +/* --------- 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
    +
    +/* The name of the log files */
    +#ifndef DEFAULT_XFERLOG
    +#if defined(OS2) || defined(WIN32)
    +#define DEFAULT_XFERLOG "logs/access.log"
    +#else
    +#define DEFAULT_XFERLOG "logs/access_log"
    +#endif
    +#endif /* DEFAULT_XFERLOG */
    +
    +#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
    +
    +/* 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
    +#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_BASEVERSION "Apache/1.3.12"	/* SEE COMMENTS ABOVE */
    +#define SERVER_VERSION  SERVER_BASEVERSION
    +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 */
    +};
    +
    +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 10312100
    +
    +#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 "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;
    +    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;
    +
    +/* 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_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_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); 
    +
    +#ifdef OS2
    +void os2pathname(char *path);
    +char *ap_double_quotes(pool *p, char *str);
    +#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);
    +
    +/* 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_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);
    +#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 _OSD_POSIX
    +extern const char *os_set_account(pool *p, const char *account);
    +extern int os_init_job_environment(server_rec *s, const char *user_name, int one_process);
    +#endif /* _OSD_POSIX */
    +
    +char *ap_get_local_host(pool *);
    +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 __cplusplus
    +}
    +#endif
    +
    +#endif	/* !APACHE_HTTPD_H */
    diff --git a/APACHE_1_3_12/src/include/multithread.h b/APACHE_1_3_12/src/include/multithread.h
    new file mode 100644
    index 0000000000..901046fd08
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/multithread.h
    @@ -0,0 +1,69 @@
    +#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)	(0)
    +
    +#endif /* ndef MULTITHREAD */
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif /* !APACHE_MULTITHREAD_H */
    diff --git a/APACHE_1_3_12/src/include/rfc1413.h b/APACHE_1_3_12/src/include/rfc1413.h
    new file mode 100644
    index 0000000000..e69c9d2a14
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/rfc1413.h
    @@ -0,0 +1,71 @@
    +/* ====================================================================
    + * Copyright (c) 1996-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +
    +#ifndef APACHE_RFC1413_H
    +#define APACHE_RFC1413_H
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +extern char *ap_rfc1413(conn_rec *conn, server_rec *srv);
    +
    +#ifdef __cplusplus
    +}
    +#endif
    +
    +#endif	/* !APACHE_RFC1413_H */
    diff --git a/APACHE_1_3_12/src/include/scoreboard.h b/APACHE_1_3_12/src/include/scoreboard.h
    new file mode 100644
    index 0000000000..0fadf8a820
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/scoreboard.h
    @@ -0,0 +1,207 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +
    +#ifndef APACHE_SCOREBOARD_H
    +#define APACHE_SCOREBOARD_H
    +
    +#ifdef __cplusplus
    +extern "C" {
    +#endif
    +
    +#ifndef WIN32
    +#if defined(TPF) || defined(NETWARE)
    +#include <time.h>
    +#else
    +#include <sys/times.h>
    +#endif /* TPF */
    +#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)
    +#ifdef TPF
    +#define SCOREBOARD_NAME		"SCOREBRD"
    +#define SCOREBOARD_FRAMES		SCOREBOARD_SIZE/4095 + 1
    +#endif
    +
    +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_12/src/include/util_date.h b/APACHE_1_3_12/src/include/util_date.h
    new file mode 100644
    index 0000000000..8e2051024e
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/util_date.h
    @@ -0,0 +1,85 @@
    +/* ====================================================================
    + * Copyright (c) 1996-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +
    +#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_12/src/include/util_md5.h b/APACHE_1_3_12/src/include/util_md5.h
    new file mode 100644
    index 0000000000..0a0dc9c9b3
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/util_md5.h
    @@ -0,0 +1,80 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +
    +#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_12/src/include/util_script.h b/APACHE_1_3_12/src/include/util_script.h
    new file mode 100644
    index 0000000000..416d72942d
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/util_script.h
    @@ -0,0 +1,91 @@
    +/* ====================================================================
    + * Copyright (c) 1995-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission. For written permission, please contact
    + *    apache@apache.org.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +
    +#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(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_12/src/include/util_uri.h b/APACHE_1_3_12/src/include/util_uri.h
    new file mode 100644
    index 0000000000..d5a67593fc
    --- /dev/null
    +++ b/APACHE_1_3_12/src/include/util_uri.h
    @@ -0,0 +1,128 @@
    +/* ====================================================================
    + * Copyright (c) 1998-1999 The Apache Group.  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 acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * 4. The names "Apache Server" and "Apache Group" must not be used to
    + *    endorse or promote products derived from this software without
    + *    prior written permission.
    + *
    + * 5. Products derived from this software may not be called "Apache"
    + *    nor may "Apache" appear in their names without prior written
    + *    permission of the Apache Group.
    + *
    + * 6. Redistributions of any form whatsoever must retain the following
    + *    acknowledgment:
    + *    "This product includes software developed by the Apache Group
    + *    for use in the Apache HTTP server project (http://www.apache.org/)."
    + *
    + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
    + * EXPRESSED 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 APACHE GROUP OR
    + * ITS 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.
    + * ====================================================================
    + *
    + * This software consists of voluntary contributions made by many
    + * individuals on behalf of the Apache Group and was originally based
    + * on public domain software written at the National Center for
    + * Supercomputing Applications, University of Illinois, Urbana-Champaign.
    + * For more information on the Apache Group and the Apache HTTP server
    + * project, please see <http://www.apache.org/>.
    + *
    + */
    +
    +/*
    + * 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 */
    +
    +/* 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_12/src/lib/.cvsignore b/APACHE_1_3_12/src/lib/.cvsignore
    new file mode 100644
    index 0000000000..f3c7a7c5da
    --- /dev/null
    +++ b/APACHE_1_3_12/src/lib/.cvsignore
    @@ -0,0 +1 @@
    +Makefile
    diff --git a/APACHE_1_3_12/src/lib/expat-lite/.cvsignore b/APACHE_1_3_12/src/lib/expat-lite/.cvsignore
    new file mode 100644
    index 0000000000..f3c7a7c5da
    --- /dev/null
    +++ b/APACHE_1_3_12/src/lib/expat-lite/.cvsignore
    @@ -0,0 +1 @@
    +Makefile
    diff --git a/APACHE_1_3_12/src/lib/expat-lite/CHANGES b/APACHE_1_3_12/src/lib/expat-lite/CHANGES
    new file mode 100644
    index 0000000000..0340d07ee1
    --- /dev/null
    +++ b/APACHE_1_3_12/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_12/src/lib/expat-lite/Makefile.tmpl b/APACHE_1_3_12/src/lib/expat-lite/Makefile.tmpl
    new file mode 100644
    index 0000000000..646af3b981
    --- /dev/null
    +++ b/APACHE_1_3_12/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_12/src/lib/expat-lite/asciitab.h b/APACHE_1_3_12/src/lib/expat-lite/asciitab.h
    new file mode 100644
    index 0000000000..8a8a2dd388
    --- /dev/null
    +++ b/APACHE_1_3_12/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_12/src/lib/expat-lite/dllmain.c b/APACHE_1_3_12/src/lib/expat-lite/dllmain.c
    new file mode 100644
    index 0000000000..deb7fafc81
    --- /dev/null
    +++ b/APACHE_1_3_12/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_12/src/lib/expat-lite/expat.html b/APACHE_1_3_12/src/lib/expat-lite/expat.html
    new file mode 100644
    index 0000000000..3806ca8d0e
    --- /dev/null
    +++ b/APACHE_1_3_12/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
    +
    +
    +
    +

    expat - XML Parser Toolkit

    + +

    Version 1.1

    + +
    + +

    Expat is an XML 1.0 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 ftp://ftp.jclark.com/pub/xml/expat.zip.

    + +

    The directory xmltok contains a low-level library for +tokenizing XML. The interface is documented in +xmltok/xmltok.h.

    + +

    The directory xmlparse contains an XML parser library +which is built on top of the xmltok library. The +interface is documented in xmlparse/xmlparse.h. The +directory sample contains a simple example program using +this interface; sample/build.bat is a batch file to build +the example using Visual C++.

    + +

    The directory xmlwf contains the xmlwf +application, which uses the xmlparse library. The +arguments to xmlwf are one or more files which are each +to be checked for well-formedness. An option -d +dir can be specified; for each well-formed input +file the corresponding canonical XML will +be written to dir/f, where +f is the filename (without any path) of the +input file. A -x option will cause references to +external general entities to be processed. A -s 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).

    + +

    The bin directory contains Win32 executables. The +lib directory contains Win32 import libraries.

    + +

    Answers to some frequently asked questions about expat can be found +in the expat +FAQ.

    + +

    + +
    + +James Clark + +
    + + + + diff --git a/APACHE_1_3_12/src/lib/expat-lite/hashtable.c b/APACHE_1_3_12/src/lib/expat-lite/hashtable.c new file mode 100644 index 0000000000..26a3b444f7 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/lib/expat-lite/hashtable.h b/APACHE_1_3_12/src/lib/expat-lite/hashtable.h new file mode 100644 index 0000000000..5c3f38cbb2 --- /dev/null +++ b/APACHE_1_3_12/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 + +#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_12/src/lib/expat-lite/iasciitab.h b/APACHE_1_3_12/src/lib/expat-lite/iasciitab.h new file mode 100644 index 0000000000..333d6bb779 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/lib/expat-lite/latin1tab.h b/APACHE_1_3_12/src/lib/expat-lite/latin1tab.h new file mode 100644 index 0000000000..48609aa8f9 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/lib/expat-lite/nametab.h b/APACHE_1_3_12/src/lib/expat-lite/nametab.h new file mode 100644 index 0000000000..b05e62c77a --- /dev/null +++ b/APACHE_1_3_12/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_12/src/lib/expat-lite/utf8tab.h b/APACHE_1_3_12/src/lib/expat-lite/utf8tab.h new file mode 100644 index 0000000000..a38fe624e8 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/lib/expat-lite/xmldef.h b/APACHE_1_3_12/src/lib/expat-lite/xmldef.h new file mode 100644 index 0000000000..20c31844d8 --- /dev/null +++ b/APACHE_1_3_12/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 + +#ifdef XML_WINLIB + +#define WIN32_LEAN_AND_MEAN +#define STRICT +#include + +#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 + +#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_12/src/lib/expat-lite/xmlparse.c b/APACHE_1_3_12/src/lib/expat-lite/xmlparse.c new file mode 100644 index 0000000000..62f4116171 --- /dev/null +++ b/APACHE_1_3_12/src/lib/expat-lite/xmlparse.c @@ -0,0 +1,3256 @@ +/* +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; + 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_12/src/lib/expat-lite/xmlparse.def b/APACHE_1_3_12/src/lib/expat-lite/xmlparse.def new file mode 100644 index 0000000000..c309076f47 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/lib/expat-lite/xmlparse.dsp b/APACHE_1_3_12/src/lib/expat-lite/xmlparse.dsp new file mode 100644 index 0000000000..6681620e8c --- /dev/null +++ b/APACHE_1_3_12/src/lib/expat-lite/xmlparse.dsp @@ -0,0 +1,124 @@ +# Microsoft Developer Studio Project File - Name="xmlparse" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.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 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 /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\xmltok" /I "..\xmlwf" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D XMLTOKAPI=__declspec(dllimport) /D XMLPARSEAPI=__declspec(dllexport) /YX /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 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 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 /base:"0x20000000" /subsystem:windows /dll /machine:I386 /out:"Release\xmlparse.dll" +# SUBTRACT LINK32 /profile + +!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 /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MDd /W3 /GX /Od /I "..\xmltok" /I "..\xmlwf" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D XMLTOKAPI=__declspec(dllimport) /D XMLPARSEAPI=__declspec(dllexport) /YX /FD /ZI /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 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 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 /base:"0x20000000" /subsystem:windows /dll /debug /machine:I386 /out:"Debug\xmlparse.dll" + +!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_12/src/lib/expat-lite/xmlparse.h b/APACHE_1_3_12/src/lib/expat-lite/xmlparse.h new file mode 100644 index 0000000000..f2f9c9be1c --- /dev/null +++ b/APACHE_1_3_12/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 +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_12/src/lib/expat-lite/xmlparse.mak b/APACHE_1_3_12/src/lib/expat-lite/xmlparse.mak new file mode 100644 index 0000000000..4f878df12c --- /dev/null +++ b/APACHE_1_3_12/src/lib/expat-lite/xmlparse.mak @@ -0,0 +1,289 @@ +# 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)\vc50.idb" + -@erase "$(INTDIR)\xmlparse.obj" + -@erase "$(OUTDIR)\xmlparse.dll" + -@erase "$(OUTDIR)\xmlparse.exp" + -@erase "$(OUTDIR)\xmlparse.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /ML /W3 /GX /O2 /I "..\xmltok" /I "..\xmlwf" /D "NDEBUG" /D\ + "WIN32" /D "_WINDOWS" /D XMLTOKAPI=__declspec(dllimport) /D\ + XMLPARSEAPI=__declspec(dllexport) /Fp"$(INTDIR)\xmlparse.pch" /YX\ + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\Release/ +CPP_SBRS=. + +.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) $< +<< + +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 user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\ + odbccp32.lib /nologo /base:"0x20000000" /subsystem:windows /dll /incremental:no\ + /pdb:"$(OUTDIR)\xmlparse.pdb" /machine:I386 /def:".\xmlparse.def"\ + /out:"$(OUTDIR)\xmlparse.dll" /implib:"$(OUTDIR)\xmlparse.lib" +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)\vc50.idb" + -@erase "$(INTDIR)\xmlparse.obj" + -@erase "$(OUTDIR)\xmlparse.dll" + -@erase "$(OUTDIR)\xmlparse.exp" + -@erase "$(OUTDIR)\xmlparse.ilk" + -@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 /Od /I "..\xmltok" /I "..\xmlwf" /D "_DEBUG" /D\ + "WIN32" /D "_WINDOWS" /D XMLTOKAPI=__declspec(dllimport) /D\ + XMLPARSEAPI=__declspec(dllexport) /Fp"$(INTDIR)\xmlparse.pch" /YX\ + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /Zi /c +CPP_OBJS=.\Debug/ +CPP_SBRS=. + +.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) $< +<< + +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 user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\ + odbccp32.lib /nologo /base:"0x20000000" /subsystem:windows /dll\ + /incremental:yes /pdb:"$(OUTDIR)\xmlparse.pdb" /debug /machine:I386\ + /def:".\xmlparse.def" /out:"$(OUTDIR)\xmlparse.dll"\ + /implib:"$(OUTDIR)\xmlparse.lib" +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 "$(CFG)" == "xmlparse - Win32 Release" || "$(CFG)" ==\ + "xmlparse - Win32 Debug" +SOURCE=.\hashtable.c +DEP_CPP_HASHT=\ + ".\hashtable.h"\ + ".\xmldef.h"\ + +NODEP_CPP_HASHT=\ + ".\ap_config.h"\ + ".\nspr.h"\ + + +"$(INTDIR)\hashtable.obj" : $(SOURCE) $(DEP_CPP_HASHT) "$(INTDIR)" + + +SOURCE=.\xmlparse.c +DEP_CPP_XMLPA=\ + ".\hashtable.h"\ + ".\xmldef.h"\ + ".\xmlparse.h"\ + ".\xmlrole.h"\ + ".\xmltok.h"\ + +NODEP_CPP_XMLPA=\ + ".\ap_config.h"\ + ".\nspr.h"\ + + +"$(INTDIR)\xmlparse.obj" : $(SOURCE) $(DEP_CPP_XMLPA) "$(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) CLEAN /F ".\xmltok.mak" CFG="xmltok - Win32 Release"\ + RECURSE=1 + 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) CLEAN /F ".\xmltok.mak" CFG="xmltok - Win32 Debug"\ + RECURSE=1 + cd "." + +!ENDIF + + +!ENDIF + diff --git a/APACHE_1_3_12/src/lib/expat-lite/xmlrole.c b/APACHE_1_3_12/src/lib/expat-lite/xmlrole.c new file mode 100644 index 0000000000..b18e35eb3c --- /dev/null +++ b/APACHE_1_3_12/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_12/src/lib/expat-lite/xmlrole.h b/APACHE_1_3_12/src/lib/expat-lite/xmlrole.h new file mode 100644 index 0000000000..877c40ba1f --- /dev/null +++ b/APACHE_1_3_12/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_12/src/lib/expat-lite/xmltok.c b/APACHE_1_3_12/src/lib/expat-lite/xmltok.c new file mode 100644 index 0000000000..f0570d8145 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/lib/expat-lite/xmltok.def b/APACHE_1_3_12/src/lib/expat-lite/xmltok.def new file mode 100644 index 0000000000..3be476c555 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/lib/expat-lite/xmltok.dsp b/APACHE_1_3_12/src/lib/expat-lite/xmltok.dsp new file mode 100644 index 0000000000..f506f15165 --- /dev/null +++ b/APACHE_1_3_12/src/lib/expat-lite/xmltok.dsp @@ -0,0 +1,160 @@ +# Microsoft Developer Studio Project File - Name="xmltok" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.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 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 /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D XMLTOKAPI=__declspec(dllexport) /YX /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 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 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 /entry:"DllMain" /subsystem:windows /dll /machine:I386 /out:"Release\xmltok.dll" + +!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 /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MTd /W3 /GX /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D XMLTOKAPI=__declspec(dllexport) /YX /FD /ZI /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 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 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 /out:"Debug\xmltok.dll" + +!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_12/src/lib/expat-lite/xmltok.h b/APACHE_1_3_12/src/lib/expat-lite/xmltok.h new file mode 100644 index 0000000000..fd0ed08e34 --- /dev/null +++ b/APACHE_1_3_12/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 */ +#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 /* */ +#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_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_12/src/lib/expat-lite/xmltok.mak b/APACHE_1_3_12/src/lib/expat-lite/xmltok.mak new file mode 100644 index 0000000000..45e1e3b679 --- /dev/null +++ b/APACHE_1_3_12/src/lib/expat-lite/xmltok.mak @@ -0,0 +1,261 @@ +# 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 + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\xmltok.dll" + +!ELSE + +ALL : "$(OUTDIR)\xmltok.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\dllmain.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\xmlrole.obj" + -@erase "$(INTDIR)\xmltok.obj" + -@erase "$(OUTDIR)\xmltok.dll" + -@erase "$(OUTDIR)\xmltok.exp" + -@erase "$(OUTDIR)\xmltok.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D\ + XMLTOKAPI=__declspec(dllexport) /Fp"$(INTDIR)\xmltok.pch" /YX /Fo"$(INTDIR)\\"\ + /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\Release/ +CPP_SBRS=. + +.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) $< +<< + +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=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 /entry:"DllMain" /subsystem:windows /dll /incremental:no\ + /pdb:"$(OUTDIR)\xmltok.pdb" /machine:I386 /def:".\xmltok.def"\ + /out:"$(OUTDIR)\xmltok.dll" /implib:"$(OUTDIR)\xmltok.lib" +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 + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\xmltok.dll" + +!ELSE + +ALL : "$(OUTDIR)\xmltok.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\dllmain.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\xmlrole.obj" + -@erase "$(INTDIR)\xmltok.obj" + -@erase "$(OUTDIR)\xmltok.dll" + -@erase "$(OUTDIR)\xmltok.exp" + -@erase "$(OUTDIR)\xmltok.ilk" + -@erase "$(OUTDIR)\xmltok.lib" + -@erase "$(OUTDIR)\xmltok.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MTd /W3 /GX /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D\ + XMLTOKAPI=__declspec(dllexport) /Fp"$(INTDIR)\xmltok.pch" /YX /Fo"$(INTDIR)\\"\ + /Fd"$(INTDIR)\\" /FD /Zi /c +CPP_OBJS=.\Debug/ +CPP_SBRS=. + +.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) $< +<< + +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=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)\xmltok.pdb" /debug /machine:I386 /def:".\xmltok.def"\ + /out:"$(OUTDIR)\xmltok.dll" /implib:"$(OUTDIR)\xmltok.lib" +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 "$(CFG)" == "xmltok - Win32 Release" || "$(CFG)" == "xmltok - Win32 Debug" +SOURCE=.\dllmain.c + +"$(INTDIR)\dllmain.obj" : $(SOURCE) "$(INTDIR)" + + +SOURCE=.\xmlrole.c +DEP_CPP_XMLRO=\ + ".\xmldef.h"\ + ".\xmlrole.h"\ + ".\xmltok.h"\ + +NODEP_CPP_XMLRO=\ + ".\ap_config.h"\ + ".\nspr.h"\ + + +"$(INTDIR)\xmlrole.obj" : $(SOURCE) $(DEP_CPP_XMLRO) "$(INTDIR)" + + +SOURCE=.\xmltok.c +DEP_CPP_XMLTO=\ + ".\asciitab.h"\ + ".\iasciitab.h"\ + ".\latin1tab.h"\ + ".\nametab.h"\ + ".\utf8tab.h"\ + ".\xmldef.h"\ + ".\xmltok.h"\ + ".\xmltok_impl.c"\ + ".\xmltok_impl.h"\ + ".\xmltok_ns.c"\ + +NODEP_CPP_XMLTO=\ + ".\ap_config.h"\ + ".\nspr.h"\ + + +"$(INTDIR)\xmltok.obj" : $(SOURCE) $(DEP_CPP_XMLTO) "$(INTDIR)" + + +SOURCE=.\xmltok_impl.c + +!ENDIF + diff --git a/APACHE_1_3_12/src/lib/expat-lite/xmltok_impl.c b/APACHE_1_3_12/src/lib/expat-lite/xmltok_impl.c new file mode 100644 index 0000000000..5dfe29f1b9 --- /dev/null +++ b/APACHE_1_3_12/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 "')) { + *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 " */ + 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 "')) { + *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 "')) { + *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_12/src/lib/expat-lite/xmltok_impl.h b/APACHE_1_3_12/src/lib/expat-lite/xmltok_impl.h new file mode 100644 index 0000000000..e72b225c83 --- /dev/null +++ b/APACHE_1_3_12/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 diff --git a/APACHE_1_3_12/src/lib/expat-lite/xmltok_ns.c b/APACHE_1_3_12/src/lib/expat-lite/xmltok_ns.c new file mode 100644 index 0000000000..a32c577458 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/main/.cvsignore b/APACHE_1_3_12/src/main/.cvsignore new file mode 100644 index 0000000000..f8193cb91b --- /dev/null +++ b/APACHE_1_3_12/src/main/.cvsignore @@ -0,0 +1,13 @@ +Makefile +uri_delims.h +gen_uri_delims +test_char.h +gen_test_char +gen_uri_delims_R +gen_test_char_R +gen_uri_delims_D +gen_uri_delims.ilk +gen_uri_delims.pdb +gen_test_char_D +gen_test_char.ilk +gen_test_char.pdb diff --git a/APACHE_1_3_12/src/main/.indent.pro b/APACHE_1_3_12/src/main/.indent.pro new file mode 100644 index 0000000000..a9fbe9f9a1 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/main/Makefile.tmpl b/APACHE_1_3_12/src/main/Makefile.tmpl new file mode 100644 index 0000000000..0d774c3abb --- /dev/null +++ b/APACHE_1_3_12/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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_12/src/main/alloc.c b/APACHE_1_3_12/src/main/alloc.c new file mode 100644 index 0000000000..f8ac634b87 --- /dev/null +++ b/APACHE_1_3_12/src/main/alloc.c @@ -0,0 +1,2707 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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 + +#ifdef OS2 +#define INCL_DOS +#include +#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; + +#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 + blok = (union block_hdr *) malloc(size + sizeof(union block_hdr)); + if (blok == NULL) { + fprintf(stderr, "Ouch! malloc failed in malloc_block()\n"); + 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 + +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; +} + +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 +}; + +static int psprintf_flush(ap_vformatter_buff *vbuff) +{ + struct psprintf_data *ps = (struct psprintf_data *)vbuff; +#ifdef ALLOC_USE_MALLOC + int size; + char *ptr; + + size = (char *)ps->vbuff.curpos - ps->base; + ptr = realloc(ps->base, 2*size); + if (ptr == NULL) { + fputs("Ouch! Out of memory!\n", stderr); + exit(1); + } + ps->base = ptr; + ps->vbuff.curpos = ptr + size; + ps->vbuff.endpos = ptr + 2*size - 1; + return 0; +#else + union block_hdr *blok; + union block_hdr *nblok; + size_t cur_len; + char *strp; + + blok = ps->blok; + strp = ps->vbuff.curpos; + cur_len = strp - blok->h.first_avail; + + /* must try another blok */ + (void) ap_acquire_mutex(alloc_mutex); + nblok = new_block(2 * cur_len); + (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; + + 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 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(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(pool *p, void *data, void (*plain_cleanup) (void *), + void (*child_cleanup) (void *)) +{ + struct cleanup *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; +} + +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) + /* + * Don't need to do anything on NT 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. + */ + +static void fd_cleanup(void *fdv) +{ + close((int) (long) fdv); +} + +API_EXPORT(void) ap_note_cleanups_for_fd(pool *p, int fd) +{ + ap_register_cleanup(p, (void *) (long) fd, fd_cleanup, fd_cleanup); +} + +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(pool *a, const char *name, int flg, int mode) +{ + 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(a, fd); + } + ap_unblock_alarms(); + errno = save_errno; + return fd; +} + +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 *fdv) +{ + CloseHandle((HANDLE) fdv); +} + +API_EXPORT(void) ap_note_cleanups_for_h(pool *p, HANDLE hDevice) +{ + ap_register_cleanup(p, (void *) hDevice, h_cleanup, h_cleanup); +} + +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)); +} + +API_EXPORT(void) ap_note_cleanups_for_file(pool *p, FILE *fp) +{ + ap_register_cleanup(p, (void *) fp, file_cleanup, file_child_cleanup); +} + +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); +} + +API_EXPORT(void) ap_note_cleanups_for_socket(pool *p, int fd) +{ + ap_register_cleanup(p, (void *) (long) fd, socket_cleanup, socket_cleanup); +} + +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(pool *p, int domain, int type, int protocol) +{ + 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(p, fd); + ap_unblock_alarms(); + return fd; +} + +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 + * unblock alarms and return the pid + */ + + } +#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(p, hPipeOutputRead); + + /* 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(p, hPipeInputWrite); + + /* 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(p, hPipeErrorRead); + + /* 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(p, fd_out); + ap_bpushfd(*pipe_out, fd_out, fd_out); + } + + if (pipe_in) { + *pipe_in = ap_bcreate(p, B_WR); + ap_note_cleanups_for_fd(p, fd_in); + ap_bpushfd(*pipe_in, fd_in, fd_in); + } + + if (pipe_err) { + *pipe_err = ap_bcreate(p, B_RD); + ap_note_cleanups_for_fd(p, fd_err); + ap_bpushfd(*pipe_err, fd_err, fd_err); + } +#endif + + ap_unblock_alarms(); + return pid; +} + +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 (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)) { + /* Subprocess may be dead already. Only need the timeout if not. */ + if (ap_os_kill(p->pid, SIGTERM) != -1) + need_timeout = 1; + } + else if (p->kill_how == kill_always) { + kill(p->pid, SIGKILL); + } + } + + /* 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) + kill(p->pid, SIGKILL); + + if (p->kill_how != kill_never) + waitpid(p->pid, &status, 0); + } +#endif /* WIN32 */ +} diff --git a/APACHE_1_3_12/src/main/buff.c b/APACHE_1_3_12/src/main/buff.c new file mode 100644 index 0000000000..59e54f8399 --- /dev/null +++ b/APACHE_1_3_12/src/main/buff.c @@ -0,0 +1,1639 @@ +/* ==================================================================== + * Copyright (c) 1996-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +#include "httpd.h" +#include "http_main.h" +#include "http_log.h" + +#include +#include +#include +#include +#ifndef NO_WRITEV +#include +#include +#endif + +#ifdef HAVE_BSTRING_H +#include /* 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 + + +/* 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) + +/* + select() sometimes returns 1 even though the write will block. We must work around this. +*/ + +int 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; + + if (!(tv.tv_sec = ap_check_alarm())) + return (send(sock, buf, len, flags)); + + 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; +#ifdef NETWARE + ap_log_error(APLOG_MARK,APLOG_DEBUG,NULL, + "select claimed we could write, but in fact we couldn't."); + ThreadSwitchWithDelay(); +#else + ap_log_error(APLOG_MARK,APLOG_DEBUG,NULL, + "select claimed we could write, but in fact we couldn't. This is a bug in Windows."); + Sleep(100); +#endif + } + } + } + } while(retry); + } + + ioctlsocket(sock, FIONBIO, (u_long*)&iostate); + + if (rv == SOCKET_ERROR) + WSASetLastError(err); + return (rv); +} + + +int recvwithtimeout(int sock, char *buf, int len, int flags) +{ + int iostate = 1; + fd_set fdset; + struct timeval tv; + int err = WSAEWOULDBLOCK; + int rv; + + if (!(tv.tv_sec = ap_check_alarm())) + return (recv(sock, buf, len, flags)); + + 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) { + 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(); + } + } + } + + 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) + if (fb->flags & B_SOCKET) { + rv = 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; + rv = ap_select(fb->fd_in + 1, &fds, NULL, NULL, &tv); + 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 defined(WIN32) || defined(NETWARE) + if (fb->flags & B_SOCKET) { + rv = 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 + + 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) + 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; + + /* 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, 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 = 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 = 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)) + 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 defined(WIN32) || defined(NETWARE) + 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; + } + } +#ifndef NETWARE + else if (fb->hFH != INVALID_HANDLE_VALUE) { + rc2 = ap_pcloseh(fb->pool, fb->hFH); + rc3 = 0; + } +#endif + else { +#elif defined(BEOS) + 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 { +#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) || defined (BEOS) || defined(NETWARE) + } +#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_12/src/main/gen_test_char.c b/APACHE_1_3_12/src/main/gen_test_char.c new file mode 100644 index 0000000000..dc33a73d86 --- /dev/null +++ b/APACHE_1_3_12/src/main/gen_test_char.c @@ -0,0 +1,62 @@ +/* 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) + +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 (%u)\n" +"#define T_ESCAPE_PATH_SEGMENT (%u)\n" +"#define T_OS_ESCAPE_PATH (%u)\n" +"#define T_HTTP_TOKEN_STOP (%u)\n" +"\n" +"static const unsigned char test_char_table[256] = {\n" +" 0,", + T_ESCAPE_SHELL_CMD, + T_ESCAPE_PATH_SEGMENT, + T_OS_ESCAPE_PATH, + T_HTTP_TOKEN_STOP); + + /* we explicitly dealt with NUL above + * in case some strchr() do bogosity with it */ + + for (c = 1; c < 256; ++c) { + flags = 0; + if (c % 20 == 0) + printf("\n "); + + /* escape_shell_cmd */ + if (strchr("&;`'\"|*?~<>^()[]{}$\\\n", c)) { + flags |= T_ESCAPE_SHELL_CMD; + } + + 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 (ap_iscntrl(c) || strchr(" \t()<>@,;:\\/[]?={}", c)) { + flags |= T_HTTP_TOKEN_STOP; + } + printf("%u%c", flags, (c < 255) ? ',' : ' '); + + } + printf("\n};\n"); + + return 0; +} diff --git a/APACHE_1_3_12/src/main/gen_test_char.dsp b/APACHE_1_3_12/src/main/gen_test_char.dsp new file mode 100644 index 0000000000..c2630ce9d1 --- /dev/null +++ b/APACHE_1_3_12/src/main/gen_test_char.dsp @@ -0,0 +1,105 @@ +# Microsoft Developer Studio Project File - Name="gen_test_char" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.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 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 "gen_test" +# PROP BASE Intermediate_Dir "gen_test" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "" +# PROP Intermediate_Dir "gen_test_char_R" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /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 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:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:I386 +# Begin Special Build Tool +SOURCE=$(InputPath) +PostBuild_Desc=Create test_char.h +PostBuild_Cmds=.\gen_test_char > test_char.h +# End Special Build Tool + +!ELSEIF "$(CFG)" == "gen_test_char - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "gen_tes0" +# PROP BASE Intermediate_Dir "gen_tes0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "" +# PROP Intermediate_Dir "gen_test_char_D" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /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 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:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# Begin Special Build Tool +SOURCE=$(InputPath) +PostBuild_Desc=Create test_char.h +PostBuild_Cmds=.\gen_test_char > test_char.h +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "gen_test_char - Win32 Release" +# Name "gen_test_char - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\gen_test_char.c +# End Source File +# End Group +# End Target +# End Project diff --git a/APACHE_1_3_12/src/main/gen_test_char.mak b/APACHE_1_3_12/src/main/gen_test_char.mak new file mode 100644 index 0000000000..14d5558b09 --- /dev/null +++ b/APACHE_1_3_12/src/main/gen_test_char.mak @@ -0,0 +1,236 @@ +# 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 + +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "gen_test_char - Win32 Release" + +OUTDIR=. +INTDIR=.\gen_test_char_R +# Begin Custom Macros +OutDir=. +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\gen_test_char.exe" + +!ELSE + +ALL : "$(OUTDIR)\gen_test_char.exe" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\gen_test_char.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\gen_test_char.exe" + +"$(INTDIR)" : + if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)" + +CPP_PROJ=/nologo /ML /W3 /GX /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D\ + "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\gen_test_char.pch" /YX /Fo"$(INTDIR)\\"\ + /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\gen_test_char_R/ +CPP_SBRS=. +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\gen_test_char.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib /nologo /subsystem:console /incremental:no\ + /pdb:"$(OUTDIR)\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) +<< + +SOURCE=$(InputPath) +PostBuild_Desc=Create test_char.h +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +ALL : $(DS_POSTBUILD_DEP) + +# Begin Custom Macros +OutDir=. +# End Custom Macros + +$(DS_POSTBUILD_DEP) : "$(OUTDIR)\gen_test_char.exe" + .\gen_test_char > test_char.h + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ELSEIF "$(CFG)" == "gen_test_char - Win32 Debug" + +OUTDIR=. +INTDIR=.\gen_test_char_D +# Begin Custom Macros +OutDir=. +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\gen_test_char.exe" + +!ELSE + +ALL : "$(OUTDIR)\gen_test_char.exe" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\gen_test_char.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\gen_test_char.exe" + -@erase "$(OUTDIR)\gen_test_char.ilk" + -@erase "$(OUTDIR)\gen_test_char.pdb" + +"$(INTDIR)" : + if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)" + +CPP_PROJ=/nologo /MLd /W3 /Gm /GX /Zi /Od /I "..\include" /D "WIN32" /D\ + "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\gen_test_char.pch" /YX\ + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\gen_test_char_D/ +CPP_SBRS=. +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\gen_test_char.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib /nologo /subsystem:console /incremental:yes\ + /pdb:"$(OUTDIR)\gen_test_char.pdb" /debug /machine:I386\ + /out:"$(OUTDIR)\gen_test_char.exe" /pdbtype:sept +LINK32_OBJS= \ + "$(INTDIR)\gen_test_char.obj" + +"$(OUTDIR)\gen_test_char.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +SOURCE=$(InputPath) +PostBuild_Desc=Create test_char.h +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +ALL : $(DS_POSTBUILD_DEP) + +# Begin Custom Macros +OutDir=. +# End Custom Macros + +$(DS_POSTBUILD_DEP) : "$(OUTDIR)\gen_test_char.exe" + .\gen_test_char > test_char.h + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!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) $< +<< + + +!IF "$(CFG)" == "gen_test_char - Win32 Release" || "$(CFG)" ==\ + "gen_test_char - Win32 Debug" +SOURCE=.\gen_test_char.c + +!IF "$(CFG)" == "gen_test_char - Win32 Release" + +DEP_CPP_GEN_T=\ + "..\include\alloc.h"\ + "..\include\ap.h"\ + "..\include\buff.h"\ + "..\include\conf.h"\ + "..\include\hsregex.h"\ + "..\include\httpd.h"\ + "..\include\util_uri.h"\ + "..\os\win32\os.h"\ + "..\os\win32\readdir.h"\ + + +"$(INTDIR)\gen_test_char.obj" : $(SOURCE) $(DEP_CPP_GEN_T) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "gen_test_char - Win32 Debug" + +DEP_CPP_GEN_T=\ + "..\include\alloc.h"\ + "..\include\ap.h"\ + "..\include\buff.h"\ + "..\include\conf.h"\ + "..\include\hsregex.h"\ + "..\include\httpd.h"\ + "..\include\util_uri.h"\ + "..\os\win32\os.h"\ + "..\os\win32\readdir.h"\ + + +"$(INTDIR)\gen_test_char.obj" : $(SOURCE) $(DEP_CPP_GEN_T) "$(INTDIR)" + + +!ENDIF + + +!ENDIF + diff --git a/APACHE_1_3_12/src/main/gen_uri_delims.c b/APACHE_1_3_12/src/main/gen_uri_delims.c new file mode 100644 index 0000000000..15a73fbc7a --- /dev/null +++ b/APACHE_1_3_12/src/main/gen_uri_delims.c @@ -0,0 +1,31 @@ +#include + +/* 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_12/src/main/gen_uri_delims.dsp b/APACHE_1_3_12/src/main/gen_uri_delims.dsp new file mode 100644 index 0000000000..566dd83e27 --- /dev/null +++ b/APACHE_1_3_12/src/main/gen_uri_delims.dsp @@ -0,0 +1,105 @@ +# Microsoft Developer Studio Project File - Name="gen_uri_delims" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.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 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 "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "" +# PROP Intermediate_Dir "gen_uri_delims_R" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /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 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:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:I386 +# Begin Special Build Tool +SOURCE=$(InputPath) +PostBuild_Desc=Create uri_delims.h +PostBuild_Cmds=.\gen_uri_delims > uri_delims.h +# End Special Build Tool + +!ELSEIF "$(CFG)" == "gen_uri_delims - 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 "" +# PROP Intermediate_Dir "gen_uri_delims_D" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /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 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:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# Begin Special Build Tool +SOURCE=$(InputPath) +PostBuild_Desc=Create uri_delims.h +PostBuild_Cmds=.\gen_uri_delims > uri_delims.h +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "gen_uri_delims - Win32 Release" +# Name "gen_uri_delims - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\gen_uri_delims.c +# End Source File +# End Group +# End Target +# End Project diff --git a/APACHE_1_3_12/src/main/gen_uri_delims.mak b/APACHE_1_3_12/src/main/gen_uri_delims.mak new file mode 100644 index 0000000000..63ec6dca9c --- /dev/null +++ b/APACHE_1_3_12/src/main/gen_uri_delims.mak @@ -0,0 +1,204 @@ +# 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 + +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "gen_uri_delims - Win32 Release" + +OUTDIR=. +INTDIR=.\gen_uri_delims_R +# Begin Custom Macros +OutDir=. +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\gen_uri_delims.exe" + +!ELSE + +ALL : "$(OUTDIR)\gen_uri_delims.exe" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\gen_uri_delims.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\gen_uri_delims.exe" + +"$(INTDIR)" : + if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)" + +CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D\ + "_MBCS" /Fp"$(INTDIR)\gen_uri_delims.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\"\ + /FD /c +CPP_OBJS=.\gen_uri_delims_R/ +CPP_SBRS=. +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\gen_uri_delims.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib /nologo /subsystem:console /incremental:no\ + /pdb:"$(OUTDIR)\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) +<< + +SOURCE=$(InputPath) +PostBuild_Desc=Create uri_delims.h +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +ALL : $(DS_POSTBUILD_DEP) + +# Begin Custom Macros +OutDir=. +# End Custom Macros + +$(DS_POSTBUILD_DEP) : "$(OUTDIR)\gen_uri_delims.exe" + .\gen_uri_delims > uri_delims.h + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!ELSEIF "$(CFG)" == "gen_uri_delims - Win32 Debug" + +OUTDIR=. +INTDIR=.\gen_uri_delims_D +# Begin Custom Macros +OutDir=. +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\gen_uri_delims.exe" + +!ELSE + +ALL : "$(OUTDIR)\gen_uri_delims.exe" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\gen_uri_delims.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\gen_uri_delims.exe" + -@erase "$(OUTDIR)\gen_uri_delims.ilk" + -@erase "$(OUTDIR)\gen_uri_delims.pdb" + +"$(INTDIR)" : + if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)" + +CPP_PROJ=/nologo /MLd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\ + /D "_MBCS" /Fp"$(INTDIR)\gen_uri_delims.pch" /YX /Fo"$(INTDIR)\\"\ + /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\gen_uri_delims_D/ +CPP_SBRS=. +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\gen_uri_delims.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib /nologo /subsystem:console /incremental:yes\ + /pdb:"$(OUTDIR)\gen_uri_delims.pdb" /debug /machine:I386\ + /out:"$(OUTDIR)\gen_uri_delims.exe" /pdbtype:sept +LINK32_OBJS= \ + "$(INTDIR)\gen_uri_delims.obj" + +"$(OUTDIR)\gen_uri_delims.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +SOURCE=$(InputPath) +PostBuild_Desc=Create uri_delims.h +DS_POSTBUILD_DEP=$(INTDIR)\postbld.dep + +ALL : $(DS_POSTBUILD_DEP) + +# Begin Custom Macros +OutDir=. +# End Custom Macros + +$(DS_POSTBUILD_DEP) : "$(OUTDIR)\gen_uri_delims.exe" + .\gen_uri_delims > uri_delims.h + echo Helper for Post-build step > "$(DS_POSTBUILD_DEP)" + +!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) $< +<< + + +!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_12/src/main/http_config.c b/APACHE_1_3_12/src/main/http_config.c new file mode 100644 index 0000000000..ebb713ca16 --- /dev/null +++ b/APACHE_1_3_12/src/main/http_config.c @@ -0,0 +1,1646 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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" + +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; +} + +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]); + } +} + +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; + +/* 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; +} + +int ap_translate_name(request_rec *r) +{ + return run_method(r, offsets_into_method_ptrs.translate_handler, 0); +} + +int ap_check_access(request_rec *r) +{ + return run_method(r, offsets_into_method_ptrs.access_checker, 1); +} + +int ap_find_types(request_rec *r) +{ + return run_method(r, offsets_into_method_ptrs.type_checker, 0); +} + +int ap_run_fixups(request_rec *r) +{ + return run_method(r, offsets_into_method_ptrs.fixer_upper, 1); +} + +int ap_log_transaction(request_rec *r) +{ + return run_method(r, offsets_into_method_ptrs.logger, 1); +} + +int ap_header_parse(request_rec *r) +{ + return run_method(r, offsets_into_method_ptrs.header_parser, 1); +} + +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. + */ + +int ap_check_user_id(request_rec *r) +{ + return run_method(r, offsets_into_method_ptrs.ap_check_user_id, 0); +} + +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; +} + +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"); + exit(1); + } + + 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"); + exit(1); + } + } + + /* 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; +} + +void ap_setup_prelinked_modules() +{ + 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"); + exit(1); + } + 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; + 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) +{ + 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); + exit(1); + } + + ap_cfg_closefile(parms.config_file); +} + +void ap_process_resource_config(server_rec *s, char *fname, pool *p, pool *ptemp) +{ + const char *errmsg; + cmd_parms parms; + struct stat finfo; + + 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; + } + + /* 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); + exit(1); + } + + 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); + exit(1); + } + + ap_cfg_closefile(parms.config_file); +} + + +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; + new->local_addr.sin_port = htons(s->port ? s->port : DEFAULT_HTTP_PORT); + new->fd = -1; + new->used = 0; + new->next = NULL; + ap_listeners = new; +} + + +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; +} + +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)); +} + +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); +} + +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); +} + +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 or --> 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 , or "); + else + printf("only inside , or "); + + /* Warn if the directive is allowed inside 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 -h. + */ +void ap_show_directives() +{ + 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. */ +void ap_show_modules() +{ + int n; + + printf("Compiled-in modules:\n"); + for (n = 0; ap_loaded_modules[n]; ++n) { + printf(" %s\n", ap_loaded_modules[n]->name); + } + printf("suexec: %s\n", + ap_suexec_enabled + ? "enabled; valid wrapper " SUEXEC_BIN + : "disabled; invalid wrapper " SUEXEC_BIN); +} diff --git a/APACHE_1_3_12/src/main/http_core.c b/APACHE_1_3_12/src/main/http_core.c new file mode 100644 index 0000000000..4c4c64d275 --- /dev/null +++ b/APACHE_1_3_12/src/main/http_core.c @@ -0,0 +1,3266 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +#define CORE_PRIVATE +#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 + +/* mmap support for static files based on ideas from John Heidemann's + * patch against 1.0.5. See + * . + */ + +/* 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 + +/* 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; + + 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_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; + } + + 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 *)); + + 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); + + return conf; +} + +/* Add per-directory configuration entry (for 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(). + */ + +#ifdef HAVE_DRIVE_LETTERS +#define IS_SPECIAL(entry_core) \ + ((entry_core)->r != NULL \ + || ((entry_core)->d[0] != '/' && (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; +} + +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_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). + */ + +char *ap_response_code_string(request_rec *r, int error_index) +{ + core_dir_config *conf; + + conf = (core_dir_config *)ap_get_module_config(r->per_dir_config, + &core_module); + + if (conf->response_code_strings == NULL) { + return NULL; + } + return conf->response_code_strings[error_index]; +} + + +/* Code from Harald Hanche-Olsen */ +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; + 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; +} + +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 (conn->double_reverse != 1) { + conn->remote_host = NULL; + } + } + } + /* 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; + core_dir_config *d = + (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module); + + port = r->server->port ? r->server->port : ap_default_port(r); + + if (d->use_canonical_name == USE_CANONICAL_NAME_OFF + || d->use_canonical_name == USE_CANONICAL_NAME_DNS) { + return r->hostname ? ntohs(r->connection->local_addr.sin_port) + : port; + } + /* 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 canonical way shell command entries are entered in the Win32 + * registry is as follows: + * shell [options] "%1" + * 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 + * "%1" - Place holder for file to run the shell against. + * Typically quoted. + * + * If we find a %1 or a quoted %1, lop it off. + */ + if (buffer && *buffer) { + if ((s = strstr(buffer, "\"%1"))) + *s = '\0'; + else if ((s = strstr(buffer, "%1"))) + *s = '\0'; + } + + 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"))) { + return eFileTypeEXE32; + } + + /* 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); 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[] = ""; +static const char end_directorymatch_section[] = ""; +static const char end_location_section[] = ""; +static const char end_locationmatch_section[] = ""; +static const char end_files_section[] = ""; +static const char end_filesmatch_section[] = ""; +static const char end_virtualhost_section[] = ""; +static const char end_ifmodule_section[] = ""; +static const char end_ifdefine_section[] = ""; + + +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 section", NULL); + } + + if ((forbidden & NOT_IN_LIMIT) && cmd->limited != -1) { + return ap_pstrcat(cmd->pool, cmd->cmd->name, gt, + " cannot occur within 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 " + "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_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_dir_config *conf = + ap_get_module_config(r->per_dir_config, &core_module); + int idx; + + if(conf->response_code_strings == NULL) { + conf->response_code_strings = + ap_pcalloc(r->pool, + sizeof(*conf->response_code_strings) * + RESPONSE_CODES); + } + + idx = ap_index_of_response(status); + + conf->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 + * section. NB we need to have a way to cut the srm_command_loop + * invoked by dirsection (i.e., ) short when 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 or 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 "; + } + else if (methnum == M_INVALID) { + return ap_pstrcat(cmd->pool, "unknown method \"", method, + "\" in " : ">", NULL); + } + else { + limited |= (1 << methnum); + } + } + + /* Killing two features with one function, + * if (tog == NULL) , else + */ + 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 ? " unexpected" : " 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 and , 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) { /* */ + r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED|USE_ICASE); + } + else if (!strcmp(cmd->path, "~")) { + cmd->path = ap_getword_conf(cmd->pool, &arg); + r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED|USE_ICASE); + } + 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) { /* */ + r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED); + } + else if (!strcmp(cmd->path, "~")) { + cmd->path = ap_getword_conf(cmd->pool, &arg); + r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED); + } + + 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) { /* */ + r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED|USE_ICASE); + } + else if (!strcmp(cmd->path, "~")) { + cmd->path = ap_getword_conf(cmd->pool, &arg); + r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED|USE_ICASE); + } + 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 sections are closed properly. + * Extra (redundant, unpaired) 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, "")) { + 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, "")) { + nest--; + } + } + if (nest) { + cmd->end_token = end_ifdefine_section; + return missing_endsection(cmd, nest); + } + return NULL; +} + +/* httpd.conf commands... beginning with the 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 + 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 " 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 "; + } + 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) +{ + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + if (err != NULL) { + return err; + } + + 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 " + "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 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"; + } + 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; +} + +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 "; + } + 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 + +static const char *set_listener(cmd_parms *cmd, void *dummy, char *ips) +{ + listen_rec *new; + char *ports; + unsigned short 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 :"; + } + *(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); + } + port = atoi(ports); + if (!port) { + return "Port must be numeric"; + } + new->local_addr.sin_port = htons(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)); + 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, "
    " SERVER_BASEVERSION + " Server at server->server_admin, "\">", + ap_get_server_name(r), " Port ", sport, + "
    \n", NULL); + } + return ap_pstrcat(r->pool, prefix, "
    " SERVER_BASEVERSION + " Server at ", ap_get_server_name(r), " Port ", sport, + "
    \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; +} + +#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*/ + +/* + * 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 { + ap_server_tokens = SrvTk_FULL; + } + 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)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 { + d->script_interpreter_source = INTERPRETER_SOURCE_SHEBANG; + } + return NULL; +} +#endif + +/* 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 */ + +{ "" }, +{ "" }, +{ "" }, +{ "" }, +{ "", endlimit_section, NULL, OR_ALL, NO_ARGS, + "Marks end of " }, +{ "", endlimit_section, (void*)1, OR_ALL, NO_ARGS, + "Marks end of " }, +{ "" }, +{ "" }, +{ "" }, +{ "" }, +{ "" }, +{ "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\")" }, +{ "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)" }, +{ "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 +{ "ServerTokens", set_serv_tokens, NULL, RSRC_CONF, TAKE1, + "Determine tokens displayed in the Server: header - Min(imal), OS or 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" }, +{ 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 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 +#ifdef CHARSET_EBCDIC + int convert_flag; +#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", 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) + /* 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 CHARSET_EBCDIC + /* To make serving of "raw ASCII text" files easy (they serve faster + * since they don't have to be converted from EBCDIC), a new + * "magic" type prefix was invented: text/x-ascii-{plain,html,...} + * If we detect one of these content types here, we simply correct + * the type to the real text/{plain,html,...} type. Otherwise, we + * set a flag that translation is required later on. + * + * Note: convert_flag is not used in the MMAP path; + * ap_checkconv() sets a request_req flag based on content_type + */ + convert_flag = ap_checkconv(r); +#endif +#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, convert_flag)); + } +#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)", + offset, length); + } + 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_12/src/main/http_log.c b/APACHE_1_3_12/src/main/http_log.c new file mode 100644 index 0000000000..4a1e5fe2e7 --- /dev/null +++ b/APACHE_1_3_12/src/main/http_log.c @@ -0,0 +1,786 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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 + +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; + + 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) + child_pid = spawnl(_P_NOWAIT, SHELL_PATH, SHELL_PATH, "/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); + } + } +} + +void ap_open_logs(server_rec *s_main, pool *p) +{ + server_rec *virt, *q; + int replace_stderr; + + 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]; + 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; + } +#ifdef TPF + else if (tpf_child) { + /* + * 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 = stderr; + } +#endif /* TPF */ + 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 TPF + 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 /* TPF */ + 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 + + len += ap_vsnprintf(errstr + len, sizeof(errstr) - len, fmt, args); + + /* 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(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(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); +} + +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(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: + if (pl->pid != -1) { + kill(pl->pid, SIGTERM); + } + 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]); +} + + +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(p, pl, piped_log_cleanup, piped_log_cleanup_for_exec); + 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; + + 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) + child_pid = spawnl(_P_NOWAIT, SHELL_PATH, SHELL_PATH, "/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_12/src/main/http_main.c b/APACHE_1_3_12/src/main/http_main.c new file mode 100644 index 0000000000..6ba9833fab --- /dev/null +++ b/APACHE_1_3_12/src/main/http_main.c @@ -0,0 +1,7075 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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 +#ifdef USE_SHMGET_SCOREBOARD +#include +#include +#include +#endif +#ifdef SecureWare +#include +#include +#include +#endif +#ifdef WIN32 +#include "../os/win32/getopt.h" +#elif !defined(BEOS) && !defined(TPF) && !defined(NETWARE) && !defined(OS390) +#include +#endif +#ifdef HAVE_BSTRING_H +#include /* for IRIX, FD_SET calls bzero() */ +#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. + */ +extern void ap_force_library_loading(void); +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 +#include +#include +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 +int ap_thread_count = 0; +BOOL ap_main_finished = FALSE; +unsigned int ap_thread_stack_size = 65536; +#endif +int ap_standalone=0; +int ap_configtestonly=0; +int ap_docrootcheck=1; +uid_t ap_user_id=0; +char *ap_user_name=NULL; +gid_t ap_group_id=0; +#ifdef MULTIPLE_GROUPS +gid_t group_id_list[NGROUPS_MAX]; +#endif +int ap_max_requests_per_child=0; +int ap_threads_per_child=0; +int ap_excess_requests_per_child=0; +char *ap_pid_fname=NULL; +char *ap_scoreboard_fname=NULL; +char *ap_lock_fname; +char *ap_server_argv0=NULL; +struct in_addr ap_bind_address; +int ap_daemons_to_start=0; +int ap_daemons_min_free=0; +int ap_daemons_max_free=0; +int ap_daemons_limit=0; +time_t ap_restart_time=0; +int ap_suexec_enabled = 0; +int ap_listenbacklog; +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; +static listen_rec *head_listener; + +API_VAR_EXPORT char ap_server_root[MAX_STRING_LEN]=""; +char ap_server_confname[MAX_STRING_LEN]=""; +char ap_coredump_dir[MAX_STRING_LEN]; + +array_header *ap_server_pre_read_config; +array_header *ap_server_post_read_config; +array_header *ap_server_config_defines; + +/* *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; + +/* 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 *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 +int tpf_child = 0; +char tpf_server_name[INETD_SERVNAME_LENGTH+1]; +#endif /* TPF */ + +scoreboard *ap_scoreboard_image = NULL; + +/* + * 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; + +/* + * 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_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) +{ + if (pchild) { + ap_child_exit_modules(pchild, server_conf); + ap_destroy_pool(pchild); + } + chdir_for_gprof(); + exit(code); +} + +#if defined(USE_FCNTL_SERIALIZED_ACCEPT) || defined(USE_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 (USE_USLOCK_SERIALIZED_ACCEPT) + +#include + +static ulock_t uslock = NULL; + +#define accept_mutex_child_init(x) + +static void accept_mutex_init(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(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(void) +{ + if (usunsetlock(uslock) == -1) { + perror("usunsetlock"); + clean_child_exit(APEXIT_CHILDFATAL); + } +} + +#elif defined (USE_PTHREAD_SERIALIZED_ACCEPT) + +/* This code probably only works on Solaris ... but it works really fast + * on Solaris. 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 + +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(void *foo) +{ + if (accept_mutex != (void *)(caddr_t)-1 + && have_accept_mutex) { + pthread_mutex_unlock(accept_mutex); + } +} + +static void accept_mutex_child_init(pool *p) +{ + ap_register_cleanup(p, NULL, accept_mutex_child_cleanup, ap_null_cleanup); +} + +static void accept_mutex_cleanup(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; +} + +static void accept_mutex_init(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"); + exit(APEXIT_INIT); + } + close(fd); + if ((errno = pthread_mutexattr_init(&mattr))) { + perror("pthread_mutexattr_init"); + exit(APEXIT_INIT); + } + if ((errno = pthread_mutexattr_setpshared(&mattr, + PTHREAD_PROCESS_SHARED))) { + perror("pthread_mutexattr_setpshared"); + exit(APEXIT_INIT); + } + 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); + ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup); +} + +static void accept_mutex_on(void) +{ + int err; + + if (sigprocmask(SIG_BLOCK, &accept_block_mask, &accept_previous_mask)) { + perror("sigprocmask(SIG_BLOCK)"); + clean_child_exit(APEXIT_CHILDFATAL); + } + if ((err = pthread_mutex_lock(accept_mutex))) { + errno = err; + perror("pthread_mutex_lock"); + clean_child_exit(APEXIT_CHILDFATAL); + } + have_accept_mutex = 1; +} + +static void accept_mutex_off(void) +{ + int err; + + if ((err = pthread_mutex_unlock(accept_mutex))) { + errno = err; + perror("pthread_mutex_unlock"); + clean_child_exit(APEXIT_CHILDFATAL); + } + /* There is a slight race condition right here... if we were to die right + * now, we'd do another pthread_mutex_unlock. Now, doing that would let + * another process into the mutex. pthread mutexes are designed to be + * fast, as such they don't have protection for things like testing if the + * thread owning a mutex is actually unlocking it (or even any way of + * testing who owns the mutex). + * + * If we were to unset have_accept_mutex prior to releasing the mutex + * then the race could result in the server unable to serve hits. Doing + * it this way means that the server can continue, but an additional + * child might be in the critical section ... at least it's still serving + * hits. + */ + have_accept_mutex = 0; + if (sigprocmask(SIG_SETMASK, &accept_previous_mask, NULL)) { + perror("sigprocmask(SIG_SETMASK)"); + clean_child_exit(1); + } +} + +#elif defined (USE_SYSVSEM_SERIALIZED_ACCEPT) + +#include +#include +#include + +#ifdef NEED_UNION_SEMUN +/* it makes no sense, but this isn't defined on solaris */ +union semun { + long 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(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(x) + +static void accept_mutex_init(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, 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(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(void) +{ + while (semop(sem_id, &op_off, 1) < 0) { + if (errno != EINTR) { + perror("accept_mutex_off"); + clean_child_exit(APEXIT_CHILDFATAL); + } + } +} + +#elif defined(USE_FCNTL_SERIALIZED_ACCEPT) +static struct flock lock_it; +static struct flock unlock_it; + +static int lock_fd = -1; + +#define accept_mutex_child_init(x) + +/* + * Initialize mutex lock. + * Must be safe to call this on a restart. + */ +static void accept_mutex_init(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(p, ap_lock_fname, O_CREAT | O_WRONLY | O_EXCL, 0644); + 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(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(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); + } +} + +#elif defined(USE_FLOCK_SERIALIZED_ACCEPT) + +static int lock_fd = -1; + +static void accept_mutex_cleanup(void *foo) +{ + unlink(ap_lock_fname); +} + +/* + * Initialize mutex lock. + * Done by each child at it's birth + */ +static void accept_mutex_child_init(pool *p) +{ + + lock_fd = ap_popenf(p, ap_lock_fname, O_WRONLY, 0600); + if (lock_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(pool *p) +{ + expand_lock_fname(p); + unlink(ap_lock_fname); + lock_fd = ap_popenf(p, ap_lock_fname, O_CREAT | O_WRONLY | O_EXCL, 0600); + if (lock_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, ap_null_cleanup); +} + +static void accept_mutex_on(void) +{ + int ret; + + while ((ret = flock(lock_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(void) +{ + if (flock(lock_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); + } +} + +#elif defined(USE_OS2SEM_SERIALIZED_ACCEPT) + +static HMTX lock_sem = -1; + +static void accept_mutex_cleanup(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(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, ap_null_cleanup); + } +} + +/* + * Initialize mutex lock. + * Must be safe to call this on a restart. + */ +static void accept_mutex_init(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, ap_null_cleanup); +} + +static void accept_mutex_on(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(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); + } +} + +#elif defined(USE_TPF_CORE_SERIALIZED_ACCEPT) + +static int tpf_core_held; + +static void accept_mutex_cleanup(void *foo) +{ + if(tpf_core_held) + coruc(RESOURCE_KEY); +} + +#define accept_mutex_init(x) + +static void accept_mutex_child_init(pool *p) +{ + ap_register_cleanup(p, NULL, accept_mutex_cleanup, ap_null_cleanup); + tpf_core_held = 0; +} + +static void accept_mutex_on(void) +{ + corhc(RESOURCE_KEY); + tpf_core_held = 1; + ap_check_signals(); +} + +static void accept_mutex_off(void) +{ + coruc(RESOURCE_KEY); + tpf_core_held = 0; + ap_check_signals(); +} + +#else +/* Default --- no serialization. Other methods *could* go here, + * as #elifs... + */ +#if !defined(MULTITHREAD) +/* Multithreaded systems don't complete between processes for + * the sockets. */ +#define NO_SERIALIZED_ACCEPT +#define accept_mutex_child_init(x) +#define accept_mutex_init(x) +#define accept_mutex_on() +#define accept_mutex_off() +#endif +#endif + +/* 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 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]\n", pad); +#ifdef WIN32 + fprintf(stderr, " %s [-n service] [-k signal] [-i] [-u]\n", pad); +#endif + fprintf(stderr, "Options:\n"); +#ifdef SHARED_CORE + fprintf(stderr, " -R directory : specify an alternate location for shared object files\n"); +#endif + fprintf(stderr, " -D name : define a name for use in 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"); + 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"); +#ifdef WIN32 + fprintf(stderr, " -n name : set service name and use its ServerConfigFile\n"); + fprintf(stderr, " -k 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, " -i : install an Apache service\n"); + fprintf(stderr, " -u : uninstall an Apache service\n"); +#endif + +#ifdef 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; + +#define get_tsd TSD* tsd = (TSD*) GetThreadDataAreaPtr(); +#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(0); + } + 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; + } +} + + +#ifndef TPF +/* + * 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); + } + } +} +#endif /* TPF */ + +#ifndef NETWARE +static APACHE_TLS void (*volatile alarm_fn) (int) = NULL; +#endif +#ifdef WIN32 +static APACHE_TLS unsigned int alarm_expiry_time = 0; +#endif /* WIN32 */ + +#if !defined(WIN32) && !defined(NETWARE) +static void alrm_handler(int sig) +{ + if (alarm_fn) { + (*alarm_fn) (sig); + } +} +#endif + +unsigned int ap_set_callback_and_alarm(void (*fn) (int), int x) +{ + unsigned int old; + +#if defined(WIN32) || defined(NETWARE) +#ifdef NETWARE + get_tsd +#endif + old = alarm_expiry_time; + + if (old) + old -= time(0); + if (x == 0) { + alarm_fn = NULL; + alarm_expiry_time = 0; + } + else { + alarm_fn = fn; + alarm_expiry_time = time(NULL) + 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) +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 */ + + + +/* 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); + } +} + + + + +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) && + (read(lsd, dummybuf, sizeof dummybuf) > 0)); + + /* 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 +/* + * 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: + * 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 + */ + } + else { /* only worry about permissions if we attached the segment */ + 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) +{ +} + +#elif defined(USE_TPF_SCOREBOARD) + +static void cleanup_scoreboard_heap() +{ + int rv; + rv = rsysc(ap_scoreboard_image, SCOREBOARD_FRAMES, SCOREBOARD_NAME); + if(rv == RSYSC_ERROR) { + ap_log_error(APLOG_MARK, APLOG_ERR, server_conf, + "rsysc() could not release scoreboard system heap"); + } +} + +static void setup_shared_mem(pool *p) +{ + cinfc(CINFC_WRITE, CINFC_CMMCTK2); + ap_scoreboard_image = (scoreboard *) gsysc(SCOREBOARD_FRAMES, SCOREBOARD_NAME); + + if (!ap_scoreboard_image) { + fprintf(stderr, "httpd: Could not create scoreboard system heap storage.\n"); + exit(APEXIT_INIT); + } + + ap_register_cleanup(p, NULL, cleanup_scoreboard_heap, ap_null_cleanup); + ap_scoreboard_image->global.running_generation = 0; +} + +static void reopen_scoreboard(pool *p) +{ + cinfc(CINFC_WRITE, CINFC_CMMCTK2); +} + +#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(p, ap_scoreboard_fname, O_CREAT | O_BINARY | O_RDWR, 0666); + 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(p, ap_scoreboard_fname, O_CREAT | O_BINARY | O_RDWR, 0644); + 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 */ +static void clean_parent_exit(int code) __attribute__((noreturn)); +static void clean_parent_exit(int code) +{ +#ifdef NETWARE + AMCSocketCleanup(); + ap_main_finished = TRUE; +#endif + /* Clear the pool - including any registered cleanups */ + ap_destroy_pool(pglobal); + exit(code); +} + +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; + } + 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_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; +#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. + */ + tv.tv_sec = waittime / 1000000; + tv.tv_usec = waittime % 1000000; + waittime = waittime * 4; + ap_select(0, NULL, NULL, NULL, &tv); + + /* 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; + + waitret = waitpid(pid, &status, WNOHANG); + if (waitret == pid || waitret == -1) { + ap_scoreboard_image->parent[i].pid = 0; + 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; + } + } +#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_DEATH, 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(); + if (ap_scoreboard_image->servers[n].status != SERVER_DEAD && + kill((pid = ap_scoreboard_image->parent[n].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)); + return(pid); + } + } + return 0; +} +#endif + +/* Finally, this routine is used by the caretaker process to wait for + * a while... + */ + +/* 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; + 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; + h[hi++] = (HANDLE) ap_scoreboard_image->parent[pi].pid; + } + + } + 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); +#elif defined(NETWARE) + struct timeval tv; + int ret = 0; + + ++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 + } + + if (ret == -1 && errno == EINTR) { + return -1; + } + + if (ret > 0) { + return ret; + } + + tv.tv_sec = SCOREBOARD_MAINTENANCE_INTERVAL / 1000000; + tv.tv_usec = SCOREBOARD_MAINTENANCE_INTERVAL % 1000000; + ap_select(0, NULL, NULL, NULL, &tv); + 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 */ +} + + +#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[] */ + + +/* handle all varieties of core dumping signals */ +static void sig_coredump(int sig) +{ + chdir(ap_coredump_dir); + signal(sig, SIG_DFL); +#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; +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. + */ + + 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. + */ + +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 */ +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) +{ +#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) +/* Don't detach for MPE because child processes can't survive the death of + the parent. */ + 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); + 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(); +#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) + 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. + */ + if (setgid(ap_group_id) == -1) { + 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); + } + + /* 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 /* ndef WIN32 */ +} + +/* check to see if we have the 'suexec' setuid wrapper installed */ +static int init_suexec(void) +{ + int result = 0; + +#ifndef WIN32 + 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) +{ + /* 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 + ap_log_error(APLOG_MARK, APLOG_WARNING, server_conf, + "setsockopt: (TCP_NODELAY)"); + } +} + +#else +#define sock_disable_nagle(s) /* 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(p, s); /* arrange to close on exec or restart */ +#ifdef TPF + os_note_additional_cleanups(p, s); +#endif /* TPF */ +#endif + +#ifndef _OSD_POSIX + if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(int)) < 0) { + ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf, + "make_sock: for %s, setsockopt: (SO_REUSEADDR)", addr); +#ifdef BEOS + closesocket(s); +#else + close(s); +#endif + ap_unblock_alarms(); + return -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); +#ifdef BEOS + closesocket(s); +#else + close(s); +#endif + + ap_unblock_alarms(); + return -1; + } +#endif + + sock_disable_nagle(s); + 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 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 + +#ifdef BEOS + closesocket(s); +#else + close(s); +#endif + 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); +#ifdef BEOS + closesocket(s); +#else + close(s); +#endif + ap_unblock_alarms(); + exit(1); + } + +#ifdef WORKAROUND_SOLARIS_BUG + s = ap_slack(s, AP_SLACK_HIGH); + + ap_note_cleanups_for_socket(p, s); /* 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); +#ifdef BEOS + closesocket(s); +#else + close(s); +#endif + return -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); + +#ifdef NETWARE + ThreadSwitch(); +#endif + + 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; +} + + +/* 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(p, fd); + } + if (fd >= 0) { + 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 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 { +#ifdef NETWARE + ThreadSwitch(); +#endif + 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 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_TPF_SCOREBOARD + printf(" -D USE_TPF_SCOREBOARD\n"); +#endif +#ifdef USE_TPF_DAEMON + printf(" -D USE_TPF_DAEMON\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 USE_FCNTL_SERIALIZED_ACCEPT + printf(" -D USE_FCNTL_SERIALIZED_ACCEPT\n"); +#endif +#ifdef USE_FLOCK_SERIALIZED_ACCEPT + printf(" -D USE_FLOCK_SERIALIZED_ACCEPT\n"); +#endif +#ifdef USE_USLOCK_SERIALIZED_ACCEPT + printf(" -D USE_USLOCK_SERIALIZED_ACCEPT\n"); +#endif +#ifdef USE_SYSVSEM_SERIALIZED_ACCEPT + printf(" -D USE_SYSVSEM_SERIALIZED_ACCEPT\n"); +#endif +#ifdef USE_PTHREAD_SERIALIZED_ACCEPT + printf(" -D USE_PTHREAD_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 +#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 + +/* This list displays the compiled-in default paths: */ +#ifdef HTTPD_ROOT + printf(" -D HTTPD_ROOT=\"" HTTPD_ROOT "\"\n"); +#endif +#ifdef SUEXEC_BIN + 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_XFERLOG + printf(" -D DEFAULT_XFERLOG=\"" DEFAULT_XFERLOG "\"\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) +{ + 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); + 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 *)); +} + +#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); + + /* needs to be done before we switch UIDs so we have permissions */ + reopen_scoreboard(pchild); + SAFE_ACCEPT(accept_mutex_child_init(pchild)); + + set_group_privs(); +#ifdef MPE + /* Only try to switch if we're running as MANAGER.SYS */ + if (geteuid() == 1 && ap_user_id > 1) { + 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 */ + if (!geteuid() && ( +#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 + + 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) { +#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 + 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_EMERG, server_conf, + "offload device inactive"); + clean_child_exit(APEXIT_CHILDFATAL); + break; + default: + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 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" */ + +#ifdef TPF + if (csd == 0) /* 0 is invalid socket for TPF */ + continue; +#endif + + /* 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_fd(ptrans, csd); + + /* 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. + */ + + clen = sizeof(sa_server); + if (getsockname(csd, &sa_server, &clen) < 0) { + ap_log_error(APLOG_MARK, APLOG_ERR, server_conf, "getsockname"); + continue; + } + + sock_disable_nagle(csd); + + (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_fd(ptrans, dupped_csd); + + /* 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); + + 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 + 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; +#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(0); + + 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; + +static void perform_idle_server_maintenance(void) +{ + int i; + int to_kill; + int idle_count; + short_score *ss; + time_t now = time(0); + 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; + kill(ps->pid, SIGALRM); + } + } +#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 + */ + kill(ap_scoreboard_image->parent[to_kill].pid, SIGUSR1); + idle_spawn_rate = 1; + } + 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) { + 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); + ptrans = ap_make_sub_pool(pconf); + + 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(pconf, scoreboard_fd); + } +#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()); + 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 + */ + if (pid >= 0) { + 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(0)); + --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(); +#ifdef TPF + shutdown_pending = os_check_server(tpf_server_name); + ap_check_signals(); + sleep(1); +#endif /*TPF */ + } + + 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; + +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:f: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': + 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 (ap_standalone) { + if(!tpf_child) { + memcpy(tpf_server_name, input_parms.parent.servname, + INETD_SERVNAME_LENGTH); + tpf_server_name[INETD_SERVNAME_LENGTH+1] = '\0'; + ap_open_logs(server_conf, pconf); + } + ap_set_version(); + ap_init_modules(pconf, server_conf); + version_locked++; + if(tpf_child) { + copy_listeners(pconf); + reset_tpf_listeners(&input_parms.child); + server_conf->error_log = NULL; +#ifdef SCOREBOARD_FILE + scoreboard_fd = input_parms.child.scoreboard_fd; + ap_scoreboard_image = &_scoreboard_image; +#else /* must be USE_TPF_SCOREBOARD or USE_SHMGET_SCOREBOARD */ + ap_scoreboard_image = + (scoreboard *)input_parms.child.scoreboard_heap; +#endif + 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 + /* Only try to switch if we're running as MANAGER.SYS */ + if (geteuid() == 1 && ap_user_id > 1) { + 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 */ + if (!geteuid() && 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); + exit(1); + } +#endif + if (ap_setjmp(jmpbuffer)) { + exit(0); + } + +#ifdef TPF +/* TPF's Internet Daemon passes the incoming socket nbr (inetd mode only) */ + sock_in = sock_out = input_parms.parent.socket; +/* TPF also needs a signal set for alarm in inetd mode */ + signal(SIGALRM, alrm_handler); +#elif defined(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(void) +{ + joblist *job; + int sock; + +#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); + 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*) GetThreadDataAreaPtr(); + ThreadSwitchWithDelay(); + } + + SetCurrentNameSpace(4); + SetTargetNameSpace(4); + + ap_thread_count++; +#endif + + 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*) GetThreadDataAreaPtr(); +#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(); + if (csd == -1) + break; /* time to exit */ + + requests_this_child++; + + ap_note_cleanups_for_socket(ptrans, csd); + + /* + * 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); + + (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(ptrans, dupped_csd); +#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) { +#ifdef NETWARE + ThreadSwitch(); +#endif + (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; + + 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); + +#ifdef NETWARE + ap_thread_count--; +#endif +} + + +#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; + + memset(&Tsd, 0, sizeof(TSD)); + SaveThreadDataAreaPtr(&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(p, fd); + 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; + int total_jobs = 0; + thread **child_handles; + int rv; + int i; + struct timeval tv; + int my_pid; + + int count_select_errors = 0; + pool *pchild; + + 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(0); + } + + 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.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 == EINTR); + + if (csd == INVALID_SOCKET) { + 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); + + 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(0); + } + 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(0); + } + 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 (nthreads > max_daemons_limit) { + max_daemons_limit = nthreads; + } + + while (1) { + if (max_jobs_per_exe && (total_jobs > max_jobs_per_exe)) { + /* MaxRequestsPerChild hit... + */ + 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; + 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; + } + + pCommand = ap_psprintf(p, "\"%s\" -Z %s -f \"%s\"", buf, exit_event_name, ap_server_confname); + + for (i = 1; i < argc; i++) { + 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; + } + + /* Give the read in of teh 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_USESHOWWINDOW | STARTF_USESTDHANDLES; + si.wShowWindow = SW_HIDE; + si.hStdInput = hPipeRead; + + 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); + + 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); + + 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, + ¤t_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, restart the child process */ + 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, ¤t_live_processes); + } + processes_to_create = nchild; + ++ap_my_generation; + continue; + } else { + /* A child process must have exited because of MaxRequestPerChild being hit + * or a fatal error condition (seg fault, etc.). Remove the dead process + * from the process_handles and process_kill_events table and create a new + * child process. + */ + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, server_conf, + "master_main: Child processed exited (due to MaxRequestsPerChild?). Restarting the child process."); + ap_assert(cld < current_live_processes); + cleanup_process(process_handles, process_kill_events, cld, ¤t_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, ¤t_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); + + service_set_status(SERVICE_STOPPED); + 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(); +} + +int service_init() +{ + common_init(); + + ap_cpystrn(ap_server_root, HTTPD_ROOT, sizeof(ap_server_root)); + if (ap_registry_get_service_conf(pconf, ap_server_confname, sizeof(ap_server_confname), + ap_server_argv0)) + return FALSE; + + ap_setup_prelinked_modules(); + server_conf = ap_read_config(pconf, ptrans, ap_server_confname); + ap_log_pid(pconf, ap_pid_fname); + post_parse_init(); + return TRUE; +} + + +#ifdef NETWARE +extern char *optarg; + +void signal_handler(int sig) +{ + switch (sig) { + case SIGTERM: + shutdown_pending = 1; + + while(!ap_main_finished) + ThreadSwitchWithDelay(); + + break; + } + return; +} + +int main(int argc, char *argv[]) +{ + ExitThread(TSR_THREAD, 0); +} +#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; + char *service_name = NULL; + int install = 0; + int conf_specified = 0; + char *signal_to_send = NULL; + char cwd[MAX_STRING_LEN]; + +#ifdef NETWARE + TSD Tsd; + + SetCurrentNameSpace(4); + SetTargetNameSpace(4); + signal(SIGTERM, signal_handler); + memset(&Tsd, 0, sizeof(Tsd)); + SaveThreadDataAreaPtr(&Tsd); +#else + /* Service application + * Configuration file in registry at: + * HKLM\System\CurrentControlSet\Services\[Svc name]\Parameters\ConfPath + */ + if (isProcessService()) { + service_main(master_main, argc, argv); + clean_parent_exit(0); + } +#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(); + +#ifdef NETWARE + if(!*ap_server_root) { + ap_cpystrn(ap_server_root, bslash2slash(remove_filename(argv[0])), + sizeof(ap_server_root)); + } +#else + if(!GetCurrentDirectory(sizeof(cwd),cwd)) { + ap_log_error(APLOG_MARK,APLOG_WIN32ERROR, NULL, + "GetCurrentDirectory() failure"); + return -1; + } + + ap_cpystrn(cwd, ap_os_canonical_filename(pcommands, cwd), sizeof(cwd)); + ap_cpystrn(ap_server_root, cwd, sizeof(ap_server_root)); +#endif + + while ((c = getopt(argc, argv, "D:C:c:Xd:f:vVlLZ:iusStThk:n:")) != -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; +#ifdef WIN32 + case 'Z': + 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); + if (isValidService(optarg)) { + ap_registry_get_service_conf(pconf, ap_server_confname, sizeof(ap_server_confname), + optarg); + conf_specified = 1; + } + break; + case 'i': + install = 1; + break; + case 'u': + install = -1; + break; + case 'S': + ap_dump_settings = 1; + break; + case 'k': + signal_to_send = optarg; + break; +#endif /* WIN32 */ + case 'd': + optarg = ap_os_canonical_filename(pcommands, optarg); + if (!ap_os_is_path_absolute(optarg)) { + optarg = ap_pstrcat(pcommands, cwd, optarg, NULL); + ap_getparents(optarg); + } + if (optarg[strlen(optarg)-1] != '/') + optarg = ap_pstrcat(pcommands, optarg, "/", NULL); + ap_cpystrn(ap_server_root, + optarg, + sizeof(ap_server_root)); + break; + 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()); + clean_parent_exit(0); + + case 'V': + ap_set_version(); + show_compile_settings(); + clean_parent_exit(0); + + case 'l': + ap_show_modules(); + clean_parent_exit(0); + + case 'L': + ap_show_directives(); + clean_parent_exit(0); + + 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 */ + + /* ServerConfFile is found in this order: + * (1) -f or -n + * (2) [-d]/SERVER_CONFIG_FILE + * (3) ./SERVER_CONFIG_FILE + * (4) [Registry: HKLM\Software\[product]\ServerRoot]/SERVER_CONFIG_FILE + * (5) /HTTPD_ROOT/SERVER_CONFIG_FILE + */ + + if (!conf_specified) { + ap_cpystrn(ap_server_confname, SERVER_CONFIG_FILE, sizeof(ap_server_confname)); + if (access(ap_server_root_relative(pcommands, ap_server_confname), 0)) { +#ifndef NETWARE + ap_registry_get_server_root(pconf, ap_server_root, sizeof(ap_server_root)); +#endif + if (!*ap_server_root) + ap_cpystrn(ap_server_root, HTTPD_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_confname)) { + char *full_conf_path; + + full_conf_path = ap_pstrcat(pcommands, ap_server_root, "/", ap_server_confname, NULL); + full_conf_path = ap_os_canonical_filename(pcommands, full_conf_path); + ap_cpystrn(ap_server_confname, full_conf_path, sizeof(ap_server_confname)); + } + ap_getparents(ap_server_confname); + ap_no2slash(ap_server_confname); + +#ifdef WIN32 + if (install) { + if (!service_name) + service_name = ap_pstrdup(pconf, DEFAULTSERVICENAME); + if (install > 0) + InstallService(service_name, ap_server_root_relative(pcommands, ap_server_confname)); + else + RemoveService(service_name); + clean_parent_exit(0); + } + + if (service_name && signal_to_send) { + send_signal_to_service(service_name, signal_to_send); + clean_parent_exit(0); + } + + if (service_name && !conf_specified) { + printf("Unknown service: %s\n", service_name); + clean_parent_exit(0); + } +#endif + server_conf = ap_read_config(pconf, ptrans, ap_server_confname); + + if (ap_configtestonly) { + fprintf(stderr, "%s: Syntax OK\n", ap_server_root_relative(pcommands, ap_server_confname)); + clean_parent_exit(0); + } + + if (ap_dump_settings) { + clean_parent_exit(0); + } + + /* Treat -k start confpath as just -f confpath */ + if (signal_to_send && strcasecmp(signal_to_send, "start")) { + send_signal(pconf, signal_to_send); + clean_parent_exit(0); + } + +#ifndef NETWARE + if (!child && !ap_dump_settings) { + ap_log_pid(pconf, ap_pid_fname); + } +#endif + + post_parse_init(); + +#ifdef OS2 + printf("%s running...\n", ap_get_server_version()); +#endif +#if defined(WIN32) || defined(NETWARE) + if (!child) { + 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); + worker_main(); + ap_destroy_mutex(start_mutex); + destroy_event(exit_event); + } + else + master_main(argc, argv); +#endif + + 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 */ + +#ifdef OS2 +/* Shared core loader for OS/2 */ + +int ap_main(int argc, char *argv[]); /* Load time linked from libhttpd.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 +#include +#include + +#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:f:vVlLR:SZ:tTh")) != -1) { + switch (c) { + case 'D': + case 'C': + case 'c': + case 'X': + case 'd': + 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; + } + } + + /* + * 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_12/src/main/http_protocol.c b/APACHE_1_3_12/src/main/http_protocol.c new file mode 100644 index 0000000000..d325cd7510 --- /dev/null +++ b/APACHE_1_3_12/src/main/http_protocol.c @@ -0,0 +1,2886 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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 +#include "http_conf_globals.h" + +#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_OUTPUTCONVERSION_STATE(_buff, _onoff) \ + int _convert_out = ap_bgetflag(_buff, B_EBCDIC2ASCII); \ + ap_bsetflag(_buff, B_EBCDIC2ASCII, _onoff); + +#define POP_EBCDIC_OUTPUTCONVERSION_STATE(_buff) \ + ap_bsetflag(_buff, B_EBCDIC2ASCII, _convert_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 = (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; +} + +static int parse_byterange(char *range, long clength, long *start, long *end) +{ + char *dash = strchr(range, '-'); + + if (!dash) + return 0; + + if ((dash == range)) { + /* In the form "-5" */ + *start = clength - atol(dash + 1); + *end = clength - 1; + } + else { + *dash = '\0'; + dash++; + *start = atol(range); + if (*dash) + *end = atol(dash); + else /* "5-" */ + *end = clength - 1; + } + + if (*start < 0) + *start = 0; + + if (*end >= clength) + *end = clength - 1; + + if (*start > *end) + return 0; + + return (*start > 0 || *end < clength - 1); +} + +static int internal_byterange(int, long *, request_rec *, const char **, long *, + long *); + +API_EXPORT(int) ap_set_byterange(request_rec *r) +{ + const char *range, *if_range, *match; + long range_start, range_end; + + 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)) { + return 0; + } + + /* 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; + } + + if (!strchr(range, ',')) { + /* A single range */ + if (!parse_byterange(ap_pstrdup(r->pool, range + 6), r->clength, + &range_start, &range_end)) + return 0; + + r->byterange = 1; + + ap_table_setn(r->headers_out, "Content-Range", + ap_psprintf(r->pool, "bytes %ld-%ld/%ld", + range_start, range_end, r->clength)); + ap_table_setn(r->headers_out, "Content-Length", + ap_psprintf(r->pool, "%ld", range_end - range_start + 1)); + } + else { + /* a multiple range */ + const char *r_range = ap_pstrdup(r->pool, range + 6); + long tlength = 0; + + r->byterange = 2; + r->boundary = ap_psprintf(r->pool, "%lx%lx", + r->request_time, (long) getpid()); + while (internal_byterange(0, &tlength, r, &r_range, NULL, NULL)); + ap_table_setn(r->headers_out, "Content-Length", + ap_psprintf(r->pool, "%ld", tlength)); + } + + r->status = PARTIAL_CONTENT; + r->range = range + 6; + + return 1; +} + +API_EXPORT(int) ap_each_byterange(request_rec *r, long *offset, long *length) +{ + return internal_byterange(1, NULL, r, &r->range, offset, length); +} + +/* If this function is called with realreq=1, it will spit out + * the correct headers for a byterange chunk, and set offset and + * length to the positions they should be. + * + * If it is called with realreq=0, it will add to tlength the length + * it *would* have used with realreq=1. + * + * Either case will return 1 if it should be called again, and 0 + * when done. + */ +static int internal_byterange(int realreq, long *tlength, request_rec *r, + const char **r_range, long *offset, long *length) +{ + long range_start, range_end; + char *range; +#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->connection->client, 1); +#endif /*CHARSET_EBCDIC*/ + + if (!**r_range) { + if (r->byterange > 1) { + if (realreq) + ap_rvputs(r, CRLF "--", r->boundary, "--" CRLF, NULL); + else + *tlength += 4 + strlen(r->boundary) + 4; + } +#ifdef CHARSET_EBCDIC + POP_EBCDIC_OUTPUTCONVERSION_STATE(r->connection->client); +#endif /*CHARSET_EBCDIC*/ + return 0; + } + + range = ap_getword(r->pool, r_range, ','); + if (!parse_byterange(range, r->clength, &range_start, &range_end)) { +#ifdef CHARSET_EBCDIC + POP_EBCDIC_OUTPUTCONVERSION_STATE(r->connection->client); +#endif /*CHARSET_EBCDIC*/ + /* Skip this one */ + return internal_byterange(realreq, tlength, r, r_range, offset, + length); + } + + if (r->byterange > 1) { + const char *ct = make_content_type(r, r->content_type); + char ts[MAX_STRING_LEN]; + + ap_snprintf(ts, sizeof(ts), "%ld-%ld/%ld", range_start, range_end, + r->clength); + if (realreq) + ap_rvputs(r, CRLF "--", r->boundary, CRLF "Content-type: ", + ct, CRLF "Content-range: bytes ", ts, CRLF CRLF, + NULL); + else + *tlength += 4 + strlen(r->boundary) + 16 + strlen(ct) + 23 + + strlen(ts) + 4; + } + + if (realreq) { + *offset = range_start; + *length = range_end - range_start + 1; + } + else { + *tlength += range_end - range_start + 1; + } +#ifdef CHARSET_EBCDIC + POP_EBCDIC_OUTPUTCONVERSION_STATE(r->connection->client); +#endif /*CHARSET_EBCDIC*/ + return 1; +} + +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; + + 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; + + /* + * 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) { + etag = ap_psprintf(r->pool, + "%s\"%lx-%lx-%lx\"", weak, + (unsigned long) r->finfo.st_ino, + (unsigned long) r->finfo.st_size, + (unsigned long) r->mtime); + } + 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); + } + 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); + + /* 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. + */ +static int getline(char *s, int n, BUFF *in, int fold) +{ + char *pos, next; + int retval; + int total = 0; +#ifdef CHARSET_EBCDIC + /* When 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]; /* getline's two extra for \n\0 */ + const char *ll = l; + const char *uri; + conn_rec *conn = r->connection; + int major = 1, minor = 0; /* Assume HTTP/1.0 if non-"HTTP" protocol */ + int len; + + /* 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 = getline(l, sizeof(l), conn->client, 0)) <= 0) { + if ((len < 0) || ap_bgetflag(conn->client, B_EOF)) { + 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); + + /* 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"); + + if (2 == sscanf(r->protocol, "HTTP/%u.%u", &major, &minor) + && 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); + + return 1; +} + +static void get_mime_headers(request_rec *r) +{ + char field[DEFAULT_LIMIT_REQUEST_FIELDSIZE + 2]; /* getline's two extra */ + conn_rec *c = r->connection; + char *value; + char *copy; + int len; + unsigned 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 = 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.

    \n"); + return; + } + /* 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.

    \n" + "

    \n", ap_escape_html(r->pool, field), "
    \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.

    \n" + "

    \n", ap_escape_html(r->pool, copy), "
    \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); +} + +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|B_EBCDIC2ASCII, 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"); + 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"); + ap_send_error_response(r, 0); + ap_log_transaction(r); + return r; + } + } + 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 RFC2068 section 9, and 14.23): %s", r->uri); + } + if (r->status != HTTP_OK) { + ap_send_error_response(r, 0); + ap_log_transaction(r); + return r; + } + 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; + } + } + + if ((access_status = ap_run_post_read_request(r))) { + ap_die(access_status, r); + ap_log_transaction(r); + return NULL; + } + + 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... + */ + +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; +} + +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) +{ + ap_table_setn(r->err_headers_out, + r->proxyreq == STD_PROXY ? "Proxy-Authenticate" + : "WWW-Authenticate", + ap_psprintf(r->pool, "Digest realm=\"%s\", nonce=\"%lu\"", + ap_auth_name(r), 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; + } + + /* CHARSET_EBCDIC Issue's here ?!? Compare with 32/9 instead + * as we are operating on an octed stream ? + */ + 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) +{ + 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)]; + + /* mod_proxy is only HTTP/1.0, so avoid sending HTTP/1.1 error response; + * kluge around broken browsers when indicated by force-response-1.0 + */ + if (r->proxyreq != NOT_PROXY + || (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->connection->client, 1); +#endif /*CHARSET_EBCDIC*/ + + /* Output the HTTP/1.x Status-Line and the Date and Server fields */ + + ap_rvputs(r, protocol, " ", r->status_line, CRLF, NULL); + + ap_send_header_field(r, "Date", ap_gm_timestr_822(r->pool, r->request_time)); + ap_send_header_field(r, "Server", ap_get_server_version()); + + ap_table_unset(r->headers_out, "Date"); /* Avoid bogosity */ + ap_table_unset(r->headers_out, "Server"); +#ifdef CHARSET_EBCDIC + POP_EBCDIC_OUTPUTCONVERSION_STATE(r->connection->client); } +#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 field-value from the request handler method mask. + * Note that we always allow TRACE, since it is handled below. + */ +static char *make_allow(request_rec *r) +{ + return 2 + 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" : "", + ", TRACE", + NULL); +} + +API_EXPORT(int) ap_send_http_trace(request_rec *r) +{ + int rv; + + /* Get the original request */ + while (r->prev) + r = r->prev; + + if ((rv = ap_setup_client_block(r, REQUEST_NO_BODY))) + return rv; + + ap_hard_timeout("send TRACE", r); + + r->content_type = "message/http"; + ap_send_http_header(r); + + /* 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); + + ap_kill_timeout(r); + return OK; +} + +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"); + ap_table_setn(r->headers_out, "Allow", make_allow(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; + + 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->connection->client, 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->connection->client); } +#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->connection->client, 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->connection->client); +#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; + + while (ap_isdigit(*pos) || ap_isspace(*pos)) + ++pos; + if (*pos != '\0') { + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, + "Invalid Content-Length %s", lenp); + return HTTP_BAD_REQUEST; + } + + r->remaining = atol(lenp); + } + + if ((r->read_body == REQUEST_NO_BODY) && + (r->read_chunked || (r->remaining > 0))) { + 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 && (r->remaining > max_body)) { + 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 + { + /* @@@ Temporary kludge for guessing the conversion @@@ + * from looking at the MIME header. + * If no Content-Type header is found, text conversion is assumed. + */ + const char *typep = ap_table_get(r->headers_in, "Content-Type"); + int convert_in = (typep == NULL || + strncasecmp(typep, "text/", 5) == 0 || + strncasecmp(typep, "message/", 8) == 0 || + strncasecmp(typep, "multipart/", 10) == 0 || + strcasecmp (typep, "application/x-www-form-urlencoded") == 0 + ); + ap_bsetflag(r->connection->client, B_ASCII2EBCDIC, convert_in); + } +#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; +} + +static long get_chunk_size(char *b) +{ + long chunksize = 0; + + while (ap_isxdigit(*b)) { + 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; + ++b; + } + + 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 && (r->read_length > max_body)) { + 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 = 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 = 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 { + 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 = + 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->connection->client, 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->connection->client); +#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; + + if (length == 0) + return 0; + + /* Make fb unbuffered and non-blocking */ + ap_bsetflag(fb, B_RD, 0); +#ifndef TPF + 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 + */ + ap_select(fd + 1, &fds, NULL, NULL, NULL); +#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(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"); + + /* + * 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; + r->content_type = "text/html; charset=iso-8859-1"; + + if ((status == METHOD_NOT_ALLOWED) || (status == NOT_IMPLEMENTED)) + ap_table_setn(r->headers_out, "Allow", make_allow(r)); + + ap_send_http_header(r); + + if (r->header_only) { + ap_finalize_request_protocol(r); + ap_rflush(r); + return; + } + } + + 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 + "\n", title, + "\n\n

    ", h1, "

    \n", + NULL); + + switch (status) { + case HTTP_MOVED_PERMANENTLY: + case HTTP_MOVED_TEMPORARILY: + case HTTP_TEMPORARY_REDIRECT: + ap_rvputs(r, "The document has moved pool, location), "\">here.

    \n", + NULL); + break; + case HTTP_SEE_OTHER: + ap_rvputs(r, "The answer to your request is located pool, location), "\">here.

    \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), + "
    \nYou will need to ", + "configure your client to use that proxy.

    \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.

    \n", r); + break; + case BAD_REQUEST: + ap_rputs("Your browser sent a request that " + "this server could not understand.

    \n", r); + if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) { + ap_rvputs(r, error_notes, "

    \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.

    \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.

    \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), + ".

    \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.

    \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.

    \n", NULL); + if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) { + ap_rvputs(r, error_notes, "

    \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.

    \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.

    \n", NULL); + if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) { + ap_rvputs(r, error_notes, "

    \n", NULL); + } + break; + case BAD_GATEWAY: + ap_rputs("The proxy server received an invalid" CRLF + "response from an upstream server.

    " CRLF, r); + if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) { + ap_rvputs(r, error_notes, "

    \n", NULL); + } + break; + case VARIANT_ALSO_VARIES: + ap_rvputs(r, "A variant for the requested resource\n

    \n",
    +		      ap_escape_html(r->pool, r->uri),
    +		      "\n
    \nis itself a negotiable resource. " + "This indicates a configuration error.

    \n", NULL); + break; + case HTTP_REQUEST_TIME_OUT: + ap_rputs("I'm tired of waiting for your request.\n", r); + break; + case HTTP_GONE: + ap_rvputs(r, "The requested resource
    ", + ap_escape_html(r->pool, r->uri), + "
    \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
    ", + ap_escape_html(r->pool, r->uri), "
    \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.

    \n", r); + if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) { + ap_rvputs(r, error_notes, "

    \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.

    \n" + "The client sent

    \n    Expect: ",
    +	              ap_table_get(r->headers_in, "Expect"), "\n
    \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, "

    \n", NULL); + } + else { + ap_rvputs(r, "The server encountered an internal error or\n" + "misconfiguration and was unable to complete\n" + "your request.

    \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.

    \n" + "More information about this error may be available\n" + "in the server error log.

    \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, "

    \n", NULL); + * } + */ + break; + } + + if (recursive_error) { + ap_rvputs(r, "

    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("


    \n", r), r); + ap_rputs("\n", r); + } + ap_kill_timeout(r); + ap_finalize_request_protocol(r); + ap_rflush(r); +} diff --git a/APACHE_1_3_12/src/main/http_request.c b/APACHE_1_3_12/src/main/http_request.c new file mode 100644 index 0000000000..7b4ebe2f1a --- /dev/null +++ b/APACHE_1_3_12/src/main/http_request.c @@ -0,0 +1,1375 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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; +#ifdef HAVE_DRIVE_LETTERS + 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; + + + /* 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; + } + + 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); + } + + 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) +#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, iStart; + int j, test_filename_len; + + /* + * 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->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)) { + 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); + + iStart = 1; +#ifdef WIN32 + /* If the name is a UNC name, then do not walk through the + * machine and share name (e.g. \\machine\share\) + */ + if (num_dirs > 3 && test_filename[0] == '/' && test_filename[1] == '/') + iStart = 4; +#endif + + /* j keeps track of which section we're on, see core_reorder_directories */ + j = 0; + for (i = iStart; 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 ((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 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) + || entry_core->d_components > i) + 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); + } + } + overrides_here = core_dir->override; + + /* If .htaccess files are enabled, check for one. */ + + 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; + 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)); + } + + 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); + + /* + * 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; + } + + 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) +{ +#ifndef CHARSET_EBCDIC + int retval = ap_invoke_handler(r); +#else /*CHARSET_EBCDIC*/ + /* Save the EBCDIC conversion setting of the caller across subrequests */ + int convert = ap_bgetflag(r->connection->client, B_EBCDIC2ASCII); + int retval = ap_invoke_handler(r); + ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, convert); +#endif /*CHARSET_EBCDIC*/ + ap_finalize_sub_req_protocol(r); + return retval; +} + +API_EXPORT(void) ap_destroy_sub_req(request_rec *r) +{ + /* 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; + } + + /* + * 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 != -1)) { + + (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... + */ + 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); + } + 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) || !ap_auth_type(r)) { + if (!ap_some_auth_required(r)) { + decl_die(access_status ? access_status : + HTTP_INTERNAL_SERVER_ERROR, + ap_auth_type(r) ? "check access" + : "perform authentication. AuthType not set!", 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); +} + +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 = (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; + + 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); + 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 (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_12/src/main/http_vhost.c b/APACHE_1_3_12/src/main/http_vhost.c new file mode 100644 index 0000000000..0152ddda32 --- /dev/null +++ b/APACHE_1_3_12/src/main/http_vhost.c @@ -0,0 +1,948 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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 */ +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
    [: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 addresses */ +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; +} + + +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_vhost_config(FILE *f) +{ + int i; + ipaddr_chain *ic; + name_chain *nc; + char buf[MAX_STRING_LEN]; + + fprintf(f, "VirtualHost configuration:\n"); + for (i = 0; i < IPHASH_TABLE_SIZE; ++i) { + for (ic = iphash_table[i]; ic; ic = ic->next) { + if (ic->sar->host_port == 0) { + ap_snprintf(buf, sizeof(buf), "%pA:*", &ic->sar->host_addr); + } + else { + ap_snprintf(buf, sizeof(buf), "%pA:%u", &ic->sar->host_addr, + ic->sar->host_port); + } + if (ic->names == NULL) { + fprintf(f, "%-22s %s (%s:%u)\n", buf, + ic->server->server_hostname, ic->server->defn_name, + ic->server->defn_line_number); + continue; + } + 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); + } + } + } + if (default_list) { + fprintf(f, "_default_ servers:\n"); + for (ic = default_list; ic; ic = ic->next) { + if (ic->sar->host_port == 0) { + fprintf(f, "port * "); + } + else { + fprintf(f, "port %u ", ic->sar->host_port); + } + fprintf(f, "server %s (%s:%u)\n", + ic->server->server_hostname, ic->server->defn_name, + ic->server->defn_line_number); + } + } +} + +/* compile the tables and such we need to do the run-time vhost lookups */ +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 *new = new_ipaddr_chain(p, NULL, sar); + + *iphash_table_tail[bucket] = new; + iphash_table_tail[bucket] = &new->next; + + /* Notice that what we've done is insert an ipaddr_chain with + * both server and names NULL. Remember that. + */ + } + + /* 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) { + /* add it to default bucket for each appropriate sar + * since we need to do a port test + */ + ipaddr_chain *other; + + other = find_default_server(sar->host_port); + if (other && other->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); + } + has_default_vhost_addr = 1; + ic = new_ipaddr_chain(p, s, sar); + ic->next = default_list; + default_list = ic; + } + else { + /* see if it matches something we've already got */ + ic = find_ipaddr(&sar->host_addr, sar->host_port); + + /* the first time we encounter a NameVirtualHost address + * ic->server will be NULL, on subsequent encounters + * ic->names will be non-NULL. + */ + if (ic && (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); + } + } + else if (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; + } + else { + 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; + } + } + } + + /* 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) { + ipaddr_chain **pic = &iphash_table[i]; + + 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; + } + } + } + +#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. + */ +static void fix_hostname(request_rec *r) +{ + char *host = ap_palloc(r->pool, strlen(r->hostname) + 1); + const char *src; + char *dst; + + /* check and copy the host part */ + src = r->hostname; + dst = host; + while (*src) { + if (!ap_isalnum(*src) && *src != '.' && *src != '-') { + if (*src == ':') + break; + else + goto bad; + } else { + *dst++ = *src++; + } + } + /* check the port part */ + if (*src++ == ':') { + while (*src) { + if (!ap_isdigit(*src++)) { + goto bad; + } + } + } + /* 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 values */ + /* XXX: If this is a NameVirtualHost then we may not be doing the Right Thing + * consider: + * + * NameVirtualHost 10.1.1.1 + * + * ServerName v1 + * + * + * ServerName v2 + * + * + * 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; + } + } +} + + +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. + */ +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; + } + + /* There's certainly no name-vhosts with this address, they would have + * been matched above. + */ + conn->vhost_lookup_data = NULL; + + /* maybe there's a default server matching this port */ + trav = find_default_server(port); + if (trav) { + conn->server = trav->server; + } + + /* otherwise we're stuck with just the main server */ +} diff --git a/APACHE_1_3_12/src/main/rfc1413.c b/APACHE_1_3_12/src/main/rfc1413.c new file mode 100644 index 0000000000..c503be185c --- /dev/null +++ b/APACHE_1_3_12/src/main/rfc1413.c @@ -0,0 +1,266 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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 */ + +static JMP_BUF timebuf; + +/* ident_timeout - handle timeouts */ +static void ident_timeout(int sig) +{ + ap_longjmp(timebuf, sig); +} + +/* 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 < 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 */ +char *ap_rfc1413(conn_rec *conn, server_rec *srv) +{ + static char user[RFC1413_USERLEN + 1]; /* XXX */ + static char *result; + static int sock; + + result = FROM_UNKNOWN; + + sock = ap_psocket(conn->pool, AF_INET, SOCK_STREAM, IPPROTO_TCP); + 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. + */ + 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); + ap_pclosesocket(conn->pool, sock); + conn->remote_logname = result; + + return conn->remote_logname; +} diff --git a/APACHE_1_3_12/src/main/util.c b/APACHE_1_3_12/src/main/util.c new file mode 100644 index 0000000000..5b8fba06d6 --- /dev/null +++ b/APACHE_1_3_12/src/main/util.c @@ -0,0 +1,2186 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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() +{ + 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); +} +/* + * 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 paseses, 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 WIN32 + /* 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/ + */ +API_EXPORT(char *) ap_make_dirstr_prefix(char *d, const char *s, int n) +{ + 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 { + 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); +} + +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(OS2) || defined(WIN32) || defined(NETWARE) + /* Don't allow '&' in parameters under OS/2. */ + /* This can be used to send commands to the shell. */ + if (*s == '&') { + *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 & 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 + * 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); + } +} + +/* 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_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; + + 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], "<", 4); + j += 3; + } + else if (s[i] == '>') { + memcpy(&x[j], ">", 4); + j += 3; + } + else if (s[i] == '&') { + memcpy(&x[j], "&", 5); + j += 4; + } + 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)); +} + +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); +#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) +/* 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
    [:port] + * :port is permitted if 'port' is not NULL + */ +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, '.')) { + for (x = 0; p->h_aliases[x]; ++x) { + if (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); +} + +char *ap_get_local_host(pool *a) +{ +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 256 +#endif + char str[MAXHOSTNAMELEN]; + char *server_hostname; + 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 */ + perror("Unable to gethostname"); + exit(1); + } + str[sizeof(str) - 1] = '\0'; + if ((!(p = gethostbyname(str))) || (!(server_hostname = find_fqdn(a, p)))) { + fprintf(stderr, "%s: cannot determine local host name.\n", + ap_server_argv0); + fprintf(stderr, "Use the ServerName directive to set it manually.\n"); + exit(1); + } + + 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); +} + +#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); +}; + +/* quotes in the string are doubled up. + * Used to escape quotes in args passed to OS/2's cmd.exe + */ +char *ap_double_quotes(pool *p, char *str) +{ + int num_quotes = 0; + int len = 0; + char *quote_doubled_str, *dest; + + while (str[len]) { + num_quotes += str[len++] == '\"'; + } + + 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; +} +#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; +} diff --git a/APACHE_1_3_12/src/main/util_date.c b/APACHE_1_3_12/src/main/util_date.c new file mode 100644 index 0000000000..5111a600f0 --- /dev/null +++ b/APACHE_1_3_12/src/main/util_date.c @@ -0,0 +1,321 @@ +/* ==================================================================== + * Copyright (c) 1996-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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 +#include + +/* + * 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 + * - 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 , 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_12/src/main/util_md5.c b/APACHE_1_3_12/src/main/util_md5.c new file mode 100644 index 0000000000..368ddf63b2 --- /dev/null +++ b/APACHE_1_3_12/src/main/util_md5.c @@ -0,0 +1,229 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/************************************************************************ + * 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]; + long length = 0; + int nbytes; + + ap_MD5Init(&context); + while ((nbytes = fread(buf, 1, sizeof(buf), infile))) { + length += nbytes; + 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]; + long length = 0; + unsigned int nbytes; + + ap_MD5Init(&context); + while ((nbytes = fread(buf, 1, sizeof(buf), infile))) { + length += nbytes; + ap_MD5Update(&context, buf, nbytes); + } + rewind(infile); + return ap_md5contextTo64(p, &context); +} + +#endif /* CHARSET_EBCDIC */ diff --git a/APACHE_1_3_12/src/main/util_script.c b/APACHE_1_3_12/src/main/util_script.c new file mode 100644 index 0000000000..3c41fe175e --- /dev/null +++ b/APACHE_1_3_12/src/main/util_script.c @@ -0,0 +1,1159 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +#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 +#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. + * + * XXXX: note that the WIN32 code uses one of the suexec strings + * to pass an interpreter name. Remember this if changing the way they + * are handled in create_argv. + * + */ +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")) { + ap_table_addn(e, "COMSPEC", env_temp); + } + if (env_temp = getenv("ETC")) { + ap_table_addn(e, "ETC", env_temp); + } + if (env_temp = getenv("DPATH")) { + ap_table_addn(e, "DPATH", env_temp); + } + if (env_temp = getenv("PERLLIB_PREFIX")) { + 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_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); +} + + +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", (size + 512) / 1024); + } + else if (size < 103809024) { + ap_rprintf(r, "%4.1fM", size / 1048576.0); + } + else { + ap_rprintf(r, "%4dM", (size + 524288) / 1048576); + } +} + +#if defined(OS2) || defined(WIN32) +static char **create_argv_cmd(pool *p, char *av0, const char *args, char *path) +{ + register int x, n; + char **av; + char *w; + + for (x = 0, n = 2; args[x]; x++) { + if (args[x] == '+') { + ++n; + } + } + + /* Add extra strings to array. */ + n = n + 2; + + av = (char **) ap_palloc(p, (n + 1) * sizeof(char *)); + av[0] = av0; + + /* Now insert the extra strings we made room for above. */ + av[1] = strdup("/C"); + av[2] = strdup(path); + + for (x = (1 + 2); x < n; x++) { + w = ap_getword(p, &args, '+'); + ap_unescape_url(w); + av[x] = ap_escape_shell_cmd(p, w); + } + av[n] = NULL; + return av; +} +#endif + + +API_EXPORT(int) ap_call_exec(request_rec *r, child_info *pinfo, char *argv0, + char **env, int shellcmd) +{ + int pid = 0; +#if defined(RLIMIT_CPU) || defined(RLIMIT_NPROC) || \ + defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined (RLIMIT_AS) + + core_dir_config *conf; + conf = (core_dir_config *) ap_get_module_config(r->per_dir_config, + &core_module); + +#endif + +#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 (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 *arguments = NULL; + char *ext = NULL; + char *exename = NULL; + char *s = NULL; + char *quoted_filename; + 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); + } + + /* + * Look at the arguments... + */ + arguments = ""; + if ((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. + */ + ap_unescape_url(arguments); + arguments = ap_escape_shell_cmd(r->pool, arguments); + } + + /* + * We have the interpreter (if there is one) and we have + * the arguments (if there are any). + * Build the command string to pass to CreateProcess. + */ + quoted_filename = ap_pstrcat(r->pool, "\"", r->filename, "\"", NULL); + if (interpreter && *interpreter) { + pCommand = ap_pstrcat(r->pool, interpreter, " ", + quoted_filename, " ", arguments, NULL); + } + else { + pCommand = ap_pstrcat(r->pool, quoted_filename, " ", arguments, NULL); + } + + } else { + + char *shell_cmd = "CMD.EXE /C "; + OSVERSIONINFO osver; + osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + + /* + * Use CMD.EXE for NT, COMMAND.COM for WIN95 + */ + if (GetVersionEx(&osver)) { + if (osver.dwPlatformId != VER_PLATFORM_WIN32_NT) { + shell_cmd = "COMMAND.COM /C "; + } + } + pCommand = ap_pstrcat(r->pool, shell_cmd, argv0, 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_USESHOWWINDOW | STARTF_USESTDHANDLES; + 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++; + } + + if (CreateProcess(NULL, pCommand, NULL, NULL, TRUE, + 0, + pEnvBlock, + ap_make_dirstr_parent(r->pool, r->filename), + &si, &pi)) { + if (fileType == eFileTypeEXE16) { + /* 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 ((!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 ((!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_12/src/main/util_uri.c b/APACHE_1_3_12/src/main/util_uri.c new file mode 100644 index 0000000000..10eb5dc0d0 --- /dev/null +++ b/APACHE_1_3_12/src/main/util_uri.c @@ -0,0 +1,599 @@ +/* ==================================================================== + * Copyright (c) 1998-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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; + + 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) +{ + struct hostent *hp = gethostbyname(hostname); + return (hp == NULL) ? NULL : ap_pduphostent(p, hp); +} + + +/* Unparse a uri_components structure to an URI string. + * Optionally suppress the password for security reasons. + */ +API_EXPORT(char *) ap_unparse_uri_components(pool *p, const uri_components *uptr, unsigned flags) +{ + char *ret = ""; + + /* If suppressing the site part, omit both user name & scheme://hostname */ + if (!(flags & UNP_OMITSITEPART)) { + + /* Construct a "user:password@" string, honoring the passed UNP_ flags: */ + if (uptr->user||uptr->password) + ret = ap_pstrcat (p, + (uptr->user && !(flags & UNP_OMITUSER)) ? uptr->user : "", + (uptr->password && !(flags & UNP_OMITPASSWORD)) ? ":" : "", + (uptr->password && !(flags & UNP_OMITPASSWORD)) + ? ((flags & UNP_REVEALPASSWORD) ? uptr->password : "XXXXXXXX") + : "", + "@", NULL); + + /* Construct scheme://site string */ + if (uptr->hostname) { + int is_default_port; + + is_default_port = + (uptr->port_str == NULL || + uptr->port == 0 || + uptr->port == ap_default_port_for_scheme(uptr->scheme)); + + ret = ap_pstrcat (p, + uptr->scheme, "://", ret, + uptr->hostname ? uptr->hostname : "", + is_default_port ? "" : ":", + is_default_port ? "" : uptr->port_str, + NULL); + } + } + + /* Should we suppress all path info? */ + if (!(flags & UNP_OMITPATHINFO)) { + /* Append path, query and fragment strings: */ + ret = ap_pstrcat (p, + ret, + uptr->path ? uptr->path : "", + (uptr->query && !(flags & UNP_OMITQUERY)) ? "?" : "", + (uptr->query && !(flags & UNP_OMITQUERY)) ? uptr->query : "", + (uptr->fragment && !(flags & UNP_OMITQUERY)) ? "#" : NULL, + (uptr->fragment && !(flags & UNP_OMITQUERY)) ? uptr->fragment : NULL, + NULL); + } + return ret; +} + +/* The regex version of parse_uri_components has the advantage that it is + * relatively easy to understand and extend. But it has the disadvantage + * that the regexes are complex enough that regex libraries really + * don't do a great job with them performancewise. + * + * The default is a hand coded scanner that is two orders of magnitude + * faster. + */ +#ifdef UTIL_URI_REGEX + +static regex_t re_uri; +static regex_t re_hostpart; + +void ap_util_uri_init(void) +{ + int ret; + const char *re_str; + + /* This is a modified version of the regex that appeared in + * draft-fielding-uri-syntax-01. It doesnt allow the uri to contain a + * scheme but no hostinfo or vice versa. + * + * draft-fielding-uri-syntax-01.txt, section 4.4 tells us: + * + * Although the BNF defines what is allowed in each component, it is + * ambiguous in terms of differentiating between a site component and + * a path component that begins with two slash characters. + * + * RFC2068 disambiguates this for the Request-URI, which may only ever be + * the "abs_path" portion of the URI. So a request "GET //foo/bar + * HTTP/1.1" is really referring to the path //foo/bar, not the host foo, + * path /bar. Nowhere in RFC2068 is it possible to have a scheme but no + * hostinfo or a hostinfo but no scheme. (Unless you're proxying a + * protocol other than HTTP, but this parsing engine probably won't work + * for other protocols.) + * + * 12 3 4 5 6 7 8 */ + re_str = "^(([^:/?#]+)://([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$"; + /* ^scheme--^ ^site---^ ^path--^ ^query^ ^frag */ + if ((ret = regcomp(&re_uri, re_str, REG_EXTENDED)) != 0) { + char line[1024]; + + /* Make a readable error message */ + ret = regerror(ret, &re_uri, line, sizeof line); + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL, + "Internal error: regcomp(\"%s\") returned non-zero (%s) - " + "possibly due to broken regex lib! " + "Did you define WANTHSREGEX=yes?", + re_str, line); + + exit(1); + } + + /* This is a sub-RE which will break down the hostinfo part, + * i.e., user, password, hostname and port. + * $ 12 3 4 5 6 7 */ + re_str = "^(([^:]*)(:(.*))?@)?([^@:]*)(:([0-9]*))?$"; + /* ^^user^ :pw ^host^ ^:[port]^ */ + if ((ret = regcomp(&re_hostpart, re_str, REG_EXTENDED)) != 0) { + char line[1024]; + + /* Make a readable error message */ + ret = regerror(ret, &re_hostpart, line, sizeof line); + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL, + "Internal error: regcomp(\"%s\") returned non-zero (%s) - " + "possibly due to broken regex lib! " + "Did you define WANTHSREGEX=yes?", + re_str, line); + + exit(1); + } +} + + +/* 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) +{ + int ret; + regmatch_t match[10]; /* This must have at least as much elements + * as there are braces in the re_strings */ + + ap_assert (uptr != NULL); + + /* 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; + + ret = ap_regexec(&re_uri, uri, re_uri.re_nsub + 1, match, 0); + + if (ret != 0) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL, + "ap_regexec() could not parse uri (\"%s\")", + uri); + + return HTTP_BAD_REQUEST; + } + + if (match[2].rm_so != match[2].rm_eo) + uptr->scheme = ap_pstrndup (p, uri+match[2].rm_so, match[2].rm_eo - match[2].rm_so); + + /* empty hostinfo is valid, that's why we test $1 but use $3 */ + if (match[1].rm_so != match[1].rm_eo) + uptr->hostinfo = ap_pstrndup (p, uri+match[3].rm_so, match[3].rm_eo - match[3].rm_so); + + if (match[4].rm_so != match[4].rm_eo) + uptr->path = ap_pstrndup (p, uri+match[4].rm_so, match[4].rm_eo - match[4].rm_so); + + /* empty query string is valid, that's why we test $5 but use $6 */ + if (match[5].rm_so != match[5].rm_eo) + uptr->query = ap_pstrndup (p, uri+match[6].rm_so, match[6].rm_eo - match[6].rm_so); + + /* empty fragment is valid, test $7 use $8 */ + if (match[7].rm_so != match[7].rm_eo) + uptr->fragment = ap_pstrndup (p, uri+match[8].rm_so, match[8].rm_eo - match[8].rm_so); + + if (uptr->hostinfo) { + /* Parse the hostinfo part to extract user, password, host, and port */ + ret = ap_regexec(&re_hostpart, uptr->hostinfo, re_hostpart.re_nsub + 1, match, 0); + if (ret != 0) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, NULL, + "ap_regexec() could not parse (\"%s\") as host part", + uptr->hostinfo); + + return HTTP_BAD_REQUEST; + } + + /* $ 12 3 4 5 6 7 */ + /* "^(([^:]*)(:(.*))?@)?([^@:]*)(:([0-9]*))?$" */ + /* ^^user^ :pw ^host^ ^:[port]^ */ + + /* empty user is valid, that's why we test $1 but use $2 */ + if (match[1].rm_so != match[1].rm_eo) + uptr->user = ap_pstrndup (p, uptr->hostinfo+match[2].rm_so, match[2].rm_eo - match[2].rm_so); + + /* empty password is valid, test $3 but use $4 */ + if (match[3].rm_so != match[3].rm_eo) + uptr->password = ap_pstrndup (p, uptr->hostinfo+match[4].rm_so, match[4].rm_eo - match[4].rm_so); + + /* empty hostname is valid, and implied by the existence of hostinfo */ + uptr->hostname = ap_pstrndup (p, uptr->hostinfo+match[5].rm_so, match[5].rm_eo - match[5].rm_so); + + if (match[6].rm_so != match[6].rm_eo) { + /* Note that the port string can be empty. + * If it is, we use the default port associated with the scheme + */ + uptr->port_str = ap_pstrndup (p, uptr->hostinfo+match[7].rm_so, match[7].rm_eo - match[7].rm_so); + if (uptr->port_str[0] != '\0') { + char *endstr; + int port; + + port = strtol(uptr->port_str, &endstr, 10); + uptr->port = port; + if (*endstr != '\0') { + /* Invalid characters after ':' found */ + return HTTP_BAD_REQUEST; + } + } + else { + uptr->port = uptr->scheme ? ap_default_port_for_scheme(uptr->scheme) : DEFAULT_HTTP_PORT; + } + } + } + + if (ret == 0) + ret = HTTP_OK; + return ret; +} +#else + +/* 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 */ +} + +/* 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 = 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 = strtol(uptr->port_str, &endstr, 10); + if (*endstr == '\0') { + return HTTP_OK; + } + /* Invalid characters after ':' found */ + } + return HTTP_BAD_REQUEST; +} +#endif diff --git a/APACHE_1_3_12/src/modules/.cvsignore b/APACHE_1_3_12/src/modules/.cvsignore new file mode 100644 index 0000000000..f3c7a7c5da --- /dev/null +++ b/APACHE_1_3_12/src/modules/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/APACHE_1_3_12/src/modules/README b/APACHE_1_3_12/src/modules/README new file mode 100644 index 0000000000..df25f051f2 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/modules/example/.cvsignore b/APACHE_1_3_12/src/modules/example/.cvsignore new file mode 100644 index 0000000000..8b4c6e3da4 --- /dev/null +++ b/APACHE_1_3_12/src/modules/example/.cvsignore @@ -0,0 +1,3 @@ +Makefile +*.lo +*.so diff --git a/APACHE_1_3_12/src/modules/example/.indent.pro b/APACHE_1_3_12/src/modules/example/.indent.pro new file mode 100644 index 0000000000..a9fbe9f9a1 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/modules/example/Makefile.tmpl b/APACHE_1_3_12/src/modules/example/Makefile.tmpl new file mode 100644 index 0000000000..ac0bca36dc --- /dev/null +++ b/APACHE_1_3_12/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)/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_12/src/modules/example/README b/APACHE_1_3_12/src/modules/example/README new file mode 100644 index 0000000000..77abc097c0 --- /dev/null +++ b/APACHE_1_3_12/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: + + + SetHandler example-handler + + +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_12/src/modules/example/mod_example.c b/APACHE_1_3_12/src/modules/example/mod_example.c new file mode 100644 index 0000000000..68a6b06fe3 --- /dev/null +++ b/APACHE_1_3_12/src/modules/example/mod_example.c @@ -0,0 +1,1149 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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 + +/*--------------------------------------------------------------------------*/ +/* */ +/* 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 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, "
  85. \n", "
    \n", "
    ", + note, "\n", "
    \n", "
    [", + where, "]\n", "
    \n", "
    \n", + "
  86. \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 && (s != NULL)) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, s, "mod_example: %s", note); + } +} + +/*--------------------------------------------------------------------------*/ +/* 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); + /* + * 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("\n", r); + ap_rputs(" \n", r); + ap_rputs(" mod_example Module Content-Handler Output\n", r); + ap_rputs(" \n", r); + ap_rputs(" \n", r); + ap_rputs(" \n", r); + ap_rputs("

    mod_example Module Content-Handler Output\n", r); + ap_rputs("

    \n", r); + ap_rputs("

    \n", r); + ap_rprintf(r, " Apache HTTP Server version: \"%s\"\n", + ap_get_server_version()); + ap_rputs("
    \n", r); + ap_rprintf(r, " Server built: \"%s\"\n", ap_get_server_built()); + ap_rputs("

    \n", r);; + ap_rputs("

    \n", r); + ap_rputs(" The format for the callback trace is:\n", r); + ap_rputs("

    \n", r); + ap_rputs("
    \n", r); + ap_rputs("
    n.<routine-name>", r); + ap_rputs("(<routine-data>)\n", r); + ap_rputs("
    \n", r); + ap_rputs("
    [<applies-to>]\n", r); + ap_rputs("
    \n", r); + ap_rputs("
    \n", r); + ap_rputs("

    \n", r); + ap_rputs(" The <routine-data> is supplied by\n", r); + ap_rputs(" the routine when it requests the trace,\n", r); + ap_rputs(" and the <applies-to> is extracted\n", r); + ap_rputs(" from the configuration record at the time of the trace.\n", r); + ap_rputs(" SVR() 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); DIR()\n", r); + ap_rputs(" indicates a location in the URL or filesystem\n", r); + ap_rputs(" namespace.\n", r); + ap_rputs("

    \n", r); + ap_rprintf(r, "

    Static callbacks so far:

    \n
      \n%s
    \n", + trace); + ap_rputs("

    Request-specific callbacks so far:

    \n", r); + ap_rprintf(r, "
      \n%s
    \n", ap_table_get(r->notes, TRACE_NOTE)); + ap_rputs("

    Environment for this call:

    \n", r); + ap_rputs("
      \n", r); + ap_rprintf(r, "
    • Applies-to: %s\n
    • \n", dcfg->loc); + ap_rprintf(r, "
    • \"Example\" directive declared here: %s\n
    • \n", + (dcfg->local ? "YES" : "NO")); + ap_rprintf(r, "
    • \"Example\" inherited: %s\n
    • \n", + (dcfg->congenital ? "YES" : "NO")); + ap_rputs("
    \n", r); + ap_rputs(" \n", r); + ap_rputs("\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 up 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 , , 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 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 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, /* [7] 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_12/src/modules/experimental/.cvsignore b/APACHE_1_3_12/src/modules/experimental/.cvsignore new file mode 100644 index 0000000000..8b4c6e3da4 --- /dev/null +++ b/APACHE_1_3_12/src/modules/experimental/.cvsignore @@ -0,0 +1,3 @@ +Makefile +*.lo +*.so diff --git a/APACHE_1_3_12/src/modules/experimental/.indent.pro b/APACHE_1_3_12/src/modules/experimental/.indent.pro new file mode 100644 index 0000000000..a9fbe9f9a1 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/modules/experimental/Makefile.tmpl b/APACHE_1_3_12/src/modules/experimental/Makefile.tmpl new file mode 100644 index 0000000000..30cabaf5b7 --- /dev/null +++ b/APACHE_1_3_12/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)/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)/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_12/src/modules/experimental/mod_auth_digest.c b/APACHE_1_3_12/src/modules/experimental/mod_auth_digest.c new file mode 100644 index 0000000000..18312aea94 --- /dev/null +++ b/APACHE_1_3_12/src/modules/experimental/mod_auth_digest.c @@ -0,0 +1,2019 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * mod_auth_digest: MD5 digest authentication + * + * Originally by Alexei Kosut + * Updated to RFC-2617 by Ronald Tschalär + * 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 + * - shared-mem not completely tested yet. Seems to work ok for me, + * but... (definitely won't work on Windoze) + */ + +/* 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 +#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 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; + size_t got, 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; tottable = (client_entry**) (client_list + 1); + for (idx=0; idxtable[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; + const 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 = tmp; + + return NULL; +} + +static const char *set_nonce_lifetime(cmd_parms *cmd, void *config, + const char *t) +{ + char *endptr; + long lifetime; + + lifetime = 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} +}; + + +#ifdef HAVE_SHMEM_MM +/* + * client list code + * + * Each client is assigned a number, which is transfered 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; idxtbl_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 is memory is low. + */ +static client_entry *add_client(unsigned long key, client_entry *new, + 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, new, 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) 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, 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> 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 = { 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, 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 returns 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 + * + * ap_md5(r->pool, + * ap_pstrcat(r->pool, username, ":", ap_auth_name(r), ":", passwd)) + * + * You must implement this yourself, and will probably consist of code + * contacting the password server and retrieving 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) +{ + /* for now, just get it from pwfile */ + return conf->ha1; +} + + +static const char *get_session(const request_rec *r, + digest_header_rec *resp, + const digest_config_rec *conf) +{ + const char *ha1 = NULL, *urp; + + /* get ha1 from client list */ + if (resp->opaque && resp->client) + ha1 = resp->client->ha1; + + /* generate new session if necessary */ + if (ha1 == NULL || ha1[0] == '\0') { + urp = get_userpw_hash(r, resp, conf); + ha1 = ap_md5(r->pool, + (unsigned char *) ap_pstrcat(r->pool, urp, ":", resp->nonce, + ":", resp->cnonce, NULL)); + if (!resp->client) + resp->client = gen_client(r); + if (resp->client) + 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 *guess_domain(pool *p, const char *uri, const char *filename, + const char *dir) +{ + size_t u_len = strlen(uri), f_len = strlen(filename), d_len = strlen(dir); + const char *u, *f; + + + /* Because of things like mod_alias and mod_rewrite and the fact that + * protection is often on a directory basis (not a location basis) it + * is hard to determine the uri to put in the domain attribute. + * + * What we do is the following: first we see if the directory is + * a prefix for the uri - if this is the case we assume that therefore + * a directive was protecting this uri and we can use it + * for the domain. + */ + if (u_len >= d_len && !memcmp(uri, dir, d_len)) + return dir; + + /* Now we check for , and if we find one we send back a + * dummy uri - this is the only way to specify that the protection + * space only covers a single uri. + */ + if (dir[0] != '/') + /* This doesn't work for Amaya (ok, it's of arguable validity in + * the first place), so just return the file name instead + return "http://0.0.0.0/"; + */ + return dir; + + /* Next we find the largest common common suffix of the request-uri + * and the final file name, ignoring any extensions; this gives us a + * hint as to where any rewriting could've occured (assuming that some + * prefix of the uri is rewritten, not a suffix). + */ + u = uri + u_len - 1; /* strip any extension */ + while (u > uri && *u != '/') u--; + while (*u && *u != '.') u++; + if (*u == '.') u--; + if (*u == '/') u--; + + f = filename + f_len - 1; /* strip any extension */ + while (f > filename && *f != '/') f--; + while (*f && *f != '.') f++; + if (*f == '.') f--; + if (*f == '/') f--; + + while (*f == *u && f > filename && u > uri) u--, f--; + f++; u++; + + while (*f && *f != '/') f++, u++; /* suffix must start with / */ + + /* Now, if the directory reaches into this common suffix then we can + * take the uri with the same reach. + */ + if ((unsigned long) (f-filename) < d_len) { + char *tmp = ap_pstrdup(p, uri); + tmp[(u-uri)+(d_len-(f-filename))] = '\0'; + return tmp; + } + + return ""; /* give up */ +} + + +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); + } + + /* MD5-sess stuff */ + + if (!stale && !strcasecmp(conf->algorithm, "MD5-sess")) + clear_session(resp); + + /* 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 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!). + */ + + if (r->proxyreq != NOT_PROXY) + domain = NULL; /* don't send domain for proxy requests */ + else if (conf->uri_list) + domain = conf->uri_list; + else { + /* They didn't specify any domain, so let's guess at it */ + domain = guess_domain(r->pool, resp->psd_request_uri->path, r->filename, + conf->dir_name); + if (domain[0] == '/' && domain[1] == '\0') + domain = NULL; /* "/" is the default, so no need to send it */ + else + domain = ap_pstrcat(r->pool, ", domain=\"", domain, "\"", NULL); + } + + 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) +{ + if (conf->check_nc && client_mm) { + unsigned long nc; + + const char *snc = resp->nonce_count; + char *endptr; + + nc = 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_DEBUG, r, + "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 */ + +static const char *old_digest(const request_rec *r, + const digest_header_rec *resp, const char *ha1) +{ + const char *ha2; + + /* rfc-2069 */ + 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)); +} + +static const char *new_digest(const request_rec *r, + digest_header_rec *resp, + const digest_config_rec *conf) +{ + const char *ha1, *ha2, *a2; + + /* draft-ietf-http-authentication-03 */ + if (resp->algorithm && !strcasecmp(resp->algorithm, "MD5-sess")) + ha1 = get_session(r, resp, conf); + 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); + } + + if (src->query && src->query[0] != '\0') { + dst->query = ap_pstrdup(r->pool, src->query); + ap_unescape_url(dst->query); + } +} + +/* 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 */ + (d_uri.hostname && d_uri.hostname[0] != '\0' + && strcasecmp(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 { + 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 (strcmp(resp->digest, new_digest(r, resp, conf))) { + 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; + } + } + + if (check_nc(r, resp, conf) != OK) { + 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(r, resp, conf); + 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_12/src/modules/experimental/mod_mmap_static.c b/APACHE_1_3_12/src/modules/experimental/mod_mmap_static.c new file mode 100644 index 0000000000..127fee8125 --- /dev/null +++ b/APACHE_1_3_12/src/modules/experimental/mod_mmap_static.c @@ -0,0 +1,395 @@ +/* ==================================================================== + * Copyright (c) 1998-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * mod_mmap_static: mmap a config-time list of files for faster serving + * + * v0.04 + * + * Author: Dean Gaudet + * + * 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 +#include +#include +#include +#include +#include +#include + +#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; + } + + 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_12/src/modules/extra/.cvsignore b/APACHE_1_3_12/src/modules/extra/.cvsignore new file mode 100644 index 0000000000..d063aabbf2 --- /dev/null +++ b/APACHE_1_3_12/src/modules/extra/.cvsignore @@ -0,0 +1,7 @@ +Makefile +*.lo +*.so +*.dll +*.def +*.exp +mod_*.c diff --git a/APACHE_1_3_12/src/modules/extra/.indent.pro b/APACHE_1_3_12/src/modules/extra/.indent.pro new file mode 100644 index 0000000000..a9fbe9f9a1 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/modules/extra/Makefile.tmpl b/APACHE_1_3_12/src/modules/extra/Makefile.tmpl new file mode 100644 index 0000000000..67c70fab94 --- /dev/null +++ b/APACHE_1_3_12/src/modules/extra/Makefile.tmpl @@ -0,0 +1,6 @@ + +#Dependencies + +$(OBJS) $(OBJS_PIC): Makefile + +# DO NOT REMOVE diff --git a/APACHE_1_3_12/src/modules/proxy/.cvsignore b/APACHE_1_3_12/src/modules/proxy/.cvsignore new file mode 100644 index 0000000000..e0eb7a9f30 --- /dev/null +++ b/APACHE_1_3_12/src/modules/proxy/.cvsignore @@ -0,0 +1,12 @@ +Debug +Release +ApacheModuleProxy.dsw +ApacheModuleProxy.mdp +ApacheModuleProxy.ncb +ApacheModuleProxy.opt +ApacheModuleProxy.plg +Makefile +*.lo +*.so +*.dll +*.def diff --git a/APACHE_1_3_12/src/modules/proxy/.indent.pro b/APACHE_1_3_12/src/modules/proxy/.indent.pro new file mode 100644 index 0000000000..20c2d83371 --- /dev/null +++ b/APACHE_1_3_12/src/modules/proxy/.indent.pro @@ -0,0 +1,55 @@ +-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 +-Tproxy_server_conf diff --git a/APACHE_1_3_12/src/modules/proxy/ApacheModuleProxy.dsp b/APACHE_1_3_12/src/modules/proxy/ApacheModuleProxy.dsp new file mode 100644 index 0000000000..6ee5cf30dd --- /dev/null +++ b/APACHE_1_3_12/src/modules/proxy/ApacheModuleProxy.dsp @@ -0,0 +1,133 @@ +# Microsoft Developer Studio Project File - Name="ApacheModuleProxy" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=ApacheModuleProxy - 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 "ApacheModuleProxy.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 "ApacheModuleProxy.mak"\ + CFG="ApacheModuleProxy - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleProxy - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleProxy - Win32 Debug" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleProxy - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir ".\ApacheMo" +# PROP BASE Intermediate_Dir ".\ApacheMo" +# 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 /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /D "WIN32_LEAN_AND_MEAN" /YX /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 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 ws2_32.lib /nologo /subsystem:windows /dll /machine:I386 + +!ELSEIF "$(CFG)" == "ApacheModuleProxy - 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 /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /D "WIN32_LEAN_AND_MEAN" /YX /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 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 ws2_32.lib /nologo /subsystem:windows /dll /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "ApacheModuleProxy - Win32 Release" +# Name "ApacheModuleProxy - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" +# Begin Source File + +SOURCE=.\mod_proxy.c +# End Source File +# Begin Source File + +SOURCE=.\proxy_cache.c +# End Source File +# Begin Source File + +SOURCE=.\proxy_connect.c +# End Source File +# Begin Source File + +SOURCE=.\proxy_ftp.c +# End Source File +# Begin Source File + +SOURCE=.\proxy_http.c +# End Source File +# Begin Source File + +SOURCE=.\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=.\mod_proxy.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_12/src/modules/proxy/ApacheModuleProxy.mak b/APACHE_1_3_12/src/modules/proxy/ApacheModuleProxy.mak new file mode 100644 index 0000000000..b7074715e8 --- /dev/null +++ b/APACHE_1_3_12/src/modules/proxy/ApacheModuleProxy.mak @@ -0,0 +1,549 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ApacheModuleProxy.dsp +!IF "$(CFG)" == "" +CFG=ApacheModuleProxy - Win32 Release +!MESSAGE No configuration specified. Defaulting to ApacheModuleProxy - Win32\ + Release. +!ENDIF + +!IF "$(CFG)" != "ApacheModuleProxy - Win32 Release" && "$(CFG)" !=\ + "ApacheModuleProxy - 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 "ApacheModuleProxy.mak"\ + CFG="ApacheModuleProxy - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleProxy - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleProxy - 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 + +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleProxy - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +# Begin Custom Macros +OutDir=.\.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleProxy.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleProxy.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_proxy.obj" + -@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 "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheModuleProxy.dll" + -@erase "$(OUTDIR)\ApacheModuleProxy.exp" + -@erase "$(OUTDIR)\ApacheModuleProxy.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D\ + "_WINDOWS" /D "SHARED_MODULE" /D "WIN32_LEAN_AND_MEAN"\ + /Fp"$(INTDIR)\ApacheModuleProxy.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD\ + /c +CPP_OBJS=.\Release/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleProxy.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib ws2_32.lib /nologo\ + /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)\ApacheModuleProxy.pdb"\ + /machine:I386 /out:"$(OUTDIR)\ApacheModuleProxy.dll"\ + /implib:"$(OUTDIR)\ApacheModuleProxy.lib" +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" + +"$(OUTDIR)\ApacheModuleProxy.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ApacheModuleProxy - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +# Begin Custom Macros +OutDir=.\.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleProxy.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleProxy.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_proxy.obj" + -@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 "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\ApacheModuleProxy.dll" + -@erase "$(OUTDIR)\ApacheModuleProxy.exp" + -@erase "$(OUTDIR)\ApacheModuleProxy.ilk" + -@erase "$(OUTDIR)\ApacheModuleProxy.lib" + -@erase "$(OUTDIR)\ApacheModuleProxy.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D\ + "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /D "WIN32_LEAN_AND_MEAN"\ + /Fp"$(INTDIR)\ApacheModuleProxy.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD\ + /c +CPP_OBJS=.\Debug/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleProxy.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib ws2_32.lib /nologo\ + /subsystem:windows /dll /incremental:yes /pdb:"$(OUTDIR)\ApacheModuleProxy.pdb"\ + /debug /machine:I386 /out:"$(OUTDIR)\ApacheModuleProxy.dll"\ + /implib:"$(OUTDIR)\ApacheModuleProxy.lib" +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" + +"$(OUTDIR)\ApacheModuleProxy.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) $< +<< + + +!IF "$(CFG)" == "ApacheModuleProxy - Win32 Release" || "$(CFG)" ==\ + "ApacheModuleProxy - Win32 Debug" +SOURCE=.\mod_proxy.c + +!IF "$(CFG)" == "ApacheModuleProxy - Win32 Release" + +DEP_CPP_MOD_P=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_config.h"\ + "..\..\include\ap_ctype.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"\ + "..\..\os\win32\os.h"\ + "..\..\os\win32\readdir.h"\ + ".\mod_proxy.h"\ + + +"$(INTDIR)\mod_proxy.obj" : $(SOURCE) $(DEP_CPP_MOD_P) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ApacheModuleProxy - Win32 Debug" + +DEP_CPP_MOD_P=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_config.h"\ + "..\..\include\ap_ctype.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"\ + "..\..\os\win32\os.h"\ + "..\..\os\win32\readdir.h"\ + ".\mod_proxy.h"\ + + +"$(INTDIR)\mod_proxy.obj" : $(SOURCE) $(DEP_CPP_MOD_P) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\proxy_cache.c + +!IF "$(CFG)" == "ApacheModuleProxy - Win32 Release" + +DEP_CPP_PROXY=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_config.h"\ + "..\..\include\ap_ctype.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_log.h"\ + "..\..\include\http_main.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\httpd.h"\ + "..\..\include\multithread.h"\ + "..\..\include\util_date.h"\ + "..\..\include\util_uri.h"\ + "..\..\os\win32\os.h"\ + "..\..\os\win32\readdir.h"\ + ".\mod_proxy.h"\ + + +"$(INTDIR)\proxy_cache.obj" : $(SOURCE) $(DEP_CPP_PROXY) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ApacheModuleProxy - Win32 Debug" + +DEP_CPP_PROXY=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_config.h"\ + "..\..\include\ap_ctype.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_log.h"\ + "..\..\include\http_main.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\httpd.h"\ + "..\..\include\multithread.h"\ + "..\..\include\util_date.h"\ + "..\..\include\util_uri.h"\ + "..\..\os\win32\os.h"\ + "..\..\os\win32\readdir.h"\ + ".\mod_proxy.h"\ + + +"$(INTDIR)\proxy_cache.obj" : $(SOURCE) $(DEP_CPP_PROXY) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\proxy_connect.c + +!IF "$(CFG)" == "ApacheModuleProxy - Win32 Release" + +DEP_CPP_PROXY_=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_config.h"\ + "..\..\include\ap_ctype.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"\ + "..\..\os\win32\os.h"\ + "..\..\os\win32\readdir.h"\ + ".\mod_proxy.h"\ + + +"$(INTDIR)\proxy_connect.obj" : $(SOURCE) $(DEP_CPP_PROXY_) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ApacheModuleProxy - Win32 Debug" + +DEP_CPP_PROXY_=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_config.h"\ + "..\..\include\ap_ctype.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"\ + "..\..\os\win32\os.h"\ + "..\..\os\win32\readdir.h"\ + ".\mod_proxy.h"\ + + +"$(INTDIR)\proxy_connect.obj" : $(SOURCE) $(DEP_CPP_PROXY_) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\proxy_ftp.c + +!IF "$(CFG)" == "ApacheModuleProxy - Win32 Release" + +DEP_CPP_PROXY_F=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_config.h"\ + "..\..\include\ap_ctype.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"\ + "..\..\os\win32\os.h"\ + "..\..\os\win32\readdir.h"\ + ".\mod_proxy.h"\ + + +"$(INTDIR)\proxy_ftp.obj" : $(SOURCE) $(DEP_CPP_PROXY_F) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ApacheModuleProxy - Win32 Debug" + +DEP_CPP_PROXY_F=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_config.h"\ + "..\..\include\ap_ctype.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"\ + "..\..\os\win32\os.h"\ + "..\..\os\win32\readdir.h"\ + ".\mod_proxy.h"\ + + +"$(INTDIR)\proxy_ftp.obj" : $(SOURCE) $(DEP_CPP_PROXY_F) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\proxy_http.c + +!IF "$(CFG)" == "ApacheModuleProxy - Win32 Release" + +DEP_CPP_PROXY_H=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_config.h"\ + "..\..\include\ap_ctype.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"\ + "..\..\os\win32\os.h"\ + "..\..\os\win32\readdir.h"\ + ".\mod_proxy.h"\ + + +"$(INTDIR)\proxy_http.obj" : $(SOURCE) $(DEP_CPP_PROXY_H) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ApacheModuleProxy - Win32 Debug" + +DEP_CPP_PROXY_H=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_config.h"\ + "..\..\include\ap_ctype.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"\ + "..\..\os\win32\os.h"\ + "..\..\os\win32\readdir.h"\ + ".\mod_proxy.h"\ + + +"$(INTDIR)\proxy_http.obj" : $(SOURCE) $(DEP_CPP_PROXY_H) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\proxy_util.c + +!IF "$(CFG)" == "ApacheModuleProxy - Win32 Release" + +DEP_CPP_PROXY_U=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_config.h"\ + "..\..\include\ap_ctype.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"\ + "..\..\os\win32\os.h"\ + "..\..\os\win32\readdir.h"\ + ".\mod_proxy.h"\ + + +"$(INTDIR)\proxy_util.obj" : $(SOURCE) $(DEP_CPP_PROXY_U) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ApacheModuleProxy - Win32 Debug" + +DEP_CPP_PROXY_U=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_config.h"\ + "..\..\include\ap_ctype.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"\ + "..\..\os\win32\os.h"\ + "..\..\os\win32\readdir.h"\ + ".\mod_proxy.h"\ + + +"$(INTDIR)\proxy_util.obj" : $(SOURCE) $(DEP_CPP_PROXY_U) "$(INTDIR)" + + +!ENDIF + + +!ENDIF + diff --git a/APACHE_1_3_12/src/modules/proxy/Makefile.OS2 b/APACHE_1_3_12/src/modules/proxy/Makefile.OS2 new file mode 100644 index 0000000000..260f005080 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/modules/proxy/Makefile.libdir b/APACHE_1_3_12/src/modules/proxy/Makefile.libdir new file mode 100644 index 0000000000..7b5254013a --- /dev/null +++ b/APACHE_1_3_12/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_12/src/modules/proxy/Makefile.tmpl b/APACHE_1_3_12/src/modules/proxy/Makefile.tmpl new file mode 100644 index 0000000000..906de39cf8 --- /dev/null +++ b/APACHE_1_3_12/src/modules/proxy/Makefile.tmpl @@ -0,0 +1,113 @@ + +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 + $(LD_SHLIB) $(LDFLAGS_SHLIB) -o $* $(OBJS_PIC) $(LIBS_SHLIB) + emxbind -b -q -s -h0 -dmod_proxy.def $* && \ + rm $* + +.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)/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)/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)/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)/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)/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)/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_12/src/modules/proxy/mod_proxy.c b/APACHE_1_3_12/src/modules/proxy/mod_proxy.c new file mode 100644 index 0000000000..54b56e9124 --- /dev/null +++ b/APACHE_1_3_12/src/modules/proxy/mod_proxy.c @@ -0,0 +1,965 @@ +/* ==================================================================== + * Copyright (c) 1996-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +#include "mod_proxy.h" + +#define CORE_PRIVATE + +#include "http_log.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: + * 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) { + int maxfwd = 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, "%d", (maxfwd > 0) ? maxfwd-1 : 0)); + } + + if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) + return rc; + + url = r->filename + 6; + p = strchr(url, ':'); + if (p == NULL) + return HTTP_BAD_REQUEST; + + 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 + 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->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 = -1; + ps->cache.gcinterval_set = 0; + /* 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 = 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->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_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 = 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"}, + {"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 */ +}; + + +#ifdef NETWARE +int main(int argc, char *argv[]) +{ + ExitThread(TSR_THREAD, 0); +} +#endif diff --git a/APACHE_1_3_12/src/modules/proxy/mod_proxy.h b/APACHE_1_3_12/src/modules/proxy/mod_proxy.h new file mode 100644 index 0000000000..9edd6e6eaa --- /dev/null +++ b/APACHE_1_3_12/src/modules/proxy/mod_proxy.h @@ -0,0 +1,320 @@ +/* ==================================================================== + * Copyright (c) 1996-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +#ifndef MOD_PROXY_H +#define MOD_PROXY_H + +/* + * Main include file for the Apache proxy + */ + +/* + + Note that the Explain() stuff is not yet complete. + Also 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. + + This code is still experimental! + + Things to do: + + 1. Make it garbage collect in the background, not while someone is waiting for + a response! + + 2. Check the logic thoroughly. + + 3. Empty directories are only removed the next time round (but this does avoid + two passes). Consider doing them the first time round. + + Ben Laurie 30 Mar 96 + + More things to do: + + 0. Code cleanup (ongoing) + + 1. add 230 response output for ftp now that it works + + 2. Make the ftp proxy transparent, also same with (future) gopher & wais + + 3. Use protocol handler struct a la Apache module handlers (Dirk van Gulik) + + 4. Use a cache expiry database for more efficient GC (Jeremy Wohl) + + 5. Bulletproof GC against SIGALRM + + Chuck Murcko 15 April 1997 + + */ + +#define TESTING 0 +#undef EXPLAIN + +#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) + +/* 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; +} 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, of NULL if not caching */ + time_t ims; /* if-modified-since date of request; -1 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) */ + 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 */ + 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 like (protocol, code + message) */ + table *hdrs; /* the HTTP headers of the file */ +} cache_req; + +/* Additional information passed to the function called by ap_table_do() */ +struct tbl_do_args { + request_rec *req; + cache_req *cache; +}; + +/* 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); +void ap_proxy_send_headers(request_rec *r, const char *respline, table *hdrs); +int ap_proxy_liststr(const char *list, const 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); + +#endif /*MOD_PROXY_H*/ diff --git a/APACHE_1_3_12/src/modules/proxy/proxy_cache.c b/APACHE_1_3_12/src/modules/proxy/proxy_cache.c new file mode 100644 index 0000000000..00854cb8f2 --- /dev/null +++ b/APACHE_1_3_12/src/modules/proxy/proxy_cache.c @@ -0,0 +1,1200 @@ +/* ==================================================================== + * Copyright (c) 1996-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* 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 "util_date.h" +#ifdef WIN32 +#include +#else +#include +#endif /* WIN32 */ +#include "multithread.h" +#include "ap_md5.h" +#ifdef __TANDEM +#include +#include +#endif +#ifdef TPF +#include "os.h" +#endif + +DEF_Explain + +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 * const) ap; + const struct gc_ent *b = (const struct gc_ent * const) 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); + } +#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 /.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); + Explain3("GC Unlinking %s (expiry %ld, garbage_now %ld)", filename, fent->expire, 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[27]; + 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); + Explain1("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); + Explain1("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) { + Explain1("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 */ + 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; + } + +/* 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]; + close(fd); + 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 + + i = read(fd, line, 26); + 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 + 18); + 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 + */ +static int rdcache(request_rec *r, BUFF *cachefp, cache_req *c) +{ + char urlbuff[1034], *strp; + int len; +/* read the data from the cache file */ +/* format + * date SP lastmod SP expire SP count SP content-length CRLF + * dates are stored as hex seconds since 1970 + */ + len = ap_bgets(urlbuff, sizeof urlbuff, cachefp); + if (len == -1) + 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); + c->lmod = ap_proxy_hex2sec(urlbuff + 9); + c->expire = ap_proxy_hex2sec(urlbuff + 18); + c->version = ap_proxy_hex2sec(urlbuff + 27); + c->len = ap_proxy_hex2sec(urlbuff + 36); + +/* check that we have the same URL */ + len = ap_bgets(urlbuff, sizeof urlbuff, cachefp); + if (len == -1) + 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; + +/* What follows is the message */ + len = ap_bgets(urlbuff, sizeof urlbuff, cachefp); + if (len == -1) + 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) + 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 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 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) +{ + char hashfile[66]; + const char *imstr, *pragma, *auth; + cache_req *c; + time_t now; + BUFF *cachefp; + int cfd, i; + const long int zero = 0L; + void *sconf = r->server->module_config; + proxy_server_conf *pconf = + (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); + + c = ap_pcalloc(r->pool, sizeof(cache_req)); + *cr = c; + c->req = r; + c->url = ap_pstrdup(r->pool, url); + +/* get the If-Modified-Since date of the request */ + c->ims = BAD_DATE; + imstr = ap_table_get(r->headers_in, "If-Modified-Since"); + if (imstr != NULL) { +/* this may modify the value in the original table */ + imstr = ap_proxy_date_canon(r->pool, imstr); + c->ims = ap_parseHTTPdate(imstr); + if (c->ims == BAD_DATE) /* bad or out of range date; remove it */ + ap_table_unset(r->headers_in, "If-Modified-Since"); + } + +/* find the filename for this cache entry */ + ap_proxy_hash(url, hashfile, pconf->cache.dirlevels, pconf->cache.dirlength); + if (conf->root != NULL) + c->filename = ap_pstrcat(r->pool, conf->root, "/", hashfile, NULL); + else + c->filename = NULL; + + cachefp = NULL; +/* find out about whether the request can access the cache */ + pragma = ap_table_get(r->headers_in, "Pragma"); + auth = ap_table_get(r->headers_in, "Authorization"); + Explain5("Request for %s, pragma=%s, auth=%s, ims=%ld, imstr=%s", url, + pragma, auth, c->ims, imstr); + if (c->filename != NULL && r->method_number == M_GET && + strlen(url) < 1024 && !ap_proxy_liststr(pragma, "no-cache") && + auth == NULL) { + Explain1("Check file %s", c->filename); + cfd = open(c->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", + c->filename); +#ifdef EXPLAIN + else + Explain1("File %s not found", c->filename); +#endif + } + + 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; + } + } +/* 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? */ + now = time(NULL); +/* Ok, have we got some un-expired data? */ + if (cachefp != NULL && c->expire != BAD_DATE && now < c->expire) { + Explain0("Unexpired data available"); +/* check IMS */ + if (c->lmod != BAD_DATE && c->ims != BAD_DATE && c->ims >= c->lmod) { +/* has the cached file changed since this request? */ + if (c->date == BAD_DATE || c->date > c->ims) { +/* No, but these header values may have changed, so we send them with the + * 304 HTTP_NOT_MODIFIED response + */ + const char *q; + + if ((q = ap_table_get(c->hdrs, "Expires")) != NULL) + ap_table_set(r->headers_out, "Expires", q); + } + ap_pclosef(r->pool, ap_bfileno(cachefp, B_WR)); + Explain0("Use local copy, cached file hasn't changed"); + return HTTP_NOT_MODIFIED; + } + +/* Ok, has been modified */ + Explain0("Local copy modified, send it"); + r->status_line = strchr(c->resp_line, ' ') + 1; + r->status = c->status; + if (!r->assbackwards) { + ap_soft_timeout("proxy send headers", r); + ap_proxy_send_headers(r, c->resp_line, c->hdrs); + ap_kill_timeout(r); + } + ap_bsetopt(r->connection->client, BO_BYTECT, &zero); + r->sent_bodyct = 1; + if (!r->header_only) + ap_proxy_send_fb(cachefp, r, NULL); + ap_pclosef(r->pool, ap_bfileno(cachefp, B_WR)); + return OK; + } + +/* if we already have data and a last-modified date, and it is not a head + * request, then add an If-Modified-Since + */ + + if (cachefp != NULL && c->lmod != BAD_DATE && !r->header_only) { +/* + * 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); + } + } + c->fp = cachefp; + + Explain0("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; + int i; + const char *expire, *lmods, *dates, *clen; + time_t expc, date, lmod, now; + char buff[46]; + void *sconf = r->server->module_config; + proxy_server_conf *conf = + (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); + const long int zero = 0L; + + c->tempfile = NULL; + +/* we've received the response */ +/* 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? + * Unknown status responses and those known to be uncacheable + * 304 HTTP_NOT_MODIFIED response when we have no valid cache file, or + * 200 HTTP_OK response from HTTP/1.0 and up without a Last-Modified header, or + * HEAD requests, or + * requests with an Authorization header, or + * protocol requests nocache (e.g. ftp with user/password) + */ +/* @@@ XXX FIXME: is the test "r->status != HTTP_MOVED_PERMANENTLY" correct? + * or shouldn't it be "ap_is_HTTP_REDIRECT(r->status)" ? -MnKr */ + if ((r->status != HTTP_OK && r->status != HTTP_MOVED_PERMANENTLY && r->status != HTTP_NOT_MODIFIED) || + (expire != NULL && expc == BAD_DATE) || + (r->status == HTTP_NOT_MODIFIED && (c == NULL || c->fp == NULL)) || + (r->status == HTTP_OK && lmods == NULL && is_HTTP1) || + r->header_only || + ap_table_get(r->headers_in, "Authorization") != NULL || + nocache) { + Explain1("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 */ + } + +/* otherwise, we are going to cache the response */ +/* + * 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); + Explain0("Added date header"); + } + +/* check last-modified date */ + if (lmod != BAD_DATE && lmod > date) +/* if its in the future, then replace by date */ + { + lmod = date; + lmods = dates; + Explain0("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; + Explain0("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 + */ + Explain1("Expiry date is %ld", 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; + Explain1("Expiry date calculated %ld", expc); + } + +/* get the content-length header */ + clen = ap_table_get(resp_hdrs, "Content-Length"); + if (clen == NULL) + c->len = -1; + else + c->len = atoi(clen); + + ap_proxy_sec2hex(date, buff); + buff[8] = ' '; + ap_proxy_sec2hex(lmod, buff + 9); + buff[17] = ' '; + ap_proxy_sec2hex(expc, buff + 18); + buff[26] = ' '; + ap_proxy_sec2hex(c->version++, buff + 27); + buff[35] = ' '; + ap_proxy_sec2hex(c->len, buff + 36); + buff[44] = '\n'; + buff[45] = '\0'; + +/* if file not modified */ + if (r->status == HTTP_NOT_MODIFIED) { + if (c->ims != BAD_DATE && lmod != BAD_DATE && lmod <= c->ims) { +/* set any changed headers somehow */ +/* update dates and version, but not content-length */ + if (lmod != c->lmod || expc != c->expire || date != c->date) { + off_t curpos = lseek(ap_bfileno(c->fp, B_WR), 0, SEEK_SET); + if (curpos == -1) + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "proxy: error seeking on cache file %s", + c->filename); + else if (write(ap_bfileno(c->fp, B_WR), buff, 35) == -1) + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "proxy: error updating cache file %s", + c->filename); + } + ap_pclosef(r->pool, ap_bfileno(c->fp, B_WR)); + Explain0("Remote document not modified, use local copy"); + /* CHECKME: Is this right? Shouldn't we check IMS again here? */ + return HTTP_NOT_MODIFIED; + } + else { +/* return the whole document */ + Explain0("Remote document updated, sending"); + r->status_line = strchr(c->resp_line, ' ') + 1; + r->status = c->status; + if (!r->assbackwards) { + ap_soft_timeout("proxy send headers", r); + ap_proxy_send_headers(r, c->resp_line, c->hdrs); + ap_kill_timeout(r); + } + ap_bsetopt(r->connection->client, BO_BYTECT, &zero); + r->sent_bodyct = 1; + if (!r->header_only) + ap_proxy_send_fb(c->fp, r, NULL); +/* set any changed headers somehow */ +/* update dates and version, but not content-length */ + if (lmod != c->lmod || expc != c->expire || date != c->date) { + off_t curpos = lseek(ap_bfileno(c->fp, B_WR), 0, SEEK_SET); + + if (curpos == -1) + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "proxy: error seeking on cache file %s", + c->filename); + else if (write(ap_bfileno(c->fp, B_WR), buff, 35) == -1) + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "proxy: error updating cache file %s", + c->filename); + } + ap_pclosef(r->pool, ap_bfileno(c->fp, B_WR)); + return OK; + } + } +/* new or modified file */ + if (c->fp != NULL) { + ap_pclosef(r->pool, ap_bfileno(c->fp, B_WR)); + } + c->version = 0; + ap_proxy_sec2hex(0, buff + 27); + buff[35] = ' '; + +/* open temporary file */ +#ifndef TPF +#define TMPFILESTR "/tmpXXXXXX" + if (conf->cache.root == NULL) + return DECLINED; + 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) + return DECLINED; + 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) + return DECLINED; + + Explain1("Create temporary file %s", c->tempfile); + + i = open(c->tempfile, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0622); + if (i == -1) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "proxy: error creating cache file %s", + c->tempfile); + return DECLINED; + } + ap_note_cleanups_for_fd(r->pool, i); + c->fp = ap_bcreate(r->pool, B_WR); + ap_bpushfd(c->fp, -1, i); + + 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); + ap_pclosef(r->pool, ap_bfileno(c->fp, B_WR)); + unlink(c->tempfile); + c->fp = NULL; + } + return DECLINED; +} + +void ap_proxy_cache_tidy(cache_req *c) +{ + server_rec *s; + long int bc; + + if (c == NULL || c->fp == NULL) + 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[9]; + off_t curpos; + + c->len = bc; + ap_bflush(c->fp); + ap_proxy_sec2hex(c->len, buff); + curpos = lseek(ap_bfileno(c->fp, B_WR), 36, 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, 8) == -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->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) + /* 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); + } +#else + + if (link(c->tempfile, c->filename) == -1) + ap_log_error(APLOG_MARK, APLOG_ERR, 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_12/src/modules/proxy/proxy_connect.c b/APACHE_1_3_12/src/modules/proxy/proxy_connect.c new file mode 100644 index 0000000000..5fe8000c85 --- /dev/null +++ b/APACHE_1_3_12/src/modules/proxy/proxy_connect.c @@ -0,0 +1,288 @@ +/* ==================================================================== + * Copyright (c) 1996-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* CONNECT method for Apache proxy */ + +#include "mod_proxy.h" +#include "http_log.h" +#include "http_main.h" + +#ifdef HAVE_BSTRING_H +#include /* for IRIX, FD_SET calls bzero() */ +#endif + +DEF_Explain + +/* + * 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) { + Explain2("CONNECT to remote proxy %s on port %d", proxyhost, proxyport); + } + else { + Explain2("CONNECT to %s on port %d", host, port); + } + + server.sin_port = (proxyport ? htons(proxyport) : htons(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(r->pool, PF_INET, SOCK_STREAM, IPPROTO_TCP); + 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:
    ", + 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. + */ + Explain0("Sending the CONNECT request to the remote proxy"); + ap_snprintf(buffer, sizeof(buffer), "CONNECT %s HTTP/1.0" CRLF, + r->uri); + write(sock, buffer, strlen(buffer)); + ap_snprintf(buffer, sizeof(buffer), + "Proxy-agent: %s" CRLF CRLF, ap_get_server_version()); + write(sock, buffer, strlen(buffer)); + } + else { + Explain0("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); + + Explain0("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); + Explain1("Woke from select(), i=%d", i); + + if (i) { + if (FD_ISSET(sock, &fds)) { + Explain0("sock was set"); + if ((nbytes = read(sock, buffer, HUGE_STRING_LEN)) != 0) { + if (nbytes == -1) + break; + if (write(ap_bfileno(r->connection->client, B_WR), buffer, nbytes) == EOF) + break; + Explain1("Wrote %d bytes to client", nbytes); + } + else + break; + } + else if (FD_ISSET(ap_bfileno(r->connection->client, B_WR), &fds)) { + Explain0("client->fd was set"); + if ((nbytes = read(ap_bfileno(r->connection->client, B_WR), buffer, + HUGE_STRING_LEN)) != 0) { + if (nbytes == -1) + break; + if (write(sock, buffer, nbytes) == EOF) + break; + Explain1("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_12/src/modules/proxy/proxy_ftp.c b/APACHE_1_3_12/src/modules/proxy/proxy_ftp.c new file mode 100644 index 0000000000..9c57a704e8 --- /dev/null +++ b/APACHE_1_3_12/src/modules/proxy/proxy_ftp.c @@ -0,0 +1,1285 @@ +/* ==================================================================== + * Copyright (c) 1996-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* FTP routines for Apache proxy */ + +#include "mod_proxy.h" +#include "http_main.h" +#include "http_log.h" +#include "http_core.h" + +#define AUTODETECT_PWD + +DEF_Explain + +/* + * 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 *f) +{ + int len, status; + char linebuff[100], buff[5]; + + len = ap_bgets(linebuff, sizeof linebuff, f); + 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(f); + } + +/* skip continuation lines */ + if (linebuff[3] == '-') { + memcpy(buff, linebuff, 3); + buff[3] = ' '; + do { + len = ap_bgets(linebuff, sizeof linebuff, f); + if (len == -1) + return -1; + if (linebuff[len - 1] != '\n') { + (void)ap_bskiplf(f); + } + } 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 *f, char *msgbuf, int msglen) +{ + int len, status; + char linebuff[100], buff[5]; + char *mb = msgbuf, + *me = &msgbuf[msglen]; + + len = ap_bgets(linebuff, sizeof linebuff, f); + 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(f); + + if (linebuff[3] == '-') { + memcpy(buff, linebuff, 3); + buff[3] = ' '; + do { + len = ap_bgets(linebuff, sizeof linebuff, f); + if (len == -1) + return -1; + if (linebuff[len - 1] != '\n') { + (void)ap_bskiplf(f); + } + mb = ap_cpystrn(mb, linebuff+4, me - mb); + } while (memcmp(linebuff, buff, 4) != 0); + } + return status; +} + +static long int send_dir(BUFF *f, request_rec *r, cache_req *c, char *cwd) +{ + char buf[IOBUFSIZE]; + char buf2[IOBUFSIZE]; + char *filename; + int searchidx = 0; + char *searchptr = NULL; + int firstfile = 1; + unsigned long total_bytes_sent = 0; + register int n, o, w; + conn_rec *con = r->connection; + char *dir, *path, *reldir, *site; + + /* Save "scheme://site" prefix without password */ + site = ap_unparse_uri_components(r->pool, &r->parsed_uri, UNP_OMITPASSWORD|UNP_OMITPATHINFO); + /* ... and path without query args */ + path = ap_unparse_uri_components(r->pool, &r->parsed_uri, UNP_OMITSITEPART|UNP_OMITQUERY); + (void)decodeenc(path); + + /* Copy path, strip (all except the last) trailing slashes */ + path = dir = ap_pstrcat(r->pool, path, "/", NULL); + while ((n = strlen(path)) > 1 && path[n-1] == '/' && path[n-2] == '/') + path[n-1] = '\0'; + + /* print "ftp://host/" */ + n = ap_snprintf(buf, sizeof(buf), DOCTYPE_HTML_3_2 + "%s%s\n" + "\n" + "

    Directory of " + "%s/", + site, path, site, path, site); + total_bytes_sent += ap_proxy_bputs2(buf, con->client, c); + + while ((dir = strchr(dir+1, '/')) != NULL) + { + *dir = '\0'; + if ((reldir = strrchr(path+1, '/'))==NULL) + reldir = path+1; + else + ++reldir; + /* print "path/" component */ + ap_snprintf(buf, sizeof(buf), "%s/", path+1, reldir); + total_bytes_sent += ap_proxy_bputs2(buf, con->client, c); + *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, sizeof(buf), "

    \n
    ");
    +    } else {
    +	ap_snprintf(buf, sizeof(buf), "\n(%s)\n
    ", cwd);
    +    }
    +    total_bytes_sent += ap_proxy_bputs2(buf, con->client, c);
    +
    +    while (!con->aborted) {
    +	n = ap_bgets(buf, sizeof buf, f);
    +	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[0] == 'l' && (filename=strstr(buf, " -> ")) != NULL) {
    +	    char *link_ptr = filename;
    +
    +	    do {
    +		filename--;
    +	    } while (filename[0] != ' ');
    +	    *(filename++) = '\0';
    +	    *(link_ptr++) = '\0';
    +	    if ((n = strlen(link_ptr)) > 1 && link_ptr[n - 1] == '\n')
    +	      link_ptr[n - 1] = '\0';
    +	    ap_snprintf(buf2, sizeof(buf2), "%s %s %s\n", buf, filename, filename, link_ptr);
    +	    ap_cpystrn(buf, buf2, sizeof(buf));
    +	    n = strlen(buf);
    +	}
    +	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;
    +	    filename[strlen(filename) - 1] = 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 '..' */
    +	    if (!strcmp(filename, ".") || !strcmp(filename, "..") || buf[0] == 'd') {
    +		ap_snprintf(buf2, sizeof(buf2), "%s %s\n",
    +		    buf, filename, filename);
    +	    }
    +	    else {
    +		ap_snprintf(buf2, sizeof(buf2), "%s %s\n", buf, filename, filename);
    +	    }
    +	    ap_cpystrn(buf, buf2, sizeof(buf));
    +	    n = strlen(buf);
    +	}
    +
    +	o = 0;
    +	total_bytes_sent += n;
    +
    +	if (c != NULL && c->fp && ap_bwrite(c->fp, buf, n) != n) {
    +	    ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req,
    +		"proxy: error writing to %s", c->tempfile);
    +	    c = ap_proxy_cache_error(c);
    +	}
    +
    +	while (n && !r->connection->aborted) {
    +	    w = ap_bwrite(con->client, &buf[o], n);
    +	    if (w <= 0)
    +		break;
    +	    ap_reset_timeout(r);	/* reset timeout after successfule write */
    +	    n -= w;
    +	    o += w;
    +	}
    +    }
    +
    +    total_bytes_sent += ap_proxy_bputs2("

    \n", con->client, c); + total_bytes_sent += ap_proxy_bputs2(ap_psignature("", r), con->client, c); + total_bytes_sent += ap_proxy_bputs2("\n", con->client, c); + + 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; +} + +/* + * Handles direct access of ftp:// URLs + * Original (Non-PASV) version from + * Troy Morrison + * PASV added by Chuck + */ +int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) +{ + char *host, *path, *strp, *parms; + 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 port, i, j, len, sock, dsock, rc, nocache = 0; + int csd = 0; + struct sockaddr_in server; + struct hostent server_hp; + struct in_addr destaddr; + table *resp_hdrs; + BUFF *f; + BUFF *data = NULL; + pool *p = r->pool; + int one = 1; + const long int zero = 0L; + NET_SIZE_T clen; + struct tbl_do_args tdo; + + 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 */ + + host = r->parsed_uri.hostname; + port = (r->parsed_uri.port != 0) + ? r->parsed_uri.port + : ap_default_port_for_request(r); + path = ap_pstrdup(p, r->parsed_uri.path); + path = (path != NULL && path[0] != '\0') ? &path[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(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"); + } + + Explain2("FTP: connect to %s:%d", host, port); + + parms = strchr(path, ';'); + if (parms != NULL) + *(parms++) = '\0'; + + memset(&server, 0, sizeof(struct sockaddr_in)); + server.sin_family = AF_INET; + server.sin_port = htons(port); + err = ap_proxy_host2addr(host, &server_hp); + if (err != NULL) + return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, err); + + sock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sock == -1) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "proxy: error creating socket"); + return HTTP_INTERNAL_SERVER_ERROR; + } + +#ifndef TPF + 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) { + ap_pclosesocket(p, sock); + return ap_proxyerror(r, HTTP_BAD_GATEWAY, ap_pstrcat(r->pool, + "Could not connect to remote machine: ", + strerror(errno), NULL)); + } + + f = ap_bcreate(p, B_RDWR | B_SOCKET); + ap_bpushfd(f, sock, sock); +/* shouldn't we implement telnet control options here? */ + +#ifdef CHARSET_EBCDIC + ap_bsetflag(f, 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(f, resp, sizeof resp); + Explain1("FTP: returned status %d", i); + if (i == -1) { + ap_kill_timeout(r); + return ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server"); + } +#if 0 + if (i == 120) { + ap_kill_timeout(r); + /* 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 ) + */ + ap_set_header("Retry-After", ap_psprintf(p, "%u", 60*wait_mins); + return ap_proxyerror(r, HTTP_SERVICE_UNAVAILABLE, resp); + } +#endif + if (i != 220) { + ap_kill_timeout(r); + return ap_proxyerror(r, HTTP_BAD_GATEWAY, resp); + } + + Explain0("FTP: connected."); + + ap_bvputs(f, "USER ", user, CRLF, NULL); + ap_bflush(f); /* capture any errors */ + Explain1("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(f); + Explain1("FTP: returned status %d", i); + if (i == -1) { + ap_kill_timeout(r); + return ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server"); + } + if (i == 530) { + ap_kill_timeout(r); + return ftp_unauthorized (r, 1); /* log it: user name guessing attempt? */ + } + if (i != 230 && i != 331) { + ap_kill_timeout(r); + return HTTP_BAD_GATEWAY; + } + + if (i == 331) { /* send password */ + if (password == NULL) { + return ftp_unauthorized (r, 0); + } + ap_bvputs(f, "PASS ", password, CRLF, NULL); + ap_bflush(f); + Explain1("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(f); + Explain1("FTP: returned status %d", i); + if (i == -1) { + ap_kill_timeout(r); + return ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server"); + } + if (i == 332) { + ap_kill_timeout(r); + return ap_proxyerror(r, HTTP_UNAUTHORIZED, + "Need account for login"); + } + /* @@@ questionable -- we might as well return a 403 Forbidden here */ + if (i == 530) { + ap_kill_timeout(r); + return ftp_unauthorized (r, 1); /* log it: passwd guessing attempt? */ + } + if (i != 230 && i != 202) { + ap_kill_timeout(r); + return 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, '/'); + if (strp == NULL) + break; + *strp = '\0'; + + len = decodeenc(path); + ap_bvputs(f, "CWD ", path, CRLF, NULL); + ap_bflush(f); + Explain1("FTP: CWD %s", path); + *strp = '/'; +/* 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(f); + Explain1("FTP: returned status %d", i); + if (i == -1) { + ap_kill_timeout(r); + return ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server"); + } + if (i == 550) { + ap_kill_timeout(r); + return HTTP_NOT_FOUND; + } + if (i != 250) { + ap_kill_timeout(r); + return HTTP_BAD_GATEWAY; + } + + path = strp + 1; + } + + if (parms != NULL && strncmp(parms, "type=", 5) == 0) { + parms += 5; + if ((parms[0] != 'd' && parms[0] != 'a' && parms[0] != 'i') || + parms[1] != '\0') + parms = ""; + } + else + parms = ""; + + /* changed to make binary transfers the default */ + + if (parms[0] != 'a') { + /* set type to image */ + /* TM - Added CRLF to the end of TYPE I, otherwise it hangs the + connection */ + ap_bputs("TYPE I" CRLF, f); + ap_bflush(f); + Explain0("FTP: TYPE I"); +/* 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. */ + i = ftp_getrc(f); + Explain1("FTP: returned status %d", i); + if (i == -1) { + ap_kill_timeout(r); + return ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server"); + } + if (i != 200 && i != 504) { + ap_kill_timeout(r); + return HTTP_BAD_GATEWAY; + } +/* Allow not implemented */ + if (i == 504) + parms[0] = '\0'; + } + +/* try to set up PASV data connection first */ + dsock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (dsock == -1) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "proxy: error creating PASV socket"); + ap_bclose(f); + ap_kill_timeout(r); + return HTTP_INTERNAL_SERVER_ERROR; + } + +#ifndef TPF + 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, f); + ap_bflush(f); + Explain0("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), f); + if (i == -1) { + ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r, + "PASV: control connection is toast"); + ap_pclosesocket(p, dsock); + ap_bclose(f); + ap_kill_timeout(r); + return HTTP_INTERNAL_SERVER_ERROR; + } + 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); + + Explain1("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; + Explain5("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) { + ap_kill_timeout(r); + return ap_proxyerror(r, HTTP_BAD_GATEWAY, + ap_pstrcat(r->pool, + "Could not connect to remote machine: ", + strerror(errno), NULL)); + } + else { + pasvmode = 1; + } + } + else + ap_pclosesocket(p, dsock); /* and try the regular way */ + } + + if (!pasvmode) { /* set up data connection */ + clen = sizeof(struct sockaddr_in); + if (getsockname(sock, (struct sockaddr *) &server, &clen) < 0) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "proxy: error getting socket address"); + ap_bclose(f); + ap_kill_timeout(r); + return HTTP_INTERNAL_SERVER_ERROR; + } + + dsock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (dsock == -1) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "proxy: error creating socket"); + ap_bclose(f); + ap_kill_timeout(r); + return HTTP_INTERNAL_SERVER_ERROR; + } + + if (setsockopt(dsock, 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"); + ap_pclosesocket(p, dsock); + ap_bclose(f); + ap_kill_timeout(r); + return HTTP_INTERNAL_SERVER_ERROR; +#endif /*_OSD_POSIX*/ + } + + if (bind(dsock, (struct sockaddr *) &server, + sizeof(struct sockaddr_in)) == -1) { + char buff[22]; + + ap_snprintf(buff, sizeof(buff), "%s:%d", inet_ntoa(server.sin_addr), server.sin_port); + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "proxy: error binding to ftp data socket %s", buff); + ap_bclose(f); + ap_pclosesocket(p, dsock); + return HTTP_INTERNAL_SERVER_ERROR; + } + listen(dsock, 2); /* only need a short queue */ + } + +/* set request; "path" holds last path component */ + len = decodeenc(path); + + /* TM - if len == 0 then it must be a directory (you can't RETR nothing) */ + + if (len == 0) { + parms = "d"; + } + else { + ap_bvputs(f, "SIZE ", path, CRLF, NULL); + ap_bflush(f); + Explain1("FTP: SIZE %s", path); + i = ftp_getrc_msg(f, resp, sizeof resp); + Explain2("FTP: returned status %d with response %s", i, resp); + if (i != 500) { /* Size command not recognized */ + if (i == 550) { /* Not a regular file */ + Explain0("FTP: SIZE shows this is a directory"); + parms = "d"; + ap_bvputs(f, "CWD ", path, CRLF, NULL); + ap_bflush(f); + Explain1("FTP: CWD %s", path); + i = ftp_getrc(f); + /* 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. */ + Explain1("FTP: returned status %d", i); + if (i == -1) { + ap_kill_timeout(r); + return ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server"); + } + if (i == 550) { + ap_kill_timeout(r); + return HTTP_NOT_FOUND; + } + if (i != 250) { + ap_kill_timeout(r); + return 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(f, "PWD", CRLF, NULL); + ap_bflush(f); + Explain0("FTP: PWD"); +/* responses: 257, 500, 501, 502, 421, 550 */ + /* 257 "" */ + /* 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(f, resp, sizeof resp); + Explain1("FTP: PWD returned status %d", i); + if (i == -1 || i == 421) { + ap_kill_timeout(r); + return ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server"); + } + if (i == 550) { + ap_kill_timeout(r); + return HTTP_NOT_FOUND; + } + if (i == 257) { + const char *dirp = resp; + cwd = ap_getword_conf(r->pool, &dirp); + } +#endif /*AUTODETECT_PWD*/ + + if (parms[0] == 'd') { + if (len != 0) + ap_bvputs(f, "LIST ", path, CRLF, NULL); + else + ap_bputs("LIST -lag" CRLF, f); + Explain1("FTP: LIST %s", (len == 0 ? "" : path)); + } + else { + ap_bvputs(f, "RETR ", path, CRLF, NULL); + Explain1("FTP: RETR %s", path); + } + ap_bflush(f); +/* 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(f); + Explain1("FTP: returned status %d", rc); + if (rc == -1) { + ap_kill_timeout(r); + return ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server"); + } + if (rc == 550) { + Explain0("FTP: RETR failed, trying LIST instead"); + parms = "d"; + ap_bvputs(f, "CWD ", path, CRLF, NULL); + ap_bflush(f); + Explain1("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(f); + Explain1("FTP: returned status %d", rc); + if (rc == -1) { + ap_kill_timeout(r); + return ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server"); + } + if (rc == 550) { + ap_kill_timeout(r); + return HTTP_NOT_FOUND; + } + if (rc != 250) { + ap_kill_timeout(r); + return HTTP_BAD_GATEWAY; + } + +#ifdef AUTODETECT_PWD + ap_bvputs(f, "PWD", CRLF, NULL); + ap_bflush(f); + Explain0("FTP: PWD"); +/* responses: 257, 500, 501, 502, 421, 550 */ + /* 257 "" */ + /* 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(f, resp, sizeof resp); + Explain1("FTP: PWD returned status %d", i); + if (i == -1 || i == 421) { + ap_kill_timeout(r); + return ap_proxyerror(r, HTTP_BAD_GATEWAY, + "Error reading from remote server"); + } + if (i == 550) { + ap_kill_timeout(r); + return 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, f); + ap_bflush(f); + Explain0("FTP: LIST -lag"); + rc = ftp_getrc(f); + Explain1("FTP: returned status %d", rc); + if (rc == -1) + return 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 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 (parms[0] == 'd') + ap_table_setn(resp_hdrs, "Content-Type", "text/html"); + else { + if (r->content_type != NULL) { + ap_table_setn(resp_hdrs, "Content-Type", r->content_type); + Explain1("FTP: Content-Type set to %s", r->content_type); + } + else { + ap_table_setn(resp_hdrs, "Content-Type", ap_default_type(r)); + } + if (parms[0] != 'a' && size != NULL) { + /* We "trust" the ftp server to really serve (size) bytes... */ + ap_table_set(resp_hdrs, "Content-Length", size); + Explain1("FTP: Content-Length set to %s", size); + } + } + if (r->content_encoding != NULL && r->content_encoding[0] != '\0') { + Explain1("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 */ + for (i = 0; i < conf->nocaches->nelts; i++) { + if ((ncent[i].name != NULL && strstr(host, ncent[i].name) != NULL) + || destaddr.s_addr == ncent[i].addr.s_addr || ncent[i].name[0] == '*') + nocache = 1; + } + + i = ap_proxy_cache_update(c, resp_hdrs, 0, nocache); + + if (i != DECLINED) { + ap_pclosesocket(p, dsock); + ap_bclose(f); + return 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"); + ap_pclosesocket(p, dsock); + ap_bclose(f); + ap_kill_timeout(r); + if (c != NULL) + c = ap_proxy_cache_error(c); + return HTTP_BAD_GATEWAY; + } + ap_note_cleanups_for_socket(p, csd); + 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 */ + if (!r->assbackwards) + ap_rvputs(r, "HTTP/1.0 ", r->status_line, CRLF, NULL); + if (c != NULL && c->fp != NULL + && ap_bvputs(c->fp, "HTTP/1.0 ", r->status_line, CRLF, NULL) == -1) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, c->req, + "proxy: error writing CRLF to %s", c->tempfile); + c = ap_proxy_cache_error(c); + } + +/* send headers */ + tdo.req = r; + tdo.cache = c; + ap_table_do(ap_proxy_send_hdr_line, &tdo, resp_hdrs, NULL); + + if (!r->assbackwards) + ap_rputs(CRLF, r); + if (c != NULL && 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); + } + + ap_bsetopt(r->connection->client, BO_BYTECT, &zero); + r->sent_bodyct = 1; +/* send body */ + if (!r->header_only) { + if (parms[0] != 'd') { +/* we need to set this for ap_proxy_send_fb()... */ + if (c != NULL) + c->cache_completion = 0; + ap_proxy_send_fb(data, r, c); + } else + send_dir(data, r, c, cwd); + + if (rc == 125 || rc == 150) + rc = ftp_getrc(f); + + /* XXX: we checked for 125||150||226||250 above. This is redundant. */ + if (rc != 226 && rc != 250) + /* XXX: we no longer log an "error writing to c->tempfile" - should we? */ + c = ap_proxy_cache_error(c); + } + else { +/* abort the transfer */ + ap_bputs("ABOR" CRLF, f); + ap_bflush(f); + if (!pasvmode) + ap_bclose(data); + Explain0("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(f); + Explain1("FTP: returned status %d", i); + } + + ap_kill_timeout(r); + ap_proxy_cache_tidy(c); + +/* finish */ + ap_bputs("QUIT" CRLF, f); + ap_bflush(f); + Explain0("FTP: QUIT"); +/* responses: 221, 500 */ + /* 221 Service closing control connection. */ + /* 500 Syntax error, command unrecognized. */ + i = ftp_getrc(f); + Explain1("FTP: QUIT: status %d", i); + + if (pasvmode) + ap_bclose(data); + ap_bclose(f); + + ap_rflush(r); /* flush before garbage collection */ + + ap_proxy_garbage_coll(r); + + return OK; +} diff --git a/APACHE_1_3_12/src/modules/proxy/proxy_http.c b/APACHE_1_3_12/src/modules/proxy/proxy_http.c new file mode 100644 index 0000000000..2a417f39af --- /dev/null +++ b/APACHE_1_3_12/src/modules/proxy/proxy_http.c @@ -0,0 +1,546 @@ +/* ==================================================================== + * Copyright (c) 1996-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* 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; +} + +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; +} + +/* Clear all connection-based headers from the incoming headers table */ +static void clear_connection(pool *p, table *headers) +{ + const char *name; + char *next = ap_pstrdup(p, ap_table_get(headers, "Connection")); + + ap_table_unset(headers, "Proxy-Connection"); + if (!next) + return; + + 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"); +} + +/* + * 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; + array_header *reqhdrs_arr; + table *resp_hdrs; + table_entry *reqhdrs; + 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; + const long int zero = 0L; + int destport = 0; + char *destportstr = NULL; + const char *urlptr = NULL; + const char *datestr; + struct tbl_do_args tdo; + + 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; + + 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 ((npent[i].name != NULL && strstr(desthost, 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"); + } + + if (proxyhost != NULL) { + server.sin_port = htons(proxyport); + err = ap_proxy_host2addr(proxyhost, &server_hp); + if (err != NULL) + return DECLINED; /* try another */ + } + else { + server.sin_port = htons(destport); + err = ap_proxy_host2addr(desthost, &server_hp); + if (err != NULL) + return ap_proxyerror(r, HTTP_INTERNAL_SERVER_ERROR, err); + } + + sock = ap_psocket(p, PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sock == -1) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "proxy: error creating socket"); + return HTTP_INTERNAL_SERVER_ERROR; + } + +#ifndef TPF + 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; + } + } +#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) { + 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)); + } + + clear_connection(r->pool, r->headers_in); /* Strip connection-based headers */ + + 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.0" CRLF, + NULL); + 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(r->headers_in, "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(r->headers_in, "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) + ); + } + + reqhdrs_arr = ap_table_elts(r->headers_in); + reqhdrs = (table_entry *) reqhdrs_arr->elts; + for (i = 0; i < reqhdrs_arr->nelts; i++) { + if (reqhdrs[i].key == NULL || reqhdrs[i].val == NULL + /* Clear out headers not to send */ + || !strcasecmp(reqhdrs[i].key, "Host") /* Already sent */ + /* XXX: @@@ FIXME: "Proxy-Authorization" should *only* be + * suppressed if THIS server requested the authentication, + * not when a frontend proxy requested it! + */ + || !strcasecmp(reqhdrs[i].key, "Proxy-Authorization")) + continue; + ap_bvputs(f, reqhdrs[i].key, ": ", reqhdrs[i].val, CRLF, NULL); + } + + ap_bputs(CRLF, f); +/* send the request data, if any. */ + + if (ap_should_client_block(r)) { + while ((i = ap_get_client_block(r, buffer, sizeof buffer)) > 0) + ap_bwrite(f, buffer, i); + } + ap_bflush(f); + ap_kill_timeout(r); + + ap_hard_timeout("proxy receive", r); + + len = ap_bgets(buffer, sizeof buffer - 1, f); + if (len == -1) { + ap_bclose(f); + ap_kill_timeout(r); + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "ap_bgets() - proxy receive - Error reading from remote server %s (length %d)", + proxyhost ? proxyhost : desthost, len); + 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? This is buggy if we ever see an HTTP/1.10 */ + if (ap_checkmask(buffer, "HTTP/#.# ###*")) { + int major, minor; + if (2 != sscanf(buffer, "HTTP/%u.%u", &major, &minor)) { + major = 1; + minor = 0; + } + +/* If not an HTTP/1 message or if the status line was > 8192 bytes */ + if (buffer[5] != '1' || buffer[len - 1] != '\n') { + ap_bclose(f); + ap_kill_timeout(r); + return HTTP_BAD_GATEWAY; + } + backasswards = 0; + buffer[--len] = '\0'; + + buffer[12] = '\0'; + r->status = atoi(&buffer[9]); + buffer[12] = ' '; + r->status_line = ap_pstrdup(p, &buffer[9]); + +/* read the 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, HUGE_STRING_LEN, 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 */ + } + + 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) + ); + } + + clear_connection(p, resp_hdrs); /* Strip Connection hdrs */ + } + else { +/* an http/0.9 response */ + backasswards = 1; + r->status = 200; + r->status_line = "200 OK"; + +/* no headers */ + resp_hdrs = ap_make_table(p, 20); + } + + c->hdrs = resp_hdrs; + + ap_kill_timeout(r); + +/* + * HTTP/1.0 requires us to accept 3 types of dates, but only generate + * one type + */ + 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)); + + if ((datestr = ap_table_get(resp_hdrs, "Location")) != NULL) + ap_table_set(resp_hdrs, "Location", proxy_location_reverse_map(r, datestr)); + if ((datestr = ap_table_get(resp_hdrs, "URI")) != NULL) + ap_table_set(resp_hdrs, "URI", proxy_location_reverse_map(r, datestr)); + +/* check if NoCache directive on this host */ + for (i = 0; i < conf->nocaches->nelts; i++) { + if ((ncent[i].name != NULL && strstr(desthost, ncent[i].name) != NULL) + || destaddr.s_addr == ncent[i].addr.s_addr || ncent[i].name[0] == '*') + nocache = 1; + } + + i = ap_proxy_cache_update(c, resp_hdrs, !backasswards, nocache); + if (i != DECLINED) { + ap_bclose(f); + return i; + } + + ap_hard_timeout("proxy receive", r); + +/* write status line */ + if (!r->assbackwards) + ap_rvputs(r, "HTTP/1.0 ", r->status_line, CRLF, NULL); + if (c != NULL && c->fp != NULL && + ap_bvputs(c->fp, "HTTP/1.0 ", r->status_line, 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); + } + +/* send headers */ + tdo.req = r; + tdo.cache = c; + ap_table_do(ap_proxy_send_hdr_line, &tdo, resp_hdrs, NULL); + + if (!r->assbackwards) + ap_rputs(CRLF, r); + if (c != NULL && 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); + } + + ap_bsetopt(r->connection->client, BO_BYTECT, &zero); + r->sent_bodyct = 1; +/* Is it an HTTP/0.9 respose? If so, send the extra data */ + if (backasswards) { + 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) + */ + 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 */ + if (!r->header_only) { +/* we need to set this for ap_proxy_send_fb()... */ + c->cache_completion = conf->cache.cache_completion; + ap_proxy_send_fb(f, r, c); + } + + ap_proxy_cache_tidy(c); + + ap_bclose(f); + + ap_proxy_garbage_coll(r); + return OK; +} diff --git a/APACHE_1_3_12/src/modules/proxy/proxy_util.c b/APACHE_1_3_12/src/modules/proxy/proxy_util.c new file mode 100644 index 0000000000..d1d4720807 --- /dev/null +++ b/APACHE_1_3_12/src/modules/proxy/proxy_util.c @@ -0,0 +1,1292 @@ +/* ==================================================================== + * Copyright (c) 1996-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* 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); + +/* already called in the knowledge that the characters are hex digits */ +int ap_proxy_hex2c(const char *x) +{ + int i, ch; + +#ifndef CHARSET_EBCDIC + 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 &= 0xFF; + x[0] = '%'; + x[1] = ntoa[(os_toascii[ch]>>4)&0x0F]; + x[2] = ntoa[os_toascii[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, 1); + if (password == NULL) + return "Bad %-escape in URL (password)"; + } + + user = ap_proxy_canonenc(p, user, strlen(user), enc_user, 1); + 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) + 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"; + } + +/* if (strchr(host,'.') == NULL && domain != NULL) + host = pstrcat(p, host, domain, NULL); + */ + *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 (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 acstime() date */ + if (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; +} + + +/* NOTE: This routine is taken from http_protocol::getline() + * because the old code found in the proxy module was too + * difficult to understand and maintain. + */ +/* 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. + */ +static int proxy_getline(char *s, int n, BUFF *in, int fold) +{ + char *pos, next; + int retval; + int total = 0; + + pos = s; + + do { + retval = ap_bgets(pos, n, in); /* retval == -1 if error, 0 if EOF */ + + if (retval <= 0) + return ((retval < 0) && (total == 0)) ? -1 : total; + + /* 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? */ + *pos = '\0'; + --total; + ++n; + } + else + return total; /* 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'))); + + return total; +} + + +/* + * 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. + * @@@: XXX: FIXME: currently the headers are passed thru un-merged. + * Is that okay, or should they be collapsed where possible? + */ +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 = proxy_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 header " + "returned by %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'; + + 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 = proxy_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; +} + +long int ap_proxy_send_fb(BUFF *f, request_rec *r, cache_req *c) +{ + int ok; + char buf[IOBUFSIZE]; + long total_bytes_rcvd; + register int n, o, w; + conn_rec *con = r->connection; + int alternate_timeouts = 1; /* 1 if we alternate between soft & hard timeouts */ + + 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); + if (c != NULL && c->fp != NULL) + ap_bsetflag(c->fp, 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) + /* 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 (ok = 1; ok; ) { + if (alternate_timeouts) + ap_hard_timeout("proxy recv body from upstream server", r); + + /* Read block from server */ + n = ap_bread(f, buf, IOBUFSIZE); + + 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; + + /* 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 (!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 && c->fp != 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) { + 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 */ + } /* loop and ap_bread while "ok" */ + + if (!con->aborted) + ap_bflush(con->client); + + ap_kill_timeout(r); + return total_bytes_rcvd; +} + +/* + * Sends response line and headers. Uses the client fd and the + * headers_out array from the passed request_rec to talk to the client + * and to properly set the headers it sends for things such as logging. + * + * A timeout should be set before calling this routine. + */ +void ap_proxy_send_headers(request_rec *r, const char *respline, table *t) +{ + int i; + BUFF *fp = r->connection->client; + table_entry *elts = (table_entry *) ap_table_elts(t)->elts; + + ap_bvputs(fp, respline, CRLF, NULL); + + for (i = 0; i < ap_table_elts(t)->nelts; ++i) { + if (elts[i].key != NULL) { + ap_bvputs(fp, elts[i].key, ": ", elts[i].val, CRLF, NULL); + ap_table_addn(r->headers_out, elts[i].key, elts[i].val); + } + } + + ap_bputs(CRLF, fp); +} + + +/* + * 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 *val) +{ + int len, i; + const char *p; + + len = strlen(val); + + 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, val, len) == 0) + 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(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 8 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 < 8; 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); + } + if (j == 0xffffffff) + return -1; /* so that it works with 8-byte ints */ + else + return j; +} + +/* + * Converts a time integer to 8 hex digits + */ +void ap_proxy_sec2hex(int t, char *y) +{ + int i, ch; + unsigned int j = t; + + for (i = 7; i >= 0; i--) { + ch = j & 0xF; + j >>= 4; + if (ch >= 10) + y[i] = ch + ('A' - 10); + else + y[i] = ch + '0'; + } + y[8] = '\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->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 " + "pool, r->uri), + "\">", ap_escape_html(r->pool, r->method), + " ", + ap_escape_html(r->pool, r->uri), ".

    \n" + "Reason: ", + ap_escape_html(r->pool, message), + "", 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; + static APACHE_TLS struct hostent hpbuf; + static APACHE_TLS u_long ipaddr; + static APACHE_TLS char *charpbuf[2]; + + 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 { + ipaddr = ap_inet_addr(host); + hp = gethostbyaddr((char *) &ipaddr, sizeof(u_long), AF_INET); + if (hp == NULL) { + memset(&hpbuf, 0, sizeof(hpbuf)); + hpbuf.h_name = 0; + hpbuf.h_addrtype = AF_INET; + hpbuf.h_length = sizeof(u_long); + hpbuf.h_addr_list = charpbuf; + hpbuf.h_addr_list[0] = (char *) &ipaddr; + hpbuf.h_addr_list[1] = 0; + hp = &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] = 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 = 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 table_do_args struct pointer and a MIME field and value pair */ +int ap_proxy_send_hdr_line(void *p, const char *key, const char *value) +{ + struct tbl_do_args *parm = (struct tbl_do_args *)p; + + if (key == NULL || value == NULL || value[0] == '\0') + return 1; + if (!parm->req->assbackwards) + ap_rvputs(parm->req, key, ": ", value, CRLF, NULL); + if (parm->cache != NULL && parm->cache->fp != NULL && + ap_bvputs(parm->cache->fp, key, ": ", value, CRLF, NULL) == -1) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, parm->cache->req, + "proxy: error writing header to %s", parm->cache->tempfile); + parm->cache = ap_proxy_cache_error(parm->cache); + } + 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; +} + diff --git a/APACHE_1_3_12/src/modules/standard/.cvsignore b/APACHE_1_3_12/src/modules/standard/.cvsignore new file mode 100644 index 0000000000..c3690626fe --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/.cvsignore @@ -0,0 +1,6 @@ +Makefile +*.lo +*.so +*.dll +*.def +*.exp diff --git a/APACHE_1_3_12/src/modules/standard/.indent.pro b/APACHE_1_3_12/src/modules/standard/.indent.pro new file mode 100644 index 0000000000..a9fbe9f9a1 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/modules/standard/Makefile.OS2 b/APACHE_1_3_12/src/modules/standard/Makefile.OS2 new file mode 100644 index 0000000000..49df7d25f9 --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/Makefile.OS2 @@ -0,0 +1,115 @@ +# 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_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_12/src/modules/standard/Makefile.tmpl b/APACHE_1_3_12/src/modules/standard/Makefile.tmpl new file mode 100644 index 0000000000..7351a15bc2 --- /dev/null +++ b/APACHE_1_3_12/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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)/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_12/src/modules/standard/mod_access.c b/APACHE_1_3_12/src/modules/standard/mod_access.c new file mode 100644 index 0000000000..6179510451 --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_access.c @@ -0,0 +1,410 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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 { + unsigned long net; + unsigned long 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, '/'))) { + unsigned long 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 = 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 = ap_inet_addr(s); + if (mask == INADDR_NONE) { + a->type = T_FAIL; + return "syntax error in mask portion of network/netmask"; + } + } + else { + /* assume it's in /nnn form */ + mask = atoi(s); + if (mask > 32 || mask <= 0) { + a->type = T_FAIL; + return "invalid mask in network/netmask"; + } + mask = 0xFFFFFFFFUL << (32 - mask); + mask = htonl(mask); + } + a->x.ip.mask = mask; + a->x.ip.net = (a->x.ip.net & mask); /* 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 = 0; + a->x.ip.mask = 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) { + 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 |= octet << shift; + a->x.ip.mask |= 0xFFUL << shift; + s = t; + shift -= 8; + } + a->x.ip.net = ntohl(a->x.ip.net); + a->x.ip.mask = ntohl(a->x.ip.mask); + } + 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 != INADDR_NONE + && (r->connection->remote_addr.sin_addr.s_addr + & ap[i].x.ip.mask) == ap[i].x.ip.net) { + 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_12/src/modules/standard/mod_actions.c b/APACHE_1_3_12/src/modules/standard/mod_actions.c new file mode 100644 index 0000000000..4b5aad2b57 --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_actions.c @@ -0,0 +1,290 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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_12/src/modules/standard/mod_alias.c b/APACHE_1_3_12/src/modules/standard/mod_alias.c new file mode 100644 index 0000000000..f92d982d23 --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_alias.c @@ -0,0 +1,418 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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_config.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->fake = f; + new->real = r; + 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[10]; + 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, p->regexp->re_nsub + 1, regm, 0)) { + if (p->real) { + found = ap_pregsub(r->pool, p->real, r->uri, + p->regexp->re_nsub + 1, 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)) + 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_12/src/modules/standard/mod_asis.c b/APACHE_1_3_12/src/modules/standard/mod_asis.c new file mode 100644 index 0000000000..5e299df926 --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_asis.c @@ -0,0 +1,145 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +#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_12/src/modules/standard/mod_auth.c b/APACHE_1_3_12/src/modules/standard/mod_auth.c new file mode 100644 index 0000000000..bd1b4c2fc2 --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_auth.c @@ -0,0 +1,333 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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) + 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")) + return OK; + if (!strcmp(w, "user")) { + while (t[0]) { + w = ap_getword_conf(r->pool, &t); + if (!strcmp(user, w)) + return OK; + } + } + else if (!strcmp(w, "group")) { + if (!grpstatus) + 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_12/src/modules/standard/mod_auth_anon.c b/APACHE_1_3_12/src/modules/standard/mod_auth_anon.c new file mode 100644 index 0000000000..a6b8b80c77 --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_auth_anon.c @@ -0,0 +1,322 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * IT'S 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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 setup: + * + * Anonymous magic-user-id [magic-user-id]... + * + * Anonymous_MustGiveEmail [ on | off ] default = off + * 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 off. + * + * 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 */ +}; + +#ifdef NETWARE +int main(int argc, char *argv[]) +{ + ExitThread(TSR_THREAD, 0); +} +#endif diff --git a/APACHE_1_3_12/src/modules/standard/mod_auth_db.c b/APACHE_1_3_12/src/modules/standard/mod_auth_db.c new file mode 100644 index 0000000000..a633988543 --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_auth_db.c @@ -0,0 +1,355 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * IT'S 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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 + +#if defined(DB_VERSION_MAJOR) +#if (DB_VERSION_MAJOR == 2) +#define DB2 +#endif +#if (DB_VERSION_MAJOR == 3) +#define DB3 +#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) + if ( db_create(&f, NULL, 0) != 0 + || f->open(f, auth_dbpwfile, NULL, DB_HASH, DB_RDONLY, 0664) != 0) { +#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) + 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) + (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_12/src/modules/standard/mod_auth_db.module b/APACHE_1_3_12/src/modules/standard/mod_auth_db.module new file mode 100644 index 0000000000..4636763b2a --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_auth_db.module @@ -0,0 +1,35 @@ +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 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' + 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_12/src/modules/standard/mod_auth_dbm.c b/APACHE_1_3_12/src/modules/standard/mod_auth_dbm.c new file mode 100644 index 0000000000..bb32361a6d --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_auth_dbm.c @@ -0,0 +1,335 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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(__GLIBC__) && defined(__GLIBC_MINOR__) \ + && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1 +#include +#else +#include +#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 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 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_12/src/modules/standard/mod_autoindex.c b/APACHE_1_3_12/src/modules/standard/mod_autoindex.c new file mode 100644 index 0000000000..7ca656b06c --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_autoindex.c @@ -0,0 +1,1774 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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 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, + "\n \n Index of ", title, + "\n \n \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, "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; + 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("

    \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("<", r);
    +	    }
    +	    else if (ch == '>') {
    +		ap_rputs(">", r);
    +	    }
    +	    else if (ch == '&') {
    +		ap_rputs("&", r);
    +	    }
    +	    c = i + 1;
    +	}
    +    }
    +    ap_rputs("
    \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; + + /* + * 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
     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 (emit_amble) {
    +	emit_preamble(r, title);
    +    }
    +    if (emit_H1) {
    +	ap_rvputs(r, "

    Index of ", title, "

    \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; + + /* + * 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 (!suppress_sig) { + ap_rputs(ap_psignature("", r), r); + } + if (!suppress_post) { + ap_rputs("\n", r); + } + if (rr != NULL) { + ap_destroy_sub_req(rr); + } +} + + +static char *find_title(request_rec *r) +{ + char titlebuf[MAX_STRING_LEN], *find = ""; + 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->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 ä 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; + + /* + * 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; + } + return strcmp(c1->name, c2->name); +} + + +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"; + + ap_send_http_header(r); + + 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 != '\0') { + direction = *qstring; + } + 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_12/src/modules/standard/mod_cern_meta.c b/APACHE_1_3_12/src/modules/standard/mod_cern_meta.c new file mode 100644 index 0000000000..d8101948c7 --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_cern_meta.c @@ -0,0 +1,405 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * IT'S 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see <http://www.apache.org/>. + * + */ + +/* + * 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 */ +}; + + +#ifdef NETWARE +int main(int argc, char *argv[]) +{ + ExitThread(TSR_THREAD, 0); +} +#endif diff --git a/APACHE_1_3_12/src/modules/standard/mod_cgi.c b/APACHE_1_3_12/src/modules/standard/mod_cgi.c new file mode 100644 index 0000000000..617817ebef --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_cgi.c @@ -0,0 +1,609 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see <http://www.apache.org/>. + * + */ + +/* + * 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) { + 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 (r->method_number == M_OPTIONS) { + /* 99 out of 100 CGI scripts, this is all they support */ + r->allowed |= (1 << M_GET); + r->allowed |= (1 << M_POST); + return DECLINED; + } + + 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 + /* XXX:@@@ Is the generated/included output ALWAYS in text/ebcdic format? */ + /* Or must we check the Content-Type first? */ + ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, 1); +#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); + } + +#ifdef CHARSET_EBCDIC + /* Now check the Content-Type to decide if conversion is needed */ + ap_checkconv(r); +#endif /*CHARSET_EBCDIC*/ + + 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; + } + while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0) { + continue; + } + 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); + while (ap_bgets(argsbuffer, HUGE_STRING_LEN, script_err) > 0) { + continue; + } + 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_12/src/modules/standard/mod_digest.c b/APACHE_1_3_12/src/modules/standard/mod_digest.c new file mode 100644 index 0000000000..02b8215fd9 --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_digest.c @@ -0,0 +1,399 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see <http://www.apache.org/>. + * + */ + +/* + * 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... */ + +#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: + if (ap_isalnum(auth_line[0])) { + value[vv] = auth_line[0]; + vv++; + } + else if (auth_line[0] == '\"') { + s = D_STRING; + } + 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 */ + +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; + + 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 */ +}; + + +#ifdef NETWARE +int main(int argc, char *argv[]) +{ + ExitThread(TSR_THREAD, 0); +} +#endif diff --git a/APACHE_1_3_12/src/modules/standard/mod_dir.c b/APACHE_1_3_12/src/modules/standard/mod_dir.c new file mode 100644 index 0000000000..a32b390a88 --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_dir.c @@ -0,0 +1,246 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see <http://www.apache.org/>. + * + */ + +/* + * 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)) { + + 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_12/src/modules/standard/mod_env.c b/APACHE_1_3_12/src/modules/standard/mod_env.c new file mode 100644 index 0000000000..351a48712b --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_env.c @@ -0,0 +1,270 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * IT'S 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see <http://www.apache.org/>. + * + */ + +/* + * 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; + 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_12/src/modules/standard/mod_expires.c b/APACHE_1_3_12/src/modules/standard/mod_expires.c new file mode 100644 index 0000000000..5d1bf13aeb --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_expires.c @@ -0,0 +1,519 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * IT'S 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see <http://www.apache.org/>. + * + */ + +/* + * 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_setn(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 */ +}; + + +#ifdef NETWARE +int main(int argc, char *argv[]) +{ + ExitThread(TSR_THREAD, 0); +} +#endif diff --git a/APACHE_1_3_12/src/modules/standard/mod_headers.c b/APACHE_1_3_12/src/modules/standard/mod_headers.c new file mode 100644 index 0000000000..d3e66a55d9 --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_headers.c @@ -0,0 +1,273 @@ +/* ==================================================================== + * Copyright (c) 1996-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see <http://www.apache.org/>. + * + */ + +/* + * 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; +} 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 (!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, NULL, 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]; + switch (hdr->action) { + case hdr_add: + ap_table_addn(r->headers_out, hdr->header, hdr->value); + break; + case hdr_append: + ap_table_mergen(r->headers_out, hdr->header, hdr->value); + break; + case hdr_set: + ap_table_setn(r->headers_out, hdr->header, hdr->value); + break; + case hdr_unset: + ap_table_unset(r->headers_out, 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 */ +}; + +#ifdef NETWARE +int main(int argc, char *argv[]) +{ + ExitThread(TSR_THREAD, 0); +} +#endif + diff --git a/APACHE_1_3_12/src/modules/standard/mod_imap.c b/APACHE_1_3_12/src/modules/standard/mod_imap.c new file mode 100644 index 0000000000..c5152e71e4 --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_imap.c @@ -0,0 +1,919 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * IT'S 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see <http://www.apache.org/>. + * + */ + +/* + * 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_pstrdup(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"; + ap_send_http_header(r); + ap_hard_timeout("send menu", r); /* killed in menu_footer */ + + ap_rvputs(r, DOCTYPE_HTML_3_2, "<html><head>\n<title>Menu for ", r->uri, + "\n\n", NULL); + + if (!strcasecmp(menu, "formatted")) { + ap_rvputs(r, "

    Menu for ", r->uri, "

    \n
    \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("
    \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, "
    (Default) ", text,
    +               "
    \n", NULL); + } + if (!strcasecmp(menu, "semiformatted")) { + ap_rvputs(r, "
    (Default) ", text,
    +               "
    \n", NULL); + } + if (!strcasecmp(menu, "unformatted")) { + ap_rvputs(r, "", text, "", 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, "
              ", text,
    +               "
    \n", NULL); + } + if (!strcasecmp(menu, "semiformatted")) { + ap_rvputs(r, "
              ", text,
    +               "
    \n", NULL); + } + if (!strcasecmp(menu, "unformatted")) { + ap_rvputs(r, "", text, "", NULL); + } + return; +} + +static void menu_footer(request_rec *r) +{ + ap_rputs("\n\n\n\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_12/src/modules/standard/mod_include.c b/APACHE_1_3_12/src/modules/standard/mod_include.c new file mode 100644 index 0000000000..65dc18823c --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_include.c @@ -0,0 +1,2559 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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 accessed + * times.
    + * + * + * + * -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 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) +{ +#ifndef WIN32 + 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, � 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(pool *p, FILE *in, char *tag, int tagbuf_len, int dodecode) +{ + char *t = tag, *tag_val, c, term; + + /* 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'; + return NULL; + } +/* Want to accept \" as a valid character within a string. */ + if (c == '\\') { + *(t++) = c; /* Add backslash */ + GET_CHAR(in, c, NULL, p); + if (c == term) { /* Only if */ + *(--t) = c; /* Replace backslash ONLY for terminator */ + } + } + 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, pool *p) +{ + char *d = dest; + 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 - dest == len) { + 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 > end_out - next) ? (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, "", location, "", NULL); + } + + ap_destroy_sub_req(rr); +#ifndef WIN32 + 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 + */ +static int is_only_below(const char *path) +{ +#ifdef HAVE_DRIVE_LETTERS + if (path[1] == ':') + 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->pool, 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. + * + * 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 ( (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"; + } +#ifndef WIN32 + 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->pool, 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 */ +#ifndef WIN32 + 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 */ +#ifndef WIN32 + 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->pool, 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->pool, 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->pool, 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->pool, 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->pool, 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) { + token->value[next++] = ch; + } + + /* + * 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; + 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; + } + 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; + 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; + } + 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 /", ¤t->right->token.value[1], "/\n", NULL); +#endif + current->value = + re_check(r, current->left->token.value, + ¤t->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->pool, in, tag, sizeof(tag), 0); + if (*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->pool, in, tag, sizeof(tag), 0); + if (*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->pool, 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->pool, 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->pool, 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->pool, 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) +{ + char directive[MAX_STRING_LEN], error[MAX_STRING_LEN]; + char timefmt[MAX_STRING_LEN]; + 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; + +#ifndef WIN32 + 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->pool)) { + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, + "mod_include: error reading directive in %s", + r->filename); + ap_rputs(error, r); + return; + } + if (!strcmp(directive, "if")) { + if (!printing) { + if_nesting++; + } + else { + ret = handle_if(f, r, error, &conditional_status, + &printing); + if_nesting = 0; + } + continue; + } + else if (!strcmp(directive, "else")) { + if (!if_nesting) { + ret = handle_else(f, r, error, &conditional_status, + &printing); + } + continue; + } + else if (!strcmp(directive, "elif")) { + if (!if_nesting) { + ret = handle_elif(f, r, error, &conditional_status, + &printing); + } + continue; + } + else if (!strcmp(directive, "endif")) { + if (!if_nesting) { + ret = handle_endif(f, r, error, &conditional_status, + &printing); + } + else { + if_nesting--; + } + continue; + } + if (!printing) { + continue; + } + 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) + /* 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 . + * 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) + /* 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_12/src/modules/standard/mod_info.c b/APACHE_1_3_12/src/modules/standard/mod_info.c new file mode 100644 index 0000000000..3dd696cd43 --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_info.c @@ -0,0 +1,703 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * Info Module. Display configuration information for the server and + * all included modules. + * + * + * SetHandler server-info + * + * + * 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 , May 1996 + * + * 05.01.96 Initial Version + * + * Lou Langholtz , 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; + +module MODULE_VAR_EXPORT info_module; +extern module *top_module; + +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, "<", end_buf - t); + t += 4; + } + else if (*s == '>') { + strncpy(t, ">", end_buf - t); + t += 4; + } + else if (*s == '&') { + strncpy(t, "&", 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, "cmd, "cmd, "cmd, "next; + nest++; + continue; + } + else if (nest && (!strncasecmp(li->cmd, "cmd, "cmd, "cmd, "", r); + if (nest == 2) { + ap_rputs("  ", 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("\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("
    ", r); + ap_rputs(label, r); + ap_rputs("\n", r); + lab = 1; + } + if (((nest && block_start == NULL) || + (nest == 2 && block_start == li_st)) && + (strncasecmp(li->cmd, "cmd, "cmd, "cmd, "cmd, "cmd, "cmd, "", 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("\n", r); + block_start = li_st; + if (li_se) { + ap_rputs("
      ", 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("\n", r); + block_start = li_se; + } + } + ap_rputs("
    ", r); + if (nest) { + ap_rputs("  ", r); + } + if (nest == 2) { + ap_rputs("  ", r); + } + ap_rputs(mod_info_html_cmd_string(li->cmd, buf, sizeof(buf)), r); + if (li->line) { + ap_rputs(" ", r); + ap_rputs(mod_info_html_cmd_string(li->line, buf, sizeof(buf)), r); + ap_rputs("", r); + } + ap_rputs("", 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 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; + info_cfg_lines *mod_info_cfg_httpd = NULL; + info_cfg_lines *mod_info_cfg_srm = NULL; + info_cfg_lines *mod_info_cfg_access = NULL; + + 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; + } + ap_hard_timeout("send server info", r); + + ap_rputs(DOCTYPE_HTML_3_2 + "Server Information\n", r); + ap_rputs("

    Apache Server Information

    \n", r); + if (!r->args || strcasecmp(r->args, "list")) { + cfname = ap_server_root_relative(r->pool, ap_server_confname); + mod_info_cfg_httpd = mod_info_load_config(r->pool, cfname, r); + cfname = ap_server_root_relative(r->pool, serv->srm_confname); + mod_info_cfg_srm = mod_info_load_config(r->pool, cfname, r); + cfname = ap_server_root_relative(r->pool, serv->access_confname); + mod_info_cfg_access = mod_info_load_config(r->pool, cfname, r); + if (!r->args) { + ap_rputs("Server Settings, ", r); + for (modp = top_module; modp; modp = modp->next) { + ap_rprintf(r, "%s", modp->name, modp->name); + if (modp->next) { + ap_rputs(", ", r); + } + } + ap_rputs("
    ", r); + + } + if (!r->args || !strcasecmp(r->args, "server")) { + ap_rprintf(r, "Server Version: " + "%s
    \n", + ap_get_server_version()); + ap_rprintf(r, "Server Built: " + "%s
    \n", + ap_get_server_built()); + ap_rprintf(r, "API Version: " + "%d:%d
    \n", + MODULE_MAGIC_NUMBER_MAJOR, MODULE_MAGIC_NUMBER_MINOR); + ap_rprintf(r, "Run Mode: %s
    \n", + (ap_standalone ? "standalone" : "inetd")); + ap_rprintf(r, "User/Group: " + "%s(%d)/%d
    \n", + ap_user_name, (int) ap_user_id, (int) ap_group_id); + ap_rprintf(r, "Hostname/port: " + "%s:%u
    \n", + serv->server_hostname, serv->port); + ap_rprintf(r, "Daemons: " + "start: %d    " + "min idle: %d    " + "max idle: %d    " + "max: %d
    \n", + ap_daemons_to_start, ap_daemons_min_free, + ap_daemons_max_free, ap_daemons_limit); + ap_rprintf(r, "Max Requests: " + "per child: %d    " + "keep alive: %s    " + "max per connection: %d
    \n", + ap_max_requests_per_child, + (serv->keep_alive ? "on" : "off"), + serv->keep_alive_max); + ap_rprintf(r, "Threads: " + "per child: %d   
    \n", + ap_threads_per_child); + ap_rprintf(r, "Excess requests: " + "per child: %d   
    \n", + ap_excess_requests_per_child); + ap_rprintf(r, "Timeouts: " + "connection: %d    " + "keep-alive: %d
    ", + serv->timeout, serv->keep_alive_timeout); + ap_rprintf(r, "Server Root: " + "%s
    \n", ap_server_root); + ap_rprintf(r, "Config File: " + "%s
    \n", ap_server_confname); + ap_rprintf(r, "PID File: " + "%s
    \n", ap_pid_fname); + ap_rprintf(r, "Scoreboard File: " + "%s
    \n", ap_scoreboard_fname); + } + ap_rputs("
    ", r); + for (modp = top_module; modp; modp = modp->next) { + if (!r->args || !strcasecmp(modp->name, r->args)) { + ap_rprintf(r, "
    Module Name: " + "%s\n", + modp->name, modp->name); + ap_rputs("
    Content handlers:", r); + hand = modp->handlers; + if (hand) { + while (hand) { + if (hand->content_type) { + ap_rprintf(r, " %s\n", hand->content_type); + } + else { + break; + } + hand++; + if (hand && hand->content_type) { + ap_rputs(",", r); + } + } + } + else { + ap_rputs(" none", r); + } + ap_rputs("
    Configuration Phase Participation: \n", + r); + if (modp->child_init) { + ap_rputs("Child Init", r); + comma = 1; + } + if (modp->create_dir_config) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("Create Directory Config", r); + comma = 1; + } + if (modp->merge_dir_config) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("Merge Directory Configs", r); + comma = 1; + } + if (modp->create_server_config) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("Create Server Config", r); + comma = 1; + } + if (modp->merge_server_config) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("Merge Server Configs", r); + comma = 1; + } + if (modp->child_exit) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("Child Exit", r); + comma = 1; + } + if (!comma) + ap_rputs(" none", r); + comma = 0; + ap_rputs("
    Request Phase Participation: \n", + r); + if (modp->post_read_request) { + ap_rputs("Post-Read Request", r); + comma = 1; + } + if (modp->header_parser) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("Header Parse", r); + comma = 1; + } + if (modp->translate_handler) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("Translate Path", r); + comma = 1; + } + if (modp->access_checker) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("Check Access", r); + comma = 1; + } + if (modp->ap_check_user_id) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("Verify User ID", r); + comma = 1; + } + if (modp->auth_checker) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("Verify User Access", r); + comma = 1; + } + if (modp->type_checker) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("Check Type", r); + comma = 1; + } + if (modp->fixer_upper) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("Fixups", r); + comma = 1; + } + if (modp->logger) { + if (comma) { + ap_rputs(", ", r); + } + ap_rputs("Logging", r); + comma = 1; + } + if (!comma) + ap_rputs(" none", r); + comma = 0; + ap_rputs("
    Module Directives: ", r); + cmd = modp->cmds; + if (cmd) { + while (cmd) { + if (cmd->name) { + ap_rprintf(r, "
    %s - ", + mod_info_html_cmd_string(cmd->name, + buf, sizeof(buf))); + if (cmd->errmsg) { + ap_rputs(cmd->errmsg, r); + } + ap_rputs("\n", r); + } + else { + break; + } + cmd++; + } + ap_rputs("
    Current Configuration:\n", r); + mod_info_module_cmds(r, mod_info_cfg_httpd, modp->cmds, + "httpd.conf"); + mod_info_module_cmds(r, mod_info_cfg_srm, modp->cmds, + "srm.conf"); + mod_info_module_cmds(r, mod_info_cfg_access, modp->cmds, + "access.conf"); + } + else { + ap_rputs(" none\n", r); + } + more_info = find_more_info(serv, modp->name); + if (more_info) { + ap_rputs("
    Additional Information:\n
    ", + r); + ap_rputs(more_info, r); + } + ap_rputs("

    \n", r); + if (r->args) { + break; + } + } + } + if (!modp && r->args && strcasecmp(r->args, "server")) { + ap_rputs("No such module\n", r); + } + } + else { + for (modp = top_module; modp; modp = modp->next) { + ap_rputs(modp->name, r); + if (modp->next) { + ap_rputs("
    ", r); + } + } + } + ap_rputs("
    \n", r); + ap_rputs(ap_psignature("",r), r); + ap_rputs("\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 */ +}; + + +#ifdef NETWARE +int main(int argc, char *argv[]) +{ + ExitThread(TSR_THREAD, 0); +} +#endif diff --git a/APACHE_1_3_12/src/modules/standard/mod_log_agent.c b/APACHE_1_3_12/src/modules/standard/mod_log_agent.c new file mode 100644 index 0000000000..b625afcf0c --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_log_agent.c @@ -0,0 +1,188 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + + +#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(p, fname, xfer_flags, xfer_mode)) < 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_12/src/modules/standard/mod_log_config.c b/APACHE_1_3_12/src/modules/standard/mod_log_config.c new file mode 100644 index 0000000000..397402ca3c --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_log_config.c @@ -0,0 +1,1180 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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 + * + * LogFormat "... custom format ..." + * TransferLog log/virtual_only + * CustomLog log/virtual_useragents "%t %{user-agent}i" + * + * + * 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'. + * %...{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 + +module MODULE_VAR_EXPORT config_log_module; + +static int xfer_flags = (O_WRONLY | O_APPEND | O_CREAT); +#if defined(OS2) || defined(WIN32) +/* 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_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()); +} + +/***************************************************************** + * + * 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 + }, + { + '\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(p, fname, xfer_flags, xfer_mode)) < 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_12/src/modules/standard/mod_log_referer.c b/APACHE_1_3_12/src/modules/standard/mod_log_referer.c new file mode 100644 index 0000000000..f63cb2ebea --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_log_referer.c @@ -0,0 +1,229 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + + +#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(p, fname, xfer_flags, xfer_mode)) < 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_12/src/modules/standard/mod_mime.c b/APACHE_1_3_12/src/modules/standard/mod_mime.c new file mode 100644 index 0000000000..8b27d141e9 --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_mime.c @@ -0,0 +1,736 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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 handlers_info { + char *name; +} handlers_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 */ + + 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(handlers_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; + handlers_info *hand; + + hand = (handlers_info *) add->handlers_remove->elts; + for (i = 0; i < add->handlers_remove->nelts; i++) { + ap_table_unset(base->handlers, hand[i].name); + } + + 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); + + 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; + handlers_info *hand; + + if (*ext == '.') { + ++ext; + } + hand = (handlers_info *) ap_push_array(mcfg->handlers_remove); + hand->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"}, + {"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 log 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(char c) +{ + int res; + + res = (ap_isascii(c) && ap_isgraph(c) + && (strchr(tspecial, c) == NULL)) ? 1 : -1; + return res; +} + +static int is_qtext(char 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) +{ + const char *fn = strrchr(r->filename, '/'); + mime_dir_config *conf = + (mime_dir_config *) ap_get_module_config(r->per_dir_config, &mime_module); + char *ext; + const char *orighandler = r->handler; + const char *type; + const char *charset = NULL; + + if (S_ISDIR(r->finfo.st_mode)) { + r->content_type = DIR_MAGIC_TYPE; + return OK; + } + + /* TM -- FIXME + * if r->filename does not contain a '/', the following passes a null + * pointer to getword, causing a SEGV .. + */ + + if (fn == NULL) { + fn = r->filename; + } + + /* 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; + } + + /* This is to deal with cases such as foo.gif.bak, which we want + * to not have a type. So if we find an unknown extension, we + * zap the type/language/encoding and reset the handler + */ + + if (!found) { + r->content_type = NULL; + r->content_language = NULL; + r->content_languages = NULL; + r->content_encoding = NULL; + r->handler = orighandler; + charset = NULL; + } + } + + 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_12/src/modules/standard/mod_mime_magic.c b/APACHE_1_3_12/src/modules/standard/mod_mime_magic.c new file mode 100644 index 0000000000..7f4d6ba6e3 --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_mime_magic.c @@ -0,0 +1,2474 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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 + * 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" + +#include + + +/* + * 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 */ + { + "", L_HTML + }, + { + "", L_HTML + }, + { + "", L_HTML + }, + { + "", L_HTML + }, + { + "", 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 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, strdup(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 errors */ + if (!r->content_type || + (state == rsl_encoding && !r->content_encoding)) { + 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) { + 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) 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 = 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, 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, 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 + 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 + 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; + 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 defined(WIN32) + int child_pid; +#endif + + if (compr[parm->method].silent) { + close(STDERR_FILENO); + } + +#if defined(WIN32) + child_pid = spawnvp(compr[parm->method].argv[0], + new_argv); + return (child_pid); +#else + 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; +#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 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_12/src/modules/standard/mod_negotiation.c b/APACHE_1_3_12/src/modules/standard/mod_negotiation.c new file mode 100644 index 0000000000..5f7411260c --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_negotiation.c @@ -0,0 +1,2748 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see <http://www.apache.org/>. + * + */ + +/* + * 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 = atof(cp); + } + else if (parm[0] == 'l' && !strcmp(&parm[1], "evel")) { + result->level = 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 = 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; + + 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; + } + + while ((dir_entry = readdir(dirp))) { + request_rec *sub_req; + + /* Do we have a match? */ + + if (strncmp(dir_entry->d_name, filp, prefix_len)) { + 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; + } + + 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); + + 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 ((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 = 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 */ + 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_12/src/modules/standard/mod_rewrite.c b/APACHE_1_3_12/src/modules/standard/mod_rewrite.c new file mode 100644 index 0000000000..0469e53eb0 --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_rewrite.c @@ -0,0 +1,4293 @@ +/* ==================================================================== + * Copyright (c) 1996-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see <http://www.apache.org/>. + * + */ + + +/* _ _ _ +** _ __ ___ ___ __| | _ __ _____ ___ __(_) |_ ___ +** | '_ ` _ \ / _ \ / _` | | '__/ _ \ \ /\ / / '__| | __/ _ \ +** | | | | | | (_) | (_| | | | | __/\ 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 + +/* +** +-------------------------------------------------------+ +** | | +** | 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; + + 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; + + 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)); + + 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; + + 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, + rewrite_perdir_conf *dconf, char *option) +{ + rewrite_server_conf *sconf; + const char *err; + + sconf = (rewrite_server_conf *) + ap_get_module_config(cmd->server->module_config, &rewrite_module); + + if (cmd->path == NULL) { /* is server command */ + err = cmd_rewriteoptions_setoption(cmd->pool, + &(sconf->options), option); + } + else { /* is per-directory command */ + err = cmd_rewriteoptions_setoption(cmd->pool, + &(dconf->options), option); + } + + return err; +} + +static const char *cmd_rewriteoptions_setoption(pool *p, int *options, + char *name) +{ + if (strcasecmp(name, "inherit") == 0) { + *options |= OPTION_INHERIT; + } + else { + return ap_pstrcat(p, "RewriteOptions: unknown option '", + name, "'\n", NULL); + } + 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; + } + else if (strncmp(a2, "rnd:", 4) == 0) { + new->type = MAPTYPE_RND; + new->datafile = a2+4; + new->checkfile = a2+4; + } + 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); +#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; + } + else if (strncmp(a2, "int:", 4) == 0) { + new->type = MAPTYPE_INT; + new->datafile = NULL; + new->checkfile = 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->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, "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]; + char *cp, *cp2; + const char *ccp; + struct stat finfo; + unsigned int port; + 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 ... + */ + if (apply_rewrite_list(r, conf->rewriterules, NULL)) { + + 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 ( (strlen(r->filename) > 7 && + strncasecmp(r->filename, "http://", 7) == 0) + || (strlen(r->filename) > 8 && + strncasecmp(r->filename, "https://", 8) == 0) + || (strlen(r->filename) > 9 && + strncasecmp(r->filename, "gopher://", 9) == 0) + || (strlen(r->filename) > 6 && + strncasecmp(r->filename, "ftp://", 6) == 0) + || (strlen(r->filename) > 5 && + strncasecmp(r->filename, "ldap:", 5) == 0) + || (strlen(r->filename) > 5 && + strncasecmp(r->filename, "news:", 5) == 0) + || (strlen(r->filename) > 7 && + strncasecmp(r->filename, "mailto:", 7) == 0)) { + /* it was finally rewritten to a remote URL */ + + /* skip 'scheme:' */ + for (cp = r->filename; *cp != ':' && *cp != '\0'; cp++) + ; + /* skip '://' */ + cp += 3; + /* skip host part */ + for ( ; *cp != '/' && *cp != '\0'; cp++) + ; + if (*cp != '\0') { + rewritelog(r, 1, "escaping %s for redirect", r->filename); + cp2 = ap_escape_uri(r->pool, cp); + *cp = '\0'; + r->filename = ap_pstrcat(r->pool, r->filename, cp2, NULL); + } + + /* append the QUERY_STRING part */ + if (r->args != NULL) { + r->filename = ap_pstrcat(r->pool, r->filename, "?", + 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 has to start with a slash! */ + if (r->filename[0] != '/') { + 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, &finfo); + 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 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 (!(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; + } + else { + /* FollowSymLinks is given, but the user can + * still turn off the rewriting engine + */ + if (dconf->state == ENGINE_DISABLED) { + return DECLINED; + } + } + + /* + * 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 ... + */ + if (apply_rewrite_list(r, dconf->rewriterules, dconf->directory)) { + + 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 ( (strlen(r->filename) > 7 && + strncasecmp(r->filename, "http://", 7) == 0) + || (strlen(r->filename) > 8 && + strncasecmp(r->filename, "https://", 8) == 0) + || (strlen(r->filename) > 9 && + strncasecmp(r->filename, "gopher://", 9) == 0) + || (strlen(r->filename) > 6 && + strncasecmp(r->filename, "ftp://", 6) == 0) + || (strlen(r->filename) > 5 && + strncasecmp(r->filename, "ldap:", 5) == 0) + || (strlen(r->filename) > 5 && + strncasecmp(r->filename, "news:", 5) == 0) + || (strlen(r->filename) > 7 && + strncasecmp(r->filename, "mailto:", 7) == 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:' */ + for (cp = r->filename; *cp != ':' && *cp != '\0'; cp++) + ; + /* skip '://' */ + cp += 3; + if ((cp = strchr(cp, '/')) != NULL) { + rewritelog(r, 2, + "[per-dir %s] trying to replace " + "prefix %s with %s", + dconf->directory, dconf->directory, + dconf->baseurl); + cp2 = subst_prefix_path(r, cp, dconf->directory, + dconf->baseurl); + if (strcmp(cp2, cp) != 0) { + *cp = '\0'; + r->filename = ap_pstrcat(r->pool, r->filename, + cp2, NULL); + } + } + } + + /* now prepare the redirect... */ + + /* skip 'scheme:' */ + for (cp = r->filename; *cp != ':' && *cp != '\0'; cp++) + ; + /* skip '://' */ + cp += 3; + /* skip host part */ + for ( ; *cp != '/' && *cp != '\0'; cp++) + ; + if (*cp != '\0') { + rewritelog(r, 1, "[per-dir %s] escaping %s for redirect", + dconf->directory, r->filename); + cp2 = ap_escape_uri(r->pool, cp); + *cp = '\0'; + r->filename = ap_pstrcat(r->pool, r->filename, cp2, NULL); + } + + /* append the QUERY_STRING part */ + if (r->args != NULL) { + r->filename = ap_pstrcat(r->pool, r->filename, "?", + 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 has to start with a slash! */ + if (r->filename[0] != '/') { + 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; + } + + /* 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; +} + + +/* +** +-------------------------------------------------------+ +** | | +** | 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 = 1; + } + + /* + * 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 = 1; + 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 = 1; + 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 = 1; + 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]; + char env[MAX_STRING_LEN]; + regex_t *regexp; + regmatch_t regmatch[MAX_NMATCH]; + 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, regexp->re_nsub+1, 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) { + for (i = 0; p->env[i] != NULL; i++) { + /* 1. take the string */ + ap_cpystrn(env, p->env[i], sizeof(env)); + /* 2. expand $N (i.e. backrefs to RewriteRule pattern) */ + expand_backref_inbuffer(r->pool, env, sizeof(env), briRR, '$'); + /* 3. expand %N (i.e. backrefs to latest RewriteCond pattern) */ + expand_backref_inbuffer(r->pool, env, sizeof(env), briRC, '%'); + /* 4. expand %{...} (i.e. variables) */ + expand_variables_inbuffer(r, env, sizeof(env)); + /* 5. expand ${...} (RewriteMap lookups) */ + expand_map_lookups(r, env, sizeof(env)); + /* and add the variable to Apache's structures */ + add_env_variable(r, env); + } + 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'. + */ + /* 1. take the output string */ + ap_cpystrn(newuri, output, sizeof(newuri)); + /* 2. expand $N (i.e. backrefs to RewriteRule pattern) */ + expand_backref_inbuffer(r->pool, newuri, sizeof(newuri), briRR, '$'); + /* 3. expand %N (i.e. backrefs to latest RewriteCond pattern) */ + expand_backref_inbuffer(r->pool, newuri, sizeof(newuri), briRC, '%'); + /* 4. expand %{...} (i.e. variables) */ + expand_variables_inbuffer(r, newuri, sizeof(newuri)); + /* 5. expand ${...} (RewriteMap lookups) */ + expand_map_lookups(r, newuri, sizeof(newuri)); + /* and log the result... */ + 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>]'). + */ + for (i = 0; p->env[i] != NULL; i++) { + /* 1. take the string */ + ap_cpystrn(env, p->env[i], sizeof(env)); + /* 2. expand $N (i.e. backrefs to RewriteRule pattern) */ + expand_backref_inbuffer(r->pool, env, sizeof(env), briRR, '$'); + /* 3. expand %N (i.e. backrefs to latest RewriteCond pattern) */ + expand_backref_inbuffer(r->pool, env, sizeof(env), briRC, '%'); + /* 4. expand %{...} (i.e. variables) */ + expand_variables_inbuffer(r, env, sizeof(env)); + /* 5. expand ${...} (RewriteMap lookups) */ + expand_map_lookups(r, env, sizeof(env)); + /* and add the variable to Apache's structures */ + add_env_variable(r, env); + } + + /* + * 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); + + /* + * Again 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 starting with either a slash + * or a fully qualified URL scheme. + */ + i = strlen(r->filename); + if ( prefixstrip + && !( r->filename[0] == '/' + || ( (i > 7 && strncasecmp(r->filename, "http://", 7) == 0) + || (i > 8 && strncasecmp(r->filename, "https://", 8) == 0) + || (i > 9 && strncasecmp(r->filename, "gopher://", 9) == 0) + || (i > 6 && strncasecmp(r->filename, "ftp://", 6) == 0) + || (i > 5 && strncasecmp(r->filename, "ldap:", 5) == 0) + || (i > 5 && strncasecmp(r->filename, "news:", 5) == 0) + || (i > 7 && strncasecmp(r->filename, "mailto:", 7) == 0)))) { + 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. + */ + i = strlen(r->filename); + if ( (i > 7 && strncasecmp(r->filename, "http://", 7) == 0) + || (i > 8 && strncasecmp(r->filename, "https://", 8) == 0) + || (i > 9 && strncasecmp(r->filename, "gopher://", 9) == 0) + || (i > 6 && strncasecmp(r->filename, "ftp://", 6) == 0) + || (i > 5 && strncasecmp(r->filename, "ldap:", 5) == 0) + || (i > 5 && strncasecmp(r->filename, "news:", 5) == 0) + || (i > 7 && strncasecmp(r->filename, "mailto:", 7) == 0) ) { + 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; + } + + /* + * Now we are sure it is not a fully qualified URL. But + * there is still one special case left: A local rewrite in + * per-directory context, i.e. a substitution URL which does + * not start with a slash. Here we add again the initially + * stripped per-directory prefix. + */ + if (prefixstrip && r->filename[0] != '/') { + 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); + } + + /* + * 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[MAX_NMATCH]; + int rc; + + /* + * Construct the string we match against + */ + + /* 1. take the string */ + ap_cpystrn(input, p->input, sizeof(input)); + /* 2. expand $N (i.e. backrefs to RewriteRule pattern) */ + expand_backref_inbuffer(r->pool, input, sizeof(input), briRR, '$'); + /* 3. expand %N (i.e. backrefs to latest RewriteCond pattern) */ + expand_backref_inbuffer(r->pool, input, sizeof(input), briRC, '%'); + /* 4. expand %{...} (i.e. variables) */ + expand_variables_inbuffer(r, input, sizeof(input)); + /* 5. expand ${...} (RewriteMap lookups) */ + expand_map_lookups(r, input, sizeof(input)); + + /* + * 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) + 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 /* nonempty path, and */ + && ( r->main == NULL /* - either not in a subrequest */ + || ( r->main->uri != NULL /* - or in a subrequest... */ + && r->uri != NULL /* ...and URIs aren't NULL... */ + /* ...and sub/main URIs differ */ + && strcmp(r->main->uri, r->uri) != 0) ) ) { + + /* 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 /* nonempty path, and */ + && ( r->main == NULL /* - either not in a subrequest */ + || ( r->main->uri != NULL /* - or in a subrequest... */ + && r->uri != NULL /* ...and URIs aren't NULL... */ + /* ...and sub/main URIs differ */ + && strcmp(r->main->uri, r->uri) != 0) ) ) { + + /* 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, + p->regexp->re_nsub+1, 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 +** | | +** +-------------------------------------------------------+ +*/ + +/* +** +** split out a QUERY_STRING part from +** the current URI string +** +*/ + +static void splitout_queryargs(request_rec *r, int qsappend) +{ + char *q; + char *olduri; + + 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 ( 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) +{ + int i; + char buf[32]; + const char *thisserver; + char *thisport; + int port; + + i = strlen(r->filename); + if (!( (i > 7 && strncasecmp(r->filename, "http://", 7) == 0) + || (i > 8 && strncasecmp(r->filename, "https://", 8) == 0) + || (i > 9 && strncasecmp(r->filename, "gopher://", 9) == 0) + || (i > 6 && strncasecmp(r->filename, "ftp://", 6) == 0) + || (i > 5 && strncasecmp(r->filename, "ldap:", 5) == 0) + || (i > 5 && strncasecmp(r->filename, "news:", 5) == 0) + || (i > 7 && strncasecmp(r->filename, "mailto:", 7) == 0))) { + + 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; +} + + +/* +** +** Expand the %0-%9 or $0-$9 regex backreferences +** +*/ + +static void expand_backref_inbuffer(pool *p, char *buf, int nbuf, + backrefinfo *bri, char c) +{ + register int i; + + /* protect existing $N and & backrefs and replace <c>N with $N backrefs */ + for (i = 0; buf[i] != '\0' && i < nbuf; i++) { + if (buf[i] == '\\' && (buf[i+1] != '\0' && i < (nbuf-1))) { + i++; /* protect next */ + } + else if (buf[i] == '&') { + buf[i] = '\001'; + } + else if (c != '$' && buf[i] == '$' && (buf[i+1] >= '0' && buf[i+1] <= '9')) { + buf[i] = '\002'; + i++; /* speedup */ + } + else if (buf[i] == c && (buf[i+1] >= '0' && buf[i+1] <= '9')) { + buf[i] = '$'; + i++; /* speedup */ + } + } + + /* now apply the standard regex substitution function */ + ap_cpystrn(buf, ap_pregsub(p, buf, bri->source, + bri->nsub+1, bri->regmatch), nbuf); + + /* restore the original $N and & backrefs */ + for (i = 0; buf[i] != '\0' && i < nbuf; i++) { + if (buf[i] == '\001') { + buf[i] = '&'; + } + else if (buf[i] == '\002') { + buf[i] = '$'; + } + } +} + + +/* +** +** 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 + +/* +** +** mapfile expansion support +** i.e. expansion of MAP lookup directives +** ${<mapname>:<key>} in RewriteRule rhs +** +*/ + +#define limit_length(n) (n > LONG_STRING_LEN-1 ? LONG_STRING_LEN-1 : n) + +static void expand_map_lookups(request_rec *r, char *uri, int uri_len) +{ + char newuri[MAX_STRING_LEN]; + char *cpI; + char *cpIE; + char *cpO; + char *cpT; + char *cpT2; + char mapname[LONG_STRING_LEN]; + char mapkey[LONG_STRING_LEN]; + char defaultvalue[LONG_STRING_LEN]; + int n; + + cpI = uri; + cpIE = cpI+strlen(cpI); + cpO = newuri; + while (cpI < cpIE) { + if (cpI+6 < cpIE && strncmp(cpI, "${", 2) == 0) { + /* missing delimiter -> take it as plain text */ + if ( strchr(cpI+2, ':') == NULL + || strchr(cpI+2, '}') == NULL) { + memcpy(cpO, cpI, 2); + cpO += 2; + cpI += 2; + continue; + } + cpI += 2; + + cpT = strchr(cpI, ':'); + n = cpT-cpI; + memcpy(mapname, cpI, limit_length(n)); + mapname[limit_length(n)] = '\0'; + cpI += n+1; + + cpT2 = strchr(cpI, '|'); + cpT = strchr(cpI, '}'); + if (cpT2 != NULL && cpT2 < cpT) { + n = cpT2-cpI; + memcpy(mapkey, cpI, limit_length(n)); + mapkey[limit_length(n)] = '\0'; + cpI += n+1; + + n = cpT-cpI; + memcpy(defaultvalue, cpI, limit_length(n)); + defaultvalue[limit_length(n)] = '\0'; + cpI += n+1; + } + else { + n = cpT-cpI; + memcpy(mapkey, cpI, limit_length(n)); + mapkey[limit_length(n)] = '\0'; + cpI += n+1; + + defaultvalue[0] = '\0'; + } + + cpT = lookup_map(r, mapname, mapkey); + if (cpT != NULL) { + n = strlen(cpT); + if (cpO + n >= newuri + sizeof(newuri)) { + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, + r, "insufficient space in " + "expand_map_lookups, aborting"); + return; + } + memcpy(cpO, cpT, n); + cpO += n; + } + else { + n = strlen(defaultvalue); + if (cpO + n >= newuri + sizeof(newuri)) { + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, + r, "insufficient space in " + "expand_map_lookups, aborting"); + return; + } + memcpy(cpO, defaultvalue, n); + cpO += n; + } + } + else { + cpT = strstr(cpI, "${"); + if (cpT == NULL) + cpT = cpI+strlen(cpI); + n = cpT-cpI; + if (cpO + n >= newuri + sizeof(newuri)) { + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, + r, "insufficient space in " + "expand_map_lookups, aborting"); + return; + } + memcpy(cpO, cpI, n); + cpO += n; + cpI += n; + } + } + *cpO = '\0'; + ap_cpystrn(uri, newuri, uri_len); + return; +} + +#undef limit_length + + + +/* +** +-------------------------------------------------------+ +** | | +** | 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->name, 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->name, 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->name, 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->name, 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->name, 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->name, 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->name, 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->name, 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->name, 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 = NULL; + char buf[MAX_STRING_LEN]; + + dbmkey.dptr = key; + dbmkey.dsize = strlen(key); + if ((dbmfp = dbm_open(file, O_RDONLY, 0666)) != NULL) { + dbmval = dbm_fetch(dbmfp, dbmkey); + if (dbmval.dptr != NULL) { + memcpy(buf, dbmval.dptr, + dbmval.dsize < sizeof(buf)-1 ? + dbmval.dsize : sizeof(buf)-1 ); + buf[dbmval.dsize] = '\0'; + value = ap_pstrdup(r->pool, buf); + } + 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. + */ + if (fpin == -1 || fpout == -1) { + 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 ((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 ); +#ifdef 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(p, fname, rewritelog_flags, + rewritelog_mode)) < 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 +** | | +** +-------------------------------------------------------+ +*/ + +#ifdef 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) +{ + rewrite_server_conf *conf; + + conf = ap_get_module_config(s->module_config, &rewrite_module); + + /* 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(p, lockname, O_WRONLY|O_CREAT, + REWRITELOCK_MODE)) < 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 + + return; +} + +static void rewritelock_open(server_rec *s, pool *p) +{ + rewrite_server_conf *conf; + + conf = ap_get_module_config(s->module_config, &rewrite_module); + + /* 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(p, lockname, O_WRONLY, + REWRITELOCK_MODE)) < 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; +} + +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, + environ, 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 void expand_variables_inbuffer(request_rec *r, char *buf, int buf_len) +{ + char *newbuf; + newbuf = expand_variables(r, buf); + if (strcmp(newbuf, buf) != 0) { + ap_cpystrn(buf, newbuf, buf_len); + } + return; +} + +static char *expand_variables(request_rec *r, char *str) +{ + char output[MAX_STRING_LEN]; + char input[MAX_STRING_LEN]; + char *cp; + char *cp2; + char *cp3; + int expanded; + char *outp; + char *endp; + + ap_cpystrn(input, str, sizeof(input)); + output[0] = '\0'; + outp = output; + endp = output + sizeof(output); + expanded = 0; + for (cp = input; cp < input+MAX_STRING_LEN; ) { + if ((cp2 = strstr(cp, "%{")) != NULL) { + if ((cp3 = strstr(cp2, "}")) != NULL) { + *cp2 = '\0'; + outp = ap_cpystrn(outp, cp, endp - outp); + + cp2 += 2; + *cp3 = '\0'; + outp = ap_cpystrn(outp, lookup_variable(r, cp2), endp - outp); + + cp = cp3+1; + expanded = 1; + continue; + } + } + outp = ap_cpystrn(outp, cp, endp - outp); + break; + } + return expanded ? ap_pstrdup(r->pool, output) : str; +} + +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_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 ap_pstrdup(c->pool, ce->value); +} + +static int cache_tlb_hash(char *key) +{ + unsigned long n; + char *p; + + n = 0; + for (p=key; *p != '\0'; ++p) { + n = n * 53711 + 134561 + (unsigned)(*p & 0xff); + } + + return 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 +** | | +** +-------------------------------------------------------+ +*/ + +static char *subst_prefix_path(request_rec *r, char *input, char *match, + char *subst) +{ + char matchbuf[LONG_STRING_LEN]; + char substbuf[LONG_STRING_LEN]; + char *output; + int l; + + output = input; + + /* first create a match string which always has a trailing slash */ + l = ap_cpystrn(matchbuf, match, sizeof(matchbuf)) - matchbuf; + if (matchbuf[l-1] != '/') { + matchbuf[l] = '/'; + matchbuf[l+1] = '\0'; + l++; + } + /* now compare the prefix */ + if (strncmp(input, matchbuf, l) == 0) { + rewritelog(r, 5, "strip matching prefix: %s -> %s", output, output+l); + output = ap_pstrdup(r->pool, output+l); + + /* and now add the base-URL as replacement prefix */ + l = ap_cpystrn(substbuf, subst, sizeof(substbuf)) - substbuf; + if (substbuf[l-1] != '/') { + substbuf[l] = '/'; + substbuf[l+1] = '\0'; + l++; + } + if (output[0] == '/') { + rewritelog(r, 4, "add subst prefix: %s -> %s%s", + output, substbuf, output+1); + output = ap_pstrcat(r->pool, substbuf, output+1, NULL); + } + else { + rewritelog(r, 4, "add subst prefix: %s -> %s%s", + output, substbuf, output); + output = ap_pstrcat(r->pool, substbuf, output, NULL); + } + } + return output; +} + + +/* +** +** 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); + } +} + + + +/* +** +** stat() for only the prefix of a path +** +*/ + +static int prefix_stat(const char *path, struct stat *sb) +{ + char curpath[LONG_STRING_LEN]; + char *cp; + + ap_cpystrn(curpath, path, sizeof(curpath)); + if (curpath[0] != '/') { + return 0; + } + if ((cp = strchr(curpath+1, '/')) != NULL) { + *cp = '\0'; + } + if (stat(curpath, sb) == 0) { + return 1; + } + else { + 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 + + 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 + + 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; +} + +#ifdef NETWARE +int main(int argc, char *argv[]) +{ + ExitThread(TSR_THREAD, 0); +} +#endif + +/*EOF*/ diff --git a/APACHE_1_3_12/src/modules/standard/mod_rewrite.h b/APACHE_1_3_12/src/modules/standard/mod_rewrite.h new file mode 100644 index 0000000000..46c255279f --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_rewrite.h @@ -0,0 +1,499 @@ +/* ==================================================================== + * Copyright (c) 1996-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see <http://www.apache.org/>. + * + */ + + +#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 +#if defined(__GLIBC__) && defined(__GLIBC_MINOR__) \ + && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1 +#include <db1/ndbm.h> +#else +#include <ndbm.h> +#endif +#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... :-( + */ +#if defined(USE_FCNTL_SERIALIZED_ACCEPT) +#define USE_FCNTL 1 +#include <fcntl.h> +#endif +#if defined(USE_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 +#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 + + +/* +** +** 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 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 + +#define MAX_NMATCH 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 *); +} 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 */ +} 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 */ +} rewrite_perdir_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[10]; +} 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, + rewrite_perdir_conf *dconf, + char *option); +static const char *cmd_rewriteoptions_setoption(pool *p, int *options, + char *name); +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); + + /* 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 void expand_backref_inbuffer(pool *p, char *buf, int nbuf, + backrefinfo *bri, char c); +static char *expand_tildepaths(request_rec *r, char *uri); +static void expand_map_lookups(request_rec *r, char *uri, int uri_len); + + /* 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 void expand_variables_inbuffer(request_rec *r, char *buf, int buf_len); +static char *expand_variables(request_rec *r, char *str); +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, + char *subst); +static int parseargline(char *str, char **a1, char **a2, char **a3); +static int prefix_stat(const char *path, struct stat *sb); +static void add_env_variable(request_rec *r, char *s); + + /* 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); + +#endif /* _MOD_REWRITE_H */ + +/*EOF*/ diff --git a/APACHE_1_3_12/src/modules/standard/mod_setenvif.c b/APACHE_1_3_12/src/modules/standard/mod_setenvif.c new file mode 100644 index 0000000000..27eef0aec9 --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_setenvif.c @@ -0,0 +1,423 @@ +/* ==================================================================== + * Copyright (c) 1996-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * IT'S 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see <http://www.apache.org/>. + * + */ + +/* + * 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: + * + * remote_host Remote host name (if available) + * remote_addr Remote IP address + * remote_user Remote authenticated user (if any) + * 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_REMOTE_USER, + SPECIAL_REQUEST_URI, + SPECIAL_REQUEST_METHOD, + SPECIAL_REQUEST_PROTOCOL +}; +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; + +static void *create_setenvif_config(pool *p, server_rec *dummy) +{ + 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 *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)) + +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 = ap_get_module_config(cmd->server->module_config, + &setenvif_module); + sei_entry *new, *entries = (sei_entry *) sconf->conditionals->elts; + char *var; + int i; + int beenhere = 0; + unsigned icase; + + /* 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 idential 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, "remote_user")) { + new->special_type = SPECIAL_REMOTE_USER; + } + 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 { + 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, + RSRC_CONF, RAW_ARGS, "A header-name, regex and a list of variables." }, + { "SetEnvIfNoCase", add_setenvif, ICASE_MAGIC, + RSRC_CONF, RAW_ARGS, "a header-name, regex and a list of variables." }, + { "BrowserMatch", add_browser, NULL, + RSRC_CONF, RAW_ARGS, "A browser regex and a list of variables." }, + { "BrowserMatchNoCase", add_browser, ICASE_MAGIC, + RSRC_CONF, RAW_ARGS, "A browser regex and a list of variables." }, + { NULL }, +}; + +static int match_headers(request_rec *r) +{ + server_rec *s = r->server; + sei_cfg_rec *sconf; + sei_entry *entries; + table_entry *elts; + const char *val; + int i, j; + char *last_name; + + sconf = (sei_cfg_rec *) ap_get_module_config(s->module_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_REMOTE_HOST: + val = ap_get_remote_host(r->connection, r->per_dir_config, + REMOTE_NAME); + break; + case SPECIAL_REMOTE_USER: + val = r->connection->user; + 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 */ + NULL, /* dir config creater */ + NULL, /* dir merger --- default is to override */ + create_setenvif_config, /* 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 */ + NULL, /* input header parse */ + NULL, /* child (process) initialization */ + NULL, /* child (process) rundown */ + match_headers /* post_read_request */ +}; diff --git a/APACHE_1_3_12/src/modules/standard/mod_so.c b/APACHE_1_3_12/src/modules/standard/mod_so.c new file mode 100644 index 0000000000..0f0b63d37c --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_so.c @@ -0,0 +1,360 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see <http://www.apache.org/>. + * + */ + +/* + * 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 */ + 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; + + /* + * check for already existing module + * If it already exists, we have nothing to do + */ + 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) + return 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; + + 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_12/src/modules/standard/mod_speling.c b/APACHE_1_3_12/src/modules/standard/mod_speling.c new file mode 100644 index 0000000000..1e3a1b34ff --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_speling.c @@ -0,0 +1,566 @@ +#define WANT_BASENAME_MATCH +/* ==================================================================== + * Copyright (c) 1996-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see <http://www.apache.org/>. + * + */ + +#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 */ +}; + +#ifdef NETWARE +int main(int argc, char *argv[]) +{ + ExitThread(TSR_THREAD, 0); +} +#endif diff --git a/APACHE_1_3_12/src/modules/standard/mod_status.c b/APACHE_1_3_12/src/modules/standard/mod_status.c new file mode 100644 index 0000000000..448857905a --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_status.c @@ -0,0 +1,777 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see <http://www.apache.org/>. + * + */ + +/* 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"; + + /* + * 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: + if (*(loc + strlen(status_options[i].form_data_str)) == '=') + ap_table_set(r->headers_out, + status_options[i].hdr_out_str, + loc + strlen(status_options[i].hdr_out_str) + 1); + else + ap_table_set(r->headers_out, + status_options[i].hdr_out_str, "1"); + break; + case STAT_OPT_NOTABLE: + no_table_report = 1; + break; + case STAT_OPT_AUTO: + r->content_type = "text/plain"; + short_report = 1; + break; + } + } + i++; + } + } + + ap_send_http_header(r); + + 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\n\n", + r); + ap_rputs("

    Apache Server Status for ", r); + ap_rvputs(r, ap_get_server_name(r), "

    \n\n", NULL); + ap_rvputs(r, "Server Version: ", + ap_get_server_version(), "
    \n", NULL); + ap_rvputs(r, "Server Built: ", + ap_get_server_built(), "
    \n
    \n", NULL); + ap_rvputs(r, "Current Time: ", + ap_ht_time(r->pool, nowtime, DEFAULT_TIME_FORMAT, 0), "
    \n", NULL); + ap_rvputs(r, "Restart Time: ", + ap_ht_time(r->pool, ap_restart_time, DEFAULT_TIME_FORMAT, 0), + "
    \n", NULL); + ap_rprintf(r, "Parent Server Generation: %d
    \n", (int) ap_my_generation); + ap_rputs("Server uptime: ", r); + show_time(r, up_time); + ap_rputs("
    \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("
    \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("
    \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, KBYTE * (float) kbcount / (float) up_time); + ap_rputs("/second - ", r); + } + + if (count > 0) { + format_byte_out(r, KBYTE * (float) kbcount / (float) count); + ap_rputs("/request", r); + } + + ap_rputs("
    \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("
    ", 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("
    \n", r); + ap_rputs("Scoreboard Key:
    \n", r); + ap_rputs("\"_\" Waiting for Connection, \n", r); + ap_rputs("\"S\" Starting up, \n", r); + ap_rputs("\"R\" Reading Request,
    \n", r); + ap_rputs("\"W\" Sending Reply, \n", r); + ap_rputs("\"K\" Keepalive (read), \n", r); + ap_rputs("\"D\" DNS Lookup,
    \n", r); + ap_rputs("\"L\" Logging, \n", r); + ap_rputs("\"G\" Gracefully finishing, \n", r); + ap_rputs("\".\" Open slot with no current process

    \n", r); + ap_rputs("

    \n", r); + if (!ap_extended_status) { + int j = 0; + ap_rputs("PID Key:
    \n", r); + ap_rputs("

    \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("
    \n", r); + } + } + + if (ap_extended_status) { + if (!short_report) { + if (no_table_report) + ap_rputs("


    Server Details

    \n\n", r); + else +#ifdef NO_TIMES + /* Allow for OS/2 not having CPU stats */ + ap_rputs("

    \n\n\n\n", r); +#else + ap_rputs("

    \n\n

    SrvPIDAccM\nSSReqConnChildSlotClientVHostRequest
    \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) + ap_rprintf(r, + "Server %d-%d (-): %d|%lu|%lu [", + i, (int) ps_record.generation, (int) conn_lres, + my_lres, lres); + else + ap_rprintf(r, + "Server %d-%d (%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("Read", r); + break; + case SERVER_BUSY_WRITE: + ap_rputs("Write", r); + break; + case SERVER_BUSY_KEEPALIVE: + ap_rputs("Keepalive", r); + break; + case SERVER_BUSY_LOG: + ap_rputs("Logging", r); + break; + case SERVER_BUSY_DNS: + ap_rputs("DNS lookup", 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, " %s {%s}[%s]
    \n\n", + ap_escape_html(r->pool, score_record.client), + ap_escape_html(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) + ap_rprintf(r, + "\n\n"); + else + ap_rprintf(r, + "\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, score_record.request)); + } /* no_table_report */ + } /* !short_report */ + } /* if () */ + } /* for () */ + + if (!(short_report || no_table_report)) { +#ifdef NO_TIMES + ap_rputs("
    SrvPIDAccMCPU\nSSReqConnChildSlotClientVHostRequest
    %d-%d-%d/%lu/%lu", + i, (int) ps_record.generation, + (int) conn_lres, my_lres, lres); + else + ap_rprintf(r, + "
    %d-%d%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("_", r); + break; + case SERVER_STARTING: + ap_rputs("S", r); + break; + case SERVER_BUSY_READ: + ap_rputs("R", r); + break; + case SERVER_BUSY_WRITE: + ap_rputs("W", r); + break; + case SERVER_BUSY_KEEPALIVE: + ap_rputs("K", r); + break; + case SERVER_BUSY_LOG: + ap_rputs("L", r); + break; + case SERVER_BUSY_DNS: + ap_rputs("D", r); + break; + case SERVER_DEAD: + ap_rputs(".", r); + break; + case SERVER_GRACEFUL: + ap_rputs("G", r); + break; + default: + ap_rputs("?", r); + break; + } +#ifdef NO_TIMES + /* Allow for OS/2 not having CPU stats */ + ap_rprintf(r, "\n%.0f%ld", +#else + ap_rprintf(r, "\n%.2f%.0f%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, "%-1.1f%-2.2f%-2.2f\n", + (float) conn_bytes / KBYTE, (float) my_bytes / MBYTE, + (float) bytes / MBYTE); + if (score_record.status == SERVER_BUSY_READ) + ap_rprintf(r, + "??..reading..
    %s%s%s
    \n \ +


    \ +\n \ +
    SrvChild Server number - generation\n \ +
    PIDOS process ID\n \ +
    AccNumber of accesses this connection / this child / this slot\n \ +
    MMode of operation\n \ +
    SSSeconds since beginning of most recent request\n \ +
    ReqMilliseconds required to process most recent request\n \ +
    ConnKilobytes transferred this connection\n \ +
    ChildMegabytes transferred this child\n \ +
    SlotTotal megabytes transferred this slot\n \ +
    \n", r); +#else + ap_rputs("\n \ +
    \ +\n \ +
    SrvChild Server number - generation\n \ +
    PIDOS process ID\n \ +
    AccNumber of accesses this connection / this child / this slot\n \ +
    MMode of operation\n \ +
    CPUCPU usage, number of seconds\n \ +
    SSSeconds since beginning of most recent request\n \ +
    ReqMilliseconds required to process most recent request\n \ +
    ConnKilobytes transferred this connection\n \ +
    ChildMegabytes transferred this child\n \ +
    SlotTotal megabytes transferred this slot\n \ +
    \n", r); +#endif + } + + } else { + + ap_rputs("
    To obtain a full report with current status information ", r); + ap_rputs("you need to use the ExtendedStatus On directive. \n", r); + + } + + if (!short_report) { + ap_rputs(ap_psignature("
    \n",r), r); + ap_rputs("\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 */ +}; + +#ifdef NETWARE +int main(int argc, char *argv[]) +{ + ExitThread(TSR_THREAD, 0); +} +#endif diff --git a/APACHE_1_3_12/src/modules/standard/mod_unique_id.c b/APACHE_1_3_12/src/modules/standard/mod_unique_id.c new file mode 100644 index 0000000000..63474ed1fe --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_unique_id.c @@ -0,0 +1,400 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * mod_unique_id.c: generate a unique identifier for each request + * + * Original author: Dean Gaudet + * UUencoding modified by: Alvaro Martinez Echevarria + */ + +#include "httpd.h" +#include "http_config.h" +#include "http_log.h" +#include "multithread.h" + +#ifdef MULTITHREAD +#error sorry this module does not support multithreaded servers yet +#endif + +typedef struct { + unsigned int stamp; + unsigned int in_addr; + unsigned int pid; + 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. * A similar fix is needed to support multithreaded + * servers, using a pid/tid combo. + * + * 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; + +static APACHE_TLS unique_id_rec cur_unique_id; + +/* + * Number of elements in the structure unique_id_rec. + */ +#define UNIQUE_ID_REC_MAX 4 + +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 + + /* + * 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); + 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]; + + /* + * 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 + + /* + * 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. + * + * XXX: for multithread this needs to use a pid/tid combo and probably + * needs to be expanded to 32 bits + */ + 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 (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; + + /* 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); + + /* 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_12/src/modules/standard/mod_userdir.c b/APACHE_1_3_12/src/modules/standard/mod_userdir.c new file mode 100644 index 0000000000..829f8e2233 --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_userdir.c @@ -0,0 +1,349 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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* ~ 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 = (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 = (userdir_config *) ap_get_module_config + ( + cmd->server->module_config, + &userdir_module + ); + char *username; + const char + *usernames = arg; + char *kw = ap_getword_conf(cmd->pool, &usernames); + table *usertable; + + /* + * 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, just copy + * the string to the userdir string. + */ + s_cfg->userdir = ap_pstrdup(cmd->pool, arg); + 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; + char *x = NULL; + 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; + + if (strchr(userdir, '*')) + x = ap_getword(r->pool, &userdir, '*'); + + if (userdir[0] == '\0' || ap_os_is_path_absolute(userdir)) { + if (x) { +#ifdef HAVE_DRIVE_LETTERS + /* + * Crummy hack. Need to figure out whether we have been + * redirected to a URL or to a file on some drive. Since I + * know of no protocols that are a single letter, if the : is + * the second character, I will assume a file was specified + */ + if (strchr(x + 2, ':')) +#else + if (strchr(x, ':')) +#endif /* WIN32 */ + { + redirect = ap_pstrcat(r->pool, x, w, userdir, dname, NULL); + ap_table_setn(r->headers_out, "Location", redirect); + return REDIRECT; + } + else + filename = ap_pstrcat(r->pool, x, w, userdir, NULL); + } + else + filename = ap_pstrcat(r->pool, userdir, "/", w, NULL); + } + else if (strchr(userdir, ':')) { + redirect = ap_pstrcat(r->pool, userdir, "/", w, dname, NULL); + ap_table_setn(r->headers_out, "Location", redirect); + return REDIRECT; + } + else { +#if defined(WIN32) || defined(NETWARE) + /* Need to figure out home dirs on NT and NetWare */ + 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_12/src/modules/standard/mod_usertrack.c b/APACHE_1_3_12/src/modules/standard/mod_usertrack.c new file mode 100644 index 0000000000..9598302856 --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_usertrack.c @@ -0,0 +1,393 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* User Tracking Module (Was mod_cookies.c) + * + * 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 Netscape browsers, Microsoft Internet + * Explorer and others currently being developed. + * + * 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" + * + * Notes: + * 1. This code now logs the initial transaction (the one that created + * the cookie to start with). + * 2. This module has been designed to not interfere with other Cookies + * your site may be using; just avoid sending out cookies with + * the name "Apache=" or things will get confused. + * 3. If you want you can modify the Set-Cookie line so that the Cookie + * never expires. You would then get the same Cookie each time the + * user revisits your site. + * + * Mark Cox, mark@ukweb.com, 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) +#include +#endif + +module MODULE_VAR_EXPORT usertrack_module; + +typedef struct { + int always; + time_t expires; +} cookie_log_state; + +typedef struct { + int enabled; + char *cookie_name; +} 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 + +/* Make Cookie: Now we have to generate something that is going to be + * pretty unique. We can base it on the pid, time, hostip */ + +#define COOKIE_NAME "Apache" + +static void make_cookie(request_rec *r) +{ + cookie_log_state *cls = ap_get_module_config(r->server->module_config, + &usertrack_module); +#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 + /* 1024 == hardcoded constant */ + char cookiebuf[1024]; + char *new_cookie; + const char *rname = ap_get_remote_host(r->connection, r->per_dir_config, + REMOTE_NAME); + cookie_dir_rec *dcfg; + + 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); + + ap_snprintf(cookiebuf, sizeof(cookiebuf), "%s.%d%ld%ld", rname, + (int) getpid(), + (long) r->request_time, (long) mpe_tms.tms_utime); +#elif defined(NETWARE) + ap_snprintf(cookiebuf, sizeof(cookiebuf), "%s.%d%ld%ld", rname, + (int) getpid(), (long) r->request_time, (long) clock()); +#elif defined(WIN32) + /* + * We lack gettimeofday() and we lack times(). So we'll use a combination + * of time() and GetTickCount(), which returns milliseconds since Windows + * was started. It should be relatively unique. + */ + + ap_snprintf(cookiebuf, sizeof(cookiebuf), "%s.%d%ld%ld", rname, + (int) getpid(), + (long) r->request_time, (long) GetTickCount()); + +#else + gettimeofday(&tv, &tz); + + ap_snprintf(cookiebuf, sizeof(cookiebuf), "%s.%d%ld%d", rname, + (int) getpid(), + (long) tv.tv_sec, (int) tv.tv_usec / 1000); +#endif + + if (cls->expires) { + struct tm *tms; + time_t when = r->request_time + cls->expires; + +#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=/; expires=%s, %.2d-%s-%.2d %.2d:%.2d:%.2d GMT", + dcfg->cookie_name, cookiebuf, 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=%s; path=/", + dcfg->cookie_name, cookiebuf); + } + + ap_table_setn(r->headers_out, "Set-Cookie", new_cookie); + ap_table_setn(r->notes, "cookie", ap_pstrdup(r->pool, cookiebuf)); /* log first time */ + return; +} + +static int spot_cookie(request_rec *r) +{ + cookie_dir_rec *dcfg = ap_get_module_config(r->per_dir_config, + &usertrack_module); + const char *cookie; + char *value; + + if (!dcfg->enabled) { + return DECLINED; + } + + if ((cookie = ap_table_get(r->headers_in, "Cookie"))) + if ((value = strstr(cookie, dcfg->cookie_name))) { + char *cookiebuf, *cookieend; + + value += strlen(dcfg->cookie_name) + 1; /* Skip over the '=' */ + cookiebuf = ap_pstrdup(r->pool, value); + cookieend = strchr(cookiebuf, ';'); + if (cookieend) + *cookieend = '\0'; /* Ignore anything after a ; */ + + /* Set the cookie in a note, for logging */ + ap_table_setn(r->notes, "cookie", cookiebuf); + + 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->enabled = 0; + 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 = ap_get_module_config(parms->server->module_config, + &usertrack_module); + time_t factor, modifier = 0; + time_t num = 0; + char *word; + + /* 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] { }*" + */ + + word = ap_getword_conf(parms->pool, &arg); + if (!strncasecmp(word, "plus", 1)) { + word = ap_getword_conf(parms->pool, &arg); + }; + + /* { }* */ + while (word[0]) { + /* */ + if (ap_isdigit(word[0])) + num = atoi(word); + else + return "bad expires code, numeric value expected."; + + /* */ + word = ap_getword_conf(parms->pool, &arg); + if (!word[0]) + return "bad expires code, missing "; + + 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 */ + 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); + return NULL; +} + +static const command_rec cookie_log_cmds[] = { + {"CookieExpires", set_cookie_exp, NULL, RSRC_CONF, 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"}, + {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 */ +}; + + +#ifdef NETWARE +int main(int argc, char *argv[]) +{ + ExitThread(TSR_THREAD, 0); +} +#endif + diff --git a/APACHE_1_3_12/src/modules/standard/mod_vhost_alias.c b/APACHE_1_3_12/src/modules/standard/mod_vhost_alias.c new file mode 100644 index 0000000000..65cc5a2ef4 --- /dev/null +++ b/APACHE_1_3_12/src/modules/standard/mod_vhost_alias.c @@ -0,0 +1,482 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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 . + * + * 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 . + */ + +#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 (*map != '/') { + if (strcasecmp(map, "none")) { + return "format string must start with '/' or be '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; + int cgi; + + conf = (mva_sconf_t *) ap_get_module_config(r->server->module_config, + &vhost_alias_module); + if (!strncmp(r->uri, "/cgi-bin/", 9)) { + mode = conf->cgi_root_mode; + map = conf->cgi_root; + uri = r->uri + 8; + /* + * can't force cgi immediately because we might not handle this + * call if the mode is wrong + */ + cgi = 1; + } + else if (r->uri[0] == '/') { + mode = conf->doc_root_mode; + map = conf->doc_root; + uri = r->uri; + cgi = 0; + } + 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_12/src/modules/test/.cvsignore b/APACHE_1_3_12/src/modules/test/.cvsignore new file mode 100644 index 0000000000..8b4c6e3da4 --- /dev/null +++ b/APACHE_1_3_12/src/modules/test/.cvsignore @@ -0,0 +1,3 @@ +Makefile +*.lo +*.so diff --git a/APACHE_1_3_12/src/modules/test/.indent.pro b/APACHE_1_3_12/src/modules/test/.indent.pro new file mode 100644 index 0000000000..a9fbe9f9a1 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/modules/test/Makefile.tmpl b/APACHE_1_3_12/src/modules/test/Makefile.tmpl new file mode 100644 index 0000000000..9c220b1507 --- /dev/null +++ b/APACHE_1_3_12/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)/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)/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_12/src/modules/test/README b/APACHE_1_3_12/src/modules/test/README new file mode 100644 index 0000000000..c61763c1dd --- /dev/null +++ b/APACHE_1_3_12/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_12/src/modules/test/mod_rndchunk.c b/APACHE_1_3_12/src/modules/test/mod_rndchunk.c new file mode 100644 index 0000000000..3f2a702a82 --- /dev/null +++ b/APACHE_1_3_12/src/modules/test/mod_rndchunk.c @@ -0,0 +1,179 @@ +/* ==================================================================== + * Copyright (c) 1998-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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: + * + * + * SetHandler rndchunk + * + * + * 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); + 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 ?seed,count", r); + ap_kill_timeout(r); + return 0; + } + seed = strtol(args, &endptr, 0); + if (!endptr || *endptr != ',') { + goto error; + } + ++endptr; + count = 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_12/src/modules/test/mod_test_util_uri.c b/APACHE_1_3_12/src/modules/test/mod_test_util_uri.c new file mode 100644 index 0000000000..4fb428fafc --- /dev/null +++ b/APACHE_1_3_12/src/modules/test/mod_test_util_uri.c @@ -0,0 +1,354 @@ +/* ==================================================================== + * Copyright (c) 1998-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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: + * + * + * SetHandler test-util-uri + * + * + * 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 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, "%d0x%02x0x%02x%d\"%s\"", row, u, expect, status, input_uri); +#define DUMP(f) \ + if (result.f) { \ + ap_rvputs(r, "\"", result.f, "\"
    ", NULL); \ + } \ + else { \ + ap_rputs("NULL
    ", r); \ + } \ + if (expect & T_##f) { \ + ap_rvputs(r, "\"", pieces->f, "\"", NULL); \ + } \ + else { \ + ap_rputs("NULL", r); \ + } + DUMP(scheme); + DUMP(user); + DUMP(password); + DUMP(hostname); + DUMP(port_str); + DUMP(path); + DUMP(query); + DUMP(fragment); +#undef DUMP + ap_rputs("\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); + if(r->header_only) { + return 0; + } + ap_hard_timeout("test_util_uri", r); + + ap_rputs( +DOCTYPE_HTML_2_0 " + +

    Key: +

    +
    row +
    entry number in the uri_tests array +
    u +
    fields under test +
    expected +
    fields expected in the result +
    status +
    response from parse_uri_components, or 500 if unexpected results +
    input uri +
    the uri given to parse_uri_components +
    +

    The remaining fields are the pieces returned from parse_uri_components, and +the values we expected for each piece (resp.). +

    Only failures are displayed. +

    +", r); +#define HEADER(f) ap_rprintf(r, "", 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, "
    rowuexpectstatusinput uri" #f "
    0x%02x
    \nStopped early to save your browser " + "from certain death!\nTOTAL FAILURES = %u\n", + total_failures); + return OK; + } + } + } + ap_rprintf(r, "\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_12/src/os/.indent.pro b/APACHE_1_3_12/src/os/.indent.pro new file mode 100644 index 0000000000..a9fbe9f9a1 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/os/bs2000/.cvsignore b/APACHE_1_3_12/src/os/bs2000/.cvsignore new file mode 100644 index 0000000000..f3c7a7c5da --- /dev/null +++ b/APACHE_1_3_12/src/os/bs2000/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/APACHE_1_3_12/src/os/bs2000/Makefile.tmpl b/APACHE_1_3_12/src/os/bs2000/Makefile.tmpl new file mode 100644 index 0000000000..e56c1b618c --- /dev/null +++ b/APACHE_1_3_12/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 ebcdic.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)/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)/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_12/src/os/bs2000/bs2login.c b/APACHE_1_3_12/src/os/bs2000/bs2login.c new file mode 100644 index 0000000000..dad5bab5f9 --- /dev/null +++ b/APACHE_1_3_12/src/os/bs2000/bs2login.c @@ -0,0 +1,296 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +#ifdef _OSD_POSIX +#include "httpd.h" +#include "http_config.h" +#include "http_log.h" +#include +#include + +#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_12/src/os/bs2000/ebcdic.c b/APACHE_1_3_12/src/os/bs2000/ebcdic.c new file mode 100644 index 0000000000..be92650375 --- /dev/null +++ b/APACHE_1_3_12/src/os/bs2000/ebcdic.c @@ -0,0 +1,182 @@ +/* ==================================================================== + * Copyright (c) 1998-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + + +#ifdef CHARSET_EBCDIC +#include "ap_config.h" +#include "ebcdic.h" +/* + Initial Port for Apache-1.3 by + +"BS2000 OSD/POSIX" is a POSIX subsystem on a main frame. It is made +by Fujitsu-Siemens Computers GmbH, Germany. The POSIX system has been +derived from a regular SVR4 source and thus is very "compatible" +to other unixes. In fact, it received the X/Open branding. + +Within the POSIX subsystem, the same character set was chosen as in +"native BS2000", namely EBCDIC. This requires conversions at various +stages of the request and response processing. + +EBCDIC Table. (In EBCDIC, the letters 'a'..'z' are not contiguous!) +This table is bijective, i.e. there are no ambigous or duplicate characters +*/ + +/* Bijective ebcdic-to-ascii table: */ +const unsigned char os_toascii[256] = { +/*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.{.}.~*/ +}; + + +/* Bijective ascii-to-ebcdic table: */ +const unsigned char os_toebcdic[256] = { +/*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 /*................*/ +}; + +/* 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). + */ + +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; +} + +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_12/src/os/bs2000/ebcdic.h b/APACHE_1_3_12/src/os/bs2000/ebcdic.h new file mode 100644 index 0000000000..f54817d724 --- /dev/null +++ b/APACHE_1_3_12/src/os/bs2000/ebcdic.h @@ -0,0 +1,11 @@ +#ifndef AP_EBCDIC_H +#define AP_EBCDIC_H "$Id: ebcdic.h,v 1.7 2000/01/07 16:04:12 martin Exp $" + +#include + +extern const unsigned char os_toascii[256]; +extern const unsigned char os_toebcdic[256]; +void *ebcdic2ascii(void *dest, const void *srce, size_t count); +void *ascii2ebcdic(void *dest, const void *srce, size_t count); + +#endif /*AP_EBCDIC_H*/ diff --git a/APACHE_1_3_12/src/os/bs2000/os-inline.c b/APACHE_1_3_12/src/os/bs2000/os-inline.c new file mode 100644 index 0000000000..e58917af36 --- /dev/null +++ b/APACHE_1_3_12/src/os/bs2000/os-inline.c @@ -0,0 +1,31 @@ +/* + * 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_12/src/os/bs2000/os.c b/APACHE_1_3_12/src/os/bs2000/os.c new file mode 100644 index 0000000000..a23e245f77 --- /dev/null +++ b/APACHE_1_3_12/src/os/bs2000/os.c @@ -0,0 +1,104 @@ +/* ==================================================================== + * Copyright (c) 1998-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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" + +/* Check the Content-Type to decide if conversion is needed */ +int ap_checkconv(struct request_rec *r) +{ + int convert_to_ascii; + const char *type; + + /* To make serving of "raw ASCII text" files easy (they serve faster + * since they don't have to be converted from EBCDIC), a new + * "magic" type prefix was invented: text/x-ascii-{plain,html,...} + * If we detect one of these content types here, we simply correct + * the type to the real text/{plain,html,...} type. Otherwise, we + * set a flag that translation is required later on. + */ + + type = (r->content_type == NULL) ? ap_default_type(r) : r->content_type; + + /* If no content type is set then treat it as (ebcdic) text/plain */ + convert_to_ascii = (type == NULL); + + /* Conversion is applied to text/ files only, if ever. */ + if (type && (strncasecmp(type, "text/", 5) == 0 || + strncasecmp(type, "message/", 8) == 0 || + strncasecmp(type, "multipart/", 10) == 0)) { + if (strncasecmp(type, ASCIITEXT_MAGIC_TYPE_PREFIX, + sizeof(ASCIITEXT_MAGIC_TYPE_PREFIX)-1) == 0) + r->content_type = ap_pstrcat(r->pool, "text/", + type+sizeof(ASCIITEXT_MAGIC_TYPE_PREFIX)-1, + NULL); + else + /* translate EBCDIC to ASCII */ + convert_to_ascii = 1; + } + /* Enable conversion if it's a text document */ + ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, convert_to_ascii); + + return convert_to_ascii; +} + diff --git a/APACHE_1_3_12/src/os/bs2000/os.h b/APACHE_1_3_12/src/os/bs2000/os.h new file mode 100644 index 0000000000..1ede0813f2 --- /dev/null +++ b/APACHE_1_3_12/src/os/bs2000/os.h @@ -0,0 +1,51 @@ +#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) +typedef struct { + char *username; + char *account; + char *processor_name; +} _rini_struct; + +extern int _rini(_rini_struct *); +#endif /* !defined(_POSIX_SOURCE) && !defined(_XOPEN_SOURCE) */ + +/* Sorry if this is ugly, but the include order doesn't allow me + * to use request_rec here... */ +struct request_rec; +extern int ap_checkconv(struct request_rec *r); +extern pid_t os_fork(const char *user); + +#endif /*! APACHE_OS_H*/ diff --git a/APACHE_1_3_12/src/os/mpeix/Makefile.tmpl b/APACHE_1_3_12/src/os/mpeix/Makefile.tmpl new file mode 100644 index 0000000000..6cf10dedf6 --- /dev/null +++ b/APACHE_1_3_12/src/os/mpeix/Makefile.tmpl @@ -0,0 +1,50 @@ +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) mpe_dl_stub.o + +LIB= libos.a + +all: $(LIB) mpe_dl_stub.o + +$(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 +mpe_dl_stub.o: mpe_dl_stub.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_12/src/os/mpeix/README b/APACHE_1_3_12/src/os/mpeix/README new file mode 100644 index 0000000000..33b6a3ff64 --- /dev/null +++ b/APACHE_1_3_12/src/os/mpeix/README @@ -0,0 +1,5 @@ +For the latest info about Apache for MPE/iX, please see: + + http://jazz.external.hp.com/src/apache/index.html + or + http://www.bixby.org/mark/apacheix.html diff --git a/APACHE_1_3_12/src/os/mpeix/dlopen.c b/APACHE_1_3_12/src/os/mpeix/dlopen.c new file mode 100644 index 0000000000..f991867c53 --- /dev/null +++ b/APACHE_1_3_12/src/os/mpeix/dlopen.c @@ -0,0 +1,216 @@ +/* + * 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); + +/* +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. +*/ + +/* 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; + +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_12/src/os/mpeix/gettimeofday.c b/APACHE_1_3_12/src/os/mpeix/gettimeofday.c new file mode 100644 index 0000000000..3b593fa1cd --- /dev/null +++ b/APACHE_1_3_12/src/os/mpeix/gettimeofday.c @@ -0,0 +1,116 @@ +/* + stub for gettimeofday(): + gettimeofday() is UNIX, not POSIX +*/ + +/*-------------------------------------------------------------------*/ +/* */ +/* gettimeofday */ +/* */ +/*-------------------------------------------------------------------*/ +/* */ +/* #include */ +/* */ +/* 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 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 /* 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_12/src/os/mpeix/mpe_dl_stub.c b/APACHE_1_3_12/src/os/mpeix/mpe_dl_stub.c new file mode 100644 index 0000000000..876ba16575 --- /dev/null +++ b/APACHE_1_3_12/src/os/mpeix/mpe_dl_stub.c @@ -0,0 +1 @@ +int mpe_dl_stub(void) { return 0; }; diff --git a/APACHE_1_3_12/src/os/mpeix/os-inline.c b/APACHE_1_3_12/src/os/mpeix/os-inline.c new file mode 100644 index 0000000000..fe3e5fc9a5 --- /dev/null +++ b/APACHE_1_3_12/src/os/mpeix/os-inline.c @@ -0,0 +1 @@ +#include "../unix/os-inline.c" diff --git a/APACHE_1_3_12/src/os/mpeix/os.c b/APACHE_1_3_12/src/os/mpeix/os.c new file mode 100644 index 0000000000..d3884a5dc4 --- /dev/null +++ b/APACHE_1_3_12/src/os/mpeix/os.c @@ -0,0 +1 @@ +#include "../unix/os.c" diff --git a/APACHE_1_3_12/src/os/mpeix/os.h b/APACHE_1_3_12/src/os/mpeix/os.h new file mode 100644 index 0000000000..b92457af16 --- /dev/null +++ b/APACHE_1_3_12/src/os/mpeix/os.h @@ -0,0 +1,147 @@ +/* ==================================================================== + * Copyright (c) 1998-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +#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 +#endif + +/* + * Do not use native AIX DSO support + */ +#ifdef AIX +#undef HAVE_DLFCN_H +#endif + +#ifdef HAVE_DLFCN_H +#include +#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_12/src/os/netware/Apache.def b/APACHE_1_3_12/src/os/netware/Apache.def new file mode 100644 index 0000000000..9f1c81463d --- /dev/null +++ b/APACHE_1_3_12/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_12/src/os/netware/ApacheCore.imp b/APACHE_1_3_12/src/os/netware/ApacheCore.imp new file mode 100644 index 0000000000..072ccaed59 --- /dev/null +++ b/APACHE_1_3_12/src/os/netware/ApacheCore.imp @@ -0,0 +1,347 @@ +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_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_path_segment +ap_escape_quotes +ap_escape_shell_cmd +ap_exists_scoreboard_image +ap_finalize_request_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_pregcomp +ap_pregfree +ap_pregsub +ap_psignature +ap_psocket +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 +apache_main +ap_get_virthost_addr +ap_listeners +ap_listenbacklog + diff --git a/APACHE_1_3_12/src/os/netware/ApacheCoreNW.def b/APACHE_1_3_12/src/os/netware/ApacheCoreNW.def new file mode 100644 index 0000000000..f171a764a6 --- /dev/null +++ b/APACHE_1_3_12/src/os/netware/ApacheCoreNW.def @@ -0,0 +1,4 @@ +MODULE CLIB.NLM +MODULE WS2_32.NLM +IMPORT KillMe +EXPORT @apachecore.imp diff --git a/APACHE_1_3_12/src/os/netware/ApacheModuleAuthAnon.def b/APACHE_1_3_12/src/os/netware/ApacheModuleAuthAnon.def new file mode 100644 index 0000000000..7465f677d1 --- /dev/null +++ b/APACHE_1_3_12/src/os/netware/ApacheModuleAuthAnon.def @@ -0,0 +1,2 @@ +EXPORT anon_auth_module + diff --git a/APACHE_1_3_12/src/os/netware/ApacheModuleCERNMeta.def b/APACHE_1_3_12/src/os/netware/ApacheModuleCERNMeta.def new file mode 100644 index 0000000000..cb57210ebd --- /dev/null +++ b/APACHE_1_3_12/src/os/netware/ApacheModuleCERNMeta.def @@ -0,0 +1 @@ +EXPORT cern_meta_module diff --git a/APACHE_1_3_12/src/os/netware/ApacheModuleDigest.def b/APACHE_1_3_12/src/os/netware/ApacheModuleDigest.def new file mode 100644 index 0000000000..74575fff4f --- /dev/null +++ b/APACHE_1_3_12/src/os/netware/ApacheModuleDigest.def @@ -0,0 +1 @@ +EXPORT digest_module diff --git a/APACHE_1_3_12/src/os/netware/ApacheModuleExpires.def b/APACHE_1_3_12/src/os/netware/ApacheModuleExpires.def new file mode 100644 index 0000000000..b48301ca05 --- /dev/null +++ b/APACHE_1_3_12/src/os/netware/ApacheModuleExpires.def @@ -0,0 +1 @@ +EXPORT expires_module diff --git a/APACHE_1_3_12/src/os/netware/ApacheModuleHeaders.def b/APACHE_1_3_12/src/os/netware/ApacheModuleHeaders.def new file mode 100644 index 0000000000..5c765c286e --- /dev/null +++ b/APACHE_1_3_12/src/os/netware/ApacheModuleHeaders.def @@ -0,0 +1 @@ +EXPORT headers_module diff --git a/APACHE_1_3_12/src/os/netware/ApacheModuleInfo.def b/APACHE_1_3_12/src/os/netware/ApacheModuleInfo.def new file mode 100644 index 0000000000..6669099004 --- /dev/null +++ b/APACHE_1_3_12/src/os/netware/ApacheModuleInfo.def @@ -0,0 +1,2 @@ +EXPORT info_module + diff --git a/APACHE_1_3_12/src/os/netware/ApacheModuleProxy.def b/APACHE_1_3_12/src/os/netware/ApacheModuleProxy.def new file mode 100644 index 0000000000..7b1c93b7d7 --- /dev/null +++ b/APACHE_1_3_12/src/os/netware/ApacheModuleProxy.def @@ -0,0 +1 @@ +EXPORT proxy_module diff --git a/APACHE_1_3_12/src/os/netware/ApacheModuleRewrite.def b/APACHE_1_3_12/src/os/netware/ApacheModuleRewrite.def new file mode 100644 index 0000000000..2f7d7e8c11 --- /dev/null +++ b/APACHE_1_3_12/src/os/netware/ApacheModuleRewrite.def @@ -0,0 +1 @@ +EXPORT rewrite_module diff --git a/APACHE_1_3_12/src/os/netware/ApacheModuleSpeling.def b/APACHE_1_3_12/src/os/netware/ApacheModuleSpeling.def new file mode 100644 index 0000000000..dec9ffc366 --- /dev/null +++ b/APACHE_1_3_12/src/os/netware/ApacheModuleSpeling.def @@ -0,0 +1,2 @@ +EXPORT speling_module + diff --git a/APACHE_1_3_12/src/os/netware/ApacheModuleStatus.def b/APACHE_1_3_12/src/os/netware/ApacheModuleStatus.def new file mode 100644 index 0000000000..06f9577cea --- /dev/null +++ b/APACHE_1_3_12/src/os/netware/ApacheModuleStatus.def @@ -0,0 +1 @@ +EXPORT status_module diff --git a/APACHE_1_3_12/src/os/netware/ApacheModuleUserTrack.def b/APACHE_1_3_12/src/os/netware/ApacheModuleUserTrack.def new file mode 100644 index 0000000000..bd975910c2 --- /dev/null +++ b/APACHE_1_3_12/src/os/netware/ApacheModuleUserTrack.def @@ -0,0 +1 @@ +EXPORT usertrack_module diff --git a/APACHE_1_3_12/src/os/netware/getopt.c b/APACHE_1_3_12/src/os/netware/getopt.c new file mode 100644 index 0000000000..969a5629e7 --- /dev/null +++ b/APACHE_1_3_12/src/os/netware/getopt.c @@ -0,0 +1,161 @@ +#include +#include +#include +#include + +#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 ] files...\n"); + exit(2); + } + + for ( ; optind < argc; optind++) + (void)printf("%s\n", argv[optind]); + + return 0; +} + +#endif /* TESTGETOPT */ \ No newline at end of file diff --git a/APACHE_1_3_12/src/os/netware/getopt.h b/APACHE_1_3_12/src/os/netware/getopt.h new file mode 100644 index 0000000000..f0a4e696ce --- /dev/null +++ b/APACHE_1_3_12/src/os/netware/getopt.h @@ -0,0 +1,10 @@ +#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 */ \ No newline at end of file diff --git a/APACHE_1_3_12/src/os/netware/main_nlm.c b/APACHE_1_3_12/src/os/netware/main_nlm.c new file mode 100644 index 0000000000..5950d4f73b --- /dev/null +++ b/APACHE_1_3_12/src/os/netware/main_nlm.c @@ -0,0 +1,10 @@ +/* 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_12/src/os/netware/mod_nlm.c b/APACHE_1_3_12/src/os/netware/mod_nlm.c new file mode 100644 index 0000000000..2b1aabd5f5 --- /dev/null +++ b/APACHE_1_3_12/src/os/netware/mod_nlm.c @@ -0,0 +1,148 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +#include "httpd.h" +#include "http_config.h" +#include + +module MODULE_VAR_EXPORT nlm_module; +static int been_there_done_that = 0; /* Loaded the modules yet? */ + +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; +} + +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_12/src/os/netware/modules.c b/APACHE_1_3_12/src/os/netware/modules.c new file mode 100644 index 0000000000..16e6688a76 --- /dev/null +++ b/APACHE_1_3_12/src/os/netware/modules.c @@ -0,0 +1,70 @@ +/* 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_12/src/os/netware/multithread.c b/APACHE_1_3_12/src/os/netware/multithread.c new file mode 100644 index 0000000000..2b306d8fe9 --- /dev/null +++ b/APACHE_1_3_12/src/os/netware/multithread.c @@ -0,0 +1,102 @@ + +#include "ap_config.h" +#include "httpd.h" +#include "http_conf_globals.h" +#include "multithread.h" +#include + + + +thread *create_thread(void (thread_fn)(void *), void *thread_arg) +{ + int rv; + + rv = BeginThread(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(malloc(1)); +} + +mutex * ap_open_mutex(char *name) +{ + return((mutex*)EnterCritSec()); +} + +int ap_acquire_mutex(mutex *mutex_id) +{ + return(EnterCritSec()); +} + +int ap_release_mutex(mutex *mutex_id) +{ + return(ExitCritSec()); +} + +void ap_destroy_mutex(mutex *mutex_id) +{ + free(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_12/src/os/netware/os.c b/APACHE_1_3_12/src/os/netware/os.c new file mode 100644 index 0000000000..1518ba5e8b --- /dev/null +++ b/APACHE_1_3_12/src/os/netware/os.c @@ -0,0 +1,124 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +#include "ap_config.h" + +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 = FindNLMHandle((char*)moduleName); + + if (nlmHandle == NULL) { + spawnlp(P_NOWAIT | P_SPAWN_IN_CURRENT_DOMAIN, path, NULL); + nlmHandle = FindNLMHandle((char *)moduleName); + } + + 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); +} + +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. + * + */ + +#ifndef APACHE_OS_H +#define APACHE_OS_H + +#define PLATFORM "NETWARE" + +/* + * 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 int int32; +typedef int uid_t; +typedef int gid_t; + +#include "ap_config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 GetThreadID +#define lstat(x, y) stat(x, y) +#define ap_os_is_filename_valid(f) (1) +#define strcasecmp(s1, s2) stricmp(s1, s2) +#define strncasecmp(s1, s2, n) strnicmp(s1, s2, n) +#define mktemp(s) tmpnam(s) +#define _getch(c) getch(c) + + +/* Prototypes */ +void AMCSocketCleanup(void); +static void clean_parent_exit(int code); + +inline int ap_os_is_path_absolute(const char *file) +{ + if (strstr(file, ":/")) + return 1; + else + 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 *); +const char *ap_os_dso_error(void); +char *remove_filename(char*); +char *bslash2slash(char*); +#endif /*! APACHE_OS_H*/ + diff --git a/APACHE_1_3_12/src/os/netware/precomp.h b/APACHE_1_3_12/src/os/netware/precomp.h new file mode 100644 index 0000000000..b5c7d0f86b --- /dev/null +++ b/APACHE_1_3_12/src/os/netware/precomp.h @@ -0,0 +1,11 @@ +#pragma precompile_target "precomp.mch" +#define NETWARE + +#ifndef __int64 +#define __int64 long long +#endif + + + + + diff --git a/APACHE_1_3_12/src/os/netware/test_char.h b/APACHE_1_3_12/src/os/netware/test_char.h new file mode 100644 index 0000000000..bd26df220a --- /dev/null +++ b/APACHE_1_3_12/src/os/netware/test_char.h @@ -0,0 +1,21 @@ +/* this file is automatically generated by gen_test_char, do not edit */ +#define T_ESCAPE_SHELL_CMD (1) +#define T_ESCAPE_PATH_SEGMENT (2) +#define T_OS_ESCAPE_PATH (4) +#define T_HTTP_TOKEN_STOP (8) + +static const unsigned char test_char_table[256] = { + 0,14,14,14,14,14,14,14,14,14,15,14,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,14,14,14,14,14,14,0,7,6,1,6,1,1, + 9,9,1,0,8,0,0,10,0,0,0,0,0,0,0,0,0,0,8,15, + 15,8,15,15,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,15,15,15,7,0,7,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,15,7,15,1,14,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6 +}; diff --git a/APACHE_1_3_12/src/os/netware/uri_delims.h b/APACHE_1_3_12/src/os/netware/uri_delims.h new file mode 100644 index 0000000000..0c855bf726 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/os/os2/.cvsignore b/APACHE_1_3_12/src/os/os2/.cvsignore new file mode 100644 index 0000000000..f3c7a7c5da --- /dev/null +++ b/APACHE_1_3_12/src/os/os2/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/APACHE_1_3_12/src/os/os2/Makefile.tmpl b/APACHE_1_3_12/src/os/os2/Makefile.tmpl new file mode 100644 index 0000000000..98e96aaf84 --- /dev/null +++ b/APACHE_1_3_12/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)/alloc.h $(INCDIR)/buff.h \ + $(INCDIR)/ap.h $(INCDIR)/util_uri.h $(INCDIR)/http_log.h diff --git a/APACHE_1_3_12/src/os/os2/os-inline.c b/APACHE_1_3_12/src/os/os2/os-inline.c new file mode 100644 index 0000000000..e3ff9f2fb8 --- /dev/null +++ b/APACHE_1_3_12/src/os/os2/os-inline.c @@ -0,0 +1,34 @@ +/* + * 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] == ':'); +} diff --git a/APACHE_1_3_12/src/os/os2/os.c b/APACHE_1_3_12/src/os/os2/os.c new file mode 100644 index 0000000000..934ca24614 --- /dev/null +++ b/APACHE_1_3_12/src/os/os2/os.c @@ -0,0 +1,63 @@ +/* + * 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 +#include +#include + +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_12/src/os/os2/os.h b/APACHE_1_3_12/src/os/os2/os.h new file mode 100644 index 0000000000..d717f1f8ca --- /dev/null +++ b/APACHE_1_3_12/src/os/os2/os.h @@ -0,0 +1,52 @@ +#ifndef APACHE_OS_H +#define APACHE_OS_H + +#define PLATFORM "OS/2" +#define HAVE_CANONICAL_FILENAME +#define HAVE_DRIVE_LETTERS + +/* + * 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 + +/* 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_12/src/os/os2/util_os2.c b/APACHE_1_3_12/src/os/os2/util_os2.c new file mode 100644 index 0000000000..820ea61800 --- /dev/null +++ b/APACHE_1_3_12/src/os/os2/util_os2.c @@ -0,0 +1,96 @@ +#define INCL_DOS +#define INCL_DOSERRORS +#include +#include "httpd.h" +#include "http_log.h" + + +API_EXPORT(char *)ap_os_canonical_filename(pool *pPool, const char *szFile) +{ + char buf[HUGE_STRING_LEN]; + char buf2[HUGE_STRING_LEN]; + int rc, len; + char *pos; + +/* Remove trailing slash unless it's a root directory */ + strcpy(buf, szFile); + len = strlen(buf); + + if (len > 3 && buf[len-1] == '/') + buf[--len] = 0; + + rc = DosQueryPathInfo(buf, FIL_QUERYFULLNAME, buf2, HUGE_STRING_LEN); + + 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, ""); + } else { + return ap_pstrdup(pPool, szFile); + } + } + + strlwr(buf2); + +/* Switch backslashes to forward */ + for (pos=buf2; *pos; pos++) + if (*pos == '\\') + *pos = '/'; + + return ap_pstrdup(pPool, buf2); +} + + + +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 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 + +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)/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_12/src/os/os390/README.os390 b/APACHE_1_3_12/src/os/os390/README.os390 new file mode 100644 index 0000000000..547b3f6633 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/os/os390/ebcdic.c b/APACHE_1_3_12/src/os/os390/ebcdic.c new file mode 100644 index 0000000000..02ae9db3e8 --- /dev/null +++ b/APACHE_1_3_12/src/os/os390/ebcdic.c @@ -0,0 +1,173 @@ +/* ==================================================================== + * Copyright (c) 1998-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + + +#ifdef CHARSET_EBCDIC +#include "ap_config.h" +#include "ebcdic.h" +/* +This code does basic character mapping for IBM's OS/390 Unix +System Services operating system. It is a modified version +of 's code for the BS2000 +(apache/src/os/bs2000/ebcdic.c). +*/ + +/* +Bijective EBCDIC (character set IBM-1047) to US-ASCII table: +This table is bijective - there are no ambigous or duplicate characters. +*/ +const unsigned char os_toascii[256] = { + 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...... */ +}; + + +/* +The US-ASCII to EBCDIC (character set IBM-1047) table: +This table is bijective (no ambiguous or duplicate characters) +*/ +const unsigned char os_toebcdic[256] = { + 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 /* ................ */ +}; + +/* 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. + */ +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++]; + } +} + +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++]; + } +} +#endif /*CHARSET_EBCDIC*/ + diff --git a/APACHE_1_3_12/src/os/os390/ebcdic.h b/APACHE_1_3_12/src/os/os390/ebcdic.h new file mode 100644 index 0000000000..82b6f699be --- /dev/null +++ b/APACHE_1_3_12/src/os/os390/ebcdic.h @@ -0,0 +1,6 @@ +#include + +extern const unsigned char os_toascii[256]; +extern const unsigned char os_toebcdic[256]; +void ebcdic2ascii(void *dest, const void *srce, size_t count); +void ascii2ebcdic(void *dest, const void *srce, size_t count); diff --git a/APACHE_1_3_12/src/os/os390/os-inline.c b/APACHE_1_3_12/src/os/os390/os-inline.c new file mode 100644 index 0000000000..e58917af36 --- /dev/null +++ b/APACHE_1_3_12/src/os/os390/os-inline.c @@ -0,0 +1,31 @@ +/* + * 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_12/src/os/os390/os.c b/APACHE_1_3_12/src/os/os390/os.c new file mode 100644 index 0000000000..c33810a2f0 --- /dev/null +++ b/APACHE_1_3_12/src/os/os390/os.c @@ -0,0 +1,103 @@ +/* ==================================================================== + * Copyright (c) 1998-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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" + +/* Check the Content-Type to decide if conversion is needed */ +int ap_checkconv(struct request_rec *r) +{ + int convert_to_ascii; + const char *type; + + /* To make serving of "raw ASCII text" files easy (they serve faster + * since they don't have to be converted from EBCDIC), a new + * "magic" type prefix was invented: text/x-ascii-{plain,html,...} + * If we detect one of these content types here, we simply correct + * the type to the real text/{plain,html,...} type. Otherwise, we + * set a flag that translation is required later on. + */ + + type = (r->content_type == NULL) ? ap_default_type(r) : r->content_type; + + /* If no content type is set then treat it as (ebcdic) text/plain */ + convert_to_ascii = (type == NULL); + + /* Conversion is applied to text/ files only, if ever. */ + if (type && (strncasecmp(type, "text/", 5) == 0 || + strncasecmp(type, "message/", 8) == 0)) { + if (strncasecmp(type, ASCIITEXT_MAGIC_TYPE_PREFIX, + sizeof(ASCIITEXT_MAGIC_TYPE_PREFIX)-1) == 0) + r->content_type = ap_pstrcat(r->pool, "text/", + type+sizeof(ASCIITEXT_MAGIC_TYPE_PREFIX)-1, + NULL); + else + /* translate EBCDIC to ASCII */ + convert_to_ascii = 1; + } + /* Enable conversion if it's a text document */ + ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, convert_to_ascii); + + return convert_to_ascii; +} + diff --git a/APACHE_1_3_12/src/os/os390/os.h b/APACHE_1_3_12/src/os/os390/os.h new file mode 100644 index 0000000000..4aec04aa5f --- /dev/null +++ b/APACHE_1_3_12/src/os/os390/os.h @@ -0,0 +1,40 @@ +#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) + +/* Sorry if this is ugly, but the include order doesn't allow me + * to use request_rec here... */ +struct request_rec; +extern int ap_checkconv(struct request_rec *r); + +#endif /*! APACHE_OS_H*/ diff --git a/APACHE_1_3_12/src/os/os390/xebcdic.sh b/APACHE_1_3_12/src/os/os390/xebcdic.sh new file mode 100755 index 0000000000..8aa6998065 --- /dev/null +++ b/APACHE_1_3_12/src/os/os390/xebcdic.sh @@ -0,0 +1,202 @@ +#!/bin/sh +# +# 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_12/src/os/tpf/Makefile.tmpl b/APACHE_1_3_12/src/os/tpf/Makefile.tmpl new file mode 100644 index 0000000000..14aa0899b1 --- /dev/null +++ b/APACHE_1_3_12/src/os/tpf/Makefile.tmpl @@ -0,0 +1,42 @@ +CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS) +LIBS=$(EXTRA_LIBS) $(LIBS1) +INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES) +LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS) + +OBJS= os.o os-inline.o ebcdic.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 +ebcdic.o: ebcdic.c +cgetop.o: cgetop.c +# DO NOT REMOVE +os.o: os.c diff --git a/APACHE_1_3_12/src/os/tpf/TPFExport b/APACHE_1_3_12/src/os/tpf/TPFExport new file mode 100644 index 0000000000..c737f8d0b2 --- /dev/null +++ b/APACHE_1_3_12/src/os/tpf/TPFExport @@ -0,0 +1,9 @@ +#!/bin/sh +echo " Setting TPF/c89 environment variables" +export _C89_CCMODE=1 +# replace the following with the location of your TPF include files +export _C89_INCDIRS="/u/tpf41/currentmaint/include /u/tpf41/currentmaint/include/oco" +export TPF=YES +export _C89_INCLIBS="" +export _C89_CSYSLIB="" +echo "Done" diff --git a/APACHE_1_3_12/src/os/tpf/cgetop.c b/APACHE_1_3_12/src/os/tpf/cgetop.c new file mode 100644 index 0000000000..90ffbce5f4 --- /dev/null +++ b/APACHE_1_3_12/src/os/tpf/cgetop.c @@ -0,0 +1,151 @@ +/**********************************************************************/ +/* */ +/* 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. */ +/* */ +/**********************************************************************/ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)getopt.c 8.2 (Berkeley) 4/2/94"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include + +#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 = ∅ + 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 */ +} \ No newline at end of file diff --git a/APACHE_1_3_12/src/os/tpf/ebcdic.c b/APACHE_1_3_12/src/os/tpf/ebcdic.c new file mode 100644 index 0000000000..5207ea8811 --- /dev/null +++ b/APACHE_1_3_12/src/os/tpf/ebcdic.c @@ -0,0 +1,170 @@ +/* ==================================================================== + * Copyright (c) 1998-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + + +#ifdef CHARSET_EBCDIC +#include "ap_config.h" +#include "ebcdic.h" +/* +This code does basic character mapping for IBM's TPF operating system. +It is a modified version of 's code for +the BS2000 (apache/src/os/bs2000/ebcdic.c). +*/ + +/* +Bijective EBCDIC (character set IBM-1047) to US-ASCII table: +This table is bijective - there are no ambigous or duplicate characters. +*/ +const unsigned char os_toascii[256] = { + 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...... */ +}; + +/* +The US-ASCII to EBCDIC (character set IBM-1047) table: +This table is bijective (no ambiguous or duplicate characters) +*/ +const unsigned char os_toebcdic[256] = { + 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 /* ................ */ +}; + +/* 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. + */ +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++]; + } +} +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++]; + } +} +#endif /*CHARSET_EBCDIC*/ + diff --git a/APACHE_1_3_12/src/os/tpf/ebcdic.h b/APACHE_1_3_12/src/os/tpf/ebcdic.h new file mode 100644 index 0000000000..3f2a63f06d --- /dev/null +++ b/APACHE_1_3_12/src/os/tpf/ebcdic.h @@ -0,0 +1,7 @@ +#include + +extern const unsigned char os_toascii[256]; +extern const unsigned char os_toebcdic[256]; +void ebcdic2ascii(void *dest, const void *srce, size_t count); +void ascii2ebcdic(void *dest, const void *srce, size_t count); + diff --git a/APACHE_1_3_12/src/os/tpf/os-inline.c b/APACHE_1_3_12/src/os/tpf/os-inline.c new file mode 100644 index 0000000000..e58917af36 --- /dev/null +++ b/APACHE_1_3_12/src/os/tpf/os-inline.c @@ -0,0 +1,31 @@ +/* + * 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_12/src/os/tpf/os.c b/APACHE_1_3_12/src/os/tpf/os.c new file mode 100644 index 0000000000..d0f1bf9f47 --- /dev/null +++ b/APACHE_1_3_12/src/os/tpf/os.c @@ -0,0 +1,664 @@ +/* ==================================================================== + * Copyright (c) 1998-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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 __PIPE_ +#include "ipc.h" +#include "shm.h" +static TPF_FD_LIST *tpf_fds = NULL; +#endif + +void *tpf_shm_static_ptr = NULL; + +static FILE *sock_fp; + +/* Check the Content-Type to decide if conversion is needed */ +int ap_checkconv(struct request_rec *r) +{ + int convert_to_ascii; + const char *type; + + /* To make serving of "raw ASCII text" files easy (they serve faster + * since they don't have to be converted from EBCDIC), a new + * "magic" type prefix was invented: text/x-ascii-{plain,html,...} + * If we detect one of these content types here, we simply correct + * the type to the real text/{plain,html,...} type. Otherwise, we + * set a flag that translation is required later on. + */ + + type = (r->content_type == NULL) ? ap_default_type(r) : r->content_type; + + /* If no content type is set then treat it as (ebcdic) text/plain */ + convert_to_ascii = (type == NULL); + + /* Conversion is applied to text/ files only, if ever. */ + if (type && (strncasecmp(type, "text/", 5) == 0 || + strncasecmp(type, "message/", 8) == 0)) { + if (strncasecmp(type, ASCIITEXT_MAGIC_TYPE_PREFIX, + sizeof(ASCIITEXT_MAGIC_TYPE_PREFIX)-1) == 0){ + r->content_type = ap_pstrcat(r->pool, "text/", + type+sizeof(ASCIITEXT_MAGIC_TYPE_PREFIX)-1, NULL); + if (r->method_number == M_PUT) + ap_bsetflag(r->connection->client, B_ASCII2EBCDIC, 0); + } + + else + /* translate EBCDIC to ASCII */ + convert_to_ascii = 1; + } + else{ + if (r->method_number == M_PUT) + ap_bsetflag(r->connection->client, B_ASCII2EBCDIC, 0); + /* don't translate non-text files to EBCDIC */ + } + /* Enable conversion if it's a text document */ + ap_bsetflag(r->connection->client, B_EBCDIC2ASCII, convert_to_ascii); + + return convert_to_ascii; +} + +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 = 0; + int rv; + + if(maxfds) { + if(tv) + timeout = tv->tv_sec * 1000 + tv->tv_usec; + sockets[0] = maxfds-1; + no_reads++; + } + else + sockets[0] = 0; + + ap_check_signals(); + rv = select(sockets, no_reads, no_writes, no_excepts, timeout); + ap_check_signals(); + + return rv; + +} + +int tpf_accept(int sockfd, struct sockaddr *peer, int *paddrlen) +{ + int socks[1]; + int rv; + + ap_check_signals(); + socks[0] = sockfd; + rv = select(socks, 1, 0, 0, 1000); + errno = sock_errno(); + if(rv>0) { + ap_check_signals(); + 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, temp_in, temp_err, save_errno, pid, result=0; + int fd_flags_out, fd_flags_in, fd_flags_err; + struct tpf_fork_input fork_input; + TPF_FORK_CHILD *cld = (TPF_FORK_CHILD *) data; + array_header *env_arr = ap_table_elts ((array_header *) cld->subprocess_env); + table_entry *elts = (table_entry *) env_arr->elts; + + 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); + } + + if (cld->subprocess_env) { + for (i = 0; i < env_arr->nelts; ++i) { + if (!elts[i].key) + continue; + setenv (elts[i].key, elts[i].val, 1); + } + } + + 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; + + + if ((pid = tpf_fork(&fork_input)) < 0) { + 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; + } + + if (cld->subprocess_env) { + for (i = 0; i < env_arr->nelts; ++i) { + if (!elts[i].key) + continue; + unsetenv (elts[i].key); + } + } + + 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; + + fflush(stdin); + if (dup2(fileno(sock_fp), STDIN_FILENO) == -1) + ap_log_error(APLOG_MARK, APLOG_CRIT, s, + "unable to replace stdin with sock device driver"); + fflush(stdout); + if (dup2(fileno(sock_fp), STDOUT_FILENO) == -1) + ap_log_error(APLOG_MARK, APLOG_CRIT, s, + "unable to replace stdout with sock device driver"); + input_parms.generation = ap_my_generation; +#ifdef SCOREBOARD_FILE + input_parms.scoreboard_fd = scoreboard_fd; +#else /* must be USE_TPF_SCOREBOARD or 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 = "-x"; + return tpf_fork(&fork_input); +} + +int os_check_server(char *server) { + #ifndef USE_TPF_DAEMON + int rv; + int *current_acn; + if((rv = inetd_getServerStatus(server)) == INETD_SERVER_STATUS_INACTIVE) + return 1; + else { + current_acn = (int *)cinfc_fast(CINFC_CMMACNUM); + if(ecbp2()->ce2acn != *current_acn) + return 1; + } + #endif + return 0; +} + +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+"); + /* arrange to close on exec or restart */ + ap_note_cleanups_for_file(p, sock_fp); + fcntl(sd,F_SETFD,FD_CLOEXEC); +} + +void os_tpf_child(APACHE_TPF_INPUT *input_parms) { + 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; +} + +#ifndef __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; + void *result; + + if ((shmid = shmget(shmkey, size, IPC_CREAT | SHM_R | SHM_W)) == -1) { + perror("shmget failed in ap_tpf_get_shared_mem funciton"); + 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 necssary */ + 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 /* __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 "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); +} diff --git a/APACHE_1_3_12/src/os/tpf/os.h b/APACHE_1_3_12/src/os/tpf/os.h new file mode 100644 index 0000000000..7c04b9cc12 --- /dev/null +++ b/APACHE_1_3_12/src/os/tpf/os.h @@ -0,0 +1,138 @@ +#ifndef APACHE_OS_H +#define APACHE_OS_H + +#define PLATFORM "TPF" + +/* 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 +#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 + */ + +#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) + +/* Sorry if this is ugly, but the include order doesn't allow me + * to use request_rec here... */ +struct request_rec; +extern int ap_checkconv(struct request_rec *r); + +#include +#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 + +#ifdef FD_SET +#undef FD_SET +#define FD_SET(n, p) (0) +#endif + +#define RESOURCE_KEY ((void*) 0xC1C2C1C3) + +/* 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 + +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; + +#include +typedef struct apache_input { + void *scoreboard_heap; /* scoreboard system heap address */ + int scoreboard_fd; /* scoreboard file descriptor */ + 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); +int os_check_server(char *server); +char *getpass(const char *prompt); +extern char *ap_server_argv0; +extern int scoreboard_fd; +#include +#ifndef SIGPIPE +#define SIGPIPE 14 +#endif +#ifdef NSIG +#undef NSIG +#endif +#endif /*! APACHE_OS_H*/ diff --git a/APACHE_1_3_12/src/os/tpf/samples/linkdll.jcl b/APACHE_1_3_12/src/os/tpf/samples/linkdll.jcl new file mode 100644 index 0000000000..b57aa04ad6 --- /dev/null +++ b/APACHE_1_3_12/src/os/tpf/samples/linkdll.jcl @@ -0,0 +1,155 @@ +//LINKDLL JOB MSGLEVEL=(1,1),CLASS=G,MSGCLASS=S +/*ROUTE PRINT +/*ROUTE PUNCH +/*NOTIFY +//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' +//PLKED.SYSLIB DD DISP=SHR,DSN=ACP.STUB.RLSE40 +// DD DISP=SHR,DSN=ACP.CLIB.RLSE40 +//PLKED.OBJLIB DD DISP=SHR,DSN=ACP.MAIN.SYST.OBBSS +// DD DISP=SHR,DSN=ACP.DF.MAIN.SYST.OBBSS +// DD DISP=SHR,DSN=ACP.OBJ.RLSE40.BSS +//PLKED.OBJ01 DD PATH='//src/ap/ap_base64.o' +//PLKED.OBJ02 DD PATH='//src/ap/ap_checkpass.o' +//PLKED.OBJ03 DD PATH='//src/ap/ap_cpystrn.o' +//PLKED.OBJ04 DD PATH='//src/ap/ap_execve.o' +//PLKED.OBJ05 DD PATH='//src/ap/ap_fnmatch.o' +//PLKED.OBJ06 DD PATH='//src/ap/ap_getpass.o' +//PLKED.OBJ07 DD PATH='//src/ap/ap_md5c.o' +//PLKED.OBJ08 DD PATH='//src/ap/ap_sha1.o' +//PLKED.OBJ09 DD PATH='//src/ap/ap_signal.o' +//PLKED.OBJ10 DD PATH='//src/ap/ap_slack.o' +//PLKED.OBJ11 DD PATH='//src/ap/ap_snprintf.o' +//PLKED.OBJ12 DD PATH='//src/buildmark.o' +//PLKED.OBJ13 DD PATH='//src/main/alloc.o' +//PLKED.OBJ14 DD PATH='//src/main/buff.o' +//PLKED.OBJ15 DD PATH='//src/main/http_config.o' +//PLKED.OBJ16 DD PATH='//src/main/http_core.o' +//PLKED.OBJ17 DD PATH='//src/main/http_log.o' +//PLKED.OBJ18 DD PATH='//src/main/http_main.o' +//PLKED.OBJ19 DD PATH='//src/main/http_protocol.o' +//PLKED.OBJ20 DD PATH='//src/main/http_request.o' +//PLKED.OBJ21 DD PATH='//src/main/http_vhost.o' +//PLKED.OBJ22 DD PATH='//src/main/rfc1413.o' +//PLKED.OBJ23 DD PATH='//src/main/util.o' +//PLKED.OBJ24 DD PATH='//src/main/util_date.o' +//PLKED.OBJ25 DD PATH='//src/main/util_md5.o' +//PLKED.OBJ26 DD PATH='//src/main/util_script.o' +//PLKED.OBJ27 DD PATH='//src/main/util_uri.o' +//PLKED.OBJ28 DD PATH='//src/modules.o' +//PLKED.OBJ29 DD PATH='//src/modules/standard/mod_acce\ +// ss.o' +//PLKED.OBJ30 DD PATH='//src/modules/standard/mod_acti\ +// ons.o' +//PLKED.OBJ31 DD PATH='//src/modules/standard/mod_alia\ +// s.o' +//PLKED.OBJ32 DD PATH='//src/modules/standard/mod_asis\ +// .o' +//PLKED.OBJ33 DD PATH='//src/modules/standard/mod_auth\ +// .o' +//PLKED.OBJ34 DD PATH='//src/modules/standard/mod_auto\ +// index.o' +//PLKED.OBJ35 DD PATH='//src/modules/standard/mod_cgi.\ +// o' +//PLKED.OBJ36 DD PATH='//src/modules/standard/mod_dir.\ +// o' +//PLKED.OBJ37 DD PATH='//src/modules/standard/mod_env.\ +// o' +//PLKED.OBJ38 DD PATH='//src/modules/standard/mod_imap\ +// .o' +//PLKED.OBJ39 DD PATH='//src/modules/standard/mod_incl\ +// ude.o' +//PLKED.OBJ40 DD PATH='//src/modules/standard/mod_log_\ +// config.o' +//PLKED.OBJ41 DD PATH='//src/modules/standard/mod_mime\ +// .o' +//PLKED.OBJ42 DD PATH='//src/modules/standard/mod_nego\ +// tiation.o' +//PLKED.OBJ43 DD PATH='//src/modules/standard/mod_sete\ +// nvif.o' +//PLKED.OBJ44 DD PATH='//src/modules/standard/mod_stat\ +// us.o' +//PLKED.OBJ45 DD PATH='//src/modules/standard/mod_user\ +// dir.o' +//PLKED.OBJ46 DD PATH='//src/os/tpf/cgetop.o' +//PLKED.OBJ47 DD PATH='//src/os/tpf/ebcdic.o' +//PLKED.OBJ48 DD PATH='//src/os/tpf/os.o' +//PLKED.OBJ49 DD PATH='//src/os/tpf/os-inline.o' +//PLKED.OBJ50 DD PATH='//src/regex/regcomp.o' +//PLKED.OBJ51 DD PATH='//src/regex/regerror.o' +//PLKED.OBJ52 DD PATH='//src/regex/regexec.o' +//PLKED.OBJ53 DD PATH='//src/regex/regfree.o' +//PLKED.OBJ54 DD PATH='//src/lib/expat-lite/hashtable.\ +// o' +//PLKED.OBJ55 DD PATH='//src/lib/expat-lite/xmlparse.o\ +// ' +//PLKED.OBJ56 DD PATH='//src/lib/expat-lite/xmlrole.o' +//PLKED.OBJ57 DD PATH='//src/lib/expat-lite/xmltok.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 OBJ55 + INCLUDE OBJ56 + INCLUDE OBJ57 + INCLUDE OBJLIB(CINET640) +/* +//*** WARNING *** NEVER change .LK to .OB in SYSLMOD!!! +//LKED.SYSLMOD DD DISP=OLD,DSN=(CHTA) +// diff --git a/APACHE_1_3_12/src/os/tpf/samples/loadset.jcl b/APACHE_1_3_12/src/os/tpf/samples/loadset.jcl new file mode 100644 index 0000000000..445f6ccf1e --- /dev/null +++ b/APACHE_1_3_12/src/os/tpf/samples/loadset.jcl @@ -0,0 +1,41 @@ +//LOADSET JOB MSGLEVEL=1,CLASS=G,MSGCLASS=S +/*ROUTE PRINT +/*ROUTE PUNCH +//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=,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 +LOADER CALL PROG CHTA +/* +//TRANSMIT EXEC PGM=IKJEFT01, +// PARM='TRANSMIT DDNAME(SYSTSIN) NOLOG NONOTIFY SEQ' +//SYSTSIN DD UNIT=SYSDA, +// DSN=&&VRDROUT,DISP=(OLD,DELETE) +//SYSTSPRT DD DUMMY diff --git a/APACHE_1_3_12/src/os/unix/.cvsignore b/APACHE_1_3_12/src/os/unix/.cvsignore new file mode 100644 index 0000000000..f3c7a7c5da --- /dev/null +++ b/APACHE_1_3_12/src/os/unix/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/APACHE_1_3_12/src/os/unix/Makefile.tmpl b/APACHE_1_3_12/src/os/unix/Makefile.tmpl new file mode 100644 index 0000000000..a68b781fcf --- /dev/null +++ b/APACHE_1_3_12/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_12/src/os/unix/os-aix-dso.c b/APACHE_1_3_12/src/os/unix/os-aix-dso.c new file mode 100644 index 0000000000..45d9db531a --- /dev/null +++ b/APACHE_1_3_12/src/os/unix/os-aix-dso.c @@ -0,0 +1,668 @@ +/* ==================================================================== + * Copyright (c) 1998-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* +** 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 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 +*/ + +#include +#include +#include +#include +#include +#include +#include + +#undef FREAD +#undef FWRITE +#include + +/* + * 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 intialize, 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_12/src/os/unix/os-inline.c b/APACHE_1_3_12/src/os/unix/os-inline.c new file mode 100644 index 0000000000..54ff49a639 --- /dev/null +++ b/APACHE_1_3_12/src/os/unix/os-inline.c @@ -0,0 +1,31 @@ +/* + * 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_12/src/os/unix/os.c b/APACHE_1_3_12/src/os/unix/os.c new file mode 100644 index 0000000000..aff2a94600 --- /dev/null +++ b/APACHE_1_3_12/src/os/unix/os.c @@ -0,0 +1,184 @@ +/* + * 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 < 43 +#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 + +/* + * 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|BIND_NOSTART, 0L); + return (void *)handle; + +#elif defined(HAVE_DYLD) + NSObjectFileImage image; + if (NSCreateObjectFileImageFromFile(path, &image) != + NSObjectFileImageSuccess) + return NULL; + return NSLinkModule(image, path, TRUE); + +#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_12/src/os/unix/os.h b/APACHE_1_3_12/src/os/unix/os.h new file mode 100644 index 0000000000..ed32d6abe0 --- /dev/null +++ b/APACHE_1_3_12/src/os/unix/os.h @@ -0,0 +1,150 @@ +/* ==================================================================== + * Copyright (c) 1998-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +#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 +#endif + +/* + * Do not use native AIX DSO support on releases of AIX prior + * to 4.3. + */ +#ifdef AIX +#if AIX < 43 +#undef HAVE_DLFCN_H +#endif +#endif + +#ifdef HAVE_DLFCN_H +#include +#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_12/src/os/win32/.cvsignore b/APACHE_1_3_12/src/os/win32/.cvsignore new file mode 100644 index 0000000000..17564450e9 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/.cvsignore @@ -0,0 +1,27 @@ +*.mdp +*.ncb +*.opt +*.plg +*.dsw +ApacheModuleAuthAnonD +ApacheModuleAuthAnonR +ApacheModuleCERNMetaD +ApacheModuleCERNMetaR +ApacheModuleDigestD +ApacheModuleDigestR +ApacheModuleExpiresD +ApacheModuleExpiresR +ApacheModuleHeadersD +ApacheModuleHeadersR +ApacheModuleInfoD +ApacheModuleInfoR +ApacheModuleRewriteD +ApacheModuleRewriteR +ApacheModuleSpelingD +ApacheModuleSpelingR +ApacheModuleStatusD +ApacheModuleStatusR +ApacheModuleUserTrackD +ApacheModuleUserTrackR +ApacheOSR +ApacheOSD diff --git a/APACHE_1_3_12/src/os/win32/ApacheModuleAuthAnon.dsp b/APACHE_1_3_12/src/os/win32/ApacheModuleAuthAnon.dsp new file mode 100644 index 0000000000..afe8cc7e2f --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/ApacheModuleAuthAnon.dsp @@ -0,0 +1,113 @@ +# Microsoft Developer Studio Project File - Name="ApacheModuleAuthAnon" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=ApacheModuleAuthAnon - 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 "ApacheModuleAuthAnon.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 "ApacheModuleAuthAnon.mak"\ + CFG="ApacheModuleAuthAnon - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleAuthAnon - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleAuthAnon - Win32 Debug" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleAuthAnon - 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 ".\ApacheModuleAuthAnonR" +# PROP Intermediate_Dir ".\ApacheModuleAuthAnonR" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /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 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 /nologo /subsystem:windows /dll /machine:I386 + +!ELSEIF "$(CFG)" == "ApacheModuleAuthAnon - 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 ".\ApacheModuleAuthAnonD" +# PROP Intermediate_Dir ".\ApacheModuleAuthAnonD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# 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 "..\..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /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 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 /nologo /subsystem:windows /dll /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "ApacheModuleAuthAnon - Win32 Release" +# Name "ApacheModuleAuthAnon - 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\standard\mod_auth_anon.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\readdir.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_12/src/os/win32/ApacheModuleAuthAnon.mak b/APACHE_1_3_12/src/os/win32/ApacheModuleAuthAnon.mak new file mode 100644 index 0000000000..c098031c8a --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/ApacheModuleAuthAnon.mak @@ -0,0 +1,241 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ApacheModuleAuthAnon.dsp +!IF "$(CFG)" == "" +CFG=ApacheModuleAuthAnon - Win32 Release +!MESSAGE No configuration specified. Defaulting to ApacheModuleAuthAnon - Win32\ + Release. +!ENDIF + +!IF "$(CFG)" != "ApacheModuleAuthAnon - Win32 Release" && "$(CFG)" !=\ + "ApacheModuleAuthAnon - 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 "ApacheModuleAuthAnon.mak"\ + CFG="ApacheModuleAuthAnon - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleAuthAnon - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleAuthAnon - 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 + +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleAuthAnon - Win32 Release" + +OUTDIR=.\ApacheModuleAuthAnonR +INTDIR=.\ApacheModuleAuthAnonR +# Begin Custom Macros +OutDir=.\.\ApacheModuleAuthAnonR +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleAuthAnon.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleAuthAnon.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_auth_anon.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheModuleAuthAnon.dll" + -@erase "$(OUTDIR)\ApacheModuleAuthAnon.exp" + -@erase "$(OUTDIR)\ApacheModuleAuthAnon.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D\ + "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleAuthAnon.pch" /YX\ + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleAuthAnonR/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleAuthAnon.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:no /pdb:"$(OUTDIR)\ApacheModuleAuthAnon.pdb" /machine:I386\ + /out:"$(OUTDIR)\ApacheModuleAuthAnon.dll"\ + /implib:"$(OUTDIR)\ApacheModuleAuthAnon.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_auth_anon.obj" + +"$(OUTDIR)\ApacheModuleAuthAnon.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ApacheModuleAuthAnon - Win32 Debug" + +OUTDIR=.\ApacheModuleAuthAnonD +INTDIR=.\ApacheModuleAuthAnonD +# Begin Custom Macros +OutDir=.\.\ApacheModuleAuthAnonD +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleAuthAnon.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleAuthAnon.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_auth_anon.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\ApacheModuleAuthAnon.dll" + -@erase "$(OUTDIR)\ApacheModuleAuthAnon.exp" + -@erase "$(OUTDIR)\ApacheModuleAuthAnon.ilk" + -@erase "$(OUTDIR)\ApacheModuleAuthAnon.lib" + -@erase "$(OUTDIR)\ApacheModuleAuthAnon.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D\ + "WIN32" /D "_WINDOWS" /D "SHARED_MODULE"\ + /Fp"$(INTDIR)\ApacheModuleAuthAnon.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\"\ + /FD /c +CPP_OBJS=.\ApacheModuleAuthAnonD/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleAuthAnon.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:yes /pdb:"$(OUTDIR)\ApacheModuleAuthAnon.pdb" /debug\ + /machine:I386 /out:"$(OUTDIR)\ApacheModuleAuthAnon.dll"\ + /implib:"$(OUTDIR)\ApacheModuleAuthAnon.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_auth_anon.obj" + +"$(OUTDIR)\ApacheModuleAuthAnon.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) $< +<< + + +!IF "$(CFG)" == "ApacheModuleAuthAnon - Win32 Release" || "$(CFG)" ==\ + "ApacheModuleAuthAnon - Win32 Debug" +SOURCE=..\..\modules\standard\mod_auth_anon.c + +!IF "$(CFG)" == "ApacheModuleAuthAnon - Win32 Release" + +DEP_CPP_MOD_A=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.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"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_A=\ + "..\..\include\ebcdic.h"\ + "..\..\include\os.h"\ + "..\..\include\sfio.h"\ + + +"$(INTDIR)\mod_auth_anon.obj" : $(SOURCE) $(DEP_CPP_MOD_A) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheModuleAuthAnon - Win32 Debug" + +DEP_CPP_MOD_A=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.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"\ + + +"$(INTDIR)\mod_auth_anon.obj" : $(SOURCE) $(DEP_CPP_MOD_A) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + + +!ENDIF + diff --git a/APACHE_1_3_12/src/os/win32/ApacheModuleAuthDigest.dsp b/APACHE_1_3_12/src/os/win32/ApacheModuleAuthDigest.dsp new file mode 100644 index 0000000000..ea2f015121 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/ApacheModuleAuthDigest.dsp @@ -0,0 +1,97 @@ +# Microsoft Developer Studio Project File - Name="ApacheModuleAuthDigest" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=ApacheModuleAuthDigest - 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 "apachemoduleauthdigest.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 "apachemoduleauthdigest.mak"\ + CFG="ApacheModuleAuthDigest - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleAuthDigest - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleAuthDigest - Win32 Debug" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleAuthDigest - 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 ".\ApacheModuleAuthDigestD" +# PROP Intermediate_Dir ".\ApacheModuleAuthDigestD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /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 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 + +!ELSEIF "$(CFG)" == "ApacheModuleAuthDigest - 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 ".\ApacheModuleAuthDigestD" +# PROP Intermediate_Dir ".\ApacheModuleAuthDigestD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /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 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 /pdbtype:sept +# 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 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "ApacheModuleAuthDigest - Win32 Release" +# Name "ApacheModuleAuthDigest - 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_12/src/os/win32/ApacheModuleAuthDigest.mak b/APACHE_1_3_12/src/os/win32/ApacheModuleAuthDigest.mak new file mode 100644 index 0000000000..67b6434ca2 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/ApacheModuleAuthDigest.mak @@ -0,0 +1,246 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ApacheModuleAuthDigest.dsp +!IF "$(CFG)" == "" +CFG=ApacheModuleAuthDigest - Win32 Debug +!MESSAGE No configuration specified. Defaulting to ApacheModuleAuthDigest -\ + Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "ApacheModuleAuthDigest - Win32 Release" && "$(CFG)" !=\ + "ApacheModuleAuthDigest - 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 "ApacheModuleAuthDigest.mak"\ + CFG="ApacheModuleAuthDigest - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleAuthDigest - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleAuthDigest - 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)" == "ApacheModuleAuthDigest - Win32 Release" + +OUTDIR=.\ApacheModuleAuthDigestD +INTDIR=.\ApacheModuleAuthDigestD +# Begin Custom Macros +OutDir=.\.\ApacheModuleAuthDigestD +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleAuthDigest.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleAuthDigest.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_auth_digest.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheModuleAuthDigest.dll" + -@erase "$(OUTDIR)\ApacheModuleAuthDigest.exp" + -@erase "$(OUTDIR)\ApacheModuleAuthDigest.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MT /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D\ + "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleAuthDigest.pch" /YX\ + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleAuthDigestD/ +CPP_SBRS=. + +.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) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 +RSC=rc.exe +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleAuthDigest.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +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)\ApacheModuleAuthDigest.pdb" /machine:I386\ + /out:"$(OUTDIR)\ApacheModuleAuthDigest.dll"\ + /implib:"$(OUTDIR)\ApacheModuleAuthDigest.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_auth_digest.obj" + +"$(OUTDIR)\ApacheModuleAuthDigest.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ApacheModuleAuthDigest - Win32 Debug" + +OUTDIR=.\ApacheModuleAuthDigestD +INTDIR=.\ApacheModuleAuthDigestD +# Begin Custom Macros +OutDir=.\.\ApacheModuleAuthDigestD +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleAuthDigest.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleAuthDigest.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_auth_digest.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\ApacheModuleAuthDigest.dll" + -@erase "$(OUTDIR)\ApacheModuleAuthDigest.exp" + -@erase "$(OUTDIR)\ApacheModuleAuthDigest.ilk" + -@erase "$(OUTDIR)\ApacheModuleAuthDigest.lib" + -@erase "$(OUTDIR)\ApacheModuleAuthDigest.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D\ + "WIN32" /D "_WINDOWS" /D "SHARED_MODULE"\ + /Fp"$(INTDIR)\ApacheModuleAuthDigest.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\"\ + /FD /c +CPP_OBJS=.\ApacheModuleAuthDigestD/ +CPP_SBRS=. + +.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) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o NUL /win32 +RSC=rc.exe +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleAuthDigest.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +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)\ApacheModuleAuthDigest.pdb" /debug\ + /machine:I386 /out:"$(OUTDIR)\ApacheModuleAuthDigest.dll"\ + /implib:"$(OUTDIR)\ApacheModuleAuthDigest.lib" /pdbtype:sept +LINK32_OBJS= \ + "$(INTDIR)\mod_auth_digest.obj" + +"$(OUTDIR)\ApacheModuleAuthDigest.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + + +!IF "$(CFG)" == "ApacheModuleAuthDigest - Win32 Release" || "$(CFG)" ==\ + "ApacheModuleAuthDigest - Win32 Debug" +SOURCE=..\..\modules\experimental\mod_auth_digest.c +DEP_CPP_MOD_A=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_config.h"\ + "..\..\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_auth_digest.obj" : $(SOURCE) $(DEP_CPP_MOD_A) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + + +!ENDIF + diff --git a/APACHE_1_3_12/src/os/win32/ApacheModuleCERNMeta.dsp b/APACHE_1_3_12/src/os/win32/ApacheModuleCERNMeta.dsp new file mode 100644 index 0000000000..3564c0e2ef --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/ApacheModuleCERNMeta.dsp @@ -0,0 +1,113 @@ +# Microsoft Developer Studio Project File - Name="ApacheModuleCERNMeta" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=ApacheModuleCERNMeta - 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 "ApacheModuleCERNMeta.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 "ApacheModuleCERNMeta.mak"\ + CFG="ApacheModuleCERNMeta - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleCERNMeta - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleCERNMeta - Win32 Debug" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleCERNMeta - 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 ".\ApacheModuleCERNMetaR" +# PROP Intermediate_Dir ".\ApacheModuleCERNMetaR" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /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 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 /nologo /subsystem:windows /dll /machine:I386 + +!ELSEIF "$(CFG)" == "ApacheModuleCERNMeta - 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 ".\ApacheModuleCERNMetaD" +# PROP Intermediate_Dir ".\ApacheModuleCERNMetaD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# 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 "..\..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /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 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 /nologo /subsystem:windows /dll /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "ApacheModuleCERNMeta - Win32 Release" +# Name "ApacheModuleCERNMeta - 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\standard\mod_cern_meta.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\readdir.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_12/src/os/win32/ApacheModuleCERNMeta.mak b/APACHE_1_3_12/src/os/win32/ApacheModuleCERNMeta.mak new file mode 100644 index 0000000000..0a19cb45aa --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/ApacheModuleCERNMeta.mak @@ -0,0 +1,239 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ApacheModuleCERNMeta.dsp +!IF "$(CFG)" == "" +CFG=ApacheModuleCERNMeta - Win32 Release +!MESSAGE No configuration specified. Defaulting to ApacheModuleCERNMeta - Win32\ + Release. +!ENDIF + +!IF "$(CFG)" != "ApacheModuleCERNMeta - Win32 Release" && "$(CFG)" !=\ + "ApacheModuleCERNMeta - 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 "ApacheModuleCERNMeta.mak"\ + CFG="ApacheModuleCERNMeta - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleCERNMeta - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleCERNMeta - 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 + +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleCERNMeta - Win32 Release" + +OUTDIR=.\ApacheModuleCERNMetaR +INTDIR=.\ApacheModuleCERNMetaR +# Begin Custom Macros +OutDir=.\.\ApacheModuleCERNMetaR +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleCERNMeta.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleCERNMeta.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_cern_meta.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheModuleCERNMeta.dll" + -@erase "$(OUTDIR)\ApacheModuleCERNMeta.exp" + -@erase "$(OUTDIR)\ApacheModuleCERNMeta.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D\ + "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleCERNMeta.pch" /YX\ + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleCERNMetaR/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleCERNMeta.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:no /pdb:"$(OUTDIR)\ApacheModuleCERNMeta.pdb" /machine:I386\ + /out:"$(OUTDIR)\ApacheModuleCERNMeta.dll"\ + /implib:"$(OUTDIR)\ApacheModuleCERNMeta.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_cern_meta.obj" + +"$(OUTDIR)\ApacheModuleCERNMeta.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ApacheModuleCERNMeta - Win32 Debug" + +OUTDIR=.\ApacheModuleCERNMetaD +INTDIR=.\ApacheModuleCERNMetaD +# Begin Custom Macros +OutDir=.\.\ApacheModuleCERNMetaD +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleCERNMeta.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleCERNMeta.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_cern_meta.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\ApacheModuleCERNMeta.dll" + -@erase "$(OUTDIR)\ApacheModuleCERNMeta.exp" + -@erase "$(OUTDIR)\ApacheModuleCERNMeta.ilk" + -@erase "$(OUTDIR)\ApacheModuleCERNMeta.lib" + -@erase "$(OUTDIR)\ApacheModuleCERNMeta.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D\ + "WIN32" /D "_WINDOWS" /D "SHARED_MODULE"\ + /Fp"$(INTDIR)\ApacheModuleCERNMeta.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\"\ + /FD /c +CPP_OBJS=.\ApacheModuleCERNMetaD/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleCERNMeta.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:yes /pdb:"$(OUTDIR)\ApacheModuleCERNMeta.pdb" /debug\ + /machine:I386 /out:"$(OUTDIR)\ApacheModuleCERNMeta.dll"\ + /implib:"$(OUTDIR)\ApacheModuleCERNMeta.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_cern_meta.obj" + +"$(OUTDIR)\ApacheModuleCERNMeta.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) $< +<< + + +!IF "$(CFG)" == "ApacheModuleCERNMeta - Win32 Release" || "$(CFG)" ==\ + "ApacheModuleCERNMeta - Win32 Debug" +SOURCE=..\..\modules\standard\mod_cern_meta.c + +!IF "$(CFG)" == "ApacheModuleCERNMeta - Win32 Release" + +DEP_CPP_MOD_C=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.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"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_C=\ + "..\..\include\ebcdic.h"\ + "..\..\include\os.h"\ + "..\..\include\sfio.h"\ + + +"$(INTDIR)\mod_cern_meta.obj" : $(SOURCE) $(DEP_CPP_MOD_C) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheModuleCERNMeta - Win32 Debug" + +DEP_CPP_MOD_C=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.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"\ + + +"$(INTDIR)\mod_cern_meta.obj" : $(SOURCE) $(DEP_CPP_MOD_C) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + + +!ENDIF + diff --git a/APACHE_1_3_12/src/os/win32/ApacheModuleDigest.dsp b/APACHE_1_3_12/src/os/win32/ApacheModuleDigest.dsp new file mode 100644 index 0000000000..fd18022582 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/ApacheModuleDigest.dsp @@ -0,0 +1,113 @@ +# Microsoft Developer Studio Project File - Name="ApacheModuleDigest" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=ApacheModuleDigest - 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 "ApacheModuleDigest.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 "ApacheModuleDigest.mak"\ + CFG="ApacheModuleDigest - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleDigest - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleDigest - Win32 Debug" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleDigest - 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 ".\ApacheModuleDigestR" +# PROP Intermediate_Dir ".\ApacheModuleDigestR" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /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 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 /nologo /subsystem:windows /dll /machine:I386 + +!ELSEIF "$(CFG)" == "ApacheModuleDigest - 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 ".\ApacheModuleDigestD" +# PROP Intermediate_Dir ".\ApacheModuleDigestD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# 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 "..\..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /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 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 /nologo /subsystem:windows /dll /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "ApacheModuleDigest - Win32 Release" +# Name "ApacheModuleDigest - 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\standard\mod_digest.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\readdir.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_12/src/os/win32/ApacheModuleDigest.mak b/APACHE_1_3_12/src/os/win32/ApacheModuleDigest.mak new file mode 100644 index 0000000000..8bc9f51071 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/ApacheModuleDigest.mak @@ -0,0 +1,242 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ApacheModuleDigest.dsp +!IF "$(CFG)" == "" +CFG=ApacheModuleDigest - Win32 Release +!MESSAGE No configuration specified. Defaulting to ApacheModuleDigest - Win32\ + Release. +!ENDIF + +!IF "$(CFG)" != "ApacheModuleDigest - Win32 Release" && "$(CFG)" !=\ + "ApacheModuleDigest - 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 "ApacheModuleDigest.mak"\ + CFG="ApacheModuleDigest - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleDigest - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleDigest - 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 + +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleDigest - Win32 Release" + +OUTDIR=.\ApacheModuleDigestR +INTDIR=.\ApacheModuleDigestR +# Begin Custom Macros +OutDir=.\.\ApacheModuleDigestR +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleDigest.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleDigest.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_digest.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheModuleDigest.dll" + -@erase "$(OUTDIR)\ApacheModuleDigest.exp" + -@erase "$(OUTDIR)\ApacheModuleDigest.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D\ + "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleDigest.pch" /YX\ + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleDigestR/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleDigest.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:no /pdb:"$(OUTDIR)\ApacheModuleDigest.pdb" /machine:I386\ + /out:"$(OUTDIR)\ApacheModuleDigest.dll"\ + /implib:"$(OUTDIR)\ApacheModuleDigest.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_digest.obj" + +"$(OUTDIR)\ApacheModuleDigest.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ApacheModuleDigest - Win32 Debug" + +OUTDIR=.\ApacheModuleDigestD +INTDIR=.\ApacheModuleDigestD +# Begin Custom Macros +OutDir=.\.\ApacheModuleDigestD +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleDigest.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleDigest.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_digest.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\ApacheModuleDigest.dll" + -@erase "$(OUTDIR)\ApacheModuleDigest.exp" + -@erase "$(OUTDIR)\ApacheModuleDigest.ilk" + -@erase "$(OUTDIR)\ApacheModuleDigest.lib" + -@erase "$(OUTDIR)\ApacheModuleDigest.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D\ + "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleDigest.pch"\ + /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleDigestD/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleDigest.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:yes /pdb:"$(OUTDIR)\ApacheModuleDigest.pdb" /debug\ + /machine:I386 /out:"$(OUTDIR)\ApacheModuleDigest.dll"\ + /implib:"$(OUTDIR)\ApacheModuleDigest.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_digest.obj" + +"$(OUTDIR)\ApacheModuleDigest.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) $< +<< + + +!IF "$(CFG)" == "ApacheModuleDigest - Win32 Release" || "$(CFG)" ==\ + "ApacheModuleDigest - Win32 Debug" +SOURCE=..\..\modules\standard\mod_digest.c + +!IF "$(CFG)" == "ApacheModuleDigest - Win32 Release" + +DEP_CPP_MOD_D=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\httpd.h"\ + "..\..\include\ap_md5.h"\ + "..\..\include\util_md5.h"\ + "..\..\include\util_uri.h"\ + ".\os.h"\ + ".\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_D=\ + "..\..\include\ebcdic.h"\ + "..\..\include\os.h"\ + "..\..\include\sfio.h"\ + + +"$(INTDIR)\mod_digest.obj" : $(SOURCE) $(DEP_CPP_MOD_D) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheModuleDigest - Win32 Debug" + +DEP_CPP_MOD_D=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\http_log.h"\ + "..\..\include\http_protocol.h"\ + "..\..\include\httpd.h"\ + "..\..\include\ap_md5.h"\ + "..\..\include\util_md5.h"\ + "..\..\include\util_uri.h"\ + ".\os.h"\ + ".\readdir.h"\ + + +"$(INTDIR)\mod_digest.obj" : $(SOURCE) $(DEP_CPP_MOD_D) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + + +!ENDIF + diff --git a/APACHE_1_3_12/src/os/win32/ApacheModuleExpires.dsp b/APACHE_1_3_12/src/os/win32/ApacheModuleExpires.dsp new file mode 100644 index 0000000000..0b2fe902bb --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/ApacheModuleExpires.dsp @@ -0,0 +1,113 @@ +# Microsoft Developer Studio Project File - Name="ApacheModuleExpires" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=ApacheModuleExpires - 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 "ApacheModuleExpires.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 "ApacheModuleExpires.mak"\ + CFG="ApacheModuleExpires - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleExpires - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleExpires - Win32 Debug" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleExpires - 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 ".\ApacheModuleExpiresR" +# PROP Intermediate_Dir ".\ApacheModuleExpiresR" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /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 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 /nologo /subsystem:windows /dll /machine:I386 + +!ELSEIF "$(CFG)" == "ApacheModuleExpires - 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 ".\ApacheModuleExpiresD" +# PROP Intermediate_Dir ".\ApacheModuleExpiresD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# 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 "..\..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /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 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 /nologo /subsystem:windows /dll /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "ApacheModuleExpires - Win32 Release" +# Name "ApacheModuleExpires - 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\standard\mod_expires.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\readdir.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_12/src/os/win32/ApacheModuleExpires.mak b/APACHE_1_3_12/src/os/win32/ApacheModuleExpires.mak new file mode 100644 index 0000000000..e8ee779d71 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/ApacheModuleExpires.mak @@ -0,0 +1,234 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ApacheModuleExpires.dsp +!IF "$(CFG)" == "" +CFG=ApacheModuleExpires - Win32 Release +!MESSAGE No configuration specified. Defaulting to ApacheModuleExpires - Win32\ + Release. +!ENDIF + +!IF "$(CFG)" != "ApacheModuleExpires - Win32 Release" && "$(CFG)" !=\ + "ApacheModuleExpires - 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 "ApacheModuleExpires.mak"\ + CFG="ApacheModuleExpires - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleExpires - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleExpires - 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 + +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleExpires - Win32 Release" + +OUTDIR=.\ApacheModuleExpiresR +INTDIR=.\ApacheModuleExpiresR +# Begin Custom Macros +OutDir=.\.\ApacheModuleExpiresR +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleExpires.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleExpires.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_expires.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheModuleExpires.dll" + -@erase "$(OUTDIR)\ApacheModuleExpires.exp" + -@erase "$(OUTDIR)\ApacheModuleExpires.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D\ + "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleExpires.pch" /YX\ + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleExpiresR/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleExpires.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:no /pdb:"$(OUTDIR)\ApacheModuleExpires.pdb" /machine:I386\ + /out:"$(OUTDIR)\ApacheModuleExpires.dll"\ + /implib:"$(OUTDIR)\ApacheModuleExpires.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_expires.obj" + +"$(OUTDIR)\ApacheModuleExpires.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ApacheModuleExpires - Win32 Debug" + +OUTDIR=.\ApacheModuleExpiresD +INTDIR=.\ApacheModuleExpiresD +# Begin Custom Macros +OutDir=.\.\ApacheModuleExpiresD +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleExpires.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleExpires.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_expires.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\ApacheModuleExpires.dll" + -@erase "$(OUTDIR)\ApacheModuleExpires.exp" + -@erase "$(OUTDIR)\ApacheModuleExpires.ilk" + -@erase "$(OUTDIR)\ApacheModuleExpires.lib" + -@erase "$(OUTDIR)\ApacheModuleExpires.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D\ + "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleExpires.pch"\ + /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleExpiresD/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleExpires.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:yes /pdb:"$(OUTDIR)\ApacheModuleExpires.pdb" /debug\ + /machine:I386 /out:"$(OUTDIR)\ApacheModuleExpires.dll"\ + /implib:"$(OUTDIR)\ApacheModuleExpires.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_expires.obj" + +"$(OUTDIR)\ApacheModuleExpires.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) $< +<< + + +!IF "$(CFG)" == "ApacheModuleExpires - Win32 Release" || "$(CFG)" ==\ + "ApacheModuleExpires - Win32 Debug" +SOURCE=..\..\modules\standard\mod_expires.c + +!IF "$(CFG)" == "ApacheModuleExpires - Win32 Release" + +DEP_CPP_MOD_E=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_log.h"\ + "..\..\include\httpd.h"\ + "..\..\include\util_uri.h"\ + ".\os.h"\ + ".\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_E=\ + "..\..\include\ebcdic.h"\ + "..\..\include\os.h"\ + "..\..\include\sfio.h"\ + + +"$(INTDIR)\mod_expires.obj" : $(SOURCE) $(DEP_CPP_MOD_E) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheModuleExpires - Win32 Debug" + +DEP_CPP_MOD_E=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_log.h"\ + "..\..\include\httpd.h"\ + "..\..\include\util_uri.h"\ + ".\os.h"\ + ".\readdir.h"\ + + +"$(INTDIR)\mod_expires.obj" : $(SOURCE) $(DEP_CPP_MOD_E) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + + +!ENDIF + diff --git a/APACHE_1_3_12/src/os/win32/ApacheModuleHeaders.dsp b/APACHE_1_3_12/src/os/win32/ApacheModuleHeaders.dsp new file mode 100644 index 0000000000..1dc76027b3 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/ApacheModuleHeaders.dsp @@ -0,0 +1,113 @@ +# Microsoft Developer Studio Project File - Name="ApacheModuleHeaders" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=ApacheModuleHeaders - 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 "ApacheModuleHeaders.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 "ApacheModuleHeaders.mak"\ + CFG="ApacheModuleHeaders - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleHeaders - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleHeaders - Win32 Debug" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleHeaders - 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 ".\ApacheModuleHeadersR" +# PROP Intermediate_Dir ".\ApacheModuleHeadersR" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /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 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 /nologo /subsystem:windows /dll /machine:I386 + +!ELSEIF "$(CFG)" == "ApacheModuleHeaders - 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 ".\ApacheModuleHeadersD" +# PROP Intermediate_Dir ".\ApacheModuleHeadersD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# 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 "..\..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /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 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 /nologo /subsystem:windows /dll /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "ApacheModuleHeaders - Win32 Release" +# Name "ApacheModuleHeaders - 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\standard\mod_headers.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\readdir.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_12/src/os/win32/ApacheModuleHeaders.mak b/APACHE_1_3_12/src/os/win32/ApacheModuleHeaders.mak new file mode 100644 index 0000000000..72bfd9fe26 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/ApacheModuleHeaders.mak @@ -0,0 +1,232 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ApacheModuleHeaders.dsp +!IF "$(CFG)" == "" +CFG=ApacheModuleHeaders - Win32 Release +!MESSAGE No configuration specified. Defaulting to ApacheModuleHeaders - Win32\ + Release. +!ENDIF + +!IF "$(CFG)" != "ApacheModuleHeaders - Win32 Release" && "$(CFG)" !=\ + "ApacheModuleHeaders - 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 "ApacheModuleHeaders.mak"\ + CFG="ApacheModuleHeaders - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleHeaders - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleHeaders - 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 + +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleHeaders - Win32 Release" + +OUTDIR=.\ApacheModuleHeadersR +INTDIR=.\ApacheModuleHeadersR +# Begin Custom Macros +OutDir=.\.\ApacheModuleHeadersR +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleHeaders.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleHeaders.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_headers.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheModuleHeaders.dll" + -@erase "$(OUTDIR)\ApacheModuleHeaders.exp" + -@erase "$(OUTDIR)\ApacheModuleHeaders.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D\ + "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleHeaders.pch" /YX\ + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleHeadersR/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleHeaders.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:no /pdb:"$(OUTDIR)\ApacheModuleHeaders.pdb" /machine:I386\ + /out:"$(OUTDIR)\ApacheModuleHeaders.dll"\ + /implib:"$(OUTDIR)\ApacheModuleHeaders.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_headers.obj" + +"$(OUTDIR)\ApacheModuleHeaders.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ApacheModuleHeaders - Win32 Debug" + +OUTDIR=.\ApacheModuleHeadersD +INTDIR=.\ApacheModuleHeadersD +# Begin Custom Macros +OutDir=.\.\ApacheModuleHeadersD +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleHeaders.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleHeaders.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_headers.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\ApacheModuleHeaders.dll" + -@erase "$(OUTDIR)\ApacheModuleHeaders.exp" + -@erase "$(OUTDIR)\ApacheModuleHeaders.ilk" + -@erase "$(OUTDIR)\ApacheModuleHeaders.lib" + -@erase "$(OUTDIR)\ApacheModuleHeaders.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D\ + "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleHeaders.pch"\ + /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleHeadersD/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleHeaders.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:yes /pdb:"$(OUTDIR)\ApacheModuleHeaders.pdb" /debug\ + /machine:I386 /out:"$(OUTDIR)\ApacheModuleHeaders.dll"\ + /implib:"$(OUTDIR)\ApacheModuleHeaders.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_headers.obj" + +"$(OUTDIR)\ApacheModuleHeaders.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) $< +<< + + +!IF "$(CFG)" == "ApacheModuleHeaders - Win32 Release" || "$(CFG)" ==\ + "ApacheModuleHeaders - Win32 Debug" +SOURCE=..\..\modules\standard\mod_headers.c + +!IF "$(CFG)" == "ApacheModuleHeaders - Win32 Release" + +DEP_CPP_MOD_H=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\httpd.h"\ + "..\..\include\util_uri.h"\ + ".\os.h"\ + ".\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_H=\ + "..\..\include\ebcdic.h"\ + "..\..\include\os.h"\ + "..\..\include\sfio.h"\ + + +"$(INTDIR)\mod_headers.obj" : $(SOURCE) $(DEP_CPP_MOD_H) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheModuleHeaders - Win32 Debug" + +DEP_CPP_MOD_H=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\httpd.h"\ + "..\..\include\util_uri.h"\ + ".\os.h"\ + ".\readdir.h"\ + + +"$(INTDIR)\mod_headers.obj" : $(SOURCE) $(DEP_CPP_MOD_H) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + + +!ENDIF + diff --git a/APACHE_1_3_12/src/os/win32/ApacheModuleInfo.dsp b/APACHE_1_3_12/src/os/win32/ApacheModuleInfo.dsp new file mode 100644 index 0000000000..cf85646335 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/ApacheModuleInfo.dsp @@ -0,0 +1,112 @@ +# Microsoft Developer Studio Project File - Name="ApacheModuleInfo" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=ApacheModuleInfo - 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 "ApacheModuleInfo.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 "ApacheModuleInfo.mak" CFG="ApacheModuleInfo - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleInfo - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleInfo - Win32 Debug" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleInfo - 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 ".\ApacheModuleInfoR" +# PROP Intermediate_Dir ".\ApacheModuleInfoR" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /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 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 /nologo /subsystem:windows /dll /machine:I386 + +!ELSEIF "$(CFG)" == "ApacheModuleInfo - 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 ".\ApacheModuleInfoD" +# PROP Intermediate_Dir ".\ApacheModuleInfoD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# 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 "..\..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /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 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 /nologo /subsystem:windows /dll /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "ApacheModuleInfo - Win32 Release" +# Name "ApacheModuleInfo - 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\standard\mod_info.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\readdir.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_12/src/os/win32/ApacheModuleInfo.mak b/APACHE_1_3_12/src/os/win32/ApacheModuleInfo.mak new file mode 100644 index 0000000000..5f1e3bda21 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/ApacheModuleInfo.mak @@ -0,0 +1,211 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ApacheModuleInfo.dsp +!IF "$(CFG)" == "" +CFG=ApacheModuleInfo - Win32 Release +!MESSAGE No configuration specified. Defaulting to ApacheModuleInfo - Win32\ + Release. +!ENDIF + +!IF "$(CFG)" != "ApacheModuleInfo - Win32 Release" && "$(CFG)" !=\ + "ApacheModuleInfo - 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 "ApacheModuleInfo.mak" CFG="ApacheModuleInfo - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleInfo - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleInfo - 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 + +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleInfo - Win32 Release" + +OUTDIR=.\ApacheModuleInfoR +INTDIR=.\ApacheModuleInfoR +# Begin Custom Macros +OutDir=.\.\ApacheModuleInfoR +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleInfo.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleInfo.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_info.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheModuleInfo.dll" + -@erase "$(OUTDIR)\ApacheModuleInfo.exp" + -@erase "$(OUTDIR)\ApacheModuleInfo.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D\ + "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleInfo.pch" /YX\ + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleInfoR/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleInfo.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:no /pdb:"$(OUTDIR)\ApacheModuleInfo.pdb" /machine:I386\ + /out:"$(OUTDIR)\ApacheModuleInfo.dll" /implib:"$(OUTDIR)\ApacheModuleInfo.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_info.obj" + +"$(OUTDIR)\ApacheModuleInfo.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ApacheModuleInfo - Win32 Debug" + +OUTDIR=.\ApacheModuleInfoD +INTDIR=.\ApacheModuleInfoD +# Begin Custom Macros +OutDir=.\.\ApacheModuleInfoD +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleInfo.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleInfo.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_info.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\ApacheModuleInfo.dll" + -@erase "$(OUTDIR)\ApacheModuleInfo.exp" + -@erase "$(OUTDIR)\ApacheModuleInfo.ilk" + -@erase "$(OUTDIR)\ApacheModuleInfo.lib" + -@erase "$(OUTDIR)\ApacheModuleInfo.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D\ + "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleInfo.pch"\ + /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleInfoD/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleInfo.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:yes /pdb:"$(OUTDIR)\ApacheModuleInfo.pdb" /debug\ + /machine:I386 /out:"$(OUTDIR)\ApacheModuleInfo.dll"\ + /implib:"$(OUTDIR)\ApacheModuleInfo.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_info.obj" + +"$(OUTDIR)\ApacheModuleInfo.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) $< +<< + + +!IF "$(CFG)" == "ApacheModuleInfo - Win32 Release" || "$(CFG)" ==\ + "ApacheModuleInfo - Win32 Debug" +SOURCE=..\..\modules\standard\mod_info.c +DEP_CPP_MOD_I=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.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"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_I=\ + "..\..\include\ebcdic.h"\ + "..\..\include\os.h"\ + "..\..\include\sfio.h"\ + + +"$(INTDIR)\mod_info.obj" : $(SOURCE) $(DEP_CPP_MOD_I) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + + +!ENDIF + diff --git a/APACHE_1_3_12/src/os/win32/ApacheModuleRewrite.dsp b/APACHE_1_3_12/src/os/win32/ApacheModuleRewrite.dsp new file mode 100644 index 0000000000..4a0ffd1bf6 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/ApacheModuleRewrite.dsp @@ -0,0 +1,117 @@ +# Microsoft Developer Studio Project File - Name="ApacheModuleRewrite" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=ApacheModuleRewrite - 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 "ApacheModuleRewrite.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 "ApacheModuleRewrite.mak"\ + CFG="ApacheModuleRewrite - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleRewrite - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleRewrite - Win32 Debug" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleRewrite - 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 ".\ApacheModuleRewriteR" +# PROP Intermediate_Dir ".\ApacheModuleRewriteR" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "NO_DBM_REWRITEMAP" /D "SHARED_MODULE" /D "WIN32_LEAN_AND_MEAN" /YX /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 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 ws2_32.lib /nologo /subsystem:windows /dll /machine:I386 + +!ELSEIF "$(CFG)" == "ApacheModuleRewrite - 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 ".\ApacheModuleRewriteD" +# PROP Intermediate_Dir ".\ApacheModuleRewriteD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# 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 "..\..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "NO_DBM_REWRITEMAP" /D "SHARED_MODULE" /D "WIN32_LEAN_AND_MEAN" /YX /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 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 ws2_32.lib /nologo /subsystem:windows /dll /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "ApacheModuleRewrite - Win32 Release" +# Name "ApacheModuleRewrite - 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\standard\mod_rewrite.c +# End Source File +# Begin Source File + +SOURCE=.\passwd.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\readdir.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_12/src/os/win32/ApacheModuleRewrite.mak b/APACHE_1_3_12/src/os/win32/ApacheModuleRewrite.mak new file mode 100644 index 0000000000..6d2e565908 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/ApacheModuleRewrite.mak @@ -0,0 +1,255 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ApacheModuleRewrite.dsp +!IF "$(CFG)" == "" +CFG=ApacheModuleRewrite - Win32 Release +!MESSAGE No configuration specified. Defaulting to ApacheModuleRewrite - Win32\ + Release. +!ENDIF + +!IF "$(CFG)" != "ApacheModuleRewrite - Win32 Release" && "$(CFG)" !=\ + "ApacheModuleRewrite - 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 "ApacheModuleRewrite.mak"\ + CFG="ApacheModuleRewrite - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleRewrite - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleRewrite - 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 + +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleRewrite - Win32 Release" + +OUTDIR=.\ApacheModuleRewriteR +INTDIR=.\ApacheModuleRewriteR +# Begin Custom Macros +OutDir=.\.\ApacheModuleRewriteR +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleRewrite.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleRewrite.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_rewrite.obj" + -@erase "$(INTDIR)\passwd.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheModuleRewrite.dll" + -@erase "$(OUTDIR)\ApacheModuleRewrite.exp" + -@erase "$(OUTDIR)\ApacheModuleRewrite.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D\ + "_WINDOWS" /D "NO_DBM_REWRITEMAP" /D "SHARED_MODULE" /D "WIN32_LEAN_AND_MEAN"\ + /Fp"$(INTDIR)\ApacheModuleRewrite.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\"\ + /FD /c +CPP_OBJS=.\ApacheModuleRewriteR/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleRewrite.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib ws2_32.lib /nologo\ + /subsystem:windows /dll /incremental:no\ + /pdb:"$(OUTDIR)\ApacheModuleRewrite.pdb" /machine:I386\ + /out:"$(OUTDIR)\ApacheModuleRewrite.dll"\ + /implib:"$(OUTDIR)\ApacheModuleRewrite.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_rewrite.obj" \ + "$(INTDIR)\passwd.obj" + +"$(OUTDIR)\ApacheModuleRewrite.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ApacheModuleRewrite - Win32 Debug" + +OUTDIR=.\ApacheModuleRewriteD +INTDIR=.\ApacheModuleRewriteD +# Begin Custom Macros +OutDir=.\.\ApacheModuleRewriteD +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleRewrite.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleRewrite.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_rewrite.obj" + -@erase "$(INTDIR)\passwd.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\ApacheModuleRewrite.dll" + -@erase "$(OUTDIR)\ApacheModuleRewrite.exp" + -@erase "$(OUTDIR)\ApacheModuleRewrite.ilk" + -@erase "$(OUTDIR)\ApacheModuleRewrite.lib" + -@erase "$(OUTDIR)\ApacheModuleRewrite.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D\ + "WIN32" /D "_WINDOWS" /D "NO_DBM_REWRITEMAP" /D "SHARED_MODULE" /D\ + "WIN32_LEAN_AND_MEAN" /Fp"$(INTDIR)\ApacheModuleRewrite.pch" /YX\ + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleRewriteD/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleRewrite.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib ws2_32.lib /nologo\ + /subsystem:windows /dll /incremental:yes\ + /pdb:"$(OUTDIR)\ApacheModuleRewrite.pdb" /debug /machine:I386\ + /out:"$(OUTDIR)\ApacheModuleRewrite.dll"\ + /implib:"$(OUTDIR)\ApacheModuleRewrite.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_rewrite.obj" \ + "$(INTDIR)\passwd.obj" + +"$(OUTDIR)\ApacheModuleRewrite.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) $< +<< + + +!IF "$(CFG)" == "ApacheModuleRewrite - Win32 Release" || "$(CFG)" ==\ + "ApacheModuleRewrite - Win32 Debug" +SOURCE=..\..\modules\standard\mod_rewrite.c + +!IF "$(CFG)" == "ApacheModuleRewrite - Win32 Release" + +DEP_CPP_MOD_R=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_config.h"\ + "..\..\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_rewrite.obj" : $(SOURCE) $(DEP_CPP_MOD_R) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheModuleRewrite - Win32 Debug" + +DEP_CPP_MOD_R=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_config.h"\ + "..\..\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_rewrite.obj" : $(SOURCE) $(DEP_CPP_MOD_R) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\passwd.c +DEP_CPP_PASSW=\ + ".\passwd.h"\ + + +"$(INTDIR)\passwd.obj" : $(SOURCE) $(DEP_CPP_PASSW) "$(INTDIR)" + + + +!ENDIF + diff --git a/APACHE_1_3_12/src/os/win32/ApacheModuleSpeling.dsp b/APACHE_1_3_12/src/os/win32/ApacheModuleSpeling.dsp new file mode 100644 index 0000000000..499a72f3f7 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/ApacheModuleSpeling.dsp @@ -0,0 +1,113 @@ +# Microsoft Developer Studio Project File - Name="ApacheModuleSpeling" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=ApacheModuleSpeling - 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 "ApacheModuleSpeling.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 "ApacheModuleSpeling.mak"\ + CFG="ApacheModuleSpeling - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleSpeling - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleSpeling - Win32 Debug" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleSpeling - 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 ".\ApacheModuleSpelingR" +# PROP Intermediate_Dir ".\ApacheModuleSpelingR" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /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 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 /nologo /subsystem:windows /dll /machine:I386 + +!ELSEIF "$(CFG)" == "ApacheModuleSpeling - 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 ".\ApacheModuleSpelingD" +# PROP Intermediate_Dir ".\ApacheModuleSpelingD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# 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 "..\..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /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 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 /nologo /subsystem:windows /dll /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "ApacheModuleSpeling - Win32 Release" +# Name "ApacheModuleSpeling - 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\standard\mod_speling.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\readdir.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_12/src/os/win32/ApacheModuleSpeling.mak b/APACHE_1_3_12/src/os/win32/ApacheModuleSpeling.mak new file mode 100644 index 0000000000..300ad98cea --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/ApacheModuleSpeling.mak @@ -0,0 +1,236 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ApacheModuleSpeling.dsp +!IF "$(CFG)" == "" +CFG=ApacheModuleSpeling - Win32 Release +!MESSAGE No configuration specified. Defaulting to ApacheModuleSpeling - Win32\ + Release. +!ENDIF + +!IF "$(CFG)" != "ApacheModuleSpeling - Win32 Release" && "$(CFG)" !=\ + "ApacheModuleSpeling - 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 "ApacheModuleSpeling.mak"\ + CFG="ApacheModuleSpeling - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleSpeling - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleSpeling - 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 + +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleSpeling - Win32 Release" + +OUTDIR=.\ApacheModuleSpelingR +INTDIR=.\ApacheModuleSpelingR +# Begin Custom Macros +OutDir=.\.\ApacheModuleSpelingR +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleSpeling.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleSpeling.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_speling.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheModuleSpeling.dll" + -@erase "$(OUTDIR)\ApacheModuleSpeling.exp" + -@erase "$(OUTDIR)\ApacheModuleSpeling.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D\ + "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleSpeling.pch" /YX\ + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleSpelingR/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleSpeling.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:no /pdb:"$(OUTDIR)\ApacheModuleSpeling.pdb" /machine:I386\ + /out:"$(OUTDIR)\ApacheModuleSpeling.dll"\ + /implib:"$(OUTDIR)\ApacheModuleSpeling.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_speling.obj" + +"$(OUTDIR)\ApacheModuleSpeling.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ApacheModuleSpeling - Win32 Debug" + +OUTDIR=.\ApacheModuleSpelingD +INTDIR=.\ApacheModuleSpelingD +# Begin Custom Macros +OutDir=.\.\ApacheModuleSpelingD +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleSpeling.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleSpeling.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_speling.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\ApacheModuleSpeling.dll" + -@erase "$(OUTDIR)\ApacheModuleSpeling.exp" + -@erase "$(OUTDIR)\ApacheModuleSpeling.ilk" + -@erase "$(OUTDIR)\ApacheModuleSpeling.lib" + -@erase "$(OUTDIR)\ApacheModuleSpeling.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D\ + "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleSpeling.pch"\ + /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleSpelingD/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleSpeling.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:yes /pdb:"$(OUTDIR)\ApacheModuleSpeling.pdb" /debug\ + /machine:I386 /out:"$(OUTDIR)\ApacheModuleSpeling.dll"\ + /implib:"$(OUTDIR)\ApacheModuleSpeling.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_speling.obj" + +"$(OUTDIR)\ApacheModuleSpeling.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) $< +<< + + +!IF "$(CFG)" == "ApacheModuleSpeling - Win32 Release" || "$(CFG)" ==\ + "ApacheModuleSpeling - Win32 Debug" +SOURCE=..\..\modules\standard\mod_speling.c + +!IF "$(CFG)" == "ApacheModuleSpeling - Win32 Release" + +DEP_CPP_MOD_S=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.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"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_S=\ + "..\..\include\ebcdic.h"\ + "..\..\include\os.h"\ + "..\..\include\sfio.h"\ + + +"$(INTDIR)\mod_speling.obj" : $(SOURCE) $(DEP_CPP_MOD_S) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheModuleSpeling - Win32 Debug" + +DEP_CPP_MOD_S=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.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"\ + + +"$(INTDIR)\mod_speling.obj" : $(SOURCE) $(DEP_CPP_MOD_S) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + + +!ENDIF + diff --git a/APACHE_1_3_12/src/os/win32/ApacheModuleStatus.dsp b/APACHE_1_3_12/src/os/win32/ApacheModuleStatus.dsp new file mode 100644 index 0000000000..8bc9271959 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/ApacheModuleStatus.dsp @@ -0,0 +1,113 @@ +# Microsoft Developer Studio Project File - Name="ApacheModuleStatus" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=ApacheModuleStatus - 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 "ApacheModuleStatus.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 "ApacheModuleStatus.mak"\ + CFG="ApacheModuleStatus - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleStatus - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleStatus - Win32 Debug" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleStatus - 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 ".\ApacheModuleStatusR" +# PROP Intermediate_Dir ".\ApacheModuleStatusR" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /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 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 /nologo /subsystem:windows /dll /machine:I386 + +!ELSEIF "$(CFG)" == "ApacheModuleStatus - 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 ".\ApacheModuleStatusD" +# PROP Intermediate_Dir ".\ApacheModuleStatusD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# 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 "..\..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /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 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 /nologo /subsystem:windows /dll /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "ApacheModuleStatus - Win32 Release" +# Name "ApacheModuleStatus - 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\standard\mod_status.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\readdir.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_12/src/os/win32/ApacheModuleStatus.mak b/APACHE_1_3_12/src/os/win32/ApacheModuleStatus.mak new file mode 100644 index 0000000000..e8d23623b5 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/ApacheModuleStatus.mak @@ -0,0 +1,274 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ApacheModuleStatus.dsp +!IF "$(CFG)" == "" +CFG=ApacheModuleStatus - Win32 Release +!MESSAGE No configuration specified. Defaulting to ApacheModuleStatus - Win32\ + Release. +!ENDIF + +!IF "$(CFG)" != "ApacheModuleStatus - Win32 Release" && "$(CFG)" !=\ + "ApacheModuleStatus - 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 "ApacheModuleStatus.mak"\ + CFG="ApacheModuleStatus - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleStatus - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleStatus - 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)" == "ApacheModuleStatus - Win32 Release" + +OUTDIR=.\ApacheModuleStatusR +INTDIR=.\ApacheModuleStatusR +# Begin Custom Macros +OutDir=.\.\ApacheModuleStatusR +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleStatus.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleStatus.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_status.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheModuleStatus.dll" + -@erase "$(OUTDIR)\ApacheModuleStatus.exp" + -@erase "$(OUTDIR)\ApacheModuleStatus.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D\ + "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleStatus.pch" /YX\ + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleStatusR/ +CPP_SBRS=. + +.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) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +RSC=rc.exe +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleStatus.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:no /pdb:"$(OUTDIR)\ApacheModuleStatus.pdb" /machine:I386\ + /out:"$(OUTDIR)\ApacheModuleStatus.dll"\ + /implib:"$(OUTDIR)\ApacheModuleStatus.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_status.obj" + +"$(OUTDIR)\ApacheModuleStatus.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ApacheModuleStatus - Win32 Debug" + +OUTDIR=.\ApacheModuleStatusD +INTDIR=.\ApacheModuleStatusD +# Begin Custom Macros +OutDir=.\.\ApacheModuleStatusD +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleStatus.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleStatus.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_status.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\ApacheModuleStatus.dll" + -@erase "$(OUTDIR)\ApacheModuleStatus.exp" + -@erase "$(OUTDIR)\ApacheModuleStatus.ilk" + -@erase "$(OUTDIR)\ApacheModuleStatus.lib" + -@erase "$(OUTDIR)\ApacheModuleStatus.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D\ + "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleStatus.pch"\ + /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleStatusD/ +CPP_SBRS=. + +.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) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +RSC=rc.exe +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleStatus.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:yes /pdb:"$(OUTDIR)\ApacheModuleStatus.pdb" /debug\ + /machine:I386 /out:"$(OUTDIR)\ApacheModuleStatus.dll"\ + /implib:"$(OUTDIR)\ApacheModuleStatus.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_status.obj" + +"$(OUTDIR)\ApacheModuleStatus.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + + +!IF "$(CFG)" == "ApacheModuleStatus - Win32 Release" || "$(CFG)" ==\ + "ApacheModuleStatus - Win32 Debug" +SOURCE=..\..\modules\standard\mod_status.c + +!IF "$(CFG)" == "ApacheModuleStatus - Win32 Release" + +DEP_CPP_MOD_S=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\ap_config.h"\ + "..\..\include\ap_ctype.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"\ + + +"$(INTDIR)\mod_status.obj" : $(SOURCE) $(DEP_CPP_MOD_S) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheModuleStatus - Win32 Debug" + +DEP_CPP_MOD_S=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\ap_config.h"\ + "..\..\include\ap_ctype.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\httpd.h"\ + "..\..\include\scoreboard.h"\ + "..\..\include\util_script.h"\ + "..\..\include\util_uri.h"\ + ".\os.h"\ + ".\readdir.h"\ + + +"$(INTDIR)\mod_status.obj" : $(SOURCE) $(DEP_CPP_MOD_S) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + + +!ENDIF + diff --git a/APACHE_1_3_12/src/os/win32/ApacheModuleUserTrack.dsp b/APACHE_1_3_12/src/os/win32/ApacheModuleUserTrack.dsp new file mode 100644 index 0000000000..e3aee558ce --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/ApacheModuleUserTrack.dsp @@ -0,0 +1,113 @@ +# Microsoft Developer Studio Project File - Name="ApacheModuleUserTrack" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=ApacheModuleUserTrack - 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 "ApacheModuleUserTrack.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 "ApacheModuleUserTrack.mak"\ + CFG="ApacheModuleUserTrack - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleUserTrack - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleUserTrack - Win32 Debug" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleUserTrack - 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 ".\ApacheModuleUserTrackR" +# PROP Intermediate_Dir ".\ApacheModuleUserTrackR" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /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 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 /nologo /subsystem:windows /dll /machine:I386 + +!ELSEIF "$(CFG)" == "ApacheModuleUserTrack - 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 ".\ApacheModuleUserTrackD" +# PROP Intermediate_Dir ".\ApacheModuleUserTrackD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# 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 "..\..\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "SHARED_MODULE" /YX /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 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 /nologo /subsystem:windows /dll /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "ApacheModuleUserTrack - Win32 Release" +# Name "ApacheModuleUserTrack - 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\standard\mod_usertrack.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" +# Begin Source File + +SOURCE=.\readdir.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_12/src/os/win32/ApacheModuleUserTrack.mak b/APACHE_1_3_12/src/os/win32/ApacheModuleUserTrack.mak new file mode 100644 index 0000000000..20e415410b --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/ApacheModuleUserTrack.mak @@ -0,0 +1,235 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ApacheModuleUserTrack.dsp +!IF "$(CFG)" == "" +CFG=ApacheModuleUserTrack - Win32 Release +!MESSAGE No configuration specified. Defaulting to ApacheModuleUserTrack -\ + Win32 Release. +!ENDIF + +!IF "$(CFG)" != "ApacheModuleUserTrack - Win32 Release" && "$(CFG)" !=\ + "ApacheModuleUserTrack - 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 "ApacheModuleUserTrack.mak"\ + CFG="ApacheModuleUserTrack - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ApacheModuleUserTrack - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "ApacheModuleUserTrack - 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 + +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ApacheModuleUserTrack - Win32 Release" + +OUTDIR=.\ApacheModuleUserTrackR +INTDIR=.\ApacheModuleUserTrackR +# Begin Custom Macros +OutDir=.\.\ApacheModuleUserTrackR +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleUserTrack.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleUserTrack.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_usertrack.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheModuleUserTrack.dll" + -@erase "$(OUTDIR)\ApacheModuleUserTrack.exp" + -@erase "$(OUTDIR)\ApacheModuleUserTrack.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "..\..\include" /D "NDEBUG" /D "WIN32" /D\ + "_WINDOWS" /D "SHARED_MODULE" /Fp"$(INTDIR)\ApacheModuleUserTrack.pch" /YX\ + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheModuleUserTrackR/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleUserTrack.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreR\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:no /pdb:"$(OUTDIR)\ApacheModuleUserTrack.pdb" /machine:I386\ + /out:"$(OUTDIR)\ApacheModuleUserTrack.dll"\ + /implib:"$(OUTDIR)\ApacheModuleUserTrack.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_usertrack.obj" + +"$(OUTDIR)\ApacheModuleUserTrack.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ApacheModuleUserTrack - Win32 Debug" + +OUTDIR=.\ApacheModuleUserTrackD +INTDIR=.\ApacheModuleUserTrackD +# Begin Custom Macros +OutDir=.\.\ApacheModuleUserTrackD +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheModuleUserTrack.dll" + +!ELSE + +ALL : "$(OUTDIR)\ApacheModuleUserTrack.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\mod_usertrack.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\ApacheModuleUserTrack.dll" + -@erase "$(OUTDIR)\ApacheModuleUserTrack.exp" + -@erase "$(OUTDIR)\ApacheModuleUserTrack.ilk" + -@erase "$(OUTDIR)\ApacheModuleUserTrack.lib" + -@erase "$(OUTDIR)\ApacheModuleUserTrack.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\..\include" /D "_DEBUG" /D\ + "WIN32" /D "_WINDOWS" /D "SHARED_MODULE"\ + /Fp"$(INTDIR)\ApacheModuleUserTrack.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\"\ + /FD /c +CPP_OBJS=.\ApacheModuleUserTrackD/ +CPP_SBRS=. +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32 +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ApacheModuleUserTrack.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=..\..\CoreD\ApacheCore.lib kernel32.lib user32.lib gdi32.lib\ + winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows\ + /dll /incremental:yes /pdb:"$(OUTDIR)\ApacheModuleUserTrack.pdb" /debug\ + /machine:I386 /out:"$(OUTDIR)\ApacheModuleUserTrack.dll"\ + /implib:"$(OUTDIR)\ApacheModuleUserTrack.lib" +LINK32_OBJS= \ + "$(INTDIR)\mod_usertrack.obj" + +"$(OUTDIR)\ApacheModuleUserTrack.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) $< +<< + + +!IF "$(CFG)" == "ApacheModuleUserTrack - Win32 Release" || "$(CFG)" ==\ + "ApacheModuleUserTrack - Win32 Debug" +SOURCE=..\..\modules\standard\mod_usertrack.c + +!IF "$(CFG)" == "ApacheModuleUserTrack - Win32 Release" + +DEP_CPP_MOD_U=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\httpd.h"\ + "..\..\include\util_uri.h"\ + ".\os.h"\ + ".\readdir.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_MOD_U=\ + "..\..\include\ebcdic.h"\ + "..\..\include\os.h"\ + "..\..\include\sfio.h"\ + + +"$(INTDIR)\mod_usertrack.obj" : $(SOURCE) $(DEP_CPP_MOD_U) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "ApacheModuleUserTrack - Win32 Debug" + +DEP_CPP_MOD_U=\ + "..\..\include\alloc.h"\ + "..\..\include\ap.h"\ + "..\..\include\ap_mmn.h"\ + "..\..\include\buff.h"\ + "..\..\include\conf.h"\ + "..\..\include\hsregex.h"\ + "..\..\include\http_config.h"\ + "..\..\include\http_core.h"\ + "..\..\include\httpd.h"\ + "..\..\include\util_uri.h"\ + ".\os.h"\ + ".\readdir.h"\ + + +"$(INTDIR)\mod_usertrack.obj" : $(SOURCE) $(DEP_CPP_MOD_U) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + + +!ENDIF + diff --git a/APACHE_1_3_12/src/os/win32/ApacheOS.dsp b/APACHE_1_3_12/src/os/win32/ApacheOS.dsp new file mode 100755 index 0000000000..55b814873e --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/ApacheOS.dsp @@ -0,0 +1,86 @@ +# Microsoft Developer Studio Project File - Name="ApacheOS" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.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 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 "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "ApacheOSR" +# PROP Intermediate_Dir "ApacheOSR" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /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 "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "ApacheOSD" +# PROP Intermediate_Dir "ApacheOSD" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /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_12/src/os/win32/ApacheOS.mak b/APACHE_1_3_12/src/os/win32/ApacheOS.mak new file mode 100755 index 0000000000..4630d8c54b --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/ApacheOS.mak @@ -0,0 +1,164 @@ +# 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 + +CPP=cl.exe + +!IF "$(CFG)" == "ApacheOS - Win32 Release" + +OUTDIR=.\ApacheOSR +INTDIR=.\ApacheOSR +# Begin Custom Macros +OutDir=.\ApacheOSR +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheOS.lib" + +!ELSE + +ALL : "$(OUTDIR)\ApacheOS.lib" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\os.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheOS.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\ + /Fp"$(INTDIR)\ApacheOS.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheOSR/ +CPP_SBRS=. +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=.\ApacheOSD +INTDIR=.\ApacheOSD +# Begin Custom Macros +OutDir=.\ApacheOSD +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\ApacheOS.lib" + +!ELSE + +ALL : "$(OUTDIR)\ApacheOS.lib" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\os.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\ApacheOS.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS"\ + /Fp"$(INTDIR)\ApacheOS.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\ApacheOSD/ +CPP_SBRS=. +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 + +.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) $< +<< + + +!IF "$(CFG)" == "ApacheOS - Win32 Release" || "$(CFG)" ==\ + "ApacheOS - Win32 Debug" +SOURCE=.\os.c +DEP_CPP_OS_C0=\ + ".\os.h"\ + + +"$(INTDIR)\os.obj" : $(SOURCE) $(DEP_CPP_OS_C0) "$(INTDIR)" + + + +!ENDIF + diff --git a/APACHE_1_3_12/src/os/win32/MakeModuleMak.cpp b/APACHE_1_3_12/src/os/win32/MakeModuleMak.cpp new file mode 100644 index 0000000000..9ab9f27221 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/MakeModuleMak.cpp @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include + +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] << " [ ]+\n"; + exit(1); + } + for(int n=1 ; n < argc ; n+=2) + MakeMake(argv[n],argv[n+1]); + } + diff --git a/APACHE_1_3_12/src/os/win32/MakeModuleMak.mak b/APACHE_1_3_12/src/os/win32/MakeModuleMak.mak new file mode 100644 index 0000000000..6b51ed0834 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/MakeModuleMak.mak @@ -0,0 +1,195 @@ +# Microsoft Developer Studio Generated NMAKE File, Format Version 4.20 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +!IF "$(CFG)" == "" +CFG=MakeModuleMak - Win32 Debug +!MESSAGE No configuration specified. Defaulting to MakeModuleMak - Win32\ + Debug. +!ENDIF + +!IF "$(CFG)" != "MakeModuleMak - Win32 Release" && "$(CFG)" !=\ + "MakeModuleMak - 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 "MakeModuleMak.mak" CFG="MakeModuleMak - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "MakeModuleMak - Win32 Release" (based on\ + "Win32 (x86) Console Application") +!MESSAGE "MakeModuleMak - 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 +################################################################################ +# Begin Project +RSC=rc.exe +CPP=cl.exe + +!IF "$(CFG)" == "MakeModuleMak - 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 Target_Dir "" +OUTDIR=.\Release +INTDIR=.\Release + +ALL : "$(OUTDIR)\MakeModuleMak.exe" + +CLEAN : + -@erase "$(INTDIR)\MakeModuleMak.obj" + -@erase "$(OUTDIR)\MakeModuleMak.exe" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /YX /c +CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ + /Fp"$(INTDIR)/MakeModuleMak.pch" /YX /Fo"$(INTDIR)/" /c +CPP_OBJS=.\Release/ +CPP_SBRS=.\. +# 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)/MakeModuleMak.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:console /machine:I386 +# ADD 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:console /machine:I386 +LINK32_FLAGS=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:console /incremental:no\ + /pdb:"$(OUTDIR)/MakeModuleMak.pdb" /machine:I386\ + /out:"$(OUTDIR)/MakeModuleMak.exe" +LINK32_OBJS= \ + "$(INTDIR)\MakeModuleMak.obj" + +"$(OUTDIR)\MakeModuleMak.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "MakeModuleMak - 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 Target_Dir "" +OUTDIR=.\Debug +INTDIR=.\Debug + +ALL : "$(OUTDIR)\MakeModuleMak.exe" + +CLEAN : + -@erase "$(INTDIR)\MakeModuleMak.obj" + -@erase "$(INTDIR)\vc40.idb" + -@erase "$(INTDIR)\vc40.pdb" + -@erase "$(OUTDIR)\MakeModuleMak.exe" + -@erase "$(OUTDIR)\MakeModuleMak.ilk" + -@erase "$(OUTDIR)\MakeModuleMak.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c +CPP_PROJ=/nologo /MLd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\ + /Fp"$(INTDIR)/MakeModuleMak.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c +CPP_OBJS=.\Debug/ +CPP_SBRS=.\. +# 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)/MakeModuleMak.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:console /debug /machine:I386 +# ADD 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:console /debug /machine:I386 +LINK32_FLAGS=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:console /incremental:yes\ + /pdb:"$(OUTDIR)/MakeModuleMak.pdb" /debug /machine:I386\ + /out:"$(OUTDIR)/MakeModuleMak.exe" +LINK32_OBJS= \ + "$(INTDIR)\MakeModuleMak.obj" + +"$(OUTDIR)\MakeModuleMak.exe" : "$(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 "MakeModuleMak - Win32 Release" +# Name "MakeModuleMak - Win32 Debug" + +!IF "$(CFG)" == "MakeModuleMak - Win32 Release" + +!ELSEIF "$(CFG)" == "MakeModuleMak - Win32 Debug" + +!ENDIF + +################################################################################ +# Begin Source File + +SOURCE=.\MakeModuleMak.cpp + +"$(INTDIR)\MakeModuleMak.obj" : $(SOURCE) "$(INTDIR)" + + +# End Source File +# End Target +# End Project +################################################################################ diff --git a/APACHE_1_3_12/src/os/win32/Module.mak.tmpl b/APACHE_1_3_12/src/os/win32/Module.mak.tmpl new file mode 100644 index 0000000000..162456f064 --- /dev/null +++ b/APACHE_1_3_12/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=\ + "..\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_12/src/os/win32/apache.ico b/APACHE_1_3_12/src/os/win32/apache.ico new file mode 100755 index 0000000000000000000000000000000000000000..161bcf7841cb95d326d9729fb0000941cef010d2 GIT binary patch literal 766 zcmcIiyKVw85Znt$i7TjRC~{@~0Yy+;gB1ES`4%kk0ioT3FQGA2+AEUc3QLrfNHkYO z+061d+ZUu%tZ%$Kp7HuDnJB}^^FC?p?uZ7+Pe2Y#fQ-7Bi7d41VIe}X_LMNAB^)TsBsHWP6w-$U*}emq-5YDhJteeZ$Sa@ literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/src/os/win32/apache.rc b/APACHE_1_3_12/src/os/win32/apache.rc new file mode 100755 index 0000000000..6dde63f950 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/os/win32/getopt.c b/APACHE_1_3_12/src/os/win32/getopt.c new file mode 100644 index 0000000000..187807216a --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/getopt.c @@ -0,0 +1,170 @@ +#include +#include +#include +#include + +#ifdef WIN32 + +#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); +} + +#endif /* WIN32 */ + +#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 ] files...\n"); + exit (2); + } + for ( ; optind < argc; optind++) + (void)printf("%s\n", argv[optind]); + return 0; + } + +#endif /* TESTGETOPT */ \ No newline at end of file diff --git a/APACHE_1_3_12/src/os/win32/getopt.h b/APACHE_1_3_12/src/os/win32/getopt.h new file mode 100644 index 0000000000..f0a4e696ce --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/getopt.h @@ -0,0 +1,10 @@ +#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 */ \ No newline at end of file diff --git a/APACHE_1_3_12/src/os/win32/installer/README.TXT b/APACHE_1_3_12/src/os/win32/installer/README.TXT new file mode 100644 index 0000000000..247cdd1fe3 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/installer/README.TXT @@ -0,0 +1,6 @@ +Read the Apache for Windows how to release document at + + http://dev.apache.org/how-to-release-win32.html + +for details of how to use this IS2 configuration file and +the installer DLL to build an Apache release. diff --git a/APACHE_1_3_12/src/os/win32/installer/apache.iwz b/APACHE_1_3_12/src/os/win32/installer/apache.iwz new file mode 100644 index 0000000000..6af3320c83 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/installer/apache.iwz @@ -0,0 +1,995 @@ + +[InstallShield Wizard] +iDate=1 +iTime=1 +Flag=fe000000 +ISX.EXE Size=630784 +ISX.EXE Date=10:43:52 24/2/1998 +ISX.EXE Ver=2.0.0.143 +SETUP.EXE Size=45312 +SETUP.EXE Date=9:53:32 18/1/1997 +SETUP.EXE Ver=3.0.111.0 +SETUP.INS Size=70160 +SETUP.INS Date=13:16:56 11/2/1998 +SETUP.INS Ver=Not available +_INST16.EX_ Size=282766 +_INST16.EX_ Date=9:56:04 18/1/1997 +_INST16.EX_ Ver=Not available +_INST32I.EX_ Size=320411 +_INST32I.EX_ Date=10:04:08 18/1/1997 +_INST32I.EX_ Ver=Not available +ISDEPEND.INI Size=320411 +ISDEPEND.INI Date=10:04:08 18/1/1997 +ISDEPEND.INI Ver=Not available +SWDEPEND.INI Size=320411 +SWDEPEND.INI Date=10:04:08 18/1/1997 +SWDEPEND.INI Ver=Not available +ICOMP.EXE Size=119808 +ICOMP.EXE Date=14:05:10 15/1/1996 +ICOMP.EXE Ver=3.00.062 +SPLIT.EXE Size=90624 +SPLIT.EXE Date=14:09:36 15/1/1996 +SPLIT.EXE Ver=3.00.060 +PACKLIST.EXE Size=87552 +PACKLIST.EXE Date=14:10:30 15/1/1996 +PACKLIST.EXE Ver=3.00.060 +Version=2.02 +DevTool=Generic Windows +Platform=Win32 +DisksDir=apache\650MB\ +TabsVisit=1111001110000111100011 +LangNum=451 +LangDir=LANG\ENG\ + +[VisualDesign] +AppName=Apache +AppExe= +AppExeFile= +Version=1.3.7 dev +Company=Apache Group +Title=Apache Web Server 1.3.7 dev +TitleType=1 +BackgrndBmp= +BackgrndAlign=4 +Backgrnd=1 +BackgrndColor=10 +Uninstall=1 +Silent=1 +SmsMode=0 + +[Types] +Types=3 +Type1Components=6 +Type1Name=Custom +Type1ComponentList=1 3 4 6 5 2 +Type2Components=5 +Type2Name=Typical +Type2ComponentList=1 3 4 6 5 +Type3Components=2 +Type3Name=Compact +Type3ComponentList=1 6 + +[Components] +Components=6 +Component1Groups=6 +Component1Name=Application Files +Component1Description=Application files needed to run the application +Component1GroupList=1 3 24 25 4 35 +Component2Groups=17 +Component2Name=Source Code +Component2Description=Source code for Apache and support tools +Component2GroupList=10 11 12 13 14 15 16 17 18 19 20 21 22 23 31 32 34 +Component3Groups=6 +Component3Name=Apache Manual +Component3Description=Apache documentation +Component3GroupList=5 6 7 8 9 36 +Component4Groups=1 +Component4Name=Additional Modules +Component4Description=Apache modules to extend the server +Component4GroupList=2 +Component5Groups=2 +Component5Name=Icons +Component5Description=Icons for directory indexes +Component5GroupList=27 33 +Component6Groups=4 +Component6Name=Required Directories +Component6Description= +Component6GroupList=26 28 29 30 + +[Groups] +Groups=36 +Group1Size=346325 +Group1Files=9 +Group1Name=Program Executables +Group1Dir= +Group1Update=0 +Group1TargetOS=-1 +Group1File1=C:\Apache\Apache.exe +Group1File2=C:\Apache\ApacheCore.dll +Group1File3=C:\Apache\Announcement +Group1File4=C:\Apache\ABOUT_APACHE +Group1File5=C:\Apache\KEYS +Group1File6=C:\Apache\LICENSE +Group1File7=C:\Apache\README +Group1File8=C:\apache\Makefile.tmpl +Group1File9=C:\apache\README-NT.TXT +Group2Size=133120 +Group2Files=10 +Group2Name=Additional Modules +Group2Dir=\modules +Group2Update=0 +Group2TargetOS=-1 +Group2File1=C:\Apache\modules\ApacheModuleDigest.dll +Group2File2=C:\Apache\modules\ApacheModuleCERNMeta.dll +Group2File3=C:\Apache\modules\ApacheModuleAuthAnon.dll +Group2File4=C:\Apache\modules\ApacheModuleExpires.dll +Group2File5=C:\Apache\modules\ApacheModuleHeaders.dll +Group2File6=C:\Apache\modules\ApacheModuleProxy.dll +Group2File7=C:\Apache\modules\ApacheModuleSpeling.dll +Group2File8=C:\Apache\modules\ApacheModuleStatus.dll +Group2File9=C:\Apache\modules\ApacheModuleUserTrack.dll +Group2File10=C:\apache\modules\ApacheModuleRewrite.dll +Group3Size=49860 +Group3Files=6 +Group3Name=Configuration Files +Group3Dir=\.tmp +Group3Update=0 +Group3TargetOS=-1 +Group3File1=C:\Apache\conf\httpd.conf-dist-win +Group3File2=C:\Apache\conf\access.conf-dist-win +Group3File3=C:\Apache\conf\magic +Group3File4=C:\Apache\conf\mime.types +Group3File5=C:\Apache\conf\srm.conf-dist-win +Group3File6=C:\apache\conf\highperformance.conf-dist +Group4Size=3999 +Group4Files=2 +Group4Name=Initial Document Root Files +Group4Dir=\.tmp +Group4Update=1 +Group4TargetOS=-1 +Group4File1=C:\Apache\htdocs\index.html +Group4File2=C:\apache\htdocs\apache_pb.gif +Group5Size=295033 +Group5Files=34 +Group5Name=Manual +Group5Dir=\htdocs\manual +Group5Update=0 +Group5TargetOS=-1 +Group5File1=C:\apache\htdocs\manual\custom-error.html +Group5File2=C:\apache\htdocs\manual\content-negotiation.html +Group5File3=C:\apache\htdocs\manual\cgi_path.html +Group5File4=C:\apache\htdocs\manual\dns-caveats.html +Group5File5=C:\apache\htdocs\manual\dso.html +Group5File6=C:\apache\htdocs\manual\ebcdic.html +Group5File7=C:\apache\htdocs\manual\env.html +Group5File8=C:\apache\htdocs\manual\footer.html +Group5File9=C:\apache\htdocs\manual\handler.html +Group5File10=C:\apache\htdocs\manual\header.html +Group5File11=C:\apache\htdocs\manual\index.html +Group5File12=C:\apache\htdocs\manual\install.html +Group5File13=C:\apache\htdocs\manual\invoking.html +Group5File14=C:\apache\htdocs\manual\keepalive.html +Group5File15=C:\apache\htdocs\manual\LICENSE +Group5File16=C:\apache\htdocs\manual\location.html +Group5File17=C:\apache\htdocs\manual\man-template.html +Group5File18=C:\apache\htdocs\manual\multilogs.html +Group5File19=C:\apache\htdocs\manual\new_features_1_0.html +Group5File20=C:\apache\htdocs\manual\new_features_1_1.html +Group5File21=C:\apache\htdocs\manual\new_features_1_2.html +Group5File22=C:\apache\htdocs\manual\new_features_1_3.html +Group5File23=C:\apache\htdocs\manual\process-model.html +Group5File24=C:\apache\htdocs\manual\sections.html +Group5File25=C:\apache\htdocs\manual\sourcereorg.html +Group5File26=C:\apache\htdocs\manual\stopping.html +Group5File27=C:\apache\htdocs\manual\suexec.html +Group5File28=C:\apache\htdocs\manual\unixware.html +Group5File29=C:\apache\htdocs\manual\upgrading_to_1_3.html +Group5File30=C:\apache\htdocs\manual\windows.html +Group5File31=C:\apache\htdocs\manual\bind.html +Group5File32=C:\apache\htdocs\manual\suexec_1_2.html +Group5File33=C:\apache\htdocs\manual\install-tpf.html +Group5File34=C:\apache\htdocs\manual\readme-tpf.html +Group6Size=42478 +Group6Files=8 +Group6Name=images +Group6Dir=[Manual]\images +Group6Update=0 +Group6TargetOS=-1 +Group6File1=C:\Apache\htdocs\manual\images\custom_errordocs.gif +Group6File2=C:\Apache\htdocs\manual\images\home.gif +Group6File3=C:\Apache\htdocs\manual\images\index.gif +Group6File4=C:\Apache\htdocs\manual\images\sub.gif +Group6File5=C:\apache\htdocs\manual\images\mod_rewrite_fig1.fig +Group6File6=C:\apache\htdocs\manual\images\mod_rewrite_fig1.gif +Group6File7=C:\apache\htdocs\manual\images\mod_rewrite_fig2.fig +Group6File8=C:\apache\htdocs\manual\images\mod_rewrite_fig2.gif +Group7Size=329371 +Group7Files=22 +Group7Name=misc +Group7Dir=[Manual]\misc +Group7Update=0 +Group7TargetOS=-1 +Group7File1=C:\Apache\htdocs\manual\misc\API.html +Group7File2=C:\Apache\htdocs\manual\misc\client_block_api.html +Group7File3=C:\Apache\htdocs\manual\misc\compat_notes.html +Group7File4=C:\Apache\htdocs\manual\misc\custom_errordocs.html +Group7File5=C:\Apache\htdocs\manual\misc\descriptors.html +Group7File6=C:\Apache\htdocs\manual\misc\FAQ.html +Group7File7=C:\Apache\htdocs\manual\misc\fin_wait_2.html +Group7File8=C:\Apache\htdocs\manual\misc\footer.html +Group7File9=C:\Apache\htdocs\manual\misc\header.html +Group7File10=C:\Apache\htdocs\manual\misc\howto.html +Group7File11=C:\Apache\htdocs\manual\misc\index.html +Group7File12=C:\Apache\htdocs\manual\misc\known_client_problems.html +Group7File13=C:\Apache\htdocs\manual\misc\nopgp.html +Group7File14=C:\Apache\htdocs\manual\misc\perf-bsd44.html +Group7File15=C:\Apache\htdocs\manual\misc\perf-dec.html +Group7File16=C:\Apache\htdocs\manual\misc\perf-hp.html +Group7File17=C:\Apache\htdocs\manual\misc\perf-tuning.html +Group7File18=C:\Apache\htdocs\manual\misc\perf.html +Group7File19=C:\Apache\htdocs\manual\misc\security_tips.html +Group7File20=C:\Apache\htdocs\manual\misc\vif-info.html +Group7File21=C:\Apache\htdocs\manual\misc\windoz_keepalive.html +Group7File22=C:\apache\htdocs\manual\misc\HTTP_Features.tsv +Group8Size=558131 +Group8Files=48 +Group8Name=mod +Group8Dir=[Manual]\mod +Group8Update=0 +Group8TargetOS=-1 +Group8File1=C:\Apache\htdocs\manual\mod\core.html +Group8File2=C:\Apache\htdocs\manual\mod\directive-dict.html +Group8File3=C:\Apache\htdocs\manual\mod\directives.html +Group8File4=C:\Apache\htdocs\manual\mod\footer.html +Group8File5=C:\Apache\htdocs\manual\mod\header.html +Group8File6=C:\Apache\htdocs\manual\mod\index.html +Group8File7=C:\Apache\htdocs\manual\mod\mod_access.html +Group8File8=C:\Apache\htdocs\manual\mod\mod_actions.html +Group8File9=C:\Apache\htdocs\manual\mod\mod_alias.html +Group8File10=C:\Apache\htdocs\manual\mod\mod_asis.html +Group8File11=C:\Apache\htdocs\manual\mod\mod_auth.html +Group8File12=C:\Apache\htdocs\manual\mod\mod_auth_anon.html +Group8File13=C:\Apache\htdocs\manual\mod\mod_auth_db.html +Group8File14=C:\Apache\htdocs\manual\mod\mod_auth_dbm.html +Group8File15=C:\Apache\htdocs\manual\mod\mod_autoindex.html +Group8File16=C:\Apache\htdocs\manual\mod\mod_browser.html +Group8File17=C:\Apache\htdocs\manual\mod\mod_cern_meta.html +Group8File18=C:\Apache\htdocs\manual\mod\mod_cgi.html +Group8File19=C:\Apache\htdocs\manual\mod\mod_cookies.html +Group8File20=C:\Apache\htdocs\manual\mod\mod_digest.html +Group8File21=C:\Apache\htdocs\manual\mod\mod_dir.html +Group8File22=C:\Apache\htdocs\manual\mod\mod_dld.html +Group8File23=C:\Apache\htdocs\manual\mod\mod_dll.html +Group8File24=C:\Apache\htdocs\manual\mod\mod_env.html +Group8File25=C:\Apache\htdocs\manual\mod\mod_example.html +Group8File26=C:\Apache\htdocs\manual\mod\mod_expires.html +Group8File27=C:\Apache\htdocs\manual\mod\mod_headers.html +Group8File28=C:\Apache\htdocs\manual\mod\mod_imap.html +Group8File29=C:\Apache\htdocs\manual\mod\mod_include.html +Group8File30=C:\Apache\htdocs\manual\mod\mod_info.html +Group8File31=C:\Apache\htdocs\manual\mod\mod_isapi.html +Group8File32=C:\Apache\htdocs\manual\mod\mod_log_agent.html +Group8File33=C:\Apache\htdocs\manual\mod\mod_log_common.html +Group8File34=C:\Apache\htdocs\manual\mod\mod_log_config.html +Group8File35=C:\Apache\htdocs\manual\mod\mod_log_referer.html +Group8File36=C:\Apache\htdocs\manual\mod\mod_mime.html +Group8File37=C:\Apache\htdocs\manual\mod\mod_mime_magic.html +Group8File38=C:\Apache\htdocs\manual\mod\mod_negotiation.html +Group8File39=C:\Apache\htdocs\manual\mod\mod_proxy.html +Group8File40=C:\Apache\htdocs\manual\mod\mod_rewrite.html +Group8File41=C:\Apache\htdocs\manual\mod\mod_setenvif.html +Group8File42=C:\Apache\htdocs\manual\mod\mod_so.html +Group8File43=C:\Apache\htdocs\manual\mod\mod_speling.html +Group8File44=C:\Apache\htdocs\manual\mod\mod_status.html +Group8File45=C:\Apache\htdocs\manual\mod\mod_unique_id.html +Group8File46=C:\Apache\htdocs\manual\mod\mod_userdir.html +Group8File47=C:\Apache\htdocs\manual\mod\mod_usertrack.html +Group8File48=C:\apache\htdocs\manual\mod\mod_mmap_static.html +Group9Size=112629 +Group9Files=13 +Group9Name=vhosts +Group9Dir=[Manual]\vhosts +Group9Update=0 +Group9TargetOS=-1 +Group9File1=C:\Apache\htdocs\manual\vhosts\details.html +Group9File2=C:\Apache\htdocs\manual\vhosts\details_1_2.html +Group9File3=C:\Apache\htdocs\manual\vhosts\examples.html +Group9File4=C:\Apache\htdocs\manual\vhosts\fd-limits.html +Group9File5=C:\Apache\htdocs\manual\vhosts\footer.html +Group9File6=C:\Apache\htdocs\manual\vhosts\header.html +Group9File7=C:\Apache\htdocs\manual\vhosts\host.html +Group9File8=C:\Apache\htdocs\manual\vhosts\index.html +Group9File9=C:\Apache\htdocs\manual\vhosts\ip-based.html +Group9File10=C:\Apache\htdocs\manual\vhosts\name-based.html +Group9File11=C:\Apache\htdocs\manual\vhosts\vhosts-in-depth.html +Group9File12=C:\Apache\htdocs\manual\vhosts\virtual-host.html +Group9File13=C:\apache\htdocs\manual\vhosts\mass.html +Group10Size=523748 +Group10Files=19 +Group10Name=src +Group10Dir=\src +Group10Update=0 +Group10TargetOS=-1 +Group10File1=C:\Apache\src\.gdbinit +Group10File2=C:\Apache\src\Apache.dsp +Group10File3=C:\Apache\src\Apache.mak +Group10File4=C:\Apache\src\ApacheCore.def +Group10File5=C:\Apache\src\ApacheCore.dsp +Group10File6=C:\Apache\src\ApacheCore.mak +Group10File7=C:\Apache\src\buildmark.c +Group10File8=C:\Apache\src\CHANGES +Group10File9=C:\Apache\src\Configuration.tmpl +Group10File10=C:\Apache\src\Configure +Group10File11=C:\Apache\src\INSTALL +Group10File12=C:\Apache\src\Makefile.nt +Group10File13=C:\Apache\src\Makefile.tmpl +Group10File14=C:\Apache\src\PORTING +Group10File15=C:\Apache\src\README +Group10File16=C:\Apache\src\README.EBCDIC +Group10File17=C:\apache\src\BUILD.NOTES +Group10File18=C:\apache\src\Makefile_win32.txt +Group10File19=C:\apache\src\Makefile_win32_debug.txt +Group11Size=92924 +Group11Files=10 +Group11Name=ap +Group11Dir=[src]\ap +Group11Update=0 +Group11TargetOS=-1 +Group11File1=C:\Apache\src\ap\ap.dsp +Group11File2=C:\Apache\src\ap\ap.mak +Group11File3=C:\Apache\src\ap\ap_cpystrn.c +Group11File4=C:\Apache\src\ap\ap_execve.c +Group11File5=C:\Apache\src\ap\ap_signal.c +Group11File6=C:\Apache\src\ap\ap_slack.c +Group11File7=C:\Apache\src\ap\ap_snprintf.c +Group11File8=C:\Apache\src\ap\Makefile.tmpl +Group11File9=C:\apache\src\ap\ap_fnmatch.c +Group11File10=C:\apache\src\ap\ap_md5c.c +Group12Size=255397 +Group12Files=29 +Group12Name=include +Group12Dir=[src]\include +Group12Update=0 +Group12TargetOS=-1 +Group12File1=C:\Apache\src\include\alloc.h +Group12File2=C:\Apache\src\include\ap.h +Group12File3=C:\Apache\src\include\buff.h +Group12File4=C:\Apache\src\include\conf.h +Group12File5=C:\Apache\src\include\explain.h +Group12File6=C:\Apache\src\include\fnmatch.h +Group12File7=C:\Apache\src\include\hsregex.h +Group12File8=C:\Apache\src\include\httpd.h +Group12File9=C:\Apache\src\include\http_config.h +Group12File10=C:\Apache\src\include\http_conf_globals.h +Group12File11=C:\Apache\src\include\http_core.h +Group12File12=C:\Apache\src\include\http_log.h +Group12File13=C:\Apache\src\include\http_main.h +Group12File14=C:\Apache\src\include\http_protocol.h +Group12File15=C:\Apache\src\include\http_request.h +Group12File16=C:\Apache\src\include\http_vhost.h +Group12File17=C:\Apache\src\include\ap_md5.h +Group12File18=C:\Apache\src\include\multithread.h +Group12File19=C:\Apache\src\include\rfc1413.h +Group12File20=C:\Apache\src\include\scoreboard.h +Group12File21=C:\Apache\src\include\util_date.h +Group12File22=C:\Apache\src\include\util_md5.h +Group12File23=C:\Apache\src\include\util_script.h +Group12File24=C:\apache\src\include\compat.h +Group12File25=C:\apache\src\include\util_uri.h +Group12File26=C:\apache\src\include\ap_compat.h +Group12File27=C:\apache\src\include\ap_config.h +Group12File28=C:\apache\src\include\ap_ctype.h +Group12File29=C:\apache\src\include\ap_mmn.h +Group13Size=789788 +Group13Files=22 +Group13Name=main +Group13Dir=[src]\main +Group13Update=0 +Group13TargetOS=-1 +Group13File1=C:\apache\src\main\alloc.c +Group13File2=C:\apache\src\main\buff.c +Group13File3=C:\apache\src\main\gen_test_char.c +Group13File4=C:\apache\src\main\gen_test_char.dsp +Group13File5=C:\apache\src\main\gen_test_char.mak +Group13File6=C:\apache\src\main\gen_uri_delims.c +Group13File7=C:\apache\src\main\gen_uri_delims.dsp +Group13File8=C:\apache\src\main\gen_uri_delims.mak +Group13File9=C:\apache\src\main\http_config.c +Group13File10=C:\apache\src\main\http_core.c +Group13File11=C:\apache\src\main\http_log.c +Group13File12=C:\apache\src\main\http_main.c +Group13File13=C:\apache\src\main\http_protocol.c +Group13File14=C:\apache\src\main\http_request.c +Group13File15=C:\apache\src\main\http_vhost.c +Group13File16=C:\apache\src\main\Makefile.tmpl +Group13File17=C:\apache\src\main\rfc1413.c +Group13File18=C:\apache\src\main\util.c +Group13File19=C:\apache\src\main\util_date.c +Group13File20=C:\apache\src\main\util_md5.c +Group13File21=C:\apache\src\main\util_script.c +Group13File22=C:\apache\src\main\util_uri.c +Group14Size=895 +Group14Files=1 +Group14Name=modules +Group14Dir=[src]\modules +Group14Update=0 +Group14TargetOS=-1 +Group14File1=C:\Apache\src\modules\README +Group15Size=48416 +Group15Files=3 +Group15Name=example +Group15Dir=[modules]\example +Group15Update=0 +Group15TargetOS=-1 +Group15File1=C:\Apache\src\modules\example\Makefile.tmpl +Group15File2=C:\Apache\src\modules\example\mod_example.c +Group15File3=C:\Apache\src\modules\example\README +Group16Size=13194 +Group16Files=2 +Group16Name=experimental +Group16Dir=[modules]\experimental +Group16Update=0 +Group16TargetOS=-1 +Group16File1=C:\Apache\src\modules\experimental\Makefile.tmpl +Group16File2=C:\Apache\src\modules\experimental\mod_mmap_static.c +Group17Size=69 +Group17Files=1 +Group17Name=extra +Group17Dir=[modules]\extra +Group17Update=0 +Group17TargetOS=-1 +Group17File1=C:\Apache\src\modules\extra\Makefile.tmpl +Group18Size=205708 +Group18Files=11 +Group18Name=proxy +Group18Dir=[modules]\proxy +Group18Update=0 +Group18TargetOS=-1 +Group18File1=C:\apache\src\modules\proxy\ApacheModuleProxy.dsp +Group18File2=C:\apache\src\modules\proxy\ApacheModuleProxy.mak +Group18File3=C:\apache\src\modules\proxy\Makefile.libdir +Group18File4=C:\apache\src\modules\proxy\Makefile.tmpl +Group18File5=C:\apache\src\modules\proxy\mod_proxy.c +Group18File6=C:\apache\src\modules\proxy\mod_proxy.h +Group18File7=C:\apache\src\modules\proxy\proxy_cache.c +Group18File8=C:\apache\src\modules\proxy\proxy_connect.c +Group18File9=C:\apache\src\modules\proxy\proxy_ftp.c +Group18File10=C:\apache\src\modules\proxy\proxy_http.c +Group18File11=C:\apache\src\modules\proxy\proxy_util.c +Group19Size=863524 +Group19Files=36 +Group19Name=standard +Group19Dir=[modules]\standard +Group19Update=0 +Group19TargetOS=-1 +Group19File1=C:\apache\src\modules\standard\Makefile.tmpl +Group19File2=C:\apache\src\modules\standard\mod_access.c +Group19File3=C:\apache\src\modules\standard\mod_actions.c +Group19File4=C:\apache\src\modules\standard\mod_alias.c +Group19File5=C:\apache\src\modules\standard\mod_asis.c +Group19File6=C:\apache\src\modules\standard\mod_auth.c +Group19File7=C:\apache\src\modules\standard\mod_auth_anon.c +Group19File8=C:\apache\src\modules\standard\mod_auth_db.c +Group19File9=C:\apache\src\modules\standard\mod_auth_db.module +Group19File10=C:\apache\src\modules\standard\mod_auth_dbm.c +Group19File11=C:\apache\src\modules\standard\mod_autoindex.c +Group19File12=C:\apache\src\modules\standard\mod_cern_meta.c +Group19File13=C:\apache\src\modules\standard\mod_cgi.c +Group19File14=C:\apache\src\modules\standard\mod_digest.c +Group19File15=C:\apache\src\modules\standard\mod_dir.c +Group19File16=C:\apache\src\modules\standard\mod_env.c +Group19File17=C:\apache\src\modules\standard\mod_expires.c +Group19File18=C:\apache\src\modules\standard\mod_headers.c +Group19File19=C:\apache\src\modules\standard\mod_imap.c +Group19File20=C:\apache\src\modules\standard\mod_include.c +Group19File21=C:\apache\src\modules\standard\mod_info.c +Group19File22=C:\apache\src\modules\standard\mod_log_agent.c +Group19File23=C:\apache\src\modules\standard\mod_log_config.c +Group19File24=C:\apache\src\modules\standard\mod_log_referer.c +Group19File25=C:\apache\src\modules\standard\mod_mime.c +Group19File26=C:\apache\src\modules\standard\mod_mime_magic.c +Group19File27=C:\apache\src\modules\standard\mod_negotiation.c +Group19File28=C:\apache\src\modules\standard\mod_rewrite.c +Group19File29=C:\apache\src\modules\standard\mod_rewrite.h +Group19File30=C:\apache\src\modules\standard\mod_setenvif.c +Group19File31=C:\apache\src\modules\standard\mod_so.c +Group19File32=C:\apache\src\modules\standard\mod_speling.c +Group19File33=C:\apache\src\modules\standard\mod_status.c +Group19File34=C:\apache\src\modules\standard\mod_unique_id.c +Group19File35=C:\apache\src\modules\standard\mod_userdir.c +Group19File36=C:\apache\src\modules\standard\mod_usertrack.c +Group20Size=170796 +Group20Files=25 +Group20Name=regex +Group20Dir=[src]\regex +Group20Update=0 +Group20TargetOS=-1 +Group20File1=C:\Apache\src\regex\cclass.h +Group20File2=C:\Apache\src\regex\cname.h +Group20File3=C:\Apache\src\regex\COPYRIGHT +Group20File4=C:\Apache\src\regex\debug.c +Group20File5=C:\Apache\src\regex\engine.c +Group20File6=C:\Apache\src\regex\engine.ih +Group20File7=C:\Apache\src\regex\main.c +Group20File8=C:\Apache\src\regex\Makefile.tmpl +Group20File9=C:\Apache\src\regex\mkh +Group20File10=C:\Apache\src\regex\README +Group20File11=C:\Apache\src\regex\regcomp.c +Group20File12=C:\Apache\src\regex\regcomp.ih +Group20File13=C:\Apache\src\regex\regerror.c +Group20File14=C:\Apache\src\regex\regerror.ih +Group20File15=C:\Apache\src\regex\regex.3 +Group20File16=C:\Apache\src\regex\regex.7 +Group20File17=C:\Apache\src\regex\regex.dsp +Group20File18=C:\Apache\src\regex\regex.mak +Group20File19=C:\Apache\src\regex\regex2.h +Group20File20=C:\Apache\src\regex\regexec.c +Group20File21=C:\Apache\src\regex\regfree.c +Group20File22=C:\Apache\src\regex\split.c +Group20File23=C:\Apache\src\regex\tests +Group20File24=C:\Apache\src\regex\utils.h +Group20File25=C:\Apache\src\regex\WHATSNEW +Group21Size=210232 +Group21Files=28 +Group21Name=support +Group21Dir=[src]\support +Group21Update=0 +Group21TargetOS=-1 +Group21File1=C:\apache\src\support\ab.c +Group21File2=C:\apache\src\support\apachectl +Group21File3=C:\apache\src\support\apxs.8 +Group21File4=C:\apache\src\support\apxs.pl +Group21File5=C:\apache\src\support\dbmmanage +Group21File6=C:\apache\src\support\dbmmanage.1 +Group21File7=C:\apache\src\support\htdigest.1 +Group21File8=C:\apache\src\support\htdigest.c +Group21File9=C:\apache\src\support\htpasswd.1 +Group21File10=C:\apache\src\support\htpasswd.c +Group21File11=C:\apache\src\support\httpd.8 +Group21File12=C:\apache\src\support\log_server_status +Group21File13=C:\apache\src\support\logresolve.8 +Group21File14=C:\apache\src\support\logresolve.c +Group21File15=C:\apache\src\support\logresolve.pl +Group21File16=C:\apache\src\support\Makefile.tmpl +Group21File17=C:\apache\src\support\phf_abuse_log.cgi +Group21File18=C:\apache\src\support\rotatelogs.8 +Group21File19=C:\apache\src\support\rotatelogs.c +Group21File20=C:\apache\src\support\split-logfile +Group21File21=C:\apache\src\support\suexec.8 +Group21File22=C:\apache\src\support\suexec.c +Group21File23=C:\apache\src\support\suexec.h +Group21File24=C:\apache\src\support\httpd.exp +Group21File25=C:\apache\src\support\htpasswd.dsp +Group21File26=C:\apache\src\support\htpasswd.mak +Group21File27=C:\apache\src\support\ab.8 +Group21File28=C:\apache\src\support\apachectl.8 +Group22Size=0 +Group22Files=0 +Group22Name=os +Group22Dir=[src]\os +Group22Update=0 +Group22TargetOS=-1 +Group23Size=210812 +Group23Files=46 +Group23Name=win32 +Group23Dir=[os]\win32 +Group23Update=0 +Group23TargetOS=-1 +Group23File1=C:\apache\src\os\win32\ApacheModuleAuthAnon.dsp +Group23File2=C:\apache\src\os\win32\ApacheModuleAuthAnon.mak +Group23File3=C:\apache\src\os\win32\ApacheModuleCERNMeta.dsp +Group23File4=C:\apache\src\os\win32\ApacheModuleCERNMeta.mak +Group23File5=C:\apache\src\os\win32\ApacheModuleDigest.dsp +Group23File6=C:\apache\src\os\win32\ApacheModuleDigest.mak +Group23File7=C:\apache\src\os\win32\ApacheModuleExpires.dsp +Group23File8=C:\apache\src\os\win32\ApacheModuleExpires.mak +Group23File9=C:\apache\src\os\win32\ApacheModuleHeaders.dsp +Group23File10=C:\apache\src\os\win32\ApacheModuleHeaders.mak +Group23File11=C:\apache\src\os\win32\ApacheModuleInfo.dsp +Group23File12=C:\apache\src\os\win32\ApacheModuleInfo.mak +Group23File13=C:\apache\src\os\win32\ApacheModuleRewrite.dsp +Group23File14=C:\apache\src\os\win32\ApacheModuleRewrite.mak +Group23File15=C:\apache\src\os\win32\ApacheModuleSpeling.dsp +Group23File16=C:\apache\src\os\win32\ApacheModuleSpeling.mak +Group23File17=C:\apache\src\os\win32\ApacheModuleStatus.dsp +Group23File18=C:\apache\src\os\win32\ApacheModuleStatus.mak +Group23File19=C:\apache\src\os\win32\ApacheModuleUserTrack.dsp +Group23File20=C:\apache\src\os\win32\ApacheModuleUserTrack.mak +Group23File21=C:\apache\src\os\win32\ApacheOS.dsp +Group23File22=C:\apache\src\os\win32\ApacheOS.mak +Group23File23=C:\apache\src\os\win32\getopt.c +Group23File24=C:\apache\src\os\win32\getopt.h +Group23File25=C:\apache\src\os\win32\main_win32.c +Group23File26=C:\apache\src\os\win32\MakeModuleMak.cpp +Group23File27=C:\apache\src\os\win32\MakeModuleMak.mak +Group23File28=C:\apache\src\os\win32\mod_dll.c +Group23File29=C:\apache\src\os\win32\mod_isapi.c +Group23File30=C:\apache\src\os\win32\Module.mak.tmpl +Group23File31=C:\apache\src\os\win32\modules.c +Group23File32=C:\apache\src\os\win32\multithread.c +Group23File33=C:\apache\src\os\win32\os.c +Group23File34=C:\apache\src\os\win32\os.h +Group23File35=C:\apache\src\os\win32\passwd.c +Group23File36=C:\apache\src\os\win32\passwd.h +Group23File37=C:\apache\src\os\win32\readdir.c +Group23File38=C:\apache\src\os\win32\readdir.h +Group23File39=C:\apache\src\os\win32\registry.c +Group23File40=C:\apache\src\os\win32\registry.h +Group23File41=C:\apache\src\os\win32\service.c +Group23File42=C:\apache\src\os\win32\service.h +Group23File43=C:\apache\src\os\win32\util_win32.c +Group23File44=C:\apache\src\os\win32\apache.ico +Group23File45=C:\apache\src\os\win32\apache.rc +Group23File46=C:\apache\src\os\win32\resource.h +Group24Size=84480 +Group24Files=1 +Group24Name=Installer DLL +Group24Dir= +Group24Update=0 +Group24TargetOS=-1 +Group24File1=C:\Apache\install.dll +Group25Size=254005 +Group25Files=1 +Group25Name=Shared DLLs +Group25Dir= +Group25Update=0 +Group25TargetOS=-1 +Group25File1=C:\Apache\MSVCRT.DLL +Group26Size=0 +Group26Files=0 +Group26Name=logs +Group26Dir=\logs +Group26Update=0 +Group26TargetOS=-1 +Group27Size=37127 +Group27Files=76 +Group27Name=icons +Group27Dir=\icons +Group27Update=1 +Group27TargetOS=-1 +Group27File1=C:\apache\icons\a.gif +Group27File2=C:\apache\icons\alert.black.gif +Group27File3=C:\apache\icons\alert.red.gif +Group27File4=C:\apache\icons\apache_pb.gif +Group27File5=C:\apache\icons\back.gif +Group27File6=C:\apache\icons\ball.gray.gif +Group27File7=C:\apache\icons\ball.red.gif +Group27File8=C:\apache\icons\binary.gif +Group27File9=C:\apache\icons\binhex.gif +Group27File10=C:\apache\icons\blank.gif +Group27File11=C:\apache\icons\bomb.gif +Group27File12=C:\apache\icons\box1.gif +Group27File13=C:\apache\icons\box2.gif +Group27File14=C:\apache\icons\broken.gif +Group27File15=C:\apache\icons\burst.gif +Group27File16=C:\apache\icons\c.gif +Group27File17=C:\apache\icons\comp.blue.gif +Group27File18=C:\apache\icons\comp.gray.gif +Group27File19=C:\apache\icons\compressed.gif +Group27File20=C:\apache\icons\continued.gif +Group27File21=C:\apache\icons\dir.gif +Group27File22=C:\apache\icons\down.gif +Group27File23=C:\apache\icons\dvi.gif +Group27File24=C:\apache\icons\f.gif +Group27File25=C:\apache\icons\folder.gif +Group27File26=C:\apache\icons\folder.open.gif +Group27File27=C:\apache\icons\folder.sec.gif +Group27File28=C:\apache\icons\forward.gif +Group27File29=C:\apache\icons\generic.gif +Group27File30=C:\apache\icons\generic.red.gif +Group27File31=C:\apache\icons\generic.sec.gif +Group27File32=C:\apache\icons\hand.right.gif +Group27File33=C:\apache\icons\hand.up.gif +Group27File34=C:\apache\icons\icon.sheet.gif +Group27File35=C:\apache\icons\image1.gif +Group27File36=C:\apache\icons\image2.gif +Group27File37=C:\apache\icons\image3.gif +Group27File38=C:\apache\icons\index.gif +Group27File39=C:\apache\icons\layout.gif +Group27File40=C:\apache\icons\left.gif +Group27File41=C:\apache\icons\link.gif +Group27File42=C:\apache\icons\movie.gif +Group27File43=C:\apache\icons\p.gif +Group27File44=C:\apache\icons\patch.gif +Group27File45=C:\apache\icons\pdf.gif +Group27File46=C:\apache\icons\pie0.gif +Group27File47=C:\apache\icons\pie1.gif +Group27File48=C:\apache\icons\pie2.gif +Group27File49=C:\apache\icons\pie3.gif +Group27File50=C:\apache\icons\pie4.gif +Group27File51=C:\apache\icons\pie5.gif +Group27File52=C:\apache\icons\pie6.gif +Group27File53=C:\apache\icons\pie7.gif +Group27File54=C:\apache\icons\pie8.gif +Group27File55=C:\apache\icons\portal.gif +Group27File56=C:\apache\icons\ps.gif +Group27File57=C:\apache\icons\quill.gif +Group27File58=C:\apache\icons\README +Group27File59=C:\apache\icons\right.gif +Group27File60=C:\apache\icons\screw1.gif +Group27File61=C:\apache\icons\screw2.gif +Group27File62=C:\apache\icons\script.gif +Group27File63=C:\apache\icons\sound1.gif +Group27File64=C:\apache\icons\sound2.gif +Group27File65=C:\apache\icons\sphere1.gif +Group27File66=C:\apache\icons\sphere2.gif +Group27File67=C:\apache\icons\tar.gif +Group27File68=C:\apache\icons\tex.gif +Group27File69=C:\apache\icons\text.gif +Group27File70=C:\apache\icons\transfer.gif +Group27File71=C:\apache\icons\unknown.gif +Group27File72=C:\apache\icons\up.gif +Group27File73=C:\apache\icons\uu.gif +Group27File74=C:\apache\icons\uuencoded.gif +Group27File75=C:\apache\icons\world1.gif +Group27File76=C:\apache\icons\world2.gif +Group28Size=0 +Group28Files=0 +Group28Name=conf +Group28Dir=\conf +Group28Update=0 +Group28TargetOS=-1 +Group29Size=2326 +Group29Files=1 +Group29Name=htdocs +Group29Dir=\htdocs +Group29Update=0 +Group29TargetOS=-1 +Group29File1=C:\apache\htdocs\apache_pb.gif +Group30Size=0 +Group30Files=0 +Group30Name=cgi-bin +Group30Dir=\cgi-bin +Group30Update=0 +Group30TargetOS=-1 +Group31Size=37002 +Group31Files=2 +Group31Name=installer +Group31Dir=[win32]\installer +Group31Update=0 +Group31TargetOS=-1 +Group31File1=C:\apache\src\os\win32\installer\apache.iwz +Group31File2=C:\apache\src\os\win32\installer\README.TXT +Group32Size=30356 +Group32Files=4 +Group32Name=installdll +Group32Dir=[installer]\installdll +Group32Update=0 +Group32TargetOS=-1 +Group32File1=C:\apache\src\os\win32\installer\installdll\install.c +Group32File2=C:\apache\src\os\win32\installer\installdll\install.def +Group32File3=C:\apache\src\os\win32\installer\installdll\install.dsp +Group32File4=C:\apache\src\os\win32\installer\installdll\install.mak +Group33Size=8247 +Group33Files=33 +Group33Name=small +Group33Dir=[icons]\small +Group33Update=0 +Group33TargetOS=-1 +Group33File1=C:\apache\icons\small\back.gif +Group33File2=C:\apache\icons\small\binary.gif +Group33File3=C:\apache\icons\small\binhex.gif +Group33File4=C:\apache\icons\small\blank.gif +Group33File5=C:\apache\icons\small\broken.gif +Group33File6=C:\apache\icons\small\burst.gif +Group33File7=C:\apache\icons\small\comp1.gif +Group33File8=C:\apache\icons\small\comp2.gif +Group33File9=C:\apache\icons\small\compressed.gif +Group33File10=C:\apache\icons\small\continued.gif +Group33File11=C:\apache\icons\small\dir.gif +Group33File12=C:\apache\icons\small\dir2.gif +Group33File13=C:\apache\icons\small\forward.gif +Group33File14=C:\apache\icons\small\generic.gif +Group33File15=C:\apache\icons\small\generic2.gif +Group33File16=C:\apache\icons\small\generic3.gif +Group33File17=C:\apache\icons\small\image.gif +Group33File18=C:\apache\icons\small\image2.gif +Group33File19=C:\apache\icons\small\index.gif +Group33File20=C:\apache\icons\small\movie.gif +Group33File21=C:\apache\icons\small\rainbow.gif +Group33File22=C:\apache\icons\small\README.txt +Group33File23=C:\apache\icons\small\sound.gif +Group33File24=C:\apache\icons\small\sound2.gif +Group33File25=C:\apache\icons\small\tar.gif +Group33File26=C:\apache\icons\small\text.gif +Group33File27=C:\apache\icons\small\transfer.gif +Group33File28=C:\apache\icons\small\unknown.gif +Group33File29=C:\apache\icons\small\uu.gif +Group33File30=C:\apache\icons\small\key.gif +Group33File31=C:\apache\icons\small\patch.gif +Group33File32=C:\apache\icons\small\ps.gif +Group33File33=C:\apache\icons\small\doc.gif +Group34Size=21478 +Group34Files=8 +Group34Name=test +Group34Dir=[installdll]\test +Group34Update=0 +Group34TargetOS=-1 +Group34File1=C:\apache\src\os\win32\installer\installdll\test\resource.h +Group34File2=C:\apache\src\os\win32\installer\installdll\test\test.c +Group34File3=C:\apache\src\os\win32\installer\installdll\test\test.def +Group34File4=C:\apache\src\os\win32\installer\installdll\test\test.dsp +Group34File5=C:\apache\src\os\win32\installer\installdll\test\test.h +Group34File6=C:\apache\src\os\win32\installer\installdll\test\test.ico +Group34File7=C:\apache\src\os\win32\installer\installdll\test\test.mak +Group34File8=C:\apache\src\os\win32\installer\installdll\test\test.rc +Group35Size=58368 +Group35Files=1 +Group35Name=bin +Group35Dir=\bin +Group35Update=0 +Group35TargetOS=-1 +Group35File1=C:\apache\bin\htpasswd.exe +Group36Size=7223 +Group36Files=1 +Group36Name=search +Group36Dir=[manual]\search +Group36Update=0 +Group36TargetOS=-1 +Group36File1=C:\apache\htdocs\manual\search\manual-index.cgi + +[Sequence] +DestinationLocationDir=\Apache Group\Apache +SelectProgramFolderName=Apache Web Server +LicenseAgreement=1 +LicenseAgreementFile=C:\Apache\LICENSE +ReadMeFileBrowser=1 +ReadMeFileBrowserFile=C:\apache\WARNING-NT.TXT +DestinationLocation=1 +SetupType=1 +CustomSetup=1 +SelectProgramFolder=1 +ProgressBar=1 +SetupComplete=1 +SetupCompleteExec= +SetupCompleteExecParam= +SetupCompleteExecReadme=[Program Executables]\README-NT.TXT + +[RegEntries] +Reg1Path=HKEY_CLASSES_ROOT +Reg1Val1Type=0 +Reg1Val1Name=(Default) +Reg1Val1Data=(value not set) +Reg1Vals=1 +Reg2Path=HKEY_CURRENT_USER +Reg2Val1Type=0 +Reg2Val1Name=(Default) +Reg2Val1Data=(value not set) +Reg2Vals=1 +Reg3Path=HKEY_LOCAL_MACHINE +Reg3Val1Type=0 +Reg3Val1Name=(Default) +Reg3Val1Data=(value not set) +Reg3Vals=1 +Reg4Path=HKEY_USERS +Reg4Val1Type=0 +Reg4Val1Name=(Default) +Reg4Val1Data=(value not set) +Reg4Vals=1 +Reg5Path=HKEY_CURRENT_CONFIG +Reg5Val1Type=0 +Reg5Val1Name=(Default) +Reg5Val1Data=(value not set) +Reg5Vals=1 +Reg6Path=HKEY_DYN_DATA +Reg6Val1Type=0 +Reg6Val1Name=(Default) +Reg6Val1Data=(value not set) +Reg6Vals=1 +Reg7Path=HKEY_LOCAL_MACHINE\SOFTWARE +Reg7Val1Type=0 +Reg7Val1Name=(Default) +Reg7Val1Data=(value not set) +Reg7Vals=1 +Reg8Path=HKEY_LOCAL_MACHINE\SOFTWARE\Apache Group +Reg8Val1Type=0 +Reg8Val1Name=(Default) +Reg8Val1Data=(value not set) +Reg8Vals=1 +Reg9Path=HKEY_LOCAL_MACHINE\SOFTWARE\Apache Group\Apache +Reg9Val1Type=0 +Reg9Val1Name=(Default) +Reg9Val1Data=(value not set) +Reg9Vals=1 +Reg10Path=HKEY_LOCAL_MACHINE\SOFTWARE\Apache Group\Apache\1.3.7 dev +Reg10Val1Type=0 +Reg10Val1Name=(Default) +Reg10Val1Data=(value not set) +Reg10Val2Type=0 +Reg10Val2Name=ServerRoot +Reg10Val2Data= +Reg10Vals=2 +Regs=10 + +[Registry] +Reg1Path=HKEY_LOCAL_MACHINE\SOFTWARE +Reg2Path=HKEY_LOCAL_MACHINE\SOFTWARE\Apache Group +Reg3Path=HKEY_LOCAL_MACHINE\SOFTWARE\Apache Group\Apache +Reg4Path=HKEY_LOCAL_MACHINE\SOFTWARE\Apache Group\Apache\1.3.7 dev +Reg5Path=HKEY_LOCAL_MACHINE\SOFTWARE\Apache Group\Apache\1.3.7 dev +Reg5ValName=ServerRoot +Reg5ValType=0 +Reg5ValData= +Regs=5 + +[Icons] +Icons=5 +Icon1Param=-d "" -s +Icon1Cmd=[Program Executables]\Apache.exe +Icon1Description=Start Apache as console app +Icon1WorkingDir=[Program Executables] +Icon1IconFile=[Program Executables]\Apache.exe +Icon1RealFile=C:\Apache\Apache.exe +Icon1WhichIcon=0 +Icon1KeyVirtual=0 +Icon1KeyFlags=0 +Icon1StartMenu=0 +Icon1Window=0 +Icon2Param= +Icon2Cmd=[Manual]\index.html +Icon2Description=Apache Documentation +Icon2WorkingDir=[Manual] +Icon2IconFile= +Icon2RealFile=C:\Apache\htdocs\manual\index.html +Icon2WhichIcon=0 +Icon2KeyVirtual=0 +Icon2KeyFlags=0 +Icon2StartMenu=0 +Icon2Window=0 +Icon3Param=-d "" -i +Icon3Cmd=[Program Executables]\Apache.exe +Icon3Description=Install Apache as Service (NT only) +Icon3WorkingDir=[Program Executables] +Icon3IconFile= +Icon3RealFile=C:\Apache\Apache.exe +Icon3WhichIcon=0 +Icon3KeyVirtual=0 +Icon3KeyFlags=0 +Icon3StartMenu=0 +Icon3Window=0 +Icon4Param=-d "" -u +Icon4Cmd=[Program Executables]\Apache.exe +Icon4Description=Uninstall Apache Service (NT only) +Icon4WorkingDir=[Program Executables] +Icon4IconFile= +Icon4RealFile=C:\Apache\Apache.exe +Icon4WhichIcon=0 +Icon4KeyVirtual=0 +Icon4KeyFlags=0 +Icon4StartMenu=0 +Icon4Window=0 +Icon5Param=-d "" -k shutdown +Icon5Cmd=[Program Executables]\Apache.exe +Icon5Description=Shutdown Apache console app +Icon5WorkingDir=[Program Executables] +Icon5IconFile= +Icon5RealFile=C:\Apache\Apache.exe +Icon5WhichIcon=0 +Icon5KeyVirtual=0 +Icon5KeyFlags=0 +Icon5StartMenu=0 +Icon5Window=0 + +[VisualBasic] +PRJFile= + +[Ext] +Ext1Dlg=Setup Complete +Ext1Param1=[Installer DLL]\install.dll +Ext1Param2=BeforeExit +Ext1Op=DLL + +[Temp Files] +File1=C:\Apache\install.dll + +[Autoexec] +PathDir= +ShareLocks= +ShareFiles= +Command= + +[CopyToFloppy] +DriveOption=Path for a 1 File Installation. +DestinationPath= +DestinationPathOneFile=C:\ +Password= diff --git a/APACHE_1_3_12/src/os/win32/installer/installdll/install.c b/APACHE_1_3_12/src/os/win32/installer/installdll/install.c new file mode 100644 index 0000000000..39da17a104 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/installer/installdll/install.c @@ -0,0 +1,666 @@ +/* Apache Installer */ + +/* + * 26/06/97 PCS 1.000 Initial version + * 22/02/98 PCS 1.001 Used the excellent NTemacs to apply proper formating + * 04/05/98 PCS 1.002 Copy conf files to *.conf.default, then to *.conf + * 16/02/99 PCS 1.003 Add logging to "install.log" in the installed directory + */ + +#define VERSION ( "1.003 " __DATE__ " " __TIME__ ) + +#include +#include +#include +#include +#include + +#include "conf.h" +#include "ap.h" + +#ifdef strftime +#undef strftime +#endif + +#define AP_WIN32ERROR 1 + +/* Global to store the instance handle */ +HINSTANCE hInstance = NULL; + +static char *szLogFilename = NULL; +static FILE *fpLog = NULL; + +void LogMessage(char *fmt, ...) +{ + char buf[4000]; + va_list ap; + struct tm *tms; + time_t nowtime; + char *bp = buf; + int rv; + int free = sizeof(buf); + + if (!fpLog) { + return; + } + + nowtime = time(NULL); + tms = localtime(&nowtime); + rv = strftime(bp, free, "%c", tms); + bp += rv; + free -= rv; + if (free) { + *bp++ = ' '; + free--; + } + + va_start(ap, fmt); + rv = ap_vsnprintf(bp, free, fmt, ap); + va_end(ap); + + free -= rv; + + fprintf(fpLog, "%s\n", buf); +} + +/* + * MessageBox_error() is a helper function to display an error in a + * message box, optionally including a Win32 error message. If + * the "opt" argument is value AP_WIN32ERROR then get the last Win32 + * error (with GetLastError()) and add it on to the end of + * the output string. The output string is given as a printf-format + * and replacement arguments. The hWnd, title and mb_opt fields are + * passed on to the Win32 MessageBox() call. + */ + +int MessageBox_error(HWND hWnd, int opt, char *title, + int mb_opt, char *fmt, ...) +{ + char buf[1000]; + va_list ap; + int free = sizeof(buf); /* Number of bytes free in the buffer */ + int rv; + char *p; + + va_start(ap, fmt); + rv = ap_vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + + free -= rv; + + if (opt & AP_WIN32ERROR && free > 3) { + /* We checked in the "if" that we have enough space in buf for + * at least three extra characters. + */ + p = buf + strlen(buf); + *p++ = '\r'; + *p++ = '\r'; + *p++ = '('; + free -= 3; + /* NB: buf is now not null terminated */ + + /* Now put the error message straight into buf. This function + * takes the free buffer size as the 6th argument. + */ + rv = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + GetLastError(), + 0, + p, + free, + NULL); + + if (rv == 0) { + /* FormatMessage failed, so get rid of the "\r\r(" we just placed + * in the buffer, since there is no system error message. + */ + p -= 3; + *p = '\0'; + free += 3; + } else { + free -= rv; + p += rv; + + /* Strip any trailing \r or \n characters to make it look nice on + * the screen. + */ + while (*(p-1) == '\r' || *(p-1) == '\n') + p--, free++; + *p = '\0'; + + /* Append a trailing ) */ + if (free >= 1) { + *p++ = ')'; + *p++ = '\0'; + } + } + } + + for (p = buf; *p; p++) { + if (*p == '\n' || *p == '\r') { + *p = ' '; + } + } + LogMessage("MSG %s", buf); + + return MessageBox(hWnd, buf, title, mb_opt); +} + +int OpenLog(HWND hwnd, char *dir, char *fn) +{ + szLogFilename = malloc(strlen(dir) + 1 + strlen(fn) + 1); + sprintf(szLogFilename, "%s\\%s", dir, fn); + + if ((fpLog = fopen(szLogFilename, "a+")) == NULL) { + MessageBox_error(hwnd, + AP_WIN32ERROR, + "Installation Problem", + MB_OK | MB_ICONSTOP, + "Cannot open log file %s", szLogFilename); + return -1; + } + return 0; +} + +void CloseLog(void) +{ + if (fpLog) { + fclose(fpLog); + } +} + +/* + * The next few functions handle expanding the @@ServerRoot@@ type + * sequences found in the distribution files. The main entry point + * is expandFile(), which is given a file to expand and the filename + * to write the expanded file it. It reads a line at a time, and + * if the line includes an "@@" sequence, calls expandLine() to + * expand the sequences. + * + * expandLine() looks for @@ sequences in the line, and when it finds + * one, looks for a corresponding entry in the replaceTable[]. If it + * finds one it writes the replacement value from the table into + * an output string. + * + * The helper function appendText() is used when expanding strings. It + * is called to copy text into an output buffer. If the output buffer + * is not big enough, it is expanded. This function also ensures that + * the output buffer is null terminated after each append operation. + * + * A table is used of values to replace, rather than just hardcoding + * the functionality, so we could replace additional values in the + * future. We also take care to ensure that the expanded line can be + * arbitrary length (though at the moment the lines read from the + * configuration files can only be up to 2000 characters). + */ + +/* + * Table of items to replace. The "value" elements are filled in at runtime + * by FillInReplaceTable(). Note that the "tmpl" element is case + * sensitive. + */ + +typedef struct { + char *tmpl; + char *value; +} REPLACEITEM; +typedef REPLACEITEM *REPLACETABLE; + +REPLACEITEM replaceHttpd[] = { + { "@@ServerRoot@@", NULL }, /* ServerRoot directory (i.e. install dir) */ + { NULL, NULL } +}; + +/* + * A relatively intelligent version of strcat, that expands the destination + * buffer if needed. + * + * On entry, ppBuf points to the output buffer, pnPos points to the offset + * of the current position within that buffer, and pnSize points to the + * current size of *ppBuf. pSrc points to the string to copy into the buffer, + * and nToCopy gives the number of characters to copy from pSrc. + * + * On exit, *ppBuf, *pnPos and *pnSize may have been updated if the output + * buffer needed to be expanded. The output buffer will be null terminated. + * Returns 0 on success, -1 on error. Does not report errors to the user. + */ + +int appendText(char **ppBuf, int *pnPos, int *pnSize, char *pSrc, int nToCopy) +{ + char *pBuf = *ppBuf; /* output buffer */ + int nPos = *pnPos; /* current offset into pBuf */ + int nSize = *pnSize; /* current size of pBuf */ + + while (nPos + nToCopy >= nSize) { + /* Not enough space, double size of output buffer. Note we use + * >= not > so that we have enough space for the NULL character + * in the output buffer */ + char *pBufNew; + + pBufNew = realloc(pBuf, nSize * 2); + if (!pBufNew) + return -1; + nSize *= 2; + + /* Update the max size and buffer pointer */ + *pnSize = nSize; + *ppBuf = pBuf = pBufNew; + } + + /* Ok, now we have enough space, copy the stuff */ + + strncpy(pBuf+nPos, pSrc, nToCopy); + nPos += nToCopy; + *pnPos = nPos; /* update current position */ + pBuf[nPos] = '\0'; /* append trailing NULL */ + + return 0; +} + +/* + * Expand all the sequences in an input line. Returns a pointer to the + * expanded line. The caller should free the returned data. + * The replaceTable argument is a table of sequences to expand. + * + * Returns NULL on error. Does not report errors to the user. + */ + +char *expandLine(char *in, REPLACETABLE replaceTable) +{ + REPLACEITEM *item; + char *pos; /* current position in input buffer */ + char *outbuf; /* output buffer */ + int outbuf_size; /* current size of output buffer */ + int outbuf_position; /* current position in output buffer */ + char *start; /* position to copy from in input buffer */ + + /* Create an initial output buffer. Guess that twice the input size + * is a good length, after expansion. Don't worry if we need more + * though, appendText() will expand as needed. + */ + outbuf_size = strlen(in) * 2; + outbuf_position = 0; + outbuf = malloc(outbuf_size); + if (!outbuf) + return NULL; + + start = in; /* mark the start of uncopied data */ + pos = in; /* current position in input buffer */ + + while (1) { + + /* Look for '@@' sequence, or end of input */ + if (*pos && !(*pos == '@' && *(pos+1) == '@')) { + pos++; + continue; + } + + if (!*pos) { + /* End of input string, copy the uncopied data */ + if (appendText(&outbuf, &outbuf_position, &outbuf_size, + start, pos-start) < 0) { + return NULL; + } + break; + } + + /* Found first @ of a possible token to replace. Look for end + * of the token + */ + for (item = replaceTable; item->tmpl; ++item) { + if (!strncmp(pos, item->tmpl, strlen(item->tmpl))) + break; + } + + if (item->tmpl) { + /* Found match. First copy the uncopied data from the input + * buffer (start through to pos-1), then copy the expanded + * value. */ + if (appendText(&outbuf, &outbuf_position, &outbuf_size, + start, pos-start) < 0) { + return NULL; + } + if (appendText(&outbuf, &outbuf_position, &outbuf_size, + item->value, strlen(item->value)) < 0) { + return NULL; + } + + /* Update current position to skip over the input buffer + * @@...@@ sequence, and update the "start" pointer to uncopied + * data + */ + pos += strlen(item->tmpl); + start = pos; + } + else { + /* The sequence did not exist in the replace table, so copy + * it as-is to the output. + */ + pos++; + } + } + + return outbuf; +} + +/* + * Some options to determine how we copy a file. Apart from OPT_NONE, these should + * be OR'able + */ + +typedef enum { + OPT_NONE = 0, + OPT_OVERWRITE = 1, /* Always overwrite destination file */ + OPT_EXPAND = 2, /* Expand any @@...@@ tokens in replaceHttpd */ + OPT_DELETESOURCE = 4, /* Delete the source file after the copy */ + OPT_SILENT = 8, /* Don't tell use about failures */ +} options_t; + +/* + * Copy a file, expanding sequences from the replaceTable argument. + * Returns 0 on success, -1 on error. Reports errors to user. + */ +#define MAX_INPUT_LINE 2000 +int WINAPI ExpandConfFile(HWND hwnd, LPSTR szInst, LPSTR szinFile, LPSTR szoutFile, REPLACETABLE replaceTable, options_t options) +{ + char inFile[_MAX_PATH]; + char outFile[_MAX_PATH]; + char inbuf[MAX_INPUT_LINE]; + FILE *infp; + FILE *outfp; + + ap_snprintf(inFile, sizeof(inFile), "%s\\%s", szInst, szinFile); + ap_snprintf(outFile, sizeof(outFile), "%s\\%s", szInst, szoutFile); + + if (!(infp = fopen(inFile, "r"))) { + MessageBox_error(hwnd, + AP_WIN32ERROR, + "Installation Problem", + MB_OK | MB_ICONSTOP, + "Cannot read file %s", inFile); + return -1; + } + if (! (options & OPT_OVERWRITE)) { + /* Overwrite not allowed if file does not exist */ + if ((outfp = fopen(outFile, "r"))) { + if (! (options & OPT_SILENT)) { + MessageBox_error(hwnd, + 0, + "File not overwritten", + MB_OK | MB_ICONWARNING, + "Preserving existing file %s.\r\r" + "The new version of this file has been left in %s", + outFile, inFile); + } + fclose(outfp); + fclose(infp); + return 0; + } + /* To get here, output file does not exist */ + } + if (!(outfp = fopen(outFile, "w"))) { + MessageBox_error(hwnd, + AP_WIN32ERROR, + "Installation Problem", + MB_OK | MB_ICONSTOP, + "Cannot write to file %s", outFile); + fclose(infp); + return -1; + } + + while (fgets(inbuf, MAX_INPUT_LINE, infp)) { + char *pos; + char *outbuf; + + /* Quickly look to see if this line contains any + * @@ tokens. If it doesn't, we don't need to bother + * called expandLine() or taking a copy of the input + * buffer. + */ + if (options & OPT_EXPAND) { + for (pos = inbuf; *pos; ++pos) + if (*pos == '@' && *(pos+1) == '@') + break; + } + + if (options & OPT_EXPAND && *pos) { + /* The input line contains at least one '@@' sequence, so + * call expandLine() to expand any sequences we know about. + */ + outbuf = expandLine(inbuf, replaceTable); + if (outbuf == NULL) { + fclose(infp); + fclose(outfp); + MessageBox_error(hwnd, + 0, + "Installation Problem", + MB_OK|MB_ICONSTOP, + "An error occurred during installation"); + return -1; + } + } + else { + outbuf = NULL; + } + + /* If outbuf is NULL, we did not need to expand sequences, so + * just output the contents of the input buffer. + */ + fwrite(outbuf ? outbuf : inbuf, 1, + strlen(outbuf ? outbuf : inbuf), outfp); + + if (outbuf) + free(outbuf); + } + fclose(infp); + fclose(outfp); + + LogMessage("COPY: expanded %s to %s", inFile, outFile); + + if (options & OPT_DELETESOURCE) { + unlink(inFile); + LogMessage("COPY: deleted file %s", inFile); + } + + return 0; +} + +int FillInReplaceTable(HWND hwnd, REPLACETABLE table, char *szInst) +{ + REPLACEITEM *item; + for (item = table; item->tmpl; ++item) { + if (!strcmp(item->tmpl, "@@ServerRoot@@")) { + char *p; + +#if NEED_SHORT_PATHS + int len; + len = GetShortPathName(szInst, NULL, 0); + if (len > 0) { + item->value = (char*)malloc(len+1); + GetShortPathName(szInst, item->value, len); + } +#else + if ((item->value = strdup(szInst)) == NULL) + return -1; +#endif + for (p = item->value; *p; p++) + if (*p == '\\') *p = '/'; + + LogMessage("FillInReplaceTable tmpl=%s value=%s", item->tmpl, item->value); + + continue; + } +#if NEED_FQDN + if (!strcmp(item->tmpl, "FQDN")) { + item->value = GetHostName(hwnd); + continue; + } +#endif + } + return 0; +} + +/* + * actionTable[] contains things we do when this DLL is called by InstallShield + * during the install. It is like a simple script, without us having to + * worry about parsing, error checking, etc. + * + * Each item in the table is of type ACTIONITEM. The first element is the action + * to perform (e.g. CMD_COPY). The second and third elements are filenames + * (e.g. for CMD_COPY, the first filename is the source and the second filename + * is the destination). The final element of ACTIONITEM is a set of options + * which apply to the current "command". For example, OPT_EXPAND on a CMD_COPY + * line, tells the copy function to expand @@ServerRoot@@ tokens found in the + * source file. + * + * The contents of this table are performed in order, top to bottom. This lets + * us expand the files to the *.conf.default names, then copy to *.conf only + * if the corresponding *.conf file does not already exist. If it does exist, + * it is not overwritten. + * + * Return 1 on success, 0 on error. + */ + +typedef enum { + CMD_COPY = 0, + CMD_RMDIR, + CMD_RM, + CMD_END +} cmd_t; + +typedef struct { + cmd_t command; + char *in; + char *out; + options_t options; +} ACTIONITEM; +typedef ACTIONITEM *ACTIONTABLE; + +ACTIONITEM actionTable[] = { + /* + * Installation of the configuraton files. These are installed into the ".tmp" + * directory by the installer. We first move them to conf\*.default (overwriting + * any *.default file from a previous install). The *.conf-dist-win files + * are also expanded for any @@...@@ tokens. Then we copy the conf\*.default + * file to corresponding conf\* file, unless that would overwrite an existing file. + */ + { CMD_COPY, ".tmp\\mime.types", "conf\\mime.types.default", + OPT_OVERWRITE|OPT_DELETESOURCE }, + { CMD_COPY, ".tmp\\magic", "conf\\magic.default", + OPT_OVERWRITE|OPT_DELETESOURCE }, + { CMD_COPY, ".tmp\\httpd.conf-dist-win", "conf\\httpd.conf.default", + OPT_OVERWRITE|OPT_EXPAND|OPT_DELETESOURCE }, + { CMD_COPY, ".tmp\\srm.conf-dist-win", "conf\\srm.conf.default", + OPT_OVERWRITE|OPT_EXPAND|OPT_DELETESOURCE }, + { CMD_COPY, ".tmp\\access.conf-dist-win", "conf\\access.conf.default", + OPT_OVERWRITE|OPT_EXPAND|OPT_DELETESOURCE }, + + /* Now copy to the 'live' files, unless they already exist */ + { CMD_COPY, "conf\\httpd.conf.default", "conf\\httpd.conf", OPT_NONE }, + { CMD_COPY, "conf\\srm.conf.default", "conf\\srm.conf", OPT_NONE }, + { CMD_COPY, "conf\\access.conf.default", "conf\\access.conf", OPT_NONE }, + { CMD_COPY, "conf\\magic.default", "conf\\magic", OPT_NONE }, + { CMD_COPY, "conf\\mime.types.default", "conf\\mime.types", OPT_NONE }, + + { CMD_COPY, ".tmp\\highperformance.conf-dist", "conf\\highperformance.conf-dist", + OPT_EXPAND|OPT_OVERWRITE|OPT_DELETESOURCE }, + + { CMD_RMDIR, ".tmp", NULL }, + + { CMD_END, NULL, NULL, OPT_NONE } +}; + +/* + * BeforeExit() is the DLL call from InstallShield. The arguments and + * return value as defined by the installer. We are only interested + * in the install directory, szInst. Return 0 on error and 1 on + * success (!?). + */ + +CHAR WINAPI BeforeExit(HWND hwnd, LPSTR szSrcDir, LPSTR szSupport, LPSTR szInst, LPSTR szRes) +{ + ACTIONITEM *pactionItem; + int end = 0; + + OpenLog(hwnd, szInst, "install.log"); + LogMessage("STARTED %s", VERSION); + LogMessage("src=%s support=%s inst=%s", + szSrcDir, szSupport, szInst); + + FillInReplaceTable(hwnd, replaceHttpd, szInst); + + pactionItem = actionTable; + while (!end) { + + LogMessage("command=%d 1in=%s out=%s options=%d", + pactionItem->command, + pactionItem->in ? pactionItem->in : "NULL", + pactionItem->out ? pactionItem->out : "NULL", + pactionItem->options); + + switch(pactionItem->command) { + case CMD_END: + end = 1; + break; + case CMD_COPY: + if (ExpandConfFile(hwnd, szInst, + pactionItem->in, + pactionItem->out, + replaceHttpd, + pactionItem->options) < 0) { + /* Error has already been reported to the user */ + return 0; + } + break; + case CMD_RM: { + char inFile[MAX_INPUT_LINE]; + + ap_snprintf(inFile, sizeof(inFile), "%s\\%s", szInst, pactionItem->in); + if (unlink(inFile) < 0 && !(pactionItem->options & OPT_SILENT)) { + MessageBox_error(hwnd, AP_WIN32ERROR, "Error during configuration", + MB_ICONHAND, + "Could not remove file %s", + inFile); + return 0; + } + LogMessage("RM: deleted file %s", inFile); + break; + } + case CMD_RMDIR: { + char inFile[MAX_INPUT_LINE]; + + ap_snprintf(inFile, sizeof(inFile), "%s\\%s", szInst, pactionItem->in); + if (rmdir(inFile) < 0) { + MessageBox_error(hwnd, AP_WIN32ERROR, "Error during configuration", + MB_ICONHAND, + "Could not delete temporary directory %s", + inFile); + return 0; + } + LogMessage("RMDIR: deleted directory %s", inFile); + break; + } + default: + MessageBox_error(hwnd, 0, "Error during configuration", + MB_ICONHAND, + "An error has occurred during configuration\r" + "(Error: unknown command %d)", (int)pactionItem->command); + end = 1; + break; + } + pactionItem++; + } + + LogMessage("FINISHED OK"); + CloseLog(); + + return 1; +} + + +BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + if (fdwReason == DLL_PROCESS_ATTACH) + hInstance = hInstDLL; + return TRUE; +} diff --git a/APACHE_1_3_12/src/os/win32/installer/installdll/install.def b/APACHE_1_3_12/src/os/win32/installer/installdll/install.def new file mode 100644 index 0000000000..aae6ded275 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/installer/installdll/install.def @@ -0,0 +1,6 @@ +LIBRARY INSTALL +DESCRIPTION 'Installer DLL For Apache' + +EXPORTS + BeforeExit @1 + DllMain @2 diff --git a/APACHE_1_3_12/src/os/win32/installer/installdll/install.dsp b/APACHE_1_3_12/src/os/win32/installer/installdll/install.dsp new file mode 100644 index 0000000000..9c33d71a78 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/installer/installdll/install.dsp @@ -0,0 +1,107 @@ +# Microsoft Developer Studio Project File - Name="install" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=install - 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 "install.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 "install.mak" CFG="install - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "install - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "install - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "install - 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 /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../../../include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /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 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 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 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib wsock32.lib /nologo /subsystem:windows /dll /machine:I386 + +!ELSEIF "$(CFG)" == "install - 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 /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "../../../../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /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 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 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 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib wsock32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "install - Win32 Release" +# Name "install - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\..\ap\ap_snprintf.c +# End Source File +# Begin Source File + +SOURCE=.\install.c +# End Source File +# Begin Source File + +SOURCE=.\install.def +# End Source File +# End Group +# End Target +# End Project diff --git a/APACHE_1_3_12/src/os/win32/installer/installdll/install.mak b/APACHE_1_3_12/src/os/win32/installer/installdll/install.mak new file mode 100644 index 0000000000..65d7608ba5 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/installer/installdll/install.mak @@ -0,0 +1,297 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on install.dsp +!IF "$(CFG)" == "" +CFG=install - Win32 Debug +!MESSAGE No configuration specified. Defaulting to install - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "install - Win32 Release" && "$(CFG)" !=\ + "install - 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 "install.mak" CFG="install - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "install - Win32 Release" (based on\ + "Win32 (x86) Dynamic-Link Library") +!MESSAGE "install - 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)" == "install - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\install.dll" + +!ELSE + +ALL : "$(OUTDIR)\install.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\ap_snprintf.obj" + -@erase "$(INTDIR)\install.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\install.dll" + -@erase "$(OUTDIR)\install.exp" + -@erase "$(OUTDIR)\install.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MT /W3 /GX /O2 /I "../../../../include" /D "WIN32" /D\ + "NDEBUG" /D "_WINDOWS" /Fp"$(INTDIR)\install.pch" /YX /Fo"$(INTDIR)\\"\ + /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\Release/ +CPP_SBRS=. + +.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) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o NUL /win32 +RSC=rc.exe +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\install.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib wsock32.lib /nologo /subsystem:windows /dll\ + /incremental:no /pdb:"$(OUTDIR)\install.pdb" /machine:I386 /def:".\install.def"\ + /out:"$(OUTDIR)\install.dll" /implib:"$(OUTDIR)\install.lib" +DEF_FILE= \ + ".\install.def" +LINK32_OBJS= \ + "$(INTDIR)\ap_snprintf.obj" \ + "$(INTDIR)\install.obj" + +"$(OUTDIR)\install.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "install - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\install.dll" + +!ELSE + +ALL : "$(OUTDIR)\install.dll" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\ap_snprintf.obj" + -@erase "$(INTDIR)\install.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\install.dll" + -@erase "$(OUTDIR)\install.exp" + -@erase "$(OUTDIR)\install.ilk" + -@erase "$(OUTDIR)\install.lib" + -@erase "$(OUTDIR)\install.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MTd /W3 /Gm /GX /Zi /Od /I "../../../../include" /D "WIN32"\ + /D "_DEBUG" /D "_WINDOWS" /Fp"$(INTDIR)\install.pch" /YX /Fo"$(INTDIR)\\"\ + /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\Debug/ +CPP_SBRS=. + +.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) $< +<< + +MTL=midl.exe +MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o NUL /win32 +RSC=rc.exe +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\install.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib wsock32.lib /nologo /subsystem:windows /dll\ + /incremental:yes /pdb:"$(OUTDIR)\install.pdb" /debug /machine:I386\ + /def:".\install.def" /out:"$(OUTDIR)\install.dll"\ + /implib:"$(OUTDIR)\install.lib" /pdbtype:sept +DEF_FILE= \ + ".\install.def" +LINK32_OBJS= \ + "$(INTDIR)\ap_snprintf.obj" \ + "$(INTDIR)\install.obj" + +"$(OUTDIR)\install.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + + +!IF "$(CFG)" == "install - Win32 Release" || "$(CFG)" ==\ + "install - Win32 Debug" +SOURCE=..\..\..\..\ap\ap_snprintf.c + +!IF "$(CFG)" == "install - Win32 Release" + +DEP_CPP_AP_SN=\ + "..\..\..\..\include\alloc.h"\ + "..\..\..\..\include\ap.h"\ + "..\..\..\..\include\ap_config.h"\ + "..\..\..\..\include\ap_ctype.h"\ + "..\..\..\..\include\ap_mmn.h"\ + "..\..\..\..\include\buff.h"\ + "..\..\..\..\include\hsregex.h"\ + "..\..\..\..\include\httpd.h"\ + "..\..\..\..\include\util_uri.h"\ + "..\..\os.h"\ + "..\..\readdir.h"\ + + +"$(INTDIR)\ap_snprintf.obj" : $(SOURCE) $(DEP_CPP_AP_SN) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "install - Win32 Debug" + +DEP_CPP_AP_SN=\ + "..\..\..\..\include\alloc.h"\ + "..\..\..\..\include\ap.h"\ + "..\..\..\..\include\ap_config.h"\ + "..\..\..\..\include\ap_ctype.h"\ + "..\..\..\..\include\ap_mmn.h"\ + "..\..\..\..\include\buff.h"\ + "..\..\..\..\include\hsregex.h"\ + "..\..\..\..\include\httpd.h"\ + "..\..\..\..\include\util_uri.h"\ + "..\..\os.h"\ + "..\..\readdir.h"\ + + +"$(INTDIR)\ap_snprintf.obj" : $(SOURCE) $(DEP_CPP_AP_SN) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\install.c + +!IF "$(CFG)" == "install - Win32 Release" + +DEP_CPP_INSTA=\ + "..\..\..\..\include\ap.h"\ + "..\..\..\..\include\ap_config.h"\ + "..\..\..\..\include\ap_ctype.h"\ + "..\..\..\..\include\ap_mmn.h"\ + "..\..\..\..\include\conf.h"\ + "..\..\..\..\include\hsregex.h"\ + "..\..\os.h"\ + + +"$(INTDIR)\install.obj" : $(SOURCE) $(DEP_CPP_INSTA) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "install - Win32 Debug" + +DEP_CPP_INSTA=\ + "..\..\..\..\include\ap.h"\ + "..\..\..\..\include\ap_config.h"\ + "..\..\..\..\include\ap_ctype.h"\ + "..\..\..\..\include\ap_mmn.h"\ + "..\..\..\..\include\conf.h"\ + "..\..\..\..\include\hsregex.h"\ + "..\..\os.h"\ + + +"$(INTDIR)\install.obj" : $(SOURCE) $(DEP_CPP_INSTA) "$(INTDIR)" + + +!ENDIF + + +!ENDIF + diff --git a/APACHE_1_3_12/src/os/win32/installer/installdll/test/resource.h b/APACHE_1_3_12/src/os/win32/installer/installdll/test/resource.h new file mode 100644 index 0000000000..6d1f9d8b4e --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/installer/installdll/test/resource.h @@ -0,0 +1,26 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by test.rc +// +#define IDM_TEST 102 +#define IDI_TEST 106 +#define IDM_EXIT 106 +#define IDD_ABOUT 107 +#define IDD_SETDIRECTORY 109 +#define IDM_ABOUT 303 +#define IDC_DIRECTORY 1000 +#define IDM_BEFOREEXIT 40001 +#define IDM_CONFIGURE 40001 +#define IDC_STATIC -1 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 110 +#define _APS_NEXT_COMMAND_VALUE 40002 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/APACHE_1_3_12/src/os/win32/installer/installdll/test/test.c b/APACHE_1_3_12/src/os/win32/installer/installdll/test/test.c new file mode 100644 index 0000000000..8a595094ba --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/installer/installdll/test/test.c @@ -0,0 +1,269 @@ +/* + * Tester for the Apache Install DLL + */ + +#include +#include + +#include "test.h" + +#define APPNAME "Test" + +HINSTANCE hInst; // current instance +char szAppName[100]; // Name of the app +char szTitle[100]; // The title bar text + +// This is imported from the Apache INSTALL.DLL +extern CHAR WINAPI BeforeExit(HWND, LPSTR,LPSTR,LPSTR,LPSTR); + +BOOL InitApplication(HINSTANCE); +BOOL InitInstance(HINSTANCE, int); +BOOL CenterWindow (HWND hwndChild, HWND hwndParent); +LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK SetDirectory(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); + +char szInstDir[MAX_PATH]; + +int APIENTRY WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) +{ + MSG msg; + HANDLE hAccelTable; + + lstrcpy (szAppName, APPNAME); + lstrcpy (szTitle, APPNAME); + + getcwd(szInstDir, sizeof(szInstDir)); + + if (!hPrevInstance) { + if (!InitApplication(hInstance)) { + return (FALSE); + } + } + + if (!InitInstance(hInstance, nCmdShow)) { + return (FALSE); + } + + hAccelTable = LoadAccelerators (hInstance, szAppName); + + while (GetMessage(&msg, NULL, 0, 0)) { + if (!TranslateAccelerator (msg.hwnd, hAccelTable, &msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + return (msg.wParam); + + lpCmdLine; // This will prevent 'unused formal parameter' warnings +} + +BOOL InitApplication(HINSTANCE hInstance) +{ + WNDCLASS wc; + HWND hwnd; + + hwnd = FindWindow (szAppName, szTitle); + + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = (WNDPROC)WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(IDI_TEST)); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wc.lpszMenuName = MAKEINTRESOURCE(IDM_TEST); + wc.lpszClassName = szAppName; + + return RegisterClass(&wc); +} + +BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) +{ + HWND hWnd; + + hInst = hInstance; + + hWnd = CreateWindow(szAppName, szTitle, WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, // x + 0, // y + 400, // width + 100, // height + NULL, // parent + NULL, // menu + hInstance, // instance handle + NULL); + + if (!hWnd) { + return (FALSE); + } + + ShowWindow(hWnd, nCmdShow); + UpdateWindow(hWnd); + + return (TRUE); +} + +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + int wmId, wmEvent; + + switch (message) { + + case WM_COMMAND: + wmId = LOWORD(wParam); + wmEvent = HIWORD(wParam); + + switch (wmId) { + + case IDM_ABOUT: + DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUT), hWnd, (DLGPROC)About); + break; + + case IDM_CONFIGURE: + { + int rc; + + if (DialogBox(hInst, MAKEINTRESOURCE(IDD_SETDIRECTORY), hWnd, (DLGPROC)SetDirectory) == FALSE) + break; + rc = BeforeExit(hWnd, szInstDir, szInstDir, szInstDir, NULL); + if (rc == 1) { + MessageBox(hWnd, "Configuration successful", + "Configuration successful", + MB_OK); + } + break; + } + case IDM_EXIT: + DestroyWindow (hWnd); + break; + + default: + return (DefWindowProc(hWnd, message, wParam, lParam)); + } + break; + + case WM_DESTROY: + PostQuitMessage(0); + break; + + default: + return (DefWindowProc(hWnd, message, wParam, lParam)); + } + return (0); +} + +LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + + switch (message) { + case WM_INITDIALOG: + CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER)); + return (TRUE); + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { + EndDialog(hDlg, TRUE); + return (TRUE); + } + break; + } + + return FALSE; +} + +LRESULT CALLBACK SetDirectory(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + + switch (message) { + case WM_INITDIALOG: + CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER)); + + SetDlgItemText(hDlg, IDC_DIRECTORY, szInstDir); + //SetFocus(GetDlgItem(hDlg, IDC_DIRECTORY)); + return (TRUE); + + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDCANCEL: + EndDialog(hDlg, FALSE); + return TRUE; + case IDOK: + GetDlgItemText(hDlg, IDC_DIRECTORY, szInstDir, sizeof(szInstDir)); + EndDialog(hDlg, TRUE); + return TRUE; + } + break; + } + + return FALSE; +} + +// +// FUNCTION: CenterWindow(HWND, HWND) +// +// PURPOSE: Centers one window over another. +// +// COMMENTS: +// +// In this function, we save the instance handle in a global variable and +// create and display the main program window. +// +// This functionwill center one window over another ensuring that +// the placement of the window is within the 'working area', meaning +// that it is both within the display limits of the screen, and not +// obscured by the tray or other framing elements of the desktop. +BOOL CenterWindow (HWND hwndChild, HWND hwndParent) +{ + RECT rChild, rParent, rWorkArea; + int wChild, hChild, wParent, hParent; + int xNew, yNew; + BOOL bResult; + + // Get the Height and Width of the child window + GetWindowRect (hwndChild, &rChild); + wChild = rChild.right - rChild.left; + hChild = rChild.bottom - rChild.top; + + // Get the Height and Width of the parent window + GetWindowRect (hwndParent, &rParent); + wParent = rParent.right - rParent.left; + hParent = rParent.bottom - rParent.top; + + // Get the limits of the 'workarea' + bResult = SystemParametersInfo( + SPI_GETWORKAREA, // system parameter to query or set + sizeof(RECT), + &rWorkArea, + 0); + if (!bResult) { + rWorkArea.left = rWorkArea.top = 0; + rWorkArea.right = GetSystemMetrics(SM_CXSCREEN); + rWorkArea.bottom = GetSystemMetrics(SM_CYSCREEN); + } + + // Calculate new X position, then adjust for workarea + xNew = rParent.left + ((wParent - wChild) /2); + if (xNew < rWorkArea.left) { + xNew = rWorkArea.left; + } else if ((xNew+wChild) > rWorkArea.right) { + xNew = rWorkArea.right - wChild; + } + + // Calculate new Y position, then adjust for workarea + yNew = rParent.top + ((hParent - hChild) /2); + if (yNew < rWorkArea.top) { + yNew = rWorkArea.top; + } else if ((yNew+hChild) > rWorkArea.bottom) { + yNew = rWorkArea.bottom - hChild; + } + + // Set it, and return + return SetWindowPos (hwndChild, NULL, xNew, yNew, 0, 0, SWP_NOSIZE | SWP_NOZORDER); +} + diff --git a/APACHE_1_3_12/src/os/win32/installer/installdll/test/test.def b/APACHE_1_3_12/src/os/win32/installer/installdll/test/test.def new file mode 100644 index 0000000000..30ab5c666c --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/installer/installdll/test/test.def @@ -0,0 +1,2 @@ +NAME Test +DESCRIPTION 'Test Installer DLL' diff --git a/APACHE_1_3_12/src/os/win32/installer/installdll/test/test.dsp b/APACHE_1_3_12/src/os/win32/installer/installdll/test/test.dsp new file mode 100644 index 0000000000..9ce6921ae3 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/installer/installdll/test/test.dsp @@ -0,0 +1,121 @@ +# Microsoft Developer Studio Project File - Name="test" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=test - 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 "test.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 "test.mak" CFG="test - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "test - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "test - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "test - 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 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /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 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 winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 ..\Release\install.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows /machine:I386 + +!ELSEIF "$(CFG)" == "test - 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 /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /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 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 winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 ..\Debug\install.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "test - Win32 Release" +# Name "test - Win32 Debug" +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# Begin Source File + +SOURCE=.\test.c +# End Source File +# Begin Source File + +SOURCE=.\test.def +# End Source File +# Begin Source File + +SOURCE=.\test.h +# End Source File +# Begin Source File + +SOURCE=.\test.ico +# End Source File +# Begin Source File + +SOURCE=.\test.rc + +!IF "$(CFG)" == "test - Win32 Release" + +!ELSEIF "$(CFG)" == "test - Win32 Debug" + +!ENDIF + +# End Source File +# End Target +# End Project diff --git a/APACHE_1_3_12/src/os/win32/installer/installdll/test/test.h b/APACHE_1_3_12/src/os/win32/installer/installdll/test/test.h new file mode 100644 index 0000000000..93a871ff59 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/installer/installdll/test/test.h @@ -0,0 +1,4 @@ +#include "resource.h" + + + diff --git a/APACHE_1_3_12/src/os/win32/installer/installdll/test/test.ico b/APACHE_1_3_12/src/os/win32/installer/installdll/test/test.ico new file mode 100644 index 0000000000000000000000000000000000000000..0011934f782320bd4289a914cef8713d8a0fd8d1 GIT binary patch literal 766 zcmc&yyAi`643%?fd@h_Swabi=g2r1h0)-p)NJrywQfdR`Nj?lFxl55E0-@h~0_#lF zVNKJ8RGufIE9?zALGRFx&NzuYYM;fUh>G`{!3mevb%oV}*d`J6pjevH_-7fl)hO7) z+6>lQ1XXN7j`iv{JgB)|@p*f_^;h@10HwXNa7r. + * + */ + +/* + * mod_dll.c - DLL module loader for Windows + * by Alexei Kosut, based on mod_dld.c by rst + * + * This module loads another module into the server that has been + * compiled as a DLL. It doesn't work perfectly, but well enough. + * + * To use, compile the module into a DLL. Then add the following to the + * server's config file (before any directives belonging to the loaded module): + * + * LoadModule module_name mod_name.dll + * + * module_name should be the name of the module (e.g. includes_module), + * and mod_name.dll should be the name of the DLL, relative to the server + * root. + * + * There is also a directive that will load a non-module DLL, if you'd + * like to load additional libraries into the server: + * + * LoadFile filename.dll + * + * Compiling a module as a DLL (using Microsoft Visual C++): + * + * 1. Add the following to the module source file's module record + * definition: MODULE_VAR_EXPORT. i.e. if you have + * "module foo_module;", replace it with + * "module MODULE_VAR_EXPORT foo_module;". If your module is to be + * compiled with both Windows and Unix, you may wish to use an #ifdef + * WIN32 + * + * Note that your module should still work just fine compiled-in + * with this code bit there. It only activates when using the module + * as a DLL. + * + * 2. Create a DLL file with just the module source file (and any associated + * files). Be sure to link it against the ApacheCore.lib created when + * compiling ApacheCore.dll. You may also have to tweak the settings to + * find all of the Apache includes files correctly. After creating the + * DLL, follow the above instructions to load it into Apache. + */ + +#include "httpd.h" +#include "http_config.h" + +/* + * The hard part of implementing LoadModule is deciding what to do about + * rereading the config files. This proof-of-concept implementation takes the + * cheap way out: we only actually load the modules the first time through. + */ + +static int been_there_done_that = 0; /* Loaded the modules yet? */ +static int have_symbol_table = 0; + +char *load_module (cmd_parms *cmd, void *dummy, char *modname, char *filename) +{ + HINSTANCE modhandle; + module *modp; + const char *szModuleFile=ap_server_root_relative(cmd->pool, filename); + + if (been_there_done_that) return NULL; + + if (!(modhandle = LoadLibraryEx(szModuleFile, NULL, + LOAD_WITH_ALTERED_SEARCH_PATH))) + return ap_pstrcat (cmd->pool, "Cannot load ", szModuleFile, " into server", + NULL); + + /* If I knew what the correct cast is here, I'd be happy. But + * I don't. So I'll use (void *). It works. + */ + if (!(modp = (module *)(GetProcAddress (modhandle, modname)))) { + return ap_pstrcat (cmd->pool, "Can't find module ", modname, + " in file ", filename, NULL); + } + + ap_add_module (modp); + + /* Alethea Patch (rws,djw2) - need to run configuration functions + in new modules */ + + 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; +} + +char *load_file (cmd_parms *cmd, void *dummy, char *filename) +{ + if (been_there_done_that) return NULL; + + if (!LoadLibrary(ap_server_root_relative(cmd->pool, filename))) + 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 dll_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 dll_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 */ + dll_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_12/src/os/win32/mod_isapi.c b/APACHE_1_3_12/src/os/win32/mod_isapi.c new file mode 100644 index 0000000000..f5e48a6a7d --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/mod_isapi.c @@ -0,0 +1,569 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * mod_isapi.c - Internet Server Application (ISA) module for Apache + * by Alexei Kosut + * + * 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. + */ + +#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" + +/* We use the exact same header file as the original */ +#include + +/* 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 + +module isapi_module; + +/* 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; + int retval; + + /* 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; + + /* Load the module */ + + if (!(isapi_handle = LoadLibraryEx(r->filename, NULL, + LOAD_WITH_ALTERED_SEARCH_PATH))) { + ap_log_rerror(APLOG_MARK, APLOG_ALERT, r, + "Could not load DLL: %s", r->filename); + return SERVER_ERROR; + } + + if (!(isapi_version = + (void *)(GetProcAddress(isapi_handle, "GetExtensionVersion")))) { + ap_log_rerror(APLOG_MARK, APLOG_ALERT, r, + "DLL could not load GetExtensionVersion(): %s", r->filename); + FreeLibrary(isapi_handle); + return SERVER_ERROR; + } + + if (!(isapi_entry = + (void *)(GetProcAddress(isapi_handle, "HttpExtensionProc")))) { + ap_log_rerror(APLOG_MARK, APLOG_ALERT, r, + "DLL could not load HttpExtensionProc(): %s", r->filename); + FreeLibrary(isapi_handle); + return SERVER_ERROR; + } + + isapi_term = (void *)(GetProcAddress(isapi_handle, "TerminateExtension")); + + /* Run GetExtensionVersion() */ + + if (!(*isapi_version)(pVer)) { + ap_log_rerror(APLOG_MARK, APLOG_ALERT, r, + "ISAPI GetExtensionVersion() failed: %s", r->filename); + FreeLibrary(isapi_handle); + return SERVER_ERROR; + } + + /* Set up variables */ + ap_add_common_vars(r); + ap_add_cgi_vars(r); + + /* 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 = r->method; + ecb->lpszQueryString = ap_table_get(e, "QUERY_STRING"); + ecb->lpszPathInfo = ap_table_get(e, "PATH_INFO"); + ecb->lpszPathTranslated = ap_table_get(e, "PATH_TRANSLATED"); + ecb->lpszContentType = 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)(HSE_TERM_MUST_UNLOAD); + FreeLibrary(isapi_handle); + return retval; + } + + if (ap_should_client_block(r)) { + /* Unlike IIS, which limits this to 48k, we read the whole + * sucker in. I suppose this could be bad for memory if someone + * uploaded the complete works of Shakespeare. Well, WebSite + * does the same thing. + */ + long to_read = atol(ap_table_get(e, "CONTENT_LENGTH")); + long read; + + /* Actually, let's cap it at 48k, until we figure out what + * to do with this... we don't want a Content-Length: 1000000000 + * taking out the machine. + */ + + if (to_read > 49152) { + if (isapi_term) (*isapi_term)(HSE_TERM_MUST_UNLOAD); + FreeLibrary(isapi_handle); + return HTTP_REQUEST_ENTITY_TOO_LARGE; + } + + ecb->lpbData = ap_pcalloc(r->pool, 1 + to_read); + + if ((read = ap_get_client_block(r, ecb->lpbData, to_read)) < 0) { + if (isapi_term) (*isapi_term)(HSE_TERM_MUST_UNLOAD); + FreeLibrary(isapi_handle); + return SERVER_ERROR; + } + + /* Although its not to spec, IIS seems to null-terminate + * its lpdData string. So we will too. To make sure + * cbAvailable matches cbTotalBytes, we'll up the latter + * and equalize them. + */ + ecb->cbAvailable = ecb->cbTotalBytes = read + 1; + 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_ERR, r, + "%s: %s", ecb->lpszLogData, r->filename); + + /* All done with the DLL... get rid of it */ + if (isapi_term) (*isapi_term)(HSE_TERM_MUST_UNLOAD); + FreeLibrary(isapi_handle); + + switch(retval) { + 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 */ + ap_log_rerror(APLOG_MARK, 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; + table *e = r->subprocess_env; + const char *result; + + /* Mostly, we just grab it from the environment, but there are + * a couple of special cases + */ + + if (!strcasecmp(lpszVariableName, "UNMAPPED_REMOTE_USER")) { + /* We don't support NT users, so this is always the same as + * REMOTE_USER + */ + result = ap_table_get(e, "REMOTE_USER"); + } + else if (!strcasecmp(lpszVariableName, "SERVER_PORT_SECURE")) { + /* Apache doesn't support secure requests inherently, so + * we have no way of knowing. We'll be conservative, and say + * all requests are insecure. + */ + result = "0"; + } + else if (!strcasecmp(lpszVariableName, "URL")) { + result = r->uri; + } + else { + result = ap_table_get(e, lpszVariableName); + } + + if (result) { + if (strlen(result) > *lpdwSizeofBuffer) { + *lpdwSizeofBuffer = strlen(result); + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return FALSE; + } + strncpy(lpvBuffer, result, *lpdwSizeofBuffer); + return TRUE; + } + + /* Didn't find it */ + SetLastError(ERROR_INVALID_INDEX); + return FALSE; +} + +BOOL WINAPI WriteClient (HCONN ConnID, LPVOID Buffer, LPDWORD lpwdwBytes, + DWORD dwReserved) { + request_rec *r = ((isapi_cid *)ConnID)->r; + int writ; /* written, actually, but why shouldn't I make up words? */ + + /* We only support synchronous writing */ + if (dwReserved && dwReserved != HSE_IO_SYNC) { + ap_log_rerror(APLOG_MARK, APLOG_WARNING, r, + "ISAPI asynchronous I/O not supported: %s", r->filename); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if ((writ = ap_rwrite(Buffer, *lpwdwBytes, r)) == EOF) { + SetLastError(ERROR); /* XXX: Find the right error code */ + return FALSE; + } + + *lpwdwBytes = writ; + return TRUE; +} + +BOOL WINAPI ReadClient (HCONN ConnID, LPVOID lpvBuffer, LPDWORD lpdwSize) { + /* Doesn't need to do anything; we've read all the data already */ + return TRUE; +} + +/* XXX: There is an O(n^2) attack possible here. */ +BOOL WINAPI ServerSupportFunction (HCONN hConn, DWORD dwHSERequest, + LPVOID lpvBuffer, LPDWORD lpdwSize, + LPDWORD lpdwDataType) { + isapi_cid *cid = (isapi_cid *)hConn; + request_rec *subreq, *r = cid->r; + char *data; + + switch (dwHSERequest) { + case HSE_REQ_SEND_URL_REDIRECT_RESP: + /* Set the status to be returned when the HttpExtensionProc() + * is done. + */ + ap_table_set (r->headers_out, "Location", lpvBuffer); + cid->status = cid->r->status = cid->ecb->dwHttpStatusCode = REDIRECT; + return TRUE; + + case HSE_REQ_SEND_URL: + /* Read any additional input */ + + if (r->remaining > 0) { + char argsbuffer[HUGE_STRING_LEN]; + + while (ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN)); + } + + /* 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"); + + ap_internal_redirect((char *)lpvBuffer, r); + return TRUE; + + case HSE_REQ_SEND_RESPONSE_HEADER: + r->status_line = lpvBuffer ? lpvBuffer : ap_pstrdup(r->pool, "200 OK"); + sscanf(r->status_line, "%d", &r->status); + cid->ecb->dwHttpStatusCode = r->status; + + /* Now fill in the HTTP headers, and the rest of it. Ick. + * lpdwDataType contains a string that has headers (in MIME + * format), a blank like, then (possibly) data. We need + * to parse it. + * + * Easy case first: + */ + if (!lpdwDataType) { + ap_send_http_header(r); + return TRUE; + } + + /* Make a copy - don't disturb the original */ + data = ap_pstrdup(r->pool, (char *)lpdwDataType); + + /* We *should* break before this while loop ends */ + while (*data) { + char *value, *lf = strchr(data, '\n'); + int p; + +#ifdef RELAX_HEADER_RULE + if (lf) + *lf = '\0'; +#else + if (!lf) { /* Huh? Invalid data, I think */ + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "ISA sent invalid headers: %s", r->filename); + SetLastError(ERROR); /* XXX: Find right error */ + return FALSE; + } + + /* Get rid of \n and \r */ + *lf = '\0'; +#endif + p = strlen(data); + if (p > 0 && data[p-1] == '\r') data[p-1] = '\0'; + + /* End of headers */ + if (*data == '\0') { +#ifdef RELAX_HEADER_RULE + if (lf) +#endif + data = lf + 1; /* Reset data */ + break; + } + + if (!(value = strchr(data, ':'))) { + SetLastError(ERROR); /* XXX: Find right error */ + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "ISA sent invalid headers", r->filename); + return FALSE; + } + + *value++ = '\0'; + while (*value && ap_isspace(*value)) ++value; + + /* Check all the special-case headers. Similar to what + * ap_scan_script_header_err() does (see that function for + * more detail) + */ + + if (!strcasecmp(data, "Content-Type")) { + char *tmp; + /* Nuke trailing whitespace */ + + char *endp = value + strlen(value) - 1; + while (endp > value && ap_isspace(*endp)) *endp-- = '\0'; + + tmp = ap_pstrdup (r->pool, value); + ap_str_tolower(tmp); + r->content_type = tmp; + } + else if (!strcasecmp(data, "Content-Length")) { + ap_table_set(r->headers_out, data, value); + } + else if (!strcasecmp(data, "Transfer-Encoding")) { + ap_table_set(r->headers_out, data, value); + } + else if (!strcasecmp(data, "Set-Cookie")) { + ap_table_add(r->err_headers_out, data, value); + } + else { + ap_table_merge(r->err_headers_out, data, value); + } + + /* Reset data */ +#ifdef RELAX_HEADER_RULE + if (!lf) { + data += p; + break; + } +#endif + data = lf + 1; + } + + /* All the headers should be set now */ + + ap_send_http_header(r); + + /* Any data left should now be sent directly */ + ap_rputs(data, r); + + return TRUE; + + case HSE_REQ_MAP_URL_TO_PATH: + /* Map a URL to a filename */ + subreq = ap_sub_req_lookup_uri(ap_pstrndup(r->pool, (char *)lpvBuffer, + *lpdwSize), r); + + GetFullPathName(subreq->filename, *lpdwSize - 1, (char *)lpvBuffer, NULL); + + /* IIS puts a trailing slash on directories, Apache doesn't */ + + if (S_ISDIR (subreq->finfo.st_mode)) { + int l = strlen((char *)lpvBuffer); + + ((char *)lpvBuffer)[l] = '\\'; + ((char *)lpvBuffer)[l + 1] = '\0'; + } + + return TRUE; + + case HSE_REQ_DONE_WITH_SESSION: + /* Do nothing... since we don't support async I/O, they'll + * return from HttpExtensionProc soon + */ + return TRUE; + + /* We don't support all this async I/O, Microsoft-specific stuff */ + case HSE_REQ_IO_COMPLETION: + case HSE_REQ_TRANSMIT_FILE: + ap_log_rerror(APLOG_MARK, APLOG_WARNING, r, + "ISAPI asynchronous I/O not supported: %s", r->filename); + default: + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } +} + +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 */ + NULL, /* 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 */ +}; diff --git a/APACHE_1_3_12/src/os/win32/modules.c b/APACHE_1_3_12/src/os/win32/modules.c new file mode 100644 index 0000000000..d55d3d832c --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/modules.c @@ -0,0 +1,72 @@ +/* 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 + */ + +#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 +}; diff --git a/APACHE_1_3_12/src/os/win32/multithread.c b/APACHE_1_3_12/src/os/win32/multithread.c new file mode 100644 index 0000000000..a68c3ae220 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/multithread.c @@ -0,0 +1,258 @@ + +#include "ap_config.h" +#include "multithread.h" + +#ifdef WIN32 +#include +#include + + +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_12/src/os/win32/os.c b/APACHE_1_3_12/src/os/win32/os.c new file mode 100755 index 0000000000..8877f50bc8 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/os.c @@ -0,0 +1,7 @@ +/* + * OS abstraction functions. Small functions should be defined + * as "__inline" in os.h. + */ + +#include "os.h" + diff --git a/APACHE_1_3_12/src/os/win32/os.h b/APACHE_1_3_12/src/os/win32/os.h new file mode 100755 index 0000000000..18f1a16422 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/os.h @@ -0,0 +1,197 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +#ifndef APACHE_OS_H +#define APACHE_OS_H + +/* + * 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 + +#include +#include +#include +#include +#include +#include +#include + +#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 + +#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 +typedef int uid_t; +typedef int gid_t; +typedef int pid_t; +typedef int mode_t; +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 +#else +# define API_VAR_EXPORT __declspec(dllexport) +# define API_EXPORT(type) __declspec(dllexport) type __stdcall +# define API_EXPORT_NONSTD(type) __declspec(dllexport) type +#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) +#define S_ISLNK(m) (0) +#define S_ISREG(m) ((m & _S_IFREG) == _S_IFREG) +#ifndef S_ISDIR +#define S_ISDIR(m) (((m) & S_IFDIR) == S_IFDIR) +#endif +#ifndef S_ISREG +#define S_ISREG(m) (((m)&(S_IFREG)) == (S_IFREG)) +#endif +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 +#define JMP_BUF jmp_buf +#define sleep(t) Sleep(t*1000) +#define O_CREAT _O_CREAT +#define O_RDWR _O_RDWR +#define SIGPIPE 17 +/* Seems Windows is not a subgenius */ +#define NO_SLACK +#include + +#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[0] == '/' || file[1] == ':'; +} + +#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(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_load(l) LoadLibraryEx(l, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) +#define ap_os_dso_unload(l) FreeLibrary(l) +#define ap_os_dso_sym(h,s) GetProcAddress(h,s) +#define ap_os_dso_error() "" /* for now */ + +/* Other ap_os_ routines not used by this platform */ +#define ap_os_kill(pid, sig) kill(pid, sig) + +#endif /* ! APACHE_OS_H */ diff --git a/APACHE_1_3_12/src/os/win32/passwd.c b/APACHE_1_3_12/src/os/win32/passwd.c new file mode 100644 index 0000000000..bde691cf29 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/passwd.c @@ -0,0 +1,16 @@ +#include +#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; +} diff --git a/APACHE_1_3_12/src/os/win32/passwd.h b/APACHE_1_3_12/src/os/win32/passwd.h new file mode 100644 index 0000000000..784ab6f6ff --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/passwd.h @@ -0,0 +1,8 @@ +#include + +struct passwd +{ + char pw_dir[_MAX_PATH]; +}; + +struct passwd *getpwnam(const char *szUser); diff --git a/APACHE_1_3_12/src/os/win32/readdir.c b/APACHE_1_3_12/src/os/win32/readdir.c new file mode 100644 index 0000000000..c03c90d998 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/readdir.c @@ -0,0 +1,80 @@ +#include +#include +#include + +#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; +} diff --git a/APACHE_1_3_12/src/os/win32/readdir.h b/APACHE_1_3_12/src/os/win32/readdir.h new file mode 100644 index 0000000000..d87fd1987e --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/readdir.h @@ -0,0 +1,36 @@ +/* + * Structures and types used to implement opendir/readdir/closedir + * on Windows 95/NT. + */ + +#include +#include +#include +#include + +#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 *); diff --git a/APACHE_1_3_12/src/os/win32/registry.c b/APACHE_1_3_12/src/os/win32/registry.c new file mode 100755 index 0000000000..cb4e4a4951 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/registry.c @@ -0,0 +1,471 @@ +/* + * 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 +#include + +#include "httpd.h" +#include "http_log.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 VENDOR "Apache Group" +#define SOFTWARE "Apache" +#define VERSION "1.3.12" + +#define REGKEY "SOFTWARE\\" VENDOR "\\" SOFTWARE "\\" VERSION + +#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. + */ + +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 < -1) ? -1 : 0; +} + +char *ap_get_service_key(char *service_name) +{ + char *key = malloc(strlen(SERVICEKEYPRE) + + strlen(service_name) + + strlen(SERVICEKEYPOST) + 1); + + sprintf(key,"%s%s%s", SERVICEKEYPRE, service_name, SERVICEKEYPOST); + + return(key); +} + +int ap_registry_get_service_conf(pool *p, char *dir, int size, char *service_name) +{ + int rv; + char *key = ap_get_service_key(service_name); + + rv = ap_registry_get_key_int(p, key, "ConfPath", dir, size, NULL); + if (rv < 0) { + dir[0] = '\0'; + } + + free(key); + return (rv < -1) ? -1 : 0; +} + +/********************************************************************** + * 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 service confpath 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_service_conf(char *conf, char *service_name) +{ + int rv; + char *key = ap_get_service_key(service_name); + + rv = ap_registry_store_key_int(key, "ConfPath", REG_SZ, conf, strlen(conf)+1); + free(key); + + return rv < 0 ? -1: 0; +} + +/* + * 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; +} + diff --git a/APACHE_1_3_12/src/os/win32/registry.h b/APACHE_1_3_12/src/os/win32/registry.h new file mode 100755 index 0000000000..7075e78606 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/registry.h @@ -0,0 +1,8 @@ +/* + * Declarations for users of the functions defined in registry.c + */ + +extern 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_conf(pool *p, char *dir, int size, char *service_name); +extern int ap_registry_set_service_conf(char *dir, char *service_name); diff --git a/APACHE_1_3_12/src/os/win32/resource.h b/APACHE_1_3_12/src/os/win32/resource.h new file mode 100755 index 0000000000..820bb6aaaf --- /dev/null +++ b/APACHE_1_3_12/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_12/src/os/win32/service.c b/APACHE_1_3_12/src/os/win32/service.c new file mode 100644 index 0000000000..8108ae1ad9 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/service.c @@ -0,0 +1,431 @@ +#ifdef WIN32 + +#include +#include +#include +#include +#include + +#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" + +static struct +{ + int (*main_fn)(int, char **); + event *stop_event; + int connected; + SERVICE_STATUS_HANDLE hServiceStatus; + char *name; + int exit_status; + SERVICE_STATUS ssStatus; + FILE *logFile; +} globdat; + +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); +static int ap_stop_service(SC_HANDLE); + +int service_main(int (*main_fn)(int, char **), int argc, char **argv ) +{ + SERVICE_TABLE_ENTRY dispatchTable[] = + { + { "", service_main_fn }, + { NULL, NULL } + }; + + globdat.main_fn = main_fn; + globdat.stop_event = create_event(0, 0, "apache-signal"); + 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"); + return(globdat.exit_status); + } + else + { + return(globdat.exit_status); + } +} + +void service_cd() +{ + /* change to the drive with the executable */ + char buf[300]; + GetModuleFileName(NULL, buf, 300); + buf[2] = 0; + chdir(buf); +} + +void __stdcall service_main_fn(DWORD argc, LPTSTR *argv) +{ + ap_server_argv0 = globdat.name = argv[0]; + + if(!(globdat.hServiceStatus = RegisterServiceCtrlHandler( globdat.name, 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 + + service_cd(); + if( service_init() ) + /* Arguments are ok except for \! */ + globdat.exit_status = (*globdat.main_fn)( argc, argv ); + + ReportStatusToSCMgr(SERVICE_STOPPED, NO_ERROR, 0); + + return; +} + +void service_set_status(int status) +{ + ReportStatusToSCMgr(status, NO_ERROR, 3000); +} + + + +// +// 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: +// +VOID WINAPI service_ctrl(DWORD dwCtrlCode) +{ + int state; + + + state = globdat.ssStatus.dwCurrentState; + switch(dwCtrlCode) + { + // Stop the service. + // + case SERVICE_CONTROL_STOP: + state = SERVICE_STOP_PENDING; + ap_start_shutdown(); + break; + + // Update the service status. + // + case SERVICE_CONTROL_INTERROGATE: + break; + + // invalid control code + // + default: + break; + + } + + ReportStatusToSCMgr(state, NO_ERROR, 0); +} + + +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) + globdat.ssStatus.dwControlsAccepted = 0; + else + globdat.ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; + + globdat.ssStatus.dwCurrentState = currentState; + globdat.ssStatus.dwWin32ExitCode = exitCode; + if(waitHint) + globdat.ssStatus.dwWaitHint = waitHint; + + if ( ( currentState == SERVICE_RUNNING ) || + ( currentState == SERVICE_STOPPED ) ) + { + globdat.ssStatus.dwWaitHint = 0; + globdat.ssStatus.dwCheckPoint = 0; + } + else + globdat.ssStatus.dwCheckPoint = ++checkPoint; + + rv = SetServiceStatus(globdat.hServiceStatus, &globdat.ssStatus); + + } + return(1); +} + +void InstallService(char *service_name, char *conf) +{ + SC_HANDLE schService; + SC_HANDLE schSCManager; + + TCHAR szPath[512]; + TCHAR szQuotedPath[512]; + + printf("Installing the %s service to use %s\n", service_name, conf); + + if (GetModuleFileName( NULL, szPath, 512 ) == 0) + { + ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL, + "GetModuleFileName failed"); + return; + } + + ap_snprintf(szQuotedPath, 512, "\"%s\"", szPath); + + 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"); + } + else { + schService = CreateService( + schSCManager, // SCManager database + service_name, // name of service + service_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 + NULL, // dependencies + NULL, // LocalSystem account + NULL); // no password + + if (schService) { + CloseServiceHandle(schService); + + /* Now store the server_root in the registry */ + if(!ap_registry_set_service_conf(conf, service_name)) + printf("The %s service has been installed successfully.\n", service_name ); + } + else { + ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL, + "CreateService failed"); + } + + CloseServiceHandle(schSCManager); + } +} + + +void RemoveService(char *service_name) +{ + SC_HANDLE schService; + SC_HANDLE schSCManager; + + printf("Removing the %s service\n", service_name); + + 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"); + } + else { + 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 + printf("The %s service has been removed successfully.\n", service_name ); + CloseServiceHandle(schService); + } + /* SCM removes registry parameters */ + CloseServiceHandle(schSCManager); + } + +} + +/* A hack to determine if we're running as a service without waiting for + * the SCM to fail; if AllocConsole succeeds, we're a service. + */ + +BOOL isProcessService() { + if( !AllocConsole() ) + return FALSE; + FreeConsole(); + return TRUE; +} + +/* Determine is service_name is a valid service + */ + +BOOL isValidService(char *service_name) { + SC_HANDLE schSCM, schSVC; + int Err; + + if (!(schSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS))) { + ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL, + "OpenSCManager failed"); + return FALSE; + } + + if ((schSVC = OpenService(schSCM, service_name, SERVICE_ALL_ACCESS))) { + CloseServiceHandle(schSVC); + CloseServiceHandle(schSCM); + return TRUE; + } + + Err = GetLastError(); + if (Err != ERROR_SERVICE_DOES_NOT_EXIST && Err != ERROR_INVALID_NAME) + ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL, + "OpenService failed"); + + return FALSE; +} + +int send_signal_to_service(char *service_name, char *sig) { + SC_HANDLE schService; + SC_HANDLE schSCManager; + 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; + } + + 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"); + } + else { + 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 { + if (!QueryServiceStatus(schService, &globdat.ssStatus)) + ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL, + "QueryService failed"); + else { + if (globdat.ssStatus.dwCurrentState == SERVICE_STOPPED && action == stop) + printf("The %s service is not started.\n", service_name); + else if (globdat.ssStatus.dwCurrentState == SERVICE_RUNNING && action == start) + printf("The %s service has already been started.\n", service_name); + else { + printf("The %s service is %s.\n", service_name, participle[action]); + + if (action == stop || action == restart) + success = ap_stop_service(schService); + if (action == start || action == restart) + success = ap_start_service(schService); + + if( success ) + printf("The %s service has %s.\n", service_name, past[action]); + else + printf("Failed to %s the %s service.\n", sig, service_name ); + } + + CloseServiceHandle(schService); + } + } + /* SCM removes registry parameters */ + 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) { + if (StartService(schService, 0, NULL)) { + 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; +} + +#endif /* WIN32 */ + diff --git a/APACHE_1_3_12/src/os/win32/service.h b/APACHE_1_3_12/src/os/win32/service.h new file mode 100644 index 0000000000..822596c416 --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/service.h @@ -0,0 +1,17 @@ + +#ifndef SERVICE_H +#define SERVICE_H + +#ifdef WIN32 +int service_main(int (*main_fn)(int, char **), int argc, char **argv); +void service_set_status(int status); +void service_cd(); +BOOL isProcessService(); +BOOL isValidService(char *service_name); +void InstallService(char *service_name, char *conf); +void RemoveService(char *service_name); +int service_init(); +int send_signal_to_service(char *service_name, char *sig); +#endif /* WIN32 */ + +#endif /* SERVICE_H */ diff --git a/APACHE_1_3_12/src/os/win32/util_win32.c b/APACHE_1_3_12/src/os/win32/util_win32.c new file mode 100644 index 0000000000..348e0f9e2a --- /dev/null +++ b/APACHE_1_3_12/src/os/win32/util_win32.c @@ -0,0 +1,677 @@ +#include +#include +#include +#include +#include + +#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. + */ +API_EXPORT(char *) ap_os_systemcase_filename(pool *pPool, + const char *szFile) +{ + char buf[HUGE_STRING_LEN]; + char *pInputName; + char *p, *q; + BOOL bDone = FALSE; + BOOL bFileExists = TRUE; + HANDLE hFind; + WIN32_FIND_DATA wfd; + + if (!szFile || strlen(szFile) == 0 || strlen(szFile) >= sizeof(buf)) + return ap_pstrdup(pPool, ""); + + buf[0] = '\0'; + pInputName = ap_pstrdup(pPool, szFile); + + /* First convert all slashes to \ so Win32 calls work OK */ + for (p = pInputName; *p; p++) { + if (*p == '/') + *p = '\\'; + } + + p = pInputName; + /* If there is drive information, copy it over. */ + if (pInputName[1] == ':') { + buf[0] = tolower(*p++); + buf[1] = *p++; + buf[2] = '\0'; + + /* If all we have is a drive letter, then we are done */ + if (strlen(pInputName) == 2) + bDone = TRUE; + } + + q = p; + if (*p == '\\') { + p++; + if (*p == '\\') /* Possible UNC name */ + { + p++; + /* Get past the machine name. FindFirstFile */ + /* will not find a machine name only */ + p = strchr(p, '\\'); + if (p) + { + p++; + /* Get past the share name. FindFirstFile */ + /* will not find a \\machine\share name only */ + p = strchr(p, '\\'); + if (p) { + strncat(buf,q,p-q); + q = p; + p++; + } + } + + if (!p) + p = q; + } + } + + p = strchr(p, '\\'); + + while (!bDone) { + if (p) + *p = '\0'; + + if (strchr(q, '*') || strchr(q, '?')) + bFileExists = FALSE; + + /* 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. + * Note: in the call to OnlyDots, we may have to skip + * a leading slash. + */ + if (bFileExists && !OnlyDots((*q == '.' ? q : q+1))) { + hFind = FindFirstFile(pInputName, &wfd); + + if (hFind == INVALID_HANDLE_VALUE) { + bFileExists = FALSE; + } + else { + FindClose(hFind); + + if (*q == '\\') + strcat(buf,"\\"); + strcat(buf, wfd.cFileName); + } + } + + if (!bFileExists || OnlyDots((*q == '.' ? q : q+1))) { + strcat(buf, q); + } + + if (p) { + q = p; + *p++ = '\\'; + p = strchr(p, '\\'); + } + else { + bDone = TRUE; + } + } + + /* First convert all slashes to / so server code handles it ok */ + for (p = buf; *p; p++) { + if (*p == '\\') + *p = '/'; + } + + return ap_pstrdup(pPool, 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. + */ + p = strchr(pNewStr, '~'); + if (p != NULL) { + char *pConvertedName, *pQstr, *pPstr; + char buf[HUGE_STRING_LEN]; + /* We potentially have a short name. Call + * ap_os_systemcase_filename to examine the filesystem + * and possibly extract the long name. + */ + pConvertedName = ap_os_systemcase_filename(pPool, pNewStr); + + /* Since we want to preserve the incoming case as much + * as we can, compare for differences in the string and + * only substitute in the path names that changed. + */ + if (stricmp(pNewStr, pConvertedName)) { + buf[0] = '\0'; + + q = pQstr = pConvertedName; + p = pPstr = pNewStr; + do { + q = strchr(q,'/'); + p = strchr(p,'/'); + + if (p != NULL) { + *q = '\0'; + *p = '\0'; + } + + if (stricmp(pQstr, pPstr)) + strcat(buf, pQstr); /* Converted name */ + else + strcat(buf, pPstr); /* Original name */ + + + if (p != NULL) { + pQstr = q; + pPstr = p; + *q++ = '/'; + *p++ = '/'; + } + + } while (p != NULL); + + pNewStr = ap_pstrdup(pPool, buf); + } + } + + + 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; +} + +/* 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; + + if (strlen(szPath) == 0) { + return -1; + } + + if (szPath[0] == '/' && szPath[1] == '/') { + char buf[_MAX_PATH]; + char *s; + int nSlashes = 0; + + ap_assert(strlen(szPath) < _MAX_PATH); + 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) { + *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]; + + ap_assert(n < _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(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 = ap_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; +} + +/* + * 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; +} diff --git a/APACHE_1_3_12/src/regex/.cvsignore b/APACHE_1_3_12/src/regex/.cvsignore new file mode 100644 index 0000000000..4487e89a7e --- /dev/null +++ b/APACHE_1_3_12/src/regex/.cvsignore @@ -0,0 +1,6 @@ +re +Debug +Release +regex.mdp +regex.ncb +Makefile diff --git a/APACHE_1_3_12/src/regex/COPYRIGHT b/APACHE_1_3_12/src/regex/COPYRIGHT new file mode 100644 index 0000000000..d43362fbfc --- /dev/null +++ b/APACHE_1_3_12/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_12/src/regex/Makefile.tmpl b/APACHE_1_3_12/src/regex/Makefile.tmpl new file mode 100644 index 0000000000..6ecb4c6ba9 --- /dev/null +++ b/APACHE_1_3_12/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 &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_12/src/regex/README b/APACHE_1_3_12/src/regex/README new file mode 100644 index 0000000000..cea9b67b66 --- /dev/null +++ b/APACHE_1_3_12/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 . + +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_12/src/regex/WHATSNEW b/APACHE_1_3_12/src/regex/WHATSNEW new file mode 100644 index 0000000000..6e82e1dae0 --- /dev/null +++ b/APACHE_1_3_12/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' + 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_12/src/regex/cclass.h b/APACHE_1_3_12/src/regex/cclass.h new file mode 100644 index 0000000000..727cbb9255 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/regex/cname.h b/APACHE_1_3_12/src/regex/cname.h new file mode 100644 index 0000000000..ff116e55e2 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/regex/debug.c b/APACHE_1_3_12/src/regex/debug.c new file mode 100644 index 0000000000..fdf49f6cde --- /dev/null +++ b/APACHE_1_3_12/src/regex/debug.c @@ -0,0 +1,243 @@ +#include +#include +#include +#include +#include +#include + +#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_12/src/regex/engine.c b/APACHE_1_3_12/src/regex/engine.c new file mode 100644 index 0000000000..c91da17d80 --- /dev/null +++ b/APACHE_1_3_12/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®_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 int 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®_NOSUB) + nmatch = 0; + if (eflags®_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®_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®_NOTBOL)) || + (sp < m->endp && *(sp-1) == '\n' && + (m->g->cflags®_NEWLINE)) ) + { /* yes */ } + else + return(NULL); + break; + case OEOL: + if ( (sp == m->endp && !(m->eflags®_NOTEOL)) || + (sp < m->endp && *sp == '\n' && + (m->g->cflags®_NEWLINE)) ) + { /* yes */ } + else + return(NULL); + break; + case OBOW: + if (( (sp == m->beginp && !(m->eflags®_NOTBOL)) || + (sp < m->endp && *(sp-1) == '\n' && + (m->g->cflags®_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®_NOTEOL)) || + (sp < m->endp && *sp == '\n' && + (m->g->cflags®_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®_NEWLINE) || + (lastc == OUT && !(m->eflags®_NOTBOL)) ) { + flagch = BOL; + i = m->g->nbol; + } + if ( (c == '\n' && m->g->cflags®_NEWLINE) || + (c == OUT && !(m->eflags®_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®_NEWLINE) || + (lastc == OUT && !(m->eflags®_NOTBOL)) ) { + flagch = BOL; + i = m->g->nbol; + } + if ( (c == '\n' && m->g->cflags®_NEWLINE) || + (c == OUT && !(m->eflags®_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®_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®_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_12/src/regex/engine.ih b/APACHE_1_3_12/src/regex/engine.ih new file mode 100644 index 0000000000..713abd6107 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/regex/main.c b/APACHE_1_3_12/src/regex/main.c new file mode 100644 index 0000000000..5a9ada8ffd --- /dev/null +++ b/APACHE_1_3_12/src/regex/main.c @@ -0,0 +1,516 @@ +#include +#include +#include +#include +#include +#ifdef TPF +#include /* 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®_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®_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®_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)®_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®_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_12/src/regex/mkh b/APACHE_1_3_12/src/regex/mkh new file mode 100644 index 0000000000..b766fff167 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/regex/regcomp.c b/APACHE_1_3_12/src/regex/regcomp.c new file mode 100644 index 0000000000..1e60ca3682 --- /dev/null +++ b/APACHE_1_3_12/src/regex/regcomp.c @@ -0,0 +1,1585 @@ +#include +#include +#include +#include +#include +#include + +#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 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 */ + 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®_EXTENDED) && (cflags®_NOSPEC)) + return(REG_INVARG); + + if (cflags®_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®_EXTENDED) + p_ere(p, OUT); + else if (cflags®_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®_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<g->cflags®_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®_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®_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 */ + /* 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®_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 int 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 int 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 int 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 int 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<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<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_12/src/regex/regcomp.ih b/APACHE_1_3_12/src/regex/regcomp.ih new file mode 100644 index 0000000000..5e4e9c65e9 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/regex/regerror.c b/APACHE_1_3_12/src/regex/regerror.c new file mode 100644 index 0000000000..d056f38647 --- /dev/null +++ b/APACHE_1_3_12/src/regex/regerror.c @@ -0,0 +1,124 @@ +#include +#include +#include +#include +#include +#include + +#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®_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_12/src/regex/regerror.ih b/APACHE_1_3_12/src/regex/regerror.ih new file mode 100644 index 0000000000..ff55461654 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/regex/regex.3 b/APACHE_1_3_12/src/regex/regex.3 new file mode 100644 index 0000000000..100c8a7f71 --- /dev/null +++ b/APACHE_1_3_12/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 +.br +#include +.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 +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_12/src/regex/regex.7 b/APACHE_1_3_12/src/regex/regex.7 new file mode 100644 index 0000000000..d89012bda1 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/regex/regex.dsp b/APACHE_1_3_12/src/regex/regex.dsp new file mode 100644 index 0000000000..60dd109075 --- /dev/null +++ b/APACHE_1_3_12/src/regex/regex.dsp @@ -0,0 +1,114 @@ +# Microsoft Developer Studio Project File - Name="regex" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.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 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 "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 Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /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 "regex___" +# PROP BASE Intermediate_Dir "regex___" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c +# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /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_12/src/regex/regex.mak b/APACHE_1_3_12/src/regex/regex.mak new file mode 100644 index 0000000000..1484294ea4 --- /dev/null +++ b/APACHE_1_3_12/src/regex/regex.mak @@ -0,0 +1,266 @@ +# 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 + +CPP=cl.exe + +!IF "$(CFG)" == "regex - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\regex.lib" + +!ELSE + +ALL : "$(OUTDIR)\regex.lib" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\regcomp.obj" + -@erase "$(INTDIR)\regerror.obj" + -@erase "$(INTDIR)\regexec.obj" + -@erase "$(INTDIR)\regfree.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\regex.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MD /W3 /GX /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D\ + "_WINDOWS" /Fp"$(INTDIR)\regex.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD\ + /c +CPP_OBJS=.\Release/ +CPP_SBRS=. +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=.\Debug +INTDIR=.\Debug +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\regex.lib" + +!ELSE + +ALL : "$(OUTDIR)\regex.lib" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\regcomp.obj" + -@erase "$(INTDIR)\regerror.obj" + -@erase "$(INTDIR)\regexec.obj" + -@erase "$(INTDIR)\regfree.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\regex.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MDd /W3 /GX /Z7 /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D\ + "_WINDOWS" /Fp"$(INTDIR)\regex.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD\ + /c +CPP_OBJS=.\Debug/ +CPP_SBRS=. +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 + +.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) $< +<< + + +!IF "$(CFG)" == "regex - Win32 Release" || "$(CFG)" == "regex - Win32 Debug" +SOURCE=.\regcomp.c + +!IF "$(CFG)" == "regex - Win32 Release" + +DEP_CPP_REGCO=\ + "..\include\hsregex.h"\ + ".\cclass.h"\ + ".\cname.h"\ + ".\regcomp.ih"\ + ".\regex2.h"\ + ".\utils.h"\ + + +"$(INTDIR)\regcomp.obj" : $(SOURCE) $(DEP_CPP_REGCO) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "regex - Win32 Debug" + +DEP_CPP_REGCO=\ + "..\include\hsregex.h"\ + ".\cclass.h"\ + ".\cname.h"\ + ".\regcomp.ih"\ + ".\regex2.h"\ + ".\utils.h"\ + + +"$(INTDIR)\regcomp.obj" : $(SOURCE) $(DEP_CPP_REGCO) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\regerror.c + +!IF "$(CFG)" == "regex - Win32 Release" + +DEP_CPP_REGER=\ + "..\include\hsregex.h"\ + ".\regerror.ih"\ + ".\utils.h"\ + + +"$(INTDIR)\regerror.obj" : $(SOURCE) $(DEP_CPP_REGER) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "regex - Win32 Debug" + +DEP_CPP_REGER=\ + "..\include\hsregex.h"\ + ".\regerror.ih"\ + ".\utils.h"\ + + +"$(INTDIR)\regerror.obj" : $(SOURCE) $(DEP_CPP_REGER) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\regexec.c + +!IF "$(CFG)" == "regex - Win32 Release" + +DEP_CPP_REGEX=\ + "..\include\hsregex.h"\ + ".\engine.c"\ + ".\engine.ih"\ + ".\regex2.h"\ + ".\utils.h"\ + + +"$(INTDIR)\regexec.obj" : $(SOURCE) $(DEP_CPP_REGEX) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "regex - Win32 Debug" + +DEP_CPP_REGEX=\ + "..\include\hsregex.h"\ + ".\engine.c"\ + ".\engine.ih"\ + ".\regex2.h"\ + ".\utils.h"\ + + +"$(INTDIR)\regexec.obj" : $(SOURCE) $(DEP_CPP_REGEX) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\regfree.c +DEP_CPP_REGFR=\ + "..\include\hsregex.h"\ + ".\regex2.h"\ + ".\utils.h"\ + + +"$(INTDIR)\regfree.obj" : $(SOURCE) $(DEP_CPP_REGFR) "$(INTDIR)" + + + +!ENDIF + diff --git a/APACHE_1_3_12/src/regex/regex2.h b/APACHE_1_3_12/src/regex/regex2.h new file mode 100644 index 0000000000..d15cb17233 --- /dev/null +++ b/APACHE_1_3_12/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) + = #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< 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_12/src/regex/regexec.c b/APACHE_1_3_12/src/regex/regexec.c new file mode 100644 index 0000000000..d2f0a00bf6 --- /dev/null +++ b/APACHE_1_3_12/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 +#include +#include +#include +#include +#include + +#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 long +#define states1 states /* for later use in regexec() decision */ +#define CLEAR(v) ((v) = 0) +#define SET0(v, n) ((v) &= ~(1 << (n))) +#define SET1(v, n) ((v) |= 1 << (n)) +#define ISSET(v, n) ((v) & (1 << (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) = 0) +#define onestate int +#define INIT(o, n) ((o) = (unsigned)1 << (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) |= ((unsigned)(src)&(here)) << (n)) +#define BACK(dst, src, n) ((dst) |= ((unsigned)(src)&(here)) >> (n)) +#define ISSETBACK(v, n) ((v) & ((unsigned)here >> (n))) +/* 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®_LARGE)) + return(smatcher(g, (char *)string, nmatch, pmatch, eflags)); + else + return(lmatcher(g, (char *)string, nmatch, pmatch, eflags)); +} diff --git a/APACHE_1_3_12/src/regex/regfree.c b/APACHE_1_3_12/src/regex/regfree.c new file mode 100644 index 0000000000..840899a8e7 --- /dev/null +++ b/APACHE_1_3_12/src/regex/regfree.c @@ -0,0 +1,38 @@ +#include +#include +#include + +#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_12/src/regex/split.c b/APACHE_1_3_12/src/regex/split.c new file mode 100644 index 0000000000..6359aba8ab --- /dev/null +++ b/APACHE_1_3_12/src/regex/split.c @@ -0,0 +1,318 @@ +#include +#include + +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_12/src/regex/tests b/APACHE_1_3_12/src/regex/tests new file mode 100644 index 0000000000..c05846177f --- /dev/null +++ b/APACHE_1_3_12/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_12/src/regex/utils.h b/APACHE_1_3_12/src/regex/utils.h new file mode 100644 index 0000000000..f271f759b1 --- /dev/null +++ b/APACHE_1_3_12/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 + +/* 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_12/src/support/.cvsignore b/APACHE_1_3_12/src/support/.cvsignore new file mode 100644 index 0000000000..399f114e93 --- /dev/null +++ b/APACHE_1_3_12/src/support/.cvsignore @@ -0,0 +1,11 @@ +Makefile +rotatelogs +htpasswd +htdigest +unescape +inc2shtml +httpd_monitor +suexec +logresolve +ab +apxs diff --git a/APACHE_1_3_12/src/support/.indent.pro b/APACHE_1_3_12/src/support/.indent.pro new file mode 100644 index 0000000000..a9fbe9f9a1 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/support/Makefile.tmpl b/APACHE_1_3_12/src/support/Makefile.tmpl new file mode 100644 index 0000000000..68b69edc8a --- /dev/null +++ b/APACHE_1_3_12/src/support/Makefile.tmpl @@ -0,0 +1,82 @@ + +CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS) +LIBS=-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 + +OBJS=htpasswd.o htdigest.o rotatelogs.o logresolve.o ab.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) + +apxs: apxs.pl + sed 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_12/src/support/README b/APACHE_1_3_12/src/support/README new file mode 100644 index 0000000000..80e9cafde0 --- /dev/null +++ b/APACHE_1_3_12/src/support/README @@ -0,0 +1,62 @@ +Support files: + +ab + ABuse your server with this benchmarker. Rudimentary + command line testing tool. + +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_12/src/support/SHA1/README.sha1 b/APACHE_1_3_12/src/support/SHA1/README.sha1 new file mode 100644 index 0000000000..3998e1fdd9 --- /dev/null +++ b/APACHE_1_3_12/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 . + +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_12/src/support/SHA1/convert-sha1.pl b/APACHE_1_3_12/src/support/SHA1/convert-sha1.pl new file mode 100755 index 0000000000..35228022a0 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/support/SHA1/htpasswd-sha1.pl b/APACHE_1_3_12/src/support/SHA1/htpasswd-sha1.pl new file mode 100755 index 0000000000..ad624d1101 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/support/SHA1/ldif-sha1.example b/APACHE_1_3_12/src/support/SHA1/ldif-sha1.example new file mode 100644 index 0000000000..b8fe917eaf --- /dev/null +++ b/APACHE_1_3_12/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_12/src/support/ab.8 b/APACHE_1_3_12/src/support/ab.8 new file mode 100644 index 0000000000..eb9829e9d6 --- /dev/null +++ b/APACHE_1_3_12/src/support/ab.8 @@ -0,0 +1,215 @@ +.TH ab 1 "October 1999" +.\" Copyright (c) 1998-1999 The Apache Group. 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 acknowledgment: +.\" "This product includes software developed by the Apache Group +.\" for use in the Apache HTTP server project (http://www.apache.org/)." +.\" +.\" 4. The names "Apache Server" and "Apache Group" must not be used to +.\" endorse or promote products derived from this software without +.\" prior written permission. +.\" +.\" 5. Products derived from this software may not be called "Apache" +.\" nor may "Apache" appear in their names without prior written +.\" permission of the Apache Group. +.\" +.\" 6. Redistributions of any form whatsoever must retain the following +.\" acknowledgment: +.\" "This product includes software developed by the Apache Group +.\" for use in the Apache HTTP server project (http://www.apache.org/)." +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY +.\" EXPRESSED 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 APACHE GROUP OR +.\" ITS 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. +.\" ==================================================================== +.\" +.\" This software consists of voluntary contributions made by many +.\" individuals on behalf of the Apache Group and was originally based +.\" on public domain software written at the National Center for +.\" Supercomputing Applications, University of Illinois, Urbana-Champaign. +.\" For more information on the Apache Group and the Apache HTTP server +.\" project, please see . +.SH NAME +ab \- Apache HTTP server benchmarking tool +.SH SYNOPSIS +.B ab +[ +.B \-k +] [ +.B \-i +] [ +.BI \-n " requests" +] [ +.BI \-t " timelimit" +] [ +.BI \-c " concurrency" +] [ +.BI \-p " POST file" +] [ +.BI \-A " Authenticate username:password" +] [ +.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 \-x " attributes" +] +] [ +.BI \-y " attributes" +] +] [ +.BI \-z "
    attributes" +] +.I [http://]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 \-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 \-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 +.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 . Attributes are inserted +
    +.TP 12 +.BI \-y " attributes" +The string to use as attributes for . +.TP 12 +.BI \-z " attributes" +The string to use as attributes for
    . +.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. + +.SH SEE ALSO +.BR httpd(8) +. diff --git a/APACHE_1_3_12/src/support/ab.c b/APACHE_1_3_12/src/support/ab.c new file mode 100644 index 0000000000..95badef916 --- /dev/null +++ b/APACHE_1_3_12/src/support/ab.c @@ -0,0 +1,1130 @@ +/* ==================================================================== + * Copyright (c) 1998-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + ** 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 , March 1996 + ** with input from Mike Belshe and + ** Michael Campanella + ** - Enhanced by Dean Gaudet , November 1997 + ** - Cleaned up by Ralf S. Engelschall , March 1998 + ** - POST and verbosity by Kurt Sussman , August 1998 + ** - HTML table output added by David N. Welton , January 1999 + ** - Added Cookie, Arbitrary header and auth support. , April 1999 + ** + */ + +/* + * 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 + */ + +#define VERSION "1.3c" + +/* -------------------------------------------------------------------- */ + +/* affects include files on Solaris */ +#define BSD_COMP + +/* allow compilation outside an Apache build tree */ +#ifdef NO_APACHE_INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ap_select select +#else /* (!)NO_APACHE_INCLUDES */ +#include "ap_config.h" +#include "ap.h" +#ifdef CHARSET_EBCDIC +#include "ebcdic.h" +#endif +#include +#ifndef MPE +#include +#endif + +#ifndef NO_WRITEV +#include +#include +#endif + +#endif /* NO_APACHE_INCLUDES */ +/* ------------------- 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, 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 ap_min(a,b) ((a)<(b))?(a):(b) +#define ap_max(a,b) ((a)>(b))?(a):(b) + +/* --------------------- GLOBALS ---------------------------- */ + +int verbosity = 0; /* no verbosity by default */ +int posting = 0; /* GET by default */ +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 servername[1024]; /* name that server reports */ +char hostname[1024]; /* host name */ +char path[1024]; /* path name */ +char postfile[1024]; /* name of file containing post data */ +char *postdata; /* *buffer containing data from postfile */ +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 */ +int totalread = 0; /* total number of bytes read */ +int totalbread = 0; /* totoal amount of entity body read */ +int totalposted = 0; /* total number of bytes posted, inc. headers */ +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; +int err_response = 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[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 + +/* --------------------------------------------------------- */ + +/* simple little function to perror and exit */ + +static void err(char *s) +{ + if (errno) { + perror(s); + } + else { + printf("%s", s); + } + exit(errno); +} + +/* --------------------------------------------------------- */ + +/* 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) +{ +#ifndef NO_WRITEV + struct iovec out[2]; int outcnt = 1; +#endif + gettimeofday(&c->connect, 0); +#ifndef NO_WRITEV + 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); + } + writev(c->fd,out, outcnt); +#else + ab_write(c->fd,request,reqlen); + if (posting>0) { + ab_write(c->fd,postdata,postlen); + totalposted += (reqlen + postlen); + } +#endif + + c->state = STATE_READ; + FD_SET(c->fd, &readbits); + FD_CLR(c->fd, &writebits); +} + +/* --------------------------------------------------------- */ + +/* 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 void output_results(void) +{ + int timetaken; + + 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: %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 (err_response) + printf("Non-2xx responses: %d\n", err_response); + if (keepalive) + printf("Keep-Alive requests: %d\n", doneka); + printf("Total transferred: %d bytes\n", totalread); + if (posting>0) + printf("Total POSTed: %d\n", totalposted); + printf("HTML transferred: %d bytes\n", totalbread); + + /* avoid divide by zero */ + if (timetaken) { + printf("Requests per second: %.2f\n", 1000 * (float) (done) / timetaken); + printf("Transfer rate: %.2f kb/s 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); + } + } + + { + /* 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 = 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("\nConnnection Times (ms)\n"); + printf(" min avg max\n"); + printf("Connect: %5d %5d %5d\n", mincon, totalcon / requests, maxcon); + printf("Processing: %5d %5d %5d\n", + mintot - mincon, (total / requests) - (totalcon / requests), + maxtot - maxcon); + printf("Total: %5d %5d %5d\n", mintot, total / requests, maxtot); + } + } +} + +/* --------------------------------------------------------- */ + +/* calculate and output results in HTML */ + +static void output_html_results(void) +{ + int timetaken; + + gettimeofday(&endtime, 0); + timetaken = timedif(endtime, start); + + printf("\n\n\n", tablestring); + printf("" + "\n", + trstring, tdstring, tdstring, servername); + printf("" + "\n", + trstring, tdstring, tdstring, hostname); + printf("" + "\n", + trstring, tdstring, tdstring, port); + printf("" + "\n", + trstring, tdstring, tdstring, path); + printf("" + "\n", + trstring, tdstring, tdstring, doclen); + printf("" + "\n", + trstring, tdstring, tdstring, concurrency); + printf("" + "\n", + trstring, tdstring, tdstring, timetaken / 1000, timetaken % 1000); + printf("" + "\n", + trstring, tdstring, tdstring, done); + printf("" + "\n", + trstring, tdstring, tdstring, bad); + if (bad) + printf("\n", + trstring, tdstring, err_conn, err_length, err_except); + if (err_response) + printf("" + "\n", + trstring, tdstring, tdstring, err_response); + if (keepalive) + printf("" + "\n", + trstring, tdstring, tdstring, doneka); + printf("" + "\n", + trstring, tdstring, tdstring, totalread); + if (posting>0) + printf("" + "\n", + trstring, tdstring, tdstring, totalposted); + printf("" + "\n", + trstring, tdstring, tdstring, totalbread); + + /* avoid divide by zero */ + if (timetaken) { + printf("" + "\n", + trstring, tdstring, tdstring, 1000 * (float) (done) / timetaken); + printf("" + "\n", + trstring, tdstring, tdstring, (float) (totalread) / timetaken); + if (posting>0) { + printf("" + "\n", + trstring, tdstring, tdstring, + (float) (totalposted) / timetaken); + printf("" + "\n", + trstring, tdstring, tdstring, + (float) (totalread + totalposted) / 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 = 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("\n", + trstring, tdstring); + printf("\n", + trstring, tdstring, tdstring, tdstring, tdstring); + printf("" + "" + "" + "\n", + trstring, tdstring, tdstring, mincon, tdstring, totalcon / requests, tdstring, maxcon); + printf("" + "" + "" + "\n", + trstring, tdstring, tdstring, mintot - mincon, tdstring, + (total / requests) - (totalcon / requests), tdstring, maxtot - maxcon); + printf("" + "" + "" + "\n", + trstring, tdstring, tdstring, mintot, tdstring, total / requests, tdstring, maxtot); + } + printf("
    Server Software:%s
    Server Hostname:%s
    Server Port:%d
    Document Path:%s
    Document Length:%d bytes
    Concurrency Level:%d
    Time taken for tests:%d.%03d seconds
    Complete requests:%d
    Failed requests:%d
    (Connect: %d, Length: %d, Exceptions: %d)
    Non-2xx responses:%d
    Keep-Alive requests:%d
    Total transferred:%d bytes
    Total POSTed:%d
    HTML transferred:%d bytes
    Requests per second:%.2f
    Transfer rate:%.2f kb/s received
     %.2f kb/s sent
     %.2f kb/s total
    Connnection Times (ms)
      min avg max
    Connect:%5d%5d%5d
    Processing:%5d%5d%5d
    Total:%5d%5d%5d
    \n"); + } +} + +/* --------------------------------------------------------- */ + +/* start asnchronous non-blocking connection */ + +static 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 { + ab_close(c->fd); + err_conn++; + if (bad++ > 10) { + err("\nTest aborted after 10 failures\n\n"); + } + start_connect(c); + } + } + + /* connected first time */ + c->state = STATE_CONNECTING; + FD_SET(c->fd, &writebits); +} + +/* --------------------------------------------------------- */ + +/* 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 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; + } + } + + 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 */ + + 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; + p = strstr(c->cbuff, "Server:"); + q = servername; + if (p) { + p += 8; + while (*p > 32) + *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_ */ + strncpy(respcode, (part + strlen("HTTP/1.x_")), 3); + respcode[3] = '\0'; + 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; + 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 */ + +static void test(void) +{ + struct timeval timeout, now; + fd_set sel_read, sel_except, sel_write; + int i; + + if (!use_html) { + printf("Benchmarking %s (be patient)...", hostname); + fflush(stdout); + } + + { + /* get server information */ + struct hostent *he; + he = gethostbyname(hostname); + if (!he) + err("bad hostname"); + 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 */ + if (posting <= 0) { + sprintf(request, "%s %s HTTP/1.0\r\n" + "User-Agent: ApacheBench/%s\r\n" + "%s" "%s" "%s" + "Host: %s\r\n" + "Accept: */*\r\n" + "%s" "\r\n", + (posting == 0) ? "GET" : "HEAD", + path, + VERSION, + keepalive ? "Connection: Keep-Alive\r\n" : "", + cookie, auth, hostname, hdrs); + } + else { + sprintf(request, "POST %s HTTP/1.0\r\n" + "User-Agent: ApacheBench/%s\r\n" + "%s" "%s" "%s" + "Host: %s\r\n" + "Accept: */*\r\n" + "Content-length: %d\r\n" + "Content-type: %s\r\n" + "%s" + "\r\n", + path, + VERSION, + keepalive ? "Connection: Keep-Alive\r\n" : "", + cookie, auth, + hostname, 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 = 30; + 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 (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.38 $> apache-1.3"); + printf("Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/\n"); + printf("Copyright (c) 1998-1999 The Apache Group, http://www.apache.org/\n"); + printf("\n"); + } + else { + printf("

    \n"); + printf(" This is ApacheBench, Version %s <%s> apache-1.3
    \n", VERSION, "$Revision: 1.38 $"); + printf(" Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
    \n"); + printf(" Copyright (c) 1998-1999 The Apache Group, http://www.apache.org/
    \n"); + printf("

    \n

    \n"); + } +} + +/* display usage information */ +static void usage(char *progname) +{ + fprintf(stderr, "Usage: %s [options] [http://]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, " -V Print version number and exit\n"); + fprintf(stderr, " -k Use HTTP KeepAlive feature\n"); + fprintf(stderr, " -h Display usage information (this message)\n"); + exit(EINVAL); +} + +/* ------------------------------------------------------- */ + +/* split URL into parts */ + +static int parse_url(char *url) +{ + char *cp; + char *h; + char *p = NULL; + + if (strlen(url) > 7 && strncmp(url, "http://", 7) == 0) + url += 7; + h = url; + if ((cp = strchr(url, ':')) != NULL) { + *cp++ = '\0'; + p = cp; + url = cp; + } + if ((cp = strchr(url, '/')) == NULL) + return 1; + strcpy(path, cp); + *cp = '\0'; + strcpy(hostname, h); + if (p != NULL) + port = atoi(p); + 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'; + optind = 1; + while ((c = getopt(argc, argv, "n:c:t:T:p:v:kVhwix:y:z:C:H:P:A:")) > 0) { + switch (c) { + case 'n': + requests = atoi(optarg); + if (!requests) { + err("Invalid number of requests\n"); + } + break; + case 'k': + keepalive = 1; + break; + case 'c': + concurrency = atoi(optarg); + 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)); + strncat(cookie, optarg, sizeof(cookie)); + strncat(cookie, "\r\n", sizeof(cookie)); + break; + case 'A': + /* assume username passwd already to be in colon separated form. Ready + * to be uu-encoded. + */ + while(isspace(*optarg)) + optarg++; + l=ap_base64encode(tmp,optarg,strlen(optarg)); + tmp[l]='\0'; + + strncat(auth, "Authorization: basic ", sizeof(auth)); + strncat(auth, tmp, sizeof(auth)); + strncat(auth, "\r\n", sizeof(auth)); + break; + case 'P': + /* + * assume username passwd already to be in colon separated form. + */ + while(isspace(*optarg)) + optarg++; + l=ap_base64encode(tmp,optarg,strlen(optarg)); + tmp[l]='\0'; + + strncat(auth, "Proxy-Authorization: basic ", sizeof(auth)); + strncat(auth, tmp, sizeof(auth)); + strncat(auth, "\r\n", sizeof(auth)); + break; + case 'H': + strncat(hdrs, optarg, sizeof(hdrs)); + strncat(hdrs, "\r\n", sizeof(hdrs)); + 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]); + } + + if (parse_url(argv[optind++])) { + fprintf(stderr, "%s: invalid URL\n", argv[0]); + usage(argv[0]); + } + + copyright(); + test(); + + exit(0); +} diff --git a/APACHE_1_3_12/src/support/apachectl b/APACHE_1_3_12/src/support/apachectl new file mode 100755 index 0000000000..978c59b4ab --- /dev/null +++ b/APACHE_1_3_12/src/support/apachectl @@ -0,0 +1,229 @@ +#!/bin/sh +# +# 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 <. +# diff --git a/APACHE_1_3_12/src/support/apachectl.8 b/APACHE_1_3_12/src/support/apachectl.8 new file mode 100644 index 0000000000..72300eb98b --- /dev/null +++ b/APACHE_1_3_12/src/support/apachectl.8 @@ -0,0 +1,133 @@ +.TH apachectl 1 "September 1997" +.\" Copyright (c) 1997-1999 The Apache Group. 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 acknowledgment: +.\" "This product includes software developed by the Apache Group +.\" for use in the Apache HTTP server project (http://www.apache.org/)." +.\" +.\" 4. The names "Apache Server" and "Apache Group" must not be used to +.\" endorse or promote products derived from this software without +.\" prior written permission. +.\" +.\" 5. Products derived from this software may not be called "Apache" +.\" nor may "Apache" appear in their names without prior written +.\" permission of the Apache Group. +.\" +.\" 6. Redistributions of any form whatsoever must retain the following +.\" acknowledgment: +.\" "This product includes software developed by the Apache Group +.\" for use in the Apache HTTP server project (http://www.apache.org/)." +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY +.\" EXPRESSED 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 APACHE GROUP OR +.\" ITS 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. +.\" ==================================================================== +.\" +.\" This software consists of voluntary contributions made by many +.\" individuals on behalf of the Apache Group and was originally based +.\" on public domain software written at the National Center for +.\" Supercomputing Applications, University of Illinois, Urbana-Champaign. +.\" For more information on the Apache Group and the Apache HTTP server +.\" project, please see . +.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://www.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_12/src/support/apxs.8 b/APACHE_1_3_12/src/support/apxs.8 new file mode 100644 index 0000000000..15e5f28199 --- /dev/null +++ b/APACHE_1_3_12/src/support/apxs.8 @@ -0,0 +1,464 @@ +.TH apxs 8 "April 1998" +.\" Copyright (c) 1998-1999 The Apache Group. 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 acknowledgment: +.\" "This product includes software developed by the Apache Group +.\" for use in the Apache HTTP server project (http://www.apache.org/)." +.\" +.\" 4. The names "Apache Server" and "Apache Group" must not be used to +.\" endorse or promote products derived from this software without +.\" prior written permission. +.\" +.\" 5. Products derived from this software may not be called "Apache" +.\" nor may "Apache" appear in their names without prior written +.\" permission of the Apache Group. +.\" +.\" 6. Redistributions of any form whatsoever must retain the following +.\" acknowledgment: +.\" "This product includes software developed by the Apache Group +.\" for use in the Apache HTTP server project (http://www.apache.org/)." +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY +.\" EXPRESSED 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 APACHE GROUP OR +.\" ITS 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. +.\" ==================================================================== +.\" +.\" This software consists of voluntary contributions made by many +.\" individuals on behalf of the Apache Group and was originally based +.\" on public domain software written at the National Center for +.\" Supercomputing Applications, University of Illinois, Urbana-Champaign. +.\" For more information on the Apache Group and the Apache HTTP server +.\" project, please see . +.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_12/src/support/apxs.pl b/APACHE_1_3_12/src/support/apxs.pl new file mode 100644 index 0000000000..83e06793eb --- /dev/null +++ b/APACHE_1_3_12/src/support/apxs.pl @@ -0,0 +1,655 @@ +#!/usr/local/bin/perl +## ==================================================================== +## Copyright (c) 1998-1999 The Apache Group. 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 acknowledgment: +## "This product includes software developed by the Apache Group +## for use in the Apache HTTP server project (http://www.apache.org/)." +## +## 4. The names "Apache Server" and "Apache Group" must not be used to +## endorse or promote products derived from this software without +## prior written permission. For written permission, please contact +## apache@apache.org. +## +## 5. Products derived from this software may not be called "Apache" +## nor may "Apache" appear in their names without prior written +## permission of the Apache Group. +## +## 6. Redistributions of any form whatsoever must retain the following +## acknowledgment: +## "This product includes software developed by the Apache Group +## for use in the Apache HTTP server project (http://www.apache.org/)." +## +## THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY +## EXPRESSED 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 APACHE GROUP OR +## ITS 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. +## ==================================================================== +## +## This software consists of voluntary contributions made by many +## individuals on behalf of the Apache Group and was originally based +## on public domain software written at the National Center for +## Supercomputing Applications, University of Illinois, Urbana-Champaign. +## For more information on the Apache Group and the Apache HTTP server +## project, please see . +## + +## +## apxs -- APache eXtenSion tool +## Written by Ralf S. Engelschall +## + +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; + +# 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 =] -n \n"; + print STDERR " apxs -q [-S =] ...\n"; + print STDERR " apxs -c [-S =] [-o ] [-D [=]]\n"; + print STDERR " [-I ] [-L ] [-l ] [-Wc,]\n"; + print STDERR " [-Wl,] ...\n"; + print STDERR " apxs -i [-S =] [-a] [-A] [-n ] ...\n"; + print STDERR " apxs -e [-S =] [-a] [-A] [-n ] ...\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; + } + eval "\$CFG_${var}=\"${val}\""; + } else { + print STDERR "apxs:Error: malformatted -S option\n"; + &usage; + } + } +} + +## +## Initial DSO support check +## +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 =~ s|%NAME%|$name|sg; + $data =~ s|%TARGET%|$CFG_TARGET|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|\.[^.]+$|.so|; + } + elsif ($#objs > -1) { + $dso_file = $objs[0]; + $dso_file =~ s|\.[^.]+$|.so|; + } + else { + $dso_file = "mod_unknown.so"; + } + } + 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 "; + } + foreach $opt_D (@opt_D) { + $opt .= "-D$opt_D "; + } + my $cflags = "$CFG_CFLAGS $CFG_CFLAGS_SHLIB"; + my $s; + foreach $s (@srcs) { + my $o = $s; + $o =~ s|\.c$|.o|; + $o =~ s|^.*/||; + push(@cmds, "$CFG_CC $cflags -I$CFG_INCLUDEDIR $opt -c $s"); + unshift(@objs, $o); + } + + # create link command + my $cmd = "$CFG_LD_SHLIB $CFG_LDFLAGS_SHLIB -o $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) { + $opt .= " -L$opt_L"; + } + foreach $opt_l (@opt_l) { + $opt .= " -l$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|\.so$|) { + print STDERR "apxs:Error: file $f is not a DSO\n"; + exit(1); + } + my $t = $f; + $t =~ s|^.+/([^/]+)$|$1|; + if ($opt_i) { + push(@cmds, "cp $f $CFG_LIBEXECDIR/$t"); + push(@cmds, "chmod 755 $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('', ); + 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|^[^/]+/||; + } + } + if ($name eq '') { + if ($base =~ m|.*mod_([a-zA-Z0-9_]+)\..+|) { + $name = "$1"; + $filename = $base; + $filename =~ s|^[^/]+/||; + } + } + 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)); + } + + # execute the commands + &execute_cmds(@cmds); + + # activate module via LoadModule/AddModule directive + if ($opt_a or $opt_A) { + if (not -f "$CFG_SYSCONFDIR/$CFG_TARGET.conf") { + print STDERR "apxs:Error: Config file $CFG_SYSCONFDIR/$CFG_TARGET.conf not found\n"; + exit(1); + } + + open(FP, "<$CFG_SYSCONFDIR/$CFG_TARGET.conf") || die; + my $content = join('', ); + close(FP); + + if ($content !~ m|\n#?\s*LoadModule\s+|) { + print STDERR "apxs:Error: Activation failed for custom $CFG_SYSCONFDIR/$CFG_TARGET.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|) { + $content =~ s|^(.*\n#?\s*LoadModule\s+[^\n]+\n)|$1$c$lmd\n|sg; + } else { + $content =~ s|^(.*\n)#?\s*$lmd[^\n]*\n|$1$c$lmd\n|sg; + } + $lmd =~ m|LoadModule\s+(.+?)_module.*|; + print STDERR "[$what module `$1' in $CFG_SYSCONFDIR/$CFG_TARGET.conf]\n"; + } + my $amd; + foreach $amd (@amd) { + if ($content !~ m|\n#?\s*$amd|) { + $content =~ s|^(.*\n#?\s*AddModule\s+[^\n]+\n)|$1$c$amd\n|sg; + } else { + $content =~ s|^(.*\n)#?\s*$amd[^\n]*\n|$1$c$amd\n|sg; + } + } + if (@lmd or @amd) { + if (open(FP, ">$CFG_SYSCONFDIR/$CFG_TARGET.conf.new")) { + print FP $content; + close(FP); + system("cp $CFG_SYSCONFDIR/$CFG_TARGET.conf $CFG_SYSCONFDIR/$CFG_TARGET.conf.bak && " . + "cp $CFG_SYSCONFDIR/$CFG_TARGET.conf.new $CFG_SYSCONFDIR/$CFG_TARGET.conf && " . + "rm $CFG_SYSCONFDIR/$CFG_TARGET.conf.new"); + } else { + print STDERR "apxs:Error: unable to open configuration file\n"; + } + } + } +} + +##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%.so + +# compile the DSO file +mod_%NAME%.so: 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%.so + +# cleanup +clean: + -rm -f mod_%NAME%.o mod_%NAME%.so + +# 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%.so +** +** SetHandler %NAME% +** +** +** 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_12/src/support/dbmmanage b/APACHE_1_3_12/src/support/dbmmanage new file mode 100644 index 0000000000..d176d85748 --- /dev/null +++ b/APACHE_1_3_12/src/support/dbmmanage @@ -0,0 +1,189 @@ +#!/usr/local/bin/perl + +# ==================================================================== +# Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: +# "This product includes software developed by the Apache Group +# for use in the Apache HTTP server project (http://www.apache.org/)." +# +# 4. The names "Apache Server" and "Apache Group" must not be used to +# endorse or promote products derived from this software without +# prior written permission. For written permission, please contact +# apache@apache.org. +# +# 5. Products derived from this software may not be called "Apache" +# nor may "Apache" appear in their names without prior written +# permission of the Apache Group. +# +# 6. Redistributions of any form whatsoever must retain the following +# acknowledgment: +# "This product includes software developed by the Apache Group +# for use in the Apache HTTP server project (http://www.apache.org/)." +# +# THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY +# EXPRESSED 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 APACHE GROUP OR +# ITS 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. +# ==================================================================== +# +# This software consists of voluntary contributions made by many +# individuals on behalf of the Apache Group and was originally based +# on public domain software written at the National Center for +# Supercomputing Applications, University of Illinois, Urbana-Champaign. +# For more information on the Apache Group and the Apache HTTP server +# project, please see . + +#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 + +package dbmmanage; +# -ldb -lndbm -lgdbm +BEGIN { @AnyDBM_File::ISA = qw(DB_File NDBM_File GDBM_File) } +use strict; +use Fcntl; +use AnyDBM_File (); + +my($file,$command,$key,$crypted_pwd) = @ARGV; + +usage() unless $file and $command and defined &{$dbmc::{$command}}; + +# 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 = join '|', qw{bsdos}; #others? + +# remove extension if any +my $chop = join '|', qw{db.? pag dir}; +$file =~ s/\.($chop)$//; + +my $is_update = $command eq "update"; +my $Is_Win32 = $^O eq "MSWin32"; +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; + +sub usage { + my $cmds = join "|", sort keys %dbmc::; + die "usage: $0 filename [$cmds] [username]\n"; +} + +my $x; +sub genseed { + my $psf; + 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 salt { + my $newstyle = $^O =~ /(?:$newstyle_salt)/; + genseed() unless @range; + return $newstyle ? + join '', "_", randchar, "a..", randchar(4) : + randchar(2); +} + +sub getpass { + my $prompt = shift || "Enter password:"; + + unless($Is_Win32) { + 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 $Is_Win32; + 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}; + dbmc->adduser; +} + +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}; + } + $DB{$key} = $crypted_pwd; + my $action = $is_update ? "updated" : "added"; + print "User $key $action with password encrypted to $DB{$key}\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 = crypt $value, caller->salt; + 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}; + print crypt(getpass(), $DB{$key}) eq $DB{$key} ? "password ok\n" : "password mismatch\n"; +} + +sub dbmc::import { + while(defined($_ = ) and chomp) { + ($key,$crypted_pwd) = split /:/, $_, 2; + dbmc->add; + } +} + diff --git a/APACHE_1_3_12/src/support/dbmmanage.1 b/APACHE_1_3_12/src/support/dbmmanage.1 new file mode 100644 index 0000000000..06380ff0f5 --- /dev/null +++ b/APACHE_1_3_12/src/support/dbmmanage.1 @@ -0,0 +1,171 @@ +.TH dbmmanage 1 "March 1998" +.\" Copyright (c) 1998-1999 The Apache Group. 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 acknowledgment: +.\" "This product includes software developed by the Apache Group +.\" for use in the Apache HTTP server project (http://www.apache.org/)." +.\" +.\" 4. The names "Apache Server" and "Apache Group" must not be used to +.\" endorse or promote products derived from this software without +.\" prior written permission. +.\" +.\" 5. Products derived from this software may not be called "Apache" +.\" nor may "Apache" appear in their names without prior written +.\" permission of the Apache Group. +.\" +.\" 6. Redistributions of any form whatsoever must retain the following +.\" acknowledgment: +.\" "This product includes software developed by the Apache Group +.\" for use in the Apache HTTP server project (http://www.apache.org/)." +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY +.\" EXPRESSED 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 APACHE GROUP OR +.\" ITS 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. +.\" ==================================================================== +.\" +.\" This software consists of voluntary contributions made by many +.\" individuals on behalf of the Apache Group and was originally based +.\" on public domain software written at the National Center for +.\" Supercomputing Applications, University of Illinois, Urbana-Champaign. +.\" For more information on the Apache Group and the Apache HTTP server +.\" project, please see . +.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://www.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, +.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_12/src/support/htdigest.1 b/APACHE_1_3_12/src/support/htdigest.1 new file mode 100644 index 0000000000..c719e456ce --- /dev/null +++ b/APACHE_1_3_12/src/support/htdigest.1 @@ -0,0 +1,97 @@ +.TH htdigest 1 "March 1998" +.\" Copyright (c) 1997-1999 The Apache Group. 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 acknowledgment: +.\" "This product includes software developed by the Apache Group +.\" for use in the Apache HTTP server project (http://www.apache.org/)." +.\" +.\" 4. The names "Apache Server" and "Apache Group" must not be used to +.\" endorse or promote products derived from this software without +.\" prior written permission. For written permission, please contact +.\" apache@apache.org. +.\" +.\" 5. Products derived from this software may not be called "Apache" +.\" nor may "Apache" appear in their names without prior written +.\" permission of the Apache Group. +.\" +.\" 6. Redistributions of any form whatsoever must retain the following +.\" acknowledgment: +.\" "This product includes software developed by the Apache Group +.\" for use in the Apache HTTP server project (http://www.apache.org/)." +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY +.\" EXPRESSED 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 APACHE GROUP OR +.\" ITS 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. +.\" ==================================================================== +.\" +.\" This software consists of voluntary contributions made by many +.\" individuals on behalf of the Apache Group and was originally based +.\" on public domain software written at the National Center for +.\" Supercomputing Applications, University of Illinois, Urbana-Champaign. +.\" For more information on the Apache Group and the Apache HTTP server +.\" project, please see . +.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://www.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 given, 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 to. +.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_12/src/support/htdigest.c b/APACHE_1_3_12/src/support/htdigest.c new file mode 100644 index 0000000000..cb98a1147d --- /dev/null +++ b/APACHE_1_3_12/src/support/htdigest.c @@ -0,0 +1,300 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ +/****************************************************************************** + ****************************************************************************** + * 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 +#endif +#include "ap.h" +#include "ap_md5.h" +#if defined(MPE) || defined(QNX) || defined(WIN32) || defined(__TANDEM) || defined(OS390) || defined(BEOS) +#include +#else +#include +#endif + +#ifdef WIN32 +#include +#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(); + 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); + } + strcpy(user, argv[3]); + strcpy(realm, argv[2]); + + 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_12/src/support/htdigest.dsp b/APACHE_1_3_12/src/support/htdigest.dsp new file mode 100644 index 0000000000..f00f87e7e7 --- /dev/null +++ b/APACHE_1_3_12/src/support/htdigest.dsp @@ -0,0 +1,103 @@ +# Microsoft Developer Studio Project File - Name="htdigest" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.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 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 "htdigest" +# PROP BASE Intermediate_Dir "htdigest" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "" +# PROP Intermediate_Dir "" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /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 user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD 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:console /machine:I386 /out:"release/htdigest.exe" +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "htdigest - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "htdiges0" +# PROP BASE Intermediate_Dir "htdiges0" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "" +# PROP Intermediate_Dir "" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /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 user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD 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:console /debug /machine:I386 /out:"debug/htdigest.exe" /pdbtype:sept + +!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_12/src/support/htdigest.mak b/APACHE_1_3_12/src/support/htdigest.mak new file mode 100644 index 0000000000..0f048e7d39 --- /dev/null +++ b/APACHE_1_3_12/src/support/htdigest.mak @@ -0,0 +1,297 @@ +# 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=. +INTDIR=. +# Begin Custom Macros +OutDir=. +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\release\htdigest.exe" + +!ELSE + +ALL : "$(OUTDIR)\release\htdigest.exe" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\ap_cpystrn.obj" + -@erase "$(INTDIR)\ap_getpass.obj" + -@erase "$(INTDIR)\ap_md5c.obj" + -@erase "$(INTDIR)\htdigest.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\release\htdigest.exe" + +CPP=cl.exe +CPP_PROJ=/nologo /ML /W3 /GX /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D\ + "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\htdigest.pch" /YX /FD /c +CPP_OBJS=. +CPP_SBRS=. + +.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) $< +<< + +RSC=rc.exe +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\htdigest.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=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:console /incremental:no\ + /pdb:"$(OUTDIR)\htdigest.pdb" /machine:I386\ + /out:"$(OUTDIR)\release\htdigest.exe" +LINK32_OBJS= \ + "$(INTDIR)\ap_cpystrn.obj" \ + "$(INTDIR)\ap_getpass.obj" \ + "$(INTDIR)\ap_md5c.obj" \ + "$(INTDIR)\htdigest.obj" + +"$(OUTDIR)\release\htdigest.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "htdigest - Win32 Debug" + +OUTDIR=. +INTDIR=. +# Begin Custom Macros +OutDir=. +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\debug\htdigest.exe" + +!ELSE + +ALL : "$(OUTDIR)\debug\htdigest.exe" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\ap_cpystrn.obj" + -@erase "$(INTDIR)\ap_getpass.obj" + -@erase "$(INTDIR)\ap_md5c.obj" + -@erase "$(INTDIR)\htdigest.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\debug\htdigest.exe" + -@erase "$(OUTDIR)\debug\htdigest.ilk" + -@erase "$(OUTDIR)\htdigest.pdb" + +CPP=cl.exe +CPP_PROJ=/nologo /MLd /W3 /Gm /GX /Zi /Od /I "..\include" /D "WIN32" /D\ + "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\htdigest.pch" /YX /FD /c +CPP_OBJS=. +CPP_SBRS=. + +.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) $< +<< + +RSC=rc.exe +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\htdigest.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=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:console /incremental:yes\ + /pdb:"$(OUTDIR)\htdigest.pdb" /debug /machine:I386\ + /out:"$(OUTDIR)\debug\htdigest.exe" /pdbtype:sept +LINK32_OBJS= \ + "$(INTDIR)\ap_cpystrn.obj" \ + "$(INTDIR)\ap_getpass.obj" \ + "$(INTDIR)\ap_md5c.obj" \ + "$(INTDIR)\htdigest.obj" + +"$(OUTDIR)\debug\htdigest.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + + +!IF "$(CFG)" == "htdigest - Win32 Release" || "$(CFG)" ==\ + "htdigest - Win32 Debug" +SOURCE=..\ap\ap_cpystrn.c +DEP_CPP_AP_CP=\ + "..\include\alloc.h"\ + "..\include\ap.h"\ + "..\include\ap_config.h"\ + "..\include\ap_ctype.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"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_AP_CP=\ + "..\include\ap_config_auto.h"\ + "..\include\ebcdic.h"\ + "..\include\os.h"\ + "..\include\sfio.h"\ + + +"$(INTDIR)\ap_cpystrn.obj" : $(SOURCE) $(DEP_CPP_AP_CP) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=..\ap\ap_getpass.c +DEP_CPP_AP_GE=\ + "..\include\ap.h"\ + "..\include\ap_config.h"\ + "..\include\ap_ctype.h"\ + "..\include\ap_mmn.h"\ + "..\include\hsregex.h"\ + "..\os\win32\os.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_AP_GE=\ + "..\include\ap_config_auto.h"\ + "..\include\os.h"\ + + +"$(INTDIR)\ap_getpass.obj" : $(SOURCE) $(DEP_CPP_AP_GE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=..\ap\ap_md5c.c +DEP_CPP_AP_MD=\ + "..\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"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_AP_MD=\ + "..\ap\ebcdic.h"\ + "..\include\ap_config_auto.h"\ + "..\include\os.h"\ + + +"$(INTDIR)\ap_md5c.obj" : $(SOURCE) $(DEP_CPP_AP_MD) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +SOURCE=.\htdigest.c +DEP_CPP_HTDIG=\ + "..\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"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_HTDIG=\ + "..\include\ap_config_auto.h"\ + "..\include\os.h"\ + + +"$(INTDIR)\htdigest.obj" : $(SOURCE) $(DEP_CPP_HTDIG) "$(INTDIR)" + + + +!ENDIF + diff --git a/APACHE_1_3_12/src/support/htdigest.mcp.gz b/APACHE_1_3_12/src/support/htdigest.mcp.gz new file mode 100644 index 0000000000000000000000000000000000000000..a2c23f218af93689e2e78f25aa6628fa1e9f04f9 GIT binary patch literal 10565 zcmX|{1yCGa(5}&70fGmIh2Rq0*$~_lf&~HuC%C(l;Jy$b$R^n0?oNP3!{QoX@c@f2 zZg;=`{`XGRJk$N2o<4o5rfSY~4PzWGE*+n@I2xv%r_~o*YY$I8Crei}L@r?M#!@Gs4HKmf^|Q6jN2r7FJJ9)!{z0@%iD{=7Mmv!;k$t9JdkXOIO{M196RF z2jKdwax&#{Aju`LiHVQjA;o3V+@pR*LppcGU>Y_c8y_2x6G-&w7}9Oy?Q^;4cXRx7 z14E3R6AW6QXRxZ4Td6MjRq~kl&}-_dPgx>!Hr&wm(Pp&V7Uqnhlo-|+hIp5%?>Q24fbDvsP-A&CeyaEYNSr=ZVUZ%{YRSKE950wxFf7;S;PwCQRT_t-a z5zvwfZ{em2{vMVNN$J-a6?^ueY^3m>apA7YlU!T2C-I)_lzicF@)6*Hcdx#%n>i>9 zX)<-C0!!`EzBQN z6H}+^bT7iI?p~G1kudBtyJe$m=n!uWsrd`IamtwD~ zStzMPus2VB(7doK{D6aSxjkTOEFfSL0ci;@&3~mK8Z2CW_g39Ma`rTuMpMoBS+gf0 z(i7=;kn&7PW>xF>he+O@$NWYZtQz~?{Cv`mLvkzqq`S=T7I10^;Jk=}#;XQZ_0|s0 zMBNU0DfE$a98?IM=0JetD+O$3RtXg?B5widRrFdu2yQ(g56ZBdOQc zYw&LpcY}c=v_uJBUjc4;Z(Q+T=Ha_fq{MvPC$_(RzH^Sw`9(UemF4kWT3#%IkTrFk zD3;kI^c!u$tKV||c}?LzaIuj|)6JU|w#Woq$F(X~!zI$VvJQ7SqAF#=eelM*#Qt1A0{BvG1END72t|#jmee?#uUQr!_3Y?1vc+j)DrS| z?k)sH9|{^u80s4u9BLhUKV&=bn3)l9#eB@t%o4?{&D`wI${@v*#L^6a zm`jHS6I#C50&Yoe8E$EKNQZxl?}%|DfN~Di5B(ade~H6n0MND=3;pz|_GjfjT|BmT z%2B^s`^{+}oigpBygwmrPhZlm{9NgaKLD|r%Aw1$G1H)MeL!J2#r&`jKU5$d)oJ#FcHmJVS zpBH^UsMgGq`U5cT_#W~&YGea!04~m-hL=osG;WkUL-U5LH8z(W7})cEkUHd^GK7li zeAd`3DVfMzedPwjd~G47JT0EjAy6z(#xGJlNi!P%rJ>*5l7>aQ9;fGD-Bc!2rD-G+ zYS*-s35~9UW)x8NPEy>Fzfxf>Jbw^< z4pv9>y@Z0tUasw9%kRzjv#wZu-|ei@2I}qP(MV?r3f||9b=Gtx3SLdYDY60#>AwkK zmb@3257qw`V0Bfkf4hV z-(uhh4SUh^*(u`Bl>(p&oSs4nos`&rXwom@`lZ-x1P%_*gWp17+2{Eyb}3L6{LZq8 zYx!SpQExX12juflzrEeW$1YIvAdh)WV`vvh^oP{a{ejwk?ua;?wY%@^@$H)PjXwqX zLCH5;pKW@@N4iwz9a9@nAx$zj0PG|8PSq zsa6m3yyn;nsyMc3;Nl+4Qa1K2wg5c|c8ekAh4l_Hk?cE4i>tfm&*Po1PPx)(%ZHpG zzU9@`5u*D?6Uh6x&va-*xBlZ!arIq7LN2eDgL`v|nll@f>&&pfa?!ja+bpwnwGXp3 zTUGSD34Dm&`QCOX=1hRV!*;83_FUM_1-(gYKC3`?_2?2oGtKC(NgUYc8l#th5E}8{ z*{rtJP{??f$Sg`Nta#MzZXH#n@ZD}6oG0cuJ~dfBQ_Ki*fsS1Tnf&t!DZP_(+ffC39XJE6Ga&fTw zHl-f1SO1T4=O+ITz2%Q(_B->e-@Ew<^Uosh{CCFr4L@qIf=<11b3rq)k`1MHIP`5^ zP_kOME>o$O*0U?myh%4D+t-v6k`JfvAVD1kgc%P!+|PulZ08~5<3S&5HeT)>A6C75 z2Z~uR6{%G||A}r*TfqNAm+ZaB-dlqKFpvJJcVj+~UyzO|vf4H(4zIx&J$=F#MA z{V_$Fc>iC8%@ORq^YX$P{qsXS4JfH>wTrKAA@pYW2#yEz*}9RkAXriE`KxU(sTJb5 z{Cl$yDgv6?%H9`?$7Wa;_Sm zo8l}Ax_^3;#6CkBTVrv*tT$;X%6bG8AHK%t;l22c_x*Xj$w@0~LtK$5px3>}k?Iq- zdP-A2--kYP*oiJ(I;~IPr$J}w#u)-0aX?{1+y(wF$>SiQ)!_G|KT`Ptjqp5r=1wT2 z>3_yE5A*xGOio-qabnZ)6TQZ~-|sh=@LXUJB)+txvc7dId&5)%8E=6Rbi>FYKNgW)!I3X9RHtKIYwV4(2bM^LdC17%fa5X0FE15T9Z6{}~`ZB|=$V3z;SfO79s8ET+fuVVj} z(EtTv4pc}rHwwEH`C^0weHYrXmINoxwK&NUQ*peQ%w4+_=p zs7bXwP*DDhx}CFG&*Vw}KQRA?c4t(!aukB!=b_v*X_SlYhl-Q=542~f>{mMdA9~M_?nUaAb{p9^K$E7?)?5{8TmbjILC5IE;3jR$>IMTFe3H;bCtdtHM7s z-=T+d6D$(E`1^h+I2iu;_7ZOf*qki$&_hhHXz-##Z%8)cXL0m{VNaVL@b3L@(+GGWsW;9fu>5N$=>?3- z94znZg%`jW4oj~A{_5g;h48@**8ja4Em?#x!`0%kUX!0N9_fnlzt`~wpwFk*5d&Jv z(}IY4K}CO`_D|IpT}aY0Y8e6Ijqx&My~To;a#-tvmq0ABj9PZUwLA44WjJG6EivHQ zi#mX9e;JY!MA)0Pjflc+`d$wPEEtUEMZxFXy>-xuzt=x8`&Q+2l3ZMGBl>WcxE9z+ zatwM+W8oY4m&#ZMx;2b!*Phq`R^iopt_)L~1~vR_zD41k5j~7t3%jJkdUZfH@%GdQ zk+AAidb3cY;ovOznc8LF%zSxjr(o|c_hJTFV0&tiP_H)EqA^*=M^wPiw%7;GUTQrA zIv!tzMTn;B7m7QMaAG|-E$l1ZS{#6HN9+SduXg!DR0=TE#Qu$gNPs~2dD)^ENk{vS z2eMvI5mb0~`Qj)^VCj!e+TN@3MFh=ruBpuC> zCLTSxBGR&GNpm&YEZ6S|131Fh=4*f~cGcF5%C5n@0b=_HI-{nE{`W?gCRpGK>nFt% z72dno;kyotmCBIBPR1}uVi3cHlipx(0$j!m@ql|dOU;njU+INl$786lgejkB&?kBI zRPQe|lM2t)`>=^a@*aeH2QCmVu~IJ(zwl&rV8Pk&BmYY%)>?@zQ1e7b=FT3YHB3gN z7mpCph}TB5;6e6js>hN)$b@ELknHbNPhK{hfDkc?cPUmw%vKQvb=x4FE)lKF#pz`Os0xWKD& z-VxxwRuBpZ3$GTgU*qtt%?gt1W&E*7OWx2>^Tg&GKoAfZ-b;CjhE2wcfZJiLKvU8^yUW0W~d#Z-`zB zV^4}+Dq|Zo*LHKZbS4C8_EIe`)RPC+Cj`CgJ$FI`;IG#?|S* zVt*&LdvZ=JPX|M6D!zBvcdgmV=oml6Cc(uDPmgX<9{Am%Jka`Ho#x;=OEarYb0CP4 zlKVlHz>Uv2xc`AYe6a#~r~OsF7W)=^(gXkNS`8BwZnt@gnGVT~BAP-l$reV6SwFvB zRMhqf!BXu9boQ(CpG{7PW1`4QEH+C#@VuBb*SG_o4GRhy{ccfc(VIkad@ly+{Y`in za`&I8TrMuW`pN!hds-0< zZqB}ZhhCd1Uut!xSL=qJgtn)09Dn`L2}aoGB9=NzahiJlFi$(mY_FuSFmZJ^algiL;61hc?;W%4dxTh#pr7#hiCBvw?XIKsVir`QISyy+xjG- zx=PzZmSn%;u=h#L)9p5zw~eW+iS;&`ZS(bUAiuDj!C^p z>7Rgso5oOJ4)cq_Q(L5y4+DF$+aJ1$c|DsP4cpT~;X>lKf)r7W^+ z-KSs&ZX2fyhPN5HHR?(7caACCO#~U8Mbrxabotv;`j1w-66iO7tz_9O&4^ebVjAYR zD%Tb^muCd1Vb_G7q_#d5sT-_1U#YP@AwHr_Z#%78ON!Qhx2to^UQ z#{K*{ctjio@-7*~`}$xM84ME4DLDA#ar!W|sbTXdJUA*u4a?-B=Z9@Gx07Tao}JWY zz;-pKokV%t8H7eH`HdQHc8AXvxSevW7pEm;=2YADKQbIFK;3*RENKVVYZHU$YzHO1 z-4cc-Q4CCUlvjxE6_i+^E<7C|j zDYY&$7;LHOjpHNpZFBdsWPO}|XncHSJ$tV6)AQVF_IwHIw(!3gbelV08o(=yWB6)2 zdtPjo#{&~|Qm5r;uh;N)qq7M|9;BPF)x=qzKNN@~v1vyp#Igo8?4gGdOl3Bnywp3R zAGN87tPwwTl#;298iJA}#6|aBk1tr=8srWvqMCtwtg*VsB@lV?_PO;!hzA4vIfg_M z=%zg9|2`tadfGl;p=CsKaRFoT4{D-rl%2T}S{$j_hh*wJ{yBSvI6gI~_mV5S+lkq@ z|5(gPesetoyMc_0f-&-#(m%&eoZXadl#}eA8|mr5(Us-DaN75d=E2|Z24v4u?&5;j zW?aRa#{YkB&2$9&$El+M(@%SvgjEpP&Igvq{+1ue=jFpz9Foqm%e46AdFUb1d1rqk zOW%qA+so2oyWjcH<}lv!KOmFP#wQ&{6xd?R^3b44!t3uywVQx}$bE zMhm{JH$BQCDnYgSCq+iiMTiKtqffbbr{(NRj*OMqm%34D}+8vg2 zjBCr36y?Sg)z|IO?=wi^O1CQaTN_t&Ug$&ptjx5G&|Sk2ex85Rs}Q{p(;pu6ytI!I z!r7u5oUAnxQ#@KoR?D19zYmu3v<3=a$#|Uzn`_Rm`k&Ra-QxQM(+Y1!dmHDqU{6?}+Q2_Y zJtq*6N3<%%`<2eM?C=KO@WP|7l@pSG(<{P}#HHm)^s1)1OWfbN%u)Hn=2xf;e69d!`ZfgGK_ug9awW!#nN? z7-Fx@_phAP46djAf|k%sH1h4IpA^5nB~^tf6W+a=z%dUK{S;T{DW{=E#>W7VLEsOo z`btJ~OuWIWG<`d>@2%jtl7Qcpt*HCaWDLU!Y&*p3I{s^-?_U0w9@)ep(vBG@1IftA zo0i111Xh;xPA|HOClGp3i#pZ=Rc)4eTE=}O=8#pe`tbyIeIf4Vuxv2PsIq7yrOk*t zR6$yJChyUC&UG2~`}=GK2#XVZNb-BMovV*PH0oZJTC3c%y}bJQnI_h-fuBc#D(6 zB~BCOC9j70{*W&1+Id$=w7z{H;+rhF42SNxGlh(#l6(~{iKjQ%70o;Q-yjQltlWIe zQkx=OTTmMAO2zoMyL?m6Bwuf^`Aub*CNJNgXvsmEgpwxSxo9=FS*00??=Ix~2+70} zpUzL_uLeuqt2P$$t&M-yng~=4N8|7Q2s@vd`yF#WgaAaHGkqKB+Gn7 zS~=<4z(S!n4HZl#8=T@QwWQ`4vMk+3);6eNNIa(_uj3(S-Iyh!IaL!$sUy*S$4QIM zp2d^?Lo1LB@pU7~`y>+hu2gq&WU4%RK+535XyMvf{~I$~;f{QM8m|`yl6$nTa3HUyj8`P0rC#XW5`G=1d$1lnK`>FE^@0LbG z1K+1D%|b`=K=B)nlEZlNG&Pu@{+U75RO@RH@DrR3l3W779BwGEMiywYlVV>YN zc`2KwfS>)aj+#tq@~bSz@by&JLXpX96+M zor|<(ef!0;BEqOzi7*X}z5QeDJiQME-So|pA``|dS^r8^FJH|)_q>GIx6OYt^iaFt z6mcNUE&Y*bRk7pREc)a=w(k6fDaxc{RRonfnAMP#U`vGxDDhfxVS@Nl20Ke$MTH-V zjs0^|`m9U)vv;E`f-B1;m$;qFrg%4h6oS{AV**sjFreV%EO z@EM|dsAb^|xvL>yO@70s74CDomk+cxaSZa43z2|u-pFb)feh=+B#pEG5zN1ml5A(Y z{DOUO&lmx&5r^)xxV-mJ_gJZm+>g{Nd(~(w!tKvj4jt862d~2j3u!;gH`YPnEB3ZVD&cgA5M|RQi4K ze|Ieev5t)0#2N3??nLd*&sUaM0s-n&)tMnJv?5_TZ}3$;^5-uw->TgLM!#>bTQ%-D zV6_^MFBPT=D+0Xy#6JW`XN|>y6*X54#t&OdyFof!37RP#*QI71f{Zeg46-io<1!}e zhSXq}6+Fz~f9VG4o6g9*;J_oL~L0fYLPAMV7Z7J+c( zi?!Rb`j?s5wAlG|rqvW%`t)H%0B*k(6%`2{_f;M#a;_uM()NWZZL@Sg z2d*61p0DH`6&}3XYnO=-sHV=g4HygHKl*ko$_e(Q5E=~N_x|FZO?TXx7R+W{bRJM$ z&{0Nr>?Qqh-7$ZP+&niOTu$l^pyvmY1yvU~!y0mqcxQs$+nZ0$Kv5)Bwbr$}YX8ax zcoPyBvLqLkM(B=t(^AGySATz-B=d1uhoDLT{adxLuJBneHFu^Z&!$s$FY6df8DWEr z9PAC+ZeJib>(Bh}P7VAz?<-;w14#2eZ0j|%59$@`sVTQs3i{ogN|2URb2q2-j3y~R z3IL&|QqH2q;1Y*GPxeXjG)k&=)Q6MrSmPTvAr&g60E4mbvn#R>6-Nx!jDKIMRe`t5 zr}j)c7SghOi#goKSj?UwMa2sauG%`StKL_d5Hu%IE7n^~C122wQb= zi77CzYKL;Xi{sS=NH^!fE(rF2*(Yb1>d@03>0uG?dZedUU2A+-)Ck1k+&5R97Kc zp!y`Cq>dJn(Fe{$8R%1)G5=>8??wZ??}I8ju>U@%`0B1L7(K}~7?+(^9Vx~xaOWEp zYEVnCR`(xgHVreU^>+eA@2ULlULO58~r+u{500xLj(YG{I8w!QWR*6uNM)H;pG@ zi~;0cEh!v>Y!&b!xU;%_T@cl(&Po>l`QV?>7iOXzN%5So4c{&tnVST|2S zu_P9n`R(nKPpc9v{WSN>&hk$_UI{N8&O{Dak=+T4gJ?->iH|OwA(@5|hXp7ox~4GbYgESv;iR>6CV4rm7^8g433qbwx5JF{Lw?|=?2c z=WIiS)N7A&?~Q(#V)=StZ&+!>5$lh$I!Tjf(CnV_k0}*_F?VH=9onNFW zrtjU#%iY|V=POv(mIMOh#7_WC)Q=blnt1t@FyRM2I5-GnGiNFF*Ba(M(&Xi?l6U7C zPM|6w^rpb%%PnS)+2XfH;wsq0pU~sAZ>Jjc8q)`8!2b2C&g5caH1H!Uw3RjI7ZBsV z$2s11nS$D127c^*{f1561uf?ue^c63GjbL8B+d5qxKCa1BK~y+$}%uZ`?ZX=cJ&;3 zv;Kwp*0P7{uvZ*B_5If}y7p18I4gCCGe+P8L;ShN2O*?Q5C0RY7$mKrC+-OdJRrVy z*7=={aLTTJK}0; zK*4t~DdH*>NR%Sb(Dv^`-xgoFjH9e85uBZ$n#~9Ev6{ZZSw0us=@I=G(|1Rq z;D9ht$vyh7!>KvLs9w(%BMsmRJ&>2>KHJsAfbk{Z3NtvA&~-&W=L%Igx~XC8eQAhq zv^3gv*CN!Ikgy|e;6|>8e;s-i6av%;Cb|Y$i?6}gf{}?`1teo)zJbmZ<6^!Yo}wt; zLtp<#+wGkWbr+bXn4Ogv{HcF-c#U0zC9*9Ch;w(4xI*KHe^Tx4dl*6EM|0B4Xz|$P z6{i$T=o?!O5{eZ*V+`( zUI?_!ZF!o;5ATFusn+?vOPz%u^YO;Vb(LbVDy1`Yu-QU}Gem=>8#|DUDoXi4jC|vY|8yrmx$@ai_M60>yz%O=|69$Gr-Ouf} zWO}mW1hg|8r-trA*+=Y}9s|o&Swhh7XM}1W5!aPUvS|0y?|)PRrFNo*%+QayptsYH z$_atE*HICMw$6vMLvlUfoEWb!n@%(mSl1(<+DD!${FEfL5GP8g$GI$TJK*e+XY0Hy zTi7BDQ~^KRC0=@!@f=x+tZUkW@D3P>6Lh%Jn+Q**cI9Tl!XFtiY^R(t`)SJklzCYxd`)bd=1Y z))`bUza`$&T+w&GUq+m=7b=z)adE#k`qt_h{7V1xs?2LC1skJF1IyKmx)yrk>m9#L zpFKu&>5gMLk` z{>3}+=I8@W7UuPQb&vD|*(MAx6qXs`7I2h7Q;HS1D^2IKx>l0H)ieF+j^FwaNTUDv O$Ows6?2O7nNBciebV|ek literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/src/support/htpasswd.1 b/APACHE_1_3_12/src/support/htpasswd.1 new file mode 100644 index 0000000000..58b6b338c1 --- /dev/null +++ b/APACHE_1_3_12/src/support/htpasswd.1 @@ -0,0 +1,225 @@ +.TH htpasswd 1 "February 2000" +.\" Copyright (c) 1997-2000 The Apache Group. 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 acknowledgment: +.\" "This product includes software developed by the Apache Group +.\" for use in the Apache HTTP server project (http://www.apache.org/)." +.\" +.\" 4. The names "Apache Server" and "Apache Group" must not be used to +.\" endorse or promote products derived from this software without +.\" prior written permission. For written permission, please contact +.\" apache@apache.org. +.\" +.\" 5. Products derived from this software may not be called "Apache" +.\" nor may "Apache" appear in their names without prior written +.\" permission of the Apache Group. +.\" +.\" 6. Redistributions of any form whatsoever must retain the following +.\" acknowledgment: +.\" "This product includes software developed by the Apache Group +.\" for use in the Apache HTTP server project (http://www.apache.org/)." +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY +.\" EXPRESSED 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 APACHE GROUP OR +.\" ITS 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. +.\" ==================================================================== +.\" +.\" This software consists of voluntary contributions made by many +.\" individuals on behalf of the Apache Group and was originally based +.\" on public domain software written at the National Center for +.\" Supercomputing Applications, University of Illinois, Urbana-Champaign. +.\" For more information on the Apache Group and the Apache HTTP server +.\" project, please see . +.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 +.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 be used +when the usernames are stored in a flat-file. 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 . +.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. +.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 +onm 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_12/src/support/htpasswd.c b/APACHE_1_3_12/src/support/htpasswd.c new file mode 100644 index 0000000000..23d0941ed6 --- /dev/null +++ b/APACHE_1_3_12/src/support/htpasswd.c @@ -0,0 +1,589 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/****************************************************************************** + ****************************************************************************** + * 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 +#endif +#include +#include +#include "ap.h" +#include "ap_md5.h" +#include "ap_sha1.h" + +#ifdef WIN32 +#include +#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; + +/* + * 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 (>%d)", + 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, " -c Create a new file.\n"); + fprintf(stderr, " -m Force MD5 encryption of the password" +#if defined(WIN32) || defined(TPF) + " (default)" +#endif + ".\n"); + fprintf(stderr, " -d Force CRYPT encryption of the password" +#if (!(defined(WIN32) || defined(TPF))) + " (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 and TPF 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 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 == '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(); + } + 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 (>%d)\n", argv[0], + 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 (>%d)\n", argv[0], + 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) + if (alg == ALG_CRYPT) { + alg = ALG_APMD5; + fprintf(stderr, "Automatically using MD5 format.\n"); + } +#endif + +#if (!(defined(WIN32) || defined(TPF))) + if (alg == ALG_PLAIN) { + fprintf(stderr,"Warning: storing passwords as plain text might " + "just not work on this platform.\n"); + } +#endif + /* + * 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 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); + } + + /* + * We can access the files the right way, and we have a record + * to add or update. Let's do it.. + */ + tempfilename = tmpnam(NULL); + ftemp = fopen(tempfilename, "w+"); + if (ftemp == NULL) { + fprintf(stderr, "%s: unable to create temporary file\n", argv[0]); + 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_12/src/support/htpasswd.dsp b/APACHE_1_3_12/src/support/htpasswd.dsp new file mode 100644 index 0000000000..7949d7f7e8 --- /dev/null +++ b/APACHE_1_3_12/src/support/htpasswd.dsp @@ -0,0 +1,119 @@ +# Microsoft Developer Studio Project File - Name="htpasswd" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 5.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 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 /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "WIN32_LEAN_AND_MEAN" /YX /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 user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ws2_32.lib /nologo /subsystem:console /machine:I386 + +!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 /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "WIN32_LEAN_AND_MEAN" /YX /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 user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "htpasswd - Win32 Release" +# Name "htpasswd - 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=..\ap\ap_snprintf.c +# End Source File +# Begin Source File + +SOURCE=..\ap\ap_sha1.c +# End Source File +# Begin Source File + +SOURCE=..\ap\ap_checkpass.c +# End Source File +# Begin Source File + +SOURCE=..\ap\ap_base64.c +# End Source File +# Begin Source File + +SOURCE=.\htpasswd.c +# End Source File +# End Target +# End Project diff --git a/APACHE_1_3_12/src/support/htpasswd.mak b/APACHE_1_3_12/src/support/htpasswd.mak new file mode 100644 index 0000000000..fa69fcd350 --- /dev/null +++ b/APACHE_1_3_12/src/support/htpasswd.mak @@ -0,0 +1,550 @@ +# 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 + +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "htpasswd - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\htpasswd.exe" + +!ELSE + +ALL : "$(OUTDIR)\htpasswd.exe" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\ap_cpystrn.obj" + -@erase "$(INTDIR)\ap_getpass.obj" + -@erase "$(INTDIR)\ap_md5c.obj" + -@erase "$(INTDIR)\ap_snprintf.obj" + -@erase "$(INTDIR)\ap_sha1.obj" + -@erase "$(INTDIR)\ap_checkpass.obj" + -@erase "$(INTDIR)\ap_base64.obj" + -@erase "$(INTDIR)\htpasswd.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(OUTDIR)\htpasswd.exe" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /ML /W3 /GX /O2 /I "..\include" /D "NDEBUG" /D "WIN32" /D\ + "_CONSOLE" /D "_MBCS" /D "WIN32_LEAN_AND_MEAN" /Fp"$(INTDIR)\htpasswd.pch" /YX\ + /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\Release/ +CPP_SBRS=. +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\htpasswd.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib ws2_32.lib /nologo /subsystem:console /incremental:no\ + /pdb:"$(OUTDIR)\htpasswd.pdb" /machine:I386 /out:"$(OUTDIR)\htpasswd.exe" +LINK32_OBJS= \ + "$(INTDIR)\ap_cpystrn.obj" \ + "$(INTDIR)\ap_getpass.obj" \ + "$(INTDIR)\ap_md5c.obj" \ + "$(INTDIR)\ap_snprintf.obj" \ + "$(INTDIR)\ap_sha1.obj" \ + "$(INTDIR)\ap_checkpass.obj" \ + "$(INTDIR)\ap_base64.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 + +!IF "$(RECURSE)" == "0" + +ALL : "$(OUTDIR)\htpasswd.exe" + +!ELSE + +ALL : "$(OUTDIR)\htpasswd.exe" + +!ENDIF + +CLEAN : + -@erase "$(INTDIR)\ap_cpystrn.obj" + -@erase "$(INTDIR)\ap_getpass.obj" + -@erase "$(INTDIR)\ap_md5c.obj" + -@erase "$(INTDIR)\ap_snprintf.obj" + -@erase "$(INTDIR)\ap_sha1.obj" + -@erase "$(INTDIR)\ap_checkpass.obj" + -@erase "$(INTDIR)\ap_base64.obj" + -@erase "$(INTDIR)\htpasswd.obj" + -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(OUTDIR)\htpasswd.exe" + -@erase "$(OUTDIR)\htpasswd.ilk" + -@erase "$(OUTDIR)\htpasswd.pdb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP_PROJ=/nologo /MLd /W3 /Gm /GX /Zi /Od /I "..\include" /D "_DEBUG" /D\ + "WIN32" /D "_CONSOLE" /D "_MBCS" /D "WIN32_LEAN_AND_MEAN"\ + /Fp"$(INTDIR)\htpasswd.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c +CPP_OBJS=.\Debug/ +CPP_SBRS=. +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\htpasswd.bsc" +BSC32_SBRS= \ + +LINK32=link.exe +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib ws2_32.lib /nologo /subsystem:console /incremental:yes\ + /pdb:"$(OUTDIR)\htpasswd.pdb" /debug /machine:I386\ + /out:"$(OUTDIR)\htpasswd.exe" /pdbtype:sept +LINK32_OBJS= \ + "$(INTDIR)\ap_cpystrn.obj" \ + "$(INTDIR)\ap_getpass.obj" \ + "$(INTDIR)\ap_md5c.obj" \ + "$(INTDIR)\ap_snprintf.obj" \ + "$(INTDIR)\ap_sha1.obj" \ + "$(INTDIR)\ap_checkpass.obj" \ + "$(INTDIR)\ap_base64.obj" \ + "$(INTDIR)\htpasswd.obj" + +"$(OUTDIR)\htpasswd.exe" : "$(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) $< +<< + + +!IF "$(CFG)" == "htpasswd - Win32 Release" || "$(CFG)" ==\ + "htpasswd - Win32 Debug" +SOURCE=..\ap\ap_cpystrn.c + +!IF "$(CFG)" == "htpasswd - Win32 Release" + +DEP_CPP_AP_CP=\ + "..\include\alloc.h"\ + "..\include\ap.h"\ + "..\include\ap_config.h"\ + "..\include\ap_ctype.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"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_AP_CP=\ + "..\include\ap_config_auto.h"\ + "..\include\ebcdic.h"\ + "..\include\os.h"\ + "..\include\sfio.h"\ + + +"$(INTDIR)\ap_cpystrn.obj" : $(SOURCE) $(DEP_CPP_AP_CP) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "htpasswd - Win32 Debug" + +DEP_CPP_AP_CP=\ + "..\include\alloc.h"\ + "..\include\ap.h"\ + "..\include\ap_config.h"\ + "..\include\ap_ctype.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"\ + + +"$(INTDIR)\ap_cpystrn.obj" : $(SOURCE) $(DEP_CPP_AP_CP) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\ap\ap_getpass.c + +!IF "$(CFG)" == "htpasswd - Win32 Release" + +DEP_CPP_AP_GE=\ + "..\include\ap.h"\ + "..\include\ap_config.h"\ + "..\include\ap_ctype.h"\ + "..\include\ap_mmn.h"\ + "..\include\hsregex.h"\ + "..\os\win32\os.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_AP_GE=\ + "..\include\ap_config_auto.h"\ + "..\include\os.h"\ + + +"$(INTDIR)\ap_getpass.obj" : $(SOURCE) $(DEP_CPP_AP_GE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "htpasswd - Win32 Debug" + +DEP_CPP_AP_GE=\ + "..\include\ap.h"\ + "..\include\ap_config.h"\ + "..\include\ap_ctype.h"\ + "..\include\ap_mmn.h"\ + "..\include\hsregex.h"\ + "..\os\win32\os.h"\ + + +"$(INTDIR)\ap_getpass.obj" : $(SOURCE) $(DEP_CPP_AP_GE) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\ap\ap_md5c.c + +!IF "$(CFG)" == "htpasswd - Win32 Release" + +DEP_CPP_AP_MD=\ + "..\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"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_AP_MD=\ + "..\ap\ebcdic.h"\ + "..\include\ap_config_auto.h"\ + "..\include\os.h"\ + + +"$(INTDIR)\ap_md5c.obj" : $(SOURCE) $(DEP_CPP_AP_MD) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "htpasswd - Win32 Debug" + +DEP_CPP_AP_MD=\ + "..\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"\ + + +"$(INTDIR)\ap_md5c.obj" : $(SOURCE) $(DEP_CPP_AP_MD) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\ap\ap_snprintf.c + +!IF "$(CFG)" == "htpasswd - Win32 Release" + +DEP_CPP_AP_SN=\ + "..\include\alloc.h"\ + "..\include\ap.h"\ + "..\include\ap_config.h"\ + "..\include\ap_ctype.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"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_AP_SN=\ + "..\include\ap_config_auto.h"\ + "..\include\ebcdic.h"\ + "..\include\os.h"\ + "..\include\sfio.h"\ + + +"$(INTDIR)\ap_snprintf.obj" : $(SOURCE) $(DEP_CPP_AP_SN) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "htpasswd - Win32 Debug" + +DEP_CPP_AP_SN=\ + "..\include\alloc.h"\ + "..\include\ap.h"\ + "..\include\ap_config.h"\ + "..\include\ap_ctype.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"\ + + +"$(INTDIR)\ap_snprintf.obj" : $(SOURCE) $(DEP_CPP_AP_SN) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\ap\ap_sha1.c + +!IF "$(CFG)" == "htpasswd - Win32 Release" + +DEP_CPP_AP_SH=\ + "..\include\ap.h"\ + "..\include\ap_config.h"\ + "..\include\ap_ctype.h"\ + "..\include\ap_sha1.h"\ + "..\include\ap_mmn.h"\ + "..\include\hsregex.h"\ + "..\os\win32\os.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_AP_SH=\ + "..\ap\ebcdic.h"\ + "..\include\ap_config_auto.h"\ + "..\include\os.h"\ + + +"$(INTDIR)\ap_sha1.obj" : $(SOURCE) $(DEP_CPP_AP_SH) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "htpasswd - Win32 Debug" + +DEP_CPP_AP_SH=\ + "..\include\ap.h"\ + "..\include\ap_config.h"\ + "..\include\ap_ctype.h"\ + "..\include\ap_sha1.h"\ + "..\include\ap_mmn.h"\ + "..\include\hsregex.h"\ + "..\os\win32\os.h"\ + + +"$(INTDIR)\ap_sha1.obj" : $(SOURCE) $(DEP_CPP_AP_SH) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\ap\ap_checkpass.c + +!IF "$(CFG)" == "htpasswd - Win32 Release" + +DEP_CPP_AP_CH=\ + "..\include\ap.h"\ + "..\include\ap_config.h"\ + "..\include\ap_ctype.h"\ + "..\include\ap_mmn.h"\ + "..\include\hsregex.h"\ + "..\os\win32\os.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_AP_CH=\ + "..\ap\ebcdic.h"\ + "..\include\ap_config_auto.h"\ + "..\include\os.h"\ + + +"$(INTDIR)\ap_checkpass.obj" : $(SOURCE) $(DEP_CPP_AP_CH) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "htpasswd - Win32 Debug" + +DEP_CPP_AP_CH=\ + "..\include\ap.h"\ + "..\include\ap_config.h"\ + "..\include\ap_ctype.h"\ + "..\include\ap_mmn.h"\ + "..\include\hsregex.h"\ + "..\os\win32\os.h"\ + + +"$(INTDIR)\ap_checkpass.obj" : $(SOURCE) $(DEP_CPP_AP_CH) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=..\ap\ap_base64.c + +!IF "$(CFG)" == "htpasswd - Win32 Release" + +DEP_CPP_AP_BA=\ + "..\include\ap.h"\ + "..\include\ap_config.h"\ + "..\include\ap_ctype.h"\ + "..\include\ap_mmn.h"\ + "..\include\hsregex.h"\ + "..\os\win32\os.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_AP_BA=\ + "..\ap\ebcdic.h"\ + "..\include\ap_config_auto.h"\ + "..\include\os.h"\ + + +"$(INTDIR)\ap_base64.obj" : $(SOURCE) $(DEP_CPP_AP_BA) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ELSEIF "$(CFG)" == "htpasswd - Win32 Debug" + +DEP_CPP_AP_BA=\ + "..\include\ap.h"\ + "..\include\ap_config.h"\ + "..\include\ap_ctype.h"\ + "..\include\ap_mmn.h"\ + "..\include\hsregex.h"\ + "..\os\win32\os.h"\ + + +"$(INTDIR)\ap_base64.obj" : $(SOURCE) $(DEP_CPP_AP_BA) "$(INTDIR)" + $(CPP) $(CPP_PROJ) $(SOURCE) + + +!ENDIF + +SOURCE=.\htpasswd.c + +!IF "$(CFG)" == "htpasswd - Win32 Release" + +DEP_CPP_HTPAS=\ + "..\include\ap.h"\ + "..\include\ap_config.h"\ + "..\include\ap_ctype.h"\ + "..\include\ap_md5.h"\ + "..\include\ap_mmn.h"\ + "..\include\hsregex.h"\ + "..\os\win32\getopt.h"\ + "..\os\win32\os.h"\ + {$(INCLUDE)}"sys\stat.h"\ + {$(INCLUDE)}"sys\types.h"\ + +NODEP_CPP_HTPAS=\ + "..\include\ap_config_auto.h"\ + "..\include\os.h"\ + + +"$(INTDIR)\htpasswd.obj" : $(SOURCE) $(DEP_CPP_HTPAS) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "htpasswd - Win32 Debug" + +DEP_CPP_HTPAS=\ + "..\include\ap.h"\ + "..\include\ap_config.h"\ + "..\include\ap_ctype.h"\ + "..\include\ap_md5.h"\ + "..\include\ap_mmn.h"\ + "..\include\hsregex.h"\ + "..\os\win32\getopt.h"\ + "..\os\win32\os.h"\ + + +"$(INTDIR)\htpasswd.obj" : $(SOURCE) $(DEP_CPP_HTPAS) "$(INTDIR)" + + +!ENDIF + + +!ENDIF + diff --git a/APACHE_1_3_12/src/support/htpasswd.mcp.gz b/APACHE_1_3_12/src/support/htpasswd.mcp.gz new file mode 100644 index 0000000000000000000000000000000000000000..88d4853bf2d30c127fdbfb1031ff8280bd99b2ab GIT binary patch literal 10067 zcmYj#bySpJ)HU6m(%s!5F@T7Glt@WQNq0$uhzu!8N)8|;AkxwTL&pq)#86VsP$JCG z1M|)A{l0gt@A+fjbM`rVpL_2=&svu&jf4a&5vGiT?-3H<6dWAxD(UMIfO8x}`jUMl zH|!jRXp@}!C~iYcFBwJoWEs!JZ%Q>i!*%8b-osH+&Wy*4GCwKg_ z*DcPwH|l?)q6SUJn`B2{iKJgEi5wlI{nn9jF~NaUb$`knH4T5+B}KPSuB*23q*n9y z`{s$aZ1MM$2*(6J+-{Cq4i6Tn0Z0npm*@rA0_g%S3Ido)n8oR4@xT!#ktbQ84iU?u z_E0c=fG7ee;jI&dutAwXO?WZ*h(mxoUPQty(M>q0HQo|u9k-1PAqJoYIe~)X7jf-z z`k@fO1eWJ_l(C0aO$B7cK{38`C)T0wn{^0p1Jh5H)BthzCTTPyvAB`QoTj zdvHP@gOCYc39oQDh}#%zIT0QpBfuCA2YHAL)D6IlYfl;?0Zjqa;I!i?;M~ z<_X3`UIbn^-FP09rc$O{rqoaifG?mCzypfI?Iu73fxP4UiP{Jds-XG=CcF}Y5LIXi zAT7Qy{wuL6rH70ulPRYuizy?G8V5yLDjqkrsU)8(o*T|q>vIBmMh{j~Qd5z6P7zDo z5MihjAPL}zH%T-}Tu3F4U&~rchv4RBh7JN$0Os+N310CV_%}2N`^QQ-q#;Vt?6}=r z2p$l1{9n8qCa5s953oseLxOMtnIvf7!zfXt4&<&!@jK!18^kxn9mKE6vdD4>cZnv6 zZXV{Wj+%Q570Zq7f1PIN9SR#}f zv?<}91f>bUkfQ{lW$_z0H{?+N_*in3DD)5zhkqjnbxgSDg02EiaPE|#lA!#ASSl1b z$Pup(55)_Ob1KueC5sPAn2i4t-%pIj;6&0PSlHQq$1rEU$5kgo#eix8(i1fQ--Q?# z0rmizZ_l{OH-5miK?b0G03+ZRKrY@ZJ}90uArgY8PKCmMjQkr6Fu}ijfS~#6*q889 z8vNphcdnp@@7pVBX$BX=)qKS^g(bx%k5|4^>KUOKdhA;^N^zXAr#BU`j;5H7UVjf8 zzTr50GsyN}fH0j)V~jnz(z3pGzTiPl2b++Qx|tCGVEuz z5DjS3WN6d7^qDR0r!|ni%m+Kex+DTpYi5|Kyf>MsE(v?oXAYfd9di^2yWcG}kUmli z$-L_Kc}?P{3|i-fb?GMX90wy+<8TV;SclRm3E%Wup?y5Pi#EhhKP-__UK8QJfH-~F z*nS=U5%?EC&Gv#VlfX;I{!Urj+KK|?mR^3aapI=~k~7K72X4SKLKOSdF?3_}Gg*0tGE6ghoKVdQN(9=CH$l@i*wiHZcrR4}9W zMab5Y7F*3Kd)qGrGic_~DlqI>C&Z%_npqz6XaM(^6QjmQRZCB~B6$aZVK)gZgkL_DlC z`A6p8P`wc7``Lk3r#i;+-zK|Yw0hFgpD&nA)Du=DX{2W&btXTCYOjeYZR8k==+= zq^}XF_I6G2Kc%j2{yCbgY|(M~N=-f65b(RT>I`z#ixAu3`?SF)@91_0$w(h%NjU8B zxsOn&RH0Asrna{V@Rd)B8$D0?O8>oM3SKs+DfPQ-E_o3yiPB2Daz|ykvwqjy0!j43cX z&F8^374ynd@VaD69FRk@WfQ1p?;1?|zH7XcuQc$3?<4fIu4?k@IqZznFKK`Lz)_Md zQNX9UKBN_o1T=91vkYSKwuN)igkXKqYf9jV=)U~+(_AzO*ee%J@o2z6kt^`4K|jtm zUG6JmFs0~^0xw>SWA4i@Xke@Z6C9OdNH{?o8#yGz9v z*P0;;mV6mtd-)uYxU`!3bFHB+bdC%Ia8#0v%MX9erVv#DS^{$NMW!J{D)JGy+D&vZ z4^c?yrOp6#jG9%Ux9Z@E!;9ONzduS#HfhO|#=^;A(C_j=Fy5^tP+UT+u0t<){y&zw##fuowV+?58nSJx>L{5Om4C4m z2yBI9jz)ioxk{!8j{Cfnc{)q6^H=7(-nw>5NrQUQHX_1wT5)cfAetnIvIn$i4N?~= zq`53*wXPwrZZ_#Bw38+sS0C>A&NSLl<6m-~A$&vW+Pq8rBSi0%9;IuOcT6|s##A9p z4-$3^VW$~Qrv7|Bv=%!t12M{~tRsZE*>QE*-H_R}tKlEt)m2BPx~Zc`nUrgjV|5Y} zBN4XZA*R%K?;jJNL-jm^Od*L;&!`T{o94GcoHshH>PONX7I+Atu<8<57QASTpRP-1ziNPzy4kZN$YTCyO;S--29_Rv} zM%8dgKPaNJQ8|w4#sRo%4qLGqw7XQEO!~ZO&0@kiNnxb&4`VlN6RT-*3o|^;^0axM z7ilnr?;i3hJ1;c*exjJ<2uVp-y)5B%Z6_`-l!%n`;n#oa09?^BCf~U>Oh~(ThD^a! znO2Xx^qoZAiD#k z8A$o-O2D|(3zac3)VHjEG?5(2ablZAaW6tq$v;ytE7PgEjYjJ+`1kjw;8n!2wWLv{ z!f40-JIylvPP06!(Tui~Wq_RD`;x)0RzW#PqnQ=?t-}SW$*}T;2=8az2 z6)Q)ek<>h`*lDincA;YfU+Mn2s zB*dE9xH&)nS?OFiW;>?&Nv`OKtn^a2a>??3!_VK1slNufQ@pJQWt~iWIfO=zp zxx#S20xlo*k>2a&=Tp(Vib(?j!mLit4>sEP9~VJ3H@0|?uDv#D^Q&vT{R)qWv%6=a zLysBg$F5|B0`mwLg~H5-Y)h*-jeZOEo=)gS$(MK^ryVfsN3J~kcHW~O=`EvwlI>kk zny|YKhVyj2yIy%BsiZD6F_Hp#n#y{E%(ff({B~lb`n1_Y%dRSWN}Nk3Emo1b(>{qo z$tilF(Xi{CEi{ws1qfHXDVj;GyEK*aT@Sc}N7_g>3ixEO1mX?}5Pihb@^AN#!6 z;EvAAx{k}D*+Nsa!$NZd&+xpmrR`wscE#Z?o$=Y)+mf4g(~5Hoa*@nUlTF6}#fz z8s?iwyVZ~9`OFFpQvSl7-+RmDyIkm`yd`P#4Syr2_yf!fG6+r}+Y`pMP7lxw@Q)#= z){nfL)>f@bsgL7UhPFS}_(&}5;@cV;o9iBGcx-|EYuOlo8T3(<)}Jf*kY{sP8{!Vd zwCA0COPg1w-VfnVT6JMr;kC*A`6aRTmH+3Xg#_CluAwyAzGE+*7@G^Us{+MVUYN0k zf`%3jXqaC%Qfc=OOB%aO9~+w2CI&Em^wXYZ%kz3EX{=~4>ZD|?$m)ljsFsm8{3c?+ zY1s@^sM8kfe+`qd$TaX)7TQ3wWm!+#B@T2P=>b_>0Tplys>x zwsL=3KC80^2M)c;=z{ioyGRD0*7LFUv%rfBd| z1zktH;WsWpv>IE`NVFW}Awm4hPx+Wg_MGOR8FW+@-S_6awJ9H_aTiHg1b39`D8)rR zTUFt%)BY(ATKe{hIDJH4E}t@2g&shRBT*SbFecax zMP%3d+DnE~hxVsVqaO_<*2$+{bnLjmDoniiHj6qxdTfMr(iL^TizrfWmR~VyZg7U> zbms6}z$Mbo8zZN*Z6`)4qwDilb8U{cZA-rTB5WBRTwF972UnAJWXRsxb2mfL#JH^` zt&4LEhumqZiluL>!V2>=nOYjoXJ2h)oBB28hKcc}k>#;^wnsQy6x3!gtqL+7w_k)e zprC%oZh>F)i6s_Ym}-<++>2gWAC!(b1g}Zk9@u&Lwl2sSQW`EuL^ZZ733(eCl3FSX~;$EMGWRaf!(D=?gWq^R#nXd&Tc97wOsa(%zitOH&o!@8G28S7TyX;$q4N z1QMF3&O1H+I4TCk@OYsJExIM(Qs z_#{jGYq7K-GH&TdHTiL0r>m{AfiA5gaGVN>qEd@T;fi}40H5jVVtk;)N{$jvGhfje zt;f<#^%^cPzf~j-ce~PO(mlQ)Pe+A_M(>YlCN6l0eNrLbx>QGnj3!Zq!I3f0iE0G= zXzim;1QpFC+|(Es9ITS#jdKcTpHzu2_-NQgOoPcW45ry`vrD~xkAPGyV}SKRBE&e( z{P{s*9=_96#pJ-HAdySFZLY4IL|ilFq##yqsxs~7hwa`*<;4`R_G(iNLU5J2@EG29 zzeouc=U0tk>I5WMZt=*hnLt5}UaJpfv<>`a1t15&d_ z@dCqOdQSje!<+1hSFVgdQ{}>+)%;xNF;MEZZ6BaY+jBQcAS4Nd~)WA_s z26vXzU!DxfEX_`=BW=2Csu^f}@XoyO65jTRXAUv$>5^xT3+@LS?XCwjzXWpPaLpXG zuOHAf3gkS*oio=~VW45oF_k0)QwlH`GB;PgJyYT?l_5I$-yO6Iq&gKABl`0b$cxhRAl6H%s45I zU%2Hk;|F@N?0o}VO$z4|I-9fXwE@-~9!Dt9Xo^>=u>zN-#xJ#_EgyGD(Uk7z=-~(c z44F($xH=1&oJmj)R~?yrye40=O~n^xT!Ur>T2-58QiJv8MNX0h2a1D2xQ!)i?6`or zdpXPmv?4X^oWPmAoJ*Z-N8@WvngP+8H7+3aq=*nnMem!SMDEOb5IYZWmTXd~VxkGO z#tl3a6}FV!wq?wbA~=mE+@sLyHPgC&MDv#=rgJKPG+!NZVrU-lsLq$YaV0crl!Fm)>L691?;lOStXn^6TnlturmA04BoTIaeUlk z$+(xGg|1DF4hPp;ND<{YcW`vvwMN(e&tXT&e<77SkQ>oix8)Ut$R)8zxm!) z7}Vf#XJgc5NkeU6UdjlDd=bHrZO?d34!>EpH@dc_5m3O6lIeMO_Kn-PuKfEl&`lwy zh)~8_=h}vb&09E}+&P$XFIg+P=H1zMj~EA?E<2j01?#cfv2&)Igw*|Y@BBZ8e;RzE z5&Mg~!Tf^60hC)E(6nn1^LeYUNw)Hjgec*6@;a!dw_tv4wfvv_Nv&7oblHTmqbu-) zn0x1k<`=hCIgQe%O~OTtFwx%b)_=cbHEQD1AtHQv`VVAQ`0^%J%wD!YGG&+FDSZBw zCGFB;OUVL%h65*52{st7&84HqWodr~W9IuD^8xVWmRE*0>q7Vb_y{?8|F5$ZUuftY z&Sm=IueW{y&t*G*$arWnf%eyj{DOEv>&@^L`@P6L8_%LZ8xaNUl zUv^ejR>5awQ@MtdjLouift2QEy(+1ctBR|S)qdkHwPb!0=wP0;_Y~f|<@jY;>p0An z0ZQ%d_0d})Li+6gpy$qHWl{jCn|J8Jt-k=6xd7EmMC6C5ZKSSnx0fe(#~Sm8FESBM z1yb_F!JddUfHY$N0adcjhh@>>_bbZYj+@`W4hc^E*1s#R-`ook+O)Urqbzj1E7$Ss zZ-~q!Dm(=Y*h!%0yi$D*S*y)n!pa4fU%<>9-444Cf2GC54AVtX)-n?oI=H@xlgSA} zFfyHXv{!xEq9GR^F67~|#rtAYzqI-?^x#3W>H{hhU~y98zU>BVY0sv?#?GfOv?R~+ z;hV zn-{B=GLM5Ym507Y`vg7P%nDYi3(p?q7OLVN3&J}b?dz+W*f+8t8@yxi4Eni7IsQM- zv(ic2A9oD*RUhW>n5@VWAHzOR=~ty>?tPB%_q2H#b3m5fDaLA@-QmniajQd5OBU0v zNml~wY_<$1jGC9s@12p@hYxR|rX+=eXxi7y<>hQ%cmxOg3Wo{^A$tXd*r`HSm>&*$ z8BwLLD6@4GwhY1CKMHT0sHK$Vjih-kq0T>lY5VNN!bQ3oPQfhhbs<@IOkER=S2Dhz zf=VoYGI<*qUy*Y5L~sEgkwHl`zhp$%BAmE$%&FmG{A0RjV5Z>8q|sm5O+YBJcH)#c zW{v?VXsxVwa%>DnVvlPQqcCc>%CQN#=?~$wh2567=kuI|;)!1Lumq=jOL<@~ zT;^+^&)!kKT*-WUrf>b|_eFiNv8@+EjqJ(ZC8(g{#?YS=E34idx3?m!^ROX@+2uv1 z{oSYWN#36RPjBZ-88eP0Bs@zO?q;542KqX!&b!#zeug6YIy(Yn9SV!@Jbasb{cB^t zy04=n6!U^a+2*Io-y9vJd;T%P&Y3Q<%pCrt)W_~F=dY@=o)GwO%cU^l_{2TE=c$+v zVTNzMNC|s#-j9BJmsW!P-OmyC04lYYQ_rT2ZVE-RTH;Kfa8K6cF`NtfRFhv+6@w@^ zUCAQn6} zKdI|4R4`q+SCbKL;z6V95dIqf0OuPa2A0mUeOIDzsHC3UcY2j8$lIBMzCqIKYvkLR z-o&{;%(`~AoR((UN||_qpb#DB$@i&F9)5oQZIb5F()FIG$RSvB|2_NhxHUm$PuTGW z$1m(M(zcT)F$`<2f!iHhI}TVrl5GR3!KVJYjZJyjQnRzcRapaMKN%^5%USFJPbPi?l#5vpRobf7^8r# zT2Me>eYal6-@TU<{?mH5W3{1J?Z$*{uz~Z1_O)O4+yDK*%oMWMZxy8V_5c37sG{_p zX`c~03c3)7ZZ~`KtgJDWudr*49%Ow>O#j8>M95OFGejn9nf#W~wSkIMY}}fI&N8c6 zmA`@8CG^R%*85)x{WV+6MIy1CB0PaFE0mZnbSu4k)Qu9pZjoLqY%-GvQJW8uundT_ zv$G87kNUF?U{{f<|C_+%#;=S#C95VroED7+3SbKYuIOs{tkWXw61e$3ebW^mONL@A zSZPZg?~YQ{yY$VRKhFxW1`|ZGvDxXH{5wiElURdifKmUCr$ra+|HI02s$609Ie%hZ z(So)wpZO8qPd#YjPQj--%h#i$qf>SDks>8cK?(nIUSru&9(PZ^1c==S7hVJsg+S{9 zLb__7%b-3s4~Uj;;1QpH0Xbk_$9|dmmnTLlm^RI6^(BHFvJ)dYYnP5d8~GrIw8Tha zojx0?0}j0N%mC99)7s8ut-fK<1|9J^RdOWq>G?w7uk0-4EN+)7gD3y{Jtg|>n0JP< zx;=%ovR<6q>mM1t4*aL{!4FdS!<2hFEs3|36ZGyIWV1)9VjXdCsWN_AkY5)xA2d$J3Mb`>DEBYK-`!E9>oj-zI$RiG?nkFQv*i&l7Qn8_YdU!aB;%p)z^=p^_%`(CtBo=J5%Ch^p5%`f3Dk~< zqh51)*t7O-SROGbd3)Kn4QWD`jx*lg{P%L(DujxqX5YneyYkYBf*q3d!IcK3H9jb6 zG|NTQO)43E$Ngb#w;wsUZ19=T$N5DORcg8Bu15C{*G)al&cxH(hlc!23U}-O-aF#n zO}mR1{3uI`JbdLNoS^w;@I6$y%T>TP0xVXE(2JeGOFLWv|s-?29)8=fm8H;F{5RYhv)S3z%Y6 zD$86&D<5ugmO(cfW6rJGlqP zuILh}Pp?g)e&n`FGDcpVWj-vpcVE3QC{G^fzN4zf5Juj+X;X9k#kSz|HhpD2bNu>W zce#~=!0zT|Pwsw#t)_~>_yFUV@lz4DJ5Qk%!Ci8d*x@*S0l& zZjnrt{xi&H>PkLtH@}(Jd3UXPV~N?e(P^S1$f)rfUrF@^gcy==;9ns&1RNf$5@Po9 zJGy4K(8RBRr?8gL=X3bFn$JZ3lpUy4rgDC{jljn=ZkXwYtN3-kk>;T+PrpzZM`q9ex_3B?* zq`uxvZ4eLK{dvmuXS`jXZ8VF5_B}q-pE>v*`gE@BeW}71yP@mwStd01cvlW`v)2KI zB>hx5=~f)~Is*ae$u-*xnjMJF`@IR1|6(_IU2>Tk>u|RP3=)9nvrFAvpM+5h2b zm5J=>NQ?DLxVR^WFL6rUL|g{*O`aE*MGa(O_TQQ95zR{VIHKH9^R#=9XUlwl$H7Nv z-Q?h9K?4YQG^F;-zu2)~2L=B!^*FZ(6~=NkTv<6eQyjNTH3u2C$`I`gxR;?$i|wZ# zbt8vMMO&kgx$sQU&Y;*0<2lHCX6(k{=<dV zHo82hyt6TxXl1x~An+ZNqtTAz84PE2;+k!e@*V)exs`;Uh;w6zuP=SfR(gu#s><&> zvL-in(4QXn1lLV&z|r)SX!NDs5q?bXP3{%)c9&H2HVf%rC|NpRi6?qX49A$X|KO`(jY48Was4mc$^!3$ zlgWDGHfcpyXRgP_7#2V2qIWccMy#f}tkUi=`%iQC<7)dZq6IYk)!NM5BxfD_wNfB# zkm4%YTqGB6|KISL1FKKA`Ej)cCTO!seGVGO3h3ux~Ob;?DkhJ3{3^m-&{n z=>$_+K}2yDjuMpshPB7gWV)*qS84(ytU z-}g4zHnxnZV1!;aonM#JqTn*K1E;=BWyELo&oA(2r4+A@387`?uX{Ei%r|JiqRBI5 z%_V97T|WyOtn-7bvNsx1r84gVO{Jkk41bejwiIgMhBcS*U`vSd zel_pb!YG-x$Z({$jdgTSL=wK?=Ij7_T{#&$e(lb>$Si@hP|TgWZju8Bhx{QF75jr; zvP^{|2J4?IW*|3}pIt#t2L3t=6l2n!owAFxT3AkApTy{@=@|}`x5&;8v;frf%K8tS z=T$HrvNCb8|K6mj&zxY&gPij79m~BSRNLQmMtZ-<*B$Bg_V+wpK5Y7GVUu)U9LvA> z5Xt#`g<|%kM6$GJX|b;1Bhp_MRdir!!w7fmw_H9gwam2$zTb{7fSmN$xM}{mMBaTG z>Mx7vo%DKr*Q3dVM8D&+xS(i?vuk>7?4KB@0$kd(c0wpYG42s}-lAZ%=B+`l`q*_i X_LNJGwO%p6D-2mzRbN^*F3$e}WhwKh literal 0 HcmV?d00001 diff --git a/APACHE_1_3_12/src/support/httpd.8 b/APACHE_1_3_12/src/support/httpd.8 new file mode 100644 index 0000000000..ae320bad2a --- /dev/null +++ b/APACHE_1_3_12/src/support/httpd.8 @@ -0,0 +1,211 @@ +.TH httpd 8 "February 1997" +.\" Copyright (c) 1995-1997 David Robinson. All rights reserved. +.\" Copyright (c) 1997-1999 The Apache Group. 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 acknowledgment: +.\" "This product includes software developed by the Apache Group +.\" for use in the Apache HTTP server project (http://www.apache.org/)." +.\" +.\" 4. The names "Apache Server" and "Apache Group" must not be used to +.\" endorse or promote products derived from this software without +.\" prior written permission. For written permission, please contact +.\" apache@apache.org. +.\" +.\" 5. Products derived from this software may not be called "Apache" +.\" nor may "Apache" appear in their names without prior written +.\" permission of the Apache Group. +.\" +.\" 6. Redistributions of any form whatsoever must retain the following +.\" acknowledgment: +.\" "This product includes software developed by the Apache Group +.\" for use in the Apache HTTP server project (http://www.apache.org/)." +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY +.\" EXPRESSED 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 APACHE GROUP OR +.\" ITS 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. +.\" ==================================================================== +.\" +.\" This software consists of voluntary contributions made by many +.\" individuals on behalf of the Apache Group and was originally based +.\" on public domain software written at the National Center for +.\" Supercomputing Applications, University of Illinois, Urbana-Champaign. +.\" For more information on the Apache Group and the Apache HTTP server +.\" project, please see . +.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 standalone 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://www.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 +... 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_12/src/support/httpd.exp b/APACHE_1_3_12/src/support/httpd.exp new file mode 100644 index 0000000000..4a004a8840 --- /dev/null +++ b/APACHE_1_3_12/src/support/httpd.exp @@ -0,0 +1,415 @@ +#! . +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_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_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_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_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_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_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_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_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_pregcomp +ap_pregfree +ap_pregsub +ap_prelinked_modules +ap_preloaded_modules +ap_process_request +ap_process_resource_config +ap_psignature +ap_psocket +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_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_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_strcmp_match +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_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_validate_password +ap_vbprintf +ap_vformatter +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_12/src/support/log_server_status b/APACHE_1_3_12/src/support/log_server_status new file mode 100755 index 0000000000..1eb2893edc --- /dev/null +++ b/APACHE_1_3_12/src/support/log_server_status @@ -0,0 +1,118 @@ +#!/usr/local/bin/perl + +# ==================================================================== +# Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: +# "This product includes software developed by the Apache Group +# for use in the Apache HTTP server project (http://www.apache.org/)." +# +# 4. The names "Apache Server" and "Apache Group" must not be used to +# endorse or promote products derived from this software without +# prior written permission. For written permission, please contact +# apache@apache.org. +# +# 5. Products derived from this software may not be called "Apache" +# nor may "Apache" appear in their names without prior written +# permission of the Apache Group. +# +# 6. Redistributions of any form whatsoever must retain the following +# acknowledgment: +# "This product includes software developed by the Apache Group +# for use in the Apache HTTP server project (http://www.apache.org/)." +# +# THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY +# EXPRESSED 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 APACHE GROUP OR +# ITS 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. +# ==================================================================== +# +# This software consists of voluntary contributions made by many +# individuals on behalf of the Apache Group and was originally based +# on public domain software written at the National Center for +# Supercomputing Applications, University of Illinois, Urbana-Champaign. +# For more information on the Apache Group and the Apache HTTP server +# project, please see . + + +# 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 () { + $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_12/src/support/logresolve.8 b/APACHE_1_3_12/src/support/logresolve.8 new file mode 100644 index 0000000000..4851269ad6 --- /dev/null +++ b/APACHE_1_3_12/src/support/logresolve.8 @@ -0,0 +1,87 @@ +.TH logresolve 8 "March 1998" +.\" Copyright (c) 1998-1999 The Apache Group. 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 acknowledgment: +.\" "This product includes software developed by the Apache Group +.\" for use in the Apache HTTP server project (http://www.apache.org/)." +.\" +.\" 4. The names "Apache Server" and "Apache Group" must not be used to +.\" endorse or promote products derived from this software without +.\" prior written permission. +.\" +.\" 5. Products derived from this software may not be called "Apache" +.\" nor may "Apache" appear in their names without prior written +.\" permission of the Apache Group. +.\" +.\" 6. Redistributions of any form whatsoever must retain the following +.\" acknowledgment: +.\" "This product includes software developed by the Apache Group +.\" for use in the Apache HTTP server project (http://www.apache.org/)." +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY +.\" EXPRESSED 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 APACHE GROUP OR +.\" ITS 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. +.\" ==================================================================== +.\" +.\" This software consists of voluntary contributions made by many +.\" individuals on behalf of the Apache Group and was originally based +.\" on public domain software written at the National Center for +.\" Supercomputing Applications, University of Illinois, Urbana-Champaign. +.\" For more information on the Apache Group and the Apache HTTP server +.\" project, please see . +.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_12/src/support/logresolve.c b/APACHE_1_3_12/src/support/logresolve.c new file mode 100644 index 0000000000..2e02e3a80f --- /dev/null +++ b/APACHE_1_3_12/src/support/logresolve.c @@ -0,0 +1,351 @@ +/* + * 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 + +#include + +#ifndef MPE +#ifndef BEOS +#include +#else +/* BeOS lacks the necessary files until we get the new networking */ +#include +#define NO_ADDRESS 4 +#endif /* BEOS */ +#endif /* MPE */ + +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 + */ + +#ifndef h_errno +extern int h_errno; /* some machines don't have this in their headers */ +#endif + +/* largeste 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) { + 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; + + 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(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); + } + + 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_12/src/support/logresolve.pl b/APACHE_1_3_12/src/support/logresolve.pl new file mode 100644 index 0000000000..59ab9ebaf2 --- /dev/null +++ b/APACHE_1_3_12/src/support/logresolve.pl @@ -0,0 +1,264 @@ +#!/usr/local/bin/perl + +# ==================================================================== +# Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: +# "This product includes software developed by the Apache Group +# for use in the Apache HTTP server project (http://www.apache.org/)." +# +# 4. The names "Apache Server" and "Apache Group" must not be used to +# endorse or promote products derived from this software without +# prior written permission. For written permission, please contact +# apache@apache.org. +# +# 5. Products derived from this software may not be called "Apache" +# nor may "Apache" appear in their names without prior written +# permission of the Apache Group. +# +# 6. Redistributions of any form whatsoever must retain the following +# acknowledgment: +# "This product includes software developed by the Apache Group +# for use in the Apache HTTP server project (http://www.apache.org/)." +# +# THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY +# EXPRESSED 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 APACHE GROUP OR +# ITS 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. +# ==================================================================== +# +# This software consists of voluntary contributions made by many +# individuals on behalf of the Apache Group and was originally based +# on public domain software written at the National Center for +# Supercomputing Applications, University of Illinois, Urbana-Champaign. +# For more information on the Apache Group and the Apache HTTP server +# project, please see . + +# logresolve.pl +# +# v 1.2 by robh @ imdb.com +# +# usage: logresolve.pl 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 + +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() { + @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 ($_ = )); + + ## 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_12/src/support/phf_abuse_log.cgi b/APACHE_1_3_12/src/support/phf_abuse_log.cgi new file mode 100755 index 0000000000..9ce2749c57 --- /dev/null +++ b/APACHE_1_3_12/src/support/phf_abuse_log.cgi @@ -0,0 +1,21 @@ +#!/usr/local/bin/perl + +# 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 "" 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\nSmile, you're on Candid Camera.\n"; diff --git a/APACHE_1_3_12/src/support/rotatelogs.8 b/APACHE_1_3_12/src/support/rotatelogs.8 new file mode 100644 index 0000000000..aee02e11ec --- /dev/null +++ b/APACHE_1_3_12/src/support/rotatelogs.8 @@ -0,0 +1,83 @@ +.TH rotatelogs 8 "March 1998" +.\" Copyright (c) 1998-1999 The Apache Group. 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 acknowledgment: +.\" "This product includes software developed by the Apache Group +.\" for use in the Apache HTTP server project (http://www.apache.org/)." +.\" +.\" 4. The names "Apache Server" and "Apache Group" must not be used to +.\" endorse or promote products derived from this software without +.\" prior written permission. +.\" +.\" 5. Products derived from this software may not be called "Apache" +.\" nor may "Apache" appear in their names without prior written +.\" permission of the Apache Group. +.\" +.\" 6. Redistributions of any form whatsoever must retain the following +.\" acknowledgment: +.\" "This product includes software developed by the Apache Group +.\" for use in the Apache HTTP server project (http://www.apache.org/)." +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY +.\" EXPRESSED 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 APACHE GROUP OR +.\" ITS 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. +.\" ==================================================================== +.\" +.\" This software consists of voluntary contributions made by many +.\" individuals on behalf of the Apache Group and was originally based +.\" on public domain software written at the National Center for +.\" Supercomputing Applications, University of Illinois, Urbana-Champaign. +.\" For more information on the Apache Group and the Apache HTTP server +.\" project, please see . +.SH NAME +rotatelogs \- rotate Apache logs without having to kill the server +.SH SYNOPSIS +.B rotatelogs +.I logfile +.I rotationtime +.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" +.mf + +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. The suffix .nnnn is automatically +added. +.IP \fB\fIrotationtime\fP +The rotation time in seconds. +.PD +.SH SEE ALSO +.BR httpd(8) +. diff --git a/APACHE_1_3_12/src/support/rotatelogs.c b/APACHE_1_3_12/src/support/rotatelogs.c new file mode 100644 index 0000000000..dc6bd97729 --- /dev/null +++ b/APACHE_1_3_12/src/support/rotatelogs.c @@ -0,0 +1,82 @@ +/* + * Simple program to rotate Apache logs without having to kill the server. + * + * Contributed by Ben Laurie + * + * 12 Mar 1996 + */ + + +#define BUFSIZE 65536 +#define MAX_PATH 1024 + +#include "ap_config.h" +#include +#include +#include + +int main (int argc, char **argv) +{ + char buf[BUFSIZE], buf2[MAX_PATH]; + time_t tLogEnd = 0; + time_t tRotation; + int nLogFD = -1; + int nRead; + char *szLogRoot; + + if (argc != 3) { + fprintf(stderr, + "%s \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]; + tRotation = atoi(argv[2]); + if (tRotation <= 0) { + fprintf(stderr, "Rotation time must be > 0\n"); + exit(6); + } + + for (;;) { + nRead = read(0, buf, sizeof buf); + if (nRead == 0) + exit(3); + if (nRead < 0) + if (errno != EINTR) + exit(4); + if (nLogFD >= 0 && (time(NULL) >= tLogEnd || nRead < 0)) { + close(nLogFD); + nLogFD = -1; + } + if (nLogFD < 0) { + time_t tLogStart = (time(NULL) / tRotation) * tRotation; + sprintf(buf2, "%s.%010d", szLogRoot, (int) tLogStart); + tLogEnd = tLogStart + tRotation; + nLogFD = open(buf2, O_WRONLY | O_CREAT | O_APPEND, 0666); + if (nLogFD < 0) { + perror(buf2); + exit(2); + } + } + if (write(nLogFD, buf, nRead) != nRead) { + perror(buf2); + exit(5); + } + } +} diff --git a/APACHE_1_3_12/src/support/split-logfile b/APACHE_1_3_12/src/support/split-logfile new file mode 100644 index 0000000000..7cc4652da8 --- /dev/null +++ b/APACHE_1_3_12/src/support/split-logfile @@ -0,0 +1,103 @@ +#!/usr/local/bin/perl +# +# ==================================================================== +# Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: +# "This product includes software developed by the Apache Group +# for use in the Apache HTTP server project (http://www.apache.org/)." +# +# 4. The names "Apache Server" and "Apache Group" must not be used to +# endorse or promote products derived from this software without +# prior written permission. For permission please contact +# Apache@Apache.Org. +# +# 5. Products derived from this software may not be called "Apache" +# nor may "Apache" appear in their names without prior written +# permission of the Apache Group. +# +# 6. Redistributions of any form whatsoever must retain the following +# acknowledgment: +# "This product includes software developed by the Apache Group +# for use in the Apache HTTP server project (http://www.apache.org/)." +# +# THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY +# EXPRESSED 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 APACHE GROUP OR +# ITS 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. +# ==================================================================== +# +# This software consists of voluntary contributions made by many +# individuals on behalf of the Apache Group and was originally based +# on public domain software written at the National Center for +# Supercomputing Applications, University of Illinois, Urbana-Champaign. +# For more information on the Apache Group and the Apache HTTP server +# project, please see . +# + +# +# 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 = ) { + # + # 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 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_12/src/support/suexec.8 b/APACHE_1_3_12/src/support/suexec.8 new file mode 100644 index 0000000000..801d7abce9 --- /dev/null +++ b/APACHE_1_3_12/src/support/suexec.8 @@ -0,0 +1,70 @@ +.TH suexec 8 "March 1998" +.\" Copyright (c) 1998-1999 The Apache Group. 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 acknowledgment: +.\" "This product includes software developed by the Apache Group +.\" for use in the Apache HTTP server project (http://www.apache.org/)." +.\" +.\" 4. The names "Apache Server" and "Apache Group" must not be used to +.\" endorse or promote products derived from this software without +.\" prior written permission. +.\" +.\" 5. Products derived from this software may not be called "Apache" +.\" nor may "Apache" appear in their names without prior written +.\" permission of the Apache Group. +.\" +.\" 6. Redistributions of any form whatsoever must retain the following +.\" acknowledgment: +.\" "This product includes software developed by the Apache Group +.\" for use in the Apache HTTP server project (http://www.apache.org/)." +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY +.\" EXPRESSED 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 APACHE GROUP OR +.\" ITS 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. +.\" ==================================================================== +.\" +.\" This software consists of voluntary contributions made by many +.\" individuals on behalf of the Apache Group and was originally based +.\" on public domain software written at the National Center for +.\" Supercomputing Applications, University of Illinois, Urbana-Champaign. +.\" For more information on the Apache Group and the Apache HTTP server +.\" project, please see . +.SH NAME +suexec \- Switch User For Exec +.SH SYNOPSIS +No synopsis for usage, because this program +is used internally by Apache only. +.PP +.SH DESCRIPTION +.B suexec +is the "wrapper" support program for the suEXEC behaviour for Apache. +It is run from within Apache automatically to switch the user when +an external program has to be run under a different user. For more +information about suEXEC see the document `Apache suEXEC Support' +under http://www.apache.org/docs/suexec.html . +.PD +.SH SEE ALSO +.BR httpd(8) +. diff --git a/APACHE_1_3_12/src/support/suexec.c b/APACHE_1_3_12/src/support/suexec.c new file mode 100644 index 0000000000..075bad44dc --- /dev/null +++ b/APACHE_1_3_12/src/support/suexec.c @@ -0,0 +1,593 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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 +#include +#include + +#include + +#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(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[] = +{ + "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; + + + 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 = environ; *ep && cidx < AP_ENVBUF-1; ep++) { + if (!strncmp(*ep, "HTTP_", 5)) { + cleanenv[cidx] = *ep; + cidx++; + } + else { + 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 */ + + /* + * If there are a proper number of arguments, set + * all of them to variables. Otherwise, error out. + */ + prog = argv[0]; + if (argc < 4) { + log_err("alert: too few arguments\n"); + exit(101); + } + target_uname = argv[1]; + target_gname = argv[2]; + cmd = argv[3]; + + /* + * 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); + } + + /* + * 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; + 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 != waitpid(pid, &status, 0)) + ; + /* @@@ 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 */ + clean_env(); + + /* + * 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_12/src/support/suexec.h b/APACHE_1_3_12/src/support/suexec.h new file mode 100644 index 0000000000..892badd1e0 --- /dev/null +++ b/APACHE_1_3_12/src/support/suexec.h @@ -0,0 +1,143 @@ +/* ==================================================================== + * Copyright (c) 1995-1999 The Apache Group. 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 acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED 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 APACHE GROUP OR + * ITS 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see . + * + */ + +/* + * 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_12/src/test/.cvsignore b/APACHE_1_3_12/src/test/.cvsignore new file mode 100644 index 0000000000..e2244a438e --- /dev/null +++ b/APACHE_1_3_12/src/test/.cvsignore @@ -0,0 +1,11 @@ +a.out +time-FCNTL +time-FLOCK +time-SYSVSEM +time-SYSVSEM2 +time-PTHREAD +time-USLOCK +zb +test-writev +test_date +test_select diff --git a/APACHE_1_3_12/src/test/.indent.pro b/APACHE_1_3_12/src/test/.indent.pro new file mode 100644 index 0000000000..a9fbe9f9a1 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/test/README b/APACHE_1_3_12/src/test/README new file mode 100644 index 0000000000..9f8be502b8 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/test/check_chunked b/APACHE_1_3_12/src/test/check_chunked new file mode 100755 index 0000000000..6a12167211 --- /dev/null +++ b/APACHE_1_3_12/src/test/check_chunked @@ -0,0 +1,42 @@ +#!/usr/bin/perl -w + +# 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_12/src/test/cls.c b/APACHE_1_3_12/src/test/cls.c new file mode 100644 index 0000000000..91114a784c --- /dev/null +++ b/APACHE_1_3_12/src/test/cls.c @@ -0,0 +1,166 @@ +#include +#include +#include +#include +#include + +/* + * Compare a string to a mask + * Mask characters: + * @ - uppercase letter + * # - lowercase letter + * & - hex digit + * # - digit + * * - swallow remaining characters + * - 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_12/src/test/rename/Makefile b/APACHE_1_3_12/src/test/rename/Makefile new file mode 100644 index 0000000000..4e3454d1d6 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/test/rename/README b/APACHE_1_3_12/src/test/rename/README new file mode 100644 index 0000000000..87e501e611 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/test/rename/apapi.h b/APACHE_1_3_12/src/test/rename/apapi.h new file mode 100644 index 0000000000..9bcb3dee6f --- /dev/null +++ b/APACHE_1_3_12/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_12/src/test/rename/apapi.h.mk b/APACHE_1_3_12/src/test/rename/apapi.h.mk new file mode 100755 index 0000000000..13c64eb652 --- /dev/null +++ b/APACHE_1_3_12/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('', ); + 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 = ) { + $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_12/src/test/rename/apapi_compat.h b/APACHE_1_3_12/src/test/rename/apapi_compat.h new file mode 100644 index 0000000000..8e2e58798b --- /dev/null +++ b/APACHE_1_3_12/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_12/src/test/rename/apapi_compat.h.mk b/APACHE_1_3_12/src/test/rename/apapi_compat.h.mk new file mode 100755 index 0000000000..ac43e9d1a7 --- /dev/null +++ b/APACHE_1_3_12/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 () { + 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_12/src/test/rename/compat.h b/APACHE_1_3_12/src/test/rename/compat.h new file mode 100644 index 0000000000..3bd365cf1c --- /dev/null +++ b/APACHE_1_3_12/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_12/src/test/rename/compat.h.mk b/APACHE_1_3_12/src/test/rename/compat.h.mk new file mode 100755 index 0000000000..ed1c4107af --- /dev/null +++ b/APACHE_1_3_12/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 () { + 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_12/src/test/rename/csubst/Makefile b/APACHE_1_3_12/src/test/rename/csubst/Makefile new file mode 100644 index 0000000000..655704fccb --- /dev/null +++ b/APACHE_1_3_12/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_12/src/test/rename/csubst/csubst.c b/APACHE_1_3_12/src/test/rename/csubst/csubst.c new file mode 100644 index 0000000000..5da2bb8c97 --- /dev/null +++ b/APACHE_1_3_12/src/test/rename/csubst/csubst.c @@ -0,0 +1,131 @@ + +#include +#include +#include +#include + +#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_12/src/test/rename/csubst/lexer.c b/APACHE_1_3_12/src/test/rename/csubst/lexer.c new file mode 100644 index 0000000000..a171868add --- /dev/null +++ b/APACHE_1_3_12/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 + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include +#include + +/* 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 +#include +#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 +#include +#include + +#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 +#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_12/src/test/rename/csubst/lexer.l b/APACHE_1_3_12/src/test/rename/csubst/lexer.l new file mode 100644 index 0000000000..83f91ddfb8 --- /dev/null +++ b/APACHE_1_3_12/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 +#include +#include + +#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_12/src/test/rename/csubst/tokens.h b/APACHE_1_3_12/src/test/rename/csubst/tokens.h new file mode 100644 index 0000000000..8b29aba7e5 --- /dev/null +++ b/APACHE_1_3_12/src/test/rename/csubst/tokens.h @@ -0,0 +1,41 @@ +/* $Id: tokens.h,v 1.1 1998/04/03 06:20:16 rse Exp $ */ + +/* + * 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_12/src/test/rename/csubst/util.c b/APACHE_1_3_12/src/test/rename/csubst/util.c new file mode 100644 index 0000000000..2806690fe6 --- /dev/null +++ b/APACHE_1_3_12/src/test/rename/csubst/util.c @@ -0,0 +1,137 @@ + +#include +#include +#include +#include +#include +#include +#include + +#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_12/src/test/rename/csubst/util.h b/APACHE_1_3_12/src/test/rename/csubst/util.h new file mode 100644 index 0000000000..163c0cd6d7 --- /dev/null +++ b/APACHE_1_3_12/src/test/rename/csubst/util.h @@ -0,0 +1,11 @@ + +#include + +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_12/src/test/rename/rename.cf b/APACHE_1_3_12/src/test/rename/rename.cf new file mode 100644 index 0000000000..4d679620c1 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/test/rename/rename.cf.clean-api b/APACHE_1_3_12/src/test/rename/rename.cf.clean-api new file mode 100644 index 0000000000..6ead5c019c --- /dev/null +++ b/APACHE_1_3_12/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_12/src/test/rename/rename.cf.update b/APACHE_1_3_12/src/test/rename/rename.cf.update new file mode 100755 index 0000000000..61a8313f11 --- /dev/null +++ b/APACHE_1_3_12/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 = ) { + $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_12/src/test/rename/rename.pl b/APACHE_1_3_12/src/test/rename/rename.pl new file mode 100755 index 0000000000..1dc581b46b --- /dev/null +++ b/APACHE_1_3_12/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 +## + +# configuration +$config = "./rename.cf"; +$csubst = "./csubst/csubst"; + +# parameter +@SRC = @ARGV; + +# read config file into hash +%PREFIX = (); +%SUBST = (); +open(CFG, "<$config") || die; +while () { + 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 () { + 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_12/src/test/tcpdumpscii.txt b/APACHE_1_3_12/src/test/tcpdumpscii.txt new file mode 100644 index 0000000000..9c1060edab --- /dev/null +++ b/APACHE_1_3_12/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 +To: TLOSAP +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 +To: Nate Williams +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 () { + 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_12/src/test/test-writev.c b/APACHE_1_3_12/src/test/test-writev.c new file mode 100644 index 0000000000..852c701766 --- /dev/null +++ b/APACHE_1_3_12/src/test/test-writev.c @@ -0,0 +1,85 @@ +/* + 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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_12/src/test/test_date.c b/APACHE_1_3_12/src/test/test_date.c new file mode 100644 index 0000000000..4beaf7943b --- /dev/null +++ b/APACHE_1_3_12/src/test/test_date.c @@ -0,0 +1,180 @@ +/* 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 +#include +#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_12/src/test/test_find.c b/APACHE_1_3_12/src/test/test_find.c new file mode 100644 index 0000000000..6f887f5007 --- /dev/null +++ b/APACHE_1_3_12/src/test/test_find.c @@ -0,0 +1,62 @@ +/* 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 +#include +#include "httpd.h" +#include "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_12/src/test/test_limits.c b/APACHE_1_3_12/src/test/test_limits.c new file mode 100644 index 0000000000..8d76ce2e08 --- /dev/null +++ b/APACHE_1_3_12/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 + * From: Dag-Erling Coidan =?ISO-8859-1?Q?Sm=F8rgrav?= + * 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 +#include + +#include +#include + +#include +#include +#include +#include +#include + +#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_12/src/test/test_parser.c b/APACHE_1_3_12/src/test/test_parser.c new file mode 100644 index 0000000000..23e2c21c50 --- /dev/null +++ b/APACHE_1_3_12/src/test/test_parser.c @@ -0,0 +1,59 @@ +/* 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 +#include +#include "httpd.h" +#include "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_12/src/test/test_select.c b/APACHE_1_3_12/src/test/test_select.c new file mode 100644 index 0000000000..8c0a6a4363 --- /dev/null +++ b/APACHE_1_3_12/src/test/test_select.c @@ -0,0 +1,30 @@ +/* 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 +#include +#include + +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_12/src/test/time-sem.c b/APACHE_1_3_12/src/test/time-sem.c new file mode 100644 index 0000000000..8bf67c7254 --- /dev/null +++ b/APACHE_1_3_12/src/test/time-sem.c @@ -0,0 +1,572 @@ +/* +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 + +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 +#include +#include + +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 + +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 + +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 +#include +#include + +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 +#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_12/src/test/vhtest/README b/APACHE_1_3_12/src/test/vhtest/README new file mode 100644 index 0000000000..e5b422201a --- /dev/null +++ b/APACHE_1_3_12/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 +- 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_12/src/test/vhtest/bin/test1 b/APACHE_1_3_12/src/test/vhtest/bin/test1 new file mode 100644 index 0000000000..0b3dc8c456 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/test/vhtest/bin/test1d b/APACHE_1_3_12/src/test/vhtest/bin/test1d new file mode 100644 index 0000000000..53c7e39d12 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/test/vhtest/bin/test2 b/APACHE_1_3_12/src/test/vhtest/bin/test2 new file mode 100644 index 0000000000..074f6ddbf1 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/test/vhtest/bin/test2d b/APACHE_1_3_12/src/test/vhtest/bin/test2d new file mode 100644 index 0000000000..df90392e7c --- /dev/null +++ b/APACHE_1_3_12/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_12/src/test/vhtest/bin/test3 b/APACHE_1_3_12/src/test/vhtest/bin/test3 new file mode 100644 index 0000000000..18c92e3eea --- /dev/null +++ b/APACHE_1_3_12/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_12/src/test/vhtest/bin/test4 b/APACHE_1_3_12/src/test/vhtest/bin/test4 new file mode 100644 index 0000000000..f0d54b3465 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/test/vhtest/bin/test5 b/APACHE_1_3_12/src/test/vhtest/bin/test5 new file mode 100644 index 0000000000..de73c35561 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/test/vhtest/bin/test6 b/APACHE_1_3_12/src/test/vhtest/bin/test6 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/APACHE_1_3_12/src/test/vhtest/bin/vhget b/APACHE_1_3_12/src/test/vhtest/bin/vhget new file mode 100755 index 0000000000..62f3148c02 --- /dev/null +++ b/APACHE_1_3_12/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 <) || die "error reading response: $!\n"; + +($line =~ m#^HTTP/1\.1 200#) || die "HTTP error: $line\n"; + +while (defined($line = )) { + last if $line =~ /^\r?$/; +} + +defined($line = ) || 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_12/src/test/vhtest/conf/common.conf b/APACHE_1_3_12/src/test/vhtest/conf/common.conf new file mode 100644 index 0000000000..ec5e9fe94b --- /dev/null +++ b/APACHE_1_3_12/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 + + +AllowOverride none +Options FollowSymLinks +order allow,deny +allow from all + + diff --git a/APACHE_1_3_12/src/test/vhtest/conf/mime.types b/APACHE_1_3_12/src/test/vhtest/conf/mime.types new file mode 100644 index 0000000000..5af88ff4f2 --- /dev/null +++ b/APACHE_1_3_12/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_12/src/test/vhtest/conf/test1.conf b/APACHE_1_3_12/src/test/vhtest/conf/test1.conf new file mode 100644 index 0000000000..2053020122 --- /dev/null +++ b/APACHE_1_3_12/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 + + +ServerName vhost1 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost1 + + + +ServerName vhost2 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost2 + + + +ServerName vhost3 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost3 + + + +ServerName vhost4 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost4 + diff --git a/APACHE_1_3_12/src/test/vhtest/conf/test1d.conf b/APACHE_1_3_12/src/test/vhtest/conf/test1d.conf new file mode 100644 index 0000000000..d55cff7ada --- /dev/null +++ b/APACHE_1_3_12/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 + + +ServerName vhost1 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost1 + + + +ServerName vhost2 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost2 + + + +ServerName vhost3 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost3 + + + +ServerName vhost4 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost4 + + + +ServerName default1 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/default1 + diff --git a/APACHE_1_3_12/src/test/vhtest/conf/test2.conf b/APACHE_1_3_12/src/test/vhtest/conf/test2.conf new file mode 100644 index 0000000000..0bed833702 --- /dev/null +++ b/APACHE_1_3_12/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 + + +ServerName vhost1 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost1 + + + +ServerName vhost2 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost2 + + + +ServerName vhost3 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost3 + + + +ServerName vhost4 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost4 + + + +ServerName vhost5 +ServerAlias alt5 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost5 + diff --git a/APACHE_1_3_12/src/test/vhtest/conf/test2d.conf b/APACHE_1_3_12/src/test/vhtest/conf/test2d.conf new file mode 100644 index 0000000000..9be181edae --- /dev/null +++ b/APACHE_1_3_12/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 + + +ServerName vhost1 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost1 + + + +ServerName vhost2 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost2 + + + +ServerName vhost3 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost3 + + + +ServerName vhost4 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost4 + + + +ServerName vhost5 +ServerAlias alt5 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost5 + + + +ServerName default1 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/default1 + + + +ServerName default2 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/default2 + + diff --git a/APACHE_1_3_12/src/test/vhtest/conf/test3.conf b/APACHE_1_3_12/src/test/vhtest/conf/test3.conf new file mode 100644 index 0000000000..753d56bc8c --- /dev/null +++ b/APACHE_1_3_12/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 + + +ServerName vhost1 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost1 + + + +ServerName vhost2 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost2 + + + +ServerName vhost3 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost3 + + + +ServerName vhost4 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost4 + + + +ServerName vhost5 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost5 + diff --git a/APACHE_1_3_12/src/test/vhtest/conf/test4.conf b/APACHE_1_3_12/src/test/vhtest/conf/test4.conf new file mode 100644 index 0000000000..e0cd9ca931 --- /dev/null +++ b/APACHE_1_3_12/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:* + + +ServerName vhost1 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost1 + + + +ServerName vhost2 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost2 + diff --git a/APACHE_1_3_12/src/test/vhtest/conf/test5.conf b/APACHE_1_3_12/src/test/vhtest/conf/test5.conf new file mode 100644 index 0000000000..cd31f416d1 --- /dev/null +++ b/APACHE_1_3_12/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 + + +ServerName vhost1 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost1 + + + +ServerName vhost2 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost2 + + + +ServerName vhost3 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost3 + + + +ServerName default1 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/default1 + + + +ServerName vhost4 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost4 + + + +ServerName vhost5 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost5 + + + +ServerName default2 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/default2 + diff --git a/APACHE_1_3_12/src/test/vhtest/conf/test6.conf b/APACHE_1_3_12/src/test/vhtest/conf/test6.conf new file mode 100644 index 0000000000..b62e8bcb23 --- /dev/null +++ b/APACHE_1_3_12/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:* + + +ServerName vhost1 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost1 + + +## expect a warning about mixing * and non-* ports on vhost 127.0.0.2:0 +NameVirtualHost 127.0.0.2:8081 + + +ServerName vhost2 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost2 + + +## expect a warning about overlapping _default_ on port 8080 + +ServerName default1 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/default1 + + + +ServerName default2 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/default2 + + +## expect a warning about overlapping virtualhosts on 127.0.0.3:8080 + +ServerName vhost3 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost3 + + + +ServerName vhost4 +DocumentRoot /home/dgaudet/ap/vhtest/docroot/vhost4 + + +## expect all warnings to be printed twice, and probably in the opposite +## order mentioned here diff --git a/APACHE_1_3_12/src/test/vhtest/docroot/default1/vhost.txt b/APACHE_1_3_12/src/test/vhtest/docroot/default1/vhost.txt new file mode 100644 index 0000000000..312ae9a115 --- /dev/null +++ b/APACHE_1_3_12/src/test/vhtest/docroot/default1/vhost.txt @@ -0,0 +1 @@ +default1 diff --git a/APACHE_1_3_12/src/test/vhtest/docroot/default2/vhost.txt b/APACHE_1_3_12/src/test/vhtest/docroot/default2/vhost.txt new file mode 100644 index 0000000000..07cee68e42 --- /dev/null +++ b/APACHE_1_3_12/src/test/vhtest/docroot/default2/vhost.txt @@ -0,0 +1 @@ +default2 diff --git a/APACHE_1_3_12/src/test/vhtest/docroot/default3/vhost.txt b/APACHE_1_3_12/src/test/vhtest/docroot/default3/vhost.txt new file mode 100644 index 0000000000..3df81a4e03 --- /dev/null +++ b/APACHE_1_3_12/src/test/vhtest/docroot/default3/vhost.txt @@ -0,0 +1 @@ +default3 diff --git a/APACHE_1_3_12/src/test/vhtest/docroot/main/vhost.txt b/APACHE_1_3_12/src/test/vhtest/docroot/main/vhost.txt new file mode 100644 index 0000000000..ba2906d066 --- /dev/null +++ b/APACHE_1_3_12/src/test/vhtest/docroot/main/vhost.txt @@ -0,0 +1 @@ +main diff --git a/APACHE_1_3_12/src/test/vhtest/docroot/vhost1/vhost.txt b/APACHE_1_3_12/src/test/vhtest/docroot/vhost1/vhost.txt new file mode 100644 index 0000000000..0535c7a40c --- /dev/null +++ b/APACHE_1_3_12/src/test/vhtest/docroot/vhost1/vhost.txt @@ -0,0 +1 @@ +vhost1 diff --git a/APACHE_1_3_12/src/test/vhtest/docroot/vhost2/vhost.txt b/APACHE_1_3_12/src/test/vhtest/docroot/vhost2/vhost.txt new file mode 100644 index 0000000000..64290e275d --- /dev/null +++ b/APACHE_1_3_12/src/test/vhtest/docroot/vhost2/vhost.txt @@ -0,0 +1 @@ +vhost2 diff --git a/APACHE_1_3_12/src/test/vhtest/docroot/vhost3/vhost.txt b/APACHE_1_3_12/src/test/vhtest/docroot/vhost3/vhost.txt new file mode 100644 index 0000000000..f43b943a61 --- /dev/null +++ b/APACHE_1_3_12/src/test/vhtest/docroot/vhost3/vhost.txt @@ -0,0 +1 @@ +vhost3 diff --git a/APACHE_1_3_12/src/test/vhtest/docroot/vhost4/vhost.txt b/APACHE_1_3_12/src/test/vhtest/docroot/vhost4/vhost.txt new file mode 100644 index 0000000000..8e66b98d9c --- /dev/null +++ b/APACHE_1_3_12/src/test/vhtest/docroot/vhost4/vhost.txt @@ -0,0 +1 @@ +vhost4 diff --git a/APACHE_1_3_12/src/test/vhtest/docroot/vhost5/vhost.txt b/APACHE_1_3_12/src/test/vhtest/docroot/vhost5/vhost.txt new file mode 100644 index 0000000000..a67c8304fb --- /dev/null +++ b/APACHE_1_3_12/src/test/vhtest/docroot/vhost5/vhost.txt @@ -0,0 +1 @@ +vhost5 diff --git a/APACHE_1_3_12/src/test/vhtest/logs/.cvsignore b/APACHE_1_3_12/src/test/vhtest/logs/.cvsignore new file mode 100644 index 0000000000..72e8ffc0db --- /dev/null +++ b/APACHE_1_3_12/src/test/vhtest/logs/.cvsignore @@ -0,0 +1 @@ +* diff --git a/APACHE_1_3_12/src/test/vhtest/runtest b/APACHE_1_3_12/src/test/vhtest/runtest new file mode 100755 index 0000000000..e281ec265a --- /dev/null +++ b/APACHE_1_3_12/src/test/vhtest/runtest @@ -0,0 +1,42 @@ +#!/bin/sh + +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_12/src/test/zb.c b/APACHE_1_3_12/src/test/zb.c new file mode 100644 index 0000000000..0a6666eb25 --- /dev/null +++ b/APACHE_1_3_12/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* ------------------- 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; iread = 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 = (spacecbuff+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 (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=requests) output_results(); + } + return 0; +} + +/* ------------------------------------------------------- */ + +/* display usage information */ + +void usage(char *progname) { + printf("\nZeusBench v1.0\n\n"); + printf("Usage: %s [-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; +} + + + + + + -- GitLab

    Copyright (c) 1998, 1999 James Clark. Expat is subject to the Mozilla Public +License Version 1.1. Alternatively you may use expat under the GNU General Public +License instead. Please contact me if you wish to negotiate an +alternative license.