diff options
186 files changed, 16087 insertions, 8726 deletions
diff --git a/usr.sbin/httpd/Announcement b/usr.sbin/httpd/Announcement index 9382397d10c..b04612e632b 100644 --- a/usr.sbin/httpd/Announcement +++ b/usr.sbin/httpd/Announcement @@ -1,26 +1,33 @@ -Apache 1.3.3 Released +Apache 1.3.4 Released ===================== The Apache Group is pleased to announce the release of version -1.3.3 of the Apache HTTP server. - -This new Apache version is a bugfix release, primarily to fix a -serious problem with server error reporting introduced in 1.3.2. -This affected the functionality of most custom ErrorDocuments and -of some modules that depend on special error output (e.g., mod_speling). -A side-effect bug that resulted in incorrect error reporting of -nonexistent .htaccess files has also been fixed. - -Additional changes in this release consist of new supported platforms, -Win32 and Unix portability fixes, ErrorDocument environment enhancements, -improved protocol behavior to match the HTTP/1.1 revised specification, -and assorted other features or fixes. Users should review the CHANGES file -and decide on their upgrade plans. We consider Apache 1.3.3 to be the -most stable 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. - -Apache 1.3.3 is available for download from +1.3.4 of the Apache HTTP server. + +This new Apache version incorporates over 90 significant improvements +to the server, including avoidance of some denial-of-service attacks, +support for 3rd-party WebDAV modules, a complete overhaul of content +negotiation, optional column sorting for fancy indexes, the ability to +set a DefaultLanguage, and many fixes to improve consistency, portability, +and squish bugs. A complete listing is provided in the src/CHANGES file. + +Of special note are the many changes to the Apache configuration process. +The default path layout generated by the "configure" script has been +changed to be more consistent with the traditional Apache layout, and +several new command-line options have been added to make compilation +easier. Please see the README.configure and INSTALL files for complete +information. In addition, we have moved all of the server configuration +directives to a single file (httpd.conf-dist), updated mime.types, and +improved the examples for first-time installers. Finally, a few of the +rarely-used command-line options for httpd have been changed to be more +consistent with the help options of other programs. + +We consider Apache 1.3.4 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.4 is available for download from http://www.apache.org/dist/ diff --git a/usr.sbin/httpd/INSTALL b/usr.sbin/httpd/INSTALL index 1fc381e8844..520d752fcd4 100644 --- a/usr.sbin/httpd/INSTALL +++ b/usr.sbin/httpd/INSTALL @@ -79,12 +79,11 @@ platform-dependend. The current state is this: o Out-of-the-box supported platforms are: - - Linux - IRIX - - FreeBSD - HPUX - - OpenBSD - Digital UNIX - - NetBSD - UnixWare - - SunOS - AIX - - Solaris - SCO + - Linux - SunOS - UnixWare + - FreeBSD - Solaris - AIX + - OpenBSD - IRIX - SCO + - NetBSD - HPUX + - BSDI - Digital Unix o Entirely unsupported platforms are: - Ultrix @@ -135,37 +134,37 @@ Reference: - $ [CC=...] [CFLAGS_SHLIB=...] + $ [CC=...] [CFLAGS_SHLIB=...] [TARGET=...] [OPTIM=...] [LD_SHLIB=...] [CFLAGS=...] [LDFLAGS_SHLIB=...] [INCLUDES=...] [LDFLAGS_SHLIB_EXPORT=...] [LDFLAGS=...] [RANLIB=...] - [LIBS=...] - ./configure [--quiet] [--prefix=DIR] [--enable-rule=NAME] - [--verbose] [--exec-prefix=PREFIX] [--disable-rule=NAME] - [--shadow] [--bindir=EPREFIX] [--add-module=FILE] - [--help] [--sbindir=DIR] [--activate-module=FILE] - [--layout] [--libexecdir=DIR] [--enable-module=NAME] - [--mandir=DIR] [--disable-module=NAME] - [--sysconfdir=DIR] [--enable-shared=NAME] - [--datadir=DIR] [--disable-shared=NAME] - [--includedir=DIR] - [--localstatedir=DIR] [--enable-suexec] - [--runtimedir=DIR] [--suexec-caller=UID] - [--logfiledir=DIR] [--suexec-userdir=DIR] - [--proxycachedir=DIR] [--suexec-uidmin=UID] - [--compat] [--suexec-gidmin=GID] - [--suexec-safepath=PATH] - - [--with-perl=FILE] - [--without-support] - [--without-confadjust] + [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] Use the CC, OPTIM, CFLAGS, INCLUDES, LDFLAGS, LIBS, CFLAGS_SHLIB, - LD_SHLIB, LDFLAGS_SHLIB, LDFLAGS_SHLIB_EXPORT and RANLIB environment - variables to override the corresponding default entries in the - src/Configuration.tmpl file (see there for more information about their - usage). + 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 @@ -213,11 +212,17 @@ make sure the paths fit your situation by checking the finally chosen paths via the --layout option. - Use the --compat option to install Apache into a installation tree which - has a similar layout than the one used with Apache 1.2. + 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 "<Layout FOO>...</Layout>" 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 --layout option to check the final installation path layout while - fiddling with the options above. + 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 @@ -282,6 +287,7 @@ 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 @@ -298,8 +304,8 @@ Miscellaneous (+) mod_imap ......... Server-side Image Map support (-) mod_proxy ........ Caching Proxy Module (HTTP, HTTPS, FTP) - Experimental (-) 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) @@ -340,6 +346,15 @@ 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 @@ -357,12 +372,14 @@ 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, the --suexec-userdir=DIR to set the user - subdirectory, the --suexec-uidmin=UID/--suexec-gidmin=GID to set the - minimal allowed UID/GID 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 --enable-suexec option to let APACI accept - your request for using the suEXEC feature. + 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 @@ -380,7 +397,8 @@ 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). + 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. diff --git a/usr.sbin/httpd/KEYS b/usr.sbin/httpd/KEYS index 0158466e091..3a51c83f751 100644 --- a/usr.sbin/httpd/KEYS +++ b/usr.sbin/httpd/KEYS @@ -40,20 +40,33 @@ q5He4RrTiXeAEFBzz+J+R+EQ -----END PGP PUBLIC KEY BLOCK----- -Type bits/keyID Date User ID -pub 1024/A99F75DD 1997/01/24 Ken A L Coar <Coar@DECUS.Org> +Type Bits/KeyID Date User ID +pub 1024/A99F75DD 1997/01/24 Rodent of Unusual Size <Ken.Coar@Golux.Com> + Rodent of Unusual Size <coar@Apache.Org> + Rodent of Unusual Size <Coar@Raleigh.IBM.Com> + Rodent of Unusual Size <Coar@DECUS.Org> -----BEGIN PGP PUBLIC KEY BLOCK----- -Version: 2.6.2 +Version: 2.6.3a mQCNAzLpIyUAAAEEAN9KC8CxTeozPYJjsnhFpJ14d4Hhf2M6OTgqPQFRHOswM/3j B7IW0s+HwVyQ5/SjIlo+8ur9X7yaj1FS2GQmKD1x9LKeHRAoosBIs33okRtoeDRy ufTaTyQTwLklxClWm3JEef4xZioun1mtWbpz0yVEOCSZcRvtnJrNPMCpn3XdAAUR -tB1LZW4gQSBMIENvYXIgPENvYXJAREVDVVMuT3JnPokAlQMFEDNLrGCazTzAqZ91 -3QEBzwEEAMqamgAftJ8X39dH+slXVZhXAkUDfUNPkDyy7Yd8R+UTCdXXZMRrVSc3 -3nGsd7sycFot+TQ4RWK8g1o/eY0LzgT+hSxsI80BabdnX2hCP8Yq6aqBw9XfHRQU -+zUHA5h150dX9vEUp+Rb8UKPvkqTNz58Cv1HFAHboZ55KMJ+oeTk -=arlJ +tCtSb2RlbnQgb2YgVW51c3VhbCBTaXplIDxLZW4uQ29hckBHb2x1eC5Db20+iQCV +AwUQNiiZ2JrNPMCpn3XdAQGlgwP+JLlZvNV/fJ2azKIwjibDa4n2LUDxa7ofKboU +QL+D7FD24zQcmzmkBQm/BL/FSUtxZasJkvdVbU98N3G4h3C4AyErfQOFcrepyGAB +M88onQ1DbQ6tiUA3gw9gIB+2l1C5R8wBOtlwoRJM4GFvjjtRp+KaQqvN3f+lLMMt +hKYB70m0KFJvZGVudCBvZiBVbnVzdWFsIFNpemUgPGNvYXJAQXBhY2hlLk9yZz6J +AJUDBRA2KJmIms08wKmfdd0BAT3yBADEDHAn++77n7bLA/u9QYM2LBQHnXdw5Is8 +YGHpHcNZVDA8CtRTOdub8rhe9qgsid/jEry0hT9Sygfx/ry5ntjmF12ltnxBDPdZ +uU2DaHaIh/zBUAv0hyaQeAXEYiV9J75GrDkTj5Jrrnd623uyIRoMZPKYb+oqsZ4H +jIe/w+CDfrQtUm9kZW50IG9mIFVudXN1YWwgU2l6ZSA8Q29hckBSYWxlaWdoLklC +TS5Db20+iQCVAwUQNiiiaZrNPMCpn3XdAQFnMwP/cX21KHwg6ID7NoGzEKxsfZE/ +dEgRGHFp5T6vznI9fO9WZZ2HmISWjEjri5zAAmXvQG2nWEYFVcF1oWph/ndLgLws +PfIsZiPXpj1LD7oon5PEXvJlkFfpHDqiG4xOORbbGWBcv1sqkx6djkpfyXLoMD36 +5YazFuKurHpWPwAQRJK0J1JvZGVudCBvZiBVbnVzdWFsIFNpemUgPENvYXJAREVD +VVMuT3JnPg== +=kWdi -----END PGP PUBLIC KEY BLOCK----- Type Bits/KeyID Date User ID @@ -92,7 +105,7 @@ GU+TR7zdwnByP72AxPEBJ/F22LwNyreuph+fRpWCnCf+9gVW9Heh =jS5Z -----END PGP PUBLIC KEY BLOCK----- -=========================== + =========================== Rob Hartill <robh@imdb.com> -----BEGIN PGP PUBLIC KEY BLOCK----- @@ -125,7 +138,9 @@ GcDYAW3qW5DpKsQchfvXq9QOBDxP+Kbbe2B8xGEyGUhLkacISFTrIhhQSg== -----END PGP PUBLIC KEY BLOCK----- Type Bits/KeyID Date User ID -pub 1024/49A563D9 1997/02/24 Mark Cox <mark@ukweb.com> +pub 1024/49A563D9 1997/02/24 Mark Cox <mark@awe.com> + Mark Cox <mcox@c2.net> + Mark Cox <mark@ukweb.com> -----BEGIN PGP PUBLIC KEY BLOCK----- Version: 2.6.3ia @@ -133,11 +148,19 @@ Version: 2.6.3ia mQCNAzMRY/IAAAEEAOloTOU0f4w7FDRMM6kA/6XazXxJ/HH8dsmb6E7RuYfVlXsd kCwxUBOkyW+AYhkHbYUwnB5qBoFUyLrbLGuwKHW1KnAwgbeZLTH5nqQLpA0RLGVZ v3tzImKUdyyxBphZWC4IeEgUbl9cc+piOsEJ8QzF7gnqwWo/Ku6tTP1JpWPZAAUR -tBlNYXJrIENveCA8bWFya0B1a3dlYi5jb20+iQCVAwUQMxFj8u6tTP1JpWPZAQHz -eQP+N0nQDbPzWeqLssQLyhFkjw5zZByN60j8p25+6JEq7RXgkN1cHtAdH5LMwRAG -fc258f7P9Syp64lH8s4XWYSX5GX8YA8MurOrJmoGFrJs/yxWng8xtxI9tFUnuoIb -HqnD7HCS9Oj1INdyyQuCxZYGHAgxHhpfNTZt+33tMSFIZTQ= -=uIkU +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 @@ -185,3 +208,264 @@ 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 <dougm@osf.org> + +-----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 <dgaudet@arctic.org> + +-----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 768/8F394E3D 1995/08/08 Martin Kraemer <Martin.Kraemer@Mch.SNI.De> + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6 + +mQBtAzAnjA8AAAEDAKlpkRzZ7c4yDdVnW9fMHMXrMJ8gQ+UIzr1xt2+y7Sv71Nv9 +GfUuTeCWdOoynFUXvvBjyCuEIZ426s9UfrnWv94VppoS8sjFgLYkRIAhZiDMHYp0 +j8i1/f82KtdYjzlOPQAFEbQqTWFydGluIEtyYWVtZXIgPE1hcnRpbi5LcmFlbWVy +QE1jaC5TTkkuRGU+ +=hcsR +-----END PGP PUBLIC KEY BLOCK----- + + +Type Bits/KeyID Date User ID +pub 1024/EC140B81 1997/04/10 Dirk-Willem van Gulik <dirkx@webweaving.org> + Dirk-Willem van Gulik <Dirk.vanGulik@jrc.it> + Dirk-Willem van Gulik <dirkx@webweaving.nl> + Dirk-Willem van Gulik <dirkx@dds.nl> + Dirk-Willem van Gulik <dirkx@bigfoot.com> + Dirk-Willem van Gulik <dirkx@technologist.com> + +-----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 <dgaudet@arctic.org> +uid Dean Gaudet <dgaudet-djg20@arctic.org> +uid Dean Gaudet <dgaudet@apache.org> + +-----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 <sfx@unix-ag.org> + Lars Eilebrecht <Lars.Eilebrecht@unix-ag.org> + Lars `SFX' Eilebrecht <SFX@unix-ag.uni-siegen.de> + Lars `SFX' Eilebrecht <SFX@appl2.hrz.uni-siegen.de> + Lars `SFX' Eilebrecht <SFX@appl1.hrz.uni-siegen.de> + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.3a + +mQCKAi6+wOsAAAED53PJgrIYS7iHbZn0ycrnzS03fwvwsDpoAVouoqqBSVNoVXH+ +lL+8HzX/fADvNyk1lYi5kTiYR2meKB1p0qpvj4bQ8ZEmcBemhV0FbESJ4CxIgy6V +euxOD3v9gauyf1u4lkfyLIsCepuJqpkH+aOviE9VhTcE/D6Pt/L4g0HZAAURtCFM +YXJzIEVpbGVicmVjaHQgPHNmeEB1bml4LWFnLm9yZz6JAJUDBRA2KRwZms08wKmf +dd0BASoSA/9ZwyAWilXJNMWsV0KfyUeHZ7CsFA9/KQixLtpSH8ij4raLasr6rurc +Sckrd+OiQKPQG0/TSXSAEP7suatV6XTTLEFHJbmqchTZXMSapwxFWGLxdG+buCiO +uVxbpop4ZoKz2xb+GtdeyeDr+//gFL+wbEqlZMXfvwgzBCxcOM/tZYkAkgMFEDPN +Dtg+j7fy+INB2QEBxpcD527wocmN2jHxCkmImID+YMVF8g1Rij3CEy+oLAZiiNWS +Rxj2lWTHhsVZXtzF53+AD79rJqrFhZUCx+W6vG46uLMuu3/VpnEfq2QsD0d6zIUv +SDFIxsy/s4knyvgfMeXczHmb7vjGbGsyP9mqjAyN7MUcqgBBANH4HX9CSRN8tC1M +YXJzIEVpbGVicmVjaHQgPExhcnMuRWlsZWJyZWNodEB1bml4LWFnLm9yZz6JAJID +BRAzzQwFPo+38viDQdkBAa31A+dPvsRw1zWvyMDp2aQwqIawIi2wiFl56lYfpkwW +WjsdftuK0HHe+gek0aJ1vLwJFlrivroEukF1JaK3kS/ob2u/TNIZ4MKWjfhbkJW4 +0Y7gCKCUJPzh6hDw1nYfc4N9XKnwubiRVdW2ig1HVoKZUN9Ad034m30jMHEzqXbO +4LQxTGFycyBgU0ZYJyBFaWxlYnJlY2h0IDxTRlhAdW5peC1hZy51bmktc2llZ2Vu +LmRlPokAdQMFEDMR9XVLXCU0Hmjw3QEBftADALeK5boLfjNzxZ7g1VPHw6k6QwSU +ESwiPJCmGTIT5f941YhHqohgwN5kGR9XDxWCCJAqQfFvbxhiZv0zu4HvQ7FYLVLO +2zwZrVvOfR259jvGDFpPqRBq1ccxTNXuvf2a44kAlQIFEDD5Hn++gkWXZmzJrQEB +WVYD/R4XFxImsJxzpaykt8Hl4kpQNWYWHd5ae81QFla/vfIplBqeVWr299pUbO1x +Bt4EFPi5aya8CGwXs8uRsHKn3u711jfTri1mKpiMBWt149BsUk5lFCnE9gVo5UxY +cpM2vb1I5DKeo/8/DuYz1FQhXwOxGqBqIr+ggQ1fN7Q0v5qziQEVAwUQMSxVdPCJ +hGMAVxgRAQFafAf+OZxiZqpgeA3iMZzbOr17v4YjL/J4N3phrcy8ssh0rmTBbNHW +OfRR0yzGlAXespCSLzBnSQMph2MXc3Al51LK4z487iAQxpu5k/ZKrg5ahZI7X5ok +viTcRjmXkpbbXp+sMs6J3ZOOjxO1tWytSXW5/3lKwbjzaURlbUbBA9QQSGAYPnsw +Z+CPKRNuUsk2EI3y4DWVjuabOcCeNy4TLfB9UIY81oXfXOyT+i2FwZ0f1befeZuu +PICGQIxlEFi3Hd3hDEAgNJ8Hu9C6XACnYieT7dVYtlYH14UTk6/CLKkbWNhd/I5S +QMPbijKK2zU5U3vPcolA1UalSBckftDQ2iTmmYkAlQMFEDD5QYseKXCPGoSZUQEB +yFYD/jqPx2u8D1aQzKHvZqS9PUYSsPMTgn10FR/tp2c9Ch60f+BQ96fOUCzmRt94 +Iq1iMZsJ0oTyLLf6wf/Mdb1LhvsGf7rXFATh25OUpPx1qPUWstSToHSn0+Zf8e1B +0p6PJ96duI6rimoc8NKppOwSmRvqAD3ATCKpMiOSwWe9+mBZiQBVAwUQMPl9Sgk0 +Yuy5gjk9AQEX2AIAlCphj4JI/yvodYIlpC2MPOs+hfTvaMPVhSCZZ0EVfZgTZpLQ +XQDiUolYBvTHJnjBZyXZozln/df4MBHQgKWwmIkAVQIFEDD5RPk+NMzsOfhZGwEB +5EoCAINMQWZZn+12r2nFScCScf5TaKpm+Y6MfEsvVg0trveEJ74ibbFDo8ABZ2g6 +FgzfDxAMbxNsUQaMrhh0TaSC9EyJAJUCBRAw+O6OHdm2eHD917EBAfj1A/4/cYEE +a7jN8+ptmxZKsfZ0xOP2dxsPnicDT4VR16MHN6rkVrto782XSiRx3ZUsd9RjUmfH +ZA3mHoJIGo6JRFVOeyjg3LEASSSfZr4YFkhutnf0lDlJOeEKhqvIw/dSO7MDwdLx +hOqAFv9UzAlpOm4GLx9p1N61xDl1dIYEnY9cOIkAlQIFEDD5QnyFat0badac6QEB +CCMEAKV60AedWZyXWokcwWIbW/PLgNTCh8JL1vijXGnBvT2PuA0L7/rCXPhbb20A +rrq+P6xbGFxi42iWieeU2T5zN5IlPObT6cPeRWJkxPnaSf8ZD33Y1almcuhhYMUc +7lkL7yqSo1J8TRVCSxjQ4W0+QDUFIEvrigb5Scd7zYHGOqoSiQBVAgUQMPjN2pva +UYPwhBsRAQGNhQH/Z6IlBI4hdGb8teelMgY2kf3Iq08NByyygJAI48HqTe0cKIW6 +BPcBkJqMooJtRJTX6Rkt8fRKe/IPGeHGqyW3eIkA7gMFEDDhUR6K3WTWEs11KQEB +TnkGwQEgJMk8SHR+2iBmOJQ2x+kv4LVmPp8hdaKCBdfvJDmrSpuEgrBWFI9PDpSw +F7NWLPqESPnWo5dd8YeynzYz3aCiIXAOUB0rG8tujF1dSn/kFUCMqgqvbPOU3sSv +6tVlECIAh67GTNHn61IIhLM0KG4v9elo0Lk/SpWwRRPJZW/ltQBApjtR+juFOiq6 +86+eE9kKBCImCIthBeE/cf6JfwuS4+1ui+MmkkqrnO8+07bdjbkWTSzTL3l12v/t +M2p8Fwqps41y+3nIEOzq7Isf4zBjfw2ZKeXbEXq0M0xhcnMgYFNGWCcgRWlsZWJy +ZWNodCA8U0ZYQGFwcGwyLmhyei51bmktc2llZ2VuLmRlPokAlQIFEDD5Hv6+gkWX +ZmzJrQEBD9QD/iIIvOUqyKRBWjHgJD7zoskxDQH/YVhJu59zoCEOJGwXFPLlT3ce +meMCaVLa5XvoDnLYWZ/bfI5nFd9vF9GwwbmP8/x39Z3N2xKfJpD8eH5inu5AwtIs +kfXjmcZhSfDgv2XpAaFigz3wIBt+XbkPRxJJxfqD5oJ1ys0qNe0U6jjyiQEVAwUQ +MSxVrvCJhGMAVxgRAQHLVgf/cW6FlzmOeIvJ/3yB7vhSOlpivnY00iKnzzCpWLOa +saC4NPazhqNIewBa01KSuamIicYkzXk8MeaTq5EaQfJyA+NtdWSm/3/ivKWoO4Ka +qJbVPnxaDnB2KBH+2mq0BJ4rS4i2jVZuopbtMAHV+lQUHaVH826YaFPa+425A/H+ +Oaqn2EdkL80fpIJsACsudYPDGCKS3zcMjspVK1cXqNRDzIOZ8I/XtyNEJpw1yRGf +t4jrn4lj9jU4y0v6sFOt6jpuvAmyRN/pebwjYJw1Ye697MMkn0nEafH55Et+XfdB +OYNm3Sb/J2g8j2JVVhN6JKuFYyM1kvK13Rky3SiLPUzD94kAlQIFEDD5QqqFat0b +adac6QEB6HsD/RooPR6pFnSisCerTlPhSvDI2gl2HUMFw0CZJ5JKVlj5GFDZp5jl +0yhgCFCweFuE7RUgMOkvGeEoEPZeyipacsrVIcO26aCQyerLTQd6JTgOuCEeEvkj +BwiqOrVNSEPM5TWPzQc7Q7IDtKTsCT+xNGtO6Pi2+ArZaodZTtp4tXkCiQBVAgUQ +MPjOC5vaUYPwhBsRAQHdVAH/eIgCk6fo3/Mvxu7IESdDLM/ozh14yvZz6FvC/VKt +Sp51goqsV5jI9wKANIjonLeO7GJubjO+lqHvsEVsGQ+wpIkA7gMFEDDhUjOK3WTW +Es11KQEBgTUGwQGH8Ic7zNaUlRmYm5J8R375iP8CrJ/xILbET69VsR2aDG2MA2z8 +NBBkV1ARrAC2YWa9sO91yCyf3NAI6I1oqtbv/09Im/s0bTu66dWrqRAiuTB3Ou+g +HJ0fc85gTWcBd9/xS/mNlZb1/ZXjkBaYdl0Bzm72c3+HqZjHzT3nlxVY5HCi15J4 +iDgCuCPzeo1r8QgGmsbP7fD+0Hka7tlXb87WxPZt+nkjGS9xmLrNHw5/vJpcN4+f +zevzhTQD8IcsUr0QcZUH9jZpm6xWpibPF5z7FzXTorguf+W0M0xhcnMgYFNGWCcg +RWlsZWJyZWNodCA8U0ZYQGFwcGwxLmhyei51bmktc2llZ2VuLmRlPokAlQIFEDD5 +Htq+gkWXZmzJrQEBjswD/1Nwm7yoV6sj7qTiKaW9S3DQD3LKXtweiDdYF0lp961I +WkuyBur4aYBNROQK82zFQqKNKfsm+FXu+N6AYQ2zEUJEUkT9RQgmsrfU1q067Zoo ++dck5T2zuH+/kqmF9t28Gv4jjxVTit6C92NEhciutNO48kK32BT2mgX2w7tds6G4 +iQEVAwUQMSxVvPCJhGMAVxgRAQFUKgf/Y4Djeo18+ZAfr0BKl14P29dKK3p8OLcn +qXh6juBfTRiWnFJtrQfGH9w3pQvpi2RRuDZTTQzhO4eOq2g5gy9MytU1htLRVpVw +BnmmjLRWz0WGqr4y4ZULbg3ha5NsfBppdgHKk5Y+BptvIL/37ZBkztkiBXfs0Zbc +3fZR4bSU1xDOE+HS0BofOxubqfZrCZvAjMCC5NJ4R13H8xnYg6NKQCAqOfeCOVWk +Gnc/BK7VArMXjC8o/9nQDzY2fRPINPnCb4f/4PunwOrEza6zLxXfgNraQJ19boPb +/o9DBlvNOWkq9gSmVnTEkqrEMtiXd31KAU/LVCRH/70mx7XZkF5/N4kAVQMFEDD5 +fY4JNGLsuYI5PQEBW0kB/0s9AqawHqJ/0rO9jsMhk3vuHNgwVF4DoKTL5EDIORET +ccAf4UZVJo+JzmjYxc1f2RkwkMkk/N9afKZmcNSYzteJAFUCBRAw+UUZPjTM7Dn4 +WRsBAah7AgCIWR/HNt+V20bDueCO9mhwGirq5E7TJU+C9xT+3BeZXmyy/AR7tWJd +KnC6laGDLnMko3CWr/XRKD+rC050nNsriQCVAgUQMPju3R3Ztnhw/dexAQF0awP/ +cXwIBaEAj4D/ShzMna3NQ/EM4aTniAHdVIH4d6Uh2RwDCoYt6HwEP11xfBwI6bDW +lQhdUgDzGOXmOxKxv/Xti4viHOwO1KqjRtHOyDf4hI/ou2p0bntXMZ5yVv0WakyW +7kYd7KxTbYd/CTKe8HB+8wkj8h1pb31JJoXzWsgmwXiJAJUCBRAw+ULYhWrdG2nW +nOkBAQUwA/9AUqFQsXW9kMi5RooITiQbRynunPh2aqadVnuLZoAhxp16c+EQYpc4 +Qi6jLPBVemHdS4PW8vJegF1pJtDZ4VfLNwwkIxj7Y0hU8A4BcHUIfFdOER7SwbW/ +i7QTU8u3vNHfmgIodv19D7rFxEzqqPxMHRpIs8/IOG9L3zc3kV8rnYkAVQIFEDD4 +ziyb2lGD8IQbEQEBg6kCANj9mr20gcYRZ4eDfnuTSkSvtjvKox0EtM+UnAAgihxU +q5vNCZDEeohZSZBR/p2pktcSu+cdk5bBFHtzkaNTt82JAFUCBRAv0u2cmTVOo2j9 +/00BAdubAgCcmQl3gvdeQuA2zSmqHNrCEXdmjIIltOWc8WFCPJjDt6c2cBdmuwoO +YknWWGDMKXvTlh6lPgIVx3fhlhobxxFKiQCVAgUQL9M+R0axifvg3qptAQF7tAP7 +B78y93gaojDMC8NwfiNKh7l5cBh0ONA+W1g3O7YLE5W7Z/fOg4H3pOujnqU7H3Ns +ChmDxtBKQIIiZXpnNg4Nt3F765t8EPrMmjjQJ4a6+8CHfmXmfNSWqPMdjgJW4ykM +nUasGhgF1Z8flNNkfH5gfW9Gr8UcClgKqa5xvkhC5cyJAFUDBRAv0zvKQwZ3Rx/t +AzsBAVs0Af91cEjH3oZPIaydSZxPUjF1SE3p93NnY6A3mKZR1vkewG6sRqVa4MO4 +lw8w8AU7ge2rvwupF3weF1Z9DG2bauGmiQCVAgUQL9M4SuXLhgyrRKDJAQH/vQQA +jGM370MwcIfmtQ9e/0j0nztQwQ18dXMA+dMyNHiGrc+JC71u5zjxwmO7R1Vv7ZSA +af9PslF/118wS6fFg9BP+LO5T4D44wMJTfiMMv30Q4Sfxn9DX9N3iYzL1PTHmlCO +fCQQqvC451XbcXECqmqWHEqII8//4w/h9yrl/5F/uXmJAFUCBRAv0lcf/ZhK+bLW +8KUBAc/rAf9rmJ56O40QVD803+bU1zSiSE1x+FURt+ceAsozqo9taFoRIGXTa8Mp +swStyALnJKpyDkGEnTfRdARVQtcEzYJniQBVAgUQL9JDvxEZCRz6lM9/AQG2xwH+ +IQAJZEvldNHzeikez18Txy12EnJ9k+za2rjPVnlX7+teIY3VNO1homUgwqjoOHpZ +kdGgdOdmufOglT3Rqrk5FYkAlQIFEC/Rt+1JSaYsE52Q4QEBzUYEAMonc3UFNjGo +n8F/omc0PPA3rfH2IS6G31FN6fRarW1Pwk7CWlx3wgHm6gO9xfV5lDjBJ+lVmbmL +z/1MZhg646eFRbugtBYbOXwE6zmNrKBhchVueVONzwWPIA8BZtR2Lw6CikAOhKgl +4ndg8PO8UUg8gh0VUKGTPDK0MKR7ZCpGiQBVAgUQL9IXPnmMGAx7t12JAQGpIAH/ +Zrl16ULw3/gl7T11EbnbA9T3LjXuD4TG3IGeEV3z1wbRp227yN12a3PbavEKJj1m +fWrZaT89Xt1smYBaIwX4aokAlQIFEC8YGepIX6svI9kr4wEBnO0D/1R4HlUM43CU +jxdinzcijOJxRNe7ieXpp7xNn9SuJotDVeCLDRFSpmF2EFb0KDyoX2bY18xPT9sW +tIMYv4XigSBwfuR+Sp+J1CLdP+zzmIZbZBc+3G5xM6nipvaKl1DkhSlLqedW4dmg +1rKgCOXYKHdzHUcaneNE4rkoWlVwG5rhiQCVAgUQLs1+vx4pcI8ahJlRAQHwXAP8 +CKLDWFLJ7Fc3JZ0MnuPxW79M9nRQwL2TI/Vd4lCUSiDOUdEvjU45MLmLgU+4OZNP +eXaBSLkN4z8PUkxGEEvSeCFE7u04VNq1GJ2aC+fHVFzuWbp0LsezqDSnm6xvBxz4 +0yEaZnkXu3+66kXZV/E4BNIkCaB5V2qXxrBIg0D10iCJAJQCBRAux7auD0cvWzTX +TcEBATNVA/jU+bTUqnlZdrf6KgCv+hDOs6VO538cExQNsBl7x82Djbp8Q5t21YEV +8LiFN1imuLYqHXqDEHt7qtroNaBYXgnR24QjI3urel+kYMibZWxGrq382C2apRea +EDmQ1qtEzP+kXexaawAzKMo8VKWMnXjQYBLZohuUqfciE9A7OQF1iQBFAgUQLr7F +rZXTi1FmcalVAQFOLQF/WCuTfcsEc7z1WK5BMQltCgnNvuz0himNP2FxPl4g5rq3 +u8i03dqPbuVwfrxSzy+m +=tg0D +-----END PGP PUBLIC KEY BLOCK----- diff --git a/usr.sbin/httpd/LICENSE b/usr.sbin/httpd/LICENSE index ec09d302feb..6ac6538b3ca 100644 --- a/usr.sbin/httpd/LICENSE +++ b/usr.sbin/httpd/LICENSE @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1997 The Apache Group. All rights reserved. + * 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 @@ -20,9 +20,14 @@ * * 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. + * prior written permission. For written permission, please contact + * apache@apache.org. * - * 5. Redistributions of any form whatsoever must retain the following + * 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/)." diff --git a/usr.sbin/httpd/Makefile b/usr.sbin/httpd/Makefile index 15197f846c9..e87f386909b 100644 --- a/usr.sbin/httpd/Makefile +++ b/usr.sbin/httpd/Makefile @@ -31,6 +31,7 @@ MANUALFILES= \ manual/header.html \ manual/index.html \ manual/install.html \ + manual/install-tpf.html \ manual/invoking.html \ manual/keepalive.html \ manual/location.html \ @@ -41,9 +42,11 @@ MANUALFILES= \ manual/new_features_1_2.html \ manual/new_features_1_3.html \ manual/process-model.html \ + manual/readme-tpf.html \ manual/sections.html \ manual/sourcereorg.html \ manual/stopping.html \ + manual/suexec_1_2.html \ manual/suexec.html \ manual/unixware.html \ manual/upgrading_to_1_3.html \ @@ -156,7 +159,23 @@ ICONFILES= \ icons/box2.gif icons/generic.gif icons/pdf.gif \ icons/script.gif icons/broken.gif icons/generic.red.gif \ icons/pie0.gif icons/sound1.gif icons/burst.gif \ - icons/generic.sec.gif icons/pie1.gif icons/sound2.gif + icons/generic.sec.gif icons/pie1.gif icons/sound2.gif \ + icons/small/uu.gif icons/small/back.gif icons/small/binary.gif \ + icons/small/binhex.gif icons/small/blank.gif \ + icons/small/broken.gif icons/small/burst.gif \ + icons/small/comp1.gif icons/small/comp2.gif \ + icons/small/compressed.gif icons/small/continued.gif \ + icons/small/dir.gif icons/small/dir2.gif \ + icons/small/forward.gif icons/small/generic.gif \ + icons/small/generic2.gif icons/small/generic3.gif \ + icons/small/image.gif icons/small/image2.gif \ + icons/small/index.gif icons/small/key.gif icons/small/movie.gif \ + icons/small/rainbow.gif icons/small/sound.gif \ + icons/small/sound2.gif icons/small/tar.gif icons/small/text.gif \ + icons/small/transfer.gif icons/small/unknown.gif \ + icons/small/README.txt + + distribution: @-for i in ${CONFFILES}; do \ diff --git a/usr.sbin/httpd/Makefile.tmpl b/usr.sbin/httpd/Makefile.tmpl index a1fea7c7c51..c8a0538c20d 100644 --- a/usr.sbin/httpd/Makefile.tmpl +++ b/usr.sbin/httpd/Makefile.tmpl @@ -1,5 +1,5 @@ ## ==================================================================== -## Copyright (c) 1998 The Apache Group. All rights reserved. +## 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 @@ -70,7 +70,7 @@ SHELL = /bin/sh # paths to the source tree parts -TOP = @TOP@ +TOP = . SRC = @SRC@ MKF = @MKF@ AUX = @AUX@ @@ -88,6 +88,9 @@ INSTALL_SCRIPT = $(INSTALL) -m 755 INSTALL_DATA = $(INSTALL) -m 644 PERL = @PERL@ +# installation name of Apache webserver +TARGET = @TARGET@ + # installation root # (overrideable by package maintainers for # rolling packages without bristling the system) @@ -113,6 +116,8 @@ 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@ @@ -147,10 +152,15 @@ all: build # build the package build: @echo "===> $(SRC)" - @$(MAKE) -f $(MKF) $(MFLAGS) $(MFWD) build-std $(build-support) + @$(MAKE) -f $(TOP)/$(MKF) $(MFLAGS) $(MFWD) build-std + @$(MAKE) -f $(TOP)/$(MKF) $(MFLAGS) $(MFWD) $(build-support) @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: @cd $(TOP)/$(SRC); $(MAKE) $(MFLAGS) SDP=$(SRC)/ all @@ -166,8 +176,8 @@ build-support: -DUID_MIN=$(suexec_uidmin) \ -DGID_MIN=$(suexec_gidmin) \ -DUSERDIR_SUFFIX=\"$(suexec_userdir)\" \ - -DLOG_EXEC=\"$(logfiledir)/suexec_log\" \ - -DDOC_ROOT=\"$(datadir)/htdocs\" \ + -DLOG_EXEC=\"$(suexec_logexec)\" \ + -DDOC_ROOT=\"$(suexec_docroot)\" \ -DSAFE_PATH=\"$(suexec_safepath)\" \ ' \ suexec; \ @@ -183,28 +193,33 @@ build-support: # separate parts of the installation process. install: @if [ ! -f $(TOP)/$(SRC)/.apaci.build.ok ]; then \ - $(MAKE) -f $(MKF) $(MFLAGS) $(MFWD) build; \ + $(MAKE) -f $(TOP)/$(MKF) $(MFLAGS) $(MFWD) build; \ else \ :; \ fi - @$(MAKE) -f $(MKF) $(MFLAGS) $(MFWD) \ + @$(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)/{httpd,access,srm}.conf"; \ + 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 "| $(sbindir)/$${apachectl} start"; \ echo "| |"; \ echo "| Thanks for using Apache. The Apache Group |"; \ echo "| http://www.apache.org/ |"; \ @@ -213,7 +228,7 @@ install: # the non-verbose variant for package maintainers install-quiet: - @$(MAKE) -f $(MKF) $(MFLAGS) $(MFWD) QUIET=1 install + @$(MAKE) -f $(TOP)/$(MKF) $(MFLAGS) $(MFWD) QUIET=1 install # create the installation tree install-mktree: @@ -236,26 +251,26 @@ install-mktree: # install the server program and optionally corresponding # shared object files. install-programs: - @echo "===> [programs: Installing Apache httpd program and shared objects]" - $(INSTALL_PROGRAM) $(TOP)/$(SRC)/httpd $(root)$(sbindir)/httpd + @echo "===> [programs: Installing Apache $(TARGET) program and shared objects]" + $(INSTALL_PROGRAM) $(TOP)/$(SRC)/$(TARGET) $(root)$(sbindir)/$(TARGET) -@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_DSO) $(TOP)/$(SRC)/libhttpd.ep $(root)$(libexecdir)/libhttpd.ep"; \ - $(INSTALL_DSO) $(TOP)/$(SRC)/libhttpd.ep $(root)$(libexecdir)/libhttpd.ep; \ - echo "$(INSTALL_DSO) $(TOP)/$(SRC)/libhttpd.$${SHLIB_SUFFIX_NAME} $(root)$(libexecdir)/libhttpd.$${SHLIB_SUFFIX_NAME}"; \ - $(INSTALL_DSO) $(TOP)/$(SRC)/libhttpd.$${SHLIB_SUFFIX_NAME} $(root)$(libexecdir)/libhttpd.$${SHLIB_SUFFIX_NAME}; \ + echo "$(INSTALL_DSO) $(TOP)/$(SRC)/lib$(TARGET).ep $(root)$(libexecdir)/lib$(TARGET).ep"; \ + $(INSTALL_DSO) $(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)/libhttpd.$${SHLIB_SUFFIX_NAME}.*"; \ - $(RM) $(libexecdir)/libhttpd.$${SHLIB_SUFFIX_NAME}.*; \ + 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)/libhttpd.$${SHLIB_SUFFIX_NAME} $(root)$(libexecdir)/libhttpd.$${SHLIB_SUFFIX_NAME}.$${suffix}"; \ - $(LN) $(root)$(libexecdir)/libhttpd.$${SHLIB_SUFFIX_NAME} $(root)$(libexecdir)/libhttpd.$${SHLIB_SUFFIX_NAME}.$${suffix}; \ + 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/httpd.8 + $(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 |\ @@ -276,7 +291,7 @@ install-programs: sed -e 's:SharedModule:AddModule:' \ -e 's:modules/[^/]*/::' \ -e 's:[ ]lib: mod_:' \ - -e 's:\.[soa]*$$:.c:' >>$(SRC)/.apaci.install.conf; \ + -e 's:\.[soam].*$$:.c:' >>$(SRC)/.apaci.install.conf; \ fi @echo "<=== [programs]" @@ -285,12 +300,18 @@ 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.1 $(root)$(mandir)/man1/ab.1 - @echo "$(INSTALL_SCRIPT) $(TOP)/$(SRC)/support/apachectl[*] $(root)$(sbindir)/apachectl"; \ - sed -e 's;PIDFILE=.*;PIDFILE=$(runtimedir)/httpd.pid;' \ - -e 's;HTTPD=.*;HTTPD=$(sbindir)/httpd;' \ + @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 - $(INSTALL_DATA) $(TOP)/$(SRC)/support/apachectl.1 $(root)$(mandir)/man1/apachectl.1 + $(INSTALL_SCRIPT) $(TOP)/$(SRC)/.apaci.install.tmp $(root)$(sbindir)/$${apachectl}; \ + echo "$(INSTALL_DATA) $(TOP)/$(SRC)/support/apachectl.1 $(root)$(mandir)/man1/$${apachectl}.1"; \ + $(INSTALL_DATA) $(TOP)/$(SRC)/support/apachectl.1 $(root)$(mandir)/man1/$${apachectl}.1 $(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 @@ -332,7 +353,9 @@ install-include: $(CP) $(TOP)/$(SRC)/include/*.h $(root)$(includedir)/ @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)/ + $(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 @echo "<=== [include]" @@ -344,8 +367,8 @@ install-data: echo "[PRESERVING EXISTING DATA SUBDIR: $(root)$(datadir)/htdocs/]"; \ else \ echo "Copying tree $(TOP)/htdocs/ -> $(root)$(datadir)/htdocs/"; \ - (cd $(TOP)/htdocs/ && $(TAR) cf - *) |\ - (cd $(root)$(datadir)/htdocs/ && $(TAR) xf -); \ + (cd $(TOP)/htdocs/ && $(TAR) -hcf - *) |\ + (cd $(root)$(datadir)/htdocs/ && $(TAR) -xf -); \ find $(root)$(datadir)/htdocs/ -type d -exec chmod a+rx {} \; ; \ find $(root)$(datadir)/htdocs/ -type f -exec chmod a+r {} \; ; \ fi @@ -355,14 +378,14 @@ install-data: for script in printenv test-cgi; do \ cat $(TOP)/cgi-bin/$${script} |\ sed -e 's;^#!/.*perl;#!$(PERL);' \ - > $(TOP)/$(SRC)/.apaci.install.tmp; \ + > $(TOP)/$(SRC)/.apaci.install.tmp; \ echo "$(INSTALL_DATA) $(TOP)/conf/$${script}[*] $(root)$(datadir)/cgi-bin/$${script}"; \ $(INSTALL_DATA) $(TOP)/$(SRC)/.apaci.install.tmp $(root)$(datadir)/cgi-bin/$${script}; \ done; \ fi @echo "Copying tree $(TOP)/icons/ -> $(root)$(datadir)/icons/"; \ - (cd $(TOP)/icons/ && $(TAR) cf - *) |\ - (cd $(root)$(datadir)/icons/ && $(TAR) xf -); \ + (cd $(TOP)/icons/ && $(TAR) -hcf - *) |\ + (cd $(root)$(datadir)/icons/ && $(TAR) -xf -); \ find $(root)$(datadir)/icons/ -type d -exec chmod a+rx {} \; ;\ find $(root)$(datadir)/icons/ -type f -exec chmod a+r {} \; @echo "<=== [data]" @@ -372,8 +395,18 @@ install-data: 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 "## $${conf} -- Apache HTTP server configuration file"; \ + echo "## $${target_conf} -- Apache HTTP server configuration file"; \ echo "##"; \ echo ""; \ cat $(TOP)/conf/$${conf}-dist ) |\ @@ -382,28 +415,28 @@ install-config: -e 's;@@ServerRoot@@/icons;$(datadir)/icons;' \ -e 's;@@ServerRoot@@/cgi-bin;$(datadir)/cgi-bin;' \ -e 's;@@ServerRoot@@/proxy;$(proxycachedir);' \ - -e 's;@@ServerRoot@@;$(prefix);' \ - -e 's;logs/accept.lock;$(runtimedir)/httpd.lock;' \ - -e 's;logs/apache_runtime_status;$(runtimedir)/httpd.scoreboard;' \ - -e 's;logs/httpd.pid;$(runtimedir)/httpd.pid;' \ - -e 's;logs/access_log;$(logfiledir)/access_log;' \ - -e 's;logs/error_log;$(logfiledir)/error_log;' \ - -e 's;logs/referer_log;$(logfiledir)/referer_log;' \ - -e 's;logs/agent_log;$(logfiledir)/agent_log;' \ + -e 's;@@ServerRoot@@;$(prefix);g' \ + -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;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)/$${conf}.default"; \ - $(INSTALL_DATA) $(TOP)/$(SRC)/.apaci.install.tmp $(root)$(sysconfdir)/$${conf}.default; \ - if [ ! -f "$(root)$(sysconfdir)/$${conf}" ]; then \ - echo "$(INSTALL_DATA) $(TOP)/conf/$${conf}-dist[*] $(root)$(sysconfdir)/$${conf}"; \ - $(INSTALL_DATA) $(TOP)/$(SRC)/.apaci.install.tmp $(root)$(sysconfdir)/$${conf}; \ + > $(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)/$${conf}]"; \ + echo "[PRESERVING EXISTING CONFIG FILE: $(root)$(sysconfdir)/$${target_conf}]"; \ fi; \ done -@for conf in mime.types magic; do \ @@ -427,7 +460,7 @@ install-config: # created by the build target clean: @echo "===> $(SRC)" - @$(MAKE) -f $(MKF) $(MFLAGS) $(MFWD) clean-std $(clean-support) + @$(MAKE) -f $(TOP)/$(MKF) $(MFLAGS) $(MFWD) clean-std $(clean-support) @echo "<=== $(SRC)" @$(RM) $(TOP)/$(SRC)/.apaci.build.ok @@ -450,14 +483,14 @@ clean-support: # When --shadow is used we just remove the complete shadow tree. distclean: @if [ ".$(SRC)" = .src ]; then \ - $(MAKE) -f $(MKF) $(MFLAGS) $(MFWD) distclean-normal; \ + $(MAKE) -f $(TOP)/$(MKF) $(MFLAGS) $(MFWD) distclean-normal; \ else \ - $(MAKE) -f $(MKF) $(MFLAGS) $(MFWD) distclean-shadow; \ + $(MAKE) -f $(TOP)/$(MKF) $(MFLAGS) $(MFWD) distclean-shadow; \ fi distclean-normal: @echo "===> $(SRC)" - @$(MAKE) -f $(MKF) $(MFLAGS) $(MFWD) distclean-std $(distclean-support) + @$(MAKE) -f $(TOP)/$(MKF) $(MFLAGS) $(MFWD) distclean-std $(distclean-support) @echo "<=== $(SRC)" -$(RM) $(SRC)/Configuration.apaci -$(RM) $(SRC)/apaci @@ -480,7 +513,7 @@ distclean-support: distclean-shadow: $(RM) -r $(SRC) - $(RM) $(MKF) + $(RM) $(TOP)/$(MKF) -@if [ ".`ls $(TOP)/src.* 2>/dev/null`" = . ]; then \ echo "$(RM) Makefile"; \ $(RM) Makefile; \ diff --git a/usr.sbin/httpd/README.configure b/usr.sbin/httpd/README.configure index e8d0ddc2271..66390da3b71 100644 --- a/usr.sbin/httpd/README.configure +++ b/usr.sbin/httpd/README.configure @@ -98,7 +98,9 @@ $ ./configure --prefix=/path/to/apache \ --enable-suexec \ --suexec-caller=www \ - --suexec-userdir=.www + --suexec-userdir=.www \ + --suexec-docroot=/path/to/root/dir \ + --suexec-logfile=/path/to/logdir/suexec_log \ --suexec-uidmin=1000 \ --suexec-gidmin=1000 \ --suexec-safepath="/bin:/usr/bin" @@ -106,9 +108,12 @@ $ make install This automatically builds and installs Apache 1.3 with suEXEC support for - the caller uid "www" and the user's homedir subdirs ".www". The access - paths for the suexec program are automatically adjusted and the suexec - program is installed, so Apache can find it on startup. + the caller uid "www" and the user's homedir subdirs ".www". The default + paths for --suexec-docroot is the value from the --datadir option with + the suffix "/htdocs" and the --logfiledir value with the suffix + "/suexec_log" for the --suexec-logfile option. The access paths for the + suexec program are automatically adjusted and the suexec program is + installed, so Apache can find it on startup. Building multiple platforms in parallel --------------------------------------- diff --git a/usr.sbin/httpd/conf/access.conf b/usr.sbin/httpd/conf/access.conf index 96cafc8a289..a38b11baced 100644 --- a/usr.sbin/httpd/conf/access.conf +++ b/usr.sbin/httpd/conf/access.conf @@ -1,95 +1,8 @@ -# access.conf: Global access configuration -# Online docs at http://www.apache.org/ - -# This file defines server settings which affect which types of services -# are allowed, and in what circumstances. - -# 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). - -# Originally by Rob McCool - -# First, we configure the "default" to be a very restrictive set of -# permissions. - -<Directory /> -Options FollowSymLinks -AllowOverride None -</Directory> - -# 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. - -<Directory /var/www/htdocs> - -# 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 - -</Directory> - -# @@ServerRoot@@/cgi-bin should be changed to whatever your ScriptAliased -# CGI directory exists, if you have that configured. - -<Directory /var/www/cgi-bin> -AllowOverride None -Options None -</Directory> - -# Allow server status reports, with the URL of http://servername/server-status -# Change the ".your_domain.com" to match your domain to enable. - -#<Location /server-status> -#SetHandler server-status - -#order deny,allow -#deny from all -#allow from .your_domain.com -#</Location> - -# 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. - -#<Location /server-info> -#SetHandler server-info - -#order deny,allow -#deny from all -#allow from .your_domain.com -#</Location> - -# 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. - -#<Location /cgi-bin/phf*> -#deny from all -#ErrorDocument 403 http://phf.apache.org/phf_abuse_log.cgi -#</Location> - -# You may place any other directories or locations you wish to have -# access information for after this one. - +# +# 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/usr.sbin/httpd/conf/access.conf-dist b/usr.sbin/httpd/conf/access.conf-dist index c965cdb7569..a38b11baced 100644 --- a/usr.sbin/httpd/conf/access.conf-dist +++ b/usr.sbin/httpd/conf/access.conf-dist @@ -1,95 +1,8 @@ -# access.conf: Global access configuration -# Online docs at http://www.apache.org/ - -# This file defines server settings which affect which types of services -# are allowed, and in what circumstances. - -# 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). - -# Originally by Rob McCool - -# First, we configure the "default" to be a very restrictive set of -# permissions. - -<Directory /> -Options FollowSymLinks -AllowOverride None -</Directory> - -# 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. - -<Directory "@@ServerRoot@@/htdocs"> - -# 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 - -</Directory> - -# @@ServerRoot@@/cgi-bin should be changed to whatever your ScriptAliased -# CGI directory exists, if you have that configured. - -<Directory "@@ServerRoot@@/cgi-bin"> -AllowOverride None -Options None -</Directory> - -# Allow server status reports, with the URL of http://servername/server-status -# Change the ".your_domain.com" to match your domain to enable. - -#<Location /server-status> -#SetHandler server-status - -#order deny,allow -#deny from all -#allow from .your_domain.com -#</Location> - -# 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. - -#<Location /server-info> -#SetHandler server-info - -#order deny,allow -#deny from all -#allow from .your_domain.com -#</Location> - -# 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. - -#<Location /cgi-bin/phf*> -#deny from all -#ErrorDocument 403 http://phf.apache.org/phf_abuse_log.cgi -#</Location> - -# You may place any other directories or locations you wish to have -# access information for after this one. - +# +# 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/usr.sbin/httpd/conf/access.conf-dist-win b/usr.sbin/httpd/conf/access.conf-dist-win index ab32c4e2a73..a38b11baced 100644 --- a/usr.sbin/httpd/conf/access.conf-dist-win +++ b/usr.sbin/httpd/conf/access.conf-dist-win @@ -1,101 +1,8 @@ -# access.conf: Global access configuration -# Online docs at http://www.apache.org/ - -# This file defines server settings which affect which types of services -# are allowed, and in what circumstances. - -# 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). - -# Note: Where filenames are specified, you must use forward slashes -# instead of backslashes. e.g. "c:/apache" instead of "c:\apache". If -# the drive letter is ommited, the drive where Apache.exe is located -# will be assumed - -# Originally by Rob McCool - -# First, we configure the "default" to be a very restrictive set of -# permissions. - -# XXXX disabled because it is currently broken on Win32 -#<Directory /> -#Options FollowSymLinks -#AllowOverride None -#</Directory> - -# 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. - -<Directory "@@ServerRoot@@/htdocs"> - -# 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 - -</Directory> - -# @@ServerRoot@@/cgi-bin should be changed to whatever your ScriptAliased -# CGI directory exists, if you have that configured. - -<Directory "@@ServerRoot@@/cgi-bin"> -AllowOverride None -Options None -</Directory> - -# Allow server status reports, with the URL of http://servername/server-status -# Change the ".your_domain.com" to match your domain to enable. - -#<Location /server-status> -#SetHandler server-status - -#order deny,allow -#deny from all -#allow from .your_domain.com -#</Location> - -# 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. - -#<Location /server-info> -#SetHandler server-info - -#order deny,allow -#deny from all -#allow from .your_domain.com -#</Location> - -# 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. - -#<Location /cgi-bin/phf*> -#deny from all -#ErrorDocument 403 http://phf.apache.org/phf_abuse_log.cgi -#</Location> - -# You may place any other directories or locations you wish to have -# access information for after this one. - +# +# 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/usr.sbin/httpd/conf/httpd.conf b/usr.sbin/httpd/conf/httpd.conf index e413ab7c4d7..f712717054c 100644 --- a/usr.sbin/httpd/conf/httpd.conf +++ b/usr.sbin/httpd/conf/httpd.conf @@ -1,12 +1,184 @@ -# This is the main server configuration file. See URL http://www.apache.org/ -# for instructions. - +# +# 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 <URL:http://www.apache.org/docs/> for detailed information about +# the directives. +# # Do NOT simply read the instructions in here without understanding -# what they do, if you are unsure consult the online docs. You have been -# warned. +# 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 +# /var/www/conf/srm.conf and then /var/www/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 <URL:http://www.apache.org/docs/mod/core.html#lockfile>); +# you will save yourself a lot of trouble. +# +# Do NOT add a slash at the end of the directory path. +# +ServerRoot "/var/www" + +# +# 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 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 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 in httpd.conf-dist 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. +# +MaxRequestsPerChild 30 + +# +# Listen: Allows you to bind Apache to specific IP addresses and/or +# ports, in addition to the default. See also the <VirtualHost> +# directive. +# +#Listen 3000 +#Listen 12.34.56.78:80 -# Originally by Rob McCool +# +# 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 <VirtualHost> 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 @@ -17,227 +189,619 @@ # 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 -# ServerType is either inetd, or standalone. - -ServerType standalone +# +# 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 -# If you are running from inetd, go to "ServerAdmin". +### 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 +# <VirtualHost> definition. These values also provide defaults for +# any <VirtualHost> containers you may define later in the file. +# +# All of these directives may appear inside <VirtualHost> containers, +# in which case these default settings will be overridden for the +# virtual host being defined. +# -# Port: The port the standalone listens to. For ports < 1023, you will -# need httpd to be run as root initially. +# +# 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 -# HostnameLookups: Log the names of clients or just their IP numbers -# 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. - -HostnameLookups off - +# # 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. +# . 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! -# On OpenBSD, use user www, group www - +# On OpenBSD, use user www, group www. +# User www Group www +# # ServerAdmin: Your address, where problems with the server should be -# e-mailed. - +# e-mailed. This address appears on some server-generated pages, such +# as error documents. +# ServerAdmin you@your.address -# ServerRoot: The directory the server's config, error, and log files -# are kept in. -# NOTE! If you intend to place this on a NFS (or otherwise network) -# mounted filesystem then please read the LockFile documentation, -# you will save yourself a lot of trouble. +# +# 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 -ServerRoot /var/www +# +# 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 "/var/www/htdocs" -# BindAddress: You can support virtual hosts with this option. This option -# 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 VirtualHost directive. +# +# 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. +# +<Directory /> + Options FollowSymLinks + AllowOverride None +</Directory> -#BindAddress * +# +# 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. +# +<Directory "/var/www/htdocs"> + +# +# 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 +</Directory> + +# +# 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. +# +#<Directory /*/public_html> +# AllowOverride FileInfo AuthConfig Limit +# Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec +# <Limit GET POST OPTIONS PROPFIND> +# Order allow,deny +# Allow from all +# </Limit> +# <Limit PUT DELETE PATCH PROPPATCH MKCOL COPY MOVE LOCK UNLOCK> +# Order deny,allow +# Deny from all +# </Limit> +#</Directory> + +# +# 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. +# +<Files .htaccess> + Order allow,deny + Deny from all +</Files> -# ErrorLog: The location of the error log file. If this does not start -# with /, ServerRoot is prepended to it. +# +# 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 <IfModule> container. +# This means that the MIMEMagicFile directive will only be processed if the +# module is part of the server. +# +<IfModule mod_mime_magic.c> + MIMEMagicFile conf/magic +</IfModule> + +# +# 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 <VirtualHost> +# container, error messages relating to that virtual host will be +# logged here. If you *do* define an error logfile for a <VirtualHost> +# 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 of the access logfile (Common Logfile Format). -# If this does not start with /, ServerRoot is prepended to it. - +# +# The location and format of the access logfile (Common Logfile Format). +# If you do not define any access logfiles within a <VirtualHost> +# container, they will be logged here. Contrariwise, if you *do* +# define per-<VirtualHost> access logfiles, transactions will be +# logged therein and *not* in this file. +# CustomLog logs/access_log common -# If you would like to have an agent and referer logfile uncomment the +# +# 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 +# +# 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 -# PidFile: The file the server should log its pid to -PidFile logs/httpd.pid +# +# 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 -# ScoreBoardFile: File used to store internal server process information. -# Not all architectures require this. But if yours does (you'll know because -# this file is 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 +# +# 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/ "/var/www/icons/" + +<Directory "/var/www/icons"> + Options Indexes MultiViews + AllowOverride None + Order allow,deny + Allow from all +</Directory> -# 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 +# 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/ "/var/www/cgi-bin/" -# 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 +# "/var/www/cgi-bin" should be changed to whatever your ScriptAliased +# CGI directory exists, if you have that configured. +# +<Directory "/var/www/cgi-bin"> + AllowOverride None + Options None + Order allow,deny + Allow from all +</Directory> -# 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. +# 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 +# -#ServerName new.host.name +# +# Directives controlling the display of server-generated directory listings. +# -# 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 SSI generated documents). -# Set to "EMail" to also include a mailto: link to the ServerAdmin. -# Set to one of: On | Off | EMail -ServerSignature on +# +# FancyIndexing is whether you want fancy directory indexing or standard +# +IndexOptions FancyIndexing -# 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 CGIs. -UseCanonicalName on +# +# 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^^ -# 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. +# +# DefaultIcon is which icon to show for files which do not have an icon +# explicitly set. +# +DefaultIcon /icons/unknown.gif -#CacheNegotiatedDocs +# +# 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 -# Timeout: The number of seconds before receives and sends time out +# +# 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 -Timeout 300 +# +# 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 -# KeepAlive: Whether or not to allow persistent connections (more than -# one request per connection). Set to "Off" to deactivate. +# +# 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 -KeepAlive On +# +# 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 -# 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. +# +# 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 -MaxKeepAliveRequests 100 +# +# 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 -# KeepAliveTimeout: Number of seconds to wait for the next request +# +# 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 -KeepAliveTimeout 15 +# +# To use server-parsed HTML files +# +#AddType text/html .shtml +#AddHandler server-parsed .shtml -# 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). +# +# Uncomment the following line to enable Apache's send-asis HTTP file +# feature +# +#AddHandler send-as-is asis -# 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. These values are probably OK for most sites --- +# +# If you wish to use server-parsed imagemap files, use +# +#AddHandler imap-file map -MinSpareServers 5 -MaxSpareServers 10 +# +# To enable type maps, you might want to use +# +#AddHandler type-map var -# Number of servers to start --- should be a reasonable ballpark figure. +# +# 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 +# -StartServers 5 +# +# 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 -# 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... +# +# MetaSuffix: specifies the file name suffix for the file containing the +# meta information. +# +#MetaSuffix .meta -MaxClients 150 +# +# 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. -# 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. On most systems, this -# isn't really needed, but a few (such as Solaris) do have notable leaks -# in the libraries. +# +# 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 -MaxRequestsPerChild 30 +# +# 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 -# Proxy Server directives. Uncomment the following line to -# enable the proxy server: +# +# Allow server status reports, with the URL of http://servername/server-status +# Change the ".your_domain.com" to match your domain to enable. +# +#<Location /server-status> +# SetHandler server-status +# Order deny,allow +# Deny from all +# Allow from .your_domain.com +#</Location> + +# +# 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. +# +#<Location /server-info> +# SetHandler server-info +# Order deny,allow +# Deny from all +# Allow from .your_domain.com +#</Location> +# +# 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. +# +#<Location /cgi-bin/phf*> +# Deny from all +# ErrorDocument 403 http://phf.apache.org/phf_abuse_log.cgi +#</Location> + +# +# Proxy Server directives. Uncomment the following lines to +# enable the proxy server: +# +#<IfModule mod_proxy.c> #ProxyRequests On +# +#<Directory proxy:*> +# Order deny,allow +# Deny from all +# Allow from .your_domain.com +#</Directory> +# # 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 +# +#ProxyVia On +# # To enable the cache as well, edit and uncomment the following lines: # (no cacheing without CacheRoot) - -#CacheRoot @@ServerRoot@@/proxy - +# +#CacheRoot "/var/www/proxy" #CacheSize 5 #CacheGcInterval 4 #CacheMaxExpire 24 @@ -245,26 +809,36 @@ MaxRequestsPerChild 30 #CacheDefaultExpire 1 #NoCache a_domain.com another_domain.edu joes.garage_sale.com -# Listen: Allows you to bind Apache to specific IP addresses and/or -# ports, in addition to the default. See also the VirtualHost command +#</IfModule> +# End of proxy directives. -#Listen 3000 -#Listen 12.34.56.78:80 +### 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 <URL:http://www.apache.org/docs/vhosts/> +# for further details before you try to setup virtual hosts. +# You may use the command line option '-S' to verify your virtual host +# configuration. -# VirtualHost: Allows the daemon to respond to requests for more than one -# server address, if your server machine is configured to accept IP packets -# for multiple addresses. This can be accomplished with the ifconfig -# alias flag, or through kernel patches like VIF. - -# Any httpd.conf or srm.conf directive may go into a VirtualHost command. -# See also the BindAddress entry. - -#<VirtualHost host.some_domain.com> -#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 -#TransferLog logs/host.some_domain.com-access_log -#</VirtualHost> +# +# 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. +# +#<VirtualHost ip.address.of.host.some_domain.com> +# 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 +#</VirtualHost> +#<VirtualHost _default_:*> +#</VirtualHost> diff --git a/usr.sbin/httpd/conf/httpd.conf-dist b/usr.sbin/httpd/conf/httpd.conf-dist index 264d9f0b52f..c6f92e52a03 100644 --- a/usr.sbin/httpd/conf/httpd.conf-dist +++ b/usr.sbin/httpd/conf/httpd.conf-dist @@ -1,12 +1,185 @@ -# This is the main server configuration file. See URL http://www.apache.org/ -# for instructions. - +# +# 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 <URL:http://www.apache.org/docs/> for detailed information about +# the directives. +# # Do NOT simply read the instructions in here without understanding -# what they do, if you are unsure consult the online docs. You have been -# warned. +# 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". +# -# Originally by Rob McCool +### 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 <URL:http://www.apache.org/docs/mod/core.html#lockfile>); +# 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 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 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 in httpd.conf-dist 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. +# +MaxRequestsPerChild 30 + +# +# Listen: Allows you to bind Apache to specific IP addresses and/or +# ports, in addition to the default. See also the <VirtualHost> +# 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 <VirtualHost> 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 @@ -17,226 +190,618 @@ # 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 -# ServerType is either inetd, or standalone. - -ServerType standalone +# +# 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 -# If you are running from inetd, go to "ServerAdmin". +### 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 +# <VirtualHost> definition. These values also provide defaults for +# any <VirtualHost> containers you may define later in the file. +# +# All of these directives may appear inside <VirtualHost> containers, +# in which case these default settings will be overridden for the +# virtual host being defined. +# -# Port: The port the standalone listens to. For ports < 1023, you will -# need httpd to be run as root initially. +# +# 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 -# HostnameLookups: Log the names of clients or just their IP numbers -# 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. - -HostnameLookups off - +# # 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. +# . 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. - +# e-mailed. This address appears on some server-generated pages, such +# as error documents. +# ServerAdmin you@your.address -# ServerRoot: The directory the server's config, error, and log files -# are kept in. -# NOTE! If you intend to place this on a NFS (or otherwise network) -# mounted filesystem then please read the LockFile documentation, -# you will save yourself a lot of trouble. +# +# 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 -ServerRoot "@@ServerRoot@@" +# +# 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" -# BindAddress: You can support virtual hosts with this option. This option -# 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 VirtualHost directive. +# +# 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. +# +<Directory /> + Options FollowSymLinks + AllowOverride None +</Directory> -#BindAddress * +# +# 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. +# +<Directory "@@ServerRoot@@/htdocs"> + +# +# 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 +</Directory> + +# +# 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. +# +#<Directory /*/public_html> +# AllowOverride FileInfo AuthConfig Limit +# Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec +# <Limit GET POST OPTIONS PROPFIND> +# Order allow,deny +# Allow from all +# </Limit> +# <Limit PUT DELETE PATCH PROPPATCH MKCOL COPY MOVE LOCK UNLOCK> +# Order deny,allow +# Deny from all +# </Limit> +#</Directory> + +# +# 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. +# +<Files .htaccess> + Order allow,deny + Deny from all +</Files> + +# +# 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 -# ErrorLog: The location of the error log file. If this does not start -# with /, ServerRoot is prepended to it. +# +# 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 <IfModule> container. +# This means that the MIMEMagicFile directive will only be processed if the +# module is part of the server. +# +<IfModule mod_mime_magic.c> + MIMEMagicFile conf/magic +</IfModule> + +# +# 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 <VirtualHost> +# container, error messages relating to that virtual host will be +# logged here. If you *do* define an error logfile for a <VirtualHost> +# 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 of the access logfile (Common Logfile Format). -# If this does not start with /, ServerRoot is prepended to it. - +# +# The location and format of the access logfile (Common Logfile Format). +# If you do not define any access logfiles within a <VirtualHost> +# container, they will be logged here. Contrariwise, if you *do* +# define per-<VirtualHost> access logfiles, transactions will be +# logged therein and *not* in this file. +# CustomLog logs/access_log common -# If you would like to have an agent and referer logfile uncomment the +# +# 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 +# +# 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 -# PidFile: The file the server should log its pid to -PidFile logs/httpd.pid +# +# 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 -# ScoreBoardFile: File used to store internal server process information. -# Not all architectures require this. But if yours does (you'll know because -# this file is 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 +# +# 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/" + +<Directory "@@ServerRoot@@/icons"> + Options Indexes MultiViews + AllowOverride None + Order allow,deny + Allow from all +</Directory> -# 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 +# 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/" -# 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 +# "@@ServerRoot@@/cgi-bin" should be changed to whatever your ScriptAliased +# CGI directory exists, if you have that configured. +# +<Directory "@@ServerRoot@@/cgi-bin"> + AllowOverride None + Options None + Order allow,deny + Allow from all +</Directory> -# 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. +# 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 +# -#ServerName new.host.name +# +# Directives controlling the display of server-generated directory listings. +# -# 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 SSI generated documents). -# Set to "EMail" to also include a mailto: link to the ServerAdmin. -# Set to one of: On | Off | EMail -ServerSignature on +# +# FancyIndexing is whether you want fancy directory indexing or standard +# +IndexOptions FancyIndexing -# 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 CGIs. -UseCanonicalName on +# +# 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^^ -# 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. +# +# DefaultIcon is which icon to show for files which do not have an icon +# explicitly set. +# +DefaultIcon /icons/unknown.gif -#CacheNegotiatedDocs +# +# 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 -# Timeout: The number of seconds before receives and sends time out +# +# 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 -Timeout 300 +# +# 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 -# KeepAlive: Whether or not to allow persistent connections (more than -# one request per connection). Set to "Off" to deactivate. +# +# 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 -KeepAlive On +# +# 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 -# 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. +# +# 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 -MaxKeepAliveRequests 100 +# +# 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 -# KeepAliveTimeout: Number of seconds to wait for the next request +# +# 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 -KeepAliveTimeout 15 +# +# To use server-parsed HTML files +# +#AddType text/html .shtml +#AddHandler server-parsed .shtml -# 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). +# +# Uncomment the following line to enable Apache's send-asis HTTP file +# feature +# +#AddHandler send-as-is asis -# 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. These values are probably OK for most sites --- +# +# If you wish to use server-parsed imagemap files, use +# +#AddHandler imap-file map -MinSpareServers 5 -MaxSpareServers 10 +# +# To enable type maps, you might want to use +# +#AddHandler type-map var -# Number of servers to start --- should be a reasonable ballpark figure. +# +# 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 +# -StartServers 5 +# +# 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 -# 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... +# +# MetaSuffix: specifies the file name suffix for the file containing the +# meta information. +# +#MetaSuffix .meta -MaxClients 150 +# +# 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. -# 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. On most systems, this -# isn't really needed, but a few (such as Solaris) do have notable leaks -# in the libraries. +# +# 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 -MaxRequestsPerChild 30 +# +# 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 -# Proxy Server directives. Uncomment the following line to -# enable the proxy server: +# +# Allow server status reports, with the URL of http://servername/server-status +# Change the ".your_domain.com" to match your domain to enable. +# +#<Location /server-status> +# SetHandler server-status +# Order deny,allow +# Deny from all +# Allow from .your_domain.com +#</Location> + +# +# 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. +# +#<Location /server-info> +# SetHandler server-info +# Order deny,allow +# Deny from all +# Allow from .your_domain.com +#</Location> +# +# 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. +# +#<Location /cgi-bin/phf*> +# Deny from all +# ErrorDocument 403 http://phf.apache.org/phf_abuse_log.cgi +#</Location> + +# +# Proxy Server directives. Uncomment the following lines to +# enable the proxy server: +# +#<IfModule mod_proxy.c> #ProxyRequests On +# +#<Directory proxy:*> +# Order deny,allow +# Deny from all +# Allow from .your_domain.com +#</Directory> +# # 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 +# +#ProxyVia On +# # To enable the cache as well, edit and uncomment the following lines: # (no cacheing without CacheRoot) - -#CacheRoot @@ServerRoot@@/proxy - +# +#CacheRoot "@@ServerRoot@@/proxy" #CacheSize 5 #CacheGcInterval 4 #CacheMaxExpire 24 @@ -244,26 +809,36 @@ MaxRequestsPerChild 30 #CacheDefaultExpire 1 #NoCache a_domain.com another_domain.edu joes.garage_sale.com -# Listen: Allows you to bind Apache to specific IP addresses and/or -# ports, in addition to the default. See also the VirtualHost command +#</IfModule> +# End of proxy directives. -#Listen 3000 -#Listen 12.34.56.78:80 +### 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 <URL:http://www.apache.org/docs/vhosts/> +# for further details before you try to setup virtual hosts. +# You may use the command line option '-S' to verify your virtual host +# configuration. -# VirtualHost: Allows the daemon to respond to requests for more than one -# server address, if your server machine is configured to accept IP packets -# for multiple addresses. This can be accomplished with the ifconfig -# alias flag, or through kernel patches like VIF. - -# Any httpd.conf or srm.conf directive may go into a VirtualHost command. -# See also the BindAddress entry. - -#<VirtualHost host.some_domain.com> -#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 -#TransferLog logs/host.some_domain.com-access_log -#</VirtualHost> +# +# 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. +# +#<VirtualHost ip.address.of.host.some_domain.com> +# 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 +#</VirtualHost> +#<VirtualHost _default_:*> +#</VirtualHost> diff --git a/usr.sbin/httpd/conf/httpd.conf-dist-win b/usr.sbin/httpd/conf/httpd.conf-dist-win index 7cf79956aa6..1ad64192832 100644 --- a/usr.sbin/httpd/conf/httpd.conf-dist-win +++ b/usr.sbin/httpd/conf/httpd.conf-dist-win @@ -1,26 +1,179 @@ -# This is the main server configuration file. See URL http://www.apache.org/ -# for instructions. - +# +# 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 <URL:http://www.apache.org/docs/> for detailed information about +# the directives. +# # Do NOT simply read the instructions in here without understanding -# what they do, if you are unsure consult the online docs. You have been -# warned. +# 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. +# -# Originally by Rob McCool +### 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. +# -# Note: Where filenames are specified, you must use forward slashes -# instead of backslashes. e.g. "c:/apache" instead of "c:\apache". If -# the drive letter is ommited, the drive where Apache.exe is located -# will be assumed +# +# ServerType is either inetd, or standalone. Inetd mode is only supported on +# Unix platforms. +# +ServerType standalone -# ServerType must be 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@@" -ServerType standalone +# +# 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 + +# +# 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 + +# +# 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 <VirtualHost> +# 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 <VirtualHost> and Listen directives. +# +#BindAddress * # -# The following lists extra modules that can be uncommented to be loaded -# to enable extra functionality. See the manual -# (http://www.apache.org/docs/mod/) for details on the functionality -# of each module. +# 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 @@ -33,176 +186,560 @@ ServerType standalone #LoadModule status_module modules/ApacheModuleStatus.dll #LoadModule usertrack_module modules/ApacheModuleUserTrack.dll +### 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 +# <VirtualHost> definition. These values also provide defaults for +# any <VirtualHost> containers you may define later in the file. +# +# All of these directives may appear inside <VirtualHost> containers, +# in which case these default settings will be overridden for the +# virtual host being defined. +# -# Port: The port the standalone listens to. +# +# 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 -# HostnameLookups: Log the names of clients or just their IP numbers -# 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. +# +# 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 -HostnameLookups off +# +# 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 -# If you wish httpd to run as a different user or group, you must run -# httpd as root initially and it will switch. -# ServerAdmin: Your address, where problems with the server should be -# e-mailed. +# +# 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" -ServerAdmin you@your.address +# +# 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. +# +<Directory /> + Options FollowSymLinks + AllowOverride None +</Directory> -# ServerRoot: The directory the server's config, error, and log files -# are kept in +# +# 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. +# -ServerRoot "@@ServerRoot@@" +# +# This should be changed to whatever you set DocumentRoot to. +# +<Directory "@@ServerRoot@@/htdocs"> -# BindAddress: You can support virtual hosts with this option. This option -# 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 VirtualHost directive. +# +# 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 -#BindAddress * +# +# 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 +</Directory> + +# +# 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 -# ErrorLog: The location of the error log file. If this does not start -# with /, ServerRoot is prepended to it. +# +# 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. +# +<Files .htaccess> + Order allow,deny + Deny from all +</Files> + +# +# 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 <IfModule> container. +# This means that the MIMEMagicFile directive will only be processed if the +# module is part of the server. +# +<IfModule mod_mime_magic.c> + MIMEMagicFile conf/magic +</IfModule> + +# +# 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 <VirtualHost> +# container, error messages relating to that virtual host will be +# logged here. If you *do* define an error logfile for a <VirtualHost> +# 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 of the access logfile (Common Logfile Format). -# If this does not start with /, ServerRoot is prepended to it. - +# +# The location and format of the access logfile (Common Logfile Format). +# If you do not define any access logfiles within a <VirtualHost> +# container, they will be logged here. Contrariwise, if you *do* +# define per-<VirtualHost> access logfiles, transactions will be +# logged therein and *not* in this file. +# CustomLog logs/access.log common -# If you would like to have an agent and referer logfile uncomment the +# +# 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 +# +# 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 -# PidFile: The file the server should log its pid to -PidFile logs/httpd.pid +# +# 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 -# ScoreBoardFile: File used to store internal server process information. -# Not all architectures require this. But if yours does (you'll know because -# this file is created when you run Apache) then you *must* ensure that -# no two invocations of Apache share the same scoreboard file. -ScoreBoardFile logs/apache_status +# +# 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/" -# 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 +# 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/" -# 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. +# "@@ServerRoot@@/cgi-bin" should be changed to whatever your ScriptAliased +# CGI directory exists, if you have that configured. +# +<Directory "@@ServerRoot@@/cgi-bin"> + AllowOverride None + Options None +</Directory> -#ServerName new.host.name +# +# 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 +# -# 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 SSI generated documents). -# Set to "EMail" to also include a mailto: link to the ServerAdmin. -# Set to one of: On | Off | EMail -ServerSignature on +# +# Directives controlling the display of server-generated directory listings. +# -# 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 CGIs. -UseCanonicalName on +# +# FancyIndexing is whether you want fancy directory indexing or standard +# +IndexOptions FancyIndexing -# 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. +# +# 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^^ -#CacheNegotiatedDocs +# +# DefaultIcon is which icon to show for files which do not have an icon +# explicitly set. +# +DefaultIcon /icons/unknown.gif -# Timeout: The number of seconds before receives and sends time out +# +# 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 -Timeout 300 +# +# 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 -# KeepAlive: Whether or not to allow persistent connections (more than -# one request per connection). Set to "Off" to deactivate. +# +# 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 -KeepAlive On +# +# 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 -# 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. +# +# 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 -MaxKeepAliveRequests 100 +# +# 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 -# KeepAliveTimeout: Number of seconds to wait for the next request +# +# 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 -KeepAliveTimeout 15 +# +# 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 -# Apache 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 determine the behaviour of the threads and processes. +# +# To use server-parsed HTML files +# +#AddType text/html .shtml +#AddHandler server-parsed .shtml -# Don't force a server to exit after it has served some number of requests. -# If you do want server's to exit after they have run for a long time (to -# help the system clean up after the process), please set this to a pretty -# large number - like 10,000. What this will do, is, each child server will -# exit after serving 10,000 requests, and another server will take its place. +# +# Uncomment the following line to enable Apache's send-asis HTTP file +# feature +# +#AddHandler send-as-is asis -MaxRequestsPerChild 0 +# +# If you wish to use server-parsed imagemap files, use +# +#AddHandler imap-file map -# Number of concurrent threads at a time (set the value to more or less -# depending on the responsiveness you want and the resources you wish -# this server to consume). +# +# To enable type maps, you might want to use +# +#AddHandler type-map var -ThreadsPerChild 50 +# +# 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. +# +#<Location /server-status> +# SetHandler server-status +# Order deny,allow +# Deny from all +# Allow from .your_domain.com +#</Location> + +# +# 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. +# +#<Location /server-info> +# SetHandler server-info +# Order deny,allow +# Deny from all +# Allow from .your_domain.com +#</Location> + +# +# 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. +# +#<Location /cgi-bin/phf*> +# Deny from all +# ErrorDocument 403 http://phf.apache.org/phf_abuse_log.cgi +#</Location> + +# # 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 +# +#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 @@ -210,26 +747,33 @@ ThreadsPerChild 50 #CacheDefaultExpire 1 #NoCache a_domain.com another_domain.edu joes.garage_sale.com -# Listen: Allows you to bind Apache to specific IP addresses and/or -# ports, in addition to the default. See also the VirtualHost command +### 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 <URL:http://www.apache.org/docs/vhosts/> +# for further details before you try to setup virtual hosts. +# You may use the command line option '-S' to verify your virtual host +# configuration. -#Listen 3000 -#Listen 12.34.56.78:80 +# +# 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: Allows the daemon to respond to requests for more than one -# server address, if your server machine is configured to accept IP packets -# for multiple addresses. This can be accomplished with the ifconfig -# alias flag, or through kernel patches like VIF. - -# Any httpd.conf or srm.conf directive may go into a VirtualHost command. -# See also the BindAddress entry. - -#<VirtualHost host.some_domain.com> -#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 -#TransferLog logs/host.some_domain.com-access.log +# +# VirtualHost example: +# Almost any Apache directive may go into a VirtualHost container. +# +#<VirtualHost ip.address.of.host.some_domain.com> +# 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 #</VirtualHost> - +#<VirtualHost _default_:*> +#</VirtualHost> diff --git a/usr.sbin/httpd/conf/mime.types b/usr.sbin/httpd/conf/mime.types index 6408d6a8eea..d8e3b94a66c 100644 --- a/usr.sbin/httpd/conf/mime.types +++ b/usr.sbin/httpd/conf/mime.types @@ -1,51 +1,175 @@ -# This file controls what MIME types are sent to the client for the -# given file extensions. Sending the correct MIME type to the client +# 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 MIME types -# please read RFC 2045, 2046, 2047, 2048, and 2077. +# 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 <ftp://ftp.iana.org/in-notes/iana/assignments/media-types/>. # MIME type Extension +application/EDI-Consent +application/EDI-X12 +application/EDIFACT application/activemessage -application/andrew-inset +application/andrew-inset ez application/applefile application/atomicmail +application/cals-1840 +application/commonground +application/cybercash application/dca-rft application/dec-dx +application/eshop +application/hyperstudio +application/iges application/mac-binhex40 hqx application/mac-compactpro cpt application/macwriteii +application/marc +application/mathematica 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/pgp-encrypted +application/pgp-keys +application/pgp-signature +application/pkcs10 +application/pkcs7-mime +application/pkcs7-signature application/postscript ai eps ps -application/powerpoint ppt +application/prs.alvestrand.titrax-sheet +application/prs.cww +application/prs.nprend application/remote-printing +application/riscos application/rtf rtf +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 sml +application/smil smi smil +application/vemmi +application/vnd.3M.Post-it-Notes +application/vnd.FloGraphIt +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.comsocaller +application/vnd.dna +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.salt +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.hp-HPGL +application/vnd.hp-PCL +application/vnd.hp-PCLXL +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.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-organizer +application/vnd.lotus-screencam +application/vnd.lotus-wordpro +application/vnd.meridian-slingshot +application/vnd.mif mif +application/vnd.minisoft-hp3000-save +application/vnd.mitsubishi.misty-guard.trustweb +application/vnd.ms-artgalry +application/vnd.ms-asf +application/vnd.ms-excel +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.powerbuilder6 +application/vnd.powerbuilder6-s +application/vnd.rapid +application/vnd.seemail +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.truedoc +application/vnd.visio +application/vnd.webturbo +application/vnd.wrq-hp3000-labelled +application/vnd.wt.stf +application/vnd.xara +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-mif mif 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 @@ -59,21 +183,35 @@ 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/midi mid midi kar audio/mpeg mpga mp2 mp3 +audio/vnd.qcelp audio/x-aiff aif aiff aifc -audio/x-pn-realaudio ram +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/cgm +image/g3fax image/gif gif image/ief ief image/jpeg jpeg jpg jpe +image/naplps image/png png +image/prs.btif image/tiff tiff tif +image/vnd.dwg +image/vnd.dxf +image/vnd.fpx +image/vnd.net-fpx +image/vnd.svf +image/vnd.xiff image/x-cmu-raster ras image/x-portable-anymap pnm image/x-portable-bitmap pbm @@ -83,30 +221,55 @@ 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 model/iges igs iges -model/vrml wrl vrml model/mesh msh mesh silo +model/vnd.dwf +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/css css +text/directory +text/enriched text/html html htm -text/plain txt +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.fmi.flexstor +text/vnd.in3d.3dml +text/vnd.in3d.spot +text/vnd.latex-z text/x-setext etx -text/x-sgml sgml sgm -text/xml xml dtd +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 - -# This is a comment. I love comments. diff --git a/usr.sbin/httpd/conf/srm.conf b/usr.sbin/httpd/conf/srm.conf index 23c953c9ce3..394b6fa64dd 100644 --- a/usr.sbin/httpd/conf/srm.conf +++ b/usr.sbin/httpd/conf/srm.conf @@ -1,250 +1,8 @@ -# With this document, you define the name space that users see of your http -# server. This file also defines server settings which affect how requests are -# serviced, and how results should be formatted. - -# See the tutorials at http://www.apache.org/ for -# more information. - -# Originally by Rob McCool; Adapted for Apache - - -# 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 /var/www/htdocs - -# UserDir: The name of the directory which is appended onto a user's home -# directory if a ~user request is recieved. - -# UserDir public_html - -# DirectoryIndex: Name of the file or files to use as a pre-written HTML -# directory index. Separate multiple entries with spaces. - -DirectoryIndex index.html - -# FancyIndexing is whether you want fancy directory indexing or standard - -FancyIndexing on - -# AddIcon tells the server which icon to show for different files or filename -# extensions - -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. -# Format: AddDescription "description" filename - -# ReadmeName is the name of the README file the server will look for by -# default. Format: ReadmeName name # -# The server will first look for name.html, include it if found, and it will -# then look for name and include it as plaintext if found. +# This is the default file for the ResourceConfig directive in httpd.conf. +# It is processed after httpd.conf but before access.conf. # -# HeaderName is the name of a file which should be prepended to -# directory indexes. - -ReadmeName README -HeaderName HEADER - -# IndexIgnore is a set of filenames which directory indexing should ignore -# Format: IndexIgnore name1 name2... - -IndexIgnore .??* *~ *# HEADER* README* RCS - -# 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. - -<Files .htaccess> -order allow,deny -deny from all -</Files> - -# TypesConfig describes where the mime.types file (or equivalent) is -# to be found. - -TypesConfig conf/mime.types - -# DefaultType is the default MIME type for documents which the server -# cannot find the type of from filename extensions. - -DefaultType text/plain - -# AddEncoding allows you to have certain browsers (Mosaic/X 2.1+) uncompress -# information on the fly. Note: Not all browsers support this. - -AddEncoding x-compress Z -AddEncoding x-gzip gz - -# 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 - -# 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 fakename url - - -# 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. - -Alias /icons/ /var/www/icons/ - -# ScriptAlias: This controls which directories contain server scripts. -# Format: ScriptAlias fakename realname - -ScriptAlias /cgi-bin/ /var/www/cgi-bin/ - -# If you want to use server side includes, or CGI outside -# ScriptAliased directories, uncomment the following lines. - -# AddType allows you to tweak mime.types without actually editing it, or to -# make certain files to be certain types. -# Format: AddType type/subtype ext1 - -# 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 - -# 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) -# Format: AddHandler action-name ext1 - -# 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 +# 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. # -# 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. 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 -# - -# mod_mime_magic allows the server to use various hints from the file itself -# to determine its type. -#MimeMagicFile conf/magic - -# 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 diff --git a/usr.sbin/httpd/conf/srm.conf-dist b/usr.sbin/httpd/conf/srm.conf-dist index d71d148b987..394b6fa64dd 100644 --- a/usr.sbin/httpd/conf/srm.conf-dist +++ b/usr.sbin/httpd/conf/srm.conf-dist @@ -1,250 +1,8 @@ -# With this document, you define the name space that users see of your http -# server. This file also defines server settings which affect how requests are -# serviced, and how results should be formatted. - -# See the tutorials at http://www.apache.org/ for -# more information. - -# Originally by Rob McCool; Adapted for Apache - - -# 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" - -# UserDir: The name of the directory which is appended onto a user's home -# directory if a ~user request is recieved. - -UserDir public_html - -# DirectoryIndex: Name of the file or files to use as a pre-written HTML -# directory index. Separate multiple entries with spaces. - -DirectoryIndex index.html - -# FancyIndexing is whether you want fancy directory indexing or standard - -FancyIndexing on - -# AddIcon tells the server which icon to show for different files or filename -# extensions - -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. -# Format: AddDescription "description" filename - -# ReadmeName is the name of the README file the server will look for by -# default. Format: ReadmeName name # -# The server will first look for name.html, include it if found, and it will -# then look for name and include it as plaintext if found. +# This is the default file for the ResourceConfig directive in httpd.conf. +# It is processed after httpd.conf but before access.conf. # -# HeaderName is the name of a file which should be prepended to -# directory indexes. - -ReadmeName README -HeaderName HEADER - -# IndexIgnore is a set of filenames which directory indexing should ignore -# Format: IndexIgnore name1 name2... - -IndexIgnore .??* *~ *# HEADER* README* RCS - -# 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. - -<Files .htaccess> -order allow,deny -deny from all -</Files> - -# TypesConfig describes where the mime.types file (or equivalent) is -# to be found. - -TypesConfig conf/mime.types - -# DefaultType is the default MIME type for documents which the server -# cannot find the type of from filename extensions. - -DefaultType text/plain - -# AddEncoding allows you to have certain browsers (Mosaic/X 2.1+) uncompress -# information on the fly. Note: Not all browsers support this. - -AddEncoding x-compress Z -AddEncoding x-gzip gz - -# 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 - -# 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 fakename url - - -# 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. - -Alias /icons/ "@@ServerRoot@@/icons/" - -# ScriptAlias: This controls which directories contain server scripts. -# Format: ScriptAlias fakename realname - -#ScriptAlias /cgi-bin/ "@@ServerRoot@@/cgi-bin/" - -# If you want to use server side includes, or CGI outside -# ScriptAliased directories, uncomment the following lines. - -# AddType allows you to tweak mime.types without actually editing it, or to -# make certain files to be certain types. -# Format: AddType type/subtype ext1 - -# 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 - -# 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) -# Format: AddHandler action-name ext1 - -# 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 +# 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. # -# 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. 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 -# - -# mod_mime_magic allows the server to use various hints from the file itself -# to determine its type. -#MimeMagicFile conf/magic - -# 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 diff --git a/usr.sbin/httpd/conf/srm.conf-dist-win b/usr.sbin/httpd/conf/srm.conf-dist-win index fdd60cf1e78..394b6fa64dd 100644 --- a/usr.sbin/httpd/conf/srm.conf-dist-win +++ b/usr.sbin/httpd/conf/srm.conf-dist-win @@ -1,258 +1,8 @@ -# With this document, you define the name space that users see of your http -# server. This file also defines server settings which affect how requests are -# serviced, and how results should be formatted. - -# See the tutorials at http://www.apache.org/ for -# more information. - -# Originally by Rob McCool; Adapted for Apache - -# Note: Where filenames are specified, you must use forward slashes -# instead of backslashes. e.g. "c:/apache" instead of "c:\apache". If -# the drive letter is ommited, the drive where Apache.exe is located -# will be assumed. - -# 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" - -# UserDir: The name of the directory which is appended onto a user's home -# directory if a ~user request is recieved. # -# Under Win32, we do not currently try to determine the home directory of -# a Windows login, so one of the forms such as the below needs to be -# used. See the manual for details. +# This is the default file for the ResourceConfig directive in httpd.conf. +# It is processed after httpd.conf but before access.conf. # -#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 - -# FancyIndexing is whether you want fancy directory indexing or standard - -FancyIndexing on - -# AddIcon tells the server which icon to show for different files or filename -# extensions - -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. -# Format: AddDescription "description" filename - -# ReadmeName is the name of the README file the server will look for by -# default. Format: ReadmeName name +# 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. # -# The server will first look for name.html, include it if found, and it will -# then look for name and include it as plaintext if found. -# -# HeaderName is the name of a file which should be prepended to -# directory indexes. - -ReadmeName README -HeaderName HEADER - -# IndexIgnore is a set of filenames which directory indexing should ignore -# Format: IndexIgnore name1 name2... - -IndexIgnore .??* *~ *# HEADER* README* RCS - -# 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. - -<Files .htaccess> -order allow,deny -deny from all -</Files> - -# TypesConfig describes where the mime.types file (or equivalent) is -# to be found. - -TypesConfig conf/mime.types - -# DefaultType is the default MIME type for documents which the server -# cannot find the type of from filename extensions. - -DefaultType text/plain - -# AddEncoding allows you to have certain browsers (Mosaic/X 2.1+) uncompress -# information on the fly. Note: Not all browsers support this. - -AddEncoding x-compress Z -AddEncoding x-gzip gz - -# 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 - -# 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 fakename url - - -# 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. - -Alias /icons/ "@@ServerRoot@@/icons/" - -# ScriptAlias: This controls which directories contain server scripts. -# Format: ScriptAlias fakename realname - -#ScriptAlias /cgi-bin/ "@@ServerRoot@@/cgi-bin/" - -# If you want to use server side includes, or CGI outside -# ScriptAliased directories, uncomment the following lines. - -# AddType allows you to tweak mime.types without actually editing it, or to -# make certain files to be certain types. -# Format: AddType type/subtype ext1 - -# 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 - -# 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) -# Format: AddHandler action-name ext1 - -# 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. 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 -# - -# mod_mime_magic allows the server to use various hints from the file itself -# to determine its type. -#MimeMagicFile conf/magic - -# 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 diff --git a/usr.sbin/httpd/configure b/usr.sbin/httpd/configure index 8a3aa60e115..88fc65e4c04 100644 --- a/usr.sbin/httpd/configure +++ b/usr.sbin/httpd/configure @@ -1,6 +1,6 @@ #!/bin/sh ## ==================================================================== -## Copyright (c) 1998 The Apache Group. All rights reserved. +## 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 @@ -58,7 +58,7 @@ ## ## configure -- Apache Autoconf-style Interface (APACI) ## -## Written by Ralf S. Engelschall <rse@apache.org> +## Initially written by Ralf S. Engelschall <rse@apache.org> ## # default input separator chars: <space><tab><cr> @@ -68,19 +68,21 @@ DIFS=' ## ## 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 @@ -94,7 +96,6 @@ esac ## ## display version information ## - if [ ".$quiet" = .no ]; then APV=`cat $src/include/httpd.h |\ grep "#define SERVER_BASEVERSION" |\ @@ -105,7 +106,6 @@ 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." @@ -117,7 +117,6 @@ fi ## ## determine path to (optional) Perl interpreter ## - PERL=no-perl-on-this-system perlpath="`$aux/PrintPath perl5 perl miniperl`" if [ ".$perlpath" != . ]; then @@ -130,7 +129,6 @@ fi ## 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 [ ".$bytes" != .3 ]; then @@ -152,7 +150,6 @@ fi ## standard Awks are really braindead and cause ## problems for our scripts under some platforms. ## - AWK=awk awkpath="`$aux/PrintPath nawk gawk awk`" if [ ".$awkpath" != . ]; then @@ -164,54 +161,37 @@ fi ## # default paths -prefix='/usr/local/apache' -exec_prefix='$prefix' -bindir='$exec_prefix/bin' -sbindir='$exec_prefix/sbin' -libexecdir='$exec_prefix/libexec' -mandir='$prefix/man' -sysconfdir='$prefix/etc' -datadir='$prefix/share' -includedir='$prefix/include' -localstatedir='$prefix/var' -runtimedir='$localstatedir/run' -logfiledir='$localstatedir/log' -proxycachedir='$localstatedir/proxy' - -# customization flags for -# automatic "apache" suffix -customized_sysconfdir=0 -customized_datadir=0 -customized_localstatedir=0 -customized_includedir=0 +prefix=UNSET -# check and debug -layout=0 +# 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" -# with support tools +# various other flags support=1 - -# with adjustments confadjust=1 +permute='' # determine rules -rules="" -rulelist="" +rules='' +rulelist='' OIFS="$IFS" IFS=' ' for rule in `grep '^Rule' $src/Configuration.tmpl`; do - rule=`echo "$rule" | sed -e 's/^Rule[ ]*//'` + rule=`echo "$rule" | sed -e 's/^Rule[ ]*//'` name=`echo "$rule" | sed -e 's/=.*$//'` - namelow=`echo "$name" | tr "A-Z" "a-z"` + namelow=`echo "$name" | tr 'A-Z' 'a-z'` arg=`echo "$rule" | sed -e 's/^.*=//'` eval "rule_$namelow=$arg" rules="$rules:$namelow" @@ -221,13 +201,11 @@ IFS="$OIFS" rules=`echo $rules | sed -e 's/^://'` # determine modules -rm -f $addconf 2>/dev/null -touch $addconf -modules="" -modulelist="" +modules='' +modulelist='' OIFS="$IFS" IFS=' ' -for module in `egrep '^[# ]*(Add|Shared)Module' $src/Configuration.tmpl`; do +for module in `egrep '^[# ]*(Add|Shared)Module' $src/Configuration.tmpl`; do add=yes share=no if [ ".`echo $module | grep '^#'`" != . ]; then @@ -239,6 +217,7 @@ for module in `egrep '^[# ]*(Add|Shared)Module' $src/Configuration.tmpl`; do module=`echo "$module" |\ sed -e 's%^.*/\(.*\)$%\1%' \ -e 's/\.[oa]$//' \ + -e 's/\.module$//' \ -e 's/^mod_//' \ -e 's/^lib//'` eval "module_$module=$add" @@ -252,7 +231,7 @@ done IFS="$OIFS" modules=`echo $modules | sed -e 's/^://'` -# backward compatibility from old src/Configuration.tmpl +# backward compatibility for old src/Configuration.tmpl # parameter names to the canonical Autoconf-style shell # variable names. OIFS="$IFS" IFS="$DIFS" @@ -266,50 +245,29 @@ for var in CFLAGS LDFLAGS LIBS INCLUDES DEPS; do done IFS="$OIFS" -# create a config status script for restoring -# the configuration via a simple shell script -if [ ".$help" = .no ]; then - 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; do - eval "val=\"\$$var\"" - if [ ".$val" != . ]; then - echo "$var=$val" |\ - sed -e 's:\(["$\\]\):\\\1:g' \ - -e 's:\([A-Z]*=\):\1":' \ - -e 's:$:" \\:' >>$configstatus +## +## support for the default layout +## +case "$*" in + *--with-layout=* ) + ;; + * ) + if [ ".$*" = . ]; then + set -- '--with-layout=Apache' + else + set -- '--with-layout=Apache' "$@" fi - done - if [ $# -eq 0 ]; then - echo "./configure" >>$configstatus - else - echo $SEO "./configure \\" >>$configstatus - for arg - do - echo "$arg" |\ - sed -e 's:\(["$\\]\):\\\1:g' \ - -e 's:^:":' \ - -e 's:$:" \\:' >>$configstatus - done - fi - echo '"$@"' >>$configstatus - echo '' >>$configstatus - chmod a+x $configstatus -fi + ;; +esac ## -## parse argument line options +## Iterate over the command line options the first time. ## - -apc_prev="" +## 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 @@ -324,16 +282,178 @@ do -*=*) 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 " --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 " --without-support disable the build and installation of support tools" + echo " --without-confadjust disable the user/situation adjustments in config" + 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 "" + 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 [ ".$apc_option" = ".--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 + OIFS="$IFS" IFS="$DIFS" + for var in prefix exec_prefix bindir sbindir libexecdir mandir \ + sysconfdir datadir 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="$OIFS" + rm -f $pldconf 2>/dev/null + if [ ".$prefix" = .UNSET ]; then + echo "configure:Error: Path layout definition not found or incorrect" 1>&2 + exit 1 + fi + if [ ".$quiet" = .no ]; then + echo " + using installation path layout: $name ($file)" + fi + 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='' +OIFS1="$IFS" IFS="$DIFS" +for apc_option +do + # if previous option needs an argument, assign it. + if [ ".$apc_prev" != . ]; 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) + --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 [ .$quiet = .no ]; 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 [ .$quiet = .no ]; 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) @@ -345,10 +465,15 @@ do echo "## Apache Makefile (shadow wrapper)" >> Makefile echo "##" >> Makefile echo "" >> Makefile + if [ ".$shadow" != . ]; then + echo "SHADOW=$shadow" >> Makefile + else + echo "SHADOW=." >> Makefile + fi 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 " @\$(MAKE) -f Makefile.\$(GNUTRIPLE) \$(MFLAGS) \$@" >> Makefile + echo " @cd \$(SHADOW); \$(MAKE) -f Makefile.\$(GNUTRIPLE) \$(MFLAGS) \$@" >> Makefile echo "" >> Makefile fi # set shadow paths @@ -357,9 +482,10 @@ do shadowaux="src.$gnutriple/helpers" shadowsedsubst="src.$gnutriple/.apaci.sedsubst" shadowaddconf="src.$gnutriple/.apaci.addconf" + shadowtplconf="src.$gnutriple/.apaci.tplconf" # (re)create shadow tree if [ .$quiet = .no ]; then - echo " + create shadow tree ($shadowsrc)" + echo " + creating internal platform shadow tree ($shadowsrc)" fi rm -rf $shadowsrc $aux/mkshadow.sh $src $shadowsrc @@ -368,127 +494,66 @@ do src=$shadowsrc aux=$shadowaux sedsubst=$shadowsedsubst - rm -f $addconf 2>/dev/null addconf=$shadowaddconf - rm -f $addconf 2>/dev/null - touch $addconf + tplconf=$shadowtplconf ;; - --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 switch to a shadow tree for building" - echo "" - echo "Stand-alone options:" - echo " --help, -h print this message" - echo " --layout print installation layout (check and debug)" - echo "" - echo "Installation layout options:" - 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 [EPREFIX/bin]" - echo " --sbindir=DIR install sysadmin executables in DIR [EPREFIX/sbin]" - echo " --libexecdir=DIR install program executables in DIR [EPREFIX/libexec]" - echo " --mandir=DIR install manual pages in DIR [PREFIX/man]" - echo " --sysconfdir=DIR install configuration files in DIR [PREFIX/etc]" - echo " --datadir=DIR install read-only data files in DIR [PREFIX/share]" - echo " --includedir=DIR install includes files in DIR [PREFIX/include]" - echo " --localstatedir=DIR install modifiable data files in DIR [PREFIX/var]" - echo " --runtimedir=DIR install runtime data in DIR [PREFIX/var/run]" - echo " --logfiledir=DIR install logfile data in DIR [PREFIX/var/log]" - echo " --proxycachedir=DIR install proxy cache data in DIR [PREFIX/var/proxy]" - echo " --compat install with old Apache 1.2 installation paths" - 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 third-party Module source" - echo " --activate-module=FILE on-the-fly activate existing third-party Module source" - 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 shared object" - echo " --disable-shared=NAME disable build of Module named 'NAME' as a shared object" - echo " --with-perl=FILE set the path to the optional Perl interpreter to use" - echo " --without-support disable the build and installation of support tools" - echo " --without-confadjust disable some build user/situation adjustments to config files" - 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-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 "" - exit 0 + --show-layout|--layout) + show_layout=1 ;; - --layout) - 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" - customized_sysconfdir=1 + autosuffix_sysconfdir=no ;; --datadir=*) datadir="$apc_optarg" - customized_datadir=1 + autosuffix_datadir=no ;; --includedir=*) includedir="$apc_optarg" - customized_includedir=1 + autosuffix_includedir=no ;; --localstatedir=*) localstatedir="$apc_optarg" - customized_localstatedir=1 + autosuffix_localstatedir=no ;; --runtimedir=*) runtimedir="$apc_optarg" + autosuffix_runtimedir=no ;; --logfiledir=*) logfiledir="$apc_optarg" + autosuffix_logfiledir=no ;; --proxycachedir=*) proxycachedir="$apc_optarg" - ;; - --compat) - exec_prefix='$prefix' - bindir='$exec_prefix/bin' - sbindir='$exec_prefix/bin' - libexecdir='$exec_prefix/libexec' - mandir='$prefix/man' - sysconfdir='$prefix/conf' - datadir='$prefix' - includedir='$prefix/include' - localstatedir='$prefix' - runtimedir='$localstatedir/logs' - logfiledir='$localstatedir/logs' - proxycachedir='$localstatedir/proxy' - customized_sysconfdir=1 - customized_datadir=1 - customized_localstatedir=1 - customized_includedir=1 + autosuffix_proxycachedir=no ;; --add-module=*) file="$apc_optarg" @@ -505,6 +570,11 @@ do if [ ".$file" != ".$src/modules/extra/$modfilec" ]; then cp $file $src/modules/extra/$modfilec fi + if [ ".$addconf_created" = .0 ]; 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 @@ -531,6 +601,11 @@ do ;; esac modfile=`echo $file | sed -e 's;^src/;;'` + if [ ".$addconf_created" = .0 ]; 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 @@ -693,6 +768,29 @@ do ;; 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 [ ".$exists" = . ]; 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" ;; @@ -706,6 +804,14 @@ do 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 @@ -733,9 +839,48 @@ if [ ".$apc_prev" != . ]; then echo "configure:Error: missing argument to --`echo $apc_prev | sed 's/_/-/g'`" 1>&2 exit 1 fi +if [ ".$addconf_created" = .0 ]; then + rm -f $addconf 2>/dev/null + touch $addconf 2>/dev/null +fi ## -## a few errors +## 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 [ ".$val" != . ]; 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 [ ".$suexec" = .1 ]; then if [ ".$suexec_ok" = .0 ]; then @@ -746,12 +891,6 @@ if [ ".$suexec" = .1 ]; then echo " and htdocs/manual/suexec.html documents first." exit 1 fi -fi - -## -## a few warnings -## -if [ ".$suexec" = .1 ]; then if [ ".`id | grep root`" = . ]; then echo " + Warning: You enabled the suEXEC feature. Be aware that you need" 1>&2 echo " + root privileges for this, at the latest at the installation step." 1>&2 @@ -765,30 +904,34 @@ if [ ".$PERL" = .no-perl-on-this-system ]; then fi ## +## target name +## +if [ ".$TARGET" != . ]; 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 \ - includedir localstatedir runtimedir \ - logfiledir proxycachedir; do +for var in prefix exec_prefix bindir sbindir libexecdir mandir \ + sysconfdir datadir includedir localstatedir runtimedir \ + logfiledir proxycachedir suexec_docroot suexec_logexec; do eval "val=\"\$$var\""; val=`echo $val | sed -e 's:/*$::'` eval "$var=\"$val\"" - case $var in - libexecdir|sysconfdir|datadir|localstatedir|includedir ) - eval "val=\$$var" - case $val in - *apache | *apache* ) ;; - * ) eval "customized=\$customized_$var" - if [ ".$customized" = .0 ]; then - eval "$var=\"\$$var/apache\"" - fi - ;; - esac - ;; - esac + # expand value + eval "val=\$$var" + # add target suffix when requested + if [ ".`echo $val | grep $thetarget`" = . ]; then + eval "autosuffix=\$autosuffix_$var" + if [ ".$autosuffix" = .yes ]; then + eval "$var=\"\$$var/$thetarget\"" + fi + fi done IFS="$OIFS" @@ -796,15 +939,15 @@ IFS="$OIFS" ## determine special configurable Makefile targets ## if [ ".$support" = .1 ]; then - build_support=build-support - install_support=install-support - clean_support=clean-support - distclean_support=distclean-support + build_support='build-support' + install_support='install-support' + clean_support='clean-support' + distclean_support='distclean-support' else - build_support= - install_support= - clean_support= - distclean_support= + build_support='' + install_support='' + clean_support='' + distclean_support='' fi ## @@ -846,7 +989,7 @@ libexecdir_relative=`echo $libexecdir | sed -e "s:^$prefix/*::" -e 's:\(.\)$:\1/ ## ## check and debug ## -if [ ".$layout" = .1 ]; then +if [ ".$show_layout" = .1 ]; then echo "" echo "Installation paths:" echo " prefix: $prefix" @@ -865,18 +1008,29 @@ if [ ".$layout" = .1 ]; then echo "" echo "Compilation paths:" echo " HTTPD_ROOT: $prefix" - echo " SUEXEC_BIN: $sbindir/suexec" echo " SHARED_CORE_DIR: $libexecdir" - echo " DEFAULT_PIDLOG: ${runtimedir_relative}httpd.pid" - echo " DEFAULT_SCOREBOARD: ${runtimedir_relative}httpd.scoreboard" - echo " DEFAULT_LOCKFILE: ${runtimedir_relative}httpd.lock" + 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}httpd.conf" + 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 [ ".$suexec" = .1 ]; 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" + echo "" + fi exit 0 fi @@ -888,10 +1042,10 @@ if [ .$quiet = .no ]; then fi sed <Makefile.tmpl >$mkf \ -e "s%@PERL@%$PERL%g" \ --e "s%@TOP@%$top%g" \ -e "s%@SRC@%$src%g" \ -e "s%@MKF@%$mkf%g" \ -e "s%@AUX@%$aux%g" \ +-e "s%@TARGET@%$thetarget%g" \ -e "s%@prefix@%$prefix%g" \ -e "s%@exec_prefix@%$exec_prefix%g" \ -e "s%@bindir@%$bindir%g" \ @@ -908,6 +1062,8 @@ sed <Makefile.tmpl >$mkf \ -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" \ @@ -932,13 +1088,13 @@ 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}httpd.pid\"'" >>$src/apaci -echo "echo '-DDEFAULT_SCOREBOARD=\"${runtimedir_relative}httpd.scoreboard\"'" >>$src/apaci -echo "echo '-DDEFAULT_LOCKFILE=\"${runtimedir_relative}httpd.lock\"'" >>$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}httpd.conf\"'" >>$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 @@ -956,7 +1112,7 @@ 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; do + LDFLAGS_SHLIB_EXPORT LIBS INCLUDES RANLIB DEPS TARGET; do eval "val=\"\$$var\""; if [ ".$val" != . ]; then case $var in @@ -1008,22 +1164,94 @@ if [ ".$shared_so" = .yes ]; then exit 1 fi +# module permutation support +if [ ".$permute" != . ]; then + sed -e '/## mod_mmap_static/,$d' <src/Configuration.tmpl >$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 OIFS="$IFS" IFS=':' for module in $modules; do eval "add=\$module_$module" if [ $add = yes ]; then - echo $SEO "s%^.*\\(AddModule.*$module\\..*\\)%\\1%g" >>$sedsubst - echo $SEO "s%^.*\\(SharedModule.*$module\\..*\\)%\\1%g" >>$sedsubst + echo $SEO "s%^.*\\(AddModule.*[_b/]$module\\..*\\)%\\1%g" >>$sedsubst + echo $SEO "s%^.*\\(SharedModule.*[_b/]$module\\..*\\)%\\1%g" >>$sedsubst m="yes [static]" else - echo $SEO "s%^.*\\(AddModule.*$module\\..*\\)%# \\1%g" >>$sedsubst - echo $SEO "s%^.*\\(SharedModule.*$module\\..*\\)%# \\1%g" >>$sedsubst + echo $SEO "s%^.*\\(AddModule.*[_b/]$module\\..*\\)%# \\1%g" >>$sedsubst + echo $SEO "s%^.*\\(SharedModule.*[_b/]$module\\..*\\)%# \\1%g" >>$sedsubst m=no fi eval "share=\$shared_$module" if [ $share = yes ]; then - echo $SEO "s%^\\(.*\\)AddModule\\(.*$module\\.\\)[oa]\\(.*\\)%\\1SharedModule\\2so\\3%g" >>$sedsubst + echo $SEO "s%^\\(.*\\)AddModule\\(.*[_b/]$module\\.\\)[oam].*\\(.*\\)%\\1SharedModule\\2so\\3%g" >>$sedsubst m="yes [shared]" fi if [ $verbose = yes ]; then @@ -1056,11 +1284,12 @@ IFS="$OIFS" # and finally translate the config template # according to our defined configuration -eval "cat $src/Configuration.tmpl $addconf | $substcmd >$src/Configuration.apaci" +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 @@ -1075,3 +1304,19 @@ else -e "s:Makefile\$:Makefile in $src:") fi +## +## final hints +## +if [ .$quiet = .no ]; then + if [ ".$shadow" != . ]; 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/usr.sbin/httpd/htdocs/manual/LICENSE b/usr.sbin/httpd/htdocs/manual/LICENSE index ec09d302feb..6ac6538b3ca 100644 --- a/usr.sbin/httpd/htdocs/manual/LICENSE +++ b/usr.sbin/httpd/htdocs/manual/LICENSE @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1997 The Apache Group. All rights reserved. + * 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 @@ -20,9 +20,14 @@ * * 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. + * prior written permission. For written permission, please contact + * apache@apache.org. * - * 5. Redistributions of any form whatsoever must retain the following + * 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/)." diff --git a/usr.sbin/httpd/htdocs/manual/content-negotiation.html b/usr.sbin/httpd/htdocs/manual/content-negotiation.html index ad4eae9fa57..044e196f587 100644 --- a/usr.sbin/httpd/htdocs/manual/content-negotiation.html +++ b/usr.sbin/httpd/htdocs/manual/content-negotiation.html @@ -15,27 +15,29 @@ <DIV ALIGN="CENTER"> <IMG SRC="images/sub.gif" ALT="[APACHE DOCUMENTATION]"> <H3> - Apache HTTP Server Version 1.2 + Apache HTTP Server Version 1.3 </H3> </DIV> -<h1 ALIGN="CENTER">Content Negotiation</h1> +<H1 ALIGN="CENTER">Content Negotiation</H1> +<P> 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. <p> +browsers which send incomplete negotiation information. <P> -Content negotiation is provided by the -<a href="mod/mod_negotiation.html">mod_negotiation</a> module, +Content negotiation is provided by the +<A HREF="mod/mod_negotiation.html">mod_negotiation</A> module, which is compiled in by default. -<hr> +<HR> -<h2>About Content Negotiation</h2> +<H2>About Content Negotiation</H2> +<P> 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 @@ -48,13 +50,14 @@ 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 -<pre> +<PRE> Accept-Language: fr -</pre> +</PRE> +<P> Note that this preference will only be applied when there is a choice -of representations and they vary by language. -<p> +of representations and they vary by language. +<P> As an example of a more complex request, this browser has been configured to accept French and English, but prefer French, and to @@ -62,52 +65,54 @@ 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: -<pre> +<PRE> 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 -</pre> +</PRE> 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. -<p> +<P> -The terms used in content negotiation are: a <b>resource</b> is an +The terms used in content negotiation are: a <STRONG>resource</STRONG> is an item which can be requested of a server, which might be selected as the result of a content negotiation algorithm. If a resource is -available in several formats, these are called <b>representations</b> -or <b>variants</b>. The ways in which the variants for a particular -resource vary are called the <b>dimensions</b> of negotiation. +available in several formats, these are called <STRONG>representations</STRONG> +or <STRONG>variants</STRONG>. The ways in which the variants for a particular +resource vary are called the <STRONG>dimensions</STRONG> of negotiation. -<h2>Negotiation in Apache</h2> +<H2>Negotiation in Apache</H2> +<P> 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: +ways: -<ul> - <li> Using a type map (i.e., a <code>*.var</code> file) which +<UL> + <LI> Using a type map (<EM>i.e.</EM>, a <CODE>*.var</CODE> file) which names the files containing the variants explicitly - <li> Or using a 'MultiViews' search, where the server does an implicit + <LI> Or using a 'MultiViews' search, where the server does an implicit filename pattern match, and chooses from among the results. -</ul> +</UL> -<h3>Using a type-map file</h3> +<H3>Using a type-map file</H3> +<P> A type map is a document which is associated with the handler -named <code>type-map</code> (or, for backwards-compatibility with +named <CODE>type-map</CODE> (or, for backwards-compatibility with older Apache configurations, the mime type -<code>application/x-type-map</code>). Note that to use this feature, -you've got to have a <code>SetHandler</code> some place which defines a -file suffix as <code>type-map</code>; this is best done with a -<pre> +<CODE>application/x-type-map</CODE>). Note that to use this feature, +you've got to have a <CODE>SetHandler</CODE> some place which defines a +file suffix as <CODE>type-map</CODE>; this is best done with a +<PRE> AddHandler type-map var -</pre> -in <code>srm.conf</code>. See comments in the sample config files for -details. <p> +</PRE> +in <CODE>srm.conf</CODE>. See comments in the sample config files for +details. <P> Type map files have an entry for each available variant; these entries consist of contiguous RFC822-format header lines. Entries for @@ -116,7 +121,7 @@ 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: -<pre> +<PRE> URI: foo @@ -127,12 +132,12 @@ map file is: URI: foo.fr.de.html Content-type: text/html; charset=iso-8859-2 Content-language: fr, de -</pre> +</PRE> 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): -<pre> +<PRE> URI: foo URI: foo.jpeg @@ -144,82 +149,83 @@ as jpeg, gif, or ASCII-art): URI: foo.txt Content-type: text/plain; qs=0.01 -</pre> -<p> +</PRE> +<P> qs values can vary between 0.000 and 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. <p> +parameter value are given a qs factor of 1.0. <P> The full list of headers recognized is: -<dl> - <dt> <code>URI:</code> - <dd> uri of the file containing the variant (of the given media +<DL> + <DT> <CODE>URI:</CODE> + <DD> 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. - <dt> <code>Content-type:</code> - <dd> media type --- charset, level and "qs" parameters may be given. These + directly. + <DT> <CODE>Content-type:</CODE> + <DD> media type --- charset, level and "qs" parameters may be given. These are often referred to as MIME types; typical media types are - <code>image/gif</code>, <code>text/plain</code>, or - <code>text/html; level=3</code>. - <dt> <code>Content-language:</code> - <dd> The languages of the variant, specified as an Internet standard - language code (e.g., <code>en</code> for English, - <code>kr</code> for Korean, etc.). - <dt> <code>Content-encoding:</code> - <dd> If the file is compressed, or otherwise encoded, rather than + <CODE>image/gif</CODE>, <CODE>text/plain</CODE>, or + <CODE>text/html; level=3</CODE>. + <DT> <CODE>Content-language:</CODE> + <DD> The languages of the variant, specified as an Internet standard + language code (<EM>e.g.</EM>, <CODE>en</CODE> for English, + <CODE>kr</CODE> for Korean, <EM>etc.</EM>). + <DT> <CODE>Content-encoding:</CODE> + <DD> If the file is compressed, or otherwise encoded, rather than containing the actual raw data, this says how that was done. For compressed files (the only case where this generally comes up), content encoding should be - <code>x-compress</code>, or <code>x-gzip</code>, as appropriate. - <dt> <code>Content-length:</code> - <dd> The size of the file. Clients can ask to receive a given media + <CODE>x-compress</CODE>, or <CODE>x-gzip</CODE>, as appropriate. + <DT> <CODE>Content-length:</CODE> + <DD> The size of the file. Clients can ask to receive a given media type only if the variant isn't too big; specifying a content length in the map allows the server to compare against these thresholds without checking the actual file. -</dl> +</DL> -<h3>Multiviews</h3> +<H3>Multiviews</H3> +<P> This is a per-directory option, meaning it can be set with an -<code>Options</code> directive within a <code><Directory></code>, -<code><Location></code> or <code><Files></code> -section in <code>access.conf</code>, or (if <code>AllowOverride</code> -is properly set) in <code>.htaccess</code> files. Note that -<code>Options All</code> does not set <code>MultiViews</code>; you +<CODE>Options</CODE> directive within a <CODE><Directory></CODE>, +<CODE><Location></CODE> or <CODE><Files></CODE> +section in <CODE>access.conf</CODE>, or (if <CODE>AllowOverride</CODE> +is properly set) in <CODE>.htaccess</CODE> files. Note that +<CODE>Options All</CODE> does not set <CODE>MultiViews</CODE>; you have to ask for it by name. (Fixing this is a one-line change to -<code>http_core.h</code>). +<CODE>http_core.h</CODE>). -<p> +<P> -The effect of <code>MultiViews</code> is as follows: if the server -receives a request for <code>/some/dir/foo</code>, if -<code>/some/dir</code> has <code>MultiViews</code> enabled, and -<code>/some/dir/foo</code> does <em>not</em> exist, then the server reads the +The effect of <CODE>MultiViews</CODE> is as follows: if the server +receives a request for <CODE>/some/dir/foo</CODE>, if +<CODE>/some/dir</CODE> has <CODE>MultiViews</CODE> enabled, and +<CODE>/some/dir/foo</CODE> does <EM>not</EM> 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, and forwards them along. -<p> +<P> This applies to searches for the file named by the -<code>DirectoryIndex</code> directive, if the server is trying to +<CODE>DirectoryIndex</CODE> directive, if the server is trying to index a directory; if the configuration files specify -<pre> +<PRE> DirectoryIndex index -</pre> then the server will arbitrate between <code>index.html</code> -and <code>index.html3</code> if both are present. If neither are -present, and <code>index.cgi</code> is there, the server will run it. +</PRE> then the server will arbitrate between <CODE>index.html</CODE> +and <CODE>index.html3</CODE> if both are present. If neither are +present, and <CODE>index.cgi</CODE> is there, the server will run it. -<p> +<P> 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 @@ -229,7 +235,7 @@ 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. -<h2>The Negotiation Algorithm</h2> +<H2>The Negotiation Algorithm</H2> 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 @@ -238,99 +244,105 @@ any. To do this it calculates a quality value for each variant in each of the dimensions of variance. 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 in detail the algorithm used for those interested. <p> +explains in detail the algorithm used for those interested. <P> In some circumstances, Apache can '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. -<h3>Dimensions of Negotiation</h3> +<H3>Dimensions of Negotiation</H3> -<table> -<tr><th>Dimension -<th>Notes -<tr><td>Media Type -<td>Browser indicates preferences on Accept: header. Each item +<TABLE> +<TR><TH>Dimension +<TH>Notes +<TR><TD>Media Type +<TD>Browser indicates preferences on Accept: header. Each item can have an associated quality factor. Variant description can also have a quality factor. -<tr><td>Language -<td>Browser indicates preferences on Accept-Language: header. Each +<TR><TD>Language +<TD>Browser indicates preferences on Accept-Language: header. Each item can have a quality factor. Variants can be associated with none, one or more languages. -<tr><td>Encoding -<td>Browser indicates preference with Accept-Encoding: header. -<tr><td>Charset -<td>Browser indicates preference with Accept-Charset: header. Variants +<TR><TD>Encoding +<TD>Browser indicates preference with Accept-Encoding: header. +<TR><TD>Charset +<TD>Browser indicates preference with Accept-Charset: header. Variants can indicate a charset as a parameter of the media type. -</table> +</TABLE> -<h3>Apache Negotiation Algorithm</h3> +<H3>Apache Negotiation Algorithm</H3> +<P> Apache uses an algorithm to select the 'best' variant (if any) to return to the browser. This algorithm is not configurable. It operates like this: -<p> -<ol> -<li> +<OL> +<LI> Firstly, for each dimension of the negotiation, the appropriate Accept header is checked and a quality assigned to this each variant. If the Accept header for any dimension means that this variant is not acceptable, eliminate it. If no variants remain, go to step 4. -<li>Select the 'best' variant by a process of elimination. Each of +<LI>Select the 'best' variant by a process of elimination. Each of the following tests is applied in order. Any variants not selected at each stage are eliminated. After each test, if only one variant remains, it is selected as the best match. If more than one variant remains, move onto the next test. -<ol> -<li>Multiply the quality factor from the Accept header with the +<OL> +<LI>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 -<li>Select the variants with the highest language quality factor +<LI>Select the variants with the highest language quality factor -<li>Select the variants with the best language match, using either the - order of languages on the <code>LanguagePriority</code> directive (if present), +<LI>Select the variants with the best language match, using either the + order of languages on the <CODE>LanguagePriority</CODE> directive (if + present), else the order of languages on the Accept-Language header. -<li>Select the variants with the highest 'level' media parameter - (used to give the version of text/html media types). +<LI>Select the variants with the highest 'level' media parameter + (used to give the version of text/html media types). -<li>Select only unencoded variants, if there is a mix of encoded - and non-encoded variants. If either all variants are encoded - or all variants are not encoded, select all. +<LI>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. -<li>Select only variants with acceptable charset media parameters, +<LI>Select only variants with acceptable charset media parameters, as given on the Accept-Charset header line. Charset ISO-8859-1 is always acceptable. Variants not associated with a particular charset are assumed to be in ISO-8859-1. -<li>Select the variants with the smallest content length +<LI>Select the variants with the smallest content length -<li>Select the first variant of those remaining (this will be either the +<LI>Select the first variant of those remaining (this will be either the first listed in the type-map file, or the first read from the directory) and go to stage 3. -</ol> +</OL> -<li>The algorithm has now selected one 'best' variant, so return +<LI>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. -<li>To get here means no variant was selected (because non are acceptable +<LI>To get here means no variant was selected (because non 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. -</ol> -<h2><a name="better">Fiddling with Quality Values</a></h2> +</OL> + +<H2><A NAME="better">Fiddling with Quality Values</A></H2> +<P> Apache sometimes changes the quality values from what would be expected by a strict interpretation of the algorithm above. This is to get a better result from the algorithm for browsers which do not send @@ -339,24 +351,25 @@ 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. -<p> +<P> -<h3>Media Types and Wildcards</h3> +<H3>Media Types and Wildcards</H3> +<P> 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: -<pre> +<PRE> Accept: image/*, */* -</pre> +</PRE> 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: -<pre> +<PRE> Accept: text/html, text/plain, image/gif, image/jpeg, */* -</pre> +</PRE> The intention of this is to indicate that the explicitly listed types are preferred, but if a different representation is @@ -365,72 +378,163 @@ 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: -<pre> +<PRE> Accept: text/html, text/plain, image/gif, image/jpeg, */*; q=0.01 -</pre> +</PRE> 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. -<p> +no variant matches an explicitly listed type. +<P> -If the Accept: header contains <i>no</i> q factors at all, Apache sets +If the Accept: header contains <EM>no</EM> 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 <i>not</i> applied, so requests from browsers +these special values are <EM>not</EM> applied, so requests from browsers which send the correct information to start with work as expected. -<h3>Variants with no Language</h3> +<H3>Variants with no Language</H3> +<P> 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.<p> +are given a very low language quality factor of 0.001.<P> 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. +other variants match the browser's language preferences. For example, consider the situation with three variants: -<ul> -<li>foo.en.html, language en -<li>foo.fr.html, language en -<li>foo.html, no language -</ul> +<UL> +<LI>foo.en.html, language en +<LI>foo.fr.html, language en +<LI>foo.html, no language +</UL> +<P> 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. -<h2>Note on Caching</h2> - +<H2>Note on hyperlinks and naming conventions</H2> + +<P> +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 <A HREF="mod/mod_mime.html">mod_mime</A> documentation for details). +<P> +A typical file has a MIME-type extension (<EM>e.g.</EM>, <SAMP>html</SAMP>), +maybe an encoding extension (<EM>e.g.</EM>, <SAMP>gz</SAMP>), and of course a +language extension (<EM>e.g.</EM>, <SAMP>en</SAMP>) when we have different +language variants of this file. + +<P> +Examples: +<UL> +<LI>foo.en.html +<LI>foo.html.en +<LI>foo.en.html.gz +</UL> + +<P> +Here some more examples of filenames together with valid and invalid +hyperlinks: +</P> + +<TABLE BORDER=1 CELLPADDING=8 CELLSPACING=0> +<TR> + <TH>Filename</TH> + <TH>Valid hyperlink</TH> + <TH>Invalid hyperlink</TH> +</TR> +<TR> + <TD><EM>foo.html.en</EM></TD> + <TD>foo<BR> + foo.html</TD> + <TD>-</TD> +</TR> +<TR> + <TD><EM>foo.en.html</EM></TD> + <TD>foo</TD> + <TD>foo.html</TD> +</TR> +<TR> + <TD><EM>foo.html.en.gz</EM></TD> + <TD>foo<BR> + foo.html</TD> + <TD>foo.gz<BR> + foo.html.gz</TD> +</TR> +<TR> + <TD><EM>foo.en.html.gz</EM></TD> + <TD>foo</TD> + <TD>foo.html<BR> + foo.html.gz<BR> + foo.gz</TD> +</TR> +<TR> + <TD><EM>foo.gz.html.en</EM></TD> + <TD>foo<BR> + foo.gz<BR> + foo.gz.html</TD> + <TD>foo.html</TD> +</TR> +<TR> + <TD><EM>foo.html.gz.en</EM></TD> + <TD>foo<BR> + foo.html<BR> + foo.html.gz</TD> + <TD>foo.gz</TD> +</TR> +</TABLE> + +<P> +Looking at the table above you will notice that it is always possible to +use the name without any extensions in an hyperlink (<EM>e.g.</EM>, <SAMP>foo</SAMP>). +The advantage is that you can hide the actual type of a +document rsp. file and can change it later, <EM>e.g.</EM>, from <SAMP>html</SAMP> +to <SAMP>shtml</SAMP> or <SAMP>cgi</SAMP> without changing any +hyperlink references. + +<P> +If you want to continue to use a MIME-type in your hyperlinks (<EM>e.g.</EM> +<SAMP>foo.html</SAMP>) the language extension (including an encoding extension +if there is one) must be on the right hand side of the MIME-type extension +(<EM>e.g.</EM>, <SAMP>foo.html.en</SAMP>). + + +<H2>Note on Caching</H2> + +<P> When a cache stores a document, it associates it with the request URL. The next time that URL is requested, the cache can use the stored document, provided it is still within date. But if the resource is subject to content negotiation at the server, this would result in only the first requested variant being cached, and subsequent cache -hits could return the wrong response. To prevent this, +hits could 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 +as non-cacheable by HTTP/1.0 clients. Apache also supports the HTTP/1.1 protocol features to allow caching of negotiated responses. <P> For requests which come from a HTTP/1.0 compliant client (either a -browser or a cache), the directive <tt>CacheNegotiatedDocs</tt> can be +browser or a cache), the directive <TT>CacheNegotiatedDocs</TT> 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. <HR> -<H3 ALIGN="CENTER"> - Apache HTTP Server Version 1.2 -</H3> + <H3 ALIGN="CENTER"> + Apache HTTP Server Version 1.3 + </H3> <A HREF="./"><IMG SRC="images/index.gif" ALT="Index"></A> diff --git a/usr.sbin/httpd/htdocs/manual/dso.html b/usr.sbin/httpd/htdocs/manual/dso.html index da6d0f13978..4c48262512b 100644 --- a/usr.sbin/httpd/htdocs/manual/dso.html +++ b/usr.sbin/httpd/htdocs/manual/dso.html @@ -183,6 +183,7 @@ platforms are supported. The definitive current state (May 1998) is this: o FreeBSD (2.1.5, 2.2.5, 2.2.6) o OpenBSD (2.x) o NetBSD (1.3.1) +o BSDI (4.0) o Linux (Debian/1.3.1, RedHat/4.2) o Solaris (2.4, 2.5.1, 2.6) o SunOS (4.1.3) diff --git a/usr.sbin/httpd/htdocs/manual/handler.html b/usr.sbin/httpd/htdocs/manual/handler.html index 43a0047228c..597ea8cd9e4 100644 --- a/usr.sbin/httpd/htdocs/manual/handler.html +++ b/usr.sbin/httpd/htdocs/manual/handler.html @@ -15,136 +15,190 @@ <DIV ALIGN="CENTER"> <IMG SRC="images/sub.gif" ALT="[APACHE DOCUMENTATION]"> <H3> - Apache HTTP Server Version 1.2 + Apache HTTP Server Version 1.3 </H3> </DIV> -<h1 ALIGN="CENTER">Apache's Handler Use</h1> +<H1 ALIGN="CENTER">Apache's Handler Use</H1> -<h2>What is a Handler</h2> +<H2>What is a Handler</H2> -<p>A "handler" is an internal Apache representation of the action to be +<P>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.</p> +"application/x-httpd-cgi" to invoke CGI scripts.</P> -<p>Apache 1.1 adds the additional ability to use handlers +<P>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 -<strong>and</strong> a handler to be associated with a file.</p> - -<p>Handlers can either be built into the server or to a module, or -they can be added with the <a -href="mod/mod_actions.html#action">Action</a> directive. The built-in -handlers in the standard distribution are as follows:</p> - -<ul> -<li><strong>send-as-is</strong>: +<STRONG>and</STRONG> a handler to be associated with a file (See also +<A HREF="mod/mod_mime#multipleext">Files with Multiple Extensions</A>) + +</P> + +<P>Handlers can either be built into the server or to a module, or +they can be added with the <A +HREF="mod/mod_actions.html#action">Action</A> directive. The built-in +handlers in the standard distribution are as follows:</P> + +<UL> +<LI><STRONG>default-handler</STRONG>: + Send the file using the <CODE>default_handler()</CODE>, which is the + handler used by default to handle static content. + (core) +<LI><STRONG>send-as-is</STRONG>: Send file with HTTP headers as is. - (<a href="mod/mod_asis.html">mod_asis</a>) -<li><strong>cgi-script</strong>: + (<A HREF="mod/mod_asis.html">mod_asis</A>) +<LI><STRONG>cgi-script</STRONG>: Treat the file as a CGI script. - (<a href="mod/mod_cgi.html">mod_cgi</a>) -<li><strong>imap-file</strong>: + (<A HREF="mod/mod_cgi.html">mod_cgi</A>) +<LI><STRONG>imap-file</STRONG>: Imagemap rule file. - (<a href="mod/mod_imap.html">mod_imap</a>) -<li><strong>server-info</strong>: + (<A HREF="mod/mod_imap.html">mod_imap</A>) +<LI><STRONG>server-info</STRONG>: Get the server's configuration information - (<a href="mod/mod_info.html">mod_info</a>) -<li><strong>server-parsed</strong>: + (<A HREF="mod/mod_info.html">mod_info</A>) +<LI><STRONG>server-parsed</STRONG>: Parse for server-side includes - (<a href="mod/mod_include.html">mod_include</a>) -<li><strong>server-status</strong>: + (<A HREF="mod/mod_include.html">mod_include</A>) +<LI><STRONG>server-status</STRONG>: Get the server's status report - (<a href="mod/mod_status.html">mod_status</a>) -<li><strong>type-map</strong>: + (<A HREF="mod/mod_status.html">mod_status</A>) +<LI><STRONG>type-map</STRONG>: Parse as a type map file for content negotiation - (<a href="mod/mod_negotiation.html">mod_negotiation</a>) -</ul> - -<p> + (<A HREF="mod/mod_negotiation.html">mod_negotiation</A>) +</UL> -<h2>Directives</h2> -<ul> -<li><A HREF="#addhandler">AddHandler</A> -<li><A HREF="#sethandler">SetHandler</A> -</ul> +<P> -<hr> +<H2>Directives</H2> +<UL> +<LI><A HREF="#addhandler">AddHandler</A> +<LI><A HREF="#sethandler">SetHandler</A> +</UL> -<h2><a name="addhandler">AddHandler</a></h2> - -<strong>Syntax:</strong> <AddHandler <em>handler-name extension</em>><br> -<strong>Context:</strong> server config, virtual host, directory, .htaccess<br> -<strong>Status:</strong> Base<br> -<strong>Module:</strong> mod_mime +<HR> -<p>AddHandler maps the filename extension <em>extension</em> to the -handler <em>handler-name</em>. For example, to activate CGI scripts -with the file extension "<code>.cgi</code>", you might use: -<pre> +<H2><A NAME="addhandler">AddHandler</A></H2> + +<A + HREF="mod/directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> AddHandler <EM>handler-name extension extension...</EM><BR> +<A + HREF="mod/directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config, virtual host, directory, .htaccess<BR> +<A + HREF="mod/directive-dict.html#Override" + REL="Help" +><STRONG>Override:</STRONG></A> FileInfo<BR> +<A + HREF="mod/directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Base<BR> +<A + HREF="mod/directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_mime<BR> +<A + HREF="mod/directive-dict.html#Compatibility" + REL="Help" +><STRONG>Compatibility:</STRONG></A> AddHandler is only available in Apache +1.1 and later<P> + +<P>AddHandler maps the filename extensions <EM>extension</EM> to the +handler <EM>handler-name</EM>. This mapping is added to any already +in force, overriding any mappings that already exist for the same +<EM>extension</EM>. + +For example, to activate CGI scripts +with the file extension "<CODE>.cgi</CODE>", you might use: +<PRE> AddHandler cgi-script cgi -</pre> +</PRE> -<p>Once that has been put into your srm.conf or httpd.conf file, any -file ending with "<code>.cgi</code>" will be treated as a CGI -program.</p> +<P>Once that has been put into your srm.conf or httpd.conf file, any +file containing the "<CODE>.cgi</CODE>" extension will be treated as a +CGI program.</P> -<hr> +<P> -<h2><a name="sethandler">SetHandler</a></h2> +<STRONG>See also</STRONG>: <A HREF="mod/mod_mime.html#multipleext">Files with +multiple extensions</A> -<strong>Syntax:</strong> <SetHandler <em>handler-name</em>><br> -<strong>Context:</strong> directory, .htaccess<br> -<strong>Status:</strong> Base<br> -<strong>Module:</strong> mod_mime +<HR> -<p>When placed into an <code>.htaccess</code> file or a -<code><Directory></code> or <code><Location></code> section, -this directive forces all matching files to be parsed through the -handler given by <em>handler-name</em>. For example, if you had a +<H2><A NAME="sethandler">SetHandler</A></H2> + +<A + HREF="mod/directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> SetHandler <EM>handler-name</EM><BR> +<A + HREF="mod/directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> directory, .htaccess<BR> +<A + HREF="mod/directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Base<BR> +<A + HREF="mod/directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_mime<BR> +<A + HREF="mod/directive-dict.html#Compatibility" + REL="Help" +><STRONG>Compatibility:</STRONG></A> SetHandler is only available in Apache +1.1 and later.<P> + +<P>When placed into an <CODE>.htaccess</CODE> file or a +<CODE><Directory></CODE> or <CODE><Location></CODE> +section, this directive forces all matching files to be parsed through +the handler given by <EM>handler-name</EM>. 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 -<code>.htaccess</code> file in that directory: -<pre> +<CODE>.htaccess</CODE> file in that directory: +<PRE> SetHandler imap-file -</pre> -<p>Another example: if you wanted to have the server display a status -report whenever a URL of <code>http://servername/status</code> was +</PRE> + +<P>Another example: if you wanted to have the server display a status +report whenever a URL of <CODE>http://servername/status</CODE> was called, you might put the following into access.conf: -<pre> +<PRE> <Location /status> SetHandler server-status </Location> -</pre> - -<p><hr> +</PRE> +<HR> -<h2>Programmer's Note</h2> +<H2>Programmer's Note</H2> -<p>In order to implement the handler features, an addition has been -made to the <a href="misc/API.html">Apache API</a> that you may wish to +<P>In order to implement the handler features, an addition has been +made to the <A HREF="misc/API.html">Apache API</A> that you may wish to make use of. Specifically, a new record has been added to the -<code>request_rec</code> structure:</p> -<pre> +<CODE>request_rec</CODE> structure:</P> +<PRE> char *handler -</pre> -<p>If you wish to have your module engage a handler, you need only to -set <code>r->handler</code> to the name of the handler at any time -prior to the <code>invoke_handler</code> stage of the +</PRE> +<P>If you wish to have your module engage a handler, you need only to +set <CODE>r->handler</CODE> to the name of the handler at any time +prior to the <CODE>invoke_handler</CODE> 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.</p> +type name-space.</P> <HR> -<H3 ALIGN="CENTER"> - Apache HTTP Server Version 1.2 -</H3> + <H3 ALIGN="CENTER"> + Apache HTTP Server Version 1.3 + </H3> <A HREF="./"><IMG SRC="images/index.gif" ALT="Index"></A> diff --git a/usr.sbin/httpd/htdocs/manual/index.html b/usr.sbin/httpd/htdocs/manual/index.html index dc967b83335..ff46a78f9a0 100644 --- a/usr.sbin/httpd/htdocs/manual/index.html +++ b/usr.sbin/httpd/htdocs/manual/index.html @@ -1,7 +1,7 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <HTML> <HEAD> -<TITLE>Apache documentation</TITLE> +<TITLE>Apache 1.3 documentation</TITLE> </HEAD> <!-- Background white, links blue (unvisited), navy (visited), red (active) --> @@ -15,62 +15,58 @@ <DIV ALIGN="CENTER"> <IMG SRC="images/sub.gif" ALT="[APACHE DOCUMENTATION]"> <H3> - Apache HTTP Server Version 1.2 + Apache HTTP Server Version 1.3 </H3> </DIV> -<h1 ALIGN="CENTER">Apache User's Guide</h1> +<H1 ALIGN="CENTER">Apache 1.3 User's Guide</H1> -<hr> - -<h3><a name="new">Release Notes</a></h3> -<ul> -<li><a href="new_features_1_2.html">New features in Apache 1.2</a> -<li><a href="new_features_1_1.html">New features in Apache 1.1</a> -<li><a href="new_features_1_0.html">New features in Apache 1.0</a> -</ul> -<ul> -<li><a href="misc/known_bugs.html">Known Bugs</a> -<li><a href="misc/compat_notes.html">Compatibility Notes with NCSA httpd</a> -<li><a href="LICENSE">Apache License</A> -</ul> +<HR> -<H3><a name="ref">Apache Reference Manual</a></h3> +<H3><A NAME="new">Release Notes</A></H3> <UL> - <LI><A - HREF="http://www.apache.org/manual-index/docs" - ><STRONG>Search</STRONG></A> - the master manual pages for key words - </LI> +<LI><A HREF="new_features_1_3.html">New features in Apache 1.3</A> +<LI><A HREF="upgrading_to_1_3.html">Upgrading to Apache 1.3</A> +<LI><A HREF="LICENSE">Apache License</A> </UL> -<ul> -<li><A HREF="install.html">Compiling and Installing Apache</A> -<li><A HREF="invoking.html">Starting Apache</A> -<li><A HREF="stopping.html">Stopping or Restarting Apache</A> -<li><A HREF="mod/directives.html">Apache run-time configuration directives</A> -<li><A HREF="mod/">Apache modules</A> -<li><A HREF="handler.html">Apache's handler use</A> -<li><A HREF="env.html">Special purpose environment variables</A> -<LI><A HREF="misc/API.html">Highly generalized API to server functionality</A> + +<H3><A NAME="ref">Apache Reference Manual</A></H3> + +<UL> +<LI><A HREF="http://www.apache.org/manual-index.cgi/docs"> + <STRONG>Search</STRONG></A> for key words +<LI><A HREF="install.html">Compiling and Installing</A> +<LI><A HREF="invoking.html">Starting</A> +<LI><A HREF="stopping.html">Stopping or Restarting</A> +<LI><A HREF="mod/directives.html">Run-time configuration directives</A> +<LI><A HREF="mod/index.html">Modules</A> +<LI><A HREF="vhosts/index.html">Virtual Hosts</A> +<LI><A HREF="dso.html">Dynamic Shared Object (DSO) support</A> +<LI><A HREF="handler.html">Handlers</A> +<LI><A HREF="env.html">Special purpose environment variables</A> +<LI><A HREF="misc/API.html">The Apache API</A> <LI><A HREF="suexec.html">Using SetUserID Execution for CGI</A> -</ul> +</UL> -<h3><a name="oth">Other Notes</a></h3> -<ul> -<li><A HREF="misc/FAQ.html">Frequently Asked Questions list</a> -<li><A href="misc/howto.html">How do I? documentation</A> +<H3><A NAME="oth">Other Notes</A></H3> +<UL> +<LI><A HREF="misc/FAQ.html">Frequently Asked Questions</A> +<LI><A HREF="misc/perf-tuning.html">General Performance hints</A> for +getting the best performance out of Apache +<LI><A HREF="misc/perf.html">OS Specific Performance hints</A> to help +fine-tune specific platforms <LI><A HREF="misc/security_tips.html">Security tips</A> -<LI><A HREF="misc/perf.html">Performance hints</a> for heavily loaded web servers. +<LI><A HREF="misc/compat_notes.html">Compatibility Notes with NCSA httpd</A> +<LI><A HREF="misc/howto.html">How do I? documentation</A> <LI><A HREF="misc/fin_wait_2.html">Discussion of the FIN_WAIT_2 problem</A> -<LI><A - HREF="http://www.apache.org/info/jdk-102.html" - >Java's 1.0.2 virtual machine and HTTP/1.1</A> -</ul> +<LI><A HREF="misc/known_client_problems.html">Known problems with various + clients</A> +</UL> <HR> -<H3 ALIGN="CENTER"> - Apache HTTP Server Version 1.2 -</H3> + <H3 ALIGN="CENTER"> + Apache HTTP Server Version 1.3 + </H3> <A HREF="./"><IMG SRC="images/index.gif" ALT="Index"></A> diff --git a/usr.sbin/httpd/htdocs/manual/install.html b/usr.sbin/httpd/htdocs/manual/install.html index 0bdc45c87df..73ab0d9a73f 100644 --- a/usr.sbin/httpd/htdocs/manual/install.html +++ b/usr.sbin/httpd/htdocs/manual/install.html @@ -15,15 +15,20 @@ <DIV ALIGN="CENTER"> <IMG SRC="images/sub.gif" ALT="[APACHE DOCUMENTATION]"> <H3> - Apache HTTP Server Version 1.2 + Apache HTTP Server Version 1.3 </H3> </DIV> -<H1 ALIGN="CENTER">Compiling and Installing Apache 1.2</H1> +<H1 ALIGN="CENTER">Compiling and Installing Apache 1.3</H1> -<P>If you wish to download and install an earlier version of Apache please -read <A HREF="install_1_1.html">Compiling and Installing Apache 1.1</A>.</P> +This document covers compilation and installation of Apache on Unix +systems only. For compiling and installation on Windows, see <A +HREF="windows.html">Using Apache with Microsoft Windows</A> and for +TPF see <A HREF="install-tpf.html">Installing the Apache 1.3 HTTP +Server on TPF</A>. + +<P> UnixWare users will want to consult <A HREF="unixware.html">build notes</A> for various UnixWare versions before compiling. @@ -34,7 +39,7 @@ Information on the latest version of Apache can be found on the Apache web server at <A HREF="http://www.apache.org/">http://www.apache.org/</A>. This will list the current release, any more recent beta-test release, together -with details of mirror web and anonymous ftp sites. +with details of mirror web and anonymous ftp sites. <P> @@ -42,10 +47,10 @@ If you downloaded a binary distribution, skip to <A HREF="#install">Installing Apache</A>. Otherwise read the next section for how to compile the server. -<h2>Compiling Apache</h2> +<H2>Compiling Apache</H2> Compiling Apache consists of three steps: Firstly select which Apache -<b>modules</b> you want to include into the server. Secondly create a +<STRONG>modules</STRONG> you want to include into the server. Secondly create a configuration for your operating system. Thirdly compile the executable. <P> @@ -57,7 +62,7 @@ directory of the Apache distribution. Change into this directory. <LI> Select modules to compile into Apache in the <CODE>Configuration</CODE> file. Uncomment lines corresponding to - those optional modules you wish to include (among the Module lines + 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 <A HREF="misc/API.html">API.html</A> for preliminary docs on how to @@ -74,11 +79,11 @@ directory of the Apache distribution. Change into this directory. <LI> Configure Apache for your operating system. Normally you can just type run the <CODE>Configure</CODE> script as given below. However - if this fails or you have any special requirements (e.g. to include + if this fails or you have any special requirements (<EM>e.g.</EM>, to include an additional library required by an optional module) you might need to edit one or more of the following options in the <CODE>Configuration</CODE> file: - <CODE>EXTRA_CFLAGS, LIBS, LFLAGS, INCLUDES</CODE>. + <CODE>EXTRA_CFLAGS, LIBS, LDFLAGS, INCLUDES</CODE>. <P> Run the <CODE>Configure</CODE> script: @@ -89,7 +94,12 @@ directory of the Apache distribution. Change into this directory. + 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 </PRE> </BLOCKQUOTE> @@ -114,12 +124,13 @@ directory of the Apache distribution. Change into this directory. 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 <A -HREF="http://www.apache.org/dist/contrib/modules/"><URL:http://www.apache.org/dist/contrib/modules/></a>. +parties with specific needs or functions are available at +<<A HREF="http://www.apache.org/dist/contrib/modules/" + >http://www.apache.org/dist/contrib/modules/</A>>. There are instructions on that page for linking these modules into the core Apache code. -<h2><A NAME="install">Installing Apache</A></h2> +<H2><A NAME="install">Installing Apache</A></H2> You will have a binary file called <CODE>httpd</CODE> in the <CODE>src</CODE> directory. A binary distribution of Apache will @@ -129,10 +140,12 @@ 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 <CODE>conf</CODE>, <CODE>logs</CODE> and -<CODE>icons</CODE> directories into it. <P> +<CODE>icons</CODE> directories into it. In either case you should +read the <A HREF="misc/security_tips.html#serverroot">security tips</A> +describing how to set the permissions on the server root directory.<P> The next step is to edit the configuration files for the server. This -consists of setting up various <B>directives</B> in up to three +consists of setting up various <STRONG>directives</STRONG> in up to three central configuration files. By default, these files are located in the <CODE>conf</CODE> directory and are called <CODE>srm.conf</CODE>, <CODE>access.conf</CODE> and <CODE>httpd.conf</CODE>. To help you get @@ -149,34 +162,42 @@ file usually does not need editing. <P> First edit <CODE>httpd.conf</CODE>. This sets up general attributes -about the server: the port number, the user it runs as, etc. Next +about the server: the port number, the user it runs as, <EM>etc.</EM> Next edit the <CODE>srm.conf</CODE> file; this sets up the root of the document tree, special functions like server-parsed HTML or internal -imagemap parsing, etc. Finally, edit the <CODE>access.conf</CODE> +imagemap parsing, <EM>etc.</EM> Finally, edit the <CODE>access.conf</CODE> file to at least set the base cases of access. <P> In addition to these three files, the server behavior can be configured on a directory-by-directory basis by using <CODE>.htaccess</CODE> -files in directories accessed by the server. +files in directories accessed by the server. + +<H3>Set your system time properly!</H3> + +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. <H3>Starting and Stopping the Server</H3> To start the server, simply run <CODE>httpd</CODE>. This will look for <CODE>httpd.conf</CODE> in the location compiled into the code (by -default <CODE>/usr/locale/etc/httpd/conf/httpd.conf</CODE>). If +default <CODE>/usr/local/apache/conf/httpd.conf</CODE>). If this file is somewhere else, you can give the real location with the -f argument. For example: <PRE> - /usr/local/etc/apache/src/httpd -f /usr/local/etc/apache/conf/httpd.conf + /usr/local/apache/httpd -f /usr/local/apache/conf/httpd.conf </PRE> 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. +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 @@ -190,10 +211,10 @@ port of 80, a suitable URL to enter into your browser is <P> Note that when the server starts it will create a number of -<i>child</i> processes to handle the requests. If you started Apache +<EM>child</EM> 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. +file. <P> @@ -216,7 +237,7 @@ this will be located in the file <CODE>error_log</CODE> in the If you want your server to continue running after a system reboot, you should add a call to <CODE>httpd</CODE> to your system startup files (typically <CODE>rc.local</CODE> or a file in an -<CODE>rc.<I>N</I></CODE> directory). This will start Apache as root. +<CODE>rc.<EM>N</EM></CODE> directory). This will start Apache as root. Before doing this ensure that your server is properly configured for security and access restrictions. @@ -229,7 +250,7 @@ attempt to kill the child processes because they will be renewed by the parent. A typical command to stop the server is: <PRE> - kill -TERM `cat /usr/local/etc/apache/logs/httpd.pid` + kill -TERM `cat /usr/local/apache/logs/httpd.pid` </PRE> <P> @@ -251,9 +272,9 @@ the support programs, change into this directory and type </PRE> <HR> -<H3 ALIGN="CENTER"> - Apache HTTP Server Version 1.2 -</H3> + <H3 ALIGN="CENTER"> + Apache HTTP Server Version 1.3 + </H3> <A HREF="./"><IMG SRC="images/index.gif" ALT="Index"></A> diff --git a/usr.sbin/httpd/htdocs/manual/invoking.html b/usr.sbin/httpd/htdocs/manual/invoking.html index b960916cfee..22f3dc07bad 100644 --- a/usr.sbin/httpd/htdocs/manual/invoking.html +++ b/usr.sbin/httpd/htdocs/manual/invoking.html @@ -15,120 +15,205 @@ <DIV ALIGN="CENTER"> <IMG SRC="images/sub.gif" ALT="[APACHE DOCUMENTATION]"> <H3> - Apache HTTP Server Version 1.2 + Apache HTTP Server Version 1.3 </H3> </DIV> -<h1 ALIGN="CENTER">Starting Apache</h1> +<H1 ALIGN="CENTER">Starting Apache</H1> -<h2>Invoking Apache</h2> -The <code>httpd</code> program is usually run as a daemon which executes -continuously, handling requests. It is possible to invoke Apache by -the Internet daemon <code>inetd</code> each time a connection to the HTTP -service is made (use the -<A HREF="mod/core.html#servertype">ServerType</A> directive) -but this is not recommended. +<H2>Invoking Apache</H2> -<h2>Command line options</h2> +On Unix, the <CODE>httpd</CODE> program is usually run as a daemon +which executes continuously, handling requests. It is possible to +invoke Apache by the Internet daemon <CODE>inetd</CODE> each time a +connection to the HTTP service is made (use the <A +HREF="mod/core.html#servertype">ServerType</A> directive) but this is +not recommended. + +<P> + +On Windows, Apache is normally run as a service on Windows NT, or as a +console application on Windows 95. See also <A +HREF="windows.html#run">running Apache for Windows</A>. + +<H2>Command line options</H2> The following options are recognized on the httpd command line: -<dl> -<dt><code>-d</code> <em>serverroot</em> -<dd>Set the initial value for the +<DL> +<DT><CODE>-d</CODE> <EM>serverroot</EM> +<DD>Set the initial value for the <A HREF="mod/core.html#serverroot">ServerRoot</A> variable to -<em>serverroot</em>. This can be overridden by the ServerRoot command in the -configuration file. The default is <code>/usr/local/etc/httpd</code>. - -<dt><code>-f</code> <em>config</em> -<dd>Execute the commands in the file <em>config</em> on startup. If -<em>config</em> does not begin with a <code>/</code>, then it is taken to be a +<EM>serverroot</EM>. This can be overridden by the ServerRoot command +in the configuration file. The default is +<CODE>/usr/local/apache</CODE> on Unix, <CODE>/apache</CODE> on +Windows and <CODE>/os2httpd</CODE> on OS/2. + +<DT><CODE>-D</CODE> <EM>name</EM> +<DD>Define a name for use in in +<A HREF="mod/core.html#ifdefine">IfDefine</A> 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. + +<DT><CODE>-f</CODE> <EM>config</EM> +<DD>Execute the commands in the file <EM>config</EM> on startup. If +<EM>config</EM> does not begin with a <CODE>/</CODE>, then it is taken to be a path relative to the <A HREF="mod/core.html#serverroot">ServerRoot</A>. The -default is <code>conf/httpd.conf</code>. +default is <CODE>conf/httpd.conf</CODE>. + +<DT><CODE>-C</CODE> <EM>"directive"</EM> +<DD>Process the given apache "directive" (just as if it had been part of a +configuration file) <STRONG>before</STRONG> actually reading the regular configuration files. + +<DT><CODE>-c</CODE> <EM>"directive"</EM> +<DD>Process the given apache "directive" <STRONG>after</STRONG> reading +all the regular configuration files. -<dt><code>-X</code> -<dd>Run in single-process mode, for internal debugging purposes only; the -daemon does not detach from the terminal or fork any children. Do <em>NOT</em> +<DT><CODE>-X</CODE> +<DD>Run in single-process mode, for internal debugging purposes only; the +daemon does not detach from the terminal or fork any children. Do <EM>NOT</EM> use this mode to provide ordinary web service. -<dt><code>-v</code> -<dd>Print the version of httpd, and then exit. +<DT><CODE>-v</CODE> +<DD>Print the version of httpd and its build date, and then exit. + +<DT><A NAME="version"><CODE>-V</CODE></A> +<DD>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 (<EM>e.g.</EM>, +<SAMP>-DUSE_MMAP_FILES</SAMP>), +then exit. + +<DT><A NAME="help"><CODE>-L</CODE></A> +<DD> + +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). + + +<DT><CODE>-l</CODE></A> +<DD> + +Give a list of all modules compiled into the server, then exit. +(Apache 1.3.4 and later. Earlier versions used -h instead).<br> -<dt><a name="help"><code>-h</code></a> -<dd>Give a list of directives together with expected arguments and -places where the directive is valid. (New in Apache 1.2) +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). -<dt><code>-l</code> -<dd>Give a list of all modules compiled into the server. -<dt><code>-?</code> -<dd>Print a list of the httpd options, and then exit. -</dl> -<h2>Configuration files</h2> -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 -<A HREF="mod/core.html#serverroot">ServerRoot</A> directive, or the -<code>-d</code> command line flag. +<DT><CODE>-h</CODE> +<DD> + +Print a list of the httpd options, then exit. (Apache 1.3.4 and +later. Earlier versions used -? instead).<br> + +Give a list of all modules compiled into the server, then exit. (Up to +Apache 1.3.3. Later versions use -l instead).<br> + + +<DT><CODE>-S</CODE> +<DD>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). + +<DT><CODE>-t</CODE> +<DD>Test the configuration file syntax (<EM>i.e.</EM>, 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. + +<DT><CODE>-k</CODE> <EM>option</EM> +<DD>Windows only: signal Apache to restart or shutdown. <EM>option</EM> +is one of "shutdown" or "restart". (Apache 1.3.3 and later). + +<DT><CODE>-?</CODE> +<DD>Print a list of the httpd options, and then exit (up to Apache +1.3.3. Later version use -h instead). + +</DL> + +<H2>Configuration files</H2> +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 +<A HREF="mod/core.html#serverroot">ServerRoot</A> directive, the +<CODE>-d</CODE> command line flag, or (on Windows only) the registry +(see <A HREF="windows.html#run">Running Apache for Windows</A>). Conventionally, the files are: -<dl> -<dt><code>conf/httpd.conf</code> -<dd>Contains directives that control the operation of the server daemon. -The filename may be overridden with the <code>-f</code> command line flag. +<DL> +<DT><CODE>conf/httpd.conf</CODE> +<DD>Contains directives that control the operation of the server daemon. +The filename may be overridden with the <CODE>-f</CODE> command line flag. -<dt><code>conf/srm.conf</code> -<dd>Contains directives that control the specification of documents that +<DT><CODE>conf/srm.conf</CODE> +<DD>Contains directives that control the specification of documents that the server can provide to clients. The filename may be overridden with the <A HREF="mod/core.html#resourceconfig">ResourceConfig</A> directive. -<dt><code>conf/access.conf</code> -<dd>Contains directives that control access to documents. +<DT><CODE>conf/access.conf</CODE> +<DD>Contains directives that control access to documents. The filename may be overridden with the <A HREF="mod/core.html#accessconfig">AccessConfig</A> directive. -</dl> +</DL> However, these conventions need not be adhered to. -<p> +<P> The server also reads a file containing mime document types; the filename -is set by the <A HREF="mod/mod_mime.html#typesconfig">TypesConfig</A> directive, -and is <code>conf/mime.types</code> by default. +is set by the <A HREF="mod/mod_mime.html#typesconfig">TypesConfig</A> +directive, +and is <CODE>conf/mime.types</CODE> by default. -<h2>Log files</h2> -<h3>security warning</h3> +<H2>Log files</H2> +<H3>security warning</H3> 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 <EM>NOT</EM> give people write access to the directory the logs are stored in without being aware of the consequences; see the <A HREF="misc/security_tips.html">security tips</A> document for details. -<h3>pid file</h3> -On daemon startup, it saves the process id of the parent httpd process to -the file <code>logs/httpd.pid</code>. This filename can be changed with the -<A HREF="mod/core.html#pidfile">PidFile</A> directive. The process-id is for -use by the administrator in restarting and terminating the daemon; -A HUP or USR1 signal causes the daemon to re-read its configuration files and -a TERM signal causes it to die gracefully. For more information -see the <a href="stopping.html">Stopping and Restarting</a> page. -<p> +<H3>pid file</H3> + +On startup, Apache saves the process id of the parent httpd process to +the file <CODE>logs/httpd.pid</CODE>. This filename can be changed +with the <A HREF="mod/core.html#pidfile">PidFile</A> 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 <A HREF="stopping.html">Stopping and +Restarting</A> page. + +<P> If the process dies (or is killed) abnormally, then it will be necessary to kill the children httpd processes. -<h3>Error log</h3> -The server will log error messages to a log file, <code>logs/error_log</code> -by default. The filename can be set using the -<A HREF="mod/core.html#errorlog">ErrorLog</A> directive; different error logs can -be set for different <A HREF="mod/core.html#virtualhost">virtual hosts</A>. +<H3>Error log</H3> -<h3>Transfer log</h3> -The server will typically log each request to a transfer file, -<code>logs/access_log</code> by default. The filename can be set using a -<A HREF="mod/mod_log_common.html#transferlog">TransferLog</A> directive; different -transfer logs can be set for different <A HREF="mod/core.html#virtualhost">virtual -hosts</A>. +The server will log error messages to a log file, by default +<CODE>logs/error_log</CODE> on Unix or <CODE>logs/error.log</CODE> on +OS/2. The filename can be set using the <A +HREF="mod/core.html#errorlog">ErrorLog</A> directive; different error +logs can be set for different <A +HREF="mod/core.html#virtualhost">virtual hosts</A>. + +<H3>Transfer log</H3> + +The server will typically log each request to a transfer file, by +default <CODE>logs/access_log</CODE> on Unix or +<CODE>logs/access.log</CODE> on OS/2. The filename can be set using a +<A HREF="mod/mod_log_config.html#transferlog">TransferLog</A> +directive or additional log files created with the <A +HREF="mod/mod_log_config.html#customlog">CustomLog</A> directive; +different transfer logs can be set for different <A +HREF="mod/core.html#virtualhost">virtual hosts</A>. <HR> -<H3 ALIGN="CENTER"> - Apache HTTP Server Version 1.2 -</H3> + <H3 ALIGN="CENTER"> + Apache HTTP Server Version 1.3 + </H3> <A HREF="./"><IMG SRC="images/index.gif" ALT="Index"></A> diff --git a/usr.sbin/httpd/htdocs/manual/misc/FAQ.html b/usr.sbin/httpd/htdocs/manual/misc/FAQ.html index 767a5759eb0..d7d335f7810 100644 --- a/usr.sbin/httpd/htdocs/manual/misc/FAQ.html +++ b/usr.sbin/httpd/htdocs/manual/misc/FAQ.html @@ -20,7 +20,7 @@ <H1 ALIGN="CENTER">Apache Server Frequently Asked Questions</H1> <P> - $Revision: 1.2 $ ($Date: 1998/10/11 19:45:05 $) + $Revision: 1.3 $ ($Date: 1999/03/01 01:05:09 $) </P> <P> The latest version of this FAQ is always available from the main @@ -85,6 +85,8 @@ <!-- (A: you can't but "satisfy any; allow from all" can be close --> <!-- - '400 malformed request' on Win32 might mean stale proxy; see --> <!-- PR #2300. --> +<!-- - "expected </Directory> saw </Directory" due to buggy AIX --> +<!-- compiler. --> <UL> <LI><STRONG>Background</STRONG> <OL START=1> @@ -194,9 +196,6 @@ </LI> <LI><A HREF="#SSL-i">Why doesn't Apache include SSL?</A> </LI> - <LI><A HREF="#HPUX-core">Why do I get core dumps under HPUX using - HP's ANSI C compiler?</A> - </LI> <LI><A HREF="#midi">How do I get Apache to send a MIDI file so the browser can play it?</A> </LI> @@ -732,6 +731,12 @@ whatever language you <EM>are</EM> using (<EM>e.g.</EM>, for C, call <CODE>fflush()</CODE> after writing the headers). </P> + <P> + 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. + </P> <HR> </LI> @@ -1242,7 +1247,7 @@ 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 - <A HREF="http://www.fastcgi.com/servers/apache/" + <A HREF="http://www.fastcgi.com/" >FastCGI web site</A>. When a new version of Apache was released, the version of the FastCGI module included with it would soon be out of date. </P> @@ -1436,18 +1441,6 @@ <HR> </LI> - <LI><A NAME="HPUX-core"> - <STRONG>Why do I get core dumps under HPUX using HP's ANSI - C compiler?</STRONG> - </A> - <P> - We have had numerous reports of Apache dumping core when compiled - with HP's ANSI C compiler using optimization. Disabling the compiler - optimization has fixed these problems. - </P> - <HR> - </LI> - <LI><A NAME="midi"> <STRONG>How do I get Apache to send a MIDI file so the browser can play it?</STRONG> @@ -1717,7 +1710,7 @@ <BR> AuthUserFile /usr/local/apache/conf/htpasswd.users <BR> - AuthName special directory + AuthName "special directory" <BR> require valid-user <BR> diff --git a/usr.sbin/httpd/htdocs/manual/misc/compat_notes.html b/usr.sbin/httpd/htdocs/manual/misc/compat_notes.html index b6594d354e6..3a6a1c40f8d 100644 --- a/usr.sbin/httpd/htdocs/manual/misc/compat_notes.html +++ b/usr.sbin/httpd/htdocs/manual/misc/compat_notes.html @@ -1,6 +1,8 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> -<HTML><HEAD> -<TITLE>Apache HTTP Server: Compatibility Notes with NCSA's Server</TITLE> +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" + "http://www.w3.org/TR/REC-html40/loose.dtd"> +<HTML> +<HEAD> +<TITLE>Apache HTTP Server: Notes about Compatibility with NCSA's Server</TITLE> </HEAD> <!-- Background white, links blue (unvisited), navy (visited), red (active) --> <BODY @@ -13,7 +15,7 @@ <DIV ALIGN="CENTER"> <IMG SRC="../images/sub.gif" ALT="[APACHE DOCUMENTATION]"> <H3> - Apache HTTP Server Version 1.2 + Apache HTTP Server Version 1.3 </H3> </DIV> @@ -21,125 +23,114 @@ <HR> -While Apache 0.8.x and beyond are for the most part a drop-in -replacement for NCSA's httpd and earlier versions of Apache, 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, <a -href="http://www.apache.org/bugdb.cgi">let us know.</a> - -<P>Please also check the <A HREF="known_bugs.html">known bugs</A> page. - +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, <A +HREF="http://www.apache.org/bug_report.html">let us know.</A> +<P>Please also check the <A HREF="known_client_problems.html">known +client problems</A> page. <OL> +<LI>As of Apache 1.3.1, methods named in a + <A HREF="../mod/core.html#limit"><SAMP><Limit></SAMP></A> + section <EM>must</EM> be listed in upper-case. Lower- or mixed-case + method names will result in a configuration error. + <P> + </P> +</LI> <LI>The basic mod_auth <CODE>AuthGroupFile</CODE>-specified group file - format allows commas between user names - Apache does not.<BR> - <I>- added 12/1/96</I> - <p> - - <LI><P>If you follow the NCSA guidelines for setting up access restrictions - based on client domain, you may well have added entries for, - <CODE>AuthType, AuthName, AuthUserFile</CODE> or <CODE>AuthGroupFile</CODE>. - <B>None</B> of these are needed (or appropriate) for restricting access - based on client domain. - - <P>When Apache sees <CODE>AuthType</CODE> it (reasonably) assumes you - are using some authorization type based on username and password. - - <P>Please remove <CODE>AuthType</CODE>, it's unnecessary even for NCSA. - - <P> - - <LI><CODE>AuthUserFile</CODE> requires a full pathname. In earlier - versions of NCSA httpd and Apache, you could use a filename - relative to the .htaccess file. This could be a major security hole, - as it made it trivially easy to make a ".htpass" file in the a - directory easily accessible by the world. We recommend you store - your passwords outside your document tree. - - <P> - - <LI><CODE>OldScriptAlias</CODE> is no longer supported. - - <P> - - <LI><CODE>exec cgi=""</CODE> produces reasonable <B>malformed header</B> - responses when used to invoke non-CGI scripts.<BR> - The NCSA code ignores the missing header. (bad idea)<BR> - Solution: write CGI to the CGI spec or use <CODE>exec cmd=""</CODE> instead. - <P>We might add <CODE>virtual</CODE> support to <CODE>exec cmd</CODE> to - make up for this difference. - - <P> - - <LI><Limit> silliness - in the old Apache 0.6.5, a - directive of <Limit GET> would also restrict POST methods - Apache 0.8.8's new - core is correct in not presuming a limit on a GET is the same limit on a POST, - so if you are relying on that behavior you need to change your access configurations - to reflect that. - - <P> - - <LI>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 -<a href="mailto:kevinh@eit.com">Kevin Hughes</a> at -<a href="http://www.eit.com/">EIT</a>. - If you are using the same srm.conf from an old distribution, make sure - you add the new - <A - HREF="../mod/mod_dir.html#addicon" - >AddIcon</A>, - <A - HREF="../mod/mod_dir.html#addiconbytype" - >AddIconByType</A>, - and - <A - HREF="../mod/mod_dir.html#defaulticon" - >DefaultIcon</A> - directives. - - <P> - - <LI>Under IRIX, the "Group" directive in httpd.conf needs to be a - valid group name - (<EM>i.e.</EM>, "nogroup") not the numeric group ID. The distribution - httpd.conf, and earlier ones, had the default Group be "#-1", which - was causing silent exits at startup.<p> - -<li><code>.asis</code> files: Apache 0.6.5 did not require a Status header; -it added one automatically if the .asis file contained a Location header. -0.8.14 requires a Status header. <p> - - <P> - <LI>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. - </LI> - - <LI>Apache does not permit commas delimiting the methods in <Limit>. - - <LI>Apache's <CODE><VirtualHost></CODE> 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 <code>optional</code> keyword is included. - - <LI>Apache does not implement <CODE>OnDeny</CODE> use - <a href="../mod/core.html#errordocument"><code>ErrorDocument</code></a> - instead. + format allows commas between user names - Apache does not. + +<P> +<LI>If you follow the NCSA guidelines for setting up access + restrictions based on client domain, you may well have added + entries for, <CODE>AuthType, AuthName, AuthUserFile</CODE> or + <CODE>AuthGroupFile</CODE>. <STRONG>None</STRONG> of these are + needed (or appropriate) for restricting access based on client + domain. When Apache sees <CODE>AuthType</CODE> it (reasonably) + assumes you are using some authorization type based on username + and password. Please remove <CODE>AuthType</CODE>, it's + unnecessary even for NCSA. + +<P> +<LI><CODE>OldScriptAlias</CODE> is no longer supported. + +<P> +<LI><CODE>exec cgi=""</CODE> produces reasonable <STRONG>malformed + header</STRONG> responses when used to invoke non-CGI scripts.<BR> + The NCSA code ignores the missing header. (bad idea) + <BR>Solution: write CGI to the CGI spec and use + <CODE>include virtual</CODE>, or use <CODE>exec cmd=""</CODE> instead. + +<P> +<LI>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 <A + HREF="mailto:kevinh@eit.com">Kevin Hughes</A> at <A + HREF="http://www.eit.com/">EIT</A>. If you are using the same + srm.conf from an old distribution, make sure you add the new <A + HREF="../mod/mod_autoindex.html#addicon">AddIcon</A>, <A + HREF="../mod/mod_autoindex.html#addiconbytype">AddIconByType</A>, + and <A + HREF="../mod/mod_autoindex.html#defaulticon">DefaultIcon</A> + directives. + +<P> +<LI>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. + +<P> +<LI>Apache does not permit commas delimiting the methods in <Limit>. + +<P> +<LI>Apache's <CODE><VirtualHost></CODE> treats all addresses as + "optional" (<EM>i.e.</EM>, the server should continue booting if it can't + resolve the address). Whereas in NCSA the default is to fail + booting unless an added <CODE>optional</CODE> keyword is included. + +<P> +<LI>Apache does not implement <CODE>OnDeny</CODE> use + <A HREF="../mod/core.html#errordocument"><CODE>ErrorDocument</CODE></A> + instead. + +<P> +<LI>Apache (as of 1.3) always performs the equivalent of + <CODE>HostnameLookups minimal</CODE>. <CODE>minimal</CODE> is not an + option to <A HREF="../mod/core.html#hostnamelookups"><CODE> + HostnameLookups</CODE></A>. + +<P> +<LI>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. + +<P> +<LI>Apache does not implement the NCSA <CODE>referer</CODE> + directive. See <A HREF="http://bugs.apache.org/index/full/968"> + PR#968</A> for a few brief suggestions on alternative ways to + implement the same thing under Apache. + +<P> +<LI>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, <EM>etc.</EM> </OL> More to come when we notice them.... <HR> + <H3 ALIGN="CENTER"> - Apache HTTP Server Version 1.2 + Apache HTTP Server Version 1.3 </H3> <A HREF="./"><IMG SRC="../images/index.gif" ALT="Index"></A> diff --git a/usr.sbin/httpd/htdocs/manual/misc/howto.html b/usr.sbin/httpd/htdocs/manual/misc/howto.html index c3ddf868066..62f1116656a 100644 --- a/usr.sbin/httpd/htdocs/manual/misc/howto.html +++ b/usr.sbin/httpd/htdocs/manual/misc/howto.html @@ -1,7 +1,8 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <HTML> <HEAD> -<META NAME="description" CONTENT="Some 'how to' tips for the Apache httpd server"> +<META NAME="description" + CONTENT="Some 'how to' tips for the Apache httpd server"> <META NAME="keywords" CONTENT="apache,redirect,robots,rotate,logfiles"> <TITLE>Apache HOWTO documentation</TITLE> </HEAD> @@ -17,56 +18,64 @@ <DIV ALIGN="CENTER"> <IMG SRC="../images/sub.gif" ALT="[APACHE DOCUMENTATION]"> <H3> - Apache HTTP Server Version 1.2 + Apache HTTP Server Version 1.3 </H3> </DIV> <H1 ALIGN="CENTER">Apache HOWTO documentation</H1> How to: -<ul> -<li><A HREF="#redirect">redirect an entire server or directory to a single URL</A> -<li><A HREF="#logreset">reset your log files</A> -<li><A HREF="#stoprob">stop/restrict robots</A> -</ul> +<UL> +<LI><A HREF="#redirect">redirect an entire server or directory to a single + URL</A> +<LI><A HREF="#logreset">reset your log files</A> +<LI><A HREF="#stoprob">stop/restrict robots</A> +<LI><A HREF="#proxyssl">proxy SSL requests <EM>through</EM> your non-SSL + server</A> +</UL> <HR> -<H2><A name="redirect">How to redirect an entire server or directory to a single URL</A></H2> +<H2><A NAME="redirect">How to redirect an entire server or directory to a +single URL</A></H2> <P>There are two chief ways to redirect all requests for an entire server to a single location: one which requires the use of -<code>mod_rewrite</code>, and another which uses a CGI script. +<CODE>mod_rewrite</CODE>, and another which uses a CGI script. <P>First: if all you need to do is migrate a server from one name to -another, simply use the <code>Redirect</code> directive, as supplied -by <code>mod_alias</code>: +another, simply use the <CODE>Redirect</CODE> directive, as supplied +by <CODE>mod_alias</CODE>: -<blockquote><pre> +<BLOCKQUOTE><PRE> Redirect / http://www.apache.org/ -</pre></blockquote> +</PRE></BLOCKQUOTE> -<P>Since <code>Redirect</code> will forward along the complete path, +<P>Since <CODE>Redirect</CODE> 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. -<P>The best option is to use the standard Apache module <code>mod_rewrite</code>. -If that module is compiled in, the following lines: +<P>The best option is to use the standard Apache module +<CODE>mod_rewrite</CODE>. +If that module is compiled in, the following lines -<blockquote><pre>RewriteEngine On +<BLOCKQUOTE><PRE>RewriteEngine On RewriteRule /.* http://www.apache.org/ [R] -</pre></blockquote> +</PRE></BLOCKQUOTE> 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 <CODE>ScriptAlias</Code> pointing to -a <B>cgi script</B> which outputs a 301 or 302 status and the location +The second option is to set up a <CODE>ScriptAlias</CODE> pointing to +a <STRONG>CGI script</STRONG> which outputs a 301 or 302 status and the +location of the other server.</P> -<P>By using a <B>cgi-script</B> you can intercept various requests and -treat them specially, e.g. you might want to intercept <B>POST</B> +<P>By using a <STRONG>CGI script</STRONG> you can intercept various requests +and +treat them specially, <EM>e.g.</EM>, you might want to intercept +<STRONG>POST</STRONG> 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 @@ -74,21 +83,22 @@ want to compile mod_rewrite into your server. <P>Here's how to redirect all requests to a script... In the server configuration file, -<blockquote><pre>ScriptAlias / /usr/local/httpd/cgi-bin/redirect_script</pre></blockquote> +<BLOCKQUOTE><PRE>ScriptAlias / /usr/local/httpd/cgi-bin/redirect_script</PRE> +</BLOCKQUOTE> and here's a simple perl script to redirect requests: -<blockquote><pre> +<BLOCKQUOTE><PRE> #!/usr/local/bin/perl print "Status: 302 Moved Temporarily\r Location: http://www.some.where.else.com/\r\n\r\n"; -</pre></blockquote></P> +</PRE></BLOCKQUOTE></P> <HR> -<H2><A name="logreset">How to reset your log files</A></H2> +<H2><A NAME="logreset">How to reset your log files</A></H2> <P>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 @@ -104,16 +114,19 @@ 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.</P> -<P>The correct procedure is to move the logfile, then signal Apache to tell it to reopen the logfiles.</P> +<P>The correct procedure is to move the logfile, then signal Apache to tell +it to reopen the logfiles.</P> -<P>Apache is signaled using the <B>SIGHUP</B> (-1) signal. e.g. -<blockquote><code> +<P>Apache is signaled using the <STRONG>SIGHUP</STRONG> (-1) signal. +<EM>e.g.</EM> +<BLOCKQUOTE><CODE> mv access_log access_log.old<BR> kill -1 `cat httpd.pid` -</code></blockquote> +</CODE></BLOCKQUOTE> </P> -<P>Note: <code>httpd.pid</code> is a file containing the <B>p</B>rocess <B>id</B> +<P>Note: <CODE>httpd.pid</CODE> is a file containing the +<STRONG>p</STRONG>rocess <STRONG>id</STRONG> of the Apache httpd daemon, Apache saves this in the same directory as the log files.</P> @@ -121,22 +134,29 @@ files.</P> nightly or weekly basis.</P> <HR> -<H2><A name="stoprob">How to stop or restrict robots</A></H2> +<H2><A NAME="stoprob">How to stop or restrict robots</A></H2> <P>Ever wondered why so many clients are interested in a file called -<code>robots.txt</code> which you don't have, and never did have?</P> +<CODE>robots.txt</CODE> which you don't have, and never did have?</P> -<P>These clients are called <B>robots</B> (also known as crawlers, +<P>These clients are called <STRONG>robots</STRONG> (also known as crawlers, spiders and other cute name) - special automated clients which wander around the web looking for interesting resources.</P> -<P>Most robots are used to generate some kind of <em>web index</em> which -is then used by a <em>search engine</em> to help locate information.</P> +<P>Most robots are used to generate some kind of <EM>web index</EM> which +is then used by a <EM>search engine</EM> to help locate information.</P> -<P><code>robots.txt</code> provides a means to request that robots limit their +<P><CODE>robots.txt</CODE> provides a means to request that robots limit their activities at the site, or more often than not, to leave the site alone.</P> -<P>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 <A HREF="http://info.webcrawler.com/mak/projects/robots/guidelines.html"> Guidelines for Robot Writers</A>, but even so, some robots may <A HREF="http://www.zyzzyva.com/robots/alert/">exhibit unfriendly behavior</A> which the webmaster isn't willing to tolerate, and will want to stop.</P> +<P>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 <A +HREF="http://info.webcrawler.com/mak/projects/robots/guidelines.html"> +Guidelines for Robot Writers</A>, but even so, some robots may exhibit +unfriendly behavior which the webmaster isn't willing to tolerate, and +will want to stop.</P> <P>Another reason some webmasters want to block access to robots, is to stop them indexing dynamic information. Many search engines will use the @@ -146,11 +166,53 @@ stale by the time people find it in a search engine.</P> <P>If you decide to exclude robots completely, or just limit the areas in which they can roam, create a <CODE>robots.txt</CODE> file; refer -to the <A HREF="http://info.webcrawler.com/mak/projects/robots/robots.html">robot information pages</A> provided by Martijn Koster for the syntax.</P> +to the <A HREF="http://info.webcrawler.com/mak/projects/robots/robots.html" +>robot information pages</A> provided by Martijn Koster for the syntax.</P> <HR> +<H2><A NAME="proxyssl">How to proxy SSL requests <EM>through</EM> + your non-SSL Apache server</A> + <BR> + <SMALL>(<EM>submitted by David Sedlock</EM>)</SMALL> +</H2> +<P> +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: +</P> +<PRE> + Listen 80 + Listen 443 +</PRE> +<P> +Then set the security proxy in your browser to 443. That might be it! +</P> +<P> +If your proxy is sending requests to another proxy, then you may have +to set the directive ProxyRemote differently. Here are my settings: +</P> +<PRE> + ProxyRemote http://nicklas:80/ http://proxy.mayn.franken.de:8080 + ProxyRemote http://nicklas:443/ http://proxy.mayn.franken.de:443 +</PRE> +<P> +Requests on port 80 of my proxy <SAMP>nicklas</SAMP> are forwarded to +proxy<SAMP>.mayn.franken.de:8080</SAMP>, while requests on port 443 are +forwarded to <SAMP>proxy.mayn.franken.de:443</SAMP>. +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. +</P> +<P> +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. +</P> +<HR> + <H3 ALIGN="CENTER"> - Apache HTTP Server Version 1.2 + Apache HTTP Server Version 1.3 </H3> <A HREF="./"><IMG SRC="../images/index.gif" ALT="Index"></A> diff --git a/usr.sbin/httpd/htdocs/manual/misc/perf-hp.html b/usr.sbin/httpd/htdocs/manual/misc/perf-hp.html index 9db0a08c9ff..a65184609fb 100644 --- a/usr.sbin/httpd/htdocs/manual/misc/perf-hp.html +++ b/usr.sbin/httpd/htdocs/manual/misc/perf-hp.html @@ -50,6 +50,10 @@ 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. + <P> How to pick the value? Examine the output of diff --git a/usr.sbin/httpd/htdocs/manual/misc/perf-tuning.html b/usr.sbin/httpd/htdocs/manual/misc/perf-tuning.html index 9ab35a0340e..956a7febbc5 100644 --- a/usr.sbin/httpd/htdocs/manual/misc/perf-tuning.html +++ b/usr.sbin/httpd/htdocs/manual/misc/perf-tuning.html @@ -340,7 +340,7 @@ the inner loop. The loop looks like this (differences highlighted): 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 <CODE>src/conf.h</CODE> (pre-1.3) or -<CODE>src/main/conf.h</CODE> (1.3 or later). Some architectures +<CODE>src/include/ap_config.h</CODE> (1.3 or later). Some architectures do not have any locking choice made, on these architectures it is unsafe to use multiple <CODE>Listen</CODE> directives. @@ -432,7 +432,7 @@ and then single-socket servers will not serialize at all. <P>As discussed in <A - HREF="ftp://ds.internic.net/internet-drafts/draft-ietf-http-connection-00.txt" + HREF="http://www.ics.uci.edu/pub/ietf/http/draft-ietf-http-connection-00.txt" >draft-ietf-http-connection-00.txt</A> section 8, in order for an HTTP server to <STRONG>reliably</STRONG> implement the protocol it needs to shutdown each direction of the communication independently diff --git a/usr.sbin/httpd/htdocs/manual/mod/core.html b/usr.sbin/httpd/htdocs/manual/mod/core.html index f8734d1d9d7..f7a38be36bc 100644 --- a/usr.sbin/httpd/htdocs/manual/mod/core.html +++ b/usr.sbin/httpd/htdocs/manual/mod/core.html @@ -287,7 +287,8 @@ Allow use of the directives controlling specific directory features 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. +password to send. <SAMP>AuthName</SAMP> takes a single argument; +if the realm name contains spaces, it must be enclosed in quotation marks. It must be accompanied by <A HREF="#authtype">AuthType</A> and <A HREF="#require">require</A> directives, and directives such as <A HREF="mod_auth.html#authuserfile">AuthUserFile</A> and @@ -450,11 +451,11 @@ re-populated using the <A HREF="#addmodule">AddModule</A> directive.<P><HR> <A HREF="directive-dict.html#Override" REL="Help" -><STRONG>Override:</STRONG></A> AuthConfig<BR> +><STRONG>Override:</STRONG></A> Options<BR> <A HREF="directive-dict.html#Status" REL="Help" -><STRONG>Status:</STRONG></A> experimental<P> +><STRONG>Status:</STRONG></A> experimental<BR> <A HREF="directive-dict.html#Compatibility" REL="Help" @@ -818,7 +819,7 @@ responses.</A><P><HR> <A HREF="directive-dict.html#Syntax" REL="Help" -><STRONG>Syntax:</STRONG></A> ErrorLog ><EM>filename</EM>|<CODE>syslog[:facility]</CODE> +><STRONG>Syntax:</STRONG></A> ErrorLog <EM>filename</EM>|<CODE>syslog[:facility]</CODE> <BR> <A HREF="directive-dict.html#Default" @@ -2050,7 +2051,7 @@ See also <A HREF="#maxspareservers">MaxSpareServers</A> and <A HREF="directive-dict.html#Status" REL="Help" -><STRONG>Status:</STRONG></A> core<P> +><STRONG>Status:</STRONG></A> core<BR> <A HREF="directive-dict.html#Compatibility" REL="Help" @@ -3011,7 +3012,7 @@ a packet is sent. <STRONG>Context:</STRONG></A> server config, virtual host, directory, .htaccess <BR> <A HREF="directive-dict.html#Override" REL="Help"> -<STRONG>Override:</STRONG></A> AuthConfig<BR> +<STRONG>Override:</STRONG></A> Options<BR> <A HREF="directive-dict.html#Compatibility" REL="Help"> <STRONG>Compatibility:</STRONG></A> UseCanonicalName is only available in Apache 1.3 and later<P> diff --git a/usr.sbin/httpd/htdocs/manual/mod/directives.html b/usr.sbin/httpd/htdocs/manual/mod/directives.html index e5d8fb839e1..57938e5b190 100644 --- a/usr.sbin/httpd/htdocs/manual/mod/directives.html +++ b/usr.sbin/httpd/htdocs/manual/mod/directives.html @@ -15,172 +15,216 @@ <DIV ALIGN="CENTER"> <IMG SRC="../images/sub.gif" ALT="[APACHE DOCUMENTATION]"> <H3> - Apache HTTP Server Version 1.2 + Apache HTTP Server Version 1.3 </H3> </DIV> -<H1 ALIGN="CENTER">Apache directives</H1> - -<ul> -<li><A HREF="core.html#accessconfig">AccessConfig</A> -<li><A HREF="core.html#accessfilename">AccessFileName</A> -<li><A HREF="mod_actions.html#action">Action</A> -<li><A HREF="mod_dir.html#addalt">AddAlt</A> -<li><A HREF="mod_dir.html#addaltbyencoding">AddAltByEncoding</A> -<li><A HREF="mod_dir.html#addaltbytype">AddAltByType</A> -<li><A HREF="mod_dir.html#adddescription">AddDescription</A> -<li><A HREF="mod_mime.html#addencoding">AddEncoding</A> -<li><A HREF="mod_mime.html#addhandler">AddHandler</A> -<li><A HREF="mod_dir.html#addicon">AddIcon</A> -<li><A HREF="mod_dir.html#addiconbyencoding">AddIconByEncoding</A> -<li><A HREF="mod_dir.html#addiconbytype">AddIconByType</A> -<li><A HREF="mod_mime.html#addlanguage">AddLanguage</A> -<li><A HREF="core.html#addmodule">AddModule</A> -<li><A HREF="mod_mime.html#addtype">AddType</A> -<li><A HREF="mod_log_agent.html#agentlog">AgentLog</A> -<li><A HREF="mod_alias.html#alias">Alias</A> -<li><A HREF="mod_access.html#allow">allow</A> -<li><A HREF="core.html#allowoverride">AllowOverride</A> -<li><A HREF="mod_auth_anon.html#anonymous">Anonymous</A> -<li><A HREF="mod_auth_anon.html#Authoritative">Anonymous_Authoritative</A> -<li><A HREF="mod_auth_anon.html#LogEmail">Anonymous_LogEmail</A> -<li><A HREF="mod_auth_anon.html#MustGiveEmail">Anonymous_MustGiveEmail</A> -<li><A HREF="mod_auth_anon.html#NoUserID">Anonymous_NoUserID</A> -<li><A HREF="mod_auth_anon.html#VerifyEmail">Anonymous_VerifyEmail</A> -<li><A HREF="mod_auth.html#authauthoritative">AuthAuthoritative</A> -<li><A HREF="mod_auth_db.html#authdbauthoritative">AuthDBAuthoritative</A> -<li><A HREF="mod_auth_db.html#authdbgroupfile">AuthDBGroupFile</A> -<li><A HREF="mod_auth_dbm.html#authdbmauthoritative">AuthDBMAuthoritative</A> -<li><A HREF="mod_auth_dbm.html#authdbmgroupfile">AuthDBMGroupFile</A> -<li><A HREF="mod_auth_dbm.html#authdbmgroupfile">AuthDBMGroupFile</A> -<li><A HREF="mod_auth_db.html#authdbuserfile">AuthDBUserFile</A> -<li><A HREF="mod_auth_dbm.html#authdbmuserfile">AuthDBMUserFile</A> -<li><A HREF="mod_digest.html#authdigestfile">AuthDigestFile</A> -<li><A HREF="mod_auth.html#authgroupfile">AuthGroupFile</A> -<li><A HREF="core.html#authname">AuthName</A> -<li><A HREF="core.html#authtype">AuthType</A> -<li><A HREF="mod_auth.html#authuserfile">AuthUserFile</A> -<li><A HREF="core.html#bindaddress">BindAddress</A> -<li><A HREF="mod_browser.html#browsermatch">BrowserMatch</A> -<li><A HREF="mod_browser.html#browsermatchnocase">BrowserMatchNoCase</A> -<li><A HREF="mod_proxy.html#cachedefaultexpire">CacheDefaultExpire</A> -<li><A HREF="mod_proxy.html#cachedirlength">CacheDirLength</A> -<li><A HREF="mod_proxy.html#cachedirlevels">CacheDirLevels</A> -<li><A HREF="mod_proxy.html#cachegcinterval">CacheGcInterval</A> -<li><A HREF="mod_proxy.html#cachelastmodifiedfactor">CacheLastModifiedFactor</A> -<li><A HREF="mod_proxy.html#cachemaxexpire">CacheMaxExpire</A> -<li><A HREF="mod_negotiation.html#cachenegotiateddocs">CacheNegotiatedDocs</A> -<li><A HREF="mod_proxy.html#cacheroot">CacheRoot</A> -<li><A HREF="mod_proxy.html#cachesize">CacheSize</A> -<li><A HREF="core.html#clearmodulelist">ClearModuleList</A> -<li><A HREF="mod_usertrack.html#cookieexpires">CookieExpires</A> -<li><A HREF="mod_cookies.html#cookielog">CookieLog</A> (mod_cookies) -<li><A HREF="mod_log_config.html#cookielog">CookieLog</A> (mod_log_config) -<li><A HREF="mod_usertrack.html#cookietracking">CookieTracking</A> -<li><A HREF="mod_log_config.html#customlog">CustomLog</A> -<li><A HREF="mod_dir.html#defaulticon">DefaultIcon</A> -<li><A HREF="core.html#defaulttype">DefaultType</A> -<li><A HREF="mod_access.html#deny">deny</A> -<li><A HREF="core.html#directory"><Directory></A> -<li><A HREF="mod_dir.html#directoryindex">DirectoryIndex</A> -<li><A HREF="core.html#documentroot">DocumentRoot</A> -<li><A HREF="core.html#errordocument">ErrorDocument</A> -<li><A HREF="core.html#errorlog">ErrorLog</A> -<li><A HREF="mod_example.html#example">Example</A> -<li><A HREF="mod_expires.html#expiresactive">ExpiresActive</A> -<li><A HREF="mod_expires.html#expiresbytype">ExpiresByType</A> -<li><A HREF="mod_expires.html#expiresdefault">ExpiresDefault</A> -<li><A HREF="mod_dir.html#fancyindexing">FancyIndexing</A> -<li><A HREF="core.html#files"><Files></A> -<li><A HREF="mod_mime.html#forcetype">ForceType</A> -<li><A HREF="core.html#group">Group</A> -<li><A HREF="mod_headers.html#header">Header</A> -<li><A HREF="mod_dir.html#headername">HeaderName</A> -<li><A HREF="core.html#hostnamelookups">HostNameLookups</A> -<li><A HREF="core.html#identitycheck">IdentityCheck</A> -<li><A HREF="core.html#ifmodule"><IfModule></A> -<li><A HREF="mod_imap.html#imapbase">ImapBase</A> -<li><A HREF="mod_imap.html#imapdefault">ImapDefault</A> -<li><A HREF="mod_imap.html#imapmenu">ImapMenu</A> -<li><A HREF="mod_dir.html#indexignore">IndexIgnore</A> -<li><A HREF="mod_dir.html#indexoptions">IndexOptions</A> -<li><A HREF="core.html#keepalive">KeepAlive</A> -<li><A HREF="core.html#keepalivetimeout">KeepAliveTimeout</A> -<li><A HREF="mod_negotiation.html#languagepriority">LanguagePriority</A> -<li><A HREF="core.html#limit"><Limit></A> -<li><A HREF="core.html#listen">Listen</A> -<li><A HREF="mod_dld.html#loadfile">LoadFile</A> -<li><A HREF="mod_dld.html#loadmodule">LoadModule</A> -<li><A HREF="core.html#location"><Location></A> -<li><A HREF="core.html#lockfile">LockFile</A> -<li><A HREF="mod_log_config.html#logformat">LogFormat</A> -<li><A HREF="core.html#maxclients">MaxClients</A> -<li><A HREF="core.html#maxkeepaliverequests">MaxKeepAliveRequests</A> -<li><A HREF="core.html#maxrequestsperchild">MaxRequestsPerChild</A> -<li><A HREF="core.html#maxspareservers">MaxSpareServers</A> -<li><A HREF="mod_cern_meta.html#metadir">MetaDir</A> -<li><A HREF="mod_cern_meta.html#metasuffix">MetaSuffix</A> -<li><A HREF="core.html#minspareservers">MinSpareServers</A> -<li><A HREF="mod_proxy.html#nocache">NoCache</A> -<li><A HREF="core.html#options">Options</A> -<li><A HREF="mod_access.html#order">order</A> -<li><A HREF="mod_env.html#passenv">PassEnv</A> -<li><A HREF="core.html#pidfile">PidFile</A> -<li><A HREF="core.html#port">Port</A> -<li><A HREF="mod_proxy.html#proxyblock">ProxyBlock</A> -<li><A HREF="mod_proxy.html#proxypass">ProxyPass</A> -<li><A HREF="mod_proxy.html#proxyremote">ProxyRemote</A> -<li><A HREF="mod_proxy.html#proxyrequests">ProxyRequests</A> -<li><A HREF="mod_dir.html#readmename">ReadmeName</A> -<li><A HREF="mod_alias.html#redirect">Redirect</A> -<li><A HREF="mod_alias.html#redirectperm">RedirectPermanent</A> -<li><A HREF="mod_alias.html#redirecttemp">RedirectTemp</A> -<li><A HREF="mod_log_referer.html#refererignore">RefererIgnore</A> -<li><A HREF="mod_log_referer.html#refererlog">RefererLog</A> -<li><A HREF="core.html#require">require</A> -<li><A HREF="core.html#resourceconfig">ResourceConfig</A> -<li><A HREF="mod_rewrite.html#RewriteBase">RewriteBase</A> -<li><A HREF="mod_rewrite.html#RewriteCond">RewriteCond</A> -<li><A HREF="mod_rewrite.html#RewriteEngine">RewriteEngine</A> -<li><A HREF="mod_rewrite.html#RewriteLog">RewriteLog</A> -<li><A HREF="mod_rewrite.html#RewriteLogLevel">RewriteLogLevel</A> -<li><A HREF="mod_rewrite.html#RewriteMap">RewriteMap</A> -<li><A HREF="mod_rewrite.html#RewriteOptions">RewriteOptions</A> -<li><A HREF="mod_rewrite.html#RewriteRule">RewriteRule</A> -<li><A HREF="core.html#rlimitcpu">RLimitCPU</A> -<li><A HREF="core.html#rlimitmem">RLimitMEM</A> -<li><A HREF="core.html#rlimitnproc">RLimitNPROC</A> -<li><A HREF="core.html#satisfy">Satisfy</A> -<li><A HREF="core.html#scoreboardfile">ScoreBoardFile</A> -<li><A HREF="mod_actions.html#script">Script</A> -<li><A HREF="mod_alias.html#scriptalias">ScriptAlias</A> -<li><A HREF="mod_cgi.html#scriptlog">ScriptLog</A> -<li><A HREF="mod_cgi.html#scriptlogbuffer">ScriptLogBuffer</A> -<li><A HREF="mod_cgi.html#scriptloglength">ScriptLogLength</A> -<li><A HREF="core.html#sendbuffersize">SendBufferSize</A> -<li><A HREF="core.html#serveradmin">ServerAdmin</A> -<li><A HREF="core.html#serveralias">ServerAlias</A> -<li><A HREF="core.html#servername">ServerName</A> -<li><A HREF="core.html#serverpath">ServerPath</A> -<li><A HREF="core.html#serverroot">ServerRoot</A> -<li><A HREF="core.html#servertype">ServerType</A> -<li><A HREF="mod_env.html#setenv">SetEnv</A> -<li><A HREF="mod_mime.html#sethandler">SetHandler</A> -<li><A HREF="core.html#startservers">StartServers</A> -<li><A HREF="core.html#timeout">TimeOut</A> -<li><A HREF="mod_log_common.html#transferlog">TransferLog</A> (mod_log_common) -<li><A HREF="mod_log_config.html#transferlog">TransferLog</A> (mod_log_config) -<li><A HREF="mod_mime.html#typesconfig">TypesConfig</A> -<li><A HREF="mod_env.html#unsetenv">UnsetEnv</A> -<li><A HREF="core.html#user">User</A> -<li><A HREF="mod_userdir.html#userdir">UserDir</A> -<li><A HREF="core.html#virtualhost"><VirtualHost></A> -<li><A HREF="mod_include.html#xbithack">XBitHack</A> -</ul> +<H1 ALIGN="CENTER">Apache Directives</H1> +<P> +Each Apache directive available in the standard Apache distribution is +listed here. They are described using a consistent format, and there is +<A + HREF="directive-dict.html" + REL="Glossary" +>a dictionary</A> +of the terms used in their descriptions available. +</P> +<UL> +<LI><A HREF="core.html#accessconfig">AccessConfig</A> +<LI><A HREF="core.html#accessfilename">AccessFileName</A> +<LI><A HREF="mod_actions.html#action">Action</A> +<LI><A HREF="mod_autoindex.html#addalt">AddAlt</A> +<LI><A HREF="mod_autoindex.html#addaltbyencoding">AddAltByEncoding</A> +<LI><A HREF="mod_autoindex.html#addaltbytype">AddAltByType</A> +<LI><A HREF="mod_autoindex.html#adddescription">AddDescription</A> +<LI><A HREF="mod_mime.html#addencoding">AddEncoding</A> +<LI><A HREF="mod_mime.html#addhandler">AddHandler</A> +<LI><A HREF="mod_autoindex.html#addicon">AddIcon</A> +<LI><A HREF="mod_autoindex.html#addiconbyencoding">AddIconByEncoding</A> +<LI><A HREF="mod_autoindex.html#addiconbytype">AddIconByType</A> +<LI><A HREF="mod_mime.html#addlanguage">AddLanguage</A> +<LI><A HREF="core.html#addmodule">AddModule</A> +<LI><A HREF="mod_info.html#addmoduleinfo">AddModuleInfo</A> +<LI><A HREF="mod_mime.html#addtype">AddType</A> +<LI><A HREF="mod_log_agent.html#agentlog">AgentLog</A> +<LI><A HREF="mod_alias.html#alias">Alias</A> +<LI><A HREF="mod_alias.html#aliasmatch">AliasMatch</A> +<LI><A HREF="mod_access.html#allow">allow</A> +<LI><A HREF="core.html#allowoverride">AllowOverride</A> +<LI><A HREF="mod_auth_anon.html#anonymous">Anonymous</A> +<LI><A HREF="mod_auth_anon.html#Authoritative">Anonymous_Authoritative</A> +<LI><A HREF="mod_auth_anon.html#LogEmail">Anonymous_LogEmail</A> +<LI><A HREF="mod_auth_anon.html#MustGiveEmail">Anonymous_MustGiveEmail</A> +<LI><A HREF="mod_auth_anon.html#NoUserID">Anonymous_NoUserID</A> +<LI><A HREF="mod_auth_anon.html#VerifyEmail">Anonymous_VerifyEmail</A> +<LI><A HREF="mod_auth.html#authauthoritative">AuthAuthoritative</A> +<LI><A HREF="mod_auth_db.html#authdbauthoritative">AuthDBAuthoritative</A> +<LI><A HREF="mod_auth_db.html#authdbgroupfile">AuthDBGroupFile</A> +<LI><A HREF="mod_auth_dbm.html#authdbmauthoritative">AuthDBMAuthoritative</A> +<LI><A HREF="mod_auth_dbm.html#authdbmgroupfile">AuthDBMGroupFile</A> +<LI><A HREF="mod_auth_dbm.html#authdbmgroupfile">AuthDBMGroupFile</A> +<LI><A HREF="mod_auth_db.html#authdbuserfile">AuthDBUserFile</A> +<LI><A HREF="mod_auth_dbm.html#authdbmuserfile">AuthDBMUserFile</A> +<LI><A HREF="mod_digest.html#authdigestfile">AuthDigestFile</A> +<LI><A HREF="mod_auth.html#authgroupfile">AuthGroupFile</A> +<LI><A HREF="core.html#authname">AuthName</A> +<LI><A HREF="core.html#authtype">AuthType</A> +<LI><A HREF="mod_auth.html#authuserfile">AuthUserFile</A> +<LI><A HREF="core.html#bindaddress">BindAddress</A> +<LI><A HREF="mod_setenvif.html#BrowserMatch">BrowserMatch</A> +<LI><A HREF="mod_setenvif.html#BrowserMatchNoCase">BrowserMatchNoCase</A> +<LI><A HREF="core.html#bs2000account">BS2000Account</A> +<LI><A HREF="mod_proxy.html#cachedefaultexpire">CacheDefaultExpire</A> +<LI><A HREF="mod_proxy.html#cachedirlength">CacheDirLength</A> +<LI><A HREF="mod_proxy.html#cachedirlevels">CacheDirLevels</A> +<LI><A HREF="mod_proxy.html#cacheforcecompletion">CacheForceCompletion</A> +<LI><A HREF="mod_proxy.html#cachegcinterval">CacheGcInterval</A> +<LI><A HREF="mod_proxy.html#cachelastmodifiedfactor">CacheLastModifiedFactor</A> +<LI><A HREF="mod_proxy.html#cachemaxexpire">CacheMaxExpire</A> +<LI><A HREF="mod_negotiation.html#cachenegotiateddocs">CacheNegotiatedDocs</A> +<LI><A HREF="mod_proxy.html#cacheroot">CacheRoot</A> +<LI><A HREF="mod_proxy.html#cachesize">CacheSize</A> +<LI><A HREF="mod_speling.html#checkspelling">CheckSpelling</A> +<LI><A HREF="core.html#clearmodulelist">ClearModuleList</A> +<LI><A HREF="core.html#contentdigest">ContentDigest</A> +<LI><A HREF="mod_usertrack.html#cookieexpires">CookieExpires</A> +<LI><A HREF="mod_cookies.html#cookielog">CookieLog</A> (mod_cookies) +<LI><A HREF="mod_log_config.html#cookielog">CookieLog</A> (mod_log_config) +<LI><A HREF="mod_usertrack.html#cookietracking">CookieTracking</A> +<LI><A HREF="core.html#coredumpdirectory">CoreDumpDirectory</A> +<LI><A HREF="mod_log_config.html#customlog">CustomLog</A> +<LI><A HREF="mod_autoindex.html#defaulticon">DefaultIcon</A> +<LI><A HREF="mod_mime.html#defaultlanguage">DefaultLanguage</A> +<LI><A HREF="core.html#defaulttype">DefaultType</A> +<LI><A HREF="mod_access.html#deny">deny</A> +<LI><A HREF="core.html#directory"><Directory></A> +<LI><A HREF="core.html#directorymatch"><DirectoryMatch></A> +<LI><A HREF="mod_dir.html#directoryindex">DirectoryIndex</A> +<LI><A HREF="core.html#documentroot">DocumentRoot</A> +<LI><A HREF="core.html#errordocument">ErrorDocument</A> +<LI><A HREF="core.html#errorlog">ErrorLog</A> +<LI><A HREF="mod_example.html#example">Example</A> +<LI><A HREF="mod_expires.html#expiresactive">ExpiresActive</A> +<LI><A HREF="mod_expires.html#expiresbytype">ExpiresByType</A> +<LI><A HREF="mod_expires.html#expiresdefault">ExpiresDefault</A> +<LI><A HREF="mod_status.html#extendedstatus">ExtendedStatus</A> +<LI><A HREF="mod_autoindex.html#fancyindexing">FancyIndexing</A> +<LI><A HREF="core.html#files"><Files></A> +<LI><A HREF="core.html#filesmatch"><FilesMatch></A> +<LI><A HREF="mod_mime.html#forcetype">ForceType</A> +<LI><A HREF="core.html#group">Group</A> +<LI><A HREF="mod_headers.html#header">Header</A> +<LI><A HREF="mod_autoindex.html#headername">HeaderName</A> +<LI><A HREF="core.html#hostnamelookups">HostNameLookups</A> +<LI><A HREF="core.html#identitycheck">IdentityCheck</A> +<LI><A HREF="core.html#ifdefine"><IfDefine></A> +<LI><A HREF="core.html#ifmodule"><IfModule></A> +<LI><A HREF="mod_imap.html#imapbase">ImapBase</A> +<LI><A HREF="mod_imap.html#imapdefault">ImapDefault</A> +<LI><A HREF="mod_imap.html#imapmenu">ImapMenu</A> +<LI><A HREF="core.html#include">Include</A> +<LI><A HREF="mod_autoindex.html#indexignore">IndexIgnore</A> +<LI><A HREF="mod_autoindex.html#indexoptions">IndexOptions</A> +<LI><A HREF="core.html#keepalive">KeepAlive</A> +<LI><A HREF="core.html#keepalivetimeout">KeepAliveTimeout</A> +<LI><A HREF="mod_negotiation.html#languagepriority">LanguagePriority</A> +<LI><A HREF="core.html#limit"><Limit></A> +<LI><A HREF="core.html#limitrequestbody">LimitRequestBody</A> +<LI><A HREF="core.html#limitrequestfields">LimitRequestFields</A> +<LI><A HREF="core.html#limitrequestfieldsize">LimitRequestFieldsize</A> +<LI><A HREF="core.html#limitrequestline">LimitRequestLine</A> +<LI><A HREF="core.html#listen">Listen</A> +<LI><A HREF="core.html#listenbacklog">ListenBacklog</A> +<LI><A HREF="mod_so.html#loadfile">LoadFile</A> +<LI><A HREF="mod_so.html#loadmodule">LoadModule</A> +<LI><A HREF="core.html#location"><Location></A> +<LI><A HREF="core.html#locationmatch"><LocationMatch></A> +<LI><A HREF="core.html#lockfile">LockFile</A> +<LI><A HREF="mod_log_config.html#logformat">LogFormat</A> +<LI><A HREF="core.html#loglevel">LogLevel</A> +<LI><A HREF="core.html#maxclients">MaxClients</A> +<LI><A HREF="core.html#maxkeepaliverequests">MaxKeepAliveRequests</A> +<LI><A HREF="core.html#maxrequestsperchild">MaxRequestsPerChild</A> +<LI><A HREF="core.html#maxspareservers">MaxSpareServers</A> +<LI><A HREF="mod_cern_meta.html#metadir">MetaDir</A> +<LI><A HREF="mod_cern_meta.html#metafiles">MetaFiles</A> +<LI><A HREF="mod_cern_meta.html#metasuffix">MetaSuffix</A> +<LI><A HREF="mod_mime_magic.html#mimemagicfile">MimeMagicFile</A> +<LI><A HREF="core.html#minspareservers">MinSpareServers</A> +<LI><A HREF="mod_mmap_static.html#mmapfile">MMapFile</A> +<LI><A HREF="core.html#namevirtualhost">NameVirtualHost</A> +<LI><A HREF="mod_proxy.html#nocache">NoCache</A> +<LI><A HREF="core.html#options">Options</A> +<LI><A HREF="mod_access.html#order">order</A> +<LI><A HREF="mod_env.html#passenv">PassEnv</A> +<LI><A HREF="core.html#pidfile">PidFile</A> +<LI><A HREF="core.html#port">Port</A> +<LI><A HREF="mod_proxy.html#proxyblock">ProxyBlock</A> +<LI><A HREF="mod_proxy.html#proxypass">ProxyPass</A> +<LI><A HREF="mod_proxy.html#proxypassreverse">ProxyPassReverse</A> +<LI><A HREF="mod_proxy.html#proxyreceivebuffersize">ProxyReceiveBufferSize</A> +<LI><A HREF="mod_proxy.html#proxyremote">ProxyRemote</A> +<LI><A HREF="mod_proxy.html#proxyrequests">ProxyRequests</A> +<LI><A HREF="mod_proxy.html#proxyvia">ProxyVia</A> +<LI><A HREF="mod_autoindex.html#readmename">ReadmeName</A> +<LI><A HREF="mod_alias.html#redirect">Redirect</A> +<LI><A HREF="mod_alias.html#redirectmatch">RedirectMatch</A> +<LI><A HREF="mod_alias.html#redirectperm">RedirectPermanent</A> +<LI><A HREF="mod_alias.html#redirecttemp">RedirectTemp</A> +<LI><A HREF="mod_log_referer.html#refererignore">RefererIgnore</A> +<LI><A HREF="mod_log_referer.html#refererlog">RefererLog</A> +<LI><A HREF="core.html#require">require</A> +<LI><A HREF="core.html#resourceconfig">ResourceConfig</A> +<LI><A HREF="mod_rewrite.html#RewriteBase">RewriteBase</A> +<LI><A HREF="mod_rewrite.html#RewriteCond">RewriteCond</A> +<LI><A HREF="mod_rewrite.html#RewriteEngine">RewriteEngine</A> +<LI><A HREF="mod_rewrite.html#RewriteLock">RewriteLock</A> +<LI><A HREF="mod_rewrite.html#RewriteLog">RewriteLog</A> +<LI><A HREF="mod_rewrite.html#RewriteLogLevel">RewriteLogLevel</A> +<LI><A HREF="mod_rewrite.html#RewriteMap">RewriteMap</A> +<LI><A HREF="mod_rewrite.html#RewriteOptions">RewriteOptions</A> +<LI><A HREF="mod_rewrite.html#RewriteRule">RewriteRule</A> +<LI><A HREF="core.html#rlimitcpu">RLimitCPU</A> +<LI><A HREF="core.html#rlimitmem">RLimitMEM</A> +<LI><A HREF="core.html#rlimitnproc">RLimitNPROC</A> +<LI><A HREF="core.html#satisfy">Satisfy</A> +<LI><A HREF="core.html#scoreboardfile">ScoreBoardFile</A> +<LI><A HREF="mod_actions.html#script">Script</A> +<LI><A HREF="mod_alias.html#scriptalias">ScriptAlias</A> +<LI><A HREF="mod_alias.html#scriptaliasmatch">ScriptAliasMatch</A> +<LI><A HREF="mod_cgi.html#scriptlog">ScriptLog</A> +<LI><A HREF="mod_cgi.html#scriptlogbuffer">ScriptLogBuffer</A> +<LI><A HREF="mod_cgi.html#scriptloglength">ScriptLogLength</A> +<LI><A HREF="core.html#sendbuffersize">SendBufferSize</A> +<LI><A HREF="core.html#serveradmin">ServerAdmin</A> +<LI><A HREF="core.html#serveralias">ServerAlias</A> +<LI><A HREF="core.html#servername">ServerName</A> +<LI><A HREF="core.html#serverpath">ServerPath</A> +<LI><A HREF="core.html#serverroot">ServerRoot</A> +<LI><A HREF="core.html#serversignature">ServerSignature</A> +<LI><A HREF="core.html#servertokens">ServerTokens</A> +<LI><A HREF="core.html#servertype">ServerType</A> +<LI><A HREF="mod_env.html#setenv">SetEnv</A> +<LI><A HREF="mod_setenvif.html#setenvif">SetEnvIf</A> +<LI><A HREF="mod_setenvif.html#SetEnvIfNoCase">SetEnvIfNoCase</A> +<LI><A HREF="mod_mime.html#sethandler">SetHandler</A> +<LI><A HREF="core.html#startservers">StartServers</A> +<LI><A HREF="core.html#threadsperchild">ThreadsPerChild</A> +<LI><A HREF="core.html#timeout">TimeOut</A> +<LI><A HREF="mod_log_config.html#transferlog">TransferLog</A> +<LI><A HREF="mod_mime.html#typesconfig">TypesConfig</A> +<LI><A HREF="mod_env.html#unsetenv">UnsetEnv</A> +<LI><A HREF="core.html#usecanonicalname">UseCanonicalName</A> +<LI><A HREF="core.html#user">User</A> +<LI><A HREF="mod_userdir.html#userdir">UserDir</A> +<LI><A HREF="core.html#virtualhost"><VirtualHost></A> +<LI><A HREF="mod_include.html#xbithack">XBitHack</A> +</UL> <HR> + <H3 ALIGN="CENTER"> - Apache HTTP Server Version 1.2 + Apache HTTP Server Version 1.3 </H3> <A HREF="./"><IMG SRC="../images/index.gif" ALT="Index"></A> diff --git a/usr.sbin/httpd/htdocs/manual/mod/mod_actions.html b/usr.sbin/httpd/htdocs/manual/mod/mod_actions.html index 686760abf26..816a186ed2a 100644 --- a/usr.sbin/httpd/htdocs/manual/mod/mod_actions.html +++ b/usr.sbin/httpd/htdocs/manual/mod/mod_actions.html @@ -15,79 +15,122 @@ <DIV ALIGN="CENTER"> <IMG SRC="../images/sub.gif" ALT="[APACHE DOCUMENTATION]"> <H3> - Apache HTTP Server Version 1.2 + Apache HTTP Server Version 1.3 </H3> </DIV> -<H1 ALIGN="CENTER">Module mod_actions</h1> - -This module is contained in the <code>mod_actions.c</code> file, and +<H1 ALIGN="CENTER">Module mod_actions</H1> +<P> +This module is contained in the <CODE>mod_actions.c</CODE> 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. - -<h2>Summary</h2> - +</P> +<H2>Summary</H2> +<P> 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. +</P> +<H2>Directives</H2> +<UL> +<LI><A HREF="#action">Action</A> +<LI><A HREF="#script">Script</A> +</UL> -<h2>Directives</h2> -<ul> -<li><A HREF="#action">Action</A> -<li><A HREF="#script">Script</A> -</ul> - -<hr> +<HR> -<A name="action"><h2>Action</h2></A> -<strong>Syntax:</strong> Action <em>mime-type cgi-script</em><br> -<strong>Context:</strong> server config, virtual host, directory, .htaccess<br> -<strong>Override:</strong> FileInfo<br> -<strong>Status:</strong> Base<br> -<strong>Module:</strong> mod_actions<br> -<strong>Compatibility:</strong> Action is only available in Apache 1.1 -and later<p> +<H2><A NAME="action">Action directive</A></H2> +<P> +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> Action <EM>action-type cgi-script</EM><BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config, virtual host, directory, + .htaccess<BR> +<A + HREF="directive-dict.html#Override" + REL="Help" +><STRONG>Override:</STRONG></A> FileInfo<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Base<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_actions<BR> +<A + HREF="directive-dict.html#Compatibility" + REL="Help" +><STRONG>Compatibility:</STRONG></A> Action is only available in Apache 1.1 +and later +</P> +<P> +This directive adds an action, which will activate <EM>cgi-script</EM> when +<EM>action-type</EM> is triggered by the request. The <EM>action-type</EM> can +be either a <A HREF="../handler.html">handler</A> 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. +</P> +<HR> -This directive adds an action, which will activate <em>cgi-script</em> when -a file of content type <em>mime-type</em> is requested. It sends the +<H2><A NAME="script">Script directive</A></H2> +<P> +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> Script <EM>method cgi-script</EM><BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config, virtual host, directory<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Base<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_actions<BR> +<A + HREF="directive-dict.html#Compatibility" + REL="Help" +><STRONG>Compatibility:</STRONG></A> Script is only available in Apache 1.1 +and later +</P> + +<P> +This directive adds an action, which will activate <EM>cgi-script</EM> when +a file is requested using the method of <EM>method</EM>, which can be +one of <CODE>GET</CODE>, <CODE>POST</CODE>, <CODE>PUT</CODE> or +<CODE>DELETE</CODE>. It sends the URL and file path of the requested document using the standard CGI PATH_INFO and PATH_TRANSLATED environment variables. - -<hr> - -<A name="script"><h2>Script</h2></A> -<strong>Syntax:</strong> Script <em>method cgi-script</em><br> -<strong>Context:</strong> server config, virtual host, directory<br> -<strong>Status:</strong> Base<br> -<strong>Module:</strong> mod_actions<br> -<strong>Compatibility:</strong> Script is only available in Apache 1.1 -and later<p> - -<p>This directive adds an action, which will activate <em>cgi-script</em> when -a file is requested using the method of <em>method</em>, which can be -one of <code>GET</code>, <code>POST</code>, <code>PUT</code> or -<code>DELETE</code>. It sends the -URL and file path of the requested document using the standard -CGI PATH_INFO and PATH_TRANSLATED environment variables. - -<p>Note that the Script command defines default actions only. If a CGI +</P> +<P> +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 <code>GET</code> will only be called if there are -query arguments present (e.g. foo.html?hi). Otherwise, the request +the requested method internally, it will do so. Also note that Script +with a method of <CODE>GET</CODE> will only be called if there are +query arguments present (<EM>e.g.</EM>, foo.html?hi). Otherwise, the request will proceed normally. - -<p>Examples: -<pre> - Script GET /cgi-bin/search #e.g. for <ISINDEX>-style searching +</P> +<P> +Examples: +</P> +<PRE> + Script GET /cgi-bin/search #<EM>e.g.</EM> for <ISINDEX>-style searching Script PUT /~bob/put.cgi - -</pre> +</PRE> <HR> + <H3 ALIGN="CENTER"> - Apache HTTP Server Version 1.2 + Apache HTTP Server Version 1.3 </H3> <A HREF="./"><IMG SRC="../images/index.gif" ALT="Index"></A> @@ -95,4 +138,3 @@ will proceed normally. </BODY> </HTML> - diff --git a/usr.sbin/httpd/htdocs/manual/mod/mod_alias.html b/usr.sbin/httpd/htdocs/manual/mod/mod_alias.html index 247cdc35ade..affa6d3cc9f 100644 --- a/usr.sbin/httpd/htdocs/manual/mod/mod_alias.html +++ b/usr.sbin/httpd/htdocs/manual/mod/mod_alias.html @@ -15,140 +15,400 @@ <DIV ALIGN="CENTER"> <IMG SRC="../images/sub.gif" ALT="[APACHE DOCUMENTATION]"> <H3> - Apache HTTP Server Version 1.2 + Apache HTTP Server Version 1.3 </H3> </DIV> -<H1 ALIGN="CENTER">Module mod_alias</h1> - -This module is contained in the <code>mod_alias.c</code> file, and +<H1 ALIGN="CENTER">Module mod_alias</H1> +<P> +This module is contained in the <CODE>mod_alias.c</CODE> 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. +</P> - -<menu> -<li><A HREF="#alias">Alias</A> -<li><A HREF="#redirect">Redirect</A> -<li><A HREF="#redirecttemp">RedirectTemp</A> -<li><A HREF="#redirectperm">RedirectPermanent</A> -<li><A HREF="#scriptalias">ScriptAlias</A> -</menu> -<hr> +<H2>Directives</H2> +<UL> +<LI><A HREF="#alias">Alias</A> +<LI><A HREF="#aliasmatch">AliasMatch</A> +<LI><A HREF="#redirect">Redirect</A> +<LI><A HREF="#redirectmatch">RedirectMatch</A> +<LI><A HREF="#redirecttemp">RedirectTemp</A> +<LI><A HREF="#redirectperm">RedirectPermanent</A> +<LI><A HREF="#scriptalias">ScriptAlias</A> +<LI><A HREF="#scriptaliasmatch">ScriptAliasMatch</A> +</UL> +<HR> -<A name="alias"><h2>Alias</h2></A> +<H2><A NAME="alias">Alias directive</A></H2> +<P> <!--%plaintext <?INDEX {\tt Alias} directive> --> -<strong>Syntax:</strong> Alias <em>url-path directory-filename</em><br> -<Strong>Context:</strong> server config, virtual host<br> -<strong>Status:</strong> Base<br> -<strong>Module:</strong> mod_alias<br> - +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> Alias <EM>url-path directory-filename</EM><BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config, virtual host<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Base<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_alias +</P> +<P> The Alias directive allows documents to be stored in the local filesystem other than under the <A HREF="core.html#documentroot">DocumentRoot</A>. -URLs with a (%-decoded) path beginning with <em>url-path</em> will be -mapped to local files beginning with <em>directory-filename</em>. +URLs with a (%-decoded) path beginning with <EM>url-path</EM> will be +mapped to local files beginning with <EM>directory-filename</EM>. +<P> Example: -<blockquote><code>Alias /image /ftp/pub/image</code></blockquote> +</P> +<BLOCKQUOTE><CODE>Alias /image /ftp/pub/image</CODE></BLOCKQUOTE> +<P> A request for http://myserver/image/foo.gif would cause the server to -return the file /ftp/pub/image/foo.gif.<p> - -Note that if you include a trailing / on the <em>url-path</em> then the +return the file /ftp/pub/image/foo.gif. +</P> +<P> +Note that if you include a trailing / on the <EM>url-path</EM> then the server will require a trailing / in order to expand the alias. That is, -if you use <code>Alias /icons/ /usr/local/etc/httpd/icons/</code> then -the url <code>/icons</code> will not be aliased.<p> +if you use <CODE>Alias /icons/ /usr/local/apache/icons/</CODE> then +the url <CODE>/icons</CODE> will not be aliased. +</P> +<P> +Note that you may need to specify additional +<A HREF="core.html#directory"><CODE><Directory></CODE></A> sections +which cover the <EM>destination</EM> of aliases. Aliasing occurs +before <CODE><Directory></CODE> sections are checked, so only +the destination of aliases are affected. (Note however +<A HREF="core.html#location"><CODE><Location></CODE></A> +sections are run through once before aliases are performed, so they +will apply.) +<P> +See also <A HREF="#scriptalias">ScriptAlias</A>. +</P> +<HR> -See also <A HREF="#scriptalias">ScriptAlias</A>.<p><hr> +<H2><A NAME="aliasmatch">AliasMatch</A></H2> +<P> +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> AliasMatch <EM>regex directory-filename</EM><BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config, virtual host<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Base<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_alias<BR> +<A + HREF="directive-dict.html#Compatibility" + REL="Help" +><STRONG>Compatibility:</STRONG></A> Available in Apache 1.3 and later +</P> -<A name="redirect"><h2>Redirect</h2></A> -<!--%plaintext <?INDEX {\tt Redirect} directive> --> -<strong>Syntax:</strong> Redirect [ <em>status</em> ] <em>url-path url</em><br> -<Strong>Context:</strong> server config, virtual host, directory, .htaccess<br> -<strong>Status:</strong> Base<br> -<strong>Module:</strong> mod_alias<br> -<strong>Compatibility:</strong> The directory and .htaccess context's -are only available in versions 1.1 and later. The <em>status</em> argument is only available in Apache 1.2 or later.<p> +<P>This directive is equivalent to <A HREF="#alias">Alias</A>, 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 <CODE>/icons</CODE> directory, one might use: +<PRE> + AliasMatch ^/icons(.*) /usr/local/apache/icons$1 +</PRE> +</P> +<HR> + +<H2><A NAME="redirect">Redirect directive</A></H2> +<P> +<!--%plaintext <?INDEX {\tt Redirect} directive> --> +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> Redirect [ <EM>status</EM> ] + <EM>url-path url</EM><BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config, virtual host, directory, + .htaccess<BR> +<A + HREF="directive-dict.html#Override" + REL="Help" +><STRONG>Override:</STRONG></A> FileInfo<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Base<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_alias<BR> +<A + HREF="directive-dict.html#Compatibility" + REL="Help" +><STRONG>Compatibility:</STRONG></A> The directory and .htaccess context's +are only available in versions 1.1 and later. The <EM>status</EM> +argument is only available in Apache 1.2 or later. +</P> +<P> 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. -<em>Url-path</em> a (%-decoded) path; any requests for documents beginning with +<EM>Url-path</EM> a (%-decoded) path; any requests for documents beginning with this path will be returned a redirect error to a new (%-encoded) url -beginning with <em>url</em>. Example: -<blockquote><code>Redirect /service -http://foo2.bar.com/service</code></blockquote> +beginning with <EM>url</EM>. +</P> +<P> +Example: +</P> +<BLOCKQUOTE><CODE>Redirect /service +http://foo2.bar.com/service</CODE></BLOCKQUOTE> +<P> If the client requests http://myserver/service/foo.txt, it will be told to -access http://foo2.bar.com/service/foo.txt instead.<p> - -Note: Redirect directives take precedence over Alias and ScriptAlias +access http://foo2.bar.com/service/foo.txt instead. +</P> +<P> +<STRONG>Note:</STRONG> Redirect directives take precedence over Alias +and ScriptAlias directives, irrespective of their ordering in the configuration file. Also, -<em>Url-path</em> must be an absolute path, not a relative path, even when used with -.htaccess files or inside of <Directory> sections.<p> - -If no <em>status</em> argument is given, the redirect will be -"temporary" (HTTP status 302). This indicates to the client that the -resources is has moved temporarily. The <em>status</em> +<EM>Url-path</EM> must be an absolute path, not a relative path, even +when used with .htaccess files or inside of <Directory> sections. +</P> +<P> +If no <EM>status</EM> argument is given, the redirect will be +"temporary" (HTTP status 302). This indicates to the client that the +resources is has moved temporarily. The <EM>status</EM> argument can be used to return other HTTP status codes: -<dl> -<dt>permanent<dd>Returns a permanent redirect status (301) indicating that +<P> +<DL> +<DT>permanent +<DD>Returns a permanent redirect status (301) indicating that the resource has moved permanently. -<dt>temp<dd>Returns a temporary redirect status (302). This is the +<DT>temp +<DD>Returns a temporary redirect status (302). This is the default. -<dt>seeother<dd>Returns a "See Other" status (303) indicating that +<DT>seeother +<DD>Returns a "See Other" status (303) indicating that the resource has been replaced. -<dt>gone<dd>Returns a "Gone" status (410) indicating that the resource -has been permanently removed. When this status is used the <em>url</em> +<DT>gone +<DD>Returns a "Gone" status (410) indicating that the resource +has been permanently removed. When this status is used the <EM>url</EM> argument should be omitted. -</dl> - +</DL> +<P> Other status codes can be returned by giving the numeric status code -as the value of <em>status</em>. If the status is between 300 and 399, -the <em>url</em> argument must be present, otherwise it must be +as the value of <EM>status</EM>. If the status is between 300 and 399, +the <EM>url</EM> argument must be present, otherwise it must be omitted. Note that the status must be known to the Apache code (see -the function <code>send_error_response</code> in http_protocol.c). +the function <CODE>send_error_response</CODE> in http_protocol.c). +</P> +<HR> -<A name="redirecttemp"><h2>RedirectTemp</h2></A> -<!--%plaintext <?INDEX {\tt Redirect} directive> --> -<strong>Syntax:</strong> RedirectTemp <em>url-path url</em><br> -<Strong>Context:</strong> server config, virtual host, directory, .htaccess<br> -<strong>Status:</strong> Base<br> -<strong>Module:</strong> mod_alias<br> -<strong>Compatibility:</strong> This directive is only available in 1.2<P> +<H2><A NAME="redirectmatch">RedirectMatch</A></H2> +<P> +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> + RedirectMatch [<EM>status</EM>] <EM>regex url</EM> +<BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config, virtual host<BR> +<A + HREF="directive-dict.html#Override" + REL="Help" +><STRONG>Override:</STRONG></A> FileInfo<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Base<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_alias<BR> +<A + HREF="directive-dict.html#Compatibility" + REL="Help" +><STRONG>Compatibility:</STRONG></A> Available in Apache 1.3 and later +</P> -This directive makes the client know that the Redirect is only -temporary. (Status 302). Exactly equivalent to <code>Redirect temporary </code><P> +<P>This directive is equivalent to <A HREF="#alias">Redirect</A>, 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: +<PRE> + RedirectMatch (.*)\.gif$ http://www.anotherserver.com$1.jpg +</PRE> +</P> + +<HR> -<A name="redirectperm"><h2>RedirectPermanent</h2></A> +<H2><A NAME="redirecttemp">RedirectTemp directive</A></H2> +<P> <!--%plaintext <?INDEX {\tt Redirect} directive> --> -<strong>Syntax:</strong> RedirectPermanent <em>url-path url</em><br> -<Strong>Context:</strong> server config, virtual host, directory, .htaccess<br> -<strong>Status:</strong> Base<br> -<strong>Module:</strong> mod_alias<br> -<strong>Compatibility:</strong> This directive is only available in 1.2<P> +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> RedirectTemp <EM>url-path url</EM><BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config, virtual host, directory, + .htaccess<BR> +<A + HREF="directive-dict.html#Override" + REL="Help" +><STRONG>Override:</STRONG></A> FileInfo<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Base<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_alias<BR> +<A + HREF="directive-dict.html#Compatibility" + REL="Help" +><STRONG>Compatibility:</STRONG></A> This directive is only available in 1.2 +</P> +<P> +This directive makes the client know that the Redirect is only +temporary (status 302). Exactly equivalent to <CODE>Redirect +temporary</CODE>. +</P> +<HR> -This directive makes the client know that the Redirect is permanent. -(Status 301). Exactly equivalent to <code>Redirect permanent</code><P> +<H2><A NAME="redirectperm">RedirectPermanent directive</A></H2> +<P> +<!--%plaintext <?INDEX {\tt Redirect} directive> --> +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> RedirectPermanent <EM>url-path url</EM><BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config, virtual host, directory, + .htaccess<BR> +<A + HREF="directive-dict.html#Override" + REL="Help" +><STRONG>Override:</STRONG></A> FileInfo<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Base<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_alias<BR> +<A + HREF="directive-dict.html#Compatibility" + REL="Help" +><STRONG>Compatibility:</STRONG></A> This directive is only available in 1.2 +</P> +<P> +This directive makes the client know that the Redirect is permanent +(status 301). Exactly equivalent to <CODE>Redirect permanent</CODE>. +</P> +<HR> -<hr> -<A name="scriptalias"><h2>ScriptAlias</h2></A> +<H2><A NAME="scriptalias">ScriptAlias directive</A></H2> +<P> <!--%plaintext <?INDEX {\tt ScriptAlias} directive> --> -<strong>Syntax:</strong> ScriptAlias <em>url-path directory-filename</em><br> -<Strong>Context:</strong> server config, virtual host<br> -<strong>Status:</strong> Base<br> -<strong>Module:</strong> mod_alias<br> - +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> ScriptAlias <EM>url-path directory-filename</EM> +<BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config, virtual host<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Base<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_alias +</P> +<P> The ScriptAlias directive has the same behavior as the <A HREF="#alias">Alias</A> directive, except that in addition it marks the target directory as containing CGI scripts. -URLs with a (%-decoded) path beginning with <em>url-path</em> will be -mapped to scripts beginning with <em>directory-filename</em>. +URLs with a (%-decoded) path beginning with <EM>url-path</EM> will be +mapped to scripts beginning with <EM>directory-filename</EM>. +<P> Example: -<blockquote><code>ScriptAlias /cgi-bin/ /web/cgi-bin/</code></blockquote> +</P> +<BLOCKQUOTE><CODE>ScriptAlias /cgi-bin/ /web/cgi-bin/</CODE></BLOCKQUOTE> +<P> A request for http://myserver/cgi-bin/foo would cause the server to -run the script /web/cgi-bin/foo.<p> +run the script /web/cgi-bin/foo. +</P> <HR> + +<H2><A NAME="scriptaliasmatch">ScriptAliasMatch</A></H2> +<P> +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> ScriptAliasMatch + <EM>regex directory-filename</EM><BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config, virtual host<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Base<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_alias<BR> +<A + HREF="directive-dict.html#Compatibility" + REL="Help" +><STRONG>Compatibility:</STRONG></A> Available in Apache 1.3 and later +</P> + +<P>This directive is equivalent to <A HREF="#scriptalias">ScriptAlias</A>, 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 <CODE>/cgi-bin</CODE>, one might use: +<PRE> + ScriptAliasMatch ^/cgi-bin(.*) /usr/local/apache/cgi-bin$1 +</PRE> +</P> + +<HR> + <H3 ALIGN="CENTER"> - Apache HTTP Server Version 1.2 + Apache HTTP Server Version 1.3 </H3> <A HREF="./"><IMG SRC="../images/index.gif" ALT="Index"></A> @@ -156,4 +416,3 @@ run the script /web/cgi-bin/foo.<p> </BODY> </HTML> - diff --git a/usr.sbin/httpd/htdocs/manual/mod/mod_autoindex.html b/usr.sbin/httpd/htdocs/manual/mod/mod_autoindex.html index f4091df25da..7fa844647b6 100644 --- a/usr.sbin/httpd/htdocs/manual/mod/mod_autoindex.html +++ b/usr.sbin/httpd/htdocs/manual/mod/mod_autoindex.html @@ -80,6 +80,7 @@ order) even though they both are shown as "1K". <LI><A HREF="#headername">HeaderName</A> <LI><A HREF="#indexignore">IndexIgnore</A> <LI><A HREF="#indexoptions">IndexOptions</A> +<LI><A HREF="#indexorderdefault">IndexOrderDefault</A> <LI><A HREF="#readmename">ReadmeName</A> </MENU> <HR> @@ -213,7 +214,15 @@ extension, partial filename, wild-card expression or full filename for files to describe. <EM>String</EM> is enclosed in double quotes (<CODE>"</CODE>). Example: <BLOCKQUOTE><CODE>AddDescription "The planet Mars" /web/pics/mars.gif -</CODE></BLOCKQUOTE><P><HR> +</CODE></BLOCKQUOTE> +<P> +The description field is 23 bytes wide. 7 more bytes may be +added if the directory is covered by an +<CODE>IndexOptions SuppressSize</CODE>, and 19 bytes may be +added if <CODE>IndexOptions SuppressLastModified</CODE> is +in effect. The widest this column can be is therefore 49 bytes. +</P> +<HR> <H2><A NAME="addicon">AddIcon</A></H2> <!--%plaintext <?INDEX {\tt AddIcon} directive> --> @@ -578,6 +587,7 @@ listing by the values in that column. <!--%plaintext <?INDEX {\tt SuppressDescription} index option> --> This will suppress the file description in fancy indexing listings. <DT><A NAME="indexoptions:suppresshtmlpreamble">SuppressHTMLPreamble</A> + (<EM>Apache 1.3 and later</EM>) <DD> <!--%plaintext <?INDEX {\tt SuppressHTMLPreamble} index option> --> If the directory actually contains a file specified by the @@ -665,6 +675,66 @@ keywords without either '+' or '-' prefixes. </P> </DD> </DL> + +<HR> + +<H2><A NAME="indexorderdefault">IndexOrderDefault</A></H2> +<!--%plaintext <?INDEX {\tt IndexOrderDefault} directive> --> +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> IndexOrderDefault + <EM>Ascending|Descending</EM> <EM>Name|Date|Size|Description</EM> +<BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config, virtual host, directory, + .htaccess +<BR> +<A + HREF="directive-dict.html#Override" + REL="Help" +><STRONG>Override:</STRONG></A> Indexes +<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Base +<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_autoindex +<BR> +<A + HREF="directive-dict.html#Compatibility" + REL="Help" +><STRONG>Compatibility:</STRONG></A> IndexOrderDefault is only available in +Apache 1.3.4 and later. + +<P> +The <SAMP>IndexOrderDefault</SAMP> directive is used in combination with +the <A HREF="#indexoptions:fancyindexing"><SAMP>FancyIndexing</SAMP></A> +index option. By default, fancyindexed directory listings are displayed in ascending order by filename; the <SAMP>IndexOrderDefault</SAMP> allows +you to change this initial display order. +</P> +<P> +<SAMP>IndexOrderDefault</SAMP> takes two arguments. The first must be either +<SAMP>Ascending</SAMP> or <SAMP>Descending</SAMP>, indicating the direction +of the sort. The second argument must be one of the keywords +<SAMP>Name</SAMP>, <SAMP>Date</SAMP>, <SAMP>Size</SAMP>, or +<SAMP>Description</SAMP>, and identifies the primary key. The secondary +key is <EM>always</EM> the ascending filename. +</P> +<P> +You can force a directory listing to only be displayed in a particular +order by combining this directive with the +<A HREF="#indexoptions:suppresscolumnsorting" +><SAMP>SuppressColumnSorting</SAMP></A> index option; this will prevent +the client from requesting the directory listing in a different order. +</P> + <HR> <H2><A NAME="readmename">ReadmeName</A></H2> diff --git a/usr.sbin/httpd/htdocs/manual/mod/mod_cgi.html b/usr.sbin/httpd/htdocs/manual/mod/mod_cgi.html index d1cfa745a5b..dd6e29277e5 100644 --- a/usr.sbin/httpd/htdocs/manual/mod/mod_cgi.html +++ b/usr.sbin/httpd/htdocs/manual/mod/mod_cgi.html @@ -1,8 +1,8 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> -<html> -<head> -<title>Apache module mod_cgi</title> -</head> +<HTML> +<HEAD> +<TITLE>Apache module mod_cgi</TITLE> +</HEAD> <!-- Background white, links blue (unvisited), navy (visited), red (active) --> <BODY @@ -15,52 +15,58 @@ <DIV ALIGN="CENTER"> <IMG SRC="../images/sub.gif" ALT="[APACHE DOCUMENTATION]"> <H3> - Apache HTTP Server Version 1.2 + Apache HTTP Server Version 1.3 </H3> </DIV> -<h1 ALIGN="CENTER">Module mod_cgi</h1> +<H1 ALIGN="CENTER">Module mod_cgi</H1> -This module is contained in the <code>mod_cgi.c</code> file, and +This module is contained in the <CODE>mod_cgi.c</CODE> file, and is compiled in by default. It provides for execution of CGI scripts. -Any file with mime type <code>application/x-httpd-cgi</code> will be +Any file with mime type <CODE>application/x-httpd-cgi</CODE> will be processed by this module. <!--%plaintext <?INDEX {\tt application/x-httpd-cgi} mime type> --> <!--%plaintext <?INDEX CGI scripts> --> -<h2>Summary</h2> -Any file that has the mime type <code>application/x-httpd-cgi</code> -or handler <code>cgi-script</code> (Apache 1.1 or later) +<H2>Summary</H2> +Any file that has the mime type <CODE>application/x-httpd-cgi</CODE> +or handler <CODE>cgi-script</CODE> (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 ending in an extension defined by the +having a name containing an extension defined by the <A HREF="mod_mime.html#addtype">AddType</A> directive, or by being in -a <A HREF="mod_alias.html#scriptalias">ScriptAlias</A> directory. <p> +a <A HREF="mod_alias.html#scriptalias">ScriptAlias</A> directory. <P> When the server invokes a CGI script, it will add a variable called -<code>DOCUMENT_ROOT</code> to the environment. This variable will contain the +<CODE>DOCUMENT_ROOT</CODE> to the environment. This variable will contain the value of the <A HREF="core.html#documentroot">DocumentRoot</A> configuration variable. -<h2>CGI Environment variables</h2> -The server will set the CGI environment variables as described in the CGI -specification, with the following provisions: -<dl> -<dt>REMOTE_HOST -<dd>This will only be set if the server has not been compiled with -<code>MINIMAL_DNS</code>. -<dt>REMOTE_IDENT -<dd>This will only be set if -<A HREF="core.html#identitycheck">IdentityCheck</A> is set to <code>on</code>. -<dt>REMOTE_USER -<dd>This will only be set if the CGI script is subject to authentication. -</dl> +<H2>CGI Environment variables</H2> +The server will set the CGI environment variables as described in the +<A HREF="http://hoohoo.ncsa.uiuc.edu/cgi/">CGI specification</A>, with the +following provisions: +<DL> +<DT>REMOTE_HOST +<DD>This will only be set if <A HREF="core.html#hostnamelookups"><CODE>HostnameLookups</CODE></A> +is set to <CODE>on</CODE> (it is off by default), and if a reverse DNS +lookup of the accessing host's address indeed finds a host name. +<DT>REMOTE_IDENT +<DD>This will only be set if +<A HREF="core.html#identitycheck">IdentityCheck</A> is set to <CODE>on</CODE> +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. +<DT>REMOTE_USER +<DD>This will only be set if the CGI script is subject to authentication. +</DL> <P> -<hr> +<HR> -<h2><a name="cgi_debug">CGI Debugging</a></h2> +<H2><A NAME="cgi_debug">CGI Debugging</A></H2> Debugging CGI scripts has traditionally been difficult, mainly because it has @@ -71,62 +77,74 @@ which are failing to run properly. These directives, included in Apache 1.2 and later, provide more detailed logging of errors when they occur. -<hr> +<HR> -<h2>CGI Logfile Format</h2> +<H2>CGI Logfile Format</H2> 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: -<pre> - %% [<i>time</i>] <i>request-line</i> - %% <i>HTTP-status</i> <i>CGI-script-filename</i> -</pre> +<PRE> + %% [<EM>time</EM>] <EM>request-line</EM> + %% <EM>HTTP-status</EM> <EM>CGI-script-filename</EM> +</PRE> If the error is that CGI script cannot be run, the log file will contain an extra two lines: -<pre> +<PRE> %%error - <i>error-message</i> -</pre> + <EM>error-message</EM> +</PRE> 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: -<pre> +<PRE> %request - <i>All HTTP request headers received</i> - <i>POST or PUT entity (if any)</i> + <EM>All HTTP request headers received</EM> + <EM>POST or PUT entity (if any)</EM> %response - <i>All headers output by the CGI script</i> + <EM>All headers output by the CGI script</EM> %stdout - <i>CGI standard output</i> + <EM>CGI standard output</EM> %stderr - <i>CGI standard error</i> -</pre> + <EM>CGI standard error</EM> +</PRE> (The %stdout and %stderr parts may be missing if the script did not output anything on standard output or standard error). -<hr> - -<h2>Directives</h2> - -<h3><a name="scriptlog">ScriptLog</a></h3> +<HR> -<b>Syntax:</b> ScriptLog <i>filename</i><br> -<b>Default:</b> none<br> -<b>Context:</b> resource config<br> -<b>Status:</b> mod_cgi -<p> +<H2>Directives</H2> + +<H3><A NAME="scriptlog">ScriptLog</A></H3> + +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> ScriptLog <EM>filename</EM><BR> +<A + HREF="directive-dict.html#Default" + REL="Help" +><STRONG>Default:</STRONG></A> none<BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> mod_cgi +<P> -The <tt>ScriptLog</tt> directive sets the CGI script error logfile. +The <TT>ScriptLog</TT> 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. @@ -140,34 +158,58 @@ script log in your main logs directory, do <STRONG>NOT</STRONG> change the directory permissions to make it writable by the user the child processes run as.</P> -<p>Note that script logging is meant to be a debugging feature when +<P>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.</p> - -<h3><a name="scriptloglength">ScriptLogLength</a></h3> - -<b>Syntax:</b> ScriptLogLength <i>size</i><br> -<b>Default:</b> 10385760<br> -<b>Context:</b> resource config<br> -<b>Status:</b> mod_cgi -<p> +it was designed.</P> + +<H3><A NAME="scriptloglength">ScriptLogLength</A></H3> + +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> ScriptLogLength <EM>size</EM><BR> +<A + HREF="directive-dict.html#Default" + REL="Help" +><STRONG>Default:</STRONG></A> 10385760<BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> mod_cgi +<P> -<tt>ScriptLogLength</tt> can be used to limit the size of the CGI +<TT>ScriptLogLength</TT> 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. -<h3><a name="scriptlogbuffer">ScriptLogBuffer</a></h3> - -<b>Syntax:</b> ScriptLogBuffer <i>size</i><br> -<b>Default:</b> 1024<br> -<b>Context:</b> resource config<br> -<b>Status:</b> mod_cgi -<p> +<H3><A NAME="scriptlogbuffer">ScriptLogBuffer</A></H3> + +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> ScriptLogBuffer <EM>size</EM><BR> +<A + HREF="directive-dict.html#Default" + REL="Help" +><STRONG>Default:</STRONG></A> 1024<BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> mod_cgi +<P> 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 @@ -175,8 +217,9 @@ bodies are being received. By default, up to 1024 bytes are logged, but this can be changed with this directive. <HR> + <H3 ALIGN="CENTER"> - Apache HTTP Server Version 1.2 + Apache HTTP Server Version 1.3 </H3> <A HREF="./"><IMG SRC="../images/index.gif" ALT="Index"></A> diff --git a/usr.sbin/httpd/htdocs/manual/mod/mod_env.html b/usr.sbin/httpd/htdocs/manual/mod/mod_env.html index f3b602fdd72..0e1faea4d14 100644 --- a/usr.sbin/httpd/htdocs/manual/mod/mod_env.html +++ b/usr.sbin/httpd/htdocs/manual/mod/mod_env.html @@ -15,86 +15,132 @@ <DIV ALIGN="CENTER"> <IMG SRC="../images/sub.gif" ALT="[APACHE DOCUMENTATION]"> <H3> - Apache HTTP Server Version 1.2 + Apache HTTP Server Version 1.3 </H3> </DIV> -<H1 ALIGN="CENTER">Module mod_env</H1> +<H1 ALIGN="CENTER">Apache module mod_env</H1> -This module is contained in the <code>mod_env.c</code> file, and -is not compiled in by default. It provides for +This module is contained in the <CODE>mod_env.c</CODE> 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. -<h2>Summary</h2> +<H2>Summary</H2> 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 - -<h2>Directives</h2> -<ul> -<li><A HREF="#passenv">PassEnv</A> -<li><A HREF="#setenv">SetEnv</A> -<li><A HREF="#unsetenv">UnsetEnv</A> -</ul> - -<hr> - -<h2><A name="passenv">PassEnv</A></h2> -<strong>Syntax:</strong> PassEnv <em>variable variable ...</em><br> -<strong>Context:</strong> server config, virtual host<br> -<strong>Status:</strong> Base<br> -<strong>Module:</strong> mod_env<br> -<strong>Compatibility:</strong> PassEnv is only available in -Apache 1.1 and later.<p> + +<H2>Directives</H2> +<UL> +<LI><A HREF="#passenv">PassEnv</A> +<LI><A HREF="#setenv">SetEnv</A> +<LI><A HREF="#unsetenv">UnsetEnv</A> +</UL> + +<HR> + +<H2><A NAME="passenv">PassEnv</A></H2> +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> PassEnv <EM>variable variable ...</EM><BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config, virtual host<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Base<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_env<BR> +<A + HREF="directive-dict.html#Compatibility" + REL="Help" +><STRONG>Compatibility:</STRONG></A> PassEnv is only available in +Apache 1.1 and later.<P> Specifies one or more environment variables to pass to CGI scripts from the server's own environment. Example: -<pre> +<PRE> PassEnv LD_LIBRARY_PATH -</pre> +</PRE> <HR> -<h2><A name="setenv">SetEnv</A></h2> -<strong>Syntax:</strong> SetEnv <em>variable value</em><br> -<strong>Context:</strong> server config, virtual host<br> -<strong>Status:</strong> Base<br> -<strong>Module:</strong> mod_env<br> -<strong>Compatibility:</strong> SetEnv is only available in -Apache 1.1 and later.<p> +<H2><A NAME="setenv">SetEnv</A></H2> +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> SetEnv <EM>variable value</EM><BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config, virtual host<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Base<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_env<BR> +<A + HREF="directive-dict.html#Compatibility" + REL="Help" +><STRONG>Compatibility:</STRONG></A> SetEnv is only available in +Apache 1.1 and later.<P> Sets an environment variable, which is then passed on to CGI scripts. Example: -<pre> +<PRE> SetEnv SPECIAL_PATH /foo/bin -</pre> +</PRE> -<hr> +<HR> -<h2><A name="unsetenv">UnsetEnv</A></h2> -<strong>Syntax:</strong> UnsetEnv <em>variable variable ...</em><br> -<strong>Context:</strong> server config, virtual host<br> -<strong>Status:</strong> Base<br> -<strong>Module:</strong> mod_env<br> -<strong>Compatibility:</strong> UnsetEnv is only available in -Apache 1.1 and later.<p> +<H2><A NAME="unsetenv">UnsetEnv</A></H2> +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> UnsetEnv <EM>variable variable ...</EM><BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config, virtual host<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Base<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_env<BR> +<A + HREF="directive-dict.html#Compatibility" + REL="Help" +><STRONG>Compatibility:</STRONG></A> UnsetEnv is only available in +Apache 1.1 and later.<P> Removes one or more environment variables from those passed on to CGI scripts. Example: -<pre> +<PRE> UnsetEnv LD_LIBRARY_PATH -</pre> +</PRE> -<p> +<P> <HR> + <H3 ALIGN="CENTER"> - Apache HTTP Server Version 1.2 + Apache HTTP Server Version 1.3 </H3> <A HREF="./"><IMG SRC="../images/index.gif" ALT="Index"></A> diff --git a/usr.sbin/httpd/htdocs/manual/mod/mod_mime.html b/usr.sbin/httpd/htdocs/manual/mod/mod_mime.html index aaf392a3e4a..1c02c8c3212 100644 --- a/usr.sbin/httpd/htdocs/manual/mod/mod_mime.html +++ b/usr.sbin/httpd/htdocs/manual/mod/mod_mime.html @@ -15,17 +15,17 @@ <DIV ALIGN="CENTER"> <IMG SRC="../images/sub.gif" ALT="[APACHE DOCUMENTATION]"> <H3> - Apache HTTP Server Version 1.2 + Apache HTTP Server Version 1.3 </H3> </DIV> -<H1 ALIGN="CENTER">Module mod_mime</h1> +<H1 ALIGN="CENTER">Module mod_mime</H1> -This module is contained in the <code>mod_mime.c</code> file, and is +This module is contained in the <CODE>mod_mime.c</CODE> file, and is compiled in by default. It provides for determining the types of files from the filename. -<h2>Summary</h2> +<H2>Summary</H2> This module is used to determine various bits of "meta information" about documents. This information relates to the content of the @@ -40,18 +40,24 @@ HREF="#addhandler">AddHandler</A>, <A HREF="#addlanguage">AddLanguage</A> and <A HREF="#addtype">AddType</A> are all used to map file extensions onto the meta-information for that file. Respectively they set the content-encoding, handler, -content-language and mime-type (content-type) of documents. The +content-language and MIME-type (content-type) of documents. The directive <A HREF="#typesconfig">TypesConfig</A> is used to specify a -file which also maps extensions onto mime types. The directives <A +file which also maps extensions onto MIME types. The directives <A HREF="#forcetype">ForceType</A> and <A HREF="#sethandler">SetHandler</A> are used to associated all the files -in a given location (e.g. a particular directory) onto a particular -mime type or handler. +in a given location (<EM>e.g.</EM>, a particular directory) onto a particular +MIME type or handler. <P> +Note that changing the type or encoding of a file does not change the +value of the <CODE>Last-Modified</CODE> header. Thus, previously cached +copies may still be used by a client or proxy, with the previous headers. + +<H2><A NAME="multipleext">Files with Multiple Extensions</A></H2> + Files can have more than one extension, and the order of the -extensions is normally irrelevant. For example, if the file +extensions is <EM>normally</EM> irrelevant. For example, if the file <CODE>welcome.html.fr</CODE> maps onto content type text/html and language French then the file <CODE>welcome.fr.html</CODE> will map onto exactly the same information. The only exception to this is if an @@ -61,182 +67,464 @@ 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 <CODE>welcome.fr.xxx.html</CODE> will be associated with content-type -text/html but <i>no</i> language. +text/html but <EM>no</EM> language. + +<P> + +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 <CODE>welcome.gif.html</CODE> will +be associated with the MIME-type "text/html". <P> -<h2> Directives</h2> -<ul> -<li><A HREF="#addencoding">AddEncoding</A> -<li><A HREF="#addhandler">AddHandler</A> -<li><A HREF="#addlanguage">AddLanguage</A> -<li><A HREF="#addtype">AddType</A> -<li><A HREF="#forcetype">ForceType</A> -<li><A HREF="#sethandler">SetHandler</A> -<li><A HREF="#typesconfig">TypesConfig</A> -</ul> -<hr> +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 <CODE>.imap</CODE> extension is mapped to +the handler "imap-file" (from mod_imap) and the <CODE>.html</CODE> +extension is mapped to the MIME-type "text/html", then the file +<CODE>world.imap.html</CODE> 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. + +<H2>Directives</H2> +<UL> +<LI><A HREF="#addencoding">AddEncoding</A> +<LI><A HREF="#addhandler">AddHandler</A> +<LI><A HREF="#addlanguage">AddLanguage</A> +<LI><A HREF="#addtype">AddType</A> +<LI><A HREF="#defaultlanguage">DefaultLanguage</A> +<LI><A HREF="#forcetype">ForceType</A> +<LI><A HREF="#removehandler">RemoveHandler</A> +<LI><A HREF="#sethandler">SetHandler</A> +<LI><A HREF="#typesconfig">TypesConfig</A> +</UL> +<HR> -<h2><A name="addencoding">AddEncoding</A></h2> +<H2><A NAME="addencoding">AddEncoding</A></H2> <!--%plaintext <?INDEX {\tt AddEncoding} directive> --> -<strong>Syntax:</strong> AddEncoding <em>mime-enc extension extension...</em><br> -<Strong>Context:</strong> server config, virtual host, directory, .htaccess<br> -<Strong>Override:</strong> FileInfo<br> -<strong>Status:</strong> Base<br> -<strong>Module:</strong> mod_mime<p> - -The AddEncoding directive adds to the list of filename extensions which -filenames may end in for the specified encoding type. <em>Mime-enc</em> -is the mime encoding to use for documents ending in <em>extension</em>. +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> AddEncoding <EM>MIME-enc extension extension...</EM><BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config, virtual host, directory, .htaccess<BR> +<A + HREF="directive-dict.html#Override" + REL="Help" +><STRONG>Override:</STRONG></A> FileInfo<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Base<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_mime<P> + +The AddEncoding directive maps the given filename extensions to the +specified encoding type. <EM>MIME-enc</EM> is the MIME encoding to use +for documents containing the <EM>extension</EM>. This mapping is added +to any already in force, overriding any mappings that already exist +for the same <EM>extension</EM>. + Example: -<blockquote><code> -AddEncoding x-gzip gz<br> -AddEncoding x-compress Z -</code></blockquote> - -This will cause files ending in .gz to be marked as encoded using the x-gzip -encoding, and .Z files to be marked as encoded with x-compress.<p><hr> - -<h2><a name="addhandler">AddHandler</a></h2> - -<strong>Syntax:</strong> AddHandler <em>handler-name extension extension...</em><br> -<strong>Context:</strong> server config, virtual host, directory, .htaccess<br> -<strong>Status:</strong> Base<br> -<strong>Module:</strong> mod_mime<br> -<strong>Compatibility:</strong> AddHandler is only available in Apache -1.1 and later<p> - -<p>AddHandler maps the filename extensions <em>extension</em> to the -<a href="../handler.html">handler</a> -<em>handler-name</em>. For example, to activate CGI scripts -with the file extension "<code>.cgi</code>", you might use: -<pre> +<BLOCKQUOTE><CODE> AddEncoding x-gzip gz<BR> AddEncoding x-compress Z +</CODE></BLOCKQUOTE> + +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.<P> + +Old clients expect <CODE>x-gzip</CODE> and <CODE>x-compress</CODE>, +however the standard dictates that they're equivalent to <CODE>gzip</CODE> +and <CODE>compress</CODE> respectively. Apache does content encoding +comparisons by ignoring any leading <CODE>x-</CODE>. When responding +with an encoding Apache will use whatever form (<EM>i.e.</EM>, <CODE>x-foo</CODE> +or <CODE>foo</CODE>) the client requested. If the client didn't +specifically request a particular form Apache will use the form given by +the <CODE>AddEncoding</CODE> directive. To make this long story short, +you should always use <CODE>x-gzip</CODE> and <CODE>x-compress</CODE> +for these two specific encodings. More recent encodings, such as +<CODE>deflate</CODE> should be specified without the <CODE>x-</CODE>. + +<P> + +<STRONG>See also</STRONG>: <A HREF="#multipleext">Files with +multiple extensions</A> + +<P><HR> + +<H2><A NAME="addhandler">AddHandler</A></H2> + +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> AddHandler <EM>handler-name extension extension...</EM><BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config, virtual host, directory, .htaccess<BR> +<A + HREF="directive-dict.html#Override" + REL="Help" +><STRONG>Override:</STRONG></A> FileInfo<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Base<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_mime<BR> +<A + HREF="directive-dict.html#Compatibility" + REL="Help" +><STRONG>Compatibility:</STRONG></A> AddHandler is only available in Apache +1.1 and later<P> + +<P>AddHandler maps the filename extensions <EM>extension</EM> to the +<A HREF="../handler.html">handler</A> <EM>handler-name</EM>. This +mapping is added to any already in force, overriding any mappings that +already exist for the same <EM>extension</EM>. + +For example, to activate CGI scripts +with the file extension "<CODE>.cgi</CODE>", you might use: +<PRE> AddHandler cgi-script cgi -</pre> +</PRE> + +<P>Once that has been put into your srm.conf or httpd.conf file, any +file containing the "<CODE>.cgi</CODE>" extension will be treated as a +CGI program.</P> + +<P> + +<STRONG>See also</STRONG>: <A HREF="#multipleext">Files with +multiple extensions</A> -<p>Once that has been put into your srm.conf or httpd.conf file, any -file ending with "<code>.cgi</code>" will be treated as a CGI -program.</p> <HR> -<h2><A name="addlanguage">AddLanguage</A></h2> +<H2><A NAME="addlanguage">AddLanguage</A></H2> <!--%plaintext <?INDEX {\tt AddLanguage} directive> --> -<strong>Syntax:</strong> AddLanguage <em>mime-lang extension extension...</em><br> -<Strong>Context:</strong> server config, virtual host, directory, .htaccess<br> -<Strong>Override:</strong> FileInfo<br> -<strong>Status:</strong> Base<br> -<strong>Module:</strong> mod_mime<p> - -The AddLanguage directive adds to the list of filename extensions which -filenames may end in for the specified content language. <em>Mime-lang</em> -is the mime language of files with names ending <em>extension</em>, -after any content encoding extensions have been removed. Example: -<blockquote><code> -AddEncoding x-compress Z<br> -AddLanguage en .en<br> -AddLanguage fr .fr<br> -</code></blockquote> - -Then the document <code>xxxx.en.Z</code> will be treated as being a compressed -English document. 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.<p><hr> - -<h2><A name="addtype">AddType</A></h2> +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> AddLanguage <EM>MIME-lang extension extension...</EM><BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config, virtual host, directory, .htaccess<BR> +<A + HREF="directive-dict.html#Override" + REL="Help" +><STRONG>Override:</STRONG></A> FileInfo<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Base<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_mime<P> + +The AddLanguage directive maps the given filename extensions to the +specified content language. <EM>MIME-lang</EM> is the MIME language of +filenames containing <EM>extension</EM>. This mapping is added to any +already in force, overriding any mappings that already exist for the +same <EM>extension</EM>. + +Example: <BLOCKQUOTE><CODE> +AddEncoding x-compress Z<BR> AddLanguage en .en<BR> AddLanguage fr +.fr<BR> </CODE></BLOCKQUOTE> + +Then the document <CODE>xxxx.en.Z</CODE> will be treated as being a +compressed English document (as will the document +<CODE>xxxx.Z.en</CODE>). Although the content language is reported to +the client, the browser is unlikely to use this information. The +AddLanguage directive is more useful for <A +HREF="../content-negotiation.html">content negotiation</A>, where +the server returns one from several documents based on the client's +language preference.<P> + +<P> + +<STRONG>See also</STRONG>: <A HREF="#multipleext">Files with +multiple extensions</A> +<BR> +<STRONG>See also</STRONG>: <A +HREF="./mod_negotiation.html">mod_negotiation</A> + +<HR> + +<H2><A NAME="addtype">AddType</A></H2> <!--%plaintext <?INDEX {\tt AddType} directive> --> -<strong>Syntax:</strong> AddType <em>mime-type extension extension...</em><br> -<Strong>Context:</strong> server config, virtual host, directory, .htaccess<br> -<Strong>Override:</strong> FileInfo<br> -<strong>Status:</strong> Base<br> -<strong>Module:</strong> mod_mime<p> - -The AddType directive adds to the list of filename extensions which -filenames may end in for the specified content type. <em>Mime-enc</em> -is the mime type to use for documents ending in <em>extension</em>. -after content-encoding and language extensions have been removed. Example: -<blockquote><code> +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> AddType <EM>MIME-type extension extension...</EM><BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config, virtual host, directory, .htaccess<BR> +<A + HREF="directive-dict.html#Override" + REL="Help" +><STRONG>Override:</STRONG></A> FileInfo<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Base<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_mime<P> + +The AddType directive maps the given filename extensions onto the +specified content type. <EM>MIME-enc</EM> is the MIME type to use for +filenames containing <EM>extension</EM>. This mapping is added to any +already in force, overriding any mappings that already exist for the +same <EM>extension</EM>. This directive can be used to add mappings +not listed in the MIME types file (see the <CODE><A +HREF="#typesconfig">TypesConfig</A></CODE> directive). + +Example: +<BLOCKQUOTE><CODE> AddType image/gif GIF -</code></blockquote> -It is recommended that new mime types be added using the AddType directive -rather than changing the <A HREF="#typesconfig">TypesConfig</A> file.<p> +</CODE></BLOCKQUOTE> +It is recommended that new MIME types be added using the AddType directive +rather than changing the <A HREF="#typesconfig">TypesConfig</A> file.<P> Note that, unlike the NCSA httpd, this directive cannot be used to set the -type of particular files.<p><hr> +type of particular files.<P> + +<P> + +<STRONG>See also</STRONG>: <A HREF="#multipleext">Files with +multiple extensions</A> -<h2><a name="forcetype">ForceType</a></h2> +<HR> + +<H2><A NAME="defaultlanguage">DefaultLanguage</A></H2> +<!--%plaintext <?INDEX {\tt DefaultLanguage} directive> --> +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> DefaultLanguage <EM>MIME-lang</EM><BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config, virtual host, directory, .htaccess<BR> +<A + HREF="directive-dict.html#Override" + REL="Help" +><STRONG>Override:</STRONG></A> FileInfo<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Base<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_mime<P> + +The DefaultLanguage directive tells Apache that all files in the +directive's scope (<EM>e.g.</EM>, all files covered by the current +<CODE><Directory></CODE> container) that don't have an explicit +language extension (such as <SAMP>.fr</SAMP> or <SAMP>.de</SAMP> as +configured by <SAMP>AddLanguage</SAMP>) should be considered to be in +the specified <EM>MIME-lang</EM> 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, <SAMP>DefaultLanguage</SAMP> can only specify a +single language. -<strong>Syntax:</strong> ForceType <em>media type</em><br> -<strong>Context:</strong> directory, .htaccess<br> -<strong>Status:</strong> Base<br> -<strong>Module:</strong> mod_mime<br> -<strong>Compatibility:</strong> ForceType is only available in Apache -1.1 and later.<p> +<P> -<p>When placed into an <code>.htaccess</code> file or a -<code><Directory></code> or <code><Location></code> section, +If no <SAMP>DefaultLanguage</SAMP> directive is in force, and a file +does not have any language extensions as configured by +<SAMP>AddLanguage</SAMP>, then that file will be considered to have no +language attribute. + +<P> + +<STRONG>See also</STRONG>: <A +HREF="./mod_negotiation.html">mod_negotiation</A> +<BR> +<STRONG>See also</STRONG>: <A HREF="#multipleext">Files with +multiple extensions</A> + +<HR> + +<H2><A NAME="forcetype">ForceType</A></H2> + +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> ForceType <EM>media type</EM><BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> directory, .htaccess<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Base<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_mime<BR> +<A + HREF="directive-dict.html#Compatibility" + REL="Help" +><STRONG>Compatibility:</STRONG></A> ForceType is only available in Apache +1.1 and later.<P> + +<P>When placed into an <CODE>.htaccess</CODE> file or a +<CODE><Directory></CODE> or <CODE><Location></CODE> section, this directive forces all matching files to be served -as the content type given by <em>media type</em>. For example, if you +as the content type given by <EM>media type</EM>. 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: -<pre> +<PRE> ForceType image/gif -</pre> -<p>Note that this will override any filename extensions that might -media type.</p> - -<h2><a name="sethandler">SetHandler</a></h2> +</PRE> +<P>Note that this will override any filename extensions that might determine +the media type.</P><HR> + +<H2><A NAME="removehandler">RemoveHandler</A></H2> + +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> RemoveHandler <EM>extension extension...</EM><BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> directory, .htaccess<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Base<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_mime<BR> +<A + HREF="directive-dict.html#Compatibility" + REL="Help" +><STRONG>Compatibility:</STRONG></A> RemoveHandler is only available in Apache +1.3.4 and later.<P> -<strong>Syntax:</strong> SetHandler <em>handler-name</em><br> -<strong>Context:</strong> directory, .htaccess<br> -<strong>Status:</strong> Base<br> -<strong>Module:</strong> mod_mime<br> -<strong>Compatibility:</strong> SetHandler is only available in Apache -1.1 and later.<p> +<P> +The <SAMP>RemoveHandler</SAMP> directive removes any +handler associations for files with the given extensions. +This allows <CODE>.htaccess</CODE> files in subdirectories to undo +any associations inherited from parent directories or the server +config files. An example of its use might be: +</P> +<DL> + <DT><CODE>/foo/.htaccess:</CODE></DT> + <DD><CODE>AddHandler server-parsed .html</CODE></DD> + <DT><CODE>/foo/bar/.htaccess:</CODE></DT> + <DD><CODE>RemoveHandler .html</CODE></DD> +</DL> +<P> +This has the effect of returning <SAMP>.html</SAMP> files in the +<SAMP>/foo/bar</SAMP> directory to being treated as normal +files, rather than as candidates for parsing (see the +<A HREF="mod_include.html"><SAMP>mod_include</SAMP></A> module). +</P> +<HR> -<p>When placed into an <code>.htaccess</code> file or a -<code><Directory></code> or <code><Location></code> section, +<H2><A NAME="sethandler">SetHandler</A></H2> + +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> SetHandler <EM>handler-name</EM><BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> directory, .htaccess<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Base<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_mime<BR> +<A + HREF="directive-dict.html#Compatibility" + REL="Help" +><STRONG>Compatibility:</STRONG></A> SetHandler is only available in Apache +1.1 and later.<P> + +<P>When placed into an <CODE>.htaccess</CODE> file or a +<CODE><Directory></CODE> or <CODE><Location></CODE> section, this directive forces all matching files to be parsed through the -<a href="../handler.html">handler</a> -given by <em>handler-name</em>. For example, if you had a +<A HREF="../handler.html">handler</A> +given by <EM>handler-name</EM>. 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 -<code>.htaccess</code> file in that directory: -<pre> +<CODE>.htaccess</CODE> file in that directory: +<PRE> SetHandler imap-file -</pre> +</PRE> -<p>Another example: if you wanted to have the server display a status -report whenever a URL of <code>http://servername/status</code> was +<P>Another example: if you wanted to have the server display a status +report whenever a URL of <CODE>http://servername/status</CODE> was called, you might put the following into access.conf: -<pre> +<PRE> <Location /status> SetHandler server-status </Location> -</pre> +</PRE> <HR> -<h2><A name="typesconfig">TypesConfig</A></h2> +<H2><A NAME="typesconfig">TypesConfig</A></H2> <!--%plaintext <?INDEX {\tt TypesConfig} directive> --> -<strong>Syntax:</strong> TypesConfig <em>filename</em><br> -<strong>Default:</strong> <code>TypesConfig conf/mime.types</code><br> -<Strong>Context:</strong> server config<br> -<strong>Status:</strong> Base<br> -<strong>Module:</strong> mod_mime<p> - -The TypesConfig directive sets the location of the mime types configuration -file. <em>Filename</em> is relative to the +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> TypesConfig <EM>filename</EM><BR> +<A + HREF="directive-dict.html#Default" + REL="Help" +><STRONG>Default:</STRONG></A> <CODE>TypesConfig conf/MIME.types</CODE><BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Base<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_mime<P> + +The TypesConfig directive sets the location of the MIME types configuration +file. <EM>Filename</EM> is relative to the <A HREF="core.html#serverroot">ServerRoot</A>. This file sets the default list of mappings from filename extensions to content types; changing this file is not recommended. Use the <A HREF="#addtype">AddType</A> directive instead. The file contains lines in the format of the arguments to an AddType command: -<blockquote><em>mime-type extension extension ...</em></blockquote> +<BLOCKQUOTE><EM>MIME-type extension extension ...</EM></BLOCKQUOTE> The extensions are lower-cased. Blank lines, and lines beginning with a hash -character (`#') are ignored.<p> +character (`#') are ignored.<P> <HR> + <H3 ALIGN="CENTER"> - Apache HTTP Server Version 1.2 + Apache HTTP Server Version 1.3 </H3> <A HREF="./"><IMG SRC="../images/index.gif" ALT="Index"></A> diff --git a/usr.sbin/httpd/htdocs/manual/mod/mod_negotiation.html b/usr.sbin/httpd/htdocs/manual/mod/mod_negotiation.html index 94cef4e5ac3..818d5e1fd68 100644 --- a/usr.sbin/httpd/htdocs/manual/mod/mod_negotiation.html +++ b/usr.sbin/httpd/htdocs/manual/mod/mod_negotiation.html @@ -15,30 +15,30 @@ <DIV ALIGN="CENTER"> <IMG SRC="../images/sub.gif" ALT="[APACHE DOCUMENTATION]"> <H3> - Apache HTTP Server Version 1.2 + Apache HTTP Server Version 1.3 </H3> </DIV> -<H1 ALIGN="CENTER">Module mod_negotiation</h1> +<H1 ALIGN="CENTER">Module mod_negotiation</H1> -This module is contained in the <code>mod_negotiation.c</code> file, +This module is contained in the <CODE>mod_negotiation.c</CODE> file, and is compiled in by default. It provides for <A -HREF="../content-negotiation.html">content negotiation</A>. +HREF="../content-negotiation.html">content negotiation</A>. -<h2>Summary</h2> +<H2>Summary</H2> 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. -<ul> -<li> A type map (a file with the handler <code>type-map</code>) +<UL> +<LI> A type map (a file with the handler <CODE>type-map</CODE>) which explicitly lists the files containing the variants. -<li> A MultiViews search (enabled by the MultiViews +<LI> A MultiViews search (enabled by the MultiViews <A HREF="core.html#options">Option</A>, where the server does an implicit filename pattern match, and choose from amongst the results. -</ul> +</UL> -<h3>Type maps</h3> +<H3>Type maps</H3> 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 @@ -50,106 +50,144 @@ between the header name and value, and between the tokens of value. The headers allowed are: -<dl> -<dt>Content-Encoding: -<dd>The encoding of the file. Currently only two encodings are recognized -by http; <code>x-compress</code> for compressed files, and <code>x-gzip</code> +<DL> +<DT>Content-Encoding: +<DD>The encoding of the file. Currently only two encodings are recognized +by http; <CODE>x-compress</CODE> for compressed files, and <CODE>x-gzip</CODE> for gzipped files. -<dt>Content-Language: -<dd>The language of the variant, as an Internet standard language code, such -as <code>en</code>. -<dt>Content-Length: -<dd>The length of the file, in bytes. If this header is not present, then +<DT>Content-Language: +<DD>The language of the variant, as an Internet standard language code, such +as <CODE>en</CODE>. +<DT>Content-Length: +<DD>The length of the file, in bytes. If this header is not present, then the actual length of the file is used. -<dt>Content-Type: -<dd>The MIME media type of the document, with optional parameters. +<DT>Content-Type: +<DD>The MIME media type of the document, with optional parameters. parameters are separated from the media type and from one another by semi-colons. Parameter syntax is name=value; allowed parameters are: -<dl> -<dt>level -<dd>the value is an integer, which specifies the version of the media type. -For <code>text/html</code> this defaults to 2, otherwise 0. -<dt>qs -<dd>the value is a floating-point number with value between 0. and 1. +<DL> +<DT>level +<DD>the value is an integer, which specifies the version of the media type. +For <CODE>text/html</CODE> this defaults to 2, otherwise 0. +<DT>qs +<DD>the value is a floating-point number with value between 0. and 1. It indications the 'quality' of this variant. -</dl> +</DL> Example: -<blockquote><code>Content-Type: image/jpeg; qs=0.8</code></blockquote> -<dt>URI: -<dd>The path to the file containing this variant, relative to the map file. -</dl> +<BLOCKQUOTE><CODE>Content-Type: image/jpeg; qs=0.8</CODE></BLOCKQUOTE> +<DT>URI: +<DD>The path to the file containing this variant, relative to the map file. +</DL> -<h3>MultiViews</h3> +<H3>MultiViews</H3> A MultiViews search is enabled by the MultiViews <A HREF="core.html#options">Option</A>. -If the server receives a request for <code>/some/dir/foo</code> and -<code>/some/dir/foo</code> does <em>not</em> exist, then the server reads the -directory looking for all files named <code>foo.*</code>, and effectively +If the server receives a request for <CODE>/some/dir/foo</CODE> and +<CODE>/some/dir/foo</CODE> does <EM>not</EM> exist, then the server reads the +directory looking for all files named <CODE>foo.*</CODE>, 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.<p> +requirements, and returns that document.<P> -<h2>Directives</h2> -<ul> -<li><A href="#cachenegotiateddocs">CacheNegotiatedDocs</a> -<li><A HREF="#languagepriority">LanguagePriority</A> -</ul> -<hr> - +<H2>Directives</H2> +<UL> +<LI><A HREF="#cachenegotiateddocs">CacheNegotiatedDocs</A> +<LI><A HREF="#languagepriority">LanguagePriority</A> +</UL> +<HR> -<h2><A name="cachenegotiateddocs">CacheNegotiatedDocs</A></h2> -<strong>Syntax:</strong> CacheNegotiatedDocs<br> -<Strong>Context:</strong> server config<br> -<strong>Status:</strong> Base<br> -<strong>Module:</strong> mod_negotiation<br> -<strong>Compatibility:</strong> CacheNegotiatedDocs is only available -in Apache 1.1 and later.<p> -<p>If set, this directive allows content-negotiated documents to be +<H2><A NAME="cachenegotiateddocs">CacheNegotiatedDocs</A></H2> +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> CacheNegotiatedDocs<BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Base<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_negotiation<BR> +<A + HREF="directive-dict.html#Compatibility" + REL="Help" +><STRONG>Compatibility:</STRONG></A> CacheNegotiatedDocs is only available +in Apache 1.1 and later.<P> + +<P>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. -<p> +<P> 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 +documents, and this directive has no effect in responses to HTTP/1.1 requests. -<h2><A name="languagepriority">LanguagePriority</A></h2> +<H2><A NAME="languagepriority">LanguagePriority</A></H2> <!--%plaintext <?INDEX {\tt LanguagePriority} directive> --> -<strong>Syntax:</strong> LanguagePriority <em>mime-lang mime-lang...</em><br> -<Strong>Context:</strong> server config, virtual host, directory, .htaccess<br> -<Strong>Override:</strong> FileInfo<br> -<strong>Status:</strong> Base<br> -<strong>Module:</strong> mod_negotiation<p> +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> LanguagePriority <EM>MIME-lang MIME-lang...</EM><BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config, virtual host, directory, .htaccess<BR> +<A + HREF="directive-dict.html#Override" + REL="Help" +><STRONG>Override:</STRONG></A> FileInfo<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Base<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_negotiation<P> 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 <em>mime-lang</em> are in order of decreasing +MultiViews request. The list of <EM>MIME-lang</EM> are in order of decreasing preference. Example: -<blockquote><code>LanguagePriority en fr de</code></blockquote> +<BLOCKQUOTE><CODE>LanguagePriority en fr de</CODE></BLOCKQUOTE> -For a request for <code>foo.html</code>, where <code>foo.html.fr</code> -and <code>foo.html.de</code> both existed, but the browser did not express -a language preference, then <code>foo.html.fr</code> would be returned.<p> +For a request for <CODE>foo.html</CODE>, where <CODE>foo.html.fr</CODE> +and <CODE>foo.html.de</CODE> both existed, but the browser did not express +a language preference, then <CODE>foo.html.fr</CODE> would be returned.<P> <P> Note that this directive only has an effect if a 'best' language -cannot be determined by other any other means. Correctly implemented -HTTP/1.1 requests will mean this directive has no effect. +cannot be determined by any other means. Correctly implemented +HTTP/1.1 requests will mean this directive has no effect. + +<P> + +<STRONG>See also</STRONG>: +<A HREF="./mod_mime.html#defaultlanguage">DefaultLanguage</A> and +<A HREF="./mod_mime.html#addlanguage">AddLanguage</A> + <HR> + <H3 ALIGN="CENTER"> - Apache HTTP Server Version 1.2 + Apache HTTP Server Version 1.3 </H3> <A HREF="./"><IMG SRC="../images/index.gif" ALT="Index"></A> diff --git a/usr.sbin/httpd/htdocs/manual/mod/mod_rewrite.html b/usr.sbin/httpd/htdocs/manual/mod/mod_rewrite.html index 44ed3239cf2..118ea068ccd 100644 --- a/usr.sbin/httpd/htdocs/manual/mod/mod_rewrite.html +++ b/usr.sbin/httpd/htdocs/manual/mod/mod_rewrite.html @@ -2,10 +2,10 @@ <!--%hypertext --> <!-- mod_rewrite.html --> <!-- Documentation for the mod_rewrite Apache module --> -<html> -<head> -<title>Apache module mod_rewrite</title> -</head> +<HTML> +<HEAD> +<TITLE>Apache module mod_rewrite</TITLE> +</HEAD> <!-- Background white, links blue (unvisited), navy (visited), red (active) --> <BODY @@ -15,305 +15,777 @@ VLINK="#000080" ALINK="#FF0000" > +<BLOCKQUOTE><!-- page indentation --> <DIV ALIGN="CENTER"> <IMG SRC="../images/sub.gif" ALT="[APACHE DOCUMENTATION]"> <H3> - Apache HTTP Server Version 1.2 + Apache HTTP Server Version 1.3 </H3> </DIV> -<h1 ALIGN="CENTER">Module mod_rewrite</h1> - -This module is contained in the <code>mod_rewrite.c</code> file, with Apache -1.2 and later. It provides a rule-based rewriting engine to rewrite requested -URLs on the fly. <code>mod_rewrite</code> is not compiled into the server by -default. To use <code>mod_rewrite</code> you have to enable the following line -in the server build Configuration file: -<pre> - Module rewrite_module mod_rewrite.o -</pre> - -<h2>Summary</h2> - -This module uses a rule-based rewriting engine (based on a -regular-expression parser) to rewrite requested URLs on the fly. - -<p> -It supports an unlimited number of additional rule conditions (which can -operate on a lot of variables, including HTTP headers) for granular -matching and external database lookups (either via plain text -tables, DBM hash files or external processes) for advanced URL -substitution. - -<p> -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 rewritten result can lead to internal -sub-processing, external request redirection or to internal proxy throughput. - -<p> -This module was originally written in April 1996 and -gifted exclusively to the The Apache Group in July 1997 by -<p> -<blockquote> - <i>Ralf S. Engelschall</i><br> - <a href="mailto:rse@engelschall.com"><tt>rse@engelschall.com</tt></a><br> - <a href="http://www.engelschall.com/"><tt>www.engelschall.com</tt></a> -</blockquote> - -<!--%hypertext --> -<HR> -<!--/%hypertext --> - -<p> -<h2>Directives</h2> - -<ul> - <li><a href="#RewriteEngine">RewriteEngine</a> - <li><a href="#RewriteOptions">RewriteOptions</a> - <li><a href="#RewriteLog">RewriteLog</a> - <li><a href="#RewriteLogLevel">RewriteLogLevel</a> - <li><a href="#RewriteMap">RewriteMap</a> - <li><a href="#RewriteBase">RewriteBase</a> - <li><a href="#RewriteCond">RewriteCond</a> - <li><a href="#RewriteRule">RewriteRule</a> -</ul> - -<!--%hypertext --> -<hr> -<!--/%hypertext --> - - -<center> -<a name="Configuration"> -<h1>Configuration Directives</h1> -</a> -</center> +<BR> +<H1 ALIGN="CENTER">Module mod_rewrite<BR>URL Rewriting Engine</H1> + +This module is contained in the <CODE>mod_rewrite.c</CODE> 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 +<CODE>mod_rewrite</CODE> you have to enable the following line in the server +build <CODE>Configuration</CODE> file: +<PRE> + AddModule modules/standard/mod_rewrite.o +</PRE> + +<P> +<HR NOSHADE SIZE=1> + +<BR> +<H2>Summary</H2> + +<BLOCKQUOTE> +<BLOCKQUOTE> +<BLOCKQUOTE> +<EM>``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.''</EM> +<DIV ALIGN=RIGHT> +-- Brian Behlendorf<BR> +Apache Group +</DIV> +</BLOCKQUOTE> +</BLOCKQUOTE> +</BLOCKQUOTE> + +<BLOCKQUOTE> +<BLOCKQUOTE> +<BLOCKQUOTE> +<EM>`` +Despite the tons of examples and docs, mod_rewrite +is voodoo. Damned cool voodoo, but still voodoo. +''</EM> +<DIV ALIGN=RIGHT> +-- Brian Moore<BR> +bem@news.cmc.net +</DIV> +</BLOCKQUOTE> +</BLOCKQUOTE> +</BLOCKQUOTE> + +Welcome to mod_rewrite, the Swiss Army Knife of URL manipulation! + +<P> +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. + +<P> +This module operates on the full URLs (including the path-info part) both in +per-server context (<CODE>httpd.conf</CODE>) and per-directory context +(<CODE>.htaccess</CODE>) and even can 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. + +<P> +But all this functionality and flexibility has its drawback: complexity. So +don't expect to understand this module in it's whole in just one day. + +<P> +This module was invented and originally written in April 1996<BR> +and gifted exclusively to the The Apache Group in July 1997 by + +<P> +<BLOCKQUOTE> +<A HREF="http://www.engelschall.com/"><CODE>Ralf S. Engelschall</CODE></A><BR> +<A HREF="mailto:rse@engelschall.com"><CODE>rse@engelschall.com</CODE></A><BR> +<A HREF="http://www.engelschall.com/"><CODE>www.engelschall.com</CODE></A> +</BLOCKQUOTE> + +<P> +<HR NOSHADE SIZE=1> + +<H2>Table Of Contents</H2> + +<P> +<STRONG>Internal Processing</STRONG> +<UL> + <LI><A HREF="#InternalAPI">API Phases</A> + <LI><A HREF="#InternalRuleset">Ruleset Processing</A> + <LI><A HREF="#InternalBackRefs">Regex Back-Reference Availability</A> +</UL> +<P> +<STRONG>Configuration Directives</STRONG> +<UL> + <LI><A HREF="#RewriteEngine">RewriteEngine</A> + <LI><A HREF="#RewriteOptions">RewriteOptions</A> + <LI><A HREF="#RewriteLog">RewriteLog</A> + <LI><A HREF="#RewriteLogLevel">RewriteLogLevel</A> + <LI><A HREF="#RewriteLock">RewriteLock</A> + <LI><A HREF="#RewriteMap">RewriteMap</A> + <LI><A HREF="#RewriteBase">RewriteBase</A> + <LI><A HREF="#RewriteCond">RewriteCond</A> + <LI><A HREF="#RewriteRule">RewriteRule</A> +</UL> +<STRONG>Miscellaneous</STRONG> +<UL> + <LI><A HREF="#EnvVar">Environment Variables</A> + <LI><A HREF="#Solutions">Practical Solutions</A> +</UL> + +<P> +<HR NOSHADE SIZE=1> + +<CENTER> +<H1><A NAME="Internal">Internal Processing</A></H1> +</CENTER> + +<P> +<HR NOSHADE SIZE=1> + +<P> +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. + +<H2><A NAME="InternalAPI">API Phases</A></H2> + +<P> +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 was read and before any authorization +starts and the Fixup hook which is triggered after the authorization phases +and after the per-directory config files (<CODE>.htaccess</CODE>) where read, +but before the content handler is activated. + +<P> +So, after a request comes in and Apache has determined the corresponding +server (or virtual server) the rewriting engine start 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 either rewrites URLs 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 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: + +<OL> +<LI>The API currently provides only a URL-to-filename hook. Although + mod_rewrite rewrites URLs to URLs, URLs to filenames and even + filenames to filenames. 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 + then the API intends for it. +<P> +<LI>Unbelievably mod_rewrite provides URL manipulations in per-directory + context, <EM>i.e.</EM>, within <CODE>.htaccess</CODE> files, although + these are + reached a very long time after the URLs were translated to filenames (this + has to be this way, because <CODE>.htaccess</CODE> files stay in the + filesystem, so processing has already been reached this stage of + processing). 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 it usually impossible, but see the + <CODE>RewriteBase</CODE> directive below for the trick to achieve this) + and then initiates a new internal sub-request with the new URL. This leads + to a new processing of the API phases from the beginning. + <P> + 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. +</OL> + +<P> +Don't forget these two points! + +<H2><A NAME="InternalRuleset">Ruleset Processing</A></H2> + +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 while 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. Just the final result processing is +different. + +<P> +The order of rules in the ruleset is important because the rewriting engine +processes them in a special order. And this order is not very obvious. The +rule is this: The rewriting engine loops through the ruleset rule by rule +(<CODE>RewriteRule</CODE> directives!) and when a particular rule matched it +optionally loops through existing corresponding conditions +(<CODE>RewriteCond</CODE> directives). Because of historical reasons the +conditions are given first, the control flow is a little bit winded. See +Figure 1 for more details. + +<P> +<DIV ALIGN=CENTER> +<TABLE CELLSPACING=0 CELLPADDING=2 BORDER=0> +<TR> +<TD BGCOLOR="#CCCCCC"><IMG + SRC="../images/mod_rewrite_fig1.gif" + WIDTH="428" HEIGHT="385" + ALT="[Needs graphics capability to display]"></TD> +</TR> +<TR> +<TD ALIGN=CENTER> +<STRONG>Figure 1:</STRONG> The control flow through the rewriting ruleset +</TD> +</TR> +</TABLE> +</DIV> -<a name="RewriteEngine"><h3>RewriteEngine</h3></a> -<strong>Syntax:</strong> <code>RewriteEngine</code> {<code>on,off</code>}<br> -<strong>Default:</strong> <strong><code>RewriteEngine off</code></strong><br> -<strong>Context:</strong> server config, virtual host, per-directory config<br> -<p> +<P> +As you can see, first the URL is matched against the <EM>Pattern</EM> of each +rule. When it fails mod_rewrite immediately stops processing this rule and +continues with the next rule. If the <EM>Pattern</EM> matched, 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 +<EM>Substitution</EM> and goes on with its rule-looping. But +if conditions exists, it starts an inner loop for processing them in order +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 +<EM>TestString</EM> by expanding variables, back-references, map lookups, +<EM>etc.</EM> and then we try to match <EM>CondPattern</EM> 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 condition is available. If all conditions matched processing is +continued with the substitution of the URL with <EM>Substitution</EM>. + +<H2><A NAME="InternalBackRefs">Regex Back-Reference Availability</A></H2> + +One important thing here has to be remembered: Whenever you +use parenthesis in <EM>Pattern</EM> or in one of the <EM>CondPattern</EM> +back-reference are internally created which can be used with the +strings <CODE>$N</CODE> and <CODE>%N</CODE> (see below). And these +are available for creating the strings <EM>Substitution</EM> and +<EM>TestCond</EM>. Figure 2 shows at which locations the back-references are +transfered to for expansion. + +<P> +<DIV ALIGN=CENTER> +<TABLE CELLSPACING=0 CELLPADDING=2 BORDER=0> +<TR> +<TD BGCOLOR="#CCCCCC"><IMG + SRC="../images/mod_rewrite_fig2.gif" + WIDTH="381" HEIGHT="179" + ALT="[Needs graphics capability to display]"></TD> +</TR> +<TR> +<TD ALIGN=CENTER> +<STRONG>Figure 2:</STRONG> The back-reference flow through a rule +</TD> +</TR> +</TABLE> +</DIV> -The <tt>RewriteEngine</tt> directive enables or disables the -runtime rewriting engine. If it is set to <code>off</code> this module does -no runtime processing at all. It does not even update the <tt>SCRIPT_URx</tt> +<P> +We know, this was a crash course of mod_rewrite's internal processing. But +you will benefit from this knowledge when reading the following documentation +of the available directives. + +<P> +<HR NOSHADE SIZE=1> + +<CENTER> +<H1><A NAME="Configuration">Configuration Directives</A></H1> +</CENTER> + +<P> +<HR NOSHADE SIZE=1> + +<H3><A NAME="RewriteEngine">RewriteEngine</A></H3> +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> + <CODE>RewriteEngine</CODE> {<CODE>on,off</CODE>}<BR> +<A + HREF="directive-dict.html#Default" + REL="Help" +><STRONG>Default:</STRONG></A> + <STRONG><CODE>RewriteEngine off</CODE></STRONG><BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> + server config, virtual host, directory, .htaccess<BR> +<A + HREF="directive-dict.html#Override" + REL="Help" +><STRONG>Override:</STRONG></A> FileInfo<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Extension<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_rewrite.c<BR> +<A + HREF="directive-dict.html#Compatibility" + REL="Help" +><STRONG>Compatibility:</STRONG></A> Apache 1.2<BR> + +<P> +The <CODE>RewriteEngine</CODE> directive enables or disables the runtime +rewriting engine. If it is set to <CODE>off</CODE> this module does no runtime +processing at all. It does not even update the <CODE>SCRIPT_URx</CODE> environment variables. -<p> +<P> Use this directive to disable the module instead of commenting out -all <tt>RewriteRule</tt> directives! - -<p> -<hr noshade size=1> -<p> - -<a name="RewriteOptions"><h3>RewriteOptions</h3></a> -<strong>Syntax:</strong> <code>RewriteOptions</code> <em>Option</em> ...<br> -<strong>Default:</strong> -<em>None</em>-<br> -<strong>Context:</strong> server config, virtual host, per-directory config<br> -<p> - -The <tt>RewriteOption</tt> directive sets some special options for the -current per-server or per-directory configuration. The <em>Option</em> +all <CODE>RewriteRule</CODE> directives! + +<P> +Note that, by default, rewrite configurations are not inherited. +This means that you need to have a <CODE>RewriteEngine on</CODE> +directive for each virtual host you wish to use it in. + +<P> +<HR NOSHADE SIZE=1> +<P> + +<H3><A NAME="RewriteOptions">RewriteOptions</A></H3> +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> <CODE>RewriteOptions</CODE> <EM>Option</EM><BR> +<A + HREF="directive-dict.html#Default" + REL="Help" +><STRONG>Default:</STRONG></A> <EM>None</EM><BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config, virtual host, directory, + .htaccess<BR> +<A + HREF="directive-dict.html#Override" + REL="Help" +><STRONG>Override:</STRONG></A> FileInfo<BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Extension<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_rewrite.c<BR> +<A + HREF="directive-dict.html#Compatibility" + REL="Help" +><STRONG>Compatibility:</STRONG></A> Apache 1.2<BR> + +<P> +The <CODE>RewriteOptions</CODE> directive sets some special options for the +current per-server or per-directory configuration. The <EM>Option</EM> strings can be one of the following: -<ul> -<li>'<strong><code>inherit</code></strong>'<br> +<UL> +<LI>'<STRONG><CODE>inherit</CODE></STRONG>'<BR> 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 gets inherited. In per-directory context this means that conditions and rules of the parent directory's - <tt>.htaccess</tt> configuration gets inherited. -</ul> - -<p> -<hr noshade size=1> -<p> - -<a name="RewriteLog"><h3>RewriteLog</h3></a> -<strong>Syntax:</strong> <code>RewriteLog</code> <em>Filename</em><br> -<strong>Default:</strong> -<em>None</em>-<br> -<strong>Context:</strong> server config, virtual host<br> -<p> - -The <tt>RewriteLog</tt> directive sets the name of the file to which the + <CODE>.htaccess</CODE> configuration gets inherited. +</UL> + +<P> +<HR NOSHADE SIZE=1> +<P> + +<H3><A NAME="RewriteLog">RewriteLog</A></H3> +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> <CODE>RewriteLog</CODE> <EM>Filename</EM><BR> +<A + HREF="directive-dict.html#Default" + REL="Help" +><STRONG>Default:</STRONG></A> <EM>None</EM><BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config, virtual host<BR> +<A + HREF="directive-dict.html#Override" + REL="Help" +><STRONG>Override:</STRONG></A> <EM>Not applicable</EM><BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Extension<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_rewrite.c<BR> +<A + HREF="directive-dict.html#Compatibility" + REL="Help" +><STRONG>Compatibility:</STRONG></A> Apache 1.2<BR> + +<P> +The <CODE>RewriteLog</CODE> 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 ('<tt>/</tt>') then it is assumed to be relative to the -<em>Server Root</em>. The directive should occur only once per server +with a slash ('<CODE>/</CODE>') then it is assumed to be relative to the +<EM>Server Root</EM>. The directive should occur only once per server config. -<p> -<table width="70%" border=0 bgcolor="#f0f0f0" cellspacing=0 cellpadding=10> -<tr><td> -To disable the logging of rewriting actions it is not recommended -to set <em>Filename</em> -to <code>/dev/null</code>, because although the rewriting engine does +<P> +<TABLE WIDTH="70%" BORDER=0 BGCOLOR="#E0E0F0" CELLSPACING=0 CELLPADDING=10> +<TR><TD> +<STRONG>Notice</STRONG>: To disable the logging of rewriting actions it is +not recommended to set <EM>Filename</EM> +to <CODE>/dev/null</CODE>, because although the rewriting engine does not create output to a logfile it still creates the logfile -output internally. <b>This will slow down the server with no advantage to the -administrator!</b> +output internally. <STRONG>This will slow down the server with no advantage +to the administrator!</STRONG> To disable logging either remove or comment out the -<tt>RewriteLog</tt> directive or use <tt>RewriteLogLevel 0</tt>! -</td></tr> -</table> - -<p> -<table width="70%" border=0 bgcolor="#fff0f0" cellspacing=0 cellpadding=10> -<tr><td> -SECURITY: See the <a -href="../misc/security_tips.html">Apache Security -Tips</a> document for details on why your security could be compromised if the +<CODE>RewriteLog</CODE> directive or use <CODE>RewriteLogLevel 0</CODE>! +</TD></TR> +</TABLE> + +<P> +<TABLE WIDTH="70%" BORDER=0 BGCOLOR="#E0E0F0" CELLSPACING=0 CELLPADDING=10> +<TR><TD> +<STRONG>Security</STRONG>: See the <A +HREF="../misc/security_tips.html">Apache Security +Tips</A> 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. -</td></tr> -</table> +</TD></TR> +</TABLE> -<p> -<b>Example:</b> -<blockquote> -<pre> +<P> +<STRONG>Example:</STRONG> +<BLOCKQUOTE> +<PRE> RewriteLog "/usr/local/var/apache/logs/rewrite.log" -</pre> -</blockquote> - -<p> -<hr noshade size=1> -<p> - -<a name="RewriteLogLevel"><h3>RewriteLogLevel</h3></a> -<strong>Syntax:</strong> <code>RewriteLogLevel</code> <em>Level</em><br> -<strong>Default:</strong> <strong><code>RewriteLogLevel 0</code></strong><br> -<strong>Context:</strong> server config, virtual host<br> -<p> - -The <tt>RewriteLogLevel</tt> directive set the verbosity level of the rewriting +</PRE> +</BLOCKQUOTE> + +<P> +<HR NOSHADE SIZE=1> +<P> + +<H3><A NAME="RewriteLogLevel">RewriteLogLevel</A></H3> +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> <CODE>RewriteLogLevel</CODE> <EM>Level</EM><BR> +<A + HREF="directive-dict.html#Default" + REL="Help" +><STRONG>Default:</STRONG></A> <STRONG><CODE>RewriteLogLevel 0</CODE></STRONG> +<BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config, virtual host<BR> +<A + HREF="directive-dict.html#Override" + REL="Help" +><STRONG>Override:</STRONG></A> <EM>Not applicable</EM><BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Extension<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_rewrite.c<BR> +<A + HREF="directive-dict.html#Compatibility" + REL="Help" +><STRONG>Compatibility:</STRONG></A> Apache 1.2<BR> + +<P> +The <CODE>RewriteLogLevel</CODE> directive set 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. -<p> -To disable the logging of rewriting actions simply set <em>Level</em> to 0. +<P> +To disable the logging of rewriting actions simply set <EM>Level</EM> to 0. This disables all rewrite action logs. -<p> -<table width="70%" border=0 bgcolor="#f0f0f0" cellspacing=0 cellpadding=10> -<tr><td> -<b>Notice:</b> Using a high value for <i>Level</i> will slow down your Apache +<P> +<TABLE WIDTH="70%" BORDER=0 BGCOLOR="#E0E0F0" CELLSPACING=0 CELLPADDING=10> +<TR><TD> +<STRONG>Notice:</STRONG> Using a high value for <EM>Level</EM> will slow down +your Apache server dramatically! Use the rewriting logfile only for debugging or at least -at <em>Level</em> not greater than 2! -</td></tr> -</table> +at <EM>Level</EM> not greater than 2! +</TD></TR> +</TABLE> -<p> -<b>Example:</b> -<blockquote> -<pre> +<P> +<STRONG>Example:</STRONG> +<BLOCKQUOTE> +<PRE> RewriteLogLevel 3 -</pre> -</blockquote> - -<p> -<hr noshade size=1> -<p> - -<a name="RewriteMap"><h3>RewriteMap</h3></a> -<strong>Syntax:</strong> <code>RewriteMap</code> <em>Mapname</em> <code>{txt,dbm,prg}:</code><em>Filename</em><br> -<strong>Default:</strong> not used per default<br> -<strong>Context:</strong> server config, virtual host<br> -<p> - -The <tt>RewriteMap</tt> directive defines an external <em>Rewriting Map</em> +</PRE> +</BLOCKQUOTE> + +<P> +<HR NOSHADE SIZE=1> +<P> + +<H3><A NAME="RewriteLock">RewriteLock</A></H3> +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> <CODE>RewriteLock</CODE> <EM>Filename</EM><BR> +<A + HREF="directive-dict.html#Default" + REL="Help" +><STRONG>Default:</STRONG></A> <EM>None</EM><BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config, virtual host<BR> +<A + HREF="directive-dict.html#Override" + REL="Help" +><STRONG>Override:</STRONG></A> <EM>Not applicable</EM><BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Extension<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_rewrite.c<BR> +<A + HREF="directive-dict.html#Compatibility" + REL="Help" +><STRONG>Compatibility:</STRONG></A> Apache 1.3<BR> + +<P> +This directive sets the filename for a synchronization lockfile which +mod_rewrite needs to communicate with <SAMP>RewriteMap</SAMP> +<EM>programs</EM>. 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 +SAMP using all other types of rewriting maps. + +<P> +<HR NOSHADE SIZE=1> +<P> + +<H3><A NAME="RewriteMap">RewriteMap</A></H3> +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> <CODE>RewriteMap</CODE> <EM>MapName </EM> + <EM>MapType</EM><CODE>:</CODE><EM>MapSource</EM><BR> +<A + HREF="directive-dict.html#Default" + REL="Help" +><STRONG>Default:</STRONG></A> not used per default<BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config, virtual host<BR> +<A + HREF="directive-dict.html#Override" + REL="Help" +><STRONG>Override:</STRONG></A> <EM>Not applicable</EM><BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Extension<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_rewrite.c<BR> +<A + HREF="directive-dict.html#Compatibility" + REL="Help" +><STRONG>Compatibility:</STRONG></A> Apache 1.2 (partially), Apache 1.3<BR> + +<P> +The <CODE>RewriteMap</CODE> directive defines a <EM>Rewriting Map</EM> which can be used inside rule substitution strings by the mapping-functions -to insert/substitute fields through a key lookup. -<p> +to insert/substitute fields through a key lookup. The source of this +lookup can be of various types. +<P> -The <a name="mapfunc"><em>Mapname</em></a> is the name of the map and will +The <A NAME="mapfunc"><EM>MapName</EM></A> is the name of the map and will be used to specify a mapping-function for the substitution strings of a -rewriting rule via - -<blockquote><strong> -<code>${</code> <em>Mapname</em> <code>:</code> <em>LookupKey</em> -<code>|</code> <em>DefaultValue</em> <code>}</code> -</strong></blockquote> - -When such a directive occurs the map <em>Mapname</em> -is consulted and the key <em>LookupKey</em> is looked-up. If the key is -found, the map-function directive is substituted by <em>SubstValue</em>. If -the key is not found then it is substituted by <em>DefaultValue</em>. - -<p> -The <em>Filename</em> must be a valid Unix filepath, containing one -of the following formats: - -<ol> -<li><b>Plain Text Format</b> - <p> - This is a ASCII file which contains either blank lines, comment lines - (starting with a '#' character) or - - <blockquote><strong> - <em>MatchingKey</em> <em>SubstValue</em> - </strong></blockquote> - - pairs - one per line. You can create such files either manually, - using your favorite editor, or by using the programs - <tt>mapcollect</tt> and <tt>mapmerge</tt> from the <tt>support</tt> - directory of the <b>mod_rewrite</b> distribution. - <p> - To declare such a map prefix, <em>Filename</em> with a <code>txt:</code> - string as in the following example: - -<p> -<table border=0 cellspacing=1 cellpadding=5 bgcolor="#f0f0f0"> -<tr><td><pre> -# -# map.real-to-user -- maps realnames to usernames -# +rewriting rule via one of the following constructs: + +<BLOCKQUOTE><STRONG> +<CODE>${</CODE> <EM>MapName</EM> <CODE>:</CODE> <EM>LookupKey</EM> +<CODE>}</CODE><BR> +<CODE>${</CODE> <EM>MapName</EM> <CODE>:</CODE> <EM>LookupKey</EM> +<CODE>|</CODE> <EM>DefaultValue</EM> <CODE>}</CODE> +</STRONG></BLOCKQUOTE> + +When such a construct occurs the map <EM>MapName</EM> +is consulted and the key <EM>LookupKey</EM> is looked-up. If the key is +found, the map-function construct is substituted by <EM>SubstValue</EM>. If +the key is not found then it is substituted by <EM>DefaultValue</EM> or +the empty string if no <EM>DefaultValue</EM> was specified. + +<P> +The following combinations for <EM>MapType</EM> and <EM>MapSource</EM> +can be used: + +<UL> +<LI><STRONG>Standard Plain Text</STRONG><BR> + MapType: <CODE>txt</CODE>, MapSource: Unix filesystem path to valid regular + file + <P> + This is the standard rewriting map feature where the <EM>MapSource</EM> is + a plain ASCII file containing either blank lines, comment lines (starting + with a '#' character) or pairs like the following - one per line. + + <BLOCKQUOTE><STRONG> + <EM>MatchingKey</EM> <EM>SubstValue</EM> + </STRONG></BLOCKQUOTE> + + <P> + Example: +<P> +<TABLE BORDER=0 CELLSPACING=1 CELLPADDING=5 BGCOLOR="#F0F0F0"> +<TR><TD><PRE> +## +## map.txt -- rewriting map +## Ralf.S.Engelschall rse # Bastard Operator From Hell -Dr.Fred.Klabuster fred # Mr. DAU -</pre></td></tr> -</table> - -<p> -<table border=0 cellspacing=1 cellpadding=5 bgcolor="#f0f0f0"> -<tr><td><pre> -RewriteMap real-to-host txt:/path/to/file/map.real-to-user -</pre></td></tr> -</table> - -<p> -<li><b>DBM Hashfile Format</b> - <p> - This is a binary NDBM format file containing the - same contents as the <em>Plain Text Format</em> files. You can create - such a file with any NDBM tool or with the <tt>dbmmanage</tt> program - from the <tt>support</tt> directory of the Apache distribution. - <p> - To declare such a map prefix <em>Filename</em> with a <code>dbm:</code> - string. -<p> -<li><b>Program Format</b> - <p> - This is a Unix executable, not a lookup file. To create it you can use +Mr.Joe.Average joe # Mr. Average +</PRE></TD></TR> +</TABLE> + +<P> +<TABLE BORDER=0 CELLSPACING=1 CELLPADDING=5 BGCOLOR="#F0F0F0"> +<TR><TD><PRE> +RewriteMap real-to-user txt:/path/to/file/map.txt +</PRE></TD></TR> +</TABLE> + +<P> +<LI><STRONG>Randomized Plain Text</STRONG><BR> + MapType: <CODE>rnd</CODE>, MapSource: Unix filesystem path to valid regular + file + <P> + 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 ``<CODE>|</CODE>'' characters which have the meaning of + ``or''. 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: +<P> +<TABLE BORDER=0 CELLSPACING=1 CELLPADDING=5 BGCOLOR="#F0F0F0"> +<TR><TD><PRE> +## +## map.txt -- rewriting map +## + +static www1|www2|www3|www4 +dynamic www5|www6 +</PRE></TD></TR> +</TABLE> + +<P> +<TABLE BORDER=0 CELLSPACING=1 CELLPADDING=5 BGCOLOR="#F0F0F0"> +<TR><TD><PRE> +RewriteMap servers rnd:/path/to/file/map.txt +</PRE></TD></TR> +</TABLE> + +<P> +<LI><STRONG>Hash File</STRONG><BR> + MapType: <CODE>dbm</CODE>, MapSource: Unix filesystem path to valid + regular file + <P> + Here the source is a binary NDBM format file containing the same contents + as a <EM>Plain Text</EM> 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: + <P> + <TABLE BORDER=0 CELLSPACING=1 CELLPADDING=5 BGCOLOR="#F0F0F0"> + <TR><TD><PRE> +#!/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)</PRE></TD></TR> + </TABLE> + <P> + <TABLE BORDER=0 CELLSPACING=1 CELLPADDING=5 BGCOLOR="#F0F0F0"> + <TR><TD><PRE>$ txt2dbm map.txt map.db </PRE></TD></TR> + </TABLE> +<P> +<LI><STRONG>Internal Function</STRONG><BR> + MapType: <CODE>int</CODE>, MapSource: Internal Apache function + <P> + Here the source is an internal Apache function. Currently you cannot + create your own, but the following functions already exists: + <UL> + <LI><STRONG>toupper</STRONG>:<BR> + Converts the looked up key to all upper case. + <LI><STRONG>tolower</STRONG>:<BR> + Converts the looked up key to all lower case. + <LI><STRONG>escape</STRONG>:<BR> + Translates special characters in the looked up key to hex-encodings. + <LI><STRONG>unescape</STRONG>:<BR> + Translates hex-encodings in the looked up key back to special characters. + </UL> +<P> +<LI><STRONG>External Rewriting Program</STRONG><BR> + MapType: <CODE>prg</CODE>, MapSource: Unix filesystem path to valid + regular file + <P> + Here the source is a Unix program, not a map file. To create it you can use the language of your choice, but the result has to be a run-able Unix - binary (i.e. either object-code or a script with the - magic cookie trick '<tt>#!/path/to/interpreter</tt>' as the first line). - <p> + executable (<EM>i.e.</EM>, either object-code or a script with the + magic cookie trick '<CODE>#!/path/to/interpreter</CODE>' as the first + line). + <P> This program gets started once at startup of the Apache servers and then - communicates with the rewriting engine over its <tt>stdin</tt> and - <tt>stdout</tt> file-handles. For each map-function lookup it will + communicates with the rewriting engine over its <CODE>stdin</CODE> and + <CODE>stdout</CODE> file-handles. For each map-function lookup it will receive the key to lookup as a newline-terminated string on - <tt>stdin</tt>. It then has to give back the looked-up value as a - newline-terminated string on <tt>stdout</tt> or the four-character string - ``<tt>NULL</tt>'' if it fails (i.e. there is no corresponding value + <CODE>stdin</CODE>. It then has to give back the looked-up value as a + newline-terminated string on <CODE>stdout</CODE> or the four-character + string ``<CODE>NULL</CODE>'' if it fails (<EM>i.e.</EM>, 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: - <p> -<table border=0 cellspacing=1 cellpadding=5 bgcolor="#f0f0f0"> -<tr><td><pre> + (<EM>i.e.</EM>, key == value) could be: + <P> +<TABLE BORDER=0 CELLSPACING=1 CELLPADDING=5 BGCOLOR="#F0F0F0"> +<TR><TD><PRE> #!/usr/bin/perl $| = 1; while (<STDIN>) { @@ -321,90 +793,117 @@ while (<STDIN>) { # or lookups should occur... print $_; } -</pre></td></tr> -</table> - <p> - <b>But be very careful:</b><br> - <ol> - <li>``<i>Keep the program simple, stupid</i>'' (KISS), because +</PRE></TD></TR> +</TABLE> + <P> + But be very careful:<BR> + <OL> + <LI>``<EM>Keep the program simple, stupid</EM>'' (KISS), because if this program hangs it will lead to a hang of the Apache server when the rule occurs. - <li>Avoid one common mistake: never do buffered I/O on <tt>stdout</tt>! - This will cause a deadloop! Hence the ``<tt>$|=1</tt>'' in the above - example... - </ol> - <p> - To declare such a map prefix <em>Filename</em> with a <code>prg:</code> - string. -</ol> - -The <tt>RewriteMap</tt> directive can occur more than once. For each -mapping-function use one <tt>RewriteMap</tt> directive to declare its -rewriting mapfile. While you cannot <b>declare</b> a map in per-directory -context it is of course possible to <b>use</b> this map in per-directory -context. - -<p> -<table width="70%" border=0 bgcolor="#f0f0f0" cellspacing=0 cellpadding=10> -<tr><td> -For plain text and DBM format files the looked-up keys are cached in-core -until the <tt>mtime</tt> of the mapfile changes or the server does a + <LI>Avoid one common mistake: never do buffered I/O on <CODE>stdout</CODE>! + This will cause a deadloop! Hence the ``<CODE>$|=1</CODE>'' in the + above example... + <LI>Use the <SAMP>RewriteLock</SAMP> directive to define a lockfile + mod_rewrite can use to synchronize the communication to the program. + Per default no such synchronization takes place. + </OL> +</UL> + +The <CODE>RewriteMap</CODE> directive can occur more than once. For each +mapping-function use one <CODE>RewriteMap</CODE> directive to declare its +rewriting mapfile. While you cannot <STRONG>declare</STRONG> a map in +per-directory context it is of course possible to <STRONG>use</STRONG> +this map in per-directory context. + +<P> +<TABLE WIDTH="70%" BORDER=0 BGCOLOR="#E0E0F0" CELLSPACING=0 CELLPADDING=10> +<TR><TD> +<STRONG>Notice:</STRONG> For plain text and DBM format files the looked-up +keys are cached in-core +until the <CODE>mtime</CODE> of the mapfile changes or the server does a restart. This way you can have map-functions in rules which are used -for <b>every</b> request. This is no problem, because the external lookup -only happens once! -</td></tr> -</table> - - -<p> -<hr noshade size=1> -<p> - -<a name="RewriteBase"><h3>RewriteBase</h3></a> -<strong>Syntax:</strong> <code>RewriteBase</code> <em>BaseURL</em><br> -<strong>Default:</strong> <em>default is the physical directory path</em><br> -<strong>Context:</strong> per-directory config<br> -<p> - -The <tt>RewriteBase</tt> directive explicitly sets the base URL for -per-directory rewrites. As you will see below, <tt>RewriteRule</tt> can be -used in per-directory config files (<tt>.htaccess</tt>). There it will act -locally, i.e. the local directory prefix is stripped at this stage of +for <STRONG>every</STRONG> request. This is no problem, because the +external lookup only happens once! +</TD></TR> +</TABLE> + +<P> +<HR NOSHADE SIZE=1> +<P> + +<H3><A NAME="RewriteBase">RewriteBase</A></H3> +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> <CODE>RewriteBase</CODE> <EM>BaseURL</EM><BR> +<A + HREF="directive-dict.html#Default" + REL="Help" +><STRONG>Default:</STRONG></A> <EM>default is the physical directory path</EM> +<BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> directory, .htaccess<BR> +<A + HREF="directive-dict.html#Override" + REL="Help" +><STRONG>Override:</STRONG></A> <EM>FileInfo</EM><BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Extension<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_rewrite.c<BR> +<A + HREF="directive-dict.html#Compatibility" + REL="Help" +><STRONG>Compatibility:</STRONG></A> Apache 1.2<BR> + +<P> +The <CODE>RewriteBase</CODE> directive explicitly sets the base URL for +per-directory rewrites. As you will see below, <CODE>RewriteRule</CODE> can be +used in per-directory config files (<CODE>.htaccess</CODE>). There it will act +locally, <EM>i.e.</EM>, 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. -<p> -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. <b>But at most websites URLs are -<b>NOT</b> directly related to physical filename paths, so this assumption -will be usually be wrong!</b> There you have to use the <tt>RewriteBase</tt> -directive to specify the correct URL-prefix. - -<p> -<table width="70%" border=0 bgcolor="#fff0f0" cellspacing=0 cellpadding=10> -<tr><td> -So, if your webserver's URLs are <b>not</b> directly -related to physical file paths, you have to use <tt>RewriteBase</tt> in every -<tt>.htaccess</tt> files where you want to use <tt>RewriteRule</tt> +<P> +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. <STRONG>But at most websites URLs are +<STRONG>NOT</STRONG> directly related to physical filename paths, so this +assumption will be usually be wrong!</STRONG> There you have to use the +<CODE>RewriteBase</CODE> directive to specify the correct URL-prefix. + +<P> +<TABLE WIDTH="70%" BORDER=0 BGCOLOR="#E0E0F0" CELLSPACING=0 CELLPADDING=10> +<TR><TD> +<STRONG>Notice:</STRONG> If your webserver's URLs are <STRONG>not</STRONG> +directly related to physical file paths, you have to use +<CODE>RewriteBase</CODE> in every +<CODE>.htaccess</CODE> files where you want to use <CODE>RewriteRule</CODE> directives. -</td></tr> -</table> +</TD></TR> +</TABLE> -<p> -<b>Example:</b> +<P> +<STRONG>Example:</STRONG> -<blockquote> +<BLOCKQUOTE> Assume the following per-directory config file: -<p> -<table border=0 cellspacing=1 cellpadding=5 bgcolor="#f0f0f0"> -<tr><td><pre> +<P> +<TABLE BORDER=0 CELLSPACING=1 CELLPADDING=5 BGCOLOR="#F0F0F0"> +<TR><TD><PRE> # # /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. +# Remember: /abc/def is the physical path of /xyz, <EM>i.e.</EM>, the server +# has a 'Alias /xyz /abc/def' directive <EM>e.g.</EM> # RewriteEngine On @@ -415,35 +914,36 @@ RewriteBase /xyz # now the rewriting rules RewriteRule ^oldstuff\.html$ newstuff.html -</pre></td></tr> -</table> - -<p> -In the above example, a request to <tt>/xyz/oldstuff.html</tt> gets correctly -rewritten to the physical file <tt>/abc/def/newstuff.html</tt>. - -<p> -<table width="70%" border=0 bgcolor="#fff0f0" cellspacing=0 cellpadding=10> -<tr><td> -<font size=-1> -<b>For the Apache hackers:</b><br> +</PRE></TD></TR> +</TABLE> + +<P> +In the above example, a request to <CODE>/xyz/oldstuff.html</CODE> +gets correctly +rewritten to the physical file <CODE>/abc/def/newstuff.html</CODE>. + +<P> +<TABLE WIDTH="70%" BORDER=0 BGCOLOR="#E0E0F0" CELLSPACING=0 CELLPADDING=10> +<TR><TD> +<FONT SIZE=-1> +<STRONG>Notice - For the Apache hackers:</STRONG><BR> The following list gives detailed information about the internal processing steps: -<p> -<pre> +<P> +<PRE> 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) + /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 -</pre> +</PRE> This seems very complicated but is the correct Apache internal processing, because the per-directory rewriting comes too late in the process. So, @@ -452,263 +952,343 @@ kernel! BUT: While this seems like a serious overhead, it really isn't, because this re-injection happens fully internal 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. -</font> -</td></tr> -</table> +</FONT> +</TD></TR> +</TABLE> + +</BLOCKQUOTE> + + +<P> +<HR NOSHADE SIZE=1> +<P> + +<H3><A NAME="RewriteCond">RewriteCond</A></H3> +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> <CODE>RewriteCond</CODE> <EM>TestString</EM> + <EM>CondPattern</EM><BR> +<A + HREF="directive-dict.html#Default" + REL="Help" +><STRONG>Default:</STRONG></A> <EM>None</EM><BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config, virtual host, directory, + .htaccess<BR> +<A + HREF="directive-dict.html#Override" + REL="Help" +><STRONG>Override:</STRONG></A> <EM>FileInfo</EM><BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Extension<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_rewrite.c<BR> +<A + HREF="directive-dict.html#Compatibility" + REL="Help" +><STRONG>Compatibility:</STRONG></A> Apache 1.2 (partially), Apache 1.3<BR> + +<P> +The <CODE>RewriteCond</CODE> directive defines a rule condition. Precede a +<CODE>RewriteRule</CODE> directive with one or more <CODE>RewriteCond</CODE> +directives. -</blockquote> +The following rewriting rule is only used if its pattern matches the current +state of the URI <STRONG>and</STRONG> if these additional conditions apply +too. +<P> +<EM>TestString</EM> is a string which can contains the following +expanded constructs in addition to plain text: -<p> -<hr noshade size=1> -<p> +<UL> +<LI><STRONG>RewriteRule backreferences</STRONG>: These are backreferences of + the form -<a name="RewriteCond"><h3>RewriteCond</h3></a> -<strong>Syntax:</strong> <code>RewriteCond</code> <em>TestString</em> <em>CondPattern</em><br> -<strong>Default:</strong> -<em>None</em>-<br> -<strong>Context:</strong> server config, virtual host, per-directory config<br> -<p> +<BLOCKQUOTE><STRONG> +<CODE>$N</CODE> +</STRONG></BLOCKQUOTE> -The <tt>RewriteCond</tt> directive defines a rule condition. Precede a -<tt>RewriteRule</tt> directive with one or more <tt>RewriteCond</tt> -directives. +(1 <= N <= 9) which provide access to the grouped parts (parenthesis!) +of the +pattern from the corresponding <CODE>RewriteRule</CODE> directive (the one +following the current bunch of <CODE>RewriteCond</CODE> directives). -The following rewriting rule is only used if its pattern matches the current -state of the URI <b>AND</b> if these additional conditions apply, too. +<P> +<LI><STRONG>RewriteCond backreferences</STRONG>: These are backreferences of +the form + +<BLOCKQUOTE><STRONG> +<CODE>%N</CODE> +</STRONG></BLOCKQUOTE> -<p> -<em>TestString</em> is a string which contains server-variables of the form +(1 <= N <= 9) which provide access to the grouped parts (parenthesis!) of +the pattern from the last matched <CODE>RewriteCond</CODE> directive in the +current bunch of conditions. -<blockquote><strong> -<tt>%{</tt> <em>NAME_OF_VARIABLE</em> <tt>}</tt> -</strong></blockquote> +<P> +<LI><STRONG>Server-Variables</STRONG>: These are variables + of the form -where <em>NAME_OF_VARIABLE</em> can be a string +<BLOCKQUOTE><STRONG> +<CODE>%{</CODE> <EM>NAME_OF_VARIABLE</EM> <CODE>}</CODE> +</STRONG></BLOCKQUOTE> + +where <EM>NAME_OF_VARIABLE</EM> can be a string of the following list: -<p> -<table bgcolor="#f0f0f0" cellspacing=0 cellpadding=5> -<tr> -<td valign=top> -<b>HTTP headers:</b><p> -<font size=-1> -HTTP_USER_AGENT<br> -HTTP_REFERER<br> -HTTP_COOKIE<br> -HTTP_FORWARDED<br> -HTTP_HOST<br> -HTTP_PROXY_CONNECTION<br> -HTTP_ACCEPT<br> -</font> -</td> - -<td valign=top> -<b>connection & request:</b><p> -<font size=-1> -REMOTE_ADDR<br> -REMOTE_HOST<br> -REMOTE_USER<br> -REMOTE_IDENT<br> -REQUEST_METHOD<br> -SCRIPT_FILENAME<br> -PATH_INFO<br> -QUERY_STRING<br> -AUTH_TYPE<br> -</font> -</td> - -</tr> -<tr> - -<td valign=top> -<b>server internals:</b><p> -<font size=-1> -DOCUMENT_ROOT<br> -SERVER_ADMIN<br> -SERVER_NAME<br> -SERVER_PORT<br> -SERVER_PROTOCOL<br> -SERVER_SOFTWARE<br> -SERVER_VERSION<br> -</font> -</td> - -<td valign=top> -<b>system stuff:</b><p> -<font size=-1> -TIME_YEAR<br> -TIME_MON<br> -TIME_DAY<br> -TIME_HOUR<br> -TIME_MIN<br> -TIME_SEC<br> -TIME_WDAY<br> -TIME<br> -</font> -</td> - -<td valign=top> -<b>specials:</b><p> -<font size=-1> -API_VERSION<br> -THE_REQUEST<br> -REQUEST_URI<br> -REQUEST_FILENAME<br> -IS_SUBREQ<br> -</font> -</td> -</tr> -</table> - - -<p> -<table width="70%" border=0 bgcolor="#f0f0f0" cellspacing=0 cellpadding=10> -<tr><td> -These variables all correspond to the similar named HTTP MIME-headers, C -variables of the Apache server or <tt>struct tm</tt> fields of the Unix -system. -</td></tr> -</table> - -<p> +<P> +<TABLE BGCOLOR="#F0F0F0" CELLSPACING=0 CELLPADDING=5> +<TR> +<TD VALIGN=TOP> +<STRONG>HTTP headers:</STRONG><P> +<FONT SIZE=-1> +HTTP_USER_AGENT<BR> +HTTP_REFERER<BR> +HTTP_COOKIE<BR> +HTTP_FORWARDED<BR> +HTTP_HOST<BR> +HTTP_PROXY_CONNECTION<BR> +HTTP_ACCEPT<BR> +</FONT> +</TD> + +<TD VALIGN=TOP> +<STRONG>connection & request:</STRONG><P> +<FONT SIZE=-1> +REMOTE_ADDR<BR> +REMOTE_HOST<BR> +REMOTE_USER<BR> +REMOTE_IDENT<BR> +REQUEST_METHOD<BR> +SCRIPT_FILENAME<BR> +PATH_INFO<BR> +QUERY_STRING<BR> +AUTH_TYPE<BR> +</FONT> +</TD> + +</TR> +<TR> + +<TD VALIGN=TOP> +<STRONG>server internals:</STRONG><P> +<FONT SIZE=-1> +DOCUMENT_ROOT<BR> +SERVER_ADMIN<BR> +SERVER_NAME<BR> +SERVER_PORT<BR> +SERVER_PROTOCOL<BR> +SERVER_SOFTWARE<BR> +</FONT> +</TD> + +<TD VALIGN=TOP> +<STRONG>system stuff:</STRONG><P> +<FONT SIZE=-1> +TIME_YEAR<BR> +TIME_MON<BR> +TIME_DAY<BR> +TIME_HOUR<BR> +TIME_MIN<BR> +TIME_SEC<BR> +TIME_WDAY<BR> +TIME<BR> +</FONT> +</TD> + +<TD VALIGN=TOP> +<STRONG>specials:</STRONG><P> +<FONT SIZE=-1> +API_VERSION<BR> +THE_REQUEST<BR> +REQUEST_URI<BR> +REQUEST_FILENAME<BR> +IS_SUBREQ<BR> +</FONT> +</TD> +</TR> +</TABLE> + +<P> +<TABLE WIDTH="70%" BORDER=0 BGCOLOR="#E0E0F0" CELLSPACING=0 CELLPADDING=10> +<TR><TD> +<STRONG>Notice:</STRONG> These variables all correspond to the similar named +HTTP MIME-headers, C variables of the Apache server or <CODE>struct tm</CODE> +fields of the Unix system. +</TD></TR> +</TABLE> + +</UL> + +<P> Special Notes: -<ol> -<li>The variables SCRIPT_FILENAME and REQUEST_FILENAME contain the same -value, i.e. the value of the <tt>filename</tt> field of the internal -<tt>request_rec</tt> structure of the Apache server. The first name is just the + +<OL> +<LI>The variables SCRIPT_FILENAME and REQUEST_FILENAME contain the same +value, <EM>i.e.</EM>, the value of the <CODE>filename</CODE> field of +the internal +<CODE>request_rec</CODE> 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 <tt>uri</tt> -field of <tt>request_rec</tt>). - -<p> -<li>There is the special format: <tt>%{ENV:variable}</tt> where -<i>variable</i> can be any environment variable. This is looked-up via -internal Apache structures and (if not found there) via <tt>getenv()</tt> from -the Apache server process. - -<p> -<li>There is the special format: <tt>%{HTTP:header}</tt> where -<i>header</i> can be any HTTP MIME-header name. This is looked-up -from the HTTP request. Example: <tt>%{HTTP:Proxy-Connection}</tt> -is the value of the HTTP header ``<tt>Proxy-Connection:</tt>''. - -<p> -<li>There is the special format: <tt>%{LA-U:url}</tt> -for look-aheads like <tt>-U</tt>. This performs a internal sub-request to -look-ahead for the final value of <i>url</i>. - -<p> -<li>There is the special format: <tt>%{LA-F:file}</tt> -for look-aheads like <tt>-F</tt>. This performs a internal sub-request to -look-ahead for the final value of <i>file</i>. -</ol> - -<p> -<em>CondPattern</em> is the condition pattern, i.e. a regular expression -which gets applied to the current instance of the <em>TestString</em>, i.e. -<em>TestString</em> gets evaluated and then matched against -<em>CondPattern</em>. - -<p> -<b>Remember:</b> <em>CondPattern</em> is a standard -<em>Extended Regular Expression</em> with some additions: - -<ol> -<li>You can precede the pattern string with a '<tt>!</tt>' character -(exclamation mark) to specify a <b>non</b>-matching pattern. - -<p> -<li> -There are some special variants of <em>CondPatterns</em>. Instead of real +counterpart to REQUEST_URI (which contains the value of the <CODE>uri</CODE> +field of <CODE>request_rec</CODE>). + +<P> +<LI>There is the special format: <CODE>%{ENV:variable}</CODE> where +<EM>variable</EM> can be any environment variable. This is looked-up via +internal Apache structures and (if not found there) via <CODE>getenv()</CODE> +from the Apache server process. + +<P> +<LI>There is the special format: <CODE>%{HTTP:header}</CODE> where +<EM>header</EM> can be any HTTP MIME-header name. This is looked-up +from the HTTP request. Example: <CODE>%{HTTP:Proxy-Connection}</CODE> +is the value of the HTTP header ``<CODE>Proxy-Connection:</CODE>''. + +<P> +<LI>There is the special format <CODE>%{LA-U:variable}</CODE> for look-aheads +which perform an internal (URL-based) sub-request to determine the final value +of <EM>variable</EM>. Use this when you want to use a variable for rewriting +which actually is 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 +<CODE>REMOTE_USER</CODE> variable from within the per-server context +(<CODE>httpd.conf</CODE> file) you have to use <CODE>%{LA-U:REMOTE_USER}</CODE> +because this variable is set by the authorization phases which come +<EM>after</EM> the URL translation phase where mod_rewrite operates. On the +other hand, because mod_rewrite implements its per-directory context +(<CODE>.htaccess</CODE> file) via the Fixup phase of the API and because the +authorization phases come <EM>before</EM> this phase, you just can use +<CODE>%{REMOTE_USER}</CODE> there. + +<P> +<LI>There is the special format: <CODE>%{LA-F:variable}</CODE> which perform an +internal (filename-based) sub-request to determine the final value of +<EM>variable</EM>. This is the most of the time the same as LA-U above. +</OL> + +<P> +<EM>CondPattern</EM> is the condition pattern, <EM>i.e.</EM>, a regular +expression +which gets applied to the current instance of the <EM>TestString</EM>, +<EM>i.e.</EM>, <EM>TestString</EM> gets evaluated and then matched against +<EM>CondPattern</EM>. + +<P> +<STRONG>Remember:</STRONG> <EM>CondPattern</EM> is a standard +<EM>Extended Regular Expression</EM> with some additions: + +<OL> +<LI>You can precede the pattern string with a '<CODE>!</CODE>' character +(exclamation mark) to specify a <STRONG>non</STRONG>-matching pattern. + +<P> +<LI> +There are some special variants of <EM>CondPatterns</EM>. Instead of real regular expression strings you can also use one of the following: -<p> -<ul> -<li>'<b><CondPattern</b>' (is lexicographically lower)<br> -Treats the <i>CondPattern</i> as a plain string and compares it -lexicographically to <i>TestString</i> and results in a true expression if -<i>TestString</i> is lexicographically lower then <i>CondPattern</i>. -<p> -<li>'<b>>CondPattern</b>' (is lexicographically greater)<br> -Treats the <i>CondPattern</i> as a plain string and compares it -lexicographically to <i>TestString</i> and results in a true expression if -<i>TestString</i> is lexicographically greater then <i>CondPattern</i>. -<p> -<li>'<b>=CondPattern</b>' (is lexicographically equal)<br> -Treats the <i>CondPattern</i> as a plain string and compares it -lexicographically to <i>TestString</i> and results in a true expression if -<i>TestString</i> is lexicographically equal to <i>CondPattern</i>, i.e the +<P> +<UL> +<LI>'<STRONG><CondPattern</STRONG>' (is lexicographically lower)<BR> +Treats the <EM>CondPattern</EM> as a plain string and compares it +lexicographically to <EM>TestString</EM> and results in a true expression if +<EM>TestString</EM> is lexicographically lower than <EM>CondPattern</EM>. +<P> +<LI>'<STRONG>>CondPattern</STRONG>' (is lexicographically greater)<BR> +Treats the <EM>CondPattern</EM> as a plain string and compares it +lexicographically to <EM>TestString</EM> and results in a true expression if +<EM>TestString</EM> is lexicographically greater than <EM>CondPattern</EM>. +<P> +<LI>'<STRONG>=CondPattern</STRONG>' (is lexicographically equal)<BR> +Treats the <EM>CondPattern</EM> as a plain string and compares it +lexicographically to <EM>TestString</EM> and results in a true expression if +<EM>TestString</EM> is lexicographically equal to <EM>CondPattern</EM>, i.e the two strings are exactly equal (character by character). -<p> -<li>'<b>-d</b>' (is <b>d</b>irectory)<br> -Treats the <i>TestString</i> as a pathname and +If <EM>CondPattern</EM> is just <SAMP>""</SAMP> (two quotation marks) this +compares <EM>TestString</EM> against the empty string. +<P> +<LI>'<STRONG>-d</STRONG>' (is <STRONG>d</STRONG>irectory)<BR> +Treats the <EM>TestString</EM> as a pathname and tests if it exists and is a directory. -<p> -<li>'<b>-f</b>' (is regular <b>f</b>ile)<br> -Treats the <i>TestString</i> as a pathname and +<P> +<LI>'<STRONG>-f</STRONG>' (is regular <STRONG>f</STRONG>ile)<BR> +Treats the <EM>TestString</EM> as a pathname and tests if it exists and is a regular file. -<p> -<li>'<b>-s</b>' (is regular file with <b>s</b>ize)<br> -Treats the <i>TestString</i> as a pathname and -tests if it exists and is a regular file with size greater then zero. -<p> -<li>'<b>-l</b>' (is symbolic <b>l</b>ink)<br> -Treats the <i>TestString</i> as a pathname and +<P> +<LI>'<STRONG>-s</STRONG>' (is regular file with <STRONG>s</STRONG>ize)<BR> +Treats the <EM>TestString</EM> as a pathname and +tests if it exists and is a regular file with size greater than zero. +<P> +<LI>'<STRONG>-l</STRONG>' (is symbolic <STRONG>l</STRONG>ink)<BR> +Treats the <EM>TestString</EM> as a pathname and tests if it exists and is a symbolic link. -<p> -<li>'<b>-F</b>' (is existing file via subrequest)<br> -Checks if <i>TestString</i> is a valid file and accessible via all the +<P> +<LI>'<STRONG>-F</STRONG>' (is existing file via subrequest)<BR> +Checks if <EM>TestString</EM> 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! -<p> -<li>'<b>-U</b>' (is existing URL via subrequest)<br> -Checks if <i>TestString</i> is a valid URL and accessible via all the server's +<P> +<LI>'<STRONG>-U</STRONG>' (is existing URL via subrequest)<BR> +Checks if <EM>TestString</EM> 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 servers performance! -</ul> -<p> -Notice: All of these tests can also be prefixed by a not ('!') character +your server's performance! +</UL> +<P> +<TABLE WIDTH="70%" BORDER=0 BGCOLOR="#E0E0F0" CELLSPACING=0 CELLPADDING=10> +<TR><TD> +<STRONG>Notice:</STRONG> +All of these tests can also be prefixed by a not ('!') character to negate their meaning. -</ol> +</TD></TR> +</TABLE> +</OL> -<p> -Additionally you can set special flags for <em>CondPattern</em> by appending +<P> +Additionally you can set special flags for <EM>CondPattern</EM> by appending -<blockquote><strong> -<code>[</code><em>flags</em><code>]</code> -</strong></blockquote> +<BLOCKQUOTE><STRONG> +<CODE>[</CODE><EM>flags</EM><CODE>]</CODE> +</STRONG></BLOCKQUOTE> -as the third argument to the <tt>RewriteCond</tt> directive. <em>Flags</em> +as the third argument to the <CODE>RewriteCond</CODE> directive. <EM>Flags</EM> is a comma-separated list of the following flags: -<ul> -<li>'<strong><code>nocase|NC</code></strong>' (<b>n</b>o <b>c</b>ase)<br> - This makes the condition test case-insensitive, i.e. there is +<UL> +<LI>'<STRONG><CODE>nocase|NC</CODE></STRONG>' (<STRONG>n</STRONG>o <STRONG>c</STRONG>ase)<BR> + This makes the condition test case-insensitive, <EM>i.e.</EM>, there is no difference between 'A-Z' and 'a-z' both in the expanded - <em>TestString</em> and the <em>CondPattern</em>. -<p> -<li>'<strong><code>ornext|OR</code></strong>' (<b>or</b> next condition)<br> + <EM>TestString</EM> and the <EM>CondPattern</EM>. +<P> +<LI>'<STRONG><CODE>ornext|OR</CODE></STRONG>' (<STRONG>or</STRONG> next condition)<BR> Use this to combine rule conditions with a local OR instead of the implicit AND. Typical example: - <p> -<blockquote><pre> + <P> +<BLOCKQUOTE><PRE> RewriteCond %{REMOTE_HOST} ^host1.* [OR] RewriteCond %{REMOTE_HOST} ^host2.* [OR] RewriteCond %{REMOTE_HOST} ^host3.* RewriteRule ...some special stuff for any of these hosts... -</pre></blockquote> +</PRE></BLOCKQUOTE> Without this flag you had to write down the cond/rule three times. -</ul> +</UL> -<p> -<b>Example:</b> -<blockquote> +<P> +<STRONG>Example:</STRONG> +<BLOCKQUOTE> -To rewrite the Homepage of a site according to the ``<tt>User-Agent:</tt>'' +To rewrite the Homepage of a site according to the ``<CODE>User-Agent:</CODE>'' header of the request, you can use the following: -<blockquote><pre> +<BLOCKQUOTE><PRE> RewriteCond %{HTTP_USER_AGENT} ^Mozilla.* RewriteRule ^/$ /homepage.max.html [L] @@ -716,354 +1296,417 @@ RewriteCond %{HTTP_USER_AGENT} ^Lynx.* RewriteRule ^/$ /homepage.min.html [L] RewriteRule ^/$ /homepage.std.html [L] -</pre></blockquote> +</PRE></BLOCKQUOTE> 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 +Frames, <EM>etc.</EM> If you use the Lynx browser (which is Terminal-based), then you +get the min homepage, which contains no images, no tables, <EM>etc.</EM> If you use any other browser you get the standard homepage. -</blockquote> - -<p> -<hr noshade size=1> -<p> - -<a name="RewriteRule"><h3>RewriteRule</h3></a> -<strong>Syntax:</strong> <code>RewriteRule</code> <em>Pattern</em> <em>Substitution</em><br> -<strong>Default:</strong> -<em>None</em>-<br> -<strong>Context:</strong> server config, virtual host, per-directory config<br> - -<p> -The <tt>RewriteRule</tt> directive is the real rewriting workhorse. The +</BLOCKQUOTE> + +<P> +<HR NOSHADE SIZE=1> +<P> + +<H3><A NAME="RewriteRule">RewriteRule</A></H3> +<A + HREF="directive-dict.html#Syntax" + REL="Help" +><STRONG>Syntax:</STRONG></A> <CODE>RewriteRule</CODE> <EM>Pattern</EM> <EM>Substitution</EM><BR> +<A + HREF="directive-dict.html#Default" + REL="Help" +><STRONG>Default:</STRONG></A> <EM>None</EM><BR> +<A + HREF="directive-dict.html#Context" + REL="Help" +><STRONG>Context:</STRONG></A> server config, virtual host, directory, .htaccess<BR> +<A + HREF="directive-dict.html#Override" + REL="Help" +><STRONG>Override:</STRONG></A> <EM>FileInfo</EM><BR> +<A + HREF="directive-dict.html#Status" + REL="Help" +><STRONG>Status:</STRONG></A> Extension<BR> +<A + HREF="directive-dict.html#Module" + REL="Help" +><STRONG>Module:</STRONG></A> mod_rewrite.c<BR> +<A + HREF="directive-dict.html#Compatibility" + REL="Help" +><STRONG>Compatibility:</STRONG></A> Apache 1.2 (partially), Apache 1.3<BR> + +<P> +The <CODE>RewriteRule</CODE> directive is the real rewriting workhorse. The directive can occur more than once. Each directive then defines one single -rewriting rule. The <b>definition order</b> of these rules is -<b>important</b>, because this order is used when applying the rules at +rewriting rule. The <STRONG>definition order</STRONG> of these rules is +<STRONG>important</STRONG>, because this order is used when applying the rules at run-time. -<p> -<a name="patterns"><em>Pattern</em></a> can be (for Apache 1.1.x a System -V8 and for Apache 1.2.x a POSIX) <a name="regexp">regular expression</a> +<P> +<A NAME="patterns"><EM>Pattern</EM></A> can be (for Apache 1.1.x a System +V8 and for Apache 1.2.x a POSIX) <A NAME="regexp">regular expression</A> 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 original requested URL, because there could be any number of rules before which already matched and made alterations to it. -<p> +<P> Some hints about the syntax of regular expressions: -<p> -<table bgcolor="#f0f0f0" cellspacing=0 cellpadding=5> -<tr> -<td valign=top> -<pre> -<strong><code>^</code></strong> Start of line -<strong><code>$</code></strong> End of line -<strong><code>.</code></strong> Any single character -<strong><code>[</code></strong>chars<strong><code>]</code></strong> One of chars -<strong><code>[^</code></strong>chars<strong><code>]</code></strong> None of chars - -<strong><code>?</code></strong> 0 or 1 of the preceding char -<strong><code>*</code></strong> 0 or N of the preceding char -<strong><code>+</code></strong> 1 or N of the preceding char - -<strong><code>\</code></strong>char escape that specific char - (e.g. for specifying the chars "<code>.[]()</code>" etc.) - -<strong><code>(</code></strong>string<strong><code>)</code></strong> Grouping of chars (the <b>N</b>th group can be used on the RHS with <code>$</code><b>N</b>) -</pre> -</td> -</tr> -</table> - -<p> -Additionally the NOT character ('<tt>!</tt>') is a possible pattern -prefix. This gives you the ability to negate a pattern; to say, for instance: ``<i>if -the current URL does <b>NOT</b> match to this pattern</i>''. This can be used -for special cases where it is better to match the negative pattern or as a -last default rule. - -<p> -<table width="70%" border=0 bgcolor="#fff0f0" cellspacing=0 cellpadding=10> -<tr><td> -<b>Notice!</b> When using the NOT character to negate a pattern you cannot +<P> +<TABLE BGCOLOR="#F0F0F0" CELLSPACING=0 CELLPADDING=5> +<TR> +<TD VALIGN=TOP> +<PRE> +<STRONG>Text:</STRONG> + <STRONG><CODE>.</CODE></STRONG> Any single character + <STRONG><CODE>[</CODE></STRONG>chars<STRONG><CODE>]</CODE></STRONG> Character class: One of chars + <STRONG><CODE>[^</CODE></STRONG>chars<STRONG><CODE>]</CODE></STRONG> Character class: None of chars + text1<STRONG><CODE>|</CODE></STRONG>text2 Alternative: text1 or text2 + +<STRONG>Quantifiers:</STRONG> + <STRONG><CODE>?</CODE></STRONG> 0 or 1 of the preceding text + <STRONG><CODE>*</CODE></STRONG> 0 or N of the preceding text (N > 1) + <STRONG><CODE>+</CODE></STRONG> 1 or N of the preceding text (N > 1) + +<STRONG>Grouping:</STRONG> + <STRONG><CODE>(</CODE></STRONG>text<STRONG><CODE>)</CODE></STRONG> Grouping of text + (either to set the borders of an alternative or + for making backreferences where the <STRONG>N</STRONG>th group can + be used on the RHS of a RewriteRule with <CODE>$</CODE><STRONG>N</STRONG>) + +<STRONG>Anchors:</STRONG> + <STRONG><CODE>^</CODE></STRONG> Start of line anchor + <STRONG><CODE>$</CODE></STRONG> End of line anchor + +<STRONG>Escaping:</STRONG> + <STRONG><CODE>\</CODE></STRONG>char escape that particular char + (for instance to specify the chars "<CODE>.[]()</CODE>" <EM>etc.</EM>) +</PRE> +</TD> +</TR> +</TABLE> + +<P> +For more information about regular expressions either have a look at your +local regex(3) manpage or its <CODE>src/regex/regex.3</CODE> copy in the +Apache 1.3 distribution. When you are interested in more detailed and deeper +information about regular expressions and its variants (POSIX regex, Perl +regex, <EM>etc.</EM>) have a look at the following dedicated book on this topic: + +<BLOCKQUOTE> +<EM>Mastering Regular Expressions</EM><BR> +Jeffrey E.F. Friedl<BR> +Nutshell Handbook Series<BR> +O'Reilly & Associates, Inc. 1997<BR> +ISBN 1-56592-257-3<BR> +</BLOCKQUOTE> + +<P> +Additionally in mod_rewrite the NOT character ('<CODE>!</CODE>') is a possible +pattern prefix. This gives you the ability to negate a pattern; to say, for +instance: ``<EM>if the current URL does <STRONG>NOT</STRONG> match to this +pattern</EM>''. This can be used for special cases where it is better to match +the negative pattern or as a last default rule. + +<P> +<TABLE WIDTH="70%" BORDER=0 BGCOLOR="#E0E0F0" CELLSPACING=0 CELLPADDING=10> +<TR><TD> +<STRONG>Notice:</STRONG> 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 <tt>$N</tt> in the +consequence, if negated patterns are used, you cannot use <CODE>$N</CODE> in the substitution string! -</td></tr> -</table> +</TD></TR> +</TABLE> -<p> -<a name="rhs"><em>Substitution</em></a> of a rewriting rule is the string +<P> +<A NAME="rhs"><EM>Substitution</EM></A> of a rewriting rule is the string which is substituted for (or replaces) the original URL for which -<em>Pattern</em> matched. Beside plain text you can use - -<ol> -<li>pattern-group back-references (<code>$N</code>) -<li>server-variables as in rule condition test-strings (<code>%{VARNAME}</code>) -<li><a href="#mapfunc">mapping-function</a> calls (<code>${mapname:key|default}</code>) -</ol> - -Back-references are <code>$</code><b>N</b> (<b>N</b>=1..9) identifiers which -will be replaced by the contents of the <b>N</b>th group of the matched -<em>Pattern</em>. The server-variables are the same as for the -<em>TestString</em> of a <tt>RewriteCond</tt> directive. The -mapping-functions come from the <tt>RewriteMap</tt> directive and are +<EM>Pattern</EM> matched. Beside plain text you can use + +<OL> +<LI>back-references <CODE>$N</CODE> to the RewriteRule pattern +<LI>back-references <CODE>%N</CODE> to the last matched RewriteCond pattern +<LI>server-variables as in rule condition test-strings (<CODE>%{VARNAME}</CODE>) +<LI><A HREF="#mapfunc">mapping-function</A> calls (<CODE>${mapname:key|default}</CODE>) +</OL> + +Back-references are <CODE>$</CODE><STRONG>N</STRONG> (<STRONG>N</STRONG>=1..9) identifiers which +will be replaced by the contents of the <STRONG>N</STRONG>th group of the matched +<EM>Pattern</EM>. The server-variables are the same as for the +<EM>TestString</EM> of a <CODE>RewriteCond</CODE> directive. The +mapping-functions come from the <CODE>RewriteMap</CODE> directive and are explained there. These three types of variables are expanded in the order of the above list. -<p> +<P> As already mentioned above, all the rewriting rules are applied to the -<em>Substitution</em> (in the order of definition in the config file). The -URL is <b>completely replaced</b> by the <em>Substitution</em> and the +<EM>Substitution</EM> (in the order of definition in the config file). The +URL is <STRONG>completely replaced</STRONG> by the <EM>Substitution</EM> and the rewriting process goes on until there are no more rules (unless explicitly -terminated by a <code><b>L</b></code> flag - see below). +terminated by a <CODE><STRONG>L</STRONG></CODE> flag - see below). -<p> -There is a special substitution string named '<tt>-</tt>' which means: -<b>NO substitution</b>! Sounds silly? No, it is useful to provide rewriting -rules which <b>only</b> match some URLs but do no substitution, e.g. in -conjunction with the <b>C</b> (chain) flag to be able to have more than one +<P> +There is a special substitution string named '<CODE>-</CODE>' which means: +<STRONG>NO substitution</STRONG>! Sounds silly? No, it is useful to provide rewriting +rules which <STRONG>only</STRONG> match some URLs but do no substitution, <EM>e.g.</EM>, in +conjunction with the <STRONG>C</STRONG> (chain) flag to be able to have more than one pattern to be applied before a substitution occurs. -<p> +<P> 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. -<p> -<table width="70%" border=0 bgcolor="#fff0f0" cellspacing=0 cellpadding=10> -<tr><td> -<b>Notice</b>: There is a special feature. When you prefix a substitution -field with <tt>http://</tt><em>thishost</em>[<em>:thisport</em>] then -<b>mod_rewrite</b> automatically strips it out. This auto-reduction on +<P> +<TABLE WIDTH="70%" BORDER=0 BGCOLOR="#E0E0F0" CELLSPACING=0 CELLPADDING=10> +<TR><TD> +<STRONG>Notice</STRONG>: There is a special feature. When you prefix a substitution +field with <CODE>http://</CODE><EM>thishost</EM>[<EM>:thisport</EM>] then +<STRONG>mod_rewrite</STRONG> 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. -<p> -<b>Remember:</b> An unconditional external redirect to your own server will -not work with the prefix <tt>http://thishost</tt> because of this feature. -To achieve such a self-redirect, you have to use the <b>R</b>-flag (see +</TD></TR> +</TABLE> + +<P> +<TABLE WIDTH="70%" BORDER=0 BGCOLOR="#E0E0F0" CELLSPACING=0 CELLPADDING=10> +<TR><TD> +<STRONG>Remember:</STRONG> An unconditional external redirect to your own server will +not work with the prefix <CODE>http://thishost</CODE> because of this feature. +To achieve such a self-redirect, you have to use the <STRONG>R</STRONG>-flag (see below). -</td></tr> -</table> +</TD></TR> +</TABLE> -<p> -Additionally you can set special flags for <em>Substitution</em> by appending +<P> +Additionally you can set special flags for <EM>Substitution</EM> by appending -<blockquote><strong> -<code>[</code><em>flags</em><code>]</code> -</strong></blockquote> +<BLOCKQUOTE><STRONG> +<CODE>[</CODE><EM>flags</EM><CODE>]</CODE> +</STRONG></BLOCKQUOTE> -as the third argument to the <tt>RewriteRule</tt> directive. <em>Flags</em> is a +as the third argument to the <CODE>RewriteRule</CODE> directive. <EM>Flags</EM> is a comma-separated list of the following flags: -<ul> -<li>'<strong><code>redirect|R</code>[=<i>code</i>]</strong>' (force <a name="redirect"><b>r</b>edirect</a>)<br> - Prefix <em>Substitution</em> - with <code>http://thishost[:thisport]/</code> (which makes the new URL a URI) to - force a external redirection. If no <i>code</i> is given a HTTP response +<UL> +<LI>'<STRONG><CODE>redirect|R</CODE> [=<EM>code</EM>]</STRONG>' (force <A NAME="redirect"><STRONG>r</STRONG>edirect</A>)<BR> + Prefix <EM>Substitution</EM> + with <CODE>http://thishost[:thisport]/</CODE> (which makes the new URL a URI) to + force a external redirection. If no <EM>code</EM> 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: <tt>temp</tt> (default), <tt>permanent</tt>, - <tt>seeother</tt>. + one of the following symbolic names: <CODE>temp</CODE> (default), <CODE>permanent</CODE>, + <CODE>seeother</CODE>. Use it for rules which should - canonicalize the URL and gives it back to the client, e.g. translate - ``<code>/~</code>'' into ``<code>/u/</code>'' or always append a slash to - <code>/u/</code><em>user</em>, etc.<br> - <p> - <b>Notice:</b> When you use this flag, make sure that the + canonicalize the URL and gives it back to the client, <EM>e.g.</EM>, translate + ``<CODE>/~</CODE>'' into ``<CODE>/u/</CODE>'' or always append a slash to + <CODE>/u/</CODE><EM>user</EM>, etc.<BR> + <P> + <STRONG>Notice:</STRONG> 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 <code>http://thishost[:thisport]/</code>, but rewriting goes on. + URL with <CODE>http://thishost[:thisport]/</CODE>, but rewriting goes on. Usually you also want to stop and do the redirection immediately. To stop the rewriting you also have to provide the 'L' flag. -<p> -<li>'<strong><code>forbidden|F</code></strong>' (force URL to be <b>f</b>orbidden)<br> - This forces the current URL to be forbidden, i.e. it immediately sends +<P> +<LI>'<STRONG><CODE>forbidden|F</CODE></STRONG>' (force URL to be <STRONG>f</STRONG>orbidden)<BR> + This forces the current URL to be forbidden, <EM>i.e.</EM>, it immediately sends back a HTTP response of 403 (FORBIDDEN). Use this flag in conjunction with appropriate RewriteConds to conditionally block some URLs. -<p> -<li>'<strong><code>gone|G</code></strong>' (force URL to be <b>g</b>one)<br> - This forces the current URL to be gone, i.e. it immediately sends back a +<P> +<LI>'<STRONG><CODE>gone|G</CODE></STRONG>' (force URL to be <STRONG>g</STRONG>one)<BR> + This forces the current URL to be gone, <EM>i.e.</EM>, it immediately sends back a HTTP response of 410 (GONE). Use this flag to mark no longer existing pages as gone. -<p> -<li>'<strong><code>proxy|P</code></strong>' (force <b>p</b>roxy)<br> +<P> +<LI>'<STRONG><CODE>proxy|P</CODE></STRONG>' (force <STRONG>p</STRONG>roxy)<BR> 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 <tt>http://</tt>) 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 <tt>mod_proxy</tt> directive <tt>ProxyPass</tt>, to map - some remote stuff into the namespace of the local server. - <p> - Notice: <b>You really have to put <tt>ProxyRequests On</tt> into your - server configuration to prevent proxy requests from leading to core-dumps - inside the Apache kernel. If you have not compiled in the proxy module, - then there is no core-dump problem, because mod_rewrite checks for - existence of the proxy module and if lost forbids proxy URLs. </b> -<p> -<li>'<strong><code>last|L</code></strong>' (<b>l</b>ast rule)<br> + request and immediately (<EM>i.e.</EM>, rewriting rule processing stops here) put + through the <A HREF="mod_proxy.html">proxy module</A>. You have to make + sure that the substitution string is a valid URI (<EM>e.g.</EM>, typically starting + with <CODE>http://</CODE><EM>hostname</EM>) 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 <A + HREF="mod_proxy.html#proxypass">ProxyPass</A> directive, to map some + remote stuff into the namespace of the local server. + <P> + 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 <CODE>mod_proxy.c</CODE> is part of the ``<CODE>httpd -l</CODE>'' + output. If yes, this functionality is available to mod_rewrite. If not, + then you first have to rebuild the ``<CODE>httpd</CODE>'' program with + mod_proxy enabled. +<P> +<LI>'<STRONG><CODE>last|L</CODE></STRONG>' (<STRONG>l</STRONG>ast rule)<BR> Stop the rewriting process here and don't apply any more rewriting rules. This corresponds to the Perl - <code>last</code> command or the <code>break</code> command from the C + <CODE>last</CODE> command or the <CODE>break</CODE> command from the C language. Use this flag to prevent the currently rewritten URL from being rewritten further by following rules which may be wrong. For - example, use it to rewrite the root-path URL ('<code>/</code>') to a real - one, e.g. '<code>/e/www/</code>'. -<p> -<li>'<strong><code>next|N</code></strong>' (<b>n</b>ext round)<br> + example, use it to rewrite the root-path URL ('<CODE>/</CODE>') to a real + one, <EM>e.g.</EM>, '<CODE>/e/www/</CODE>'. +<P> +<LI>'<STRONG><CODE>next|N</CODE></STRONG>' (<STRONG>n</STRONG>ext round)<BR> 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 - <code>next</code> command or the <code>continue</code> command from the C - language. Use this flag to restart the rewriting process, i.e. to - immediately go to the top of the loop. <br> - <b>But be careful not to create a deadloop!</b> -<p> -<li>'<strong><code>chain|C</code></strong>' (<b>c</b>hained with next rule)<br> + <CODE>next</CODE> command or the <CODE>continue</CODE> command from the C + language. Use this flag to restart the rewriting process, <EM>i.e.</EM>, to + immediately go to the top of the loop. <BR> + <STRONG>But be careful not to create a deadloop!</STRONG> +<P> +<LI>'<STRONG><CODE>chain|C</CODE></STRONG>' (<STRONG>c</STRONG>hained with next rule)<BR> This flag chains the current rule with the next rule (which itself can - also be chained with its 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 <b>not</b> match, then all following + also be chained with its following rule, <EM>etc.</EM>). This has the following + effect: if a rule matches, then processing continues as usual, <EM>i.e.</EM>, the + flag has no effect. If the rule does <STRONG>not</STRONG> match, then all following chained rules are skipped. For instance, use it to remove the - ``<tt>.www</tt>'' part inside a per-directory rule set when you let an - external redirect happen (where the ``<tt>.www</tt>'' part should not to + ``<CODE>.www</CODE>'' part inside a per-directory rule set when you let an + external redirect happen (where the ``<CODE>.www</CODE>'' part should not to occur!). -<p> -<li>'<strong><code>type|T</code></strong>=<em>mime-type</em>' (force MIME <b>t</b>ype)<br> - Force the MIME-type of the target file to be <em>mime-type</em>. For - instance, this can be used to simulate the old <tt>mod_alias</tt> - directive <tt>ScriptAlias</tt> which internally forces all files inside +<P> +<LI>'<STRONG><CODE>type|T</CODE></STRONG>=<EM>MIME-type</EM>' (force MIME <STRONG>t</STRONG>ype)<BR> + Force the MIME-type of the target file to be <EM>MIME-type</EM>. For + instance, this can be used to simulate the <CODE>mod_alias</CODE> + directive <CODE>ScriptAlias</CODE> which internally forces all files inside the mapped directory to have a MIME type of - ``<tt>application/x-httpd-cgi</tt>''. -<p> -<li>'<strong><code>nosubreq|NS</code></strong>' (used only if <b>n</b>o internal <b>s</b>ub-request)<br> + ``<CODE>application/x-httpd-cgi</CODE>''. +<P> +<LI>'<STRONG><CODE>nosubreq|NS</CODE></STRONG>' (used only if <STRONG>n</STRONG>o internal <STRONG>s</STRONG>ub-request)<BR> 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 <tt>mod_include</tt> tries to find out - information about possible directory default files (<tt>index.xxx</tt>). + occur internally in Apache when <CODE>mod_include</CODE> tries to find out + information about possible directory default files (<CODE>index.xxx</CODE>). 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.<br> - <p> + if the complete set of rules are applied. Use this flag to exclude some rules.<BR> + <P> 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. -<p> -<li>'<strong><code>qsappend|QSA</code></strong>' (<b>q</b>uery <b>s</b>tring - <b>a</b>ppend)<br> +<P> +<LI>'<STRONG><CODE>nocase|NC</CODE></STRONG>' (<STRONG>n</STRONG>o <STRONG>c</STRONG>ase)<BR> + This makes the <EM>Pattern</EM> case-insensitive, <EM>i.e.</EM>, there is + no difference between 'A-Z' and 'a-z' when <EM>Pattern</EM> is matched + against the current URL. +<P> +<LI>'<STRONG><CODE>qsappend|QSA</CODE></STRONG>' (<STRONG>q</STRONG>uery <STRONG>s</STRONG>tring + <STRONG>a</STRONG>ppend)<BR> 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. -<p> -<li>'<strong><code>passthrough|PT</code></strong>' (<b>p</b>ass <b>t</b>hrough to next handler)<br> - This flag forces the rewriting engine to set the <code>uri</code> field - of the internal <code>request_rec</code> structure to the value - of the <code>filename</code> field. This flag is just a hack to be able - to post-process the output of <tt>RewriteRule</tt> directives by - <tt>Alias</tt>, <tt>ScriptAlias</tt>, <tt>Redirect</tt>, etc. directives +<P> +<LI>'<STRONG><CODE>passthrough|PT</CODE></STRONG>' (<STRONG>p</STRONG>ass <STRONG>t</STRONG>hrough to next handler)<BR> + This flag forces the rewriting engine to set the <CODE>uri</CODE> field + of the internal <CODE>request_rec</CODE> structure to the value + of the <CODE>filename</CODE> field. This flag is just a hack to be able + to post-process the output of <CODE>RewriteRule</CODE> directives by + <CODE>Alias</CODE>, <CODE>ScriptAlias</CODE>, <CODE>Redirect</CODE>, <EM>etc.</EM> directives from other URI-to-filename translators. A trivial example to show the semantics: - If you want to rewrite <tt>/abc</tt> to <tt>/def</tt> via the rewriting - engine of <tt>mod_rewrite</tt> and then <tt>/def</tt> to <tt>/ghi</tt> - with <tt>mod_alias</tt>: - <pre> + If you want to rewrite <CODE>/abc</CODE> to <CODE>/def</CODE> via the rewriting + engine of <CODE>mod_rewrite</CODE> and then <CODE>/def</CODE> to <CODE>/ghi</CODE> + with <CODE>mod_alias</CODE>: + <PRE> RewriteRule ^/abc(.*) /def$1 [PT] Alias /def /ghi - </pre> - If you omit the <tt>PT</tt> flag then <tt>mod_rewrite</tt> - will do its job fine, i.e. it rewrites <tt>uri=/abc/...</tt> to - <tt>filename=/def/...</tt> as a full API-compliant URI-to-filename - translator should do. Then <tt>mod_alias</tt> comes and tries to do a + </PRE> + If you omit the <CODE>PT</CODE> flag then <CODE>mod_rewrite</CODE> + will do its job fine, <EM>i.e.</EM>, it rewrites <CODE>uri=/abc/...</CODE> to + <CODE>filename=/def/...</CODE> as a full API-compliant URI-to-filename + translator should do. Then <CODE>mod_alias</CODE> comes and tries to do a URI-to-filename transition which will not work. - <p> - Notice: <b>You have to use this flag if you want to intermix directives - of different modules which contain URL-to-filename translators</b>. The - typical example is the use of <tt>mod_alias</tt> and - <tt>mod_rewrite</tt>.. -<p> -<table width="70%" border=0 bgcolor="#fff0f0" cellspacing=0 cellpadding=10> -<tr><td> + <P> + Notice: <STRONG>You have to use this flag if you want to intermix directives + of different modules which contain URL-to-filename translators</STRONG>. The + typical example is the use of <CODE>mod_alias</CODE> and + <CODE>mod_rewrite</CODE>.. +<P> +<TABLE WIDTH="70%" BORDER=0 BGCOLOR="#E0E0F0" CELLSPACING=0 CELLPADDING=10> +<TR><TD> <font size=-1> - <b>For the Apache hackers:</b><br> + <STRONG>Notice - For the Apache hackers:</STRONG><BR> 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 hooks into Apache version 2.0. -</font> -</td></tr> -</table> -<p> -<li>'<strong><code>skip|S</code></strong>=<em>num</em>' (<b>s</b>kip next rule(s))<br> - This flag forces the rewriting engine to skip the next <em>num</em> rules +</FONT> +</TD></TR> +</TABLE> +<P> +<LI>'<STRONG><CODE>skip|S</CODE></STRONG>=<EM>num</EM>' (<STRONG>s</STRONG>kip next rule(s))<BR> + This flag forces the rewriting engine to skip the next <EM>num</EM> 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 - a <tt>skip=N</tt> where N is the number of rules in the else-clause. - (This is <b>not</b> the same as the 'chain|C' flag!) -<p> -<li>'<strong><code>env|E=</code></strong><i>VAR</i>:<i>VAL</i>' (set <b>e</b>nvironment variable)<br> - This forces an environment variable named <i>VAR</i> to be set to the value - <i>VAL</i>, where <i>VAL</i> can contain regexp backreferences <tt>$N</tt> - which will be expanded. You can use this flag more than once to set more - than one variable. The variables can be later dereferenced at a lot of - situations, but the usual location will be from within XSSI (via - <tt><!--#echo var="VAR"--></tt>) or CGI (e.g. <tt>$ENV{'VAR'}</tt>). - But additionally you can also dereference it in a following RewriteCond - pattern via <tt>%{ENV:VAR}</tt>. Use this to strip but remember - information from URLs. -</ul> - -<p> -<table width="70%" border=0 bgcolor="#fff0f0" cellspacing=0 cellpadding=10> -<tr><td> -Remember: Never forget that <em>Pattern</em> gets applied to a complete URL -in per-server configuration files. <b>But in per-directory configuration + a <CODE>skip=N</CODE> where N is the number of rules in the else-clause. + (This is <STRONG>not</STRONG> the same as the 'chain|C' flag!) +<P> +<LI>'<STRONG><CODE>env|E=</CODE></STRONG><EM>VAR</EM>:<EM>VAL</EM>' (set <STRONG>e</STRONG>nvironment variable)<BR> + This forces an environment variable named <EM>VAR</EM> to be set to the + value <EM>VAL</EM>, where <EM>VAL</EM> can contain regexp backreferences + <CODE>$N</CODE> and <CODE>%N</CODE> which will be expanded. You can use this flag + more than once to set more than one variable. The variables can be later + dereferenced at a lot of situations, but the usual location will be from + within XSSI (via <CODE><!--#echo var="VAR"--></CODE>) or CGI (<EM>e.g.</EM> + <CODE>$ENV{'VAR'}</CODE>). But additionally you can also dereference it in a + following RewriteCond pattern via <CODE>%{ENV:VAR}</CODE>. Use this to strip + but remember information from URLs. +</UL> + +<P> +<TABLE WIDTH="70%" BORDER=0 BGCOLOR="#E0E0F0" CELLSPACING=0 CELLPADDING=10> +<TR><TD> +<STRONG>Notice:</STRONG> Never forget that <EM>Pattern</EM> gets applied to a complete URL +in per-server configuration files. <STRONG>But in per-directory configuration files, the per-directory prefix (which always is the same for a specific -directory!) gets automatically <em>removed</em> for the pattern matching and -automatically <em>added</em> after the substitution has been done.</b> This feature is +directory!) gets automatically <EM>removed</EM> for the pattern matching and +automatically <EM>added</EM> after the substitution has been done.</STRONG> 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. -<p> +<P> There is one exception: If a substitution string starts with -``<tt>http://</tt>'' then the directory prefix will be <b>not</b> added and a -external redirect or proxy throughput (if flag <b>P</b> is used!) is forced! -</td></tr> -</table> - -<p> -<table width="70%" border=0 bgcolor="#fff0f0" cellspacing=0 cellpadding=10> -<tr><td> -Notice! To enable the rewriting engine for per-directory configuration files -you need to set ``<tt>RewriteEngine On</tt>'' in these files <b>and</b> -``<tt>Option FollowSymLinks</tt>'' enabled. If your administrator has -disabled override of <tt>FollowSymLinks</tt> for a user's directory, then +``<CODE>http://</CODE>'' then the directory prefix will be <STRONG>not</STRONG> added and a +external redirect or proxy throughput (if flag <STRONG>P</STRONG> is used!) is forced! +</TD></TR> +</TABLE> + +<P> +<TABLE WIDTH="70%" BORDER=0 BGCOLOR="#E0E0F0" CELLSPACING=0 CELLPADDING=10> +<TR><TD> +<STRONG>Notice:</STRONG> To enable the rewriting engine for per-directory configuration files +you need to set ``<CODE>RewriteEngine On</CODE>'' in these files <STRONG>and</STRONG> +``<CODE>Option FollowSymLinks</CODE>'' enabled. If your administrator has +disabled override of <CODE>FollowSymLinks</CODE> for a user's directory, then you cannot use the rewriting engine. This restriction is needed for security reasons. -</td></tr> -</table> +</TD></TR> +</TABLE> -<p> +<P> Here are all possible substitution combinations and their meanings: -<p> -<b>Inside per-server configuration (<tt>httpd.conf</tt>)<br> -for request ``<tt>GET /somepath/pathinfo</tt>'':</b><br> +<P> +<STRONG>Inside per-server configuration (<CODE>httpd.conf</CODE>)<BR> +for request ``<CODE>GET /somepath/pathinfo</CODE>'':</STRONG><BR> -<p> -<table bgcolor="#f0f0f0" cellspacing=0 cellpadding=5> -<tr> -<td> -<pre> -<b>Given Rule</b> <b>Resulting Substitution</b> +<P> +<TABLE BGCOLOR="#F0F0F0" CELLSPACING=0 CELLPADDING=5> +<TR> +<TD> +<PRE> +<STRONG>Given Rule</STRONG> <STRONG>Resulting Substitution</STRONG> ---------------------------------------------- ---------------------------------- ^/somepath(.*) otherpath$1 not supported, because invalid! @@ -1094,23 +1737,23 @@ for request ``<tt>GET /somepath/pathinfo</tt>'':</b><br> ^/somepath(.*) http://otherhost/otherpath$1 [P] http://otherhost/otherpath/pathinfo via internal proxy -</pre> -</td> -</tr> -</table> - -<p> -<b>Inside per-directory configuration for <tt>/somepath</tt><br> -(i.e. file <tt>.htaccess</tt> in dir <tt>/physical/path/to/somepath</tt> containing -<tt>RewriteBase /somepath</tt>)<br> for -request ``<tt>GET /somepath/localpath/pathinfo</tt>'':</b><br> - -<p> -<table bgcolor="#f0f0f0" cellspacing=0 cellpadding=5> -<tr> -<td> -<pre> -<b>Given Rule</b> <b>Resulting Substitution</b> +</PRE> +</TD> +</TR> +</TABLE> + +<P> +<STRONG>Inside per-directory configuration for <CODE>/somepath</CODE><BR> +(<EM>i.e.</EM>, file <CODE>.htaccess</CODE> in dir <CODE>/physical/path/to/somepath</CODE> containing +<CODE>RewriteBase /somepath</CODE>)<BR> for +request ``<CODE>GET /somepath/localpath/pathinfo</CODE>'':</STRONG><BR> + +<P> +<TABLE BGCOLOR="#F0F0F0" CELLSPACING=0 CELLPADDING=5> +<TR> +<TD> +<PRE> +<STRONG>Given Rule</STRONG> <STRONG>Resulting Substitution</STRONG> ---------------------------------------------- ---------------------------------- ^localpath(.*) otherpath$1 /somepath/otherpath/pathinfo @@ -1142,90 +1785,103 @@ request ``<tt>GET /somepath/localpath/pathinfo</tt>'':</b><br> ^localpath(.*) http://otherhost/otherpath$1 [P] http://otherhost/otherpath/pathinfo via internal proxy -</pre> -</td> -</tr> -</table> - - -<p> -<b>Example:</b> -<p> -<blockquote> +</PRE> +</TD> +</TR> +</TABLE> + +<P> +<STRONG>Example:</STRONG> +<P> +<BLOCKQUOTE> We want to rewrite URLs of the form -<blockquote> -<code>/</code> <em>Language</em> -<code>/~</code> <em>Realname</em> -<code>/.../</code> <em>File</em> -</blockquote> +<BLOCKQUOTE> +<CODE>/</CODE> <EM>Language</EM> +<CODE>/~</CODE> <EM>Realname</EM> +<CODE>/.../</CODE> <EM>File</EM> +</BLOCKQUOTE> into -<blockquote> -<code>/u/</code> <em>Username</em> -<code>/.../</code> <em>File</em> -<code>.</code> <em>Language</em> -</blockquote> -<p> +<BLOCKQUOTE> +<CODE>/u/</CODE> <EM>Username</EM> +<CODE>/.../</CODE> <EM>File</EM> +<CODE>.</CODE> <EM>Language</EM> +</BLOCKQUOTE> +<P> We take the rewrite mapfile from above and save it under -<code>/anywhere/map.real-to-user</code>. Then we only have to add the +<CODE>/path/to/file/map.txt</CODE>. Then we only have to add the following lines to the Apache server configuration file: -<blockquote> -<pre> -RewriteLog /anywhere/rewrite.log -RewriteMap real-to-user txt:/anywhere/map.real-to-host +<BLOCKQUOTE> +<PRE> +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 -</pre> -</blockquote> -</blockquote> +</PRE> +</BLOCKQUOTE> +</BLOCKQUOTE> -<!--%hypertext --> -<hr> -<!--/%hypertext --> +<P> +<HR NOSHADE SIZE=1> -<center> -<a name="Additional"> -<h1>Additional Features</h1> -</a> -</center> +<CENTER> +<H1><A NAME="Miscelleneous">Miscellaneous</A></H1> +</CENTER> -<a name="EnvVar"> -<h2>Environment Variables</h2> -</a> +<P> +<HR NOSHADE SIZE=1> + +<H2><A NAME="EnvVar">Environment Variables</A></H2> This module keeps track of two additional (non-standard) CGI/SSI environment -variables named <tt>SCRIPT_URL</tt> and <tt>SCRIPT_URI</tt>. These contain -the <em>logical</em> Web-view to the current resource, while the standard CGI/SSI -variables <tt>SCRIPT_NAME</tt> and <tt>SCRIPT_FILENAME</tt> contain the -<em>physical</em> System-view. - -<p> -Notice: These variables hold the URI/URL <em>as they were initially -requested</em>, i.e. in a state <em>before</em> any rewriting. This is +variables named <CODE>SCRIPT_URL</CODE> and <CODE>SCRIPT_URI</CODE>. These contain +the <EM>logical</EM> Web-view to the current resource, while the standard CGI/SSI +variables <CODE>SCRIPT_NAME</CODE> and <CODE>SCRIPT_FILENAME</CODE> contain the +<EM>physical</EM> System-view. + +<P> +Notice: These variables hold the URI/URL <EM>as they were initially +requested</EM>, <EM>i.e.</EM>, in a state <EM>before</EM> any rewriting. This is important because the rewriting process is primarily used to rewrite logical URLs to physical pathnames. -<p> -<b>Example:</b> +<P> +<STRONG>Example:</STRONG> -<blockquote> -<pre> -SCRIPT_NAME=/v/sw/free/lib/apache/global/u/rse/.www/index.html +<BLOCKQUOTE> +<PRE> +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://en2.en.sdm.de/u/rse/ -</pre> -</blockquote> +SCRIPT_URI=http://en1.engelschall.com/u/rse/ +</PRE> +</BLOCKQUOTE> + +<P> +<HR NOSHADE SIZE=1> +<H2><A NAME="Solutions">Practical Solutions</A></H2> + +There is a comprehensive collection of practical solutions for URL-based +problems available by the author of mod_rewrite. Here you will find real-life +rulesets and additional information. + +<BLOCKQUOTE> +<STRONG>Apache URL Rewriting Guide</STRONG><BR> +<STRONG><A HREF="http://www.engelschall.com/pw/apache/rewriteguide/" + >http://www.engelschall.com/pw/apache/rewriteguide/</A></STRONG> +</BLOCKQUOTE> <HR> + <H3 ALIGN="CENTER"> - Apache HTTP Server Version 1.2 + Apache HTTP Server Version 1.3 </H3> <A HREF="./"><IMG SRC="../images/index.gif" ALT="Index"></A> <A HREF="../"><IMG SRC="../images/home.gif" ALT="Home"></A> +</BLOCKQUOTE><!-- page indentation --> </BODY> </HTML> <!--/%hypertext --> diff --git a/usr.sbin/httpd/htdocs/manual/new_features_1_3.html b/usr.sbin/httpd/htdocs/manual/new_features_1_3.html index 0963caa9d90..2b3c0d6a135 100644 --- a/usr.sbin/httpd/htdocs/manual/new_features_1_3.html +++ b/usr.sbin/httpd/htdocs/manual/new_features_1_3.html @@ -131,6 +131,24 @@ documentation</A> for more information. <H2><A NAME="config">Configuration Enhancements</A></H2> <DL> +<DT><STRONG>Unified Server Configuration Files</STRONG></DT> +<DD><EM>(Apache 1.3.4)</EM> The contents of the three + server configuration files (<SAMP>httpd.conf</SAMP>, + <SAMP>srm.conf</SAMP>, and <SAMP>access.conf</SAMP>) have + been merged into a single <SAMP>httpd.conf</SAMP> file. + The <SAMP>srm.conf</SAMP> and <SAMP>access.conf</SAMP> files + are now empty except for comments directing the Webmaster + to look in <SAMP>httpd.conf</SAMP>. In addition, the + merged <SAMP>httpd.conf</SAMP> file has been restructured + to allow directives to appear in a hopefully more + intuitive and meaningful order. +</DD> +<DT><STRONG>Continuation Lines in config files</STRONG></DT> +<DD>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. +</DD> <DT><STRONG>Apache Autoconf-style Interface (APACI)</STRONG> <DD>Until Apache 1.3 there was no real out-of-the-box batch-capable build and installation procedure for the complete Apache @@ -141,7 +159,10 @@ documentation</A> for more information. <CODE>src/Configure</CODE> 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. + of new options for flexibly customizing Apache.<BR> + <STRONG>Note:</STRONG> The default installation layout has changed + for Apache 1.3.4. See the files <CODE>README.configure</CODE> and + <CODE>INSTALL</CODE> for more information. <DT><STRONG>APache eXtenSion (APXS) support tool</STRONG> <DD>Now that Apache provides full support for loading modules under @@ -193,6 +214,13 @@ documentation</A> for more information. <H3><A NAME="mod">Module Enhancements</A></H3> <DL> +<DT><A HREF="mod/mod_negotiation.html"><STRONG>Improved mod_negotiation + </STRONG></A><BR> +<DD>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. + <DT><A HREF="mod/mod_speling.html"><STRONG>NEW - Spelling correction module</STRONG></A><BR> <DD>This optional module corrects frequently occurring spelling and diff --git a/usr.sbin/httpd/htdocs/manual/stopping.html b/usr.sbin/httpd/htdocs/manual/stopping.html index 1db5e588609..e5200a31da9 100644 --- a/usr.sbin/httpd/htdocs/manual/stopping.html +++ b/usr.sbin/httpd/htdocs/manual/stopping.html @@ -15,106 +15,118 @@ <DIV ALIGN="CENTER"> <IMG SRC="images/sub.gif" ALT="[APACHE DOCUMENTATION]"> <H3> - Apache HTTP Server Version 1.2 + Apache HTTP Server Version 1.3 </H3> </DIV> -<h1 ALIGN="CENTER">Stopping and Restarting Apache</h1> +<H1 ALIGN="CENTER">Stopping and Restarting Apache</H1> -<p>You will notice many <code>httpd</code> executables running on your system, +<P>This document covers stopping and restarting Apache on Unix +only. Windows users should see <A HREF="windows.html#signal">Signalling +Apache when running</A>.</P> + +<P>You will notice many <CODE>httpd</CODE> executables running on your system, but you should not send signals to any of them except the parent, whose -pid is in the <a href="mod/core.html#pidfile">PidFile</a>. That is to +pid is in the <A HREF="mod/core.html#pidfile">PidFile</A>. 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: -<code>TERM</code>, <code>HUP</code>, and <code>USR1</code>, which will +<CODE>TERM</CODE>, <CODE>HUP</CODE>, and <CODE>USR1</CODE>, which will be described in a moment. -<p>To send a signal to the parent you should issue a command such as: -<blockquote><pre> - kill -TERM `cat /usr/local/etc/httpd/logs/httpd.pid` -</pre></blockquote> +<P>To send a signal to the parent you should issue a command such as: +<BLOCKQUOTE><PRE> + kill -TERM `cat /usr/local/apache/logs/httpd.pid` +</PRE></BLOCKQUOTE> You can read about its progress by issuing: -<blockquote><pre> - tail -f /usr/local/etc/httpd/logs/error_log -</pre></blockquote> +<BLOCKQUOTE><PRE> + tail -f /usr/local/apache/logs/error_log +</PRE></BLOCKQUOTE> Modify those examples to match your -<a href="mod/core.html#serverroot">ServerRoot</a> and -<a href="mod/core.html#pidfile">PidFile</a> settings. +<A HREF="mod/core.html#serverroot">ServerRoot</A> and +<A HREF="mod/core.html#pidfile">PidFile</A> settings. + +<P>As of Apache 1.3 we provide a script <CODE>src/support/apachectl</CODE> +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. -<h3>TERM Signal: stop now</h3> +<H3>TERM Signal: stop now</H3> -<p>Sending the <code>TERM</code> signal to the parent causes it to +<P>Sending the <CODE>TERM</CODE> 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. -<h3>HUP Signal: restart now</h3> +<H3>HUP Signal: restart now</H3> -<p>Sending the <code>HUP</code> signal to the parent causes it to kill off -its children like in <code>TERM</code> but the parent doesn't exit. It +<P>Sending the <CODE>HUP</CODE> signal to the parent causes it to kill off +its children like in <CODE>TERM</CODE> 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. -<p>Users of the -<a href="mod/mod_status.html">status module</a> +<P>Users of the +<A HREF="mod/mod_status.html">status module</A> will notice that the server statistics are -set to zero when a <code>HUP</code> is sent. +set to zero when a <CODE>HUP</CODE> is sent. -<p><b>Note:</b> If your configuration file has errors in it when you issue a +<P><STRONG>Note:</STRONG> 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. -<h3>USR1 Signal: graceful restart</h3> +<H3>USR1 Signal: graceful restart</H3> -<p><b>Note:</b> prior to release 1.2b9 this code is quite unstable and -shouldn't be used at all. +<P><STRONG>Note:</STRONG> prior to release 1.2b9 this code is quite unstable +and shouldn't be used at all. -<p>The <code>USR1</code> signal causes the parent process to <i>advise</i> +<P>The <CODE>USR1</CODE> signal causes the parent process to <EM>advise</EM> 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 <i>generation</i> of the +replaces it with a child from the new <EM>generation</EM> of the configuration, which begins serving new requests immediately. -<p>This code is designed to always respect the -<a href="mod/core.html#maxclients">MaxClients</a>, -<a href="mod/core.html#minspareservers">MinSpareServers</a>, -and <a href="mod/core.html#maxspareservers">MaxSpareServers</a> settings. -Furthermore, it respects <a href="mod/core.html#startservers">StartServers</a> +<P>This code is designed to always respect the +<A HREF="mod/core.html#maxclients">MaxClients</A>, +<A HREF="mod/core.html#minspareservers">MinSpareServers</A>, +and <A HREF="mod/core.html#maxspareservers">MaxSpareServers</A> settings. +Furthermore, it respects <A HREF="mod/core.html#startservers">StartServers</A> 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. -<p>Users of the -<a href="mod/mod_status.html">status module</a> +<P>Users of the +<A HREF="mod/mod_status.html">status module</A> will notice that the server statistics -are <b>not</b> set to zero when a <code>USR1</code> is sent. The code +are <STRONG>not</STRONG> set to zero when a <CODE>USR1</CODE> 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 <i>scoreboard</i> used to keep track +to do this it has to keep the <EM>scoreboard</EM> used to keep track of all children across generations. -<p>The status module will also use a <code>G</code> to indicate those +<P>The status module will also use a <CODE>G</CODE> to indicate those children which are still serving requests started before the graceful restart was given. -<p>At present there is no way for a log rotation script using -<code>USR1</code> to know for certain that all children writing the +<P>At present there is no way for a log rotation script using +<CODE>USR1</CODE> 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 <code>USR1</code> signal before you do anything with the +after sending the <CODE>USR1</CODE> 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. -<p><b>Note:</b> If your configuration file has errors in it when you issue a +<P><STRONG>Note:</STRONG> 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 @@ -128,9 +140,9 @@ 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. -<h3>Appendix: signals and race conditions</h3> +<H3>Appendix: signals and race conditions</H3> -<p>Prior to Apache 1.2b9 there were several <i>race conditions</i> +<P>Prior to Apache 1.2b9 there were several <EM>race conditions</EM> 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 @@ -138,11 +150,11 @@ 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. -<p>Architectures that use an on disk -<a href="mod/core.html#scoreboardfile">ScoreBoardFile</a> +<P>Architectures that use an on disk +<A HREF="mod/core.html#scoreboardfile">ScoreBoardFile</A> have the potential to corrupt their scoreboards. This can result in -the "bind: Address already in use" (after <code>HUP</code>) or -"long lost child came home!" (after <code>USR1</code>). The former is +the "bind: Address already in use" (after <CODE>HUP</CODE>) or +"long lost child came home!" (after <CODE>USR1</CODE>). 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 @@ -150,13 +162,13 @@ 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. -<p><code>NEXT</code> and <code>MACHTEN</code> (68k only) have small race +<P><CODE>NEXT</CODE> and <CODE>MACHTEN</CODE> (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. <!-- they don't have sigaction, or we're not using it -djg --> -<p>All architectures have a small race condition in each child involving +<P>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 @@ -168,9 +180,9 @@ clients successfully browsed the site without getting broken images or empty documents. <HR> -<H3 ALIGN="CENTER"> - Apache HTTP Server Version 1.2 -</H3> + <H3 ALIGN="CENTER"> + Apache HTTP Server Version 1.3 + </H3> <A HREF="./"><IMG SRC="images/index.gif" ALT="Index"></A> diff --git a/usr.sbin/httpd/htdocs/manual/suexec.html b/usr.sbin/httpd/htdocs/manual/suexec.html index fb77589b83b..7be9878127e 100644 --- a/usr.sbin/httpd/htdocs/manual/suexec.html +++ b/usr.sbin/httpd/htdocs/manual/suexec.html @@ -14,7 +14,7 @@ <DIV ALIGN="CENTER"> <IMG SRC="images/sub.gif" ALT="[APACHE DOCUMENTATION]"> <H3> - Apache HTTP Server Version 1.2 + Apache HTTP Server Version 1.3 </H3> </DIV> @@ -23,15 +23,16 @@ <P ALIGN="LEFT"> <OL> - <LH><BIG><STRONG>CONTENTS</STRONG></BIG></LH> + <LI><BIG><STRONG>CONTENTS</STRONG></BIG></LI> <LI><A HREF="#what">What is suEXEC?</A></LI> <LI><A HREF="#before">Before we begin.</A></LI> <LI><A HREF="#model">suEXEC Security Model.</A></LI> <LI><A HREF="#install">Configuring & Installing suEXEC</A></LI> <LI><A HREF="#enable">Enabling & Disabling suEXEC</A></LI> + <LI><A HREF="#usage">Using suEXEC</A></LI> <LI><A HREF="#debug">Debugging suEXEC</A></LI> <LI><A HREF="#jabberwock">Beware the Jabberwock: Warnings & - Examples</A></LI> + Examples</A></LI> </OL> </P> @@ -49,9 +50,9 @@ 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 +with managing setuid root programs and the security issues they present, we highly recommend that you not consider using suEXEC. -</P> +</P> <P ALIGN="CENTER"> <STRONG><A HREF="suexec.html">BACK TO CONTENTS</A></STRONG> @@ -71,7 +72,7 @@ capable of supporting suEXEC, may differ in their configuration. </P> <P ALIGN="LEFT"> -Second, it is assumed you are familiar with some basic concepts of your +Second, it is assumed you are familiar with some basic concepts of your computer's security and its administration. This involves an understanding of <STRONG>setuid/setgid</STRONG> operations and the various effects they may have on your system and its level of security. @@ -80,21 +81,25 @@ may have on your system and its level of security. <P ALIGN="LEFT"> Third, it is assumed that you are using an <STRONG>unmodified</STRONG> 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 -<STRONG>highly</STRONG> recommended you not alter the suEXEC code unless you +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 +<STRONG>highly</STRONG> 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. </P> <P ALIGN="LEFT"> -Fourth, and last, it has been the decision of the Apache Group to +Fourth, and last, it has been the decision of the Apache Group to <STRONG>NOT</STRONG> make suEXEC part of the default installation of Apache. -To this end, suEXEC configuration is a manual process requiring of the -administrator careful attention to details. It is through this process -that the Apache Group hopes to limit suEXEC installation only to those -who are determined to use it. +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. </P> <P ALIGN="LEFT"> @@ -118,7 +123,7 @@ are taken to ensure your system's security. 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 +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. </P> @@ -126,124 +131,150 @@ 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: - <OL> - <LI><STRONG>Was the wrapper called with the proper number of arguments?</STRONG> - <BLOCKQUOTE> - 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. - </BLOCKQUOTE> - </LI> - <LI><STRONG>Is the user executing this wrapper a valid user of this system?</STRONG> - <BLOCKQUOTE> - This is to ensure that the user executing the wrapper is truly a user of the system. - </BLOCKQUOTE> - </LI> - <LI><STRONG>Is this valid user allowed to run the wrapper?</STRONG> - <BLOCKQUOTE> - Is this user the user allowed to run this wrapper? Only one user (the Apache - user) is allowed to execute this program. - </BLOCKQUOTE> - </LI> - <LI><STRONG>Does the target program have an unsafe hierarchical reference?</STRONG> - <BLOCKQUOTE> - Does the target program contain a leading '/' or have a '..' backreference? These - are not allowed; the target program must reside within the Apache webspace. - </BLOCKQUOTE> - </LI> - <LI><STRONG>Is the target user name valid?</STRONG> - <BLOCKQUOTE> - Does the target user exist? - </BLOCKQUOTE> - </LI> - <LI><STRONG>Is the target group name valid?</STRONG> - <BLOCKQUOTE> - Does the target group exist? - </BLOCKQUOTE> - </LI> - <LI><STRONG>Is the target user <EM>NOT</EM> superuser?</STRONG> - <BLOCKQUOTE> - Presently, suEXEC does not allow 'root' to execute CGI/SSI programs. - </BLOCKQUOTE> - </LI> - <LI><STRONG>Is the target userid <EM>ABOVE</EM> the minimum ID number?</STRONG> - <BLOCKQUOTE> - 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. - </BLOCKQUOTE> - </LI> - <LI><STRONG>Is the target group <EM>NOT</EM> the superuser group?</STRONG> - <BLOCKQUOTE> - Presently, suEXEC does not allow the 'root' group to execute CGI/SSI programs. - </BLOCKQUOTE> - </LI> - <LI><STRONG>Is the target groupid <EM>ABOVE</EM> the minimum ID number?</STRONG> - <BLOCKQUOTE> - 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. - </BLOCKQUOTE> - </LI> - <LI><STRONG>Can the wrapper successfully become the target user and group?</STRONG> - <BLOCKQUOTE> - 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. - </BLOCKQUOTE> - </LI> - <LI><STRONG>Does the directory in which the program resides exist?</STRONG> - <BLOCKQUOTE> - If it doesn't exist, it can't very well contain files. - </BLOCKQUOTE> - </LI> - <LI><STRONG>Is the directory within the Apache webspace?</STRONG> - <BLOCKQUOTE> - 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? - </BLOCKQUOTE> - </LI> - <LI><STRONG>Is the directory <EM>NOT</EM> writable by anyone else?</STRONG> - <BLOCKQUOTE> - We don't want to open up the directory to others; only the owner user may be able - to alter this directories contents. - </BLOCKQUOTE> - </LI> - <LI><STRONG>Does the target program exist?</STRONG> - <BLOCKQUOTE> - If it doesn't exists, it can't very well be executed. - </BLOCKQUOTE> - </LI> - <LI><STRONG>Is the target program <EM>NOT</EM> writable by anyone else?</STRONG> - <BLOCKQUOTE> - We don't want to give anyone other than the owner the ability to change the program. - </BLOCKQUOTE> - </LI> - <LI><STRONG>Is the target program <EM>NOT</EM> setuid or setgid?</STRONG> - <BLOCKQUOTE> - We do not want to execute programs that will then change our UID/GID again. - </BLOCKQUOTE> - </LI> - <LI><STRONG>Is the target user/group the same as the program's user/group?</STRONG> - <BLOCKQUOTE> - Is the user the owner of the file? - </BLOCKQUOTE> - </LI> - <LI><STRONG>Can we successfully clean the process environment to ensure safe operations?</STRONG> - <BLOCKQUOTE> - 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). - </BLOCKQUOTE> - </LI> - <LI><STRONG>Can we successfully become the target program and execute?</STRONG> - <BLOCKQUOTE> - Here is where suEXEC ends and the target program begins. - </BLOCKQUOTE> - </LI> - </OL> +<OL> + <LI><STRONG>Was the wrapper called with the proper number of + arguments?</STRONG> + <BLOCKQUOTE> + 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. + </BLOCKQUOTE> + </LI> + <LI><STRONG>Is the user executing this wrapper a valid user of this + system?</STRONG> + <BLOCKQUOTE> + This is to ensure that the user executing the wrapper is truly a user of the + system. + </BLOCKQUOTE> + </LI> + <LI><STRONG>Is this valid user allowed to run the wrapper?</STRONG> + <BLOCKQUOTE> + Is this user the user allowed to run this wrapper? Only one user (the + Apache user) is allowed to execute this program. + </BLOCKQUOTE> + </LI> + <LI><STRONG>Does the target program have an unsafe hierarchical + reference?</STRONG> + <BLOCKQUOTE> + Does the target program contain a leading '/' or have a '..' backreference? + These are not allowed; the target program must reside within the Apache + webspace. + </BLOCKQUOTE> + </LI> + <LI><STRONG>Is the target user name valid?</STRONG> + <BLOCKQUOTE> + Does the target user exist? + </BLOCKQUOTE> + </LI> + <LI><STRONG>Is the target group name valid?</STRONG> + <BLOCKQUOTE> + Does the target group exist? + </BLOCKQUOTE> + </LI> + <LI><STRONG>Is the target user <EM>NOT</EM> superuser?</STRONG> + <BLOCKQUOTE> + Presently, suEXEC does not allow 'root' to execute CGI/SSI programs. + </BLOCKQUOTE> + </LI> + <LI><STRONG>Is the target userid <EM>ABOVE</EM> the minimum ID + number?</STRONG> + <BLOCKQUOTE> + 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. + </BLOCKQUOTE> + </LI> + <LI><STRONG>Is the target group <EM>NOT</EM> the superuser group?</STRONG> + <BLOCKQUOTE> + Presently, suEXEC does not allow the 'root' group to execute CGI/SSI + programs. + </BLOCKQUOTE> + </LI> + <LI><STRONG>Is the target groupid <EM>ABOVE</EM> the minimum ID + number?</STRONG> + <BLOCKQUOTE> + 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. + </BLOCKQUOTE> + </LI> + <LI><STRONG>Can the wrapper successfully become the target user and + group?</STRONG> + <BLOCKQUOTE> + 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. + </BLOCKQUOTE> + </LI> + <LI><STRONG>Does the directory in which the program resides exist?</STRONG> + <BLOCKQUOTE> + If it doesn't exist, it can't very well contain files. + </BLOCKQUOTE> + </LI> + <LI><STRONG>Is the directory within the Apache webspace?</STRONG> + <BLOCKQUOTE> + 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? + </BLOCKQUOTE> + </LI> + <LI><STRONG>Is the directory <EM>NOT</EM> writable by anyone else?</STRONG> + <BLOCKQUOTE> + We don't want to open up the directory to others; only the owner user + may be able + to alter this directories contents. + </BLOCKQUOTE> + </LI> + <LI><STRONG>Does the target program exist?</STRONG> + <BLOCKQUOTE> + If it doesn't exists, it can't very well be executed. + </BLOCKQUOTE> + </LI> + <LI><STRONG>Is the target program <EM>NOT</EM> writable by anyone + else?</STRONG> + <BLOCKQUOTE> + We don't want to give anyone other than the owner the ability to + change the program. + </BLOCKQUOTE> + </LI> + <LI><STRONG>Is the target program <EM>NOT</EM> setuid or setgid?</STRONG> + <BLOCKQUOTE> + We do not want to execute programs that will then change our UID/GID again. + </BLOCKQUOTE> + </LI> + <LI><STRONG>Is the target user/group the same as the program's + user/group?</STRONG> + <BLOCKQUOTE> + Is the user the owner of the file? + </BLOCKQUOTE> + </LI> + <LI><STRONG>Can we successfully clean the process environment to + ensure safe operations?</STRONG> + <BLOCKQUOTE> + 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). + </BLOCKQUOTE> + </LI> + <LI><STRONG>Can we successfully become the target program and + execute?</STRONG> + <BLOCKQUOTE> + Here is where suEXEC ends and the target program begins. + </BLOCKQUOTE> + </LI> +</OL> </P> <P ALIGN="LEFT"> @@ -255,8 +286,9 @@ in mind. <P ALIGN="LEFT"> 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 <A HREF="#beware">"Beware the Jabberwock"</A> +in regards to server configuration, as well as what security risks can be +avoided with a proper suEXEC setup, see the +<A HREF="#jabberwock">"Beware the Jabberwock"</A> section of this document. </P> @@ -266,184 +298,162 @@ section of this document. <H3><A NAME="install">Configuring & Installing suEXEC</A></H3> <P ALIGN="LEFT"> -Here's where we begin the fun. The configuration and installation of suEXEC is -a four step process: edit the suEXEC header file, compile suEXEC, place the -suEXEC binary in its proper location, and configure Apache for use with suEXEC. -</P> - -<P ALIGN="LEFT"> -<STRONG>EDITING THE SUEXEC HEADER FILE</STRONG><BR> -- From the top-level of the Apache source tree, type: -<STRONG><code>cd support [ENTER]</code></STRONG> -</P> - -<P ALIGN="LEFT"> -Edit the <code>suexec.h</code> file and change the following macros to -match your local Apache installation. -</P> - -<P ALIGN="LEFT"> -<EM>From support/suexec.h</EM> +Here's where we begin the fun. If you use Apache 1.2 or prefer to configure +Apache 1.3 with the "<CODE>src/Configure</CODE>" script you have to edit +the suEXEC header file and install the binary in its proper location +manually. This procedure is described in an +<A HREF="suexec_1_2.html">extra document</A>. +The following sections describe the configuration and installation +for Apache 1.3 with the AutoConf-style interface (APACI). +</P> + +<P ALIGN="LEFT"> +<STRONG>APACI's suEXEC configuration options</STRONG><BR> +<DL> +<DT><CODE>--enable-suexec</CODE> +<DD>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. +<DT><CODE>--suexec-caller=<EM>UID</EM></CODE> +<DD>The <A HREF="mod/core.html#user">username</A> under which + Apache normally runs. + This is the only user allowed to execute this program. +<DT><CODE>--suexec-docroot=<EM>DIR</EM></CODE> +<DD>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", <EM>e.g.</EM> if you configure with + "<CODE>--datadir=/home/apache</CODE>" the directory + "/home/apache/htdocs" is used as document root for + the suEXEC wrapper. +<DT><CODE>--suexec-logfile=<EM>FILE</EM></CODE> +<DD>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). +<DT><CODE>--suexec-userdir=<EM>DIR</EM></CODE> +<DD>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". + <BR> + 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. <STRONG>If this is not defined + properly, "~userdir" cgi requests will not work!</STRONG> +<DT><CODE>--suexec-uidmin=<EM>UID</EM></CODE> +<DD>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. +<DT><CODE>--suexec-gidmin=<EM>GID</EM></CODE> +<DD>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. +<DT><CODE>--suexec-safepath=<EM>PATH</EM></CODE> +<DD>Define a safe PATH environment to pass to CGI executables. + Default value is "/usr/local/bin:/usr/bin:/bin". +</DL> +</P> + +<P ALIGN="LEFT"> +<STRONG>Checking your suEXEC setup</STRONG><BR> +Before you compile and install the suEXEC wrapper you can check +the configuration with the --layout option. +<BR> +Example output: <PRE> - /* - * 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/etc/httpd/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/etc/httpd/htdocs" - - /* - * SAFE_PATH -- Define a safe PATH environment to pass to CGI executables. - * - */ - #define SAFE_PATH "/usr/local/bin:/usr/bin:/bin" + 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 </PRE> </P> <P ALIGN="LEFT"> -<STRONG>COMPILING THE SUEXEC WRAPPER</STRONG><BR> -You now need to compile the suEXEC wrapper. At the shell command prompt, -type: <STRONG><CODE>cc suexec.c -o suexec [ENTER]</CODE></STRONG>. -This should create the <STRONG><em>suexec</em></STRONG> wrapper executable. +<STRONG>Compiling and installing the suEXEC wrapper</STRONG><BR> +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". +<BR> +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". +<BR> +Please note that you need <STRONG><EM>root privileges</EM></STRONG> for +the installation step. In order for the wrapper to set the user ID, it +must be installed as owner <CODE><EM>root</EM></CODE> and must have the +setuserid execution bit set for file modes. </P> -<P ALIGN="LEFT"> -<STRONG>COMPILING APACHE FOR USE WITH SUEXEC</STRONG><BR> -By default, Apache is compiled to look for the suEXEC wrapper in the following -location. +<P ALIGN="CENTER"> +<STRONG><A HREF="suexec.html">BACK TO CONTENTS</A></STRONG> </P> +<H3><A NAME="enable">Enabling & Disabling suEXEC</A></H3> <P ALIGN="LEFT"> -<EM>From src/httpd.h</EM> +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: <PRE> - /* The path to the suEXEC wrapper */ - #define SUEXEC_BIN "/usr/local/etc/httpd/sbin/suexec" + [notice] suEXEC mechanism enabled (wrapper: <EM>/path/to/suexec</EM>) </PRE> -</P> - -<P ALIGN="LEFT"> -If your installation requires location of the wrapper program in a different -directory, edit src/httpd.h and recompile your Apache server. -See <A HREF="install.html">Compiling and Installing Apache</A> for more -info on this process. -</P> - -<P ALIGN="LEFT"> -<STRONG>COPYING THE SUEXEC BINARY TO ITS PROPER LOCATION</STRONG><BR> -Copy the <STRONG><em>suexec</em></STRONG> executable created in the -exercise above to the defined location for <STRONG>SUEXEC_BIN</STRONG>. -</P> - -<P ALIGN="LEFT"> -<STRONG><CODE>cp suexec /usr/local/etc/httpd/sbin/suexec [ENTER]</CODE></STRONG> -</P> - -<P ALIGN="LEFT"> -In order for the wrapper to set the user ID, it must me installed as owner -<STRONG><em>root</em></STRONG> and must have the setuserid execution bit -set for file modes. If you are not running a <STRONG><em>root</em></STRONG> -user shell, do so now and execute the following commands. -</P> - -<P ALIGN="LEFT"> -<STRONG><CODE>chown root /usr/local/etc/httpd/sbin/suexec [ENTER]</CODE></STRONG><BR> -<STRONG><CODE>chmod 4711 /usr/local/etc/httpd/sbin/suexec [ENTER]</CODE></STRONG> +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 <EM>setuid root</EM>. +<BR> +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. +<BR> +If you want to disable suEXEC you should kill and restart Apache after +you have removed the "suexec" file. </P> <P ALIGN="CENTER"> <STRONG><A HREF="suexec.html">BACK TO CONTENTS</A></STRONG> </P> -<H3><A NAME="enable">Enabling & Disabling suEXEC</A></H3> +<H3><A NAME="usage">Using suEXEC</A></H3> <P ALIGN="LEFT"> -After properly installing the <STRONG>suexec</STRONG> wrapper -executable, you must kill and restart the Apache server. A simple -<STRONG><CODE>kill -1 `cat httpd.pid`</CODE></STRONG> will not be enough. -Upon startup of the web-server, if Apache finds a properly configured -<STRONG>suexec</STRONG> wrapper, it will print the following message to -the console: -</P> - -<P ALIGN="LEFT"> -<CODE>Configuring Apache for use with suexec wrapper.</CODE> -</P> - -<P ALIGN="LEFT"> -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 <STRONG><EM>setuid root</EM></STRONG>. Check -your installation and try again. -</P> - -<P ALIGN="LEFT"> -One way to use <STRONG>suEXEC</STRONG> is through the -<a href="mod/core.html#user"><STRONG>User</STRONG></a> and -<a href="mod/core.html#group"><STRONG>Group</STRONG></a> directives in -<a href="mod/core.html#virtualhost"><STRONG>VirtualHost</STRONG></a> +<STRONG>Virtual Hosts:</STRONG><BR> +One way to use the suEXEC wrapper is through the +<A HREF="mod/core.html#user">User</A> and +<A HREF="mod/core.html#group">Group</A> directives in +<A HREF="mod/core.html#virtualhost">VirtualHost</A> definitions. By setting these directives to values different from the main server user ID, all requests for CGI resources will be executed as -the <STRONG>User</STRONG> and <STRONG>Group</STRONG> defined for that -<STRONG><VirtualHost></STRONG>. If only one or +the <EM>User</EM> and <EM>Group</EM> defined for that +<CODE><VirtualHost></CODE>. If only one or neither of these directives are specified for a -<STRONG><VirtualHost></STRONG> then the main -server userid is assumed.<p> - -<STRONG>suEXEC</STRONG> can also be used to to execute CGI programs as +<CODE><VirtualHost></CODE> then the main +server userid is assumed. +<P> +<STRONG>User directories:</STRONG><BR> +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 <STRONG>~</STRONG> character prefixing the user ID for whom -execution is desired. +using the "<STRONG><CODE>~</CODE></STRONG>" 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 <a href="#model">security checks</a> above. +scrutiny of the <A HREF="#model">security checks</A> above. <P ALIGN="CENTER"> <STRONG><A HREF="suexec.html">BACK TO CONTENTS</A></STRONG> @@ -451,9 +461,9 @@ scrutiny of the <a href="#model">security checks</a> above. <H3><A NAME="debug">Debugging suEXEC</A></H3> <P ALIGN="LEFT"> -The suEXEC wrapper will write log information to the location defined in -the <code>suexec.h</code> as indicated above. If you feel you have -configured and installed the wrapper properly, have a look at this log +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. </P> @@ -461,7 +471,9 @@ and the error_log for the server to see where you may have gone astray. <STRONG><A HREF="suexec.html">BACK TO CONTENTS</A></STRONG> </P> -<H3><A NAME="jabberwock">Beware the Jabberwock: Warnings & Examples</A></H3> +<H3> +<A NAME="jabberwock">Beware the Jabberwock: Warnings & Examples</A> +</H3> <P ALIGN="LEFT"> <STRONG>NOTE!</STRONG> This section may not be complete. For the latest revision of this section of the documentation, see the Apache Group's @@ -474,7 +486,7 @@ 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. <UL> - <LH><STRONG>suEXEC Points Of Interest</STRONG></LH> + <LI><STRONG>suEXEC Points Of Interest</STRONG></LI> <LI>Hierarchy limitations <BLOCKQUOTE> For security and efficiency reasons, all suexec requests must @@ -508,9 +520,9 @@ limitations on server setup. Please review these before submitting any </P> <HR> -<H3 ALIGN="CENTER"> - Apache HTTP Server Version 1.2 -</H3> + <H3 ALIGN="CENTER"> + Apache HTTP Server Version 1.3 + </H3> <A HREF="./"><IMG SRC="images/index.gif" ALT="Index"></A> diff --git a/usr.sbin/httpd/htdocs/manual/upgrading_to_1_3.html b/usr.sbin/httpd/htdocs/manual/upgrading_to_1_3.html index 0db2c7c666d..e4d9d081704 100644 --- a/usr.sbin/httpd/htdocs/manual/upgrading_to_1_3.html +++ b/usr.sbin/httpd/htdocs/manual/upgrading_to_1_3.html @@ -78,6 +78,21 @@ document, or in the <CODE>src/CHANGES</CODE> file. <H3>Run-Time Configuration Changes</H3> <UL> + <LI>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: + <UL> + <LI>As of Apache 1.3.0, the current config files apply different + <A HREF="mod/core.html#options">Options</A> and + <A HREF="mod/core.html#allowoverride">AllowOverride</A> settings to + various directories than were used in 1.2. + </LI> + <LI>As of the release following Apache 1.3.3, the three + config file templates have been merged into <SAMP>httpd.conf-dist</SAMP> + and the order of the directives changed. + </LI> + </UL> <LI>As of 1.3.2, <A HREF="mod/mod_expires.html"><CODE>mod_expires</CODE></A> will add Expires headers to content that does not come from a file on disk, unless you are using a modification time based setting. @@ -116,7 +131,7 @@ document, or in the <CODE>src/CHANGES</CODE> file. "<SAMP><Limit Get post></SAMP>" in your configuration files, you need to correct them to use uppercase names. <P> - Unrecognised method names in the server configuration files will + Unrecognized method names in the server configuration files will result in the server logging an error message and failing to start. In <SAMP>.htaccess</SAMP> files, unknown methods will cause the server to log an error to its error log and return an 'Internal @@ -186,7 +201,7 @@ document, or in the <CODE>src/CHANGES</CODE> file. <LI><Files> sections previously could take a full pathname, and were matched against the full pathnames. This had some - inconsistancies, and was removed. To emulate this older behaviour + inconsistencies, and was removed. To emulate this older behaviour use a <Files> section nested inside a <Directory> section. diff --git a/usr.sbin/httpd/htdocs/manual/vhosts/name-based.html b/usr.sbin/httpd/htdocs/manual/vhosts/name-based.html index 339f54949e0..d9a9ce93e8e 100644 --- a/usr.sbin/httpd/htdocs/manual/vhosts/name-based.html +++ b/usr.sbin/httpd/htdocs/manual/vhosts/name-based.html @@ -46,34 +46,49 @@ solution is addressed below.</P> <H2>Using non-IP Virtual Hosts</H2> <P>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 <CODE>httpd.conf</CODE> or <CODE>srm.conf</CODE>) -code similar to the following:</P> +like the old method. The notable difference between IP-based and +name-based virtual host configuration is the +<A HREF="../mod/core.html#namevirtualhost"><CODE>NameVirtualHost</CODE></A> +directive which specifies an IP address that should be used as a +target for name-based virtual hosts.</P> + +<P>For example, suppose that both <SAMP>www.domain.tld</SAMP> and +<SAMP>www.otherdomain.tld</SAMP> point at the IP address +<SAMP>111.22.33.44</SAMP>. Then you simply add to one of the Apache +configuration files (most likely <CODE>httpd.conf</CODE> or +<CODE>srm.conf</CODE>) code similar to the following:</P> + + + <PRE> NameVirtualHost 111.22.33.44 <VirtualHost 111.22.33.44> ServerName www.domain.tld - DocumentRoot /web/domain + DocumentRoot /www/domain </VirtualHost> -</PRE> -<P>The notable difference between IP-based and name-based virtual host -configuration is the -<A HREF="../mod/core.html#namevirtualhost"><CODE>NameVirtualHost</CODE></A> -directive which specifies an IP address that should be used as a target for -name-based virtual hosts. + <VirtualHost 111.22.33.44> + ServerName www.otherdomain.tld + DocumentRoot /www/otherdomain + </VirtualHost> +</PRE> <P>Of course, any additional directives can (and should) be placed into the <CODE><VirtualHost></CODE> section. To make this work, -all that is needed is to make sure that the name -<SAMP>www.domain.tld</SAMP> points to the IP address -<SAMP>111.22.33.44</SAMP></P> +all that is needed is to make sure that the names +<SAMP>www.domain.tld</SAMP> and <SAMP>www.otherdomain.tld</SAMP> +are pointing to the IP address <SAMP>111.22.33.44</SAMP></P> <P>Note: When you specify an IP address in a <CODE>NameVirtualHost</CODE> directive then requests to that IP address will only ever be served -by matching <VirtualHost>s. The "main server" will <STRONG>never</STRONG> -be served from the specified IP address. +by matching <VirtualHost>s. The "main server" will +<STRONG>never</STRONG> 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 +<EM>every</EM> server (hostname) you want to maintain on your server. <P>Additionally, many servers may wish to be accessible by more than one name. For example, the example server might want to be accessible diff --git a/usr.sbin/httpd/htdocs/manual/windows.html b/usr.sbin/httpd/htdocs/manual/windows.html index 8ddc4aad3e4..f23f1227d94 100644 --- a/usr.sbin/httpd/htdocs/manual/windows.html +++ b/usr.sbin/httpd/htdocs/manual/windows.html @@ -23,7 +23,7 @@ <H1 ALIGN="CENTER">Using Apache With Microsoft Windows</H1> <P>This document explains how to install, configure and run - Apache 1.3b6 and later under Microsoft Windows. Please note that at + 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 @@ -138,19 +138,6 @@ new one after the installation is finished). <P> -<BLOCKQUOTE> -<STRONG>Important note for 1.3b6 installs</STRONG>: the above only -applies for 1.3b7 and later. In 1.3b6 the installer would overwrite -any existing <SAMP>httpd.conf</SAMP>, <SAMP>access.conf</SAMP>, -<SAMP>srm.conf</SAMP> or <SAMP>mime.types</SAMP> files in the -<SAMP>conf</SAMP>, and will also overwrite your -<SAMP>index.html</SAMP> file in the <SAMP>htdocs</SAMP> directory. You -should copy these files or directories before installing Apache 1.3b6 -or install into a new directory. -</BLOCKQUOTE> - -<P> - After installing Apache, you should edit the configuration files in the <SAMP>conf</SAMP> directory as required. These files will be configured during the install ready for Apache to be run from the @@ -190,8 +177,8 @@ with To run Apache from a console window, select the "Apache Server" option from the Start menu. 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, see <A HREF="#signal>Signalling Apache -when Running</SAMP>. +Apache. To stop Apache running, see <A HREF="#signal"><SAMP>Signalling Apache +when Running</SAMP></A>. <P> @@ -275,8 +262,8 @@ The main differences in Apache for Windows are: <H2><A NAME="cmdline">Running Apache for Windows from the Command Line</A></H2> -The Start menu icons and the NT Service manager can provide an simple -interafce for administering Apache. But in some cases it is easier to +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. <P> @@ -301,27 +288,27 @@ Your current working directory when Apache is started up has no effect on Apache's behavior. <P> -Under windows, when invoked from the start menu or the Service Manager Apache is -usually passed no arguments. So using the registry entry is the perfered +When invoked from the start menu or the Service Manager, Apache is +usually passed no arguments, so using the registry entry is the preferred technique. <P> During a binary installation, a registry key will have been installed, for example: <PRE> - HKEY_LOCAL_MACHINE\Software\Apache Group\Apache\1.3.1\ServerRoot + HKEY_LOCAL_MACHINE\Software\Apache Group\Apache\1.3.4\ServerRoot </PRE> <P> 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. You can not run two invocations +old version in the file system. You cannot run two invocations of Apache on Windows simultaneously. <P> If you did not do a binary install then Apache will in some -senarios complain that about the missing registry key. This +scenarios complain that about the missing registry key. This warning can be ignored if it otherwise was able to find it's configuration files. @@ -350,7 +337,7 @@ prevents Apache waiting to see if Apache is running as a service.) <P> -To install Apache as a Windows NT service as follows: +You can install Apache as a Windows NT service as follows: <PRE> apache -i @@ -365,13 +352,19 @@ and to remove the Apache service, use <H2><A NAME="signal">Signalling Apache when running</A></H2> -On Windows 95 Apache runs as a console application. You can tell a +On Windows 95, Apache runs as a console application. You can tell a running Apache to stop by opening another console window and running <PRE> apache -k shutdown </PRE> +<BLOCKQUOTE> + <STRONG>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.</STRONG> +</BLOCKQUOTE> +<P> 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. @@ -385,10 +378,16 @@ complete without interruption. To restart Apache, run <PRE> apache -k restart </PRE> +<BLOCKQUOTE> + <STRONG>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.</STRONG> +</BLOCKQUOTE> +<P> Note for people familiar with the Unix version of Apache: these commands provide a Windows equivalent to <CODE>kill -TERM -<i>pid</i></CODE> and <CODE>kill -USR1 <i>pid</i></CODE>. The command +<EM>pid</EM></CODE> and <CODE>kill -USR1 <EM>pid</EM></CODE>. The command line option used, <CODE>-k</CODE>, was chosen as a reminder of the "kill" command used on Unix. @@ -404,13 +403,19 @@ line option used, <CODE>-k</CODE>, was chosen as a reminder of the <CODE>src</CODE> subdirectory of the Apache distribution.</P> <P>The master Apache makefile instructions are contained in the - <CODE>Makefile.nt</CODE> file. To compile Apache, simply use one of - the following commands: + <CODE>Makefile.nt</CODE> file. To compile Apache on Windows NT, simply + use one of the following commands: <UL> <LI><CODE>nmake /f Makefile.nt _apacher</CODE> (release build) <LI><CODE>nmake /f Makefile.nt _apached</CODE> (debug build) </UL> +<P><em>(1.3.4 and later)</em> To compile Apache on Windows 95, use one of +<UL> +<LI><CODE>nmake /f Makefile_win32.txt</CODE> (release build) +<LI><CODE>nmake /f Makefile_win32_debug.txt</CODE> (debug build) +</UL> + <P>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.</P> @@ -448,8 +453,15 @@ line option used, <CODE>-k</CODE>, was chosen as a reminder of the <LI><CODE>nmake /f Makefile.nt installd INSTDIR=<EM>dir</EM></CODE> (for debug build) </UL> +or, for Windows 95 (1.3.4 and later), use one of: +<UL> +<LI><CODE>nmake /f Makefile_win32.txt install INSTDIR=<EM>dir</EM></CODE> + (for release build) +<LI><CODE>nmake /f Makefile_win32_debug.txt install INSTDIR=<EM>dir</EM></CODE> + (for debug build) +</UL> -The dir argument to INSTDIR gives the installation directory. The can +The dir argument to INSTDIR gives the installation directory; it can be omitted if Apache is to be installed into <SAMP>\Apache</SAMP>. <P>This will install the following:</P> diff --git a/usr.sbin/httpd/httpd.8 b/usr.sbin/httpd/httpd.8 index e7d6e32d571..be0bcd56387 100644 --- a/usr.sbin/httpd/httpd.8 +++ b/usr.sbin/httpd/httpd.8 @@ -1,6 +1,7 @@ -.TH httpd 8 "February 1997" +.TH httpd 8 "February 1999" .\" Copyright (c) 1995-1997 David Robinson. All rights reserved. -.\" Copyright (c) 1997 The Apache Group. All rights reserved. +.\" Copyright (c) 1997-1999 The Apache Group. All rights reserved. +.\" Copyright (c) 1998-1999 Bob Beck. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions @@ -53,7 +54,9 @@ httpd \- Apache hypertext transfer protocol server .SH SYNOPSIS .B httpd [ -.B \-hlvVSt? +.B \-X +] [ +.BI \-R " libexecdir" ] [ .BI \-d " serverroot" ] [ @@ -62,7 +65,30 @@ httpd \- Apache hypertext transfer protocol server .BI \-C " directive" ] [ .BI \-c " directive" +] [ +.BI \-D " parameter" ] + +.B httpd +[ +.B \-h +] +[ +.B \-l +] +[ +.B \-L +] +[ +.B \-v +] +[ +.B \-V +] +[ +.B \-S +] + .SH DESCRIPTION .B httpd is the Apache HyperText Transfer Protocol (HTTP) server program. It is @@ -84,16 +110,15 @@ Paths in this manual page reflect those compiled into httpd by default with OpenBSD. .SH OPTIONS .TP 12 -.BI \-c " directive" -Process directive "directive" -.BI after -reading config files. -.TP -.BI \-C " directive" -Process directive "directive" -.BI before -reading config files. -.TP +.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 @@ -104,27 +129,50 @@ Execute the commands in the file \fIconfig\fP on startup. If \fIconfig\fP does not begin with a /, then it is taken to be a path relative to the ServerRoot. The default is \fBconf/httpd.conf\fP. .TP +.BI \-C " directive" +Process the configuration \fIdirective\fP before reading config files. +.TP +.BI \-c " directive" +Process the configuration \fIdirective\fP after reading config files. +.TP +.BI \-D " parameter" +Sets a configuration \fIparameter\fP which can be used with +<IfDefine>...</IfDefine> sections in the configuration files +to conditionally skip or process commands. +.TP .B \-h -Output a list of directives together with expected arguments and -places where the directive is valid. +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 -Print the parsed settings (currently only vhost settings), and then exit. +Show the settings as parsed from the config file (currently only shows the +virtualhost settings). .TP .B \-t -Run a syntax test for the configuration files, and then exit. +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 \-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 httpd, and then exit. +Print the version of +.B httpd +, and then exit. .TP .B \-V -Print the compiled in settings for httpd, and then exit. -.TP -.B \-? -Print a list of the httpd options, and then exit. +Print the version and build parameters of +.B httpd +, and then exit. .SH FILES .PD 0 .B /var/www/conf/httpd.conf diff --git a/usr.sbin/httpd/icons/README b/usr.sbin/httpd/icons/README index a1fc5a5a9c7..74b2970b9e8 100644 --- a/usr.sbin/httpd/icons/README +++ b/usr.sbin/httpd/icons/README @@ -3,19 +3,16 @@ 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@eit.com). + 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. - The distribution site for these icons is at: - - http://www.eit.com/goodies/www.icons/ - - Kevin Hughes - September 11, 1995 - + 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 diff --git a/usr.sbin/httpd/src/ApacheCore.def b/usr.sbin/httpd/src/ApacheCore.def index 8bf0fe8ba53..d6c8d8837d2 100644 --- a/usr.sbin/httpd/src/ApacheCore.def +++ b/usr.sbin/httpd/src/ApacheCore.def @@ -1 +1,327 @@ +; 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_single_module_init @316 + ap_make_etag @317 + ap_array_pstrcat @318 + ap_os_is_filename_valid @319 + diff --git a/usr.sbin/httpd/src/ApacheCore.mak b/usr.sbin/httpd/src/ApacheCore.mak index 2d0bcc2372a..e253234629d 100644 --- a/usr.sbin/httpd/src/ApacheCore.mak +++ b/usr.sbin/httpd/src/ApacheCore.mak @@ -90,6 +90,8 @@ CLEAN : -@erase "$(INTDIR)\util_uri.obj" -@erase "$(INTDIR)\util_win32.obj" -@erase "$(INTDIR)\vc50.idb" + -@erase "$(INTDIR)\ApacheCore.pch" + -@erase "$(OUTDIR)\ApacheCore.pch" -@erase "$(OUTDIR)\ApacheCore.dll" -@erase "$(OUTDIR)\ApacheCore.exp" -@erase "$(OUTDIR)\ApacheCore.lib" @@ -304,6 +306,8 @@ CLEAN : -@erase "$(INTDIR)\util_win32.sbr" -@erase "$(INTDIR)\vc50.idb" -@erase "$(INTDIR)\vc50.pdb" + -@erase "$(INTDIR)\ApacheCore.pch" + -@erase "$(OUTDIR)\ApacheCore.pch" -@erase "$(OUTDIR)\ApacheCore.bsc" -@erase "$(OUTDIR)\ApacheCore.dll" -@erase "$(OUTDIR)\ApacheCore.exp" diff --git a/usr.sbin/httpd/src/BUILD.NOTES b/usr.sbin/httpd/src/BUILD.NOTES index ebbb3dcbe1e..cdc58ef6b1c 100644 --- a/usr.sbin/httpd/src/BUILD.NOTES +++ b/usr.sbin/httpd/src/BUILD.NOTES @@ -18,3 +18,20 @@ A/UX: Jim Jagielski (jim@apache.org) if you need a precompiled build for A/UX 3.1.x. +----- +AIX: +----- + If compiling Apache on AIX (any version) using the xlC compiler version + 3.6.X and you receive an error such as: + + "Expected </Directory> but saw </Directory>" + or + "Expected </Files> but saw </Files>" + + then you have encountered a bug in xlC. This is a problem with the + 3.6.X versions of xlC, and is not a problem with the Apache code. + 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/usr.sbin/httpd/src/CHANGES b/usr.sbin/httpd/src/CHANGES index 2d9899db077..41833f59eac 100644 --- a/usr.sbin/httpd/src/CHANGES +++ b/usr.sbin/httpd/src/CHANGES @@ -1,3 +1,479 @@ +Changes with Apache 1.3.4 + + *) Renamed macros status_drops_connection to ap_status_drops_connection + and vestigial scan_script_header to ap_scan_script_header_err, + mostly for aesthetic reasons. [Roy Fielding] + + *) The query switch "httpd -S" didn't exit after showing the + vhost settings. That was inconsistent with the other query functions. + [Martin Kraemer] + + *) Moved the MODULE_MAGIC_COOKIE from before the versions and + filename to the end of the STANDARD_MODULE_STUFF. Its + presence at the beginning prevented reporting of the filename + for modules compiled before 1 January 1999. [Ken Coar] + + *) SECURITY: ap_os_is_filename_valid() has been added to Win32 + to detect and prevent access to special DOS device file names. + [Paul Sutton, Ken Parzygnat] + + *) WIN32: Created new makefiles Makefile_win32.txt (normal build) + and Makefile_win32_debug.txt (debug build) that work on Win95. + Run each of the following from the src directory: + nmake /f Makefile_win32.txt # compiles normal build + nmake /f Makefile_win32.txt install # compiles and installs + nmake /f Makefile_win32.txt clean # removes compiled junk + nmake /f Makefile_win32_debug.txt # compiles debug build + nmake /f Makefile_win32_debug.txt install + nmake /f Makefile_win32_debug.txt clean + [Roy Fielding] + + *) Added binbuild.sh and findprg.sh helpers to make it easier for us + to build binary distributions. [Lars Eilebrecht] + + *) IndexOptions SuppressColumnSorting only turned off making + the column headers anchors; you could still change the display + order by manually adding a '?N=A' or similar query string to the + URL. Now SuppressColumnSorting locks in the sort order so + it can't be overridden this way. [Ken Coar] + + *) Added IndexOrderDefault directive to supply a default sort order + for FancyIndexed directory listings. [Ken Coar] PR#1699 + + *) Change the ap_assert macro to a variant that works on all platforms. + [Richard Prinz <richard.prinz@cso.net>] PR#2575 + + *) Make sure under ELF-based NetBSD (now) and OpenBSD (future) we don't + search for an underscore on dlsym() (as it's already the case + for FreeBSD 3.0). [Todd Vierling <tv@pobox.com>] PR#2462 + + *) Small fix for mod_env.html: The module was documented as to be _not_ + compiled into Apache per default, although it _IS_ compiled into + Apache per default. [Sim Harbert <sim@mindspring.com>] PR#3572 + + *) Instead of fixing a bug in the generation procedure for config.status (a + backslash was missing) we remove the bug together with it's complete + context because the special cases of the past can now no longer occur + because of the recent magic for the --with-layout default. + [Ralf S. Engelschall] PR#3590 + + *) Make top-level Makefile aware of a parallel build procedures (make -j) by + making sure the src/support/ tools are _forced_ to be build last (they + depend on other libraries). + [Markus Theissinger <markus.theissinger@gmx.de>] + + *) Fix installation procedure: Now that os-inline.c is actually used (a + recently fixed bug prevented this) we need to also install os-include.c + in addition to os.h into the PREFIX/include/ location or building of + module DSOs with APXS fails. [Ralf S. Engelschall] PR#3527 + + *) Added MODULE_MAGIC_COOKIE as the first field in a module structure to + allow us to distinguish between a garbled DSO (or even a file which isn't + an Apache module DSO at all) and a DSO which doesn't match the current + Apache API. [Ralf S. Engelschall] PR#3152 + + *) Two minor enhancements to mod_rewrite: First RewriteRule now also + supports the ``nocase|NC'' flag (as RewriteCond already does for ages) to + match case insensitive (this especially avoids nasty patterns like + `[tT][eE][sS][tT]'). Second two additional internal map functions + `escape' and `unescape' were added which can be used to escape/unescape + to/from hex-encodings in URLs parts (this is especially useful in + combination with map lookups). + [Magnus Bodin, Ian Kallen, Ralf S. Engelschall] + + *) Renamed the macro escape_uri() to ap_escape_uri() which was + forgotten (because it was a macro) in the symbol renaming process. + [Ralf S. Engelschall] + + *) Fix some inconsistencies related to the scopes of directives. The only + user visible change is that the directives `UseCanonicalName' and + `ContentDigest' now use the (more correct) `Options' scope instead of + (less correct) `AuthConfig' scope. [Ralf S. Engelschall] + + *) Using DSO, the Server token was being mangled. Specifically, the + module's token was being added first before the Apache token. This + has been fixed. [Jim Jagielski] + + *) Major overhaul of mod_negotiation.c, part 2. + - properly handle "identity" within Accept-Encoding. + - allow encoded variants in RVSA negotiation and let them appear in + the Alternates field using the non-standard "encoding" tag-list. + - fixed both negotiation algorithms so that an explicitly accepted + encoding is preferred over no encoding if "identity" is not + included within Accept-Encoding. + - added ap_array_pstrcat() to alloc.c for efficient concatenation + of large substring sequences. + - replaced O(n^2) memory hogs in mod_negotiation with ap_array_pstrcat. + [Roy Fielding] + + *) Major overhaul of mod_negotiation.c, part 1. + - cleanups to mod_negotiation comments and code structure + - made compliant with HTTP/1.1 proposed standard (rfc2068) and added + support for everything in the upcoming HTTP/1.1 + revision (draft-ietf-http-v11-spec-rev-06.txt). + - language tag matching also handles tags with more than 2 + levels like x-y-z + - empty Accept, Accept-Language, Accept-Charset headers are + processed correctly; previously an empty header would make all + values acceptable instead of unacceptable. + - allowed for q values in Accept-Encoding + - added support for transparent content negotiation (rfc2295 and + rfc2296) (though we do not implement all features in these drafts, + e.g. no feature negotiation). Removed old experimental version. + - implemented 'structured entity tags' for better cache correctness + (structured entity tags ensure that caches which can deal with Vary + will (eventually) be updated if the set of variants on the server + is changed) + - this involved adding a vlist_validator element to request_rec + - this involved adding the ap_make_etag() function to the global API + - modified guessing of charsets used by Apache negotiation algorithm + to guess 'no charset' if the variant is not a text/* type + - added code to sort multiviews variants into a canonical order so that + negotiation results are consistent across backup/restores and mirrors + - removed possibility of a type map file resolving to another type map + file as its best variant + [Koen Holtman, Roy Fielding, Lars Eilebrecht] PR#3451, 3299, 1987 + + *) RFC2396 allows the syntax http://host:/path (with no port number) + but the proxy disallowed it (ap_proxy_canon_netloc()). + [David Kristol <dmk@bell-labs.com>] PR#3530 + + *) When modules update/modify the file name in the configfile_t structure, + syntax errors will report the updated name, not the original one. + [Fabien Coelho <coelho@cri.ensmp.fr>] PR#3573 + + *) Correct some filename case assumptions from WIN32 to + CASE_BLIND_FILESYSTEM. [Brian Havard <brianh@kheldar.apana.org.au>] + + *) For %v log ServerName regardless of the UseCanonicalName + setting (similarly for %p). [Dean Gaudet] + + *) Configure was initializing the variables $OSDIR, $INCDIR and $SHELL + rather late (too late for some invocations of TestCompile). + This improves the make environment available to TestCompile and + the *.module scripts. [Martin Kraemer] + + *) The hashbang emulation code in ap_execve.c would interpret + #!/hashbang/scripts correctly, but failed to fall back to a + standard shell for scripts which did NOT start with #! + Now SHELL_PATH is started in these cases. [Martin Kraemer] + + *) PORT: Added the Cyberguard V2 port [Richard Stagg <stagg@lentil.org>] + PR#3336 + + *) Update APXS manual page: some -q option arguments were missing + and another was incorrect. [Mark Anderson <mda@discerning.com>] PR#3553 + + *) Cleanup the command line options: `-?' was documented to show + the usage list but does it with an error because `?' is not a valid + command. OTOH a lot of users expect `-h' to print such a usage list and + instead are annoyed for ages by our huge unreadable list of directives. + So we now changed the command line options this way: + 1. `-L' => `-R' + Intent: we need `-L' to be free, and `-R' for the DSO run-time path is + very similar to the popular linker option. + 2. `-h' => `-L' + Intent: while -l gives the small list of modules, -L now gives the + large list of directives implemented by these modules. This is also + consistent with -v (short version info) and -V (large version info). + 3. `-?' => `-h' + Intent: it's now the expected option ;-) + The manual page was adjusted accordingly. + [Ralf S. Engelschall] PR#2714 + + *) Fixed problem of fclose() on an unopened file in suexec if LOG_EXEC + wasn't defined. [Rick Franchuk <rickf@transpect.net>] + + *) Removed recently introduced bugs and disfigurements in APACI: + o fixed argument line processing: using $args was broken: It was not + initialized and using args="$args $apc_option" and even args="$args + \"$apc_option\"" fails in the second processing round for any arguments + containing whitespaces. The only correct way is to use the construct + "$@" (but not possible here) or iterate _both_ times over the implicit + argument line (no argument to for-loop) which is what we now use. + o make --with-layout=Apache the default without creating + redundancy (copying the --with-layout block in the argument parsing + loop). We achieve this by using the "$@" construct together with the + `set' command to prepend --with-layout=Apache to the command line in + case --with-layout is not used. + o fixed auto-suffix handling now that config.layout exists. + Paths which are auto-suffixed are marked with a trailing plus sign in + config.layout and every path now can be marked this way (not only the + four paths for which we do it currently). Additionally the suffix is + no longer a static one. Instead it's now `/<target>' where <target> is + the argument of the --target option or per default `httpd'. + o allow also tabs (and only spaces) where we match whitespaces + o various fixes and cleanups related to used shell coding style + o made Jim happy by replacing `Written by' with `Initially written by' ;-) + o trimmed output of --help to fit into 80 columns + [Ralf S. Engelschall] + + *) Added two new core API functions, ap_single_module_configure() and + ap_single_module_init(), which are now used by mod_so to configure a module + after loading. [Ralf S. Engelschall] + + *) PORT: Add defines for USE_FLOCK_SERIALIZED_ACCEPT and + SINGLE_LISTEN_UNSERIALIZED_ACCEPT to NetBSD/OpenBSD section + of ap_config.h to allow serialized accept for multiport listens. + [Roy Fielding, Curt Sampson] PR#3120 + + *) PORT: Fixed a misplaced #endif for NetBSD/OpenBSD section + of ap_config.h that would skip several defines if DEFAULT_GROUP + was overridden. [Roy Fielding] + + *) PORT: The I86 version of DGUX has support for strncasecmp and + strcasecmp, so allow it in ap_config.h. [Amiel Lee Yee] PR#3247 + + *) Fix ordering of definitions in ap_config.h so that ap_inline is + defined before it might be used. [Victor Khimenko] + + *) PORT: Add Dynamic Shared Object (DSO) support for BSDI (v4.0). + [Tom Serkowski <tks@bsdi.com>] PR#3453 + + *) Make generation of src/Configuration.apaci more robust: It failed to + differenciate between modules when one module name was a postfix of + another (e.g. cgi vs. fastcgi). We now check for mod_XXX, libXXX and even + just XXX (think about totally non-standard names like "apache_ssl", too). + [Ralf S. Engelschall] PR#3380 + + *) In src/Configure remove the SERVER_SUBVERSION support (already deprecated + since 1.3b7) and make whitespace handling more robust (it failed horrible + when whitespaces were present in the arguments of -D options). + [Ralf S. Engelschall] PR#3240 + + *) Add APACI --shadow=DIR variant (in addition to --shadow). This now first + creates an external package shadow tree in DIR before the local build + shadow tree is generated under DIR. This way one can have the extracted + Apache distribution tree read-only on NFS or CDROM and still build Apache + from these sources. An automatically triggered VPATH-like mechanism is + provided through the TOP variable, too. + [Ralf S. Engelschall, Wilfredo Sanchez <wsanchez@apple.com>] + + *) Fix negotiation so that a Vary response header is correctly + generated when, for a particular dimension, variants only vary + in having or not having a value for that dimension. [Paul Sutton] + + *) Fix negotiation so that we prefer an encoded variant over an + unencoded variant if the user-agent explicitly says it can + accept that encoding. Previously we always preferred the unencoded + variant. + [Paul Ausbeck <paula@alumni.cse.ucsc.edu>, Paul Sutton] PR#3447 + + *) Fix APXS tool: query variables LIBS_SHLIB and TARGET were not recognized + and the usage page was inconsistent with the functionality and manpage. + [Ralf S. Engelschall] + + *) Allow special options -Wc,xxx and -Wl,xxx on APXS compile/link command. + They can occur multiple times and their arguments (`xxx') are passed AS + IS to the compiler/linker command. [Ralf S. Engelschall] + + *) Fixed possible (but harmless in practice) bug in the DBM lookup + procedure of mod_rewrite: very long keys were truncated. + [Ralf S. Engelschall] + + *) Added a generic --with-layout=[FILE:]ID option. ID here is a layout + identifier, currently "Apache" and "GNU" are pre-defined in the file + config.layout. Custom layouts are possible by using FILE:ID as the + argument where the layout ID is taken from FILE. + + The config.layout file consists of <Layout ID>..</Layout> sections + where inside those sections "path_variable: path_value" pairs can be + specified. These lines are converted to path_variable='path_value'. + + *) Add a DefaultLanguage directive so that files missing a language + extension (e.g., .fr, .de) can be labelled as being some other + default language. DefaultLanguage can appear in <Directory> and + <Files> containers as well as .htaccess files. [Paul Sutton] + PR#1180 + + *) Fix TARGET configuration when configuring and installing using + APACI configure. TARGET now defines the basename of the configuration + file, startup script, manual page, etc. log_error_core() now reports + the server binary name given by argv[0]. TARGET can now also be defined + with --target=TARGET parameter passed to APACI configure. + [Ralf Engelschall, Randy Terbush] + + *) mod_include.c:handle_perl() now properly tests for OPT_INCNOEXEC + rather than OPT_INCLUDES [Rainer Schoepf <schoepf@uni-mainz.de>] + + *) ap_md5_binary() was using sprintf() rather than a table lookup + to convert binary bytes to hex digits. + [Ronald Tschalär <ronald@innovation.ch>] PR#3409 + + *) Fix SEGV in TCN negotiation if no variants are acceptable. + [Martin Plechsmid <plechsmi@karlin.mff.cuni.cz>] PR#1987 + + *) API: ap_exists_config_define() function is now "public" [Doug MacEachern] + + *) Fix documentation of `Action' directive: It can activate a CGI script + when either a handler or a MIME content type is triggered by the request. + [Andrew Pimlott <pimlott@math.harvard.edu>] PR#3340 + + *) Document the `add' command of `dbmmanage' in `dbmmanage.1' manpage. + [David MacKenzie <djm@uu.net>] PR#3394 + + *) Ignore a "ErrorDocument 401" directive with a full URL and write a + notice to the error log. It is not possible to send a 401 response + and a redirect at the same time. [Lars Eilebrecht] + + *) Fallback to native compilers for IRIX-32 platform. It seems that + a gcc 2.8.1 compiled apache is logging client addresses with all + bits set (255.255.255.255). This is the second such problem caused + by gcc 2.8.1 compiler. The first being broken semaphore locking. + [Randy Terbush] + + *) Updated mime.types to reflect current Internet media types + and include a URL to the registry. + [Manoj Kasichainula, Roy Fielding] PR#2380, 2286, 2246 + + *) SECURITY: Do a more complete check in mod_include to avoid + an infinite loop of recursive SSI includes. [Marc Slemko] PR#3323 + + *) Add APACI --suexec-docroot and --suexec-logfile options which can be + used to set the document root directory (DOC_ROOT) and the suexec + logfile (LOG_EXEC), respectively. Additionally the --layout option + was changed to show more information about the suEXEC setup. + [Lars Eilebrecht] PR#3316, 3357, 3361 + + *) Added the last two WebDAV status codes of 424 (Failed Dependency) + and 507 (Insufficient Storage) for use by third-party modules. + [Roy Fielding] + + *) Enabled all of the WebDAV method names for use by third-party + modules, Limit, and Script directives. That includes PATCH, + PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, and UNLOCK. + Improved mod_actions.c so that it can use any of the methods + defined in httpd.h. Added ap_method_number_of(method) for + getting the internal method number. [Roy Fielding] + + *) PORT: Add a port to the TPF OS. [Joe Moenich <moenich@us.ibm.com> and + others at IBM] + + *) Fix problems with handling of UNC names (e.g., \\host\path) + on Win32. [Ken Parzygnat <kparz@us.ibm.com>] + + *) Rework os_canonical_*() on Win32 so it's simpler, more + robust, and works. [Ken Parzygnat <kparz@us.ibm.com>] + PR#2555, 2915, 3064, 3232 + + *) Work around incomplete implementation of strftime on Win32. + [Manoj Kasichainula, Ken Parzygnat <kparz@us.ibm.com>] + + *) Move a typedef to fix compile problems on Linux with 1.x kernels. + [Manoj Kasichainula] PR#3177 + + *) PORT: Add a port to the Concurrent PowerMAX OS. [Tom Horsley + <Tom.Horsley@mail.ccur.com>] + + *) WIN32: Log more explicit error messages if spawning an interpreted + script failed, including the command line used to attempt to execute + the interpreter and the Win32 error code returned. [Marc Slemko] + + *) Disable sending of error-notes on a 500 (Internal Server Error) response + since it often includes file path info. Enable sending of error-notes + on a 501 (Method Not Implemented). [Roy Fielding] PR#3173 + + *) http_config.c would respond with 501 (Method Not Implemented) if a + content type handler was specified but could not be found, which + should have been a 500 response. Likewise, mod_proxy.c would responsd + with a 501 if the URI scheme is unrecognized instead of the correct + response of 403 (Forbidden). [Roy Fielding] + + *) SECURITY: Eliminate DoS attack when a bad URI path contains what + looks like a printf format escape. [Marc Slemko, Studenten Net Twente] + + *) Fix in mod_autoindex: for files where the last modified time stamp was + unavailable, an empty string was printed which was 2 bytes short. + The size and description columns were therefore not aligned correctly. + [Martin Kraemer] (no PR#) + + *) Update BS2000 OS code to work with recent versions. Starting with + release A17, the child fork() must be replaced by a _rfork(). + (BS2000 only) [Martin Kraemer] + + *) Add the actual server_rec structure of the specific Vhost to the + scoreboard file and avoid a string copy (as well as allow some + further future enhancements). [Harrie Hazewinkel + <harrie.hazewinkel@jrc.it>] + + *) Add APACI --permute-module=foo:bar option which can be used to + on-the-fly/batch permute the order of two modules (mod_foo and mod_bar) + in the Configuration[.apaci] file. Two special and important variants are + supported for the option argument: first BEGIN:foo which permutes module + mod_foo with the begin of the module list, i.e. it `moves' the module to + the begin of the list (gives it lowest priority). And second foo:END + which permutes mod_foo with the end of the module list, i.e. it `moves' + the module to the end of the list (gives it highest priority). + [Ralf S. Engelschall] + + *) Fix problem with 'apache -k shutdown' and startup event + synchronisation (Win32). [Ken Parzygnat <kparz@raleigh.ibm.com>] + PR#3255 + + *) The config parser wasn't correctly noticing a missing '>' + on container start lines (e.g., it wouldn't spot + "<Directory /" as a syntax error). [Ryan Bloom <rbbloom@us.ibm.com>] + PR#3279 + + *) Add a 'RemoveHandler' directive which will selectively remove + all handler associations for the specified file extensions. + [Ryan Bloom <rbbloom@us.ibm.com>] PR#1799. + + *) Properly handle & allow "nul" and ".*/null" in AccessConfig and + ResourceConfig directives on Win32. Also add a note to the effect + of 'useless User directive ignored on Win32' to the errorlog if + a User directive is encountered on Win32. + [Ken Parzygnat <kparz@raleigh.ibm.com>] PR#2078, 2303. + + *) Fix multiple whitespace handling in imagemaps for mod_imap which was + broken since Apache 1.3.1 where we took out compressing of multiple + spaces in ap_cfg_getline(). + [Ivan Richwalski <ivan@seppuku.net>] PR#3249 + + *) Fix Berkeley-DB/2.x support in mod_auth_db: The data structures were not + initialized correctly and the db_open() call used an invalid mode + parameter. [Ron Klatchko <ron@ckm.ucsf.edu>] PR#3171 + + *) PORT: DSO support for UnixWare 7 + [Ralf S. Engelschall, Ron Record <rr@sco.com>] + + *) Merge the contents of the {srm,access}.conf-dist* files into the + httpd.conf-dist* files. The srm and access files now contain + only comments, and httpd.conf has all the combined contents in + a rational order. [Ken Coar] + + *) PORT: DSO/ELF support for FreeBSD 3.0. + [Ralf S. Engelschall, Dirk Froemberg <ibex@physik.TU-Berlin.DE>] + + *) Add a "default-handler" handler that calls the default_hander() + function which is normally called for static content. This allows + you to override a specific handler. [Marc Slemko] + + *) Further simplify checking for absolute paths by replacing an + hard-coded syntax check with a call to a routine we already created to + do this. [Ken Parzygnat <kparz@raleigh.ibm.com>] PR#2976, 3074 + + *) Log an error if we encounter a malformed "require" directive + in mod_auth if we know that we know that no other module can + deal with it. [Marc Slemko] + + *) Remove ap_private_extern method of hiding conflicting symbols + on the NEXT platform because it is not correct for all versions, + and the versions for which it is correct are unknown. + [Wilfredo Sanchez <wsanchez@apple.com>] + + *) Fix inheritance of IndexOptions NameWidth and remove unintended + restriction on +NameWidth, +IconHeight, and +IconWidth. [Ken Coar] + + *) Fix per-directory config merging for cases in which a 500 error + is encountered in an .htaccess file somewhere down the tree. + [Ken Coar] PR#2409 + + *) Minor performance improvement to ap_escape_html(). [Roy Fielding] + + *) Fixed a segmentation violation in mod_proxy when a response is + non-cachable. [Roy Fielding, traced by Doug Bloebaum]. PR#2950, 3056 + Changes with Apache 1.3.3 *) Added a complete implementation of the Expect header field as diff --git a/usr.sbin/httpd/src/Configuration b/usr.sbin/httpd/src/Configuration index 8fa824e0ca5..ca8b55aace5 100644 --- a/usr.sbin/httpd/src/Configuration +++ b/usr.sbin/httpd/src/Configuration @@ -63,6 +63,11 @@ EXTRA_DEPS= #RANLIB= ################################################################ +# Name of the installed Apache HTTP webserver. +# +#TARGET= + +################################################################ # Dynamic Shared Object (DSO) support # # There is experimental support for compiling the Apache core and @@ -159,7 +164,7 @@ Rule SHARED_CHAIN=default Rule SOCKS4=no Rule SOCKS5=no Rule IRIXNIS=no -Rule IRIXN32=no +Rule IRIXN32=yes Rule PARANOID=no # The following rules should be set automatically by Configure. However, if @@ -178,7 +183,7 @@ Rule PARANOID=no # out the Rule. The "default" action is "yes" unless overruled # by OS specifics -Rule WANTHSREGEX=no +Rule WANTHSREGEX=default ################################################################ # Module configuration @@ -323,8 +328,8 @@ AddModule modules/standard/mod_auth.o ## "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 +# 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. diff --git a/usr.sbin/httpd/src/Configuration.tmpl b/usr.sbin/httpd/src/Configuration.tmpl index 178308124ed..ca8b55aace5 100644 --- a/usr.sbin/httpd/src/Configuration.tmpl +++ b/usr.sbin/httpd/src/Configuration.tmpl @@ -14,12 +14,12 @@ # # Makefile options, such as CC=gcc, etc... # -# Rules, distinquished by having "Rule" at the front. These are used to +# 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 'Module' at the front. -# These list the configured modules, in reverse priority order (lowest -# priority first). They're down at the bottom. +# 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 @@ -37,30 +37,94 @@ # will be added to whatever flags Configure determines as appropriate # and needed for your platform. # -# You can also set the compiler and Optimization used here as well. -# Settings here have priority; If not set, Configure will attempt to guess -# the C compiler, and set OPTIM to '-O2' +# 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. # -# REDHAT LINUX 5.0 USERS PLEASE NOTE! You have to add -lcrypt to -# EXTRA_LIBS. This is fixed in 1.3 but will not be fixed in 1.2. +# 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_LFLAGS= +EXTRA_LDFLAGS= EXTRA_LIBS= EXTRA_INCLUDES= +EXTRA_DEPS= #CC= -#OPTIM=-O2 +#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, -# STATUS, and IRIXNIS. +# SOCKS5, IRIXNIS, IRIXN32 and PARANOID. # # For all Rules, if set to "yes", then Configure knows we want that # capability and does what is required to add it in. If set to "default" @@ -68,40 +132,55 @@ EXTRA_INCLUDES= # present, then nothing is done. # # SOCKS4: -# If SOCKS4 is set to 'yes', be sure that you add the sock library +# 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" # -# STATUS: -# If Configure determines that you are using the status_module, -# it will automatically enable full status information if set -# to 'yes'. If the status module is not included, having STATUS -# set to 'yes' has no impact. +# 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, and you are using NIS, you should set this -# to 'yes' +# 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 # -Rule STATUS=yes Rule SOCKS4=no +Rule SOCKS5=no Rule IRIXNIS=no +Rule IRIXN32=yes +Rule PARANOID=no # 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://www.apache.org/bugdb.cgi>. If your browser is forms-incapable, -# you can get the information to us by sending mail to apache-bugs@apache.org. +# <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 "no" unless overruled +# out the Rule. The "default" action is "yes" unless overruled # by OS specifics Rule WANTHSREGEX=default @@ -121,6 +200,13 @@ Rule WANTHSREGEX=default # 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 + ## ## Config manipulation modules ## @@ -128,147 +214,148 @@ Rule WANTHSREGEX=default ## passed to CGI/SSI scripts. It is listed first (lowest priority) since ## it does not do per-request stuff. -Module env_module mod_env.o - -## mod_dld defines commands that allow other modules to be loaded -## dynamically (at runtime). This module is for experimental use only. - -# Module dld_module mod_dld.o +AddModule modules/standard/mod_env.o ## ## Request logging modules ## -Module config_log_module mod_log_config.o +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. -# Module agent_log_module mod_log_agent.o -# Module referer_log_module mod_log_referer.o +# 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). +## "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. -Module mime_module mod_mime.o -Module negotiation_module mod_negotiation.o +# 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 -## STATUS=yes (see the Rules section near the start of this file) to allow -## full status information. Check conf/access.conf on how to enable this. +## the 'ExtendedStatus On' directive to allow full status information. +## Please note that doing so can result in a palpable performance hit. -# Module status_module mod_status.o +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. -# Module info_module mod_info.o +# AddModule modules/standard/mod_info.o ## mod_include translates server-side include (SSI) statements in text files. -## mod_dir handles requests on directories and directory indexes. +## 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. -Module includes_module mod_include.o -Module dir_module mod_dir.o -Module cgi_module mod_cgi.o +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 implemented ".asis" file types, which allow the embedding +## 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. -Module asis_module mod_asis.o -Module imap_module mod_imap.o -Module action_module mod_actions.o +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. -Module userdir_module mod_userdir.o +AddModule modules/standard/mod_userdir.o ## 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. -# Module proxy_module modules/proxy/libproxy.a +# AddModule modules/proxy/libproxy.a ## The Alias module provides simple URL translation and redirection. -Module alias_module mod_alias.o +AddModule modules/standard/mod_alias.o -## mod_rewrite allows for powerful URI-to-URI and URI-to-filename mapping, -## using regular expressions. +## The URL rewriting module allows for powerful URI-to-URI and +## URI-to-filename mapping using a regular expression based +## rule-controlled rewriting engine. -# Module rewrite_module mod_rewrite.o +# AddModule modules/standard/mod_rewrite.o ## ## Access control and authentication modules. ## -Module access_module mod_access.o -Module auth_module mod_auth.o +AddModule modules/standard/mod_access.o +AddModule modules/standard/mod_auth.o ## The anon_auth module allows for anonymous-FTP-style username/ ## password authentication. -# Module anon_auth_module mod_auth_anon.o +# 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) -# Module db_auth_module mod_auth_db.o -# Module dbm_auth_module mod_auth_dbm.o - -## msql_auth checks against an mSQL database. You must have mSQL installed -## and an "msql.h" available for this to even compile. Additionally, -## you may need to add a couple entries to the EXTRA_LIBS line, like -## -## -lmsql -L/usr/local/lib -L/usr/local/Minerva/lib -## -## This depends on your installation of mSQL. (This may be done by Configure -## at a later date) - -# Module msql_auth_module mod_auth_msql.o +# 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. -# Module digest_module mod_digest.o +# AddModule modules/standard/mod_digest.o ## Optional response header manipulation modules. ## ## cern_meta mimics the behavior of the CERN web server with regards to ## metainformation files. -# Module cern_meta_module mod_cern_meta.o +# 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. -# Module expires_module mod_expires.o +# 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 -# Module headers_module mod_headers.o +# AddModule modules/standard/mod_headers.o ## Miscellaneous modules ## -## mod_usertrack.c is the new name for mod_cookies.c. This module +## 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. @@ -276,17 +363,31 @@ Module auth_module mod_auth.o ## You do not need this, or any other module to allow your site ## to use Cookies. This module is for user tracking only -# Module usertrack_module mod_usertrack.o +# 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. -# Module example_module modules/example/mod_example.o +# 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_browser lets you set environment variables based on the User-Agent -## string in the request; this is useful for conditional HTML, for example. +## 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. -Module browser_module mod_browser.o +AddModule modules/standard/mod_setenvif.o + diff --git a/usr.sbin/httpd/src/Configure b/usr.sbin/httpd/src/Configure index e961d076187..d00b0e2fed3 100644 --- a/usr.sbin/httpd/src/Configure +++ b/usr.sbin/httpd/src/Configure @@ -1,6 +1,6 @@ #!/bin/sh ## ==================================================================== -## Copyright (c) 1995-1998 The Apache Group. All rights reserved. +## 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 @@ -54,21 +54,6 @@ ## For more information on the Apache Group and the Apache HTTP server ## project, please see <http://www.apache.org/>. -# HISTORY: -# -# Apache configuration script, first cut --- rst. -# Don't like it? Inspired to do something better? Go for it. -# -# second cut --- jmj -# At this point we change what Configuration contains. It maintain -# contains comments, specific compiler flags, a list of included -# modules and "rules". These rules are used to allow Configure to -# be totally configured from Configuration. -# -# third cut --- rse -# Big cleanup of the generated Makefiles and remove of -# some old kludges - # Uses 6 supplemental scripts located in ./helpers: # CutRule: Determines the value for a specified Rule # GuessOS: Uses uname to determine OS/platform @@ -129,15 +114,15 @@ fi ## Now see if Configuration.tmpl is more recent than $file. If ## so, then we complain and bail out ## -#if ls -lt Configuration.tmpl $file | 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 +if ls -lt Configuration.tmpl $file | 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" @@ -164,7 +149,7 @@ sed 's/#.*//' $file | \ using_shlib=`grep '^SharedModule' $tmpfile >/dev/null && echo 1` # But perhaps later via apxs when just mod_so is compiled in! -if [ ".$using_shlib" = . ]; then +if [ "x$using_shlib" = "x" ]; then using_shlib=`grep '^AddModule modules/standard/mod_so.o' $tmpfile >/dev/null && echo 1` fi @@ -260,7 +245,6 @@ fi DBM_LIB="-ldbm" DB_LIB="-ldb" SHELL="/bin/sh" -TARGET="httpd" SUBTARGET="target_static" SHLIB_SUFFIX_NAME="" SHLIB_SUFFIX_LIST="" @@ -286,13 +270,13 @@ OSDIR="os/unix" case "$PLAT" in *mint) - OS="MiNT" - CFLAGS="-DMINT" - LIBS="$LIBS -lportlib -lsocket" - DEF_WANTHSREGEX=yes - ;; + OS="MiNT" + CFLAGS="-DMINT" + LIBS="$LIBS -lportlib -lsocket" + DEF_WANTHSREGEX=yes + ;; *MPE/iX*) - OS='MPE/iX' + OS='MPE/iX' CFLAGS="$CFLAGS -DMPE -D_POSIX_SOURCE -D_SOCKET_SOURCE" LIBS="$LIBS -lsocket -lsvipc" LDFLAGS="$LDFLAGS -Xlinker \"-WL,cap=ia,ba,ph,pm;nmstack=1024000\"" @@ -374,9 +358,9 @@ case "$PLAT" in 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" - ;; + # Not a problem in 10.20. Otherwise, who knows? + CFLAGS="$CFLAGS -DSELECT_NEEDS_CAST" + ;; esac DEF_WANTHSREGEX=yes ;; @@ -388,7 +372,7 @@ case "$PLAT" in LIBS="$LIBS -lm" ;; *-sgi-irix64) - # Note: We'd like to see patches to compile 64-bit, but for now... + # 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 @@ -418,6 +402,7 @@ case "$PLAT" in OS='SGI IRIX' fi fi + CC='cc' CFLAGS="$CFLAGS -DIRIX" ;; *-sgi-irix) @@ -484,6 +469,8 @@ case "$PLAT" in *-openbsd*) OS='OpenBSD' DBM_LIB="" + DB_LIB="" + DEF_WANTHSREGEX=no ;; *-next-nextstep*) OS='NeXTStep' @@ -518,6 +505,7 @@ case "$PLAT" in DEF_WANTHSREGEX=yes ;; *-qnx32) + CC='cc -F' OS='QNX32' CFLAGS="$CFLAGS -DQNX -mf -3" LIBS="$LIBS -N128k -lsocket -lunix" @@ -604,19 +592,40 @@ case "$PLAT" in DEF_WANTHSREGEX=yes LIBS="$LIBS -lsocket -lnsl -lc -lgen" ;; - BS2000*-sni-sysv4*) + *-*-powermax*) + OS='SVR4' + CFLAGS="$CFLAGS -DSVR4" + DEF_WANTHSREGEX=yes + LIBS="$LIBS -lsocket -lnsl -lgen" + LD_SHLIB='cc' + LDFLAGS_SHLIB="-Zlink=so" + 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' CC='c89 -XLLML -XLLMK' CFLAGS="$CFLAGS -DCHARSET_EBCDIC -DSVR4 -D_XPG_IV" DEF_WANTHSREGEX=yes LIBS="$LIBS -lsocket -lnsl -lc" + DBM_LIB="" ;; - *-sni-sysv4*) + *-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' @@ -709,19 +718,26 @@ case "$PLAT" in DEF_WANTHSREGEX=yes ;; 4850-*.*) - OS='NCR MP/RAS' - CFLAGS="$CFLAGS -DSVR4 -DMPRAS" - DEF_WANTHSREGEX=yes - LIBS="$LIBS -lsocket -lnsl -lc -L/usr/ucblib -lucb" - ;; + 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" - ;; + 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' + ;; *) # default: Catch systems we don't know about - OS='Unknown and unsupported OS' + OS='Unknown and unsupported OS' echo Sorry, but we cannot grok \"$PLAT\" echo uname -m uname -m @@ -736,8 +752,8 @@ case "$PLAT" in 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 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 @@ -747,12 +763,28 @@ case "$PLAT" in 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" + +#################################################################### ## And adjust/override WANTHSREGEX as needed ## if [ "$RULE_WANTHSREGEX" = "default" ]; then @@ -779,8 +811,8 @@ fi 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 + # 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" @@ -817,12 +849,12 @@ fi ## Now check how we can _directly_ run the C pre-processor ## TCPP=`egrep '^CPP=' Makefile.config | tail -1 | awk -F= '{print $2}'` -if [ ".$TCPP" != . ]; then +if [ "x$TCPP" != "x" ]; then CPP=`CC=$CC CPP=$TCPP ./helpers/findcpp.sh` else CPP=`CC=$CC ./helpers/findcpp.sh` fi -if [ ".$TCPP" = . ]; then +if [ "x$TCPP" = "x" ]; then echo "CPP=$CPP" >> Makefile.config fi echo " + setting C pre-processor to $CPP" @@ -848,13 +880,13 @@ for header in $CHECK_FOR_HEADERS; do name="`echo $header | sed -e 's:/:_:g' -e 's:\.:_:g' | tr '[a-z]' '[A-Z]'`" CPP=$CPP ./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 + 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 + echo "#ifdef HAVE_${name}" >>$AP_CONFIG_AUTO_H + echo "#undef HAVE_${name}" >>$AP_CONFIG_AUTO_H + echo "#endif" >>$AP_CONFIG_AUTO_H fi done @@ -863,11 +895,11 @@ done # 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 - ;; + CPP=$CPP ./helpers/checkheader.sh sys/processor.h + if [ $? -eq 0 ]; then + CFLAGS="$CFLAGS -DAIX_BIND_PROCESSOR" + fi + ;; esac #################################################################### @@ -875,6 +907,7 @@ esac ## 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 @@ -885,6 +918,20 @@ TLDFLAGS_SHLIB_EXPORT=`egrep '^LDFLAGS_SHLIB_EXPORT=' Makefile.config | tail -1 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. ## @@ -896,252 +943,267 @@ if [ "x$using_shlib" = "x1" ] ; then SHLIB_SUFFIX_DEPTH=all SHLIB_EXPORT_FILES=no case "$PLAT" in - *-linux1) - CFLAGS_SHLIB="-fpic" - LDFLAGS_SHLIB="-Bshareable" - LDFLAGS_SHLIB_EXPORT="-rdynamic" - ;; - *-linux2) - CFLAGS_SHLIB="-fpic" - LDFLAGS_SHLIB="-Bshareable" - LDFLAGS_SHLIB_EXPORT="-rdynamic" - SHLIB_SUFFIX_DEPTH=0 - ;; - *-freebsd*) - CFLAGS_SHLIB="-fpic" - LDFLAGS_SHLIB="-Bshareable" - LDFLAGS_SHLIB_EXPORT="" - SHLIB_SUFFIX_DEPTH=2 - ;; - *-openbsd*) - CFLAGS_SHLIB="-fPIC" - LDFLAGS_SHLIB="-Bforcearchive -Bshareable" - LDFLAGS_SHLIB_EXPORT="" - SHLIB_SUFFIX_DEPTH=2 - ;; - alpha-*-netbsd*|mips-*-netbsd*|powerpc-*-netbsd*) - CFLAGS_SHLIB="-fpic -DPIC" - LDFLAGS_SHLIB="-shared" - LDFLAGS_SHLIB_EXPORT="" - SHLIB_SUFFIX_DEPTH=2 - ;; - *-netbsd*) - CFLAGS_SHLIB="-fpic -DPIC" - LDFLAGS_SHLIB="-Bshareable" - LDFLAGS_SHLIB_EXPORT="" - SHLIB_SUFFIX_DEPTH=2 - ;; - *-apple-rhapsody*) - LD_SHLIB="cc" - CFLAGS_SHLIB="" - LDFLAGS_SHLIB="-bundle -undefined suppress" - LDFLAGS_SHLIB_EXPORT="" - SHLIB_SUFFIX_DEPTH=0 - ;; - *-solaris2*) - case $CC in - */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;; - */cc|cc ) CFLAGS_SHLIB="-KPIC" ;; - esac - LDFLAGS_SHLIB="-G" - 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_SHLIB_EXPORT="" - ;; - *-sgi-irix32) - case $CC in - */gcc|gcc ) + *-linux1) + CFLAGS_SHLIB="-fpic" + LDFLAGS_SHLIB="-Bshareable" + LDFLAGS_SHLIB_EXPORT="-rdynamic" + ;; + *-linux2) + CFLAGS_SHLIB="-fpic" + LDFLAGS_SHLIB="-Bshareable" + LDFLAGS_SHLIB_EXPORT="-rdynamic" + SHLIB_SUFFIX_DEPTH=0 + ;; + *-freebsd2*) + CFLAGS_SHLIB="-fpic" + LDFLAGS_SHLIB="-Bshareable" + LDFLAGS_SHLIB_EXPORT="" + SHLIB_SUFFIX_DEPTH=2 + ;; + *-freebsd3*) + CFLAGS_SHLIB="-fpic" + LDFLAGS_SHLIB="-Bshareable" + 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_SHLIB_EXPORT="" + SHLIB_SUFFIX_DEPTH=2 + ;; + alpha-*-netbsd*|mips-*-netbsd*|powerpc-*-netbsd*) + CFLAGS_SHLIB="-fpic -DPIC" + LDFLAGS_SHLIB="-shared" + LDFLAGS_SHLIB_EXPORT="" + SHLIB_SUFFIX_DEPTH=2 + ;; + *-netbsd*) + CFLAGS_SHLIB="-fpic -DPIC" + LDFLAGS_SHLIB="-Bshareable" + LDFLAGS_SHLIB_EXPORT="" + SHLIB_SUFFIX_DEPTH=2 + ;; + *-bsdi) + CFLAGS_SHLIB="-fPIC" + LDFLAGS_SHLIB="-shared" + LDFLAGS_SHLIB_EXPORT="-rdynamic" + ;; + *-apple-rhapsody*) + LD_SHLIB="cc" + CFLAGS_SHLIB="" + LDFLAGS_SHLIB='$(EXTRA_LDFLAGS) -bundle -undefined suppress' + LDFLAGS_SHLIB_EXPORT="" + SHLIB_SUFFIX_DEPTH=0 + ;; + *-solaris2*) + case $CC in + */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;; + */cc|cc ) CFLAGS_SHLIB="-KPIC" ;; + esac + LDFLAGS_SHLIB="-G" + 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_SHLIB_EXPORT="" + ;; + *-sgi-irix32) + case $CC in + */gcc|gcc ) CFLAGS_SHLIB="-fpic" N32FLAG="" ;; - */cc|cc ) + */cc|cc ) CFLAGS_SHLIB="-KPIC" N32FLAG="-n32" ;; - esac - if [ "$RULE_IRIXN32" = "yes" ]; then - LDFLAGS_SHLIB="$N32FLAG -shared" - else - LDFLAGS_SHLIB="-shared" - fi - LDFLAGS_SHLIB_EXPORT="" - ;; - *-sgi-irix64) - case $CC in - */gcc|gcc ) + esac + if [ "$RULE_IRIXN32" = "yes" ]; then + LDFLAGS_SHLIB="$N32FLAG -shared" + else + LDFLAGS_SHLIB="-shared" + fi + LDFLAGS_SHLIB_EXPORT="" + ;; + *-sgi-irix64) + case $CC in + */gcc|gcc ) CFLAGS_SHLIB="-fpic" N32FLAG="" ;; - */cc|cc ) + */cc|cc ) CFLAGS_SHLIB="-KPIC" N32FLAG="-n32" ;; - esac - if [ "$RULE_IRIXN32" = "yes" ]; then - LDFLAGS_SHLIB="$N32FLAG -shared" - else - LDFLAGS_SHLIB="-shared" - fi - LDFLAGS_SHLIB_EXPORT="" - ;; - *-sgi-irix) - case $CC in - */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;; - */cc|cc ) CFLAGS_SHLIB="-KPIC" ;; - esac - LDFLAGS_SHLIB="-shared" - 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_SHLIB_EXPORT="" - ;; - *-unixware2) - case $CC in - */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;; - */cc|cc ) CFLAGS_SHLIB="-KPIC" ;; - esac - LDFLAGS_SHLIB="-Bdynamic -G" - LDFLAGS_SHLIB_EXPORT="-Wl,-Bexport" - ;; - *-unixware21*) - case $CC in - */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;; - */cc|cc ) CFLAGS_SHLIB="-KPIC" ;; - esac - LDFLAGS_SHLIB="-Bdynamic -G" - 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" - SHLIB_SUFFIX_DEPTH=1 - ;; - RM*-sni-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_SHLIB_EXPORT="-Wl,-Blargedynsym" - ;; - *-sni-sysv4*) - # Older SINIX machines must be linked as "shared core"-Apache - case $CC in - */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;; - */cc|cc ) CFLAGS_SHLIB="-KPIC" ;; - esac - LDFLAGS_SHLIB="-G" - 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_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_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_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_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 - ;; - *) - ## 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 [ ".$PERL" != . ]; then - # cool, Perl is installed on this platform... - if [ ".`$PERL -V:dlsrc 2>/dev/null | grep dlopen`" != . ]; 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_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 + if [ "$RULE_IRIXN32" = "yes" ]; then + LDFLAGS_SHLIB="$N32FLAG -shared" + else + LDFLAGS_SHLIB="-shared" + fi + LDFLAGS_SHLIB_EXPORT="" + ;; + *-sgi-irix) + case $CC in + */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;; + */cc|cc ) CFLAGS_SHLIB="-KPIC" ;; + esac + LDFLAGS_SHLIB="-shared" + 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_SHLIB_EXPORT="" + ;; + *-unixware*) + case $CC in + */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;; + */cc|cc ) CFLAGS_SHLIB="-KPIC" ;; + esac + LDFLAGS_SHLIB="-Bdynamic -G" + 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" + SHLIB_SUFFIX_DEPTH=1 + ;; + 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_SHLIB_EXPORT="-Wl,-Blargedynsym" + ;; + *-siemens-sysv4*) + # Older SINIX machines must be linked as "shared core"-Apache + case $CC in + */gcc|gcc ) CFLAGS_SHLIB="-fpic" ;; + */cc|cc ) CFLAGS_SHLIB="-KPIC" ;; + esac + LDFLAGS_SHLIB="-G" + 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_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_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_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_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_SHLIB_EXPORT="-Zlink=dynamic -Wl,-Bexport" + CFLAGS_SHLIB='-Zpic' + ;; + *) + ## 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_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 @@ -1150,17 +1212,17 @@ fi ## 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 + 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 @@ -1238,15 +1300,15 @@ fi #################################################################### ## OK, now handle RANLIB ## -if [ ".$RANLIB" = . ]; then - if [ ".$TRANLIB" != . ]; then - RANLIB=$TRANLIB +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 + if ./helpers/PrintPath -s ranlib; then + RANLIB="ranlib" + else + RANLIB="true" + fi fi fi @@ -1284,13 +1346,13 @@ if [ "$RULE_SOCKS4" = "yes" ]; then CFLAGS="$CFLAGS -DSOCKS -DSOCKS4" CFLAGS="$CFLAGS -Dconnect=Rconnect -Dselect=Rselect" CFLAGS="$CFLAGS -Dgethostbyname=Rgethostbyname" - if [ ".`grep EXTRA_ Makefile | grep lsocks`" = . ]; then + 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" - ;; + *-solaris2* ) + LIBS="$LIBS -lresolv" + ;; esac fi @@ -1303,13 +1365,13 @@ if [ "$RULE_SOCKS5" = "yes" ]; then CFLAGS="$CFLAGS -DSOCKS -DSOCKS5" CFLAGS="$CFLAGS -Dconnect=SOCKSconnect -Dselect=SOCKSselect" CFLAGS="$CFLAGS -Dgethostbyname=SOCKSgethostbyname -Dclose=SOCKSclose" - if [ ".`grep EXTRA_ Makefile | grep lsocks5`" = . ]; then - LIBS="$LIBS -L/usr/local/lib -lsocks5" + 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" - ;; + *-solaris2* ) + LIBS="$LIBS -lresolv" + ;; esac fi @@ -1333,7 +1395,7 @@ fi ## the module) is like this: ## ## 1 If extension is not given or is .c, assume .o was given and goto 3 -## 2 If extension if .module, go to D1 +## 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 @@ -1410,9 +1472,9 @@ for modfile in $MODFILES ; do 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 [ "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 @@ -1420,7 +1482,7 @@ for modfile in $MODFILES ; do $CAT $modbase.module > $tmpfile2 else if [ -f $modbase.c ] ; then - # Guess module structure name in case there is not + # Guess module structure name in case there is no # module definition in this file modname=`egrep '^module .*;' $modbase.c | head -1 |\ sed 's/^module.*[ ][ ]*//' | \ @@ -1447,7 +1509,7 @@ for modfile in $MODFILES ; do . ./$tmpfile3 fi rm -f $tmpfile2 $tmpfile3 - if [ $ext != so ]; then + if [ "$ext" != "so" ]; then ext=o fi fi @@ -1455,11 +1517,11 @@ for modfile in $MODFILES ; do modname=`echo $modbase | sed 's/^.*\///' | \ sed 's/^mod_//' | sed 's/^lib//' | sed 's/$/_module/'` fi - if [ $ext != so ]; then + if [ "$ext" != "so" ]; then echo "Module $modname $modbase.$ext" >>$tmpfile fi # optionally generate export file for some linkers - if [ $ext = so -a .$SHLIB_EXPORT_FILES = .yes ]; then + if [ "$ext" = "so" -a "$SHLIB_EXPORT_FILES" = "yes" ]; then echo "$modname" >$modbase.exp fi done @@ -1480,17 +1542,17 @@ fi ## LIBS_SHLIB='' if [ "x$using_shlib" = "x1" ] ; then - if [ ".$RULE_SHARED_CHAIN" = .default ] ; then - RULE_SHARED_CHAIN=$DEF_SHARED_CHAIN + if [ "$RULE_SHARED_CHAIN" = "default" ] ; then + RULE_SHARED_CHAIN=$DEF_SHARED_CHAIN fi - if [ ".$RULE_SHARED_CHAIN" = .yes ]; 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" + if [ "$RULE_SHARED_CHAIN" = "yes" ]; 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 @@ -1498,35 +1560,35 @@ fi ## Now the SHARED_CORE stuff ## if [ "x$using_shlib" = "x1" ] ; then - if [ ".$RULE_SHARED_CORE" = .default ] ; then - RULE_SHARED_CORE=$DEF_SHARED_CORE + if [ "$RULE_SHARED_CORE" = "default" ] ; then + RULE_SHARED_CORE=$DEF_SHARED_CORE fi - if [ ".$RULE_SHARED_CORE" = .yes ]; 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=3 - if [ ".$SHLIB_SUFFIX_DEPTH" = .0 ]; then - SHLIB_SUFFIX_LIST="" - fi - if [ ".$SHLIB_SUFFIX_DEPTH" = .1 ]; then - SHLIB_SUFFIX_LIST="$V" - fi - if [ ".$SHLIB_SUFFIX_DEPTH" = .2 ]; then - SHLIB_SUFFIX_LIST="$V.$R" - fi - if [ ".$SHLIB_SUFFIX_DEPTH" = .3 ]; then - SHLIB_SUFFIX_LIST="$V.$R.$P" - fi - if [ ".$SHLIB_SUFFIX_DEPTH" = .all ]; then - SHLIB_SUFFIX_LIST="$V $V.$R $V.$R.$P" - fi + if [ "$RULE_SHARED_CORE" = "yes" ]; 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=4 + if [ "$SHLIB_SUFFIX_DEPTH" = "0" ]; then + SHLIB_SUFFIX_LIST="" + fi + if [ "$SHLIB_SUFFIX_DEPTH" = "1" ]; then + SHLIB_SUFFIX_LIST="$V" + fi + if [ "$SHLIB_SUFFIX_DEPTH" = "2" ]; then + SHLIB_SUFFIX_LIST="$V.$R" + fi + if [ "$SHLIB_SUFFIX_DEPTH" = "3" ]; then + SHLIB_SUFFIX_LIST="$V.$R.$P" + fi + if [ "$SHLIB_SUFFIX_DEPTH" = "all" ]; then + SHLIB_SUFFIX_LIST="$V $V.$R $V.$R.$P" + fi fi fi @@ -1536,16 +1598,16 @@ fi ## if [ "x$using_shlib" = "x1" ] ; then if [ "x$TCFLAGS_SHLIB" = "x" ]; then - echo "CFLAGS_SHLIB=$CFLAGS_SHLIB -DSHARED_MODULE" >> Makefile.config + echo "CFLAGS_SHLIB=$CFLAGS_SHLIB -DSHARED_MODULE" >> Makefile.config fi if [ "x$TLD_SHLIB" = "x" ]; then - echo "LD_SHLIB=$LD_SHLIB" >> Makefile.config + echo "LD_SHLIB=$LD_SHLIB" >> Makefile.config fi if [ "x$TLDFLAGS_SHLIB" = "x" ]; then - echo "LDFLAGS_SHLIB=$LDFLAGS_SHLIB" >> Makefile.config + echo "LDFLAGS_SHLIB=$LDFLAGS_SHLIB" >> Makefile.config fi if [ "x$TLDFLAGS_SHLIB_EXPORT" = "x" ]; then - echo "LDFLAGS_SHLIB_EXPORT=$LDFLAGS_SHLIB_EXPORT" >> Makefile.config + echo "LDFLAGS_SHLIB_EXPORT=$LDFLAGS_SHLIB_EXPORT" >> Makefile.config fi fi @@ -1650,7 +1712,7 @@ $CAT >> $awkfile <<'EOF2' dir = pp[1] "/" pp[2] inthere = 0 for ( tdir in autodirs ) { - if (tdir == dir) + if (tdir == dir) inthere = 1 } if (inthere == 1) @@ -1687,7 +1749,6 @@ echo "" >>Makefile #################################################################### ## Now add the target for the main Makefile ## -echo "TARGET=$TARGET" >> Makefile echo "SUBDIRS=$SUBDIRS" >> Makefile echo "SUBTARGET=$SUBTARGET" >> Makefile echo "SHLIB_SUFFIX_NAME=$SHLIB_SUFFIX_NAME" >> Makefile @@ -1695,19 +1756,11 @@ echo "SHLIB_SUFFIX_LIST=$SHLIB_SUFFIX_LIST" >> Makefile echo "" >> Makefile #################################################################### -## Now add -DSERVER_SUBVERSION if $SUBVERSION is set -## -if [ "x$SUBVERSION" != "x" ] ; then - SUBVERSION=`echo $SUBVERSION | sed 's/^ +//'` - CFLAGS="$CFLAGS -DSERVER_SUBVERSION=\\\"$SUBVERSION\\\"" -fi - -#################################################################### ## Determine GNU Make variant because ## it uses ugly looking built-in directory walk messages ## while we are already using our own messages ## -if [ ".`make -v 2>/dev/null | grep 'GNU Make'`" = . ]; then +if [ "x`${MAKE} -v 2>/dev/null | grep 'GNU Make'`" = "x" ]; then MFLAGS_STATIC= else MFLAGS_STATIC=--no-print-directory @@ -1718,17 +1771,13 @@ fi ## for $LIBS at this point. This implies that anything below ## can only alter $LIBS ## -echo "CFLAGS1=$CFLAGS">> Makefile.config -echo "OSDIR=\$(SRCDIR)/$OSDIR">> Makefile.config -echo "INCDIR=\$(SRCDIR)/include" >>Makefile.config -echo "INCLUDES0=-I\$(OSDIR) -I\$(INCDIR)">> 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 "RANLIB=$RANLIB">> Makefile.config -echo "SHELL=$SHELL">> Makefile.config +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 "RANLIB=$RANLIB" >>Makefile.config #################################################################### ## Some OS-related stuff for the DSO mechanism: @@ -1737,31 +1786,31 @@ echo "SHELL=$SHELL">> Makefile.config if [ "x$using_shlib" = "x1" ] ; then DL_LIB="" case $PLAT in - *-ibm-aix* ) - DL_LIB="-lld" - ;; - *-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 - ;; + *-ibm-aix* ) + DL_LIB="-lld" + ;; + *-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 [ ".$DL_LIB" != . ]; then - LIBS="$LIBS $DL_LIB" - echo " + using $DL_LIB for vendor DSO support" + if [ "x$DL_LIB" != "x" ]; then + LIBS="$LIBS $DL_LIB" + echo " + using $DL_LIB for vendor DSO support" fi fi @@ -1772,18 +1821,33 @@ fi ## ap_config_auto.h so they are available to external modules needing to ## include Apache header files. ## -touch $tmpconfig ; -for cflag in $CFLAGS; do - echo $cflag | sed 's/\\\"/\"/g' >>$tmpconfig ; +TEXTRA_CFLAGS=`egrep '^EXTRA_CFLAGS=' Makefile.config | tail -1 |\ + sed -e 's;^EXTRA_CFLAGS=;;' -e 's;\`.*\`;;'` +tmpstr=`echo $CFLAGS $TEXTRA_CFLAGS |\ + sed -e 's;[ ]-;!-;g' -e 's/\\\"/\"/g' -e 's/\([^\\]\)"/\1/g'` +OIFS="$IFS" +IFS='!' +for cflag in $tmpstr; do + echo "$cflag" >>$tmpconfig done +IFS="$OIFS" +if [ -r $tmpconfig ]; then awk >>$AP_CONFIG_AUTO_H <$tmpconfig ' - /^-D.*/ { - define = substr($1, 3, length($1)-2) - split(define, parts, "=") - printf ("\n/* build flag: %s */\n", $0) - printf ("#ifndef %s\n#define %s %s\n#endif\n", parts[1],parts[1],parts[2]) + /^-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) + } ' +fi # finish header file echo "" >>$AP_CONFIG_AUTO_H @@ -1802,10 +1866,14 @@ echo "" >> Makefile.config ## Use TestCompile to see if $(CC) is ANSI and as a "final" sanity ## check ## -echo " + doing sanity check on compiler and options" -if ./helpers/TestCompile sanity; then + +if [ "$OS" = "TPF" ] ; then : else + echo " + doing sanity check on compiler and options" + if ./helpers/TestCompile sanity; then + : + else echo "** A test compilation with your Makefile configuration" echo "** failed. This is most likely because your C compiler" echo "** is not ANSI. Apache requires an ANSI C Compiler, such" @@ -1814,6 +1882,7 @@ else echo " Aborting!" exitcode=1 exit 1 + fi fi #################################################################### @@ -1895,7 +1964,7 @@ EOF } '` echo "OBJS=$OBJS" >> $moddir/Makefile - if [ ".$OBJS" != . ]; then + if [ "x$OBJS" != "x" ]; then echo "LIB=lib$basedir.a" >> $moddir/Makefile else # essential! @@ -1913,7 +1982,7 @@ EOF END { printf "SHLIBS=%s\n", shlibs; printf "OBJS_PIC=%s\n", objspic; - }' + }' $CAT << 'EOF' >> $moddir/Makefile @@ -1949,7 +2018,7 @@ depend: && 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 \ + -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \ > Makefile.tmpl \ && rm Makefile.new diff --git a/usr.sbin/httpd/src/Makefile.nt b/usr.sbin/httpd/src/Makefile.nt index 8e2a8749610..68c9a10db26 100644 --- a/usr.sbin/httpd/src/Makefile.nt +++ b/usr.sbin/httpd/src/Makefile.nt @@ -126,6 +126,7 @@ _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 diff --git a/usr.sbin/httpd/src/Makefile.tmpl b/usr.sbin/httpd/src/Makefile.tmpl index e30ac810dcd..bb9c9d8bc8a 100644 --- a/usr.sbin/httpd/src/Makefile.tmpl +++ b/usr.sbin/httpd/src/Makefile.tmpl @@ -30,24 +30,27 @@ target_static: subdirs modules.o $(CC) $(CFLAGS) $(LDFLAGS) $(LDFLAGS_SHLIB_EXPORT) \ -o $(TARGET) buildmark.o $(OBJS) $(REGLIB) $(LIBS) -target_shared: libhttpd.ep +target_compile_only: subdirs modules.o + $(CC) -c $(INCLUDES) $(CFLAGS) buildmark.c + +target_shared: lib$(TARGET).ep $(CC) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $(LDFLAGS_SHLIB_EXPORT) \ -o $(TARGET) -DSHARED_CORE_BOOTSTRAP main/http_main.c -libhttpd.ep: libhttpd.$(SHLIB_SUFFIX_NAME) +lib$(TARGET).ep: lib$(TARGET).$(SHLIB_SUFFIX_NAME) $(CC) $(INCLUDES) $(CFLAGS) $(LDFLAGS) $(LDFLAGS_SHLIB_EXPORT) \ - -o libhttpd.ep -DSHARED_CORE_TIESTATIC main/http_main.c \ - -L. -lhttpd $(LIBS) + -o lib$(TARGET).ep -DSHARED_CORE_TIESTATIC main/http_main.c \ + -L. -l$(TARGET) $(LIBS) -libhttpd.$(SHLIB_SUFFIX_NAME): subdirs modules.o +lib$(TARGET).$(SHLIB_SUFFIX_NAME): subdirs modules.o $(CC) -c $(INCLUDES) $(CFLAGS) buildmark.c - $(LD_SHLIB) $(LDFLAGS_SHLIB) -o libhttpd.$(SHLIB_SUFFIX_NAME) buildmark.o $(OBJS) $(REGLIB) + $(LD_SHLIB) $(LDFLAGS_SHLIB) -o lib$(TARGET).$(SHLIB_SUFFIX_NAME) buildmark.o $(OBJS) $(REGLIB) @if [ ".$(SHLIB_SUFFIX_LIST)" != . ]; then \ - rm -f libhttpd.$(SHLIB_SUFFIX_NAME).*; \ + rm -f lib$(TARGET).$(SHLIB_SUFFIX_NAME).*; \ for suffix in $(SHLIB_SUFFIX_LIST) ""; do \ [ ".$$suffix" = . ] && continue; \ - echo "ln libhttpd.$(SHLIB_SUFFIX_NAME) libhttpd.$(SHLIB_SUFFIX_NAME).$$suffix"; \ - ln libhttpd.$(SHLIB_SUFFIX_NAME) libhttpd.$(SHLIB_SUFFIX_NAME).$$suffix; \ + 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 @@ -66,7 +69,7 @@ support-dir: echo "<=== $(SDP)support" clean: - -rm -f $(TARGET) libhttpd.* *.o + -rm -f $(TARGET) lib$(TARGET).* *.o @for i in $(SUBDIRS); do \ echo "===> $(SDP)$$i"; \ ( cd $$i && $(MAKE) $(MFLAGS_STATIC) SDP='$(SDP)' $@ ) || exit 1; \ @@ -74,7 +77,7 @@ clean: done distclean: - -rm -f $(TARGET) libhttpd.* *.o + -rm -f $(TARGET) lib$(TARGET).* *.o @for i in $(SUBDIRS); do \ echo "===> $(SDP)$$i"; \ ( cd $$i && $(MAKE) $(MFLAGS_STATIC) SDP='$(SDP)' $@ ) || exit 1; \ diff --git a/usr.sbin/httpd/src/ap/ap_cpystrn.c b/usr.sbin/httpd/src/ap/ap_cpystrn.c index 159bdbe80dc..a9813f4005c 100644 --- a/usr.sbin/httpd/src/ap/ap_cpystrn.c +++ b/usr.sbin/httpd/src/ap/ap_cpystrn.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/ap/ap_execve.c b/usr.sbin/httpd/src/ap/ap_execve.c index 32c9e376c51..435334610c1 100644 --- a/usr.sbin/httpd/src/ap/ap_execve.c +++ b/usr.sbin/httpd/src/ap/ap_execve.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1998 The Apache Group. All rights reserved. + * 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 @@ -126,7 +126,8 @@ int ap_execle(const char *filename, const char *argv0, ...) } va_end(adummy); - argv = (char **) malloc((argc + 2) * sizeof(*argv)); + if ((argv = (char **) malloc((argc + 2) * sizeof(*argv))) == NULL) + return -1; /* Pass two --- copy the argument strings into the result space */ va_start(adummy, argv0); @@ -143,10 +144,27 @@ int ap_execle(const char *filename, const char *argv0, ...) return ret; } +/* Count number of entries in vector "args", including the trailing NULL entry + */ +static int +count_args(const char **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, const char *argv[], const char *envp[]) { - const char *argv0 = argv[0]; + const char **script_argv; extern char **environ; if (envp == NULL) { @@ -174,26 +192,50 @@ int ap_execve(const char *filename, const char *argv[], * 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. - */ - && (argv = hashbang(filename, argv)) != NULL) { + 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 = 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]; + } - /* new filename is the interpreter to call */ - filename = argv[0]; + execve(filename, script_argv, envp); - /* Restore argv[0] as on entry */ - if (argv0 != NULL) { - argv[0] = argv0; + 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) + return -1; + + script_argv[0] = SHELL_PATH; + + while (i > 0) { + script_argv[i] = argv[i-1]; + --i; + } - execve(filename, argv, envp); + execve(SHELL_PATH, script_argv, envp); - free(argv); + free(script_argv); + } } return -1; } diff --git a/usr.sbin/httpd/src/ap/ap_signal.c b/usr.sbin/httpd/src/ap/ap_signal.c index 26ad707b55f..5420d5061bc 100644 --- a/usr.sbin/httpd/src/ap/ap_signal.c +++ b/usr.sbin/httpd/src/ap/ap_signal.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/ap/ap_slack.c b/usr.sbin/httpd/src/ap/ap_slack.c index 5c7c19028d2..4fff5e05c87 100644 --- a/usr.sbin/httpd/src/ap/ap_slack.c +++ b/usr.sbin/httpd/src/ap/ap_slack.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/ap/ap_snprintf.c b/usr.sbin/httpd/src/ap/ap_snprintf.c index 3713b83194e..19292a92792 100644 --- a/usr.sbin/httpd/src/ap/ap_snprintf.c +++ b/usr.sbin/httpd/src/ap/ap_snprintf.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/buildmark.c b/usr.sbin/httpd/src/buildmark.c index f5624c8dc17..575b9731a09 100644 --- a/usr.sbin/httpd/src/buildmark.c +++ b/usr.sbin/httpd/src/buildmark.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/helpers/GuessOS b/usr.sbin/httpd/src/helpers/GuessOS index 096df4fd965..bac2b5ebc10 100644 --- a/usr.sbin/httpd/src/helpers/GuessOS +++ b/usr.sbin/httpd/src/helpers/GuessOS @@ -5,10 +5,7 @@ # 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) in general -# and to Jim Jagielski (jim@apache.org) in specific. -# -# Blame Jim; he wrote it (plus a cast of dozens) +# Emailed to the Apache group (apache@apache.org). # # Be as similar to the output of config.guess/config.sub # as possible. @@ -204,11 +201,11 @@ case "${SYSTEM}:${RELEASE}:${VERSION}:${MACHINE}" in ;; SINIX-?:* | ReliantUNIX-?:*) - echo "${MACHINE}-sni-sysv4"; exit 0 + echo "${MACHINE}-siemens-sysv4"; exit 0 ;; POSIX*BS2000) - echo "${MACHINE}-sni-sysv4"; exit 0 + echo "${MACHINE}-siemens-sysv4"; exit 0 ;; machten:*) @@ -222,6 +219,11 @@ case "${SYSTEM}:${RELEASE}:${VERSION}:${MACHINE}" in 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 @@ -270,6 +272,13 @@ if [ -d /usr/apollo ]; then exit 0 fi +# Apache is not compiled on the TPF platform +# therefore an environment variable is used +if [ "$TPF" = "YES" ]; then + echo "TPF" + exit 0 +fi + # Now NeXT ISNEXT=`hostinfo 2>/dev/null` case "$ISNEXT" in diff --git a/usr.sbin/httpd/src/helpers/PrintPath b/usr.sbin/httpd/src/helpers/PrintPath index 9ec0e0c37f0..71335280fd3 100644 --- a/usr.sbin/httpd/src/helpers/PrintPath +++ b/usr.sbin/httpd/src/helpers/PrintPath @@ -1,46 +1,102 @@ #!/bin/sh -# Look for $1 somewhere in $PATH -# will print out the full pathname unless -# called with the '-s' option +# Look for program[s] somewhere in $PATH. # -# We do some funny stuff to check to see -# if test/[] knows about -x +# Options: +# -s +# Do not print out full pathname. (silent) +# -pPATHNAME +# Look in PATHNAME instead of $PATH # -testfile="pp.t.$$" +# Usage: +# PrintPath [-s] [-pPATHNAME] program [program ...] +# +# 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 + cat > $testfile <<ENDTEST #!/bin/sh if [ -x / ] || [ -x /bin ] || [ -x /bin/ls ]; then - exit 0 + 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 - -if [ "x$1" = "x-s" ]; then - shift -else - echo="yes" + if `/bin/sh $testfile 2>/dev/null`; then + test_exec_flag="-x" + else + test_exec_flag="-r" + fi + rm -f $testfile fi -for path in `echo $PATH | - sed 's/^:/.:/ - s/::/:.:/g - s/:$/:./ - s/:/ /g' ` +for program in $programs do - if [ $test_exec_flag $path/$1 ] && [ ! -d $path/$1 ]; then - if [ "$echo" = "yes" ]; then - echo $path/$1 + for path in $pathname + do + if [ $test_exec_flag $path/${program}${ext} ] && \ + [ ! -d $path/${program}${ext} ]; then + if [ "$echo" = "yes" ]; then + echo $path/${program}${ext} + fi + exit 0 fi - exit 0 - fi + done done exit 1 diff --git a/usr.sbin/httpd/src/helpers/TestCompile b/usr.sbin/httpd/src/helpers/TestCompile index b57ea93e98c..6be8d474301 100644 --- a/usr.sbin/httpd/src/helpers/TestCompile +++ b/usr.sbin/httpd/src/helpers/TestCompile @@ -32,8 +32,6 @@ trap 'rm -f Makefile dummy dummy.exe testfunc.c testfunc testfunc.exe; exit $exs # located) if you want to test it out. Configure must # also call it as './helpers/TestCompile' # -# Blame Jim; he wrote it (along with a cast of dozens). -# # This script falls under the Apache License. # See http://www.apache.org/docs/LICENSE @@ -145,7 +143,7 @@ testfunc: EOF # Now run that Makefile -eval "make $TARGET >/dev/null $ERRDIR" +eval "${MAKE} ${TARGET} >/dev/null $ERRDIR" # And see if dummy exists and is executable, if so, then we # assume the condition we are testing for is good diff --git a/usr.sbin/httpd/src/helpers/mkshadow.sh b/usr.sbin/httpd/src/helpers/mkshadow.sh index d289455da97..448a09455cf 100644 --- a/usr.sbin/httpd/src/helpers/mkshadow.sh +++ b/usr.sbin/httpd/src/helpers/mkshadow.sh @@ -19,18 +19,35 @@ DIFS=' src=`echo $1 | sed -e 's:/$::'` dst=`echo $2 | sed -e 's:/$::'` -# determine if source is an absolute path +# 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 - /* ) srcisabs=1 ;; - * ) srcisabs=0 ;; + /* ) oneisabs=1 ;; esac - -# determine reverse directory to directory case $dst in - /* ) dstrevdir='' ;; - * ) dstrevdir="`$src/helpers/fp2rp $dst`/" ;; + /* ) oneisabs=1 ;; esac +# determine reverse directory for destination directory +dstrevdir='' +if [ $oneisabs = 0 ]; 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 @@ -48,7 +65,7 @@ IFS="$OIFS" # fill directory tree with symlinks to files FILES="`cd $src - find . -type f -depth -print |\ + find . -depth -print |\ sed -e '/\.o$/d' \ -e '/\.a$/d' \ -e '/\.so$/d' \ @@ -63,23 +80,29 @@ FILES="`cd $src -e 's/^\.\///'`" OIFS="$IFS" IFS="$DIFS" for file in $FILES; do + # don't use `-type f' above for find because of symlinks + if [ -d $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 [ $srcisabs = 0 -a ".$dir" != . ]; 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" + if [ $oneisabs = 0 ]; then + if [ ".$dir" != . ]; 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 - from="$dstrevdir$from" echo " $to" ln -s $from $to done diff --git a/usr.sbin/httpd/src/include/alloc.h b/usr.sbin/httpd/src/include/alloc.h index cf7cde27118..b68a89dc192 100644 --- a/usr.sbin/httpd/src/include/alloc.h +++ b/usr.sbin/httpd/src/include/alloc.h @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -149,6 +149,15 @@ 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. @@ -269,8 +278,13 @@ API_EXPORT_NONSTD(void) ap_null_cleanup(void *data); * 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 diff --git a/usr.sbin/httpd/src/include/ap.h b/usr.sbin/httpd/src/include/ap.h index b4d22a227c1..ed18dbd002c 100644 --- a/usr.sbin/httpd/src/include/ap.h +++ b/usr.sbin/httpd/src/include/ap.h @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/include/ap_compat.h b/usr.sbin/httpd/src/include/ap_compat.h index a18474f8c5a..4da74a61d07 100644 --- a/usr.sbin/httpd/src/include/ap_compat.h +++ b/usr.sbin/httpd/src/include/ap_compat.h @@ -325,6 +325,7 @@ extern "C" { #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 @@ -372,6 +373,7 @@ extern "C" { #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 diff --git a/usr.sbin/httpd/src/include/ap_config.h b/usr.sbin/httpd/src/include/ap_config.h index 60e35665ab6..1b98de0a394 100644 --- a/usr.sbin/httpd/src/include/ap_config.h +++ b/usr.sbin/httpd/src/include/ap_config.h @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -84,6 +84,27 @@ stat() properly */ #include <sys/types.h> #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_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 process.h first so we can override spawn[lv]e* properly */ #include <process.h> @@ -92,7 +113,7 @@ stat() properly */ #include "os.h" #endif -#if !defined(QNX) && !defined(MPE) && !defined(WIN32) +#if !defined(QNX) && !defined(MPE) && !defined(WIN32) && !defined(TPF) #include <sys/param.h> #endif @@ -436,11 +457,6 @@ typedef int pid_t; #define HAVE_MMAP 1 #define USE_MMAP_FILES -/* glibc 2.1 and later finally define rlim_t */ -#if !defined(__GLIBC__) || __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1) -typedef int rlim_t; -#endif - /* flock is faster ... but hasn't been tested on 1.x systems */ #define USE_FLOCK_SERIALIZED_ACCEPT @@ -457,6 +473,11 @@ typedef int rlim_t; #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 @@ -541,13 +562,18 @@ extern char *crypt(); #define NEED_INITGROUPS #define NEED_HASHBANG_EMUL /* execve() doesn't start shell scripts by default */ #undef HAVE_SHMGET +#undef NEED_STRCASECMP +#undef NEED_STRNCASECMP #undef USE_SHMGET_SCOREBOARD #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 @@ -564,14 +590,18 @@ extern char *crypt(); #endif #define NET_SIZE_T size_t #define HAVE_SYSLOG 1 -#define USE_FCNTL_SERIALIZED_ACCEPT #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 @@ -588,11 +618,13 @@ extern char *crypt(); #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 -#endif +#define USE_FLOCK_SERIALIZED_ACCEPT +#define SINGLE_LISTEN_UNSERIALIZED_ACCEPT #elif defined(UTS21) #undef HAVE_GMTOFF @@ -795,10 +827,45 @@ typedef int rlim_t; #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 NEED_INITGROUPS +#define NEED_STRCASECMP +#define NEED_STRDUP +#define NEED_STRNCASECMP +#define NO_DBM_REWRITEMAP +#define NO_GETTIMEOFDAY +#define NO_KILLPG +#define NO_LINGCLOSE +#define NO_MMAP +#define NO_OTHER_CHILD +#define NO_RELIABLE_PIPED_LOGS +#define NO_SETSID +#define NO_SHMGET +#define NO_SLACK +#define NO_TIMES +#define NO_USE_SIGACTION +#define NO_WRITEV +#define USE_LONGJMP +#define USE_TPF_SELECT +#undef offsetof +#define offsetof(s_type,field) ((size_t)&(((s_type*)0)->field)) + #else /* Unknown system - Edit these to match */ #ifdef BSD @@ -847,38 +914,17 @@ typedef int rlim_t; #define CORE_EXPORT_NONSTD API_EXPORT_NONSTD #endif -/* On OpenStep and Rhapsody, symbols that conflict with loaded dylibs +/* 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(RHAPSODY) || defined(NEXT) +#if defined(RHAPSODY) #define ap_private_extern __private_extern__ #else #define ap_private_extern #endif -/* 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_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 - /* * The particular directory style your system supports. If you have dirent.h * in /usr/include (POSIX) or /usr/include/sys (SYSV), #include @@ -904,7 +950,7 @@ typedef int rlim_t; #include <stdlib.h> #include <string.h> #include "ap_ctype.h" -#if !defined(MPE) && !defined(WIN32) +#if !defined(MPE) && !defined(WIN32) && !defined(TPF) #include <sys/file.h> #endif #ifndef WIN32 @@ -912,10 +958,12 @@ typedef int rlim_t; #ifdef HAVE_SYS_SELECT_H #include <sys/select.h> #endif /* HAVE_SYS_SELECT_H */ +#ifndef TPF #include <netinet/in.h> +#endif /* TPF */ #include <netdb.h> #include <sys/ioctl.h> -#if !defined(MPE) && !defined(BEOS) +#if !defined(MPE) && !defined(BEOS) && !defined(TPF) #include <arpa/inet.h> /* for inet_ntoa */ #endif #include <sys/wait.h> @@ -936,9 +984,12 @@ typedef int rlim_t; #endif /* ndef WIN32 */ #include <time.h> /* for ctime */ +#ifdef WIN32 +#define strftime(s,max,format,tm) os_strftime(s,max,format,tm) +#endif #include <signal.h> #include <errno.h> -#if !defined(QNX) && !defined(CONVEXOS11) && !defined(NEXT) +#if !defined(QNX) && !defined(CONVEXOS11) && !defined(NEXT) && !defined(TPF) #include <memory.h> #endif @@ -1042,6 +1093,8 @@ Sigfunc *signal(int signo, Sigfunc * func); #ifdef SELECT_NEEDS_CAST #define ap_select(_a, _b, _c, _d, _e) \ select((_a), (int *)(_b), (int *)(_c), (int *)(_d), (_e)) +#elif defined(USE_TPF_SELECT) +#define ap_select tpf_select #else #define ap_select select #endif diff --git a/usr.sbin/httpd/src/include/ap_ctype.h b/usr.sbin/httpd/src/include/ap_ctype.h index bba58b45dff..c4ff812d5ee 100644 --- a/usr.sbin/httpd/src/include/ap_ctype.h +++ b/usr.sbin/httpd/src/include/ap_ctype.h @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/include/ap_md5.h b/usr.sbin/httpd/src/include/ap_md5.h index bf61b4dcd39..0da983c62fd 100644 --- a/usr.sbin/httpd/src/include/ap_md5.h +++ b/usr.sbin/httpd/src/include/ap_md5.h @@ -29,7 +29,7 @@ */ /* ==================================================================== - * Copyright (c) 1996-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/include/ap_mmn.h b/usr.sbin/httpd/src/include/ap_mmn.h index 5ad482c319d..bbfabe604f4 100644 --- a/usr.sbin/httpd/src/include/ap_mmn.h +++ b/usr.sbin/httpd/src/include/ap_mmn.h @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1998 The Apache Group. All rights reserved. + * 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 @@ -181,10 +181,34 @@ * (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. */ +#define MODULE_MAGIC_COOKIE 0x41503133UL /* "AP13" */ + #ifndef MODULE_MAGIC_NUMBER_MAJOR -#define MODULE_MAGIC_NUMBER_MAJOR 19980917 +#define MODULE_MAGIC_NUMBER_MAJOR 19990108 #endif #define MODULE_MAGIC_NUMBER_MINOR 0 /* 0...n */ #define MODULE_MAGIC_NUMBER MODULE_MAGIC_NUMBER_MAJOR /* backward compat */ diff --git a/usr.sbin/httpd/src/include/buff.h b/usr.sbin/httpd/src/include/buff.h index a20338fa650..27ccd1537be 100644 --- a/usr.sbin/httpd/src/include/buff.h +++ b/usr.sbin/httpd/src/include/buff.h @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1996-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/include/hsregex.h b/usr.sbin/httpd/src/include/hsregex.h index 319bb4010d3..e5b24e60f77 100644 --- a/usr.sbin/httpd/src/include/hsregex.h +++ b/usr.sbin/httpd/src/include/hsregex.h @@ -16,7 +16,7 @@ extern "C" { #endif #endif -#if defined(RHAPSODY) || defined(NEXT) +#if defined(RHAPSODY) #define ap_private_extern __private_extern__ #else #define ap_private_extern diff --git a/usr.sbin/httpd/src/include/http_conf_globals.h b/usr.sbin/httpd/src/include/http_conf_globals.h index deeca88a485..c540c4e0a8c 100644 --- a/usr.sbin/httpd/src/include/http_conf_globals.h +++ b/usr.sbin/httpd/src/include/http_conf_globals.h @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/include/http_config.h b/usr.sbin/httpd/src/include/http_config.h index 8ac75f2ad7a..5962efc186c 100644 --- a/usr.sbin/httpd/src/include/http_config.h +++ b/usr.sbin/httpd/src/include/http_config.h @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -198,11 +198,15 @@ typedef struct module_struct { */ 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 @@ -286,7 +290,8 @@ typedef struct module_struct { -1, \ __FILE__, \ NULL, \ - NULL + NULL, \ + MODULE_MAGIC_COOKIE /* Generic accessors for other modules to get at their own module-specific * data @@ -336,6 +341,11 @@ 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); +void ap_single_module_init(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); @@ -361,10 +371,10 @@ 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); -/* check_cmd_context() definitions: */ +/* ap_check_cmd_context() definitions: */ API_EXPORT(const char *) ap_check_cmd_context(cmd_parms *cmd, unsigned forbidden); -/* check_cmd_context(): Forbidden in: */ +/* ap_check_cmd_context(): Forbidden in: */ #define NOT_IN_VIRTUALHOST 0x01 /* <Virtualhost> */ #define NOT_IN_LIMIT 0x02 /* <Limit> */ #define NOT_IN_DIRECTORY 0x04 /* <Directory> */ diff --git a/usr.sbin/httpd/src/include/http_core.h b/usr.sbin/httpd/src/include/http_core.h index f23439dbe30..3eeda2e8fde 100644 --- a/usr.sbin/httpd/src/include/http_core.h +++ b/usr.sbin/httpd/src/include/http_core.h @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -133,6 +133,7 @@ API_EXPORT(const char *) ap_get_server_name(const 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 @@ -156,7 +157,7 @@ API_EXPORT(const array_header *) ap_requires (request_rec *); /* * 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, anothre accessor. + * the code that cares really is in http_core.c. Also, another accessor. */ char *ap_response_code_string (request_rec *r, int error_index); diff --git a/usr.sbin/httpd/src/include/http_log.h b/usr.sbin/httpd/src/include/http_log.h index 3932fa396d2..d9162bd22fb 100644 --- a/usr.sbin/httpd/src/include/http_log.h +++ b/usr.sbin/httpd/src/include/http_log.h @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -105,6 +105,15 @@ extern "C" { #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))); diff --git a/usr.sbin/httpd/src/include/http_main.h b/usr.sbin/httpd/src/include/http_main.h index 78adaf85c8b..a0d014de785 100644 --- a/usr.sbin/httpd/src/include/http_main.h +++ b/usr.sbin/httpd/src/include/http_main.h @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/include/http_protocol.h b/usr.sbin/httpd/src/include/http_protocol.h index 84fbe7106f0..bd57fd813c6 100644 --- a/usr.sbin/httpd/src/include/http_protocol.h +++ b/usr.sbin/httpd/src/include/http_protocol.h @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -115,6 +115,7 @@ void ap_send_error_response(request_rec *r, int recursive_error); 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); @@ -209,6 +210,11 @@ void ap_finalize_sub_req_protocol(request_rec *sub_r); 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 diff --git a/usr.sbin/httpd/src/include/http_request.h b/usr.sbin/httpd/src/include/http_request.h index 1ed296151a7..bc3e938a983 100644 --- a/usr.sbin/httpd/src/include/http_request.h +++ b/usr.sbin/httpd/src/include/http_request.h @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/include/http_vhost.h b/usr.sbin/httpd/src/include/http_vhost.h index 7b23381ed74..acdb6e2f426 100644 --- a/usr.sbin/httpd/src/include/http_vhost.h +++ b/usr.sbin/httpd/src/include/http_vhost.h @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/include/httpd.h b/usr.sbin/httpd/src/include/httpd.h index d5d390ec8ce..318966b4a8d 100644 --- a/usr.sbin/httpd/src/include/httpd.h +++ b/usr.sbin/httpd/src/include/httpd.h @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -110,6 +110,11 @@ extern "C" { /* 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 ---------- * @@ -410,7 +415,7 @@ extern "C" { * Example: "Apache/1.1.0 MrWidget/0.1-alpha" */ -#define SERVER_BASEVERSION "Apache/1.3.3" /* SEE COMMENTS ABOVE */ +#define SERVER_BASEVERSION "Apache/1.3.4" /* SEE COMMENTS ABOVE */ #define SERVER_VERSION SERVER_BASEVERSION enum server_token_type { SrvTk_MIN, /* eg: Apache/1.3.0 */ @@ -422,12 +427,11 @@ 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: major minor bugfix betaseq +/* Numeric release version identifier: MMNNFFRBB: major minor fix final beta * Always increases along the same track as the source branch. - * For a final release, 'betaseq' should be set to '99'. - * For example, Apache 1.4.2 should be '1040299' + * For example, Apache 1.4.2 would be '10402100', 2.5b7 would be '20500007'. */ -#define APACHE_RELEASE 1030399 +#define APACHE_RELEASE 10304100 #define SERVER_PROTOCOL "HTTP/1.1" #ifndef SERVER_SUPPORT @@ -447,7 +451,7 @@ API_EXPORT(const char *) ap_get_server_built(void); * all of the potential response status-lines (a sparse table). * A future version should dynamically generate the table at startup. */ -#define RESPONSE_CODES 54 +#define RESPONSE_CODES 55 #define HTTP_CONTINUE 100 #define HTTP_SWITCHING_PROTOCOLS 101 @@ -487,6 +491,7 @@ API_EXPORT(const char *) ap_get_server_built(void); #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 @@ -494,6 +499,7 @@ API_EXPORT(const char *) ap_get_server_built(void); #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 @@ -522,7 +528,8 @@ API_EXPORT(const char *) ap_get_server_built(void); #define ap_is_HTTP_CLIENT_ERROR(x) (((x) >= 400)&&((x) < 500)) #define ap_is_HTTP_SERVER_ERROR(x) (((x) >= 500)&&((x) < 600)) -#define status_drops_connection(x) (((x) == HTTP_BAD_REQUEST) || \ +#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) || \ @@ -531,16 +538,28 @@ API_EXPORT(const char *) ap_get_server_built(void); ((x) == HTTP_SERVICE_UNAVAILABLE) || \ ((x) == HTTP_NOT_IMPLEMENTED)) - -#define METHODS 8 -#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_INVALID 7 +/* 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 METHODS 15 +#define M_INVALID 31 #define CGI_MAGIC_TYPE "application/x-httpd-cgi" #define INCLUDES_MAGIC_TYPE "text/x-server-parsed-html" @@ -692,6 +711,7 @@ struct request_rec { 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 @@ -722,6 +742,8 @@ struct request_rec { 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; @@ -758,7 +780,6 @@ struct request_rec { * record to improve 64bit alignment the next time we need to break * binary compatibility for some other reason. */ - unsigned expecting_100; /* is client waiting for a 100 response? */ }; @@ -923,7 +944,7 @@ 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 escape_uri(ppool,path) ap_os_escape_path(ppool,path,1) +#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); @@ -997,14 +1018,26 @@ 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); +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 *); @@ -1051,7 +1084,7 @@ API_EXPORT(char *) ap_escape_quotes(pool *p, const char *instr); */ API_EXPORT(void) ap_log_assert(const char *szExp, const char *szFile, int nLine) __attribute__((noreturn)); -#define ap_assert(exp) (void)( (exp) || (ap_log_assert(#exp, __FILE__, __LINE__), 0) ) +#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 diff --git a/usr.sbin/httpd/src/include/rfc1413.h b/usr.sbin/httpd/src/include/rfc1413.h index e84b0c3e35e..e69c9d2a147 100644 --- a/usr.sbin/httpd/src/include/rfc1413.h +++ b/usr.sbin/httpd/src/include/rfc1413.h @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1996-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/include/scoreboard.h b/usr.sbin/httpd/src/include/scoreboard.h index 9d22e9024e8..177b3bde4b8 100644 --- a/usr.sbin/httpd/src/include/scoreboard.h +++ b/usr.sbin/httpd/src/include/scoreboard.h @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -63,7 +63,11 @@ extern "C" { #endif #ifndef WIN32 +#ifdef TPF +#include <time.h> +#else #include <sys/times.h> +#endif /* TPF */ #endif /* Scoreboard info on a process is, for now, kept very brief --- @@ -102,6 +106,29 @@ extern "C" { */ 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 @@ -130,12 +157,13 @@ typedef struct { #endif char client[32]; /* Keep 'em small... */ char request[64]; /* We just want an idea... */ - char vhost[32]; /* What virtual host is being accessed? */ + server_rec *vhostrec; /* What virtual host is being accessed? */ + /* SEE ABOVE FOR SAFE USAGE! */ } short_score; typedef struct { - int exit_generation; /* Set by the main process if a graceful - restart is required */ + 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 */ @@ -145,6 +173,7 @@ typedef struct { 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 { @@ -160,6 +189,8 @@ 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 diff --git a/usr.sbin/httpd/src/include/util_date.h b/usr.sbin/httpd/src/include/util_date.h index 3ce9b715a98..8e2051024e6 100644 --- a/usr.sbin/httpd/src/include/util_date.h +++ b/usr.sbin/httpd/src/include/util_date.h @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1996-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/include/util_md5.h b/usr.sbin/httpd/src/include/util_md5.h index fa2cefe426e..3fc35dc7e0f 100644 --- a/usr.sbin/httpd/src/include/util_md5.h +++ b/usr.sbin/httpd/src/include/util_md5.h @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/include/util_script.h b/usr.sbin/httpd/src/include/util_script.h index 2c5aa5af66f..416d72942dc 100644 --- a/usr.sbin/httpd/src/include/util_script.h +++ b/usr.sbin/httpd/src/include/util_script.h @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -74,7 +74,6 @@ 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); -#define scan_script_header(a1,a2) ap_scan_script_header_err(a1,a2,NULL) 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); diff --git a/usr.sbin/httpd/src/include/util_uri.h b/usr.sbin/httpd/src/include/util_uri.h index 6309a4792b5..d5a67593fc4 100644 --- a/usr.sbin/httpd/src/include/util_uri.h +++ b/usr.sbin/httpd/src/include/util_uri.h @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/main/alloc.c b/usr.sbin/httpd/src/main/alloc.c index e85a85aa3d2..550f5f75c46 100644 --- a/usr.sbin/httpd/src/main/alloc.c +++ b/usr.sbin/httpd/src/main/alloc.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -1047,6 +1047,60 @@ API_EXPORT(array_header *) ap_append_arrays(pool *p, 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; +} + /***************************************************************** * diff --git a/usr.sbin/httpd/src/main/buff.c b/usr.sbin/httpd/src/main/buff.c index a8cb2515160..cf78599c7c7 100644 --- a/usr.sbin/httpd/src/main/buff.c +++ b/usr.sbin/httpd/src/main/buff.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1996-1998 The Apache Group. All rights reserved. + * 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 @@ -259,6 +259,24 @@ static ap_inline int buff_read(BUFF *fb, void *buf, int nbyte) } else rv = ap_read(fb, buf, nbyte); +#elif defined(TPF) + fd_set fds; + struct timeval tv; + + tpf_process_signals(); + if (fb->flags & B_SOCKET) { + alarm(rv = alarm(0)); + FD_ZERO(&fds); + FD_SET(fb->fd_in, &fds); + tv.tv_sec = rv+1; + tv.tv_usec = 0; + rv = ap_select(fb->fd_in + 1, &fds, NULL, NULL, &tv); + if (rv < 1) { + tpf_process_signals(); + return(rv); + } + } + rv = ap_read(fb, buf, nbyte); #else rv = ap_read(fb, buf, nbyte); #endif /* WIN32 */ @@ -1578,3 +1596,4 @@ API_EXPORT(int) ap_vbprintf(BUFF *fb, const char *fmt, va_list ap) } return res; } + diff --git a/usr.sbin/httpd/src/main/http_config.c b/usr.sbin/httpd/src/main/http_config.c index 50f865712b1..206dae888eb 100644 --- a/usr.sbin/httpd/src/main/http_config.c +++ b/usr.sbin/httpd/src/main/http_config.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -479,7 +479,7 @@ int ap_invoke_handler(request_rec *r) const char *handler; char *p; size_t handler_len; - int result = NOT_IMPLEMENTED; + int result = HTTP_INTERNAL_SERVER_ERROR; if (r->handler) { handler = r->handler; @@ -509,7 +509,7 @@ int ap_invoke_handler(request_rec *r) } } - if (result == NOT_IMPLEMENTED && r->handler) { + if (result == HTTP_INTERNAL_SERVER_ERROR && r->handler) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, "handler \"%s\" not found for: %s", r->handler, r->filename); } @@ -526,7 +526,7 @@ int ap_invoke_handler(request_rec *r) } } - return NOT_IMPLEMENTED; + return HTTP_INTERNAL_SERVER_ERROR; } /* One-time setup for precompiled modules --- NOT to be done on restart */ @@ -539,8 +539,8 @@ API_EXPORT(void) ap_add_module(module *m) */ if (m->version != MODULE_MAGIC_NUMBER_MAJOR) { - fprintf(stderr, "httpd: module \"%s\" is not compatible with this " - "version of Apache.\n", m->name); + 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); } @@ -554,8 +554,8 @@ API_EXPORT(void) ap_add_module(module *m) dynamic_modules++; if (dynamic_modules > DYNAMIC_MODULE_LIMIT) { - fprintf(stderr, "httpd: module \"%s\" could not be loaded, because" - " the dynamic\n", m->name); + 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); @@ -1179,8 +1179,8 @@ void ap_process_resource_config(server_rec *s, char *fname, pool *p, pool *ptemp if (!(parms.config_file = ap_pcfg_openfile(p,fname))) { perror("fopen"); - fprintf(stderr, "httpd: could not open document config file %s\n", - fname); + fprintf(stderr, "%s: could not open document config file %s\n", + ap_server_argv0, fname); exit(1); } @@ -1188,7 +1188,7 @@ void ap_process_resource_config(server_rec *s, char *fname, pool *p, pool *ptemp if (errmsg) { fprintf(stderr, "Syntax error on line %d of %s:\n", - parms.config_file->line_number, fname); + parms.config_file->line_number, parms.config_file->name); fprintf(stderr, "%s\n", errmsg); exit(1); } @@ -1476,6 +1476,23 @@ server_rec *ap_read_config(pool *p, pool *ptemp, char *confname) 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_single_module_init(pool *p, server_rec *s, module *m) +{ + if (m->init) + (*m->init)(s, p); + build_method_shortcuts(); + init_handlers(p); +} void ap_init_modules(pool *p, server_rec *s) { @@ -1540,9 +1557,9 @@ static void show_overrides(const command_rec *pc, module *pm) ((pc->req_override & (ACCESS_CONF | OR_AUTHCFG | OR_LIMIT))))) printf("anywhere"); else if (pc->req_override & RSRC_CONF) - printf("only outside <Directory> or <Location>"); + printf("only outside <Directory>, <Files> or <Location>"); else - printf("only inside <Directory> or <Location>"); + printf("only inside <Directory>, <Files> or <Location>"); /* Warn if the directive is allowed inside <Directory> or .htaccess * but module doesn't support per-dir configuration */ diff --git a/usr.sbin/httpd/src/main/http_core.c b/usr.sbin/httpd/src/main/http_core.c index 320f907e6f1..979f475122a 100644 --- a/usr.sbin/httpd/src/main/http_core.c +++ b/usr.sbin/httpd/src/main/http_core.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -418,6 +418,8 @@ void ap_core_reorder_directories(pool *p, server_rec *s) qsort(sortbin, nelts, sizeof(*sortbin), reorder_sorter); /* and now build a new array */ + /* XXX: uh I don't see why we can't reuse the old array, what + * was I thinking? -djg */ sec = ap_make_array(p, nelts, sizeof(void *)); for (i = 0; i < nelts; ++i) { *(void **)ap_push_array(sec) = sortbin[i].elt; @@ -886,15 +888,23 @@ static const char *set_error_document(cmd_parms *cmd, core_dir_config *conf, return ap_pstrcat(cmd->pool, "Unsupported HTTP response code ", w, NULL); } - - /* Store it... */ - if (conf->response_code_strings == NULL) { - conf->response_code_strings = - ap_pcalloc(cmd->pool, - sizeof(*conf->response_code_strings) * RESPONSE_CODES); + /* 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, NULL, + "cannot use a full URL in a 401 ErrorDocument " + "directive --- ignoring!"); } - conf->response_code_strings[index_number] = ap_pstrdup(cmd->pool, line); + 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; } @@ -1068,28 +1078,18 @@ CORE_EXPORT_NONSTD(const char *) ap_limit_section(cmd_parms *cmd, void *dummy, while (limited_methods[0]) { char *method = ap_getword_conf(cmd->pool, &limited_methods); - if (!strcmp(method, "GET")) { - limited |= (1 << M_GET); - } - else if (!strcmp(method, "PUT")) { - limited |= (1 << M_PUT); - } - else if (!strcmp(method, "POST")) { - limited |= (1 << M_POST); - } - else if (!strcmp(method, "DELETE")) { - limited |= (1 << M_DELETE); - } - else if (!strcmp(method, "CONNECT")) { - limited |= (1 << M_CONNECT); - } - else if (!strcmp(method, "OPTIONS")) { - limited |= (1 << M_OPTIONS); - } - else { - return ap_pstrcat(cmd->pool, "unknown method \"", - method, "\" in <Limit>", NULL); - } + int methnum = ap_method_number_of(method); + + if (methnum == M_TRACE) { + return "TRACE cannot be controlled by <Limit>"; + } + else if (methnum == M_INVALID) { + return ap_pstrcat(cmd->pool, "unknown method \"", + method, "\" in <Limit>", NULL); + } + else { + limited |= (1 << methnum); + } } cmd->limited = limited; @@ -1149,6 +1149,15 @@ static const char *end_nested_section(cmd_parms *cmd, void *dummy) 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; @@ -1167,10 +1176,12 @@ static const char *dirsection(cmd_parms *cmd, void *dummy, const char *arg) return err; } - if (endp) { - *endp = '\0'; + if (endp == NULL) { + return unclosed_directive(cmd); } + *endp = '\0'; + cmd->path = ap_getword_conf(cmd->pool, &arg); #ifdef OS2 /* Fix OS/2 HPFS filename case problem. */ @@ -1238,10 +1249,12 @@ static const char *urlsection(cmd_parms *cmd, void *dummy, const char *arg) return err; } - if (endp) { - *endp = '\0'; + if (endp == NULL) { + return unclosed_directive(cmd); } + *endp = '\0'; + cmd->path = ap_getword_conf(cmd->pool, &arg); cmd->override = OR_ALL|ACCESS_CONF; @@ -1304,10 +1317,12 @@ static const char *filesection(cmd_parms *cmd, core_dir_config *c, return err; } - if (endp) { - *endp = '\0'; + 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) { @@ -1376,9 +1391,12 @@ static const char *start_ifmod(cmd_parms *cmd, void *dummy, char *arg) module *found; int nest = 1; - if (endp) { - *endp = '\0'; + if (endp == NULL) { + return unclosed_directive(cmd); } + + *endp = '\0'; + if (not) { arg++; } @@ -1405,7 +1423,7 @@ static const char *start_ifmod(cmd_parms *cmd, void *dummy, char *arg) return NULL; } -static int ap_exists_config_define(char *name) +API_EXPORT(int) ap_exists_config_define(char *name) { char **defines; int i; @@ -1433,9 +1451,12 @@ static const char *start_ifdefine(cmd_parms *cmd, void *dummy, char *arg) int nest = 1; endp = strrchr(arg, '>'); - if (endp) { - *endp = '\0'; + if (endp == NULL) { + return unclosed_directive(cmd); } + + *endp = '\0'; + if (arg[0] == '!') { not = 1; arg++; @@ -1477,9 +1498,11 @@ static const char *virtualhost_section(cmd_parms *cmd, void *dummy, char *arg) return err; } - if (endp) { - *endp = '\0'; + if (endp == NULL) { + return unclosed_directive(cmd); } + + *endp = '\0'; /* FIXME: There's another feature waiting to happen here -- since you can now put multiple addresses/names on a single <VirtualHost> @@ -1665,6 +1688,11 @@ static const char *set_send_buffer_size(cmd_parms *cmd, void *dummy, char *arg) 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; @@ -1700,6 +1728,7 @@ static const char *set_user(cmd_parms *cmd, void *dummy, char *arg) exit (1); } #endif +#endif /* WIN32 */ return NULL; } @@ -2557,10 +2586,10 @@ static const command_rec core_cmds[] = { "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, RSRC_CONF|ACCESS_CONF|OR_AUTHCFG, +{ "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|OR_AUTHCFG, FLAG, + OR_OPTIONS, FLAG, "Whether or not to always use the canonical ServerName : Port when " "constructing URLs" }, { "StartServers", set_daemons_to_start, NULL, RSRC_CONF, TAKE1, @@ -2637,7 +2666,7 @@ static const command_rec core_cmds[] = { "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), - RSRC_CONF|ACCESS_CONF|OR_ALL, TAKE1, + OR_ALL, TAKE1, "Limit (in bytes) on maximum size of request message body" }, { NULL }, }; @@ -2754,7 +2783,7 @@ static int default_handler(request_rec *r) else { emsg = ap_pstrcat(r->pool, emsg, r->filename, r->path_info, NULL); } - ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r, emsg); + ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, r, "%s", emsg); return HTTP_NOT_FOUND; } if (r->method_number != M_GET) { @@ -2879,6 +2908,7 @@ static int default_handler(request_rec *r) static const handler_rec core_handlers[] = { { "*/*", default_handler }, +{ "default-handler", default_handler }, { NULL } }; diff --git a/usr.sbin/httpd/src/main/http_log.c b/usr.sbin/httpd/src/main/http_log.c index 3c380862563..02424e748e4 100644 --- a/usr.sbin/httpd/src/main/http_log.c +++ b/usr.sbin/httpd/src/main/http_log.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -65,6 +65,7 @@ #define CORE_PRIVATE #include "httpd.h" +#include "http_conf_globals.h" #include "http_config.h" #include "http_core.h" #include "http_log.h" @@ -206,14 +207,15 @@ static void open_error_log(server_rec *s, pool *p) fname++; for (fac = facilities; fac->t_name; fac++) { if (!strcasecmp(fname, fac->t_name)) { - openlog("httpd", LOG_NDELAY|LOG_CONS|LOG_PID, fac->t_val); + openlog(ap_server_argv0, LOG_NDELAY|LOG_CONS|LOG_PID, + fac->t_val); s->error_log = NULL; return; } } } else - openlog("httpd", LOG_NDELAY|LOG_CONS|LOG_PID, LOG_LOCAL7); + openlog(ap_server_argv0, LOG_NDELAY|LOG_CONS|LOG_PID, LOG_LOCAL7); s->error_log = NULL; } @@ -222,7 +224,8 @@ static void open_error_log(server_rec *s, pool *p) fname = ap_server_root_relative(p, s->error_fname); if (!(s->error_log = ap_pfopen(p, fname, "a"))) { perror("fopen"); - fprintf(stderr,"httpd: could not open error log file %s.\n", fname); + fprintf(stderr, "%s: could not open error log file %s.\n", + ap_server_argv0, fname); exit(1); } } @@ -319,7 +322,8 @@ static void log_error_core(const char *file, int line, int level, } if (logf) { - len = ap_snprintf(errstr, sizeof(errstr), "[%s] ", ap_get_time()); + len = ap_snprintf(errstr, sizeof(errstr), "%s: [%s] ", + ap_server_argv0, ap_get_time()); } else { len = 0; } @@ -393,7 +397,8 @@ static void log_error_core(const char *file, int line, int level, */ nErrorCode = GetLastError(); len += ap_snprintf(errstr + len, sizeof(errstr) - len, - "(FormatMessage failed with code %d): ", nErrorCode); + "(FormatMessage failed with code %d): ", + nErrorCode); } else { /* FormatMessage put the message in the buffer, but it may @@ -481,14 +486,15 @@ void ap_log_pid(pool *p, char *fname) */ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL, ap_psprintf(p, - "pid file %s overwritten -- Unclean shutdown of previous apache run?", + "pid file %s overwritten -- Unclean shutdown of previous Apache run?", fname) ); } if(!(pid_file = fopen(fname, "w"))) { perror("fopen"); - fprintf(stderr, "httpd: could not log pid to file %s\n", fname); + fprintf(stderr, "%s: could not log pid to file %s\n", + ap_server_argv0, fname); exit(1); } fprintf(pid_file, "%ld\n", (long)mypid); diff --git a/usr.sbin/httpd/src/main/http_main.c b/usr.sbin/httpd/src/main/http_main.c index defbca0b5bf..46ca62a1097 100644 --- a/usr.sbin/httpd/src/main/http_main.c +++ b/usr.sbin/httpd/src/main/http_main.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -116,7 +116,7 @@ int ap_main(int argc, char *argv[]); #endif #ifdef WIN32 #include "../os/win32/getopt.h" -#elif !defined(BEOS) +#elif !defined(BEOS) && !defined(TPF) #include <netinet/tcp.h> #endif @@ -247,7 +247,7 @@ int ap_daemons_limit; time_t ap_restart_time; int ap_suexec_enabled = 0; int ap_listenbacklog; -int ap_dump_settings; +int ap_dump_settings = 0; API_VAR_EXPORT int ap_extended_status = 0; /* @@ -978,15 +978,15 @@ static void usage(char *bin) pad[i] = ' '; pad[i] = '\0'; #ifdef SHARED_CORE - fprintf(stderr, "Usage: %s [-L directory] [-d directory] [-f file]\n", bin); + fprintf(stderr, "Usage: %s [-R directory] [-d directory] [-f file]\n", bin); #else fprintf(stderr, "Usage: %s [-d directory] [-f file]\n", bin); #endif fprintf(stderr, " %s [-C \"directive\"] [-c \"directive\"]\n", pad); - fprintf(stderr, " %s [-v] [-V] [-h] [-l] [-S] [-t]\n", pad); + fprintf(stderr, " %s [-v] [-V] [-h] [-l] [-L] [-S] [-t]\n", pad); fprintf(stderr, "Options:\n"); #ifdef SHARED_CORE - fprintf(stderr, " -L directory : specify an alternate location for shared object files\n"); + fprintf(stderr, " -R directory : specify an alternate location for shared object files\n"); #endif fprintf(stderr, " -D name : define a name for use in <IfDefine name> directives\n"); fprintf(stderr, " -d directory : specify an alternate initial ServerRoot\n"); @@ -995,8 +995,9 @@ static void usage(char *bin) 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 configuration directives\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 test for configuration files only\n"); #ifdef WIN32 @@ -1044,14 +1045,14 @@ static void timeout(int sig) if (sig == SIGPIPE) { ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, current_conn->server, - "(client %s) stopped connection before %s completed", + "[client %s] stopped connection before %s completed", current_conn->remote_ip, timeout_name ? timeout_name : "request"); } else { ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, current_conn->server, - "(client %s) %s timed out", + "[client %s] %s timed out", current_conn->remote_ip, timeout_name ? timeout_name : "request"); } @@ -1096,6 +1097,7 @@ static void timeout(int sig) } } +#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 @@ -1129,7 +1131,7 @@ API_EXPORT(void) ap_unblock_alarms(void) } } } - +#endif /* TPF */ static APACHE_TLS void (*volatile alarm_fn) (int) = NULL; #ifdef WIN32 @@ -1611,16 +1613,19 @@ static void setup_shared_mem(pool *p) m = (caddr_t) create_shared_heap("\\SHAREMEM\\SCOREBOARD", SCOREBOARD_SIZE); if (m == 0) { - fprintf(stderr, "httpd: Could not create OS/2 Shared memory pool.\n"); + 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, "httpd: Could not uopen() newly created OS/2 Shared memory pool.\n"); + 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.exit_generation = 0; + ap_scoreboard_image->global.running_generation = 0; } static void reopen_scoreboard(pool *p) @@ -1630,7 +1635,8 @@ static void reopen_scoreboard(pool *p) m = (caddr_t) get_shared_heap("\\SHAREMEM\\SCOREBOARD"); if (m == 0) { - fprintf(stderr, "httpd: Could not find existing OS/2 Shared memory pool.\n"); + fprintf(stderr, "%s: Could not find existing OS/2 Shared memory pool.\n", + ap_server_argv0); exit(APEXIT_INIT); } @@ -1676,30 +1682,37 @@ static void cleanup_shared_mem(void *d) 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) { - perror("httpd: could not open(create) scoreboard"); + 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) { - perror("httpd: could not ltrunc scoreboard"); + 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) { - perror("httpd: cannot mmap scoreboard"); + 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.exit_generation = 0; + ap_scoreboard_image->global.running_generation = 0; } static void reopen_scoreboard(pool *p) @@ -1737,14 +1750,14 @@ static void setup_shared_mem(pool *p) int fd = mkstemp(mfile); if (fd == -1) { perror("open"); - fprintf(stderr, "httpd: Could not open %s\n", mfile); + 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, "httpd: Could not mmap %s\n", mfile); + fprintf(stderr, "%s: Could not mmap %s\n", ap_server_argv0, mfile); exit(APEXIT_INIT); } close(fd); @@ -1756,7 +1769,7 @@ static void setup_shared_mem(pool *p) #endif if (m == (caddr_t) - 1) { perror("mmap"); - fprintf(stderr, "httpd: Could not mmap memory\n"); + fprintf(stderr, "%s: Could not mmap memory\n", ap_server_argv0); exit(APEXIT_INIT); } #else @@ -1766,20 +1779,20 @@ static void setup_shared_mem(pool *p) fd = open("/dev/zero", O_RDWR); if (fd == -1) { perror("open"); - fprintf(stderr, "httpd: Could not open /dev/zero\n"); + 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, "httpd: Could not mmap /dev/zero\n"); + 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.exit_generation = 0; + ap_scoreboard_image->global.running_generation = 0; } static void reopen_scoreboard(pool *p) @@ -1801,8 +1814,9 @@ static void setup_shared_mem(pool *p) #ifdef LINUX if (errno == ENOSYS) { ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, server_conf, - "httpd: Your kernel was built without CONFIG_SYSVIPC\n" - "httpd: please consult the Apache FAQ for details"); + "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, @@ -1870,7 +1884,7 @@ static void setup_shared_mem(pool *p) "sbrk() could not move break back"); } #endif - ap_scoreboard_image->global.exit_generation = 0; + ap_scoreboard_image->global.running_generation = 0; } static void reopen_scoreboard(pool *p) @@ -1937,16 +1951,16 @@ void reopen_scoreboard(pool *p) /* Called by parent process */ static void reinit_scoreboard(pool *p) { - int exit_gen = 0; + int running_gen = 0; if (ap_scoreboard_image) - exit_gen = ap_scoreboard_image->global.exit_generation; + 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.exit_generation = exit_gen; + 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); @@ -1960,7 +1974,7 @@ static void reinit_scoreboard(pool *p) 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.exit_generation = exit_gen; + ap_scoreboard_image->global.running_generation = running_gen; force_write(scoreboard_fd, ap_scoreboard_image, sizeof(*ap_scoreboard_image)); #endif } @@ -2055,9 +2069,21 @@ int ap_update_child_status(int child_num, int status, request_rec *r) r->assbackwards ? NULL : " ", r->protocol, NULL), sizeof(ss->request)); } - ap_cpystrn(ss->vhost, r->server->server_hostname, sizeof(ss->vhost)); + 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; @@ -2542,7 +2568,7 @@ static void usr1_handler(int sig) static int volatile shutdown_pending; static int volatile restart_pending; static int volatile is_graceful; -static int volatile generation; +ap_generation_t volatile ap_my_generation; #ifdef WIN32 /* @@ -2781,14 +2807,14 @@ static void detach(void) int x; chdir("/"); -#if !defined(MPE) && !defined(OS2) +#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, "httpd: unable to fork new process\n"); + fprintf(stderr, "%s: unable to fork new process\n", ap_server_argv0); exit(1); } RAISE_SIGSTOP(DETACH); @@ -2796,16 +2822,16 @@ static void detach(void) #ifndef NO_SETSID if ((pgrp = setsid()) == -1) { perror("setsid"); - fprintf(stderr, "httpd: setsid failed\n"); + 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, "httpd: setpgrp or getpgrp failed\n"); + fprintf(stderr, "%s: setpgrp or getpgrp failed\n", ap_server_argv0); exit(1); } -#elif defined(OS2) +#elif defined(OS2) || defined(TPF) /* OS/2 don't support process group IDs */ pgrp = getpid(); #elif defined(MPE) @@ -2814,15 +2840,15 @@ static void detach(void) #else if ((pgrp = setpgrp(getpid(), 0)) == -1) { perror("setpgrp"); - fprintf(stderr, "httpd: setpgrp failed\n"); + 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, "httpd: unable to replace stdin with /dev/null: %s\n", - strerror(errno)); + 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 @@ -2830,8 +2856,8 @@ static void detach(void) */ } if (freopen("/dev/null", "w", stdout) == NULL) { - fprintf(stderr, "httpd: unable to replace stdout with /dev/null: %s\n", - strerror(errno)); + 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 @@ -3532,7 +3558,7 @@ static void child_main(int child_num_arg) /* Only try to switch if we're running as root */ if (!geteuid() && ( #ifdef _OSD_POSIX - os_init_job_environment(server_conf, ap_user_name) != 0 || + 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, @@ -3590,7 +3616,7 @@ static void child_main(int child_num_arg) ap_clear_pool(ptrans); ap_sync_scoreboard_image(); - if (ap_scoreboard_image->global.exit_generation >= generation) { + if (ap_scoreboard_image->global.running_generation != ap_my_generation) { clean_child_exit(0); } @@ -3731,7 +3757,7 @@ static void child_main(int child_num_arg) * without reliable signals */ ap_sync_scoreboard_image(); - if (ap_scoreboard_image->global.exit_generation >= generation) { + if (ap_scoreboard_image->global.running_generation != ap_my_generation) { clean_child_exit(0); } } @@ -3836,7 +3862,7 @@ static void child_main(int child_num_arg) (request_rec *) NULL); ap_sync_scoreboard_image(); - if (ap_scoreboard_image->global.exit_generation >= generation) { + if (ap_scoreboard_image->global.running_generation != ap_my_generation) { ap_bclose(conn_io); clean_child_exit(0); } @@ -3904,7 +3930,13 @@ static int make_child(server_rec *s, int slot, time_t now) Explain1("Starting new child in slot %d", slot); (void) ap_update_child_status(slot, SERVER_STARTING, (request_rec *) NULL); + +#ifndef _OSD_POSIX if ((pid = fork()) == -1) { +#else /*_OSD_POSIX*/ + /* BS2000 requires a "special" version of fork() before a setuid() call */ + if ((pid = os_fork()) == -1) { +#endif /*_OSD_POSIX*/ ap_log_error(APLOG_MARK, APLOG_ERR, s, "fork: Unable to fork new process"); /* fork didn't succeed. Fix the scoreboard or else @@ -4097,7 +4129,17 @@ static void perform_idle_server_maintenance(void) 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 @@ -4141,27 +4183,27 @@ static void process_child_status(int pid, ap_wait_t status) #ifdef WCOREDUMP if (WCOREDUMP(status)) { ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, - server_conf, - "httpd: child pid %d exit signal %s (%d), " - "possible coredump in %s", - pid, (WTERMSIG(status) >= NumSIG) ? "" : - SYS_SIGLIST[WTERMSIG(status)], WTERMSIG(status), - ap_coredump_dir); + 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, - "httpd: child pid %d exit signal %s (%d)", - pid, SYS_SIGLIST[WTERMSIG(status)], WTERMSIG(status)); + 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, - "httpd: child pid %d exit signal %d", - pid, WTERMSIG(status)); + server_conf, + "child pid %d exit signal %d", + pid, WTERMSIG(status)); #endif } } @@ -4186,7 +4228,6 @@ static void standalone_main(int argc, char **argv) ap_standalone = 1; is_graceful = 0; - ++generation; if (!one_process) { detach(); @@ -4347,12 +4388,12 @@ static void standalone_main(int argc, char **argv) if ( pidfile != NULL && unlink(pidfile) == 0) ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, server_conf, - "httpd: removed PID file %s (pid=%ld)", + "removed PID file %s (pid=%ld)", pidfile, (long)getpid()); } ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf, - "httpd: caught SIGTERM, shutting down"); + "caught SIGTERM, shutting down"); clean_parent_exit(0); } @@ -4365,16 +4406,18 @@ static void standalone_main(int argc, char **argv) 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 - - /* USE WITH CAUTION: Graceful restarts are not known to work - * in various configurations on the architectures we support. */ - ap_scoreboard_image->global.exit_generation = generation; - update_scoreboard_global(); - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf, "SIGUSR1 received. Doing graceful restart"); @@ -4405,7 +4448,6 @@ static void standalone_main(int argc, char **argv) ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, server_conf, "SIGHUP received. Attempting to restart"); } - ++generation; } while (restart_pending); /*add_common_vars(NULL);*/ @@ -4422,7 +4464,10 @@ int REALMAIN(int argc, char *argv[]) { int c; int configtestonly = 0; - + int sock_in; + int sock_out; + char *s; + #ifdef SecureWare if (set_auth_parameters(argc, argv) < 0) perror("set_auth_parameters"); @@ -4441,14 +4486,21 @@ int REALMAIN(int argc, char *argv[]) common_init(); - ap_server_argv0 = argv[0]; + if ((s = strrchr(argv[0], '/')) != 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(); +#ifndef TPF while ((c = getopt(argc, argv, - "D:C:c:Xd:f:vVhlL:St" + "D:C:c:Xd:f:vVlLR:Sth" #ifdef DEBUG_SIGSTOP "Z:" #endif @@ -4482,12 +4534,12 @@ int REALMAIN(int argc, char *argv[]) ap_set_version(); show_compile_settings(); exit(0); - case 'h': - ap_show_directives(); - exit(0); case 'l': ap_show_modules(); exit(0); + case 'L': + ap_show_directives(); + exit(0); case 'X': ++one_process; /* Weird debugging mode. */ break; @@ -4497,7 +4549,7 @@ int REALMAIN(int argc, char *argv[]) break; #endif #ifdef SHARED_CORE - case 'L': + 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 @@ -4511,10 +4563,13 @@ int REALMAIN(int argc, char *argv[]) case 't': configtestonly = 1; break; + case 'h': + usage(argv[0]); case '?': usage(argv[0]); } } +#endif /* TPF */ ap_suexec_enabled = init_suexec(); server_conf = ap_read_config(pconf, ptrans, ap_server_confname); @@ -4523,6 +4578,9 @@ int REALMAIN(int argc, char *argv[]) fprintf(stderr, "Syntax OK\n"); exit(0); } + if (ap_dump_settings) { + exit(0); + } child_timeouts = !ap_standalone || one_process; @@ -4540,8 +4598,10 @@ int REALMAIN(int argc, char *argv[]) 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, pconf); ap_init_modules(pconf, server_conf); set_group_privs(); @@ -4570,33 +4630,46 @@ int REALMAIN(int argc, char *argv[]) exit(0); } +#ifdef TPF + signal(SIGALRM, alrm_handler); + ecbptr()->ebrout = PRIMECRAS; +#endif /* TPF */ + +#ifdef TPF +/* TPF only passes the incoming socket number from the internet daemon + in ebw000 */ + sock_in = * (int*)(&(ecbptr()->ebw000)); + sock_out = * (int*)(&(ecbptr()->ebw000)); +#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(fileno(stdin), &sa_client, &l)) < 0) { + 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(fileno(stdin), &sa_server, &l) < 0) { + 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); -#ifdef MPE -/* HP MPE 5.5 inetd only passes the incoming socket as stdin (fd 0), whereas - HPUX inetd passes the incoming socket as stdin (fd 0) and stdout (fd 1). - Go figure. SR 5003355016 has been submitted to request that the existing - functionality be documented, and then to enhance the functionality to be - like HPUX. */ - - cio->fd = fileno(stdin); -#else - cio->fd = fileno(stdout); -#endif - cio->fd_in = fileno(stdin); + 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); @@ -5103,7 +5176,7 @@ void worker_main(void) my_pid = getpid(); - ++generation; + ++ap_my_generation; copy_listeners(pconf); ap_restart_time = time(NULL); @@ -5483,7 +5556,6 @@ int master_main(int argc, char **argv) processes_to_create = nchild; is_graceful = 0; - ++generation; ap_snprintf(signal_prefix_string, sizeof(signal_prefix_string), "ap%d", getpid()); @@ -5644,7 +5716,7 @@ int master_main(int argc, char **argv) "SetEvent for child process in slot #%d", i); } } - ++generation; + ++ap_my_generation; } while (restart_pending); /* If we dropped out of the loop we definitly want to die completely. We need to @@ -5654,8 +5726,6 @@ int master_main(int argc, char **argv) APD2("*** main process shutdown, processes=%d ***", current_live_processes); die_now: - CloseHandle(signal_restart_event); - CloseHandle(signal_shutdown_event); tmstart = time(NULL); while (current_live_processes && ((tmstart+60) > time(NULL))) { @@ -5676,6 +5746,9 @@ die_now: TerminateProcess((HANDLE) process_handles[i], 1); } + CloseHandle(signal_restart_event); + CloseHandle(signal_shutdown_event); + /* cleanup pid file on normal shutdown */ { const char *pidfile = NULL; @@ -5683,7 +5756,7 @@ die_now: if ( pidfile != NULL && unlink(pidfile) == 0) ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, server_conf, - "httpd: removed PID file %s (pid=%ld)", + "removed PID file %s (pid=%ld)", pidfile, (long)getpid()); } @@ -5761,10 +5834,16 @@ int REALMAIN(int argc, char *argv[]) int install = 0; int configtestonly = 0; char *signal_to_send = NULL; + char *s; common_init(); - ap_server_argv0 = argv[0]; + if ((s = strrchr(argv[0], '/')) != NULL) { + ap_server_argv0 = ++s; + } + else { + ap_server_argv0 = argv[0]; + } /* Get the serverroot from the registry, if it exists. This can be * overridden by a command line -d argument. @@ -5785,7 +5864,7 @@ int REALMAIN(int argc, char *argv[]) ap_setup_prelinked_modules(); - while ((c = getopt(argc, argv, "D:C:c:Xd:f:vVhlZ:iusStk:")) != -1) { + while ((c = getopt(argc, argv, "D:C:c:Xd:f:vVlLZ:iusSthk:")) != -1) { char **new; switch (c) { case 'c': @@ -5843,18 +5922,20 @@ int REALMAIN(int argc, char *argv[]) ap_set_version(); show_compile_settings(); exit(0); - case 'h': - ap_show_directives(); - exit(0); case 'l': ap_show_modules(); exit(0); + case 'L': + ap_show_directives(); + exit(0); case 'X': ++one_process; /* Weird debugging mode. */ break; case 't': configtestonly = 1; break; + case 'h': + usage(argv[0]); case '?': usage(argv[0]); } @@ -5887,11 +5968,11 @@ int REALMAIN(int argc, char *argv[]) set_group_privs(); #ifdef OS2 - printf("%s \n", ap_get_server_version()); + printf("%s running...\n", ap_get_server_version()); #endif #ifdef WIN32 if (!child) { - printf("%s \n", ap_get_server_version()); + printf("%s running...\n", ap_get_server_version()); } #endif @@ -5971,7 +6052,7 @@ int main(int argc, char *argv[]) #endif #ifndef SHARED_CORE_EXECUTABLE_PROGRAM -#define SHARED_CORE_EXECUTABLE_PROGRAM "libhttpd.ep" +#define SHARED_CORE_EXECUTABLE_PROGRAM "lib" TARGET ".ep" #endif extern char *optarg; @@ -5992,7 +6073,7 @@ int main(int argc, char *argv[], char *envp[]) * but only handle the -L option */ llp_dir = SHARED_CORE_DIR; - while ((c = getopt(argc, argv, "D:C:c:Xd:f:vVhlL:SZ:t")) != -1) { + while ((c = getopt(argc, argv, "D:C:c:Xd:f:vVlLR:SZ:th")) != -1) { switch (c) { case 'D': case 'C': @@ -6002,14 +6083,15 @@ int main(int argc, char *argv[], char *envp[]) case 'f': case 'v': case 'V': - case 'h': case 'l': + case 'L': case 'S': case 'Z': case 't': + case 'h': case '?': break; - case 'L': + case 'R': llp_dir = strdup(optarg); break; } @@ -6052,8 +6134,8 @@ int main(int argc, char *argv[], char *envp[]) */ if (execve(prog, argv, envp) == -1) { fprintf(stderr, - "httpd: Unable to exec Shared Core Executable Program `%s'\n", - prog); + "%s: Unable to exec Shared Core Executable Program `%s'\n", + argv[0], prog); return 1; } else diff --git a/usr.sbin/httpd/src/main/http_protocol.c b/usr.sbin/httpd/src/main/http_protocol.c index e28df5c4636..cae3aa2e8fe 100644 --- a/usr.sbin/httpd/src/main/http_protocol.c +++ b/usr.sbin/httpd/src/main/http_protocol.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -305,7 +305,7 @@ API_EXPORT(int) ap_set_keepalive(request_rec *r) (r->server->keep_alive_timeout > 0) && ((r->server->keep_alive_max == 0) || (r->server->keep_alive_max > r->connection->keepalives)) && - !status_drops_connection(r->status) && + !ap_status_drops_connection(r->status) && !wimpy && !ap_find_token(r->pool, conn, "close") && (!ap_table_get(r->subprocess_env, "nokeepalive") || @@ -469,7 +469,7 @@ API_EXPORT(int) ap_meets_conditions(request_rec *r) * 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(void) ap_set_etag(request_rec *r) +API_EXPORT(char *) ap_make_etag(request_rec *r, int force_weak) { char *etag; char *weak; @@ -487,11 +487,11 @@ API_EXPORT(void) ap_set_etag(request_rec *r) * would be incorrect. */ - weak = (r->request_time - r->mtime > 1) ? "" : "W/"; + 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, + 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); @@ -501,6 +501,50 @@ API_EXPORT(void) ap_set_etag(request_rec *r) (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); } @@ -517,6 +561,72 @@ API_EXPORT(void) ap_set_last_modified(request_rec *r) 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. @@ -678,26 +788,11 @@ static int read_request_line(request_rec *r) uri = ap_getword_white(r->pool, &ll); /* Provide quick information about the request method as soon as known */ - if (!strcmp(r->method, "HEAD")) { + + r->method_number = ap_method_number_of(r->method); + if (r->method_number == M_GET && r->method[0] == 'H') { r->header_only = 1; - r->method_number = M_GET; - } - else if (!strcmp(r->method, "GET")) - r->method_number = M_GET; - else if (!strcmp(r->method, "POST")) - r->method_number = M_POST; - else if (!strcmp(r->method, "PUT")) - r->method_number = M_PUT; - else if (!strcmp(r->method, "DELETE")) - r->method_number = M_DELETE; - else if (!strcmp(r->method, "CONNECT")) - r->method_number = M_CONNECT; - else if (!strcmp(r->method, "OPTIONS")) - r->method_number = M_OPTIONS; - else if (!strcmp(r->method, "TRACE")) - r->method_number = M_TRACE; - else - r->method_number = M_INVALID; /* Will eventually croak. */ + } ap_parse_uri(r, uri); @@ -1056,7 +1151,7 @@ API_EXPORT(int) ap_get_basic_auth_pw(request_rec *r, const char **pw) * and must be listed in order. */ -static char *status_lines[] = { +static char *status_lines[RESPONSE_CODES] = { "100 Continue", "101 Switching Protocols", "102 Processing", @@ -1103,18 +1198,19 @@ static char *status_lines[] = { "421 unused", "422 Unprocessable Entity", "423 Locked", -#define LEVEL_500 43 + "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 unused", + "506 Variant Also Negotiates", + "507 Insufficient Storage", "508 unused", "509 unused", - "510 Not Extended", + "510 Not Extended" }; /* The index is found by its offset from the x00 code of each level. @@ -1237,13 +1333,22 @@ static void terminate_header(BUFF *client) 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_OPTIONS)) ? ", OPTIONS" : "", - ", TRACE", - NULL); + (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) @@ -2297,19 +2402,23 @@ void ap_send_error_response(request_rec *r, int recursive_error) ap_escape_html(r->pool, r->uri), " evaluated to false.<P>\n", NULL); break; - case NOT_IMPLEMENTED: + case HTTP_NOT_IMPLEMENTED: ap_bvputs(fd, ap_escape_html(r->pool, r->method), " to ", ap_escape_html(r->pool, r->uri), " not supported.<P>\n", NULL); + if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) { + ap_bvputs(fd, error_notes, "<P>\n", NULL); + } break; case BAD_GATEWAY: ap_bputs("The proxy server received an invalid\015\012", fd); ap_bputs("response from an upstream server.<P>\015\012", fd); break; case VARIANT_ALSO_VARIES: - ap_bvputs(fd, "A variant for the requested entity ", - ap_escape_html(r->pool, r->uri), " is itself a ", - "transparently negotiable resource.<P>\n", NULL); + ap_bvputs(fd, "A variant for the requested resource\n<PRE>\n", + ap_escape_html(r->pool, r->uri), + "\n</PRE>\nis itself a negotiable resource. " + "This indicates a configuration error.<P>\n", NULL); break; case HTTP_REQUEST_TIME_OUT: ap_bputs("I'm tired of waiting for your request.\n", fd); @@ -2363,6 +2472,18 @@ void ap_send_error_response(request_rec *r, int recursive_error) "The lock must be released or proper identification\n" "given before the method can be applied.\n", fd); break; + case HTTP_FAILED_DEPENDENCY: + ap_bputs("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", fd); + break; + case HTTP_INSUFFICIENT_STORAGE: + ap_bputs("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", fd); + break; case HTTP_SERVICE_UNAVAILABLE: ap_bputs("The server is temporarily unable to service your\n" "request due to maintenance downtime or capacity\n" @@ -2384,10 +2505,22 @@ void ap_send_error_response(request_rec *r, int recursive_error) ap_escape_html(r->pool, r->server->server_admin), " and inform them of the time the error occurred,\n" "and anything you might have done that may have\n" - "caused the error.<P>\n", NULL); - if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) { - ap_bvputs(fd, error_notes, "<P>\n", NULL); - } + "caused the error.<P>\n" + "More information about this error may be available\n" + "in the server error log.<P>\n", NULL); + /* + * It would be nice to give the user the information they need to + * fix the problem directly since many users don't have access to + * the error_log (think University sites) even though they can easily + * get this error by misconfiguring an htaccess file. However, the + * error notes tend to include the real file pathname in this case, + * which some people consider to be a breach of privacy. Until we + * can figure out a way to remove the pathname, leave this commented. + * + * if ((error_notes = ap_table_get(r->notes, "error-notes")) != NULL) { + * ap_bvputs(fd, error_notes, "<P>\n", NULL); + * } + */ break; } diff --git a/usr.sbin/httpd/src/main/http_request.c b/usr.sbin/httpd/src/main/http_request.c index 918dc9226bf..71089516a07 100644 --- a/usr.sbin/httpd/src/main/http_request.c +++ b/usr.sbin/httpd/src/main/http_request.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -179,7 +179,7 @@ static int get_path_info(request_rec *r) char *last_cp = NULL; int rv; #ifdef WIN32 - char buf[5]; + BOOL bStripSlash=TRUE; #endif if (r->finfo.st_mode) { @@ -188,22 +188,39 @@ static int get_path_info(request_rec *r) } #ifdef WIN32 - /* If the path is x:/, then convert it to x:/., coz that's what stat - * needs to work properly + /* 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] == ':') { - strcpy(buf,path); - buf[3]='.'; - buf[4]='\0'; - path=buf; - end=buf+4; - } -#endif + if (strlen(path) == 3 && path[1] == ':' && path[2] == '/') + bStripSlash = FALSE; - /* Advance over trailing slashes ... NOT part of filename */ - for (cp = end; cp > path && cp[-1] == '/'; --cp) - continue; + /* 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 = FALSE; + } + + 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) { @@ -212,8 +229,21 @@ static int get_path_info(request_rec *r) *cp = '\0'; - errno = 0; - rv = stat(path, &r->finfo); + /* 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 = '/'; @@ -293,7 +323,7 @@ static int directory_walk(request_rec *r) char *test_filename; char *test_dirname; int res; - unsigned i, num_dirs; + unsigned i, num_dirs, iStart; int j, test_filename_len; /* @@ -359,15 +389,24 @@ static int directory_walk(request_rec *r) 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); - res = get_path_info(r); - if (res != OK) { - return res; + 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))) { @@ -390,9 +429,18 @@ static int directory_walk(request_rec *r) */ 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 = 1; i <= num_dirs; ++i) { + 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); @@ -464,10 +512,12 @@ static int directory_walk(request_rec *r) if (res) return res; - if (htaccess_conf) - per_dir_defaults = - ap_merge_per_dir_configs(r->pool, per_dir_defaults, - htaccess_conf); + 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; + } } } @@ -690,7 +740,7 @@ API_EXPORT(request_rec *) ap_sub_req_lookup_uri(const char *new_file, ap_parse_uri(rnew, new_file); else { udir = ap_make_dirstr_parent(rnew->pool, r->uri); - udir = escape_uri(rnew->pool, udir); /* re-escape it */ + udir = ap_escape_uri(rnew->pool, udir); /* re-escape it */ ap_parse_uri(rnew, ap_make_full_path(rnew->pool, udir, new_file)); } @@ -776,7 +826,7 @@ API_EXPORT(request_rec *) ap_sub_req_lookup_file(const char *new_file, 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 */ + ap_parse_uri(rnew, rnew->uri); /* fill in parsed_uri values */ if (stat(rnew->filename, &rnew->finfo) < 0) { rnew->finfo.st_mode = 0; } @@ -830,14 +880,7 @@ API_EXPORT(request_rec *) ap_sub_req_lookup_file(const char *new_file, * file may not have a uri associated with it -djg */ rnew->uri = "INTERNALLY GENERATED file-relative req"; -#ifdef WIN32 - rnew->filename = ((new_file[0] == '/' - || (ap_isalpha(new_file[0]) - && new_file[1] == ':' - && new_file[2] == '/')) ? -#else - rnew->filename = ((new_file[0] == '/') ? -#endif + 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; @@ -869,7 +912,14 @@ API_EXPORT(request_rec *) ap_sub_req_lookup_file(const char *new_file, 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; } @@ -929,7 +979,7 @@ API_EXPORT(void) ap_die(int type, request_rec *r) * (if any) has been read. */ if ((r->status != HTTP_NOT_MODIFIED) && (r->status != HTTP_NO_CONTENT) - && !status_drops_connection(r->status) + && !ap_status_drops_connection(r->status) && r->connection && (r->connection->keepalive != -1)) { (void) ap_discard_request_body(r); @@ -1250,6 +1300,7 @@ static request_rec *internal_internal_redirect(const char *new_uri, request_rec new->no_cache = r->no_cache; 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)); diff --git a/usr.sbin/httpd/src/main/http_vhost.c b/usr.sbin/httpd/src/main/http_vhost.c index f0dbd1f9a59..793048f9471 100644 --- a/usr.sbin/httpd/src/main/http_vhost.c +++ b/usr.sbin/httpd/src/main/http_vhost.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/main/md5c.c b/usr.sbin/httpd/src/main/md5c.c index ad9fce33d54..a94601d3109 100644 --- a/usr.sbin/httpd/src/main/md5c.c +++ b/usr.sbin/httpd/src/main/md5c.c @@ -32,7 +32,7 @@ */ /* ==================================================================== - * Copyright (c) 1996-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/main/rfc1413.c b/usr.sbin/httpd/src/main/rfc1413.c index 641cb57e6ef..1c60a7ddab3 100644 --- a/usr.sbin/httpd/src/main/rfc1413.c +++ b/usr.sbin/httpd/src/main/rfc1413.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/main/util.c b/usr.sbin/httpd/src/main/util.c index eee03233261..81b40ca4055 100644 --- a/usr.sbin/httpd/src/main/util.c +++ b/usr.sbin/httpd/src/main/util.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -210,6 +210,14 @@ API_EXPORT(struct tm *) ap_get_gmtoff(int *tz) } #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 @@ -424,6 +432,13 @@ 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 { @@ -746,6 +761,14 @@ API_EXPORT(configfile_t *) ap_pcfg_openfile(pool *p, const char *name) 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; + } + file = ap_pfopen(p, name, "r"); #ifdef DEBUG saved_errno = errno; @@ -759,11 +782,13 @@ API_EXPORT(configfile_t *) ap_pcfg_openfile(pool *p, const char *name) if (fstat(fileno(file), &stbuf) == 0 && !S_ISREG(stbuf.st_mode) && -#ifdef WIN32 - strcasecmp(name, "nul") != 0) { +#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 +#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", @@ -1236,7 +1261,7 @@ API_EXPORT(char *) ap_os_escape_path(pool *p, const char *path, int partial) return copy; } -/* escape_uri is now a macro for os_escape_path */ +/* ap_escape_uri is now a macro for os_escape_path */ API_EXPORT(char *) ap_escape_html(pool *p, const char *s) { @@ -1251,7 +1276,8 @@ API_EXPORT(char *) ap_escape_html(pool *p, const char *s) j += 4; if (j == 0) - return ap_pstrdup(p, s); + 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] == '<') { @@ -1428,7 +1454,7 @@ char *strstr(char *s1, char *s2) #ifdef NEED_INITGROUPS int initgroups(const char *name, gid_t basegid) { -#if defined(QNX) || defined(MPE) || defined(BEOS) || defined(_OSD_POSIX) +#if defined(QNX) || defined(MPE) || defined(BEOS) || defined(_OSD_POSIX) || defined(TPF) /* QNX, MPE and BeOS do not appear to support supplementary groups. */ return 0; #else /* ndef QNX */ @@ -1517,7 +1543,7 @@ API_EXPORT(uid_t) ap_uname2id(const char *name) return (atoi(&name[1])); if (!(ent = getpwnam(name))) { - fprintf(stderr, "httpd: bad user name %s\n", name); + fprintf(stderr, "%s: bad user name %s\n", ap_server_argv0, name); exit(1); } return (ent->pw_uid); @@ -1535,7 +1561,7 @@ API_EXPORT(gid_t) ap_gname2id(const char *name) return (atoi(&name[1])); if (!(ent = getgrnam(name))) { - fprintf(stderr, "httpd: bad group name %s\n", name); + fprintf(stderr, "%s: bad group name %s\n", ap_server_argv0, name); exit(1); } return (ent->gr_gid); @@ -1626,7 +1652,8 @@ char *ap_get_local_host(pool *a) } str[MAXHOSTNAMELEN] = '\0'; if ((!(p = gethostbyname(str))) || (!(server_hostname = find_fqdn(a, p)))) { - fprintf(stderr, "httpd: cannot determine local host name.\n"); + 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); } diff --git a/usr.sbin/httpd/src/main/util_date.c b/usr.sbin/httpd/src/main/util_date.c index d95dac6287b..933079cc3f3 100644 --- a/usr.sbin/httpd/src/main/util_date.c +++ b/usr.sbin/httpd/src/main/util_date.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1996-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/main/util_md5.c b/usr.sbin/httpd/src/main/util_md5.c index 0f14e8b3507..7700de7af79 100644 --- a/usr.sbin/httpd/src/main/util_md5.c +++ b/usr.sbin/httpd/src/main/util_md5.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -89,6 +89,7 @@ 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]; @@ -102,8 +103,10 @@ API_EXPORT(char *) ap_md5_binary(pool *p, const unsigned char *buf, int length) ap_MD5Update(&my_md5, buf, length); ap_MD5Final(hash, &my_md5); - for (i = 0, r = result; i < 16; i++, r += 2) - sprintf(r, "%02x", hash[i]); + 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); diff --git a/usr.sbin/httpd/src/main/util_script.c b/usr.sbin/httpd/src/main/util_script.c index 9ee38bf8edd..48f7b96cc18 100644 --- a/usr.sbin/httpd/src/main/util_script.c +++ b/usr.sbin/httpd/src/main/util_script.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -262,7 +262,7 @@ API_EXPORT(void) ap_add_common_vars(request_rec *r) #endif ap_table_addn(e, "PATH", env_path); - ap_table_setn(e, "SERVER_SIGNATURE", ap_psignature("", r)); + 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_PORT", @@ -396,7 +396,7 @@ API_EXPORT(void) ap_add_cgi_vars(request_rec *r) */ request_rec *pa_req; - pa_req = ap_sub_req_lookup_uri(escape_uri(r->pool, r->path_info), r); + pa_req = ap_sub_req_lookup_uri(ap_escape_uri(r->pool, r->path_info), r); if (pa_req->filename) { #ifdef WIN32 @@ -1052,7 +1052,16 @@ API_EXPORT(int) ap_call_exec(request_rec *r, child_info *pinfo, char *argv0, */ CloseHandle(pi.hProcess); CloseHandle(pi.hThread); - } + } else { + if (is_script) { + /* since we are doing magic to find what we are executing + * if running a script, log what we think we should have + * executed + */ + ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, r, + "could not run script interpreter: %s", pCommand); + } + } #if 0 if ((!r->args) || (!r->args[0]) || strchr(r->args, '=')) { if (is_exe || is_binary) { diff --git a/usr.sbin/httpd/src/main/util_uri.c b/usr.sbin/httpd/src/main/util_uri.c index 4b76f2a2ce2..d34dbd1852f 100644 --- a/usr.sbin/httpd/src/main/util_uri.c +++ b/usr.sbin/httpd/src/main/util_uri.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/modules/example/mod_example.c b/usr.sbin/httpd/src/modules/example/mod_example.c index 1aeda876d01..764b1550a96 100644 --- a/usr.sbin/httpd/src/modules/example/mod_example.c +++ b/usr.sbin/httpd/src/modules/example/mod_example.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1997 The Apache Group. All rights reserved. + * 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 @@ -20,9 +20,14 @@ * * 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. + * prior written permission. For written permission, please contact + * apache@apache.org. * - * 5. Redistributions of any form whatsoever must retain the following + * 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/)." @@ -66,12 +71,12 @@ #include <stdio.h> /*--------------------------------------------------------------------------*/ -/* */ -/* Data declarations. */ -/* */ -/* Here are the static cells and structure declarations private to our */ -/* module. */ -/* */ +/* */ +/* Data declarations. */ +/* */ +/* Here are the static cells and structure declarations private to our */ +/* module. */ +/* */ /*--------------------------------------------------------------------------*/ /* @@ -90,17 +95,18 @@ * 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 example_config { - int cmode; /* Environment to which record applies (directory, */ - /* server, or combination). */ +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: was "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. */ -} example_config; +#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 @@ -110,7 +116,7 @@ typedef struct example_config { * the first time (non-request context only), and ignore subsequent calls for * the same routine/environment. */ -static char *trace = NULL; +static const char *trace = NULL; static table *static_calls_made = NULL; /* @@ -129,53 +135,59 @@ static pool *example_subpool = NULL; 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 */ +/* 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). */ -/* */ +/* 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); + * 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); + * 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); + * 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); + * 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); + * static const char *handle_TAKE3(cmd_parms *cmd, void *mconfig, + * char *word1, char *word2, char *word3); */ /* @@ -183,8 +195,8 @@ module example_module; * 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); + * static const char *handle_TAKE12(cmd_parms *cmd, void *mconfig, + * char *word1, char *word2); */ /* @@ -193,8 +205,8 @@ module example_module; * - 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); + * static const char *handle_TAKE123(cmd_parms *cmd, void *mconfig, + * char *word1, char *word2, char *word3); */ /* @@ -202,8 +214,8 @@ module example_module; * 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); + * static const char *handle_TAKE13(cmd_parms *cmd, void *mconfig, + * char *word1, char *word2, char *word3); */ /* @@ -211,8 +223,8 @@ module example_module; * 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); + * static const char *handle_TAKE23(cmd_parms *cmd, void *mconfig, + * char *word1, char *word2, char *word3); */ /* @@ -220,8 +232,8 @@ module example_module; * - 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); + * static const char *handle_ITERATE(cmd_parms *cmd, void *mconfig, + * char *word1); */ /* @@ -232,73 +244,64 @@ module example_module; * 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); + * 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. */ -/* */ +/* */ +/* 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 example_config *our_dconfig - (request_rec *r) { - - return (example_config *) get_module_config - ( - r->per_dir_config, - &example_module - ); +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 example_config *our_sconfig - (server_rec *s) { - - return (example_config *) get_module_config - ( - s->module_config, - &example_module - ); +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 example_config *our_rconfig - (request_rec *r) { - - return (example_config *) get_module_config - ( - r->request_config, - &example_module - ); +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 () { +static void setup_module_cells() +{ /* * If we haven't already allocated our module-private pool, do so now. */ if (example_pool == NULL) { - example_pool = make_sub_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 = make_table (example_pool, 16); + static_calls_made = ap_make_table(example_pool, 16); }; } @@ -322,54 +325,53 @@ static void setup_module_cells () { #define TRACE_NOTE "example-trace" -static void trace_add - (server_rec *s, request_rec *r, example_config *mconfig, - const char *note) { +static void trace_add(server_rec *s, request_rec *r, excfg *mconfig, + const char *note) +{ - char *sofar; - char *addon; - char *where; - pool *p; - char *trace_copy; - example_config - *rconfig; + 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 (); + setup_module_cells(); /* * Now, if we're in request-context, we use the request pool. */ if (r != NULL) { - p = r->pool; - if ((trace_copy = 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 = make_sub_pool (example_pool); - if (trace != NULL) { - trace = 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) { - destroy_pool (example_subpool); - } - example_subpool = p; - trace_copy = trace; + 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 @@ -386,109 +388,96 @@ static void trace_add * module's private pool, which doesn't get destroyed. */ if (r == NULL) { - char *key; - - key = pstrcat (p, note, ":", where, NULL); - if (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. - */ - table_set (static_calls_made, key, "been here"); - } + 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 = pstrcat - ( - p, - " <LI>\n", - " <DL>\n", - " <DT><SAMP>", - note, - "</SAMP>\n", - " </DT>\n", - " <DD><SAMP>[", - where, - "]</SAMP>\n", - " </DD>\n", - " </DL>\n", - " </LI>\n", - NULL - ); + addon = ap_pstrcat(p, " <LI>\n", " <DL>\n", " <DT><SAMP>", + note, "</SAMP>\n", " </DT>\n", " <DD><SAMP>[", + where, "]</SAMP>\n", " </DD>\n", " </DL>\n", + " </LI>\n", NULL); sofar = (trace_copy == NULL) ? "" : trace_copy; - trace_copy = pstrcat (p, sofar, addon, NULL); + trace_copy = ap_pstrcat(p, sofar, addon, NULL); if (r != NULL) { - table_set (r->notes, TRACE_NOTE, trace_copy); - } else { - trace = trace_copy; + ap_table_set(r->notes, TRACE_NOTE, trace_copy); + } + else { + trace = trace_copy; } /* - * You *could* uncomment the following if you wanted to see the calling + * 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. */ -/* - if (s != NULL) { - log_printf (s, "mod_example: %s", note); +#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. */ -/* */ +/* 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 */ +/* 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. */ +/* 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) { +static const char *cmd_example(cmd_parms *cmd, void *mconfig) +{ - example_config - *cfg = (example_config *) mconfig; + excfg *cfg = (excfg *) mconfig; /* * "Example Wuz Here" */ cfg->local = 1; - trace_add (cmd->server, NULL, cfg, "cmd_example()"); + 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 */ +/* 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. */ +/* 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 @@ -500,16 +489,13 @@ static const char *cmd_example * 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) { +static int example_handler(request_rec *r) +{ - example_config - *dcfg; - example_config - *rcfg; + excfg *dcfg; - dcfg = our_dconfig (r); - trace_add (r->server, r, dcfg, "example_handler()"); + 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 @@ -517,94 +503,85 @@ static int example_handler * 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"). + * "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"; - soft_timeout ("send example call trace", r); - send_http_header (r); + 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) { - kill_timeout (r); - return OK; + 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. */ - rputs ("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n", r); - rputs ("<HTML>\n", r); - rputs (" <HEAD>\n", r); - rputs (" <TITLE>mod_example Module Content-Handler Output\n", r); - rputs (" </TITLE>\n", r); - rputs (" </HEAD>\n", r); - rputs (" <BODY>\n", r); - rputs (" <H1><SAMP>mod_example</SAMP> Module Content-Handler Output\n", r); - rputs (" </H1>\n", r); - rputs (" <P>\n", r); - rputs (" The format for the callback trace is:\n", r); - rputs (" </P>\n", r); - rputs (" <DL>\n", r); - rputs (" <DT><EM>n</EM>.<SAMP><routine-name>", r); - rputs ("(<routine-data>)</SAMP>\n", r); - rputs (" </DT>\n", r); - rputs (" <DD><SAMP>[<applies-to>]</SAMP>\n", r); - rputs (" </DD>\n", r); - rputs (" </DL>\n", r); - rputs (" <P>\n", r); - rputs (" The <SAMP><routine-data></SAMP> is supplied by\n", r); - rputs (" the routine when it requests the trace,\n", r); - rputs (" and the <SAMP><applies-to></SAMP> is extracted\n", r); - rputs (" from the configuration record at the time of the trace.\n", r); - rputs (" <STRONG>SVR()</STRONG> indicates a server environment\n", r); - rputs (" (blank means the main or default server, otherwise it's\n", r); - rputs (" the name of the VirtualHost); <STRONG>DIR()</STRONG>\n", r); - rputs (" indicates a location in the URL or filesystem\n", r); - rputs (" namespace.\n", r); - rputs (" </P>\n", r); - rprintf - ( - r, - " <H2>Static callbacks so far:</H2>\n <OL>\n%s </OL>\n", - trace - ); - rprintf - ( - r, - " <H2>Request-specific callbacks so far:</H2>\n <OL>\n%s </OL>\n", - table_get (r->notes, TRACE_NOTE) - ); - rputs (" <H2>Environment for <EM>this</EM> call:</H2>\n", r); - rputs (" <UL>\n", r); - rprintf (r, " <LI>Applies-to: <SAMP>%s</SAMP>\n </LI>\n", dcfg->loc); - rprintf - ( - r, - " <LI>\"Example\" directive declared here: %s\n </LI>\n", - (dcfg->local ? "YES" : "NO") - ); - rprintf - ( - r, - " <LI>\"Example\" inherited: %s\n </LI>\n", - (dcfg->congenital ? "YES" : "NO") - ); - rputs (" </UL>\n", r); - rputs (" </BODY>\n", r); - rputs ("</HTML>\n", r); + ap_rputs("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n", r); + ap_rputs("<HTML>\n", r); + ap_rputs(" <HEAD>\n", r); + ap_rputs(" <TITLE>mod_example Module Content-Handler Output\n", r); + ap_rputs(" </TITLE>\n", r); + ap_rputs(" </HEAD>\n", r); + ap_rputs(" <BODY>\n", r); + ap_rputs(" <H1><SAMP>mod_example</SAMP> Module Content-Handler Output\n", r); + ap_rputs(" </H1>\n", r); + ap_rputs(" <P>\n", r); + ap_rprintf(r, " Apache HTTP Server version: \"%s\"\n", + ap_get_server_version()); + ap_rputs(" <BR>\n", r); + ap_rprintf(r, " Server built: \"%s\"\n", ap_get_server_built()); + ap_rputs(" </P>\n", r);; + ap_rputs(" <P>\n", r); + ap_rputs(" The format for the callback trace is:\n", r); + ap_rputs(" </P>\n", r); + ap_rputs(" <DL>\n", r); + ap_rputs(" <DT><EM>n</EM>.<SAMP><routine-name>", r); + ap_rputs("(<routine-data>)</SAMP>\n", r); + ap_rputs(" </DT>\n", r); + ap_rputs(" <DD><SAMP>[<applies-to>]</SAMP>\n", r); + ap_rputs(" </DD>\n", r); + ap_rputs(" </DL>\n", r); + ap_rputs(" <P>\n", r); + ap_rputs(" The <SAMP><routine-data></SAMP> is supplied by\n", r); + ap_rputs(" the routine when it requests the trace,\n", r); + ap_rputs(" and the <SAMP><applies-to></SAMP> is extracted\n", r); + ap_rputs(" from the configuration record at the time of the trace.\n", r); + ap_rputs(" <STRONG>SVR()</STRONG> indicates a server environment\n", r); + ap_rputs(" (blank means the main or default server, otherwise it's\n", r); + ap_rputs(" the name of the VirtualHost); <STRONG>DIR()</STRONG>\n", r); + ap_rputs(" indicates a location in the URL or filesystem\n", r); + ap_rputs(" namespace.\n", r); + ap_rputs(" </P>\n", r); + ap_rprintf(r, " <H2>Static callbacks so far:</H2>\n <OL>\n%s </OL>\n", + trace); + ap_rputs(" <H2>Request-specific callbacks so far:</H2>\n", r); + ap_rprintf(r, " <OL>\n%s </OL>\n", ap_table_get(r->notes, TRACE_NOTE)); + ap_rputs(" <H2>Environment for <EM>this</EM> call:</H2>\n", r); + ap_rputs(" <UL>\n", r); + ap_rprintf(r, " <LI>Applies-to: <SAMP>%s</SAMP>\n </LI>\n", dcfg->loc); + ap_rprintf(r, " <LI>\"Example\" directive declared here: %s\n </LI>\n", + (dcfg->local ? "YES" : "NO")); + ap_rprintf(r, " <LI>\"Example\" inherited: %s\n </LI>\n", + (dcfg->congenital ? "YES" : "NO")); + ap_rputs(" </UL>\n", r); + ap_rputs(" </BODY>\n", r); + ap_rputs("</HTML>\n", r); /* * We're all done, so cancel the timeout we set. Since this is probably * the end of the request we *could* assume this would be done during * post-processing - but it's possible that another handler might be * called and inherit our outstanding timer. Not good; to each its own. */ - kill_timeout (r); + ap_kill_timeout(r); /* * We did what we wanted to do, so tell the rest of the server we * succeeded. @@ -613,33 +590,33 @@ static int example_handler } /*--------------------------------------------------------------------------*/ -/* */ -/* 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 */ +/* */ +/* 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. */ -/* */ +/* 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 */ +/* 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. */ -/* */ +/* 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 @@ -652,23 +629,81 @@ static int example_handler /* * All our module-initialiser does is add its trace to the log. */ -static void example_init - (server_rec *s, pool *p) { +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; + char *note; + char *sname = s->server_hostname; /* * Set up any module cells that ought to be initialised. */ - setup_module_cells (); + 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 = pstrcat (p, "example_init(", sname, ")", NULL); - trace_add (s, NULL, NULL, note); + note = ap_pstrcat(p, "example_child_exit(", sname, ")", NULL); + trace_add(s, NULL, NULL, note); } /* @@ -683,17 +718,16 @@ static void example_init * The return value is a pointer to the created module-specific * structure. */ -static void *example_dir_create - (pool *p, char *dirspec) { +static void *example_create_dir_config(pool *p, char *dirspec) +{ - example_config - *cfg; - char *dname = dirspec; + excfg *cfg; + char *dname = dirspec; /* * Allocate the space for our record from the pool supplied. */ - cfg = (example_config *) pcalloc (p, sizeof(example_config)); + 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. @@ -705,8 +739,8 @@ static void *example_dir_create * Finally, add our trace to the callback list. */ dname = (dname != NULL) ? dname : ""; - cfg->loc = pstrcat (p, "DIR(", dname, ")", NULL); - trace_add (NULL, NULL, cfg, "example_dir_create()"); + cfg->loc = ap_pstrcat(p, "DIR(", dname, ")", NULL); + trace_add(NULL, NULL, cfg, "example_create_dir_config()"); return (void *) cfg; } @@ -725,24 +759,21 @@ static void *example_dir_create * The return value is a pointer to the created module-specific structure * containing the merged values. */ -static void *example_dir_merge - (pool *p, void *parent_conf, void *newloc_conf) { - - example_config - *merged_config = - (example_config *) pcalloc (p, sizeof(example_config)); - example_config - *pconf = (example_config *) parent_conf; - example_config - *nconf = (example_config *) newloc_conf; - char *note; +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 = pstrdup (p, nconf->loc); + 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 @@ -755,22 +786,14 @@ static void *example_dir_merge * the current value. */ merged_config->cmode = - (pconf->cmode == nconf->cmode) ? pconf->cmode : CONFIG_MODE_COMBO; + (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 = pstrcat - ( - p, - "example_dir_merge(\"", - pconf->loc, - "\",\"", - nconf->loc, - "\")", - NULL - ); - trace_add (NULL, NULL, merged_config, note); + note = ap_pstrcat(p, "example_merge_dir_config(\"", pconf->loc, "\",\"", + nconf->loc, "\")", NULL); + trace_add(NULL, NULL, merged_config, note); return (void *) merged_config; } @@ -781,18 +804,17 @@ static void *example_dir_merge * The return value is a pointer to the created module-specific * structure. */ -static void *example_server_create - (pool *p, server_rec *s) { +static void *example_create_server_config(pool *p, server_rec *s) +{ - example_config - *cfg; - char *sname = s->server_hostname; + excfg *cfg; + char *sname = s->server_hostname; /* - * As with the example_dir_create() reoutine, we allocate and fill in an - * empty record. + * As with the example_create_dir_config() reoutine, we allocate and fill + * in an empty record. */ - cfg = (example_config *) pcalloc (p, sizeof(example_config)); + cfg = (excfg *) ap_pcalloc(p, sizeof(excfg)); cfg->local = 0; cfg->congenital = 0; cfg->cmode = CONFIG_MODE_SERVER; @@ -800,8 +822,8 @@ static void *example_server_create * Note that we were called in the trace list. */ sname = (sname != NULL) ? sname : ""; - cfg->loc = pstrcat (p, "SVR(", sname, ")", NULL); - trace_add (s, NULL, cfg, "example_server_create()"); + cfg->loc = ap_pstrcat(p, "SVR(", sname, ")", NULL); + trace_add(s, NULL, cfg, "example_create_server_config()"); return (void *) cfg; } @@ -818,45 +840,56 @@ static void *example_server_create * The return value is a pointer to the created module-specific structure * containing the merged values. */ -static void *example_server_merge - (pool *p, void *server1_conf, void *server2_conf) { - - example_config - *merged_config = - (example_config *) pcalloc (p, sizeof(example_config)); - example_config - *s1conf = (example_config *) server1_conf; - example_config - *s2conf = (example_config *) server2_conf; - char *note; +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; + (s1conf->cmode == s2conf->cmode) ? s1conf->cmode : CONFIG_MODE_COMBO; merged_config->local = s2conf->local; merged_config->congenital = (s1conf->congenital | s1conf->local); - merged_config->loc = pstrdup (p, s2conf->loc); + merged_config->loc = ap_pstrdup(p, s2conf->loc); /* * Trace our call, including what we were asked to merge. */ - note = pstrcat - ( - p, - "example_server_merge(\"", - s1conf->loc, - "\",\"", - s2conf->loc, - "\")", - NULL - ); - trace_add (NULL, NULL, merged_config, note); + 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. @@ -864,18 +897,17 @@ static void *example_server_merge * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, no * further modules are called for this phase. */ -static int example_xlate - (request_rec *r) { +static int example_translate_handler(request_rec *r) +{ - example_config - *cfg; + excfg *cfg; - cfg = our_dconfig (r); + 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_xlate()"); + trace_add(r->server, r, cfg, "example_translate_handler()"); return DECLINED; } @@ -888,17 +920,16 @@ static int example_xlate * HTTP_UNAUTHORIZED). If we return OK, no other modules are given a chance * at the request during this phase. */ -static int example_ckuser - (request_rec *r) { +static int example_check_user_id(request_rec *r) +{ - example_config - *cfg; + excfg *cfg; - cfg = our_dconfig (r); + cfg = our_dconfig(r); /* * Don't do anything except log the call. */ - trace_add (r->server, r, cfg, "example_ckuser()"); + trace_add(r->server, r, cfg, "example_check_user_id()"); return DECLINED; } @@ -912,19 +943,18 @@ static int example_ckuser * If *all* modules return DECLINED, the request is aborted with a server * error. */ -static int example_ckauth - (request_rec *r) { +static int example_auth_checker(request_rec *r) +{ - example_config - *cfg; + excfg *cfg; - cfg = our_dconfig (r); + 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_ckauth()"); - return OK; + trace_add(r->server, r, cfg, "example_auth_checker()"); + return DECLINED; } /* @@ -936,15 +966,14 @@ static int example_ckauth * 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_ckaccess - (request_rec *r) { +static int example_access_checker(request_rec *r) +{ - example_config - *cfg; + excfg *cfg; - cfg = our_dconfig (r); - trace_add (r->server, r, cfg, "example_ckaccess()"); - return OK; + cfg = our_dconfig(r); + trace_add(r->server, r, cfg, "example_access_checker()"); + return DECLINED; } /* @@ -955,18 +984,17 @@ static int example_ckaccess * 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_typer - (request_rec *r) { +static int example_type_checker(request_rec *r) +{ - example_config - *cfg; + excfg *cfg; - cfg = our_dconfig (r); + 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_typer()"); + trace_add(r->server, r, cfg, "example_type_checker()"); return DECLINED; } @@ -978,17 +1006,16 @@ static int example_typer * server will still call any remaining modules with an handler for this * phase. */ -static int example_fixer - (request_rec *r) { +static int example_fixer_upper(request_rec *r) +{ - example_config - *cfg; + excfg *cfg; - cfg = our_dconfig (r); + cfg = our_dconfig(r); /* * Log the call and exit. */ - trace_add (r->server, r, cfg, "example_fixer()"); + trace_add(r->server, r, cfg, "example_fixer_upper()"); return OK; } @@ -999,14 +1026,13 @@ static int example_fixer * 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) { +static int example_logger(request_rec *r) +{ - example_config - *cfg; + excfg *cfg; - cfg = our_dconfig (r); - trace_add (r->server, r, cfg, "example_logger()"); + cfg = our_dconfig(r); + trace_add(r->server, r, cfg, "example_logger()"); return DECLINED; } @@ -1018,46 +1044,46 @@ static int example_logger * 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_hparser - (request_rec *r) { +static int example_header_parser(request_rec *r) +{ - example_config - *cfg; + excfg *cfg; - cfg = our_dconfig (r); - trace_add (r->server, r, cfg, "example_hparser()"); + 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 */ +/* */ +/* 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. */ -/* */ +/* collisions of directive names between modules. */ +/* */ /*--------------------------------------------------------------------------*/ /* * List of directives specific to our module. */ -command_rec example_commands[] = { +static const command_rec example_cmds[] = +{ { - "Example", /* directive name */ - cmd_example, /* action routine for directive */ - NULL, /* argument to include in call */ - OR_OPTIONS, /* where available */ - NO_ARGS, /* arguments */ - "Example directive - no arguments" - /* directive description */ + "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 } + {NULL} }; /*--------------------------------------------------------------------------*/ -/* */ -/* Now the list of content handlers available from this module. */ -/* */ +/* */ +/* Now the list of content handlers available from this module. */ +/* */ /*--------------------------------------------------------------------------*/ /* * List of content handlers our module supplies. Each handler is defined by @@ -1071,16 +1097,17 @@ command_rec example_commands[] = { * if a content-handler returns anything except DECLINED, no other * content-handlers will be called. */ -handler_rec example_handlers[] = { - { "example-handler", example_handler }, - { NULL } +static const handler_rec example_handlers[] = +{ + {"example-handler", example_handler}, + {NULL} }; /*--------------------------------------------------------------------------*/ -/* */ -/* Finally, the list of callback routines and data structures that */ +/* */ +/* 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 @@ -1090,21 +1117,33 @@ handler_rec example_handlers[] = { * during request processing. Note that not all routines are necessarily * called (such as if a resource doesn't have access restrictions). */ -module example_module = { +module example_module = +{ STANDARD_MODULE_STUFF, - example_init, /* initializer */ - example_dir_create, /* per-directory config creater */ - example_dir_merge, /* dir config merger - default is to override */ - example_server_create, /* server config creator */ - example_server_merge, /* server config merger */ - example_commands, /* command table */ - example_handlers, /* [6] list of handlers */ - example_xlate, /* [1] filename-to-URI translation */ - example_ckuser, /* [4] check/validate HTTP user_id */ - example_ckauth, /* [5] check HTTP user_id is valid *here* */ - example_ckaccess, /* [3] check access by host address, etc. */ - example_typer, /* [6] MIME type checker/setter */ - example_fixer, /* [7] fixups */ - example_logger, /* [9] logger */ - example_hparser /* [2] header parser */ + 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/usr.sbin/httpd/src/modules/experimental/mod_mmap_static.c b/usr.sbin/httpd/src/modules/experimental/mod_mmap_static.c index 207875c49da..127fee81254 100644 --- a/usr.sbin/httpd/src/modules/experimental/mod_mmap_static.c +++ b/usr.sbin/httpd/src/modules/experimental/mod_mmap_static.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/modules/proxy/mod_proxy.c b/usr.sbin/httpd/src/modules/proxy/mod_proxy.c index ce8dc88af15..0816f6640d2 100644 --- a/usr.sbin/httpd/src/modules/proxy/mod_proxy.c +++ b/usr.sbin/httpd/src/modules/proxy/mod_proxy.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1996,1997 The Apache Group. All rights reserved. + * 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 @@ -20,9 +20,14 @@ * * 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. + * prior written permission. For written permission, please contact + * apache@apache.org. * - * 5. Redistributions of any form whatsoever must retain the following + * 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/)." @@ -52,18 +57,25 @@ #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[]={ - { "ftp", DEFAULT_FTP_PORT}, - { "gopher", DEFAULT_GOPHER_PORT}, - { "http", DEFAULT_PORT}, - { "nntp", DEFAULT_NNTP_PORT}, - { "wais", DEFAULT_WAIS_PORT}, - { "https", DEFAULT_HTTPS_PORT}, - { "snews", DEFAULT_SNEWS_PORT}, - { "prospero", DEFAULT_PROSPERO_PORT}, - { NULL, -1} /* unknown port */ +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 */ }; /* @@ -79,27 +91,28 @@ static struct proxy_services defports[]={ /* -------------------------------------------------------------- */ /* Translate the URL into a 'filename' */ -static int -alias_match(char *uri, char *alias_fakename) +static int alias_match(const char *uri, const char *alias_fakename) { - char *end_fakename = alias_fakename + strlen (alias_fakename); - char *aliasp = alias_fakename, *urip = uri; + const char *end_fakename = alias_fakename + strlen(alias_fakename); + const char *aliasp = alias_fakename, *urip = uri; - while (aliasp < end_fakename) - { - if (*aliasp == '/') - { + 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; + if (*urip != '/') + return 0; + + while (*aliasp == '/') + ++aliasp; + while (*urip == '/') + ++urip; } else { /* Other characters are compared literally */ - if (*urip++ != *aliasp++) return 0; + if (*urip++ != *aliasp++) + return 0; } } @@ -116,39 +129,80 @@ alias_match(char *uri, char *alias_fakename) return urip - uri; } -static int -proxy_trans(request_rec *r) +/* 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 = 1; + 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 = 1; + 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 *)get_module_config(sconf, &proxy_module); - - if (r->proxyreq) - { - if (!conf->req) return DECLINED; - - r->filename = pstrcat(r->pool, "proxy:", r->uri, NULL); - r->handler = "proxy-server"; + (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) { + /* someone has already set up the proxy, it was possibly ourselves + * in proxy_detect + */ return OK; - } else - { - int i, len; - struct proxy_alias *ent=(struct proxy_alias *)conf->aliases->elts; - - for (i=0; i < conf->aliases->nelts; i++) - { - len = alias_match(r->uri, ent[i].fake); - - if (len > 0) - { - r->filename = pstrcat(r->pool, "proxy:", ent[i].real, - r->uri + len, NULL); - r->handler = "proxy-server"; - 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 = 1; + return OK; } - return DECLINED; } + return DECLINED; } /* -------------------------------------------------------------- */ @@ -157,155 +211,263 @@ proxy_trans(request_rec *r) /* * Canonicalise the URL */ -static int -proxy_fixup(request_rec *r) +static int proxy_fixup(request_rec *r) { char *url, *p; - int i; - if (strncmp(r->filename, "proxy:", 6) != 0) return DECLINED; + if (!r->proxyreq || strncmp(r->filename, "proxy:", 6) != 0) + return DECLINED; url = &r->filename[6]; -/* lowercase the scheme */ - p = strchr(url, ':'); - if (p == NULL || p == url) return BAD_REQUEST; - for (i=0; i != p - url; i++) url[i] = tolower(url[i]); /* canonicalise each specific scheme */ - if (strncmp(url, "http:", 5) == 0) - return proxy_http_canon(r, url+5, "http", DEFAULT_PORT); - else if (strncmp(url, "ftp:", 4) == 0) - return proxy_ftp_canon(r, url+4); - else return OK; /* otherwise; we've done the best we can */ + 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 || 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) + +static int proxy_handler(request_rec *r) { char *url, *scheme, *p; void *sconf = r->server->module_config; proxy_server_conf *conf = - (proxy_server_conf *)get_module_config(sconf, &proxy_module); - array_header *proxies=conf->proxies; - struct proxy_remote *ents=(struct proxy_remote *)proxies->elts; + (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; - struct cache_req *cr; + cache_req *cr; + int direct_connect = 0; + const char *maxfwd_str; + + if (!r->proxyreq || strncmp(r->filename, "proxy:", 6) != 0) + return DECLINED; - if (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 = 0; + 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 = setup_client_block(r, REQUEST_CHUNKED_ERROR))) + if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) return rc; url = r->filename + 6; p = strchr(url, ':'); - if (p == NULL) return BAD_REQUEST; + if (p == NULL) + return HTTP_BAD_REQUEST; - rc = proxy_cache_check(r, url, &conf->cache, &cr); - if (rc != DECLINED) return rc; + 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 = pstrdup(r->pool, url); + scheme = ap_pstrdup(r->pool, url); *p = ':'; -/* firstly, try a proxy */ - - for (i=0; i < proxies->nelts; i++) + /* 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) */ { - 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)) - { -/* we only know how to handle communication to a proxy via http */ - if (strcasecmp(ents[i].protocol, "http") == 0) - rc = proxy_http_handler(r, cr, url, ents[i].hostname, - ents[i].port); - else rc = DECLINED; - - /* an error or success */ - if (rc != DECLINED && rc != BAD_GATEWAY) return rc; - /* we failed to talk to the upstream proxy */ + 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 proxy_connect_handler(r, cr, url); + return ap_proxy_connect_handler(r, cr, url, NULL, 0); if (strcasecmp(scheme, "http") == 0) - return proxy_http_handler(r, cr, url, NULL, 0); + return ap_proxy_http_handler(r, cr, url, NULL, 0); if (strcasecmp(scheme, "ftp") == 0) - return proxy_ftp_handler(r, cr, url); - else return NOT_IMPLEMENTED; + 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 = pcalloc(p, sizeof(proxy_server_conf)); - - ps->proxies = make_array(p, 10, sizeof(struct proxy_remote)); - ps->aliases = make_array(p, 10, sizeof(struct proxy_alias)); - ps->noproxies = make_array(p, 10, sizeof(struct noproxy_entry)); - ps->nocaches = make_array(p, 10, sizeof(struct nocache_entry)); - ps->req = 0; - - ps->cache.root = NULL; - ps->cache.space = DEFAULT_CACHE_SPACE; - ps->cache.maxexpire = DEFAULT_CACHE_MAXEXPIRE; - ps->cache.defaultexpire = DEFAULT_CACHE_EXPIRE; - ps->cache.lmfactor = DEFAULT_CACHE_LMFACTOR; - ps->cache.gcinterval = -1; - /* at these levels, the cache can have 2^18 directories (256,000) */ - ps->cache.dirlevels=3; - ps->cache.dirlength=1; - - return ps; + 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->req = 0; + + ps->cache.root = NULL; + ps->cache.space = DEFAULT_CACHE_SPACE; + ps->cache.maxexpire = DEFAULT_CACHE_MAXEXPIRE; + ps->cache.defaultexpire = DEFAULT_CACHE_EXPIRE; + ps->cache.lmfactor = DEFAULT_CACHE_LMFACTOR; + ps->cache.gcinterval = -1; + /* at these levels, the cache can have 2^18 directories (256,000) */ + ps->cache.dirlevels = 3; + ps->cache.dirlength = 1; + ps->cache.cache_completion = DEFAULT_CACHE_COMPLETION; + + return ps; } static const char * -add_proxy(cmd_parms *cmd, void *dummy, char *f, char *r) + add_proxy(cmd_parms *cmd, void *dummy, char *f, char *r) { server_rec *s = cmd->server; proxy_server_conf *conf = - (proxy_server_conf *)get_module_config(s->module_config,&proxy_module); + (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 "Bad syntax for a remote proxy server"; + 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 "Bad syntax for a remote proxy server (bad port number)"; + 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; + } + else + port = -1; *p = '\0'; - if (strchr(f, ':') == NULL) str_tolower(f); /* lowercase scheme */ - str_tolower(p + 3); /* lowercase hostname */ + if (strchr(f, ':') == NULL) + ap_str_tolower(f); /* lowercase scheme */ + ap_str_tolower(p + 3); /* lowercase hostname */ - if (port == -1) - { + if (port == -1) { int i; - for (i=0; defports[i].scheme != NULL; i++) - if (strcasecmp(defports[i].scheme, r) == 0) break; + for (i = 0; defports[i].scheme != NULL; i++) + if (strcasecmp(defports[i].scheme, r) == 0) + break; port = defports[i].port; } - new = push_array (conf->proxies); + new = ap_push_array(conf->proxies); new->scheme = f; new->protocol = r; new->hostname = p + 3; @@ -314,44 +476,58 @@ add_proxy(cmd_parms *cmd, void *dummy, char *f, char *r) } static const char * -add_pass(cmd_parms *cmd, void *dummy, char *f, char *r) + add_pass(cmd_parms *cmd, void *dummy, char *f, char *r) { server_rec *s = cmd->server; proxy_server_conf *conf = - (proxy_server_conf *)get_module_config(s->module_config,&proxy_module); + (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; - new = push_array (conf->aliases); + 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) + set_proxy_exclude(cmd_parms *parms, void *dummy, char *arg) { server_rec *s = parms->server; proxy_server_conf *conf = - get_module_config (s->module_config, &proxy_module); + ap_get_module_config(s->module_config, &proxy_module); struct noproxy_entry *new; - struct noproxy_entry *list=(struct noproxy_entry*)conf->noproxies->elts; + 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 (strcmp(arg, list[i].name) == 0) + 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 = push_array (conf->noproxies); + 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 && proxy_host2addr(new->name, &hp) == NULL) + 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; @@ -359,11 +535,96 @@ set_proxy_exclude(cmd_parms *parms, void *dummy, char *arg) 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 (!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_req(cmd_parms *parms, void *dummy, int flag) + set_proxy_domain(cmd_parms *parms, void *dummy, char *arg) { proxy_server_conf *psf = - get_module_config (parms->server->module_config, &proxy_module); + 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; return NULL; @@ -371,22 +632,23 @@ set_proxy_req(cmd_parms *parms, void *dummy, int flag) static const char * -set_cache_size(cmd_parms *parms, char *struct_ptr, char *arg) + set_cache_size(cmd_parms *parms, char *struct_ptr, char *arg) { proxy_server_conf *psf = - get_module_config (parms->server->module_config, &proxy_module); + ap_get_module_config(parms->server->module_config, &proxy_module); int val; - if (sscanf(arg, "%d", &val) != 1) return "Value must be an integer"; + if (sscanf(arg, "%d", &val) != 1) + return "CacheSize value must be an integer (kBytes)"; psf->cache.space = val; return NULL; } static const char * -set_cache_root(cmd_parms *parms, void *dummy, char *arg) + set_cache_root(cmd_parms *parms, void *dummy, char *arg) { proxy_server_conf *psf = - get_module_config (parms->server->module_config, &proxy_module); + ap_get_module_config(parms->server->module_config, &proxy_module); psf->cache.root = arg; @@ -394,161 +656,243 @@ set_cache_root(cmd_parms *parms, void *dummy, char *arg) } static const char * -set_cache_factor(cmd_parms *parms, void *dummy, char *arg) + set_cache_factor(cmd_parms *parms, void *dummy, char *arg) { proxy_server_conf *psf = - get_module_config (parms->server->module_config, &proxy_module); + ap_get_module_config(parms->server->module_config, &proxy_module); double val; - if (sscanf(arg, "%lg", &val) != 1) return "Value must be a float"; + if (sscanf(arg, "%lg", &val) != 1) + return "CacheLastModifiedFactor value must be a float"; psf->cache.lmfactor = val; return NULL; } static const char * -set_cache_maxex(cmd_parms *parms, void *dummy, char *arg) + set_cache_maxex(cmd_parms *parms, void *dummy, char *arg) { proxy_server_conf *psf = - get_module_config (parms->server->module_config, &proxy_module); + ap_get_module_config(parms->server->module_config, &proxy_module); double val; - if (sscanf(arg, "%lg", &val) != 1) return "Value must be a float"; - psf->cache.maxexpire = (int)(val * (double)SEC_ONE_HR); + if (sscanf(arg, "%lg", &val) != 1) + return "CacheMaxExpire value must be a float"; + psf->cache.maxexpire = (int) (val * (double) SEC_ONE_HR); return NULL; } static const char * -set_cache_defex(cmd_parms *parms, void *dummy, char *arg) + set_cache_defex(cmd_parms *parms, void *dummy, char *arg) { proxy_server_conf *psf = - get_module_config (parms->server->module_config, &proxy_module); + ap_get_module_config(parms->server->module_config, &proxy_module); double val; - if (sscanf(arg, "%lg", &val) != 1) return "Value must be a float"; - psf->cache.defaultexpire = (int)(val * (double)SEC_ONE_HR); + if (sscanf(arg, "%lg", &val) != 1) + return "CacheDefaultExpire value must be a float"; + psf->cache.defaultexpire = (int) (val * (double) SEC_ONE_HR); return NULL; } static const char * -set_cache_gcint(cmd_parms *parms, void *dummy, char *arg) + set_cache_gcint(cmd_parms *parms, void *dummy, char *arg) { proxy_server_conf *psf = - get_module_config (parms->server->module_config, &proxy_module); + ap_get_module_config(parms->server->module_config, &proxy_module); double val; - if (sscanf(arg, "%lg", &val) != 1) return "Value must be a float"; - psf->cache.gcinterval = (int)(val * (double)SEC_ONE_HR); + if (sscanf(arg, "%lg", &val) != 1) + return "CacheGcInterval value must be a float"; + psf->cache.gcinterval = (int) (val * (double) SEC_ONE_HR); return NULL; } static const char * -set_cache_dirlevels(cmd_parms *parms, char *struct_ptr, char *arg) + set_cache_dirlevels(cmd_parms *parms, char *struct_ptr, char *arg) { proxy_server_conf *psf = - get_module_config (parms->server->module_config, &proxy_module); + ap_get_module_config(parms->server->module_config, &proxy_module); int val; - if (sscanf(arg, "%d", &val) != 1) return "Value must be an integer"; + 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; return NULL; } static const char * -set_cache_dirlength(cmd_parms *parms, char *struct_ptr, char *arg) + set_cache_dirlength(cmd_parms *parms, char *struct_ptr, char *arg) { proxy_server_conf *psf = - get_module_config (parms->server->module_config, &proxy_module); + ap_get_module_config(parms->server->module_config, &proxy_module); int val; - if (sscanf(arg, "%d", &val) != 1) return "Value must be an integer"; + 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; return NULL; } static const char * -set_cache_exclude(cmd_parms *parms, void *dummy, char *arg) + set_cache_exclude(cmd_parms *parms, void *dummy, char *arg) { server_rec *s = parms->server; proxy_server_conf *conf = - get_module_config (s->module_config, &proxy_module); + ap_get_module_config(s->module_config, &proxy_module); struct nocache_entry *new; - struct nocache_entry *list=(struct nocache_entry*)conf->nocaches->elts; + 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 (strcmp(arg, list[i].name) == 0) + 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 = push_array (conf->nocaches); + 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 && proxy_host2addr(new->name, &hp) == NULL) + 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; + new->addr.s_addr = 0; } return NULL; } -static handler_rec proxy_handlers[] = { -{ "proxy-server", proxy_handler }, -{ NULL } -}; - -static 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"}, -{ "ProxyBlock", set_proxy_exclude, NULL, RSRC_CONF, ITERATE, - "A list of names, hosts or domains to which the proxy will not connect" }, -{ "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" }, -{ 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; + 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); + 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"; + } + + return NULL; +} + +static const handler_rec proxy_handlers[] = +{ + {"proxy-server", proxy_handler}, + {NULL} }; -module proxy_module = { - STANDARD_MODULE_STUFF, - NULL, /* initializer */ - NULL, /* create per-directory config structure */ - NULL, /* merge per-directory config structures */ - create_proxy_config, /* create per-server config structure */ - NULL, /* 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 */ +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 */ + NULL, /* merge per-server config structures */ + proxy_cmds, /* command table */ + proxy_handlers, /* handlers */ + proxy_trans, /* translate_handler */ + NULL, /* check_user_id */ + NULL, /* check auth */ + NULL, /* check access */ + NULL, /* type_checker */ + proxy_fixup, /* pre-run fixups */ + NULL, /* logger */ + NULL, /* header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + proxy_detect /* post read-request */ +}; diff --git a/usr.sbin/httpd/src/modules/proxy/mod_proxy.h b/usr.sbin/httpd/src/modules/proxy/mod_proxy.h index 3287fb2a86a..61760c4c21a 100644 --- a/usr.sbin/httpd/src/modules/proxy/mod_proxy.h +++ b/usr.sbin/httpd/src/modules/proxy/mod_proxy.h @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1996,1997 The Apache Group. All rights reserved. + * 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 @@ -20,9 +20,14 @@ * * 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. + * prior written permission. For written permission, please contact + * apache@apache.org. * - * 5. Redistributions of any form whatsoever must retain the following + * 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/)." @@ -50,49 +55,52 @@ * */ +#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. + 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. + If TESTING is set, then garbage collection doesn't delete ... probably a good + idea when hacking. -This code is still experimental! + This code is still experimental! -Things to do: + Things to do: -1. Make it garbage collect in the background, not while someone is waiting for -a response! + 1. Make it garbage collect in the background, not while someone is waiting for + a response! -2. Check the logic thoroughly. + 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. + 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 <ben@algroup.co.uk> 30 Mar 96 + Ben Laurie <ben@algroup.co.uk> 30 Mar 96 -More things to do: + More things to do: -0. Code cleanup (ongoing) + 0. Code cleanup (ongoing) -1. add 230 response output for ftp now that it works + 1. add 230 response output for ftp now that it works -2. Make the ftp proxy transparent, also same with (future) gopher & wais + 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) + 3. Use protocol handler struct a la Apache module handlers (Dirk van Gulik) -5. Bulletproof GC against SIGALRM + 4. Use a cache expiry database for more efficient GC (Jeremy Wohl) -Chuck Murcko <chuck@topsail.org> 15 April 1997 + 5. Bulletproof GC against SIGALRM -*/ + Chuck Murcko <chuck@topsail.org> 15 April 1997 + + */ #define TESTING 0 #undef EXPLAIN @@ -100,24 +108,33 @@ Chuck Murcko <chuck@topsail.org> 15 April 1997 #include "httpd.h" #include "http_config.h" #include "http_protocol.h" - -#include "explain.h" - -DEF_Explain +#include "explain.h" -extern module proxy_module; +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() */ +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 */ + +#ifdef CHARSET_EBCDIC +#define CRLF "\r\n" +#else /*CHARSET_EBCDIC*/ +#define CRLF "\015\012" +#endif /*CHARSET_EBCDIC*/ + + #define SEC_ONE_DAY 86400 /* one day, in seconds */ #define SEC_ONE_HR 3600 /* one hour, in seconds */ @@ -131,19 +148,17 @@ enum enctype { enc_path, enc_search, enc_user, enc_fpath, enc_parm }; #define DEFAULT_PROSPERO_PORT 1525 /* WARNING: conflict w/Oracle */ /* Some WWW schemes and their default ports; this is basically /etc/services */ -struct proxy_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_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 { @@ -151,6 +166,13 @@ struct proxy_alias { 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; @@ -165,109 +187,130 @@ struct nocache_entry { #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 */ - int space; /* Maximum cache size (in 1024 bytes) */ - int maxexpire; /* Maximum time to keep cached files in secs */ - int defaultexpire; /* default time to keep cached file in secs */ - double lmfactor; /* factor for estimating expires date */ - int gcinterval; /* garbage collection interval, in seconds */ - int dirlevels; /* Number of levels of subdirectories */ - int dirlength; /* Length of subdirectory names */ +struct cache_conf { + const char *root; /* the location of the cache directory */ + off_t space; /* Maximum cache size (in 1024 bytes) */ + time_t maxexpire; /* Maximum time to keep cached files in secs */ + time_t defaultexpire; /* default time to keep cached file in secs */ + double lmfactor; /* factor for estimating expires date */ + time_t gcinterval; /* garbage collection interval, in seconds */ + int dirlevels; /* Number of levels of subdirectories */ + int dirlength; /* Length of subdirectory names */ + float cache_completion; /* Force cache completion after this point */ }; -typedef struct -{ - struct cache_conf cache; /* cache configuration */ +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; - int req; /* true if proxy requests are enabled */ + 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 */ + enum { + via_off, + via_on, + via_block, + via_full + } viaopt; /* how to deal with proxy Via: headers */ + size_t recv_buffer_size; } proxy_server_conf; -struct hdr_entry -{ - char *field; - char *value; +struct hdr_entry { + const char *field; + const char *value; }; /* caching information about a request */ -struct cache_req -{ - 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 */ - unsigned int len; /* content length */ - char *protocol; /* Protocol, and major/minor number, e.g. HTTP/1.1 */ - int status; /* the status of the cached file */ - char *resp_line; /* the whole status like (protocol, code + message) */ - array_header *hdrs; /* the HTTP headers of the file */ +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 proxy_cache_tidy(struct cache_req *c); -int proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf, - struct cache_req **cr); -int proxy_cache_update(struct cache_req *c, array_header *resp_hdrs, - const int is_HTTP1, int nocache); -void proxy_garbage_coll(request_rec *r); +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 proxy_connect_handler(request_rec *r, struct cache_req *c, char *url); +int ap_proxy_connect_handler(request_rec *r, cache_req *c, char *url, + const char *proxyhost, int proxyport); /* proxy_ftp.c */ -int proxy_ftp_canon(request_rec *r, char *url); -int proxy_ftp_handler(request_rec *r, struct cache_req *c, char *url); +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 proxy_http_canon(request_rec *r, char *url, const char *scheme, - int def_port); -int proxy_http_handler(request_rec *r, struct cache_req *c, char *url, - const char *proxyhost, int proxyport); +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 proxy_hex2c(const char *x); -void proxy_c2hex(int ch, char *x); -char *proxy_canonenc(pool *p, const char *x, int len, enum enctype t, - int isenc); -char *proxy_canon_netloc(pool *pool, char **const urlp, char **userp, - char **passwordp, char **hostp, int *port); -char *proxy_date_canon(pool *p, char *x); -array_header *proxy_read_headers(pool *pool, char *buffer, int size, BUFF *f); -long int proxy_send_fb(BUFF *f, request_rec *r, BUFF *f2, struct cache_req *c); -struct hdr_entry *proxy_get_header(array_header *hdrs_arr, const char *name); -struct hdr_entry *proxy_add_header(array_header *hdrs_arr, char *field, - char *value, int rep); -void proxy_del_header(array_header *hdrs_arr, const char *field); -void proxy_send_headers(BUFF *fp, const char *respline, array_header *hdrs_arr); -int proxy_liststr(const char *list, const char *val); -void proxy_hash(const char *it, char *val,int ndepth,int nlength); -int proxy_hex2sec(const char *x); -void proxy_sec2hex(int t, char *y); -void proxy_log_uerror(const char *routine, const char *file, const char *err, - server_rec *s); -BUFF *proxy_cache_error(struct cache_req *r); -int proxyerror(request_rec *r, const char *message); -const char *proxy_host2addr(const char *host, struct hostent *reqhp); -int proxy_doconnect(int sock, struct sockaddr_in *addr, request_rec *r); - +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, + int 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, 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/usr.sbin/httpd/src/modules/proxy/proxy_cache.c b/usr.sbin/httpd/src/modules/proxy/proxy_cache.c index 56f0a95cd26..a33d9000861 100644 --- a/usr.sbin/httpd/src/modules/proxy/proxy_cache.c +++ b/usr.sbin/httpd/src/modules/proxy/proxy_cache.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1996,1997 The Apache Group. All rights reserved. + * 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 @@ -20,9 +20,14 @@ * * 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. + * prior written permission. For written permission, please contact + * apache@apache.org. * - * 5. Redistributions of any form whatsoever must retain the following + * 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/)." @@ -52,253 +57,453 @@ /* Cache and garbage collection routines for Apache proxy */ -#include "md5.h" - #include "mod_proxy.h" +#include "http_conf_globals.h" #include "http_log.h" #include "http_main.h" #include "util_date.h" +#ifdef WIN32 +#include <sys/utime.h> +#else #include <utime.h> +#endif /* WIN32 */ +#include "multithread.h" +#include "ap_md5.h" -#define abs(c) ((c) >= 0 ? (c) : -(c)) +DEF_Explain -struct gc_ent -{ +struct gc_ent { unsigned long int len; time_t expire; - char file[HASH_LEN+1]; - + char file[HASH_LEN + 1]; }; -static int -gcdiff(const void *ap, const void *bp) +/* 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 every, garbage_now, garbage_expire; +static char *filename; +static mutex *garbage_mutex = NULL; + + +int ap_proxy_garbage_init(server_rec *r, pool *p) { - const struct gc_ent *a=*(struct gc_ent **)ap, *b=*(struct gc_ent **)bp; + if (!garbage_mutex) + garbage_mutex = ap_create_mutex(NULL); - if (a->expire > b->expire) return 1; - else if (a->expire < b->expire) return -1; - else return 0; + return (0); } -static int curbytes, cachesize, every; -static unsigned long int curblocks; -static time_t now, expire; -static char *filename; -static int filenamelen; -static int sub_garbage_coll(request_rec *r,array_header *files, - const char *cachedir,const char *cachesubdir); +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); +#if !defined(WIN32) && !defined(MPE) && !defined(OS2) +static void detached_proxy_garbage_coll(request_rec *r); +#endif -void proxy_garbage_coll(request_rec *r) - { + +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 !defined(WIN32) && !defined(MPE) && !defined(OS2) + 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) +static void detached_proxy_garbage_coll(request_rec *r) +{ + pid_t pid; + int status; + pid_t pgrp; + + 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 */ + +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 *)get_module_config(sconf, &proxy_module); - const struct cache_conf *conf=&pconf->cache; + (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); + const struct cache_conf *conf = &pconf->cache; array_header *files; struct stat buf; - struct gc_ent *fent,**elts; + struct gc_ent *fent; int i, timefd; - static time_t lastcheck=BAD_DATE; /* static data!!! */ + static time_t lastcheck = BAD_DATE; /* static (per-process) data!!! */ cachedir = conf->root; - cachesize = conf->space; + /* configured size is given in kB. Make it bytes, convert to long61_t: */ + cachesize.lower = cachesize.upper = 0; + add_long61(&cachesize, conf->space << 10); every = conf->gcinterval; - if (cachedir == NULL || every == -1) return; - now = time(NULL); - if (now != -1 && lastcheck != BAD_DATE && now < lastcheck + every) return; - - block_alarms(); /* avoid SIGALRM on big cache cleanup */ + if (cachedir == NULL || every == -1) + return; + garbage_now = time(NULL); + /* Usually, the modification time of <cachedir>/.time can only increase. + * Thus, even with several child processes having their own copy of + * lastcheck, if time(NULL) still < lastcheck then it's not time + * for GC yet. + */ + if (garbage_now != -1 && lastcheck != BAD_DATE && garbage_now < lastcheck + every) + return; - filenamelen = strlen(cachedir) + HASH_LEN + 2; - filename = palloc(r->pool, filenamelen); - ap_snprintf(filename, filenamelen, "%s/.time", cachedir); + ap_block_alarms(); /* avoid SIGALRM on big cache cleanup */ - if (stat(filename, &buf) == -1) /* does not exist */ - { - if (errno != ENOENT) - { - proxy_log_uerror("stat", filename, NULL, r->server); - unblock_alarms(); + filename = ap_palloc(r->pool, strlen(cachedir) + HASH_LEN + 2); + strcpy(filename, cachedir); + strcat(filename, "/.time"); + if (stat(filename, &buf) == -1) { /* does not exist */ + if (errno != ENOENT) { + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "proxy: stat(%s)", filename); + ap_unblock_alarms(); return; } - if ((timefd = creat(filename, 0666)) == -1) - { + if ((timefd = creat(filename, 0666)) == -1) { if (errno != EEXIST) - proxy_log_uerror("creat", filename, NULL, r->server); + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "proxy: creat(%s)", filename); else - lastcheck = abs(now); /* someone else got in there */ - unblock_alarms(); + lastcheck = garbage_now; /* someone else got in there */ + ap_unblock_alarms(); return; } close(timefd); - } else - { - lastcheck = buf.st_mtime; /* save the time */ - if (now < lastcheck + every) - { - unblock_alarms(); + } + else { + lastcheck = buf.st_mtime; /* save the time */ + if (garbage_now < lastcheck + every) { + ap_unblock_alarms(); return; } if (utime(filename, NULL) == -1) - proxy_log_uerror("utimes", filename, NULL, r->server); + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "proxy: utimes(%s)", filename); } - files = make_array(r->pool, 100, sizeof(struct gc_ent *)); - curblocks = 0; - curbytes = 0; + files = ap_make_array(r->pool, 100, sizeof(struct gc_ent)); + curbytes.upper = curbytes.lower = 0L; - sub_garbage_coll(r,files,cachedir,"/"); + sub_garbage_coll(r, files, cachedir, "/"); - if (curblocks < cachesize || curblocks + curbytes <= cachesize) - { - unblock_alarms(); + 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; } - qsort(files->elts, files->nelts, sizeof(struct gc_ent *), gcdiff); + /* sort the files we found by expiration date */ + qsort(files->elts, files->nelts, sizeof(struct gc_ent), gcdiff); - elts = (struct gc_ent **)files->elts; - for (i=0; i < files->nelts; i++) - { - fent = elts[i]; - ap_snprintf(filename, filenamelen, "%s%s", cachedir, fent->file); - Explain3("GC Unlinking %s (expiry %ld, now %ld)",filename,fent->expire,now); + 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); + fprintf(stderr, "Would unlink %s\n", filename); #else - if (unlink(filename) == -1) - { + if (unlink(filename) == -1) { if (errno != ENOENT) - proxy_log_uerror("unlink", filename, NULL, r->server); + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "proxy gc: unlink(%s)", filename); } else #endif { - curblocks -= fent->len >> 10; - curbytes -= fent->len & 0x3FF; - if (curbytes < 0) - { - curbytes += 1024; - curblocks--; - } - if (curblocks < cachesize || curblocks + curbytes <= cachesize) + sub_long61(&curbytes, ROUNDUP2BLOCKS(fent->len)); + if (cmp_long61(&curbytes, &cachesize) < 0) break; } } - unblock_alarms(); + + 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) +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; + int fd, i; DIR *dir; -#if defined(NEXT) +#if defined(NEXT) || defined(WIN32) struct DIR_TYPE *ent; #else struct dirent *ent; #endif struct gc_ent *fent; - int nfiles=0; + int nfiles = 0; - ap_snprintf(cachedir, sizeof(cachedir), "%s%s",cachebasedir,cachesubdir); - Explain1("GC Examining directory %s",cachedir); + ap_snprintf(cachedir, sizeof(cachedir), "%s%s", cachebasedir, cachesubdir); + Explain1("GC Examining directory %s", cachedir); dir = opendir(cachedir); - if (dir == NULL) - { - proxy_log_uerror("opendir", cachedir, NULL, r->server); + 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; - ap_snprintf(filename, filenamelen, "%s%s", cachedir, ent->d_name); - Explain1("GC Examining file %s",filename); + 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) - { + 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 (stat(filename, &buf) == -1) { if (errno != ENOENT) - proxy_log_uerror("stat", filename, NULL, r->server); - } else if (now != -1 && buf.st_atime < now - SEC_ONE_DAY && - buf.st_mtime < now - SEC_ONE_DAY) - { - Explain1("GC unlink %s",filename); + 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); + 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; */ + /* if (strlen(ent->d_name) != HASH_LEN) continue; */ + +/* under OS/2 use dirent's d_attr to identify a diretory */ +#ifdef OS2 +/* is it a directory? */ + if (ent->d_attr & A_DIR) { + 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); - if (fd == -1) - { - if (errno != ENOENT) proxy_log_uerror("open", filename,NULL, - r->server); + 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) - { - proxy_log_uerror("fstat", filename, NULL, r->server); + if (fstat(fd, &buf) == -1) { + ap_log_error(APLOG_MARK, APLOG_ERR, r->server, + "proxy gc: fstat(%s)", filename); close(fd); continue; } - if(S_ISDIR(buf.st_mode)) - { + +/* In OS/2 this has already been done above */ +#ifndef OS2 + 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); + "%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); + fprintf(stderr, "Would remove directory %s\n", newcachedir); #else rmdir(newcachedir); #endif --nfiles; - } - continue; + } else { + /* Directory is not empty. Account for its size: */ + add_long61(&curbytes, ROUNDUP2BLOCKS(buf.st_size)); } - - i = read(fd, line, 26); - if (i == -1) - { - proxy_log_uerror("read", filename, NULL, r->server); - close(fd); 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'; - expire = proxy_hex2sec(line+18); - if (!checkmask(line, "&&&&&&&& &&&&&&&& &&&&&&&&") || - expire == BAD_DATE) - { + garbage_expire = ap_proxy_hex2sec(line + 18); + if (!ap_checkmask(line, "&&&&&&&& &&&&&&&& &&&&&&&&") || + garbage_expire == BAD_DATE) { /* bad file */ - if (now != -1 && buf.st_atime > now + SEC_ONE_DAY && - buf.st_mtime > now + SEC_ONE_DAY) - { - log_error("proxy: deleting bad cache file", r->server); + 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); + fprintf(stderr, "Would unlink bad file %s\n", filename); #else unlink(filename); #endif @@ -312,23 +517,14 @@ static int sub_garbage_coll(request_rec *r,array_header *files, * file. * */ - /* FIXME: We should make the array an array of gc_ents, not gc_ent *s - */ - fent = palloc(r->pool, sizeof(struct gc_ent)); + fent = (struct gc_ent *) ap_push_array(files); fent->len = buf.st_size; - fent->expire = expire; - ap_snprintf(fent->file, sizeof(fent->file), "%s%s", cachesubdir, - ent->d_name); - *(struct gc_ent **)push_array(files) = fent; + fent->expire = garbage_expire; + strcpy(fent->file, cachesubdir); + strcat(fent->file, ent->d_name); /* accumulate in blocks, to cope with directories > 4Gb */ - curblocks += buf.st_size >> 10; /* Kbytes */ - curbytes += buf.st_size & 0x3FF; - if (curbytes >= 1024) - { - curbytes -= 1024; - curblocks++; - } + add_long61(&curbytes, ROUNDUP2BLOCKS(buf.st_size)); } closedir(dir); @@ -343,62 +539,64 @@ static int sub_garbage_coll(request_rec *r,array_header *files, * 0 on failure (bad file or wrong URL) * -1 on UNIX error */ -static int -rdcache(pool *pool, BUFF *cachefp, struct cache_req *c) +static int rdcache(request_rec *r, BUFF *cachefp, cache_req *c) { - char urlbuff[1034], *p; + 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 = bgets(urlbuff, 1034, cachefp); - if (len == -1) return -1; - if (len == 0 || urlbuff[len-1] != '\n') return 0; - urlbuff[len-1] = '\0'; + 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 (!checkmask(urlbuff, - "&&&&&&&& &&&&&&&& &&&&&&&& &&&&&&&& &&&&&&&&")) + if (!ap_checkmask(urlbuff, + "&&&&&&&& &&&&&&&& &&&&&&&& &&&&&&&& &&&&&&&&")) return 0; - c->date = proxy_hex2sec(urlbuff); - c->lmod = proxy_hex2sec(urlbuff+9); - c->expire = proxy_hex2sec(urlbuff+18); - c->version = proxy_hex2sec(urlbuff+27); - c->len = proxy_hex2sec(urlbuff+36); + 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 = bgets(urlbuff, 1034, cachefp); - if (len == -1) return -1; + 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') + urlbuff[len - 1] != '\n') + return 0; + urlbuff[len - 1] = '\0'; + if (strcmp(urlbuff + 7, c->url) != 0) return 0; - urlbuff[len-1] = '\0'; - if (strcmp(urlbuff+7, c->url) != 0) return 0; /* What follows is the message */ - len = bgets(urlbuff, 1034, cachefp); - if (len == -1) return -1; - if (len == 0 || urlbuff[len-1] != '\n') return 0; + 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 = pstrdup(pool, urlbuff); - p = strchr(urlbuff, ' '); - if (p == NULL) return 0; + c->resp_line = ap_pstrdup(r->pool, urlbuff); + strp = strchr(urlbuff, ' '); + if (strp == NULL) + return 0; - c->status = atoi(p); - c->hdrs = proxy_read_headers(pool, urlbuff, 1034, cachefp); - if (c->hdrs == NULL) return -1; - if (c->len != -1) /* add a content-length header */ - { - struct hdr_entry *q; - q = proxy_get_header(c->hdrs, "Content-Length"); - if (q == NULL) - { - p = palloc(pool, 15); - ap_snprintf(p, 15, "%u", c->len); - proxy_add_header(c->hdrs, "Content-Length", p, HDR_REP); + 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; @@ -419,110 +617,108 @@ rdcache(pool *pool, BUFF *cachefp, struct cache_req *c) * if last modified after if-modified-since then add * last modified date to request */ -int -proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf, - struct cache_req **cr) +int ap_proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf, + cache_req **cr) { - char hashfile[33], *imstr, *pragma, *p, *auth; - struct cache_req *c; + char hashfile[66]; + const char *imstr, *pragma, *auth; + cache_req *c; time_t now; BUFF *cachefp; int cfd, i; - const long int zero=0L; + const long int zero = 0L; void *sconf = r->server->module_config; proxy_server_conf *pconf = - (proxy_server_conf *)get_module_config(sconf, &proxy_module); + (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); - c = pcalloc(r->pool, sizeof(struct cache_req)); + c = ap_pcalloc(r->pool, sizeof(cache_req)); *cr = c; c->req = r; - c->url = pstrdup(r->pool, url); + c->url = ap_pstrdup(r->pool, url); /* get the If-Modified-Since date of the request */ c->ims = BAD_DATE; - imstr = table_get(r->headers_in, "If-Modified-Since"); - if (imstr != NULL) - { + imstr = ap_table_get(r->headers_in, "If-Modified-Since"); + if (imstr != NULL) { /* this may modify the value in the original table */ - imstr = proxy_date_canon(r->pool, imstr); - c->ims = parseHTTPdate(imstr); - if (c->ims == BAD_DATE) /* bad or out of range date; remove it */ - table_set(r->headers_in, "If-Modified-Since", NULL); + 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 */ - proxy_hash(url, hashfile,pconf->cache.dirlevels,pconf->cache.dirlength); + ap_proxy_hash(url, hashfile, pconf->cache.dirlevels, pconf->cache.dirlength); if (conf->root != NULL) - c->filename = pstrcat(r->pool, conf->root, "/", hashfile, 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 = table_get(r->headers_in, "Pragma"); - auth = table_get(r->headers_in, "Authorization"); - Explain5("Request for %s, pragma=%s, auth=%s, ims=%ld, imstr=%s",url, - pragma,auth,c->ims,imstr); + 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 && !proxy_liststr(pragma, "no-cache") && - auth == NULL) - { - Explain1("Check file %s",c->filename); - cfd = open(c->filename, O_RDWR); - if (cfd != -1) - { - note_cleanups_for_fd(r->pool, cfd); - cachefp = bcreate(r->pool, B_RD | B_WR); - bpushfd(cachefp, cfd, cfd); - } else if (errno != ENOENT) - proxy_log_uerror("open", c->filename, - "proxy: error opening cache file", r->server); + 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); + Explain1("File %s not found", c->filename); #endif } - - if (cachefp != NULL) - { - i = rdcache(r->pool, cachefp, c); + + if (cachefp != NULL) { + i = rdcache(r, cachefp, c); if (i == -1) - proxy_log_uerror("read", c->filename, - "proxy: error reading cache file", r->server); + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "proxy: error reading cache file %s", + c->filename); else if (i == 0) - log_error("proxy: bad cache file", r->server); - if (i != 1) - { - pclosef(r->pool, cachefp->fd); + 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, cachefp->fd); 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 = make_array(r->pool, 2, sizeof(struct hdr_entry)); + 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"); + 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) - { + 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) - { + if (c->date == BAD_DATE || c->date > c->ims) { /* No, but these header values may have changed, so we send them with the - * 304 response + * 304 HTTP_NOT_MODIFIED response */ - /* CHECKME: surely this was wrong? (Ben) - p = table_get(r->headers_in, "Expires"); - */ - p = table_get(c->hdrs, "Expires"); - if (p != NULL) table_set(r->headers_out, "Expires", p); + const char *q; + + if ((q = ap_table_get(c->hdrs, "Expires")) != NULL) + ap_table_set(r->headers_out, "Expires", q); } - pclosef(r->pool, cachefp->fd); + ap_pclosef(r->pool, cachefp->fd); Explain0("Use local copy, cached file hasn't changed"); - return USE_LOCAL_COPY; + return HTTP_NOT_MODIFIED; } /* Ok, has been modified */ @@ -530,14 +726,15 @@ proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf, r->status_line = strchr(c->resp_line, ' ') + 1; r->status = c->status; if (!r->assbackwards) { - soft_timeout("proxy send headers", r); - proxy_send_headers(r->connection->client, c->resp_line, c->hdrs); - kill_timeout(r); + ap_soft_timeout("proxy send headers", r); + ap_proxy_send_headers(r, c->resp_line, c->hdrs); + ap_kill_timeout(r); } - bsetopt(r->connection->client, BO_BYTECT, &zero); + ap_bsetopt(r->connection->client, BO_BYTECT, &zero); r->sent_bodyct = 1; - if (!r->header_only) proxy_send_fb (cachefp, r, NULL, NULL); - pclosef(r->pool, cachefp->fd); + if (!r->header_only) + ap_proxy_send_fb(cachefp, r, NULL); + ap_pclosef(r->pool, cachefp->fd); return OK; } @@ -545,21 +742,17 @@ proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf, * request, then add an If-Modified-Since */ - if (cachefp != NULL && c->lmod != BAD_DATE && !r->header_only) - { + 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) - { - struct hdr_entry *q; - - q = proxy_get_header(c->hdrs, "Last-Modified"); + if (c->ims == BAD_DATE || c->ims < c->lmod) { + const char *q; - if (q != NULL && q->value != NULL) - table_set(r->headers_in, "If-Modified-Since", - (char *)q->value); + if ((q = ap_table_get(c->hdrs, "Last-Modified")) != NULL) + ap_table_set(r->headers_in, "If-Modified-Since", + (char *) q); } } c->fp = cachefp; @@ -581,20 +774,22 @@ proxy_cache_check(request_rec *r, char *url, struct cache_conf *conf, * from the cache, maybe updating the header line * otherwise, delete the old cached file and open a new temporary file */ -int -proxy_cache_update(struct cache_req *c, array_header *resp_hdrs, - const int is_HTTP1, int nocache) +int ap_proxy_cache_update(cache_req *c, table *resp_hdrs, + const int is_HTTP1, int nocache) { - request_rec *r=c->req; +#ifdef ULTRIX_BRAIN_DEATH + extern char *mktemp(char *template); +#endif + request_rec *r = c->req; char *p; int i; - struct hdr_entry *expire, *dates, *lmods, *clen; + 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 *)get_module_config(sconf, &proxy_module); - const long int zero=0L; + (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); + const long int zero = 0L; c->tempfile = NULL; @@ -602,73 +797,75 @@ proxy_cache_update(struct cache_req *c, array_header *resp_hdrs, /* read expiry date; if a bad date, then leave it so the client can * read it */ - expire = proxy_get_header(resp_hdrs, "Expires"); - if (expire != NULL) expc = parseHTTPdate(expire->value); - else expc = BAD_DATE; + 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 = proxy_get_header(resp_hdrs, "Last-Modified"); - if (lmods != NULL) - { - lmod = parseHTTPdate(lmods->value); - if (lmod == BAD_DATE) - { + lmods = ap_table_get(resp_hdrs, "Last-Modified"); + if (lmods != NULL) { + lmod = ap_parseHTTPdate(lmods); + if (lmod == BAD_DATE) { /* kill last modified date */ - lmods->value = NULL; lmods = NULL; } - } else + } + else lmod = BAD_DATE; /* * what responses should we not cache? * Unknown status responses and those known to be uncacheable - * 304 response when we have no valid cache file, or - * 200 response from HTTP/1.0 and up without a Last-Modified header, or + * 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) */ - if ((r->status != 200 && r->status != 301 && r->status != 304) || +/* @@@ XXX FIXME: is the test "r->status != HTTP_MOVED_PERMANENTLY" corerct? + * 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 == 304 && c->fp == NULL) || - (r->status == 200 && lmods == NULL && is_HTTP1) || + (r->status == HTTP_NOT_MODIFIED && (c == NULL || c->fp == NULL)) || + (r->status == HTTP_OK && lmods == NULL && is_HTTP1) || r->header_only || - table_get(r->headers_in, "Authorization") != NULL || - nocache) - { - Explain1("Response is not cacheable, unlinking %s",c->filename); + 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) - { - pclosef(r->pool, c->fp->fd); + if (c->fp != NULL) { + ap_pclosef(r->pool, c->fp->fd); c->fp = NULL; } /* delete the previously cached file */ - unlink(c->filename); - return DECLINED; /* send data to client but not cache */ + 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 = proxy_get_header(resp_hdrs, "Date"); - if (dates != NULL) date = parseHTTPdate(dates->value); - else date = BAD_DATE; - + 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 */ - { + 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 = abs(now); - p = gm_timestr_822(r->pool, now); - dates = proxy_add_header(resp_hdrs, "Date", p, HDR_REP); + date = now; + dates = ap_gm_timestr_822(r->pool, now); + ap_table_set(resp_hdrs, "Date", dates); Explain0("Added date header"); } @@ -677,21 +874,20 @@ proxy_cache_update(struct cache_req *c, array_header *resp_hdrs, /* if its in the future, then replace by date */ { lmod = date; - lmods->value = dates->value; + 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) - { + 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 = proxy_get_header(c->hdrs, "Expires"); - if (expire != NULL) expc = parseHTTPdate(expire->value); + 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 @@ -700,234 +896,243 @@ proxy_cache_update(struct cache_req *c, array_header *resp_hdrs, * 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 = abs(now) + (int)x; - } else - expc = abs(now) + conf->cache.defaultexpire; - Explain1("Expiry date calculated %ld",expc); + 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 = proxy_get_header(c->hdrs, "Content-Length"); - if (clen == NULL) c->len = -1; - else c->len = atoi(clen->value); + clen = ap_table_get(resp_hdrs, "Content-Length"); + if (clen == NULL) + c->len = -1; + else + c->len = atoi(clen); - proxy_sec2hex(date, buff); + ap_proxy_sec2hex(date, buff); buff[8] = ' '; - proxy_sec2hex(lmod, buff+9); + ap_proxy_sec2hex(lmod, buff + 9); buff[17] = ' '; - proxy_sec2hex(expc, buff+18); + ap_proxy_sec2hex(expc, buff + 18); buff[26] = ' '; - proxy_sec2hex(c->version++, buff+27); + ap_proxy_sec2hex(c->version++, buff + 27); buff[35] = ' '; - proxy_sec2hex(c->len, buff+36); + ap_proxy_sec2hex(c->len, buff + 36); buff[44] = '\n'; buff[45] = '\0'; /* if file not modified */ - if (r->status == 304) - { - if (c->ims != BAD_DATE && lmod != BAD_DATE && lmod <= c->ims) - { + 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(c->fp->fd, 0, SEEK_SET); + if (lmod != c->lmod || expc != c->expire || date != c->date) { + off_t curpos = lseek(c->fp->fd, 0, SEEK_SET); if (curpos == -1) - proxy_log_uerror("lseek", c->filename, - "proxy: error seeking on cache file",r->server); + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "proxy: error seeking on cache file %s", + c->filename); else if (write(c->fp->fd, buff, 35) == -1) - proxy_log_uerror("write", c->filename, - "proxy: error updating cache file", r->server); + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "proxy: error updating cache file %s", + c->filename); } - pclosef(r->pool, c->fp->fd); + ap_pclosef(r->pool, c->fp->fd); Explain0("Remote document not modified, use local copy"); /* CHECKME: Is this right? Shouldn't we check IMS again here? */ - return USE_LOCAL_COPY; - } else - { + 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) { - soft_timeout("proxy send headers", r); - proxy_send_headers(r->connection->client, c->resp_line, - c->hdrs); - kill_timeout(r); + ap_soft_timeout("proxy send headers", r); + ap_proxy_send_headers(r, c->resp_line, c->hdrs); + ap_kill_timeout(r); } - bsetopt(r->connection->client, BO_BYTECT, &zero); + ap_bsetopt(r->connection->client, BO_BYTECT, &zero); r->sent_bodyct = 1; - if (!r->header_only) proxy_send_fb (c->fp, r, NULL, NULL); + 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(c->fp->fd, 0, SEEK_SET); + if (lmod != c->lmod || expc != c->expire || date != c->date) { + off_t curpos = lseek(c->fp->fd, 0, SEEK_SET); if (curpos == -1) - proxy_log_uerror("lseek", c->filename, - "proxy: error seeking on cache file",r->server); + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "proxy: error seeking on cache file %s", + c->filename); else if (write(c->fp->fd, buff, 35) == -1) - proxy_log_uerror("write", c->filename, - "proxy: error updating cache file", r->server); + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, + "proxy: error updating cache file %s", + c->filename); } - pclosef(r->pool, c->fp->fd); + ap_pclosef(r->pool, c->fp->fd); return OK; } } -/* new or modified file */ - if (c->fp != NULL) - { - pclosef(r->pool, c->fp->fd); +/* new or modified file */ + if (c->fp != NULL) { + ap_pclosef(r->pool, c->fp->fd); c->fp->fd = -1; } c->version = 0; - proxy_sec2hex(0, buff+27); + ap_proxy_sec2hex(0, buff + 27); buff[35] = ' '; /* open temporary file */ #define TMPFILESTR "/tmpXXXXXX" if (conf->cache.root == NULL) - return DECLINED; - c->tempfile=palloc(r->pool,strlen(conf->cache.root)+sizeof(TMPFILESTR)); - strcpy(c->tempfile,conf->cache.root); - strcat(c->tempfile,TMPFILESTR); + 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); if (p == NULL) - return DECLINED; + return DECLINED; - Explain1("Create temporary file %s",c->tempfile); + Explain1("Create temporary file %s", c->tempfile); - i = open(c->tempfile, O_WRONLY | O_CREAT | O_EXCL, 0622); - if (i == -1) - { - proxy_log_uerror("open", c->tempfile, - "proxy: error creating cache file", r->server); + 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; } - note_cleanups_for_fd(r->pool, i); - c->fp = bcreate(r->pool, B_WR); - bpushfd(c->fp, -1, i); - - if (bvputs(c->fp, buff, "X-URL: ", c->url, "\n", NULL) == -1) - { - proxy_log_uerror("write", c->tempfile, - "proxy: error writing cache file", r->server); - pclosef(r->pool, c->fp->fd); + 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, c->fp->fd); unlink(c->tempfile); c->fp = NULL; } return DECLINED; } -void -proxy_cache_tidy(struct cache_req *c) +void ap_proxy_cache_tidy(cache_req *c) { - server_rec *s=c->req->server; + server_rec *s; long int bc; - if (c->fp == NULL) return; + if (c == NULL || c->fp == NULL) + return; - bgetopt(c->req->connection->client, BO_BYTECT, &bc); + s = c->req->server; - if (c->len != -1) - { +/* 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) - { - pclosef(c->req->pool, c->fp->fd); /* no need to flush */ + if (bc != c->len) { + ap_pclosef(c->req->pool, c->fp->fd); /* no need to flush */ unlink(c->tempfile); return; } - } else - if (c->req->connection->aborted) { - pclosef(c->req->pool, c->fp->fd); /* no need to flush */ - unlink(c->tempfile); - return; - } else - { + } +/* 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; - bflush(c->fp); - proxy_sec2hex(c->len, buff); + ap_bflush(c->fp); + ap_proxy_sec2hex(c->len, buff); curpos = lseek(c->fp->fd, 36, SEEK_SET); if (curpos == -1) - proxy_log_uerror("lseek", c->tempfile, - "proxy: error seeking on cache file", s); + ap_log_error(APLOG_MARK, APLOG_ERR, s, + "proxy: error seeking on cache file %s", c->tempfile); else if (write(c->fp->fd, buff, 8) == -1) - proxy_log_uerror("write", c->tempfile, - "proxy: error updating cache file", s); + ap_log_error(APLOG_MARK, APLOG_ERR, s, + "proxy: error updating cache file %s", c->tempfile); } - if (bflush(c->fp) == -1) - { - proxy_log_uerror("write", c->tempfile, - "proxy: error writing to cache file", s); - pclosef(c->req->pool, c->fp->fd); + 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, c->fp->fd); unlink(c->tempfile); return; } - if (pclosef(c->req->pool, c->fp->fd) == -1) - { - proxy_log_uerror("close", c->tempfile, - "proxy: error closing cache file", s); + if (ap_pclosef(c->req->pool, c->fp->fd) == -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) - { - proxy_log_uerror("unlink", c->filename, - "proxy: error deleting old cache file", s); - } else - { + 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 *)get_module_config(s->module_config,&proxy_module); + 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) + for (p = c->filename + strlen(conf->cache.root) + 1;;) { + p = strchr(p, '/'); + if (!p) break; - *p='\0'; - if(mkdir(c->filename,S_IREAD|S_IWRITE|S_IEXEC) < 0 && errno != EEXIST) - proxy_log_uerror("mkdir",c->filename, - "proxy: error creating cache directory",s); - *p='/'; + *p = '\0'; +#ifdef WIN32 + if (mkdir(c->filename) < 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; - } -#ifdef __EMX__ - /* Under OS/2 use rename. */ - if (rename(c->tempfile, c->filename) == -1) - proxy_log_uerror("rename", c->filename, - "proxy: error renaming cache file", s); -} -#else + } +#if defined(OS2) || defined(WIN32) + /* 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) - proxy_log_uerror("link", c->filename, - "proxy: error linking cache file", s); - } + 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) - proxy_log_uerror("unlink", c->tempfile, - "proxy: error deleting temp file",s); + ap_log_error(APLOG_MARK, APLOG_ERR, s, + "proxy: error deleting temp file %s", c->tempfile); #endif } - diff --git a/usr.sbin/httpd/src/modules/proxy/proxy_connect.c b/usr.sbin/httpd/src/modules/proxy/proxy_connect.c index ba120271b66..9a19313c828 100644 --- a/usr.sbin/httpd/src/modules/proxy/proxy_connect.c +++ b/usr.sbin/httpd/src/modules/proxy/proxy_connect.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1996,1997 The Apache Group. All rights reserved. + * 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 @@ -20,9 +20,14 @@ * * 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. + * prior written permission. For written permission, please contact + * apache@apache.org. * - * 5. Redistributions of any form whatsoever must retain the following + * 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/)." @@ -50,16 +55,18 @@ * */ -/* CONNECT method SSL handling for Apache proxy */ +/* CONNECT method for Apache proxy */ #include "mod_proxy.h" #include "http_log.h" #include "http_main.h" #ifdef HAVE_BSTRING_H -#include <bstring.h> /* for IRIX, FD_SET calls bzero() */ +#include <bstring.h> /* 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 @@ -69,6 +76,9 @@ * "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 @@ -79,150 +89,197 @@ * 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^) + * 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. - */ - -int -proxy_connect_handler(request_rec *r, struct cache_req *c, char *url) + */ + +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; + int port, sock; char buffer[HUGE_STRING_LEN]; - int nbytes, i, j; + int nbytes, i, j; fd_set fds; void *sconf = r->server->module_config; proxy_server_conf *conf = - (proxy_server_conf *)get_module_config(sconf, &proxy_module); - struct noproxy_entry *npent=(struct noproxy_entry *)conf->noproxies->elts; + (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; - + server.sin_family = AF_INET; + /* Break the URL into host:port pairs */ host = url; p = strchr(url, ':'); - if (p==NULL) + if (p == NULL) port = DEFAULT_HTTPS_PORT; - else - { - port = atoi(p+1); - *p='\0'; + else { + port = atoi(p + 1); + *p = '\0'; } - + /* check if ProxyBlock directive on this host */ - destaddr.s_addr = 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 proxyerror(r, "Connect to remote machine blocked"); + 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, "Connect to remote machine blocked"); } - switch (port) - { - case DEFAULT_HTTPS_PORT: - case DEFAULT_SNEWS_PORT: - break; - default: - return HTTP_SERVICE_UNAVAILABLE; + /* 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); - Explain2("CONNECT to %s on port %d", host, port); - - server.sin_port = htons(port); - err = proxy_host2addr(host, &server_hp); if (err != NULL) - return proxyerror(r, err); /* give up */ - - sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sock == -1) - { - log_error("proxy: error creating socket", r->server); - return SERVER_ERROR; - } - note_cleanups_for_fd(r->pool, sock); - + return ap_proxyerror(r, err); /* give up */ + + 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; + } + +#ifndef WIN32 + 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 = proxy_doconnect(sock, &server, r); - if (i == 0) - break; - j++; - } - if (i == -1 ) - return proxyerror(r, "Could not connect to remote machine"); - - Explain0("Returning 200 OK Status"); - - rvputs(r, "HTTP/1.0 200 Connection established\015\012", NULL); - rvputs(r, "Proxy-agent: ", SERVER_VERSION, "\015\012\015\012", NULL); - bflush(r->connection->client); - - while (1) /* Infinite loop until error (one side closes the connection) */ - { - FD_ZERO(&fds); - FD_SET(sock, &fds); - FD_SET(r->connection->client->fd, &fds); - - Explain0("Going to sleep (select)"); - i = select((r->connection->client->fd > sock ? - r->connection->client->fd+1 : -#ifdef HPUX - sock+1), (int*)&fds, NULL, NULL, NULL); -#else - sock+1), &fds, NULL, NULL, NULL); -#endif - 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(r->connection->client->fd, buffer, nbytes)==EOF) - break; - Explain1("Wrote %d bytes to client", nbytes); - } - else break; - } - else if (FD_ISSET(r->connection->client->fd, &fds)) - { - Explain0("client->fd was set"); - if((nbytes=read(r->connection->client->fd,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; + 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, ap_pstrcat(r->pool, + "Could not connect to remote machine:<br>", + strerror(errno), NULL)); } - pclosef(r->pool,sock); - - return OK; -} + /* 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(r->connection->client->fd, &fds); + + Explain0("Going to sleep (select)"); + i = ap_select((r->connection->client->fd > sock ? + r->connection->client->fd + 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(r->connection->client->fd, buffer, nbytes) == EOF) + break; + Explain1("Wrote %d bytes to client", nbytes); + } + else + break; + } + else if (FD_ISSET(r->connection->client->fd, &fds)) { + Explain0("client->fd was set"); + if ((nbytes = read(r->connection->client->fd, 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/usr.sbin/httpd/src/modules/proxy/proxy_ftp.c b/usr.sbin/httpd/src/modules/proxy/proxy_ftp.c index f460adf9a25..1cdade07730 100644 --- a/usr.sbin/httpd/src/modules/proxy/proxy_ftp.c +++ b/usr.sbin/httpd/src/modules/proxy/proxy_ftp.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1996,1997 The Apache Group. All rights reserved. + * 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 @@ -20,9 +20,14 @@ * * 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. + * prior written permission. For written permission, please contact + * apache@apache.org. * - * 5. Redistributions of any form whatsoever must retain the following + * 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/)." @@ -54,25 +59,26 @@ #include "mod_proxy.h" #include "http_main.h" +#include "http_log.h" + +#define AUTODETECT_PWD -extern int find_ct(request_rec *r); +DEF_Explain /* * Decodes a '%' escaped string, and returns the number of characters */ -static int -decodeenc(char *x) +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++) - { + 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 == '%' && isxdigit(x[i+1]) && isxdigit(x[i+2])) - { - ch = proxy_hex2c(&x[i+1]); + if (ch == '%' && isxdigit(x[i + 1]) && isxdigit(x[i + 2])) { + ch = ap_proxy_hex2c(&x[i + 1]); i += 2; } x[j] = ch; @@ -85,20 +91,22 @@ decodeenc(char *x) * checks an encoded ftp string for bad characters, namely, CR, LF or * non-ascii character */ -static int -ftp_check_string(const char *x) +static int ftp_check_string(const char *x) { int i, ch; - for (i=0; x[i] != '\0'; i++) - { + for (i = 0; x[i] != '\0'; i++) { ch = x[i]; - if ( ch == '%' && isxdigit(x[i+1]) && isxdigit(x[i+2])) - { - ch = proxy_hex2c(&x[i+1]); + if (ch == '%' && isxdigit(x[i + 1]) && isxdigit(x[i + 2])) { + ch = ap_proxy_hex2c(&x[i + 1]); i += 2; } - if (ch == '\015' || ch == '\012' || (ch & 0x80)) return 0; +#ifndef CHARSET_EBCDIC + if (ch == '\015' || ch == '\012' || (ch & 0x80)) +#else /*CHARSET_EBCDIC*/ + if (ch == '\r' || ch == '\n' || (os_toascii[ch] & 0x80)) +#endif /*CHARSET_EBCDIC*/ + return 0; } return 1; } @@ -106,19 +114,21 @@ ftp_check_string(const char *x) /* * Canonicalise ftp URLs. */ -int -proxy_ftp_canon(request_rec *r, char *url) +int ap_proxy_ftp_canon(request_rec *r, char *url) { - char *user, *password, *host, *path, *parms, *p, sport[7]; - pool *pool=r->pool; + char *user, *password, *host, *path, *parms, *strp, sport[7]; + pool *p = r->pool; const char *err; int port; port = DEFAULT_FTP_PORT; - err = proxy_canon_netloc(pool, &url, &user, &password, &host, &port); - if (err) return BAD_REQUEST; - if (user != NULL && !ftp_check_string(user)) return BAD_REQUEST; - if (password != NULL && !ftp_check_string(password)) return BAD_REQUEST; + 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 @@ -126,46 +136,50 @@ proxy_ftp_canon(request_rec *r, char *url) * This gives rise to the problem of a ; being decoded into the * path. */ - p = strchr(url, ';'); - if (p != NULL) - { - *(p++) = '\0'; - parms = proxy_canonenc(pool, p, strlen(p), enc_parm, r->proxyreq); - if (parms == NULL) return BAD_REQUEST; - } else + 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 = proxy_canonenc(pool, url, strlen(url), enc_path, r->proxyreq); - if (path == NULL) return BAD_REQUEST; - if (!ftp_check_string(path)) return BAD_REQUEST; - - if (!r->proxyreq && r->args != NULL) - { - if (p != NULL) - { - p = proxy_canonenc(pool, r->args, strlen(r->args), enc_parm, 1); - if (p == NULL) return BAD_REQUEST; - parms = pstrcat(pool, parms, "?", p, NULL); + 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 && r->args != NULL) { + if (strp != NULL) { + strp = ap_proxy_canonenc(p, r->args, strlen(r->args), enc_parm, 1); + if (strp == NULL) + return HTTP_BAD_REQUEST; + parms = ap_pstrcat(p, parms, "?", strp, NULL); } - else - { - p = proxy_canonenc(pool, r->args, strlen(r->args), enc_fpath, 1); - if (p == NULL) return BAD_REQUEST; - path = pstrcat(pool, path, "?", p, NULL); + else { + strp = ap_proxy_canonenc(p, r->args, strlen(r->args), enc_fpath, 1); + 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'; + if (port != DEFAULT_FTP_PORT) + ap_snprintf(sport, sizeof(sport), ":%d", port); + else + sport[0] = '\0'; - r->filename = pstrcat(pool, "proxy:ftp://", (user != NULL) ? user : "", - (password != NULL) ? ":" : "", - (password != NULL) ? password : "", - (user != NULL) ? "@" : "", host, sport, "/", path, - (parms[0] != '\0') ? ";" : "", parms, NULL); + 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; } @@ -174,38 +188,35 @@ proxy_ftp_canon(request_rec *r, char *url) * Returns the ftp status code; * or -1 on I/O error, 0 on data error */ -static int -ftp_getrc(BUFF *f) +static int ftp_getrc(BUFF *f) { - int i, len, status; + int len, status; char linebuff[100], buff[5]; - len = bgets(linebuff, 100, f); - if (len == -1) return -1; + len = ap_bgets(linebuff, sizeof linebuff, f); + if (len == -1) + return -1; /* check format */ - if (len < 5 || !isdigit(linebuff[0]) || !isdigit(linebuff[1]) || - !isdigit(linebuff[2]) || (linebuff[3] != ' ' && linebuff[3] != '-')) + 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') - { - i = bskiplf(f); + if (linebuff[len - 1] != '\n') { + (void)ap_bskiplf(f); } -/* skip continuation lines */ - if (linebuff[3] == '-') - { +/* skip continuation lines */ + if (linebuff[3] == '-') { memcpy(buff, linebuff, 3); buff[3] = ' '; - do - { - len = bgets(linebuff, 100, f); - if (len == -1) return -1; - if (linebuff[len-1] != '\n') - { - i = bskiplf(f); + 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); } @@ -213,205 +224,247 @@ ftp_getrc(BUFF *f) return status; } -static char * -encode_space(request_rec *r, char *path) +/* + * 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) { - pool *pool=r->pool; - char *newpath; - int i, j, len; - - len = strlen(path); - newpath = palloc(pool, 3 * len + 1); - for (i=0, j=0; i < len; i++, j++) { - if (path[i] != ' ') - newpath[j] = path[i]; - else { - proxy_c2hex(' ', &newpath[j]); - j += 2; - } + 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); } - newpath[j] = '\0'; - return newpath; + return status; } -static long int -send_dir(BUFF *f, request_rec *r, BUFF *f2, struct cache_req *c, char *url) +static long int send_dir(BUFF *f, request_rec *r, cache_req *c, char *cwd) { char buf[IOBUFSIZE]; char buf2[IOBUFSIZE]; char *filename; - char *tempurl; - char *newurlptr; int searchidx = 0; char *searchptr = NULL; int firstfile = 1; - char urlptr[HUGE_STRING_LEN]; - long total_bytes_sent; + unsigned long total_bytes_sent = 0; register int n, o, w; conn_rec *con = r->connection; - - tempurl = pstrdup(r->pool, url); - if ((n = strcspn(tempurl, "@")) != strlen(tempurl)) /* hide user/passwd */ + 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 PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n" + "<HTML><HEAD><TITLE>%s%s</TITLE>\n" + "<BASE HREF=\"%s%s\"></HEAD>\n" + "<BODY><H2>Directory of " + "<A HREF=\"/\">%s</A>/", + site, path, site, path, site); + total_bytes_sent += ap_proxy_bputs2(buf, con->client, c); + + while ((dir = strchr(dir+1, '/')) != NULL) { - memmove(tempurl + (n - 5), tempurl, 6); - tempurl += n - 5; /* leave room for ftp:// */ + *dir = '\0'; + if ((reldir = strrchr(path+1, '/'))==NULL) + reldir = path+1; + else + ++reldir; + /* print "path/" component */ + ap_snprintf(buf, sizeof(buf), "<A HREF=\"/%s/\">%s</A>/", path+1, reldir); + total_bytes_sent += ap_proxy_bputs2(buf, con->client, c); + *dir = '/'; } - - n = decodeenc(tempurl); - ap_snprintf(buf, sizeof(buf), "<HTML><HEAD><TITLE>%s</TITLE></HEAD><BODY><H1>Directory %s</H1><HR><PRE>", tempurl, tempurl); - bwrite(con->client, buf, strlen(buf)); - if (f2 != NULL) bwrite(f2, buf, strlen(buf)); - total_bytes_sent=strlen(buf); - while(!con->aborted) - { - n = bgets(buf, IOBUFSIZE, f); - if (n == -1) /* input error */ - { - if (f2 != NULL) f2 = proxy_cache_error(c); - break; - } - if (n == 0) break; /* EOF */ - if(buf[0]=='l') - { - char *link; - - link=strstr(buf, " -> "); - filename=link; - do filename--; while (filename[0]!=' '); - *(filename++)=0; - *(link++)=0; - ap_snprintf(urlptr, sizeof(urlptr), "%s%s%s",url,(url[strlen(url)-1]=='/' ? "" : "/"), filename); - ap_snprintf(buf2, sizeof(urlptr), "%s <A HREF=\"%s\">%s %s</A>\015\012", buf, urlptr, filename, link); - strncpy(buf, buf2, sizeof(buf)-1); - buf[sizeof(buf)-1] = '\0'; - n=strlen(buf); - } - else if (strrchr(buf, ' ') && (buf[0]=='d' || buf[0]=='-' || - buf[0]=='l' || isdigit(buf[0])) ) { - if(isdigit(buf[0])) { /* handle DOS dir */ - searchptr = strchr(buf, '<'); - if(searchptr != NULL) + /* 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), "</H2>\n<HR><PRE>"); + } else { + ap_snprintf(buf, sizeof(buf), "</H2>\n(%s)\n<HR><PRE>", 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) + 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 <A HREF=\"%s\">%s %s</A>\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 = 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) { + 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, ".")) - { - ap_snprintf(urlptr, sizeof(urlptr), "%s",url); - ap_snprintf(buf2, sizeof(buf2), "%s <A HREF=\"%s\">%s</A>\015\012", buf, urlptr, filename); - } - else if (!strcmp(filename, "..")) - { - char temp[200]; - char newpath[200]; - char *method, *host, *path, *newfile; - - strncpy(temp, url, sizeof(temp)-1); - temp[sizeof(temp)-1] = '\0'; - method=temp; - - host=strchr(method,':'); - if (host == NULL) host=""; - else *(host++)=0; - host++; host++; - - path=strchr(host,'/'); - if (path == NULL) path=""; - else *(path++)=0; - - strncpy(newpath, path, sizeof(newpath)-1); - newpath[sizeof(newpath)-1] = '\0'; - newfile=strrchr(newpath,'/'); - if (newfile) *(newfile)=0; - else newpath[0]=0; - - ap_snprintf(urlptr, sizeof(urlptr), "%s://%s/%s",method,host,newpath); - ap_snprintf(buf2, sizeof(buf2), "%s <A HREF=\"%s\">%s</A>\015\012", buf, urlptr, filename); - } - else - { - ap_snprintf(urlptr, sizeof(urlptr), "%s%s%s",url,(url[strlen(url)-1]=='/' ? "" : "/"), filename); - newurlptr = encode_space(r, urlptr); - ap_snprintf(buf2, sizeof(buf2), "%s <A HREF=\"%s\">%s</A>\015\012", buf, newurlptr, filename); - } - strncpy(buf, buf2, sizeof(buf)); - buf[sizeof(buf)-1] = '\0'; - n=strlen(buf); - } - - o=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 <A HREF=\"%s/\">%s</A>\n", + buf, filename, filename); + } + else { + ap_snprintf(buf2, sizeof(buf2), "%s <A HREF=\"%s\">%s</A>\n", buf, filename, filename); + } + ap_cpystrn(buf, buf2, sizeof(buf)); + n = strlen(buf); + } + + o = 0; total_bytes_sent += n; - if (f2 != NULL) - if (bwrite(f2, buf, n) != n) f2 = proxy_cache_error(c); - - while(n && !r->connection->aborted) { - w = bwrite(con->client, &buf[o], n); + if (c != NULL && c->fp && ap_bwrite(c->fp, buf, n) != n) + c = ap_proxy_cache_error(c); + + while (n && !r->connection->aborted) { + w = ap_bwrite(con->client, &buf[o], n); if (w <= 0) break; - reset_timeout(r); /* reset timeout after successfule write */ - n-=w; - o+=w; - } - } - bputs("</PRE><HR></BODY></HTML>\015\012", con->client); - if (f2 != NULL) { - bputs("</PRE><HR></BODY></HTML>\015\012", f2); - } - total_bytes_sent+=strlen(buf); - bflush(con->client); - + ap_reset_timeout(r); /* reset timeout after successfule write */ + n -= w; + o += w; + } + } + + total_bytes_sent += ap_proxy_bputs2("</PRE><HR>\n", con->client, c); + total_bytes_sent += ap_proxy_bputs2(ap_psignature("", r), con->client, c); + total_bytes_sent += ap_proxy_bputs2("</BODY></HTML>\n", con->client, c); + + ap_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 = 0; + /* 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 <spiffnet@zoom.com> * PASV added by Chuck */ -int -proxy_ftp_handler(request_rec *r, struct cache_req *c, char *url) +int ap_proxy_ftp_handler(request_rec *r, cache_req *c, char *url) { - char *host, *path, *p, *user, *password, *parms; + 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, userlen, i, j, len, sock, dsock, rc, nocache; - int passlen = 0; + int port, i, j, len, sock, dsock, rc, nocache = 0; int csd = 0; struct sockaddr_in server; struct hostent server_hp; - struct hdr_entry *hdr; struct in_addr destaddr; - array_header *resp_hdrs; - BUFF *f, *cache; + table *resp_hdrs; + BUFF *f; BUFF *data = NULL; - pool *pool=r->pool; - const int one=1; - const long int zero=0L; + 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 *)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; + (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; @@ -421,241 +474,318 @@ proxy_ftp_handler(request_rec *r, struct cache_req *c, char *url) 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 NOT_IMPLEMENTED; + if (r->method_number != M_GET) + return HTTP_NOT_IMPLEMENTED; /* We break the URL into host, port, path-search */ - host = pstrdup(pool, url + 6); - port = DEFAULT_FTP_PORT; - path = strchr(host, '/'); - if (path == NULL) - path = ""; - else - *(path++) = '\0'; - - user = password = NULL; - nocache = 0; - p = strchr(host, '@'); - if (p != NULL) - { - (*p++) = '\0'; - user = host; - host = p; -/* find password */ - p = strchr(user, ':'); - if (p != NULL) - { - *(p++) = '\0'; - password = p; - passlen = decodeenc(password); - } - userlen = decodeenc(user); - nocache = 1; /* don't cache when a username is supplied */ - } else - { + 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_uudecode(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"; - userlen = 9; - password = "apache_proxy@"; - passlen = strlen(password); - } - - p = strchr(host, ':'); - if (p != NULL) - { - *(p++) = '\0'; - if (isdigit(*p)) - port = atoi(p); } /* check if ProxyBlock directive on this host */ - destaddr.s_addr = 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 proxyerror(r, "Connect to remote machine blocked"); + 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); + Explain2("FTP: connect to %s:%d", host, port); parms = strchr(path, ';'); - if (parms != NULL) *(parms++) = '\0'; + if (parms != NULL) + *(parms++) = '\0'; memset(&server, 0, sizeof(struct sockaddr_in)); server.sin_family = AF_INET; server.sin_port = htons(port); - err = proxy_host2addr(host, &server_hp); - if (err != NULL) return proxyerror(r, err); /* give up */ + err = ap_proxy_host2addr(host, &server_hp); + if (err != NULL) + return ap_proxyerror(r, err); /* give up */ + + 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; + } - sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sock == -1) - { - proxy_log_uerror("socket", NULL, "proxy: error creating socket", - r->server); - return SERVER_ERROR; + 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"); } - note_cleanups_for_fd(pool, sock); - if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&one, - sizeof(int)) == -1) - { - proxy_log_uerror("setsockopt", NULL, - "proxy: error setting reuseaddr option", r->server); - pclosef(pool, sock); - return SERVER_ERROR; + 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 = proxy_doconnect(sock, &server, r); - if (i == 0) - break; - j++; - } - if (i == -1) - return proxyerror(r, "Could not connect to remote machine"); - - f = bcreate(pool, B_RDWR); - bpushfd(f, sock, sock); + 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? */ -/* possible results: 120, 220, 421 */ - hard_timeout ("proxy ftp", r); - i = ftp_getrc(f); +#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) { - kill_timeout(r); - return proxyerror(r, "Error reading from remote server"); + 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) { - kill_timeout(r); - return BAD_GATEWAY; + ap_kill_timeout(r); + return ap_proxyerror(r, /*HTTP_BAD_GATEWAY*/ resp); } Explain0("FTP: connected."); - bputs("USER ", f); - bwrite(f, user, userlen); - bputs("\015\012", f); - bflush(f); /* capture any errors */ - Explain1("FTP: USER %s",user); - + 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); + Explain1("FTP: returned status %d", i); if (i == -1) { - kill_timeout(r); - return proxyerror(r, "Error sending to remote server"); + ap_kill_timeout(r); + return ap_proxyerror(r, /*HTTP_BAD_GATEWAY*/ "Error reading from remote server"); } if (i == 530) { - kill_timeout(r); - return proxyerror(r, "Not logged in"); + ap_kill_timeout(r); + return ftp_unauthorized (r, 1); /* log it: user name guessing attempt? */ } if (i != 230 && i != 331) { - kill_timeout(r); - return BAD_GATEWAY; + ap_kill_timeout(r); + return HTTP_BAD_GATEWAY; } - - if (i == 331) /* send password */ - { - if (password == NULL) return FORBIDDEN; - bputs("PASS ", f); - bwrite(f, password, passlen); - bputs("\015\012", f); - bflush(f); - Explain1("FTP: PASS %s",password); + + 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); + Explain1("FTP: returned status %d", i); if (i == -1) { - kill_timeout(r); - return proxyerror(r, "Error sending to remote server"); + ap_kill_timeout(r); + return ap_proxyerror(r, /*HTTP_BAD_GATEWAY*/ "Error reading from remote server"); } if (i == 332) { - kill_timeout(r); - return proxyerror(r, "Need account for login"); + 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) { - kill_timeout(r); - return proxyerror(r, "Not logged in"); + ap_kill_timeout(r); + return ftp_unauthorized (r, 1); /* log it: passwd guessing attempt? */ } if (i != 230 && i != 202) { - kill_timeout(r); - return BAD_GATEWAY; + ap_kill_timeout(r); + return HTTP_BAD_GATEWAY; } - } + } -/* set the directory */ -/* this is what we must do if we don't know the OS type of the remote +/* 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 (;;) - { - p = strchr(path, '/'); - if (p == NULL) break; - *p = '\0'; + for (;;) { + strp = strchr(path, '/'); + if (strp == NULL) + break; + *strp = '\0'; len = decodeenc(path); - bputs("CWD ", f); - bwrite(f, path, len); - bputs("\015\012", f); - bflush(f); - Explain1("FTP: CWD %s",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 */ -/* 1,3 error, 2 success, 4,5 failure */ + /* 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); + Explain1("FTP: returned status %d", i); if (i == -1) { - kill_timeout(r); - return proxyerror(r, "Error sending to remote server"); + ap_kill_timeout(r); + return ap_proxyerror(r, /*HTTP_BAD_GATEWAY*/ "Error reading from remote server"); } if (i == 550) { - kill_timeout(r); - return NOT_FOUND; + ap_kill_timeout(r); + return HTTP_NOT_FOUND; } if (i != 250) { - kill_timeout(r); - return BAD_GATEWAY; + ap_kill_timeout(r); + return HTTP_BAD_GATEWAY; } - path = p + 1; + path = strp + 1; } - if (parms != NULL && strncmp(parms, "type=", 5) == 0) - { + if (parms != NULL && strncmp(parms, "type=", 5) == 0) { parms += 5; if ((parms[0] != 'd' && parms[0] != 'a' && parms[0] != 'i') || - parms[1] != '\0') parms = ""; + parms[1] != '\0') + parms = ""; } - else parms = ""; + else + parms = ""; /* changed to make binary transfers the default */ - if (parms[0] != 'a') - { + if (parms[0] != 'a') { /* set type to image */ - /* TM - Added \015\012 to the end of TYPE I, otherwise it hangs the - connection */ - bputs("TYPE I\015\012", f); - bflush(f); - Explain0("FTP: TYPE I"); + /* TM - Added \015\012 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); + Explain1("FTP: returned status %d", i); if (i == -1) { - kill_timeout(r); - return proxyerror(r, "Error sending to remote server"); + ap_kill_timeout(r); + return ap_proxyerror(r, /*HTTP_BAD_GATEWAY*/ "Error reading from remote server"); } if (i != 200 && i != 504) { - kill_timeout(r); - return BAD_GATEWAY; + ap_kill_timeout(r); + return HTTP_BAD_GATEWAY; } /* Allow not implemented */ if (i == 504) @@ -663,41 +793,55 @@ proxy_ftp_handler(request_rec *r, struct cache_req *c, char *url) } /* try to set up PASV data connection first */ - dsock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (dsock == -1) - { - proxy_log_uerror("socket", NULL, "proxy: error creating PASV socket", - r->server); - pclosef(pool, sock); - kill_timeout(r); - return SERVER_ERROR; - } - note_cleanups_for_fd(pool, dsock); - - bputs("PASV\015\012", f); - bflush(f); + 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; + } + + 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"); + } + } + + ap_bputs("PASV" CRLF, f); + ap_bflush(f); Explain0("FTP: PASV command issued"); /* possible results: 227, 421, 500, 501, 502, 530 */ - i = bgets(pasv, sizeof(pasv), f); - - if (i == -1) - { - proxy_log_uerror("command", NULL, "PASV: control connection is toast", - r->server); - pclosef(pool, dsock); - pclosef(pool, sock); - kill_timeout(r); - return SERVER_ERROR; - } else - { - pasv[i-1] = '\0'; + /* 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) - { + if (pstr != NULL) { presult = atoi(pstr); - pstr = strtok(NULL, "("); /* separate address & port params */ - if (pstr != NULL) - pstr = strtok(NULL, ")"); + 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); @@ -705,311 +849,405 @@ proxy_ftp_handler(request_rec *r, struct cache_req *c, char *url) 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)) - { + "%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; + 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 = proxy_doconnect(dsock, &data_addr, r); + 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) { - kill_timeout(r); - return proxyerror(r, "Could not connect to remote machine"); + 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 { - data = bcreate(pool, B_RDWR); - bpushfd(data, dsock, dsock); - pasvmode = 1; + pasvmode = 1; } - } else - pclosef(pool, dsock); /* and try the regular way */ + } + else + ap_pclosesocket(p, dsock); /* and try the regular way */ } - if (!pasvmode) /* set up data connection */ - { - len = sizeof(struct sockaddr_in); - if (getsockname(sock, (struct sockaddr *)&server, &len) < 0) - { - proxy_log_uerror("getsockname", NULL, - "proxy: error getting socket address", r->server); - pclosef(pool, sock); - kill_timeout(r); - return SERVER_ERROR; - } - - dsock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (dsock == -1) - { - proxy_log_uerror("socket", NULL, "proxy: error creating socket", - r->server); - pclosef(pool, sock); - kill_timeout(r); - return SERVER_ERROR; - } - note_cleanups_for_fd(pool, dsock); - - if (setsockopt(dsock, SOL_SOCKET, SO_REUSEADDR, (const char *)&one, - sizeof(int)) == -1) - { - proxy_log_uerror("setsockopt", NULL, - "proxy: error setting reuseaddr option", r->server); - pclosef(pool, dsock); - pclosef(pool, sock); - kill_timeout(r); - return SERVER_ERROR; - } - - if (bind(dsock, (struct sockaddr *)&server, - sizeof(struct sockaddr_in)) == -1) - { + 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); - proxy_log_uerror("bind", buff, - "proxy: error binding to ftp data socket", r->server); - pclosef(pool, sock); - pclosef(pool, dsock); - } - listen(dsock, 2); /* only need a short queue */ + 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 */ +/* 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 - { - bputs("SIZE ", f); - bwrite(f, path, len); - bputs("\015\012", f); - bflush(f); - Explain1("FTP: SIZE %s",path); - i = ftp_getrc(f); - Explain1("FTP: returned status %d", i); - if (i != 500) /* Size command not recognized */ - { - if (i==550) /* Not a regular file */ - { - Explain0("FTP: SIZE shows this is a directory"); - parms="d"; - bputs("CWD ", f); - bwrite(f, path, len); - bputs("\015\012", f); - bflush(f); - Explain1("FTP: CWD %s",path); - i = ftp_getrc(f); - Explain1("FTP: returned status %d", i); - if (i == -1) { - kill_timeout(r); - return proxyerror(r, "Error sending to remote server"); - } - if (i == 550) { - kill_timeout(r); - return NOT_FOUND; - } - if (i != 250) { - kill_timeout(r); - return BAD_GATEWAY; - } - path=""; len=0; - } - } - } - - if (parms[0] == 'd') - { - if (len != 0) bputs("LIST ", f); - else bputs("LIST -lag", f); - Explain1("FTP: LIST %s",(len==0 ? "" : path)); + if (len == 0) { + parms = "d"; } - else - { - bputs("RETR ", f); - Explain1("FTP: RETR %s",path); + 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); + } + } } - bwrite(f, path, len); - bputs("\015\012", f); - bflush(f); + +#ifdef AUTODETECT_PWD + ap_bvputs(f, "PWD", CRLF, NULL); + ap_bflush(f); + Explain0("FTP: PWD"); +/* responses: 257, 500, 501, 502, 421, 550 */ + /* 257 "<directory-name>" <commentary> */ + /* 421 Service not available, closing control connection. */ + /* 500 Syntax error, command unrecognized. */ + /* 501 Syntax error in parameters or arguments. */ + /* 502 Command not implemented. */ + /* 550 Requested action not taken. */ + i = ftp_getrc_msg(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); + Explain1("FTP: returned status %d", rc); if (rc == -1) { - kill_timeout(r); - return proxyerror(r, "Error sending to remote server"); + 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"; - bputs("CWD ", f); - bwrite(f, path, len); - bputs("\015\012", f); - bflush(f); - Explain1("FTP: CWD %s", path); - rc = ftp_getrc(f); - Explain1("FTP: returned status %d", rc); - if (rc == -1) { - kill_timeout(r); - return proxyerror(r, "Error sending to remote server"); - } - if (rc == 550) { - kill_timeout(r); - return NOT_FOUND; - } - if (rc != 250) { - kill_timeout(r); - return BAD_GATEWAY; - } - - bputs("LIST -lag\015\012", f); - bflush(f); - Explain0("FTP: LIST -lag"); - rc = ftp_getrc(f); - Explain1("FTP: returned status %d", rc); - if (rc == -1) return proxyerror(r, "Error sending to remote server"); - } - kill_timeout(r); - if (rc != 125 && rc != 150 && rc != 226 && rc != 250) return BAD_GATEWAY; - - r->status = 200; + 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 "<directory-name>" <commentary> */ + /* 421 Service not available, closing control connection. */ + /* 500 Syntax error, command unrecognized. */ + /* 501 Syntax error in parameters or arguments. */ + /* 502 Command not implemented. */ + /* 550 Requested action not taken. */ + i = ftp_getrc_msg(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 = make_array(pool, 2, sizeof(struct hdr_entry)); + resp_hdrs = ap_make_table(p, 2); + c->hdrs = resp_hdrs; + if (parms[0] == 'd') - proxy_add_header(resp_hdrs, "Content-Type", "text/html", HDR_REP); - else - { - find_ct(r); - if(r->content_type != NULL) - { - proxy_add_header(resp_hdrs, "Content-Type", r->content_type, - HDR_REP); - Explain1("FTP: Content-Type set to %s",r->content_type); - } else - { - proxy_add_header(resp_hdrs, "Content-Type", "text/plain", HDR_REP); + ap_table_set(resp_hdrs, "Content-Type", "text/html"); + else { + if (r->content_type != NULL) { + ap_table_set(resp_hdrs, "Content-Type", r->content_type); + Explain1("FTP: Content-Type set to %s", r->content_type); + } + else { + ap_table_set(resp_hdrs, "Content-Type", "text/plain"); + } + 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); } } -/* 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; +/* 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 = proxy_cache_update(c, resp_hdrs, 0, nocache); + i = ap_proxy_cache_update(c, resp_hdrs, 0, nocache); - if (i != DECLINED) - { - pclosef(pool, dsock); - pclosef(pool, sock); + if (i != DECLINED) { + ap_pclosesocket(p, dsock); + ap_bclose(f); return i; } - cache = c->fp; - if (!pasvmode) /* wait for connection */ - { - hard_timeout ("proxy ftp data connect", r); - len = sizeof(struct sockaddr_in); - do csd = accept(dsock, (struct sockaddr *)&server, &len); - while (csd == -1 && errno == EINTR); - if (csd == -1) - { - proxy_log_uerror("accept", NULL, - "proxy: failed to accept data connection", r->server); - pclosef(pool, dsock); - pclosef(pool, sock); - kill_timeout(r); - proxy_cache_error(c); - return BAD_GATEWAY; - } - note_cleanups_for_fd(pool, csd); - data = bcreate(pool, B_RDWR); - bpushfd(data, csd, -1); - kill_timeout(r); - } - - hard_timeout ("proxy receive", r); + 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); + } + +#ifdef CHARSET_EBCDIC +/* bsetflag(data, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 0);*/ +#endif /*CHARSET_EBCDIC*/ + + ap_hard_timeout("proxy receive", r); /* send response */ /* write status line */ if (!r->assbackwards) - rvputs(r, "HTTP/1.0 ", r->status_line, "\015\012", NULL); - if (cache != NULL) - if (bvputs(cache, "HTTP/1.0 ", r->status_line, "\015\012", - NULL) == -1) - cache = proxy_cache_error(c); + 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) + c = ap_proxy_cache_error(c); /* send headers */ - len = resp_hdrs->nelts; - hdr = (struct hdr_entry *)resp_hdrs->elts; - for (i=0; i < len; i++) - { - if (hdr[i].field == NULL || hdr[i].value == NULL || - hdr[i].value[0] == '\0') continue; - if (!r->assbackwards) - rvputs(r, hdr[i].field, ": ", hdr[i].value, "\015\012", NULL); - if (cache != NULL) - if (bvputs(cache, hdr[i].field, ": ", hdr[i].value, "\015\012", - NULL) == -1) - cache = proxy_cache_error(c); - } + tdo.req = r; + tdo.cache = c; + ap_table_do(ap_proxy_send_hdr_line, &tdo, resp_hdrs, NULL); - if (!r->assbackwards) rputs("\015\012", r); - if (cache != NULL) - if (bputs("\015\012", cache) == -1) cache = proxy_cache_error(c); + if (!r->assbackwards) + ap_rputs(CRLF, r); + if (c != NULL && c->fp != NULL && ap_bputs(CRLF, c->fp) == -1) + c = ap_proxy_cache_error(c); - bsetopt(r->connection->client, BO_BYTECT, &zero); + ap_bsetopt(r->connection->client, BO_BYTECT, &zero); r->sent_bodyct = 1; /* send body */ - if (!r->header_only) - { - if (parms[0] != 'd') proxy_send_fb(data, r, cache, c); - else send_dir(data, r, cache, c, url); + 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); - if (rc == 125 || rc == 150) rc = ftp_getrc(f); - if (rc != 226 && rc != 250) proxy_cache_error(c); + /* XXX: we checked for 125||150||226||250 above. This is redundant. */ + if (rc != 226 && rc != 250) + c = ap_proxy_cache_error(c); } - else - { + else { /* abort the transfer */ - bputs("ABOR\015\012", f); - bflush(f); + ap_bputs("ABOR" CRLF, f); + ap_bflush(f); if (!pasvmode) - pclosef(pool, csd); - Explain0("FTP: ABOR"); + 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); + Explain1("FTP: returned status %d", i); } - kill_timeout(r); - proxy_cache_tidy(c); + ap_kill_timeout(r); + ap_proxy_cache_tidy(c); /* finish */ - bputs("QUIT\015\012", f); - bflush(f); + ap_bputs("QUIT" CRLF, f); + ap_bflush(f); Explain0("FTP: QUIT"); -/* responses: 221, 500 */ +/* 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) - pclosef(pool, csd); - pclosef(pool, dsock); - pclosef(pool, sock); + if (pasvmode) + ap_bclose(data); + ap_bclose(f); - proxy_garbage_coll(r); + ap_rflush(r); /* flush before garbage collection */ + + ap_proxy_garbage_coll(r); return OK; } - diff --git a/usr.sbin/httpd/src/modules/proxy/proxy_http.c b/usr.sbin/httpd/src/modules/proxy/proxy_http.c index 1144564ee57..2447b96aefe 100644 --- a/usr.sbin/httpd/src/modules/proxy/proxy_http.c +++ b/usr.sbin/httpd/src/modules/proxy/proxy_http.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1996,1997 The Apache Group. All rights reserved. + * 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 @@ -20,9 +20,14 @@ * * 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. + * prior written permission. For written permission, please contact + * apache@apache.org. * - * 5. Redistributions of any form whatsoever must retain the following + * 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/)." @@ -55,6 +60,7 @@ #include "mod_proxy.h" #include "http_log.h" #include "http_main.h" +#include "http_core.h" #include "util_date.h" /* @@ -63,10 +69,9 @@ * url is the URL starting with the first '/' * def_port is the default port for this scheme. */ -int -proxy_http_canon(request_rec *r, char *url, const char *scheme, int def_port) +int ap_proxy_http_canon(request_rec *r, char *url, const char *scheme, int def_port) { - char *host, *path, *search, *p, sport[7]; + char *host, *path, *search, sport[7]; const char *err; int port; @@ -74,58 +79,81 @@ proxy_http_canon(request_rec *r, char *url, const char *scheme, int def_port) * We break the URL into host, port, path, search */ port = def_port; - err = proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port); - if (err) return BAD_REQUEST; + 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 + * has already been decoded. True proxy requests have r->uri + * == r->unparsed_uri, and no others have that property. */ - if (r->proxyreq) - { - p = strchr(url, '?'); - if (p != NULL) *(p++) = '\0'; - } else - p = r->args; + if (r->uri == r->unparsed_uri) { + search = strchr(url, '?'); + if (search != NULL) + *(search++) = '\0'; + } + else + search = r->args; /* process path */ - path = proxy_canonenc(r->pool, url, strlen(url), enc_path, r->proxyreq); - if (path == NULL) return BAD_REQUEST; + path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, r->proxyreq); + if (path == NULL) + return HTTP_BAD_REQUEST; -/* process search */ - if (p != NULL) - { - search = p; - if (search == NULL) return BAD_REQUEST; - } else - search = NULL; - - if (port != def_port) ap_snprintf(sport, sizeof(sport), ":%d", port); - else sport[0] = '\0'; + if (port != def_port) + ap_snprintf(sport, sizeof(sport), ":%d", port); + else + sport[0] = '\0'; - r->filename = pstrcat(r->pool, "proxy:", scheme, "://", host, sport, "/", - path, (search) ? "?" : "", (search) ? search : "", NULL); + 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 (table *headers) +static void clear_connection(pool *p, table *headers) { - char *name; - char *next = table_get(headers, "Connection"); + const char *name; + char *next = ap_pstrdup(p, ap_table_get(headers, "Connection")); - if (!next) return; + ap_table_unset(headers, "Proxy-Connection"); + if (!next) + return; while (*next) { - name = next; - while (*next && !isspace(*next) && (*next != ',')) ++next; - while (*next && (isspace(*next) || (*next == ','))) { - *next = '\0'; - ++next; - } - table_unset(headers, name); + name = next; + while (*next && !ap_isspace(*next) && (*next != ',')) + ++next; + while (*next && (ap_isspace(*next) || (*next == ','))) { + *next = '\0'; + ++next; + } + ap_table_unset(headers, name); } - table_unset(headers, "Connection"); + ap_table_unset(headers, "Connection"); } /* @@ -137,32 +165,35 @@ static void clear_connection (table *headers) * we return DECLINED so that we can try another proxy. (Or the direct * route.) */ -int -proxy_http_handler(request_rec *r, struct cache_req *c, char *url, - const char *proxyhost, int proxyport) +int ap_proxy_http_handler(request_rec *r, cache_req *c, char *url, + const char *proxyhost, int proxyport) { - char *p; + const char *strp; + char *strp2; const char *err, *desthost; int i, j, sock, len, backasswards; - array_header *reqhdrs_arr, *resp_hdrs; + array_header *reqhdrs_arr; + table *resp_hdrs; table_entry *reqhdrs; struct sockaddr_in server; struct in_addr destaddr; struct hostent server_hp; - BUFF *f, *cache; - struct hdr_entry *hdr; + BUFF *f; char buffer[HUGE_STRING_LEN]; - pool *pool=r->pool; - const long int zero=0L; + char portstr[32]; + pool *p = r->pool; + const long int zero = 0L; int destport = 0; char *destportstr = NULL; - char *urlptr = 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 *)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; + (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)); @@ -170,134 +201,190 @@ proxy_http_handler(request_rec *r, struct cache_req *c, char *url, /* We break the URL into host, port, path-search */ - urlptr = strstr(url,"://"); - if (urlptr == NULL) return BAD_REQUEST; + urlptr = strstr(url, "://"); + if (urlptr == NULL) + return HTTP_BAD_REQUEST; urlptr += 3; - destport = DEFAULT_PORT; - p = strchr(urlptr, '/'); - if (p == NULL) - { - desthost = pstrdup(pool, urlptr); - urlptr = "/"; - } else - { - char *q = palloc(pool, p-urlptr+1); - memcpy(q, urlptr, p-urlptr); - q[p-urlptr] = '\0'; - urlptr = p; - desthost = q; + 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; } - p = strchr(desthost, ':'); - if (p != NULL) - { - *(p++) = '\0'; - if (isdigit(*p)) - { - destport = atoi(p); - destportstr = p; + 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 = 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 proxyerror(r, "Connect to remote machine blocked"); + 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, "Connect to remote machine blocked"); } - if (proxyhost != NULL) - { + if (proxyhost != NULL) { server.sin_port = htons(proxyport); - err = proxy_host2addr(proxyhost, &server_hp); - if (err != NULL) return DECLINED; /* try another */ - } else - { + err = ap_proxy_host2addr(proxyhost, &server_hp); + if (err != NULL) + return DECLINED; /* try another */ + } + else { server.sin_port = htons(destport); - err = proxy_host2addr(desthost, &server_hp); - if (err != NULL) return proxyerror(r, err); /* give up */ + err = ap_proxy_host2addr(desthost, &server_hp); + if (err != NULL) + return ap_proxyerror(r, err); /* give up */ } - sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sock == -1) - { - log_error("proxy: error creating socket", r->server); - return SERVER_ERROR; + 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; } - note_cleanups_for_fd(pool, sock); - + 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"); + } + } + +#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 = proxy_doconnect(sock, &server, r); + sizeof(struct in_addr)); + i = ap_proxy_doconnect(sock, &server, r); if (i == 0) break; j++; } - if (i == -1) - { - if (proxyhost != NULL) return DECLINED; /* try again another way */ - else return proxyerror(r, "Could not connect to remote machine"); +#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->headers_in); /* Strip connection-based headers */ + clear_connection(r->pool, r->headers_in); /* Strip connection-based headers */ - f = bcreate(pool, B_RDWR); - bpushfd(f, sock, sock); + f = ap_bcreate(p, B_RDWR | B_SOCKET); + ap_bpushfd(f, sock, sock); - hard_timeout ("proxy send", r); - bvputs(f, r->method, " ", proxyhost ? url : urlptr, " HTTP/1.0\015\012", - NULL); - bvputs(f, "Host: ", desthost, NULL); - if (destportstr != NULL && destport != DEFAULT_PORT) - bvputs(f, ":", destportstr, "\015\012", NULL); + 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 - bputs("\015\012", f); + 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 = table_elts (r->headers_in); - reqhdrs = (table_entry *)reqhdrs_arr->elts; - for (i=0; i < reqhdrs_arr->nelts; i++) - { + 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 - || !strcasecmp(reqhdrs[i].key, "Host")) /* already sent if there */ + /* 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; - bvputs(f, reqhdrs[i].key, ": ", reqhdrs[i].val, "\015\012", NULL); + ap_bvputs(f, reqhdrs[i].key, ": ", reqhdrs[i].val, CRLF, NULL); } - bputs("\015\012", f); + ap_bputs(CRLF, f); /* send the request data, if any. N.B. should we trap SIGPIPE ? */ - if (should_client_block(r)) - { - while ((i = get_client_block(r, buffer, HUGE_STRING_LEN)) > 0) - bwrite(f, buffer, i); + if (ap_should_client_block(r)) { + while ((i = ap_get_client_block(r, buffer, sizeof buffer)) > 0) + ap_bwrite(f, buffer, i); } - bflush(f); - kill_timeout(r); - - hard_timeout ("proxy receive", r); - - len = bgets(buffer, HUGE_STRING_LEN-1, f); - if (len == -1 || len == 0) - { - pclosef(pool, sock); - kill_timeout(r); - return proxyerror(r, "Error reading from remote server"); + ap_bflush(f); + ap_kill_timeout(r); + + ap_hard_timeout("proxy receive", r); + + len = ap_bgets(buffer, sizeof buffer - 1, f); + if (len == -1 || len == 0) { + 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", + proxyhost ? proxyhost : desthost); + return ap_proxyerror(r, "Error reading from remote server"); } /* Is it an HTTP/1 response? This is buggy if we ever see an HTTP/1.10 */ - if (checkmask(buffer, "HTTP/#.# ###*")) - { -/* If not an HTTP/1 messsage or if the status line was > 8192 bytes */ - if (buffer[5] != '1' || buffer[len-1] != '\n') - { - pclosef(pool, sock); - kill_timeout(r); - return BAD_GATEWAY; + 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'; @@ -305,109 +392,136 @@ proxy_http_handler(request_rec *r, struct cache_req *c, char *url, buffer[12] = '\0'; r->status = atoi(&buffer[9]); buffer[12] = ' '; - r->status_line = pstrdup(pool, &buffer[9]); + 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 = proxy_read_headers(pool, buffer, HUGE_STRING_LEN, f); + 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 */ + } - clear_connection((table *)resp_hdrs); /* Strip Connection hdrs */ + 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 - { + else { /* an http/0.9 response */ backasswards = 1; r->status = 200; r->status_line = "200 OK"; /* no headers */ - resp_hdrs = make_array(pool, 2, sizeof(struct hdr_entry)); + resp_hdrs = ap_make_table(p, 20); } - kill_timeout(r); + c->hdrs = resp_hdrs; + + ap_kill_timeout(r); /* * HTTP/1.0 requires us to accept 3 types of dates, but only generate * one type */ - - hdr = (struct hdr_entry *)resp_hdrs->elts; - for (i=0; i < resp_hdrs->nelts; i++) - { - if (hdr[i].value[0] == '\0') continue; - p = hdr[i].field; - if (strcasecmp(p, "Date") == 0 || - strcasecmp(p, "Last-Modified") == 0 || - strcasecmp(p, "Expires") == 0) - hdr[i].value = proxy_date_canon(pool, hdr[i].value); - } + 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; + 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 = proxy_cache_update(c, resp_hdrs, !backasswards, nocache); - if (i != DECLINED) - { - pclosef(pool, sock); + i = ap_proxy_cache_update(c, resp_hdrs, !backasswards, nocache); + if (i != DECLINED) { + ap_bclose(f); return i; } - cache = c->fp; - - hard_timeout ("proxy receive", r); + ap_hard_timeout("proxy receive", r); /* write status line */ if (!r->assbackwards) - rvputs(r, "HTTP/1.0 ", r->status_line, "\015\012", NULL); - if (cache != NULL) - if (bvputs(cache, "HTTP/1.0 ", r->status_line, "\015\012", NULL) == -1) - cache = proxy_cache_error(c); + 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) + c = ap_proxy_cache_error(c); /* send headers */ - for (i=0; i < resp_hdrs->nelts; i++) - { - if (hdr[i].field == NULL || hdr[i].value == NULL || - hdr[i].value[0] == '\0') continue; - if (!r->assbackwards) - rvputs(r, hdr[i].field, ": ", hdr[i].value, "\015\012", NULL); - if (cache != NULL) - if (bvputs(cache, hdr[i].field, ": ", hdr[i].value, "\015\012", - NULL) == -1) - cache = proxy_cache_error(c); - } + tdo.req = r; + tdo.cache = c; + ap_table_do(ap_proxy_send_hdr_line, &tdo, resp_hdrs, NULL); - if (!r->assbackwards) rputs("\015\012", r); - if (cache != NULL) - if (bputs("\015\012", cache) == -1) cache = proxy_cache_error(c); + if (!r->assbackwards) + ap_rputs(CRLF, r); + if (c != NULL && c->fp != NULL && ap_bputs(CRLF, c->fp) == -1) + c = ap_proxy_cache_error(c); - bsetopt(r->connection->client, BO_BYTECT, &zero); + 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) - { - bwrite(r->connection->client, buffer, len); - if (cache != NULL) - if (bwrite(f, buffer, len) != len) cache = proxy_cache_error(c); + if (backasswards) { + ap_bwrite(r->connection->client, buffer, len); + if (c != NULL && c->fp != NULL && ap_bwrite(c->fp, buffer, len) != len) + c = ap_proxy_cache_error(c); } - kill_timeout(r); + 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) proxy_send_fb(f, r, cache, c); + 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); + } - proxy_cache_tidy(c); + ap_proxy_cache_tidy(c); - pclosef(pool, sock); + ap_bclose(f); - proxy_garbage_coll(r); + ap_proxy_garbage_coll(r); return OK; } - diff --git a/usr.sbin/httpd/src/modules/proxy/proxy_util.c b/usr.sbin/httpd/src/modules/proxy/proxy_util.c index a2dfd0e8ed7..257b78bc848 100644 --- a/usr.sbin/httpd/src/modules/proxy/proxy_util.c +++ b/usr.sbin/httpd/src/modules/proxy/proxy_util.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1996-1998 The Apache Group. All rights reserved. + * 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 @@ -263,11 +263,14 @@ char * if (!ap_isdigit(strp[i])) break; - if (i == 0 || strp[i] != '\0') + /* if (i == 0) the no port was given; keep default */ + if (strp[i] != '\0') { return "Bad port number in URL"; - *port = atoi(strp); - if (*port > 65535) - return "Port number in URL > 65535"; + } 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') @@ -674,10 +677,10 @@ int ap_proxy_liststr(const char *list, const char *val) return 0; } -#ifdef WIN32 +#ifdef CASE_BLIND_FILESYSTEM /* - * On NT, the file system is NOT case sensitive. So, a == A + * 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) @@ -775,7 +778,7 @@ void ap_proxy_hash(const char *it, char *val, int ndepth, int nlength) val[i + 22 - k] = '\0'; } -#endif /* WIN32 */ +#endif /* CASE_BLIND_FILESYSTEM */ /* * Converts 8 hex digits to a time integer diff --git a/usr.sbin/httpd/src/modules/standard/mod_access.c b/usr.sbin/httpd/src/modules/standard/mod_access.c index 82a74ca94f1..f681e95501f 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_access.c +++ b/usr.sbin/httpd/src/modules/standard/mod_access.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/modules/standard/mod_actions.c b/usr.sbin/httpd/src/modules/standard/mod_actions.c index 5764cd4034c..5906ee4c43a 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_actions.c +++ b/usr.sbin/httpd/src/modules/standard/mod_actions.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -56,7 +56,7 @@ */ /* - * mod_actions.c: executes scripts based on MIME type + * 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 @@ -69,6 +69,12 @@ * 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" @@ -81,11 +87,8 @@ #include "util_script.h" typedef struct { - table *action_types; /* Added with Action... */ - char *get; /* Added with Script GET */ - char *post; /* Added with Script POST */ - char *put; /* Added with Script PUT */ - char *delete; /* Added with Script DELETE */ + table *action_types; /* Added with Action... */ + char *scripted[METHODS]; /* Added with Script... */ } action_dir_config; module action_module; @@ -96,10 +99,7 @@ static void *create_action_dir_config(pool *p, char *dummy) (action_dir_config *) ap_palloc(p, sizeof(action_dir_config)); new->action_types = ap_make_table(p, 4); - new->get = NULL; - new->post = NULL; - new->put = NULL; - new->delete = NULL; + memset(new->scripted, 0, sizeof(new->scripted)); return new; } @@ -108,17 +108,17 @@ 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)); + 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); - new->get = add->get ? add->get : base->get; - new->post = add->post ? add->post : base->post; - new->put = add->put ? add->put : base->put; - new->delete = add->delete ? add->delete : base->delete; - + for (i = 0; i < METHODS; ++i) { + new->scripted[i] = add->scripted[i] ? add->scripted[i] + : base->scripted[i]; + } return new; } @@ -129,19 +129,18 @@ static const char *add_action(cmd_parms *cmd, action_dir_config * m, char *type, return NULL; } -static const char *set_script(cmd_parms *cmd, action_dir_config * m, char *method, - char *script) +static const char *set_script(cmd_parms *cmd, action_dir_config * m, + char *method, char *script) { - if (!strcmp(method, "GET")) - m->get = script; - else if (!strcmp(method, "POST")) - m->post = script; - else if (!strcmp(method, "PUT")) - m->put = script; - else if (!strcmp(method, "DELETE")) - m->delete = script; + int methnum; + + methnum = ap_method_number_of(method); + if (methnum == M_TRACE) + return "TRACE not allowed for Script"; + else if (methnum == M_INVALID) + return "Unknown method type for Script"; else - return "Unknown method type for Script"; + m->scripted[methnum] = script; return NULL; } @@ -157,30 +156,28 @@ static const command_rec action_cmds[] = static int action_handler(request_rec *r) { - action_dir_config *conf = - (action_dir_config *) ap_get_module_config(r->per_dir_config, &action_module); + 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 : r->content_type; - const char *script = NULL; + const char *script; + int i; /* Set allowed stuff */ - if (conf->get) - r->allowed |= (1 << M_GET); - if (conf->post) - r->allowed |= (1 << M_POST); - if (conf->put) - r->allowed |= (1 << M_PUT); - if (conf->delete) - r->allowed |= (1 << M_DELETE); + 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) && r->args && conf->get) - script = conf->get; - else if ((r->method_number == M_POST) && conf->post) - script = conf->post; - else if ((r->method_number == M_PUT) && conf->put) - script = conf->put; - else if ((r->method_number == M_DELETE) && conf->delete) - script = conf->delete; + if (r->method_number == M_GET) { + if (r->args) + script = conf->scripted[M_GET]; + else + script = NULL; + } + else { + script = conf->scripted[r->method_number]; + } /* Check for looping, which can happen if the CGI script isn't */ if (script && r->prev && r->prev->prev) @@ -200,7 +197,7 @@ static int action_handler(request_rec *r) if (script == NULL) return DECLINED; - ap_internal_redirect_handler(ap_pstrcat(r->pool, script, escape_uri(r->pool, + 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; } diff --git a/usr.sbin/httpd/src/modules/standard/mod_alias.c b/usr.sbin/httpd/src/modules/standard/mod_alias.c index b100b200ae8..b7f5ba3d96c 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_alias.c +++ b/usr.sbin/httpd/src/modules/standard/mod_alias.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -305,7 +305,7 @@ static char *try_alias_list(request_rec *r, array_header *aliases, int doesc, in found = ap_pregsub(r->pool, p->real, r->uri, p->regexp->re_nsub + 1, regm); if (found && doesc) { - found = escape_uri(r->pool, found); + found = ap_escape_uri(r->pool, found); } } else { diff --git a/usr.sbin/httpd/src/modules/standard/mod_asis.c b/usr.sbin/httpd/src/modules/standard/mod_asis.c index d591ac4049d..5e299df9268 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_asis.c +++ b/usr.sbin/httpd/src/modules/standard/mod_asis.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -85,7 +85,7 @@ static int asis_handler(request_rec *r) return FORBIDDEN; } - scan_script_header(r, f); + ap_scan_script_header_err(r, f, NULL); location = ap_table_get(r->headers_out, "Location"); if (location && location[0] == '/' && diff --git a/usr.sbin/httpd/src/modules/standard/mod_auth.c b/usr.sbin/httpd/src/modules/standard/mod_auth.c index 605ef9cfa65..11df5645926 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_auth.c +++ b/usr.sbin/httpd/src/modules/standard/mod_auth.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -283,6 +283,16 @@ static int check_user_access(request_rec *r) 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); } } diff --git a/usr.sbin/httpd/src/modules/standard/mod_auth_anon.c b/usr.sbin/httpd/src/modules/standard/mod_auth_anon.c index e7a50114dab..e0c35b104fb 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_auth_anon.c +++ b/usr.sbin/httpd/src/modules/standard/mod_auth_anon.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/modules/standard/mod_auth_db.c b/usr.sbin/httpd/src/modules/standard/mod_auth_db.c index a4b5da96ce5..5571f7b51c8 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_auth_db.c +++ b/usr.sbin/httpd/src/modules/standard/mod_auth_db.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -155,11 +155,14 @@ static char *get_db_pw(request_rec *r, char *user, const char *auth_dbpwfile) DBT d, q; char *pw = NULL; + memset(&d, 0, sizeof(d)); + memset(&q, 0, sizeof(q)); + q.data = user; q.size = strlen(q.data); #ifdef DB2 - if (db_open(auth_dbpwfile, DB_HASH, O_RDONLY, 0664, NULL, NULL, &f) != 0) { + 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 diff --git a/usr.sbin/httpd/src/modules/standard/mod_auth_dbm.c b/usr.sbin/httpd/src/modules/standard/mod_auth_dbm.c index d4a72b23977..a91838b4c2b 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_auth_dbm.c +++ b/usr.sbin/httpd/src/modules/standard/mod_auth_dbm.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/modules/standard/mod_autoindex.c b/usr.sbin/httpd/src/modules/standard/mod_autoindex.c index 18f35cecce3..10436261aff 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_autoindex.c +++ b/usr.sbin/httpd/src/modules/standard/mod_autoindex.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -98,6 +98,10 @@ module MODULE_VAR_EXPORT autoindex_module; #define K_PAD 1 #define K_NOPAD 0 +#define K_NOADJUST 0 +#define K_ADJUST 1 +#define K_UNSET 2 + /* * Define keys for sorting. */ @@ -137,6 +141,7 @@ typedef struct autoindex_config_struct { int name_adjust; int icon_width; int icon_height; + char *default_order; array_header *icon_list, *alt_list, *desc_list, *ign_list; array_header *hdr_list, *rdme_list; @@ -368,8 +373,8 @@ static const char *add_opts(cmd_parms *cmd, void *d, const char *optstr) } } else if (!strncasecmp(w, "IconWidth=", 10)) { - if (action != '\0') { - return "Cannot combine '+' or '-' with IconWidth=n"; + if (action == '-') { + return "Cannot combine '-' with IconWidth=n"; } d_cfg->icon_width = atoi(&w[10]); } @@ -382,8 +387,8 @@ static const char *add_opts(cmd_parms *cmd, void *d, const char *optstr) } } else if (!strncasecmp(w, "IconHeight=", 11)) { - if (action != '\0') { - return "Cannot combine '+' or '-' with IconHeight=n"; + if (action == '-') { + return "Cannot combine '-' with IconHeight=n"; } d_cfg->icon_height = atoi(&w[11]); } @@ -393,14 +398,14 @@ static const char *add_opts(cmd_parms *cmd, void *d, const char *optstr) "'-NameWidth'"; } d_cfg->name_width = DEFAULT_NAME_WIDTH; - d_cfg->name_adjust = 0; + d_cfg->name_adjust = K_NOADJUST; } else if (!strncasecmp(w, "NameWidth=", 10)) { - if (action != '\0') { - return "Cannot combine '+' or '-' with NameWidth=n"; + if (action == '-') { + return "Cannot combine '-' with NameWidth=n"; } if (w[10] == '*') { - d_cfg->name_adjust = 1; + d_cfg->name_adjust = K_ADJUST; } else { int width = atoi(&w[10]); @@ -409,6 +414,7 @@ static const char *add_opts(cmd_parms *cmd, void *d, const char *optstr) return "NameWidth value must be greater than 1"; } d_cfg->name_width = width; + d_cfg->name_adjust = K_NOADJUST; } } else { @@ -437,6 +443,48 @@ static const char *add_opts(cmd_parms *cmd, void *d, const char *optstr) 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[] = @@ -455,6 +503,8 @@ static const command_rec autoindex_cmds[] = "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, @@ -477,7 +527,7 @@ static void *create_autoindex_config(pool *p, char *dummy) new->icon_width = 0; new->icon_height = 0; new->name_width = DEFAULT_NAME_WIDTH; - new->name_adjust = 0; + new->name_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(struct item)); @@ -487,6 +537,7 @@ static void *create_autoindex_config(pool *p, char *dummy) new->opts = 0; new->incremented_opts = 0; new->decremented_opts = 0; + new->default_order = NULL; return (void *) new; } @@ -551,9 +602,22 @@ static void *merge_autoindex_configs(pool *p, void *basev, void *addv) new->opts |= new->incremented_opts; new->opts &= ~new->decremented_opts; } - new->name_width = add->name_width; - new->name_adjust = add->name_adjust; + /* + * 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; + } + new->default_order = (add->default_order != NULL) + ? add->default_order : base->default_order; return new; } @@ -1030,7 +1094,7 @@ static void output_directories(struct ent **ar, int n, } name_width = d->name_width; - if (d->name_adjust) { + if (d->name_adjust == K_ADJUST) { for (x = 0; x < n; x++) { int t = strlen(ar[x]->name); if (t > name_width) { @@ -1160,7 +1224,8 @@ static void output_directories(struct ent **ar, int n, ap_rputs(time_str, r); } else { - ap_rputs(" ", r); + /*Length="22-Feb-1998 23:42 " (see 4 lines above) */ + ap_rputs(" ", r); } } if (!(autoindex_opts & SUPPRESS_SIZE)) { @@ -1300,31 +1365,33 @@ static int index_directory(request_rec *r, /* * 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. */ - if (autoindex_opts & SUPPRESS_COLSORT) { + 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 { - qstring = r->args; - - /* - * If no QUERY_STRING was specified, we use the default: ascending - * by name. - */ - if ((qstring == NULL) || (*qstring == '\0')) { - keyid = K_NAME; - direction = D_ASCENDING; + keyid = *qstring; + ap_getword(r->pool, &qstring, '='); + if (qstring != '\0') { + direction = *qstring; } else { - keyid = *qstring; - ap_getword(r->pool, &qstring, '='); - if (qstring != '\0') { - direction = *qstring; - } - else { - direction = D_ASCENDING; - } + direction = D_ASCENDING; } } diff --git a/usr.sbin/httpd/src/modules/standard/mod_cern_meta.c b/usr.sbin/httpd/src/modules/standard/mod_cern_meta.c index ee2afcfaa54..dbc1de6cabb 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_cern_meta.c +++ b/usr.sbin/httpd/src/modules/standard/mod_cern_meta.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/modules/standard/mod_cgi.c b/usr.sbin/httpd/src/modules/standard/mod_cgi.c index 70f7956228f..9091d0d9be0 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_cgi.c +++ b/usr.sbin/httpd/src/modules/standard/mod_cgi.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -386,12 +386,15 @@ static int cgi_handler(request_rec *r) /* Allow for cgi files without the .EXE extension on them under OS/2 */ if (r->finfo.st_mode == 0) { struct stat statbuf; + char *newfile; - r->filename = ap_pstrcat(r->pool, r->filename, ".EXE", NULL); + newfile = ap_pstrcat(r->pool, r->filename, ".EXE", NULL); - if ((stat(r->filename, &statbuf) != 0) || (!S_ISREG(statbuf.st_mode))) { + 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 diff --git a/usr.sbin/httpd/src/modules/standard/mod_digest.c b/usr.sbin/httpd/src/modules/standard/mod_digest.c index f44e7e3edea..74190d997be 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_digest.c +++ b/usr.sbin/httpd/src/modules/standard/mod_digest.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/modules/standard/mod_dir.c b/usr.sbin/httpd/src/modules/standard/mod_dir.c index a72dbc82047..04fbd1458c3 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_dir.c +++ b/usr.sbin/httpd/src/modules/standard/mod_dir.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -127,10 +127,10 @@ static int handle_dir(request_rec *r) if (r->uri[0] == '\0' || r->uri[strlen(r->uri) - 1] != '/') { char *ifile; if (r->args != NULL) - ifile = ap_pstrcat(r->pool, escape_uri(r->pool, r->uri), + ifile = ap_pstrcat(r->pool, ap_escape_uri(r->pool, r->uri), "/", "?", r->args, NULL); else - ifile = ap_pstrcat(r->pool, escape_uri(r->pool, r->uri), + ifile = ap_pstrcat(r->pool, ap_escape_uri(r->pool, r->uri), "/", NULL); ap_table_setn(r->headers_out, "Location", @@ -162,7 +162,7 @@ static int handle_dir(request_rec *r) request_rec *rr = ap_sub_req_lookup_uri(name_ptr, r); if (rr->status == HTTP_OK && rr->finfo.st_mode != 0) { - char *new_uri = escape_uri(r->pool, rr->uri); + 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); diff --git a/usr.sbin/httpd/src/modules/standard/mod_env.c b/usr.sbin/httpd/src/modules/standard/mod_env.c index fa7f8adc45a..e2bf3603a01 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_env.c +++ b/usr.sbin/httpd/src/modules/standard/mod_env.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/modules/standard/mod_expires.c b/usr.sbin/httpd/src/modules/standard/mod_expires.c index 50ebdf5c0ac..4fcf51a8106 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_expires.c +++ b/usr.sbin/httpd/src/modules/standard/mod_expires.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/modules/standard/mod_headers.c b/usr.sbin/httpd/src/modules/standard/mod_headers.c index 665182db461..c3d50503eed 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_headers.c +++ b/usr.sbin/httpd/src/modules/standard/mod_headers.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1996-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/modules/standard/mod_imap.c b/usr.sbin/httpd/src/modules/standard/mod_imap.c index 8a68985ae40..dfde31464c4 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_imap.c +++ b/usr.sbin/httpd/src/modules/standard/mod_imap.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -679,11 +679,10 @@ static int imap_handler(request_rec *r) if we aren't printing a menu */ /* find the first two space delimited fields, recall that - * cfg_getline has removed leading/trailing whitespace and - * compressed the other whitespace down to one space a piece + * ap_cfg_getline has removed leading/trailing whitespace. * * note that we're tokenizing as we go... if we were to use the - * getword() class of functions we would end up allocating extra + * ap_getword() class of functions we would end up allocating extra * memory for every line of the map file */ string_pos = input; @@ -692,7 +691,7 @@ static int imap_handler(request_rec *r) } directive = string_pos; - while (*string_pos && *string_pos != ' ') { /* past directive */ + while (*string_pos && !ap_isspace(*string_pos)) { /* past directive */ ++string_pos; } if (!*string_pos) { /* need at least two fields */ @@ -703,11 +702,15 @@ static int imap_handler(request_rec *r) 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 && *string_pos != ' ') { /* past value */ + while (*string_pos && !ap_isspace(*string_pos)) { /* past value */ ++string_pos; } - if (*string_pos == ' ') { + if (ap_isspace(*string_pos)) { *string_pos++ = '\0'; } else { diff --git a/usr.sbin/httpd/src/modules/standard/mod_include.c b/usr.sbin/httpd/src/modules/standard/mod_include.c index 3acc0c6f696..dd36668cda7 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_include.c +++ b/usr.sbin/httpd/src/modules/standard/mod_include.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -688,13 +688,41 @@ static int handle_include(FILE *in, request_rec *r, const char *error, int noexe "in parsed file %s"; } if (error_fmt == NULL) { + /* try to avoid recursive includes. We do this by walking + * up the r->main list of subrequests, and at each level + * walking back through any internal redirects. At each + * step, we compare the filenames and the URIs. + * + * The filename comparison catches a recursive include + * with an ever-changing URL, eg. + * <!--#include virtual= + * "$REQUEST_URI/$QUERY_STRING?$QUERY_STRING/x"--> + * which, although they would eventually be caught because + * we have a limit on the length of files, etc., can + * recurse for a while. + * + * The URI comparison catches the case where the filename + * is changed while processing the request, so the + * current name is never the same as any previous one. + * This can happen with "DocumentRoot /foo" when you + * request "/" on the server and it includes "/". + * This only applies to modules such as mod_dir that + * (somewhat improperly) mess with r->filename outside + * of a filename translation phase. + */ + int founddupe = 0; request_rec *p; + for (p = r; p != NULL && !founddupe; p = p->main) { + request_rec *q; + for (q = p; q != NULL; q = q->prev) { + if ( (strcmp(q->filename, rr->filename) == 0) || + (strcmp(q->uri, rr->uri) == 0) ){ + founddupe = 1; + break; + } + } + } - for (p = r; p != NULL; p = p->main) { - if (strcmp(p->filename, rr->filename) == 0) { - break; - } - } if (p != NULL) { error_fmt = "Recursive include of \"%s\" " "in parsed file %s"; @@ -768,7 +796,7 @@ static int include_cmd_child(void *arg, child_info *pinfo) ap_table_setn(env, "PATH_INFO", ap_escape_shell_cmd(r->pool, r->path_info)); - pa_req = ap_sub_req_lookup_uri(escape_uri(r->pool, r->path_info), r); + 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, @@ -805,7 +833,7 @@ static int include_cmd_child(void *arg, child_info *pinfo) fprintf(dbg, "Exec failed\n"); #endif ap_snprintf(err_string, sizeof(err_string), - "httpd: exec of %s failed, reason: %s (errno = %d)\n", + "exec of %s failed, reason: %s (errno = %d)\n", SHELL_PATH, strerror(errno), errno); write(STDERR_FILENO, err_string, strlen(err_string)); exit(0); @@ -924,10 +952,10 @@ static int handle_perl(FILE *in, request_rec *r, const char *error) SV *sub = Nullsv; AV *av = newAV(); - if (!(ap_allow_options(r) & OPT_INCLUDES)) { + if (ap_allow_options(r) & OPT_INCNOEXEC) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, - "httpd: #perl SSI disallowed by IncludesNoExec in %s", - r->filename); + "#perl SSI disallowed by IncludesNoExec in %s", + r->filename); return DECLINED; } while (1) { @@ -2176,8 +2204,8 @@ static void send_parsed_content(FILE *f, request_rec *r) if (!strcmp(directive, "exec")) { if (noexec) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, - "httpd: exec used but not allowed in %s", - r->filename); + "exec used but not allowed in %s", + r->filename); if (printing) { ap_rputs(error, r); } @@ -2215,9 +2243,9 @@ static void send_parsed_content(FILE *f, request_rec *r) #endif else { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, - "httpd: unknown directive \"%s\" " - "in parsed doc %s", - directive, r->filename); + "unknown directive \"%s\" " + "in parsed doc %s", + directive, r->filename); if (printing) { ap_rputs(error, r); } @@ -2225,8 +2253,8 @@ static void send_parsed_content(FILE *f, request_rec *r) } if (ret) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, - "httpd: premature EOF in parsed file %s", - r->filename); + "premature EOF in parsed file %s", + r->filename); return; } } diff --git a/usr.sbin/httpd/src/modules/standard/mod_info.c b/usr.sbin/httpd/src/modules/standard/mod_info.c index f45f630d45a..ce0edefc9e2 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_info.c +++ b/usr.sbin/httpd/src/modules/standard/mod_info.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/modules/standard/mod_log_agent.c b/usr.sbin/httpd/src/modules/standard/mod_log_agent.c index ea20dae7e61..b625afcf0c8 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_log_agent.c +++ b/usr.sbin/httpd/src/modules/standard/mod_log_agent.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -126,7 +126,7 @@ static void open_agent_log(server_rec *s, pool *p) 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, - "httpd: could not open agent log file %s.", fname); + "could not open agent log file %s.", fname); exit(1); } } diff --git a/usr.sbin/httpd/src/modules/standard/mod_log_config.c b/usr.sbin/httpd/src/modules/standard/mod_log_config.c index da6d2bcb458..ceab066c5fb 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_log_config.c +++ b/usr.sbin/httpd/src/modules/standard/mod_log_config.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -407,12 +407,13 @@ static const char *log_request_duration(request_rec *r, char *a) */ static const char *log_virtual_host(request_rec *r, char *a) { - return ap_get_server_name(r); + return r->server->server_hostname; } static const char *log_server_port(request_rec *r, char *a) { - return ap_psprintf(r->pool, "%u", ap_get_server_port(r)); + return ap_psprintf(r->pool, "%u", + r->server->port ? r->server->port : ap_default_port(r)); } static const char *log_child_pid(request_rec *r, char *a) @@ -913,7 +914,7 @@ static config_log_state *open_config_log(server_rec *s, pool *p, 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, - "httpd: could not open transfer log file %s.", fname); + "could not open transfer log file %s.", fname); exit(1); } } diff --git a/usr.sbin/httpd/src/modules/standard/mod_log_referer.c b/usr.sbin/httpd/src/modules/standard/mod_log_referer.c index 90750c9c0b6..f63cb2ebea6 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_log_referer.c +++ b/usr.sbin/httpd/src/modules/standard/mod_log_referer.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -143,7 +143,7 @@ static void open_referer_log(server_rec *s, pool *p) 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, - "httpd: could not open referer log file %s.", fname); + "could not open referer log file %s.", fname); exit(1); } } diff --git a/usr.sbin/httpd/src/modules/standard/mod_mime.c b/usr.sbin/httpd/src/modules/standard/mod_mime.c index b352eae4f39..80ec7ee3c82 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_mime.c +++ b/usr.sbin/httpd/src/modules/standard/mod_mime.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -68,14 +68,20 @@ #include "http_config.h" #include "http_log.h" +typedef struct handlers_info { + char *name; +} handlers_info; + typedef struct { table *forced_types; /* Additional AddTyped stuff */ table *encoding_types; /* Added with AddEncoding... */ 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; module MODULE_VAR_EXPORT mime_module; @@ -89,9 +95,11 @@ static void *create_mime_dir_config(pool *p, char *dummy) new->encoding_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; } @@ -101,7 +109,14 @@ 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)); + (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); @@ -114,6 +129,8 @@ static void *merge_mime_dir_configs(pool *p, void *basev, void *addv) 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; } @@ -158,6 +175,24 @@ static const char *add_handler(cmd_parms *cmd, mime_dir_config * m, char *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... */ @@ -181,11 +216,16 @@ static const command_rec mime_cmds[] = {"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} }; @@ -217,7 +257,7 @@ static void init_mime(server_rec *s, pool *p) if (!(f = ap_pcfg_openfile(p, types_confname))) { ap_log_error(APLOG_MARK, APLOG_ERR, s, - "httpd: could not open mime types log file %s.", types_confname); + "could not open mime types log file %s.", types_confname); exit(1); } @@ -316,6 +356,20 @@ static int find_ct(request_rec *r) } + /* 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")) diff --git a/usr.sbin/httpd/src/modules/standard/mod_mime_magic.c b/usr.sbin/httpd/src/modules/standard/mod_mime_magic.c index eb1b4eb8860..e57eea537f8 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_mime_magic.c +++ b/usr.sbin/httpd/src/modules/standard/mod_mime_magic.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/modules/standard/mod_negotiation.c b/usr.sbin/httpd/src/modules/standard/mod_negotiation.c index f3e47887c9c..b2fcf93ef74 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_negotiation.c +++ b/usr.sbin/httpd/src/modules/standard/mod_negotiation.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -65,19 +65,11 @@ #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" -/* define TCN_02 to allow for Holtman I-D transparent negotiation. - * This file currently implements the draft-02, except for - * anything to do with features and cache-control (max-age etc) - * - * Since the draft is just that, and we don't yet implement - * everything, regard the transparent negotiation stuff as experimental. - */ -/*#define TCN_02 */ - /* Commands --- configuring document caching on a per (virtual?) * server basis... */ @@ -88,17 +80,6 @@ typedef struct { module MODULE_VAR_EXPORT negotiation_module; -static char *merge_string_array(pool *p, array_header *arr, char *sep) -{ - int i; - char *t = ""; - - for (i = 0; i < arr->nelts; i++) { - t = ap_pstrcat(p, t, (i ? sep : ""), ((char **) arr->elts)[i], NULL); - } - return t; -} - static void *create_neg_dir_config(pool *p, char *dummy) { neg_dir_config *new = (neg_dir_config *) ap_palloc(p, sizeof(neg_dir_config)); @@ -157,7 +138,7 @@ static const command_rec negotiation_cmds[] = */ typedef struct accept_rec { - char *type_name; /* MUST be lowercase */ + char *name; /* MUST be lowercase */ float quality; float max_bytes; float level; @@ -174,31 +155,39 @@ typedef struct accept_rec { * 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 *type_name; /* MUST be lowercase */ + char *mime_type; /* MUST be lowercase */ char *file_name; const char *content_encoding; - array_header *content_languages; /* list of languages for this variant */ + 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 accept_type_quality, which + * 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 type_quality, + * 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()). type_quality is set from the 'qs' parameter + * (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 */ - int encoding_quality; /* ditto encoding (1 or 0 only) */ + float encoding_quality; /* ditto encoding */ float charset_quality; /* ditto charset */ - float accept_type_quality; /* ditto media type */ - float type_quality; /* quality of source for this type */ + 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... */ @@ -226,19 +215,25 @@ typedef struct { 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 */ - array_header *accepts; /* accept_recs */ - int have_accept_header; /* 1 if Accept-Header present */ - 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 count_multiviews_variants; /* number of variants found on disk */ + int is_transparent; /* 1 if this resource is trans. negotiable */ - int ua_can_negotiate; /* 1 if ua can do transparent negotiate */ - int use_transparent_neg; /* 1 if we are using transparent neg */ - int short_accept_headers; /* 1 if ua does trans neg & sent short accpt */ + 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. @@ -248,7 +243,7 @@ typedef struct { static void clean_var_rec(var_rec *mime_info) { mime_info->sub_req = NULL; - mime_info->type_name = ""; + mime_info->mime_type = ""; mime_info->file_name = ""; mime_info->content_encoding = NULL; mime_info->content_languages = NULL; @@ -264,10 +259,10 @@ static void clean_var_rec(var_rec *mime_info) mime_info->definite = 1; mime_info->charset_quality = 1.0f; - mime_info->type_quality = 0.0f; - mime_info->encoding_quality = 1; + mime_info->encoding_quality = 1.0f; mime_info->lang_quality = 1.0f; - mime_info->accept_type_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 @@ -276,16 +271,35 @@ static void clean_var_rec(var_rec *mime_info) static void set_mime_fields(var_rec *var, accept_rec *mime_info) { - var->type_name = mime_info->type_name; - var->type_quality = mime_info->quality; + 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->type_name, "text/html") - || !strcmp(var->type_name, INCLUDES_MAGIC_TYPE) - || !strcmp(var->type_name, INCLUDES_MAGIC_TYPE3)); + 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 @@ -297,7 +311,8 @@ static void set_mime_fields(var_rec *var, accept_rec *mime_info) * enter the values we recognize into the argument accept_rec */ -static const char *get_entry(pool *p, accept_rec *result, const char *accept_line) +static const char *get_entry(pool *p, accept_rec *result, + const char *accept_line) { result->quality = 1.0f; result->max_bytes = 0.0f; @@ -315,22 +330,22 @@ static const char *get_entry(pool *p, accept_rec *result, const char *accept_lin * in the CERN server code? I must be missing something). */ - result->type_name = ap_get_token(p, &accept_line, 0); - ap_str_tolower(result->type_name); /* You want case-insensitive, - * you'll *get* case-insensitive. - */ + 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->type_name, "text/html") && (result->level == 0.0)) { + if (!strcmp(result->name, "text/html") && (result->level == 0.0)) { result->level = 2.0f; } - else if (!strcmp(result->type_name, INCLUDES_MAGIC_TYPE)) { + else if (!strcmp(result->name, INCLUDES_MAGIC_TYPE)) { result->level = 2.0f; } - else if (!strcmp(result->type_name, INCLUDES_MAGIC_TYPE3)) { + else if (!strcmp(result->name, INCLUDES_MAGIC_TYPE3)) { result->level = 3.0f; } @@ -405,18 +420,19 @@ static const char *get_entry(pool *p, accept_rec *result, const char *accept_lin * basic structure of a list of items of the format * name; q=N; charset=TEXT * - * where q is only valid in Accept, Accept-Charset and Accept-Languages, - * and charset is only valid in Accept. + * where charset is only valid in Accept. */ static array_header *do_header_line(pool *p, const char *accept_line) { - array_header *accept_recs = ap_make_array(p, 40, sizeof(accept_rec)); + array_header *accept_recs; if (!accept_line) { - return accept_recs; + 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); @@ -456,12 +472,11 @@ static array_header *do_languages_line(pool *p, const char **lang_line) static negotiation_state *parse_accept_headers(request_rec *r) { - negotiation_state *new = (negotiation_state *) ap_pcalloc(r->pool, - sizeof(negotiation_state)); + negotiation_state *new = + (negotiation_state *) ap_pcalloc(r->pool, sizeof(negotiation_state)); accept_rec *elts; table *hdrs = r->headers_in; int i; - const char *hdr; new->pool = r->pool; new->r = r; @@ -469,86 +484,147 @@ static negotiation_state *parse_accept_headers(request_rec *r) new->accepts = do_header_line(r->pool, ap_table_get(hdrs, "Accept")); - hdr = ap_table_get(hdrs, "Accept-encoding"); - if (hdr) { - new->have_accept_header = 1; + /* 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, hdr); - 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)); + 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")); -#ifdef TCN_02 - if (ap_table_get(r->headers_in, "Negotiate")) { - /* Negotiate: header tells us UA does transparent negotiation - * We have to decide whether we want to ... for now, yes, - * we do */ + new->avail_vars = ap_make_array(r->pool, 40, sizeof(var_rec)); - new->ua_can_negotiate = 1; - if (r->method_number == M_GET) { - new->use_transparent_neg = 1; /* should be configurable */ - } + return new; +} - /* Check for 'Short Accept', ie either no Accept: header, - * or just "Accept: * / *" */ - if (new->accepts->nelts == 0 || - (new->accepts->nelts == 1 && - (!strcmp(((accept_rec *) new->accepts->elts)[0].type_name, - "*/*")))) { - /* Using short accept header */ - new->short_accept_headers = 1; - } - } -#endif - if (!new->use_transparent_neg) { - /* Now we check for q-values. If they're all 1.0, we assume the - * client is "broken", and we are allowed to fiddle with the - * values later. Otherwise, we leave them alone. +static void parse_negotiate_header(request_rec *r, negotiation_state *neg) +{ + const char *negotiate = ap_table_get(r->headers_in, "Negotiate"); + + if (negotiate) { + /* Negotiate: header tells us UA does transparent negotiation */ + + /* sending Alternates on non-transparent resources is allowed, + * and may even be useful, but we don't for now, also + * because it could clash with an Alternates header set by + * a sub- or super- request on a transparent resource. */ - elts = (accept_rec *) new->accepts->elts; + while (*negotiate) { + char *tok = ap_get_token(neg->pool, &negotiate, 1); + char *cp; - for (i = 0; i < new->accepts->nelts; ++i) { - if (elts[i].quality < 1.0) { - new->accept_q = 1; + for (cp = tok; (*cp && !ap_isspace(*cp) && *cp != '='); ++cp) { + *cp = ap_tolower(*cp); + } + *cp = 0; + + 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 (strcmp(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; + } } + + if (*negotiate) + negotiate++; /* skip over , */ } } - else { - new->accept_q = 1; + + if (!neg->ua_supports_trans) { + /* User agent does not support transparent negotiation, + * configure to do server-driven negotiation with the Apache + * algorithm. + */ + neg->may_choose = 1; + + /* To save network bandwidth, we do not configure to send an + * Alternates header to the user agent in this case. User + * agents which want an Alternates header for agent-driven + * negotiation will have to request it by sending an + * appropriate Negotiate header. + */ } - return new; +#if 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). + * e.g., POST or when URI includes query args or extra path info). */ - -static void maybe_add_default_encodings(negotiation_state *neg, int prefer_scripts) +static void maybe_add_default_accepts(negotiation_state *neg, + int prefer_scripts) { - accept_rec *new_accept = (accept_rec *) ap_push_array(neg->accepts); + accept_rec *new_accept; - new_accept->type_name = CGI_MAGIC_TYPE; - new_accept->quality = prefer_scripts ? 1e-20f : 1e20f; - new_accept->level = 0.0f; - new_accept->max_bytes = 0.0f; + if (!neg->accepts) { + neg->accepts = ap_make_array(neg->pool, 4, sizeof(accept_rec)); - if (neg->accepts->nelts > 1) { - return; - } + new_accept = (accept_rec *) ap_push_array(neg->accepts); + + new_accept->name = "*/*"; + new_accept->quality = 1.0f; + new_accept->level = 0.0f; + new_accept->max_bytes = 0.0f; + } new_accept = (accept_rec *) ap_push_array(neg->accepts); - new_accept->type_name = "*/*"; - new_accept->quality = 1.0f; + 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; new_accept->max_bytes = 0.0f; } @@ -646,14 +722,15 @@ static enum header_state get_header_line(char *buffer, int len, FILE *map) 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; + hdr = strchr(hdr, '"'); + if (hdr == NULL) { + return; + } + ++hdr; } else if (*hdr == '(') { while (*hdr && *hdr != ')') { @@ -682,7 +759,7 @@ static char *lcase_header_name_return_body(char *header, request_rec *r) if (!*cp) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, - "Syntax error in type map --- no ':': %s", r->filename); + "Syntax error in type map --- no ':': %s", r->filename); return NULL; } @@ -692,8 +769,8 @@ static char *lcase_header_name_return_body(char *header, request_rec *r) if (!*cp) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, - "Syntax error in type map --- no header body: %s", - r->filename); + "Syntax error in type map --- no header body: %s", + r->filename); return NULL; } @@ -707,6 +784,7 @@ static int read_type_map(negotiation_state *neg, request_rec *rr) 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; @@ -714,25 +792,26 @@ static int read_type_map(negotiation_state *neg, request_rec *rr) 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); + "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; + const char *body; if (body1 == NULL) { return SERVER_ERROR; } strip_paren_comments(body1); - body=body1; + body = body1; if (!strncmp(buffer, "uri:", 4)) { mime_info.file_name = ap_get_token(neg->pool, &body, 0); @@ -742,39 +821,77 @@ static int read_type_map(negotiation_state *neg, request_rec *rr) 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)) { - mime_info.description = ap_get_token(neg->pool, &body, 0); + /* XXX: The possibility to set a description is + * currently not documented. + */ + 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.type_quality > 0 && *mime_info.file_name) { + 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, except we use a filtered directory listing as the map... + * Same as read_type_map, except we use a filtered directory listing + * as the map... */ static int read_types_multi(negotiation_state *neg) @@ -853,14 +970,13 @@ static int read_types_multi(negotiation_state *neg) ap_pclosedir(neg->pool, dirp); neg->avail_vars->nelts = 0; - if (sub_req->status != HTTP_OK) { - return sub_req->status; - } + if (sub_req->status != HTTP_OK) { + return sub_req->status; + } return read_type_map(neg, sub_req); } - /* Have reasonable variant --- gather notes. - */ + /* Have reasonable variant --- gather notes. */ mime_info.sub_req = sub_req; mime_info.file_name = ap_pstrdup(neg->pool, dir_entry->d_name); @@ -883,13 +999,27 @@ static int read_types_multi(negotiation_state *neg) } 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. + * finding a match to the client's requirements. */ /* Matching MIME types ... the star/star and foo/star commenting conventions @@ -906,8 +1036,8 @@ static int read_types_multi(negotiation_state *neg) static int mime_match(accept_rec *accept_r, var_rec *avail) { - char *accept_type = accept_r->type_name; - char *avail_type = avail->type_name; + 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 */ @@ -970,9 +1100,13 @@ static int level_cmp(var_rec *var1, var_rec *var2) return 0; } - if (!var1->is_pseudo_html && strcmp(var1->type_name, var2->type_name)) { + 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. */ @@ -1008,12 +1142,12 @@ static int level_cmp(var_rec *var1, var_rec *var2) * 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 network algorithm). If using - * network algorithm, lang_index is never used. + * 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. + * to set lang_index. */ static int find_lang_index(array_header *accept_langs, char *lang) @@ -1021,14 +1155,14 @@ static int find_lang_index(array_header *accept_langs, char *lang) accept_rec *accs; int i; - if (!lang) { + 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].type_name, strlen(accs[i].type_name))) { + if (!strncmp(lang, accs[i].name, strlen(accs[i].name))) { return i; } } @@ -1076,8 +1210,8 @@ static int find_default_index(neg_dir_config *conf, char *lang) * 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 transparent negotiation network algorythm, - * we don't use this fiddle. + * Note that if using the RVSA/1.0 algorithm, we don't use this + * fiddle. */ static void set_default_lang_quality(negotiation_state *neg) @@ -1085,7 +1219,7 @@ static void set_default_lang_quality(negotiation_state *neg) var_rec *avail_recs = (var_rec *) neg->avail_vars->elts; int j; - if (!neg->use_transparent_neg) { + if (!neg->dont_fiddle_headers) { for (j = 0; j < neg->avail_vars->nelts; ++j) { var_rec *variant = &avail_recs[j]; if (variant->content_languages && @@ -1103,11 +1237,11 @@ static void set_default_lang_quality(negotiation_state *neg) * 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: + * 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 + * 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' @@ -1132,135 +1266,160 @@ static void set_default_lang_quality(negotiation_state *neg) static void set_language_quality(negotiation_state *neg, var_rec *variant) { - int i; - int naccept = neg->accept_langs->nelts; - int idx; - neg_dir_config *conf = NULL; char *firstlang; - - if (naccept == 0) { - conf = (neg_dir_config *) ap_get_module_config(neg->r->per_dir_config, - &negotiation_module); - } - - if (naccept == 0 && (!variant->content_languages || - !variant->content_languages->nelts)) { - return; /* no accept-language and no variant lang */ - } + 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()). */ - variant->lang_quality = neg->default_lang_quality; - - if (naccept == 0) { - return; /* no accept-language items */ + * (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 if (naccept) { - /* Variant has one (or more) languages, and we have one (or more) - * language ranges on the Accept-Language header. 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. + 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. */ - int j; - float fiddle_q = 0.0f; - accept_rec *accs = (accept_rec *) neg->accept_langs->elts; - accept_rec *best = NULL, *star = NULL; - char *p; - - for (j = 0; j < variant->content_languages->nelts; ++j) { - char *lang; /* language from variant description */ - accept_rec *bestthistag = NULL; - int prefixlen = 0; - int longest_lang_range_len = 0; - int len; - - /* 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]; - p = strchr(lang, '-'); /* find prefix part (if any) */ - if (p) { - prefixlen = p - lang; - } - /* 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].type_name, "*")) { - if (!star) { - star = &accs[i]; + 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; } - continue; - } - - /* Find language. We match if either the variant language - * tag exactly matches, or the prefix of the tag up to the - * '-' character matches the whole of the language in the - * Accept-Language header. We only use this accept-language - * item as the best match for the current tag if it - * is longer than the previous best match */ - if ((!strcmp(lang, accs[i].type_name) || - (prefixlen && - !strncmp(lang, accs[i].type_name, prefixlen) && - (accs[i].type_name[prefixlen] == '\0'))) && - ((len = strlen(accs[i].type_name)) > - longest_lang_range_len)) { - longest_lang_range_len = len; - bestthistag = &accs[i]; - } - - if (!bestthistag) { - /* 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 + /* 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. */ - if ((p = strchr(accs[i].type_name, '-'))) { - int plen = p - accs[i].type_name; - if (!strncmp(lang, accs[i].type_name, plen)) { - fiddle_q = 0.001f; + + 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; + } } - /* Finished looking at Accept-Language headers, the best - * (longest) match is in bestthistag, or NULL if no match + + /* 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 (!best || - (bestthistag && bestthistag->quality > best->quality)) { - best = bestthistag; + if ( any_match_on_star && + ((best && star->quality > best->quality) || + (!best)) ) { + best = star; + variant->definite = 0; } + + variant->lang_quality = best ? best->quality : fiddle_q; } - - variant->lang_quality = best - ? best->quality - : (star ? star->quality : fiddle_q); } /* Now set the old lang_index field. Since this is old - * stuff anyway, don't both with handling multiple languages - * per variant, just use the first one assigned to it + * 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) { @@ -1269,8 +1428,10 @@ static void set_language_quality(negotiation_state *neg, var_rec *variant) else { firstlang = ""; } - if (naccept == 0) { /* Client doesn't care */ - idx = find_default_index(conf, 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); @@ -1294,7 +1455,7 @@ static float find_content_length(negotiation_state *neg, var_rec *variant) if (variant->bytes == 0) { char *fullname = ap_make_full_path(neg->pool, neg->dir_name, - variant->file_name); + variant->file_name); if (stat(fullname, &statb) >= 0) { /* Note, precision may be lost */ @@ -1307,29 +1468,37 @@ static float find_content_length(negotiation_state *neg, var_rec *variant) /* For a given variant, find the best matching Accept: header * and assign the Accept: header's quality value to the - * accept_type_quality field of the variant, for later use in + * 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 = (accept_rec *) neg->accepts->elts; + 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) */ - if (!neg->accepts || neg->accepts->nelts == 0) { + * 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 - * accept_type_quality field. + * mime_type_quality field. * * The best match is determined like this: * type/type is better than type/ * is better than * / * @@ -1354,22 +1523,25 @@ static void set_accept_quality(negotiation_state *neg, var_rec *variant) } } - /* Check maxbytes -- not in HTTP/1.1 or Holtman */ + /* Check maxbytes -- not in HTTP/1.1 or TCN */ if (type->max_bytes > 0 && (find_content_length(neg, variant) > type->max_bytes)) { continue; } - /* If we are allowed to mess with the q-values, + /* 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->accept_q && variant->mime_stars == 1) { + if (!neg->dont_fiddle_headers && !neg->accept_q && + variant->mime_stars == 1) { q = 0.01f; } - else if (!neg->accept_q && variant->mime_stars == 2) { + else if (!neg->dont_fiddle_headers && !neg->accept_q && + variant->mime_stars == 2) { q = 0.02f; } else { @@ -1378,37 +1550,55 @@ static void set_accept_quality(negotiation_state *neg, var_rec *variant) q_definite = (variant->mime_stars == 3); } - variant->accept_type_quality = q; + variant->mime_type_quality = q; variant->definite = variant->definite && q_definite; - /* if the _best_ quality we got for this variant was 0.0, - * eliminate it now */ } /* For a given variant, find the 'q' value of the charset given * on the Accept-Charset line. If not charsets are listed, * assume value of '1'. */ - static void set_charset_quality(negotiation_state *neg, var_rec *variant) { int i; - accept_rec *accept_recs = (accept_rec *) neg->accept_charsets->elts; + 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 || neg->accept_charsets->nelts == 0) { + * 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 = "iso-8859-1"; + /* 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, + * 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. */ @@ -1416,17 +1606,18 @@ static void set_charset_quality(negotiation_state *neg, var_rec *variant) accept_rec *type = &accept_recs[i]; - if (!strcmp(type->type_name, charset)) { + if (!strcmp(type->name, charset)) { variant->charset_quality = type->quality; return; } - else if (strcmp(type->type_name, "*") == 0) { + 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 */ @@ -1438,11 +1629,6 @@ static void set_charset_quality(negotiation_state *neg, var_rec *variant) } } -/* For a given variant, find the best matching Accept: header - * and assign the Accept: header's quality value to the - * accept_type_quality field of the variant, for later use in - * determining the best matching variant. - */ /* is_identity_encoding is included for back-compat, but does anyone * use 7bit, 8bin or binary in their var files?? @@ -1454,25 +1640,46 @@ static int is_identity_encoding(const char *enc) || !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) { - int i; - accept_rec *accept_recs = (accept_rec *) neg->accept_encodings->elts; + 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; - if (!enc || is_identity_encoding(enc)) { return; } - /* if no Accept: header, leave quality alone (will - * remain at the default value of 1) */ - if (neg->accept_encodings->nelts == 0) { - /* If we had an empty Accept-Encoding header, assume that - * no encodings are acceptable, else all encodings are ok */ - variant->encoding_quality = neg->have_accept_header ? 0 : 1; - 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. */ @@ -1480,93 +1687,122 @@ static void set_encoding_quality(negotiation_state *neg, var_rec *variant) enc += 2; } for (i = 0; i < neg->accept_encodings->nelts; ++i) { - char *name = accept_recs[i].type_name; + + char *name = accept_recs[i].name; if (name[0] == 'x' && name[1] == '-') { name += 2; } if (!strcmp(name, enc)) { - variant->encoding_quality = 1; + 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 */ - variant->encoding_quality = 0; + * _not_ acceptable unless it is the identity (no encoding) + */ + variant->encoding_quality = value_if_not_found; } -/* Possible results of the network algorithm */ +/************************************************************* + * Possible results of the variant selection algorithm + */ enum algorithm_results { - na_not_applied = -1, /* net algorithm not used */ - na_choice = 1, /* choose variant */ - na_list /* list variants */ + alg_choice = 1, /* choose variant */ + alg_list /* list variants */ }; -/* - * This is a heavily-rewritten 'best_match' function. For a start, it - * now returns an int, which has one of the three values: na_not_applied, - * na_choice or na_list, which give the result of the network algorithm - * (if it was not applied, the return value is na_not_applied). - * The best variable is returned in *pbest. It also has two possible - * algorithms for determining the best match: the network algorithm, - * and the standard Apache algorithm. These are split out into - * separate functions (is_variant_better_na() and is_variant_better()). - * - * Previously, best_match iterated first through the content_types - * in the Accept: header, then checked each variant, and eliminated - * those that didn't match the variant's type. We cannot do this because - * we need full information, including language, charset, etc - * quality for _every_ variant, for the Alternates: header, - * and (possibly) the human-readable choice responses or 406 errors. +/* 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. * - * After the 'best' (if any) is determined, the overall result of - * the negotiation is obtained. If the network algorithm was not - * in use, the result is na_not_applied. Else the result is - * na_list if 'short accept header' is in use, else na_list - * if _no_ best match was found, or na_choice if a best match - * was found. + * 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 negotiation 'network algorithm' from Holtman. +/* 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_na(negotiation_state *neg, var_rec *variant, - var_rec *best, float *p_bestq) +static int is_variant_better_rvsa(negotiation_state *neg, var_rec *variant, + var_rec *best, float *p_bestq) { float bestq = *p_bestq, q; - /* Note: Encoding is not negotiated in the Holtman - * transparent neg draft, so we ignored it here. But - * it does mean we could return encodings the UA - * or proxy cannot handle. Eek. */ - - q = variant->accept_type_quality * - variant->type_quality * + /* 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; + /* Make sure that variants with a very low nonzero q value + * do not get rounded down to 0 + */ + if (q <= 0.0f) + q = 0.0f; + else if (q < 0.00001f) + q = 0.00001f; + #ifdef NEG_DEBUG - fprintf(stderr, "Variant: file=%s type=%s lang=%s acceptq=%1.3f " - "langq=%1.3f typeq=%1.3f q=%1.3f definite=%d\n", + 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->type_name ? variant->type_name : ""), + (variant->mime_name ? variant->mime_name : ""), (variant->content_languages - ? merge_string_array(neg->pool, variant->content_languages, ",") + ? ap_array_pstrcat(neg->pool, variant->content_languages, ',') : ""), - variant->accept_type_quality, + variant->source_quality, + variant->mime_type_quality, variant->lang_quality, - variant->type_quality, - q, + variant->charset_quality, + variant->encoding_qual 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; + } /* If the best variant's charset is ISO-8859-1 and this variant has * the same charset quality, then we prefer this variant */ @@ -1588,13 +1824,13 @@ static int is_variant_better_na(negotiation_state *neg, var_rec *variant, * (just about). */ -static int is_variant_better(negotiation_state *neg, var_rec *variant, var_rec *best, float *p_bestq) +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 + /* 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 length. @@ -1617,15 +1853,15 @@ static int is_variant_better(negotiation_state *neg, var_rec *variant, var_rec * * acceptable by type, charset, encoding or language. */ - if (variant->encoding_quality == 0 || - variant->lang_quality == 0 || - variant->type_quality == 0 || - variant->charset_quality == 0 || - variant->accept_type_quality == 0) { + 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->accept_type_quality * variant->type_quality; + q = variant->mime_type_quality * variant->source_quality; if (q == 0.0 || q < bestq) { return 0; } @@ -1644,7 +1880,11 @@ static int is_variant_better(negotiation_state *neg, var_rec *variant, var_rec * } /* if language qualities were equal, try the LanguagePriority - * stuff */ + * stuff + */ + /* XXX: TODO: there is a slight discrepancy between how this + * behaves and how it described in the documentation + */ if (best->lang_index != -1 && variant->lang_index > best->lang_index) { return 0; } @@ -1654,7 +1894,9 @@ static int is_variant_better(negotiation_state *neg, var_rec *variant, var_rec * return 1; } - /* content-type level (text/html only?) */ + /* 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; @@ -1664,17 +1906,6 @@ static int is_variant_better(negotiation_state *neg, var_rec *variant, var_rec * return 1; } - /* encoding -- can only be 1 or 0, and if 0 we eliminated this - * variant at the start of this function. However we - * prefer variants with no encoding over those with encoding */ - if (best->content_encoding == NULL && variant->content_encoding) { - return 0; - } - if (best->content_encoding && variant->content_encoding == NULL) { - *p_bestq = q; - return 1; - } - /* charset */ if (variant->charset_quality < best->charset_quality) { return 0; @@ -1682,6 +1913,10 @@ static int is_variant_better(negotiation_state *neg, var_rec *variant, var_rec * /* If the best variant's charset is ISO-8859-1 and this variant has * the same charset quality, then we prefer this variant */ + /* XXX: TODO: this specific tie-breaker is not described in the + * documentation + */ + if (variant->charset_quality > best->charset_quality || ((variant->content_charset != NULL && *variant->content_charset != '\0' && @@ -1693,6 +1928,15 @@ static int is_variant_better(negotiation_state *neg, var_rec *variant, var_rec * 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)) { @@ -1700,7 +1944,8 @@ static int is_variant_better(negotiation_state *neg, var_rec *variant, var_rec * } /* ok, to get here means every thing turned out equal, except - * we have a shorter content length, so use this variant */ + * we have a shorter content length, so use this variant + */ *p_bestq = q; return 1; } @@ -1710,221 +1955,307 @@ 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 = na_not_applied; + enum algorithm_results algorithm_result; var_rec *avail_recs = (var_rec *) neg->avail_vars->elts; set_default_lang_quality(neg); /* - * Find the 'best' variant + * 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 + * 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); - /* Now find out if this variant is better than the current - * best, either using the network algorithm, or Apache's - * internal server-driven algorithm. Presumably other - * server-driven algorithms are possible, and could be - * implemented here. + /* Only do variant selection if we may actually choose a + * variant for the client */ + if (neg->may_choose) { - if (neg->use_transparent_neg) { - if (is_variant_better_na(neg, variant, best, &bestq)) { - best = variant; + /* 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; + 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_transparent_neg) { - if (neg->short_accept_headers) { - algorithm_result = na_list; - } - else { - /* From Holtman, result is: - * If variant & URI are not neigbors, list_ua or list_os - * Else - * If UA can do trans neg - * IF best is definite && best q > 0, choice_ua - * ELSE list_ua - * ELSE - * IF best q > 0, choose_os - * ELSE list_os (or forward_os on proxy) - */ + /* We now either have a best variant, or no best variant */ - /* assume variant and URI are neigbors (since URI in - * var map must be in same directory) */ - - if (neg->use_transparent_neg) { - algorithm_result = (best && best->definite) && (bestq > 0) - ? na_choice : na_list; - } - else { - algorithm_result = bestq > 0 ? na_choice : na_list; - } - } + 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 the Alternates and Vary headers, used if we are going to - * return 406 Not Acceptable status, a 300 Multiple Choice status, - * or a Choice response. - * - * 'type' is the result of the network algorithm, if applied. - * We do different things if the network algorithm was not applied - * (type == na_not_applied): no Alternates header, and Vary: - * does not include 'negotiate'. +/* 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. * - * We should also add a max-age lifetime for the Alternates header, - * but how long we we give it? Presumably this should be - * configurable in the map file. + * 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 na_result) + int alg_result) { - int j; + table *hdrs; var_rec *avail_recs = (var_rec *) neg->avail_vars->elts; - char *sample_type = NULL; - char *sample_language = NULL; + const char *sample_type = NULL; + const char *sample_language = NULL; const char *sample_encoding = NULL; - char *sample_charset = 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; - table *hdrs; + int j; - /* Put headers into err_headers_out, new send_http_header() - * outputs both headers_out and err_headers_out */ + /* 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]; - char *rec; - char qstr[6]; - long len; - char lenstr[22]; /* enough for 2^64 */ - ap_snprintf(qstr, sizeof(qstr), "%1.3f", variant->type_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'; - } - } + if (variant->content_languages && variant->content_languages->nelts) { + lang = ap_array_pstrcat(r->pool, variant->content_languages, ','); + } + else { + lang = NULL; } - rec = ap_pstrcat(r->pool, "{\"", variant->file_name, "\" ", qstr, NULL); - if (variant->type_name) { - if (*variant->type_name) { - rec = ap_pstrcat(r->pool, rec, " {type ", - variant->type_name, "}", NULL); - } - if (!sample_type) { - sample_type = variant->type_name; - } - else if (strcmp(sample_type, variant->type_name)) { + /* 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 (variant->content_languages && variant->content_languages->nelts) { - char *langs = merge_string_array(r->pool, - variant->content_languages, ","); - rec = ap_pstrcat(r->pool, rec, " {language ", langs, "}", NULL); - if (!sample_language) { - sample_language = langs; + if (!vary_by_charset && + strcmp(sample_charset ? sample_charset : "", + variant->content_charset ? + variant->content_charset : "")) { + vary_by_charset = 1; } - else if (strcmp(sample_language, langs)) { + if (!vary_by_language && + strcmp(sample_language ? sample_language : "", + lang ? lang : "")) { vary_by_language = 1; } - } - if (variant->content_encoding) { - if (!sample_encoding) { - sample_encoding = variant->content_encoding; - } - else if (strcmp(sample_encoding, variant->content_encoding)) { + if (!vary_by_encoding && + strcmp(sample_encoding ? sample_encoding : "", + variant->content_encoding ? + variant->content_encoding : "")) { vary_by_encoding = 1; } } - if (variant->content_charset) { - if (*variant->content_charset) { - rec = ap_pstrcat(r->pool, rec, " {charset ", - variant->content_charset, "}", NULL); - } - if (!sample_charset) { - sample_charset = variant->content_charset; - } - else if (strcmp(sample_charset, variant->content_charset)) { - vary_by_charset = 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'; + } } } - if ((len = find_content_length(neg, variant)) != 0) { - ap_snprintf(lenstr, sizeof(lenstr), "%ld", len); - rec = ap_pstrcat(r->pool, rec, " {length ", lenstr, "}", NULL); - } + *((const char **) ap_push_array(arr)) = qstr; - rec = ap_pstrcat(r->pool, rec, "}", NULL); - - if (na_result != na_not_applied) { - ap_table_mergen(hdrs, "Alternates", rec); + 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')); + } + + /* Theoretically the negotiation result _always_ has a dependence on + * the contents of the Accept header because we do 'mxb=' + * processing in set_accept_quality(). However, variations in mxb + * only affect the relative quality of several acceptable variants, + * so there is no reason to worry about an unacceptable variant + * being mistakenly prioritized. We therefore ignore mxb in deciding + * whether or not to include Accept in the Vary field value. + */ + if (neg->is_transparent || vary_by_type || vary_by_language || + vary_by_language || vary_by_charset || vary_by_encoding) { - if (na_result != na_not_applied) { - ap_table_mergen(hdrs, "Vary", "negotiate"); + 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 (vary_by_type) { - ap_table_mergen(hdrs, "Vary", "accept"); - } - if (vary_by_language) { - ap_table_mergen(hdrs, "Vary", "accept-language"); - } - if (vary_by_charset) { - ap_table_mergen(hdrs, "Vary", "accept-charset"); - } - if (vary_by_encoding && na_result == na_not_applied) { - ap_table_mergen(hdrs, "Vary", "accept-encoding"); + + 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 - * 300 or 406 status body. + * choice response or 406 status body. */ -/* XXX: this is disgusting, this has O(n^2) behaviour! -djg */ static char *make_variant_list(request_rec *r, negotiation_state *neg) { + array_header *arr; int i; - char *t; + 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"; - t = ap_pstrdup(r->pool, "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 : ""; @@ -1932,27 +2263,39 @@ static char *make_variant_list(request_rec *r, negotiation_state *neg) 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'). */ - t = ap_pstrcat(r->pool, t, "<li><a href=\"", filename, "\">", - filename, "</a> ", description, NULL); - if (variant->type_name && *variant->type_name) { - t = ap_pstrcat(r->pool, t, ", type ", variant->type_name, NULL); + * 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) { - t = ap_pstrcat(r->pool, t, ", language ", - merge_string_array(r->pool, languages, ", "), - NULL); + *((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) { - t = ap_pstrcat(r->pool, t, ", charset ", variant->content_charset, - NULL); + *((const char **) ap_push_array(arr)) = ", charset "; + *((const char **) ap_push_array(arr)) = variant->content_charset; } - t = ap_pstrcat(r->pool, t, "\n", NULL); + 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"; } - t = ap_pstrcat(r->pool, t, "</ul>\n", NULL); + *((const char **) ap_push_array(arr)) = "</ul>\n"; - return t; + return ap_array_pstrcat(r->pool, arr, '\0'); } static void store_variant_list(request_rec *r, negotiation_state *neg) @@ -1962,17 +2305,18 @@ static void store_variant_list(request_rec *r, negotiation_state *neg) } else { ap_table_setn(r->main->notes, "variant-list", - make_variant_list(r->main, neg)); + make_variant_list(r->main, neg)); } } -/* Called if we got a "Choice" response from the network algorithm. +/* 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) +static int setup_choice_response(request_rec *r, negotiation_state *neg, + var_rec *variant) { request_rec *sub_req; const char *sub_vary; @@ -1982,7 +2326,9 @@ static int setup_choice_response(request_rec *r, negotiation_state *neg, var_rec sub_req = ap_sub_req_lookup_file(variant->file_name, r); status = sub_req->status; - if (status != HTTP_OK && status != HTTP_MULTIPLE_CHOICES) { + + if (status != HTTP_OK && + !ap_table_get(sub_req->err_headers_out, "TCN")) { ap_destroy_sub_req(sub_req); return status; } @@ -1992,27 +2338,89 @@ static int setup_choice_response(request_rec *r, negotiation_state *neg, var_rec sub_req = variant->sub_req; } - /* The network algorithm told us to return a "Choice" + /* 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 not itself return a "List" or "Choice" response. + * variant did or will not itself engage in transparent negotiation. * If not, set the appropriate headers, and fall through to * the normal variant handling */ - if ((sub_req->status == HTTP_MULTIPLE_CHOICES) || - (ap_table_get(sub_req->err_headers_out, "Alternates")) || - (ap_table_get(sub_req->err_headers_out, "Content-Location"))) { + /* 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, na_choice); /* add Alternates and Vary */ - /* to do: add Expires */ + 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; } @@ -2022,69 +2430,181 @@ static int setup_choice_response(request_rec *r, negotiation_state *neg, var_rec * Executive... */ -static int handle_map_file(request_rec *r) +static int do_negotiation(request_rec *r, negotiation_state *neg, + var_rec **bestp, int prefer_scripts) { - negotiation_state *neg = parse_accept_headers(r); - var_rec *best; + var_rec *avail_recs = (var_rec *) neg->avail_vars->elts; + int alg_result; /* result of variant selection algorithm */ int res; - int na_result; + int j; + int unencoded_variants = 0; - char *udir; + /* Decide if resource is transparently negotiable */ - if ((res = read_type_map(neg, r))) { - return res; + /* 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 (!variant->content_encoding) + unencoded_variants++; + } + + /* If there are less than 2 unencoded variants, we always + * switch to server-driven negotiation, regardless of whether + * we are contacted by a client capable of transparent + * negotiation. We do this because our current TCN + * implementation does not deal well with the case of having 0 + * or 1 unencoded variants. + */ + if (unencoded_variants < 2) + neg->is_transparent = 0; } - maybe_add_default_encodings(neg, 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); - na_result = best_match(neg, &best); + alg_result = best_match(neg, bestp); - /* na_result is one of - * na_not_applied: we didn't use the network algorithm - * na_choice: return a "Choice" response - * na_list: return a "List" response (no variant chosen) + /* alg_result is one of + * alg_choice: a best variant is chosen + * alg_list: no best variant is chosen */ - if (na_result == na_list) { - set_neg_headers(r, neg, na_list); + 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); - return MULTIPLE_CHOICES; + + 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; + } } - if (!best) { - ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, - "no acceptable variant: %s", r->filename); + /* Variant selection chose a variant */ - set_neg_headers(r, neg, na_result); - store_variant_list(r, neg); - return NOT_ACCEPTABLE; - } + /* XXX todo: merge the two cases in the if statement below */ + if (neg->is_transparent) { - if (na_result == na_choice) { - if ((res = setup_choice_response(r, neg, best)) != 0) { - return res; + 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. NB that we merge the - * header in case some other module negotiates on something else. + * HTTP/1.0, we can't allow caching at all. */ - if (!do_cache_negotiated_docs(r->server) && (r->proto_num < HTTP_VERSION(1,1))) { + + /* 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; } - if (na_result == na_not_applied) { - set_neg_headers(r, neg, na_not_applied); + 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 = escape_uri(r->pool, udir); - ap_internal_redirect(ap_pstrcat(r->pool, udir, best->file_name, r->path_info, - NULL), r); + 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; } @@ -2095,7 +2615,6 @@ static int handle_multi(request_rec *r) request_rec *sub_req; int res; int j; - int na_result; /* result of network algorithm */ if (r->finfo.st_mode != 0 || !(ap_allow_options(r) & OPT_MULTI)) { return DECLINED; @@ -2119,40 +2638,11 @@ static int handle_multi(request_rec *r) return DECLINED; } - maybe_add_default_encodings(neg, - (r->method_number != M_GET) || - r->args || r->path_info); - - na_result = best_match(neg, &best); - if (na_result == na_list) { - /* - * Network algorithm tols us to output a "List" response. - * This is output at a 300 status code, which we will - * return. The list of variants will be stored in r->notes - * under the name "variants-list". - */ - set_neg_headers(r, neg, na_list); /* set Alternates: and Vary: */ - - store_variant_list(r, neg); - res = MULTIPLE_CHOICES; - goto return_from_multi; - } - - if (!best) { - ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, - "no acceptable variant: %s", r->filename); - - set_neg_headers(r, neg, na_result); - store_variant_list(r, neg); - res = NOT_ACCEPTABLE; + 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 (na_result == na_choice) { - if ((res = setup_choice_response(r, neg, best)) != 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 @@ -2167,7 +2657,7 @@ static int handle_multi(request_rec *r) } } - /* BLETCH --- don't multi-resolve non-ordinary files */ + /* BLECH --- don't multi-resolve non-ordinary files */ if (!S_ISREG(sub_req->finfo.st_mode)) { res = NOT_FOUND; @@ -2176,15 +2666,6 @@ static int handle_multi(request_rec *r) /* Otherwise, use it. */ - if ((!do_cache_negotiated_docs(r->server) && (r->proto_num < HTTP_VERSION(1,1))) - && neg->count_multiviews_variants != 1) { - r->no_cache = 1; - } - - if (na_result == na_not_applied) { - set_neg_headers(r, neg, na_not_applied); - } - /* 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 @@ -2192,6 +2673,7 @@ static int handle_multi(request_rec *r) * 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; @@ -2218,7 +2700,8 @@ static int handle_multi(request_rec *r) return OK; } -/* There is a problem with content-encoding, as some clients send and +/********************************************************************** + * 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 @@ -2248,12 +2731,15 @@ static int fix_encoding(request_rec *r) enc += 2; } - accept_encodings = do_header_line(r->pool, - ap_table_get(r->headers_in, "Accept-encoding")); + 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].type_name; + char *name = accept_recs[i].name; if (!strcmp(name, enc)) { r->content_encoding = name; @@ -2284,7 +2770,7 @@ module MODULE_VAR_EXPORT negotiation_module = { STANDARD_MODULE_STUFF, NULL, /* initializer */ - create_neg_dir_config, /* dir config creater */ + create_neg_dir_config, /* dir config creator */ merge_neg_dir_configs, /* dir merger --- default is to override */ NULL, /* server config */ NULL, /* merge server config */ diff --git a/usr.sbin/httpd/src/modules/standard/mod_rewrite.c b/usr.sbin/httpd/src/modules/standard/mod_rewrite.c index 5ae1cd591b8..41db2358cb7 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_rewrite.c +++ b/usr.sbin/httpd/src/modules/standard/mod_rewrite.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1996-1998 The Apache Group. All rights reserved. + * 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 @@ -192,11 +192,11 @@ module MODULE_VAR_EXPORT rewrite_module = { hook_uri2file, /* [#1] URI to filename translation */ NULL, /* [#4] validate user id from request */ NULL, /* [#5] check if the user is ok _here_ */ - NULL, /* [#2] check access by host address */ + 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, /* [#3] header parser */ + NULL, /* [#2] header parser */ init_child, /* child_init */ NULL, /* child_exit */ NULL /* [#0] post read-request */ @@ -501,6 +501,12 @@ static const char *cmd_rewritemap(cmd_parms *cmd, void *dconf, char *a1, 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); @@ -708,6 +714,7 @@ static const char *cmd_rewriterule(cmd_parms *cmd, rewrite_perdir_conf *dconf, char *a3; char *cp; const char *err; + int mode; sconf = (rewrite_server_conf *) ap_get_module_config(cmd->server->module_config, &rewrite_module); @@ -726,16 +733,32 @@ static const char *cmd_rewriterule(cmd_parms *cmd, rewrite_perdir_conf *dconf, "'\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 */ - new->flags = RULEFLAG_NONE; cp = a1; if (cp[0] == '!') { new->flags |= RULEFLAG_NOTMATCH; cp++; } - if ((regexp = ap_pregcomp(cmd->pool, cp, REG_EXTENDED)) == NULL) { + 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); @@ -749,18 +772,6 @@ static const char *cmd_rewriterule(cmd_parms *cmd, rewrite_perdir_conf *dconf, */ new->output = ap_pstrdup(cmd->pool, a2); - /* arg3: optional flags field */ - new->forced_mimetype = NULL; - new->forced_responsecode = HTTP_MOVED_TEMPORARILY; - new->env[0] = NULL; - new->skip = 0; - if (a3 != NULL) { - if ((err = cmd_rewriterule_parseflagfield(cmd->pool, new, - a3)) != NULL) { - return err; - } - } - /* now, if the server or per-dir config holds an * array of RewriteCond entries, we take it for us * and clear the array @@ -917,6 +928,10 @@ static const char *cmd_rewriterule_setflag(pool *p, rewriterule_entry *cfg, || 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); } @@ -1145,7 +1160,7 @@ static int hook_uri2file(request_rec *r) ; if (*cp != '\0') { rewritelog(r, 1, "escaping %s for redirect", r->filename); - cp2 = escape_uri(r->pool, cp); + cp2 = ap_escape_uri(r->pool, cp); *cp = '\0'; r->filename = ap_pstrcat(r->pool, r->filename, cp2, NULL); } @@ -1434,7 +1449,7 @@ static int hook_fixup(request_rec *r) if (*cp != '\0') { rewritelog(r, 1, "[per-dir %s] escaping %s for redirect", dconf->directory, r->filename); - cp2 = escape_uri(r->pool, cp); + cp2 = ap_escape_uri(r->pool, cp); *cp = '\0'; r->filename = ap_pstrcat(r->pool, r->filename, cp2, NULL); } @@ -2877,12 +2892,13 @@ static char *lookup_map_dbmfile(request_rec *r, char *file, char *key) char buf[MAX_STRING_LEN]; dbmkey.dptr = key; - dbmkey.dsize = (strlen(key) < sizeof(buf) - 1 ? - strlen(key) : sizeof(buf)-1); + 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); + memcpy(buf, dbmval.dptr, + dbmval.dsize < sizeof(buf)-1 ? + dbmval.dsize : sizeof(buf)-1 ); buf[dbmval.dsize] = '\0'; value = ap_pstrdup(r->pool, buf); } @@ -2966,6 +2982,23 @@ static char *rewrite_mapfunc_tolower(request_rec *r, char *key) 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) diff --git a/usr.sbin/httpd/src/modules/standard/mod_rewrite.h b/usr.sbin/httpd/src/modules/standard/mod_rewrite.h index 2fb8a20ee97..323f0af2974 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_rewrite.h +++ b/usr.sbin/httpd/src/modules/standard/mod_rewrite.h @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1996-1998 The Apache Group. All rights reserved. + * 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 @@ -202,6 +202,7 @@ #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 @@ -427,6 +428,8 @@ static char *lookup_map_internal(request_rec *r, 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); diff --git a/usr.sbin/httpd/src/modules/standard/mod_setenvif.c b/usr.sbin/httpd/src/modules/standard/mod_setenvif.c index 005b0d30aa7..24841852946 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_setenvif.c +++ b/usr.sbin/httpd/src/modules/standard/mod_setenvif.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1996-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/modules/standard/mod_so.c b/usr.sbin/httpd/src/modules/standard/mod_so.c index 4066882dc63..80ac4bcb673 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_so.c +++ b/usr.sbin/httpd/src/modules/standard/mod_so.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -125,6 +125,7 @@ */ +#define CORE_PRIVATE #include "httpd.h" #include "http_config.h" #include "http_log.h" @@ -246,13 +247,23 @@ static const char *load_module(cmd_parms *cmd, void *dummy, * symbol name. */ if (!(modp = (module *)(ap_os_dso_sym(modhandle, modname)))) { - return ap_pstrcat(cmd->pool, "Can't find module ", modname, - " in file ", filename, ":", ap_os_dso_error(), NULL); + 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 = 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); @@ -266,15 +277,9 @@ static const char *load_module(cmd_parms *cmd, void *dummy, (void (*)(void*))unload_module, ap_null_cleanup); /* - * Finally we need to run the configuration functions - * in new modules now. + * Finally we need to run the configuration process for the module */ - 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); + ap_single_module_configure(cmd->pool, cmd->server, modp); return NULL; } diff --git a/usr.sbin/httpd/src/modules/standard/mod_speling.c b/usr.sbin/httpd/src/modules/standard/mod_speling.c index 7d1b976d639..a9f94d7fc16 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_speling.c +++ b/usr.sbin/httpd/src/modules/standard/mod_speling.c @@ -1,6 +1,6 @@ #define WANT_BASENAME_MATCH /* ==================================================================== - * Copyright (c) 1996-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/modules/standard/mod_status.c b/usr.sbin/httpd/src/modules/standard/mod_status.c index 31e9aa41abb..bba554526c0 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_status.c +++ b/usr.sbin/httpd/src/modules/standard/mod_status.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -254,6 +254,7 @@ static int status_handler(request_rec *r) 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; @@ -487,6 +488,10 @@ static int status_handler(request_rec *r) 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 @@ -652,7 +657,8 @@ static int status_handler(request_rec *r) else ap_rprintf(r, "<td>%s<td nowrap>%s<td nowrap>%s</tr>\n\n", - score_record.client, score_record.vhost, + score_record.client, + vhost ? vhost->server_hostname : "(unavailable)", ap_escape_html(r->pool, score_record.request)); } /* no_table_report */ } /* !short_report */ diff --git a/usr.sbin/httpd/src/modules/standard/mod_unique_id.c b/usr.sbin/httpd/src/modules/standard/mod_unique_id.c index d774b96f8b8..6e103942bd3 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_unique_id.c +++ b/usr.sbin/httpd/src/modules/standard/mod_unique_id.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/modules/standard/mod_userdir.c b/usr.sbin/httpd/src/modules/standard/mod_userdir.c index 37bb9140007..9aea9ce9dd2 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_userdir.c +++ b/usr.sbin/httpd/src/modules/standard/mod_userdir.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/modules/standard/mod_usertrack.c b/usr.sbin/httpd/src/modules/standard/mod_usertrack.c index 8c1d145ead9..fbf800b4dab 100644 --- a/usr.sbin/httpd/src/modules/standard/mod_usertrack.c +++ b/usr.sbin/httpd/src/modules/standard/mod_usertrack.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/os/bs2000/bs2login.c b/usr.sbin/httpd/src/os/bs2000/bs2login.c index afba7fd928b..f76c536221e 100644 --- a/usr.sbin/httpd/src/os/bs2000/bs2login.c +++ b/usr.sbin/httpd/src/os/bs2000/bs2login.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -59,51 +59,182 @@ #include "httpd.h" #include "http_config.h" #include "http_log.h" +#include <ctype.h> +#include <sys/utsname.h> + +#define ACCT_LEN 8 +#define USER_LEN 8 static const char *bs2000_account = NULL; +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; + } +} + /* 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) { - bs2000_account = ap_pstrdup(p, 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; } -int os_init_job_environment(server_rec *server, const char *user_name) +/* 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]; + int save_errno; /* 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. + */ /* 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", + "No BS2000Account configured - cannot switch to User %s", user_name); exit(APEXIT_CHILDFATAL); } - inittask.username = user_name; + /* The one_process test is placed _behind_ the BS2000Account test + * because we never want the user to forget configuring an account. + */ + if (one_process) { + 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; + } + + 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 use can switch identities. */ if (_rini(&inittask) != 0) { + save_errno = errno; + ap_log_error(APLOG_MARK, APLOG_ALERT, server, "_rini: BS2000 auth failed for user \"%s\" acct \"%s\"", inittask.username, inittask.account); + + if (save_errno == EAGAIN) { + /* This funny error code does NOT mean that the operation should + * be retried. Instead it means that authentication failed + * because of possibly incompatible `JOBCLASS'es between + * the calling (SYSROOT) and the target non-privileged user id. + * Help the administrator by logging a hint. + */ + char *curr_user, curr_uid[L_cuserid]; + + if ((curr_user = cuserid(curr_uid)) == NULL) { + /* This *SHOULD* not occur. But if it does, deal with it. */ + ap_snprintf(curr_uid, sizeof curr_uid, "#%u", getuid()); + curr_user = curr_uid; + } + + ap_log_error(APLOG_MARK, APLOG_ALERT|APLOG_NOERRNO, server, + "_rini: Hint: Possible reason: JOBCLASS of user %s " + "not compatible with that of user %s ?", + curr_user, inittask.username); + } exit(APEXIT_CHILDFATAL); } return 0; } +/* BS2000 requires a "special" version of fork() before a setuid()/_rini() call */ +/* Additionally, there's an OS release dependency here :-((( */ +/* I'm sorry, but there was no other way to make it work. -Martin */ +pid_t os_fork(void) +{ + struct utsname os_version; + + /* + * When we run as a normal user (and bypass setuid() and _rini()), + * we use the regular fork(). + */ + if (getuid() != 0) { + return fork(); + } + + if (uname(&os_version) >= 0) + { + /* + * Old versions (before XPG4 SPEC1170) don't work with Apache + * and they require a fork(), not a _rfork() + */ + if (strcmp(os_version.release, "01.0A") == 0 || + strcmp(os_version.release, "02.0A") == 0 || + strcmp(os_version.release, "02.1A") == 0) + { + return fork(); + } + + /* The following versions are special: + * OS versions before A17 work with regular fork() only, + * later versions with _rfork() only. + */ + 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) + { + return (strcmp (os_version.version, "A17") < 0) + ? fork() : _rfork(); + } + } + + /* All later OS versions will require _rfork() + * to prepare for authorization with _rini() + */ + return _rfork(); +} + #else /* _OSD_POSIX */ void bs2login_is_not_here() { diff --git a/usr.sbin/httpd/src/os/bs2000/ebcdic.c b/usr.sbin/httpd/src/os/bs2000/ebcdic.c index 4a268488de8..0303fc6dbb7 100644 --- a/usr.sbin/httpd/src/os/bs2000/ebcdic.c +++ b/usr.sbin/httpd/src/os/bs2000/ebcdic.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/os/bs2000/os.c b/usr.sbin/httpd/src/os/bs2000/os.c index 428910c2ce4..c33810a2f0d 100644 --- a/usr.sbin/httpd/src/os/bs2000/os.c +++ b/usr.sbin/httpd/src/os/bs2000/os.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/os/bs2000/os.h b/usr.sbin/httpd/src/os/bs2000/os.h index 2185aec0389..93be8ee3d20 100644 --- a/usr.sbin/httpd/src/os/bs2000/os.h +++ b/usr.sbin/httpd/src/os/bs2000/os.h @@ -16,6 +16,9 @@ * part of the header */ #define INLINE extern ap_inline + +INLINE int ap_os_is_path_absolute(const char *file); + #include "os-inline.c" #endif @@ -23,12 +26,17 @@ /* Compiler does not support inline, so prototype the inlineable functions * as normal */ -extern int ap_os_is_path_absolute(const char *f); +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) + /* 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(void); #endif /*! APACHE_OS_H*/ diff --git a/usr.sbin/httpd/src/os/os2/os.h b/usr.sbin/httpd/src/os/os2/os.h index bcee32439d1..0aa5a6f1fe2 100644 --- a/usr.sbin/httpd/src/os/os2/os.h +++ b/usr.sbin/httpd/src/os/os2/os.h @@ -15,6 +15,9 @@ * part of the header */ #define INLINE extern __inline__ + +INLINE int ap_os_is_path_absolute(const char *file); + #include "os-inline.c" #endif @@ -22,9 +25,12 @@ /* Compiler does not support inline, so prototype the inlineable functions * as normal */ -extern int ap_os_is_path_absolute(const char *f); +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) + /* OS/2 doesn't have symlinks so S_ISLNK is always false */ #define S_ISLNK(m) 0 diff --git a/usr.sbin/httpd/src/os/unix/os-aix-dso.c b/usr.sbin/httpd/src/os/unix/os-aix-dso.c index 6f4176d565e..45d9db531aa 100644 --- a/usr.sbin/httpd/src/os/unix/os-aix-dso.c +++ b/usr.sbin/httpd/src/os/unix/os-aix-dso.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/os/unix/os.h b/usr.sbin/httpd/src/os/unix/os.h index 9f14b7c37ac..496cfa9f9e8 100644 --- a/usr.sbin/httpd/src/os/unix/os.h +++ b/usr.sbin/httpd/src/os/unix/os.h @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1998 The Apache Group. All rights reserved. + * 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 @@ -73,6 +73,9 @@ * part of the header */ #define INLINE extern ap_inline + +INLINE int ap_os_is_path_absolute(const char *file); + #include "os-inline.c" #else @@ -80,9 +83,13 @@ /* Compiler does not support inline, so prototype the inlineable functions * as normal */ -extern int ap_os_is_path_absolute(const char *f); +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) + /* * Abstraction layer for loading * Apache modules under run-time via @@ -121,7 +128,9 @@ const char *dlerror(void); #define RTLD_GLOBAL 0 #endif -#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) +#if (defined(__FreeBSD__) ||\ + defined(__OpenBSD__) ||\ + defined(__NetBSD__) ) && !defined(__ELF__) #define DLSYM_NEEDS_UNDERSCORE #endif diff --git a/usr.sbin/httpd/src/os/win32/installer/apache.iwz b/usr.sbin/httpd/src/os/win32/installer/apache.iwz index 8b33a1f11c6..d9e6a9d18db 100644 --- a/usr.sbin/httpd/src/os/win32/installer/apache.iwz +++ b/usr.sbin/httpd/src/os/win32/installer/apache.iwz @@ -36,6 +36,7 @@ PACKLIST.EXE Ver=3.00.060 Version=2.02 DevTool=Generic Windows Platform=Win32 +DisksBuilt=1 DisksDir=apache\650MB\ TabsVisit=1111001110000111100011 LangNum=451 @@ -45,9 +46,9 @@ LangDir=LANG\ENG\ AppName=Apache AppExe= AppExeFile= -Version=1.3.2 +Version=1.3.3 Company=Apache Group -Title=Apache Web Server 1.3.2 +Title=Apache Web Server 1.3.3 TitleType=1 BackgrndBmp= BackgrndAlign=4 @@ -98,7 +99,7 @@ Component6GroupList=26 28 29 30 [Groups] Groups=30 -Group1Size=325379 +Group1Size=328050 Group1Files=9 Group1Name=Program Executables Group1Dir=<INSTALLDIR> @@ -129,7 +130,7 @@ 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=38680 +Group3Size=38714 Group3Files=6 Group3Name=Configuration Files Group3Dir=<INSTALLDIR>\.tmp @@ -149,8 +150,8 @@ Group4Update=1 Group4TargetOS=-1 Group4File1=C:\Apache\htdocs\index.html Group4File2=C:\apache\htdocs\apache_pb.gif -Group5Size=255387 -Group5Files=32 +Group5Size=253396 +Group5Files=31 Group5Name=Manual Group5Dir=<INSTALLDIR>\htdocs\manual Group5Update=0 @@ -186,7 +187,6 @@ 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\expand.pl Group6Size=42478 Group6Files=8 Group6Name=images @@ -201,7 +201,7 @@ 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=318711 +Group7Size=321048 Group7Files=22 Group7Name=misc Group7Dir=[Manual]\misc @@ -229,7 +229,7 @@ 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=528312 +Group8Size=531149 Group8Files=48 Group8Name=mod Group8Dir=[Manual]\mod @@ -301,8 +301,8 @@ 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 -Group10Size=463442 -Group10Files=18 +Group10Size=463830 +Group10Files=17 Group10Name=src Group10Dir=<INSTALLDIR>\src Group10Update=0 @@ -324,7 +324,6 @@ 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\INDENT Group11Size=68859 Group11Files=10 Group11Name=ap @@ -341,7 +340,7 @@ Group11File7=C:\Apache\src\ap\ap_snprintf.c Group11File8=C:\Apache\src\ap\Makefile.tmpl Group11File9=C:\apache\src\ap\.indent.pro Group11File10=C:\apache\src\ap\ap_fnmatch.c -Group12Size=245636 +Group12Size=246696 Group12Files=30 Group12Name=include Group12Dir=[src]\include @@ -377,7 +376,7 @@ Group12File27=C:\apache\src\include\ap_config.h Group12File28=C:\apache\src\include\ap_ctype.h Group12File29=C:\apache\src\include\.indent.pro Group12File30=C:\apache\src\include\ap_mmn.h -Group13Size=759628 +Group13Size=771650 Group13Files=24 Group13Name=main Group13Dir=[src]\main @@ -459,7 +458,7 @@ Group18File9=C:\apache\src\modules\proxy\proxy_connect.c Group18File10=C:\apache\src\modules\proxy\proxy_ftp.c Group18File11=C:\apache\src\modules\proxy\proxy_http.c Group18File12=C:\apache\src\modules\proxy\proxy_util.c -Group19Size=827909 +Group19Size=831125 Group19Files=37 Group19Name=standard Group19Dir=[modules]\standard @@ -533,7 +532,7 @@ 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=182616 +Group21Size=182644 Group21Files=27 Group21Name=support Group21Dir=[src]\support @@ -572,7 +571,7 @@ Group22Name=os Group22Dir=[src]\os Group22Update=0 Group22TargetOS=-1 -Group23Size=198555 +Group23Size=199605 Group23Files=43 Group23Name=win32 Group23Dir=[os]\win32 @@ -806,7 +805,7 @@ Reg9Val1Type=0 Reg9Val1Name=(Default) Reg9Val1Data=(value not set) Reg9Vals=1 -Reg10Path=HKEY_LOCAL_MACHINE\SOFTWARE\Apache Group\Apache\1.3.2 +Reg10Path=HKEY_LOCAL_MACHINE\SOFTWARE\Apache Group\Apache\1.3.3 Reg10Val1Type=0 Reg10Val1Name=(Default) Reg10Val1Data=(value not set) @@ -820,8 +819,8 @@ Regs=10 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.2 -Reg5Path=HKEY_LOCAL_MACHINE\SOFTWARE\Apache Group\Apache\1.3.2 +Reg4Path=HKEY_LOCAL_MACHINE\SOFTWARE\Apache Group\Apache\1.3.3 +Reg5Path=HKEY_LOCAL_MACHINE\SOFTWARE\Apache Group\Apache\1.3.3 Reg5ValName=ServerRoot Reg5ValType=0 Reg5ValData=<INSTALLDIR> diff --git a/usr.sbin/httpd/src/os/win32/mod_dll.c b/usr.sbin/httpd/src/os/win32/mod_dll.c index 858fdf5482c..72bbba1ea9b 100644 --- a/usr.sbin/httpd/src/os/win32/mod_dll.c +++ b/usr.sbin/httpd/src/os/win32/mod_dll.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 diff --git a/usr.sbin/httpd/src/os/win32/mod_isapi.c b/usr.sbin/httpd/src/os/win32/mod_isapi.c index 6da016a9db4..fa002708ba5 100644 --- a/usr.sbin/httpd/src/os/win32/mod_isapi.c +++ b/usr.sbin/httpd/src/os/win32/mod_isapi.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -463,7 +463,7 @@ BOOL WINAPI ServerSupportFunction (HCONN hConn, DWORD dwHSERequest, while (*value && ap_isspace(*value)) ++value; /* Check all the special-case headers. Similar to what - * scan_script_header() does (see that function for + * ap_scan_script_header_err() does (see that function for * more detail) */ diff --git a/usr.sbin/httpd/src/os/win32/os.h b/usr.sbin/httpd/src/os/win32/os.h index 8874f1f1de6..da4dd739050 100644 --- a/usr.sbin/httpd/src/os/win32/os.h +++ b/usr.sbin/httpd/src/os/win32/os.h @@ -93,6 +93,8 @@ __inline int ap_os_is_path_absolute(const char *file) #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); @@ -103,6 +105,10 @@ API_EXPORT(int) os_spawnve(int mode,const char *cmdname,const char *const *argv, #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 */ diff --git a/usr.sbin/httpd/src/os/win32/registry.c b/usr.sbin/httpd/src/os/win32/registry.c index 665f8ee67e7..0e54ca89811 100644 --- a/usr.sbin/httpd/src/os/win32/registry.c +++ b/usr.sbin/httpd/src/os/win32/registry.c @@ -28,7 +28,7 @@ #define VENDOR "Apache Group" #define SOFTWARE "Apache" -#define VERSION "1.3.3" +#define VERSION "1.3.4" #define REGKEY "SOFTWARE\\" VENDOR "\\" SOFTWARE "\\" VERSION diff --git a/usr.sbin/httpd/src/os/win32/util_win32.c b/usr.sbin/httpd/src/os/win32/util_win32.c index 3aac08767ce..249faf28e6a 100644 --- a/usr.sbin/httpd/src/os/win32/util_win32.c +++ b/usr.sbin/httpd/src/os/win32/util_win32.c @@ -1,216 +1,279 @@ #include <windows.h> #include <sys/stat.h> #include <stdarg.h> +#include <time.h> +#include <stdlib.h> #include "httpd.h" #include "http_log.h" -/* Returns TRUE if the path is real, FALSE if it is PATH_INFO */ -static BOOL sub_canonical_filename(char *szCanon, unsigned nCanon, - const char *szInFile) +/* 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]; - int n; - char *szFilePart; - char *s; - int nSlashes; - WIN32_FIND_DATA d; - HANDLE h; - const char *szFile; - - szFile = szInFile; - s = strrchr(szFile, '\\'); - for (nSlashes = 0; s > szFile && s[-1] == '\\'; ++nSlashes, --s) - ; - - if (strlen(szFile)==2 && szFile[1]==':') { - /* - * If the file name is x:, do not call GetFullPathName - * because it will use the current path of the executable - */ - strcpy(buf,szFile); - n = strlen(buf); - szFilePart = buf + n; + 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 = '\\'; } - else { - n = GetFullPathName(szFile, sizeof buf, buf, &szFilePart); + + 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; } - ap_assert(n); - ap_assert(n < sizeof buf); - - /* - * There is an implicit assumption that szInFile will contain a '\'. - * If this is not true (as in the case of <Directory *> or - * <File .htaccess>) we would assert in some of the code below. Therefore, - * if we don't get any '\' in the file name, then use the file name we get - * from GetFullPathName, because it will have at least one '\'. If there - * is no '\' in szInFile, it must just be a file name, so it should be - * valid to use the name from GetFullPathName. Be sure to adjust the - * 's' variable so the rest of the code functions normally. - * Note it is possible to get here when szFile == 'x:', but that is OK - * because we will bail out of this routine early. - */ - if (!s) { - szFile = buf; - s = strrchr(szFile, '\\'); + + 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; + } } - /* If we have \\machine\share, convert to \\machine\share\ */ - if (buf[0] == '\\' && buf[1] == '\\') { - char *s = strchr(buf + 2, '\\'); - if (s && !strchr(s + 1, '\\')) { - strcat(s + 1, "\\"); - } - } + p = strchr(p, '\\'); - if (!strchr(buf, '*') && !strchr(buf, '?')) { - h = FindFirstFile(buf, &d); - if (h != INVALID_HANDLE_VALUE) { - FindClose(h); - } - } - else { - h = INVALID_HANDLE_VALUE; - } + while (!bDone) { + if (p) + *p = '\0'; - if (szFilePart < buf + 3) { - ap_assert(strlen(buf) < nCanon); - strcpy(szCanon, buf); - /* a \ at the start means it is UNC, otherwise it is x: */ - if (szCanon[0] != '\\') { - ap_assert(ap_isalpha(szCanon[0])); - ap_assert(szCanon[1] == ':'); - szCanon[2] = '/'; - } - else { - char *s; + if (strchr(q, '*') || strchr(q, '?')) + bFileExists = FALSE; - ap_assert(szCanon[1] == '\\'); - for (s = szCanon; *s; ++s) { - if (*s == '\\') { - *s = '/'; - } - } - } - return TRUE; - } - if (szFilePart != buf + 3) { - char b2[_MAX_PATH]; - char b3[_MAX_PATH]; - ap_assert(szFilePart > buf + 3); - /* avoid SEGVs on things like "Directory *" */ - ap_assert(s >= szFile && "this is a known bug"); - - memcpy(b3, szFile, s - szFile); - b3[s - szFile] = '\0'; - -/* szFilePart[-1] = '\0'; */ - sub_canonical_filename(b2, sizeof b2, b3); - - ap_assert(strlen(b2)+1 < nCanon); - strcpy(szCanon, b2); - strcat(szCanon, "/"); - } - else { - ap_assert(strlen(buf) < nCanon); - strcpy(szCanon, buf); - szCanon[2] = '/'; - szCanon[3] = '\0'; - } - if (h == INVALID_HANDLE_VALUE) { - ap_assert(strlen(szCanon) + strlen(szFilePart) + nSlashes < nCanon); - for (n = 0; n < nSlashes; ++n) { - strcat(szCanon, "/"); - } - strcat(szCanon, szFilePart); - return 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; + } } - else { - ap_assert(strlen(szCanon)+strlen(d.cFileName) < nCanon); - strlwr(d.cFileName); - strcat(szCanon, d.cFileName); - return 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); } -/* UNC requires backslashes, hence the conversion before canonicalisation. - * Not sure how * many backslashes (could be that - * \\machine\share\some/path/is/ok for example). For now, do them all. + +/* Perform canonicalization with the exception that the + * input case is preserved. */ -API_EXPORT(char *) ap_os_canonical_filename(pool *pPool, const char *szFile) +API_EXPORT(char *) ap_os_case_canonical_filename(pool *pPool, + const char *szFile) { - char buf[HUGE_STRING_LEN]; - char b2[HUGE_STRING_LEN]; - const char *s; - char *d; - int nSlashes = 0; - - ap_assert(strlen(szFile) < sizeof b2); - - /* Eliminate directories consisting of three or more dots. - * These act like ".." but are not detected by other machinery. - * Also get rid of trailing .s on any path component, which are ignored - * by the filesystem. Simultaneously, rewrite / to \. - * This is a bit of a kludge - Ben. + 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 '.' */ - if (strlen(szFile) == 1) { - /* - * If the file is only one char (like in the case of / or .) then - * just pass that through to sub_canonical_filename. Convert a - * '/' to '\\' if necessary. - */ - if (szFile[0] == '/') { - b2[0] = '\\'; - } + 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 { - b2[0] = szFile[0]; - } - - b2[1] = '\0'; + *p = *s; + } } - else { - for (s = szFile, d = b2; (*d = *s); ++d, ++s) { - if (*s == '/') { - *d = '\\'; - } - if (*s == '.' && (s[1] == '/' || s[1] == '\\' || !s[1])) { - while (*d == '.') { - --d; - } - if (*d == '\\') { - --d; - } - } - } + *p = '\0'; - /* Finally, a trailing slash(es) screws thing, so blow them away */ - for (nSlashes = 0; d > b2 && d[-1] == '\\'; --d, ++nSlashes) - ; - /* XXXX this breaks '/' and 'c:/' cases */ - *d = '\0'; - } - sub_canonical_filename(buf, sizeof buf, b2); + /* 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'; + - buf[0] = ap_tolower(buf[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); - if (nSlashes) { - /* - * If there were additional trailing slashes, add them back on. - * Be sure not to add more than were originally there though, - * by checking to see if sub_canonical_filename added one; - * this could happen in cases where the file name is 'd:/' + /* 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. */ - ap_assert(strlen(buf)+nSlashes < sizeof buf); + 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 (nSlashes && buf[strlen(buf)-1] == '/') - nSlashes--; - while (nSlashes--) { - strcat(buf, "/"); + if (p != NULL) { + pQstr = q; + pPstr = p; + *q++ = '/'; + *p++ = '/'; + } + + } while (p != NULL); + + pNewStr = ap_pstrdup(pPool, buf); } } - return 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 @@ -225,19 +288,12 @@ API_EXPORT(char *) ap_os_canonical_filename(pool *pPool, const char *szFile) API_EXPORT(int) os_stat(const char *szPath, struct stat *pStat) { int n; - - /* be sure it is has a drive letter or is a UNC path; everything - * _must_ be canonicalized before getting to this point. - */ - if (szPath[1] != ':' && szPath[1] != '/') { - ap_log_error(APLOG_MARK, APLOG_ERR, NULL, - "Invalid path in os_stat: \"%s\", " - "should have a drive letter or be a UNC path", - szPath); - return (-1); + + if (strlen(szPath) == 0) { + return -1; } - if (szPath[0] == '/') { + if (szPath[0] == '/' && szPath[1] == '/') { char buf[_MAX_PATH]; char *s; int nSlashes = 0; @@ -416,3 +472,205 @@ API_EXPORT(int) os_spawnle(int mode, const char *cmdname, ...) 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; + char 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) { + int idx; + 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] < 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 (!strnicmp(invalid_filenames[idx], segstart, baselength)) { + return 0; + } + } + } + } + + return 1; +} diff --git a/usr.sbin/httpd/src/regex/regcomp.c b/usr.sbin/httpd/src/regex/regcomp.c index 6e599eb64c7..b74d6fc96c1 100644 --- a/usr.sbin/httpd/src/regex/regcomp.c +++ b/usr.sbin/httpd/src/regex/regcomp.c @@ -1014,30 +1014,17 @@ register struct parse *p; nbytes = nc / CHAR_BIT * css; if (p->g->sets == NULL) p->g->sets = (cset *)malloc(nc * sizeof(cset)); - else { - cset *tmp; - tmp = (cset *)realloc((char *)p->g->sets, - nc * sizeof(cset)); - if (tmp == NULL) - free(p->g->sets); - - p->g->sets = tmp; - } + 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 { - uch *tmp; - tmp = (uch *)realloc((char *)p->g->setbits, - nbytes); - if (tmp == NULL) { - free(p->g->setbits); - p->g->setbits = tmp; - } - else { - p->g->setbits = tmp; - for (i = 0; i < no; i++) - p->g->sets[i].ptr = p->g->setbits + css*(i/CHAR_BIT); - } + 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), @@ -1173,13 +1160,8 @@ register char *cp; cs->smultis += strlen(cp) + 1; if (cs->multis == NULL) cs->multis = malloc(cs->smultis); - else { - char *tmp; - tmp = realloc(cs->multis, cs->smultis); - if (tmp == NULL) - free(cs->multis); - cs->multis = tmp; - } + else + cs->multis = realloc(cs->multis, cs->smultis); if (cs->multis == NULL) { SETERROR(REG_ESPACE); return; diff --git a/usr.sbin/httpd/src/regex/regex2.h b/usr.sbin/httpd/src/regex/regex2.h index 6ec57b2ed4e..e79497181a8 100644 --- a/usr.sbin/httpd/src/regex/regex2.h +++ b/usr.sbin/httpd/src/regex/regex2.h @@ -1,5 +1,19 @@ /* * 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(RHAPSODY) + = #define ap_private_extern __private_extern__ + = #else + = #define ap_private_extern + = #endif + = = typedef off_t regoff_t; = typedef struct { = int re_magic; @@ -129,4 +143,4 @@ struct re_guts { /* misc utilities */ #define OUT (CHAR_MAX+1) /* a non-character value */ -#define ISWORD(c) (isalnum(c) || (c) == '_') +#define ISWORD(c) (ap_isalnum(c) || (c) == '_') diff --git a/usr.sbin/httpd/src/support/Makefile.tmpl b/usr.sbin/httpd/src/support/Makefile.tmpl index 02efaa2605f..04d78cb5b79 100644 --- a/usr.sbin/httpd/src/support/Makefile.tmpl +++ b/usr.sbin/httpd/src/support/Makefile.tmpl @@ -30,6 +30,7 @@ ab: ab.o apxs: apxs.pl sed <apxs.pl >apxs \ + -e 's%@TARGET@%$(TARGET)%g' \ -e 's%@CC@%$(CC)%g' \ -e 's%@CFLAGS@%$(CFLAGS)%g' \ -e 's%@CFLAGS_SHLIB@%$(CFLAGS_SHLIB)%g' \ diff --git a/usr.sbin/httpd/src/support/ab.1 b/usr.sbin/httpd/src/support/ab.1 index 2405662f5a9..953704601ce 100644 --- a/usr.sbin/httpd/src/support/ab.1 +++ b/usr.sbin/httpd/src/support/ab.1 @@ -1,5 +1,5 @@ .TH ab 1 "March 1998" -.\" Copyright (c) 1998 The Apache Group. All rights reserved. +.\" 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 diff --git a/usr.sbin/httpd/src/support/ab.c b/usr.sbin/httpd/src/support/ab.c index 866c4d4db70..051d19e8dd8 100644 --- a/usr.sbin/httpd/src/support/ab.c +++ b/usr.sbin/httpd/src/support/ab.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1998 The Apache Group. All rights reserved. + * 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 @@ -155,8 +155,8 @@ struct data { int time; /* time in ms for connection */ }; -#define min(a,b) ((a)<(b))?(a):(b) -#define max(a,b) ((a)>(b))?(a):(b) +#define ap_min(a,b) ((a)<(b))?(a):(b) +#define ap_max(a,b) ((a)>(b))?(a):(b) /* --------------------- GLOBALS ---------------------------- */ @@ -320,10 +320,10 @@ static void output_results(void) for (i = 0; i < requests; i++) { struct data s = stats[i]; - mincon = min(mincon, s.ctime); - mintot = min(mintot, s.time); - maxcon = max(maxcon, s.ctime); - maxtot = max(maxtot, s.time); + 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; } @@ -339,7 +339,7 @@ static void output_results(void) /* --------------------------------------------------------- */ -/* start asnchronous non-blocking connection */ +/* start asynchronous non-blocking connection */ static void start_connect(struct connection *c) { @@ -688,7 +688,7 @@ static void copyright(void) { printf("This is ApacheBench, Version %s\n", VERSION); printf("Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/\n"); - printf("Copyright (c) 1998 The Apache Group, http://www.apache.org/\n"); + printf("Copyright (c) 1998-1999 The Apache Group, http://www.apache.org/\n"); printf("\n"); } diff --git a/usr.sbin/httpd/src/support/apachectl b/usr.sbin/httpd/src/support/apachectl index 12fd57ea69a..7ea46467259 100644 --- a/usr.sbin/httpd/src/support/apachectl +++ b/usr.sbin/httpd/src/support/apachectl @@ -173,7 +173,7 @@ done exit $ERROR # ==================================================================== -# Copyright (c) 1995-1998 The Apache Group. All rights reserved. +# 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 diff --git a/usr.sbin/httpd/src/support/apachectl.1 b/usr.sbin/httpd/src/support/apachectl.1 index 0ef806af681..72300eb98b2 100644 --- a/usr.sbin/httpd/src/support/apachectl.1 +++ b/usr.sbin/httpd/src/support/apachectl.1 @@ -1,5 +1,5 @@ .TH apachectl 1 "September 1997" -.\" Copyright (c) 1997-1998 The Apache Group. 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 diff --git a/usr.sbin/httpd/src/support/apxs.8 b/usr.sbin/httpd/src/support/apxs.8 index 904f26417fc..581d80b80cd 100644 --- a/usr.sbin/httpd/src/support/apxs.8 +++ b/usr.sbin/httpd/src/support/apxs.8 @@ -1,5 +1,5 @@ .TH apxs 8 "April 1998" -.\" Copyright (c) 1998 The Apache Group. All rights reserved. +.\" 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 @@ -79,6 +79,12 @@ apxs \- APache eXtenSion tool [ .BI \-l " libname" ] +[ +.BI \-Wc, "compiler-flags" +] +[ +.BI \-Wl, "linker-flags" +] .IR files " ..." .B apxs @@ -199,11 +205,12 @@ knowledge about certain settings. The .I query parameters can be one or more of the following strings: .nf - CC PREFIX - LD SBINDIR - CFLAGS INCLUDEDIR - CFLAGS_SHLIB LIBEXECDIR - LDFLAGS_SHLIB SYSCONFDIR + CC TARGET + CFLAGS SBINDIR + CFLAGS_SHLIB INCLUDEDIR + LD_SHLIB LIBEXECDIR + LDFLAGS_SHLIB SYSCONFDIR + LIBS_SHLIB .fi Use this for manually determining settings. For instance use .nf @@ -269,6 +276,18 @@ Use this to add your own library directories to search to the build process. .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 options: .TP 12 diff --git a/usr.sbin/httpd/src/support/apxs.pl b/usr.sbin/httpd/src/support/apxs.pl index 7b60d339f15..8c0f802f2c1 100644 --- a/usr.sbin/httpd/src/support/apxs.pl +++ b/usr.sbin/httpd/src/support/apxs.pl @@ -1,6 +1,6 @@ #!/usr/local/bin/perl ## ==================================================================== -## Copyright (c) 1998 The Apache Group. All rights reserved. +## 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 @@ -68,6 +68,7 @@ package apxs; ## Configuration ## +my $CFG_TARGET = '@TARGET@'; # substituted via Makefile.tmpl my $CFG_CC = '@CC@'; # substituted via Makefile.tmpl my $CFG_CFLAGS = '@CFLAGS@'; # substituted via Makefile.tmpl my $CFG_CFLAGS_SHLIB = '@CFLAGS_SHLIB@'; # substituted via Makefile.tmpl @@ -90,11 +91,11 @@ $CFG_CFLAGS =~ s|\s+`.+apaci`||; ## ## Initial shared object support check ## -if (not grep(/mod_so/, `$CFG_SBINDIR/httpd -l`)) { +if (not grep(/mod_so/, `$CFG_SBINDIR/$CFG_TARGET -l`)) { print STDERR "apxs:Error: Sorry, no shared object support for Apache\n"; print STDERR "apxs:Error: available under your platform. Make sure\n"; print STDERR "apxs:Error: the Apache module mod_so is compiled into\n"; - print STDERR "apxs:Error: your server binary `$CFG_SBINDIR/httpd'.\n"; + print STDERR "apxs:Error: your server binary `$CFG_SBINDIR/$CFG_TARGET'.\n"; exit(1); } @@ -111,6 +112,7 @@ my @opt_D = (); my @opt_I = (); my @opt_L = (); my @opt_l = (); +my @opt_W = (); my $opt_i = 0; my $opt_a = 0; my $opt_A = 0; @@ -185,14 +187,15 @@ sub usage { print STDERR "Usage: apxs -g -n <modname>\n"; print STDERR " apxs -q <query> ...\n"; print STDERR " apxs -c [-o <dsofile>] [-D <name>[=<value>]] [-I <incdir>]\n"; - print STDERR " [-L <libdir>] [-l <libname>] <files> ...\n"; - print STDERR " apxs -i [-a] [-n <modname>] <dsofile> ...\n"; + print STDERR " [-L <libdir>] [-l <libname>] [-Wc,<flags>] [-Wl,<flags>]\n"; + print STDERR " <files> ...\n"; + print STDERR " apxs -i [-a] [-A] [-n <modname>] <dsofile> ...\n"; exit(1); } # option handling my $rc; -($rc, @ARGV) = &Getopts("qn:gco:I+D+L+l+iaA", @ARGV); +($rc, @ARGV) = &Getopts("qn:gco:I+D+L+l+W+iaA", @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); @@ -234,6 +237,7 @@ if ($opt_g) { my $data = join('', <DATA>); $data =~ s|%NAME%|$name|sg; + $data =~ s|%TARGET%|$CFG_TARGET|sg; my ($mkf, $src) = ($data =~ m|^(.+)-=#=-\n(.+)|s); @@ -263,7 +267,7 @@ if ($opt_q) { my $ok = 0; my $name; foreach $name (qw( - CC LD_SHLIB CFLAGS CFLAGS_SHLIB LDFLAGS_SHLIB + 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)) { @@ -322,7 +326,10 @@ if ($opt_c) { # create compilation commands my @cmds = (); my $opt = ''; - my ($opt_I, $opt_D); + 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 "; } @@ -345,7 +352,10 @@ if ($opt_c) { $cmd .= " $o"; } $opt = ''; - my ($opt_L, $opt_l); + my ($opt_Wl, $opt_L, $opt_l); + foreach $opt_Wl (@opt_W) { + $opt .= " $1" if ($opt_Wl =~ m|^\s*l,(.*)$|); + } foreach $opt_L (@opt_L) { $opt .= " -L$opt_L"; } @@ -430,17 +440,17 @@ if ($opt_i) { # activate module via LoadModule/AddModule directive if ($opt_a or $opt_A) { - if (not -f "$CFG_SYSCONFDIR/httpd.conf") { - print "apxs:Error: Config file $CFG_SYSCONFDIR/httpd.conf not found\n"; + if (not -f "$CFG_SYSCONFDIR/$CFG_TARGET.conf") { + print "apxs:Error: Config file $CFG_SYSCONFDIR/$CFG_TARGET.conf not found\n"; exit(1); } - open(FP, "<$CFG_SYSCONFDIR/httpd.conf") || die; + open(FP, "<$CFG_SYSCONFDIR/$CFG_TARGET.conf") || die; my $content = join('', <FP>); close(FP); if ($content !~ m|\n#?\s*LoadModule\s+|) { - print STDERR "apxs:Error: Activation failed for custom $CFG_SYSCONFDIR/httpd.conf file.\n"; + 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); } @@ -455,7 +465,7 @@ if ($opt_i) { $update = 1; $lmd =~ m|LoadModule\s+(.+?)_module.*|; my $what = $opt_A ? "preparing" : "activating"; - print STDERR "[$what module `$1' in $CFG_SYSCONFDIR/httpd.conf]\n"; + print STDERR "[$what module `$1' in $CFG_SYSCONFDIR/$CFG_TARGET.conf]\n"; } } my $amd; @@ -468,12 +478,12 @@ if ($opt_i) { } } if ($update) { - open(FP, ">$CFG_SYSCONFDIR/httpd.conf.new") || die; + open(FP, ">$CFG_SYSCONFDIR/$CFG_TARGET.conf.new") || die; print FP $content; close(FP); - system("cp $CFG_SYSCONFDIR/httpd.conf $CFG_SYSCONFDIR/httpd.conf.bak && " . - "cp $CFG_SYSCONFDIR/httpd.conf.new $CFG_SYSCONFDIR/httpd.conf && " . - "rm $CFG_SYSCONFDIR/httpd.conf.new"); + 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"); } } } @@ -481,7 +491,7 @@ if ($opt_i) { ##EOF## __DATA__ ## -## Makefile -- Apache for sample %NAME% module +## Makefile -- Build procedure for sample %NAME% Apache module ## Autogenerated via ``apxs -n %NAME% -g''. ## @@ -537,10 +547,10 @@ stop: ** ** $ apxs -c -i mod_%NAME%.c ** -** Then activate it in Apache's httpd.conf file for instance +** Then activate it in Apache's %TARGET%.conf file for instance ** for the URL /%NAME% in as follows: ** -** # httpd.conf +** # %TARGET%.conf ** LoadModule %NAME%_module libexec/mod_%NAME%.so ** <Location /%NAME%> ** SetHandler %NAME% @@ -559,7 +569,7 @@ stop: ** ** HTTP/1.1 200 OK ** Date: Tue, 31 Mar 1998 14:42:22 GMT -** Server: Apache/1.3b6-dev +** Server: Apache/1.3.4 (Unix) ** Connection: close ** Content-Type: text/html ** @@ -568,7 +578,8 @@ stop: #include "httpd.h" #include "http_config.h" -#include "conf.h" +#include "http_protocol.h" +#include "ap_config.h" /* The sample content handler */ static int %NAME%_handler(request_rec *r) @@ -599,11 +610,11 @@ module MODULE_VAR_EXPORT %NAME%_module = { NULL, /* [#1] URI to filename translation */ NULL, /* [#4] validate user id from request */ NULL, /* [#5] check if the user is ok _here_ */ - NULL, /* [#2] check access by host address */ + NULL, /* [#3] check access by host address */ NULL, /* [#6] determine MIME type */ NULL, /* [#7] pre-run fixups */ NULL, /* [#9] log a transaction */ - NULL, /* [#3] header parser */ + NULL, /* [#2] header parser */ NULL, /* child_init */ NULL, /* child_exit */ NULL /* [#0] post read-request */ diff --git a/usr.sbin/httpd/src/support/dbmmanage b/usr.sbin/httpd/src/support/dbmmanage index 042c686497e..721bdd1eb37 100644 --- a/usr.sbin/httpd/src/support/dbmmanage +++ b/usr.sbin/httpd/src/support/dbmmanage @@ -1,7 +1,7 @@ #!/usr/local/bin/perl # ==================================================================== -# Copyright (c) 1995-1998 The Apache Group. All rights reserved. +# 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 diff --git a/usr.sbin/httpd/src/support/dbmmanage.1 b/usr.sbin/httpd/src/support/dbmmanage.1 index cd3a5ffaaa7..f52bd2c02c8 100644 --- a/usr.sbin/httpd/src/support/dbmmanage.1 +++ b/usr.sbin/httpd/src/support/dbmmanage.1 @@ -1,5 +1,5 @@ .TH dbmmanage 1 "March 1998" -.\" Copyright (c) 1998 The Apache Group. All rights reserved. +.\" 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 @@ -60,7 +60,9 @@ dbmmanage \- Create and update user authentication files in DBM format .I command ] [ .I username -] +[ +.I encpasswd +] ] .PP .SH DESCRIPTION .B dbmmanage @@ -88,6 +90,10 @@ The filename of the DBM format file. Usually without the extension .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 . diff --git a/usr.sbin/httpd/src/support/htdigest.1 b/usr.sbin/httpd/src/support/htdigest.1 index 3c16d12f5c2..c719e456ce9 100644 --- a/usr.sbin/httpd/src/support/htdigest.1 +++ b/usr.sbin/httpd/src/support/htdigest.1 @@ -1,5 +1,5 @@ .TH htdigest 1 "March 1998" -.\" Copyright (c) 1997-1998 The Apache Group. 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 diff --git a/usr.sbin/httpd/src/support/htpasswd.1 b/usr.sbin/httpd/src/support/htpasswd.1 index fdd4c2d8ff6..5956de00d9b 100644 --- a/usr.sbin/httpd/src/support/htpasswd.1 +++ b/usr.sbin/httpd/src/support/htpasswd.1 @@ -1,5 +1,5 @@ .TH htpasswd 1 "February 1997" -.\" Copyright (c) 1997-1998 The Apache Group. 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 diff --git a/usr.sbin/httpd/src/support/httpd.8 b/usr.sbin/httpd/src/support/httpd.8 index 267530682a6..56fd2c308b3 100644 --- a/usr.sbin/httpd/src/support/httpd.8 +++ b/usr.sbin/httpd/src/support/httpd.8 @@ -1,6 +1,6 @@ .TH httpd 8 "February 1997" .\" Copyright (c) 1995-1997 David Robinson. All rights reserved. -.\" Copyright (c) 1997-1998 The Apache Group. 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 @@ -60,7 +60,7 @@ httpd \- Apache hypertext transfer protocol server [ .B \-X ] [ -.BI \-L " libexecdir" +.BI \-R " libexecdir" ] [ .BI \-d " serverroot" ] [ @@ -81,6 +81,9 @@ httpd \- Apache hypertext transfer protocol server .B \-l ] [ +.B \-L +] +[ .B \-v ] [ @@ -89,9 +92,6 @@ httpd \- Apache hypertext transfer protocol server [ .B \-S ] -[ -.B \-? -] .SH DESCRIPTION .B httpd @@ -115,7 +115,7 @@ compiled into .B httpd. .SH OPTIONS .TP 12 -.BI \-L " libexecdir" +.BI \-R " libexecdir" This option is only available if Apache was built with the .I SHARED_CORE @@ -146,12 +146,15 @@ Sets a configuration \fIparameter\fP which can be used with to conditionally skip or process commands. .TP .B \-h -Output a list of directives together with expected arguments and -places where the directive is valid. +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). @@ -175,11 +178,6 @@ Print the version of Print the version and build parameters of .B httpd , and then exit. -.TP -.B \-? -Print a list of the -.B httpd -options, and then exit. .SH FILES .PD 0 .B /usr/local/apache/conf/httpd.conf diff --git a/usr.sbin/httpd/src/support/httpd.exp b/usr.sbin/httpd/src/support/httpd.exp index b0bb4f20cb4..e11e3b2849a 100644 --- a/usr.sbin/httpd/src/support/httpd.exp +++ b/usr.sbin/httpd/src/support/httpd.exp @@ -13,6 +13,7 @@ ap_allow_options ap_allow_overrides ap_append_arrays ap_array_cat +ap_array_pstrcat ap_auth_name ap_auth_type ap_basic_http_header @@ -95,6 +96,7 @@ 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_finalize_request_protocol @@ -175,6 +177,7 @@ 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 @@ -185,7 +188,9 @@ 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 @@ -198,6 +203,7 @@ ap_null_cleanup ap_open_logs ap_open_piped_log ap_os_escape_path +ap_os_is_filename_valid ap_os_is_path_absolute ap_overlay_tables ap_overlap_tables @@ -300,6 +306,8 @@ ap_should_client_block ap_show_directives ap_show_modules ap_signal +ap_single_module_configure +ap_single_module_init ap_slack ap_snprintf ap_soft_timeout diff --git a/usr.sbin/httpd/src/support/log_server_status b/usr.sbin/httpd/src/support/log_server_status index bbab3750020..694247dd8b3 100644 --- a/usr.sbin/httpd/src/support/log_server_status +++ b/usr.sbin/httpd/src/support/log_server_status @@ -1,7 +1,7 @@ #!/usr/local/bin/perl # ==================================================================== -# Copyright (c) 1995-1998 The Apache Group. All rights reserved. +# 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 diff --git a/usr.sbin/httpd/src/support/logresolve.8 b/usr.sbin/httpd/src/support/logresolve.8 index cca3c7a49b5..4851269ad61 100644 --- a/usr.sbin/httpd/src/support/logresolve.8 +++ b/usr.sbin/httpd/src/support/logresolve.8 @@ -1,5 +1,5 @@ .TH logresolve 8 "March 1998" -.\" Copyright (c) 1998 The Apache Group. All rights reserved. +.\" 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 diff --git a/usr.sbin/httpd/src/support/logresolve.pl b/usr.sbin/httpd/src/support/logresolve.pl index 06df30d65f4..59ab9ebaf2a 100644 --- a/usr.sbin/httpd/src/support/logresolve.pl +++ b/usr.sbin/httpd/src/support/logresolve.pl @@ -1,7 +1,7 @@ #!/usr/local/bin/perl # ==================================================================== -# Copyright (c) 1995-1998 The Apache Group. All rights reserved. +# 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 diff --git a/usr.sbin/httpd/src/support/rotatelogs.8 b/usr.sbin/httpd/src/support/rotatelogs.8 index 9ee3d67fd74..aee02e11ecd 100644 --- a/usr.sbin/httpd/src/support/rotatelogs.8 +++ b/usr.sbin/httpd/src/support/rotatelogs.8 @@ -1,5 +1,5 @@ .TH rotatelogs 8 "March 1998" -.\" Copyright (c) 1998 The Apache Group. All rights reserved. +.\" 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 diff --git a/usr.sbin/httpd/src/support/split-logfile b/usr.sbin/httpd/src/support/split-logfile index 84c5504238a..7cc4652da89 100644 --- a/usr.sbin/httpd/src/support/split-logfile +++ b/usr.sbin/httpd/src/support/split-logfile @@ -1,7 +1,7 @@ #!/usr/local/bin/perl # # ==================================================================== -# Copyright (c) 1995-1998 The Apache Group. All rights reserved. +# 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 diff --git a/usr.sbin/httpd/src/support/suexec.8 b/usr.sbin/httpd/src/support/suexec.8 index a92b9471a8e..801d7abce91 100644 --- a/usr.sbin/httpd/src/support/suexec.8 +++ b/usr.sbin/httpd/src/support/suexec.8 @@ -1,5 +1,5 @@ .TH suexec 8 "March 1998" -.\" Copyright (c) 1998 The Apache Group. All rights reserved. +.\" 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 diff --git a/usr.sbin/httpd/src/support/suexec.c b/usr.sbin/httpd/src/support/suexec.c index 19afa3341a8..a260fc5e342 100644 --- a/usr.sbin/httpd/src/support/suexec.c +++ b/usr.sbin/httpd/src/support/suexec.c @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -109,7 +109,7 @@ int initgroups(const char *name, gid_t basegid) #define AP_ENVBUF 256 extern char **environ; -static FILE *log; +static FILE *log = NULL; char *safe_env_lst[] = { @@ -500,10 +500,16 @@ int main(int argc, char *argv[]) /* * 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. + * 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. */ - fclose(log); - log = NULL; + if (log != NULL) { + fclose(log); + log = NULL; + } /* * Execute the command, replacing our image with its own. diff --git a/usr.sbin/httpd/src/support/suexec.h b/usr.sbin/httpd/src/support/suexec.h index 3da06813fca..892badd1e0b 100644 --- a/usr.sbin/httpd/src/support/suexec.h +++ b/usr.sbin/httpd/src/support/suexec.h @@ -1,5 +1,5 @@ /* ==================================================================== - * Copyright (c) 1995-1998 The Apache Group. All rights reserved. + * 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 @@ -57,6 +57,7 @@ /* * suexec.h -- user-definable variables for the suexec wrapper code. + * (See README.configure on how to customize these variables.) */ |