summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/.cvsignore4
-rw-r--r--modules/Makefile.in5
-rw-r--r--modules/README55
-rw-r--r--modules/aaa/.cvsignore10
-rw-r--r--modules/aaa/.indent.pro54
-rw-r--r--modules/aaa/Makefile.in3
-rw-r--r--modules/aaa/config.m421
-rw-r--r--modules/aaa/mod_access.c345
-rw-r--r--modules/aaa/mod_access.exp1
-rw-r--r--modules/aaa/mod_auth.c338
-rw-r--r--modules/aaa/mod_auth.exp1
-rw-r--r--modules/aaa/mod_auth_anon.c313
-rw-r--r--modules/aaa/mod_auth_anon.dsp95
-rw-r--r--modules/aaa/mod_auth_anon.exp1
-rw-r--r--modules/aaa/mod_auth_anon.mak330
-rw-r--r--modules/aaa/mod_auth_db.c419
-rw-r--r--modules/aaa/mod_auth_db.module37
-rw-r--r--modules/aaa/mod_auth_dbm.c358
-rw-r--r--modules/aaa/mod_auth_dbm.dsp95
-rw-r--r--modules/aaa/mod_auth_dbm.exp1
-rw-r--r--modules/aaa/mod_auth_dbm.mak366
-rw-r--r--modules/aaa/mod_auth_digest.c2083
-rw-r--r--modules/aaa/mod_auth_digest.dsp95
-rw-r--r--modules/aaa/mod_auth_digest.mak370
-rw-r--r--modules/arch/win32/mod_isapi.c1299
-rw-r--r--modules/cache/.cvsignore10
-rw-r--r--modules/cache/.indent.pro54
-rw-r--r--modules/cache/Makefile.in3
-rw-r--r--modules/cache/config.m411
-rw-r--r--modules/cache/mod_file_cache.c468
-rw-r--r--modules/cache/mod_file_cache.dsp95
-rw-r--r--modules/cache/mod_file_cache.mak331
-rw-r--r--modules/config5.m443
-rw-r--r--modules/dav/fs/.cvsignore10
-rw-r--r--modules/dav/fs/Makefile.in3
-rw-r--r--modules/dav/fs/config6.m415
-rw-r--r--modules/dav/fs/dbm.c259
-rw-r--r--modules/dav/fs/lock.c1537
-rw-r--r--modules/dav/fs/mod_dav_fs.c142
-rw-r--r--modules/dav/fs/mod_dav_fs.dsp119
-rw-r--r--modules/dav/fs/mod_dav_fs.mak533
-rw-r--r--modules/dav/fs/repos.c2077
-rw-r--r--modules/dav/fs/repos.h110
-rw-r--r--modules/dav/main/.cvsignore10
-rw-r--r--modules/dav/main/Makefile.in3
-rw-r--r--modules/dav/main/config5.m422
-rw-r--r--modules/dav/main/liveprop.c177
-rw-r--r--modules/dav/main/mod_dav.c4731
-rw-r--r--modules/dav/main/mod_dav.dsp131
-rw-r--r--modules/dav/main/mod_dav.h2231
-rw-r--r--modules/dav/main/mod_dav.mak659
-rw-r--r--modules/dav/main/props.c1590
-rw-r--r--modules/dav/main/providers.c84
-rw-r--r--modules/dav/main/std_liveprop.c229
-rw-r--r--modules/dav/main/util.c1958
-rw-r--r--modules/dav/main/util_lock.c826
-rw-r--r--modules/echo/.cvsignore10
-rw-r--r--modules/echo/.indent.pro54
-rw-r--r--modules/echo/Makefile.in3
-rw-r--r--modules/echo/config.m411
-rw-r--r--modules/echo/mod_echo.c136
-rw-r--r--modules/experimental/.cvsignore11
-rw-r--r--modules/experimental/.indent.pro54
-rw-r--r--modules/experimental/Makefile.in3
-rw-r--r--modules/experimental/README41
-rw-r--r--modules/experimental/config.m414
-rw-r--r--modules/experimental/mod_cache.c124
-rw-r--r--modules/experimental/mod_cache.h65
-rw-r--r--modules/experimental/mod_case_filter.c113
-rw-r--r--modules/experimental/mod_charset_lite.c1142
-rw-r--r--modules/experimental/mod_disk_cache.c170
-rw-r--r--modules/experimental/mod_example.c1198
-rw-r--r--modules/experimental/mod_ext_filter.c793
-rw-r--r--modules/experimental/mod_generic_hook_export.c82
-rw-r--r--modules/experimental/mod_generic_hook_export.dsp95
-rw-r--r--modules/experimental/mod_generic_hook_export.h62
-rw-r--r--modules/experimental/mod_generic_hook_import.c83
-rw-r--r--modules/experimental/mod_generic_hook_import.dsp95
-rw-r--r--modules/experimental/mod_optional_fn_export.c86
-rw-r--r--modules/experimental/mod_optional_fn_export.h3
-rw-r--r--modules/experimental/mod_optional_fn_import.c93
-rw-r--r--modules/filters/.cvsignore10
-rw-r--r--modules/filters/.indent.pro54
-rw-r--r--modules/filters/Makefile.in3
-rw-r--r--modules/filters/config.m411
-rw-r--r--modules/filters/mod_include.c2854
-rw-r--r--modules/filters/mod_include.exp1
-rw-r--r--modules/filters/mod_include.h214
-rw-r--r--modules/generators/.cvsignore10
-rw-r--r--modules/generators/.indent.pro54
-rw-r--r--modules/generators/Makefile.in3
-rw-r--r--modules/generators/config5.m429
-rw-r--r--modules/generators/mod_asis.c142
-rw-r--r--modules/generators/mod_asis.exp1
-rw-r--r--modules/generators/mod_autoindex.c1713
-rw-r--r--modules/generators/mod_autoindex.exp1
-rw-r--r--modules/generators/mod_cgi.c1005
-rw-r--r--modules/generators/mod_cgi.exp1
-rw-r--r--modules/generators/mod_cgid.c1300
-rw-r--r--modules/generators/mod_info.c491
-rw-r--r--modules/generators/mod_info.dsp95
-rw-r--r--modules/generators/mod_info.exp1
-rw-r--r--modules/generators/mod_info.mak326
-rw-r--r--modules/generators/mod_status.c787
-rw-r--r--modules/generators/mod_status.dsp95
-rw-r--r--modules/generators/mod_status.exp1
-rw-r--r--modules/generators/mod_status.mak330
-rw-r--r--modules/generators/mod_suexec.c155
-rw-r--r--modules/generators/mod_suexec.h64
-rw-r--r--modules/http/.cvsignore10
-rw-r--r--modules/http/.indent.pro54
-rw-r--r--modules/http/Makefile.in3
-rw-r--r--modules/http/config2.m410
-rw-r--r--modules/http/http_core.c324
-rw-r--r--modules/http/http_protocol.c2439
-rw-r--r--modules/http/http_request.c574
-rw-r--r--modules/http/mod_core.h99
-rw-r--r--modules/http/mod_mime.c823
-rw-r--r--modules/http/mod_mime.exp1
-rw-r--r--modules/loggers/.cvsignore10
-rw-r--r--modules/loggers/.indent.pro54
-rw-r--r--modules/loggers/Makefile.in3
-rw-r--r--modules/loggers/config.m49
-rw-r--r--modules/loggers/mod_log_config.c1229
-rw-r--r--modules/loggers/mod_log_config.exp1
-rw-r--r--modules/loggers/mod_log_config.h75
-rw-r--r--modules/mappers/.cvsignore10
-rw-r--r--modules/mappers/.indent.pro54
-rw-r--r--modules/mappers/Makefile.in3
-rw-r--r--modules/mappers/config9.m433
-rw-r--r--modules/mappers/mod_actions.c226
-rw-r--r--modules/mappers/mod_actions.exp1
-rw-r--r--modules/mappers/mod_alias.c443
-rw-r--r--modules/mappers/mod_alias.exp1
-rw-r--r--modules/mappers/mod_dir.c252
-rw-r--r--modules/mappers/mod_dir.exp1
-rw-r--r--modules/mappers/mod_imap.c925
-rw-r--r--modules/mappers/mod_imap.exp1
-rw-r--r--modules/mappers/mod_negotiation.c2756
-rw-r--r--modules/mappers/mod_negotiation.exp1
-rw-r--r--modules/mappers/mod_rewrite.c4132
-rw-r--r--modules/mappers/mod_rewrite.dsp95
-rw-r--r--modules/mappers/mod_rewrite.exp1
-rw-r--r--modules/mappers/mod_rewrite.h473
-rw-r--r--modules/mappers/mod_rewrite.mak335
-rw-r--r--modules/mappers/mod_so.c353
-rw-r--r--modules/mappers/mod_speling.c569
-rw-r--r--modules/mappers/mod_speling.dsp95
-rw-r--r--modules/mappers/mod_speling.exp1
-rw-r--r--modules/mappers/mod_speling.mak325
-rw-r--r--modules/mappers/mod_userdir.c399
-rw-r--r--modules/mappers/mod_userdir.exp1
-rw-r--r--modules/mappers/mod_vhost_alias.c490
-rw-r--r--modules/metadata/.cvsignore10
-rw-r--r--modules/metadata/.indent.pro54
-rw-r--r--modules/metadata/Makefile.in3
-rw-r--r--modules/metadata/config.m423
-rw-r--r--modules/metadata/mod_cern_meta.c406
-rw-r--r--modules/metadata/mod_cern_meta.dsp95
-rw-r--r--modules/metadata/mod_cern_meta.exp1
-rw-r--r--modules/metadata/mod_cern_meta.mak327
-rw-r--r--modules/metadata/mod_env.c276
-rw-r--r--modules/metadata/mod_env.exp1
-rw-r--r--modules/metadata/mod_expires.c520
-rw-r--r--modules/metadata/mod_expires.dsp95
-rw-r--r--modules/metadata/mod_expires.exp1
-rw-r--r--modules/metadata/mod_expires.mak324
-rw-r--r--modules/metadata/mod_headers.c269
-rw-r--r--modules/metadata/mod_headers.dsp95
-rw-r--r--modules/metadata/mod_headers.exp1
-rw-r--r--modules/metadata/mod_headers.mak321
-rw-r--r--modules/metadata/mod_mime_magic.c2501
-rw-r--r--modules/metadata/mod_mime_magic.exp1
-rw-r--r--modules/metadata/mod_setenvif.c471
-rw-r--r--modules/metadata/mod_setenvif.exp1
-rw-r--r--modules/metadata/mod_unique_id.c402
-rw-r--r--modules/metadata/mod_unique_id.exp1
-rw-r--r--modules/metadata/mod_usertrack.c328
-rw-r--r--modules/metadata/mod_usertrack.dsp95
-rw-r--r--modules/metadata/mod_usertrack.exp1
-rw-r--r--modules/metadata/mod_usertrack.mak325
-rw-r--r--modules/proxy/.cvsignore10
-rw-r--r--modules/proxy/.indent.pro55
-rw-r--r--modules/proxy/Makefile.in3
-rw-r--r--modules/proxy/config.m424
-rw-r--r--modules/proxy/libproxy.exp1
-rw-r--r--modules/proxy/mod_proxy.c768
-rw-r--r--modules/proxy/mod_proxy.dsp123
-rw-r--r--modules/proxy/mod_proxy.h259
-rw-r--r--modules/proxy/mod_proxy.mak573
-rw-r--r--modules/proxy/proxy_connect.c427
-rw-r--r--modules/proxy/proxy_ftp.c1666
-rw-r--r--modules/proxy/proxy_http.c835
-rw-r--r--modules/proxy/proxy_util.c1187
-rw-r--r--modules/ssl/.cvsignore10
-rw-r--r--modules/ssl/README163
-rw-r--r--modules/ssl/README.dsov.fig346
-rw-r--r--modules/ssl/README.dsov.ps1138
-rw-r--r--modules/ssl/mod_ssl.c248
-rw-r--r--modules/ssl/mod_ssl.h854
-rw-r--r--modules/ssl/ssl_engine_config.c1093
-rw-r--r--modules/ssl/ssl_engine_dh.c255
-rw-r--r--modules/ssl/ssl_engine_init.c1090
-rw-r--r--modules/ssl/ssl_engine_io.c728
-rw-r--r--modules/ssl/ssl_engine_kernel.c1905
-rw-r--r--modules/ssl/ssl_engine_log.c326
-rw-r--r--modules/ssl/ssl_engine_mutex.c397
-rw-r--r--modules/ssl/ssl_engine_pphrase.c545
-rw-r--r--modules/ssl/ssl_engine_rand.c215
-rw-r--r--modules/ssl/ssl_engine_vars.c615
-rw-r--r--modules/ssl/ssl_expr.c119
-rw-r--r--modules/ssl/ssl_expr.h139
-rw-r--r--modules/ssl/ssl_expr_eval.c282
-rw-r--r--modules/ssl/ssl_expr_parse.c605
-rw-r--r--modules/ssl/ssl_expr_parse.h29
-rw-r--r--modules/ssl/ssl_expr_parse.y186
-rw-r--r--modules/ssl/ssl_expr_scan.c2002
-rw-r--r--modules/ssl/ssl_expr_scan.l261
-rw-r--r--modules/ssl/ssl_scache.c204
-rw-r--r--modules/ssl/ssl_scache_dbm.c440
-rw-r--r--modules/ssl/ssl_scache_shmcb.c1343
-rw-r--r--modules/ssl/ssl_util.c437
-rw-r--r--modules/ssl/ssl_util_ssl.c544
-rw-r--r--modules/ssl/ssl_util_ssl.h115
-rw-r--r--modules/test/.cvsignore7
-rw-r--r--modules/test/.indent.pro54
-rw-r--r--modules/test/README3
-rw-r--r--modules/test/mod_autoindex.c1711
-rw-r--r--modules/test/mod_autoindex.exp1
-rw-r--r--modules/test/mod_optional_fn_export.c86
-rw-r--r--modules/test/mod_optional_fn_export.h3
-rw-r--r--modules/test/mod_optional_fn_import.c93
-rw-r--r--modules/test/mod_rndchunk.c179
-rw-r--r--modules/test/mod_test_util_uri.c354
-rw-r--r--modules/tls/.cvsignore6
-rw-r--r--modules/tls/Makefile.in2
-rw-r--r--modules/tls/README20
-rw-r--r--modules/tls/config.m443
-rw-r--r--modules/tls/mod_tls.c417
-rw-r--r--modules/tls/openssl_state_machine.c268
-rw-r--r--modules/tls/openssl_state_machine.h15
241 files changed, 0 insertions, 89931 deletions
diff --git a/modules/.cvsignore b/modules/.cvsignore
deleted file mode 100644
index 59d7d334c8..0000000000
--- a/modules/.cvsignore
+++ /dev/null
@@ -1,4 +0,0 @@
-Makefile
-.deps
-Debug
-Release
diff --git a/modules/Makefile.in b/modules/Makefile.in
deleted file mode 100644
index ecb043547b..0000000000
--- a/modules/Makefile.in
+++ /dev/null
@@ -1,5 +0,0 @@
-
-SUBDIRS = $(MODULE_DIRS)
-
-include $(top_srcdir)/build/rules.mk
-
diff --git a/modules/README b/modules/README
deleted file mode 100644
index 51624a67f7..0000000000
--- a/modules/README
+++ /dev/null
@@ -1,55 +0,0 @@
-The directory structure for this level is as follows:
-
-aaa/
- This directory contains modules dealing with authorization and
- authentication.
-
-arch/
-
-cache/
- This directory houses modules that implement file and data caching
- capability.
-
-dav/
- This directory houses modules that implement WebDAV functionality.
-
-echo/
-
-experimental/
- In this directory we've placed some modules which we think
- provide some pretty interesting functionality, but which
- are still in the early stages of development and could
- evolve radically in the future. This code isn't supported
- officially.
-
-filters/
- This directory houses modules that perform general inline data filtering.
-
-generators/
- This directory houses modules that perform data generation functions.
-
-http/
- This directory houses modules that basic HTTP protocol implementation.
-
-loggers/
- This directory houses modules that handle logging functions.
-
-mappers/
- This directory houses modules that handle URL mapping and
- rewriting.
-
-metadata/
- This directory houses modules that deal with Header metadata.
-
-proxy/
- This houses the code for the proxy module for Apache.
-
-ssl/
-
-test/
- This directory houses modules which test various components
- of Apache. You should not compile these into a production
- server.
-
-tls/
- This directory houses code for OpenSSL functionality.
diff --git a/modules/aaa/.cvsignore b/modules/aaa/.cvsignore
deleted file mode 100644
index 65f0cc30cf..0000000000
--- a/modules/aaa/.cvsignore
+++ /dev/null
@@ -1,10 +0,0 @@
-.deps
-.libs
-*.la
-modules.mk
-Makefile
-*.lo
-*.slo
-*.so
-Debug
-Release
diff --git a/modules/aaa/.indent.pro b/modules/aaa/.indent.pro
deleted file mode 100644
index a9fbe9f9a1..0000000000
--- a/modules/aaa/.indent.pro
+++ /dev/null
@@ -1,54 +0,0 @@
--i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1
--TBUFF
--TFILE
--TTRANS
--TUINT4
--T_trans
--Tallow_options_t
--Tapache_sfio
--Tarray_header
--Tbool_int
--Tbuf_area
--Tbuff_struct
--Tbuffy
--Tcmd_how
--Tcmd_parms
--Tcommand_rec
--Tcommand_struct
--Tconn_rec
--Tcore_dir_config
--Tcore_server_config
--Tdir_maker_func
--Tevent
--Tglobals_s
--Thandler_func
--Thandler_rec
--Tjoblist_s
--Tlisten_rec
--Tmerger_func
--Tmode_t
--Tmodule
--Tmodule_struct
--Tmutex
--Tn_long
--Tother_child_rec
--Toverrides_t
--Tparent_score
--Tpid_t
--Tpiped_log
--Tpool
--Trequest_rec
--Trequire_line
--Trlim_t
--Tscoreboard
--Tsemaphore
--Tserver_addr_rec
--Tserver_rec
--Tserver_rec_chain
--Tshort_score
--Ttable
--Ttable_entry
--Tthread
--Tu_wide_int
--Tvtime_t
--Twide_int
diff --git a/modules/aaa/Makefile.in b/modules/aaa/Makefile.in
deleted file mode 100644
index 167b343d0d..0000000000
--- a/modules/aaa/Makefile.in
+++ /dev/null
@@ -1,3 +0,0 @@
-
-include $(top_srcdir)/build/special.mk
-
diff --git a/modules/aaa/config.m4 b/modules/aaa/config.m4
deleted file mode 100644
index b8b359f9b1..0000000000
--- a/modules/aaa/config.m4
+++ /dev/null
@@ -1,21 +0,0 @@
-dnl modules enabled in this directory by default
-
-dnl APACHE_MODULE(name, helptext[, objects[, structname[, default[, config]]]])
-
-APACHE_MODPATH_INIT(aaa)
-
-APACHE_MODULE(access, host-based access control, , , yes)
-APACHE_MODULE(auth, user-based access control, , , yes)
-APACHE_MODULE(auth_anon, anonymous user access, , , most)
-APACHE_MODULE(auth_dbm, DBM-based access databases, , , most)
-
-APACHE_MODULE(auth_db, DB-based access databases, , , , [
- AC_CHECK_HEADERS(db.h)
- AC_CHECK_LIB(db,main)
-])
-
-APACHE_MODULE(auth_digest, RFC2617 Digest authentication, , , most)
-
-APR_ADDTO(LTFLAGS,-export-dynamic)
-
-APACHE_MODPATH_FINISH
diff --git a/modules/aaa/mod_access.c b/modules/aaa/mod_access.c
deleted file mode 100644
index d51df93a40..0000000000
--- a/modules/aaa/mod_access.c
+++ /dev/null
@@ -1,345 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * Security options etc.
- *
- * Module derived from code originally written by Rob McCool
- *
- */
-
-#include "apr_strings.h"
-#include "apr_network_io.h"
-#include "apr_lib.h"
-
-#define APR_WANT_STRFUNC
-#define APR_WANT_BYTEFUNC
-#include "apr_want.h"
-
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_core.h"
-#include "http_config.h"
-#include "http_log.h"
-#include "http_request.h"
-
-#if APR_HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-
-enum allowdeny_type {
- T_ENV,
- T_ALL,
- T_IP,
- T_HOST,
- T_FAIL
-};
-
-typedef struct {
- int limited;
- union {
- char *from;
- apr_ipsubnet_t *ip;
- } x;
- enum allowdeny_type type;
-} allowdeny;
-
-/* things in the 'order' array */
-#define DENY_THEN_ALLOW 0
-#define ALLOW_THEN_DENY 1
-#define MUTUAL_FAILURE 2
-
-typedef struct {
- int order[METHODS];
- apr_array_header_t *allows;
- apr_array_header_t *denys;
-} access_dir_conf;
-
-module AP_MODULE_DECLARE_DATA access_module;
-
-static void *create_access_dir_config(apr_pool_t *p, char *dummy)
-{
- access_dir_conf *conf =
- (access_dir_conf *) apr_pcalloc(p, sizeof(access_dir_conf));
- int i;
-
- for (i = 0; i < METHODS; ++i)
- conf->order[i] = DENY_THEN_ALLOW;
- conf->allows = apr_array_make(p, 1, sizeof(allowdeny));
- conf->denys = apr_array_make(p, 1, sizeof(allowdeny));
-
- return (void *) conf;
-}
-
-static const char *order(cmd_parms *cmd, void *dv, const char *arg)
-{
- access_dir_conf *d = (access_dir_conf *) dv;
- int i, o;
-
- if (!strcasecmp(arg, "allow,deny"))
- o = ALLOW_THEN_DENY;
- else if (!strcasecmp(arg, "deny,allow"))
- o = DENY_THEN_ALLOW;
- else if (!strcasecmp(arg, "mutual-failure"))
- o = MUTUAL_FAILURE;
- else
- return "unknown order";
-
- for (i = 0; i < METHODS; ++i)
- if (cmd->limited & (1 << i))
- d->order[i] = o;
-
- return NULL;
-}
-
-static const char *allow_cmd(cmd_parms *cmd, void *dv, const char *from,
- const char *where_c)
-{
- access_dir_conf *d = (access_dir_conf *) dv;
- allowdeny *a;
- char *where = apr_pstrdup(cmd->pool, where_c);
- char *s;
- char msgbuf[120];
- apr_status_t rv;
-
- if (strcasecmp(from, "from"))
- return "allow and deny must be followed by 'from'";
-
- a = (allowdeny *) apr_array_push(cmd->info ? d->allows : d->denys);
- a->x.from = where;
- a->limited = cmd->limited;
-
- if (!strncasecmp(where, "env=", 4)) {
- a->type = T_ENV;
- a->x.from += 4;
-
- }
- else if (!strcasecmp(where, "all")) {
- a->type = T_ALL;
- }
- else if ((s = strchr(where, '/'))) {
- *s++ = '\0';
- rv = apr_ipsubnet_create(&a->x.ip, where, s, cmd->pool);
- if(APR_STATUS_IS_EINVAL(rv)) {
- /* looked nothing like an IP address */
- return "An IP address was expected";
- }
- else if (rv != APR_SUCCESS) {
- apr_strerror(rv, msgbuf, sizeof msgbuf);
- return apr_pstrdup(cmd->pool, msgbuf);
- }
- a->type = T_IP;
- }
- else if (!APR_STATUS_IS_EINVAL(rv = apr_ipsubnet_create(&a->x.ip, where, NULL, cmd->pool))) {
- if (rv != APR_SUCCESS) {
- apr_strerror(rv, msgbuf, sizeof msgbuf);
- return apr_pstrdup(cmd->pool, msgbuf);
- }
- a->type = T_IP;
- }
- else { /* no slash, didn't look like an IP address => must be a host */
- a->type = T_HOST;
- }
-
- return NULL;
-}
-
-static char its_an_allow;
-
-static const command_rec access_cmds[] =
-{
- AP_INIT_TAKE1("order", order, NULL, OR_LIMIT,
- "'allow,deny', 'deny,allow', or 'mutual-failure'"),
- AP_INIT_ITERATE2("allow", allow_cmd, &its_an_allow, OR_LIMIT,
- "'from' followed by hostnames or IP-address wildcards"),
- AP_INIT_ITERATE2("deny", allow_cmd, NULL, OR_LIMIT,
- "'from' followed by hostnames or IP-address wildcards"),
- {NULL}
-};
-
-static int in_domain(const char *domain, const char *what)
-{
- int dl = strlen(domain);
- int wl = strlen(what);
-
- if ((wl - dl) >= 0) {
- if (strcasecmp(domain, &what[wl - dl]) != 0)
- return 0;
-
- /* Make sure we matched an *entire* subdomain --- if the user
- * said 'allow from good.com', we don't want people from nogood.com
- * to be able to get in.
- */
-
- if (wl == dl)
- return 1; /* matched whole thing */
- else
- return (domain[0] == '.' || what[wl - dl - 1] == '.');
- }
- else
- return 0;
-}
-
-static int find_allowdeny(request_rec *r, apr_array_header_t *a, int method)
-{
- allowdeny *ap = (allowdeny *) a->elts;
- int mmask = (1 << method);
- int i;
- int gothost = 0;
- const char *remotehost = NULL;
-
- for (i = 0; i < a->nelts; ++i) {
- if (!(mmask & ap[i].limited))
- continue;
-
- switch (ap[i].type) {
- case T_ENV:
- if (apr_table_get(r->subprocess_env, ap[i].x.from)) {
- return 1;
- }
- break;
-
- case T_ALL:
- return 1;
-
- case T_IP:
- if (apr_ipsubnet_test(ap[i].x.ip, r->connection->remote_addr)) {
- return 1;
- }
- break;
-
- case T_HOST:
- if (!gothost) {
- int remotehost_is_ip;
-
- remotehost = ap_get_remote_host(r->connection, r->per_dir_config,
- REMOTE_DOUBLE_REV, &remotehost_is_ip);
-
- if ((remotehost == NULL) || remotehost_is_ip)
- gothost = 1;
- else
- gothost = 2;
- }
-
- if ((gothost == 2) && in_domain(ap[i].x.from, remotehost))
- return 1;
- break;
-
- case T_FAIL:
- /* do nothing? */
- break;
- }
- }
-
- return 0;
-}
-
-static int check_dir_access(request_rec *r)
-{
- int method = r->method_number;
- access_dir_conf *a =
- (access_dir_conf *)
- ap_get_module_config(r->per_dir_config, &access_module);
- int ret = OK;
-
- if (a->order[method] == ALLOW_THEN_DENY) {
- ret = HTTP_FORBIDDEN;
- if (find_allowdeny(r, a->allows, method))
- ret = OK;
- if (find_allowdeny(r, a->denys, method))
- ret = HTTP_FORBIDDEN;
- }
- else if (a->order[method] == DENY_THEN_ALLOW) {
- if (find_allowdeny(r, a->denys, method))
- ret = HTTP_FORBIDDEN;
- if (find_allowdeny(r, a->allows, method))
- ret = OK;
- }
- else {
- if (find_allowdeny(r, a->allows, method)
- && !find_allowdeny(r, a->denys, method))
- ret = OK;
- else
- ret = HTTP_FORBIDDEN;
- }
-
- if (ret == HTTP_FORBIDDEN
- && (ap_satisfies(r) != SATISFY_ANY || !ap_some_auth_required(r))) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "client denied by server configuration: %s",
- r->filename);
- }
-
- return ret;
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_access_checker(check_dir_access,NULL,NULL,APR_HOOK_MIDDLE);
-}
-
-module AP_MODULE_DECLARE_DATA access_module =
-{
- STANDARD20_MODULE_STUFF,
- create_access_dir_config, /* dir config creater */
- NULL, /* dir merger --- default is to override */
- NULL, /* server config */
- NULL, /* merge server config */
- access_cmds,
- register_hooks /* register hooks */
-};
diff --git a/modules/aaa/mod_access.exp b/modules/aaa/mod_access.exp
deleted file mode 100644
index f8aff339da..0000000000
--- a/modules/aaa/mod_access.exp
+++ /dev/null
@@ -1 +0,0 @@
-access_module
diff --git a/modules/aaa/mod_auth.c b/modules/aaa/mod_auth.c
deleted file mode 100644
index c3768a45fb..0000000000
--- a/modules/aaa/mod_auth.c
+++ /dev/null
@@ -1,338 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * http_auth: authentication
- *
- * Rob McCool
- *
- * Adapted to Apache by rst.
- *
- * dirkx - Added Authoritative control to allow passing on to lower
- * modules if and only if the userid is not known to this
- * module. A known user with a faulty or absent password still
- * causes an AuthRequired. The default is 'Authoritative', i.e.
- * no control is passed along.
- */
-
-#include "apr_strings.h"
-#include "apr_lib.h" /* for apr_password_validate */
-
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_core.h"
-#include "http_log.h"
-#include "http_protocol.h"
-#include "http_request.h"
-
-
-typedef struct {
- char *auth_pwfile;
- char *auth_grpfile;
- int auth_authoritative;
-} auth_config_rec;
-
-static void *create_auth_dir_config(apr_pool_t *p, char *d)
-{
- auth_config_rec *conf = apr_pcalloc(p, sizeof(*conf));
-
- conf->auth_pwfile = NULL; /* just to illustrate the default really */
- conf->auth_grpfile = NULL; /* unless you have a broken HP cc */
- conf->auth_authoritative = 1; /* keep the fortress secure by default */
- return conf;
-}
-
-static const char *set_auth_slot(cmd_parms *cmd, void *offset, const char *f,
- const char *t)
-{
- if (t && strcmp(t, "standard"))
- return apr_pstrcat(cmd->pool, "Invalid auth file type: ", t, NULL);
-
- return ap_set_file_slot(cmd, offset, f);
-}
-
-static const command_rec auth_cmds[] =
-{
- AP_INIT_TAKE12("AuthUserFile", set_auth_slot,
- (void *) XtOffsetOf(auth_config_rec, auth_pwfile), OR_AUTHCFG,
- "text file containing user IDs and passwords"),
- AP_INIT_TAKE12("AuthGroupFile", set_auth_slot,
- (void *) XtOffsetOf(auth_config_rec, auth_grpfile), OR_AUTHCFG,
- "text file containing group names and member user IDs"),
- AP_INIT_FLAG("AuthAuthoritative", ap_set_flag_slot,
- (void *) XtOffsetOf(auth_config_rec, auth_authoritative),
- OR_AUTHCFG,
- "Set to 'no' to allow access control to be passed along to lower "
- "modules if the UserID is not known to this module"),
- {NULL}
-};
-
-module AP_MODULE_DECLARE_DATA auth_module;
-
-static char *get_pw(request_rec *r, char *user, char *auth_pwfile)
-{
- ap_configfile_t *f;
- char l[MAX_STRING_LEN];
- const char *rpw, *w;
- apr_status_t status;
-
- if ((status = ap_pcfg_openfile(&f, r->pool, auth_pwfile)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
- "Could not open password file: %s", auth_pwfile);
- return NULL;
- }
- while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) {
- if ((l[0] == '#') || (!l[0]))
- continue;
- rpw = l;
- w = ap_getword(r->pool, &rpw, ':');
-
- if (!strcmp(user, w)) {
- ap_cfg_closefile(f);
- return ap_getword(r->pool, &rpw, ':');
- }
- }
- ap_cfg_closefile(f);
- return NULL;
-}
-
-static apr_table_t *groups_for_user(apr_pool_t *p, char *user, char *grpfile)
-{
- ap_configfile_t *f;
- apr_table_t *grps = apr_table_make(p, 15);
- apr_pool_t *sp;
- char l[MAX_STRING_LEN];
- const char *group_name, *ll, *w;
- apr_status_t status;
-
- if ((status = ap_pcfg_openfile(&f, p, grpfile)) != APR_SUCCESS) {
-/*add? aplog_error(APLOG_MARK, APLOG_ERR, NULL,
- "Could not open group file: %s", grpfile);*/
- return NULL;
- }
-
- apr_pool_create(&sp, p);
-
- while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) {
- if ((l[0] == '#') || (!l[0]))
- continue;
- ll = l;
- apr_pool_clear(sp);
-
- group_name = ap_getword(sp, &ll, ':');
-
- while (ll[0]) {
- w = ap_getword_conf(sp, &ll);
- if (!strcmp(w, user)) {
- apr_table_setn(grps, apr_pstrdup(p, group_name), "in");
- break;
- }
- }
- }
- ap_cfg_closefile(f);
- apr_pool_destroy(sp);
- return grps;
-}
-
-/* These functions return 0 if client is OK, and proper error status
- * if not... either HTTP_UNAUTHORIZED, if we made a check, and it failed, or
- * HTTP_INTERNAL_SERVER_ERROR, if things are so totally confused that we
- * couldn't figure out how to tell if the client is authorized or not.
- *
- * If they return DECLINED, and all other modules also decline, that's
- * treated by the server core as a configuration error, logged and
- * reported as such.
- */
-
-/* Determine user ID, and check if it really is that user, for HTTP
- * basic authentication...
- */
-
-static int authenticate_basic_user(request_rec *r)
-{
- auth_config_rec *conf = ap_get_module_config(r->per_dir_config,
- &auth_module);
- const char *sent_pw;
- char *real_pw;
- apr_status_t invalid_pw;
- int res;
-
- if ((res = ap_get_basic_auth_pw(r, &sent_pw)))
- return res;
-
- if (!conf->auth_pwfile)
- return DECLINED;
-
- if (!(real_pw = get_pw(r, r->user, conf->auth_pwfile))) {
- if (!(conf->auth_authoritative))
- return DECLINED;
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "user %s not found: %s", r->user, r->uri);
- ap_note_basic_auth_failure(r);
- return HTTP_UNAUTHORIZED;
- }
- invalid_pw = apr_password_validate(sent_pw, real_pw);
- if (invalid_pw != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "user %s: authentication failure for \"%s\": "
- "Password Mismatch",
- r->user, r->uri);
- ap_note_basic_auth_failure(r);
- return HTTP_UNAUTHORIZED;
- }
- return OK;
-}
-
-/* Checking ID */
-
-static int check_user_access(request_rec *r)
-{
- auth_config_rec *conf = ap_get_module_config(r->per_dir_config,
- &auth_module);
- char *user = r->user;
- int m = r->method_number;
- int method_restricted = 0;
- register int x;
- const char *t, *w;
- apr_table_t *grpstatus;
- const apr_array_header_t *reqs_arr = ap_requires(r);
- require_line *reqs;
-
- /* BUG FIX: tadc, 11-Nov-1995. If there is no "requires" directive,
- * then any user will do.
- */
- if (!reqs_arr)
- return (OK);
- reqs = (require_line *) reqs_arr->elts;
-
- if (conf->auth_grpfile)
- grpstatus = groups_for_user(r->pool, user, conf->auth_grpfile);
- else
- grpstatus = NULL;
-
- for (x = 0; x < reqs_arr->nelts; x++) {
-
- if (!(reqs[x].method_mask & (1 << m)))
- continue;
-
- method_restricted = 1;
-
- t = reqs[x].requirement;
- w = ap_getword_white(r->pool, &t);
- if (!strcmp(w, "valid-user"))
- return OK;
- if (!strcmp(w, "user")) {
- while (t[0]) {
- w = ap_getword_conf(r->pool, &t);
- if (!strcmp(user, w))
- return OK;
- }
- }
- else if (!strcmp(w, "group")) {
- if (!grpstatus)
- return DECLINED; /* DBM group? Something else? */
-
- while (t[0]) {
- w = ap_getword_conf(r->pool, &t);
- if (apr_table_get(grpstatus, w))
- return OK;
- }
- } else if (conf->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, 0, r,
- "access to %s failed, reason: unknown require directive:"
- "\"%s\"", r->uri, reqs[x].requirement);
- }
- }
-
- if (!method_restricted)
- return OK;
-
- if (!(conf->auth_authoritative))
- return DECLINED;
-
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "access to %s failed, reason: user %s not allowed access",
- r->uri, user);
-
- ap_note_basic_auth_failure(r);
- return HTTP_UNAUTHORIZED;
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_check_user_id(authenticate_basic_user,NULL,NULL,APR_HOOK_MIDDLE);
- ap_hook_auth_checker(check_user_access,NULL,NULL,APR_HOOK_MIDDLE);
-}
-
-module AP_MODULE_DECLARE_DATA auth_module =
-{
- STANDARD20_MODULE_STUFF,
- create_auth_dir_config, /* dir config creater */
- NULL, /* dir merger --- default is to override */
- NULL, /* server config */
- NULL, /* merge server config */
- auth_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
diff --git a/modules/aaa/mod_auth.exp b/modules/aaa/mod_auth.exp
deleted file mode 100644
index 76adad0a66..0000000000
--- a/modules/aaa/mod_auth.exp
+++ /dev/null
@@ -1 +0,0 @@
-auth_module
diff --git a/modules/aaa/mod_auth_anon.c b/modules/aaa/mod_auth_anon.c
deleted file mode 100644
index 5b008ae6ce..0000000000
--- a/modules/aaa/mod_auth_anon.c
+++ /dev/null
@@ -1,313 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * http_auth: authentication
- *
- * Rob McCool & Brian Behlendorf.
- *
- * Adapted to Apache by rst.
- *
- * Version 0.5 May 1996
- *
- * Modified by Dirk.vanGulik@jrc.it to
- *
- * Adapted to allow anonymous logins, just like with Anon-FTP, when
- * one gives the magic user name 'anonymous' and ones email address
- * as the password.
- *
- * Just add the following tokes to your <directory> setup:
- *
- * Anonymous magic-userid [magic-userid]...
- *
- * Anonymous_MustGiveEmail [ on | off ] default = on
- * Anonymous_LogEmail [ on | off ] default = on
- * Anonymous_VerifyEmail [ on | off ] default = off
- * Anonymous_NoUserId [ on | off ] default = off
- * Anonymous_Authoritative [ on | off ] default = off
- *
- * The magic user id is something like 'anonymous', it is NOT case sensitive.
- *
- * The MustGiveEmail flag can be used to force users to enter something
- * in the password field (like an email address). Default is on.
- *
- * Furthermore the 'NoUserID' flag can be set to allow completely empty
- * usernames in as well; this can be is convenient as a single return
- * in broken GUIs like W95 is often given by the user. The Default is off.
- *
- * Dirk.vanGulik@jrc.it; http://ewse.ceo.org; http://me-www.jrc.it/~dirkx
- *
- */
-
-#include "apr_strings.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#include "httpd.h"
-#include "http_config.h"
-#include "http_core.h"
-#include "http_log.h"
-#include "http_request.h"
-#include "http_protocol.h"
-
-
-typedef struct anon_auth {
- char *password;
- struct anon_auth *next;
-} anon_auth;
-
-typedef struct {
-
- anon_auth *anon_auth_passwords;
- int anon_auth_nouserid;
- int anon_auth_logemail;
- int anon_auth_verifyemail;
- int anon_auth_mustemail;
- int anon_auth_authoritative;
-
-} anon_auth_config_rec;
-
-
-static void *create_anon_auth_dir_config(apr_pool_t *p, char *d)
-{
- anon_auth_config_rec *conf = apr_pcalloc(p, sizeof(*conf));
-
- /* just to illustrate the defaults really. */
- conf->anon_auth_passwords = NULL;
-
- conf->anon_auth_nouserid = 0;
- conf->anon_auth_logemail = 1;
- conf->anon_auth_verifyemail = 0;
- conf->anon_auth_mustemail = 1;
- conf->anon_auth_authoritative = 0;
- return conf;
-}
-
-static const char *anon_set_passwd_flag(cmd_parms *cmd,
- void *my_config, int arg)
-{
- anon_auth_config_rec *conf = my_config;
- conf->anon_auth_mustemail = arg;
- return NULL;
-}
-
-static const char *anon_set_userid_flag(cmd_parms *cmd,
- void *my_config, int arg)
-{
- anon_auth_config_rec *conf = my_config;
- conf->anon_auth_nouserid = arg;
- return NULL;
-}
-
-static const char *anon_set_logemail_flag(cmd_parms *cmd,
- void *my_config, int arg)
-{
- anon_auth_config_rec *conf = my_config;
- conf->anon_auth_logemail = arg;
- return NULL;
-}
-
-static const char *anon_set_verifyemail_flag(cmd_parms *cmd,
- void *my_config, int arg)
-{
- anon_auth_config_rec *conf = my_config;
- conf->anon_auth_verifyemail = arg;
- return NULL;
-}
-static const char *anon_set_authoritative_flag(cmd_parms *cmd,
- void *my_config, int arg)
-{
- anon_auth_config_rec *conf = my_config;
- conf->anon_auth_authoritative = arg;
- return NULL;
-}
-
-static const char *anon_set_string_slots(cmd_parms *cmd,
- void *my_config, const char *arg)
-{
- anon_auth_config_rec *conf = my_config;
- anon_auth *first;
-
- if (!(*arg))
- return "Anonymous string cannot be empty, use Anonymous_NoUserId instead";
-
- /* squeeze in a record */
- first = conf->anon_auth_passwords;
-
- if (!(conf->anon_auth_passwords = apr_palloc(cmd->pool, sizeof(anon_auth))) ||
- !(conf->anon_auth_passwords->password = apr_pstrdup(cmd->pool, arg)))
- return "Failed to claim memory for an anonymous password...";
-
- /* and repair the next */
- conf->anon_auth_passwords->next = first;
-
- return NULL;
-}
-
-static const command_rec anon_auth_cmds[] =
-{
- AP_INIT_ITERATE("Anonymous", anon_set_string_slots, NULL, OR_AUTHCFG,
- "a space-separated list of user IDs"),
- AP_INIT_FLAG("Anonymous_MustGiveEmail", anon_set_passwd_flag, NULL,
- OR_AUTHCFG, "Limited to 'on' or 'off'"),
- AP_INIT_FLAG("Anonymous_NoUserId", anon_set_userid_flag, NULL, OR_AUTHCFG,
- "Limited to 'on' or 'off'"),
- AP_INIT_FLAG("Anonymous_VerifyEmail", anon_set_verifyemail_flag, NULL,
- OR_AUTHCFG, "Limited to 'on' or 'off'"),
- AP_INIT_FLAG("Anonymous_LogEmail", anon_set_logemail_flag, NULL, OR_AUTHCFG,
- "Limited to 'on' or 'off'"),
- AP_INIT_FLAG("Anonymous_Authoritative", anon_set_authoritative_flag, NULL,
- OR_AUTHCFG, "Limited to 'on' or 'off'"),
- {NULL}
-};
-
-module AP_MODULE_DECLARE_DATA auth_anon_module;
-
-static int anon_authenticate_basic_user(request_rec *r)
-{
- anon_auth_config_rec *conf = ap_get_module_config(r->per_dir_config,
- &auth_anon_module);
- const char *sent_pw;
- int res = DECLINED;
-
- if ((res = ap_get_basic_auth_pw(r, &sent_pw)))
- return res;
-
- /* Ignore if we are not configured */
- if (!conf->anon_auth_passwords)
- return DECLINED;
-
- /* Do we allow an empty userID and/or is it the magic one
- */
-
- if ((!(r->user[0])) && (conf->anon_auth_nouserid)) {
- res = OK;
- }
- else {
- anon_auth *p = conf->anon_auth_passwords;
- res = DECLINED;
- while ((res == DECLINED) && (p != NULL)) {
- if (!(strcasecmp(r->user, p->password)))
- res = OK;
- p = p->next;
- }
- }
- if (
- /* username is OK */
- (res == OK)
- /* password been filled out ? */
- && ((!conf->anon_auth_mustemail) || strlen(sent_pw))
- /* does the password look like an email address ? */
- && ((!conf->anon_auth_verifyemail)
- || ((strpbrk("@", sent_pw) != NULL)
- && (strpbrk(".", sent_pw) != NULL)))) {
- if (conf->anon_auth_logemail && ap_is_initial_req(r)) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, APR_SUCCESS, r,
- "Anonymous: Passwd <%s> Accepted",
- sent_pw ? sent_pw : "\'none\'");
- }
- return OK;
- }
- else {
- if (conf->anon_auth_authoritative) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, APR_SUCCESS, r,
- "Anonymous: Authoritative, Passwd <%s> not accepted",
- sent_pw ? sent_pw : "\'none\'");
- return HTTP_UNAUTHORIZED;
- }
- /* Drop out the bottom to return DECLINED */
- }
-
- return DECLINED;
-}
-
-static int check_anon_access(request_rec *r)
-{
-#ifdef NOTYET
- conn_rec *c = r->connection;
- anon_auth_config_rec *conf = ap_get_module_config(r->per_dir_config,
- &auth_anon_module);
-
- if (!conf->anon_auth)
- return DECLINED;
-
- if (strcasecmp(r->connection->user, conf->anon_auth))
- return DECLINED;
-
- return OK;
-#endif
- return DECLINED;
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_check_user_id(anon_authenticate_basic_user,NULL,NULL,APR_HOOK_MIDDLE);
- ap_hook_auth_checker(check_anon_access,NULL,NULL,APR_HOOK_MIDDLE);
-}
-
-module AP_MODULE_DECLARE_DATA auth_anon_module =
-{
- STANDARD20_MODULE_STUFF,
- create_anon_auth_dir_config,/* dir config creater */
- NULL, /* dir merger ensure strictness */
- NULL, /* server config */
- NULL, /* merge server config */
- anon_auth_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
diff --git a/modules/aaa/mod_auth_anon.dsp b/modules/aaa/mod_auth_anon.dsp
deleted file mode 100644
index 9971dac259..0000000000
--- a/modules/aaa/mod_auth_anon.dsp
+++ /dev/null
@@ -1,95 +0,0 @@
-# Microsoft Developer Studio Project File - Name="mod_auth_anon" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=mod_auth_anon - Win32 Release
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "mod_auth_anon.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_auth_anon.mak" CFG="mod_auth_anon - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_auth_anon - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_auth_anon - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "mod_auth_anon - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\os\win32" /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_auth_anon" /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "NDEBUG"
-# ADD RSC /l 0x809 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_auth_anon.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_auth_anon
-# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_auth_anon.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_auth_anon
-
-!ELSEIF "$(CFG)" == "mod_auth_anon - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\..\include" /I "..\..\os\win32" /I "..\..\srclib\apr\include" /I "..\..\srclib\apr-util\include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_auth_anon" /FD /c
-# ADD BASE MTL /nologo /D "_DEBUG" /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "_DEBUG"
-# ADD RSC /l 0x809 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /out:"Debug/mod_auth_anon.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_auth_anon
-# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /out:"Debug/mod_auth_anon.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_auth_anon
-
-!ENDIF
-
-# Begin Target
-
-# Name "mod_auth_anon - Win32 Release"
-# Name "mod_auth_anon - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\mod_auth_anon.c
-# End Source File
-# End Target
-# End Project
diff --git a/modules/aaa/mod_auth_anon.exp b/modules/aaa/mod_auth_anon.exp
deleted file mode 100644
index 63282532a9..0000000000
--- a/modules/aaa/mod_auth_anon.exp
+++ /dev/null
@@ -1 +0,0 @@
-auth_anon_module
diff --git a/modules/aaa/mod_auth_anon.mak b/modules/aaa/mod_auth_anon.mak
deleted file mode 100644
index cc7fba0b46..0000000000
--- a/modules/aaa/mod_auth_anon.mak
+++ /dev/null
@@ -1,330 +0,0 @@
-# Microsoft Developer Studio Generated NMAKE File, Based on mod_auth_anon.dsp
-!IF "$(CFG)" == ""
-CFG=mod_auth_anon - Win32 Release
-!MESSAGE No configuration specified. Defaulting to mod_auth_anon - Win32\
- Release.
-!ENDIF
-
-!IF "$(CFG)" != "mod_auth_anon - Win32 Release" && "$(CFG)" !=\
- "mod_auth_anon - Win32 Debug"
-!MESSAGE Invalid configuration "$(CFG)" specified.
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_auth_anon.mak" CFG="mod_auth_anon - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_auth_anon - Win32 Release" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_auth_anon - Win32 Debug" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-!ERROR An invalid configuration is specified.
-!ENDIF
-
-!IF "$(OS)" == "Windows_NT"
-NULL=
-!ELSE
-NULL=nul
-!ENDIF
-
-!IF "$(CFG)" == "mod_auth_anon - Win32 Release"
-
-OUTDIR=.\Release
-INTDIR=.\Release
-# Begin Custom Macros
-OutDir=.\Release
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_auth_anon.so"
-
-!ELSE
-
-ALL : "libhttpd - Win32 Release" "libapr - Win32 Release"\
- "$(OUTDIR)\mod_auth_anon.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libapr - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\mod_auth_anon.idb"
- -@erase "$(INTDIR)\mod_auth_anon.obj"
- -@erase "$(OUTDIR)\mod_auth_anon.exp"
- -@erase "$(OUTDIR)\mod_auth_anon.lib"
- -@erase "$(OUTDIR)\mod_auth_anon.map"
- -@erase "$(OUTDIR)\mod_auth_anon.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\os\win32" /I\
- "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D\
- "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_auth_anon" /FD /c
-CPP_OBJS=.\Release/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_auth_anon.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no\
- /pdb:"$(OUTDIR)\mod_auth_anon.pdb" /map:"$(INTDIR)\mod_auth_anon.map"\
- /machine:I386 /out:"$(OUTDIR)\mod_auth_anon.so"\
- /implib:"$(OUTDIR)\mod_auth_anon.lib"\
- /base:@..\..\os\win32\BaseAddr.ref,mod_auth_anon
-LINK32_OBJS= \
- "$(INTDIR)\mod_auth_anon.obj" \
- "..\..\Release\libhttpd.lib" \
- "..\..\srclib\apr\Release\libapr.lib"
-
-"$(OUTDIR)\mod_auth_anon.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ELSEIF "$(CFG)" == "mod_auth_anon - Win32 Debug"
-
-OUTDIR=.\Debug
-INTDIR=.\Debug
-# Begin Custom Macros
-OutDir=.\Debug
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_auth_anon.so"
-
-!ELSE
-
-ALL : "libhttpd - Win32 Debug" "libapr - Win32 Debug"\
- "$(OUTDIR)\mod_auth_anon.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libapr - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\mod_auth_anon.idb"
- -@erase "$(INTDIR)\mod_auth_anon.obj"
- -@erase "$(OUTDIR)\mod_auth_anon.exp"
- -@erase "$(OUTDIR)\mod_auth_anon.lib"
- -@erase "$(OUTDIR)\mod_auth_anon.map"
- -@erase "$(OUTDIR)\mod_auth_anon.pdb"
- -@erase "$(OUTDIR)\mod_auth_anon.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /I\
- "..\..\srclib\apr\include" /I "..\..\srclib\apr-util\include" /D "_DEBUG" /D\
- "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_auth_anon" /FD /c
-CPP_OBJS=.\Debug/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_auth_anon.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no\
- /pdb:"$(OUTDIR)\mod_auth_anon.pdb" /map:"$(INTDIR)\mod_auth_anon.map" /debug\
- /machine:I386 /out:"$(OUTDIR)\mod_auth_anon.so"\
- /implib:"$(OUTDIR)\mod_auth_anon.lib"\
- /base:@..\..\os\win32\BaseAddr.ref,mod_auth_anon
-LINK32_OBJS= \
- "$(INTDIR)\mod_auth_anon.obj" \
- "..\..\Debug\libhttpd.lib" \
- "..\..\srclib\apr\Debug\libapr.lib"
-
-"$(OUTDIR)\mod_auth_anon.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ENDIF
-
-
-!IF "$(CFG)" == "mod_auth_anon - Win32 Release" || "$(CFG)" ==\
- "mod_auth_anon - Win32 Debug"
-
-!IF "$(CFG)" == "mod_auth_anon - Win32 Release"
-
-"libapr - Win32 Release" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F .\libapr.mak CFG="libapr - Win32 Release"
- cd "..\..\modules\aaa"
-
-"libapr - Win32 ReleaseCLEAN" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libapr.mak CFG="libapr - Win32 Release"\
- RECURSE=1
- cd "..\..\modules\aaa"
-
-!ELSEIF "$(CFG)" == "mod_auth_anon - Win32 Debug"
-
-"libapr - Win32 Debug" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F .\libapr.mak CFG="libapr - Win32 Debug"
- cd "..\..\modules\aaa"
-
-"libapr - Win32 DebugCLEAN" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libapr.mak CFG="libapr - Win32 Debug"\
- RECURSE=1
- cd "..\..\modules\aaa"
-
-!ENDIF
-
-!IF "$(CFG)" == "mod_auth_anon - Win32 Release"
-
-"libhttpd - Win32 Release" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) /F .\libhttpd.mak CFG="libhttpd - Win32 Release"
- cd ".\modules\aaa"
-
-"libhttpd - Win32 ReleaseCLEAN" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libhttpd.mak CFG="libhttpd - Win32 Release"\
- RECURSE=1
- cd ".\modules\aaa"
-
-!ELSEIF "$(CFG)" == "mod_auth_anon - Win32 Debug"
-
-"libhttpd - Win32 Debug" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) /F .\libhttpd.mak CFG="libhttpd - Win32 Debug"
- cd ".\modules\aaa"
-
-"libhttpd - Win32 DebugCLEAN" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libhttpd.mak CFG="libhttpd - Win32 Debug"\
- RECURSE=1
- cd ".\modules\aaa"
-
-!ENDIF
-
-SOURCE=.\mod_auth_anon.c
-DEP_CPP_MOD_A=\
- "..\..\include\ap_config.h"\
- "..\..\include\ap_mmn.h"\
- "..\..\include\ap_release.h"\
- "..\..\include\http_config.h"\
- "..\..\include\http_core.h"\
- "..\..\include\http_log.h"\
- "..\..\include\http_protocol.h"\
- "..\..\include\http_request.h"\
- "..\..\include\httpd.h"\
- "..\..\include\pcreposix.h"\
- "..\..\include\util_cfgtree.h"\
- "..\..\include\util_filter.h"\
- "..\..\include\util_uri.h"\
- "..\..\os\win32\os.h"\
- "..\..\srclib\apr-util\include\apr_buckets.h"\
- "..\..\srclib\apr-util\include\apr_hooks.h"\
- "..\..\srclib\apr-util\include\apr_ring.h"\
- "..\..\srclib\apr-util\include\apu.h"\
- "..\..\srclib\apr\include\apr.h"\
- "..\..\srclib\apr\include\apr_dso.h"\
- "..\..\srclib\apr\include\apr_errno.h"\
- "..\..\srclib\apr\include\apr_file_info.h"\
- "..\..\srclib\apr\include\apr_file_io.h"\
- "..\..\srclib\apr\include\apr_general.h"\
- "..\..\srclib\apr\include\apr_lock.h"\
- "..\..\srclib\apr\include\apr_mmap.h"\
- "..\..\srclib\apr\include\apr_network_io.h"\
- "..\..\srclib\apr\include\apr_pools.h"\
- "..\..\srclib\apr\include\apr_portable.h"\
- "..\..\srclib\apr\include\apr_strings.h"\
- "..\..\srclib\apr\include\apr_tables.h"\
- "..\..\srclib\apr\include\apr_thread_proc.h"\
- "..\..\srclib\apr\include\apr_time.h"\
- "..\..\srclib\apr\include\apr_user.h"\
- "..\..\srclib\apr\include\apr_want.h"\
-
-NODEP_CPP_MOD_A=\
- "..\..\include\ap_config_auto.h"\
-
-
-"$(INTDIR)\mod_auth_anon.obj" : $(SOURCE) $(DEP_CPP_MOD_A) "$(INTDIR)"
-
-
-
-!ENDIF
-
diff --git a/modules/aaa/mod_auth_db.c b/modules/aaa/mod_auth_db.c
deleted file mode 100644
index a1925a8298..0000000000
--- a/modules/aaa/mod_auth_db.c
+++ /dev/null
@@ -1,419 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * mod_auth_db: authentication
- *
- * Original work by Rob McCool & Brian Behlendorf.
- *
- * Adapted to Apache by rst (mod_auth_dbm)
- *
- * Adapted for Berkeley DB by Andrew Cohen
- *
- * apache 2 port by Brian Martin
- *
- * mod_auth_db was based on mod_auth_dbm.
- *
- * Warning, this is not a drop in replacement for mod_auth_dbm,
- * for people wanting to switch from dbm to Berkeley DB.
- * It requires the use of AuthDBUserFile and AuthDBGroupFile
- * instead of AuthDBMUserFile AuthDBMGroupFile
- *
- * Also, in the configuration file you need to specify
- * auth_db_module rather than auth_dbm_module
- *
- * On some BSD systems (e.g. FreeBSD and NetBSD) dbm is automatically
- * mapped to Berkeley DB. You can use either mod_auth_dbm or
- * mod_auth_db. The latter makes it more obvious that it's Berkeley.
- * On other platforms where you want to use the DB library you
- * usually have to install it first. See http://www.sleepycat.com/
- * for the distribution. The interface this module uses is the
- * one from DB version 1.85 and 1.86, but DB version 2.x
- * can also be used when compatibility mode is enabled.
- *
- * dirkx - Added Authoritative control to allow passing on to lower
- * modules if and only if the userid is not known to this
- * module. A known user with a faulty or absent password still
- * causes an AuthRequired. The default is 'Authoritative', i.e.
- * no control is passed along.
- */
-
-#include "apr_lib.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_core.h"
-#include "http_log.h"
-#include "http_protocol.h"
-#include "http_request.h" /* for ap_hook_(check_user_id | auth_check) */
-
-#ifdef HAVE_DB_H
-#include <db.h>
-#endif
-
-#if defined(DB_VERSION_MAJOR) && (DB_VERSION_MAJOR == 3)
-#define DB_VER 3
-#elif defined(DB_VERSION_MAJOR) && (DB_VERSION_MAJOR == 2)
-#define DB_VER 2
-#else
-#define DB_VER 1
-#endif
-
-typedef struct {
-
- char *auth_dbpwfile;
- char *auth_dbgrpfile;
- int auth_dbauthoritative;
-} db_auth_config_rec;
-
-static void *create_db_auth_dir_config(apr_pool_t *p, char *d)
-{
- db_auth_config_rec *conf = apr_pcalloc(p, sizeof(*conf));
-
- conf->auth_dbpwfile = NULL;
- conf->auth_dbgrpfile = NULL;
- conf->auth_dbauthoritative = 1; /* fortress is secure by default */
- return conf;
-}
-
-static const char *set_db_slot(cmd_parms *cmd, void *offset, const char *f, const char *t)
-{
- if (!t || strcmp(t, "db"))
- return DECLINE_CMD;
-
- return ap_set_file_slot(cmd, offset, f);
-}
-
-static const command_rec db_auth_cmds[] =
-{
- AP_INIT_TAKE1("AuthDBUserFile", ap_set_file_slot,
- (void *) XtOffsetOf(db_auth_config_rec, auth_dbpwfile),
- OR_AUTHCFG, NULL),
- AP_INIT_TAKE1("AuthDBGroupFile", ap_set_file_slot,
- (void *) XtOffsetOf(db_auth_config_rec, auth_dbgrpfile),
- OR_AUTHCFG, NULL),
- AP_INIT_TAKE12("AuthUserFile", set_db_slot,
- (void *) XtOffsetOf(db_auth_config_rec, auth_dbpwfile),
- OR_AUTHCFG, NULL),
- AP_INIT_TAKE12("AuthGroupFile", set_db_slot,
- (void *) XtOffsetOf(db_auth_config_rec, auth_dbgrpfile),
- OR_AUTHCFG, NULL),
- AP_INIT_FLAG("AuthDBAuthoritative", ap_set_flag_slot,
- (void *) XtOffsetOf(db_auth_config_rec, auth_dbauthoritative),
- OR_AUTHCFG,
- "Set to 'no' to allow access control to be passed along to lower modules if the userID is not known to this module"),
- {NULL}
-};
-
-module auth_db_module;
-
-static char *get_db_pw(request_rec *r, char *user, const char *auth_dbpwfile)
-{
- DB *f;
- DBT d, q;
- char *pw = NULL;
-#if DB_VER > 1
- int retval;
-#endif
-
- memset(&d, 0, sizeof(d));
- memset(&q, 0, sizeof(q));
-
- q.data = user;
- q.size = strlen(q.data);
-
-#if DB_VER == 3
- db_create(&f, NULL, 0);
- if ((retval = f->open(f, auth_dbpwfile, NULL, DB_HASH, DB_RDONLY, 0664)) != 0) {
- char * reason;
- switch(retval) {
- case DB_OLD_VERSION:
- reason = "Old database version. Upgrade to version 3";
- break;
-
- case EEXIST:
- reason = "DB_CREATE and DB_EXCL were specified and the file exists";
- break;
-
- case EINVAL:
- reason = "An invalid flag value or parameter was specified";
- break;
-
- case ENOENT:
- reason = "A non-existent re_source file was specified";
- break;
-
- default:
- reason = "And I don't know why";
- break;
- }
- ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r,
- "could not open db auth file %s: %s",
- auth_dbpwfile, reason);
- return NULL;
- }
-#elif DB_VER == 2
- if ((retval = db_open(auth_dbpwfile, DB_HASH, DB_RDONLY, 0664, NULL, NULL, &f)) != 0) {
- char * reason;
- switch(retval) {
-
- case EEXIST:
- reason = "DB_CREATE and DB_EXCL were specified and the file exists.";
- break;
-
- case EINVAL:
- reason = "An invalid flag value or parameter was specified";
- break;
-
- case ENOENT:
- reason = "A non-existent re_source file was specified";
- break;
-
- default:
- reason = "And I don't know why";
- break;
- }
- ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r,
- "could not open db auth file %s: %s",
- auth_dbpwfile, reason);
- return NULL;
- }
-#else
- if (!(f = dbopen(auth_dbpwfile, O_RDONLY, 0664, DB_HASH, NULL))) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r,
- "could not open db auth file: %s", auth_dbpwfile);
- return NULL;
- }
-#endif
-
-#if DB_VER == 3 || DB_VER == 2
- if (!((f->get) (f, NULL, &q, &d, 0))) {
-#else
- if (!((f->get) (f, &q, &d, 0))) {
-#endif
- pw = apr_palloc(r->pool, d.size + 1);
- strncpy(pw, d.data, d.size);
- pw[d.size] = '\0'; /* Terminate the string */
- }
-
-#if DB_VER == 3 || DB_VER == 2
- (f->close) (f, 0);
-#else
- (f->close) (f);
-#endif
- return pw;
-}
-
-/* We do something strange with the group file. If the group file
- * contains any : we assume the format is
- * key=username value=":"groupname [":"anything here is ignored]
- * otherwise we now (0.8.14+) assume that the format is
- * key=username value=groupname
- * The first allows the password and group files to be the same
- * physical DB file; key=username value=password":"groupname[":"anything]
- *
- * mark@telescope.org, 22Sep95
- */
-
-static char *get_db_grp(request_rec *r, char *user, const char *auth_dbgrpfile)
-{
- char *grp_data = get_db_pw(r, user, auth_dbgrpfile);
- char *grp_colon;
- char *grp_colon2;
-
- if (grp_data == NULL)
- return NULL;
-
- if ((grp_colon = strchr(grp_data, ':')) != NULL) {
- grp_colon2 = strchr(++grp_colon, ':');
- if (grp_colon2)
- *grp_colon2 = '\0';
- return grp_colon;
- }
- return grp_data;
-}
-
-static int db_authenticate_basic_user(request_rec *r)
-{
- db_auth_config_rec *conf = ap_get_module_config(r->per_dir_config,
- &auth_db_module);
- const char *sent_pw;
- char *real_pw, *colon_pw;
- apr_status_t invalid_pw;
- int res;
-
- if ((res = ap_get_basic_auth_pw(r, &sent_pw)))
- return res;
-
- if (!conf->auth_dbpwfile) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "DB file %s not found", conf->auth_dbpwfile);
- return DECLINED;
- }
-
- if (!(real_pw = get_db_pw(r, r->user, conf->auth_dbpwfile))) {
- if (!(conf->auth_dbauthoritative))
- return DECLINED;
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "DB user %s not found: %s", r->user, r->filename);
- ap_note_basic_auth_failure(r);
- return HTTP_UNAUTHORIZED;
- }
- /* Password is up to first : if exists */
- colon_pw = strchr(real_pw, ':');
- if (colon_pw) {
- *colon_pw = '\0';
- }
-
- invalid_pw = apr_password_validate(sent_pw, real_pw);
-
- if (invalid_pw != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "DB user %s: authentication failure for \"%s\": "
- "Password Mismatch",
- r->user, r->uri);
- ap_note_basic_auth_failure(r);
- return HTTP_UNAUTHORIZED;
- }
- return OK;
-}
-
-/* Checking ID */
-
-static int db_check_auth(request_rec *r)
-{
- db_auth_config_rec *conf = ap_get_module_config(r->per_dir_config,
- &auth_db_module);
- char *user = r->user;
- int m = r->method_number;
-
- const apr_array_header_t *reqs_arr = ap_requires(r);
- require_line *reqs = reqs_arr ? (require_line *) reqs_arr->elts : NULL;
-
- register int x;
- const char *t;
- char *w;
-
- if (!conf->auth_dbgrpfile)
- return DECLINED;
- if (!reqs_arr)
- return DECLINED;
-
- for (x = 0; x < reqs_arr->nelts; x++) {
-
- if (!(reqs[x].method_mask & (1 << m)))
- continue;
-
- t = reqs[x].requirement;
- w = ap_getword_white(r->pool, &t);
-
- if (!strcmp(w, "group") && conf->auth_dbgrpfile) {
- const char *orig_groups, *groups;
- char *v;
-
- if (!(groups = get_db_grp(r, user, conf->auth_dbgrpfile))) {
- if (!(conf->auth_dbauthoritative))
- return DECLINED;
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "user %s not in DB group file %s: %s",
- user, conf->auth_dbgrpfile, r->filename);
- ap_note_basic_auth_failure(r);
- return HTTP_UNAUTHORIZED;
- }
- orig_groups = groups;
- while (t[0]) {
- w = ap_getword_white(r->pool, &t);
- groups = orig_groups;
- while (groups[0]) {
- v = ap_getword(r->pool, &groups, ',');
- if (!strcmp(v, w))
- return OK;
- }
- }
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "user %s not in right group: %s", user, r->filename);
- ap_note_basic_auth_failure(r);
- return HTTP_UNAUTHORIZED;
- }
- }
-
- return DECLINED;
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_check_user_id(db_authenticate_basic_user, NULL, NULL,
- APR_HOOK_MIDDLE);
- ap_hook_auth_checker(db_check_auth, NULL, NULL, APR_HOOK_MIDDLE);
-}
-
-module auth_db_module =
-{
- STANDARD20_MODULE_STUFF,
- create_db_auth_dir_config, /* dir config creater */
- NULL, /* dir merger --- default is to override */
- NULL, /* server config */
- NULL, /* merge server config */
- db_auth_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
-
diff --git a/modules/aaa/mod_auth_db.module b/modules/aaa/mod_auth_db.module
deleted file mode 100644
index 525075c3f1..0000000000
--- a/modules/aaa/mod_auth_db.module
+++ /dev/null
@@ -1,37 +0,0 @@
-Name: db_auth_module
-ConfigStart
- # XXX: this needs updating for apache-2.0 configuration method
- DB_VERSION=''
- DB_LIB=''
- if ./build/TestCompile func db_open; then
- DB_VERSION='Berkeley-DB/2.x'
- else
- if ./build/TestCompile lib db db_open; then
- DB_VERSION='Berkeley-DB/2.x'
- DB_LIB='-ldb'
- else
- if ./build/TestCompile func dbopen; then
- DB_VERSION='Berkeley-DB/1.x'
- else
- if ./build/TestCompile lib db dbopen; then
- DB_VERSION='Berkeley-DB/1.x'
- DB_LIB='-ldb'
- fi
- fi
- fi
- fi
- if [ ".$DB_VERSION" != . ]; then
- if [ ".$DB_LIB" != . ]; then
- LIBS="$LIBS $DB_LIB"
- echo " using $DB_VERSION for mod_auth_db ($DB_LIB)"
- else
- echo " using $DB_VERSION for mod_auth_db (-lc)"
- fi
- else
- echo "Error: Neither Berkeley-DB/1.x nor Berkeley-DB/2.x library found."
- echo " Either disable mod_auth_db or provide us with the paths"
- echo " to the Berkeley-DB include and library files."
- echo " (Hint: INCLUDES, LDFLAGS, LIBS)"
- exit 1
- fi
-ConfigEnd
diff --git a/modules/aaa/mod_auth_dbm.c b/modules/aaa/mod_auth_dbm.c
deleted file mode 100644
index 0b9fcb4273..0000000000
--- a/modules/aaa/mod_auth_dbm.c
+++ /dev/null
@@ -1,358 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * http_auth: authentication
- *
- * Rob McCool & Brian Behlendorf.
- *
- * Adapted to Apache by rst.
- *
- * dirkx - Added Authoritative control to allow passing on to lower
- * modules if and only if the userid is not known to this
- * module. A known user with a faulty or absent password still
- * causes an AuthRequired. The default is 'Authoritative', i.e.
- * no control is passed along.
- */
-
-#include "apr_lib.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#if defined(AP_AUTH_DBM_USE_APR)
-#include "apr_dbm.h"
-#define DBM apr_dbm_t
-#define datum apr_datum_t
-#define dbm_open apr_dbm_open
-#define dbm_fetch apr_dbm_fetch
-#define dbm_close apr_dbm_close
-#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) \
- && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
-#include <db1/ndbm.h>
-#else
-#include <ndbm.h>
-#endif
-
-#include "httpd.h"
-#include "http_config.h"
-#include "http_core.h"
-#include "http_log.h"
-#include "http_protocol.h"
-#include "http_request.h" /* for ap_hook_(check_user_id | auth_checker)*/
-
-
-/*
- * Module definition information - the part between the -START and -END
- * lines below is used by Configure. This could be stored in a separate
- * instead.
- *
- * XXX: this needs updating for apache-2.0 configuration method
- * MODULE-DEFINITION-START
- * Name: auth_dbm_module
- * ConfigStart
- . ./build/find-dbm-lib
- * ConfigEnd
- * MODULE-DEFINITION-END
- */
-
-typedef struct {
-
- char *auth_dbmpwfile;
- char *auth_dbmgrpfile;
- int auth_dbmauthoritative;
-
-} dbm_auth_config_rec;
-
-static void *create_dbm_auth_dir_config(apr_pool_t *p, char *d)
-{
- dbm_auth_config_rec *conf = apr_pcalloc(p, sizeof(*conf));
-
- conf->auth_dbmpwfile = NULL;
- conf->auth_dbmgrpfile = NULL;
- conf->auth_dbmauthoritative = 1; /* fortress is secure by default */
-
- return conf;
-}
-
-static const char *set_dbm_slot(cmd_parms *cmd, void *offset,
- const char *f, const char *t)
-{
- if (!t || strcmp(t, "dbm"))
- return DECLINE_CMD;
-
- return ap_set_file_slot(cmd, offset, f);
-}
-
-static const command_rec dbm_auth_cmds[] =
-{
- AP_INIT_TAKE1("AuthDBMUserFile", ap_set_file_slot,
- (void *) XtOffsetOf(dbm_auth_config_rec, auth_dbmpwfile),
- OR_AUTHCFG, NULL),
- AP_INIT_TAKE1("AuthDBMGroupFile", ap_set_file_slot,
- (void *) XtOffsetOf(dbm_auth_config_rec, auth_dbmgrpfile),
- OR_AUTHCFG, NULL),
- AP_INIT_TAKE12("AuthUserFile", set_dbm_slot,
- (void *) XtOffsetOf(dbm_auth_config_rec, auth_dbmpwfile),
- OR_AUTHCFG, NULL),
- AP_INIT_TAKE12("AuthGroupFile", set_dbm_slot,
- (void *) XtOffsetOf(dbm_auth_config_rec, auth_dbmgrpfile),
- OR_AUTHCFG, NULL),
- AP_INIT_FLAG("AuthDBMAuthoritative", ap_set_flag_slot,
- (void *) XtOffsetOf(dbm_auth_config_rec, auth_dbmauthoritative),
- OR_AUTHCFG, "Set to 'no' to allow access control to be passed along to lower modules, if the UserID is not known in this module"),
- {NULL}
-};
-
-module AP_MODULE_DECLARE_DATA auth_dbm_module;
-
-static char *get_dbm_pw(request_rec *r, char *user, char *auth_dbmpwfile)
-{
- DBM *f;
- datum d, q;
- char *pw = NULL;
-#ifdef AP_AUTH_DBM_USE_APR
- apr_status_t retval;
-#endif
- q.dptr = user;
-#ifndef NETSCAPE_DBM_COMPAT
- q.dsize = strlen(q.dptr);
-#else
- q.dsize = strlen(q.dptr) + 1;
-#endif
-
-#ifdef AP_AUTH_DBM_USE_APR
- if (!(retval = dbm_open(&f, auth_dbmpwfile, APR_DBM_READONLY, APR_OS_DEFAULT, r->pool))) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, retval, r,
- "could not open sdbm auth file: %s", auth_dbmpwfile);
- return NULL;
- }
- if (dbm_fetch(f, q, &d) == APR_SUCCESS)
- /* sorry for the obscurity ... falls through to the
- * if (d.dptr) { block ...
- */
-
-#else
- if (!(f = dbm_open(auth_dbmpwfile, O_RDONLY, 0664))) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r,
- "could not open dbm auth file: %s", auth_dbmpwfile);
- return NULL;
- }
- d = dbm_fetch(f, q);
-
-#endif
-
- if (d.dptr) {
- pw = apr_palloc(r->pool, d.dsize + 1);
- strncpy(pw, d.dptr, d.dsize);
- pw[d.dsize] = '\0'; /* Terminate the string */
- }
-
- dbm_close(f);
- return pw;
-}
-
-/* We do something strange with the group file. If the group file
- * contains any : we assume the format is
- * key=username value=":"groupname [":"anything here is ignored]
- * otherwise we now (0.8.14+) assume that the format is
- * key=username value=groupname
- * The first allows the password and group files to be the same
- * physical DBM file; key=username value=password":"groupname[":"anything]
- *
- * mark@telescope.org, 22Sep95
- */
-
-static char *get_dbm_grp(request_rec *r, char *user, char *auth_dbmgrpfile)
-{
- char *grp_data = get_dbm_pw(r, user, auth_dbmgrpfile);
- char *grp_colon;
- char *grp_colon2;
-
- if (grp_data == NULL)
- return NULL;
-
- if ((grp_colon = strchr(grp_data, ':')) != NULL) {
- grp_colon2 = strchr(++grp_colon, ':');
- if (grp_colon2)
- *grp_colon2 = '\0';
- return grp_colon;
- }
- return grp_data;
-}
-
-static int dbm_authenticate_basic_user(request_rec *r)
-{
- dbm_auth_config_rec *conf = ap_get_module_config(r->per_dir_config,
- &auth_dbm_module);
- const char *sent_pw;
- char *real_pw, *colon_pw;
- apr_status_t invalid_pw;
- int res;
-
- if ((res = ap_get_basic_auth_pw(r, &sent_pw)))
- return res;
-
- if (!conf->auth_dbmpwfile)
- return DECLINED;
-
- if (!(real_pw = get_dbm_pw(r, r->user, conf->auth_dbmpwfile))) {
- if (!(conf->auth_dbmauthoritative))
- return DECLINED;
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "DBM user %s not found: %s", r->user, r->filename);
- ap_note_basic_auth_failure(r);
- return HTTP_UNAUTHORIZED;
- }
- /* Password is up to first : if exists */
- colon_pw = strchr(real_pw, ':');
- if (colon_pw) {
- *colon_pw = '\0';
- }
- invalid_pw = apr_password_validate(sent_pw, real_pw);
- if (invalid_pw != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "DBM user %s: authentication failure for \"%s\": "
- "Password Mismatch",
- r->user, r->uri);
- ap_note_basic_auth_failure(r);
- return HTTP_UNAUTHORIZED;
- }
- return OK;
-}
-
-/* Checking ID */
-
-static int dbm_check_auth(request_rec *r)
-{
- dbm_auth_config_rec *conf = ap_get_module_config(r->per_dir_config,
- &auth_dbm_module);
- char *user = r->user;
- int m = r->method_number;
-
- const apr_array_header_t *reqs_arr = ap_requires(r);
- require_line *reqs = reqs_arr ? (require_line *) reqs_arr->elts : NULL;
-
- register int x;
- const char *t;
- char *w;
-
- if (!conf->auth_dbmgrpfile)
- return DECLINED;
- if (!reqs_arr)
- return DECLINED;
-
- for (x = 0; x < reqs_arr->nelts; x++) {
-
- if (!(reqs[x].method_mask & (1 << m)))
- continue;
-
- t = reqs[x].requirement;
- w = ap_getword_white(r->pool, &t);
-
- if (!strcmp(w, "group") && conf->auth_dbmgrpfile) {
- const char *orig_groups, *groups;
- char *v;
-
- if (!(groups = get_dbm_grp(r, user, conf->auth_dbmgrpfile))) {
- if (!(conf->auth_dbmauthoritative))
- return DECLINED;
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "user %s not in DBM group file %s: %s",
- user, conf->auth_dbmgrpfile, r->filename);
- ap_note_basic_auth_failure(r);
- return HTTP_UNAUTHORIZED;
- }
- orig_groups = groups;
- while (t[0]) {
- w = ap_getword_white(r->pool, &t);
- groups = orig_groups;
- while (groups[0]) {
- v = ap_getword(r->pool, &groups, ',');
- if (!strcmp(v, w))
- return OK;
- }
- }
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "user %s not in right group: %s",
- user, r->filename);
- ap_note_basic_auth_failure(r);
- return HTTP_UNAUTHORIZED;
- }
- }
-
- return DECLINED;
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_check_user_id(dbm_authenticate_basic_user, NULL, NULL,
- APR_HOOK_MIDDLE);
- ap_hook_auth_checker(dbm_check_auth, NULL, NULL, APR_HOOK_MIDDLE);
-}
-
-module AP_MODULE_DECLARE_DATA auth_dbm_module =
-{
- STANDARD20_MODULE_STUFF,
- create_dbm_auth_dir_config, /* dir config creater */
- NULL, /* dir merger --- default is to override */
- NULL, /* server config */
- NULL, /* merge server config */
- dbm_auth_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
diff --git a/modules/aaa/mod_auth_dbm.dsp b/modules/aaa/mod_auth_dbm.dsp
deleted file mode 100644
index 93fa4abc6d..0000000000
--- a/modules/aaa/mod_auth_dbm.dsp
+++ /dev/null
@@ -1,95 +0,0 @@
-# Microsoft Developer Studio Project File - Name="mod_auth_dbm" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=mod_auth_dbm - Win32 Release
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "mod_auth_dbm.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_auth_dbm.mak" CFG="mod_auth_dbm - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_auth_dbm - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_auth_dbm - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "mod_auth_dbm - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /I "..\..\srclib\sdbm" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "AP_AUTH_DBM_USE_APR" /Fd"Release\mod_auth_dbm" /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "NDEBUG"
-# ADD RSC /l 0x809 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_auth_dbm.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_auth_dbm
-# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_auth_dbm.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_auth_dbm
-
-!ELSEIF "$(CFG)" == "mod_auth_dbm - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\..\include" /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /I "..\..\srclib\sdbm" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "AP_AUTH_DBM_USE_APR" /Fd"Debug\mod_auth_dbm" /FD /c
-# ADD BASE MTL /nologo /D "_DEBUG" /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "_DEBUG"
-# ADD RSC /l 0x809 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /out:"Debug/mod_auth_dbm.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_auth_dbm
-# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /out:"Debug/mod_auth_dbm.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_auth_dbm
-
-!ENDIF
-
-# Begin Target
-
-# Name "mod_auth_dbm - Win32 Release"
-# Name "mod_auth_dbm - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\mod_auth_dbm.c
-# End Source File
-# End Target
-# End Project
diff --git a/modules/aaa/mod_auth_dbm.exp b/modules/aaa/mod_auth_dbm.exp
deleted file mode 100644
index 7038e8047d..0000000000
--- a/modules/aaa/mod_auth_dbm.exp
+++ /dev/null
@@ -1 +0,0 @@
-auth_dbm_module
diff --git a/modules/aaa/mod_auth_dbm.mak b/modules/aaa/mod_auth_dbm.mak
deleted file mode 100644
index 11d7970042..0000000000
--- a/modules/aaa/mod_auth_dbm.mak
+++ /dev/null
@@ -1,366 +0,0 @@
-# Microsoft Developer Studio Generated NMAKE File, Based on mod_auth_dbm.dsp
-!IF "$(CFG)" == ""
-CFG=mod_auth_dbm - Win32 Release
-!MESSAGE No configuration specified. Defaulting to mod_auth_dbm - Win32\
- Release.
-!ENDIF
-
-!IF "$(CFG)" != "mod_auth_dbm - Win32 Release" && "$(CFG)" !=\
- "mod_auth_dbm - Win32 Debug"
-!MESSAGE Invalid configuration "$(CFG)" specified.
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_auth_dbm.mak" CFG="mod_auth_dbm - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_auth_dbm - Win32 Release" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_auth_dbm - Win32 Debug" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-!ERROR An invalid configuration is specified.
-!ENDIF
-
-!IF "$(OS)" == "Windows_NT"
-NULL=
-!ELSE
-NULL=nul
-!ENDIF
-
-!IF "$(CFG)" == "mod_auth_dbm - Win32 Release"
-
-OUTDIR=.\Release
-INTDIR=.\Release
-# Begin Custom Macros
-OutDir=.\Release
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_auth_dbm.so"
-
-!ELSE
-
-ALL : "libhttpd - Win32 Release" "libaprutil - Win32 Release"\
- "libapr - Win32 Release" "$(OUTDIR)\mod_auth_dbm.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN"\
- "libhttpd - Win32 ReleaseCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\mod_auth_dbm.idb"
- -@erase "$(INTDIR)\mod_auth_dbm.obj"
- -@erase "$(OUTDIR)\mod_auth_dbm.exp"
- -@erase "$(OUTDIR)\mod_auth_dbm.lib"
- -@erase "$(OUTDIR)\mod_auth_dbm.map"
- -@erase "$(OUTDIR)\mod_auth_dbm.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\srclib\apr\include"\
- /I "../../srclib/apr-util/include" /I "..\..\srclib\sdbm" /I "..\..\os\win32"\
- /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "AP_AUTH_DBM_USE_APR" /Fo"$(INTDIR)\\"\
- /Fd"$(INTDIR)\mod_auth_dbm" /FD /c
-CPP_OBJS=.\Release/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_auth_dbm.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no\
- /pdb:"$(OUTDIR)\mod_auth_dbm.pdb" /map:"$(INTDIR)\mod_auth_dbm.map"\
- /machine:I386 /out:"$(OUTDIR)\mod_auth_dbm.so"\
- /implib:"$(OUTDIR)\mod_auth_dbm.lib"\
- /base:@..\..\os\win32\BaseAddr.ref,mod_auth_dbm
-LINK32_OBJS= \
- "$(INTDIR)\mod_auth_dbm.obj" \
- "..\..\Release\libhttpd.lib" \
- "..\..\srclib\apr-util\Release\libaprutil.lib" \
- "..\..\srclib\apr\Release\libapr.lib"
-
-"$(OUTDIR)\mod_auth_dbm.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ELSEIF "$(CFG)" == "mod_auth_dbm - Win32 Debug"
-
-OUTDIR=.\Debug
-INTDIR=.\Debug
-# Begin Custom Macros
-OutDir=.\Debug
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_auth_dbm.so"
-
-!ELSE
-
-ALL : "libhttpd - Win32 Debug" "libaprutil - Win32 Debug"\
- "libapr - Win32 Debug" "$(OUTDIR)\mod_auth_dbm.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN"\
- "libhttpd - Win32 DebugCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\mod_auth_dbm.idb"
- -@erase "$(INTDIR)\mod_auth_dbm.obj"
- -@erase "$(OUTDIR)\mod_auth_dbm.exp"
- -@erase "$(OUTDIR)\mod_auth_dbm.lib"
- -@erase "$(OUTDIR)\mod_auth_dbm.map"
- -@erase "$(OUTDIR)\mod_auth_dbm.pdb"
- -@erase "$(OUTDIR)\mod_auth_dbm.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I\
- "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /I\
- "..\..\srclib\sdbm" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D\
- "AP_AUTH_DBM_USE_APR" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_auth_dbm" /FD /c
-CPP_OBJS=.\Debug/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_auth_dbm.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no\
- /pdb:"$(OUTDIR)\mod_auth_dbm.pdb" /map:"$(INTDIR)\mod_auth_dbm.map" /debug\
- /machine:I386 /out:"$(OUTDIR)\mod_auth_dbm.so"\
- /implib:"$(OUTDIR)\mod_auth_dbm.lib"\
- /base:@..\..\os\win32\BaseAddr.ref,mod_auth_dbm
-LINK32_OBJS= \
- "$(INTDIR)\mod_auth_dbm.obj" \
- "..\..\Debug\libhttpd.lib" \
- "..\..\srclib\apr-util\Debug\libaprutil.lib" \
- "..\..\srclib\apr\Debug\libapr.lib"
-
-"$(OUTDIR)\mod_auth_dbm.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ENDIF
-
-
-!IF "$(CFG)" == "mod_auth_dbm - Win32 Release" || "$(CFG)" ==\
- "mod_auth_dbm - Win32 Debug"
-
-!IF "$(CFG)" == "mod_auth_dbm - Win32 Release"
-
-"libapr - Win32 Release" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F .\libapr.mak CFG="libapr - Win32 Release"
- cd "..\..\modules\aaa"
-
-"libapr - Win32 ReleaseCLEAN" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libapr.mak CFG="libapr - Win32 Release"\
- RECURSE=1
- cd "..\..\modules\aaa"
-
-!ELSEIF "$(CFG)" == "mod_auth_dbm - Win32 Debug"
-
-"libapr - Win32 Debug" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F .\libapr.mak CFG="libapr - Win32 Debug"
- cd "..\..\modules\aaa"
-
-"libapr - Win32 DebugCLEAN" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libapr.mak CFG="libapr - Win32 Debug"\
- RECURSE=1
- cd "..\..\modules\aaa"
-
-!ENDIF
-
-!IF "$(CFG)" == "mod_auth_dbm - Win32 Release"
-
-"libaprutil - Win32 Release" :
- cd "..\..\srclib\apr-util"
- $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release"\
-
- cd "..\..\modules\aaa"
-
-"libaprutil - Win32 ReleaseCLEAN" :
- cd "..\..\srclib\apr-util"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F ".\libaprutil.mak"\
- CFG="libaprutil - Win32 Release" RECURSE=1
- cd "..\..\modules\aaa"
-
-!ELSEIF "$(CFG)" == "mod_auth_dbm - Win32 Debug"
-
-"libaprutil - Win32 Debug" :
- cd "..\..\srclib\apr-util"
- $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug"
- cd "..\..\modules\aaa"
-
-"libaprutil - Win32 DebugCLEAN" :
- cd "..\..\srclib\apr-util"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F ".\libaprutil.mak"\
- CFG="libaprutil - Win32 Debug" RECURSE=1
- cd "..\..\modules\aaa"
-
-!ENDIF
-
-!IF "$(CFG)" == "mod_auth_dbm - Win32 Release"
-
-"libhttpd - Win32 Release" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) /F .\libhttpd.mak CFG="libhttpd - Win32 Release"
- cd ".\modules\aaa"
-
-"libhttpd - Win32 ReleaseCLEAN" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libhttpd.mak CFG="libhttpd - Win32 Release"\
- RECURSE=1
- cd ".\modules\aaa"
-
-!ELSEIF "$(CFG)" == "mod_auth_dbm - Win32 Debug"
-
-"libhttpd - Win32 Debug" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) /F .\libhttpd.mak CFG="libhttpd - Win32 Debug"
- cd ".\modules\aaa"
-
-"libhttpd - Win32 DebugCLEAN" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libhttpd.mak CFG="libhttpd - Win32 Debug"\
- RECURSE=1
- cd ".\modules\aaa"
-
-!ENDIF
-
-SOURCE=.\mod_auth_dbm.c
-DEP_CPP_MOD_A=\
- "..\..\include\ap_config.h"\
- "..\..\include\ap_mmn.h"\
- "..\..\include\ap_release.h"\
- "..\..\include\http_config.h"\
- "..\..\include\http_core.h"\
- "..\..\include\http_log.h"\
- "..\..\include\http_protocol.h"\
- "..\..\include\http_request.h"\
- "..\..\include\httpd.h"\
- "..\..\include\pcreposix.h"\
- "..\..\include\util_cfgtree.h"\
- "..\..\include\util_filter.h"\
- "..\..\include\util_uri.h"\
- "..\..\os\win32\os.h"\
- "..\..\srclib\apr-util\include\apr_buckets.h"\
- "..\..\srclib\apr-util\include\apr_dbm.h"\
- "..\..\srclib\apr-util\include\apr_hooks.h"\
- "..\..\srclib\apr-util\include\apr_ring.h"\
- "..\..\srclib\apr-util\include\apu.h"\
- "..\..\srclib\apr\include\apr.h"\
- "..\..\srclib\apr\include\apr_dso.h"\
- "..\..\srclib\apr\include\apr_errno.h"\
- "..\..\srclib\apr\include\apr_file_info.h"\
- "..\..\srclib\apr\include\apr_file_io.h"\
- "..\..\srclib\apr\include\apr_general.h"\
- "..\..\srclib\apr\include\apr_lib.h"\
- "..\..\srclib\apr\include\apr_lock.h"\
- "..\..\srclib\apr\include\apr_mmap.h"\
- "..\..\srclib\apr\include\apr_network_io.h"\
- "..\..\srclib\apr\include\apr_pools.h"\
- "..\..\srclib\apr\include\apr_portable.h"\
- "..\..\srclib\apr\include\apr_tables.h"\
- "..\..\srclib\apr\include\apr_thread_proc.h"\
- "..\..\srclib\apr\include\apr_time.h"\
- "..\..\srclib\apr\include\apr_user.h"\
- "..\..\srclib\apr\include\apr_want.h"\
-
-NODEP_CPP_MOD_A=\
- "..\..\include\ap_config_auto.h"\
-
-
-"$(INTDIR)\mod_auth_dbm.obj" : $(SOURCE) $(DEP_CPP_MOD_A) "$(INTDIR)"
-
-
-
-!ENDIF
-
diff --git a/modules/aaa/mod_auth_digest.c b/modules/aaa/mod_auth_digest.c
deleted file mode 100644
index 2b0e233172..0000000000
--- a/modules/aaa/mod_auth_digest.c
+++ /dev/null
@@ -1,2083 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * mod_auth_digest: MD5 digest authentication
- *
- * Originally by Alexei Kosut <akosut@nueva.pvt.k12.ca.us>
- * Updated to RFC-2617 by Ronald Tschalär <ronald@innovation.ch>
- * based on mod_auth, by Rob McCool and Robert S. Thau
- *
- * This module an updated version of modules/standard/mod_digest.c
- * It is still fairly new and problems may turn up - submit problem
- * reports to the Apache bug-database, or send them directly to me
- * at ronald@innovation.ch.
- *
- * Requires either /dev/random (or equivalent) or the truerand library,
- * available for instance from
- * ftp://research.att.com/dist/mab/librand.shar
- *
- * Open Issues:
- * - qop=auth-int (when streams and trailer support available)
- * - nonce-format configurability
- * - Proxy-Authorization-Info header is set by this module, but is
- * currently ignored by mod_proxy (needs patch to mod_proxy)
- * - generating the secret takes a while (~ 8 seconds) if using the
- * truerand library
- * - The source of the secret should be run-time directive (with server
- * scope: RSRC_CONF). However, that could be tricky when trying to
- * choose truerand vs. file...
- * - shared-mem not completely tested yet. Seems to work ok for me,
- * but... (definitely won't work on Windoze)
- * - Sharing a realm among multiple servers has following problems:
- * o Server name and port can't be included in nonce-hash
- * (we need two nonce formats, which must be configured explicitly)
- * o Nonce-count check can't be for equal, or then nonce-count checking
- * must be disabled. What we could do is the following:
- * (expected < received) ? set expected = received : issue error
- * The only problem is that it allows replay attacks when somebody
- * captures a packet sent to one server and sends it to another
- * one. Should we add "AuthDigestNcCheck Strict"?
- * - expired nonces give amaya fits.
- */
-
-#include "apr_sha1.h"
-#include "apr_base64.h"
-#include "apr_lib.h"
-#include "apr_time.h"
-#include "apr_errno.h"
-#include "apr_lock.h"
-#include "apr_strings.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_core.h"
-#include "http_request.h"
-#include "http_log.h"
-#include "http_protocol.h"
-#include "util_uri.h"
-#include "util_md5.h"
-
-#if APR_HAS_SHARED_MEMORY
-#include "apr_shmem.h"
-#else
-/* just provide dummies - the code does run-time checks anyway */
-typedef void apr_shmem_t;
-typedef void apr_shm_name_t;
-
-apr_status_t apr_shm_init(apr_shmem_t **m, apr_size_t reqsize, const char *file, apr_pool_t *cont) {
- return APR_ENOTIMPL;
-}
-apr_status_t apr_shm_destroy(apr_shmem_t *m) {
- return APR_ENOTIMPL;
-}
-void *apr_shm_malloc(apr_shmem_t *c, apr_size_t reqsize) {
- return NULL;
-}
-void *apr_shm_calloc(apr_shmem_t *shared, apr_size_t size) {
- return NULL;
-}
-apr_status_t apr_shm_free(apr_shmem_t *shared, void *free) {
- return APR_ENOTIMPL;
-}
-apr_status_t apr_shm_name_get(apr_shmem_t *c, apr_shm_name_t **name) {
- return APR_ENOTIMPL;
-}
-apr_status_t apr_shm_name_set(apr_shmem_t *c, apr_shm_name_t *name) {
- return APR_ENOTIMPL;
-}
-apr_status_t apr_shm_open(apr_shmem_t *c) {
- return APR_ENOTIMPL;
-}
-apr_status_t apr_shm_avail(apr_shmem_t *c, apr_size_t *avail) {
- return APR_ENOTIMPL;
-}
-#endif /* APR_HAS_SHARED_MEMORY */
-
-
-/* struct to hold the configuration info */
-
-typedef struct digest_config_struct {
- const char *dir_name;
- const char *pwfile;
- const char *grpfile;
- const char *realm;
- char **qop_list;
- apr_sha1_ctx_t nonce_ctx;
- apr_time_t nonce_lifetime;
- const char *nonce_format;
- int check_nc;
- const char *algorithm;
- char *uri_list;
- const char *ha1;
-} digest_config_rec;
-
-
-#define DFLT_ALGORITHM "MD5"
-
-#define DFLT_NONCE_LIFE (300*APR_USEC_PER_SEC)
-#define NEXTNONCE_DELTA (30*APR_USEC_PER_SEC)
-
-
-#define NONCE_TIME_LEN (((sizeof(apr_time_t)+2)/3)*4)
-#define NONCE_HASH_LEN (2*APR_SHA1_DIGESTSIZE)
-#define NONCE_LEN (NONCE_TIME_LEN + NONCE_HASH_LEN)
-
-#define SECRET_LEN 20
-
-
-/* client list definitions */
-
-typedef struct hash_entry {
- unsigned long key; /* the key for this entry */
- struct hash_entry *next; /* next entry in the bucket */
- unsigned long nonce_count; /* for nonce-count checking */
- char ha1[2*MD5_DIGESTSIZE+1]; /* for algorithm=MD5-sess */
- char last_nonce[NONCE_LEN+1]; /* for one-time nonce's */
-} client_entry;
-
-static struct hash_table {
- client_entry **table;
- unsigned long tbl_len;
- unsigned long num_entries;
- unsigned long num_created;
- unsigned long num_removed;
- unsigned long num_renewed;
-} *client_list;
-
-
-/* struct to hold a parsed Authorization header */
-
-enum hdr_sts { NO_HEADER, NOT_DIGEST, INVALID, VALID };
-
-typedef struct digest_header_struct {
- const char *scheme;
- const char *realm;
- const char *username;
- char *nonce;
- const char *uri;
- const char *digest;
- const char *algorithm;
- const char *cnonce;
- const char *opaque;
- unsigned long opaque_num;
- const char *message_qop;
- const char *nonce_count;
- /* the following fields are not (directly) from the header */
- apr_time_t nonce_time;
- enum hdr_sts auth_hdr_sts;
- const char *raw_request_uri;
- uri_components *psd_request_uri;
- int needed_auth;
- client_entry *client;
-} digest_header_rec;
-
-
-/* (mostly) nonce stuff */
-
-typedef union time_union {
- apr_time_t time;
- unsigned char arr[sizeof(apr_time_t)];
-} time_rec;
-
-
-static unsigned char secret[SECRET_LEN];
-static int call_cnt = 0;
-
-
-/* client-list, opaque, and one-time-nonce stuff */
-
-static apr_shmem_t *client_shm = NULL;
-static unsigned long *opaque_cntr;
-static apr_time_t *otn_counter; /* one-time-nonce counter */
-static apr_lock_t *client_lock = NULL;
-static apr_lock_t *opaque_lock = NULL;
-static char client_lock_name[L_tmpnam];
-static char opaque_lock_name[L_tmpnam];
-
-#define DEF_SHMEM_SIZE 1000L /* ~ 12 entries */
-#define DEF_NUM_BUCKETS 15L
-#define HASH_DEPTH 5
-
-static long shmem_size = DEF_SHMEM_SIZE;
-static long num_buckets = DEF_NUM_BUCKETS;
-
-
-module AP_MODULE_DECLARE_DATA auth_digest_module;
-
-/*
- * initialization code
- */
-
-static apr_status_t cleanup_tables(void *not_used)
-{
- ap_log_rerror(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Digest: cleaning up shared memory");
- fflush(stderr);
-
- if (client_shm) {
- apr_shm_destroy(client_shm);
- client_shm = NULL;
- }
-
- if (client_lock) {
- apr_lock_destroy(client_lock);
- client_lock = NULL;
- }
-
- if (opaque_lock) {
- apr_lock_destroy(opaque_lock);
- opaque_lock = NULL;
- }
-
- return APR_SUCCESS;
-}
-
-static void initialize_secret(server_rec *s)
-{
- apr_status_t status;
-
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, s,
- "Digest: generating secret for digest authentication ...");
-
-#if APR_HAS_RANDOM
- status = apr_generate_random_bytes(secret, sizeof(secret));
-#else
-#error APR random number support is missing; you probably need to install the truerand library.
-#endif
-
- if(!(status == APR_SUCCESS)) {
- char buf[120];
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, 0, s,
- "Digest: error generating secret: %s",
- apr_strerror(status, buf, sizeof(buf)));
- exit(1);
- }
-
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, s, "Digest: done");
-}
-
-static void log_error_and_cleanup(char *msg, apr_status_t sts, server_rec *s)
-{
- ap_log_error(APLOG_MARK, APLOG_ERR, sts, s,
- "Digest: %s - all nonce-count checking, one-time nonces, and "
- "MD5-sess algorithm disabled", msg);
-
- cleanup_tables(NULL);
-}
-
-#if APR_HAS_SHARED_MEMORY
-
-static void initialize_tables(server_rec *s, apr_pool_t *ctx)
-{
- unsigned long idx;
- apr_status_t sts;
-
- /* set up client list */
-
- sts = apr_shm_init(&client_shm, shmem_size, tmpnam(NULL), ctx);
- if (sts != APR_SUCCESS) {
- log_error_and_cleanup("failed to create shared memory segments", sts, s);
- return;
- }
-
- client_list = apr_shm_malloc(client_shm, sizeof(*client_list) +
- sizeof(client_entry*)*num_buckets);
- if (!client_list) {
- log_error_and_cleanup("failed to allocate shared memory", -1, s);
- return;
- }
- client_list->table = (client_entry**) (client_list + 1);
- for (idx=0; idx<num_buckets; idx++)
- client_list->table[idx] = NULL;
- client_list->tbl_len = num_buckets;
- client_list->num_entries = 0;
-
- tmpnam(client_lock_name);
- sts = apr_lock_create(&client_lock, APR_READWRITE, APR_LOCKALL,
- client_lock_name, ctx);
- if (sts != APR_SUCCESS) {
- log_error_and_cleanup("failed to create lock", sts, s);
- return;
- }
-
-
- /* setup opaque */
-
- opaque_cntr = apr_shm_malloc(client_shm, sizeof(*opaque_cntr));
- if (opaque_cntr == NULL) {
- log_error_and_cleanup("failed to allocate shared memory", -1, s);
- return;
- }
- *opaque_cntr = 1UL;
-
- tmpnam(opaque_lock_name);
- sts = apr_lock_create(&opaque_lock, APR_MUTEX, APR_LOCKALL,
- opaque_lock_name, ctx);
- if (sts != APR_SUCCESS) {
- log_error_and_cleanup("failed to create lock", sts, s);
- return;
- }
-
-
- /* setup one-time-nonce counter */
-
- otn_counter = apr_shm_malloc(client_shm, sizeof(*otn_counter));
- if (otn_counter == NULL) {
- log_error_and_cleanup("failed to allocate shared memory", -1, s);
- return;
- }
- *otn_counter = 0;
- /* no lock here */
-
-
- /* success */
- return;
-}
-
-#endif /* APR_HAS_SHARED_MEMORY */
-
-
-static void initialize_module(apr_pool_t *p, apr_pool_t *plog,
- apr_pool_t *ptemp, server_rec *s)
-{
- /* keep from doing the init more than once at startup, and delay
- * the init until the second round
- */
- if (++call_cnt < 2)
- return;
-
- /* only initialize the secret on startup, not on restarts */
- if (call_cnt == 2)
- initialize_secret(s);
-
-/* Disable shmem until pools/init gets sorted out - remove next line when fixed */
-#undef APR_HAS_SHARED_MEMORY
-#define APR_HAS_SHARED_MEMORY 0
-
-#if APR_HAS_SHARED_MEMORY
- /* Note: this stuff is currently fixed for the lifetime of the server,
- * i.e. even across restarts. This means that A) any shmem-size
- * configuration changes are ignored, and B) certain optimizations,
- * such as only allocating the smallest necessary entry for each
- * client, can't be done. However, the alternative is a nightmare:
- * we can't call apr_shm_destroy on a graceful restart because there
- * will be children using the tables, and we also don't know when the
- * last child dies. Therefore we can never clean up the old stuff,
- * creating a creeping memory leak.
- */
- initialize_tables(s, p);
- apr_pool_cleanup_register(p, NULL, cleanup_tables, apr_pool_cleanup_null);
-#endif /* APR_HAS_SHARED_MEMORY */
-}
-
-static void initialize_child(apr_pool_t *p, server_rec *s)
-{
- apr_status_t sts;
-
- if (!client_shm)
- return;
-
- if ((sts = apr_lock_child_init(&client_lock, client_lock_name, p))
- != APR_SUCCESS
- || (sts = apr_lock_child_init(&opaque_lock, opaque_lock_name, p))
- != APR_SUCCESS) {
- log_error_and_cleanup("failed to create lock", sts, s);
- return;
- }
-}
-
-/*
- * configuration code
- */
-
-static void *create_digest_dir_config(apr_pool_t *p, char *dir)
-{
- digest_config_rec *conf;
-
- if (dir == NULL) return NULL;
-
- conf = (digest_config_rec *) apr_pcalloc(p, sizeof(digest_config_rec));
- if (conf) {
- conf->qop_list = apr_palloc(p, sizeof(char*));
- conf->qop_list[0] = NULL;
- conf->nonce_lifetime = DFLT_NONCE_LIFE;
- conf->dir_name = apr_pstrdup(p, dir);
- conf->algorithm = DFLT_ALGORITHM;
- }
-
- return conf;
-}
-
-static const char *set_realm(cmd_parms *cmd, void *config, const char *realm)
-{
- digest_config_rec *conf = (digest_config_rec *) config;
-
- /* The core already handles the realm, but it's just too convenient to
- * grab it ourselves too and cache some setups. However, we need to
- * let the core get at it too, which is why we decline at the end -
- * this relies on the fact that http_core is last in the list.
- */
- conf->realm = realm;
-
- /* we precompute the part of the nonce hash that is constant (well,
- * the host:port would be too, but that varies for .htaccess files
- * and directives outside a virtual host section)
- */
- apr_sha1_init(&conf->nonce_ctx);
- apr_sha1_update_binary(&conf->nonce_ctx, secret, sizeof(secret));
- apr_sha1_update_binary(&conf->nonce_ctx, (const unsigned char *) realm,
- strlen(realm));
-
- return DECLINE_CMD;
-}
-
-static const char *set_digest_file(cmd_parms *cmd, void *config,
- const char *file)
-{
- ((digest_config_rec *) config)->pwfile = file;
- return NULL;
-}
-
-static const char *set_group_file(cmd_parms *cmd, void *config,
- const char *file)
-{
- ((digest_config_rec *) config)->grpfile = file;
- return NULL;
-}
-
-static const char *set_qop(cmd_parms *cmd, void *config, const char *op)
-{
- digest_config_rec *conf = (digest_config_rec *) config;
- char **tmp;
- int cnt;
-
- if (!strcasecmp(op, "none")) {
- if (conf->qop_list[0] == NULL) {
- conf->qop_list = apr_palloc(cmd->pool, 2 * sizeof(char*));
- conf->qop_list[1] = NULL;
- }
- conf->qop_list[0] = "none";
- return NULL;
- }
-
- if (!strcasecmp(op, "auth-int"))
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, cmd->server,
- "Digest: WARNING: qop `auth-int' currently only works "
- "correctly for responses with no entity");
- else if (strcasecmp(op, "auth"))
- return apr_pstrcat(cmd->pool, "Unrecognized qop: ", op, NULL);
-
- for (cnt=0; conf->qop_list[cnt] != NULL; cnt++)
- ;
- tmp = apr_palloc(cmd->pool, (cnt+2)*sizeof(char*));
- memcpy(tmp, conf->qop_list, cnt*sizeof(char*));
- tmp[cnt] = apr_pstrdup(cmd->pool, op);
- tmp[cnt+1] = NULL;
- conf->qop_list = tmp;
-
- return NULL;
-}
-
-static const char *set_nonce_lifetime(cmd_parms *cmd, void *config,
- const char *t)
-{
- char *endptr;
- long lifetime;
-
- lifetime = strtol(t, &endptr, 10);
- if (endptr < (t+strlen(t)) && !apr_isspace(*endptr))
- return apr_pstrcat(cmd->pool, "Invalid time in AuthDigestNonceLifetime: ", t, NULL);
-
- ((digest_config_rec *) config)->nonce_lifetime = lifetime * APR_USEC_PER_SEC;
- return NULL;
-}
-
-static const char *set_nonce_format(cmd_parms *cmd, void *config,
- const char *fmt)
-{
- ((digest_config_rec *) config)->nonce_format = fmt;
- return "AuthDigestNonceFormat is not implemented (yet)";
-}
-
-static const char *set_nc_check(cmd_parms *cmd, void *config, int flag)
-{
- if (flag && !client_shm)
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0,
- cmd->server, "Digest: WARNING: nonce-count checking "
- "is not supported on platforms without shared-memory "
- "support - disabling check");
-
- ((digest_config_rec *) config)->check_nc = flag;
- return NULL;
-}
-
-static const char *set_algorithm(cmd_parms *cmd, void *config, const char *alg)
-{
- if (!strcasecmp(alg, "MD5-sess")) {
- if (!client_shm) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0,
- cmd->server, "Digest: WARNING: algorithm `MD5-sess' "
- "is not supported on platforms without shared-memory "
- "support - reverting to MD5");
- alg = "MD5";
- }
- }
- else if (strcasecmp(alg, "MD5"))
- return apr_pstrcat(cmd->pool, "Invalid algorithm in AuthDigestAlgorithm: ", alg, NULL);
-
- ((digest_config_rec *) config)->algorithm = alg;
- return NULL;
-}
-
-static const char *set_uri_list(cmd_parms *cmd, void *config, const char *uri)
-{
- digest_config_rec *c = (digest_config_rec *) config;
- if (c->uri_list) {
- c->uri_list[strlen(c->uri_list)-1] = '\0';
- c->uri_list = apr_pstrcat(cmd->pool, c->uri_list, " ", uri, "\"", NULL);
- }
- else
- c->uri_list = apr_pstrcat(cmd->pool, ", domain=\"", uri, "\"", NULL);
- return NULL;
-}
-
-static const char *set_shmem_size(cmd_parms *cmd, void *config,
- const char *size_str)
-{
- char *endptr;
- long size, min;
-
- size = strtol(size_str, &endptr, 10);
- while (apr_isspace(*endptr)) endptr++;
- if (*endptr == '\0' || *endptr == 'b' || *endptr == 'B')
- ;
- else if (*endptr == 'k' || *endptr == 'K')
- size *= 1024;
- else if (*endptr == 'm' || *endptr == 'M')
- size *= 1048576;
- else
- return apr_pstrcat(cmd->pool, "Invalid size in AuthDigestShmemSize: ",
- size_str, NULL);
-
- min = sizeof(*client_list) + sizeof(client_entry*) + sizeof(client_entry);
- if (size < min)
- return apr_psprintf(cmd->pool, "size in AuthDigestShmemSize too small: "
- "%ld < %ld", size, min);
-
- shmem_size = size;
- num_buckets = (size - sizeof(*client_list)) /
- (sizeof(client_entry*) + HASH_DEPTH * sizeof(client_entry));
- if (num_buckets == 0)
- num_buckets = 1;
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, 0, cmd->server,
- "Digest: Set shmem-size: %ld, num-buckets: %ld", shmem_size,
- num_buckets);
-
- return NULL;
-}
-
-static const command_rec digest_cmds[] =
-{
- AP_INIT_TAKE1("AuthName", set_realm, NULL, OR_AUTHCFG,
- "The authentication realm (e.g. \"Members Only\")"),
- AP_INIT_TAKE1("AuthDigestFile", set_digest_file, NULL, OR_AUTHCFG,
- "The name of the file containing the usernames and password hashes"),
- AP_INIT_TAKE1("AuthDigestGroupFile", set_group_file, NULL, OR_AUTHCFG,
- "The name of the file containing the group names and members"),
- AP_INIT_ITERATE("AuthDigestQop", set_qop, NULL, OR_AUTHCFG,
- "A list of quality-of-protection options"),
- AP_INIT_TAKE1("AuthDigestNonceLifetime", set_nonce_lifetime, NULL, OR_AUTHCFG,
- "Maximum lifetime of the server nonce (seconds)"),
- AP_INIT_TAKE1("AuthDigestNonceFormat", set_nonce_format, NULL, OR_AUTHCFG,
- "The format to use when generating the server nonce"),
- AP_INIT_FLAG("AuthDigestNcCheck", set_nc_check, NULL, OR_AUTHCFG,
- "Whether or not to check the nonce-count sent by the client"),
- AP_INIT_TAKE1("AuthDigestAlgorithm", set_algorithm, NULL, OR_AUTHCFG,
- "The algorithm used for the hash calculation"),
- AP_INIT_ITERATE("AuthDigestDomain", set_uri_list, NULL, OR_AUTHCFG,
- "A list of URI's which belong to the same protection space as the current URI"),
- AP_INIT_TAKE1("AuthDigestShmemSize", set_shmem_size, NULL, RSRC_CONF,
- "The amount of shared memory to allocate for keeping track of clients"),
- {NULL}
-};
-
-
-/*
- * client list code
- *
- * Each client is assigned a number, which is transfered in the opaque
- * field of the WWW-Authenticate and Authorization headers. The number
- * is just a simple counter which is incremented for each new client.
- * Clients can't forge this number because it is hashed up into the
- * server nonce, and that is checked.
- *
- * The clients are kept in a simple hash table, which consists of an
- * array of client_entry's, each with a linked list of entries hanging
- * off it. The client's number modulo the size of the array gives the
- * bucket number.
- *
- * The clients are garbage collected whenever a new client is allocated
- * but there is not enough space left in the shared memory segment. A
- * simple semi-LRU is used for this: whenever a client entry is accessed
- * it is moved to the beginning of the linked list in its bucket (this
- * also makes for faster lookups for current clients). The garbage
- * collecter then just removes the oldest entry (i.e. the one at the
- * end of the list) in each bucket.
- *
- * The main advantages of the above scheme are that it's easy to implement
- * and it keeps the hash table evenly balanced (i.e. same number of entries
- * in each bucket). The major disadvantage is that you may be throwing
- * entries out which are in active use. This is not tragic, as these
- * clients will just be sent a new client id (opaque field) and nonce
- * with a stale=true (i.e. it will just look like the nonce expired,
- * thereby forcing an extra round trip). If the shared memory segment
- * has enough headroom over the current client set size then this should
- * not occur too often.
- *
- * To help tune the size of the shared memory segment (and see if the
- * above algorithm is really sufficient) a set of counters is kept
- * indicating the number of clients held, the number of garbage collected
- * clients, and the number of erroneously purged clients. These are printed
- * out at each garbage collection run. Note that access to the counters is
- * not synchronized because they are just indicaters, and whether they are
- * off by a few doesn't matter; and for the same reason no attempt is made
- * to guarantee the num_renewed is correct in the face of clients spoofing
- * the opaque field.
- */
-
-/*
- * Get the client given its client number (the key). Returns the entry,
- * or NULL if its not found.
- *
- * Access to the list itself is synchronized via locks. However, access
- * to the entry returned by get_client() is NOT synchronized. This means
- * that there are potentially problems if a client uses multiple,
- * simultaneous connections to access url's within the same protection
- * space. However, these problems are not new: when using multiple
- * connections you have no guarantee of the order the requests are
- * processed anyway, so you have problems with the nonce-count and
- * one-time nonces anyway.
- */
-static client_entry *get_client(unsigned long key, const request_rec *r)
-{
- int bucket;
- client_entry *entry, *prev = NULL;
-
-
- if (!key || !client_shm) return NULL;
-
- bucket = key % client_list->tbl_len;
- entry = client_list->table[bucket];
-
- apr_lock_acquire(client_lock /*, MM_LOCK_RD */);
-
- while(entry && key != entry->key) {
- prev = entry;
- entry = entry->next;
- }
-
- if (entry && prev) { /* move entry to front of list */
- prev->next = entry->next;
- entry->next = client_list->table[bucket];
- client_list->table[bucket] = entry;
- }
-
- apr_lock_release(client_lock);
-
- if (entry)
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, 0, r,
- "get_client(): client %lu found", key);
- else
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, 0, r,
- "get_client(): client %lu not found", key);
-
- return entry;
-}
-
-
-/* A simple garbage-collecter to remove unused clients. It removes the
- * last entry in each bucket and updates the counters. Returns the
- * number of removed entries.
- */
-static long gc(void)
-{
- client_entry *entry, *prev;
- unsigned long num_removed = 0, idx;
-
- /* garbage collect all last entries */
-
- for (idx=0; idx<client_list->tbl_len; idx++) {
- entry = client_list->table[idx];
- prev = NULL;
- while (entry->next) { /* find last entry */
- prev = entry;
- entry = entry->next;
- }
- if (prev) prev->next = NULL; /* cut list */
- else client_list->table[idx] = NULL;
- if (entry) { /* remove entry */
- apr_shm_free(client_shm, entry);
- num_removed++;
- }
- }
-
- /* update counters and log */
-
- client_list->num_entries -= num_removed;
- client_list->num_removed += num_removed;
-
- return num_removed;
-}
-
-
-/*
- * Add a new client to the list. Returns the entry if successful, NULL
- * otherwise. This triggers the garbage collection if memory is low.
- */
-static client_entry *add_client(unsigned long key, client_entry *info,
- server_rec *s)
-{
- int bucket;
- client_entry *entry;
-
-
- if (!key || !client_shm) return NULL;
-
- bucket = key % client_list->tbl_len;
- entry = client_list->table[bucket];
-
- apr_lock_acquire(client_lock /*, MM_LOCK_RW */);
-
- /* try to allocate a new entry */
-
- entry = apr_shm_malloc(client_shm, sizeof(client_entry));
- if (!entry) {
- long num_removed = gc();
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, s,
- "Digest: gc'd %ld client entries. Total new clients: "
- "%ld; Total removed clients: %ld; Total renewed clients: "
- "%ld", num_removed,
- client_list->num_created - client_list->num_renewed,
- client_list->num_removed, client_list->num_renewed);
- entry = apr_shm_malloc(client_shm, sizeof(client_entry));
- if (!entry) return NULL; /* give up */
- }
-
- /* now add the entry */
-
- memcpy(entry, info, sizeof(client_entry));
- entry->key = key;
- entry->next = client_list->table[bucket];
- client_list->table[bucket] = entry;
- client_list->num_created++;
- client_list->num_entries++;
-
- apr_lock_release(client_lock);
-
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, 0, s,
- "allocated new client %lu", key);
-
- return entry;
-}
-
-
-/*
- * Authorization header parser code
- */
-
-/* Parse the Authorization header, if it exists */
-static int get_digest_rec(request_rec *r, digest_header_rec *resp)
-{
- const char *auth_line;
- size_t l;
- int vk = 0, vv = 0;
- char *key, *value;
-
- auth_line = apr_table_get(r->headers_in,
- (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authorization"
- : "Authorization");
- if (!auth_line) {
- resp->auth_hdr_sts = NO_HEADER;
- return !OK;
- }
-
- resp->scheme = ap_getword_white(r->pool, &auth_line);
- if (strcasecmp(resp->scheme, "Digest")) {
- resp->auth_hdr_sts = NOT_DIGEST;
- return !OK;
- }
-
- l = strlen(auth_line);
-
- key = apr_palloc(r->pool, l+1);
- value = apr_palloc(r->pool, l+1);
-
- while (auth_line[0] != '\0') {
-
- /* find key */
-
- while (apr_isspace(auth_line[0])) auth_line++;
- vk = 0;
- while (auth_line[0] != '=' && auth_line[0] != ','
- && auth_line[0] != '\0' && !apr_isspace(auth_line[0]))
- key[vk++] = *auth_line++;
- key[vk] = '\0';
- while (apr_isspace(auth_line[0])) auth_line++;
-
- /* find value */
-
- if (auth_line[0] == '=') {
- auth_line++;
- while (apr_isspace(auth_line[0])) auth_line++;
-
- vv = 0;
- if (auth_line[0] == '\"') { /* quoted string */
- auth_line++;
- while (auth_line[0] != '\"' && auth_line[0] != '\0') {
- if (auth_line[0] == '\\' && auth_line[1] != '\0')
- auth_line++; /* escaped char */
- value[vv++] = *auth_line++;
- }
- if (auth_line[0] != '\0') auth_line++;
- }
- else { /* token */
- while (auth_line[0] != ',' && auth_line[0] != '\0'
- && !apr_isspace(auth_line[0]))
- value[vv++] = *auth_line++;
- }
- value[vv] = '\0';
- }
-
- while (auth_line[0] != ',' && auth_line[0] != '\0') auth_line++;
- if (auth_line[0] != '\0') auth_line++;
-
- if (!strcasecmp(key, "username"))
- resp->username = apr_pstrdup(r->pool, value);
- else if (!strcasecmp(key, "realm"))
- resp->realm = apr_pstrdup(r->pool, value);
- else if (!strcasecmp(key, "nonce"))
- resp->nonce = apr_pstrdup(r->pool, value);
- else if (!strcasecmp(key, "uri"))
- resp->uri = apr_pstrdup(r->pool, value);
- else if (!strcasecmp(key, "response"))
- resp->digest = apr_pstrdup(r->pool, value);
- else if (!strcasecmp(key, "algorithm"))
- resp->algorithm = apr_pstrdup(r->pool, value);
- else if (!strcasecmp(key, "cnonce"))
- resp->cnonce = apr_pstrdup(r->pool, value);
- else if (!strcasecmp(key, "opaque"))
- resp->opaque = apr_pstrdup(r->pool, value);
- else if (!strcasecmp(key, "qop"))
- resp->message_qop = apr_pstrdup(r->pool, value);
- else if (!strcasecmp(key, "nc"))
- resp->nonce_count = apr_pstrdup(r->pool, value);
- }
-
- if (!resp->username || !resp->realm || !resp->nonce || !resp->uri
- || !resp->digest
- || (resp->message_qop && (!resp->cnonce || !resp->nonce_count))) {
- resp->auth_hdr_sts = INVALID;
- return !OK;
- }
-
- if (resp->opaque)
- resp->opaque_num = (unsigned long) strtol(resp->opaque, NULL, 16);
-
- resp->auth_hdr_sts = VALID;
- return OK;
-}
-
-
-/* Because the browser may preemptively send auth info, incrementing the
- * nonce-count when it does, and because the client does not get notified
- * if the URI didn't need authentication after all, we need to be sure to
- * update the nonce-count each time we receive an Authorization header no
- * matter what the final outcome of the request. Furthermore this is a
- * convenient place to get the request-uri (before any subrequests etc
- * are initiated) and to initialize the request_config.
- *
- * Note that this must be called after mod_proxy had its go so that
- * r->proxyreq is set correctly.
- */
-static int parse_hdr_and_update_nc(request_rec *r)
-{
- digest_header_rec *resp;
- int res;
-
- if (!ap_is_initial_req(r))
- return DECLINED;
-
- resp = apr_pcalloc(r->pool, sizeof(digest_header_rec));
- resp->raw_request_uri = r->unparsed_uri;
- resp->psd_request_uri = &r->parsed_uri;
- resp->needed_auth = 0;
- ap_set_module_config(r->request_config, &auth_digest_module, resp);
-
- res = get_digest_rec(r, resp);
- resp->client = get_client(resp->opaque_num, r);
- if (res == OK && resp->client)
- resp->client->nonce_count++;
-
- return DECLINED;
-}
-
-
-/*
- * Nonce generation code
- */
-
-/* The hash part of the nonce is a SHA-1 hash of the time, realm, server host
- * and port, opaque, and our secret.
- */
-static void gen_nonce_hash(char *hash, const char *timestr, const char *opaque,
- const server_rec *server,
- const digest_config_rec *conf)
-{
- const char *hex = "0123456789abcdef";
- unsigned char sha1[APR_SHA1_DIGESTSIZE];
- apr_sha1_ctx_t ctx;
- int idx;
-
- memcpy(&ctx, &conf->nonce_ctx, sizeof(ctx));
- /*
- apr_sha1_update_binary(&ctx, (const unsigned char *) server->server_hostname,
- strlen(server->server_hostname));
- apr_sha1_update_binary(&ctx, (const unsigned char *) &server->port,
- sizeof(server->port));
- */
- apr_sha1_update_binary(&ctx, (const unsigned char *) timestr, strlen(timestr));
- if (opaque)
- apr_sha1_update_binary(&ctx, (const unsigned char *) opaque,
- strlen(opaque));
- apr_sha1_final(sha1, &ctx);
-
- for (idx=0; idx<APR_SHA1_DIGESTSIZE; idx++) {
- *hash++ = hex[sha1[idx] >> 4];
- *hash++ = hex[sha1[idx] & 0xF];
- }
-
- *hash++ = '\0';
-}
-
-
-/* The nonce has the format b64(time)+hash .
- */
-static const char *gen_nonce(apr_pool_t *p, apr_time_t now, const char *opaque,
- const server_rec *server,
- const digest_config_rec *conf)
-{
- char *nonce = apr_palloc(p, NONCE_LEN+1);
- int len;
- time_rec t;
-
- if (conf->nonce_lifetime != 0)
- t.time = now;
- else if (otn_counter)
- /* this counter is not synch'd, because it doesn't really matter
- * if it counts exactly.
- */
- t.time = (*otn_counter)++;
- else
- t.time = 42;
- len = apr_base64_encode_binary(nonce, t.arr, sizeof(t.arr));
- gen_nonce_hash(nonce+NONCE_TIME_LEN, nonce, opaque, server, conf);
-
- return nonce;
-}
-
-
-/*
- * Opaque and hash-table management
- */
-
-/*
- * Generate a new client entry, add it to the list, and return the
- * entry. Returns NULL if failed.
- */
-static client_entry *gen_client(const request_rec *r)
-{
- unsigned long op;
- client_entry new_entry = { 0, NULL, 0, "", "" }, *entry;
-
- if (!opaque_cntr) return NULL;
-
- apr_lock_acquire(opaque_lock /*, MM_LOCK_RW */);
- op = (*opaque_cntr)++;
- apr_lock_release(opaque_lock);
-
- if (!(entry = add_client(op, &new_entry, r->server))) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "Digest: failed to allocate client entry - ignoring "
- "client");
- return NULL;
- }
-
- return entry;
-}
-
-
-/*
- * MD5-sess code.
- *
- * If you want to use algorithm=MD5-sess you must write get_userpw_hash()
- * yourself (see below). The dummy provided here just uses the hash from
- * the auth-file, i.e. it is only useful for testing client implementations
- * of MD5-sess .
- */
-
-/*
- * get_userpw_hash() will be called each time a new session needs to be
- * generated and is expected to return the equivalent of
- *
- * h_urp = ap_md5(r->pool,
- * apr_pstrcat(r->pool, username, ":", ap_auth_name(r), ":", passwd))
- * ap_md5(r->pool,
- * (unsigned char *) apr_pstrcat(r->pool, h_urp, ":", resp->nonce, ":",
- * resp->cnonce, NULL));
- *
- * or put differently, it must return
- *
- * MD5(MD5(username ":" realm ":" password) ":" nonce ":" cnonce)
- *
- * If something goes wrong, the failure must be logged and NULL returned.
- *
- * You must implement this yourself, which will probably consist of code
- * contacting the password server with the necessary information (typically
- * the username, realm, nonce, and cnonce) and receiving the hash from it.
- *
- * TBD: This function should probably be in a seperate source file so that
- * people need not modify mod_auth_digest.c each time they install a new
- * version of apache.
- */
-static const char *get_userpw_hash(const request_rec *r,
- const digest_header_rec *resp,
- const digest_config_rec *conf)
-{
- return ap_md5(r->pool,
- (unsigned char *) apr_pstrcat(r->pool, conf->ha1, ":", resp->nonce,
- ":", resp->cnonce, NULL));
-}
-
-
-/* Retrieve current session H(A1). If there is none and "generate" is
- * true then a new session for MD5-sess is generated and stored in the
- * client struct; if generate is false, or a new session could not be
- * generated then NULL is returned (in case of failure to generate the
- * failure reason will have been logged already).
- */
-static const char *get_session_HA1(const request_rec *r,
- digest_header_rec *resp,
- const digest_config_rec *conf,
- int generate)
-{
- const char *ha1 = NULL;
-
- /* return the current sessions if there is one */
- if (resp->opaque && resp->client && resp->client->ha1[0])
- return resp->client->ha1;
- else if (!generate)
- return NULL;
-
- /* generate a new session */
- if (!resp->client)
- resp->client = gen_client(r);
- if (resp->client) {
- ha1 = get_userpw_hash(r, resp, conf);
- if (ha1)
- memcpy(resp->client->ha1, ha1, sizeof(resp->client->ha1));
- }
-
- return ha1;
-}
-
-
-static void clear_session(const digest_header_rec *resp)
-{
- if (resp->client)
- resp->client->ha1[0] = '\0';
-}
-
-
-/*
- * Authorization challenge generation code (for WWW-Authenticate)
- */
-
-static const char *guess_domain(apr_pool_t *p, const char *uri,
- const char *filename, const char *dir)
-{
- size_t u_len = strlen(uri), f_len = strlen(filename), d_len = strlen(dir);
- const char *u, *f;
-
-
- /* Because of things like mod_alias and mod_rewrite and the fact that
- * protection is often on a directory basis (not a location basis) it
- * is hard to determine the uri to put in the domain attribute.
- *
- * What we do is the following: first we see if the directory is
- * a prefix for the uri - if this is the case we assume that therefore
- * a <Location> directive was protecting this uri and we can use it
- * for the domain.
- */
- if (u_len >= d_len && !memcmp(uri, dir, d_len))
- return dir;
-
- /* Now we check for <Files ...>, and if we find one we send back a
- * dummy uri - this is the only way to specify that the protection
- * space only covers a single uri.
- */
- if (dir[0] != '/')
- /* This doesn't work for Amaya (ok, it's of arguable validity in
- * the first place), so just return the file name instead
- return "http://0.0.0.0/";
- */
- return dir;
-
- /* Next we find the largest common common suffix of the request-uri
- * and the final file name, ignoring any extensions; this gives us a
- * hint as to where any rewriting could've occured (assuming that some
- * prefix of the uri is rewritten, not a suffix).
- */
- u = uri + u_len - 1; /* strip any extension */
- while (u > uri && *u != '/') u--;
- while (*u && *u != '.') u++;
- if (*u == '.') u--;
- if (*u == '/') u--;
-
- f = filename + f_len - 1; /* strip any extension */
- while (f > filename && *f != '/') f--;
- while (*f && *f != '.') f++;
- if (*f == '.') f--;
- if (*f == '/') f--;
-
- while (*f == *u && f > filename && u > uri) u--, f--;
- f++; u++;
-
- while (*f && *f != '/') f++, u++; /* suffix must start with / */
-
- /* Now, if the directory reaches into this common suffix then we can
- * take the uri with the same reach.
- */
- if ((unsigned long) (f-filename) < d_len) {
- char *tmp = apr_pstrdup(p, uri);
- tmp[(u-uri)+(d_len-(f-filename))] = '\0';
- return tmp;
- }
-
- return ""; /* give up */
-}
-
-
-static const char *ltox(apr_pool_t *p, unsigned long num)
-{
- if (num != 0)
- return apr_psprintf(p, "%lx", num);
- else
- return "";
-}
-
-static void note_digest_auth_failure(request_rec *r,
- const digest_config_rec *conf,
- digest_header_rec *resp, int stale)
-{
- const char *qop, *opaque, *opaque_param, *domain, *nonce;
- int cnt;
-
- /* Setup qop */
-
- if (conf->qop_list[0] == NULL) {
- qop = ", qop=\"auth\"";
- } else if (!strcasecmp(conf->qop_list[0], "none")) {
- qop = "";
- } else {
- qop = apr_pstrcat(r->pool, ", qop=\"", conf->qop_list[0], NULL);
- for (cnt=1; conf->qop_list[cnt] != NULL; cnt++)
- qop = apr_pstrcat(r->pool, qop, ",", conf->qop_list[cnt], NULL);
- qop = apr_pstrcat(r->pool, qop, "\"", NULL);
- }
-
- /* Setup opaque */
-
- if (resp->opaque == NULL) {
- /* new client */
- if ((conf->check_nc || conf->nonce_lifetime == 0
- || !strcasecmp(conf->algorithm, "MD5-sess"))
- && (resp->client = gen_client(r)) != NULL)
- opaque = ltox(r->pool, resp->client->key);
- else
- opaque = ""; /* opaque not needed */
- }
- else if (resp->client == NULL) {
- /* client info was gc'd */
- resp->client = gen_client(r);
- if (resp->client != NULL) {
- opaque = ltox(r->pool, resp->client->key);
- stale = 1;
- client_list->num_renewed++;
- }
- else
- opaque = ""; /* ??? */
- }
- else {
- opaque = resp->opaque;
- /* we're generating a new nonce, so reset the nonce-count */
- resp->client->nonce_count = 0;
- }
-
- if (opaque[0])
- opaque_param = apr_pstrcat(r->pool, ", opaque=\"", opaque, "\"", NULL);
- else
- opaque_param = NULL;
-
- /* Setup nonce */
-
- nonce = gen_nonce(r->pool, r->request_time, opaque, r->server, conf);
- if (resp->client && conf->nonce_lifetime == 0)
- memcpy(resp->client->last_nonce, nonce, NONCE_LEN+1);
-
- /* Setup MD5-sess stuff. Note that we just clear out the session
- * info here, since we can't generate a new session until the request
- * from the client comes in with the cnonce.
- */
-
- if (!strcasecmp(conf->algorithm, "MD5-sess"))
- clear_session(resp);
-
- /* setup domain attribute. We want to send this attribute wherever
- * possible so that the client won't send the Authorization header
- * unneccessarily (it's usually > 200 bytes!).
- */
-
- if (r->proxyreq)
- domain = NULL; /* don't send domain for proxy requests */
- else if (conf->uri_list)
- domain = conf->uri_list;
- else {
- /* They didn't specify any domain, so let's guess at it */
- domain = guess_domain(r->pool, resp->psd_request_uri->path, r->filename,
- conf->dir_name);
- if (domain[0] == '/' && domain[1] == '\0')
- domain = NULL; /* "/" is the default, so no need to send it */
- else
- domain = apr_pstrcat(r->pool, ", domain=\"", domain, "\"", NULL);
- }
-
- apr_table_mergen(r->err_headers_out,
- (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authenticate" : "WWW-Authenticate",
- apr_psprintf(r->pool, "Digest realm=\"%s\", nonce=\"%s\", "
- "algorithm=%s%s%s%s%s",
- ap_auth_name(r), nonce, conf->algorithm,
- opaque_param ? opaque_param : "",
- domain ? domain : "",
- stale ? ", stale=true" : "", qop));
-
-}
-
-
-/*
- * Authorization header verification code
- */
-
-static const char *get_hash(request_rec *r, const char *user,
- const char *realm, const char *auth_pwfile)
-{
- ap_configfile_t *f;
- char l[MAX_STRING_LEN];
- const char *rpw;
- char *w, *x;
- apr_status_t sts;
-
- if ((sts = ap_pcfg_openfile(&f, r->pool, auth_pwfile)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, sts, r,
- "Digest: Could not open password file: %s", auth_pwfile);
- return NULL;
- }
- while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) {
- if ((l[0] == '#') || (!l[0]))
- continue;
- rpw = l;
- w = ap_getword(r->pool, &rpw, ':');
- x = ap_getword(r->pool, &rpw, ':');
-
- if (x && w && !strcmp(user, w) && !strcmp(realm, x)) {
- ap_cfg_closefile(f);
- return apr_pstrdup(r->pool, rpw);
- }
- }
- ap_cfg_closefile(f);
- return NULL;
-}
-
-static int check_nc(const request_rec *r, const digest_header_rec *resp,
- const digest_config_rec *conf)
-{
- unsigned long nc;
- const char *snc = resp->nonce_count;
- char *endptr;
-
- if (!conf->check_nc || !client_shm)
- return OK;
-
- nc = strtol(snc, &endptr, 16);
- if (endptr < (snc+strlen(snc)) && !apr_isspace(*endptr)) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Digest: invalid nc %s received - not a number", snc);
- return !OK;
- }
-
- if (!resp->client)
- return !OK;
-
- if (nc != resp->client->nonce_count) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Digest: Warning, possible replay attack: nonce-count "
- "check failed: %lu != %lu", nc,
- resp->client->nonce_count);
- return !OK;
- }
-
- return OK;
-}
-
-static int check_nonce(request_rec *r, digest_header_rec *resp,
- const digest_config_rec *conf)
-{
- apr_time_t dt;
- int len;
- time_rec nonce_time;
- char tmp, hash[NONCE_HASH_LEN+1];
-
- if (strlen(resp->nonce) != NONCE_LEN) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Digest: invalid nonce %s received - length is not %d",
- resp->nonce, NONCE_LEN);
- note_digest_auth_failure(r, conf, resp, 1);
- return HTTP_UNAUTHORIZED;
- }
-
- tmp = resp->nonce[NONCE_TIME_LEN];
- resp->nonce[NONCE_TIME_LEN] = '\0';
- len = apr_base64_decode_binary(nonce_time.arr, resp->nonce);
- gen_nonce_hash(hash, resp->nonce, resp->opaque, r->server, conf);
- resp->nonce[NONCE_TIME_LEN] = tmp;
- resp->nonce_time = nonce_time.time;
-
- if (strcmp(hash, resp->nonce+NONCE_TIME_LEN)) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Digest: invalid nonce %s received - hash is not %s",
- resp->nonce, hash);
- note_digest_auth_failure(r, conf, resp, 1);
- return HTTP_UNAUTHORIZED;
- }
-
- dt = r->request_time - nonce_time.time;
- if (conf->nonce_lifetime > 0 && dt < 0) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Digest: invalid nonce %s received - user attempted "
- "time travel", resp->nonce);
- note_digest_auth_failure(r, conf, resp, 1);
- return HTTP_UNAUTHORIZED;
- }
-
- if (conf->nonce_lifetime > 0) {
- if (dt > conf->nonce_lifetime) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0,r,
- "Digest: user %s: nonce expired (%.2f seconds old - max lifetime %.2f) - sending new nonce",
- r->user, ((double)dt)/APR_USEC_PER_SEC,
- ((double)(conf->nonce_lifetime))/APR_USEC_PER_SEC);
- note_digest_auth_failure(r, conf, resp, 1);
- return HTTP_UNAUTHORIZED;
- }
- }
- else if (conf->nonce_lifetime == 0 && resp->client) {
- if (memcmp(resp->client->last_nonce, resp->nonce, NONCE_LEN)) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, r,
- "Digest: user %s: one-time-nonce mismatch - sending "
- "new nonce", r->user);
- note_digest_auth_failure(r, conf, resp, 1);
- return HTTP_UNAUTHORIZED;
- }
- }
- /* else (lifetime < 0) => never expires */
-
- return OK;
-}
-
-/* The actual MD5 code... whee */
-
-/* RFC-2069 */
-static const char *old_digest(const request_rec *r,
- const digest_header_rec *resp, const char *ha1)
-{
- const char *ha2;
-
- ha2 = ap_md5(r->pool, (unsigned char *)apr_pstrcat(r->pool, r->method, ":",
- resp->uri, NULL));
- return ap_md5(r->pool,
- (unsigned char *)apr_pstrcat(r->pool, ha1, ":", resp->nonce,
- ":", ha2, NULL));
-}
-
-/* RFC-2617 */
-static const char *new_digest(const request_rec *r,
- digest_header_rec *resp,
- const digest_config_rec *conf)
-{
- const char *ha1, *ha2, *a2;
-
- if (resp->algorithm && !strcasecmp(resp->algorithm, "MD5-sess")) {
- ha1 = get_session_HA1(r, resp, conf, 1);
- if (!ha1)
- return NULL;
- }
- else
- ha1 = conf->ha1;
-
- if (resp->message_qop && !strcasecmp(resp->message_qop, "auth-int"))
- a2 = apr_pstrcat(r->pool, r->method, ":", resp->uri, ":",
- ap_md5(r->pool, (const unsigned char*) ""), NULL); /* TBD */
- else
- a2 = apr_pstrcat(r->pool, r->method, ":", resp->uri, NULL);
- ha2 = ap_md5(r->pool, (const unsigned char *)a2);
-
- return ap_md5(r->pool,
- (unsigned char *)apr_pstrcat(r->pool, ha1, ":", resp->nonce,
- ":", resp->nonce_count, ":",
- resp->cnonce, ":",
- resp->message_qop, ":", ha2,
- NULL));
-}
-
-
-static void copy_uri_components(uri_components *dst, uri_components *src,
- request_rec *r) {
- if (src->scheme && src->scheme[0] != '\0')
- dst->scheme = src->scheme;
- else
- dst->scheme = (char *) "http";
-
- if (src->hostname && src->hostname[0] != '\0') {
- dst->hostname = apr_pstrdup(r->pool, src->hostname);
- ap_unescape_url(dst->hostname);
- }
- else
- dst->hostname = (char *) ap_get_server_name(r);
-
- if (src->port_str && src->port_str[0] != '\0')
- dst->port = src->port;
- else
- dst->port = ap_get_server_port(r);
-
- if (src->path && src->path[0] != '\0') {
- dst->path = apr_pstrdup(r->pool, src->path);
- ap_unescape_url(dst->path);
- }
- else
- dst->path = src->path;
-
- if (src->query && src->query[0] != '\0') {
- dst->query = apr_pstrdup(r->pool, src->query);
- ap_unescape_url(dst->query);
- }
- else
- dst->query = src->query;
-}
-
-/* These functions return 0 if client is OK, and proper error status
- * if not... either HTTP_UNAUTHORIZED, if we made a check, and it failed, or
- * HTTP_INTERNAL_SERVER_ERROR, if things are so totally confused that we
- * couldn't figure out how to tell if the client is authorized or not.
- *
- * If they return DECLINED, and all other modules also decline, that's
- * treated by the server core as a configuration error, logged and
- * reported as such.
- */
-
-/* Determine user ID, and check if the attributes are correct, if it
- * really is that user, if the nonce is correct, etc.
- */
-
-static int authenticate_digest_user(request_rec *r)
-{
- digest_config_rec *conf;
- digest_header_rec *resp;
- request_rec *mainreq;
- const char *t;
- int res;
-
- /* do we require Digest auth for this URI? */
-
- if (!(t = ap_auth_type(r)) || strcasecmp(t, "Digest"))
- return DECLINED;
-
- if (!ap_auth_name(r)) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Digest: need AuthName: %s", r->uri);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
-
- /* get the client response and mark */
-
- mainreq = r;
- while (mainreq->main != NULL) mainreq = mainreq->main;
- while (mainreq->prev != NULL) mainreq = mainreq->prev;
- resp = (digest_header_rec *) ap_get_module_config(mainreq->request_config,
- &auth_digest_module);
- resp->needed_auth = 1;
-
-
- /* get our conf */
-
- conf = (digest_config_rec *) ap_get_module_config(r->per_dir_config,
- &auth_digest_module);
-
-
- /* check for existence and syntax of Auth header */
-
- if (resp->auth_hdr_sts != VALID) {
- if (resp->auth_hdr_sts == NOT_DIGEST)
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Digest: client used wrong authentication scheme "
- "`%s': %s", resp->scheme, r->uri);
- else if (resp->auth_hdr_sts == INVALID)
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Digest: missing user, realm, nonce, uri, digest, "
- "cnonce, or nonce_count in authorization header: %s",
- r->uri);
- /* else (resp->auth_hdr_sts == NO_HEADER) */
- note_digest_auth_failure(r, conf, resp, 0);
- return HTTP_UNAUTHORIZED;
- }
-
- r->user = (char *) resp->username;
- r->ap_auth_type = (char *) "Digest";
-
- /* check the auth attributes */
-
- if (strcmp(resp->uri, resp->raw_request_uri)) {
- /* Hmm, the simple match didn't work (probably a proxy modified the
- * request-uri), so lets do a more sophisticated match
- */
- uri_components r_uri, d_uri;
-
- copy_uri_components(&r_uri, resp->psd_request_uri, r);
- if (ap_parse_uri_components(r->pool, resp->uri, &d_uri) != HTTP_OK) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Digest: invalid uri <%s> in Authorization header",
- resp->uri);
- return HTTP_BAD_REQUEST;
- }
-
- if (d_uri.hostname)
- ap_unescape_url(d_uri.hostname);
- if (d_uri.path)
- ap_unescape_url(d_uri.path);
- if (d_uri.query)
- ap_unescape_url(d_uri.query);
-
- if (r->method_number == M_CONNECT) {
- if (strcmp(resp->uri, r_uri.hostinfo)) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Digest: uri mismatch - <%s> does not match "
- "request-uri <%s>", resp->uri, r_uri.hostinfo);
- return HTTP_BAD_REQUEST;
- }
- }
- else if (
- /* check hostname matches, if present */
- (d_uri.hostname && d_uri.hostname[0] != '\0'
- && strcasecmp(d_uri.hostname, r_uri.hostname))
- /* check port matches, if present */
- || (d_uri.port_str && d_uri.port != r_uri.port)
- /* check that server-port is default port if no port present */
- || (d_uri.hostname && d_uri.hostname[0] != '\0'
- && !d_uri.port_str && r_uri.port != ap_default_port(r))
- /* check that path matches */
- || (d_uri.path != r_uri.path
- /* either exact match */
- && (!d_uri.path || !r_uri.path
- || strcmp(d_uri.path, r_uri.path))
- /* or '*' matches empty path in scheme://host */
- && !(d_uri.path && !r_uri.path && resp->psd_request_uri->hostname
- && d_uri.path[0] == '*' && d_uri.path[1] == '\0'))
- /* check that query matches */
- || (d_uri.query != r_uri.query
- && (!d_uri.query || !r_uri.query
- || strcmp(d_uri.query, r_uri.query)))
- ) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Digest: uri mismatch - <%s> does not match "
- "request-uri <%s>", resp->uri, resp->raw_request_uri);
- return HTTP_BAD_REQUEST;
- }
- }
-
- if (resp->opaque && resp->opaque_num == 0) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Digest: received invalid opaque - got `%s'",
- resp->opaque);
- note_digest_auth_failure(r, conf, resp, 0);
- return HTTP_UNAUTHORIZED;
- }
-
- if (strcmp(resp->realm, conf->realm)) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Digest: realm mismatch - got `%s' but expected `%s'",
- resp->realm, conf->realm);
- note_digest_auth_failure(r, conf, resp, 0);
- return HTTP_UNAUTHORIZED;
- }
-
- if (resp->algorithm != NULL
- && strcasecmp(resp->algorithm, "MD5")
- && strcasecmp(resp->algorithm, "MD5-sess")) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Digest: unknown algorithm `%s' received: %s",
- resp->algorithm, r->uri);
- note_digest_auth_failure(r, conf, resp, 0);
- return HTTP_UNAUTHORIZED;
- }
-
- if (!conf->pwfile)
- return DECLINED;
-
- if (!(conf->ha1 = get_hash(r, r->user, conf->realm, conf->pwfile))) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Digest: user `%s' in realm `%s' not found: %s",
- r->user, conf->realm, r->uri);
- note_digest_auth_failure(r, conf, resp, 0);
- return HTTP_UNAUTHORIZED;
- }
-
-
- if (resp->message_qop == NULL) {
- /* old (rfc-2069) style digest */
- if (strcmp(resp->digest, old_digest(r, resp, conf->ha1))) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Digest: user %s: password mismatch: %s", r->user,
- r->uri);
- note_digest_auth_failure(r, conf, resp, 0);
- return HTTP_UNAUTHORIZED;
- }
- }
- else {
- const char *exp_digest;
- int match = 0, idx;
- for (idx=0; conf->qop_list[idx] != NULL; idx++) {
- if (!strcasecmp(conf->qop_list[idx], resp->message_qop)) {
- match = 1;
- break;
- }
- }
-
- if (!match
- && !(conf->qop_list[0] == NULL
- && !strcasecmp(resp->message_qop, "auth"))) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Digest: invalid qop `%s' received: %s",
- resp->message_qop, r->uri);
- note_digest_auth_failure(r, conf, resp, 0);
- return HTTP_UNAUTHORIZED;
- }
-
- exp_digest = new_digest(r, resp, conf);
- if (!exp_digest) {
- /* we failed to allocate a client struct */
- return HTTP_INTERNAL_SERVER_ERROR;
- }
- if (strcmp(resp->digest, exp_digest)) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Digest: user %s: password mismatch: %s", r->user,
- r->uri);
- note_digest_auth_failure(r, conf, resp, 0);
- return HTTP_UNAUTHORIZED;
- }
- }
-
- if (check_nc(r, resp, conf) != OK) {
- note_digest_auth_failure(r, conf, resp, 0);
- return HTTP_UNAUTHORIZED;
- }
-
- /* Note: this check is done last so that a "stale=true" can be
- generated if the nonce is old */
- if ((res = check_nonce(r, resp, conf)))
- return res;
-
- return OK;
-}
-
-
-/*
- * Checking ID
- */
-
-static apr_table_t *groups_for_user(request_rec *r, const char *user,
- const char *grpfile)
-{
- ap_configfile_t *f;
- apr_table_t *grps = apr_table_make(r->pool, 15);
- apr_pool_t *sp;
- char l[MAX_STRING_LEN];
- const char *group_name, *ll, *w;
- apr_status_t sts;
-
- if ((sts = ap_pcfg_openfile(&f, r->pool, grpfile)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, sts, r,
- "Digest: Could not open group file: %s", grpfile);
- return NULL;
- }
-
- if (apr_pool_create(&sp, r->pool) != APR_SUCCESS)
- return NULL;
-
- while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) {
- if ((l[0] == '#') || (!l[0]))
- continue;
- ll = l;
- apr_pool_clear(sp);
-
- group_name = ap_getword(sp, &ll, ':');
-
- while (ll[0]) {
- w = ap_getword_conf(sp, &ll);
- if (!strcmp(w, user)) {
- apr_table_setn(grps, apr_pstrdup(r->pool, group_name), "in");
- break;
- }
- }
- }
-
- ap_cfg_closefile(f);
- apr_pool_destroy(sp);
- return grps;
-}
-
-
-static int digest_check_auth(request_rec *r)
-{
- const digest_config_rec *conf =
- (digest_config_rec *) ap_get_module_config(r->per_dir_config,
- &auth_digest_module);
- const char *user = r->user;
- int m = r->method_number;
- int method_restricted = 0;
- register int x;
- const char *t, *w;
- apr_table_t *grpstatus;
- const apr_array_header_t *reqs_arr;
- require_line *reqs;
-
- if (!(t = ap_auth_type(r)) || strcasecmp(t, "Digest"))
- return DECLINED;
-
- reqs_arr = ap_requires(r);
- /* If there is no "requires" directive, then any user will do.
- */
- if (!reqs_arr)
- return OK;
- reqs = (require_line *) reqs_arr->elts;
-
- if (conf->grpfile)
- grpstatus = groups_for_user(r, user, conf->grpfile);
- else
- grpstatus = NULL;
-
- for (x = 0; x < reqs_arr->nelts; x++) {
-
- if (!(reqs[x].method_mask & (1 << m)))
- continue;
-
- method_restricted = 1;
-
- t = reqs[x].requirement;
- w = ap_getword_white(r->pool, &t);
- if (!strcasecmp(w, "valid-user"))
- return OK;
- else if (!strcasecmp(w, "user")) {
- while (t[0]) {
- w = ap_getword_conf(r->pool, &t);
- if (!strcmp(user, w))
- return OK;
- }
- }
- else if (!strcasecmp(w, "group")) {
- if (!grpstatus)
- return DECLINED;
-
- while (t[0]) {
- w = ap_getword_conf(r->pool, &t);
- if (apr_table_get(grpstatus, w))
- return OK;
- }
- }
- else {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Digest: access to %s failed, reason: unknown require "
- "directive \"%s\"", r->uri, reqs[x].requirement);
- return DECLINED;
- }
- }
-
- if (!method_restricted)
- return OK;
-
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Digest: access to %s failed, reason: user %s not allowed access",
- r->uri, user);
-
- note_digest_auth_failure(r, conf,
- (digest_header_rec *) ap_get_module_config(r->request_config,
- &auth_digest_module),
- 0);
- return HTTP_UNAUTHORIZED;
-}
-
-
-/*
- * Authorization-Info header code
- */
-
-#ifdef SEND_DIGEST
-static const char *hdr(const apr_table_t *tbl, const char *name)
-{
- const char *val = apr_table_get(tbl, name);
- if (val)
- return val;
- else
- return "";
-}
-#endif
-
-static int add_auth_info(request_rec *r)
-{
- const digest_config_rec *conf =
- (digest_config_rec *) ap_get_module_config(r->per_dir_config,
- &auth_digest_module);
- digest_header_rec *resp =
- (digest_header_rec *) ap_get_module_config(r->request_config,
- &auth_digest_module);
- const char *ai = NULL, *digest = NULL, *nextnonce = "";
-
- if (resp == NULL || !resp->needed_auth || conf == NULL)
- return OK;
-
-
- /* rfc-2069 digest
- */
- if (resp->message_qop == NULL) {
- /* old client, so calc rfc-2069 digest */
-
-#ifdef SEND_DIGEST
- /* most of this totally bogus because the handlers don't set the
- * headers until the final handler phase (I wonder why this phase
- * is called fixup when there's almost nothing you can fix up...)
- *
- * Because it's basically impossible to get this right (e.g. the
- * Content-length is never set yet when we get here, and we can't
- * calc the entity hash) it's best to just leave this #def'd out.
- */
- char date[APR_RFC822_DATE_LEN];
- apr_rfc822_date(date, r->request_time);
- char *entity_info =
- ap_md5(r->pool,
- (unsigned char *) apr_pstrcat(r->pool, resp->raw_request_uri,
- ":",
- r->content_type ? r->content_type : ap_default_type(r), ":",
- hdr(r->headers_out, "Content-Length"), ":",
- r->content_encoding ? r->content_encoding : "", ":",
- hdr(r->headers_out, "Last-Modified"), ":",
- r->no_cache && !apr_table_get(r->headers_out, "Expires") ?
- date :
- hdr(r->headers_out, "Expires"),
- NULL));
- digest =
- ap_md5(r->pool,
- (unsigned char *)apr_pstrcat(r->pool, conf->ha1, ":",
- resp->nonce, ":",
- r->method, ":",
- date, ":",
- entity_info, ":",
- ap_md5(r->pool, (unsigned char *) ""), /* H(entity) - TBD */
- NULL));
-#endif
- }
-
-
- /* setup nextnonce
- */
- if (conf->nonce_lifetime > 0) {
- /* send nextnonce if current nonce will expire in less than 30 secs */
- if ((r->request_time - resp->nonce_time) > (conf->nonce_lifetime-NEXTNONCE_DELTA)) {
- nextnonce = apr_pstrcat(r->pool, ", nextnonce=\"",
- gen_nonce(r->pool, r->request_time,
- resp->opaque, r->server, conf),
- "\"", NULL);
- if (resp->client)
- resp->client->nonce_count = 0;
- }
- }
- else if (conf->nonce_lifetime == 0 && resp->client) {
- const char *nonce = gen_nonce(r->pool, 0, resp->opaque, r->server,
- conf);
- nextnonce = apr_pstrcat(r->pool, ", nextnonce=\"", nonce, "\"", NULL);
- memcpy(resp->client->last_nonce, nonce, NONCE_LEN+1);
- }
- /* else nonce never expires, hence no nextnonce */
-
-
- /* do rfc-2069 digest
- */
- if (conf->qop_list[0] && !strcasecmp(conf->qop_list[0], "none")
- && resp->message_qop == NULL) {
- /* use only RFC-2069 format */
- if (digest)
- ai = apr_pstrcat(r->pool, "digest=\"", digest, "\"", nextnonce,NULL);
- else
- ai = nextnonce;
- }
- else {
- const char *resp_dig, *ha1, *a2, *ha2;
-
- /* calculate rspauth attribute
- */
- if (resp->algorithm && !strcasecmp(resp->algorithm, "MD5-sess")) {
- ha1 = get_session_HA1(r, resp, conf, 0);
- if (!ha1) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Digest: internal error: couldn't find session "
- "info for user %s", resp->username);
- return !OK;
- }
- }
- else
- ha1 = conf->ha1;
-
- if (resp->message_qop && !strcasecmp(resp->message_qop, "auth-int"))
- a2 = apr_pstrcat(r->pool, ":", resp->uri, ":",
- ap_md5(r->pool, (const unsigned char *) ""), NULL); /* TBD */
- else
- a2 = apr_pstrcat(r->pool, ":", resp->uri, NULL);
- ha2 = ap_md5(r->pool, (const unsigned char *)a2);
-
- resp_dig = ap_md5(r->pool,
- (unsigned char *)apr_pstrcat(r->pool, ha1, ":",
- resp->nonce, ":",
- resp->nonce_count, ":",
- resp->cnonce, ":",
- resp->message_qop ?
- resp->message_qop : "",
- ":", ha2, NULL));
-
- /* assemble Authentication-Info header
- */
- ai = apr_pstrcat(r->pool,
- "rspauth=\"", resp_dig, "\"",
- nextnonce,
- resp->cnonce ? ", cnonce=\"" : "",
- resp->cnonce ? ap_escape_quotes(r->pool, resp->cnonce) :
- "",
- resp->cnonce ? "\"" : "",
- resp->nonce_count ? ", nc=" : "",
- resp->nonce_count ? resp->nonce_count : "",
- resp->message_qop ? ", qop=" : "",
- resp->message_qop ? resp->message_qop : "",
- digest ? "digest=\"" : "",
- digest ? digest : "",
- digest ? "\"" : "",
- NULL);
- }
-
- if (ai && ai[0])
- apr_table_mergen(r->headers_out,
- (PROXYREQ_PROXY == r->proxyreq) ? "Proxy-Authentication-Info"
- : "Authentication-Info",
- ai);
- return OK;
-}
-
-
-static void register_hooks(apr_pool_t *p)
-{
- static const char * const cfgPost[]={ "http_core.c", NULL };
- static const char * const parsePre[]={ "mod_proxy.c", NULL };
-
- ap_hook_post_config(initialize_module, NULL, cfgPost, APR_HOOK_MIDDLE);
- ap_hook_child_init(initialize_child, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_post_read_request(parse_hdr_and_update_nc, parsePre, NULL, APR_HOOK_MIDDLE);
- ap_hook_check_user_id(authenticate_digest_user, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_auth_checker(digest_check_auth, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_fixups(add_auth_info, NULL, NULL, APR_HOOK_MIDDLE);
-}
-
-module AP_MODULE_DECLARE_DATA auth_digest_module =
-{
- STANDARD20_MODULE_STUFF,
- create_digest_dir_config, /* dir config creater */
- NULL, /* dir merger --- default is to override */
- NULL, /* server config */
- NULL, /* merge server config */
- digest_cmds, /* command table */
- register_hooks /* register hooks */
-};
-
diff --git a/modules/aaa/mod_auth_digest.dsp b/modules/aaa/mod_auth_digest.dsp
deleted file mode 100644
index 84d6760577..0000000000
--- a/modules/aaa/mod_auth_digest.dsp
+++ /dev/null
@@ -1,95 +0,0 @@
-# Microsoft Developer Studio Project File - Name="mod_auth_digest" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=mod_auth_digest - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "mod_auth_digest.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_auth_digest.mak" CFG="mod_auth_digest - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_auth_digest - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_auth_digest - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "mod_auth_digest - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\os\win32" /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_auth_digest" /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_auth_digest.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_auth_digest
-# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_auth_digest.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_auth_digest
-
-!ELSEIF "$(CFG)" == "mod_auth_digest - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\..\include" /I "..\..\os\win32" /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_auth_digest" /FD /c
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /out:"Debug/mod_auth_digest.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_auth_digest
-# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /out:"Debug/mod_auth_digest.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_auth_digest
-
-!ENDIF
-
-# Begin Target
-
-# Name "mod_auth_digest - Win32 Release"
-# Name "mod_auth_digest - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\mod_auth_digest.c
-# End Source File
-# End Target
-# End Project
diff --git a/modules/aaa/mod_auth_digest.mak b/modules/aaa/mod_auth_digest.mak
deleted file mode 100644
index 871e162be7..0000000000
--- a/modules/aaa/mod_auth_digest.mak
+++ /dev/null
@@ -1,370 +0,0 @@
-# Microsoft Developer Studio Generated NMAKE File, Based on mod_auth_digest.dsp
-!IF "$(CFG)" == ""
-CFG=mod_auth_digest - Win32 Debug
-!MESSAGE No configuration specified. Defaulting to mod_auth_digest - Win32\
- Debug.
-!ENDIF
-
-!IF "$(CFG)" != "mod_auth_digest - Win32 Release" && "$(CFG)" !=\
- "mod_auth_digest - Win32 Debug"
-!MESSAGE Invalid configuration "$(CFG)" specified.
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_auth_digest.mak" CFG="mod_auth_digest - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_auth_digest - Win32 Release" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_auth_digest - Win32 Debug" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-!ERROR An invalid configuration is specified.
-!ENDIF
-
-!IF "$(OS)" == "Windows_NT"
-NULL=
-!ELSE
-NULL=nul
-!ENDIF
-
-!IF "$(CFG)" == "mod_auth_digest - Win32 Release"
-
-OUTDIR=.\Release
-INTDIR=.\Release
-# Begin Custom Macros
-OutDir=.\Release
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_auth_digest.so"
-
-!ELSE
-
-ALL : "libhttpd - Win32 Release" "libaprutil - Win32 Release"\
- "libapr - Win32 Release" "$(OUTDIR)\mod_auth_digest.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN"\
- "libhttpd - Win32 ReleaseCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\mod_auth_digest.idb"
- -@erase "$(INTDIR)\mod_auth_digest.obj"
- -@erase "$(OUTDIR)\mod_auth_digest.exp"
- -@erase "$(OUTDIR)\mod_auth_digest.lib"
- -@erase "$(OUTDIR)\mod_auth_digest.map"
- -@erase "$(OUTDIR)\mod_auth_digest.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\os\win32" /I\
- "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D\
- "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_auth_digest" /FD /c
-CPP_OBJS=.\Release/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_auth_digest.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no\
- /pdb:"$(OUTDIR)\mod_auth_digest.pdb" /map:"$(INTDIR)\mod_auth_digest.map"\
- /machine:I386 /out:"$(OUTDIR)\mod_auth_digest.so"\
- /implib:"$(OUTDIR)\mod_auth_digest.lib"\
- /base:@..\..\os\win32\BaseAddr.ref,mod_auth_digest
-LINK32_OBJS= \
- "$(INTDIR)\mod_auth_digest.obj" \
- "..\..\Release\libhttpd.lib" \
- "..\..\srclib\apr-util\Release\libaprutil.lib" \
- "..\..\srclib\apr\Release\libapr.lib"
-
-"$(OUTDIR)\mod_auth_digest.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ELSEIF "$(CFG)" == "mod_auth_digest - Win32 Debug"
-
-OUTDIR=.\Debug
-INTDIR=.\Debug
-# Begin Custom Macros
-OutDir=.\Debug
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_auth_digest.so"
-
-!ELSE
-
-ALL : "libhttpd - Win32 Debug" "libaprutil - Win32 Debug"\
- "libapr - Win32 Debug" "$(OUTDIR)\mod_auth_digest.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN"\
- "libhttpd - Win32 DebugCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\mod_auth_digest.idb"
- -@erase "$(INTDIR)\mod_auth_digest.obj"
- -@erase "$(OUTDIR)\mod_auth_digest.exp"
- -@erase "$(OUTDIR)\mod_auth_digest.lib"
- -@erase "$(OUTDIR)\mod_auth_digest.map"
- -@erase "$(OUTDIR)\mod_auth_digest.pdb"
- -@erase "$(OUTDIR)\mod_auth_digest.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /I\
- "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D\
- "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_auth_digest" /FD /c
-CPP_OBJS=.\Debug/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_auth_digest.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no\
- /pdb:"$(OUTDIR)\mod_auth_digest.pdb" /map:"$(INTDIR)\mod_auth_digest.map"\
- /debug /machine:I386 /out:"$(OUTDIR)\mod_auth_digest.so"\
- /implib:"$(OUTDIR)\mod_auth_digest.lib"\
- /base:@..\..\os\win32\BaseAddr.ref,mod_auth_digest
-LINK32_OBJS= \
- "$(INTDIR)\mod_auth_digest.obj" \
- "..\..\Debug\libhttpd.lib" \
- "..\..\srclib\apr-util\Debug\libaprutil.lib" \
- "..\..\srclib\apr\Debug\libapr.lib"
-
-"$(OUTDIR)\mod_auth_digest.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ENDIF
-
-
-!IF "$(CFG)" == "mod_auth_digest - Win32 Release" || "$(CFG)" ==\
- "mod_auth_digest - Win32 Debug"
-
-!IF "$(CFG)" == "mod_auth_digest - Win32 Release"
-
-"libapr - Win32 Release" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F .\libapr.mak CFG="libapr - Win32 Release"
- cd "..\..\modules\aaa"
-
-"libapr - Win32 ReleaseCLEAN" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libapr.mak CFG="libapr - Win32 Release"\
- RECURSE=1
- cd "..\..\modules\aaa"
-
-!ELSEIF "$(CFG)" == "mod_auth_digest - Win32 Debug"
-
-"libapr - Win32 Debug" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F .\libapr.mak CFG="libapr - Win32 Debug"
- cd "..\..\modules\aaa"
-
-"libapr - Win32 DebugCLEAN" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libapr.mak CFG="libapr - Win32 Debug"\
- RECURSE=1
- cd "..\..\modules\aaa"
-
-!ENDIF
-
-!IF "$(CFG)" == "mod_auth_digest - Win32 Release"
-
-"libaprutil - Win32 Release" :
- cd "..\..\srclib\apr-util"
- $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release"\
-
- cd "..\..\modules\aaa"
-
-"libaprutil - Win32 ReleaseCLEAN" :
- cd "..\..\srclib\apr-util"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F ".\libaprutil.mak"\
- CFG="libaprutil - Win32 Release" RECURSE=1
- cd "..\..\modules\aaa"
-
-!ELSEIF "$(CFG)" == "mod_auth_digest - Win32 Debug"
-
-"libaprutil - Win32 Debug" :
- cd "..\..\srclib\apr-util"
- $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug"
- cd "..\..\modules\aaa"
-
-"libaprutil - Win32 DebugCLEAN" :
- cd "..\..\srclib\apr-util"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F ".\libaprutil.mak"\
- CFG="libaprutil - Win32 Debug" RECURSE=1
- cd "..\..\modules\aaa"
-
-!ENDIF
-
-!IF "$(CFG)" == "mod_auth_digest - Win32 Release"
-
-"libhttpd - Win32 Release" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) /F .\libhttpd.mak CFG="libhttpd - Win32 Release"
- cd ".\modules\aaa"
-
-"libhttpd - Win32 ReleaseCLEAN" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libhttpd.mak CFG="libhttpd - Win32 Release"\
- RECURSE=1
- cd ".\modules\aaa"
-
-!ELSEIF "$(CFG)" == "mod_auth_digest - Win32 Debug"
-
-"libhttpd - Win32 Debug" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) /F .\libhttpd.mak CFG="libhttpd - Win32 Debug"
- cd ".\modules\aaa"
-
-"libhttpd - Win32 DebugCLEAN" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libhttpd.mak CFG="libhttpd - Win32 Debug"\
- RECURSE=1
- cd ".\modules\aaa"
-
-!ENDIF
-
-SOURCE=.\mod_auth_digest.c
-DEP_CPP_MOD_A=\
- "..\..\include\ap_config.h"\
- "..\..\include\ap_mmn.h"\
- "..\..\include\ap_release.h"\
- "..\..\include\http_config.h"\
- "..\..\include\http_core.h"\
- "..\..\include\http_log.h"\
- "..\..\include\http_protocol.h"\
- "..\..\include\http_request.h"\
- "..\..\include\httpd.h"\
- "..\..\include\pcreposix.h"\
- "..\..\include\util_cfgtree.h"\
- "..\..\include\util_filter.h"\
- "..\..\include\util_md5.h"\
- "..\..\include\util_uri.h"\
- "..\..\os\win32\os.h"\
- "..\..\srclib\apr-util\include\apr_base64.h"\
- "..\..\srclib\apr-util\include\apr_buckets.h"\
- "..\..\srclib\apr-util\include\apr_hooks.h"\
- "..\..\srclib\apr-util\include\apr_ring.h"\
- "..\..\srclib\apr-util\include\apr_sha1.h"\
- "..\..\srclib\apr-util\include\apu.h"\
- "..\..\srclib\apr\include\apr.h"\
- "..\..\srclib\apr\include\apr_dso.h"\
- "..\..\srclib\apr\include\apr_errno.h"\
- "..\..\srclib\apr\include\apr_file_info.h"\
- "..\..\srclib\apr\include\apr_file_io.h"\
- "..\..\srclib\apr\include\apr_general.h"\
- "..\..\srclib\apr\include\apr_lib.h"\
- "..\..\srclib\apr\include\apr_lock.h"\
- "..\..\srclib\apr\include\apr_md5.h"\
- "..\..\srclib\apr\include\apr_mmap.h"\
- "..\..\srclib\apr\include\apr_network_io.h"\
- "..\..\srclib\apr\include\apr_pools.h"\
- "..\..\srclib\apr\include\apr_portable.h"\
- "..\..\srclib\apr\include\apr_shmem.h"\
- "..\..\srclib\apr\include\apr_strings.h"\
- "..\..\srclib\apr\include\apr_tables.h"\
- "..\..\srclib\apr\include\apr_thread_proc.h"\
- "..\..\srclib\apr\include\apr_time.h"\
- "..\..\srclib\apr\include\apr_user.h"\
- "..\..\srclib\apr\include\apr_want.h"\
- "..\..\srclib\apr\include\apr_xlate.h"\
-
-NODEP_CPP_MOD_A=\
- "..\..\include\ap_config_auto.h"\
-
-
-"$(INTDIR)\mod_auth_digest.obj" : $(SOURCE) $(DEP_CPP_MOD_A) "$(INTDIR)"
-
-
-
-!ENDIF
-
diff --git a/modules/arch/win32/mod_isapi.c b/modules/arch/win32/mod_isapi.c
deleted file mode 100644
index 5753afbeaf..0000000000
--- a/modules/arch/win32/mod_isapi.c
+++ /dev/null
@@ -1,1299 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * mod_isapi.c - Internet Server Application (ISA) module for Apache
- * by Alexei Kosut <akosut@apache.org>
- *
- * This module implements Microsoft's ISAPI, allowing Apache (when running
- * under Windows) to load Internet Server Applications (ISAPI extensions).
- * It implements all of the ISAPI 2.0 specification, except for the
- * "Microsoft-only" extensions dealing with asynchronous I/O. All ISAPI
- * extensions that use only synchronous I/O and are compatible with the
- * ISAPI 2.0 specification should work (most ISAPI 1.0 extensions should
- * function as well).
- *
- * To load, simply place the ISA in a location in the document tree.
- * Then add an "AddHandler isapi-isa dll" into your config file.
- * You should now be able to load ISAPI DLLs just be reffering to their
- * URLs. Make sure the ExecCGI option is active in the directory
- * the ISA is in.
- */
-
-#include "apr_strings.h"
-#include "apr_portable.h"
-#include "apr_buckets.h"
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_core.h"
-#include "http_protocol.h"
-#include "http_request.h"
-#include "http_log.h"
-#include "util_script.h"
-#include "mod_core.h"
-
-/* We use the exact same header file as the original */
-#include <HttpExt.h>
-
-#if !defined(HSE_REQ_MAP_URL_TO_PATH_EX) \
- || !defined(HSE_REQ_SEND_RESPONSE_HEADER_EX)
-#pragma message("WARNING: This build of Apache is missing the recent changes")
-#pragma message("in the Microsoft Win32 Platform SDK; some mod_isapi features")
-#pragma message("will be disabled. To obtain the latest Platform SDK files,")
-#pragma message("please refer to:")
-#pragma message("http://msdn.microsoft.com/downloads/sdks/platform/platform.asp")
-#endif
-
-/* TODO: Unknown errors that must be researched for correct codes */
-
-#define TODO_ERROR 1
-
-/* Seems IIS does not enforce the requirement for \r\n termination on HSE_REQ_SEND_RESPONSE_HEADER,
- define this to conform */
-#define RELAX_HEADER_RULE
-
-module isapi_module;
-
-/* Declare the ISAPI functions */
-
-BOOL WINAPI GetServerVariable (HCONN hConn, LPSTR lpszVariableName,
- LPVOID lpvBuffer, LPDWORD lpdwSizeofBuffer);
-BOOL WINAPI WriteClient (HCONN ConnID, LPVOID Buffer, LPDWORD lpwdwBytes,
- DWORD dwReserved);
-BOOL WINAPI ReadClient (HCONN ConnID, LPVOID lpvBuffer, LPDWORD lpdwSize);
-BOOL WINAPI ServerSupportFunction (HCONN hConn, DWORD dwHSERequest,
- LPVOID lpvBuffer, LPDWORD lpdwSize,
- LPDWORD lpdwDataType);
-
-/*
- The optimiser blows it totally here. What happens is that autos are addressed relative to the
- stack pointer, which, of course, moves around. The optimiser seems to lose track of it somewhere
- between setting HttpExtensionProc's address and calling through it. We work around the problem by
- forcing it to use frame pointers.
-
- The revisions below may eliminate this artifact.
-*/
-#pragma optimize("y",off)
-
-/* Our isapi server config structure */
-
-typedef struct {
- HANDLE lock;
- apr_array_header_t *loaded;
- DWORD ReadAheadBuffer;
- int LogNotSupported;
- int AppendLogToErrors;
- int AppendLogToQuery;
-} isapi_server_conf;
-
-/* Our loaded isapi module description structure */
-
-typedef struct {
- const char *filename;
- apr_dso_handle_t *handle;
- HSE_VERSION_INFO *pVer;
- PFN_GETEXTENSIONVERSION GetExtensionVersion;
- PFN_HTTPEXTENSIONPROC HttpExtensionProc;
- PFN_TERMINATEEXTENSION TerminateExtension;
- int refcount;
- DWORD timeout;
- BOOL fakeasync;
- DWORD reportversion;
-} isapi_loaded;
-
-/* Our "Connection ID" structure */
-
-typedef struct {
- LPEXTENSION_CONTROL_BLOCK ecb;
- isapi_server_conf *sconf;
- isapi_loaded *isa;
- request_rec *r;
- PFN_HSE_IO_COMPLETION completion;
- PVOID completion_arg;
- HANDLE complete;
-} isapi_cid;
-
-static BOOL isapi_unload(isapi_loaded* isa, int force);
-
-static apr_status_t cleanup_isapi_server_config(void *sconfv)
-{
- isapi_server_conf *sconf = sconfv;
- size_t n;
- isapi_loaded **isa;
-
- n = sconf->loaded->nelts;
- isa = (isapi_loaded **)sconf->loaded->elts;
- while(n--) {
- if ((*isa)->handle)
- isapi_unload(*isa, TRUE);
- ++isa;
- }
- CloseHandle(sconf->lock);
- return APR_SUCCESS;
-}
-
-static void *create_isapi_server_config(apr_pool_t *p, server_rec *s)
-{
- isapi_server_conf *sconf = apr_palloc(p, sizeof(isapi_server_conf));
- sconf->loaded = apr_array_make(p, 20, sizeof(isapi_loaded*));
- sconf->lock = CreateMutex(NULL, FALSE, NULL);
-
- sconf->ReadAheadBuffer = 49152;
- sconf->LogNotSupported = -1;
- sconf->AppendLogToErrors = 0;
- sconf->AppendLogToQuery = 0;
-
- apr_pool_cleanup_register(p, sconf, cleanup_isapi_server_config,
- apr_pool_cleanup_null);
-
- return sconf;
-}
-
-static int compare_loaded(const void *av, const void *bv)
-{
- const isapi_loaded **a = av;
- const isapi_loaded **b = bv;
-
- return strcmp((*a)->filename, (*b)->filename);
-}
-
-static void isapi_post_config(apr_pool_t *p, apr_pool_t *plog,
- apr_pool_t *ptemp, server_rec *s)
-{
- isapi_server_conf *sconf = ap_get_module_config(s->module_config,
- &isapi_module);
- isapi_loaded **elts = (isapi_loaded **)sconf->loaded->elts;
- int nelts = sconf->loaded->nelts;
-
- /* sort the elements of the main_server, by filename */
- qsort(elts, nelts, sizeof(isapi_loaded*), compare_loaded);
-
- /* and make the virtualhosts share the same thing */
- for (s = s->next; s; s = s->next) {
- ap_set_module_config(s->module_config, &isapi_module, sconf);
- }
-}
-
-static apr_status_t isapi_load(apr_pool_t *p, isapi_server_conf *sconf,
- request_rec *r, const char *fpath,
- isapi_loaded** isa)
-{
- isapi_loaded **found = (isapi_loaded **)sconf->loaded->elts;
- apr_status_t rv;
- int n;
-
- for (n = 0; n < sconf->loaded->nelts; ++n) {
- if (strcasecmp(fpath, (*found)->filename) == 0) {
- break;
- }
- ++found;
- }
-
- if (n < sconf->loaded->nelts)
- {
- *isa = *found;
- if ((*isa)->handle)
- {
- ++(*isa)->refcount;
- return APR_SUCCESS;
- }
- /* Otherwise we fall through and have to reload the resource
- * into this existing mod_isapi cache bucket.
- */
- }
- else
- {
- *isa = apr_pcalloc(p, sizeof(isapi_module));
- (*isa)->filename = fpath;
- (*isa)->pVer = apr_pcalloc(p, sizeof(HSE_VERSION_INFO));
-
- /* TODO: These need to become overrideable, so that we
- * assure a given isapi can be fooled into behaving well.
- */
- (*isa)->timeout = INFINITE; /* microsecs */
- (*isa)->fakeasync = TRUE;
- (*isa)->reportversion = MAKELONG(0, 5); /* Revision 5.0 */
- }
-
- rv = apr_dso_load(&(*isa)->handle, fpath, p);
- if (rv)
- {
- ap_log_rerror(APLOG_MARK, APLOG_ALERT, rv, r,
- "ISAPI %s failed to load", fpath);
- (*isa)->handle = NULL;
- return rv;
- }
-
- rv = apr_dso_sym((void**)&(*isa)->GetExtensionVersion, (*isa)->handle,
- "GetExtensionVersion");
- if (rv)
- {
- ap_log_rerror(APLOG_MARK, APLOG_ALERT, rv, r,
- "ISAPI %s is missing GetExtensionVersion()",
- fpath);
- apr_dso_unload((*isa)->handle);
- (*isa)->handle = NULL;
- return rv;
- }
-
- rv = apr_dso_sym((void**)&(*isa)->HttpExtensionProc, (*isa)->handle,
- "HttpExtensionProc");
- if (rv)
- {
- ap_log_rerror(APLOG_MARK, APLOG_ALERT, rv, r,
- "ISAPI %s is missing HttpExtensionProc()",
- fpath);
- apr_dso_unload((*isa)->handle);
- (*isa)->handle = NULL;
- return rv;
- }
-
- /* TerminateExtension() is an optional interface */
- rv = apr_dso_sym((void**)&(*isa)->TerminateExtension, (*isa)->handle,
- "TerminateExtension");
- SetLastError(0);
-
- /* Run GetExtensionVersion() */
- if (!((*isa)->GetExtensionVersion)((*isa)->pVer)) {
- apr_status_t rv = apr_get_os_error();
- ap_log_rerror(APLOG_MARK, APLOG_ALERT, rv, r,
- "ISAPI %s call GetExtensionVersion() failed",
- fpath);
- apr_dso_unload((*isa)->handle);
- (*isa)->handle = NULL;
- return rv;
- }
-
- ++(*isa)->refcount;
-
- return APR_SUCCESS;
-}
-
-static int isapi_unload(isapi_loaded* isa, int force)
-{
- /* All done with the DLL... get rid of it...
- *
- * If optionally cached, pass HSE_TERM_ADVISORY_UNLOAD,
- * and if it returns TRUE, unload, otherwise, cache it.
- */
- if ((--isa->refcount > 0) && !force)
- return FALSE;
- if (isa->TerminateExtension) {
- if (force)
- (*isa->TerminateExtension)(HSE_TERM_MUST_UNLOAD);
- else if (!(*isa->TerminateExtension)(HSE_TERM_ADVISORY_UNLOAD))
- return FALSE;
- }
- apr_dso_unload(isa->handle);
- isa->handle = NULL;
- return TRUE;
-}
-
-apr_status_t isapi_handler (request_rec *r)
-{
- isapi_server_conf * sconf;
- apr_table_t *e;
- apr_status_t rv;
- isapi_loaded *isa;
- isapi_cid *cid;
- DWORD read;
- int res;
-
- if(strcmp(r->handler, "isapi-isa"))
- return DECLINED;
-
- sconf = ap_get_module_config(r->server->module_config, &isapi_module);
- e = r->subprocess_env;
-
- /* Use similar restrictions as CGIs
- *
- * If this fails, it's pointless to load the isapi dll.
- */
- if (!(ap_allow_options(r) & OPT_EXECCGI))
- return HTTP_FORBIDDEN;
-
- if (r->finfo.filetype == APR_NOFILE)
- return HTTP_NOT_FOUND;
-
- if (r->finfo.filetype != APR_REG)
- return HTTP_FORBIDDEN;
-
- /* Load the isapi extention without caching (sconf == NULL)
- * but note that we will recover an existing cached module.
- */
- if (isapi_load(r->pool, sconf, r, r->filename, &isa) != APR_SUCCESS)
- return HTTP_INTERNAL_SERVER_ERROR;
-
- /* Set up variables */
- ap_add_common_vars(r);
- ap_add_cgi_vars(r);
- apr_table_setn(r->subprocess_env, "UNMAPPED_REMOTE_USER", "REMOTE_USER");
- apr_table_setn(r->subprocess_env, "SERVER_PORT_SECURE", "0");
- apr_table_setn(r->subprocess_env, "URL", r->uri);
-
- /* Set up connection structure and ecb */
- cid = apr_pcalloc(r->pool, sizeof(isapi_cid));
- cid->sconf = ap_get_module_config(r->server->module_config, &isapi_module);
-
- cid->ecb = apr_pcalloc(r->pool, sizeof(struct _EXTENSION_CONTROL_BLOCK));
- cid->ecb->ConnID = (HCONN)cid;
- cid->isa = isa;
- cid->r = r;
- cid->r->status = 0;
- cid->complete = NULL;
- cid->completion = NULL;
-
- cid->ecb->cbSize = sizeof(EXTENSION_CONTROL_BLOCK);
- cid->ecb->dwVersion = isa->reportversion;
- cid->ecb->dwHttpStatusCode = 0;
- strcpy(cid->ecb->lpszLogData, "");
- // TODO: are copies really needed here?
- cid->ecb->lpszMethod = apr_pstrdup(r->pool, (char*) r->method);
- cid->ecb->lpszQueryString = apr_pstrdup(r->pool,
- (char*) apr_table_get(e, "QUERY_STRING"));
- cid->ecb->lpszPathInfo = apr_pstrdup(r->pool,
- (char*) apr_table_get(e, "PATH_INFO"));
- cid->ecb->lpszPathTranslated = apr_pstrdup(r->pool,
- (char*) apr_table_get(e, "PATH_TRANSLATED"));
- cid->ecb->lpszContentType = apr_pstrdup(r->pool,
- (char*) apr_table_get(e, "CONTENT_TYPE"));
- /* Set up the callbacks */
- cid->ecb->GetServerVariable = GetServerVariable;
- cid->ecb->WriteClient = WriteClient;
- cid->ecb->ReadClient = ReadClient;
- cid->ecb->ServerSupportFunction = ServerSupportFunction;
-
-
- /* Set up client input */
- rv = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR);
- if (rv) {
- isapi_unload(isa, FALSE);
- return HTTP_INTERNAL_SERVER_ERROR; /* XXX: The wrong error */
- }
-
- if (ap_should_client_block(r)) {
- /* Time to start reading the appropriate amount of data,
- * and allow the administrator to tweak the number
- * TODO: add the httpd.conf option for ReadAheadBuffer.
- */
- if (r->remaining) {
- cid->ecb->cbTotalBytes = r->remaining;
- if (cid->ecb->cbTotalBytes > cid->sconf->ReadAheadBuffer)
- cid->ecb->cbAvailable = cid->sconf->ReadAheadBuffer;
- else
- cid->ecb->cbAvailable = cid->ecb->cbTotalBytes;
- }
- else
- {
- cid->ecb->cbTotalBytes = 0xffffffff;
- cid->ecb->cbAvailable = cid->sconf->ReadAheadBuffer;
- }
-
- cid->ecb->lpbData = apr_pcalloc(r->pool, cid->ecb->cbAvailable + 1);
-
- read = 0;
- while (read < cid->ecb->cbAvailable &&
- ((res = ap_get_client_block(r, cid->ecb->lpbData + read,
- cid->ecb->cbAvailable - read)) > 0)) {
- read += res;
- }
-
- if (res < 0) {
- isapi_unload(isa, FALSE);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- /* Although its not to spec, IIS seems to null-terminate
- * its lpdData string. So we will too.
- */
- if (res == 0)
- cid->ecb->cbAvailable = cid->ecb->cbTotalBytes = read;
- else
- cid->ecb->cbAvailable = read;
- cid->ecb->lpbData[read] = '\0';
- }
- else {
- cid->ecb->cbTotalBytes = 0;
- cid->ecb->cbAvailable = 0;
- cid->ecb->lpbData = NULL;
- }
-
- /* All right... try and run the sucker */
- rv = (*isa->HttpExtensionProc)(cid->ecb);
-
- /* Check for a log message - and log it */
- if (cid->ecb->lpszLogData && *cid->ecb->lpszLogData)
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, r,
- "ISAPI %s: %s", r->filename, cid->ecb->lpszLogData);
-
- switch(rv) {
- case HSE_STATUS_SUCCESS:
- case HSE_STATUS_SUCCESS_AND_KEEP_CONN:
- /* Ignore the keepalive stuff; Apache handles it just fine without
- * the ISA's "advice".
- * Per Microsoft: "In IIS versions 4.0 and later, the return
- * values HSE_STATUS_SUCCESS and HSE_STATUS_SUCCESS_AND_KEEP_CONN
- * are functionally identical: Keep-Alive connections are
- * maintained, if supported by the client."
- * ... so we were pat all this time
- */
- break;
-
- case HSE_STATUS_PENDING:
- /* emulating async behavior...
- *
- * Create a cid->completed event and wait on it for some timeout
- * so that the app thinks is it running async.
- *
- * All async ServerSupportFunction calls will be handled through
- * the registered IO_COMPLETION hook.
- */
-
- if (!isa->fakeasync) {
- if (cid->sconf->LogNotSupported)
- {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
- "ISAPI %s asynch I/O request refused",
- r->filename);
- cid->r->status = HTTP_INTERNAL_SERVER_ERROR;
- }
- }
- else {
- cid->complete = CreateEvent(NULL, FALSE, FALSE, NULL);
- if (WaitForSingleObject(cid->complete, isa->timeout)
- == WAIT_TIMEOUT) {
- /* TODO: Now what... if this hung, then do we kill our own
- * thread to force it's death? For now leave timeout = -1
- */
- }
- }
- break;
-
- case HSE_STATUS_ERROR:
- /* end response if we have yet to do so.
- */
- cid->r->status = HTTP_INTERNAL_SERVER_ERROR;
- break;
-
- default:
- /* TODO: log unrecognized retval for debugging
- */
- cid->r->status = HTTP_INTERNAL_SERVER_ERROR;
- break;
- }
-
- /* Set the status (for logging) */
- if (cid->ecb->dwHttpStatusCode) {
- cid->r->status = cid->ecb->dwHttpStatusCode;
- }
-
- /* All done with the DLL... get rid of it... */
- isapi_unload(isa, FALSE);
-
- return OK; /* NOT r->status, even if it has changed. */
-}
-#pragma optimize("",on)
-
-BOOL WINAPI GetServerVariable (HCONN hConn, LPSTR lpszVariableName,
- LPVOID lpvBuffer, LPDWORD lpdwSizeofBuffer)
-{
- request_rec *r = ((isapi_cid *)hConn)->r;
- const char *result;
- DWORD len;
-
- if (!strcmp(lpszVariableName, "ALL_HTTP"))
- {
- /* lf delimited, colon split, comma seperated and
- * null terminated list of HTTP_ vars
- */
- char **env = (char**) apr_table_elts(r->subprocess_env)->elts;
- int nelts = 2 * apr_table_elts(r->subprocess_env)->nelts;
- int i;
-
- for (len = 0, i = 0; i < nelts; i += 2)
- if (!strncmp(env[i], "HTTP_", 5))
- len += strlen(env[i]) + strlen(env[i + 1]) + 2;
-
- if (*lpdwSizeofBuffer < len + 1) {
- *lpdwSizeofBuffer = len + 1;
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return FALSE;
- }
-
- for (i = 0; i < nelts; i += 2)
- if (!strncmp(env[i], "HTTP_", 5)) {
- strcpy(lpvBuffer, env[i]);
- ((char*)lpvBuffer) += strlen(env[i]);
- *(((char*)lpvBuffer)++) = ':';
- strcpy(lpvBuffer, env[i + 1]);
- ((char*)lpvBuffer) += strlen(env[i + 1]);
- *(((char*)lpvBuffer)++) = '\n';
- }
-
- *(((char*)lpvBuffer)++) = '\0';
- *lpdwSizeofBuffer = len;
- return TRUE;
- }
-
- if (!strcmp(lpszVariableName, "ALL_RAW"))
- {
- /* lf delimited, colon split, comma seperated and
- * null terminated list of the raw request header
- */
- char **raw = (char**) apr_table_elts(r->headers_in)->elts;
- int nelts = 2 * apr_table_elts(r->headers_in)->nelts;
- int i;
-
- for (len = 0, i = 0; i < nelts; i += 2)
- len += strlen(raw[i]) + strlen(raw[i + 1]) + 2;
-
- if (*lpdwSizeofBuffer < len + 1) {
- *lpdwSizeofBuffer = len + 1;
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return FALSE;
- }
-
- for (i = 0; i < nelts; i += 2) {
- strcpy(lpvBuffer, raw[i]);
- ((char*)lpvBuffer) += strlen(raw[i]);
- *(((char*)lpvBuffer)++) = ':';
- *(((char*)lpvBuffer)++) = ' ';
- strcpy(lpvBuffer, raw[i + 1]);
- ((char*)lpvBuffer) += strlen(raw[i + 1]);
- *(((char*)lpvBuffer)++) = '\n';
- i += 2;
- }
- *(((char*)lpvBuffer)++) = '\0';
- *lpdwSizeofBuffer = len;
- return TRUE;
- }
-
- /* Not a special case */
- result = apr_table_get(r->subprocess_env, lpszVariableName);
-
- if (result) {
- len = strlen(result);
- if (*lpdwSizeofBuffer < len + 1) {
- *lpdwSizeofBuffer = len + 1;
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return FALSE;
- }
- strcpy(lpvBuffer, result);
- *lpdwSizeofBuffer = len;
- return TRUE;
- }
-
- /* Not Found */
- SetLastError(ERROR_INVALID_INDEX);
- return FALSE;
-}
-
-BOOL WINAPI WriteClient (HCONN ConnID, LPVOID Buffer, LPDWORD lpwdwBytes,
- DWORD dwReserved)
-{
- request_rec *r = ((isapi_cid *)ConnID)->r;
- apr_bucket_brigade *bb;
- apr_bucket *b;
-
- if (dwReserved == HSE_IO_SYNC)
- ; /* XXX: Fake it */
-
- bb = apr_brigade_create(r->pool);
- b = apr_bucket_transient_create(Buffer, *lpwdwBytes);
- APR_BRIGADE_INSERT_TAIL(bb, b);
- b = apr_bucket_eos_create();
- APR_BRIGADE_INSERT_TAIL(bb, b);
- ap_pass_brigade(r->output_filters, bb);
-
- return TRUE;
-}
-
-BOOL WINAPI ReadClient (HCONN ConnID, LPVOID lpvBuffer, LPDWORD lpdwSize)
-{
- request_rec *r = ((isapi_cid *)ConnID)->r;
- DWORD read = 0;
- int res;
-
- if (r->remaining < (long) *lpdwSize)
- *lpdwSize = r->remaining;
-
- while (read < *lpdwSize &&
- ((res = ap_get_client_block(r, (char*)lpvBuffer + read,
- *lpdwSize - read)) > 0)) {
- if (res < 0) {
- *lpdwSize = 0;
- if (!apr_get_os_error())
- SetLastError(TODO_ERROR); /* XXX: Find the right error code */
- return FALSE;
- }
-
- read += res;
- }
-
- *lpdwSize = read;
- return TRUE;
-}
-
-static apr_off_t SendResponseHeaderEx(isapi_cid *cid, const char *stat,
- const char *head, apr_size_t statlen,
- apr_size_t headlen)
-{
- int termarg;
- char *termch;
-
- if (!stat || statlen == 0 || !*stat) {
- stat = "Status: 200 OK";
- }
- else {
- char *newstat;
- newstat = apr_palloc(cid->r->pool, statlen + 9);
- strcpy(newstat, "Status: ");
- apr_cpystrn(newstat + 8, stat, statlen + 1);
- stat = newstat;
- }
-
- if (!head || headlen == 0 || !*head) {
- head = "\r\n";
- }
- else
- {
- if (head[headlen]) {
- /* Whoops... not NULL terminated */
- head = apr_pstrndup(cid->r->pool, head, headlen);
- }
- }
-
- /* Parse them out, or die trying */
- cid->r->status= ap_scan_script_header_err_strs(cid->r, NULL, &termch,
- &termarg, stat, head, NULL);
- cid->ecb->dwHttpStatusCode = cid->r->status;
- if (cid->r->status == HTTP_INTERNAL_SERVER_ERROR)
- return -1;
-
- /* Headers will actually go when they are good and ready */
-
- /* If all went well, tell the caller we consumed the headers complete */
- if (!termch)
- return(headlen);
-
- /* Any data left is sent directly by the caller, all we
- * give back is the size of the headers we consumed
- */
- if (termch && (termarg == 1) && headlen > (termch - head)) {
- return termch - head;
- }
- return 0;
-}
-
-/* XXX: Is there is still an O(n^2) attack possible here? Please detail. */
-BOOL WINAPI ServerSupportFunction(HCONN hConn, DWORD dwHSERequest,
- LPVOID lpvBuffer, LPDWORD lpdwSize,
- LPDWORD lpdwDataType)
-{
- isapi_cid *cid = (isapi_cid *)hConn;
- request_rec *r = cid->r;
- request_rec *subreq;
-
- switch (dwHSERequest) {
- case 1: /* HSE_REQ_SEND_URL_REDIRECT_RESP */
- /* Set the status to be returned when the HttpExtensionProc()
- * is done.
- * WARNING: Microsoft now advertises HSE_REQ_SEND_URL_REDIRECT_RESP
- * and HSE_REQ_SEND_URL as equivalant per the Jan 2000 SDK.
- * They most definately are not, even in their own samples.
- */
- apr_table_set (r->headers_out, "Location", lpvBuffer);
- cid->r->status = cid->ecb->dwHttpStatusCode
- = HTTP_MOVED_TEMPORARILY;
- return TRUE;
-
- case 2: /* HSE_REQ_SEND_URL */
- /* Soak up remaining input */
- if (r->remaining > 0) {
- char argsbuffer[HUGE_STRING_LEN];
- while (ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN));
- }
-
- /* Reset the method to GET */
- r->method = apr_pstrdup(r->pool, "GET");
- r->method_number = M_GET;
-
- /* Don't let anyone think there's still data */
- apr_table_unset(r->headers_in, "Content-Length");
-
- /* AV fault per PR3598 - redirected path is lost! */
- (char*)lpvBuffer = apr_pstrdup(r->pool, (char*)lpvBuffer);
- ap_internal_redirect((char*)lpvBuffer, r);
- return TRUE;
-
- case 3: /* HSE_REQ_SEND_RESPONSE_HEADER */
- {
- /* Parse them out, or die trying */
- apr_size_t statlen = 0, headlen = 0;
- int ate;
- if (lpvBuffer)
- statlen = strlen((char*) lpvBuffer);
- if (lpdwDataType)
- headlen = strlen((char*) lpdwDataType);
- ate = SendResponseHeaderEx(cid, (char*) lpvBuffer,
- (char*) lpdwDataType,
- statlen, headlen);
- if (ate < 0) {
- SetLastError(TODO_ERROR);
- return FALSE;
- }
- else if (ate < headlen) {
- apr_bucket_brigade *bb;
- apr_bucket *b;
- bb = apr_brigade_create(cid->r->pool);
- b = apr_bucket_transient_create((char*) lpdwDataType + ate,
- headlen - ate);
- APR_BRIGADE_INSERT_TAIL(bb, b);
- b = apr_bucket_eos_create();
- APR_BRIGADE_INSERT_TAIL(bb, b);
- ap_pass_brigade(cid->r->output_filters, bb);
- }
- return TRUE;
- }
-
- case 4: /* HSE_REQ_DONE_WITH_SESSION */
- /* Signal to resume the thread completing this request
- */
- if (cid->complete)
- SetEvent(cid->complete);
- return TRUE;
-
- case 1001: /* HSE_REQ_MAP_URL_TO_PATH */
- {
- /* Map a URL to a filename */
- char *file = (char *)lpvBuffer;
- DWORD len;
- subreq = ap_sub_req_lookup_uri(apr_pstrndup(r->pool, file, *lpdwSize),
- r, NULL);
-
- len = apr_cpystrn(file, subreq->filename, *lpdwSize) - file;
-
-
- /* IIS puts a trailing slash on directories, Apache doesn't */
- if (subreq->finfo.filetype == APR_DIR) {
- if (len < *lpdwSize - 1) {
- file[len++] = '\\';
- file[len] = '\0';
- }
- }
- *lpdwSize = len;
- return TRUE;
- }
-
- case 1002: /* HSE_REQ_GET_SSPI_INFO */
- if (cid->sconf->LogNotSupported)
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
- "ISAPI ServerSupportFunction HSE_REQ_GET_SSPI_INFO "
- "is not supported: %s", r->filename);
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
-
- case 1003: /* HSE_APPEND_LOG_PARAMETER */
- /* Log lpvBuffer, of lpdwSize bytes, in the URI Query (cs-uri-query) field
- */
- apr_table_set(r->notes, "isapi-parameter", (char*) lpvBuffer);
- if (cid->sconf->AppendLogToQuery) {
- if (r->args)
- r->args = apr_pstrcat(r->pool, r->args, (char*) lpvBuffer, NULL);
- else
- r->args = apr_pstrdup(r->pool, (char*) lpvBuffer);
- }
- if (cid->sconf->AppendLogToErrors)
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, r,
- "ISAPI %s: %s", cid->r->filename,
- (char*) lpvBuffer);
- return TRUE;
-
- case 1005: /* HSE_REQ_IO_COMPLETION */
- /* Emulates a completion port... Record callback address and
- * user defined arg, we will call this after any async request
- * (e.g. transmitfile) as if the request executed async.
- * Per MS docs... HSE_REQ_IO_COMPLETION replaces any prior call
- * to HSE_REQ_IO_COMPLETION, and lpvBuffer may be set to NULL.
- */
- if (!cid->isa->fakeasync) {
- if (cid->sconf->LogNotSupported)
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
- "ISAPI ServerSupportFunction HSE_REQ_IO_COMPLETION "
- "is not supported: %s", r->filename);
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- cid->completion = (PFN_HSE_IO_COMPLETION) lpvBuffer;
- cid->completion_arg = (PVOID) lpdwDataType;
- return TRUE;
-
- case 1006: /* HSE_REQ_TRANSMIT_FILE */
- {
- HSE_TF_INFO *tf = (HSE_TF_INFO*)lpvBuffer;
- apr_status_t rv;
- apr_bucket_brigade *bb;
- apr_bucket *b;
- apr_file_t *fd;
-
- if (!cid->isa->fakeasync && (tf->dwFlags & HSE_IO_ASYNC)) {
- if (cid->sconf->LogNotSupported)
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
- "ISAPI ServerSupportFunction HSE_REQ_TRANSMIT_FILE "
- "as HSE_IO_ASYNC is not supported: %s", r->filename);
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
-
- if ((rv = apr_os_file_put(&fd, tf->hFile, r->pool)) != APR_SUCCESS) {
- return FALSE;
- }
-
- /* apr_dupfile_oshandle (&fd, tf->hFile, r->pool); */
- bb = apr_brigade_create(r->pool);
-
- if (tf->dwFlags & HSE_IO_SEND_HEADERS)
- {
- /* According to MS: if calling HSE_REQ_TRANSMIT_FILE with the
- * HSE_IO_SEND_HEADERS flag, then you can't otherwise call any
- * HSE_SEND_RESPONSE_HEADERS* fn, but if you don't use the flag,
- * you must have done so. They document that the pHead headers
- * option is valid only for HSE_IO_SEND_HEADERS - we are a bit
- * more flexible and assume with the flag, pHead are the
- * response headers, and without, pHead simply contains text
- * (handled after this case).
- */
- apr_off_t ate = SendResponseHeaderEx(cid, tf->pszStatusCode,
- (char*)tf->pHead,
- strlen(tf->pszStatusCode),
- (apr_size_t)tf->HeadLength);
- if (ate < 0)
- {
- apr_brigade_destroy(bb);
- SetLastError(TODO_ERROR);
- return FALSE;
- }
- if (ate < (apr_size_t)tf->HeadLength)
- {
- b = apr_bucket_transient_create((char*)tf->pHead + ate,
- (apr_size_t)tf->HeadLength - ate);
- APR_BRIGADE_INSERT_TAIL(bb, b);
- }
- }
- else if (tf->pHead && tf->HeadLength) {
- b = apr_bucket_transient_create((char*)tf->pHead,
- (apr_size_t)tf->HeadLength);
- APR_BRIGADE_INSERT_TAIL(bb, b);
- }
-
- b = apr_bucket_file_create(fd, (apr_off_t)tf->Offset,
- (apr_size_t)tf->BytesToWrite);
- APR_BRIGADE_INSERT_TAIL(bb, b);
-
- if (tf->pTail && (apr_size_t)tf->TailLength) {
- b = apr_bucket_transient_create((char*)tf->pTail,
- (apr_size_t)tf->TailLength);
- APR_BRIGADE_INSERT_TAIL(bb, b);
- }
-
- b = apr_bucket_eos_create();
- APR_BRIGADE_INSERT_TAIL(bb, b);
- ap_pass_brigade(r->output_filters, bb);
-
- /* we do nothing with (tf->dwFlags & HSE_DISCONNECT_AFTER_SEND)
- */
-
- if (tf->dwFlags & HSE_IO_ASYNC) {
- /* XXX: Fake async response,
- * use tf->pfnHseIO, or if NULL, then use cid->fnIOComplete
- * pass pContect to the HseIO callback.
- */
- }
- return TRUE;
- }
-
- case 1007: /* HSE_REQ_REFRESH_ISAPI_ACL */
- if (cid->sconf->LogNotSupported)
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
- "ISAPI ServerSupportFunction "
- "HSE_REQ_REFRESH_ISAPI_ACL "
- "is not supported: %s", r->filename);
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
-
- case 1008: /* HSE_REQ_IS_KEEP_CONN */
- *((LPBOOL) lpvBuffer) = (r->connection->keepalive == 1);
- return TRUE;
-
- case 1010: /* XXX: Fake it : HSE_REQ_ASYNC_READ_CLIENT */
- if (cid->sconf->LogNotSupported)
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
- "ISAPI asynchronous I/O not supported: %s",
- r->filename);
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
-
- case 1011: /* HSE_REQ_GET_IMPERSONATION_TOKEN Added in ISAPI 4.0 */
- if (cid->sconf->LogNotSupported)
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
- "ISAPI ServerSupportFunction "
- "HSE_REQ_GET_IMPERSONATION_TOKEN "
- "is not supported: %s", r->filename);
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
-
-#ifdef HSE_REQ_MAP_URL_TO_PATH_EX
- case 1012: /* HSE_REQ_MAP_URL_TO_PATH_EX */
- {
- /* Map a URL to a filename */
- LPHSE_URL_MAPEX_INFO info = (LPHSE_URL_MAPEX_INFO) lpdwDataType;
- char* test_uri = apr_pstrndup(r->pool, (char *)lpvBuffer, *lpdwSize);
-
- subreq = ap_sub_req_lookup_uri(test_uri, r, NULL);
- info->cchMatchingURL = strlen(test_uri);
- info->cchMatchingPath = apr_cpystrn(info->lpszPath, subreq->filename,
- MAX_PATH) - info->lpszPath;
-
- /* Mapping started with assuming both strings matched.
- * Now roll on the path_info as a mismatch and handle
- * terminating slashes for directory matches.
- */
- if (subreq->path_info && *subreq->path_info) {
- apr_cpystrn(info->lpszPath + info->cchMatchingPath,
- subreq->path_info, MAX_PATH - info->cchMatchingPath);
- info->cchMatchingURL -= strlen(subreq->path_info);
- if (subreq->finfo.filetype == APR_DIR
- && info->cchMatchingPath < MAX_PATH - 1) {
- /* roll forward over path_info's first slash */
- ++info->cchMatchingPath;
- ++info->cchMatchingURL;
- }
- }
- else if (subreq->finfo.filetype == APR_DIR
- && info->cchMatchingPath < MAX_PATH - 1) {
- /* Add a trailing slash for directory */
- info->lpszPath[info->cchMatchingPath++] = '/';
- info->lpszPath[info->cchMatchingPath] = '\0';
- }
-
- /* If the matched isn't a file, roll match back to the prior slash */
- if (subreq->finfo.filetype == APR_NOFILE) {
- while (info->cchMatchingPath && info->cchMatchingURL) {
- if (info->lpszPath[info->cchMatchingPath - 1] == '/')
- break;
- --info->cchMatchingPath;
- --info->cchMatchingURL;
- }
- }
-
- /* Paths returned with back slashes */
- for (test_uri = info->lpszPath; *test_uri; ++test_uri)
- if (*test_uri == '/')
- *test_uri = '\\';
-
- /* is a combination of:
- * HSE_URL_FLAGS_READ 0x001 Allow read
- * HSE_URL_FLAGS_WRITE 0x002 Allow write
- * HSE_URL_FLAGS_EXECUTE 0x004 Allow execute
- * HSE_URL_FLAGS_SSL 0x008 Require SSL
- * HSE_URL_FLAGS_DONT_CACHE 0x010 Don't cache (VRoot only)
- * HSE_URL_FLAGS_NEGO_CERT 0x020 Allow client SSL cert
- * HSE_URL_FLAGS_REQUIRE_CERT 0x040 Require client SSL cert
- * HSE_URL_FLAGS_MAP_CERT 0x080 Map client SSL cert to account
- * HSE_URL_FLAGS_SSL128 0x100 Require 128-bit SSL cert
- * HSE_URL_FLAGS_SCRIPT 0x200 Allow script execution
- *
- * XxX: As everywhere, EXEC flags could use some work...
- * and this could go further with more flags, as desired.
- */
- info->dwFlags = (subreq->finfo.protection & APR_UREAD ? 0x001 : 0)
- | (subreq->finfo.protection & APR_UWRITE ? 0x002 : 0)
- | (subreq->finfo.protection & APR_UEXECUTE ? 0x204 : 0);
- return TRUE;
- }
-#endif
-
- case 1014: /* HSE_REQ_ABORTIVE_CLOSE */
- if (cid->sconf->LogNotSupported)
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
- "ISAPI ServerSupportFunction HSE_REQ_ABORTIVE_CLOSE"
- " is not supported: %s", r->filename);
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
-
- case 1015: /* HSE_REQ_GET_CERT_INFO_EX Added in ISAPI 4.0 */
- if (cid->sconf->LogNotSupported)
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
- "ISAPI ServerSupportFunction "
- "HSE_REQ_GET_CERT_INFO_EX "
- "is not supported: %s", r->filename);
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
-
-#ifdef HSE_REQ_SEND_RESPONSE_HEADER_EX
- case 1016: /* HSE_REQ_SEND_RESPONSE_HEADER_EX Added in ISAPI 4.0 */
- {
- LPHSE_SEND_HEADER_EX_INFO shi
- = (LPHSE_SEND_HEADER_EX_INFO) lpvBuffer;
- /* XXX: ignore shi->fKeepConn? We shouldn't need the advise */
- /* r->connection->keepalive = shi->fKeepConn; */
- apr_off_t ate = SendResponseHeaderEx(cid, shi->pszStatus,
- shi->pszHeader,
- shi->cchStatus,
- shi->cchHeader);
- if (ate < 0) {
- SetLastError(TODO_ERROR);
- return FALSE;
- }
- else if (ate < (apr_off_t)shi->cchHeader) {
- apr_bucket_brigade *bb;
- apr_bucket *b;
- bb = apr_brigade_create(cid->r->pool);
- b = apr_bucket_transient_create(shi->pszHeader + ate,
- (apr_size_t)shi->cchHeader - ate);
- APR_BRIGADE_INSERT_TAIL(bb, b);
- b = apr_bucket_eos_create();
- APR_BRIGADE_INSERT_TAIL(bb, b);
- ap_pass_brigade(cid->r->output_filters, bb);
- }
- return TRUE;
-
- }
-#endif
-
- case 1017: /* HSE_REQ_CLOSE_CONNECTION Added after ISAPI 4.0 */
- if (cid->sconf->LogNotSupported)
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
- "ISAPI ServerSupportFunction "
- "HSE_REQ_CLOSE_CONNECTION "
- "is not supported: %s", r->filename);
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
-
- case 1018: /* HSE_REQ_IS_CONNECTED Added after ISAPI 4.0 */
- /* Returns True if client is connected c.f. MSKB Q188346
- * assuming the identical return mechanism as HSE_REQ_IS_KEEP_CONN
- */
- *((LPBOOL) lpvBuffer) = (r->connection->aborted == 0);
- return TRUE;
-
- case 1020: /* HSE_REQ_EXTENSION_TRIGGER Added after ISAPI 4.0 */
- /* Undocumented - defined by the Microsoft Jan '00 Platform SDK
- */
- if (cid->sconf->LogNotSupported)
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
- "ISAPI ServerSupportFunction "
- "HSE_REQ_EXTENSION_TRIGGER "
- "is not supported: %s", r->filename);
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
-
- default:
- if (cid->sconf->LogNotSupported)
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
- "ISAPI ServerSupportFunction (%d) not supported: "
- "%s", dwHSERequest, r->filename);
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
-}
-
-/*
- * Command handler for the ISAPIReadAheadBuffer directive, which is TAKE1
- */
-static const char *isapi_cmd_readaheadbuffer(cmd_parms *cmd, void *config,
- char *arg)
-{
- isapi_server_conf *sconf = ap_get_module_config(cmd->server->module_config,
- &isapi_module);
- char *scan;
- long val;
-
- if (((val = strtol(arg, (char **) &scan, 10)) <= 0) || *scan)
- return "ISAPIReadAheadBuffer must be a legitimate value.";
-
- sconf->ReadAheadBuffer = val;
- return NULL;
-}
-
-/*
- * Command handler for the ISAPIReadAheadBuffer directive, which is TAKE1
- */
-static const char *isapi_cmd_lognotsupported(cmd_parms *cmd, void *config,
- char *arg)
-{
- isapi_server_conf *sconf = ap_get_module_config(cmd->server->module_config,
- &isapi_module);
-
- if (strcasecmp(arg, "on") == 0) {
- sconf->LogNotSupported = -1;
- }
- else if (strcasecmp(arg, "off") == 0) {
- sconf->LogNotSupported = 0;
- }
- else {
- return "ISAPILogNotSupported must be on or off";
- }
- return NULL;
-}
-
-static const char *isapi_cmd_appendlogtoerrors(cmd_parms *cmd, void *config,
- char *arg)
-{
- isapi_server_conf *sconf = ap_get_module_config(cmd->server->module_config,
- &isapi_module);
-
- if (strcasecmp(arg, "on") == 0) {
- sconf->AppendLogToErrors = -1;
- }
- else if (strcasecmp(arg, "off") == 0) {
- sconf->AppendLogToErrors = 0;
- }
- else {
- return "ISAPIAppendLogToErrors must be on or off";
- }
- return NULL;
-}
-
-static const char *isapi_cmd_appendlogtoquery(cmd_parms *cmd, void *config,
- char *arg)
-{
- isapi_server_conf *sconf = ap_get_module_config(cmd->server->module_config,
- &isapi_module);
-
- if (strcasecmp(arg, "on") == 0) {
- sconf->AppendLogToQuery = -1;
- }
- else if (strcasecmp(arg, "off") == 0) {
- sconf->AppendLogToQuery = 0;
- }
- else {
- return "ISAPIAppendLogToQuery must be on or off";
- }
- return NULL;
-}
-
-static const char *isapi_cmd_cachefile(cmd_parms *cmd, void *dummy,
- const char *filename)
-
-{
- isapi_server_conf *sconf = ap_get_module_config(cmd->server->module_config,
- &isapi_module);
- isapi_loaded *isa, **newisa;
- apr_finfo_t tmp;
- apr_status_t rv;
- char *fspec;
-
- fspec = ap_os_case_canonical_filename(cmd->pool, filename);
- if (apr_stat(&tmp, fspec,
- APR_FINFO_TYPE, cmd->temp_pool) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, cmd->server,
- "ISAPI: unable to stat(%s), skipping", filename);
- return NULL;
- }
- if (tmp.filetype != APR_REG) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, cmd->server,
- "ISAPI: %s isn't a regular file, skipping", filename);
- return NULL;
- }
-
- /* Load the extention as cached (passing sconf) */
- rv = isapi_load(cmd->pool, sconf, NULL, fspec, &isa);
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, rv, cmd->server,
- "ISAPI: unable to cache %s, skipping", filename);
- return NULL;
- }
-
- /* Add to cached list of loaded modules */
- newisa = apr_array_push(sconf->loaded);
- *newisa = isa;
-
- return NULL;
-}
-
-static void isapi_hooks(apr_pool_t *cont)
-{
- ap_hook_post_config(isapi_post_config, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_handler(isapi_handler, NULL, NULL, APR_HOOK_MIDDLE);
-}
-
-static const command_rec isapi_cmds[] = {
-AP_INIT_TAKE1("ISAPIReadAheadBuffer", isapi_cmd_readaheadbuffer, NULL, RSRC_CONF,
- "Maximum bytes to initially pass to the ISAPI handler"),
-AP_INIT_TAKE1("ISAPILogNotSupported", isapi_cmd_lognotsupported, NULL, RSRC_CONF,
- "Log requests not supported by the ISAPI server"),
-AP_INIT_TAKE1("ISAPIAppendLogToErrors", isapi_cmd_appendlogtoerrors, NULL, RSRC_CONF,
- "Send all Append Log requests to the error log"),
-AP_INIT_TAKE1("ISAPIAppendLogToQuery", isapi_cmd_appendlogtoquery, NULL, RSRC_CONF,
- "Append Log requests are concatinated to the query args"),
-AP_INIT_ITERATE("ISAPICacheFile", isapi_cmd_cachefile, NULL, RSRC_CONF,
- "Cache the specified ISAPI extension in-process"),
-{ NULL }
-};
-
-module isapi_module = {
- STANDARD20_MODULE_STUFF,
- NULL, /* create per-dir config */
- NULL, /* merge per-dir config */
- create_isapi_server_config, /* server config */
- NULL, /* merge server config */
- isapi_cmds, /* command apr_table_t */
- isapi_hooks /* register hooks */
-};
diff --git a/modules/cache/.cvsignore b/modules/cache/.cvsignore
deleted file mode 100644
index 65f0cc30cf..0000000000
--- a/modules/cache/.cvsignore
+++ /dev/null
@@ -1,10 +0,0 @@
-.deps
-.libs
-*.la
-modules.mk
-Makefile
-*.lo
-*.slo
-*.so
-Debug
-Release
diff --git a/modules/cache/.indent.pro b/modules/cache/.indent.pro
deleted file mode 100644
index a9fbe9f9a1..0000000000
--- a/modules/cache/.indent.pro
+++ /dev/null
@@ -1,54 +0,0 @@
--i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1
--TBUFF
--TFILE
--TTRANS
--TUINT4
--T_trans
--Tallow_options_t
--Tapache_sfio
--Tarray_header
--Tbool_int
--Tbuf_area
--Tbuff_struct
--Tbuffy
--Tcmd_how
--Tcmd_parms
--Tcommand_rec
--Tcommand_struct
--Tconn_rec
--Tcore_dir_config
--Tcore_server_config
--Tdir_maker_func
--Tevent
--Tglobals_s
--Thandler_func
--Thandler_rec
--Tjoblist_s
--Tlisten_rec
--Tmerger_func
--Tmode_t
--Tmodule
--Tmodule_struct
--Tmutex
--Tn_long
--Tother_child_rec
--Toverrides_t
--Tparent_score
--Tpid_t
--Tpiped_log
--Tpool
--Trequest_rec
--Trequire_line
--Trlim_t
--Tscoreboard
--Tsemaphore
--Tserver_addr_rec
--Tserver_rec
--Tserver_rec_chain
--Tshort_score
--Ttable
--Ttable_entry
--Tthread
--Tu_wide_int
--Tvtime_t
--Twide_int
diff --git a/modules/cache/Makefile.in b/modules/cache/Makefile.in
deleted file mode 100644
index 167b343d0d..0000000000
--- a/modules/cache/Makefile.in
+++ /dev/null
@@ -1,3 +0,0 @@
-
-include $(top_srcdir)/build/special.mk
-
diff --git a/modules/cache/config.m4 b/modules/cache/config.m4
deleted file mode 100644
index c4ad083075..0000000000
--- a/modules/cache/config.m4
+++ /dev/null
@@ -1,11 +0,0 @@
-dnl modules enabled in this directory by default
-
-dnl APACHE_MODULE(name, helptext[, objects[, structname[, default[, config]]]])
-
-APACHE_MODPATH_INIT(cache)
-
-APACHE_MODULE(file_cache, File cache, , , no)
-
-APR_ADDTO(LTFLAGS,-export-dynamic)
-
-APACHE_MODPATH_FINISH
diff --git a/modules/cache/mod_file_cache.c b/modules/cache/mod_file_cache.c
deleted file mode 100644
index 345a8e108b..0000000000
--- a/modules/cache/mod_file_cache.c
+++ /dev/null
@@ -1,468 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-/*
- * Author: mod_file_cache by Bill Stoddard <stoddard@apache.org>
- * Based on mod_mmap_static by Dean Gaudet <dgaudet@arctic.org>
- *
- * v0.01: initial implementation
- */
-
-/*
- Documentation:
-
- Some sites have a set of static files that are really busy, and
- change infrequently (or even on a regular schedule). Save time
- by caching open handles to these files. This module, unlike
- mod_mmap_static, caches open file handles, not file content.
- On systems (like Windows) with heavy system call overhead and
- that have an efficient sendfile implementation, caching file handles
- offers several advantages over caching content. First, the file system
- can manage the memory, allowing infrequently hit cached files to
- be paged out. Second, since caching open handles does not consume
- significant resources, it will be possible to enable an AutoLoadCache
- feature where static files are dynamically loaded in the cache
- as the server runs. On systems that have file change notification,
- this module can be enhanced to automatically garbage collect
- cached files that change on disk.
-
- This module should work on Unix systems that have sendfile. Place
- cachefile directives into your configuration to direct files to
- be cached.
-
- cachefile /path/to/file1
- cachefile /path/to/file2
- ...
-
- These files are only cached when the server is restarted, so if you
- change the list, or if the files are changed, then you'll need to
- restart the server.
-
- To reiterate that point: if the files are modified *in place*
- without restarting the server you may end up serving requests that
- are completely bogus. You should update files by unlinking the old
- copy and putting a new copy in place.
-
- There's no such thing as inheriting these files across vhosts or
- whatever... place the directives in the main server only.
-
- Known problems:
-
- Don't use Alias or RewriteRule to move these files around... unless
- you feel like paying for an extra stat() on each request. This is
- a deficiency in the Apache API that will hopefully be solved some day.
- The file will be served out of the file handle cache, but there will be
- an extra stat() that's a waste.
-*/
-
-#include "apr.h"
-
-#if !(APR_HAS_SENDFILE || APR_HAS_MMAP)
-#error mod_file_cache only works on systems with APR_HAS_SENDFILE or APR_HAS_MMAP
-#endif
-
-#include "apr_mmap.h"
-#include "apr_strings.h"
-#include "apr_hash.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#if APR_HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#define CORE_PRIVATE
-
-#include "httpd.h"
-#include "http_config.h"
-#include "http_log.h"
-#include "http_protocol.h"
-#include "http_request.h"
-#include "http_core.h"
-
-module AP_MODULE_DECLARE_DATA file_cache_module;
-
-typedef struct {
-#if APR_HAS_SENDFILE
- apr_file_t *file;
-#endif
- const char *filename;
- apr_finfo_t finfo;
- int is_mmapped;
-#if APR_HAS_MMAP
- apr_mmap_t *mm;
-#endif
- char mtimestr[APR_RFC822_DATE_LEN];
- char sizestr[21]; /* big enough to hold any 64-bit file size + null */
-} a_file;
-
-typedef struct {
- apr_hash_t *fileht;
-} a_server_config;
-
-
-static void *create_server_config(apr_pool_t *p, server_rec *s)
-{
- a_server_config *sconf = apr_palloc(p, sizeof(*sconf));
-
- sconf->fileht = apr_hash_make(p);
- return sconf;
-}
-
-static apr_status_t cleanup_file_cache(void *sconfv)
-{
- a_server_config *sconf = sconfv;
- a_file *file;
- apr_hash_index_t *hi;
-
- /* Iterate over the file hash table and clean up each entry */
- for (hi = apr_hash_first(sconf->fileht); hi; hi=apr_hash_next(hi)) {
- apr_hash_this(hi, NULL, NULL, (void **)&file);
-#if APR_HAS_MMAP
- if (file->is_mmapped) {
- apr_mmap_delete(file->mm);
- }
-#endif
-#if APR_HAS_SENDFILE
- if (!file->is_mmapped) {
- apr_file_close(file->file);
- }
-#endif
- }
- return APR_SUCCESS;
-}
-
-static void cache_the_file(cmd_parms *cmd, const char *filename, int mmap)
-{
- a_server_config *sconf;
- a_file *new_file;
- a_file tmp;
- apr_file_t *fd = NULL;
- apr_status_t rc;
- const char *fspec;
-
- fspec = ap_os_case_canonical_filename(cmd->pool, filename);
- if ((rc = apr_stat(&tmp.finfo, fspec, APR_FINFO_MIN,
- cmd->temp_pool)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, rc, cmd->server,
- "mod_file_cache: unable to stat(%s), skipping", fspec);
- return;
- }
- if (tmp.finfo.filetype != APR_REG) {
- ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, cmd->server,
- "mod_file_cache: %s isn't a regular file, skipping", fspec);
- return;
- }
-
- rc = apr_file_open(&fd, fspec, APR_READ | APR_XTHREAD, APR_OS_DEFAULT, cmd->pool);
- if (rc != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, rc, cmd->server,
- "mod_file_cache: unable to open(%s, O_RDONLY), skipping", fspec);
- return;
- }
-
- /* WooHoo, we have a file to put in the cache */
- new_file = apr_pcalloc(cmd->pool, sizeof(a_file));
- new_file->finfo = tmp.finfo;
-
-#if APR_HAS_MMAP
- if (mmap) {
- /* MMAPFile directive. MMAP'ing the file */
- if ((rc = apr_mmap_create(&new_file->mm, fd, 0, new_file->finfo.size,
- APR_MMAP_READ, cmd->pool)) != APR_SUCCESS) {
- apr_file_close(fd);
- ap_log_error(APLOG_MARK, APLOG_WARNING, rc, cmd->server,
- "mod_file_cache: unable to mmap %s, skipping", filename);
- return;
- }
- apr_file_close(fd);
- new_file->is_mmapped = TRUE;
- }
-#endif
-#if APR_HAS_SENDFILE
- if (!mmap) {
- /* CacheFile directive. Caching the file handle */
- new_file->is_mmapped = FALSE;
- new_file->file = fd;
- }
-#endif
-
- new_file->filename = fspec;
- apr_rfc822_date(new_file->mtimestr, new_file->finfo.mtime);
- apr_snprintf(new_file->sizestr, sizeof new_file->sizestr, "%" APR_OFF_T_FMT, new_file->finfo.size);
-
- sconf = ap_get_module_config(cmd->server->module_config, &file_cache_module);
- apr_hash_set(sconf->fileht, new_file->filename, strlen(new_file->filename), new_file);
-
- if (apr_hash_count(sconf->fileht) == 1) {
- /* first one, register the cleanup */
- apr_pool_cleanup_register(cmd->pool, sconf, cleanup_file_cache, apr_pool_cleanup_null);
- }
-}
-
-static const char *cachefilehandle(cmd_parms *cmd, void *dummy, const char *filename)
-{
-#if APR_HAS_SENDFILE
- cache_the_file(cmd, filename, 0);
-#else
- /* Sendfile not supported by this OS */
- ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, cmd->server,
- "mod_file_cache: unable to cache file: %s. Sendfile is not supported on this OS", filename);
-#endif
- return NULL;
-}
-static const char *cachefilemmap(cmd_parms *cmd, void *dummy, const char *filename)
-{
-#if APR_HAS_MMAP
- cache_the_file(cmd, filename, 1);
-#else
- /* MMAP not supported by this OS */
- ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, cmd->server,
- "mod_file_cache: unable to cache file: %s. MMAP is not supported by this OS", filename);
-#endif
- return NULL;
-}
-
-static void file_cache_post_config(apr_pool_t *p, apr_pool_t *plog,
- apr_pool_t *ptemp, server_rec *s)
-{
- /* Hummm, anything to do here? */
-}
-
-/* If it's one of ours, fill in r->finfo now to avoid extra stat()... this is a
- * bit of a kludge, because we really want to run after core_translate runs.
- */
-static int file_cache_xlat(request_rec *r)
-{
- a_server_config *sconf;
- a_file *match;
- int res;
-
- sconf = ap_get_module_config(r->server->module_config, &file_cache_module);
-
- /* we only operate when at least one cachefile directive was used */
- if (!apr_hash_count(sconf->fileht)) {
- return DECLINED;
- }
-
- res = ap_core_translate(r);
- if (res != OK || !r->filename) {
- return res;
- }
-
- /* search the cache */
- match = (a_file *) apr_hash_get(sconf->fileht, r->filename, APR_HASH_KEY_STRING);
- if (match == NULL)
- return DECLINED;
-
- /* pass search results to handler */
- ap_set_module_config(r->request_config, &file_cache_module, match);
-
- /* shortcircuit the get_path_info() stat() calls and stuff */
- r->finfo = match->finfo;
- return OK;
-}
-
-static int mmap_handler(request_rec *r, a_file *file)
-{
-#if APR_HAS_MMAP
- ap_send_mmap (file->mm, r, 0, file->finfo.size);
-#endif
- return OK;
-}
-
-static int sendfile_handler(request_rec *r, a_file *file)
-{
-#if APR_HAS_SENDFILE
- apr_size_t nbytes;
- apr_status_t rv = APR_EINIT;
-
- /* A cached file handle (more importantly, its file pointer) is
- * shared by all threads in the process. The file pointer will
- * be corrupted if multiple threads attempt to read from the
- * cached file handle. The sendfile API does not rely on the position
- * of the file pointer instead taking explicit file offset and
- * length arguments.
- *
- * We should call ap_send_fd with a cached file handle IFF
- * we are CERTAIN the file will be served with apr_sendfile().
- * The presense of an AP_FTYPE_FILTER in the filter chain nearly
- * guarantees that apr_sendfile will NOT be used to send the file.
- * Furthermore, AP_FTYPE_CONTENT filters will be at the beginning
- * of the chain, so it should suffice to just check the first
- * filter in the chain. If the first filter is not a content filter,
- * assume apr_sendfile() will be used to send the content.
- */
- if (r->output_filters && r->output_filters->frec) {
- if (r->output_filters->frec->ftype == AP_FTYPE_CONTENT)
- return DECLINED;
- }
-
-
- rv = ap_send_fd(file->file, r, 0, file->finfo.size, &nbytes);
- if (rv != APR_SUCCESS) {
- /* ap_send_fd will log the error */
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-#endif
- return OK;
-}
-
-static int file_cache_handler(request_rec *r)
-{
- a_file *match;
- int errstatus;
- int rc = OK;
-
- /* XXX: not sure if this is right yet
- * see comment in http_core.c:default_handler
- */
- if (ap_strcmp_match(r->handler, "*/*")) {
- return DECLINED;
- }
-
- /* we don't handle anything but GET */
- if (r->method_number != M_GET) return DECLINED;
-
- /* did xlat phase find the file? */
- match = ap_get_module_config(r->request_config, &file_cache_module);
-
- if (match == NULL) {
- return DECLINED;
- }
-
- /* note that we would handle GET on this resource */
- r->allowed |= (1 << M_GET);
-
- /* This handler has no use for a request body (yet), but we still
- * need to read and discard it if the client sent one.
- */
- if ((errstatus = ap_discard_request_body(r)) != OK)
- return errstatus;
-
- ap_update_mtime(r, match->finfo.mtime);
-
- /* ap_set_last_modified() always converts the file mtime to a string
- * which is slow. Accelerate the common case.
- * ap_set_last_modified(r);
- */
- {
- apr_time_t mod_time;
- char *datestr;
-
- mod_time = ap_rationalize_mtime(r, r->mtime);
- if (mod_time == match->finfo.mtime)
- datestr = match->mtimestr;
- else {
- datestr = apr_palloc(r->pool, APR_RFC822_DATE_LEN);
- apr_rfc822_date(datestr, mod_time);
- }
- apr_table_setn(r->headers_out, "Last-Modified", datestr);
- }
-
- ap_set_etag(r);
- if ((errstatus = ap_meets_conditions(r)) != OK) {
- return errstatus;
- }
-
- /* ap_set_content_length() always converts the same number and never
- * returns an error. Accelerate it.
- */
- r->clength = match->finfo.size;
- apr_table_setn(r->headers_out, "Content-Length", match->sizestr);
-
- /* Call appropriate handler */
- if (!r->header_only) {
- if (match->is_mmapped == TRUE)
- rc = mmap_handler(r, match);
- else
- rc = sendfile_handler(r, match);
- }
-
- return rc;
-}
-
-static command_rec file_cache_cmds[] =
-{
-AP_INIT_ITERATE("cachefile", cachefilehandle, NULL, RSRC_CONF,
- "A space separated list of files to add to the file handle cache at config time"),
-AP_INIT_ITERATE("mmapfile", cachefilemmap, NULL, RSRC_CONF,
- "A space separated list of files to mmap at config time"),
- {NULL}
-};
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_handler(file_cache_handler, NULL, NULL, APR_HOOK_LAST);
- ap_hook_post_config(file_cache_post_config, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_translate_name(file_cache_xlat, NULL, NULL, APR_HOOK_MIDDLE);
- /* This trick doesn't work apparently because the translate hooks
- are single shot. If the core_hook returns OK, then our hook is
- not called.
- ap_hook_translate_name(file_cache_xlat, aszPre, NULL, APR_HOOK_MIDDLE);
- */
-
-}
-
-module AP_MODULE_DECLARE_DATA file_cache_module =
-{
- STANDARD20_MODULE_STUFF,
- NULL, /* create per-directory config structure */
- NULL, /* merge per-directory config structures */
- create_server_config, /* create per-server config structure */
- NULL, /* merge per-server config structures */
- file_cache_cmds, /* command handlers */
- register_hooks /* register hooks */
-};
diff --git a/modules/cache/mod_file_cache.dsp b/modules/cache/mod_file_cache.dsp
deleted file mode 100644
index 58786f2e40..0000000000
--- a/modules/cache/mod_file_cache.dsp
+++ /dev/null
@@ -1,95 +0,0 @@
-# Microsoft Developer Studio Project File - Name="mod_file_cache" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=mod_file_cache - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "mod_file_cache.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_file_cache.mak" CFG="mod_file_cache - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_file_cache - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_file_cache - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "mod_file_cache - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\os\win32" /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_file_cache" /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 /nologo /subsystem:windows /dll /map /machine:I386 /out:"Release/mod_file_cache.so" /base:@..\..\os\win32\BaseAddr.ref,mod_file_cache
-# ADD LINK32 /nologo /subsystem:windows /dll /map /machine:I386 /out:"Release/mod_file_cache.so" /base:@..\..\os\win32\BaseAddr.ref,mod_file_cache
-
-!ELSEIF "$(CFG)" == "mod_file_cache - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\..\include" /I "..\..\os\win32" /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_file_cache" /FD /c
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /out:"Debug/mod_file_cache.so" /base:@..\..\os\win32\BaseAddr.ref,mod_file_cache
-# ADD LINK32 /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /out:"Debug/mod_file_cache.so" /base:@..\..\os\win32\BaseAddr.ref,mod_file_cache
-
-!ENDIF
-
-# Begin Target
-
-# Name "mod_file_cache - Win32 Release"
-# Name "mod_file_cache - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\mod_file_cache.c
-# End Source File
-# End Target
-# End Project
diff --git a/modules/cache/mod_file_cache.mak b/modules/cache/mod_file_cache.mak
deleted file mode 100644
index 3a4c5da41d..0000000000
--- a/modules/cache/mod_file_cache.mak
+++ /dev/null
@@ -1,331 +0,0 @@
-# Microsoft Developer Studio Generated NMAKE File, Based on mod_file_cache.dsp
-!IF "$(CFG)" == ""
-CFG=mod_file_cache - Win32 Debug
-!MESSAGE No configuration specified. Defaulting to mod_file_cache - Win32\
- Debug.
-!ENDIF
-
-!IF "$(CFG)" != "mod_file_cache - Win32 Release" && "$(CFG)" !=\
- "mod_file_cache - Win32 Debug"
-!MESSAGE Invalid configuration "$(CFG)" specified.
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_file_cache.mak" CFG="mod_file_cache - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_file_cache - Win32 Release" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_file_cache - Win32 Debug" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-!ERROR An invalid configuration is specified.
-!ENDIF
-
-!IF "$(OS)" == "Windows_NT"
-NULL=
-!ELSE
-NULL=nul
-!ENDIF
-
-!IF "$(CFG)" == "mod_file_cache - Win32 Release"
-
-OUTDIR=.\Release
-INTDIR=.\Release
-# Begin Custom Macros
-OutDir=.\Release
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_file_cache.so"
-
-!ELSE
-
-ALL : "libhttpd - Win32 Release" "libapr - Win32 Release"\
- "$(OUTDIR)\mod_file_cache.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libapr - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\mod_file_cache.idb"
- -@erase "$(INTDIR)\mod_file_cache.obj"
- -@erase "$(OUTDIR)\mod_file_cache.exp"
- -@erase "$(OUTDIR)\mod_file_cache.lib"
- -@erase "$(OUTDIR)\mod_file_cache.map"
- -@erase "$(OUTDIR)\mod_file_cache.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\os\win32" /I\
- "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D\
- "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_file_cache" /FD /c
-CPP_OBJS=.\Release/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_file_cache.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=/nologo /subsystem:windows /dll /incremental:no\
- /pdb:"$(OUTDIR)\mod_file_cache.pdb" /map:"$(INTDIR)\mod_file_cache.map"\
- /machine:I386 /out:"$(OUTDIR)\mod_file_cache.so"\
- /implib:"$(OUTDIR)\mod_file_cache.lib"\
- /base:@..\..\os\win32\BaseAddr.ref,mod_file_cache
-LINK32_OBJS= \
- "$(INTDIR)\mod_file_cache.obj" \
- "..\..\Release\libhttpd.lib" \
- "..\..\srclib\apr\Release\libapr.lib"
-
-"$(OUTDIR)\mod_file_cache.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ELSEIF "$(CFG)" == "mod_file_cache - Win32 Debug"
-
-OUTDIR=.\Debug
-INTDIR=.\Debug
-# Begin Custom Macros
-OutDir=.\Debug
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_file_cache.so"
-
-!ELSE
-
-ALL : "libhttpd - Win32 Debug" "libapr - Win32 Debug"\
- "$(OUTDIR)\mod_file_cache.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libapr - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\mod_file_cache.idb"
- -@erase "$(INTDIR)\mod_file_cache.obj"
- -@erase "$(OUTDIR)\mod_file_cache.exp"
- -@erase "$(OUTDIR)\mod_file_cache.lib"
- -@erase "$(OUTDIR)\mod_file_cache.map"
- -@erase "$(OUTDIR)\mod_file_cache.pdb"
- -@erase "$(OUTDIR)\mod_file_cache.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /I\
- "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D\
- "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_file_cache" /FD /c
-CPP_OBJS=.\Debug/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_file_cache.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=/nologo /subsystem:windows /dll /incremental:no\
- /pdb:"$(OUTDIR)\mod_file_cache.pdb" /map:"$(INTDIR)\mod_file_cache.map" /debug\
- /machine:I386 /out:"$(OUTDIR)\mod_file_cache.so"\
- /implib:"$(OUTDIR)\mod_file_cache.lib"\
- /base:@..\..\os\win32\BaseAddr.ref,mod_file_cache
-LINK32_OBJS= \
- "$(INTDIR)\mod_file_cache.obj" \
- "..\..\Debug\libhttpd.lib" \
- "..\..\srclib\apr\Debug\libapr.lib"
-
-"$(OUTDIR)\mod_file_cache.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ENDIF
-
-
-!IF "$(CFG)" == "mod_file_cache - Win32 Release" || "$(CFG)" ==\
- "mod_file_cache - Win32 Debug"
-
-!IF "$(CFG)" == "mod_file_cache - Win32 Release"
-
-"libapr - Win32 Release" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F .\libapr.mak CFG="libapr - Win32 Release"
- cd "..\..\modules\cache"
-
-"libapr - Win32 ReleaseCLEAN" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libapr.mak CFG="libapr - Win32 Release"\
- RECURSE=1
- cd "..\..\modules\cache"
-
-!ELSEIF "$(CFG)" == "mod_file_cache - Win32 Debug"
-
-"libapr - Win32 Debug" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F .\libapr.mak CFG="libapr - Win32 Debug"
- cd "..\..\modules\cache"
-
-"libapr - Win32 DebugCLEAN" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libapr.mak CFG="libapr - Win32 Debug"\
- RECURSE=1
- cd "..\..\modules\cache"
-
-!ENDIF
-
-!IF "$(CFG)" == "mod_file_cache - Win32 Release"
-
-"libhttpd - Win32 Release" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) /F .\libhttpd.mak CFG="libhttpd - Win32 Release"
- cd ".\modules\cache"
-
-"libhttpd - Win32 ReleaseCLEAN" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libhttpd.mak CFG="libhttpd - Win32 Release"\
- RECURSE=1
- cd ".\modules\cache"
-
-!ELSEIF "$(CFG)" == "mod_file_cache - Win32 Debug"
-
-"libhttpd - Win32 Debug" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) /F .\libhttpd.mak CFG="libhttpd - Win32 Debug"
- cd ".\modules\cache"
-
-"libhttpd - Win32 DebugCLEAN" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libhttpd.mak CFG="libhttpd - Win32 Debug"\
- RECURSE=1
- cd ".\modules\cache"
-
-!ENDIF
-
-SOURCE=.\mod_file_cache.c
-DEP_CPP_MOD_F=\
- "..\..\include\ap_config.h"\
- "..\..\include\ap_mmn.h"\
- "..\..\include\ap_release.h"\
- "..\..\include\http_config.h"\
- "..\..\include\http_core.h"\
- "..\..\include\http_log.h"\
- "..\..\include\http_protocol.h"\
- "..\..\include\http_request.h"\
- "..\..\include\httpd.h"\
- "..\..\include\pcreposix.h"\
- "..\..\include\util_cfgtree.h"\
- "..\..\include\util_filter.h"\
- "..\..\include\util_uri.h"\
- "..\..\os\win32\os.h"\
- "..\..\srclib\apr-util\include\apr_buckets.h"\
- "..\..\srclib\apr-util\include\apr_hooks.h"\
- "..\..\srclib\apr-util\include\apr_ring.h"\
- "..\..\srclib\apr-util\include\apu.h"\
- "..\..\srclib\apr\include\apr.h"\
- "..\..\srclib\apr\include\apr_dso.h"\
- "..\..\srclib\apr\include\apr_errno.h"\
- "..\..\srclib\apr\include\apr_file_info.h"\
- "..\..\srclib\apr\include\apr_file_io.h"\
- "..\..\srclib\apr\include\apr_general.h"\
- "..\..\srclib\apr\include\apr_hash.h"\
- "..\..\srclib\apr\include\apr_lock.h"\
- "..\..\srclib\apr\include\apr_mmap.h"\
- "..\..\srclib\apr\include\apr_network_io.h"\
- "..\..\srclib\apr\include\apr_pools.h"\
- "..\..\srclib\apr\include\apr_portable.h"\
- "..\..\srclib\apr\include\apr_strings.h"\
- "..\..\srclib\apr\include\apr_tables.h"\
- "..\..\srclib\apr\include\apr_thread_proc.h"\
- "..\..\srclib\apr\include\apr_time.h"\
- "..\..\srclib\apr\include\apr_user.h"\
- "..\..\srclib\apr\include\apr_want.h"\
-
-NODEP_CPP_MOD_F=\
- "..\..\include\ap_config_auto.h"\
-
-
-"$(INTDIR)\mod_file_cache.obj" : $(SOURCE) $(DEP_CPP_MOD_F) "$(INTDIR)"
-
-
-
-!ENDIF
-
diff --git a/modules/config5.m4 b/modules/config5.m4
deleted file mode 100644
index caa40eaf70..0000000000
--- a/modules/config5.m4
+++ /dev/null
@@ -1,43 +0,0 @@
-AC_MSG_CHECKING(for extra modules)
-AC_ARG_WITH(module,
- [ --with-module=location Include the specified module. location is the
- path to the new module.],
- [
- modtype=`echo $withval | sed -e's/\(.*\):.*/\1/'`
- pkg=`echo $withval | sed -e's/.*:\(.*\)/\1/'`
- modfilec=`echo $pkg | sed -e 's;^.*/;;'`
- modfileo=`echo $pkg | sed -e 's;^.*/;;' -e 's;\.c$;.o;'`
-
- if test "x$withval" != "xmodules/$modtype/$modfilec"; then
- cp $pkg modules/$modtype/$modfilec
- fi
- module=`echo $pkg | sed -e 's;.*/mod_\(.*\).c;\1;'`
- objects="mod_$module.lo"
- libname="mod_$module.la"
- modpath_current="modules/$modtype"
- BUILTIN_LIBS="$BUILTIN_LIBS $modpath_current/$libname"
- if test ! -s "$modpath_current/modules.mk"; then
- cat >>$modpath_current/modules.mk<<EOF
-$libname: $objects
- \$(MOD_LINK) $objects
-DISTCLEAN_TARGETS = modules.mk
-static = $libname
-shared =
-EOF
- else
- cat >>$modpath_current/modules.mk.tmp<<EOF
-$libname: $objects
- \$(MOD_LINK) $objects
-EOF
- cat $modpath_current/modules.mk >> $modpath_current/modules.mk.tmp
- rm $modpath_current/modules.mk
- mv $modpath_current/modules.mk.tmp $modpath_current/modules.mk
- sed -e "s/\(static =.*\)/\1 $libname/" $modpath_current/modules.mk > $modpath_current/modules.mk.tmp
- rm $modpath_current/modules.mk
- mv $modpath_current/modules.mk.tmp $modpath_current/modules.mk
- fi
- MODLIST="$MODLIST $module"
- AC_MSG_RESULT(added $withval)
- ],
- [ AC_MSG_RESULT(no extra modules)
- ])
diff --git a/modules/dav/fs/.cvsignore b/modules/dav/fs/.cvsignore
deleted file mode 100644
index 65f0cc30cf..0000000000
--- a/modules/dav/fs/.cvsignore
+++ /dev/null
@@ -1,10 +0,0 @@
-.deps
-.libs
-*.la
-modules.mk
-Makefile
-*.lo
-*.slo
-*.so
-Debug
-Release
diff --git a/modules/dav/fs/Makefile.in b/modules/dav/fs/Makefile.in
deleted file mode 100644
index 7c5c149d85..0000000000
--- a/modules/dav/fs/Makefile.in
+++ /dev/null
@@ -1,3 +0,0 @@
-# a modules Makefile has no explicit targets -- they will be defined by
-# whatever modules are enabled. just grab special.mk to deal with this.
-include $(top_srcdir)/build/special.mk
diff --git a/modules/dav/fs/config6.m4 b/modules/dav/fs/config6.m4
deleted file mode 100644
index ca1153aed3..0000000000
--- a/modules/dav/fs/config6.m4
+++ /dev/null
@@ -1,15 +0,0 @@
-dnl modules enabled in this directory by default
-
-APACHE_MODPATH_INIT(dav/fs)
-
-dav_fs_objects="mod_dav_fs.lo dbm.lo lock.lo repos.lo"
-
-if test "$enable_dav" = "no"; then
- dav_fs_enable=no
-else
- dav_fs_enable=yes
-fi
-
-APACHE_MODULE(dav_fs, DAV provider for the filesystem, $dav_fs_objects, , $dav_fs_enable)
-
-APACHE_MODPATH_FINISH
diff --git a/modules/dav/fs/dbm.c b/modules/dav/fs/dbm.c
deleted file mode 100644
index fd1b7714de..0000000000
--- a/modules/dav/fs/dbm.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-/*
-** DAV extension module for Apache 2.0.*
-** - Database support using DBM-style databases,
-** part of the filesystem repository implementation
-*/
-
-/*
-** This implementation uses a SDBM database per file and directory to
-** record the properties. These databases are kept in a subdirectory (of
-** the directory in question or the directory that holds the file in
-** question) named by the macro DAV_FS_STATE_DIR (.DAV). The filename of the
-** database is equivalent to the target filename, and is
-** DAV_FS_STATE_FILE_FOR_DIR (.state_for_dir) for the directory itself.
-*/
-
-#include "apr_strings.h"
-#include "apr_file_io.h"
-
-#include "apr_dbm.h"
-
-#include "mod_dav.h"
-#include "repos.h"
-
-struct dav_db {
- apr_pool_t *pool;
- apr_dbm_t *file;
-};
-
-
-void dav_dbm_get_statefiles(apr_pool_t *p, const char *fname,
- const char **state1, const char **state2)
-{
- if (fname == NULL)
- fname = DAV_FS_STATE_FILE_FOR_DIR;
-
- apr_dbm_get_usednames(p, fname, state1, state2);
-}
-
-static dav_error * dav_fs_dbm_error(dav_db *db, apr_pool_t *p,
- apr_status_t status)
-{
- int save_errno = errno;
- int errcode;
- const char *errstr;
- dav_error *err;
- char errbuf[200];
-
- if (status == APR_SUCCESS)
- return NULL;
-
- p = db ? db->pool : p;
-
- /* There might not be a <db> if we had problems creating it. */
- if (db == NULL) {
- errcode = 1;
- errstr = "Could not open property database.";
- }
- else {
- (void) apr_dbm_geterror(db->file, &errcode, errbuf, sizeof(errbuf));
- errstr = apr_pstrdup(p, errbuf);
- }
-
- err = dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, errcode, errstr);
- err->save_errno = save_errno;
- return err;
-}
-
-/* ensure that our state subdirectory is present */
-/* ### does this belong here or in dav_fs_repos.c ?? */
-void dav_fs_ensure_state_dir(apr_pool_t * p, const char *dirname)
-{
- const char *pathname = apr_pstrcat(p, dirname, "/" DAV_FS_STATE_DIR, NULL);
-
- /* ### do we need to deal with the umask? */
-
- /* just try to make it, ignoring any resulting errors */
- (void) apr_dir_make(pathname, APR_OS_DEFAULT, p);
-}
-
-/* dav_dbm_open_direct: Opens a *dbm database specified by path.
- * ro = boolean read-only flag.
- */
-dav_error * dav_dbm_open_direct(apr_pool_t *p, const char *pathname, int ro,
- dav_db **pdb)
-{
- apr_status_t status;
- apr_dbm_t *file;
-
- *pdb = NULL;
-
- if ((status = apr_dbm_open(&file, pathname,
- ro ? APR_DBM_READONLY : APR_DBM_RWCREATE,
- APR_OS_DEFAULT, p))
- != APR_SUCCESS
- && !ro) {
- /* ### do something with 'status' */
-
- /* we can't continue if we couldn't open the file
- and we need to write */
- return dav_fs_dbm_error(NULL, p, status);
- }
-
- /* may be NULL if we tried to open a non-existent db as read-only */
- if (file != NULL) {
- /* we have an open database... return it */
- *pdb = apr_pcalloc(p, sizeof(**pdb));
- (*pdb)->pool = p;
- (*pdb)->file = file;
- }
-
- return NULL;
-}
-
-static dav_error * dav_dbm_open(apr_pool_t * p, const dav_resource *resource,
- int ro, dav_db **pdb)
-{
- const char *dirpath;
- const char *fname;
- const char *pathname;
-
- /* Get directory and filename for resource */
- dav_fs_dir_file_name(resource, &dirpath, &fname);
-
- /* If not opening read-only, ensure the state dir exists */
- if (!ro) {
- /* ### what are the perf implications of always checking this? */
- dav_fs_ensure_state_dir(p, dirpath);
- }
-
- pathname = apr_pstrcat(p,
- dirpath,
- "/" DAV_FS_STATE_DIR "/",
- fname ? fname : DAV_FS_STATE_FILE_FOR_DIR,
- NULL);
-
- /* ### readers cannot open while a writer has this open; we should
- ### perform a few retries with random pauses. */
-
- /* ### do we need to deal with the umask? */
-
- return dav_dbm_open_direct(p, pathname, ro, pdb);
-}
-
-static void dav_dbm_close(dav_db *db)
-{
- apr_dbm_close(db->file);
-}
-
-static dav_error * dav_dbm_fetch(dav_db *db, dav_datum key, dav_datum *pvalue)
-{
- apr_status_t status = apr_dbm_fetch(db->file, key, pvalue);
-
- return dav_fs_dbm_error(db, NULL, status);
-}
-
-static dav_error * dav_dbm_store(dav_db *db, dav_datum key, dav_datum value)
-{
- apr_status_t status = apr_dbm_store(db->file, key, value);
-
- return dav_fs_dbm_error(db, NULL, status);
-}
-
-static dav_error * dav_dbm_delete(dav_db *db, dav_datum key)
-{
- apr_status_t status = apr_dbm_delete(db->file, key);
-
- return dav_fs_dbm_error(db, NULL, status);
-}
-
-static int dav_dbm_exists(dav_db *db, dav_datum key)
-{
- return apr_dbm_exists(db->file, key);
-}
-
-static dav_error * dav_dbm_firstkey(dav_db *db, dav_datum *pkey)
-{
- apr_status_t status = apr_dbm_firstkey(db->file, pkey);
-
- return dav_fs_dbm_error(db, NULL, status);
-}
-
-static dav_error * dav_dbm_nextkey(dav_db *db, dav_datum *pkey)
-{
- apr_status_t status = apr_dbm_nextkey(db->file, pkey);
-
- return dav_fs_dbm_error(db, NULL, status);
-}
-
-static void dav_dbm_freedatum(dav_db *db, dav_datum data)
-{
- apr_dbm_freedatum(db->file, data);
-}
-
-const dav_hooks_db dav_hooks_db_dbm =
-{
- dav_dbm_open,
- dav_dbm_close,
- dav_dbm_fetch,
- dav_dbm_store,
- dav_dbm_delete,
- dav_dbm_exists,
- dav_dbm_firstkey,
- dav_dbm_nextkey,
- dav_dbm_freedatum,
-};
diff --git a/modules/dav/fs/lock.c b/modules/dav/fs/lock.c
deleted file mode 100644
index cd7c43188d..0000000000
--- a/modules/dav/fs/lock.c
+++ /dev/null
@@ -1,1537 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-/*
-** DAV filesystem lock implementation
-*/
-
-#include "apr.h"
-#include "apr_strings.h"
-#include "apr_file_io.h"
-#include "apr_uuid.h"
-
-#define APR_WANT_MEMFUNC
-#include "apr_want.h"
-
-#include "httpd.h"
-#include "http_log.h"
-
-#include "mod_dav.h"
-#include "repos.h"
-
-
-/* ---------------------------------------------------------------
-**
-** Lock database primitives
-**
-*/
-
-/*
-** LOCK DATABASES
-**
-** Lockdiscovery information is stored in the single lock database specified
-** by the DAVLockDB directive. Information about this db is stored in the
-** global server configuration.
-**
-** KEY
-**
-** The database is keyed by a key_type unsigned char (DAV_TYPE_INODE or
-** DAV_TYPE_FNAME) followed by inode and device number if possible,
-** otherwise full path (in the case of Win32 or lock-null resources).
-**
-** VALUE
-**
-** The value consists of a list of elements.
-** DIRECT LOCK: [char (DAV_LOCK_DIRECT),
-** char (dav_lock_scope),
-** char (dav_lock_type),
-** int depth,
-** time_t expires,
-** apr_uuid_t locktoken,
-** char[] owner,
-** char[] auth_user]
-**
-** INDIRECT LOCK: [char (DAV_LOCK_INDIRECT),
-** apr_uuid_t locktoken,
-** time_t expires,
-** int key_size,
-** char[] key]
-** The key is to the collection lock that resulted in this indirect lock
-*/
-
-#define DAV_TRUE 1
-#define DAV_FALSE 0
-
-#define DAV_CREATE_LIST 23
-#define DAV_APPEND_LIST 24
-
-/* Stored lock_discovery prefix */
-#define DAV_LOCK_DIRECT 1
-#define DAV_LOCK_INDIRECT 2
-
-#define DAV_TYPE_INODE 10
-#define DAV_TYPE_FNAME 11
-
-
-/* ack. forward declare. */
-static dav_error * dav_fs_remove_locknull_member(apr_pool_t *p,
- const char *filename,
- dav_buffer *pbuf);
-
-/*
-** Use the opaquelock scheme for locktokens
-*/
-struct dav_locktoken {
- apr_uuid_t uuid;
-};
-#define dav_compare_locktoken(plt1, plt2) \
- memcmp(&(plt1)->uuid, &(plt2)->uuid, sizeof((plt1)->uuid))
-
-
-/* #################################################################
-** ### keep these structures (internal) or move fully to dav_lock?
-*/
-
-/*
-** We need to reliably size the fixed-length portion of
-** dav_lock_discovery; best to separate it into another
-** struct for a convenient sizeof, unless we pack lock_discovery.
-*/
-typedef struct dav_lock_discovery_fixed
-{
- char scope;
- char type;
- int depth;
- time_t timeout;
-} dav_lock_discovery_fixed;
-
-typedef struct dav_lock_discovery
-{
- struct dav_lock_discovery_fixed f;
-
- dav_locktoken *locktoken;
- const char *owner; /* owner field from activelock */
- const char *auth_user; /* authenticated user who created the lock */
- struct dav_lock_discovery *next;
-} dav_lock_discovery;
-
-/* Indirect locks represent locks inherited from containing collections.
- * They reference the lock token for the collection the lock is
- * inherited from. A lock provider may also define a key to the
- * inherited lock, for fast datbase lookup. The key is opaque outside
- * the lock provider.
- */
-typedef struct dav_lock_indirect
-{
- dav_locktoken *locktoken;
- dav_datum key;
- struct dav_lock_indirect *next;
- time_t timeout;
-} dav_lock_indirect;
-
-/* ################################################################# */
-
-
-/*
-** Stored direct lock info - full lock_discovery length:
-** prefix + Fixed length + lock token + 2 strings + 2 nulls (one for each string)
-*/
-#define dav_size_direct(a) (1 + sizeof(dav_lock_discovery_fixed) \
- + sizeof(apr_uuid_t) \
- + ((a)->owner ? strlen((a)->owner) : 0) \
- + ((a)->auth_user ? strlen((a)->auth_user) : 0) \
- + 2)
-
-/* Stored indirect lock info - lock token and dav_datum */
-#define dav_size_indirect(a) (1 + sizeof(apr_uuid_t) \
- + sizeof(time_t) \
- + sizeof(int) + (a)->key.dsize)
-
-/*
-** The lockdb structure.
-**
-** The <db> field may be NULL, meaning one of two things:
-** 1) That we have not actually opened the underlying database (yet). The
-** <opened> field should be false.
-** 2) We opened it readonly and it wasn't present.
-**
-** The delayed opening (determined by <opened>) makes creating a lockdb
-** quick, while deferring the underlying I/O until it is actually required.
-**
-** We export the notion of a lockdb, but hide the details of it. Most
-** implementations will use a database of some kind, but it is certainly
-** possible that alternatives could be used.
-*/
-struct dav_lockdb_private
-{
- request_rec *r; /* for accessing the uuid state */
- apr_pool_t *pool; /* a pool to use */
- const char *lockdb_path; /* where is the lock database? */
-
- int opened; /* we opened the database */
- dav_db *db; /* if non-NULL, the lock database */
-};
-typedef struct
-{
- dav_lockdb pub;
- dav_lockdb_private priv;
-} dav_lockdb_combined;
-
-/*
-** The private part of the lock structure.
-*/
-struct dav_lock_private
-{
- dav_datum key; /* key into the lock database */
-};
-typedef struct
-{
- dav_lock pub;
- dav_lock_private priv;
- dav_locktoken token;
-} dav_lock_combined;
-
-/*
-** This must be forward-declared so the open_lockdb function can use it.
-*/
-extern const dav_hooks_locks dav_hooks_locks_fs;
-
-
-/* internal function for creating locks */
-static dav_lock *dav_fs_alloc_lock(dav_lockdb *lockdb, dav_datum key,
- const dav_locktoken *locktoken)
-{
- dav_lock_combined *comb;
-
- comb = apr_pcalloc(lockdb->info->pool, sizeof(*comb));
- comb->pub.rectype = DAV_LOCKREC_DIRECT;
- comb->pub.info = &comb->priv;
- comb->priv.key = key;
-
- if (locktoken == NULL) {
- comb->pub.locktoken = &comb->token;
- apr_uuid_get(&comb->token.uuid);
- }
- else {
- comb->pub.locktoken = locktoken;
- }
-
- return &comb->pub;
-}
-
-/*
-** dav_fs_parse_locktoken
-**
-** Parse an opaquelocktoken URI into a locktoken.
-*/
-static dav_error * dav_fs_parse_locktoken(
- apr_pool_t *p,
- const char *char_token,
- dav_locktoken **locktoken_p)
-{
- dav_locktoken *locktoken;
-
- if (ap_strstr_c(char_token, "opaquelocktoken:") != char_token) {
- return dav_new_error(p,
- HTTP_BAD_REQUEST, DAV_ERR_LOCK_UNK_STATE_TOKEN,
- "The lock token uses an unknown State-token "
- "format and could not be parsed.");
- }
- char_token += 16;
-
- locktoken = apr_pcalloc(p, sizeof(*locktoken));
- if (apr_uuid_parse(&locktoken->uuid, char_token)) {
- return dav_new_error(p, HTTP_BAD_REQUEST, DAV_ERR_LOCK_PARSE_TOKEN,
- "The opaquelocktoken has an incorrect format "
- "and could not be parsed.");
- }
-
- *locktoken_p = locktoken;
- return NULL;
-}
-
-/*
-** dav_fs_format_locktoken
-**
-** Generate the URI for a locktoken
-*/
-static const char *dav_fs_format_locktoken(
- apr_pool_t *p,
- const dav_locktoken *locktoken)
-{
- char buf[APR_UUID_FORMATTED_LENGTH + 1];
-
- apr_uuid_format(buf, &locktoken->uuid);
- return apr_pstrcat(p, "opaquelocktoken:", buf, NULL);
-}
-
-/*
-** dav_fs_compare_locktoken
-**
-** Determine whether two locktokens are the same
-*/
-static int dav_fs_compare_locktoken(
- const dav_locktoken *lt1,
- const dav_locktoken *lt2)
-{
- return dav_compare_locktoken(lt1, lt2);
-}
-
-/*
-** dav_fs_really_open_lockdb:
-**
-** If the database hasn't been opened yet, then open the thing.
-*/
-static dav_error * dav_fs_really_open_lockdb(dav_lockdb *lockdb)
-{
- dav_error *err;
-
- if (lockdb->info->opened)
- return NULL;
-
- err = dav_dbm_open_direct(lockdb->info->pool,
- lockdb->info->lockdb_path,
- lockdb->ro,
- &lockdb->info->db);
- if (err != NULL) {
- return dav_push_error(lockdb->info->pool,
- HTTP_INTERNAL_SERVER_ERROR,
- DAV_ERR_LOCK_OPENDB,
- "Could not open the lock database.",
- err);
- }
-
- /* all right. it is opened now. */
- lockdb->info->opened = 1;
-
- return NULL;
-}
-
-/*
-** dav_fs_open_lockdb:
-**
-** "open" the lock database, as specified in the global server configuration.
-** If force is TRUE, then the database is opened now, rather than lazily.
-**
-** Note that only one can be open read/write.
-*/
-static dav_error * dav_fs_open_lockdb(request_rec *r, int ro, int force,
- dav_lockdb **lockdb)
-{
- dav_lockdb_combined *comb;
-
- comb = apr_pcalloc(r->pool, sizeof(*comb));
- comb->pub.hooks = &dav_hooks_locks_fs;
- comb->pub.ro = ro;
- comb->pub.info = &comb->priv;
- comb->priv.r = r;
- comb->priv.pool = r->pool;
-
- comb->priv.lockdb_path = dav_get_lockdb_path(r);
- if (comb->priv.lockdb_path == NULL) {
- return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR,
- DAV_ERR_LOCK_NO_DB,
- "A lock database was not specified with the "
- "DAVLockDB directive. One must be specified "
- "to use the locking functionality.");
- }
-
- /* done initializing. return it. */
- *lockdb = &comb->pub;
-
- if (force) {
- /* ### add a higher-level comment? */
- return dav_fs_really_open_lockdb(*lockdb);
- }
-
- return NULL;
-}
-
-/*
-** dav_fs_close_lockdb:
-**
-** Close it. Duh.
-*/
-static void dav_fs_close_lockdb(dav_lockdb *lockdb)
-{
- if (lockdb->info->db != NULL)
- (*dav_hooks_db_dbm.close)(lockdb->info->db);
-}
-
-/*
-** dav_fs_build_fname_key
-**
-** Given a pathname, build a DAV_TYPE_FNAME lock database key.
-*/
-static dav_datum dav_fs_build_fname_key(apr_pool_t *p, const char *pathname)
-{
- dav_datum key;
-
- /* ### does this allocation have a proper lifetime? need to check */
- /* ### can we use a buffer for this? */
-
- /* size is TYPE + pathname + null */
- key.dsize = strlen(pathname) + 2;
- key.dptr = apr_palloc(p, key.dsize);
- *key.dptr = DAV_TYPE_FNAME;
- memcpy(key.dptr + 1, pathname, key.dsize - 1);
- if (key.dptr[key.dsize - 2] == '/')
- key.dptr[--key.dsize - 1] = '\0';
- return key;
-}
-
-/*
-** dav_fs_build_key: Given a resource, return a dav_datum key
-** to look up lock information for this file.
-**
-** (Win32 or file is lock-null):
-** dav_datum->dvalue = full path
-**
-** (non-Win32 and file exists ):
-** dav_datum->dvalue = inode, dev_major, dev_minor
-*/
-static dav_datum dav_fs_build_key(apr_pool_t *p, const dav_resource *resource)
-{
- const char *file = dav_fs_pathname(resource);
-#ifndef WIN32
- dav_datum key;
- apr_finfo_t finfo;
-
- /* ### use lstat() ?? */
- if (apr_stat(&finfo, file, APR_FINFO_NORM, p) == APR_SUCCESS) {
-
- /* ### can we use a buffer for this? */
- key.dsize = 1 + sizeof(finfo.inode) + sizeof(finfo.device);
- key.dptr = apr_palloc(p, key.dsize);
- *key.dptr = DAV_TYPE_INODE;
- memcpy(key.dptr + 1, &finfo.inode, sizeof(finfo.inode));
- memcpy(key.dptr + 1 + sizeof(finfo.inode), &finfo.device,
- sizeof(finfo.device));
-
- return key;
- }
-#endif
-
- return dav_fs_build_fname_key(p, file);
-}
-
-/*
-** dav_fs_lock_expired: return 1 (true) if the given timeout is in the past
-** or present (the lock has expired), or 0 (false) if in the future
-** (the lock has not yet expired).
-*/
-static int dav_fs_lock_expired(time_t expires)
-{
- return expires != DAV_TIMEOUT_INFINITE && time(NULL) >= expires;
-}
-
-/*
-** dav_fs_save_lock_record: Saves the lock information specified in the
-** direct and indirect lock lists about path into the lock database.
-** If direct and indirect == NULL, the key is removed.
-*/
-static dav_error * dav_fs_save_lock_record(dav_lockdb *lockdb, dav_datum key,
- dav_lock_discovery *direct,
- dav_lock_indirect *indirect)
-{
- dav_error *err;
- dav_datum val = { 0 };
- char *ptr;
- dav_lock_discovery *dp = direct;
- dav_lock_indirect *ip = indirect;
-
-#if DAV_DEBUG
- if (lockdb->ro) {
- return dav_new_error(lockdb->info->pool,
- HTTP_INTERNAL_SERVER_ERROR, 0,
- "INTERNAL DESIGN ERROR: the lockdb was opened "
- "readonly, but an attempt to save locks was "
- "performed.");
- }
-#endif
-
- if ((err = dav_fs_really_open_lockdb(lockdb)) != NULL) {
- /* ### add a higher-level error? */
- return err;
- }
-
- /* If nothing to save, delete key */
- if (dp == NULL && ip == NULL) {
- /* don't fail if the key is not present */
- /* ### but what about other errors? */
- (void) (*dav_hooks_db_dbm.remove)(lockdb->info->db, key);
- return NULL;
- }
-
- while(dp) {
- val.dsize += dav_size_direct(dp);
- dp = dp->next;
- }
- while(ip) {
- val.dsize += dav_size_indirect(ip);
- ip = ip->next;
- }
-
- /* ### can this be apr_palloc() ? */
- /* ### hmmm.... investigate the use of a buffer here */
- ptr = val.dptr = apr_pcalloc(lockdb->info->pool, val.dsize);
- dp = direct;
- ip = indirect;
-
- while(dp) {
- *ptr++ = DAV_LOCK_DIRECT; /* Direct lock - lock_discovery struct follows */
- memcpy(ptr, dp, sizeof(dp->f)); /* Fixed portion of struct */
- ptr += sizeof(dp->f);
- memcpy(ptr, dp->locktoken, sizeof(*dp->locktoken));
- ptr += sizeof(*dp->locktoken);
- if (dp->owner == NULL) {
- *ptr++ = '\0';
- }
- else {
- memcpy(ptr, dp->owner, strlen(dp->owner) + 1);
- ptr += strlen(dp->owner) + 1;
- }
- if (dp->auth_user == NULL) {
- *ptr++ = '\0';
- }
- else {
- memcpy(ptr, dp->auth_user, strlen(dp->auth_user) + 1);
- ptr += strlen(dp->auth_user) + 1;
- }
-
- dp = dp->next;
- }
-
- while(ip) {
- *ptr++ = DAV_LOCK_INDIRECT; /* Indirect lock prefix */
- memcpy(ptr, ip->locktoken, sizeof(*ip->locktoken)); /* Locktoken */
- ptr += sizeof(*ip->locktoken);
- memcpy(ptr, &ip->timeout, sizeof(ip->timeout)); /* Expire time */
- ptr += sizeof(ip->timeout);
- memcpy(ptr, &ip->key.dsize, sizeof(ip->key.dsize)); /* Size of key */
- ptr += sizeof(ip->key.dsize);
- memcpy(ptr, ip->key.dptr, ip->key.dsize); /* Key data */
- ptr += ip->key.dsize;
- ip = ip->next;
- }
-
- if ((err = (*dav_hooks_db_dbm.store)(lockdb->info->db,
- key, val)) != NULL) {
- /* ### more details? add an error_id? */
- return dav_push_error(lockdb->info->pool,
- HTTP_INTERNAL_SERVER_ERROR,
- DAV_ERR_LOCK_SAVE_LOCK,
- "Could not save lock information.",
- err);
- }
-
- return NULL;
-}
-
-/*
-** dav_load_lock_record: Reads lock information about key from lock db;
-** creates linked lists of the direct and indirect locks.
-**
-** If add_method = DAV_APPEND_LIST, the result will be appended to the
-** head of the direct and indirect lists supplied.
-**
-** Passive lock removal: If lock has timed out, it will not be returned.
-** ### How much "logging" does RFC 2518 require?
-*/
-static dav_error * dav_fs_load_lock_record(dav_lockdb *lockdb, dav_datum key,
- int add_method,
- dav_lock_discovery **direct,
- dav_lock_indirect **indirect)
-{
- apr_pool_t *p = lockdb->info->pool;
- dav_error *err;
- apr_size_t offset = 0;
- int need_save = DAV_FALSE;
- dav_datum val = { 0 };
- dav_lock_discovery *dp;
- dav_lock_indirect *ip;
- dav_buffer buf = { 0 };
-
- if (add_method != DAV_APPEND_LIST) {
- *direct = NULL;
- *indirect = NULL;
- }
-
- if ((err = dav_fs_really_open_lockdb(lockdb)) != NULL) {
- /* ### add a higher-level error? */
- return err;
- }
-
- /*
- ** If we opened readonly and the db wasn't there, then there are no
- ** locks for this resource. Just exit.
- */
- if (lockdb->info->db == NULL)
- return NULL;
-
- if ((err = (*dav_hooks_db_dbm.fetch)(lockdb->info->db, key, &val)) != NULL)
- return err;
-
- if (!val.dsize)
- return NULL;
-
- while (offset < val.dsize) {
- switch (*(val.dptr + offset++)) {
- case DAV_LOCK_DIRECT:
- /* Create and fill a dav_lock_discovery structure */
-
- dp = apr_pcalloc(p, sizeof(*dp));
- memcpy(dp, val.dptr + offset, sizeof(dp->f));
- offset += sizeof(dp->f);
- dp->locktoken = apr_palloc(p, sizeof(*dp->locktoken));
- memcpy(dp->locktoken, val.dptr + offset, sizeof(*dp->locktoken));
- offset += sizeof(*dp->locktoken);
- if (*(val.dptr + offset) == '\0') {
- ++offset;
- }
- else {
- dp->owner = apr_pstrdup(p, val.dptr + offset);
- offset += strlen(dp->owner) + 1;
- }
-
- if (*(val.dptr + offset) == '\0') {
- ++offset;
- }
- else {
- dp->auth_user = apr_pstrdup(p, val.dptr + offset);
- offset += strlen(dp->auth_user) + 1;
- }
-
- if (!dav_fs_lock_expired(dp->f.timeout)) {
- dp->next = *direct;
- *direct = dp;
- }
- else {
- need_save = DAV_TRUE;
-
- /* Remove timed-out locknull fm .locknull list */
- if (*key.dptr == DAV_TYPE_FNAME) {
- const char *fname = key.dptr + 1;
- apr_finfo_t finfo;
-
- /* if we don't see the file, then it's a locknull */
- if (apr_lstat(&finfo, fname, APR_FINFO_NORM, p) != APR_SUCCESS) {
- if ((err = dav_fs_remove_locknull_member(p, fname, &buf)) != NULL) {
- /* ### push a higher-level description? */
- return err;
- }
- }
- }
- }
- break;
-
- case DAV_LOCK_INDIRECT:
- /* Create and fill a dav_lock_indirect structure */
-
- ip = apr_pcalloc(p, sizeof(*ip));
- ip->locktoken = apr_palloc(p, sizeof(*ip->locktoken));
- memcpy(ip->locktoken, val.dptr + offset, sizeof(*ip->locktoken));
- offset += sizeof(*ip->locktoken);
- memcpy(&ip->timeout, val.dptr + offset, sizeof(ip->timeout));
- offset += sizeof(ip->timeout);
- ip->key.dsize = *((int *) (val.dptr + offset)); /* length of datum */
- offset += sizeof(ip->key.dsize);
- ip->key.dptr = apr_palloc(p, ip->key.dsize);
- memcpy(ip->key.dptr, val.dptr + offset, ip->key.dsize);
- offset += ip->key.dsize;
-
- if (!dav_fs_lock_expired(ip->timeout)) {
- ip->next = *indirect;
- *indirect = ip;
- }
- else {
- need_save = DAV_TRUE;
- /* A locknull resource will never be locked indirectly */
- }
-
- break;
-
- default:
- (*dav_hooks_db_dbm.freedatum)(lockdb->info->db, val);
-
- /* ### should use a computed_desc and insert corrupt token data */
- --offset;
- return dav_new_error(p,
- HTTP_INTERNAL_SERVER_ERROR,
- DAV_ERR_LOCK_CORRUPT_DB,
- apr_psprintf(p,
- "The lock database was found to "
- "be corrupt. offset %"
- APR_SIZE_T_FMT ", c=%02x",
- offset, val.dptr[offset]));
- }
- }
-
- (*dav_hooks_db_dbm.freedatum)(lockdb->info->db, val);
-
- /* Clean up this record if we found expired locks */
- /*
- ** ### shouldn't do this if we've been opened READONLY. elide the
- ** ### timed-out locks from the response, but don't save that info back
- */
- if (need_save == DAV_TRUE) {
- return dav_fs_save_lock_record(lockdb, key, *direct, *indirect);
- }
-
- return NULL;
-}
-
-/* resolve <indirect>, returning <*direct> */
-static dav_error * dav_fs_resolve(dav_lockdb *lockdb,
- dav_lock_indirect *indirect,
- dav_lock_discovery **direct,
- dav_lock_discovery **ref_dp,
- dav_lock_indirect **ref_ip)
-{
- dav_error *err;
- dav_lock_discovery *dir;
- dav_lock_indirect *ind;
-
- if ((err = dav_fs_load_lock_record(lockdb, indirect->key,
- DAV_CREATE_LIST,
- &dir, &ind)) != NULL) {
- /* ### insert a higher-level description? */
- return err;
- }
- if (ref_dp != NULL) {
- *ref_dp = dir;
- *ref_ip = ind;
- }
-
- for (; dir != NULL; dir = dir->next) {
- if (!dav_compare_locktoken(indirect->locktoken, dir->locktoken)) {
- *direct = dir;
- return NULL;
- }
- }
-
- /* No match found (but we should have found one!) */
-
- /* ### use a different description and/or error ID? */
- return dav_new_error(lockdb->info->pool,
- HTTP_INTERNAL_SERVER_ERROR,
- DAV_ERR_LOCK_CORRUPT_DB,
- "The lock database was found to be corrupt. "
- "An indirect lock's direct lock could not "
- "be found.");
-}
-
-/* ---------------------------------------------------------------
-**
-** Property-related lock functions
-**
-*/
-
-/*
-** dav_fs_get_supportedlock: Returns a static string for all supportedlock
-** properties. I think we save more returning a static string than
-** constructing it every time, though it might look cleaner.
-*/
-static const char *dav_fs_get_supportedlock(const dav_resource *resource)
-{
- static const char supported[] = DEBUG_CR
- "<D:lockentry>" DEBUG_CR
- "<D:lockscope><D:exclusive/></D:lockscope>" DEBUG_CR
- "<D:locktype><D:write/></D:locktype>" DEBUG_CR
- "</D:lockentry>" DEBUG_CR
- "<D:lockentry>" DEBUG_CR
- "<D:lockscope><D:shared/></D:lockscope>" DEBUG_CR
- "<D:locktype><D:write/></D:locktype>" DEBUG_CR
- "</D:lockentry>" DEBUG_CR;
-
- return supported;
-}
-
-/* ---------------------------------------------------------------
-**
-** General lock functions
-**
-*/
-
-/* ---------------------------------------------------------------
-**
-** Functions dealing with lock-null resources
-**
-*/
-
-/*
-** dav_fs_load_locknull_list: Returns a dav_buffer dump of the locknull file
-** for the given directory.
-*/
-static dav_error * dav_fs_load_locknull_list(apr_pool_t *p, const char *dirpath,
- dav_buffer *pbuf)
-{
- apr_finfo_t finfo;
- apr_file_t *file = NULL;
- dav_error *err = NULL;
- apr_size_t amt;
-
- dav_buffer_init(p, pbuf, dirpath);
-
- if (pbuf->buf[pbuf->cur_len - 1] == '/')
- pbuf->buf[--pbuf->cur_len] = '\0';
-
- dav_buffer_place(p, pbuf, "/" DAV_FS_STATE_DIR "/" DAV_FS_LOCK_NULL_FILE);
-
- /* reset this in case we leave w/o reading into the buffer */
- pbuf->cur_len = 0;
-
- if (apr_file_open(&file, pbuf->buf, APR_READ | APR_BINARY, APR_OS_DEFAULT,
- p) != APR_SUCCESS) {
- return NULL;
- }
-
- if (apr_file_info_get(&finfo, APR_FINFO_NORM, file) != APR_SUCCESS) {
- err = dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
- apr_psprintf(p,
- "Opened but could not stat file %s",
- pbuf->buf));
- goto loaderror;
- }
-
- dav_set_bufsize(p, pbuf, finfo.size);
- amt = finfo.size;
- if (apr_file_read(file, pbuf->buf, &amt) != APR_SUCCESS
- || amt != finfo.size) {
- err = dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
- apr_psprintf(p,
- "Failure reading locknull file "
- "for %s", dirpath));
-
- /* just in case the caller disregards the returned error */
- pbuf->cur_len = 0;
- goto loaderror;
- }
-
- loaderror:
- apr_file_close(file);
- return err;
-}
-
-/*
-** dav_fs_save_locknull_list: Saves contents of pbuf into the
-** locknull file for dirpath.
-*/
-static dav_error * dav_fs_save_locknull_list(apr_pool_t *p, const char *dirpath,
- dav_buffer *pbuf)
-{
- const char *pathname;
- apr_file_t *file = NULL;
- dav_error *err = NULL;
- apr_size_t amt;
-
- if (pbuf->buf == NULL)
- return NULL;
-
- dav_fs_ensure_state_dir(p, dirpath);
- pathname = apr_pstrcat(p,
- dirpath,
- dirpath[strlen(dirpath) - 1] == '/' ? "" : "/",
- DAV_FS_STATE_DIR "/" DAV_FS_LOCK_NULL_FILE,
- NULL);
-
- if (pbuf->cur_len == 0) {
- /* delete the file if cur_len == 0 */
- if (apr_file_remove(pathname, p) != 0) {
- return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
- apr_psprintf(p,
- "Error removing %s", pathname));
- }
- return NULL;
- }
-
- if (apr_file_open(&file, pathname,
- APR_WRITE | APR_CREATE | APR_TRUNCATE | APR_BINARY,
- APR_OS_DEFAULT, p) != APR_SUCCESS) {
- return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
- apr_psprintf(p,
- "Error opening %s for writing",
- pathname));
- }
-
- amt = pbuf->cur_len;
- if (apr_file_write(file, pbuf->buf, &amt) != APR_SUCCESS
- || amt != pbuf->cur_len) {
- err = dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
- apr_psprintf(p,
- "Error writing %" APR_SIZE_T_FMT
- " bytes to %s",
- pbuf->cur_len, pathname));
- }
-
- apr_file_close(file);
- return err;
-}
-
-/*
-** dav_fs_remove_locknull_member: Removes filename from the locknull list
-** for directory path.
-*/
-static dav_error * dav_fs_remove_locknull_member(apr_pool_t *p,
- const char *filename,
- dav_buffer *pbuf)
-{
- dav_error *err;
- apr_size_t len;
- apr_size_t scanlen;
- char *scan;
- const char *scanend;
- char *dirpath = apr_pstrdup(p, filename);
- char *fname = strrchr(dirpath, '/');
- int dirty = 0;
-
- if (fname != NULL)
- *fname++ = '\0';
- else
- fname = dirpath;
- len = strlen(fname) + 1;
-
- if ((err = dav_fs_load_locknull_list(p, dirpath, pbuf)) != NULL) {
- /* ### add a higher level description? */
- return err;
- }
-
- for (scan = pbuf->buf, scanend = scan + pbuf->cur_len;
- scan < scanend;
- scan += scanlen) {
- scanlen = strlen(scan) + 1;
- if (len == scanlen && memcmp(fname, scan, scanlen) == 0) {
- pbuf->cur_len -= scanlen;
- memmove(scan, scan + scanlen, scanend - (scan + scanlen));
- dirty = 1;
- break;
- }
- }
-
- if (dirty) {
- if ((err = dav_fs_save_locknull_list(p, dirpath, pbuf)) != NULL) {
- /* ### add a higher level description? */
- return err;
- }
- }
-
- return NULL;
-}
-
-/* Note: used by dav_fs_repos.c */
-dav_error * dav_fs_get_locknull_members(
- const dav_resource *resource,
- dav_buffer *pbuf)
-{
- const char *dirpath;
-
- dav_fs_dir_file_name(resource, &dirpath, NULL);
- return dav_fs_load_locknull_list(dav_fs_pool(resource), dirpath, pbuf);
-}
-
-/* ### fold into append_lock? */
-/* ### take an optional buf parameter? */
-static dav_error * dav_fs_add_locknull_state(
- dav_lockdb *lockdb,
- const dav_resource *resource)
-{
- dav_buffer buf = { 0 };
- apr_pool_t *p = lockdb->info->pool;
- const char *dirpath;
- const char *fname;
- dav_error *err;
-
- dav_fs_dir_file_name(resource, &dirpath, &fname);
-
- if ((err = dav_fs_load_locknull_list(p, dirpath, &buf)) != NULL) {
- return dav_push_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
- "Could not load .locknull file.", err);
- }
-
- dav_buffer_append(p, &buf, fname);
- buf.cur_len++; /* we want the null-term here */
-
- if ((err = dav_fs_save_locknull_list(p, dirpath, &buf)) != NULL) {
- return dav_push_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
- "Could not save .locknull file.", err);
- }
-
- return NULL;
-}
-
-/*
-** dav_fs_remove_locknull_state: Given a request, check to see if r->filename
-** is/was a lock-null resource. If so, return it to an existant state.
-**
-** ### this function is broken... it doesn't check!
-**
-** In this implementation, this involves two things:
-** (a) remove it from the list in the appropriate .DAV/locknull file
-** (b) on *nix, convert the key from a filename to an inode.
-*/
-static dav_error * dav_fs_remove_locknull_state(
- dav_lockdb *lockdb,
- const dav_resource *resource)
-{
- dav_buffer buf = { 0 };
- dav_error *err;
- apr_pool_t *p = lockdb->info->pool;
- const char *pathname = dav_fs_pathname(resource);
-
- if ((err = dav_fs_remove_locknull_member(p, pathname, &buf)) != NULL) {
- /* ### add a higher-level description? */
- return err;
- }
-
-#ifndef WIN32
- {
- dav_lock_discovery *ld;
- dav_lock_indirect *id;
- dav_datum key;
-
- /*
- ** Fetch the lock(s) that made the resource lock-null. Remove
- ** them under the filename key. Obtain the new inode key, and
- ** save the same lock information under it.
- */
- key = dav_fs_build_fname_key(p, pathname);
- if ((err = dav_fs_load_lock_record(lockdb, key, DAV_CREATE_LIST,
- &ld, &id)) != NULL) {
- /* ### insert a higher-level error description */
- return err;
- }
-
- if ((err = dav_fs_save_lock_record(lockdb, key, NULL, NULL)) != NULL) {
- /* ### insert a higher-level error description */
- return err;
- }
-
- key = dav_fs_build_key(p, resource);
- if ((err = dav_fs_save_lock_record(lockdb, key, ld, id)) != NULL) {
- /* ### insert a higher-level error description */
- return err;
- }
- }
-#endif
-
- return NULL;
-}
-
-static dav_error * dav_fs_create_lock(dav_lockdb *lockdb,
- const dav_resource *resource,
- dav_lock **lock)
-{
- dav_datum key;
-
- key = dav_fs_build_key(lockdb->info->pool, resource);
-
- *lock = dav_fs_alloc_lock(lockdb,
- key,
- NULL);
-
- (*lock)->is_locknull = !resource->exists;
-
- return NULL;
-}
-
-static dav_error * dav_fs_get_locks(dav_lockdb *lockdb,
- const dav_resource *resource,
- int calltype,
- dav_lock **locks)
-{
- apr_pool_t *p = lockdb->info->pool;
- dav_datum key;
- dav_error *err;
- dav_lock *lock = NULL;
- dav_lock *newlock;
- dav_lock_discovery *dp;
- dav_lock_indirect *ip;
-
-#if DAV_DEBUG
- if (calltype == DAV_GETLOCKS_COMPLETE) {
- return dav_new_error(lockdb->info->pool,
- HTTP_INTERNAL_SERVER_ERROR, 0,
- "INTERNAL DESIGN ERROR: DAV_GETLOCKS_COMPLETE "
- "is not yet supported");
- }
-#endif
-
- key = dav_fs_build_key(p, resource);
- if ((err = dav_fs_load_lock_record(lockdb, key, DAV_CREATE_LIST,
- &dp, &ip)) != NULL) {
- /* ### push a higher-level desc? */
- return err;
- }
-
- /* copy all direct locks to the result list */
- for (; dp != NULL; dp = dp->next) {
- newlock = dav_fs_alloc_lock(lockdb, key, dp->locktoken);
- newlock->is_locknull = !resource->exists;
- newlock->scope = dp->f.scope;
- newlock->type = dp->f.type;
- newlock->depth = dp->f.depth;
- newlock->timeout = dp->f.timeout;
- newlock->owner = dp->owner;
- newlock->auth_user = dp->auth_user;
-
- /* hook into the result list */
- newlock->next = lock;
- lock = newlock;
- }
-
- /* copy all the indirect locks to the result list. resolve as needed. */
- for (; ip != NULL; ip = ip->next) {
- newlock = dav_fs_alloc_lock(lockdb, ip->key, ip->locktoken);
- newlock->is_locknull = !resource->exists;
-
- if (calltype == DAV_GETLOCKS_RESOLVED) {
- if ((err = dav_fs_resolve(lockdb, ip, &dp, NULL, NULL)) != NULL) {
- /* ### push a higher-level desc? */
- return err;
- }
-
- newlock->scope = dp->f.scope;
- newlock->type = dp->f.type;
- newlock->depth = dp->f.depth;
- newlock->timeout = dp->f.timeout;
- newlock->owner = dp->owner;
- newlock->auth_user = dp->auth_user;
- }
- else {
- /* DAV_GETLOCKS_PARTIAL */
- newlock->rectype = DAV_LOCKREC_INDIRECT_PARTIAL;
- }
-
- /* hook into the result list */
- newlock->next = lock;
- lock = newlock;
- }
-
- *locks = lock;
- return NULL;
-}
-
-static dav_error * dav_fs_find_lock(dav_lockdb *lockdb,
- const dav_resource *resource,
- const dav_locktoken *locktoken,
- int partial_ok,
- dav_lock **lock)
-{
- dav_error *err;
- dav_datum key;
- dav_lock_discovery *dp;
- dav_lock_indirect *ip;
-
- *lock = NULL;
-
- key = dav_fs_build_key(lockdb->info->pool, resource);
- if ((err = dav_fs_load_lock_record(lockdb, key, DAV_CREATE_LIST,
- &dp, &ip)) != NULL) {
- /* ### push a higher-level desc? */
- return err;
- }
-
- for (; dp != NULL; dp = dp->next) {
- if (!dav_compare_locktoken(locktoken, dp->locktoken)) {
- *lock = dav_fs_alloc_lock(lockdb, key, locktoken);
- (*lock)->is_locknull = !resource->exists;
- (*lock)->scope = dp->f.scope;
- (*lock)->type = dp->f.type;
- (*lock)->depth = dp->f.depth;
- (*lock)->timeout = dp->f.timeout;
- (*lock)->owner = dp->owner;
- (*lock)->auth_user = dp->auth_user;
- return NULL;
- }
- }
-
- for (; ip != NULL; ip = ip->next) {
- if (!dav_compare_locktoken(locktoken, ip->locktoken)) {
- *lock = dav_fs_alloc_lock(lockdb, ip->key, locktoken);
- (*lock)->is_locknull = !resource->exists;
-
- /* ### nobody uses the resolving right now! */
- if (partial_ok) {
- (*lock)->rectype = DAV_LOCKREC_INDIRECT_PARTIAL;
- }
- else {
- (*lock)->rectype = DAV_LOCKREC_INDIRECT;
- if ((err = dav_fs_resolve(lockdb, ip, &dp,
- NULL, NULL)) != NULL) {
- /* ### push a higher-level desc? */
- return err;
- }
- (*lock)->scope = dp->f.scope;
- (*lock)->type = dp->f.type;
- (*lock)->depth = dp->f.depth;
- (*lock)->timeout = dp->f.timeout;
- (*lock)->owner = dp->owner;
- (*lock)->auth_user = dp->auth_user;
- }
- return NULL;
- }
- }
-
- return NULL;
-}
-
-static dav_error * dav_fs_has_locks(dav_lockdb *lockdb,
- const dav_resource *resource,
- int *locks_present)
-{
- dav_error *err;
- dav_datum key;
-
- *locks_present = 0;
-
- if ((err = dav_fs_really_open_lockdb(lockdb)) != NULL) {
- /* ### insert a higher-level error description */
- return err;
- }
-
- /*
- ** If we opened readonly and the db wasn't there, then there are no
- ** locks for this resource. Just exit.
- */
- if (lockdb->info->db == NULL)
- return NULL;
-
- key = dav_fs_build_key(lockdb->info->pool, resource);
-
- *locks_present = (*dav_hooks_db_dbm.exists)(lockdb->info->db, key);
-
- return NULL;
-}
-
-static dav_error * dav_fs_append_locks(dav_lockdb *lockdb,
- const dav_resource *resource,
- int make_indirect,
- const dav_lock *lock)
-{
- apr_pool_t *p = lockdb->info->pool;
- dav_error *err;
- dav_lock_indirect *ip;
- dav_lock_discovery *dp;
- dav_datum key;
-
- key = dav_fs_build_key(lockdb->info->pool, resource);
- if ((err = dav_fs_load_lock_record(lockdb, key, 0, &dp, &ip)) != NULL) {
- /* ### maybe add in a higher-level description */
- return err;
- }
-
- /*
- ** ### when we store the lock more directly, we need to update
- ** ### lock->rectype and lock->is_locknull
- */
-
- if (make_indirect) {
- for (; lock != NULL; lock = lock->next) {
-
- /* ### this works for any <lock> rectype */
- dav_lock_indirect *newi = apr_pcalloc(p, sizeof(*newi));
-
- /* ### shut off the const warning for now */
- newi->locktoken = (dav_locktoken *)lock->locktoken;
- newi->timeout = lock->timeout;
- newi->key = lock->info->key;
- newi->next = ip;
- ip = newi;
- }
- }
- else {
- for (; lock != NULL; lock = lock->next) {
- /* create and link in the right kind of lock */
-
- if (lock->rectype == DAV_LOCKREC_DIRECT) {
- dav_lock_discovery *newd = apr_pcalloc(p, sizeof(*newd));
-
- newd->f.scope = lock->scope;
- newd->f.type = lock->type;
- newd->f.depth = lock->depth;
- newd->f.timeout = lock->timeout;
- /* ### shut off the const warning for now */
- newd->locktoken = (dav_locktoken *)lock->locktoken;
- newd->owner = lock->owner;
- newd->auth_user = lock->auth_user;
- newd->next = dp;
- dp = newd;
- }
- else {
- /* DAV_LOCKREC_INDIRECT(_PARTIAL) */
-
- dav_lock_indirect *newi = apr_pcalloc(p, sizeof(*newi));
-
- /* ### shut off the const warning for now */
- newi->locktoken = (dav_locktoken *)lock->locktoken;
- newi->key = lock->info->key;
- newi->next = ip;
- ip = newi;
- }
- }
- }
-
- if ((err = dav_fs_save_lock_record(lockdb, key, dp, ip)) != NULL) {
- /* ### maybe add a higher-level description */
- return err;
- }
-
- /* we have a special list for recording locknull resources */
- /* ### ack! this can add two copies to the locknull list */
- if (!resource->exists
- && (err = dav_fs_add_locknull_state(lockdb, resource)) != NULL) {
- /* ### maybe add a higher-level description */
- return err;
- }
-
- return NULL;
-}
-
-static dav_error * dav_fs_remove_lock(dav_lockdb *lockdb,
- const dav_resource *resource,
- const dav_locktoken *locktoken)
-{
- dav_error *err;
- dav_buffer buf = { 0 };
- dav_lock_discovery *dh = NULL;
- dav_lock_indirect *ih = NULL;
- dav_datum key;
-
- key = dav_fs_build_key(lockdb->info->pool, resource);
-
- if (locktoken != NULL) {
- dav_lock_discovery *dp;
- dav_lock_discovery *dprev = NULL;
- dav_lock_indirect *ip;
- dav_lock_indirect *iprev = NULL;
-
- if ((err = dav_fs_load_lock_record(lockdb, key, DAV_CREATE_LIST,
- &dh, &ih)) != NULL) {
- /* ### maybe add a higher-level description */
- return err;
- }
-
- for (dp = dh; dp != NULL; dp = dp->next) {
- if (dav_compare_locktoken(locktoken, dp->locktoken) == 0) {
- if (dprev)
- dprev->next = dp->next;
- else
- dh = dh->next;
- }
- dprev = dp;
- }
-
- for (ip = ih; ip != NULL; ip = ip->next) {
- if (dav_compare_locktoken(locktoken, ip->locktoken) == 0) {
- if (iprev)
- iprev->next = ip->next;
- else
- ih = ih->next;
- }
- iprev = ip;
- }
-
- }
-
- /* save the modified locks, or remove all locks (dh=ih=NULL). */
- if ((err = dav_fs_save_lock_record(lockdb, key, dh, ih)) != NULL) {
- /* ### maybe add a higher-level description */
- return err;
- }
-
- /*
- ** If this resource is a locknull resource AND no more locks exist,
- ** then remove the locknull member.
- **
- ** Note: remove_locknull_state() attempts to convert a locknull member
- ** to a real member. In this case, all locks are gone, so the
- ** locknull resource returns to the null state (ie. doesn't exist),
- ** so there is no need to update the lockdb (and it won't find
- ** any because a precondition is that none exist).
- */
- if (!resource->exists && dh == NULL && ih == NULL
- && (err = dav_fs_remove_locknull_member(lockdb->info->pool,
- dav_fs_pathname(resource),
- &buf)) != NULL) {
- /* ### maybe add a higher-level description */
- return err;
- }
-
- return NULL;
-}
-
-static int dav_fs_do_refresh(dav_lock_discovery *dp,
- const dav_locktoken_list *ltl,
- time_t new_time)
-{
- int dirty = 0;
-
- for (; ltl != NULL; ltl = ltl->next) {
- if (dav_compare_locktoken(dp->locktoken, ltl->locktoken) == 0)
- {
- dp->f.timeout = new_time;
- dirty = 1;
- }
- }
-
- return dirty;
-}
-
-static dav_error * dav_fs_refresh_locks(dav_lockdb *lockdb,
- const dav_resource *resource,
- const dav_locktoken_list *ltl,
- time_t new_time,
- dav_lock **locks)
-{
- dav_error *err;
- dav_datum key;
- dav_lock_discovery *dp;
- dav_lock_discovery *dp_scan;
- dav_lock_indirect *ip;
- int dirty = 0;
- dav_lock *newlock;
-
- *locks = NULL;
-
- key = dav_fs_build_key(lockdb->info->pool, resource);
- if ((err = dav_fs_load_lock_record(lockdb, key, DAV_CREATE_LIST,
- &dp, &ip)) != NULL) {
- /* ### maybe add in a higher-level description */
- return err;
- }
-
- /* ### we should be refreshing direct AND (resolved) indirect locks! */
-
- /* refresh all of the direct locks on this resource */
- for (dp_scan = dp; dp_scan != NULL; dp_scan = dp_scan->next) {
- if (dav_fs_do_refresh(dp_scan, ltl, new_time)) {
- /* the lock was refreshed. return the lock. */
- newlock = dav_fs_alloc_lock(lockdb, key, dp_scan->locktoken);
- newlock->is_locknull = !resource->exists;
- newlock->scope = dp_scan->f.scope;
- newlock->type = dp_scan->f.type;
- newlock->depth = dp_scan->f.depth;
- newlock->timeout = dp_scan->f.timeout;
- newlock->owner = dp_scan->owner;
- newlock->auth_user = dp_scan->auth_user;
-
- newlock->next = *locks;
- *locks = newlock;
-
- dirty = 1;
- }
- }
-
- /* if we refreshed any locks, then save them back. */
- if (dirty
- && (err = dav_fs_save_lock_record(lockdb, key, dp, ip)) != NULL) {
- /* ### maybe add in a higher-level description */
- return err;
- }
-
- /* for each indirect lock, find its direct lock and refresh it. */
- for (; ip != NULL; ip = ip->next) {
- dav_lock_discovery *ref_dp;
- dav_lock_indirect *ref_ip;
-
- if ((err = dav_fs_resolve(lockdb, ip, &dp_scan,
- &ref_dp, &ref_ip)) != NULL) {
- /* ### push a higher-level desc? */
- return err;
- }
- if (dav_fs_do_refresh(dp_scan, ltl, new_time)) {
- /* the lock was refreshed. return the lock. */
- newlock = dav_fs_alloc_lock(lockdb, ip->key, dp->locktoken);
- newlock->is_locknull = !resource->exists;
- newlock->scope = dp->f.scope;
- newlock->type = dp->f.type;
- newlock->depth = dp->f.depth;
- newlock->timeout = dp->f.timeout;
- newlock->owner = dp->owner;
- newlock->auth_user = dp_scan->auth_user;
-
- newlock->next = *locks;
- *locks = newlock;
-
- /* save the (resolved) direct lock back */
- if ((err = dav_fs_save_lock_record(lockdb, ip->key, ref_dp,
- ref_ip)) != NULL) {
- /* ### push a higher-level desc? */
- return err;
- }
- }
- }
-
- return NULL;
-}
-
-
-const dav_hooks_locks dav_hooks_locks_fs =
-{
- dav_fs_get_supportedlock,
- dav_fs_parse_locktoken,
- dav_fs_format_locktoken,
- dav_fs_compare_locktoken,
- dav_fs_open_lockdb,
- dav_fs_close_lockdb,
- dav_fs_remove_locknull_state,
- dav_fs_create_lock,
- dav_fs_get_locks,
- dav_fs_find_lock,
- dav_fs_has_locks,
- dav_fs_append_locks,
- dav_fs_remove_lock,
- dav_fs_refresh_locks,
- NULL, /* get_resource */
-};
diff --git a/modules/dav/fs/mod_dav_fs.c b/modules/dav/fs/mod_dav_fs.c
deleted file mode 100644
index 98493d7145..0000000000
--- a/modules/dav/fs/mod_dav_fs.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "httpd.h"
-#include "http_config.h"
-
-#include "mod_dav.h"
-#include "repos.h"
-
-/* per-server configuration */
-typedef struct {
- const char *lockdb_path;
-
-} dav_fs_server_conf;
-
-extern module AP_MODULE_DECLARE_DATA dav_fs_module;
-
-const char *dav_get_lockdb_path(const request_rec *r)
-{
- dav_fs_server_conf *conf;
-
- conf = ap_get_module_config(r->server->module_config, &dav_fs_module);
- return conf->lockdb_path;
-}
-
-static void *dav_fs_create_server_config(apr_pool_t *p, server_rec *s)
-{
- return apr_pcalloc(p, sizeof(dav_fs_server_conf));
-}
-
-static void *dav_fs_merge_server_config(apr_pool_t *p,
- void *base, void *overrides)
-{
- dav_fs_server_conf *parent = base;
- dav_fs_server_conf *child = overrides;
- dav_fs_server_conf *newconf;
-
- newconf = apr_pcalloc(p, sizeof(*newconf));
-
- newconf->lockdb_path =
- child->lockdb_path ? child->lockdb_path : parent->lockdb_path;
-
- return newconf;
-}
-
-/*
- * Command handler for the DAVLockDB directive, which is TAKE1
- */
-static const char *dav_fs_cmd_davlockdb(cmd_parms *cmd, void *config,
- const char *arg1)
-{
- dav_fs_server_conf *conf;
-
- conf = ap_get_module_config(cmd->server->module_config,
- &dav_fs_module);
- arg1 = ap_os_canonical_filename(cmd->pool, arg1);
- conf->lockdb_path = ap_server_root_relative(cmd->pool, arg1);
-
- return NULL;
-}
-
-static const command_rec dav_fs_cmds[] =
-{
- /* per server */
- AP_INIT_TAKE1("DAVLockDB", dav_fs_cmd_davlockdb, NULL, RSRC_CONF,
- "specify a lock database"),
-
- { NULL }
-};
-
-static void register_hooks(apr_pool_t *p)
-{
- dav_hook_gather_propsets(dav_fs_gather_propsets, NULL, NULL,
- APR_HOOK_MIDDLE);
- dav_hook_find_liveprop(dav_fs_find_liveprop, NULL, NULL, APR_HOOK_MIDDLE);
- dav_hook_insert_all_liveprops(dav_fs_insert_all_liveprops, NULL, NULL,
- APR_HOOK_MIDDLE);
-
- dav_fs_register(p);
-}
-
-module AP_MODULE_DECLARE_DATA dav_fs_module =
-{
- STANDARD20_MODULE_STUFF,
- NULL, /* dir config creater */
- NULL, /* dir merger --- default is to override */
- dav_fs_create_server_config, /* server config */
- dav_fs_merge_server_config, /* merge server config */
- dav_fs_cmds, /* command table */
- register_hooks, /* register hooks */
-};
diff --git a/modules/dav/fs/mod_dav_fs.dsp b/modules/dav/fs/mod_dav_fs.dsp
deleted file mode 100644
index d81178fd8b..0000000000
--- a/modules/dav/fs/mod_dav_fs.dsp
+++ /dev/null
@@ -1,119 +0,0 @@
-# Microsoft Developer Studio Project File - Name="mod_dav_fs" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=mod_dav_fs - Win32 Release
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "mod_dav_fs.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_dav_fs.mak" CFG="mod_dav_fs - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_dav_fs - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_dav_fs - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "mod_dav_fs - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /I "..\main" /I "..\..\..\srclib\aputil" /I "..\..\..\srclib\sdbm" /I "..\..\..\srclib\expat-lite" /I "..\..\..\srclib\apr\include" /I "../../../srclib/apr-util/include" /I "..\..\..\include" /I "..\..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_dav_fs" /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "NDEBUG"
-# ADD RSC /l 0x809 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_dav_fs.so" /machine:I386 /base:@..\..\..\os\win32\BaseAddr.ref,mod_dav_fs
-# ADD LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_dav_fs.so" /machine:I386 /base:@..\..\..\os\win32\BaseAddr.ref,mod_dav_fs
-
-!ELSEIF "$(CFG)" == "mod_dav_fs - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\main" /I "..\..\..\srclib\aputil" /I "..\..\..\srclib\sdbm" /I "..\..\..\srclib\expat-lite" /I "..\..\..\srclib\apr\include" /I "../../../srclib/apr-util/include" /I "..\..\..\include" /I "..\..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_dav_fs" /FD /c
-# ADD BASE MTL /nologo /D "_DEBUG" /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "_DEBUG"
-# ADD RSC /l 0x809 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /out:"Debug/mod_dav_fs.so" /machine:I386 /base:@..\..\..\os\win32\BaseAddr.ref,mod_dav_fs
-# ADD LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /out:"Debug/mod_dav_fs.so" /machine:I386 /base:@..\..\..\os\win32\BaseAddr.ref,mod_dav_fs
-
-!ENDIF
-
-# Begin Target
-
-# Name "mod_dav_fs - Win32 Release"
-# Name "mod_dav_fs - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
-# Begin Source File
-
-SOURCE=.\dbm.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\lock.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\mod_dav_fs.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\repos.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
-# Begin Source File
-
-SOURCE=.\repos.h
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/modules/dav/fs/mod_dav_fs.mak b/modules/dav/fs/mod_dav_fs.mak
deleted file mode 100644
index bd7b6238ae..0000000000
--- a/modules/dav/fs/mod_dav_fs.mak
+++ /dev/null
@@ -1,533 +0,0 @@
-# Microsoft Developer Studio Generated NMAKE File, Based on mod_dav_fs.dsp
-!IF "$(CFG)" == ""
-CFG=mod_dav_fs - Win32 Release
-!MESSAGE No configuration specified. Defaulting to mod_dav_fs - Win32 Release.
-!ENDIF
-
-!IF "$(CFG)" != "mod_dav_fs - Win32 Release" && "$(CFG)" !=\
- "mod_dav_fs - Win32 Debug"
-!MESSAGE Invalid configuration "$(CFG)" specified.
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_dav_fs.mak" CFG="mod_dav_fs - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_dav_fs - Win32 Release" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_dav_fs - Win32 Debug" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-!ERROR An invalid configuration is specified.
-!ENDIF
-
-!IF "$(OS)" == "Windows_NT"
-NULL=
-!ELSE
-NULL=nul
-!ENDIF
-
-!IF "$(CFG)" == "mod_dav_fs - Win32 Release"
-
-OUTDIR=.\Release
-INTDIR=.\Release
-# Begin Custom Macros
-OutDir=.\Release
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_dav_fs.so"
-
-!ELSE
-
-ALL : "mod_dav - Win32 Release" "libhttpd - Win32 Release"\
- "libaprutil - Win32 Release" "libapr - Win32 Release" "$(OUTDIR)\mod_dav_fs.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN"\
- "libhttpd - Win32 ReleaseCLEAN" "mod_dav - Win32 ReleaseCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\dbm.obj"
- -@erase "$(INTDIR)\lock.obj"
- -@erase "$(INTDIR)\mod_dav_fs.idb"
- -@erase "$(INTDIR)\mod_dav_fs.obj"
- -@erase "$(INTDIR)\repos.obj"
- -@erase "$(OUTDIR)\mod_dav_fs.exp"
- -@erase "$(OUTDIR)\mod_dav_fs.lib"
- -@erase "$(OUTDIR)\mod_dav_fs.map"
- -@erase "$(OUTDIR)\mod_dav_fs.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MD /W3 /O2 /I "..\main" /I "..\..\..\srclib\aputil" /I\
- "..\..\..\srclib\sdbm" /I "..\..\..\srclib\expat-lite" /I\
- "..\..\..\srclib\apr\include" /I "../../../srclib/apr-util/include" /I\
- "..\..\..\include" /I "..\..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS"\
- /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_dav_fs" /FD /c
-CPP_OBJS=.\Release/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_dav_fs.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows\
- /dll /incremental:no /pdb:"$(OUTDIR)\mod_dav_fs.pdb"\
- /map:"$(INTDIR)\mod_dav_fs.map" /machine:I386 /out:"$(OUTDIR)\mod_dav_fs.so"\
- /implib:"$(OUTDIR)\mod_dav_fs.lib"\
- /base:@..\..\..\os\win32\BaseAddr.ref,mod_dav_fs
-LINK32_OBJS= \
- "$(INTDIR)\dbm.obj" \
- "$(INTDIR)\lock.obj" \
- "$(INTDIR)\mod_dav_fs.obj" \
- "$(INTDIR)\repos.obj" \
- "..\..\..\Release\libhttpd.lib" \
- "..\..\..\srclib\apr-util\Release\libaprutil.lib" \
- "..\..\..\srclib\apr\Release\libapr.lib" \
- "..\main\Release\mod_dav.lib"
-
-"$(OUTDIR)\mod_dav_fs.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ELSEIF "$(CFG)" == "mod_dav_fs - Win32 Debug"
-
-OUTDIR=.\Debug
-INTDIR=.\Debug
-# Begin Custom Macros
-OutDir=.\Debug
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_dav_fs.so"
-
-!ELSE
-
-ALL : "mod_dav - Win32 Debug" "libhttpd - Win32 Debug"\
- "libaprutil - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\mod_dav_fs.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN"\
- "libhttpd - Win32 DebugCLEAN" "mod_dav - Win32 DebugCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\dbm.obj"
- -@erase "$(INTDIR)\lock.obj"
- -@erase "$(INTDIR)\mod_dav_fs.idb"
- -@erase "$(INTDIR)\mod_dav_fs.obj"
- -@erase "$(INTDIR)\repos.obj"
- -@erase "$(OUTDIR)\mod_dav_fs.exp"
- -@erase "$(OUTDIR)\mod_dav_fs.lib"
- -@erase "$(OUTDIR)\mod_dav_fs.map"
- -@erase "$(OUTDIR)\mod_dav_fs.pdb"
- -@erase "$(OUTDIR)\mod_dav_fs.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\main" /I "..\..\..\srclib\aputil"\
- /I "..\..\..\srclib\sdbm" /I "..\..\..\srclib\expat-lite" /I\
- "..\..\..\srclib\apr\include" /I "../../../srclib/apr-util/include" /I\
- "..\..\..\include" /I "..\..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS"\
- /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_dav_fs" /FD /c
-CPP_OBJS=.\Debug/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_dav_fs.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows\
- /dll /incremental:no /pdb:"$(OUTDIR)\mod_dav_fs.pdb"\
- /map:"$(INTDIR)\mod_dav_fs.map" /debug /machine:I386\
- /out:"$(OUTDIR)\mod_dav_fs.so" /implib:"$(OUTDIR)\mod_dav_fs.lib"\
- /base:@..\..\..\os\win32\BaseAddr.ref,mod_dav_fs
-LINK32_OBJS= \
- "$(INTDIR)\dbm.obj" \
- "$(INTDIR)\lock.obj" \
- "$(INTDIR)\mod_dav_fs.obj" \
- "$(INTDIR)\repos.obj" \
- "..\..\..\Debug\libhttpd.lib" \
- "..\..\..\srclib\apr-util\Debug\libaprutil.lib" \
- "..\..\..\srclib\apr\Debug\libapr.lib" \
- "..\main\Debug\mod_dav.lib"
-
-"$(OUTDIR)\mod_dav_fs.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ENDIF
-
-
-!IF "$(CFG)" == "mod_dav_fs - Win32 Release" || "$(CFG)" ==\
- "mod_dav_fs - Win32 Debug"
-SOURCE=.\dbm.c
-DEP_CPP_DBM_C=\
- "..\..\..\include\ap_config.h"\
- "..\..\..\include\ap_mmn.h"\
- "..\..\..\include\ap_release.h"\
- "..\..\..\include\httpd.h"\
- "..\..\..\include\pcreposix.h"\
- "..\..\..\include\util_uri.h"\
- "..\..\..\include\util_xml.h"\
- "..\..\..\os\win32\os.h"\
- "..\..\..\srclib\apr-util\include\apr_dbm.h"\
- "..\..\..\srclib\apr-util\include\apr_hooks.h"\
- "..\..\..\srclib\apr-util\include\apr_xml.h"\
- "..\..\..\srclib\apr-util\include\apu.h"\
- "..\..\..\srclib\apr-util\include\apu_compat.h"\
- "..\..\..\srclib\apr\include\apr.h"\
- "..\..\..\srclib\apr\include\apr_compat.h"\
- "..\..\..\srclib\apr\include\apr_errno.h"\
- "..\..\..\srclib\apr\include\apr_file_info.h"\
- "..\..\..\srclib\apr\include\apr_file_io.h"\
- "..\..\..\srclib\apr\include\apr_general.h"\
- "..\..\..\srclib\apr\include\apr_hash.h"\
- "..\..\..\srclib\apr\include\apr_network_io.h"\
- "..\..\..\srclib\apr\include\apr_pools.h"\
- "..\..\..\srclib\apr\include\apr_strings.h"\
- "..\..\..\srclib\apr\include\apr_tables.h"\
- "..\..\..\srclib\apr\include\apr_time.h"\
- "..\..\..\srclib\apr\include\apr_user.h"\
- "..\..\..\srclib\apr\include\apr_want.h"\
- "..\main\mod_dav.h"\
- ".\repos.h"\
-
-NODEP_CPP_DBM_C=\
- "..\..\..\include\ap_config_auto.h"\
-
-
-"$(INTDIR)\dbm.obj" : $(SOURCE) $(DEP_CPP_DBM_C) "$(INTDIR)"
-
-
-SOURCE=.\lock.c
-DEP_CPP_LOCK_=\
- "..\..\..\include\ap_config.h"\
- "..\..\..\include\ap_mmn.h"\
- "..\..\..\include\ap_release.h"\
- "..\..\..\include\http_log.h"\
- "..\..\..\include\httpd.h"\
- "..\..\..\include\pcreposix.h"\
- "..\..\..\include\util_uri.h"\
- "..\..\..\include\util_xml.h"\
- "..\..\..\os\win32\os.h"\
- "..\..\..\srclib\apr-util\include\apr_dbm.h"\
- "..\..\..\srclib\apr-util\include\apr_hooks.h"\
- "..\..\..\srclib\apr-util\include\apr_xml.h"\
- "..\..\..\srclib\apr-util\include\apu.h"\
- "..\..\..\srclib\apr-util\include\apu_compat.h"\
- "..\..\..\srclib\apr\include\apr.h"\
- "..\..\..\srclib\apr\include\apr_compat.h"\
- "..\..\..\srclib\apr\include\apr_errno.h"\
- "..\..\..\srclib\apr\include\apr_file_info.h"\
- "..\..\..\srclib\apr\include\apr_file_io.h"\
- "..\..\..\srclib\apr\include\apr_general.h"\
- "..\..\..\srclib\apr\include\apr_hash.h"\
- "..\..\..\srclib\apr\include\apr_network_io.h"\
- "..\..\..\srclib\apr\include\apr_pools.h"\
- "..\..\..\srclib\apr\include\apr_strings.h"\
- "..\..\..\srclib\apr\include\apr_tables.h"\
- "..\..\..\srclib\apr\include\apr_thread_proc.h"\
- "..\..\..\srclib\apr\include\apr_time.h"\
- "..\..\..\srclib\apr\include\apr_user.h"\
- "..\..\..\srclib\apr\include\apr_uuid.h"\
- "..\..\..\srclib\apr\include\apr_want.h"\
- "..\main\mod_dav.h"\
- ".\repos.h"\
-
-NODEP_CPP_LOCK_=\
- "..\..\..\include\ap_config_auto.h"\
-
-
-"$(INTDIR)\lock.obj" : $(SOURCE) $(DEP_CPP_LOCK_) "$(INTDIR)"
-
-
-SOURCE=.\mod_dav_fs.c
-DEP_CPP_MOD_D=\
- "..\..\..\include\ap_config.h"\
- "..\..\..\include\ap_mmn.h"\
- "..\..\..\include\ap_release.h"\
- "..\..\..\include\http_config.h"\
- "..\..\..\include\httpd.h"\
- "..\..\..\include\pcreposix.h"\
- "..\..\..\include\util_cfgtree.h"\
- "..\..\..\include\util_uri.h"\
- "..\..\..\include\util_xml.h"\
- "..\..\..\os\win32\os.h"\
- "..\..\..\srclib\apr-util\include\apr_dbm.h"\
- "..\..\..\srclib\apr-util\include\apr_hooks.h"\
- "..\..\..\srclib\apr-util\include\apr_xml.h"\
- "..\..\..\srclib\apr-util\include\apu.h"\
- "..\..\..\srclib\apr-util\include\apu_compat.h"\
- "..\..\..\srclib\apr\include\apr.h"\
- "..\..\..\srclib\apr\include\apr_compat.h"\
- "..\..\..\srclib\apr\include\apr_errno.h"\
- "..\..\..\srclib\apr\include\apr_file_info.h"\
- "..\..\..\srclib\apr\include\apr_file_io.h"\
- "..\..\..\srclib\apr\include\apr_general.h"\
- "..\..\..\srclib\apr\include\apr_hash.h"\
- "..\..\..\srclib\apr\include\apr_network_io.h"\
- "..\..\..\srclib\apr\include\apr_pools.h"\
- "..\..\..\srclib\apr\include\apr_tables.h"\
- "..\..\..\srclib\apr\include\apr_time.h"\
- "..\..\..\srclib\apr\include\apr_user.h"\
- "..\..\..\srclib\apr\include\apr_want.h"\
- "..\main\mod_dav.h"\
- ".\repos.h"\
-
-NODEP_CPP_MOD_D=\
- "..\..\..\include\ap_config_auto.h"\
-
-
-"$(INTDIR)\mod_dav_fs.obj" : $(SOURCE) $(DEP_CPP_MOD_D) "$(INTDIR)"
-
-
-SOURCE=.\repos.c
-DEP_CPP_REPOS=\
- "..\..\..\include\ap_config.h"\
- "..\..\..\include\ap_mmn.h"\
- "..\..\..\include\ap_release.h"\
- "..\..\..\include\http_log.h"\
- "..\..\..\include\http_protocol.h"\
- "..\..\..\include\http_request.h"\
- "..\..\..\include\httpd.h"\
- "..\..\..\include\pcreposix.h"\
- "..\..\..\include\util_filter.h"\
- "..\..\..\include\util_uri.h"\
- "..\..\..\include\util_xml.h"\
- "..\..\..\os\win32\os.h"\
- "..\..\..\srclib\apr-util\include\apr_buckets.h"\
- "..\..\..\srclib\apr-util\include\apr_dbm.h"\
- "..\..\..\srclib\apr-util\include\apr_hooks.h"\
- "..\..\..\srclib\apr-util\include\apr_ring.h"\
- "..\..\..\srclib\apr-util\include\apr_xml.h"\
- "..\..\..\srclib\apr-util\include\apu.h"\
- "..\..\..\srclib\apr-util\include\apu_compat.h"\
- "..\..\..\srclib\apr\include\apr.h"\
- "..\..\..\srclib\apr\include\apr_compat.h"\
- "..\..\..\srclib\apr\include\apr_dso.h"\
- "..\..\..\srclib\apr\include\apr_errno.h"\
- "..\..\..\srclib\apr\include\apr_file_info.h"\
- "..\..\..\srclib\apr\include\apr_file_io.h"\
- "..\..\..\srclib\apr\include\apr_general.h"\
- "..\..\..\srclib\apr\include\apr_hash.h"\
- "..\..\..\srclib\apr\include\apr_lock.h"\
- "..\..\..\srclib\apr\include\apr_mmap.h"\
- "..\..\..\srclib\apr\include\apr_network_io.h"\
- "..\..\..\srclib\apr\include\apr_pools.h"\
- "..\..\..\srclib\apr\include\apr_portable.h"\
- "..\..\..\srclib\apr\include\apr_strings.h"\
- "..\..\..\srclib\apr\include\apr_tables.h"\
- "..\..\..\srclib\apr\include\apr_thread_proc.h"\
- "..\..\..\srclib\apr\include\apr_time.h"\
- "..\..\..\srclib\apr\include\apr_user.h"\
- "..\..\..\srclib\apr\include\apr_want.h"\
- "..\main\mod_dav.h"\
- ".\repos.h"\
-
-NODEP_CPP_REPOS=\
- "..\..\..\include\ap_config_auto.h"\
-
-
-"$(INTDIR)\repos.obj" : $(SOURCE) $(DEP_CPP_REPOS) "$(INTDIR)"
-
-
-!IF "$(CFG)" == "mod_dav_fs - Win32 Release"
-
-"libapr - Win32 Release" :
- cd "..\../..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F .\libapr.mak CFG="libapr - Win32 Release"
- cd "..\..\modules\dav\fs"
-
-"libapr - Win32 ReleaseCLEAN" :
- cd "..\../..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libapr.mak CFG="libapr - Win32 Release"\
- RECURSE=1
- cd "..\..\modules\dav\fs"
-
-!ELSEIF "$(CFG)" == "mod_dav_fs - Win32 Debug"
-
-"libapr - Win32 Debug" :
- cd "..\../..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F .\libapr.mak CFG="libapr - Win32 Debug"
- cd "..\..\modules\dav\fs"
-
-"libapr - Win32 DebugCLEAN" :
- cd "..\../..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libapr.mak CFG="libapr - Win32 Debug"\
- RECURSE=1
- cd "..\..\modules\dav\fs"
-
-!ENDIF
-
-!IF "$(CFG)" == "mod_dav_fs - Win32 Release"
-
-"libaprutil - Win32 Release" :
- cd "..\../..\srclib\apr-util"
- $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release"\
-
- cd "..\..\modules\dav\fs"
-
-"libaprutil - Win32 ReleaseCLEAN" :
- cd "..\../..\srclib\apr-util"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F ".\libaprutil.mak"\
- CFG="libaprutil - Win32 Release" RECURSE=1
- cd "..\..\modules\dav\fs"
-
-!ELSEIF "$(CFG)" == "mod_dav_fs - Win32 Debug"
-
-"libaprutil - Win32 Debug" :
- cd "..\../..\srclib\apr-util"
- $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug"
- cd "..\..\modules\dav\fs"
-
-"libaprutil - Win32 DebugCLEAN" :
- cd "..\../..\srclib\apr-util"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F ".\libaprutil.mak"\
- CFG="libaprutil - Win32 Debug" RECURSE=1
- cd "..\..\modules\dav\fs"
-
-!ENDIF
-
-!IF "$(CFG)" == "mod_dav_fs - Win32 Release"
-
-"libhttpd - Win32 Release" :
- cd "..\../.."
- $(MAKE) /$(MAKEFLAGS) /F .\libhttpd.mak CFG="libhttpd - Win32 Release"
- cd ".\modules\dav\fs"
-
-"libhttpd - Win32 ReleaseCLEAN" :
- cd "..\../.."
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libhttpd.mak CFG="libhttpd - Win32 Release"\
- RECURSE=1
- cd ".\modules\dav\fs"
-
-!ELSEIF "$(CFG)" == "mod_dav_fs - Win32 Debug"
-
-"libhttpd - Win32 Debug" :
- cd "..\../.."
- $(MAKE) /$(MAKEFLAGS) /F .\libhttpd.mak CFG="libhttpd - Win32 Debug"
- cd ".\modules\dav\fs"
-
-"libhttpd - Win32 DebugCLEAN" :
- cd "..\../.."
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libhttpd.mak CFG="libhttpd - Win32 Debug"\
- RECURSE=1
- cd ".\modules\dav\fs"
-
-!ENDIF
-
-!IF "$(CFG)" == "mod_dav_fs - Win32 Release"
-
-"mod_dav - Win32 Release" :
- cd "..\../..\modules\dav\main"
- $(MAKE) /$(MAKEFLAGS) /F .\mod_dav.mak CFG="mod_dav - Win32 Release"
- cd "..\fs"
-
-"mod_dav - Win32 ReleaseCLEAN" :
- cd "..\../..\modules\dav\main"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\mod_dav.mak CFG="mod_dav - Win32 Release"\
- RECURSE=1
- cd "..\fs"
-
-!ELSEIF "$(CFG)" == "mod_dav_fs - Win32 Debug"
-
-"mod_dav - Win32 Debug" :
- cd "..\../..\modules\dav\main"
- $(MAKE) /$(MAKEFLAGS) /F .\mod_dav.mak CFG="mod_dav - Win32 Debug"
- cd "..\fs"
-
-"mod_dav - Win32 DebugCLEAN" :
- cd "..\../..\modules\dav\main"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\mod_dav.mak CFG="mod_dav - Win32 Debug"\
- RECURSE=1
- cd "..\fs"
-
-!ENDIF
-
-
-!ENDIF
-
diff --git a/modules/dav/fs/repos.c b/modules/dav/fs/repos.c
deleted file mode 100644
index e8064d1cc7..0000000000
--- a/modules/dav/fs/repos.c
+++ /dev/null
@@ -1,2077 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-/*
-** DAV filesystem-based repository provider
-*/
-
-#include "apr.h"
-#include "apr_file_io.h"
-#include "apr_strings.h"
-
-#if APR_HAVE_STDIO_H
-#include <stdio.h> /* for sprintf() */
-#endif
-
-#include "httpd.h"
-#include "http_log.h"
-#include "http_protocol.h" /* for ap_set_* (in dav_fs_set_headers) */
-#include "http_request.h" /* for ap_update_mtime() */
-
-#include "mod_dav.h"
-#include "repos.h"
-
-
-/* to assist in debugging mod_dav's GET handling */
-#define DEBUG_GET_HANDLER 0
-#define DEBUG_PATHNAME_STYLE 0
-
-#define DAV_FS_COPY_BLOCKSIZE 16384 /* copy 16k at a time */
-
-/* context needed to identify a resource */
-struct dav_resource_private {
- apr_pool_t *pool; /* memory storage pool associated with request */
- const char *pathname; /* full pathname to resource */
- apr_finfo_t finfo; /* filesystem info */
-};
-
-/* private context for doing a filesystem walk */
-typedef struct {
- /* the input walk parameters */
- const dav_walk_params *params;
-
- /* reused as we walk */
- dav_walk_resource wres;
-
- dav_resource res1;
- dav_resource_private info1;
- dav_buffer path1;
- dav_buffer uri_buf;
-
- /* MOVE/COPY need a secondary path */
- dav_resource res2;
- dav_resource_private info2;
- dav_buffer path2;
-
- dav_buffer locknull_buf;
-
-} dav_fs_walker_context;
-
-typedef struct {
- int is_move; /* is this a MOVE? */
- dav_buffer work_buf; /* handy buffer for copymove_file() */
-
- /* CALLBACK: this is a secondary resource managed specially for us */
- const dav_resource *res_dst;
-
- /* copied from dav_walk_params (they are invariant across the walk) */
- const dav_resource *root;
- apr_pool_t *pool;
-
-} dav_fs_copymove_walk_ctx;
-
-/* an internal WALKTYPE to walk hidden files (the .DAV directory) */
-#define DAV_WALKTYPE_HIDDEN 0x4000
-
-/* an internal WALKTYPE to call collections (again) after their contents */
-#define DAV_WALKTYPE_POSTFIX 0x8000
-
-#define DAV_CALLTYPE_POSTFIX 1000 /* a private call type */
-
-
-/* pull this in from the other source file */
-extern const dav_hooks_locks dav_hooks_locks_fs;
-
-/* forward-declare the hook structures */
-static const dav_hooks_repository dav_hooks_repository_fs;
-static const dav_hooks_liveprop dav_hooks_liveprop_fs;
-
-/*
-** The namespace URIs that we use. This list and the enumeration must
-** stay in sync.
-*/
-static const char * const dav_fs_namespace_uris[] =
-{
- "DAV:",
- "http://apache.org/dav/props/",
-
- NULL /* sentinel */
-};
-enum {
- DAV_FS_URI_DAV, /* the DAV: namespace URI */
- DAV_FS_URI_MYPROPS /* the namespace URI for our custom props */
-};
-
-/*
-** The single property that we define (in the DAV_FS_URI_MYPROPS namespace)
-*/
-#define DAV_PROPID_FS_executable 1
-
-static const dav_liveprop_spec dav_fs_props[] =
-{
- {
- DAV_FS_URI_DAV,
- "creationdate",
- DAV_PROPID_creationdate,
- 0
- },
- {
- DAV_FS_URI_DAV,
- "getcontentlength",
- DAV_PROPID_getcontentlength,
- 0
- },
- {
- DAV_FS_URI_DAV,
- "getetag",
- DAV_PROPID_getetag,
- 0
- },
- {
- DAV_FS_URI_DAV,
- "getlastmodified",
- DAV_PROPID_getlastmodified,
- 0
- },
-
- {
- DAV_FS_URI_MYPROPS,
- "executable",
- DAV_PROPID_FS_executable,
- 0 /* handled special in dav_fs_is_writable */
- },
-
- { 0 } /* sentinel */
-};
-
-static const dav_liveprop_group dav_fs_liveprop_group =
-{
- dav_fs_props,
- dav_fs_namespace_uris,
- &dav_hooks_liveprop_fs
-};
-
-
-/* define the dav_stream structure for our use */
-struct dav_stream {
- apr_pool_t *p;
- apr_file_t *f;
- const char *pathname; /* we may need to remove it at close time */
-};
-
-/* forward declaration for internal treewalkers */
-static dav_error * dav_fs_walk(const dav_walk_params *params, int depth,
- dav_response **response);
-static dav_error * dav_fs_internal_walk(const dav_walk_params *params,
- int depth, int is_move,
- const dav_resource *root_dst,
- dav_response **response);
-
-/* --------------------------------------------------------------------
-**
-** PRIVATE REPOSITORY FUNCTIONS
-*/
-apr_pool_t *dav_fs_pool(const dav_resource *resource)
-{
- return resource->info->pool;
-}
-
-const char *dav_fs_pathname(const dav_resource *resource)
-{
- return resource->info->pathname;
-}
-
-void dav_fs_dir_file_name(
- const dav_resource *resource,
- const char **dirpath_p,
- const char **fname_p)
-{
- dav_resource_private *ctx = resource->info;
-
- if (resource->collection) {
- *dirpath_p = ctx->pathname;
- if (fname_p != NULL)
- *fname_p = NULL;
- }
- else {
- char *dirpath = ap_make_dirstr_parent(ctx->pool, ctx->pathname);
- apr_size_t dirlen = strlen(dirpath);
-
- if (fname_p != NULL)
- *fname_p = ctx->pathname + dirlen;
- *dirpath_p = dirpath;
-
- /* remove trailing slash from dirpath, unless it's the root dir */
- /* ### Win32 check */
- if (dirlen > 1 && dirpath[dirlen - 1] == '/') {
- dirpath[dirlen - 1] = '\0';
- }
- }
-}
-
-/* Note: picked up from ap_gm_timestr_822() */
-/* NOTE: buf must be at least DAV_TIMEBUF_SIZE chars in size */
-static void dav_format_time(int style, apr_time_t sec, char *buf)
-{
- apr_exploded_time_t tms;
-
- /* ### what to do if fails? */
- (void) apr_explode_gmt(&tms, sec);
-
- if (style == DAV_STYLE_ISO8601) {
- /* ### should we use "-00:00" instead of "Z" ?? */
-
- /* 20 chars plus null term */
- sprintf(buf, "%.4d-%.2d-%.2dT%.2d:%.2d:%.2dZ",
- tms.tm_year + 1900, tms.tm_mon + 1, tms.tm_mday,
- tms.tm_hour, tms.tm_min, tms.tm_sec);
- return;
- }
-
- /* RFC 822 date format; as strftime '%a, %d %b %Y %T GMT' */
-
- /* 29 chars plus null term */
- sprintf(buf,
- "%s, %.2d %s %d %.2d:%.2d:%.2d GMT",
- apr_day_snames[tms.tm_wday],
- tms.tm_mday, apr_month_snames[tms.tm_mon],
- tms.tm_year + 1900,
- tms.tm_hour, tms.tm_min, tms.tm_sec);
-}
-
-static dav_error * dav_fs_copymove_file(
- int is_move,
- apr_pool_t * p,
- const char *src,
- const char *dst,
- dav_buffer *pbuf)
-{
- dav_buffer work_buf = { 0 };
- apr_file_t *inf = NULL;
- apr_file_t *outf = NULL;
-
- if (pbuf == NULL)
- pbuf = &work_buf;
-
- dav_set_bufsize(p, pbuf, DAV_FS_COPY_BLOCKSIZE);
-
- if ((apr_file_open(&inf, src, APR_READ | APR_BINARY, APR_OS_DEFAULT, p))
- != APR_SUCCESS) {
- /* ### use something besides 500? */
- return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
- "Could not open file for reading");
- }
-
- /* ### do we need to deal with the umask? */
- if ((apr_file_open(&outf, dst, APR_WRITE | APR_CREATE | APR_TRUNCATE | APR_BINARY,
- APR_OS_DEFAULT, p)) != APR_SUCCESS) {
- apr_file_close(inf);
-
- /* ### use something besides 500? */
- return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
- "Could not open file for writing");
- }
-
- while (1) {
- apr_size_t len = DAV_FS_COPY_BLOCKSIZE;
- apr_status_t status;
-
- status = apr_file_read(inf, pbuf->buf, &len);
- if (status != APR_SUCCESS && status != APR_EOF) {
- apr_file_close(inf);
- apr_file_close(outf);
-
- if (apr_file_remove(dst, p) != APR_SUCCESS) {
- /* ### ACK! Inconsistent state... */
-
- /* ### use something besides 500? */
- return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
- "Could not delete output after read "
- "failure. Server is now in an "
- "inconsistent state.");
- }
-
- /* ### use something besides 500? */
- return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
- "Could not read input file");
- }
-
- /* write any bytes that were read (applies to APR_EOF, too) */
- if (apr_file_write_full(outf, pbuf->buf, len, NULL) != APR_SUCCESS) {
- int save_errno = errno;
-
- apr_file_close(inf);
- apr_file_close(outf);
-
- if (apr_file_remove(dst, p) != APR_SUCCESS) {
- /* ### ACK! Inconsistent state... */
-
- /* ### use something besides 500? */
- return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
- "Could not delete output after write "
- "failure. Server is now in an "
- "inconsistent state.");
- }
-
- if (save_errno == ENOSPC) {
- return dav_new_error(p, HTTP_INSUFFICIENT_STORAGE, 0,
- "There is not enough storage to write to "
- "this resource.");
- }
-
- /* ### use something besides 500? */
- return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
- "Could not write output file");
- }
-
- if (status == APR_EOF)
- break;
- }
-
- apr_file_close(inf);
- apr_file_close(outf);
-
- if (is_move && apr_file_remove(src, p) != APR_SUCCESS) {
- dav_error *err;
- int save_errno = errno; /* save the errno that got us here */
-
- if (apr_file_remove(dst, p) != APR_SUCCESS) {
- /* ### ACK. this creates an inconsistency. do more!? */
-
- /* ### use something besides 500? */
- /* Note that we use the latest errno */
- return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
- "Could not remove source or destination "
- "file. Server is now in an inconsistent "
- "state.");
- }
-
- /* ### use something besides 500? */
- err = dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
- "Could not remove source file after move. "
- "Destination was removed to ensure consistency.");
- err->save_errno = save_errno;
- return err;
- }
-
- return NULL;
-}
-
-/* copy/move a file from within a state dir to another state dir */
-/* ### need more buffers to replace the pool argument */
-static dav_error * dav_fs_copymove_state(
- int is_move,
- apr_pool_t * p,
- const char *src_dir, const char *src_file,
- const char *dst_dir, const char *dst_file,
- dav_buffer *pbuf)
-{
- apr_finfo_t src_finfo; /* finfo for source file */
- apr_finfo_t dst_state_finfo; /* finfo for STATE directory */
- apr_status_t rv;
- const char *src;
- const char *dst;
-
- /* build the propset pathname for the source file */
- src = apr_pstrcat(p, src_dir, "/" DAV_FS_STATE_DIR "/", src_file, NULL);
-
- /* the source file doesn't exist */
- if (apr_stat(&src_finfo, src, APR_FINFO_NORM, p) != APR_SUCCESS) {
- return NULL;
- }
-
- /* build the pathname for the destination state dir */
- dst = apr_pstrcat(p, dst_dir, "/" DAV_FS_STATE_DIR, NULL);
-
- /* ### do we need to deal with the umask? */
-
- /* ensure that it exists */
- rv = apr_dir_make(dst, APR_OS_DEFAULT, p);
- if (rv != APR_SUCCESS) {
- if (!APR_STATUS_IS_EEXIST(rv)) {
- /* ### use something besides 500? */
- return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
- "Could not create internal state directory");
- }
- }
-
- /* get info about the state directory */
- if (apr_stat(&dst_state_finfo, dst, APR_FINFO_NORM, p) != APR_SUCCESS) {
- /* Ack! Where'd it go? */
- /* ### use something besides 500? */
- return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
- "State directory disappeared");
- }
-
- /* The mkdir() may have failed because a *file* exists there already */
- if (dst_state_finfo.filetype != APR_DIR) {
- /* ### try to recover by deleting this file? (and mkdir again) */
- /* ### use something besides 500? */
- return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
- "State directory is actually a file");
- }
-
- /* append the target file to the state directory pathname */
- dst = apr_pstrcat(p, dst, "/", dst_file, NULL);
-
- /* copy/move the file now */
- if (is_move && src_finfo.device == dst_state_finfo.device) {
- /* simple rename is possible since it is on the same device */
- if (apr_file_rename(src, dst, p) != APR_SUCCESS) {
- /* ### use something besides 500? */
- return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
- "Could not move state file.");
- }
- }
- else
- {
- /* gotta copy (and delete) */
- return dav_fs_copymove_file(is_move, p, src, dst, pbuf);
- }
-
- return NULL;
-}
-
-static dav_error *dav_fs_copymoveset(int is_move, apr_pool_t *p,
- const dav_resource *src,
- const dav_resource *dst,
- dav_buffer *pbuf)
-{
- const char *src_dir;
- const char *src_file;
- const char *src_state1;
- const char *src_state2;
- const char *dst_dir;
- const char *dst_file;
- const char *dst_state1;
- const char *dst_state2;
- dav_error *err;
-
- /* Get directory and filename for resources */
- dav_fs_dir_file_name(src, &src_dir, &src_file);
- dav_fs_dir_file_name(dst, &dst_dir, &dst_file);
-
- /* Get the corresponding state files for each resource */
- dav_dbm_get_statefiles(p, src_file, &src_state1, &src_state2);
- dav_dbm_get_statefiles(p, dst_file, &dst_state1, &dst_state2);
-#if DAV_DEBUG
- if ((src_state2 != NULL && dst_state2 == NULL) ||
- (src_state2 == NULL && dst_state2 != NULL)) {
- return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
- "DESIGN ERROR: dav_dbm_get_statefiles() "
- "returned inconsistent results.");
- }
-#endif
-
- err = dav_fs_copymove_state(is_move, p,
- src_dir, src_state1,
- dst_dir, dst_state1,
- pbuf);
-
- if (err == NULL && src_state2 != NULL) {
- err = dav_fs_copymove_state(is_move, p,
- src_dir, src_state2,
- dst_dir, dst_state2,
- pbuf);
-
- if (err != NULL) {
- /* ### CRAP. inconsistency. */
- /* ### should perform some cleanup at the target if we still
- ### have the original files */
-
- /* Change the error to reflect the bad server state. */
- err->status = HTTP_INTERNAL_SERVER_ERROR;
- err->desc =
- "Could not fully copy/move the properties. "
- "The server is now in an inconsistent state.";
- }
- }
-
- return err;
-}
-
-static dav_error *dav_fs_deleteset(apr_pool_t *p, const dav_resource *resource)
-{
- const char *dirpath;
- const char *fname;
- const char *state1;
- const char *state2;
- const char *pathname;
- apr_status_t status;
-
- /* Get directory, filename, and state-file names for the resource */
- dav_fs_dir_file_name(resource, &dirpath, &fname);
- dav_dbm_get_statefiles(p, fname, &state1, &state2);
-
- /* build the propset pathname for the file */
- pathname = apr_pstrcat(p,
- dirpath,
- "/" DAV_FS_STATE_DIR "/",
- state1,
- NULL);
-
- /* note: we may get ENOENT if the state dir is not present */
- if ((status = apr_file_remove(pathname, p)) != APR_SUCCESS
- && !APR_STATUS_IS_ENOENT(status)) {
- return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
- "Could not remove properties.");
- }
-
- if (state2 != NULL) {
- /* build the propset pathname for the file */
- pathname = apr_pstrcat(p,
- dirpath,
- "/" DAV_FS_STATE_DIR "/",
- state2,
- NULL);
-
- if ((status = apr_file_remove(pathname, p)) != APR_SUCCESS
- && !APR_STATUS_IS_ENOENT(status)) {
- /* ### CRAP. only removed half. */
- return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
- "Could not fully remove properties. "
- "The server is now in an inconsistent "
- "state.");
- }
- }
-
- return NULL;
-}
-
-/* --------------------------------------------------------------------
-**
-** REPOSITORY HOOK FUNCTIONS
-*/
-
-static dav_error * dav_fs_get_resource(
- request_rec *r,
- const char *root_dir,
- const char *label,
- int use_checked_in,
- dav_resource **result_resource)
-{
- dav_resource_private *ctx;
- dav_resource *resource;
- char *s;
- char *filename;
- apr_size_t len;
-
- /* ### optimize this into a single allocation! */
-
- /* Create private resource context descriptor */
- ctx = apr_pcalloc(r->pool, sizeof(*ctx));
- ctx->finfo = r->finfo;
-
- /* ### this should go away */
- ctx->pool = r->pool;
-
- /* Preserve case on OSes which fold canonical filenames */
-#if 0
- /* ### not available in Apache 2.0 yet */
- filename = r->case_preserved_filename;
-#else
- filename = r->filename;
-#endif
-
- /*
- ** If there is anything in the path_info, then this indicates that the
- ** entire path was not used to specify the file/dir. We want to append
- ** it onto the filename so that we get a "valid" pathname for null
- ** resources.
- */
- s = apr_pstrcat(r->pool, filename, r->path_info, NULL);
-
- /* make sure the pathname does not have a trailing "/" */
- len = strlen(s);
- if (len > 1 && s[len - 1] == '/') {
- s[len - 1] = '\0';
- }
- ctx->pathname = s;
-
- /* Create resource descriptor */
- resource = apr_pcalloc(r->pool, sizeof(*resource));
- resource->type = DAV_RESOURCE_TYPE_REGULAR;
- resource->info = ctx;
- resource->hooks = &dav_hooks_repository_fs;
- resource->pool = r->pool;
-
- /* make sure the URI does not have a trailing "/" */
- len = strlen(r->uri);
- if (len > 1 && r->uri[len - 1] == '/') {
- s = apr_pstrdup(r->pool, r->uri);
- s[len - 1] = '\0';
- resource->uri = s;
- }
- else {
- resource->uri = r->uri;
- }
-
- if (r->finfo.filetype != 0) {
- resource->exists = 1;
- resource->collection = r->finfo.filetype == APR_DIR;
-
- /* unused info in the URL will indicate a null resource */
-
- if (r->path_info != NULL && *r->path_info != '\0') {
- if (resource->collection) {
- /* only a trailing "/" is allowed */
- if (*r->path_info != '/' || r->path_info[1] != '\0') {
-
- /*
- ** This URL/filename represents a locknull resource or
- ** possibly a destination of a MOVE/COPY
- */
- resource->exists = 0;
- resource->collection = 0;
- }
- }
- else
- {
- /*
- ** The base of the path refers to a file -- nothing should
- ** be in path_info. The resource is simply an error: it
- ** can't be a null or a locknull resource.
- */
- return dav_new_error(r->pool, HTTP_BAD_REQUEST, 0,
- "The URL contains extraneous path "
- "components. The resource could not "
- "be identified.");
- }
-
- /* retain proper integrity across the structures */
- if (!resource->exists) {
- ctx->finfo.filetype = 0;
- }
- }
- }
-
- *result_resource = resource;
- return NULL;
-}
-
-static dav_error * dav_fs_get_parent_resource(const dav_resource *resource,
- dav_resource **result_parent)
-{
- dav_resource_private *ctx = resource->info;
- dav_resource_private *parent_ctx;
- dav_resource *parent_resource;
- char *dirpath;
-
- /* If given resource is root, then there is no parent */
- if (strcmp(resource->uri, "/") == 0 ||
-#ifdef WIN32
- (strlen(ctx->pathname) == 3 && ctx->pathname[1] == ':' && ctx->pathname[2] == '/')
-#else
- strcmp(ctx->pathname, "/") == 0
-#endif
- ) {
- *result_parent = NULL;
- return NULL;
- }
-
- /* ### optimize this into a single allocation! */
-
- /* Create private resource context descriptor */
- parent_ctx = apr_pcalloc(ctx->pool, sizeof(*parent_ctx));
-
- /* ### this should go away */
- parent_ctx->pool = ctx->pool;
-
- dirpath = ap_make_dirstr_parent(ctx->pool, ctx->pathname);
- if (strlen(dirpath) > 1 && dirpath[strlen(dirpath) - 1] == '/')
- dirpath[strlen(dirpath) - 1] = '\0';
- parent_ctx->pathname = dirpath;
-
- parent_resource = apr_pcalloc(ctx->pool, sizeof(*parent_resource));
- parent_resource->info = parent_ctx;
- parent_resource->collection = 1;
- parent_resource->hooks = &dav_hooks_repository_fs;
- parent_resource->pool = resource->pool;
-
- if (resource->uri != NULL) {
- char *uri = ap_make_dirstr_parent(ctx->pool, resource->uri);
- if (strlen(uri) > 1 && uri[strlen(uri) - 1] == '/')
- uri[strlen(uri) - 1] = '\0';
- parent_resource->uri = uri;
- }
-
- if (apr_stat(&parent_ctx->finfo, parent_ctx->pathname,
- APR_FINFO_NORM, ctx->pool) == APR_SUCCESS) {
- parent_resource->exists = 1;
- }
-
- *result_parent = parent_resource;
- return NULL;
-}
-
-static int dav_fs_is_same_resource(
- const dav_resource *res1,
- const dav_resource *res2)
-{
- dav_resource_private *ctx1 = res1->info;
- dav_resource_private *ctx2 = res2->info;
-
- if (res1->hooks != res2->hooks)
- return 0;
-
-#ifdef WIN32
- return stricmp(ctx1->pathname, ctx2->pathname) == 0;
-#else
- if (ctx1->finfo.filetype != 0)
- return ctx1->finfo.inode == ctx2->finfo.inode;
- else
- return strcmp(ctx1->pathname, ctx2->pathname) == 0;
-#endif
-}
-
-static int dav_fs_is_parent_resource(
- const dav_resource *res1,
- const dav_resource *res2)
-{
- dav_resource_private *ctx1 = res1->info;
- dav_resource_private *ctx2 = res2->info;
- apr_size_t len1 = strlen(ctx1->pathname);
- apr_size_t len2;
-
- if (res1->hooks != res2->hooks)
- return 0;
-
- /* it is safe to use ctx2 now */
- len2 = strlen(ctx2->pathname);
-
- return (len2 > len1
- && memcmp(ctx1->pathname, ctx2->pathname, len1) == 0
- && ctx2->pathname[len1] == '/');
-}
-
-static dav_error * dav_fs_open_stream(const dav_resource *resource,
- dav_stream_mode mode,
- dav_stream **stream)
-{
- apr_pool_t *p = resource->info->pool;
- dav_stream *ds = apr_pcalloc(p, sizeof(*ds));
- apr_int32_t flags;
-
- switch (mode) {
- case DAV_MODE_READ:
- case DAV_MODE_READ_SEEKABLE:
- default:
- flags = APR_READ | APR_BINARY;
- break;
-
- case DAV_MODE_WRITE_TRUNC:
- flags = APR_WRITE | APR_CREATE | APR_TRUNCATE | APR_BINARY;
- break;
- case DAV_MODE_WRITE_SEEKABLE:
- flags = APR_WRITE | APR_CREATE | APR_BINARY;
- break;
- }
-
- ds->p = p;
- ds->pathname = resource->info->pathname;
- if (apr_file_open(&ds->f, ds->pathname, flags, APR_OS_DEFAULT,
- ds->p) != APR_SUCCESS) {
- /* ### use something besides 500? */
- return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
- "An error occurred while opening a resource.");
- }
-
- /* (APR registers cleanups for the fd with the pool) */
-
- *stream = ds;
- return NULL;
-}
-
-static dav_error * dav_fs_close_stream(dav_stream *stream, int commit)
-{
- apr_file_close(stream->f);
-
- if (!commit) {
- if (apr_file_remove(stream->pathname, stream->p) != APR_SUCCESS) {
- /* ### use a better description? */
- return dav_new_error(stream->p, HTTP_INTERNAL_SERVER_ERROR, 0,
- "There was a problem removing (rolling "
- "back) the resource "
- "when it was being closed.");
- }
- }
-
- return NULL;
-}
-
-static dav_error * dav_fs_read_stream(dav_stream *stream,
- void *buf, apr_size_t *bufsize)
-{
- if (apr_file_read(stream->f, buf, bufsize) != APR_SUCCESS) {
- /* ### use something besides 500? */
- return dav_new_error(stream->p, HTTP_INTERNAL_SERVER_ERROR, 0,
- "An error occurred while reading from a "
- "resource.");
- }
- return NULL;
-}
-
-static dav_error * dav_fs_write_stream(dav_stream *stream,
- const void *buf, apr_size_t bufsize)
-{
- apr_status_t status;
-
- status = apr_file_write_full(stream->f, buf, bufsize, NULL);
- if (APR_STATUS_IS_ENOSPC(status)) {
- return dav_new_error(stream->p, HTTP_INSUFFICIENT_STORAGE, 0,
- "There is not enough storage to write to "
- "this resource.");
- }
- else if (status != APR_SUCCESS) {
- /* ### use something besides 500? */
- return dav_new_error(stream->p, HTTP_INTERNAL_SERVER_ERROR, 0,
- "An error occurred while writing to a "
- "resource.");
- }
- return NULL;
-}
-
-static dav_error * dav_fs_seek_stream(dav_stream *stream, apr_off_t abs_pos)
-{
- if (apr_file_seek(stream->f, APR_SET, &abs_pos) != APR_SUCCESS) {
- /* ### should check whether apr_file_seek set abs_pos was set to the
- * correct position? */
- /* ### use something besides 500? */
- return dav_new_error(stream->p, HTTP_INTERNAL_SERVER_ERROR, 0,
- "Could not seek to specified position in the "
- "resource.");
- }
- return NULL;
-}
-
-static dav_error * dav_fs_set_headers(request_rec *r,
- const dav_resource *resource)
-{
- /* ### this function isn't really used since we have a get_pathname */
-#if DEBUG_GET_HANDLER
- if (!resource->exists)
- return NULL;
-
- /* make sure the proper mtime is in the request record */
- ap_update_mtime(r, resource->info->finfo.mtime);
-
- /* ### note that these use r->filename rather than <resource> */
- ap_set_last_modified(r);
- ap_set_etag(r);
-
- /* we accept byte-ranges */
- apr_table_setn(r->headers_out, "Accept-Ranges", "bytes");
-
- /* set up the Content-Length header */
- ap_set_content_length(r, resource->info->finfo.size);
-
- /* ### how to set the content type? */
- /* ### until this is resolved, the Content-Type header is busted */
-
-#endif
-
- return NULL;
-}
-
-#if DEBUG_PATHNAME_STYLE
-static const char * dav_fs_get_pathname(
- const dav_resource *resource,
- void **free_handle_p)
-{
- return resource->info->pathname;
-}
-#endif
-
-static void dav_fs_free_file(void *free_handle)
-{
- /* nothing to free ... */
-}
-
-static dav_error * dav_fs_create_collection(dav_resource *resource)
-{
- dav_resource_private *ctx = resource->info;
- apr_status_t status;
-
- status = apr_dir_make(ctx->pathname, APR_OS_DEFAULT, ctx->pool);
- if (status == ENOSPC) {
- return dav_new_error(ctx->pool, HTTP_INSUFFICIENT_STORAGE, 0,
- "There is not enough storage to create "
- "this collection.");
- }
- else if (status != APR_SUCCESS) {
- /* ### refine this error message? */
- return dav_new_error(ctx->pool, HTTP_FORBIDDEN, 0,
- "Unable to create collection.");
- }
-
- /* update resource state to show it exists as a collection */
- resource->exists = 1;
- resource->collection = 1;
-
- return NULL;
-}
-
-static dav_error * dav_fs_copymove_walker(dav_walk_resource *wres,
- int calltype)
-{
- dav_fs_copymove_walk_ctx *ctx = wres->walk_ctx;
- dav_resource_private *srcinfo = wres->resource->info;
- dav_resource_private *dstinfo = ctx->res_dst->info;
- dav_error *err = NULL;
-
- if (wres->resource->collection) {
- if (calltype == DAV_CALLTYPE_POSTFIX) {
- /* Postfix call for MOVE. delete the source dir.
- * Note: when copying, we do not enable the postfix-traversal.
- */
- /* ### we are ignoring any error here; what should we do? */
- (void) apr_dir_remove(srcinfo->pathname, ctx->pool);
- }
- else {
- /* copy/move of a collection. Create the new, target collection */
- if (apr_dir_make(dstinfo->pathname, APR_OS_DEFAULT,
- ctx->pool) != APR_SUCCESS) {
- /* ### assume it was a permissions problem */
- /* ### need a description here */
- err = dav_new_error(ctx->pool, HTTP_FORBIDDEN, 0, NULL);
- }
- }
- }
- else {
- err = dav_fs_copymove_file(ctx->is_move, ctx->pool,
- srcinfo->pathname, dstinfo->pathname,
- &ctx->work_buf);
- /* ### push a higher-level description? */
- }
-
- /*
- ** If we have a "not so bad" error, then it might need to go into a
- ** multistatus response.
- **
- ** For a MOVE, it will always go into the multistatus. It could be
- ** that everything has been moved *except* for the root. Using a
- ** multistatus (with no errors for the other resources) will signify
- ** this condition.
- **
- ** For a COPY, we are traversing in a prefix fashion. If the root fails,
- ** then we can just bail out now.
- */
- if (err != NULL
- && !ap_is_HTTP_SERVER_ERROR(err->status)
- && (ctx->is_move
- || !dav_fs_is_same_resource(wres->resource, ctx->root))) {
- /* ### use errno to generate DAV:responsedescription? */
- dav_add_response(wres, err->status, NULL);
-
- /* the error is in the multistatus now. do not stop the traversal. */
- return NULL;
- }
-
- return err;
-}
-
-static dav_error *dav_fs_copymove_resource(
- int is_move,
- const dav_resource *src,
- const dav_resource *dst,
- int depth,
- dav_response **response)
-{
- dav_error *err = NULL;
- dav_buffer work_buf = { 0 };
-
- *response = NULL;
-
- /* if a collection, recursively copy/move it and its children,
- * including the state dirs
- */
- if (src->collection) {
- dav_walk_params params = { 0 };
- dav_response *multi_status;
-
- params.walk_type = DAV_WALKTYPE_NORMAL | DAV_WALKTYPE_HIDDEN;
- params.func = dav_fs_copymove_walker;
- params.pool = src->info->pool;
- params.root = src;
-
- /* params.walk_ctx is managed by dav_fs_internal_walk() */
-
- /* postfix is needed for MOVE to delete source dirs */
- if (is_move)
- params.walk_type |= DAV_WALKTYPE_POSTFIX;
-
- /* note that we return the error OR the multistatus. never both */
-
- if ((err = dav_fs_internal_walk(&params, depth, is_move, dst,
- &multi_status)) != NULL) {
- /* on a "real" error, then just punt. nothing else to do. */
- return err;
- }
-
- if ((*response = multi_status) != NULL) {
- /* some multistatus responses exist. wrap them in a 207 */
- return dav_new_error(src->info->pool, HTTP_MULTI_STATUS, 0,
- "Error(s) occurred on some resources during "
- "the COPY/MOVE process.");
- }
-
- return NULL;
- }
-
- /* not a collection */
- if ((err = dav_fs_copymove_file(is_move, src->info->pool,
- src->info->pathname, dst->info->pathname,
- &work_buf)) != NULL) {
- /* ### push a higher-level description? */
- return err;
- }
-
- /* copy/move properties as well */
- return dav_fs_copymoveset(is_move, src->info->pool, src, dst, &work_buf);
-}
-
-static dav_error * dav_fs_copy_resource(
- const dav_resource *src,
- dav_resource *dst,
- int depth,
- dav_response **response)
-{
- dav_error *err;
-
-#if DAV_DEBUG
- if (src->hooks != dst->hooks) {
- /*
- ** ### strictly speaking, this is a design error; we should not
- ** ### have reached this point.
- */
- return dav_new_error(src->info->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
- "DESIGN ERROR: a mix of repositories "
- "was passed to copy_resource.");
- }
-#endif
-
- if ((err = dav_fs_copymove_resource(0, src, dst, depth,
- response)) == NULL) {
-
- /* update state of destination resource to show it exists */
- dst->exists = 1;
- dst->collection = src->collection;
- }
-
- return err;
-}
-
-static dav_error * dav_fs_move_resource(
- dav_resource *src,
- dav_resource *dst,
- dav_response **response)
-{
- dav_resource_private *srcinfo = src->info;
- dav_resource_private *dstinfo = dst->info;
- dav_error *err;
- int can_rename = 0;
-
-#if DAV_DEBUG
- if (src->hooks != dst->hooks) {
- /*
- ** ### strictly speaking, this is a design error; we should not
- ** ### have reached this point.
- */
- return dav_new_error(src->info->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
- "DESIGN ERROR: a mix of repositories "
- "was passed to move_resource.");
- }
-#endif
-
- /* determine whether a simple rename will work.
- * Assume source exists, else we wouldn't get called.
- */
- if (dstinfo->finfo.filetype != 0) {
- if (dstinfo->finfo.device == srcinfo->finfo.device) {
- /* target exists and is on the same device. */
- can_rename = 1;
- }
- }
- else {
- const char *dirpath;
- apr_finfo_t finfo;
-
- /* destination does not exist, but the parent directory should,
- * so try it
- */
- dirpath = ap_make_dirstr_parent(dstinfo->pool, dstinfo->pathname);
- if (apr_stat(&finfo, dirpath, APR_FINFO_NORM, dstinfo->pool) == 0
- && finfo.device == srcinfo->finfo.device) {
- can_rename = 1;
- }
- }
-
- /* if we can't simply rename, then do it the hard way... */
- if (!can_rename) {
- if ((err = dav_fs_copymove_resource(1, src, dst, DAV_INFINITY,
- response)) == NULL) {
- /* update resource states */
- dst->exists = 1;
- dst->collection = src->collection;
- src->exists = 0;
- src->collection = 0;
- }
-
- return err;
- }
-
- /* a rename should work. do it, and move properties as well */
-
- /* no multistatus response */
- *response = NULL;
-
- /* ### APR has no rename? */
- if (apr_file_rename(srcinfo->pathname, dstinfo->pathname,
- srcinfo->pool) != APR_SUCCESS) {
- /* ### should have a better error than this. */
- return dav_new_error(srcinfo->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
- "Could not rename resource.");
- }
-
- /* update resource states */
- dst->exists = 1;
- dst->collection = src->collection;
- src->exists = 0;
- src->collection = 0;
-
- if ((err = dav_fs_copymoveset(1, src->info->pool,
- src, dst, NULL)) == NULL) {
- /* no error. we're done. go ahead and return now. */
- return NULL;
- }
-
- /* error occurred during properties move; try to put resource back */
- if (apr_file_rename(dstinfo->pathname, srcinfo->pathname,
- srcinfo->pool) != APR_SUCCESS) {
- /* couldn't put it back! */
- return dav_push_error(srcinfo->pool,
- HTTP_INTERNAL_SERVER_ERROR, 0,
- "The resource was moved, but a failure "
- "occurred during the move of its "
- "properties. The resource could not be "
- "restored to its original location. The "
- "server is now in an inconsistent state.",
- err);
- }
-
- /* update resource states again */
- src->exists = 1;
- src->collection = dst->collection;
- dst->exists = 0;
- dst->collection = 0;
-
- /* resource moved back, but properties may be inconsistent */
- return dav_push_error(srcinfo->pool,
- HTTP_INTERNAL_SERVER_ERROR, 0,
- "The resource was moved, but a failure "
- "occurred during the move of its properties. "
- "The resource was moved back to its original "
- "location, but its properties may have been "
- "partially moved. The server may be in an "
- "inconsistent state.",
- err);
-}
-
-static dav_error * dav_fs_delete_walker(dav_walk_resource *wres, int calltype)
-{
- dav_resource_private *info = wres->resource->info;
-
- /* do not attempt to remove a null resource,
- * or a collection with children
- */
- if (wres->resource->exists &&
- (!wres->resource->collection || calltype == DAV_CALLTYPE_POSTFIX)) {
- /* try to remove the resource */
- apr_status_t result;
-
- result = wres->resource->collection
- ? apr_dir_remove(info->pathname, wres->pool)
- : apr_file_remove(info->pathname, wres->pool);
-
- /*
- ** If an error occurred, then add it to multistatus response.
- ** Note that we add it for the root resource, too. It is quite
- ** possible to delete the whole darn tree, yet fail on the root.
- **
- ** (also: remember we are deleting via a postfix traversal)
- */
- if (result != APR_SUCCESS) {
- /* ### assume there is a permissions problem */
-
- /* ### use errno to generate DAV:responsedescription? */
- dav_add_response(wres, HTTP_FORBIDDEN, NULL);
- }
- }
-
- return NULL;
-}
-
-static dav_error * dav_fs_remove_resource(dav_resource *resource,
- dav_response **response)
-{
- dav_resource_private *info = resource->info;
-
- *response = NULL;
-
- /* if a collection, recursively remove it and its children,
- * including the state dirs
- */
- if (resource->collection) {
- dav_walk_params params = { 0 };
- dav_error *err = NULL;
- dav_response *multi_status;
-
- params.walk_type = (DAV_WALKTYPE_NORMAL
- | DAV_WALKTYPE_HIDDEN
- | DAV_WALKTYPE_POSTFIX);
- params.func = dav_fs_delete_walker;
- params.pool = info->pool;
- params.root = resource;
-
- if ((err = dav_fs_walk(&params, DAV_INFINITY,
- &multi_status)) != NULL) {
- /* on a "real" error, then just punt. nothing else to do. */
- return err;
- }
-
- if ((*response = multi_status) != NULL) {
- /* some multistatus responses exist. wrap them in a 207 */
- return dav_new_error(info->pool, HTTP_MULTI_STATUS, 0,
- "Error(s) occurred on some resources during "
- "the deletion process.");
- }
-
- /* no errors... update resource state */
- resource->exists = 0;
- resource->collection = 0;
-
- return NULL;
- }
-
- /* not a collection; remove the file and its properties */
- if (apr_file_remove(info->pathname, info->pool) != APR_SUCCESS) {
- /* ### put a description in here */
- return dav_new_error(info->pool, HTTP_FORBIDDEN, 0, NULL);
- }
-
- /* update resource state */
- resource->exists = 0;
- resource->collection = 0;
-
- /* remove properties and return its result */
- return dav_fs_deleteset(info->pool, resource);
-}
-
-/* ### move this to dav_util? */
-/* Walk recursively down through directories, *
- * including lock-null resources as we go. */
-static dav_error * dav_fs_walker(dav_fs_walker_context *fsctx, int depth)
-{
- const dav_walk_params *params = fsctx->params;
- apr_pool_t *pool = params->pool;
- dav_error *err = NULL;
- int isdir = fsctx->res1.collection;
- apr_finfo_t dirent;
- apr_dir_t *dirp;
-
- /* ensure the context is prepared properly, then call the func */
- err = (*params->func)(&fsctx->wres,
- isdir
- ? DAV_CALLTYPE_COLLECTION
- : DAV_CALLTYPE_MEMBER);
- if (err != NULL) {
- return err;
- }
-
- if (depth == 0 || !isdir) {
- return NULL;
- }
-
- /* put a trailing slash onto the directory, in preparation for appending
- * files to it as we discovery them within the directory */
- dav_check_bufsize(pool, &fsctx->path1, DAV_BUFFER_PAD);
- fsctx->path1.buf[fsctx->path1.cur_len++] = '/';
- fsctx->path1.buf[fsctx->path1.cur_len] = '\0'; /* in pad area */
-
- /* if a secondary path is present, then do that, too */
- if (fsctx->path2.buf != NULL) {
- dav_check_bufsize(pool, &fsctx->path2, DAV_BUFFER_PAD);
- fsctx->path2.buf[fsctx->path2.cur_len++] = '/';
- fsctx->path2.buf[fsctx->path2.cur_len] = '\0'; /* in pad area */
- }
-
- /* Note: the URI should ALREADY have a trailing "/" */
-
- /* for this first pass of files, all resources exist */
- fsctx->res1.exists = 1;
-
- /* a file is the default; we'll adjust if we hit a directory */
- fsctx->res1.collection = 0;
- fsctx->res2.collection = 0;
-
- /* open and scan the directory */
- if ((apr_dir_open(&dirp, fsctx->path1.buf, pool)) != APR_SUCCESS) {
- /* ### need a better error */
- return dav_new_error(pool, HTTP_NOT_FOUND, 0, NULL);
- }
- while ((apr_dir_read(&dirent, APR_FINFO_DIRENT, dirp)) == APR_SUCCESS) {
- apr_size_t len;
-
- len = strlen(dirent.name);
-
- /* avoid recursing into our current, parent, or state directories */
- if (dirent.name[0] == '.'
- && (len == 1 || (dirent.name[1] == '.' && len == 2))) {
- continue;
- }
-
- if (params->walk_type & DAV_WALKTYPE_AUTH) {
- /* ### need to authorize each file */
- /* ### example: .htaccess is normally configured to fail auth */
-
- /* stuff in the state directory is never authorized! */
- if (!strcmp(dirent.name, DAV_FS_STATE_DIR)) {
- continue;
- }
- }
- /* skip the state dir unless a HIDDEN is performed */
- if (!(params->walk_type & DAV_WALKTYPE_HIDDEN)
- && !strcmp(dirent.name, DAV_FS_STATE_DIR)) {
- continue;
- }
-
- /* append this file onto the path buffer (copy null term) */
- dav_buffer_place_mem(pool, &fsctx->path1, dirent.name, len + 1, 0);
-
-
- /* ### Optimize me, dirent can give us what we need! */
- if (apr_lstat(&fsctx->info1.finfo, fsctx->path1.buf,
- APR_FINFO_NORM, pool) != APR_SUCCESS) {
- /* woah! where'd it go? */
- /* ### should have a better error here */
- err = dav_new_error(pool, HTTP_NOT_FOUND, 0, NULL);
- break;
- }
-
- /* copy the file to the URI, too. NOTE: we will pad an extra byte
- for the trailing slash later. */
- dav_buffer_place_mem(pool, &fsctx->uri_buf, dirent.name, len + 1, 1);
-
- /* if there is a secondary path, then do that, too */
- if (fsctx->path2.buf != NULL) {
- dav_buffer_place_mem(pool, &fsctx->path2, dirent.name, len + 1, 0);
- }
-
- /* set up the (internal) pathnames for the two resources */
- fsctx->info1.pathname = fsctx->path1.buf;
- fsctx->info2.pathname = fsctx->path2.buf;
-
- /* set up the URI for the current resource */
- fsctx->res1.uri = fsctx->uri_buf.buf;
-
- /* ### for now, only process regular files (e.g. skip symlinks) */
- if (fsctx->info1.finfo.filetype == APR_REG) {
- /* call the function for the specified dir + file */
- if ((err = (*params->func)(&fsctx->wres,
- DAV_CALLTYPE_MEMBER)) != NULL) {
- /* ### maybe add a higher-level description? */
- break;
- }
- }
- else if (fsctx->info1.finfo.filetype == APR_DIR) {
- apr_size_t save_path_len = fsctx->path1.cur_len;
- apr_size_t save_uri_len = fsctx->uri_buf.cur_len;
- apr_size_t save_path2_len = fsctx->path2.cur_len;
-
- /* adjust length to incorporate the subdir name */
- fsctx->path1.cur_len += len;
- fsctx->path2.cur_len += len;
-
- /* adjust URI length to incorporate subdir and a slash */
- fsctx->uri_buf.cur_len += len + 1;
- fsctx->uri_buf.buf[fsctx->uri_buf.cur_len - 1] = '/';
- fsctx->uri_buf.buf[fsctx->uri_buf.cur_len] = '\0';
-
- /* switch over to a collection */
- fsctx->res1.collection = 1;
- fsctx->res2.collection = 1;
-
- /* recurse on the subdir */
- /* ### don't always want to quit on error from single child */
- if ((err = dav_fs_walker(fsctx, depth - 1)) != NULL) {
- /* ### maybe add a higher-level description? */
- break;
- }
-
- /* put the various information back */
- fsctx->path1.cur_len = save_path_len;
- fsctx->path2.cur_len = save_path2_len;
- fsctx->uri_buf.cur_len = save_uri_len;
-
- fsctx->res1.collection = 0;
- fsctx->res2.collection = 0;
-
- /* assert: res1.exists == 1 */
- }
- }
-
- /* ### check the return value of this? */
- apr_dir_close(dirp);
-
- if (err != NULL)
- return err;
-
- if (params->walk_type & DAV_WALKTYPE_LOCKNULL) {
- apr_size_t offset = 0;
-
- /* null terminate the directory name */
- fsctx->path1.buf[fsctx->path1.cur_len - 1] = '\0';
-
- /* Include any lock null resources found in this collection */
- fsctx->res1.collection = 1;
- if ((err = dav_fs_get_locknull_members(&fsctx->res1,
- &fsctx->locknull_buf)) != NULL) {
- /* ### maybe add a higher-level description? */
- return err;
- }
-
- /* put a slash back on the end of the directory */
- fsctx->path1.buf[fsctx->path1.cur_len - 1] = '/';
-
- /* these are all non-existant (files) */
- fsctx->res1.exists = 0;
- fsctx->res1.collection = 0;
- memset(&fsctx->info1.finfo, 0, sizeof(fsctx->info1.finfo));
-
- while (offset < fsctx->locknull_buf.cur_len) {
- apr_size_t len = strlen(fsctx->locknull_buf.buf + offset);
- dav_lock *locks = NULL;
-
- /*
- ** Append the locknull file to the paths and the URI. Note that
- ** we don't have to pad the URI for a slash since a locknull
- ** resource is not a collection.
- */
- dav_buffer_place_mem(pool, &fsctx->path1,
- fsctx->locknull_buf.buf + offset, len + 1, 0);
- dav_buffer_place_mem(pool, &fsctx->uri_buf,
- fsctx->locknull_buf.buf + offset, len + 1, 0);
- if (fsctx->path2.buf != NULL) {
- dav_buffer_place_mem(pool, &fsctx->path2,
- fsctx->locknull_buf.buf + offset,
- len + 1, 0);
- }
-
- /* set up the (internal) pathnames for the two resources */
- fsctx->info1.pathname = fsctx->path1.buf;
- fsctx->info2.pathname = fsctx->path2.buf;
-
- /* set up the URI for the current resource */
- fsctx->res1.uri = fsctx->uri_buf.buf;
-
- /*
- ** To prevent a PROPFIND showing an expired locknull
- ** resource, query the lock database to force removal
- ** of both the lock entry and .locknull, if necessary..
- ** Sure, the query in PROPFIND would do this.. after
- ** the locknull resource was already included in the
- ** return.
- **
- ** NOTE: we assume the caller has opened the lock database
- ** if they have provided DAV_WALKTYPE_LOCKNULL.
- */
- /* ### we should also look into opening it read-only and
- ### eliding timed-out items from the walk, yet leaving
- ### them in the locknull database until somebody opens
- ### the thing writable.
- */
- /* ### probably ought to use has_locks. note the problem
- ### mentioned above, though... we would traverse this as
- ### a locknull, but then a PROPFIND would load the lock
- ### info, causing a timeout and the locks would not be
- ### reported. Therefore, a null resource would be returned
- ### in the PROPFIND.
- ###
- ### alternative: just load unresolved locks. any direct
- ### locks will be timed out (correct). any indirect will
- ### not (correct; consider if a parent timed out -- the
- ### timeout routines do not walk and remove indirects;
- ### even the resolve func would probably fail when it
- ### tried to find a timed-out direct lock).
- */
- if ((err = dav_lock_query(params->lockdb, &fsctx->res1,
- &locks)) != NULL) {
- /* ### maybe add a higher-level description? */
- return err;
- }
-
- /* call the function for the specified dir + file */
- if (locks != NULL &&
- (err = (*params->func)(&fsctx->wres,
- DAV_CALLTYPE_LOCKNULL)) != NULL) {
- /* ### maybe add a higher-level description? */
- return err;
- }
-
- offset += len + 1;
- }
-
- /* reset the exists flag */
- fsctx->res1.exists = 1;
- }
-
- if (params->walk_type & DAV_WALKTYPE_POSTFIX) {
- /* replace the dirs' trailing slashes with null terms */
- fsctx->path1.buf[--fsctx->path1.cur_len] = '\0';
- fsctx->uri_buf.buf[--fsctx->uri_buf.cur_len] = '\0';
- if (fsctx->path2.buf != NULL) {
- fsctx->path2.buf[--fsctx->path2.cur_len] = '\0';
- }
-
- /* this is a collection which exists */
- fsctx->res1.collection = 1;
-
- return (*params->func)(&fsctx->wres, DAV_CALLTYPE_POSTFIX);
- }
-
- return NULL;
-}
-
-static dav_error * dav_fs_internal_walk(const dav_walk_params *params,
- int depth, int is_move,
- const dav_resource *root_dst,
- dav_response **response)
-{
- dav_fs_walker_context fsctx = { 0 };
- dav_error *err;
- dav_fs_copymove_walk_ctx cm_ctx = { 0 };
-
-#if DAV_DEBUG
- if ((params->walk_type & DAV_WALKTYPE_LOCKNULL) != 0
- && params->lockdb == NULL) {
- return dav_new_error(params->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
- "DESIGN ERROR: walker called to walk locknull "
- "resources, but a lockdb was not provided.");
- }
-#endif
-
- fsctx.params = params;
- fsctx.wres.walk_ctx = params->walk_ctx;
- fsctx.wres.pool = params->pool;
-
- /* ### zero out versioned, working, baselined? */
-
- fsctx.res1 = *params->root;
- fsctx.res1.pool = params->pool;
-
- fsctx.res1.info = &fsctx.info1;
- fsctx.info1 = *params->root->info;
-
- /* the pathname is stored in the path1 buffer */
- dav_buffer_init(params->pool, &fsctx.path1, fsctx.info1.pathname);
- fsctx.info1.pathname = fsctx.path1.buf;
-
- if (root_dst != NULL) {
- /* internal call from the COPY/MOVE code. set it up. */
-
- fsctx.wres.walk_ctx = &cm_ctx;
- cm_ctx.is_move = is_move;
- cm_ctx.res_dst = &fsctx.res2;
- cm_ctx.root = params->root;
- cm_ctx.pool = params->pool;
-
- fsctx.res2 = *root_dst;
- fsctx.res2.exists = 0;
- fsctx.res2.collection = 0;
- fsctx.res2.uri = NULL; /* we don't track this */
- fsctx.res2.pool = params->pool;
-
- fsctx.res2.info = &fsctx.info2;
- fsctx.info2 = *root_dst->info;
-
- /* res2 does not exist -- clear its finfo structure */
- memset(&fsctx.info2.finfo, 0, sizeof(fsctx.info2.finfo));
-
- /* the pathname is stored in the path2 buffer */
- dav_buffer_init(params->pool, &fsctx.path2, fsctx.info2.pathname);
- fsctx.info2.pathname = fsctx.path2.buf;
- }
-
- /* prep the URI buffer */
- dav_buffer_init(params->pool, &fsctx.uri_buf, params->root->uri);
-
- /* if we have a directory, then ensure the URI has a trailing "/" */
- if (fsctx.res1.collection
- && fsctx.uri_buf.buf[fsctx.uri_buf.cur_len - 1] != '/') {
-
- /* this will fall into the pad area */
- fsctx.uri_buf.buf[fsctx.uri_buf.cur_len++] = '/';
- fsctx.uri_buf.buf[fsctx.uri_buf.cur_len] = '\0';
- }
-
- /* the current resource's URI is stored in the uri_buf buffer */
- fsctx.res1.uri = fsctx.uri_buf.buf;
-
- /* point the callback's resource at our structure */
- fsctx.wres.resource = &fsctx.res1;
-
- /* always return the error, and any/all multistatus responses */
- err = dav_fs_walker(&fsctx, depth);
- *response = fsctx.wres.response;
- return err;
-}
-
-static dav_error * dav_fs_walk(const dav_walk_params *params, int depth,
- dav_response **response)
-{
- /* always return the error, and any/all multistatus responses */
- return dav_fs_internal_walk(params, depth, 0, NULL, response);
-}
-
-/* dav_fs_etag: Stolen from ap_make_etag. Creates a strong etag
- * for file path.
- * ### do we need to return weak tags sometimes?
- */
-static const char *dav_fs_getetag(const dav_resource *resource)
-{
- dav_resource_private *ctx = resource->info;
-
- if (!resource->exists)
- return apr_pstrdup(ctx->pool, "");
-
- if (ctx->finfo.filetype != 0) {
- return apr_psprintf(ctx->pool, "\"%lx-%lx-%lx\"",
- (unsigned long) ctx->finfo.inode,
- (unsigned long) ctx->finfo.size,
- (unsigned long) ctx->finfo.mtime);
- }
-
- return apr_psprintf(ctx->pool, "\"%lx\"", (unsigned long) ctx->finfo.mtime);
-}
-
-static const dav_hooks_repository dav_hooks_repository_fs =
-{
- DEBUG_GET_HANDLER, /* normally: special GET handling not required */
- dav_fs_get_resource,
- dav_fs_get_parent_resource,
- dav_fs_is_same_resource,
- dav_fs_is_parent_resource,
- dav_fs_open_stream,
- dav_fs_close_stream,
- dav_fs_read_stream,
- dav_fs_write_stream,
- dav_fs_seek_stream,
- dav_fs_set_headers,
-#if DEBUG_PATHNAME_STYLE
- dav_fs_get_pathname,
-#else
- 0,
-#endif
- dav_fs_free_file,
- dav_fs_create_collection,
- dav_fs_copy_resource,
- dav_fs_move_resource,
- dav_fs_remove_resource,
- dav_fs_walk,
- dav_fs_getetag,
-};
-
-static dav_prop_insert dav_fs_insert_prop(const dav_resource *resource,
- int propid, dav_prop_insert what,
- ap_text_header *phdr)
-{
- const char *value;
- const char *s;
- apr_pool_t *p = resource->info->pool;
- const dav_liveprop_spec *info;
- int global_ns;
-
- /* an HTTP-date can be 29 chars plus a null term */
- /* a 64-bit size can be 20 chars plus a null term */
- char buf[DAV_TIMEBUF_SIZE];
-
- /*
- ** None of FS provider properties are defined if the resource does not
- ** exist. Just bail for this case.
- **
- ** Even though we state that the FS properties are not defined, the
- ** client cannot store dead values -- we deny that thru the is_writable
- ** hook function.
- */
- if (!resource->exists)
- return DAV_PROP_INSERT_NOTDEF;
-
- switch (propid) {
- case DAV_PROPID_creationdate:
- /*
- ** Closest thing to a creation date. since we don't actually
- ** perform the operations that would modify ctime (after we
- ** create the file), then we should be pretty safe here.
- */
- dav_format_time(DAV_STYLE_ISO8601,
- resource->info->finfo.ctime,
- buf);
- value = buf;
- break;
-
- case DAV_PROPID_getcontentlength:
- /* our property, but not defined on collection resources */
- if (resource->collection)
- return DAV_PROP_INSERT_NOTDEF;
-
- (void) sprintf(buf, "%" APR_OFF_T_FMT, resource->info->finfo.size);
- value = buf;
- break;
-
- case DAV_PROPID_getetag:
- value = dav_fs_getetag(resource);
- break;
-
- case DAV_PROPID_getlastmodified:
- dav_format_time(DAV_STYLE_RFC822,
- resource->info->finfo.mtime,
- buf);
- value = buf;
- break;
-
- case DAV_PROPID_FS_executable:
- /* our property, but not defined on collection resources */
- if (resource->collection)
- return DAV_PROP_INSERT_NOTDEF;
-
- /* our property, but not defined on this platform */
- if (!(resource->info->finfo.valid & APR_FINFO_UPROT))
- return DAV_PROP_INSERT_NOTDEF;
-
- /* the files are "ours" so we only need to check owner exec privs */
- if (resource->info->finfo.protection & APR_UEXECUTE)
- value = "T";
- else
- value = "F";
- break;
-
- default:
- /* ### what the heck was this property? */
- return DAV_PROP_INSERT_NOTDEF;
- }
-
- /* assert: value != NULL */
-
- /* get the information and global NS index for the property */
- global_ns = dav_get_liveprop_info(propid, &dav_fs_liveprop_group, &info);
-
- /* assert: info != NULL && info->name != NULL */
-
- /* DBG3("FS: inserting lp%d:%s (local %d)", ns, scan->name, scan->ns); */
-
- if (what == DAV_PROP_INSERT_VALUE) {
- s = apr_psprintf(p, "<lp%d:%s>%s</lp%d:%s>" DEBUG_CR,
- global_ns, info->name, value, global_ns, info->name);
- }
- else if (what == DAV_PROP_INSERT_NAME) {
- s = apr_psprintf(p, "<lp%d:%s/>" DEBUG_CR, global_ns, info->name);
- }
- else {
- /* assert: what == DAV_PROP_INSERT_SUPPORTED */
- s = apr_psprintf(p,
- "<D:supported-live-property D:name=\"%s\" "
- "D:namespace=\"%s\"/>" DEBUG_CR,
- info->name, dav_fs_namespace_uris[info->ns]);
- }
- ap_text_append(p, phdr, s);
-
- /* we inserted what was asked for */
- return what;
-}
-
-static int dav_fs_is_writable(const dav_resource *resource, int propid)
-{
- const dav_liveprop_spec *info;
-
-#ifndef WIN32
- /* this property is not usable (writable) on the Win32 platform */
- if (propid == DAV_PROPID_FS_executable && !resource->collection)
- return 1;
-#endif
-
- (void) dav_get_liveprop_info(propid, &dav_fs_liveprop_group, &info);
- return info->is_writable;
-}
-
-static dav_error *dav_fs_patch_validate(const dav_resource *resource,
- const ap_xml_elem *elem,
- int operation,
- void **context,
- int *defer_to_dead)
-{
- const ap_text *cdata;
- const ap_text *f_cdata;
- char value;
- dav_elem_private *priv = elem->private;
-
- if (priv->propid != DAV_PROPID_FS_executable) {
- *defer_to_dead = 1;
- return NULL;
- }
-
- if (operation == DAV_PROP_OP_DELETE) {
- return dav_new_error(resource->info->pool, HTTP_CONFLICT, 0,
- "The 'executable' property cannot be removed.");
- }
-
- cdata = elem->first_cdata.first;
-
- /* ### hmm. this isn't actually looking at all the possible text items */
- f_cdata = elem->first_child == NULL
- ? NULL
- : elem->first_child->following_cdata.first;
-
- /* DBG3("name=%s cdata=%s f_cdata=%s",elem->name,cdata ? cdata->text : "[null]",f_cdata ? f_cdata->text : "[null]"); */
-
- if (cdata == NULL) {
- if (f_cdata == NULL) {
- return dav_new_error(resource->info->pool, HTTP_CONFLICT, 0,
- "The 'executable' property expects a single "
- "character, valued 'T' or 'F'. There was no "
- "value submitted.");
- }
- cdata = f_cdata;
- }
- else if (f_cdata != NULL)
- goto too_long;
-
- if (cdata->next != NULL || strlen(cdata->text) != 1)
- goto too_long;
-
- value = cdata->text[0];
- if (value != 'T' && value != 'F') {
- return dav_new_error(resource->info->pool, HTTP_CONFLICT, 0,
- "The 'executable' property expects a single "
- "character, valued 'T' or 'F'. The value "
- "submitted is invalid.");
- }
-
- *context = (void *)(value == 'T');
-
- return NULL;
-
- too_long:
- return dav_new_error(resource->info->pool, HTTP_CONFLICT, 0,
- "The 'executable' property expects a single "
- "character, valued 'T' or 'F'. The value submitted "
- "has too many characters.");
-
-}
-
-static dav_error *dav_fs_patch_exec(const dav_resource *resource,
- const ap_xml_elem *elem,
- int operation,
- void *context,
- dav_liveprop_rollback **rollback_ctx)
-{
- int value = context != NULL;
- apr_fileperms_t perms = resource->info->finfo.protection;
- int old_value = (perms & APR_UEXECUTE) != 0;
-
- /* assert: prop == executable. operation == SET. */
-
- /* don't do anything if there is no change. no rollback info either. */
- /* DBG2("new value=%d (old=%d)", value, old_value); */
- if (value == old_value)
- return NULL;
-
- perms &= ~APR_UEXECUTE;
- if (value)
- perms |= APR_UEXECUTE;
-
- if (apr_file_perms_set(resource->info->pathname, perms) != APR_SUCCESS) {
- return dav_new_error(resource->info->pool,
- HTTP_INTERNAL_SERVER_ERROR, 0,
- "Could not set the executable flag of the "
- "target resource.");
- }
-
- /* update the resource and set up the rollback context */
- resource->info->finfo.protection = perms;
- *rollback_ctx = (dav_liveprop_rollback *)old_value;
-
- return NULL;
-}
-
-static void dav_fs_patch_commit(const dav_resource *resource,
- int operation,
- void *context,
- dav_liveprop_rollback *rollback_ctx)
-{
- /* nothing to do */
-}
-
-static dav_error *dav_fs_patch_rollback(const dav_resource *resource,
- int operation,
- void *context,
- dav_liveprop_rollback *rollback_ctx)
-{
- apr_fileperms_t perms = resource->info->finfo.protection & ~APR_UEXECUTE;
- int value = rollback_ctx != NULL;
-
- /* assert: prop == executable. operation == SET. */
-
- /* restore the executable bit */
- if (value)
- perms |= APR_UEXECUTE;
-
- if (apr_file_perms_set(resource->info->pathname, perms) != APR_SUCCESS) {
- return dav_new_error(resource->info->pool,
- HTTP_INTERNAL_SERVER_ERROR, 0,
- "After a failure occurred, the resource's "
- "executable flag could not be restored.");
- }
-
- /* restore the resource's state */
- resource->info->finfo.protection = perms;
-
- return NULL;
-}
-
-
-static const dav_hooks_liveprop dav_hooks_liveprop_fs =
-{
- dav_fs_insert_prop,
- dav_fs_is_writable,
- dav_fs_namespace_uris,
- dav_fs_patch_validate,
- dav_fs_patch_exec,
- dav_fs_patch_commit,
- dav_fs_patch_rollback
-};
-
-static const dav_provider dav_fs_provider =
-{
- &dav_hooks_repository_fs,
- &dav_hooks_db_dbm,
- &dav_hooks_locks_fs,
- NULL, /* vsn */
- NULL /* binding */
-};
-
-void dav_fs_gather_propsets(apr_array_header_t *uris)
-{
-#ifndef WIN32
- *(const char **)apr_array_push(uris) =
- "<http://apache.org/dav/propset/fs/1>";
-#endif
-}
-
-int dav_fs_find_liveprop(const dav_resource *resource,
- const char *ns_uri, const char *name,
- const dav_hooks_liveprop **hooks)
-{
- /* don't try to find any liveprops if this isn't "our" resource */
- if (resource->hooks != &dav_hooks_repository_fs)
- return 0;
- return dav_do_find_liveprop(ns_uri, name, &dav_fs_liveprop_group, hooks);
-}
-
-void dav_fs_insert_all_liveprops(request_rec *r, const dav_resource *resource,
- dav_prop_insert what, ap_text_header *phdr)
-{
- /* don't insert any liveprops if this isn't "our" resource */
- if (resource->hooks != &dav_hooks_repository_fs)
- return;
-
- if (!resource->exists) {
- /* a lock-null resource */
- /*
- ** ### technically, we should insert empty properties. dunno offhand
- ** ### what part of the spec said this, but it was essentially thus:
- ** ### "the properties should be defined, but may have no value".
- */
- return;
- }
-
- (void) dav_fs_insert_prop(resource, DAV_PROPID_creationdate,
- what, phdr);
- (void) dav_fs_insert_prop(resource, DAV_PROPID_getcontentlength,
- what, phdr);
- (void) dav_fs_insert_prop(resource, DAV_PROPID_getlastmodified,
- what, phdr);
- (void) dav_fs_insert_prop(resource, DAV_PROPID_getetag,
- what, phdr);
-
-#ifndef WIN32
- /*
- ** Note: this property is not defined on the Win32 platform.
- ** dav_fs_insert_prop() won't insert it, but we may as
- ** well not even call it.
- */
- (void) dav_fs_insert_prop(resource, DAV_PROPID_FS_executable,
- what, phdr);
-#endif
-
- /* ### we know the others aren't defined as liveprops */
-}
-
-void dav_fs_register(apr_pool_t *p)
-{
- /* register the namespace URIs */
- dav_register_liveprop_group(p, &dav_fs_liveprop_group);
-
- /* register the repository provider */
- dav_register_provider(p, "filesystem", &dav_fs_provider);
-}
diff --git a/modules/dav/fs/repos.h b/modules/dav/fs/repos.h
deleted file mode 100644
index 8e69773286..0000000000
--- a/modules/dav/fs/repos.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-/*
-** Declarations for the filesystem repository implementation
-*/
-
-#ifndef _DAV_FS_REPOS_H_
-#define _DAV_FS_REPOS_H_
-
-/* the subdirectory to hold all DAV-related information for a directory */
-#define DAV_FS_STATE_DIR ".DAV"
-#define DAV_FS_STATE_FILE_FOR_DIR ".state_for_dir"
-#define DAV_FS_LOCK_NULL_FILE ".locknull"
-
-
-/* ensure that our state subdirectory is present */
-void dav_fs_ensure_state_dir(apr_pool_t *p, const char *dirname);
-
-/* return the storage pool associated with a resource */
-apr_pool_t *dav_fs_pool(const dav_resource *resource);
-
-/* return the full pathname for a resource */
-const char *dav_fs_pathname(const dav_resource *resource);
-
-/* return the directory and filename for a resource */
-void dav_fs_dir_file_name(const dav_resource *resource,
- const char **dirpath,
- const char **fname);
-
-/* return the list of locknull members in this resource's directory */
-dav_error * dav_fs_get_locknull_members(const dav_resource *resource,
- dav_buffer *pbuf);
-
-
-/* DBM functions used by the repository and locking providers */
-extern const dav_hooks_db dav_hooks_db_dbm;
-
-dav_error * dav_dbm_open_direct(apr_pool_t *p, const char *pathname, int ro,
- dav_db **pdb);
-void dav_dbm_get_statefiles(apr_pool_t *p, const char *fname,
- const char **state1, const char **state2);
-
-/* where is the lock database located? */
-const char *dav_get_lockdb_path(const request_rec *r);
-
-const dav_hooks_locks *dav_fs_get_lock_hooks(request_rec *r);
-const dav_hooks_propdb *dav_fs_get_propdb_hooks(request_rec *r);
-
-void dav_fs_gather_propsets(apr_array_header_t *uris);
-int dav_fs_find_liveprop(const dav_resource *resource,
- const char *ns_uri, const char *name,
- const dav_hooks_liveprop **hooks);
-void dav_fs_insert_all_liveprops(request_rec *r, const dav_resource *resource,
- dav_prop_insert what, ap_text_header *phdr);
-
-void dav_fs_register(apr_pool_t *p);
-
-#endif /* _DAV_FS_REPOS_H_ */
diff --git a/modules/dav/main/.cvsignore b/modules/dav/main/.cvsignore
deleted file mode 100644
index 65f0cc30cf..0000000000
--- a/modules/dav/main/.cvsignore
+++ /dev/null
@@ -1,10 +0,0 @@
-.deps
-.libs
-*.la
-modules.mk
-Makefile
-*.lo
-*.slo
-*.so
-Debug
-Release
diff --git a/modules/dav/main/Makefile.in b/modules/dav/main/Makefile.in
deleted file mode 100644
index 7c5c149d85..0000000000
--- a/modules/dav/main/Makefile.in
+++ /dev/null
@@ -1,3 +0,0 @@
-# a modules Makefile has no explicit targets -- they will be defined by
-# whatever modules are enabled. just grab special.mk to deal with this.
-include $(top_srcdir)/build/special.mk
diff --git a/modules/dav/main/config5.m4 b/modules/dav/main/config5.m4
deleted file mode 100644
index f576f5f579..0000000000
--- a/modules/dav/main/config5.m4
+++ /dev/null
@@ -1,22 +0,0 @@
-dnl modules enabled in this directory by default
-
-APACHE_MODPATH_INIT(dav/main)
-
-dav_objects="mod_dav.lo props.lo util.lo util_lock.lo liveprop.lo providers.lo std_liveprop.lo"
-
-if test "$enable_http" = "no"; then
- dav_enable=no
-else
- dav_enable=most
-fi
-
-APACHE_MODULE(dav, WebDAV protocol handling, $dav_objects, , $dav_enable)
-
-if test "$enable_dav" != "no"; then
- apache_need_expat=yes
-
- APR_ADDTO(INCLUDES, [-I\$(top_srcdir)/$modpath_current])
-fi
-
-
-APACHE_MODPATH_FINISH
diff --git a/modules/dav/main/liveprop.c b/modules/dav/main/liveprop.c
deleted file mode 100644
index 98358afb74..0000000000
--- a/modules/dav/main/liveprop.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "apr_pools.h"
-#include "apr_hash.h"
-#include "apr_errno.h"
-#include "apr_strings.h"
-#include "util_xml.h" /* for ap_text_header */
-#include "mod_dav.h"
-
-
-static apr_hash_t *dav_liveprop_uris = NULL;
-static int dav_liveprop_count = 0;
-
-
-static apr_status_t dav_cleanup_liveprops(void *ctx)
-{
- dav_liveprop_uris = NULL;
- dav_liveprop_count = 0;
- return APR_SUCCESS;
-}
-
-static void dav_register_liveprop_namespace(apr_pool_t *p, const char *uri)
-{
- int value;
-
- if (dav_liveprop_uris == NULL) {
- dav_liveprop_uris = apr_hash_make(p);
- apr_pool_cleanup_register(p, NULL, dav_cleanup_liveprops, apr_pool_cleanup_null);
- }
-
- value = (int)apr_hash_get(dav_liveprop_uris, uri, APR_HASH_KEY_STRING);
- if (value != 0) {
- /* already registered */
- return;
- }
-
- /* start at 1, and count up */
- apr_hash_set(dav_liveprop_uris, uri, APR_HASH_KEY_STRING,
- (void *)++dav_liveprop_count);
-}
-
-DAV_DECLARE(int) dav_get_liveprop_ns_index(const char *uri)
-{
- return (int)apr_hash_get(dav_liveprop_uris, uri, APR_HASH_KEY_STRING);
-}
-
-int dav_get_liveprop_ns_count(void)
-{
- return dav_liveprop_count;
-}
-
-void dav_add_all_liveprop_xmlns(apr_pool_t *p, ap_text_header *phdr)
-{
- apr_hash_index_t *idx = apr_hash_first(dav_liveprop_uris);
-
- for ( ; idx != NULL; idx = apr_hash_next(idx) ) {
- const void *key;
- void *val;
- const char *s;
-
- apr_hash_this(idx, &key, NULL, &val);
-
- s = apr_psprintf(p, " xmlns:lp%d=\"%s\"", (int)val, (const char *)key);
- ap_text_append(p, phdr, s);
- }
-}
-
-DAV_DECLARE(int) dav_do_find_liveprop(const char *ns_uri, const char *name,
- const dav_liveprop_group *group,
- const dav_hooks_liveprop **hooks)
-{
- const char * const *uris = group->namespace_uris;
- const dav_liveprop_spec *scan;
- int ns;
-
- /* first: locate the namespace in the namespace table */
- for (ns = 0; uris[ns] != NULL; ++ns)
- if (strcmp(ns_uri, uris[ns]) == 0)
- break;
- if (uris[ns] == NULL) {
- /* not our property (the namespace matched none of ours) */
- return 0;
- }
-
- /* second: look for the property in the liveprop specs */
- for (scan = group->specs; scan->name != NULL; ++scan)
- if (ns == scan->ns && strcmp(name, scan->name) == 0) {
- *hooks = group->hooks;
- return scan->propid;
- }
-
- /* not our property (same namespace, but no matching prop name) */
- return 0;
-}
-
-DAV_DECLARE(int) dav_get_liveprop_info(int propid,
- const dav_liveprop_group *group,
- const dav_liveprop_spec **info)
-{
- const dav_liveprop_spec *scan;
-
- for (scan = group->specs; scan->name != NULL; ++scan) {
- if (scan->propid == propid) {
- *info = scan;
-
- /* map the provider-local NS into a global NS index */
- return dav_get_liveprop_ns_index(group->namespace_uris[scan->ns]);
- }
- }
-
- /* assert: should not reach this point */
- *info = NULL;
- return 0;
-}
-
-DAV_DECLARE(void) dav_register_liveprop_group(apr_pool_t *p,
- const dav_liveprop_group *group)
-{
- /* register the namespace URIs */
- const char * const * uris = group->namespace_uris;
-
- for ( ; *uris != NULL; ++uris) {
- dav_register_liveprop_namespace(p, *uris);
- }
-}
diff --git a/modules/dav/main/mod_dav.c b/modules/dav/main/mod_dav.c
deleted file mode 100644
index 8e29f05c7f..0000000000
--- a/modules/dav/main/mod_dav.c
+++ /dev/null
@@ -1,4731 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-/*
-** DAV extension module for Apache 2.0.*
-**
-** This module is repository-independent. It depends on hooks provided by a
-** repository implementation.
-**
-** APACHE ISSUES:
-** - within a DAV hierarchy, if an unknown method is used and we default
-** to Apache's implementation, it sends back an OPTIONS with the wrong
-** set of methods -- there is NO HOOK for us.
-** therefore: we need to manually handle the HTTP_METHOD_NOT_ALLOWED
-** and HTTP_NOT_IMPLEMENTED responses (not ap_send_error_response).
-** - process_mkcol_body() had to dup code from ap_setup_client_block().
-** - it would be nice to get status lines from Apache for arbitrary
-** status codes
-** - it would be nice to be able to extend Apache's set of response
-** codes so that it doesn't return 500 when an unknown code is placed
-** into r->status.
-** - http_vhost functions should apply "const" to their params
-**
-** DESIGN NOTES:
-** - For PROPFIND, we batch up the entire response in memory before
-** sending it. We may want to reorganize around sending the information
-** as we suck it in from the propdb. Alternatively, we should at least
-** generate a total Content-Length if we're going to buffer in memory
-** so that we can keep the connection open.
-*/
-
-#include "apr_strings.h"
-#include "apr_lib.h" /* for apr_is* */
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#include "httpd.h"
-#include "http_config.h"
-#include "http_core.h"
-#include "http_log.h"
-#include "http_main.h"
-#include "http_protocol.h"
-#include "http_request.h"
-#include "util_script.h"
-
-#include "mod_dav.h"
-
-
-/* ### what is the best way to set this? */
-#define DAV_DEFAULT_PROVIDER "filesystem"
-
-enum {
- DAV_ENABLED_UNSET = 0,
- DAV_ENABLED_OFF,
- DAV_ENABLED_ON
-};
-
-/* per-dir configuration */
-typedef struct {
- const char *provider_name;
- const dav_provider *provider;
- const char *dir;
- int locktimeout;
- int allow_depthinfinity;
-
- apr_table_t *d_params; /* per-directory DAV config parameters */
-
-} dav_dir_conf;
-
-/* per-server configuration */
-typedef struct {
- int unused;
-
-} dav_server_conf;
-
-#define DAV_INHERIT_VALUE(parent, child, field) \
- ((child)->field ? (child)->field : (parent)->field)
-
-
-/* forward-declare for use in configuration lookup */
-extern module DAV_DECLARE_DATA dav_module;
-
-static void dav_init_handler(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
- server_rec *s)
-{
- /* DBG0("dav_init_handler"); */
-
- ap_add_version_component(p, "DAV/2");
-}
-
-static void *dav_create_server_config(apr_pool_t *p, server_rec *s)
-{
- dav_server_conf *newconf;
-
- newconf = (dav_server_conf *) apr_pcalloc(p, sizeof(*newconf));
-
- /* ### this isn't used at the moment... */
-
- return newconf;
-}
-
-static void *dav_merge_server_config(apr_pool_t *p, void *base, void *overrides)
-{
-#if 0
- dav_server_conf *child = overrides;
-#endif
- dav_server_conf *newconf;
-
- newconf = (dav_server_conf *) apr_pcalloc(p, sizeof(*newconf));
-
- /* ### nothing to merge right now... */
-
- return newconf;
-}
-
-static void *dav_create_dir_config(apr_pool_t *p, char *dir)
-{
- /* NOTE: dir==NULL creates the default per-dir config */
-
- dav_dir_conf *conf;
-
- conf = (dav_dir_conf *) apr_pcalloc(p, sizeof(*conf));
-
- /* clean up the directory to remove any trailing slash */
- if (dir != NULL) {
- char *d;
- apr_size_t l;
-
- d = apr_pstrdup(p, dir);
- l = strlen(d);
- if (l > 1 && d[l - 1] == '/')
- d[l - 1] = '\0';
- conf->dir = d;
- }
-
- conf->d_params = apr_table_make(p, 1);
-
- return conf;
-}
-
-static void *dav_merge_dir_config(apr_pool_t *p, void *base, void *overrides)
-{
- dav_dir_conf *parent = base;
- dav_dir_conf *child = overrides;
- dav_dir_conf *newconf = (dav_dir_conf *) apr_pcalloc(p, sizeof(*newconf));
-
- /* DBG3("dav_merge_dir_config: new=%08lx base=%08lx overrides=%08lx",
- (long)newconf, (long)base, (long)overrides); */
-
- newconf->provider_name = DAV_INHERIT_VALUE(parent, child, provider_name);
- newconf->provider = DAV_INHERIT_VALUE(parent, child, provider);
- if (parent->provider_name != NULL) {
- if (child->provider_name == NULL) {
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, NULL,
- "\"DAV Off\" cannot be used to turn off a subtree "
- "of a DAV-enabled location.");
- }
- else if (strcasecmp(child->provider_name,
- parent->provider_name) != 0) {
- ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, NULL,
- "A subtree cannot specify a different DAV provider "
- "than its parent.");
- }
- }
-
- newconf->locktimeout = DAV_INHERIT_VALUE(parent, child, locktimeout);
- newconf->dir = DAV_INHERIT_VALUE(parent, child, dir);
- newconf->allow_depthinfinity = DAV_INHERIT_VALUE(parent, child,
- allow_depthinfinity);
-
- newconf->d_params = apr_table_copy(p, parent->d_params);
- apr_table_overlap(newconf->d_params, child->d_params,
- APR_OVERLAP_TABLES_SET);
-
- return newconf;
-}
-
-apr_table_t *dav_get_dir_params(const request_rec *r)
-{
- dav_dir_conf *conf;
-
- conf = ap_get_module_config(r->per_dir_config, &dav_module);
- return conf->d_params;
-}
-
-static const dav_provider * dav_get_provider(request_rec *r)
-{
- dav_dir_conf *conf;
-
- conf = ap_get_module_config(r->per_dir_config, &dav_module);
- /* assert: conf->provider_name != NULL
- (otherwise, DAV is disabled, and we wouldn't be here) */
-
- /* assert: conf->provider != NULL
- (checked when conf->provider_name is set) */
- return conf->provider;
-}
-
-const dav_hooks_locks *dav_get_lock_hooks(request_rec *r)
-{
- return dav_get_provider(r)->locks;
-}
-
-const dav_hooks_propdb *dav_get_propdb_hooks(request_rec *r)
-{
- return dav_get_provider(r)->propdb;
-}
-
-const dav_hooks_vsn *dav_get_vsn_hooks(request_rec *r)
-{
- return dav_get_provider(r)->vsn;
-}
-
-const dav_hooks_binding *dav_get_binding_hooks(request_rec *r)
-{
- return dav_get_provider(r)->binding;
-}
-
-/*
- * Command handler for the DAV directive, which is TAKE1.
- */
-static const char *dav_cmd_dav(cmd_parms *cmd, void *config, const char *arg1)
-{
- dav_dir_conf *conf = (dav_dir_conf *) config;
-
- if (strcasecmp(arg1, "on") == 0) {
- conf->provider_name = DAV_DEFAULT_PROVIDER;
- }
- else if (strcasecmp(arg1, "off") == 0) {
- conf->provider_name = NULL;
- conf->provider = NULL;
- }
- else {
- conf->provider_name = apr_pstrdup(cmd->pool, arg1);
- }
-
- if (conf->provider_name != NULL) {
- /* lookup and cache the actual provider now */
- conf->provider = dav_lookup_provider(conf->provider_name);
-
- if (conf->provider == NULL) {
- /* by the time they use it, the provider should be loaded and
- registered with us. */
- return apr_psprintf(cmd->pool,
- "Unknown DAV provider: %s",
- conf->provider_name);
- }
- }
-
- return NULL;
-}
-
-/*
- * Command handler for the DAVDepthInfinity directive, which is FLAG.
- */
-static const char *dav_cmd_davdepthinfinity(cmd_parms *cmd, void *config,
- int arg)
-{
- dav_dir_conf *conf = (dav_dir_conf *) config;
-
- if (arg)
- conf->allow_depthinfinity = DAV_ENABLED_ON;
- else
- conf->allow_depthinfinity = DAV_ENABLED_OFF;
- return NULL;
-}
-
-/*
- * Command handler for DAVMinTimeout directive, which is TAKE1
- */
-static const char *dav_cmd_davmintimeout(cmd_parms *cmd, void *config,
- const char *arg1)
-{
- dav_dir_conf *conf = (dav_dir_conf *) config;
-
- conf->locktimeout = atoi(arg1);
- if (conf->locktimeout < 0)
- return "DAVMinTimeout requires a non-negative integer.";
-
- return NULL;
-}
-
-/*
- * Command handler for DAVParam directive, which is TAKE2
- */
-static const char *dav_cmd_davparam(cmd_parms *cmd, void *config,
- const char *arg1, const char *arg2)
-{
- dav_dir_conf *conf = (dav_dir_conf *) config;
-
- apr_table_set(conf->d_params, arg1, arg2);
-
- return NULL;
-}
-
-/*
-** dav_error_response()
-**
-** Send a nice response back to the user. In most cases, Apache doesn't
-** allow us to provide details in the body about what happened. This
-** function allows us to completely specify the response body.
-**
-** ### this function is not logging any errors! (e.g. the body)
-*/
-static int dav_error_response(request_rec *r, int status, const char *body)
-{
- r->status = status;
- r->status_line = ap_get_status_line(status); /* ### needed? */
- r->content_type = "text/html";
-
- /* since we're returning DONE, ensure the request body is consumed. */
- (void) ap_discard_request_body(r);
-
- /* begin the response now... */
- ap_rvputs(r,
- DAV_RESPONSE_BODY_1,
- r->status_line,
- DAV_RESPONSE_BODY_2,
- &r->status_line[4],
- DAV_RESPONSE_BODY_3,
- NULL);
-
- ap_rputs(body, r);
-
- ap_rputs(ap_psignature("\n<P><HR>\n", r), r);
- ap_rputs(DAV_RESPONSE_BODY_4, r);
-
- /* the response has been sent. */
- /*
- * ### Use of DONE obviates logging..!
- */
- return DONE;
-}
-
-/*
-** Apache's URI escaping does not replace '&' since that is a valid character
-** in a URI (to form a query section). We must explicitly handle it so that
-** we can embed the URI into an XML document.
-*/
-static const char *dav_xml_escape_uri(apr_pool_t *p, const char *uri)
-{
- const char *e_uri = ap_escape_uri(p, uri);
-
- /* check the easy case... */
- if (ap_strchr_c(e_uri, '&') == NULL)
- return e_uri;
-
- /* there was a '&', so more work is needed... sigh. */
-
- /*
- ** Note: this is a teeny bit of overkill since we know there are no
- ** '<' or '>' characters, but who cares.
- */
- return ap_xml_quote_string(p, e_uri, 0);
-}
-
-static void dav_send_multistatus(request_rec *r, int status,
- dav_response *first,
- apr_array_header_t *namespaces)
-{
- /* Set the correct status and Content-Type */
- r->status = status;
- r->content_type = DAV_XML_CONTENT_TYPE;
-
- /* Send the headers and actual multistatus response now... */
- ap_rputs(DAV_XML_HEADER DEBUG_CR
- "<D:multistatus xmlns:D=\"DAV:\"", r);
-
- if (namespaces != NULL) {
- int i;
-
- for (i = namespaces->nelts; i--; ) {
- ap_rprintf(r, " xmlns:ns%d=\"%s\"", i,
- AP_XML_GET_URI_ITEM(namespaces, i));
- }
- }
-
- /* ap_rputc('>', r); */
- ap_rputs(">" DEBUG_CR, r);
-
- for (; first != NULL; first = first->next) {
- ap_text *t;
-
- if (first->propresult.xmlns == NULL) {
- ap_rputs("<D:response>", r);
- }
- else {
- ap_rputs("<D:response", r);
- for (t = first->propresult.xmlns; t; t = t->next) {
- ap_rputs(t->text, r);
- }
- ap_rputc('>', r);
- }
-
- ap_rputs(DEBUG_CR "<D:href>", r);
- ap_rputs(dav_xml_escape_uri(r->pool, first->href), r);
- ap_rputs("</D:href>" DEBUG_CR, r);
-
- if (first->propresult.propstats == NULL) {
- /* use the Status-Line text from Apache. Note, this will
- * default to 500 Internal Server Error if first->status
- * is not a known (or valid) status code. */
- ap_rprintf(r,
- "<D:status>HTTP/1.1 %s</D:status>" DEBUG_CR,
- ap_get_status_line(first->status));
- }
- else {
- /* assume this includes <propstat> and is quoted properly */
- for (t = first->propresult.propstats; t; t = t->next) {
- ap_rputs(t->text, r);
- }
- }
-
- if (first->desc != NULL) {
- /*
- ** We supply the description, so we know it doesn't have to
- ** have any escaping/encoding applied to it.
- */
- ap_rputs("<D:responsedescription>", r);
- ap_rputs(first->desc, r);
- ap_rputs("</D:responsedescription>" DEBUG_CR, r);
- }
-
- ap_rputs("</D:response>" DEBUG_CR, r);
- }
-
- ap_rputs("</D:multistatus>" DEBUG_CR, r);
-}
-
-/*
-** dav_log_err()
-**
-** Write error information to the log.
-*/
-static void dav_log_err(request_rec *r, dav_error *err, int level)
-{
- dav_error *errscan;
-
- /* Log the errors */
- /* ### should have a directive to log the first or all */
- for (errscan = err; errscan != NULL; errscan = errscan->prev) {
- if (errscan->desc == NULL)
- continue;
- if (errscan->save_errno != 0) {
- errno = errscan->save_errno;
- ap_log_rerror(APLOG_MARK, level, errno, r, "%s [%d, #%d]",
- errscan->desc, errscan->status, errscan->error_id);
- }
- else {
- ap_log_rerror(APLOG_MARK, level | APLOG_NOERRNO, 0, r,
- "%s [%d, #%d]",
- errscan->desc, errscan->status, errscan->error_id);
- }
- }
-}
-
-/*
-** dav_handle_err()
-**
-** Handle the standard error processing. <err> must be non-NULL.
-**
-** <response> is set by the following:
-** - dav_validate_request()
-** - dav_add_lock()
-** - repos_hooks->remove_resource
-** - repos_hooks->move_resource
-** - repos_hooks->copy_resource
-** - vsn_hooks->update
-*/
-static int dav_handle_err(request_rec *r, dav_error *err,
- dav_response *response)
-{
- /* log the errors */
- dav_log_err(r, err, APLOG_ERR);
-
- if (response == NULL) {
- /* our error messages are safe; tell Apache this */
- apr_table_setn(r->notes, "verbose-error-to", "*");
- return err->status;
- }
-
- /* since we're returning DONE, ensure the request body is consumed. */
- (void) ap_discard_request_body(r);
-
- /* send the multistatus and tell Apache the request/response is DONE. */
- dav_send_multistatus(r, err->status, response, NULL);
- return DONE;
-}
-
-/* handy function for return values of methods that (may) create things */
-static int dav_created(request_rec *r, const char *locn, const char *what,
- int replaced)
-{
- const char *body;
-
- if (locn == NULL) {
- locn = r->uri;
- }
-
- /* did the target resource already exist? */
- if (replaced) {
- /* Apache will supply a default message */
- return HTTP_NO_CONTENT;
- }
-
- /* Per HTTP/1.1, S10.2.2: add a Location header to contain the
- * URI that was created. */
-
- /* Convert locn to an absolute URI, and return in Location header */
- apr_table_setn(r->headers_out, "Location", ap_construct_url(r->pool, locn, r));
-
- /* ### insert an ETag header? see HTTP/1.1 S10.2.2 */
-
- /* Apache doesn't allow us to set a variable body for HTTP_CREATED, so
- * we must manufacture the entire response. */
- body = apr_psprintf(r->pool, "%s %s has been created.",
- what, ap_escape_html(r->pool, locn));
- return dav_error_response(r, HTTP_CREATED, body);
-}
-
-/* ### move to dav_util? */
-int dav_get_depth(request_rec *r, int def_depth)
-{
- const char *depth = apr_table_get(r->headers_in, "Depth");
-
- if (depth == NULL) {
- return def_depth;
- }
- if (strcasecmp(depth, "infinity") == 0) {
- return DAV_INFINITY;
- }
- else if (strcmp(depth, "0") == 0) {
- return 0;
- }
- else if (strcmp(depth, "1") == 0) {
- return 1;
- }
-
- /* The caller will return an HTTP_BAD_REQUEST. This will augment the
- * default message that Apache provides. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "An invalid Depth header was specified.");
- return -1;
-}
-
-static int dav_get_overwrite(request_rec *r)
-{
- const char *overwrite = apr_table_get(r->headers_in, "Overwrite");
-
- if (overwrite == NULL) {
- return 1; /* default is "T" */
- }
-
- if ((*overwrite == 'F' || *overwrite == 'f') && overwrite[1] == '\0') {
- return 0;
- }
- if ((*overwrite == 'T' || *overwrite == 't') && overwrite[1] == '\0') {
- return 1;
- }
-
- /* The caller will return an HTTP_BAD_REQUEST. This will augment the
- * default message that Apache provides. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "An invalid Overwrite header was specified.");
- return -1;
-}
-
-/* resolve a request URI to a resource descriptor.
- *
- * If label_allowed != 0, then allow the request target to be altered by
- * a Label: header.
- *
- * If use_checked_in is true, then the repository provider should return
- * the resource identified by the DAV:checked-in property of the resource
- * identified by the Request-URI.
- */
-static dav_error * dav_get_resource(request_rec *r, int label_allowed,
- int use_checked_in, dav_resource **res_p)
-{
- dav_dir_conf *conf;
- const char *label = NULL;
- dav_error *err;
-
- /* if the request target can be overridden, get any target selector */
- if (label_allowed) {
- label = apr_table_get(r->headers_in, "label");
- }
-
- conf = ap_get_module_config(r->per_dir_config, &dav_module);
- /* assert: conf->provider != NULL */
-
- /* resolve the resource */
- err = (*conf->provider->repos->get_resource)(r, conf->dir,
- label, use_checked_in,
- res_p);
- if (err != NULL) {
- err = dav_push_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
- "Could not fetch resource information.", err);
- return err;
- }
-
- /* Note: this shouldn't happen, but just be sure... */
- if (*res_p == NULL) {
- /* ### maybe use HTTP_INTERNAL_SERVER_ERROR */
- return dav_new_error(r->pool, HTTP_NOT_FOUND, 0,
- apr_psprintf(r->pool,
- "The provider did not define a "
- "resource for %s.",
- ap_escape_html(r->pool, r->uri)));
- }
-
- /* ### hmm. this doesn't feel like the right place or thing to do */
- /* if there were any input headers requiring a Vary header in the response,
- * add it now */
- dav_add_vary_header(r, r, *res_p);
-
- return NULL;
-}
-
-static dav_error * dav_open_lockdb(request_rec *r, int ro, dav_lockdb **lockdb)
-{
- const dav_hooks_locks *hooks = DAV_GET_HOOKS_LOCKS(r);
-
- if (hooks == NULL) {
- *lockdb = NULL;
- return NULL;
- }
-
- /* open the thing lazily */
- return (*hooks->open_lockdb)(r, ro, 0, lockdb);
-}
-
-static int dav_parse_range(request_rec *r,
- apr_off_t *range_start, apr_off_t *range_end)
-{
- const char *range_c;
- char *range;
- char *dash;
- char *slash;
-
- range_c = apr_table_get(r->headers_in, "content-range");
- if (range_c == NULL)
- return 0;
-
- range = apr_pstrdup(r->pool, range_c);
- if (strncasecmp(range, "bytes ", 6) != 0
- || (dash = ap_strchr(range, '-')) == NULL
- || (slash = ap_strchr(range, '/')) == NULL) {
- /* malformed header. ignore it (per S14.16 of RFC2616) */
- return 0;
- }
-
- *dash = *slash = '\0';
-
- /* ### atol may not be large enough for the apr_off_t */
- *range_start = atol(range + 6);
- *range_end = atol(dash + 1);
-
- if (*range_end < *range_start
- || (slash[1] != '*' && atol(slash + 1) <= *range_end)) {
- /* invalid range. ignore it (per S14.16 of RFC2616) */
- return 0;
- }
-
- /* we now have a valid range */
- return 1;
-}
-
-/* handle the GET method */
-static int dav_method_get(request_rec *r)
-{
- dav_resource *resource;
- int result;
- dav_error *err;
-
- /* This method should only be called when the resource is not
- * visible to Apache. We will fetch the resource from the repository,
- * then create a subrequest for Apache to handle.
- */
- err = dav_get_resource(r, 1 /* label_allowed */, 0 /* use_checked_in */,
- &resource);
- if (err != NULL)
- return dav_handle_err(r, err, NULL);
- if (!resource->exists) {
- /* Apache will supply a default error for this. */
- return HTTP_NOT_FOUND;
- }
-
- /* Check resource type */
- if (resource->type != DAV_RESOURCE_TYPE_REGULAR &&
- resource->type != DAV_RESOURCE_TYPE_VERSION &&
- resource->type != DAV_RESOURCE_TYPE_WORKING)
- {
- return dav_error_response(r, HTTP_CONFLICT,
- "Cannot GET this type of resource.");
- }
-
- /* Cannot handle GET of a collection from a repository */
- if (resource->collection) {
- return dav_error_response(r, HTTP_CONFLICT,
- "No default response to GET for a "
- "collection.");
- }
-
- /*
- ** We can use two different approaches for a GET.
- **
- ** 1) get_pathname will return a pathname to a file which should be
- ** sent to the client. If the repository provides this, then we
- ** use it.
- **
- ** This is the best alternative since it allows us to do a sub-
- ** request on the file, which gives the Apache framework a chance
- ** to deal with negotiation, MIME types, or whatever.
- **
- ** 2) open_stream and read_stream.
- */
- if (resource->hooks->get_pathname != NULL) {
- const char *pathname;
- void *fhandle;
- request_rec *new_req;
-
- /* Ask repository for copy of file */
- pathname = (*resource->hooks->get_pathname)(resource, &fhandle);
- if (pathname == NULL) {
- return HTTP_NOT_FOUND;
- }
-
- /* Convert to canonical filename, so Apache detects component
- * separators (on Windows, it only looks for '/', not '\')
- */
- pathname = ap_os_case_canonical_filename(r->pool, pathname);
-
- /* Create a sub-request with the new filename */
- new_req = ap_sub_req_lookup_file(pathname, r, NULL);
- if (new_req == NULL) {
- (*resource->hooks->free_file)(fhandle);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- /* This may be a HEAD request */
- new_req->header_only = r->header_only;
-
- /* ### this enables header generation */
- new_req->assbackwards = 0;
-
- /* Run the sub-request */
- result = ap_run_sub_req(new_req);
- ap_destroy_sub_req(new_req);
-
- /* Free resources */
- (*resource->hooks->free_file)(fhandle);
-
- return result;
- }
- else {
- dav_stream_mode mode;
- dav_stream *stream;
- dav_error *err;
- void *buffer;
- int has_range;
- apr_off_t range_start;
- apr_off_t range_end;
-
- /* set up the HTTP headers for the response */
- if ((err = (*resource->hooks->set_headers)(r, resource)) != NULL) {
- err = dav_push_error(r->pool, err->status, 0,
- "Unable to set up HTTP headers.",
- err);
- return dav_handle_err(r, err, NULL);
- }
-
- /* use plain READ mode unless we see a Content-Range */
- mode = DAV_MODE_READ;
-
- /* process the Content-Range header (if present) */
- has_range = dav_parse_range(r, &range_start, &range_end);
- if (has_range) {
- /* use a read mode which is seekable */
- mode = DAV_MODE_READ_SEEKABLE;
-
- /* prep the output */
- r->status = HTTP_PARTIAL_CONTENT;
- apr_table_setn(r->headers_out,
- "Content-Range",
- apr_psprintf(r->pool,
- "bytes %" APR_OFF_T_FMT
- "-%" APR_OFF_T_FMT "/*",
- range_start, range_end));
- ap_set_content_length(r, range_end - range_start + 1);
- }
-
- if (r->header_only) {
- return DONE;
- }
-
- if ((err = (*resource->hooks->open_stream)(resource, mode,
- &stream)) != NULL) {
- /* ### assuming FORBIDDEN is probably not quite right... */
- err = dav_push_error(r->pool, HTTP_FORBIDDEN, 0,
- apr_psprintf(r->pool,
- "Unable to GET contents for %s.",
- ap_escape_html(r->pool, r->uri)),
- err);
- return dav_handle_err(r, err, NULL);
- }
-
- if (has_range
- && (err = (*resource->hooks->seek_stream)(stream,
- range_start)) != NULL) {
- err = dav_push_error(r->pool, err->status, 0,
- "Could not seek to beginning of the "
- "specified Content-Range.", err);
- return dav_handle_err(r, err, NULL);
- }
-
- buffer = apr_palloc(r->pool, DAV_READ_BLOCKSIZE);
- while (1) {
- apr_size_t amt;
-
- if (!has_range)
- amt = DAV_READ_BLOCKSIZE;
- else if ((range_end - range_start + 1) > DAV_READ_BLOCKSIZE)
- amt = DAV_READ_BLOCKSIZE;
- else {
- /* note: range_end - range_start is an ssize_t */
- amt = (apr_size_t)(range_end - range_start + 1);
- }
-
- if ((err = (*resource->hooks->read_stream)(stream, buffer,
- &amt)) != NULL) {
- break;
- }
- if (amt == 0) {
- /* no more content */
- break;
- }
- if (ap_rwrite(buffer, amt, r) < 0) {
- /* ### what to do with this error? */
- break;
- }
-
- if (has_range) {
- range_start += amt;
- if (range_start > range_end)
- break;
- }
- }
-
- if (err != NULL)
- return dav_handle_err(r, err, NULL);
-
- /*
- ** ### range_start should equal range_end+1. if it doesn't, then
- ** ### we did not send enough data to the client. the client will
- ** ### hang (and timeout) waiting for the data.
- **
- ** ### what to do? abort the connection?
- */
- return DONE;
- }
-
- /* NOTREACHED */
-}
-
-/* validate resource on POST, then pass it off to the default handler */
-static int dav_method_post(request_rec *r)
-{
- dav_resource *resource;
- dav_error *err;
-
- /* Ask repository module to resolve the resource */
- err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
- &resource);
- if (err != NULL)
- return dav_handle_err(r, err, NULL);
-
- /* Note: depth == 0. Implies no need for a multistatus response. */
- if ((err = dav_validate_request(r, resource, 0, NULL, NULL,
- DAV_VALIDATE_RESOURCE, NULL)) != NULL) {
- /* ### add a higher-level description? */
- return dav_handle_err(r, err, NULL);
- }
-
- return DECLINED;
-}
-
-/* handle the PUT method */
-static int dav_method_put(request_rec *r)
-{
- dav_resource *resource;
- int resource_state;
- dav_auto_version_info av_info;
- const dav_hooks_locks *locks_hooks = DAV_GET_HOOKS_LOCKS(r);
- const char *body;
- dav_error *err;
- dav_error *err2;
- int result;
- dav_stream_mode mode;
- dav_stream *stream;
- dav_response *multi_response;
- int has_range;
- apr_off_t range_start;
- apr_off_t range_end;
-
- if ((result = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK)) != OK) {
- return result;
- }
-
- /* Ask repository module to resolve the resource */
- err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
- &resource);
- if (err != NULL)
- return dav_handle_err(r, err, NULL);
-
- /* If not a file or collection resource, PUT not allowed */
- if (resource->type != DAV_RESOURCE_TYPE_REGULAR
- && resource->type != DAV_RESOURCE_TYPE_WORKING) {
- body = apr_psprintf(r->pool,
- "Cannot create resource %s with PUT.",
- ap_escape_html(r->pool, r->uri));
- return dav_error_response(r, HTTP_CONFLICT, body);
- }
-
- /* Cannot PUT a collection */
- if (resource->collection) {
- return dav_error_response(r, HTTP_CONFLICT,
- "Cannot PUT to a collection.");
-
- }
-
- resource_state = dav_get_resource_state(r, resource);
-
- /*
- ** Note: depth == 0 normally requires no multistatus response. However,
- ** if we pass DAV_VALIDATE_PARENT, then we could get an error on a URI
- ** other than the Request-URI, thereby requiring a multistatus.
- **
- ** If the resource does not exist (DAV_RESOURCE_NULL), then we must
- ** check the resource *and* its parent. If the resource exists or is
- ** a locknull resource, then we check only the resource.
- */
- if ((err = dav_validate_request(r, resource, 0, NULL, &multi_response,
- resource_state == DAV_RESOURCE_NULL ?
- DAV_VALIDATE_PARENT :
- DAV_VALIDATE_RESOURCE, NULL)) != NULL) {
- /* ### add a higher-level description? */
- return dav_handle_err(r, err, multi_response);
- }
-
- /* make sure the resource can be modified (if versioning repository) */
- if ((err = dav_auto_checkout(r, resource,
- 0 /* not parent_only */,
- &av_info)) != NULL) {
- /* ### add a higher-level description? */
- return dav_handle_err(r, err, NULL);
- }
-
- /* truncate and rewrite the file unless we see a Content-Range */
- mode = DAV_MODE_WRITE_TRUNC;
-
- has_range = dav_parse_range(r, &range_start, &range_end);
- if (has_range) {
- mode = DAV_MODE_WRITE_SEEKABLE;
- }
-
- /* Create the new file in the repository */
- if ((err = (*resource->hooks->open_stream)(resource, mode,
- &stream)) != NULL) {
- /* ### assuming FORBIDDEN is probably not quite right... */
- err = dav_push_error(r->pool, HTTP_FORBIDDEN, 0,
- apr_psprintf(r->pool,
- "Unable to PUT new contents for %s.",
- ap_escape_html(r->pool, r->uri)),
- err);
- }
-
- if (err == NULL && has_range) {
- /* a range was provided. seek to the start */
- err = (*resource->hooks->seek_stream)(stream, range_start);
- }
-
- if (err == NULL) {
- if (ap_should_client_block(r)) {
- char *buffer = apr_palloc(r->pool, DAV_READ_BLOCKSIZE);
- long len;
-
- /*
- ** Once we start reading the request, then we must read the
- ** whole darn thing. ap_discard_request_body() won't do anything
- ** for a partially-read request.
- */
-
- while ((len = ap_get_client_block(r, buffer,
- DAV_READ_BLOCKSIZE)) > 0) {
- if (err == NULL) {
- /* write whatever we read, until we see an error */
- err = (*resource->hooks->write_stream)(stream,
- buffer, len);
- }
- }
-
- /*
- ** ### what happens if we read more/less than the amount
- ** ### specified in the Content-Range? eek...
- */
-
- if (len == -1) {
- /*
- ** Error reading request body. This has precedence over
- ** prior errors.
- */
- err = dav_new_error(r->pool, HTTP_BAD_REQUEST, 0,
- "An error occurred while reading the "
- "request body.");
- }
- }
-
- err2 = (*resource->hooks->close_stream)(stream,
- err == NULL /* commit */);
- if (err2 != NULL && err == NULL) {
- /* no error during the write, but we hit one at close. use it. */
- err = err2;
- }
- }
-
- /*
- ** Ensure that we think the resource exists now.
- ** ### eek. if an error occurred during the write and we did not commit,
- ** ### then the resource might NOT exist (e.g. dav_fs_repos.c)
- */
- if (err == NULL) {
- resource->exists = 1;
- }
-
- /* restore modifiability of resources back to what they were */
- err2 = dav_auto_checkin(r, resource, err != NULL /* undo if error */,
- 0 /*unlock*/, &av_info);
-
- /* check for errors now */
- if (err != NULL) {
- return dav_handle_err(r, err, NULL);
- }
- if (err2 != NULL) {
- /* just log a warning */
- err2 = dav_push_error(r->pool, err->status, 0,
- "The PUT was successful, but there "
- "was a problem automatically checking in "
- "the resource or its parent collection.",
- err2);
- dav_log_err(r, err2, APLOG_WARNING);
- }
-
- /* ### place the Content-Type and Content-Language into the propdb */
-
- if (locks_hooks != NULL) {
- dav_lockdb *lockdb;
-
- if ((err = (*locks_hooks->open_lockdb)(r, 0, 0, &lockdb)) != NULL) {
- /* The file creation was successful, but the locking failed. */
- err = dav_push_error(r->pool, err->status, 0,
- "The file was PUT successfully, but there "
- "was a problem opening the lock database "
- "which prevents inheriting locks from the "
- "parent resources.",
- err);
- return dav_handle_err(r, err, NULL);
- }
-
- /* notify lock system that we have created/replaced a resource */
- err = dav_notify_created(r, lockdb, resource, resource_state, 0);
-
- (*locks_hooks->close_lockdb)(lockdb);
-
- if (err != NULL) {
- /* The file creation was successful, but the locking failed. */
- err = dav_push_error(r->pool, err->status, 0,
- "The file was PUT successfully, but there "
- "was a problem updating its lock "
- "information.",
- err);
- return dav_handle_err(r, err, NULL);
- }
- }
-
- /* NOTE: WebDAV spec, S8.7.1 states properties should be unaffected */
-
- /* return an appropriate response (HTTP_CREATED or HTTP_NO_CONTENT) */
- return dav_created(r, NULL, "Resource", resource_state == DAV_RESOURCE_EXISTS);
-}
-
-/* ### move this to dav_util? */
-DAV_DECLARE(void) dav_add_response(dav_walk_resource *wres,
- int status, dav_get_props_result *propstats)
-{
- dav_response *resp;
-
- /* just drop some data into an dav_response */
- resp = apr_pcalloc(wres->pool, sizeof(*resp));
- resp->href = apr_pstrdup(wres->pool, wres->resource->uri);
- resp->status = status;
- if (propstats) {
- resp->propresult = *propstats;
- }
-
- resp->next = wres->response;
- wres->response = resp;
-}
-
-/* handle the DELETE method */
-static int dav_method_delete(request_rec *r)
-{
- dav_resource *resource;
- dav_auto_version_info av_info;
- dav_error *err;
- dav_error *err2;
- dav_response *multi_response;
- int result;
- int depth;
-
- /* We don't use the request body right now, so torch it. */
- if ((result = ap_discard_request_body(r)) != OK) {
- return result;
- }
-
- /* Ask repository module to resolve the resource */
- err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
- &resource);
- if (err != NULL)
- return dav_handle_err(r, err, NULL);
- if (!resource->exists) {
- /* Apache will supply a default error for this. */
- return HTTP_NOT_FOUND;
- }
-
- /* 2518 says that depth must be infinity only for collections.
- * For non-collections, depth is ignored, unless it is an illegal value (1).
- */
- depth = dav_get_depth(r, DAV_INFINITY);
-
- if (resource->collection && depth != DAV_INFINITY) {
- /* This supplies additional information for the default message. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "Depth must be \"infinity\" for DELETE of a collection.");
- return HTTP_BAD_REQUEST;
- }
- if (!resource->collection && depth == 1) {
- /* This supplies additional information for the default message. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "Depth of \"1\" is not allowed for DELETE.");
- return HTTP_BAD_REQUEST;
- }
-
- /*
- ** If any resources fail the lock/If: conditions, then we must fail
- ** the delete. Each of the failing resources will be listed within
- ** a DAV:multistatus body, wrapped into a 424 response.
- **
- ** Note that a failure on the resource itself does not generate a
- ** multistatus response -- only internal members/collections.
- */
- if ((err = dav_validate_request(r, resource, depth, NULL,
- &multi_response,
- DAV_VALIDATE_PARENT
- | DAV_VALIDATE_USE_424, NULL)) != NULL) {
- err = dav_push_error(r->pool, err->status, 0,
- apr_psprintf(r->pool,
- "Could not DELETE %s due to a failed "
- "precondition (e.g. locks).",
- ap_escape_html(r->pool, r->uri)),
- err);
- return dav_handle_err(r, err, multi_response);
- }
-
- /* ### RFC 2518 s. 8.10.5 says to remove _all_ locks, not just those
- * locked by the token(s) in the if_header.
- */
- if ((result = dav_unlock(r, resource, NULL)) != OK) {
- return result;
- }
-
- /* if versioned resource, make sure parent is checked out */
- if ((err = dav_auto_checkout(r, resource, 1 /* parent_only */,
- &av_info)) != NULL) {
- /* ### add a higher-level description? */
- return dav_handle_err(r, err, NULL);
- }
-
- /* try to remove the resource */
- err = (*resource->hooks->remove_resource)(resource, &multi_response);
-
- /* restore writability of parent back to what it was */
- err2 = dav_auto_checkin(r, NULL, err != NULL /* undo if error */,
- 0 /*unlock*/, &av_info);
-
- /* check for errors now */
- if (err != NULL) {
- err = dav_push_error(r->pool, err->status, 0,
- apr_psprintf(r->pool,
- "Could not DELETE %s.",
- ap_escape_html(r->pool, r->uri)),
- err);
- return dav_handle_err(r, err, multi_response);
- }
- if (err2 != NULL) {
- /* just log a warning */
- err = dav_push_error(r->pool, err2->status, 0,
- "The DELETE was successful, but there "
- "was a problem automatically checking in "
- "the parent collection.",
- err2);
- dav_log_err(r, err, APLOG_WARNING);
- }
-
- /* ### HTTP_NO_CONTENT if no body, HTTP_OK if there is a body (some day) */
-
- /* Apache will supply a default error for this. */
- return HTTP_NO_CONTENT;
-}
-
-/* generate DAV:supported-method-set OPTIONS response */
-static dav_error *dav_gen_supported_methods(request_rec *r,
- const ap_xml_elem *elem,
- const apr_table_t *methods,
- ap_text_header *body)
-{
- apr_array_header_t *arr;
- apr_table_entry_t *elts;
- ap_xml_elem *child;
- ap_xml_attr *attr;
- char *s;
- int i;
-
- ap_text_append(r->pool, body, "<D:supported-method-set>" DEBUG_CR);
-
- if (elem->first_child == NULL) {
- /* show all supported methods */
- arr = apr_table_elts(methods);
- elts = (apr_table_entry_t *) arr->elts;
-
- for (i = 0; i < arr->nelts; ++i) {
- if (elts[i].key == NULL)
- continue;
- s = apr_psprintf(r->pool,
- "<D:supported-method D:name=\"%s\"/>" DEBUG_CR,
- elts[i].key);
- ap_text_append(r->pool, body, s);
- }
- }
- else {
- /* check for support of specific methods */
- for (child = elem->first_child; child != NULL; child = child->next) {
- if (child->ns == AP_XML_NS_DAV_ID
- && strcmp(child->name, "supported-method") == 0) {
- const char *name = NULL;
-
- /* go through attributes to find method name */
- for (attr = child->attr; attr != NULL; attr = attr->next) {
- if (attr->ns == AP_XML_NS_DAV_ID
- && strcmp(attr->name, "name") == 0)
- name = attr->value;
- }
-
- if (name == NULL) {
- return dav_new_error(r->pool, HTTP_BAD_REQUEST, 0,
- "A DAV:supported-method element "
- "does not have a \"name\" attribute");
- }
-
- /* see if method is supported */
- if (apr_table_get(methods, name) != NULL) {
- s = apr_psprintf(r->pool,
- "<D:supported-method D:name=\"%s\"/>" DEBUG_CR,
- name);
- ap_text_append(r->pool, body, s);
- }
- }
- }
- }
-
- ap_text_append(r->pool, body, "</D:supported-method-set>" DEBUG_CR);
- return NULL;
-}
-
-/* generate DAV:supported-live-property-set OPTIONS response */
-static dav_error *dav_gen_supported_live_props(request_rec *r,
- const dav_resource *resource,
- const ap_xml_elem *elem,
- ap_text_header *body)
-{
- dav_lockdb *lockdb;
- dav_propdb *propdb;
- ap_xml_elem *child;
- ap_xml_attr *attr;
- dav_error *err;
-
- /* open lock database, to report on supported lock properties */
- /* ### should open read-only */
- if ((err = dav_open_lockdb(r, 0, &lockdb)) != NULL) {
- return dav_push_error(r->pool, err->status, 0,
- "The lock database could not be opened, "
- "preventing the reporting of supported lock "
- "properties.",
- err);
- }
-
- /* open the property database (readonly) for the resource */
- if ((err = dav_open_propdb(r, lockdb, resource, 1, NULL,
- &propdb)) != NULL) {
- if (lockdb != NULL)
- (*lockdb->hooks->close_lockdb)(lockdb);
-
- return dav_push_error(r->pool, err->status, 0,
- "The property database could not be opened, "
- "preventing report of supported properties.",
- err);
- }
-
- ap_text_append(r->pool, body, "<D:supported-live-property-set>" DEBUG_CR);
-
- if (elem->first_child == NULL) {
- /* show all supported live properties */
- dav_get_props_result props = dav_get_allprops(propdb, DAV_PROP_INSERT_SUPPORTED);
- body->last->next = props.propstats;
- while (body->last->next != NULL)
- body->last = body->last->next;
- }
- else {
- /* check for support of specific live property */
- for (child = elem->first_child; child != NULL; child = child->next) {
- if (child->ns == AP_XML_NS_DAV_ID
- && strcmp(child->name, "supported-live-property") == 0) {
- const char *name = NULL;
- const char *nmspace = NULL;
-
- /* go through attributes to find name and namespace */
- for (attr = child->attr; attr != NULL; attr = attr->next) {
- if (attr->ns == AP_XML_NS_DAV_ID) {
- if (strcmp(attr->name, "name") == 0)
- name = attr->value;
- else if (strcmp(attr->name, "namespace") == 0)
- nmspace = attr->value;
- }
- }
-
- if (name == NULL) {
- err = dav_new_error(r->pool, HTTP_BAD_REQUEST, 0,
- "A DAV:supported-live-property "
- "element does not have a \"name\" "
- "attribute");
- break;
- }
-
- /* default namespace to DAV: */
- if (nmspace == NULL)
- nmspace = "DAV:";
-
- /* check for support of property */
- dav_get_liveprop_supported(propdb, nmspace, name, body);
- }
- }
- }
-
- ap_text_append(r->pool, body, "</D:supported-live-property-set>" DEBUG_CR);
-
- dav_close_propdb(propdb);
-
- if (lockdb != NULL)
- (*lockdb->hooks->close_lockdb)(lockdb);
-
- return err;
-}
-
-/* generate DAV:supported-report-set OPTIONS response */
-static dav_error *dav_gen_supported_reports(request_rec *r,
- const dav_resource *resource,
- const ap_xml_elem *elem,
- const dav_hooks_vsn *vsn_hooks,
- ap_text_header *body)
-{
- ap_xml_elem *child;
- ap_xml_attr *attr;
- dav_error *err;
- char *s;
-
- ap_text_append(r->pool, body, "<D:supported-report-set>" DEBUG_CR);
-
- if (vsn_hooks != NULL) {
- const dav_report_elem *reports;
- const dav_report_elem *rp;
-
- if ((err = (*vsn_hooks->avail_reports)(resource, &reports)) != NULL) {
- return dav_push_error(r->pool, err->status, 0,
- "DAV:supported-report-set could not be "
- "determined due to a problem fetching the "
- "available reports for this resource.",
- err);
- }
-
- if (reports != NULL) {
- if (elem->first_child == NULL) {
- /* show all supported reports */
- for (rp = reports; rp->nmspace != NULL; ++rp) {
- /* Note: we presume reports->namespace is properly XML/URL quoted */
- s = apr_psprintf(r->pool,
- "<D:supported-report D:name=\"%s\" D:namespace=\"%s\"/>" DEBUG_CR,
- rp->name, rp->nmspace);
- ap_text_append(r->pool, body, s);
- }
- }
- else {
- /* check for support of specific report */
- for (child = elem->first_child; child != NULL; child = child->next) {
- if (child->ns == AP_XML_NS_DAV_ID
- && strcmp(child->name, "supported-report") == 0) {
- const char *name = NULL;
- const char *nmspace = NULL;
-
- /* go through attributes to find name and namespace */
- for (attr = child->attr; attr != NULL; attr = attr->next) {
- if (attr->ns == AP_XML_NS_DAV_ID) {
- if (strcmp(attr->name, "name") == 0)
- name = attr->value;
- else if (strcmp(attr->name, "namespace") == 0)
- nmspace = attr->value;
- }
- }
-
- if (name == NULL) {
- return dav_new_error(r->pool, HTTP_BAD_REQUEST, 0,
- "A DAV:supported-report element "
- "does not have a \"name\" attribute");
- }
-
- /* default namespace to DAV: */
- if (nmspace == NULL)
- nmspace = "DAV:";
-
- for (rp = reports; rp->nmspace != NULL; ++rp) {
- if (strcmp(name, rp->name) == 0
- && strcmp(nmspace, rp->nmspace) == 0) {
- /* Note: we presume reports->nmspace is properly XML/URL quoted */
- s = apr_psprintf(r->pool,
- "<D:supported-report D:name=\"%s\" D:namespace=\"%s\"/>" DEBUG_CR,
- rp->name, rp->nmspace);
- ap_text_append(r->pool, body, s);
- break;
- }
- }
- }
- }
- }
- }
- }
-
- ap_text_append(r->pool, body, "</D:supported-report-set>" DEBUG_CR);
- return NULL;
-}
-
-/* handle the OPTIONS method */
-static int dav_method_options(request_rec *r)
-{
- const dav_hooks_locks *locks_hooks = DAV_GET_HOOKS_LOCKS(r);
- const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
- const dav_hooks_binding *binding_hooks = DAV_GET_HOOKS_BINDING(r);
- dav_resource *resource;
- const char *dav_level;
- char *allow;
- char *s;
- apr_array_header_t *arr;
- apr_table_entry_t *elts;
- apr_table_t *methods = apr_table_make(r->pool, 12);
- ap_text_header vsn_options = { 0 };
- ap_text_header body = { 0 };
- ap_text *t;
- int text_size;
- int result;
- int i;
- apr_array_header_t *uri_ary;
- ap_xml_doc *doc;
- const ap_xml_elem *elem;
- dav_error *err;
-
- /* resolve the resource */
- err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
- &resource);
- if (err != NULL)
- return dav_handle_err(r, err, NULL);
-
- /* parse any request body */
- if ((result = ap_xml_parse_input(r, &doc)) != OK) {
- return result;
- }
- /* note: doc == NULL if no request body */
-
- if (doc && !dav_validate_root(doc, "options")) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "The \"options\" element was not found.");
- return HTTP_BAD_REQUEST;
- }
-
- /* determine which providers are available */
- dav_level = "1";
-
- if (locks_hooks != NULL) {
- dav_level = "1,2";
- }
-
- if (binding_hooks != NULL)
- dav_level = apr_pstrcat(r->pool, dav_level, ",bindings", NULL);
-
- /* ###
- ** MSFT Web Folders chokes if length of DAV header value > 63 characters!
- ** To workaround that, we use separate DAV headers for versioning and
- ** live prop provider namespace URIs.
- ** ###
- */
- apr_table_setn(r->headers_out, "DAV", dav_level);
-
- /*
- ** If there is a versioning provider, generate DAV headers
- ** for versioning options.
- */
- if (vsn_hooks != NULL) {
- (*vsn_hooks->get_vsn_options)(r->pool, &vsn_options);
-
- for (t = vsn_options.first; t != NULL; t = t->next)
- apr_table_addn(r->headers_out, "DAV", t->text);
- }
-
- /*
- ** Gather property set URIs from all the liveprop providers,
- ** and generate a separate DAV header for each URI, to avoid
- ** problems with long header lengths.
- */
- uri_ary = apr_array_make(r->pool, 5, sizeof(const char *));
- dav_run_gather_propsets(uri_ary);
- for (i = 0; i < uri_ary->nelts; ++i) {
- if (((char **)uri_ary->elts)[i] != NULL)
- apr_table_addn(r->headers_out, "DAV", ((char **)uri_ary->elts)[i]);
- }
-
- /* this tells MSFT products to skip looking for FrontPage extensions */
- apr_table_setn(r->headers_out, "MS-Author-Via", "DAV");
-
- /*
- ** Determine which methods are allowed on the resource.
- ** Three cases: resource is null (3), is lock-null (7.4), or exists.
- **
- ** All cases support OPTIONS, and if there is a lock provider, LOCK.
- ** (Lock-) null resources also support MKCOL and PUT.
- ** Lock-null supports PROPFIND and UNLOCK.
- ** Existing resources support lots of stuff.
- */
-
- apr_table_addn(methods, "OPTIONS", "");
-
- /* ### take into account resource type */
- switch (dav_get_resource_state(r, resource))
- {
- case DAV_RESOURCE_EXISTS:
- /* resource exists */
- apr_table_addn(methods, "GET", "");
- apr_table_addn(methods, "HEAD", "");
- apr_table_addn(methods, "POST", "");
- apr_table_addn(methods, "DELETE", "");
- apr_table_addn(methods, "TRACE", "");
- apr_table_addn(methods, "PROPFIND", "");
- apr_table_addn(methods, "PROPPATCH", "");
- apr_table_addn(methods, "COPY", "");
- apr_table_addn(methods, "MOVE", "");
-
- if (!resource->collection)
- apr_table_addn(methods, "PUT", "");
-
- if (locks_hooks != NULL) {
- apr_table_addn(methods, "LOCK", "");
- apr_table_addn(methods, "UNLOCK", "");
- }
-
- break;
-
- case DAV_RESOURCE_LOCK_NULL:
- /* resource is lock-null. */
- apr_table_addn(methods, "MKCOL", "");
- apr_table_addn(methods, "PROPFIND", "");
- apr_table_addn(methods, "PUT", "");
-
- if (locks_hooks != NULL) {
- apr_table_addn(methods, "LOCK", "");
- apr_table_addn(methods, "UNLOCK", "");
- }
-
- break;
-
- case DAV_RESOURCE_NULL:
- /* resource is null. */
- apr_table_addn(methods, "MKCOL", "");
- apr_table_addn(methods, "PUT", "");
-
- if (locks_hooks != NULL)
- apr_table_addn(methods, "LOCK", "");
-
- break;
-
- default:
- /* ### internal error! */
- break;
- }
-
- /* If there is a versioning provider, add versioning methods */
- if (vsn_hooks != NULL) {
- if (!resource->exists) {
- if ((*vsn_hooks->versionable)(resource))
- apr_table_addn(methods, "VERSION-CONTROL", "");
-
- if (vsn_hooks->can_be_workspace != NULL
- && (*vsn_hooks->can_be_workspace)(resource))
- apr_table_addn(methods, "MKWORKSPACE", "");
-
- if (vsn_hooks->can_be_activity != NULL
- && (*vsn_hooks->can_be_activity)(resource))
- apr_table_addn(methods, "MKACTIVITY", "");
- }
- else if (!resource->versioned) {
- if ((*vsn_hooks->versionable)(resource))
- apr_table_addn(methods, "VERSION-CONTROL", "");
- }
- else if (resource->working) {
- apr_table_addn(methods, "CHECKIN", "");
-
- /* ### we might not support this DeltaV option */
- apr_table_addn(methods, "UNCHECKOUT", "");
- }
- else if (vsn_hooks->add_label != NULL) {
- apr_table_addn(methods, "CHECKOUT", "");
- apr_table_addn(methods, "LABEL", "");
- }
- else {
- apr_table_addn(methods, "CHECKOUT", "");
- }
- }
-
- /* If there is a bindings provider, see if resource is bindable */
- if (binding_hooks != NULL
- && (*binding_hooks->is_bindable)(resource)) {
- apr_table_addn(methods, "BIND", "");
- }
-
- /* Generate the Allow header */
- arr = apr_table_elts(methods);
- elts = (apr_table_entry_t *) arr->elts;
- text_size = 0;
-
- /* first, compute total length */
- for (i = 0; i < arr->nelts; ++i) {
- if (elts[i].key == NULL)
- continue;
-
- /* add 1 for comma or null */
- text_size += strlen(elts[i].key) + 1;
- }
-
- s = allow = apr_palloc(r->pool, text_size);
-
- for (i = 0; i < arr->nelts; ++i) {
- if (elts[i].key == NULL)
- continue;
-
- if (s != allow)
- *s++ = ',';
-
- strcpy(s, elts[i].key);
- s += strlen(s);
- }
-
- apr_table_setn(r->headers_out, "Allow", allow);
-
- /* if there was no request body, then there is no response body */
- if (doc == NULL) {
- ap_set_content_length(r, 0);
-
- /* ### this sends a Content-Type. the default OPTIONS does not. */
-
- /* ### the default (ap_send_http_options) returns OK, but I believe
- * ### that is because it is the default handler and nothing else
- * ### will run after the thing. */
- return DONE;
- }
-
- /* handle each options request */
- for (elem = doc->root->first_child; elem != NULL; elem = elem->next) {
- /* check for something we recognize first */
- int core_option = 0;
- dav_error *err = NULL;
-
- if (elem->ns == AP_XML_NS_DAV_ID) {
- if (strcmp(elem->name, "supported-method-set") == 0) {
- err = dav_gen_supported_methods(r, elem, methods, &body);
- core_option = 1;
- }
- else if (strcmp(elem->name, "supported-live-property-set") == 0) {
- err = dav_gen_supported_live_props(r, resource, elem, &body);
- core_option = 1;
- }
- else if (strcmp(elem->name, "supported-report-set") == 0) {
- err = dav_gen_supported_reports(r, resource, elem, vsn_hooks, &body);
- core_option = 1;
- }
- }
-
- if (err != NULL)
- return dav_handle_err(r, err, NULL);
-
- /* if unrecognized option, pass to versioning provider */
- if (!core_option) {
- if ((err = (*vsn_hooks->get_option)(resource, elem, &body))
- != NULL) {
- return dav_handle_err(r, err, NULL);
- }
- }
- }
-
- /* send the options response */
- r->status = HTTP_OK;
- r->content_type = DAV_XML_CONTENT_TYPE;
-
- /* send the headers and response body */
- ap_rputs(DAV_XML_HEADER DEBUG_CR
- "<D:options-response xmlns:D=\"DAV:\">" DEBUG_CR, r);
-
- for (t = body.first; t != NULL; t = t->next)
- ap_rputs(t->text, r);
-
- ap_rputs("</D:options-response>" DEBUG_CR, r);
-
- /* we've sent everything necessary to the client. */
- return DONE;
-}
-
-static void dav_cache_badprops(dav_walker_ctx *ctx)
-{
- const ap_xml_elem *elem;
- ap_text_header hdr = { 0 };
-
- /* just return if we built the thing already */
- if (ctx->propstat_404 != NULL) {
- return;
- }
-
- ap_text_append(ctx->w.pool, &hdr,
- "<D:propstat>" DEBUG_CR
- "<D:prop>" DEBUG_CR);
-
- elem = dav_find_child(ctx->doc->root, "prop");
- for (elem = elem->first_child; elem; elem = elem->next) {
- ap_text_append(ctx->w.pool, &hdr,
- ap_xml_empty_elem(ctx->w.pool, elem));
- }
-
- ap_text_append(ctx->w.pool, &hdr,
- "</D:prop>" DEBUG_CR
- "<D:status>HTTP/1.1 404 Not Found</D:status>" DEBUG_CR
- "</D:propstat>" DEBUG_CR);
-
- ctx->propstat_404 = hdr.first;
-}
-
-static dav_error * dav_propfind_walker(dav_walk_resource *wres, int calltype)
-{
- dav_walker_ctx *ctx = wres->walk_ctx;
- dav_error *err;
- dav_propdb *propdb;
- dav_get_props_result propstats = { 0 };
-
- /*
- ** Note: ctx->doc can only be NULL for DAV_PROPFIND_IS_ALLPROP. Since
- ** dav_get_allprops() does not need to do namespace translation,
- ** we're okay.
- **
- ** Note: we cast to lose the "const". The propdb won't try to change
- ** the resource, however, since we are opening readonly.
- */
- err = dav_open_propdb(ctx->r, ctx->w.lockdb, wres->resource, 1,
- ctx->doc ? ctx->doc->namespaces : NULL, &propdb);
- if (err != NULL) {
- /* ### do something with err! */
-
- if (ctx->propfind_type == DAV_PROPFIND_IS_PROP) {
- dav_get_props_result badprops = { 0 };
-
- /* some props were expected on this collection/resource */
- dav_cache_badprops(ctx);
- badprops.propstats = ctx->propstat_404;
- dav_add_response(wres, 0, &badprops);
- }
- else {
- /* no props on this collection/resource */
- dav_add_response(wres, HTTP_OK, NULL);
- }
- return NULL;
- }
- /* ### what to do about closing the propdb on server failure? */
-
- if (ctx->propfind_type == DAV_PROPFIND_IS_PROP) {
- propstats = dav_get_props(propdb, ctx->doc);
- }
- else {
- dav_prop_insert what = ctx->propfind_type == DAV_PROPFIND_IS_ALLPROP
- ? DAV_PROP_INSERT_VALUE
- : DAV_PROP_INSERT_NAME;
- propstats = dav_get_allprops(propdb, what);
- }
- dav_close_propdb(propdb);
-
- dav_add_response(wres, 0, &propstats);
-
- return NULL;
-}
-
-/* handle the PROPFIND method */
-static int dav_method_propfind(request_rec *r)
-{
- dav_resource *resource;
- int depth;
- dav_error *err;
- int result;
- ap_xml_doc *doc;
- const ap_xml_elem *child;
- dav_walker_ctx ctx = { { 0 } };
- dav_response *multi_status;
-
- /* Ask repository module to resolve the resource */
- err = dav_get_resource(r, 1 /* label_allowed */, 0 /* use_checked_in */,
- &resource);
- if (err != NULL)
- return dav_handle_err(r, err, NULL);
-
- if (dav_get_resource_state(r, resource) == DAV_RESOURCE_NULL) {
- /* Apache will supply a default error for this. */
- return HTTP_NOT_FOUND;
- }
-
- if ((depth = dav_get_depth(r, DAV_INFINITY)) < 0) {
- /* dav_get_depth() supplies additional information for the
- * default message. */
- return HTTP_BAD_REQUEST;
- }
-
- if (depth == DAV_INFINITY && resource->collection) {
- dav_dir_conf *conf;
- conf = (dav_dir_conf *) ap_get_module_config(r->per_dir_config,
- &dav_module);
- /* default is to DISALLOW these requests */
- if (conf->allow_depthinfinity != DAV_ENABLED_ON) {
- return dav_error_response(r, HTTP_FORBIDDEN,
- apr_psprintf(r->pool,
- "PROPFIND requests with a "
- "Depth of \"infinity\" are "
- "not allowed for %s.",
- ap_escape_html(r->pool,
- r->uri)));
- }
- }
-
- if ((result = ap_xml_parse_input(r, &doc)) != OK) {
- return result;
- }
- /* note: doc == NULL if no request body */
-
- if (doc && !dav_validate_root(doc, "propfind")) {
- /* This supplies additional information for the default message. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "The \"propfind\" element was not found.");
- return HTTP_BAD_REQUEST;
- }
-
- /* ### validate that only one of these three elements is present */
-
- if (doc == NULL
- || (child = dav_find_child(doc->root, "allprop")) != NULL) {
- /* note: no request body implies allprop */
- ctx.propfind_type = DAV_PROPFIND_IS_ALLPROP;
- }
- else if ((child = dav_find_child(doc->root, "propname")) != NULL) {
- ctx.propfind_type = DAV_PROPFIND_IS_PROPNAME;
- }
- else if ((child = dav_find_child(doc->root, "prop")) != NULL) {
- ctx.propfind_type = DAV_PROPFIND_IS_PROP;
- }
- else {
- /* "propfind" element must have one of the above three children */
-
- /* This supplies additional information for the default message. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "The \"propfind\" element does not contain one of "
- "the required child elements (the specific command).");
- return HTTP_BAD_REQUEST;
- }
-
- ctx.w.walk_type = DAV_WALKTYPE_NORMAL | DAV_WALKTYPE_AUTH;
- ctx.w.func = dav_propfind_walker;
- ctx.w.walk_ctx = &ctx;
- ctx.w.pool = r->pool;
- ctx.w.root = resource;
-
- ctx.doc = doc;
- ctx.r = r;
-
- /* ### should open read-only */
- if ((err = dav_open_lockdb(r, 0, &ctx.w.lockdb)) != NULL) {
- err = dav_push_error(r->pool, err->status, 0,
- "The lock database could not be opened, "
- "preventing access to the various lock "
- "properties for the PROPFIND.",
- err);
- return dav_handle_err(r, err, NULL);
- }
- if (ctx.w.lockdb != NULL) {
- /* if we have a lock database, then we can walk locknull resources */
- ctx.w.walk_type |= DAV_WALKTYPE_LOCKNULL;
- }
-
- err = (*resource->hooks->walk)(&ctx.w, depth, &multi_status);
-
- if (ctx.w.lockdb != NULL) {
- (*ctx.w.lockdb->hooks->close_lockdb)(ctx.w.lockdb);
- }
-
- if (err != NULL) {
- /* ### add a higher-level description? */
- return dav_handle_err(r, err, NULL);
- }
-
- /* return a 207 (Multi-Status) response now. */
-
- /* if a 404 was generated for an HREF, then we need to spit out the
- * doc's namespaces for use by the 404. Note that <response> elements
- * will override these ns0, ns1, etc, but NOT within the <response>
- * scope for the badprops. */
- /* NOTE: propstat_404 != NULL implies doc != NULL */
- if (ctx.propstat_404 != NULL) {
- dav_send_multistatus(r, HTTP_MULTI_STATUS, multi_status,
- doc->namespaces);
- }
- else {
- dav_send_multistatus(r, HTTP_MULTI_STATUS, multi_status, NULL);
- }
-
- /* the response has been sent. */
- return DONE;
-}
-
-static ap_text * dav_failed_proppatch(apr_pool_t *p,
- apr_array_header_t *prop_ctx)
-{
- ap_text_header hdr = { 0 };
- int i = prop_ctx->nelts;
- dav_prop_ctx *ctx = (dav_prop_ctx *)prop_ctx->elts;
- dav_error *err424_set = NULL;
- dav_error *err424_delete = NULL;
- const char *s;
-
- /* ### might be nice to sort by status code and description */
-
- for ( ; i-- > 0; ++ctx ) {
- ap_text_append(p, &hdr,
- "<D:propstat>" DEBUG_CR
- "<D:prop>");
- ap_text_append(p, &hdr, ap_xml_empty_elem(p, ctx->prop));
- ap_text_append(p, &hdr, "</D:prop>" DEBUG_CR);
-
- if (ctx->err == NULL) {
- /* nothing was assigned here yet, so make it a 424 */
-
- if (ctx->operation == DAV_PROP_OP_SET) {
- if (err424_set == NULL)
- err424_set = dav_new_error(p, HTTP_FAILED_DEPENDENCY, 0,
- "Attempted DAV:set operation "
- "could not be completed due "
- "to other errors.");
- ctx->err = err424_set;
- }
- else if (ctx->operation == DAV_PROP_OP_DELETE) {
- if (err424_delete == NULL)
- err424_delete = dav_new_error(p, HTTP_FAILED_DEPENDENCY, 0,
- "Attempted DAV:remove "
- "operation could not be "
- "completed due to other "
- "errors.");
- ctx->err = err424_delete;
- }
- }
-
- s = apr_psprintf(p,
- "<D:status>"
- "HTTP/1.1 %d (status)"
- "</D:status>" DEBUG_CR,
- ctx->err->status);
- ap_text_append(p, &hdr, s);
-
- /* ### we should use compute_desc if necessary... */
- if (ctx->err->desc != NULL) {
- ap_text_append(p, &hdr, "<D:responsedescription>" DEBUG_CR);
- ap_text_append(p, &hdr, ctx->err->desc);
- ap_text_append(p, &hdr, "</D:responsedescription>" DEBUG_CR);
- }
-
- ap_text_append(p, &hdr, "</D:propstat>" DEBUG_CR);
- }
-
- return hdr.first;
-}
-
-static ap_text * dav_success_proppatch(apr_pool_t *p, apr_array_header_t *prop_ctx)
-{
- ap_text_header hdr = { 0 };
- int i = prop_ctx->nelts;
- dav_prop_ctx *ctx = (dav_prop_ctx *)prop_ctx->elts;
-
- /*
- ** ### we probably need to revise the way we assemble the response...
- ** ### this code assumes everything will return status==200.
- */
-
- ap_text_append(p, &hdr,
- "<D:propstat>" DEBUG_CR
- "<D:prop>" DEBUG_CR);
-
- for ( ; i-- > 0; ++ctx ) {
- ap_text_append(p, &hdr, ap_xml_empty_elem(p, ctx->prop));
- }
-
- ap_text_append(p, &hdr,
- "</D:prop>" DEBUG_CR
- "<D:status>HTTP/1.1 200 OK</D:status>" DEBUG_CR
- "</D:propstat>" DEBUG_CR);
-
- return hdr.first;
-}
-
-static void dav_prop_log_errors(dav_prop_ctx *ctx)
-{
- dav_log_err(ctx->r, ctx->err, APLOG_ERR);
-}
-
-/*
-** Call <func> for each context. This can stop when an error occurs, or
-** simply iterate through the whole list.
-**
-** Returns 1 if an error occurs (and the iteration is aborted). Returns 0
-** if all elements are processed.
-**
-** If <reverse> is true (non-zero), then the list is traversed in
-** reverse order.
-*/
-static int dav_process_ctx_list(void (*func)(dav_prop_ctx *ctx),
- apr_array_header_t *ctx_list, int stop_on_error,
- int reverse)
-{
- int i = ctx_list->nelts;
- dav_prop_ctx *ctx = (dav_prop_ctx *)ctx_list->elts;
-
- if (reverse)
- ctx += i;
-
- while (i--) {
- if (reverse)
- --ctx;
-
- (*func)(ctx);
- if (stop_on_error && DAV_PROP_CTX_HAS_ERR(*ctx)) {
- return 1;
- }
-
- if (!reverse)
- ++ctx;
- }
-
- return 0;
-}
-
-/* handle the PROPPATCH method */
-static int dav_method_proppatch(request_rec *r)
-{
- dav_error *err;
- dav_resource *resource;
- int result;
- ap_xml_doc *doc;
- ap_xml_elem *child;
- dav_propdb *propdb;
- int failure = 0;
- dav_response resp = { 0 };
- ap_text *propstat_text;
- apr_array_header_t *ctx_list;
- dav_prop_ctx *ctx;
- dav_auto_version_info av_info;
-
- /* Ask repository module to resolve the resource */
- err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
- &resource);
- if (err != NULL)
- return dav_handle_err(r, err, NULL);
- if (!resource->exists) {
- /* Apache will supply a default error for this. */
- return HTTP_NOT_FOUND;
- }
-
- if ((result = ap_xml_parse_input(r, &doc)) != OK) {
- return result;
- }
- /* note: doc == NULL if no request body */
-
- if (doc == NULL || !dav_validate_root(doc, "propertyupdate")) {
- /* This supplies additional information for the default message. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "The request body does not contain "
- "a \"propertyupdate\" element.");
- return HTTP_BAD_REQUEST;
- }
-
- /* Check If-Headers and existing locks */
- /* Note: depth == 0. Implies no need for a multistatus response. */
- if ((err = dav_validate_request(r, resource, 0, NULL, NULL,
- DAV_VALIDATE_RESOURCE, NULL)) != NULL) {
- /* ### add a higher-level description? */
- return dav_handle_err(r, err, NULL);
- }
-
- /* make sure the resource can be modified (if versioning repository) */
- if ((err = dav_auto_checkout(r, resource,
- 0 /* not parent_only */,
- &av_info)) != NULL) {
- /* ### add a higher-level description? */
- return dav_handle_err(r, err, NULL);
- }
-
- if ((err = dav_open_propdb(r, NULL, resource, 0, doc->namespaces,
- &propdb)) != NULL) {
- /* undo any auto-checkout */
- dav_auto_checkin(r, resource, 1 /*undo*/, 0 /*unlock*/, &av_info);
-
- err = dav_push_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
- apr_psprintf(r->pool,
- "Could not open the property "
- "database for %s.",
- ap_escape_html(r->pool, r->uri)),
- err);
- return dav_handle_err(r, err, NULL);
- }
- /* ### what to do about closing the propdb on server failure? */
-
- /* ### validate "live" properties */
-
- /* set up an array to hold property operation contexts */
- ctx_list = apr_array_make(r->pool, 10, sizeof(dav_prop_ctx));
-
- /* do a first pass to ensure that all "remove" properties exist */
- for (child = doc->root->first_child; child; child = child->next) {
- int is_remove;
- ap_xml_elem *prop_group;
- ap_xml_elem *one_prop;
-
- /* Ignore children that are not set/remove */
- if (child->ns != AP_XML_NS_DAV_ID
- || (!(is_remove = strcmp(child->name, "remove") == 0)
- && strcmp(child->name, "set") != 0)) {
- continue;
- }
-
- /* make sure that a "prop" child exists for set/remove */
- if ((prop_group = dav_find_child(child, "prop")) == NULL) {
- dav_close_propdb(propdb);
-
- /* undo any auto-checkout */
- dav_auto_checkin(r, resource, 1 /*undo*/, 0 /*unlock*/, &av_info);
-
- /* This supplies additional information for the default message. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "A \"prop\" element is missing inside "
- "the propertyupdate command.");
- return HTTP_BAD_REQUEST;
- }
-
- for (one_prop = prop_group->first_child; one_prop;
- one_prop = one_prop->next) {
-
- ctx = (dav_prop_ctx *)apr_array_push(ctx_list);
- ctx->propdb = propdb;
- ctx->operation = is_remove ? DAV_PROP_OP_DELETE : DAV_PROP_OP_SET;
- ctx->prop = one_prop;
-
- ctx->r = r; /* for later use by dav_prop_log_errors() */
-
- dav_prop_validate(ctx);
-
- if ( DAV_PROP_CTX_HAS_ERR(*ctx) ) {
- failure = 1;
- }
- }
- }
-
- /* ### should test that we found at least one set/remove */
-
- /* execute all of the operations */
- if (!failure && dav_process_ctx_list(dav_prop_exec, ctx_list, 1, 0)) {
- failure = 1;
- }
-
- /* generate a failure/success response */
- if (failure) {
- (void)dav_process_ctx_list(dav_prop_rollback, ctx_list, 0, 1);
- propstat_text = dav_failed_proppatch(r->pool, ctx_list);
- }
- else {
- (void)dav_process_ctx_list(dav_prop_commit, ctx_list, 0, 0);
- propstat_text = dav_success_proppatch(r->pool, ctx_list);
- }
-
- /* make sure this gets closed! */
- dav_close_propdb(propdb);
-
- /* complete any auto-versioning */
- dav_auto_checkin(r, resource, failure, 0 /*unlock*/, &av_info);
-
- /* log any errors that occurred */
- (void)dav_process_ctx_list(dav_prop_log_errors, ctx_list, 0, 0);
-
- resp.href = resource->uri;
-
- /* ### should probably use something new to pass along this text... */
- resp.propresult.propstats = propstat_text;
-
- dav_send_multistatus(r, HTTP_MULTI_STATUS, &resp, doc->namespaces);
-
- /* the response has been sent. */
- return DONE;
-}
-
-static int process_mkcol_body(request_rec *r)
-{
- /* This is snarfed from ap_setup_client_block(). We could get pretty
- * close to this behavior by passing REQUEST_NO_BODY, but we need to
- * return HTTP_UNSUPPORTED_MEDIA_TYPE (while ap_setup_client_block
- * returns HTTP_REQUEST_ENTITY_TOO_LARGE). */
-
- const char *tenc = apr_table_get(r->headers_in, "Transfer-Encoding");
- const char *lenp = apr_table_get(r->headers_in, "Content-Length");
-
- /* make sure to set the Apache request fields properly. */
- r->read_body = REQUEST_NO_BODY;
- r->read_chunked = 0;
- r->remaining = 0;
-
- if (tenc) {
- if (strcasecmp(tenc, "chunked")) {
- /* Use this instead of Apache's default error string */
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "Unknown Transfer-Encoding %s", tenc);
- return HTTP_NOT_IMPLEMENTED;
- }
-
- r->read_chunked = 1;
- }
- else if (lenp) {
- const char *pos = lenp;
-
- while (apr_isdigit(*pos) || apr_isspace(*pos)) {
- ++pos;
- }
- if (*pos != '\0') {
- /* This supplies additional information for the default message. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "Invalid Content-Length %s", lenp);
- return HTTP_BAD_REQUEST;
- }
-
- r->remaining = atol(lenp);
- }
-
- if (r->read_chunked || r->remaining > 0) {
- /* ### log something? */
-
- /* Apache will supply a default error for this. */
- return HTTP_UNSUPPORTED_MEDIA_TYPE;
- }
-
- /*
- ** Get rid of the body. this will call ap_setup_client_block(), but
- ** our copy above has already verified its work.
- */
- return ap_discard_request_body(r);
-}
-
-/* handle the MKCOL method */
-static int dav_method_mkcol(request_rec *r)
-{
- dav_resource *resource;
- int resource_state;
- dav_auto_version_info av_info;
- const dav_hooks_locks *locks_hooks = DAV_GET_HOOKS_LOCKS(r);
- dav_error *err;
- dav_error *err2;
- int result;
- dav_dir_conf *conf;
- dav_response *multi_status;
-
- /* handle the request body */
- /* ### this may move lower once we start processing bodies */
- if ((result = process_mkcol_body(r)) != OK) {
- return result;
- }
-
- conf = (dav_dir_conf *) ap_get_module_config(r->per_dir_config,
- &dav_module);
-
- /* Ask repository module to resolve the resource */
- err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
- &resource);
- if (err != NULL)
- return dav_handle_err(r, err, NULL);
-
- if (resource->exists) {
- /* oops. something was already there! */
-
- /* Apache will supply a default error for this. */
- /* ### we should provide a specific error message! */
- return HTTP_METHOD_NOT_ALLOWED;
- }
-
- resource_state = dav_get_resource_state(r, resource);
-
- /*
- ** Check If-Headers and existing locks.
- **
- ** Note: depth == 0 normally requires no multistatus response. However,
- ** if we pass DAV_VALIDATE_PARENT, then we could get an error on a URI
- ** other than the Request-URI, thereby requiring a multistatus.
- **
- ** If the resource does not exist (DAV_RESOURCE_NULL), then we must
- ** check the resource *and* its parent. If the resource exists or is
- ** a locknull resource, then we check only the resource.
- */
- if ((err = dav_validate_request(r, resource, 0, NULL, &multi_status,
- resource_state == DAV_RESOURCE_NULL ?
- DAV_VALIDATE_PARENT :
- DAV_VALIDATE_RESOURCE, NULL)) != NULL) {
- /* ### add a higher-level description? */
- return dav_handle_err(r, err, multi_status);
- }
-
- /* if versioned resource, make sure parent is checked out */
- if ((err = dav_auto_checkout(r, resource, 1 /* parent_only */,
- &av_info)) != NULL) {
- /* ### add a higher-level description? */
- return dav_handle_err(r, err, NULL);
- }
-
- /* try to create the collection */
- resource->collection = 1;
- err = (*resource->hooks->create_collection)(resource);
-
- /* restore modifiability of parent back to what it was */
- err2 = dav_auto_checkin(r, NULL, err != NULL /* undo if error */,
- 0 /*unlock*/, &av_info);
-
- /* check for errors now */
- if (err != NULL) {
- return dav_handle_err(r, err, NULL);
- }
- if (err2 != NULL) {
- /* just log a warning */
- err = dav_push_error(r->pool, err->status, 0,
- "The MKCOL was successful, but there "
- "was a problem automatically checking in "
- "the parent collection.",
- err2);
- dav_log_err(r, err, APLOG_WARNING);
- }
-
- if (locks_hooks != NULL) {
- dav_lockdb *lockdb;
-
- if ((err = (*locks_hooks->open_lockdb)(r, 0, 0, &lockdb)) != NULL) {
- /* The directory creation was successful, but the locking failed. */
- err = dav_push_error(r->pool, err->status, 0,
- "The MKCOL was successful, but there "
- "was a problem opening the lock database "
- "which prevents inheriting locks from the "
- "parent resources.",
- err);
- return dav_handle_err(r, err, NULL);
- }
-
- /* notify lock system that we have created/replaced a resource */
- err = dav_notify_created(r, lockdb, resource, resource_state, 0);
-
- (*locks_hooks->close_lockdb)(lockdb);
-
- if (err != NULL) {
- /* The dir creation was successful, but the locking failed. */
- err = dav_push_error(r->pool, err->status, 0,
- "The MKCOL was successful, but there "
- "was a problem updating its lock "
- "information.",
- err);
- return dav_handle_err(r, err, NULL);
- }
- }
-
- /* return an appropriate response (HTTP_CREATED) */
- return dav_created(r, NULL, "Collection", 0);
-}
-
-/* handle the COPY and MOVE methods */
-static int dav_method_copymove(request_rec *r, int is_move)
-{
- dav_resource *resource;
- dav_resource *resnew;
- dav_auto_version_info src_av_info = { 0 };
- dav_auto_version_info dst_av_info = { 0 };
- const char *body;
- const char *dest;
- dav_error *err;
- dav_error *err2;
- dav_error *err3;
- dav_response *multi_response;
- dav_lookup_result lookup;
- int is_dir;
- int overwrite;
- int depth;
- int result;
- dav_lockdb *lockdb;
- int replace_dest;
- int resnew_state;
-
- /* Ask repository module to resolve the resource */
- err = dav_get_resource(r, !is_move /* label_allowed */,
- 0 /* use_checked_in */, &resource);
- if (err != NULL)
- return dav_handle_err(r, err, NULL);
- if (!resource->exists) {
- /* Apache will supply a default error for this. */
- return HTTP_NOT_FOUND;
- }
-
- /* If not a file or collection resource, COPY/MOVE not allowed */
- /* ### allow COPY/MOVE of DeltaV resource types */
- if (resource->type != DAV_RESOURCE_TYPE_REGULAR) {
- body = apr_psprintf(r->pool,
- "Cannot COPY/MOVE resource %s.",
- ap_escape_html(r->pool, r->uri));
- return dav_error_response(r, HTTP_METHOD_NOT_ALLOWED, body);
- }
-
- /* get the destination URI */
- dest = apr_table_get(r->headers_in, "Destination");
- if (dest == NULL) {
- /* Look in headers provided by Netscape's Roaming Profiles */
- const char *nscp_host = apr_table_get(r->headers_in, "Host");
- const char *nscp_path = apr_table_get(r->headers_in, "New-uri");
-
- if (nscp_host != NULL && nscp_path != NULL)
- dest = apr_psprintf(r->pool, "http://%s%s", nscp_host, nscp_path);
- }
- if (dest == NULL) {
- /* This supplies additional information for the default message. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "The request is missing a Destination header.");
- return HTTP_BAD_REQUEST;
- }
-
- lookup = dav_lookup_uri(dest, r, 1 /* must_be_absolute */);
- if (lookup.rnew == NULL) {
- if (lookup.err.status == HTTP_BAD_REQUEST) {
- /* This supplies additional information for the default message. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- lookup.err.desc);
- return HTTP_BAD_REQUEST;
- }
-
- /* ### this assumes that dav_lookup_uri() only generates a status
- * ### that Apache can provide a status line for!! */
-
- return dav_error_response(r, lookup.err.status, lookup.err.desc);
- }
- if (lookup.rnew->status != HTTP_OK) {
- /* ### how best to report this... */
- return dav_error_response(r, lookup.rnew->status,
- "Destination URI had an error.");
- }
-
- /* Resolve destination resource */
- err = dav_get_resource(lookup.rnew, 0 /* label_allowed */,
- 0 /* use_checked_in */, &resnew);
- if (err != NULL)
- return dav_handle_err(r, err, NULL);
-
- /* are the two resources handled by the same repository? */
- if (resource->hooks != resnew->hooks) {
- /* ### this message exposes some backend config, but screw it... */
- return dav_error_response(r, HTTP_BAD_GATEWAY,
- "Destination URI is handled by a "
- "different repository than the source URI. "
- "MOVE or COPY between repositories is "
- "not possible.");
- }
-
- /* get and parse the overwrite header value */
- if ((overwrite = dav_get_overwrite(r)) < 0) {
- /* dav_get_overwrite() supplies additional information for the
- * default message. */
- return HTTP_BAD_REQUEST;
- }
-
- /* quick failure test: if dest exists and overwrite is false. */
- if (resnew->exists && !overwrite) {
- /* Supply some text for the error response body. */
- return dav_error_response(r, HTTP_PRECONDITION_FAILED,
- "Destination is not empty and "
- "Overwrite is not \"T\"");
- }
-
- /* are the source and destination the same? */
- if ((*resource->hooks->is_same_resource)(resource, resnew)) {
- /* Supply some text for the error response body. */
- return dav_error_response(r, HTTP_FORBIDDEN,
- "Source and Destination URIs are the same.");
-
- }
-
- is_dir = resource->collection;
-
- /* get and parse the Depth header value. "0" and "infinity" are legal. */
- if ((depth = dav_get_depth(r, DAV_INFINITY)) < 0) {
- /* dav_get_depth() supplies additional information for the
- * default message. */
- return HTTP_BAD_REQUEST;
- }
- if (depth == 1) {
- /* This supplies additional information for the default message. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "Depth must be \"0\" or \"infinity\" for COPY or MOVE.");
- return HTTP_BAD_REQUEST;
- }
- if (is_move && is_dir && depth != DAV_INFINITY) {
- /* This supplies additional information for the default message. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "Depth must be \"infinity\" when moving a collection.");
- return HTTP_BAD_REQUEST;
- }
-
- /*
- ** Check If-Headers and existing locks for each resource in the source
- ** if we are performing a MOVE. We will return a 424 response with a
- ** DAV:multistatus body. The multistatus responses will contain the
- ** information about any resource that fails the validation.
- **
- ** We check the parent resource, too, since this is a MOVE. Moving the
- ** resource effectively removes it from the parent collection, so we
- ** must ensure that we have met the appropriate conditions.
- **
- ** If a problem occurs with the Request-URI itself, then a plain error
- ** (rather than a multistatus) will be returned.
- */
- if (is_move
- && (err = dav_validate_request(r, resource, depth, NULL,
- &multi_response,
- DAV_VALIDATE_PARENT
- | DAV_VALIDATE_USE_424,
- NULL)) != NULL) {
- err = dav_push_error(r->pool, err->status, 0,
- apr_psprintf(r->pool,
- "Could not MOVE %s due to a failed "
- "precondition on the source "
- "(e.g. locks).",
- ap_escape_html(r->pool, r->uri)),
- err);
- return dav_handle_err(r, err, multi_response);
- }
-
- /*
- ** Check If-Headers and existing locks for destination. Note that we
- ** use depth==infinity since the target (hierarchy) will be deleted
- ** before the move/copy is completed.
- **
- ** Note that we are overwriting the target, which implies a DELETE, so
- ** we are subject to the error/response rules as a DELETE. Namely, we
- ** will return a 424 error if any of the validations fail.
- ** (see dav_method_delete() for more information)
- */
- if ((err = dav_validate_request(lookup.rnew, resnew, DAV_INFINITY, NULL,
- &multi_response,
- DAV_VALIDATE_PARENT
- | DAV_VALIDATE_USE_424, NULL)) != NULL) {
- err = dav_push_error(r->pool, err->status, 0,
- apr_psprintf(r->pool,
- "Could not MOVE/COPY %s due to a "
- "failed precondition on the "
- "destination (e.g. locks).",
- ap_escape_html(r->pool, r->uri)),
- err);
- return dav_handle_err(r, err, multi_response);
- }
-
- if (is_dir
- && depth == DAV_INFINITY
- && (*resource->hooks->is_parent_resource)(resource, resnew)) {
- /* Supply some text for the error response body. */
- return dav_error_response(r, HTTP_FORBIDDEN,
- "Source collection contains the "
- "Destination.");
-
- }
- if (is_dir
- && (*resnew->hooks->is_parent_resource)(resnew, resource)) {
- /* The destination must exist (since it contains the source), and
- * a condition above implies Overwrite==T. Obviously, we cannot
- * delete the Destination before the MOVE/COPY, as that would
- * delete the Source.
- */
-
- /* Supply some text for the error response body. */
- return dav_error_response(r, HTTP_FORBIDDEN,
- "Destination collection contains the Source "
- "and Overwrite has been specified.");
- }
-
- /* ### for now, we don't need anything in the body */
- if ((result = ap_discard_request_body(r)) != OK) {
- return result;
- }
-
- if ((err = dav_open_lockdb(r, 0, &lockdb)) != NULL) {
- /* ### add a higher-level description? */
- return dav_handle_err(r, err, NULL);
- }
-
- /* remove any locks from the old resources */
- /*
- ** ### this is Yet Another Traversal. if we do a rename(), then we
- ** ### really don't have to do this in some cases since the inode
- ** ### values will remain constant across the move. but we can't
- ** ### know that fact from outside the provider :-(
- **
- ** ### note that we now have a problem atomicity in the move/copy
- ** ### since a failure after this would have removed locks (technically,
- ** ### this is okay to do, but really...)
- */
- if (is_move && lockdb != NULL) {
- /* ### this is wrong! it blasts direct locks on parent resources */
- /* ### pass lockdb! */
- (void)dav_unlock(r, resource, NULL);
- }
-
- /* if this is a move, then the source parent collection will be modified */
- if (is_move) {
- if ((err = dav_auto_checkout(r, resource, 1 /* parent_only */,
- &src_av_info)) != NULL) {
- if (lockdb != NULL)
- (*lockdb->hooks->close_lockdb)(lockdb);
-
- /* ### add a higher-level description? */
- return dav_handle_err(r, err, NULL);
- }
- }
-
- /*
- * Remember the initial state of the destination, so the lock system
- * can be notified as to how it changed.
- */
- resnew_state = dav_get_resource_state(lookup.rnew, resnew);
-
- /* If destination does not exist, initialize resource object
- * to be same type as the source.
- */
- if (!resnew->exists) {
- resnew->type = resource->type;
- resnew->collection = resource->collection;
- }
-
- /* In a MOVE operation, the destination is replaced by the source.
- * In a COPY operation, if the destination exists, is under version
- * control, and is the same resource type as the source,
- * then it should not be replaced, but modified to be a copy of
- * the source.
- */
- if (!resnew->exists)
- replace_dest = 0;
- else if (is_move || !resource->versioned)
- replace_dest = 1;
- else if (resource->type != resnew->type)
- replace_dest = 1;
- else if ((resource->collection == 0) != (resnew->collection == 0))
- replace_dest = 1;
- else
- replace_dest = 0;
-
- /* If the destination must be created or replaced,
- * make sure the parent collection is writable
- */
- if (!resnew->exists || replace_dest) {
- if ((err = dav_auto_checkout(r, resnew, 1 /*parent_only*/,
- &dst_av_info)) != NULL) {
- /* could not make destination writable:
- * if move, restore state of source parent
- */
- if (is_move) {
- (void) dav_auto_checkin(r, NULL, 1 /* undo */,
- 0 /*unlock*/, &src_av_info);
- }
-
- if (lockdb != NULL)
- (*lockdb->hooks->close_lockdb)(lockdb);
-
- /* ### add a higher-level description? */
- return dav_handle_err(r, err, NULL);
- }
- }
-
- /* If source and destination parents are the same, then
- * use the same resource object, so status updates to one are reflected
- * in the other, when doing auto-versioning. Otherwise,
- * we may try to checkin the parent twice.
- */
- if (src_av_info.parent_resource != NULL
- && dst_av_info.parent_resource != NULL
- && (*src_av_info.parent_resource->hooks->is_same_resource)
- (src_av_info.parent_resource, dst_av_info.parent_resource)) {
-
- dst_av_info.parent_resource = src_av_info.parent_resource;
- }
-
- /* If destination is being replaced, remove it first
- * (we know Ovewrite must be TRUE). Then try to copy/move the resource.
- */
- if (replace_dest)
- err = (*resnew->hooks->remove_resource)(resnew, &multi_response);
-
- if (err == NULL) {
- if (is_move)
- err = (*resource->hooks->move_resource)(resource, resnew,
- &multi_response);
- else
- err = (*resource->hooks->copy_resource)(resource, resnew, depth,
- &multi_response);
- }
-
- /* perform any auto-versioning cleanup */
- err2 = dav_auto_checkin(r, NULL, err != NULL /* undo if error */,
- 0 /*unlock*/, &dst_av_info);
-
- if (is_move) {
- err3 = dav_auto_checkin(r, NULL, err != NULL /* undo if error */,
- 0 /*unlock*/, &src_av_info);
- }
- else
- err3 = NULL;
-
- /* check for error from remove/copy/move operations */
- if (err != NULL) {
- if (lockdb != NULL)
- (*lockdb->hooks->close_lockdb)(lockdb);
-
- err = dav_push_error(r->pool, err->status, 0,
- apr_psprintf(r->pool,
- "Could not MOVE/COPY %s.",
- ap_escape_html(r->pool, r->uri)),
- err);
- return dav_handle_err(r, err, multi_response);
- }
-
- /* check for errors from auto-versioning */
- if (err2 != NULL) {
- /* just log a warning */
- err = dav_push_error(r->pool, err2->status, 0,
- "The MOVE/COPY was successful, but there was a "
- "problem automatically checking in the "
- "source parent collection.",
- err2);
- dav_log_err(r, err, APLOG_WARNING);
- }
- if (err3 != NULL) {
- /* just log a warning */
- err = dav_push_error(r->pool, err3->status, 0,
- "The MOVE/COPY was successful, but there was a "
- "problem automatically checking in the "
- "destination or its parent collection.",
- err3);
- dav_log_err(r, err, APLOG_WARNING);
- }
-
- /* propagate any indirect locks at the target */
- if (lockdb != NULL) {
-
- /* notify lock system that we have created/replaced a resource */
- err = dav_notify_created(r, lockdb, resnew, resnew_state, depth);
-
- (*lockdb->hooks->close_lockdb)(lockdb);
-
- if (err != NULL) {
- /* The move/copy was successful, but the locking failed. */
- err = dav_push_error(r->pool, err->status, 0,
- "The MOVE/COPY was successful, but there "
- "was a problem updating the lock "
- "information.",
- err);
- return dav_handle_err(r, err, NULL);
- }
- }
-
- /* return an appropriate response (HTTP_CREATED or HTTP_NO_CONTENT) */
- return dav_created(r, lookup.rnew->uri, "Destination",
- resnew_state == DAV_RESOURCE_EXISTS);
-}
-
-/* dav_method_lock: Handler to implement the DAV LOCK method
-** Returns appropriate HTTP_* response.
-*/
-static int dav_method_lock(request_rec *r)
-{
- dav_error *err;
- dav_resource *resource;
- const dav_hooks_locks *locks_hooks;
- int result;
- int depth;
- int new_lock_request = 0;
- ap_xml_doc *doc;
- dav_lock *lock;
- dav_response *multi_response = NULL;
- dav_lockdb *lockdb;
- int resource_state;
-
- /* If no locks provider, decline the request */
- locks_hooks = DAV_GET_HOOKS_LOCKS(r);
- if (locks_hooks == NULL)
- return DECLINED;
-
- if ((result = ap_xml_parse_input(r, &doc)) != OK)
- return result;
-
- depth = dav_get_depth(r, DAV_INFINITY);
- if (depth != 0 && depth != DAV_INFINITY) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "Depth must be 0 or \"infinity\" for LOCK.");
- return HTTP_BAD_REQUEST;
- }
-
- /* Ask repository module to resolve the resource */
- err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
- &resource);
- if (err != NULL)
- return dav_handle_err(r, err, NULL);
-
- /*
- ** Open writable. Unless an error occurs, we'll be
- ** writing into the database.
- */
- if ((err = (*locks_hooks->open_lockdb)(r, 0, 0, &lockdb)) != NULL) {
- /* ### add a higher-level description? */
- return dav_handle_err(r, err, NULL);
- }
-
- if (doc != NULL) {
- if ((err = dav_lock_parse_lockinfo(r, resource, lockdb, doc,
- &lock)) != NULL) {
- /* ### add a higher-level description to err? */
- goto error;
- }
- new_lock_request = 1;
-
- lock->auth_user = apr_pstrdup(r->pool, r->user);
- }
-
- resource_state = dav_get_resource_state(r, resource);
-
- /*
- ** Check If-Headers and existing locks.
- **
- ** If this will create a locknull resource, then the LOCK will affect
- ** the parent collection (much like a PUT/MKCOL). For that case, we must
- ** validate the parent resource's conditions.
- */
- if ((err = dav_validate_request(r, resource, depth, NULL, &multi_response,
- (resource_state == DAV_RESOURCE_NULL
- ? DAV_VALIDATE_PARENT
- : DAV_VALIDATE_RESOURCE)
- | (new_lock_request ? lock->scope : 0)
- | DAV_VALIDATE_ADD_LD,
- lockdb)) != OK) {
- err = dav_push_error(r->pool, err->status, 0,
- apr_psprintf(r->pool,
- "Could not LOCK %s due to a failed "
- "precondition (e.g. other locks).",
- ap_escape_html(r->pool, r->uri)),
- err);
- goto error;
- }
-
- if (new_lock_request == 0) {
- dav_locktoken_list *ltl;
-
- /*
- ** Refresh request
- ** ### Assumption: We can renew multiple locks on the same resource
- ** ### at once. First harvest all the positive lock-tokens given in
- ** ### the If header. Then modify the lock entries for this resource
- ** ### with the new Timeout val.
- */
-
- if ((err = dav_get_locktoken_list(r, &ltl)) != NULL) {
- err = dav_push_error(r->pool, err->status, 0,
- apr_psprintf(r->pool,
- "The lock refresh for %s failed "
- "because no lock tokens were "
- "specified in an \"If:\" "
- "header.",
- ap_escape_html(r->pool, r->uri)),
- err);
- goto error;
- }
-
- if ((err = (*locks_hooks->refresh_locks)(lockdb, resource, ltl,
- dav_get_timeout(r),
- &lock)) != NULL) {
- /* ### add a higher-level description to err? */
- goto error;
- }
- } else {
- /* New lock request */
- char *locktoken_txt;
- dav_dir_conf *conf;
-
- conf = (dav_dir_conf *) ap_get_module_config(r->per_dir_config,
- &dav_module);
-
- /* apply lower bound (if any) from DAVMinTimeout directive */
- if (lock->timeout != DAV_TIMEOUT_INFINITE
- && lock->timeout < time(NULL) + conf->locktimeout)
- lock->timeout = time(NULL) + conf->locktimeout;
-
- err = dav_add_lock(r, resource, lockdb, lock, &multi_response);
- if (err != NULL) {
- /* ### add a higher-level description to err? */
- goto error;
- }
-
- locktoken_txt = apr_pstrcat(r->pool, "<",
- (*locks_hooks->format_locktoken)(r->pool, lock->locktoken),
- ">", NULL);
-
- apr_table_set(r->headers_out, "Lock-Token", locktoken_txt);
- }
-
- (*locks_hooks->close_lockdb)(lockdb);
-
- r->status = HTTP_OK;
- r->content_type = DAV_XML_CONTENT_TYPE;
-
- ap_rputs(DAV_XML_HEADER DEBUG_CR "<D:prop xmlns:D=\"DAV:\">" DEBUG_CR, r);
- if (lock == NULL)
- ap_rputs("<D:lockdiscovery/>" DEBUG_CR, r);
- else {
- ap_rprintf(r,
- "<D:lockdiscovery>" DEBUG_CR
- "%s" DEBUG_CR
- "</D:lockdiscovery>" DEBUG_CR,
- dav_lock_get_activelock(r, lock, NULL));
- }
- ap_rputs("</D:prop>", r);
-
- /* the response has been sent. */
- return DONE;
-
- error:
- (*locks_hooks->close_lockdb)(lockdb);
- return dav_handle_err(r, err, multi_response);
-}
-
-/* dav_method_unlock: Handler to implement the DAV UNLOCK method
- * Returns appropriate HTTP_* response.
- */
-static int dav_method_unlock(request_rec *r)
-{
- dav_error *err;
- dav_resource *resource;
- const dav_hooks_locks *locks_hooks;
- int result;
- const char *const_locktoken_txt;
- char *locktoken_txt;
- dav_locktoken *locktoken = NULL;
- int resource_state;
- dav_response *multi_response;
-
- /* If no locks provider, decline the request */
- locks_hooks = DAV_GET_HOOKS_LOCKS(r);
- if (locks_hooks == NULL)
- return DECLINED;
-
- if ((const_locktoken_txt = apr_table_get(r->headers_in, "Lock-Token")) == NULL) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "Unlock failed (%s): No Lock-Token specified in header", r->filename);
- return HTTP_BAD_REQUEST;
- }
-
- locktoken_txt = apr_pstrdup(r->pool, const_locktoken_txt);
- if (locktoken_txt[0] != '<') {
- /* ### should provide more specifics... */
- return HTTP_BAD_REQUEST;
- }
- locktoken_txt++;
-
- if (locktoken_txt[strlen(locktoken_txt) - 1] != '>') {
- /* ### should provide more specifics... */
- return HTTP_BAD_REQUEST;
- }
- locktoken_txt[strlen(locktoken_txt) - 1] = '\0';
-
- if ((err = (*locks_hooks->parse_locktoken)(r->pool, locktoken_txt,
- &locktoken)) != NULL) {
- err = dav_push_error(r->pool, HTTP_BAD_REQUEST, 0,
- apr_psprintf(r->pool,
- "The UNLOCK on %s failed -- an "
- "invalid lock token was specified "
- "in the \"If:\" header.",
- ap_escape_html(r->pool, r->uri)),
- err);
- return dav_handle_err(r, err, NULL);
- }
-
- /* Ask repository module to resolve the resource */
- err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
- &resource);
- if (err != NULL)
- return dav_handle_err(r, err, NULL);
-
- resource_state = dav_get_resource_state(r, resource);
-
- /*
- ** Check If-Headers and existing locks.
- **
- ** Note: depth == 0 normally requires no multistatus response. However,
- ** if we pass DAV_VALIDATE_PARENT, then we could get an error on a URI
- ** other than the Request-URI, thereby requiring a multistatus.
- **
- ** If the resource is a locknull resource, then the UNLOCK will affect
- ** the parent collection (much like a delete). For that case, we must
- ** validate the parent resource's conditions.
- */
- if ((err = dav_validate_request(r, resource, 0, locktoken,
- &multi_response,
- resource_state == DAV_RESOURCE_LOCK_NULL
- ? DAV_VALIDATE_PARENT
- : DAV_VALIDATE_RESOURCE, NULL)) != NULL) {
- /* ### add a higher-level description? */
- return dav_handle_err(r, err, multi_response);
- }
-
- /* ### RFC 2518 s. 8.11: If this resource is locked by locktoken,
- * _all_ resources locked by locktoken are released. It does not say
- * resource has to be the root of an infinte lock. Thus, an UNLOCK
- * on any part of an infinte lock will remove the lock on all resources.
- *
- * For us, if r->filename represents an indirect lock (part of an infinity lock),
- * we must actually perform an UNLOCK on the direct lock for this resource.
- */
- if ((result = dav_unlock(r, resource, locktoken)) != OK) {
- return result;
- }
-
- return HTTP_NO_CONTENT;
-}
-
-static int dav_method_vsn_control(request_rec *r)
-{
- dav_resource *resource;
- int resource_state;
- dav_auto_version_info av_info;
- const dav_hooks_locks *locks_hooks = DAV_GET_HOOKS_LOCKS(r);
- const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
- dav_error *err;
- ap_xml_doc *doc;
- const char *target = NULL;
- int result;
-
- /* if no versioning provider, decline the request */
- if (vsn_hooks == NULL)
- return DECLINED;
-
- /* ask repository module to resolve the resource */
- err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
- &resource);
- if (err != NULL)
- return dav_handle_err(r, err, NULL);
-
- /* remember the pre-creation resource state */
- resource_state = dav_get_resource_state(r, resource);
-
- /* parse the request body (may be a version-control element) */
- if ((result = ap_xml_parse_input(r, &doc)) != OK) {
- return result;
- }
- /* note: doc == NULL if no request body */
-
- if (doc != NULL) {
- const ap_xml_elem *child;
- apr_size_t tsize;
-
- if (!dav_validate_root(doc, "version-control")) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "The request body does not contain "
- "a \"version-control\" element.");
- return HTTP_BAD_REQUEST;
- }
-
- /* get the version URI */
- if ((child = dav_find_child(doc->root, "version")) == NULL) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "The \"version-control\" element does not contain "
- "a \"version\" element.");
- return HTTP_BAD_REQUEST;
- }
-
- if ((child = dav_find_child(child, "href")) == NULL) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "The \"version\" element does not contain "
- "an \"href\" element.");
- return HTTP_BAD_REQUEST;
- }
-
- /* get version URI */
- ap_xml_to_text(r->pool, child, AP_XML_X2T_INNER, NULL, NULL,
- &target, &tsize);
- if (tsize == 0) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "An \"href\" element does not contain a URI.");
- return HTTP_BAD_REQUEST;
- }
- }
-
- /* Check request preconditions */
-
- /* ### need a general mechanism for reporting precondition violations
- * ### (should be returning XML document for 403/409 responses)
- */
-
- /* if not versioning existing resource, must specify version to select */
- if (!resource->exists && target == NULL) {
- err = dav_new_error(r->pool, HTTP_CONFLICT, 0,
- "<DAV:initial-version-required/>");
- return dav_handle_err(r, err, NULL);
- }
- else if (resource->exists) {
- /* cannot add resource to existing version history */
- if (target != NULL) {
- err = dav_new_error(r->pool, HTTP_CONFLICT, 0,
- "<DAV:cannot-add-to-existing-history/>");
- return dav_handle_err(r, err, NULL);
- }
-
- /* resource must be unversioned and versionable, or version selector */
- if (resource->type != DAV_RESOURCE_TYPE_REGULAR
- || (!resource->versioned && !(vsn_hooks->versionable)(resource))) {
- err = dav_new_error(r->pool, HTTP_CONFLICT, 0,
- "<DAV:must-be-versionable/>");
- return dav_handle_err(r, err, NULL);
- }
-
- /* the DeltaV spec says if resource is a version selector,
- * then VERSION-CONTROL is a no-op
- */
- if (resource->versioned) {
- /* set the Cache-Control header, per the spec */
- apr_table_setn(r->headers_out, "Cache-Control", "no-cache");
-
- /* no body */
- ap_set_content_length(r, 0);
-
- return DONE;
- }
- }
-
- /* Check If-Headers and existing locks */
- /* Note: depth == 0. Implies no need for a multistatus response. */
- if ((err = dav_validate_request(r, resource, 0, NULL, NULL,
- resource_state == DAV_RESOURCE_NULL ?
- DAV_VALIDATE_PARENT :
- DAV_VALIDATE_RESOURCE, NULL)) != NULL) {
- return dav_handle_err(r, err, NULL);
- }
-
- /* if in versioned collection, make sure parent is checked out */
- if ((err = dav_auto_checkout(r, resource, 1 /* parent_only */,
- &av_info)) != NULL) {
- return dav_handle_err(r, err, NULL);
- }
-
- /* attempt to version-control the resource */
- if ((err = (*vsn_hooks->vsn_control)(resource, target)) != NULL) {
- dav_auto_checkin(r, resource, 1 /*undo*/, 0 /*unlock*/, &av_info);
- err = dav_push_error(r->pool, HTTP_CONFLICT, 0,
- apr_psprintf(r->pool,
- "Could not VERSION-CONTROL resource %s.",
- ap_escape_html(r->pool, r->uri)),
- err);
- return dav_handle_err(r, err, NULL);
- }
-
- /* revert writability of parent directory */
- err = dav_auto_checkin(r, resource, 0 /*undo*/, 0 /*unlock*/, &av_info);
- if (err != NULL) {
- /* just log a warning */
- err = dav_push_error(r->pool, err->status, 0,
- "The VERSION-CONTROL was successful, but there "
- "was a problem automatically checking in "
- "the parent collection.",
- err);
- dav_log_err(r, err, APLOG_WARNING);
- }
-
- /* if the resource is lockable, let lock system know of new resource */
- if (locks_hooks != NULL
- && (*locks_hooks->get_supportedlock)(resource) != NULL) {
- dav_lockdb *lockdb;
-
- if ((err = (*locks_hooks->open_lockdb)(r, 0, 0, &lockdb)) != NULL) {
- /* The resource creation was successful, but the locking failed. */
- err = dav_push_error(r->pool, err->status, 0,
- "The VERSION-CONTROL was successful, but there "
- "was a problem opening the lock database "
- "which prevents inheriting locks from the "
- "parent resources.",
- err);
- return dav_handle_err(r, err, NULL);
- }
-
- /* notify lock system that we have created/replaced a resource */
- err = dav_notify_created(r, lockdb, resource, resource_state, 0);
-
- (*locks_hooks->close_lockdb)(lockdb);
-
- if (err != NULL) {
- /* The dir creation was successful, but the locking failed. */
- err = dav_push_error(r->pool, err->status, 0,
- "The VERSION-CONTROL was successful, but there "
- "was a problem updating its lock "
- "information.",
- err);
- return dav_handle_err(r, err, NULL);
- }
- }
-
- /* set the Cache-Control header, per the spec */
- apr_table_setn(r->headers_out, "Cache-Control", "no-cache");
-
- /* return an appropriate response (HTTP_CREATED) */
- return dav_created(r, resource->uri, "Version selector", 0 /*replaced*/);
-}
-
-/* handle the CHECKOUT method */
-static int dav_method_checkout(request_rec *r)
-{
- dav_resource *resource;
- dav_resource *working_resource;
- const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
- dav_error *err;
- int result;
- ap_xml_doc *doc;
- int apply_to_vsn = 0;
- int is_unreserved = 0;
- int is_fork_ok = 0;
- int create_activity = 0;
- apr_array_header_t *activities = NULL;
-
- /* If no versioning provider, decline the request */
- if (vsn_hooks == NULL)
- return DECLINED;
-
- if ((result = ap_xml_parse_input(r, &doc)) != OK)
- return result;
-
- if (doc != NULL) {
- const ap_xml_elem *aset;
-
- if (!dav_validate_root(doc, "checkout")) {
- /* This supplies additional information for the default msg. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "The request body, if present, must be a "
- "DAV:checkout element.");
- return HTTP_BAD_REQUEST;
- }
-
- if (dav_find_child(doc->root, "apply-to-version") != NULL) {
- if (apr_table_get(r->headers_in, "label") != NULL) {
- /* ### we want generic 403/409 XML reporting here */
- /* ### DAV:must-not-have-label-and-apply-to-version */
- return dav_error_response(r, HTTP_CONFLICT,
- "DAV:apply-to-version cannot be "
- "used in conjunction with a "
- "Label header.");
- }
- apply_to_vsn = 1;
- }
-
- is_unreserved = dav_find_child(doc->root, "unreserved") != NULL;
- is_fork_ok = dav_find_child(doc->root, "fork-ok") != NULL;
-
- if ((aset = dav_find_child(doc->root, "activity-set")) != NULL) {
- if (dav_find_child(aset, "new") != NULL) {
- create_activity = 1;
- }
- else {
- const ap_xml_elem *child = aset->first_child;
-
- activities = apr_array_make(r->pool, 1, sizeof(const char *));
-
- for (; child != NULL; child = child->next) {
- if (child->ns == AP_XML_NS_DAV_ID
- && strcmp(child->name, "href") == 0) {
- const char *href;
-
- href = dav_xml_get_cdata(child, r->pool,
- 1 /* strip_white */);
- *(const char **)apr_array_push(activities) = href;
- }
- }
-
- if (activities->nelts == 0) {
- /* no href's is a DTD violation:
- <!ELEMENT activity-set (href+ | new)>
- */
-
- /* This supplies additional info for the default msg. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "Within the DAV:activity-set element, the "
- "DAV:new element must be used, or at least "
- "one DAV:href must be specified.");
- return HTTP_BAD_REQUEST;
- }
- }
- }
- }
-
- /* Ask repository module to resolve the resource */
- err = dav_get_resource(r, 1 /*label_allowed*/, apply_to_vsn, &resource);
- if (err != NULL)
- return dav_handle_err(r, err, NULL);
- if (!resource->exists) {
- /* Apache will supply a default error for this. */
- return HTTP_NOT_FOUND;
- }
-
- /* Check the state of the resource: must be a file or collection,
- * must be versioned, and must not already be checked out.
- */
- if (resource->type != DAV_RESOURCE_TYPE_REGULAR
- && resource->type != DAV_RESOURCE_TYPE_VERSION) {
- return dav_error_response(r, HTTP_CONFLICT,
- "Cannot checkout this type of resource.");
- }
-
- if (!resource->versioned) {
- return dav_error_response(r, HTTP_CONFLICT,
- "Cannot checkout unversioned resource.");
- }
-
- if (resource->working) {
- return dav_error_response(r, HTTP_CONFLICT,
- "The resource is already checked out to the workspace.");
- }
-
- /* ### do lock checks, once behavior is defined */
-
- /* Do the checkout */
- if ((err = (*vsn_hooks->checkout)(resource, 0 /*auto_checkout*/,
- is_unreserved, is_fork_ok,
- create_activity, activities,
- &working_resource)) != NULL) {
- err = dav_push_error(r->pool, HTTP_CONFLICT, 0,
- apr_psprintf(r->pool,
- "Could not CHECKOUT resource %s.",
- ap_escape_html(r->pool, r->uri)),
- err);
- return dav_handle_err(r, err, NULL);
- }
-
- /* set the Cache-Control header, per the spec */
- apr_table_setn(r->headers_out, "Cache-Control", "no-cache");
-
- /* if no working resource created, return OK,
- * else return CREATED with working resource URL in Location header
- */
- if (working_resource == NULL) {
- /* no body */
- ap_set_content_length(r, 0);
- return DONE;
- }
-
- return dav_created(r, working_resource->uri, "Checked-out resource", 0);
-}
-
-/* handle the UNCHECKOUT method */
-static int dav_method_uncheckout(request_rec *r)
-{
- dav_resource *resource;
- const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
- dav_error *err;
- int result;
-
- /* If no versioning provider, decline the request */
- if (vsn_hooks == NULL)
- return DECLINED;
-
- if ((result = ap_discard_request_body(r)) != OK) {
- return result;
- }
-
- /* Ask repository module to resolve the resource */
- err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
- &resource);
- if (err != NULL)
- return dav_handle_err(r, err, NULL);
- if (!resource->exists) {
- /* Apache will supply a default error for this. */
- return HTTP_NOT_FOUND;
- }
-
- /* Check the state of the resource: must be a file or collection,
- * must be versioned, and must be checked out.
- */
- if (resource->type != DAV_RESOURCE_TYPE_REGULAR) {
- return dav_error_response(r, HTTP_CONFLICT,
- "Cannot uncheckout this type of resource.");
- }
-
- if (!resource->versioned) {
- return dav_error_response(r, HTTP_CONFLICT,
- "Cannot uncheckout unversioned resource.");
- }
-
- if (!resource->working) {
- return dav_error_response(r, HTTP_CONFLICT,
- "The resource is not checked out to the workspace.");
- }
-
- /* ### do lock checks, once behavior is defined */
-
- /* Do the uncheckout */
- if ((err = (*vsn_hooks->uncheckout)(resource)) != NULL) {
- err = dav_push_error(r->pool, HTTP_CONFLICT, 0,
- apr_psprintf(r->pool,
- "Could not UNCHECKOUT resource %s.",
- ap_escape_html(r->pool, r->uri)),
- err);
- return dav_handle_err(r, err, NULL);
- }
-
- /* no body */
- ap_set_content_length(r, 0);
-
- return DONE;
-}
-
-/* handle the CHECKIN method */
-static int dav_method_checkin(request_rec *r)
-{
- dav_resource *resource;
- dav_resource *new_version;
- const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
- dav_error *err;
- int result;
- ap_xml_doc *doc;
- int keep_checked_out = 0;
-
- /* If no versioning provider, decline the request */
- if (vsn_hooks == NULL)
- return DECLINED;
-
- if ((result = ap_xml_parse_input(r, &doc)) != OK)
- return result;
-
- if (doc != NULL) {
- if (!dav_validate_root(doc, "checkin")) {
- /* This supplies additional information for the default msg. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "The request body, if present, must be a "
- "DAV:checkin element.");
- return HTTP_BAD_REQUEST;
- }
-
- keep_checked_out = dav_find_child(doc->root, "keep-checked-out") != NULL;
- }
-
- /* Ask repository module to resolve the resource */
- err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
- &resource);
- if (err != NULL)
- return dav_handle_err(r, err, NULL);
- if (!resource->exists) {
- /* Apache will supply a default error for this. */
- return HTTP_NOT_FOUND;
- }
-
- /* Check the state of the resource: must be a file or collection,
- * must be versioned, and must be checked out.
- */
- if (resource->type != DAV_RESOURCE_TYPE_REGULAR) {
- return dav_error_response(r, HTTP_CONFLICT,
- "Cannot checkin this type of resource.");
- }
-
- if (!resource->versioned) {
- return dav_error_response(r, HTTP_CONFLICT,
- "Cannot checkin unversioned resource.");
- }
-
- if (!resource->working) {
- return dav_error_response(r, HTTP_CONFLICT,
- "The resource is not checked out.");
- }
-
- /* ### do lock checks, once behavior is defined */
-
- /* Do the checkin */
- if ((err = (*vsn_hooks->checkin)(resource, keep_checked_out, &new_version))
- != NULL) {
- err = dav_push_error(r->pool, HTTP_CONFLICT, 0,
- apr_psprintf(r->pool,
- "Could not CHECKIN resource %s.",
- ap_escape_html(r->pool, r->uri)),
- err);
- return dav_handle_err(r, err, NULL);
- }
-
- return dav_created(r, new_version->uri, "Version", 0);
-}
-
-static int dav_method_update(request_rec *r)
-{
- dav_resource *resource;
- dav_resource *version = NULL;
- const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
- ap_xml_doc *doc;
- ap_xml_elem *child;
- int is_label = 0;
- int depth;
- int result;
- apr_size_t tsize;
- const char *target;
- dav_response *multi_response;
- dav_error *err;
- dav_lookup_result lookup;
-
- /* If no versioning provider, or UPDATE not supported,
- * decline the request */
- if (vsn_hooks == NULL || vsn_hooks->update == NULL)
- return DECLINED;
-
- if ((depth = dav_get_depth(r, 0)) < 0) {
- /* dav_get_depth() supplies additional information for the
- * default message. */
- return HTTP_BAD_REQUEST;
- }
-
- /* parse the request body */
- if ((result = ap_xml_parse_input(r, &doc)) != OK) {
- return result;
- }
-
- if (doc == NULL || !dav_validate_root(doc, "update")) {
- /* This supplies additional information for the default message. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "The request body does not contain "
- "an \"update\" element.");
- return HTTP_BAD_REQUEST;
- }
-
- /* check for label-name or version element, but not both */
- if ((child = dav_find_child(doc->root, "label-name")) != NULL)
- is_label = 1;
- else if ((child = dav_find_child(doc->root, "version")) != NULL) {
- /* get the href element */
- if ((child = dav_find_child(child, "href")) == NULL) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "The version element does not contain "
- "an \"href\" element.");
- return HTTP_BAD_REQUEST;
- }
- }
- else {
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "The \"update\" element does not contain "
- "a \"label-name\" or \"version\" element.");
- return HTTP_BAD_REQUEST;
- }
-
- /* a depth greater than zero is only allowed for a label */
- if (!is_label && depth != 0) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "Depth must be zero for UPDATE with a version");
- return HTTP_BAD_REQUEST;
- }
-
- /* get the target value (a label or a version URI) */
- ap_xml_to_text(r->pool, child, AP_XML_X2T_INNER, NULL, NULL,
- &target, &tsize);
- if (tsize == 0) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "A \"label-name\" or \"href\" element does not contain "
- "any content.");
- return HTTP_BAD_REQUEST;
- }
-
- /* Ask repository module to resolve the resource */
- err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
- &resource);
- if (err != NULL)
- return dav_handle_err(r, err, NULL);
-
- if (!resource->exists) {
- /* Apache will supply a default error for this. */
- return HTTP_NOT_FOUND;
- }
-
- /* ### need a general mechanism for reporting precondition violations
- * ### (should be returning XML document for 403/409 responses)
- */
- if (resource->type != DAV_RESOURCE_TYPE_REGULAR
- || !resource->versioned || resource->working) {
- return dav_error_response(r, HTTP_CONFLICT,
- "<DAV:must-be-checked-in-version-controlled-resource>");
- }
-
- /* if target is a version, resolve the version resource */
- /* ### dav_lookup_uri only allows absolute URIs; is that OK? */
- if (!is_label) {
- lookup = dav_lookup_uri(target, r, 0 /* must_be_absolute */);
- if (lookup.rnew == NULL) {
- if (lookup.err.status == HTTP_BAD_REQUEST) {
- /* This supplies additional information for the default message. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- lookup.err.desc);
- return HTTP_BAD_REQUEST;
- }
-
- /* ### this assumes that dav_lookup_uri() only generates a status
- * ### that Apache can provide a status line for!! */
-
- return dav_error_response(r, lookup.err.status, lookup.err.desc);
- }
- if (lookup.rnew->status != HTTP_OK) {
- /* ### how best to report this... */
- return dav_error_response(r, lookup.rnew->status,
- "Version URI had an error.");
- }
-
- /* resolve version resource */
- err = dav_get_resource(lookup.rnew, 0 /* label_allowed */,
- 0 /* use_checked_in */, &version);
- if (err != NULL)
- return dav_handle_err(r, err, NULL);
-
- /* NULL out target, since we're using a version resource */
- target = NULL;
- }
-
- /* do the UPDATE operation */
- err = (*vsn_hooks->update)(resource, version, target, depth, &multi_response);
-
- if (err != NULL) {
- err = dav_push_error(r->pool, err->status, 0,
- ap_psprintf(r->pool,
- "Could not UPDATE %s.",
- ap_escape_html(r->pool, r->uri)),
- err);
- return dav_handle_err(r, err, multi_response);
- }
-
- /* set the Cache-Control header, per the spec */
- apr_table_setn(r->headers_out, "Cache-Control", "no-cache");
-
- /* no body */
- ap_set_content_length(r, 0);
-
- return DONE;
-}
-
-/* context maintained during LABEL treewalk */
-typedef struct dav_label_walker_ctx
-{
- /* input: */
- dav_walk_params w;
-
- /* label being manipulated */
- const char *label;
-
- /* label operation */
- int label_op;
-#define DAV_LABEL_ADD 1
-#define DAV_LABEL_SET 2
-#define DAV_LABEL_REMOVE 3
-
- /* version provider hooks */
- const dav_hooks_vsn *vsn_hooks;
-
-} dav_label_walker_ctx;
-
-static dav_error * dav_label_walker(dav_walk_resource *wres, int calltype)
-{
- dav_label_walker_ctx *ctx = wres->walk_ctx;
- dav_error *err = NULL;
-
- /* Check the state of the resource: must be a version or
- * non-checkedout version selector
- */
- /* ### need a general mechanism for reporting precondition violations
- * ### (should be returning XML document for 403/409 responses)
- */
- if (wres->resource->type != DAV_RESOURCE_TYPE_VERSION &&
- (wres->resource->type != DAV_RESOURCE_TYPE_REGULAR
- || !wres->resource->versioned)) {
- err = dav_new_error(ctx->w.pool, HTTP_CONFLICT, 0,
- "<DAV:must-be-version-or-version-selector/>");
- }
- else if (wres->resource->working) {
- err = dav_new_error(ctx->w.pool, HTTP_CONFLICT, 0,
- "<DAV:must-not-be-checked-out/>");
- }
- else {
- /* do the label operation */
- if (ctx->label_op == DAV_LABEL_REMOVE)
- err = (*ctx->vsn_hooks->remove_label)(wres->resource, ctx->label);
- else
- err = (*ctx->vsn_hooks->add_label)(wres->resource, ctx->label,
- ctx->label_op == DAV_LABEL_SET);
- }
-
- if (err != NULL) {
- /* ### need utility routine to add response with description? */
- dav_add_response(wres, err->status, NULL);
- wres->response->desc = err->desc;
- }
-
- return NULL;
-}
-
-static int dav_method_label(request_rec *r)
-{
- dav_resource *resource;
- const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
- ap_xml_doc *doc;
- ap_xml_elem *child;
- int depth;
- int result;
- apr_size_t tsize;
- dav_error *err;
- dav_label_walker_ctx ctx = { { 0 } };
- dav_response *multi_status;
-
- /* If no versioning provider, or the provider doesn't support
- * labels, decline the request */
- if (vsn_hooks == NULL || vsn_hooks->add_label == NULL)
- return DECLINED;
-
- /* Ask repository module to resolve the resource */
- err = dav_get_resource(r, 1 /* label_allowed */, 0 /* use_checked_in */,
- &resource);
- if (err != NULL)
- return dav_handle_err(r, err, NULL);
- if (!resource->exists) {
- /* Apache will supply a default error for this. */
- return HTTP_NOT_FOUND;
- }
-
- if ((depth = dav_get_depth(r, 0)) < 0) {
- /* dav_get_depth() supplies additional information for the
- * default message. */
- return HTTP_BAD_REQUEST;
- }
-
- /* parse the request body */
- if ((result = ap_xml_parse_input(r, &doc)) != OK) {
- return result;
- }
-
- if (doc == NULL || !dav_validate_root(doc, "label")) {
- /* This supplies additional information for the default message. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "The request body does not contain "
- "a \"label\" element.");
- return HTTP_BAD_REQUEST;
- }
-
- /* check for add, set, or remove element */
- if ((child = dav_find_child(doc->root, "add")) != NULL) {
- ctx.label_op = DAV_LABEL_ADD;
- }
- else if ((child = dav_find_child(doc->root, "set")) != NULL) {
- ctx.label_op = DAV_LABEL_SET;
- }
- else if ((child = dav_find_child(doc->root, "remove")) != NULL) {
- ctx.label_op = DAV_LABEL_REMOVE;
- }
- else {
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "The \"label\" element does not contain "
- "an \"add\", \"set\", or \"remove\" element.");
- return HTTP_BAD_REQUEST;
- }
-
- /* get the label string */
- if ((child = dav_find_child(child, "label-name")) == NULL) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "The label command element does not contain "
- "a \"label-name\" element.");
- return HTTP_BAD_REQUEST;
- }
-
- ap_xml_to_text(r->pool, child, AP_XML_X2T_INNER, NULL, NULL,
- &ctx.label, &tsize);
- if (tsize == 0) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "A \"label-name\" element does not contain "
- "a label name.");
- return HTTP_BAD_REQUEST;
- }
-
- /* do the label operation walk */
- ctx.w.walk_type = DAV_WALKTYPE_NORMAL;
- ctx.w.func = dav_label_walker;
- ctx.w.walk_ctx = &ctx;
- ctx.w.pool = r->pool;
- ctx.w.root = resource;
- ctx.vsn_hooks = vsn_hooks;
-
- err = (*resource->hooks->walk)(&ctx.w, depth, &multi_status);
-
- if (err != NULL) {
- /* some sort of error occurred which terminated the walk */
- err = dav_push_error(r->pool, err->status, 0,
- "The LABEL operation was terminated prematurely.",
- err);
- return dav_handle_err(r, err, multi_status);
- }
-
- if (multi_status != NULL) {
- /* One or more resources had errors. If depth was zero, convert
- * response to simple error, else make sure there is an
- * overall error to pass to dav_handle_err()
- */
- if (depth == 0) {
- err = dav_new_error(r->pool, multi_status->status, 0, multi_status->desc);
- multi_status = NULL;
- }
- else {
- err = dav_new_error(r->pool, HTTP_MULTI_STATUS, 0,
- "Errors occurred during the LABEL operation.");
- }
-
- return dav_handle_err(r, err, multi_status);
- }
-
- /* set the Cache-Control header, per the spec */
- apr_table_setn(r->headers_out, "Cache-Control", "no-cache");
-
- /* no body */
- ap_set_content_length(r, 0);
-
- return DONE;
-}
-
-static int dav_method_report(request_rec *r)
-{
- dav_resource *resource;
- const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
- int result;
- int label_allowed;
- ap_xml_doc *doc;
- ap_text_header hdr = { 0 };
- ap_text *t;
- dav_error *err;
-
- /* If no versioning provider, decline the request */
- if (vsn_hooks == NULL)
- return DECLINED;
-
- if ((result = ap_xml_parse_input(r, &doc)) != OK)
- return result;
- if (doc == NULL) {
- /* This supplies additional information for the default msg. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "The request body must specify a report.");
- return HTTP_BAD_REQUEST;
- }
-
- /* Ask repository module to resolve the resource.
- * First determine whether a Target-Selector header is allowed
- * for this report.
- */
- label_allowed = (*vsn_hooks->report_label_header_allowed)(doc);
- err = dav_get_resource(r, label_allowed, 0 /* use_checked_in */,
- &resource);
- if (err != NULL)
- return dav_handle_err(r, err, NULL);
- if (!resource->exists) {
- /* Apache will supply a default error for this. */
- return HTTP_NOT_FOUND;
- }
-
- /* run report hook */
- /* ### writing large reports to memory could be bad...
- * ### but if provider generated output directly, it would
- * ### have to handle error responses as well.
- */
- if ((err = (*vsn_hooks->get_report)(r, resource, doc, &hdr)) != NULL)
- return dav_handle_err(r, err, NULL);
-
- /* send the report response */
- r->status = HTTP_OK;
- r->content_type = DAV_XML_CONTENT_TYPE;
-
- /* send the headers and response body */
- ap_rputs(DAV_XML_HEADER DEBUG_CR, r);
-
- for (t = hdr.first; t != NULL; t = t->next)
- ap_rputs(t->text, r);
-
- return DONE;
-}
-
-static int dav_method_make_workspace(request_rec *r)
-{
- dav_resource *resource;
- const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
- dav_error *err;
- ap_xml_doc *doc;
- int result;
-
- /* if no versioning provider, or the provider does not support workspaces,
- * decline the request
- */
- if (vsn_hooks == NULL || vsn_hooks->make_workspace == NULL)
- return DECLINED;
-
- /* ask repository module to resolve the resource */
- err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
- &resource);
- if (err != NULL)
- return dav_handle_err(r, err, NULL);
-
- /* parse the request body (must be a mkworkspace element) */
- if ((result = ap_xml_parse_input(r, &doc)) != OK) {
- return result;
- }
-
- if (doc == NULL
- || !dav_validate_root(doc, "mkworkspace")) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "The request body does not contain "
- "a \"mkworkspace\" element.");
- return HTTP_BAD_REQUEST;
- }
-
- /* Check request preconditions */
-
- /* ### need a general mechanism for reporting precondition violations
- * ### (should be returning XML document for 403/409 responses)
- */
-
- /* resource must not already exist */
- if (resource->exists) {
- err = dav_new_error(r->pool, HTTP_CONFLICT, 0,
- "<DAV:resource-must-be-null/>");
- return dav_handle_err(r, err, NULL);
- }
-
- /* ### what about locking? */
-
- /* attempt to create the workspace */
- if ((err = (*vsn_hooks->make_workspace)(resource, doc)) != NULL) {
- err = dav_push_error(r->pool, err->status, 0,
- apr_psprintf(r->pool,
- "Could not create workspace %s.",
- ap_escape_html(r->pool, r->uri)),
- err);
- return dav_handle_err(r, err, NULL);
- }
-
- /* set the Cache-Control header, per the spec */
- apr_table_setn(r->headers_out, "Cache-Control", "no-cache");
-
- /* return an appropriate response (HTTP_CREATED) */
- return dav_created(r, resource->uri, "Workspace", 0 /*replaced*/);
-}
-
-static int dav_method_make_activity(request_rec *r)
-{
- dav_resource *resource;
- const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
- dav_error *err;
- int result;
-
- /* if no versioning provider, or the provider does not support activities,
- * decline the request
- */
- if (vsn_hooks == NULL || vsn_hooks->make_activity == NULL)
- return DECLINED;
-
- /* ask repository module to resolve the resource */
- err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
- &resource);
- if (err != NULL)
- return dav_handle_err(r, err, NULL);
-
- /* MKACTIVITY does not have a defined request body. */
- if ((result = ap_discard_request_body(r)) != OK) {
- return result;
- }
-
- /* Check request preconditions */
-
- /* ### need a general mechanism for reporting precondition violations
- * ### (should be returning XML document for 403/409 responses)
- */
-
- /* resource must not already exist */
- if (resource->exists) {
- err = dav_new_error(r->pool, HTTP_CONFLICT, 0,
- "<DAV:resource-must-be-null/>");
- return dav_handle_err(r, err, NULL);
- }
-
- /* ### what about locking? */
-
- /* attempt to create the activity */
- if ((err = (*vsn_hooks->make_activity)(resource)) != NULL) {
- err = dav_push_error(r->pool, err->status, 0,
- apr_psprintf(r->pool,
- "Could not create activity %s.",
- ap_escape_html(r->pool, r->uri)),
- err);
- return dav_handle_err(r, err, NULL);
- }
-
- /* set the Cache-Control header, per the spec */
- apr_table_setn(r->headers_out, "Cache-Control", "no-cache");
-
- /* return an appropriate response (HTTP_CREATED) */
- return dav_created(r, resource->uri, "Activity", 0 /*replaced*/);
-}
-
-static int dav_method_baseline_control(request_rec *r)
-{
- /* ### */
- return HTTP_METHOD_NOT_ALLOWED;
-}
-
-static int dav_method_merge(request_rec *r)
-{
- dav_resource *resource;
- dav_resource *source_resource;
- const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
- dav_error *err;
- int result;
- ap_xml_doc *doc;
- ap_xml_elem *source_elem;
- ap_xml_elem *href_elem;
- ap_xml_elem *prop_elem;
- const char *source;
- int no_auto_merge;
- int no_checkout;
- dav_lookup_result lookup;
-
- /* If no versioning provider, decline the request */
- if (vsn_hooks == NULL)
- return DECLINED;
-
- if ((result = ap_xml_parse_input(r, &doc)) != OK)
- return result;
-
- if (doc == NULL || !dav_validate_root(doc, "merge")) {
- /* This supplies additional information for the default msg. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "The request body must be present and must be a "
- "DAV:merge element.");
- return HTTP_BAD_REQUEST;
- }
-
- if ((source_elem = dav_find_child(doc->root, "source")) == NULL) {
- /* This supplies additional information for the default msg. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "The DAV:merge element must contain a DAV:source "
- "element.");
- return HTTP_BAD_REQUEST;
- }
- if ((href_elem = dav_find_child(source_elem, "href")) == NULL) {
- /* This supplies additional information for the default msg. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "The DAV:source element must contain a DAV:href "
- "element.");
- return HTTP_BAD_REQUEST;
- }
- source = dav_xml_get_cdata(href_elem, r->pool, 1 /* strip_white */);
-
- /* get a subrequest for the source, so that we can get a dav_resource
- for that source. */
- lookup = dav_lookup_uri(source, r, 0 /* must_be_absolute */);
- if (lookup.rnew == NULL) {
- if (lookup.err.status == HTTP_BAD_REQUEST) {
- /* This supplies additional information for the default message. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- lookup.err.desc);
- return HTTP_BAD_REQUEST;
- }
-
- /* ### this assumes that dav_lookup_uri() only generates a status
- * ### that Apache can provide a status line for!! */
-
- return dav_error_response(r, lookup.err.status, lookup.err.desc);
- }
- if (lookup.rnew->status != HTTP_OK) {
- /* ### how best to report this... */
- return dav_error_response(r, lookup.rnew->status,
- "Merge source URI had an error.");
- }
- err = dav_get_resource(lookup.rnew, 0 /* label_allowed */,
- 0 /* use_checked_in */, &source_resource);
- if (err != NULL)
- return dav_handle_err(r, err, NULL);
-
- no_auto_merge = dav_find_child(doc->root, "no-auto-merge") != NULL;
- no_checkout = dav_find_child(doc->root, "no-checkout") != NULL;
-
- prop_elem = dav_find_child(doc->root, "prop");
-
- /* ### check RFC. I believe the DAV:merge element may contain any
- ### element also allowed within DAV:checkout. need to extract them
- ### here, and pass them along.
- ### if so, then refactor the CHECKOUT method handling so we can reuse
- ### the code. maybe create a structure to hold CHECKOUT parameters
- ### which can be passed to the checkout() and merge() hooks. */
-
- /* Ask repository module to resolve the resource */
- err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
- &resource);
- if (err != NULL)
- return dav_handle_err(r, err, NULL);
- if (!resource->exists) {
- /* Apache will supply a default error for this. */
- return HTTP_NOT_FOUND;
- }
-
- /* ### check the source and target resources flags/types */
-
- /* ### do lock checks, once behavior is defined */
-
- /* set the Cache-Control header, per the spec */
- /* ### correct? */
- apr_table_setn(r->headers_out, "Cache-Control", "no-cache");
-
- /* Initialize these values for a standard MERGE response. If the MERGE
- is going to do something different (i.e. an error), then it must
- return a dav_error, and we'll reset these values properly. */
- r->status = HTTP_OK;
- r->status_line = ap_get_status_line(HTTP_OK); /* ### needed? */
- r->content_type = "text/xml";
-
- /* ### should we do any preliminary response generation? probably not,
- ### because we may have an error, thus demanding something else in
- ### the response body. */
-
- /* Do the merge, including any response generation. */
- if ((err = (*vsn_hooks->merge)(resource, source_resource,
- no_auto_merge, no_checkout,
- prop_elem,
- r->output_filters)) != NULL) {
- /* ### is err->status the right error here? */
- err = dav_push_error(r->pool, err->status, 0,
- apr_psprintf(r->pool,
- "Could not MERGE resource \"%s\" "
- "into \"%s\".",
- ap_escape_html(r->pool, source),
- ap_escape_html(r->pool, r->uri)),
- err);
- return dav_handle_err(r, err, NULL);
- }
-
- /* the response was fully generated by the merge() hook. */
- /* ### urk. does this prevent logging? need to check... */
- return DONE;
-}
-
-static int dav_method_bind(request_rec *r)
-{
- dav_resource *resource;
- dav_resource *binding;
- dav_auto_version_info av_info;
- const dav_hooks_binding *binding_hooks = DAV_GET_HOOKS_BINDING(r);
- const char *dest;
- dav_error *err;
- dav_error *err2;
- dav_response *multi_response = NULL;
- dav_lookup_result lookup;
- int overwrite;
-
- /* If no bindings provider, decline the request */
- if (binding_hooks == NULL)
- return DECLINED;
-
- /* Ask repository module to resolve the resource */
- err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
- &resource);
- if (err != NULL)
- return dav_handle_err(r, err, NULL);
- if (!resource->exists) {
- /* Apache will supply a default error for this. */
- return HTTP_NOT_FOUND;
- }
-
- /* get the destination URI */
- dest = apr_table_get(r->headers_in, "Destination");
- if (dest == NULL) {
- /* This supplies additional information for the default message. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "The request is missing a Destination header.");
- return HTTP_BAD_REQUEST;
- }
-
- lookup = dav_lookup_uri(dest, r, 0 /* must_be_absolute */);
- if (lookup.rnew == NULL) {
- if (lookup.err.status == HTTP_BAD_REQUEST) {
- /* This supplies additional information for the default message. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- lookup.err.desc);
- return HTTP_BAD_REQUEST;
- }
- else if (lookup.err.status == HTTP_BAD_GATEWAY) {
- /* ### Bindings protocol draft 02 says to return 507
- * ### (Cross Server Binding Forbidden); Apache already defines 507
- * ### as HTTP_INSUFFICIENT_STORAGE. So, for now, we'll return
- * ### HTTP_FORBIDDEN
- */
- return dav_error_response(r, HTTP_FORBIDDEN,
- "Cross server bindings are not allowed by this server.");
- }
-
- /* ### this assumes that dav_lookup_uri() only generates a status
- * ### that Apache can provide a status line for!! */
-
- return dav_error_response(r, lookup.err.status, lookup.err.desc);
- }
- if (lookup.rnew->status != HTTP_OK) {
- /* ### how best to report this... */
- return dav_error_response(r, lookup.rnew->status,
- "Destination URI had an error.");
- }
-
- /* resolve binding resource */
- err = dav_get_resource(lookup.rnew, 0 /* label_allowed */,
- 0 /* use_checked_in */, &binding);
- if (err != NULL)
- return dav_handle_err(r, err, NULL);
-
- /* are the two resources handled by the same repository? */
- if (resource->hooks != binding->hooks) {
- /* ### this message exposes some backend config, but screw it... */
- return dav_error_response(r, HTTP_BAD_GATEWAY,
- "Destination URI is handled by a "
- "different repository than the source URI. "
- "BIND between repositories is not possible.");
- }
-
- /* get and parse the overwrite header value */
- if ((overwrite = dav_get_overwrite(r)) < 0) {
- /* dav_get_overwrite() supplies additional information for the
- * default message. */
- return HTTP_BAD_REQUEST;
- }
-
- /* quick failure test: if dest exists and overwrite is false. */
- if (binding->exists && !overwrite) {
- return dav_error_response(r, HTTP_PRECONDITION_FAILED,
- "Destination is not empty and "
- "Overwrite is not \"T\"");
- }
-
- /* are the source and destination the same? */
- if ((*resource->hooks->is_same_resource)(resource, binding)) {
- return dav_error_response(r, HTTP_FORBIDDEN,
- "Source and Destination URIs are the same.");
- }
-
- /*
- ** Check If-Headers and existing locks for destination. Note that we
- ** use depth==infinity since the target (hierarchy) will be deleted
- ** before the move/copy is completed.
- **
- ** Note that we are overwriting the target, which implies a DELETE, so
- ** we are subject to the error/response rules as a DELETE. Namely, we
- ** will return a 424 error if any of the validations fail.
- ** (see dav_method_delete() for more information)
- */
- if ((err = dav_validate_request(lookup.rnew, binding, DAV_INFINITY, NULL,
- &multi_response,
- DAV_VALIDATE_PARENT
- | DAV_VALIDATE_USE_424, NULL)) != NULL) {
- err = dav_push_error(r->pool, err->status, 0,
- apr_psprintf(r->pool,
- "Could not BIND %s due to a "
- "failed precondition on the "
- "destination (e.g. locks).",
- ap_escape_html(r->pool, r->uri)),
- err);
- return dav_handle_err(r, err, multi_response);
- }
-
- /* guard against creating circular bindings */
- if (resource->collection
- && (*resource->hooks->is_parent_resource)(resource, binding)) {
- return dav_error_response(r, HTTP_FORBIDDEN,
- "Source collection contains the Destination.");
- }
- if (resource->collection
- && (*resource->hooks->is_parent_resource)(binding, resource)) {
- /* The destination must exist (since it contains the source), and
- * a condition above implies Overwrite==T. Obviously, we cannot
- * delete the Destination before the BIND, as that would
- * delete the Source.
- */
-
- return dav_error_response(r, HTTP_FORBIDDEN,
- "Destination collection contains the Source and "
- "Overwrite has been specified.");
- }
-
- /* prepare the destination collection for modification */
- if ((err = dav_auto_checkout(r, binding, 1 /* parent_only */,
- &av_info)) != NULL) {
- /* could not make destination writable */
- return dav_handle_err(r, err, NULL);
- }
-
- /* If target exists, remove it first (we know Ovewrite must be TRUE).
- * Then try to bind to the resource.
- */
- if (binding->exists)
- err = (*resource->hooks->remove_resource)(binding, &multi_response);
-
- if (err == NULL) {
- err = (*binding_hooks->bind_resource)(resource, binding);
- }
-
- /* restore parent collection states */
- err2 = dav_auto_checkin(r, NULL,
- err != NULL /* undo if error */,
- 0 /*unlock*/, &av_info);
-
- /* check for error from remove/bind operations */
- if (err != NULL) {
- err = dav_push_error(r->pool, err->status, 0,
- apr_psprintf(r->pool,
- "Could not BIND %s.",
- ap_escape_html(r->pool, r->uri)),
- err);
- return dav_handle_err(r, err, multi_response);
- }
-
- /* check for errors from reverting writability */
- if (err2 != NULL) {
- /* just log a warning */
- err = dav_push_error(r->pool, err2->status, 0,
- "The BIND was successful, but there was a "
- "problem automatically checking in the "
- "source parent collection.",
- err2);
- dav_log_err(r, err, APLOG_WARNING);
- }
-
- /* return an appropriate response (HTTP_CREATED) */
- /* ### spec doesn't say what happens when destination was replaced */
- return dav_created(r, lookup.rnew->uri, "Binding", 0);
-}
-
-
-/*
- * Response handler for DAV resources
- */
-static int dav_handler(request_rec *r)
-{
- dav_dir_conf *conf;
-
- if (strcmp(r->handler, "dav-handler")) {
- return DECLINED;
- }
-
- /* quickly ignore any HTTP/0.9 requests */
- if (r->assbackwards) {
- return DECLINED;
- }
-
- /* ### do we need to do anything with r->proxyreq ?? */
-
- conf = (dav_dir_conf *) ap_get_module_config(r->per_dir_config,
- &dav_module);
-
- /*
- * Set up the methods mask, since that's one of the reasons this handler
- * gets called, and lower-level things may need the info.
- *
- * First, set the mask to the methods we handle directly. Since by
- * definition we own our managed space, we unconditionally set
- * the r->allowed field rather than ORing our values with anything
- * any other module may have put in there.
- *
- * These are the HTTP-defined methods that we handle directly.
- */
- r->allowed = 0
- | (1 << M_GET)
- | (1 << M_PUT)
- | (1 << M_DELETE)
- | (1 << M_OPTIONS)
- | (1 << M_INVALID);
- /*
- * These are the DAV methods we handle.
- */
- r->allowed |= 0
- | (1 << M_COPY)
- | (1 << M_LOCK)
- | (1 << M_UNLOCK)
- | (1 << M_MKCOL)
- | (1 << M_MOVE)
- | (1 << M_PROPFIND)
- | (1 << M_PROPPATCH);
- /*
- * These are methods that we don't handle directly, but let the
- * server's default handler do for us as our agent.
- */
- r->allowed |= 0
- | (1 << M_POST);
-
- /* ### hrm. if we return HTTP_METHOD_NOT_ALLOWED, then an Allow header
- * ### is sent; it will need the other allowed states; since the default
- * ### handler is not called on error, then it doesn't add the other
- * ### allowed states, so we must */
- /* ### we might need to refine this for just where we return the error.
- * ### also, there is the issue with other methods (see ISSUES) */
- /* ### more work necessary, now that we have M_foo for DAV methods */
-
- /* dispatch the appropriate method handler */
- if (r->method_number == M_GET) {
- return dav_method_get(r);
- }
-
- if (r->method_number == M_PUT) {
- return dav_method_put(r);
- }
-
- if (r->method_number == M_POST) {
- return dav_method_post(r);
- }
-
- if (r->method_number == M_DELETE) {
- return dav_method_delete(r);
- }
-
- if (r->method_number == M_OPTIONS) {
- return dav_method_options(r);
- }
-
- if (r->method_number == M_PROPFIND) {
- return dav_method_propfind(r);
- }
-
- if (r->method_number == M_PROPPATCH) {
- return dav_method_proppatch(r);
- }
-
- if (r->method_number == M_MKCOL) {
- return dav_method_mkcol(r);
- }
-
- if (r->method_number == M_COPY) {
- return dav_method_copymove(r, DAV_DO_COPY);
- }
-
- if (r->method_number == M_MOVE) {
- return dav_method_copymove(r, DAV_DO_MOVE);
- }
-
- if (r->method_number == M_LOCK) {
- return dav_method_lock(r);
- }
-
- if (r->method_number == M_UNLOCK) {
- return dav_method_unlock(r);
- }
-
- /*
- * NOTE: When Apache moves creates defines for the add'l DAV methods,
- * then it will no longer use M_INVALID. This code must be
- * updated each time Apache adds method defines.
- */
- if (r->method_number != M_INVALID) {
- return DECLINED;
- }
-
- if (!strcmp(r->method, "VERSION-CONTROL")) {
- return dav_method_vsn_control(r);
- }
-
- if (!strcmp(r->method, "CHECKOUT")) {
- return dav_method_checkout(r);
- }
-
- if (!strcmp(r->method, "UNCHECKOUT")) {
- return dav_method_uncheckout(r);
- }
-
- if (!strcmp(r->method, "CHECKIN")) {
- return dav_method_checkin(r);
- }
-
- if (!strcmp(r->method, "UPDATE")) {
- return dav_method_update(r);
- }
-
- if (!strcmp(r->method, "LABEL")) {
- return dav_method_label(r);
- }
-
- if (!strcmp(r->method, "REPORT")) {
- return dav_method_report(r);
- }
-
- if (!strcmp(r->method, "MKWORKSPACE")) {
- return dav_method_make_workspace(r);
- }
-
- if (!strcmp(r->method, "MKACTIVITY")) {
- return dav_method_make_activity(r);
- }
-
- if (!strcmp(r->method, "BASELINE-CONTROL")) {
- return dav_method_baseline_control(r);
- }
-
- if (!strcmp(r->method, "MERGE")) {
- return dav_method_merge(r);
- }
-
- if (!strcmp(r->method, "BIND")) {
- return dav_method_bind(r);
- }
-
- /* ### add'l methods for Advanced Collections, ACLs, DASL */
-
- return DECLINED;
-}
-
-static int dav_type_checker(request_rec *r)
-{
- dav_dir_conf *conf;
-
- conf = (dav_dir_conf *) ap_get_module_config(r->per_dir_config,
- &dav_module);
-
- /* if DAV is not enabled, then we've got nothing to do */
- if (conf->provider == NULL) {
- return DECLINED;
- }
-
- if (r->method_number == M_GET) {
- /*
- ** ### need some work to pull Content-Type and Content-Language
- ** ### from the property database.
- */
-
- /*
- ** If the repository hasn't indicated that it will handle the
- ** GET method, then just punt.
- **
- ** ### this isn't quite right... taking over the response can break
- ** ### things like mod_negotiation. need to look into this some more.
- */
- if (!conf->provider->repos->handle_get) {
- return DECLINED;
- }
- }
-
- /* ### we should (instead) trap the ones that we DO understand */
- /* ### the handler DOES handle POST, so we need to fix one of these */
- if (r->method_number != M_POST) {
-
- /*
- ** ### anything else to do here? could another module and/or
- ** ### config option "take over" the handler here? i.e. how do
- ** ### we lock down this hierarchy so that we are the ultimate
- ** ### arbiter? (or do we simply depend on the administrator
- ** ### to avoid conflicting configurations?)
- **
- ** ### I think the OK stops running type-checkers. need to look.
- */
- r->handler = "dav-handler";
- return OK;
- }
-
- return DECLINED;
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_handler(dav_handler, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_post_config(dav_init_handler, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_type_checker(dav_type_checker, NULL, NULL, APR_HOOK_FIRST);
-
- dav_hook_find_liveprop(dav_core_find_liveprop, NULL, NULL, APR_HOOK_LAST);
- dav_hook_insert_all_liveprops(dav_core_insert_all_liveprops,
- NULL, NULL, APR_HOOK_MIDDLE);
-
- dav_core_register_uris(p);
-}
-
-/*---------------------------------------------------------------------------
-**
-** Configuration info for the module
-*/
-
-static const command_rec dav_cmds[] =
-{
- /* per directory/location */
- AP_INIT_TAKE1("DAV", dav_cmd_dav, NULL, ACCESS_CONF,
- "specify the DAV provider for a directory or location"),
-
- /* per directory/location, or per server */
- AP_INIT_TAKE1("DAVMinTimeout", dav_cmd_davmintimeout, NULL,
- ACCESS_CONF|RSRC_CONF,
- "specify minimum allowed timeout"),
-
- /* per directory/location, or per server */
- AP_INIT_FLAG("DAVDepthInfinity", dav_cmd_davdepthinfinity, NULL,
- ACCESS_CONF|RSRC_CONF,
- "allow Depth infinity PROPFIND requests"),
-
- /* per directory/location, or per server */
- AP_INIT_TAKE2("DAVParam", dav_cmd_davparam, NULL,
- ACCESS_CONF|RSRC_CONF,
- "DAVParam <parameter name> <parameter value>"),
-
- { NULL }
-};
-
-module DAV_DECLARE_DATA dav_module =
-{
- STANDARD20_MODULE_STUFF,
- dav_create_dir_config, /* dir config creater */
- dav_merge_dir_config, /* dir merger --- default is to override */
- dav_create_server_config, /* server config */
- dav_merge_server_config, /* merge server config */
- dav_cmds, /* command table */
- register_hooks, /* register hooks */
-};
-
-APR_HOOK_STRUCT(
- APR_HOOK_LINK(gather_propsets)
- APR_HOOK_LINK(find_liveprop)
- APR_HOOK_LINK(insert_all_liveprops)
- )
-APR_IMPLEMENT_EXTERNAL_HOOK_VOID(dav, DAV, gather_propsets,
- (apr_array_header_t *uris),
- (uris))
-APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(dav, DAV, int, find_liveprop,
- (const dav_resource *resource,
- const char *ns_uri, const char *name,
- const dav_hooks_liveprop **hooks),
- (resource, ns_uri, name, hooks), 0);
-APR_IMPLEMENT_EXTERNAL_HOOK_VOID(dav, DAV, insert_all_liveprops,
- (request_rec *r, const dav_resource *resource,
- dav_prop_insert what, ap_text_header *phdr),
- (r, resource, what, phdr));
diff --git a/modules/dav/main/mod_dav.dsp b/modules/dav/main/mod_dav.dsp
deleted file mode 100644
index ba781d9d56..0000000000
--- a/modules/dav/main/mod_dav.dsp
+++ /dev/null
@@ -1,131 +0,0 @@
-# Microsoft Developer Studio Project File - Name="mod_dav" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=mod_dav - Win32 Release
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "mod_dav.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_dav.mak" CFG="mod_dav - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_dav - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_dav - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "mod_dav - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /I "..\..\..\srclib\aputil" /I "..\..\..\srclib\sdbm" /I "..\..\..\srclib\expat-lite" /I "..\..\..\srclib\apr\include" /I "../../../srclib/apr-util/include" /I "..\..\..\include" /I "..\..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "DAV_DECLARE_EXPORT" /Fd"Release\mod_dav" /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "NDEBUG"
-# ADD RSC /l 0x809 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_dav.so" /machine:I386 /base:@..\..\..\os\win32\BaseAddr.ref,mod_dav
-# ADD LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_dav.so" /machine:I386 /base:@..\..\..\os\win32\BaseAddr.ref,mod_dav
-
-!ELSEIF "$(CFG)" == "mod_dav - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\..\..\srclib\aputil" /I "..\..\..\srclib\sdbm" /I "..\..\..\srclib\expat-lite" /I "..\..\..\srclib\apr\include" /I "../../../srclib/apr-util/include" /I "..\..\..\include" /I "..\..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "DAV_DECLARE_EXPORT" /Fd"Debug\mod_dav" /FD /c
-# ADD BASE MTL /nologo /D "_DEBUG" /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "_DEBUG"
-# ADD RSC /l 0x809 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /out:"Debug/mod_dav.so" /machine:I386 /base:@..\..\..\os\win32\BaseAddr.ref,mod_dav
-# ADD LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /map /debug /out:"Debug/mod_dav.so" /machine:I386 /base:@..\..\..\os\win32\BaseAddr.ref,mod_dav
-
-!ENDIF
-
-# Begin Target
-
-# Name "mod_dav - Win32 Release"
-# Name "mod_dav - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
-# Begin Source File
-
-SOURCE=.\liveprop.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\mod_dav.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\props.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\providers.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\std_liveprop.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\util.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\util_lock.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
-# Begin Source File
-
-SOURCE=.\mod_dav.h
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/modules/dav/main/mod_dav.h b/modules/dav/main/mod_dav.h
deleted file mode 100644
index 162f7bff66..0000000000
--- a/modules/dav/main/mod_dav.h
+++ /dev/null
@@ -1,2231 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-/*
-** DAV extension module for Apache 2.0.*
-*/
-
-#ifndef _MOD_DAV_H_
-#define _MOD_DAV_H_
-
-#include "apr_hooks.h"
-#include "apr_hash.h"
-#include "apr_dbm.h"
-#include "apr_tables.h"
-
-#include "httpd.h"
-#include "util_filter.h"
-#include "util_xml.h"
-
-#include <limits.h> /* for INT_MAX */
-#include <time.h> /* for time_t */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#define DAV_VERSION AP_SERVER_BASEREVISION
-
-#define DAV_XML_HEADER "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
-#define DAV_XML_CONTENT_TYPE "text/xml; charset=\"utf-8\""
-
-#define DAV_READ_BLOCKSIZE 2048 /* used for reading input blocks */
-
-#define DAV_RESPONSE_BODY_1 "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<HTML><HEAD>\n<TITLE>"
-#define DAV_RESPONSE_BODY_2 "</TITLE>\n</HEAD><BODY>\n<H1>"
-#define DAV_RESPONSE_BODY_3 "</H1>\n"
-#define DAV_RESPONSE_BODY_4 "</BODY></HTML>\n"
-
-#define DAV_DO_COPY 0
-#define DAV_DO_MOVE 1
-
-
-#if 1
-#define DAV_DEBUG 1
-#define DEBUG_CR "\n"
-#define DBG0(f) ap_log_error(APLOG_MARK, \
- APLOG_ERR|APLOG_NOERRNO, 0, NULL, (f))
-#define DBG1(f,a1) ap_log_error(APLOG_MARK, \
- APLOG_ERR|APLOG_NOERRNO, 0, NULL, f, a1)
-#define DBG2(f,a1,a2) ap_log_error(APLOG_MARK, \
- APLOG_ERR|APLOG_NOERRNO, 0, NULL, f, a1, a2)
-#define DBG3(f,a1,a2,a3) ap_log_error(APLOG_MARK, \
- APLOG_ERR|APLOG_NOERRNO, 0, NULL, f, a1, a2, a3)
-#else
-#undef DAV_DEBUG
-#define DEBUG_CR ""
-#endif
-
-#define DAV_INFINITY INT_MAX /* for the Depth: header */
-
-/* Create a set of DAV_DECLARE(type), DAV_DECLARE_NONSTD(type) and
- * DAV_DECLARE_DATA with appropriate export and import tags for the platform
- */
-#if !defined(WIN32)
-#define DAV_DECLARE(type) type
-#define DAV_DECLARE_NONSTD(type) type
-#define DAV_DECLARE_DATA
-#elif defined(DAV_DECLARE_STATIC)
-#define DAV_DECLARE(type) type __stdcall
-#define DAV_DECLARE_NONSTD(type) type
-#define DAV_DECLARE_DATA
-#elif defined(DAV_DECLARE_EXPORT)
-#define DAV_DECLARE(type) __declspec(dllexport) type __stdcall
-#define DAV_DECLARE_NONSTD(type) __declspec(dllexport) type
-#define DAV_DECLARE_DATA __declspec(dllexport)
-#else
-#define DAV_DECLARE(type) __declspec(dllimport) type __stdcall
-#define DAV_DECLARE_NONSTD(type) __declspec(dllimport) type
-#define DAV_DECLARE_DATA __declspec(dllimport)
-#endif
-
-/* --------------------------------------------------------------------
-**
-** ERROR MANAGEMENT
-*/
-
-/*
-** dav_error structure.
-**
-** In most cases, mod_dav uses a pointer to a dav_error structure. If the
-** pointer is NULL, then no error has occurred.
-**
-** In certain cases, a dav_error structure is directly used. In these cases,
-** a status value of 0 means that an error has not occurred.
-**
-** Note: this implies that status != 0 whenever an error occurs.
-**
-** The desc field is optional (it may be NULL). When NULL, it typically
-** implies that Apache has a proper description for the specified status.
-*/
-typedef struct dav_error {
- int status; /* suggested HTTP status (0 for no error) */
- int error_id; /* DAV-specific error ID */
- const char *desc; /* DAV:responsedescription and error log */
-
- int save_errno; /* copy of errno causing the error */
-
- struct dav_error *prev; /* previous error (in stack) */
-
- /* deferred computation of the description */
- void (*compute_desc)(struct dav_error *err, apr_pool_t *p);
- int ctx_i;
- const char *ctx_s;
- void *ctx_p;
-
-} dav_error;
-
-/*
-** Create a new error structure. save_errno will be filled with the current
-** errno value.
-*/
-DAV_DECLARE(dav_error*) dav_new_error(apr_pool_t *p, int status,
- int error_id, const char *desc);
-
-/*
-** Push a new error description onto the stack of errors.
-**
-** This function is used to provide an additional description to an existing
-** error.
-**
-** <status> should contain the caller's view of what the current status is,
-** given the underlying error. If it doesn't have a better idea, then the
-** caller should pass prev->status.
-**
-** <error_id> can specify a new error_id since the topmost description has
-** changed.
-*/
-DAV_DECLARE(dav_error*) dav_push_error(apr_pool_t *p, int status, int error_id,
- const char *desc, dav_error *prev);
-
-
-/* error ID values... */
-
-/* IF: header errors */
-#define DAV_ERR_IF_PARSE 100 /* general parsing error */
-#define DAV_ERR_IF_MULTIPLE_NOT 101 /* multiple "Not" found */
-#define DAV_ERR_IF_UNK_CHAR 102 /* unknown char in header */
-#define DAV_ERR_IF_ABSENT 103 /* no locktokens given */
-#define DAV_ERR_IF_TAGGED 104 /* in parsing tagged-list */
-#define DAV_ERR_IF_UNCLOSED_PAREN 105 /* in no-tagged-list */
-
-/* Prop DB errors */
-#define DAV_ERR_PROP_BAD_MAJOR 200 /* major version was wrong */
-#define DAV_ERR_PROP_READONLY 201 /* prop is read-only */
-#define DAV_ERR_PROP_NO_DATABASE 202 /* writable db not avail */
-#define DAV_ERR_PROP_NOT_FOUND 203 /* prop not found */
-#define DAV_ERR_PROP_BAD_LOCKDB 204 /* could not open lockdb */
-#define DAV_ERR_PROP_OPENING 205 /* problem opening propdb */
-#define DAV_ERR_PROP_EXEC 206 /* problem exec'ing patch */
-
-/* Predefined DB errors */
-/* ### any to define?? */
-
-/* Predefined locking system errors */
-#define DAV_ERR_LOCK_OPENDB 400 /* could not open lockdb */
-#define DAV_ERR_LOCK_NO_DB 401 /* no database defined */
-#define DAV_ERR_LOCK_CORRUPT_DB 402 /* DB is corrupt */
-#define DAV_ERR_LOCK_UNK_STATE_TOKEN 403 /* unknown State-token */
-#define DAV_ERR_LOCK_PARSE_TOKEN 404 /* bad opaquelocktoken */
-#define DAV_ERR_LOCK_SAVE_LOCK 405 /* err saving locks */
-
-/*
-** Some comments on Error ID values:
-**
-** The numbers do not necessarily need to be unique. Uniqueness simply means
-** that two errors that have not been predefined above can be distinguished
-** from each other. At the moment, mod_dav does not use this distinguishing
-** feature, but it could be used in the future to collapse <response> elements
-** into groups based on the error ID (and associated responsedescription).
-**
-** If a compute_desc is provided, then the error ID should be unique within
-** the context of the compute_desc function (so the function can figure out
-** what to filled into the desc).
-**
-** Basically, subsystems can ignore defining new error ID values if they want
-** to. The subsystems *do* need to return the predefined errors when
-** appropriate, so that mod_dav can figure out what to do. Subsystems can
-** simply leave the error ID field unfilled (zero) if there isn't an error
-** that must be placed there.
-*/
-
-
-/* --------------------------------------------------------------------
-**
-** HOOK STRUCTURES
-**
-** These are here for forward-declaration purposes. For more info, see
-** the section title "HOOK HANDLING" for more information, plus each
-** structure definition.
-*/
-
-/* forward-declare this structure */
-typedef struct dav_hooks_propdb dav_hooks_propdb;
-typedef struct dav_hooks_locks dav_hooks_locks;
-typedef struct dav_hooks_vsn dav_hooks_vsn;
-typedef struct dav_hooks_repository dav_hooks_repository;
-typedef struct dav_hooks_liveprop dav_hooks_liveprop;
-typedef struct dav_hooks_binding dav_hooks_binding;
-
-/* ### deprecated name */
-typedef dav_hooks_propdb dav_hooks_db;
-
-
-/* --------------------------------------------------------------------
-**
-** RESOURCE HANDLING
-*/
-
-/*
-** Resource Types:
-** The base protocol defines only file and collection resources.
-** The versioning protocol defines several additional resource types
-** to represent artifacts of a version control system.
-**
-** This enumeration identifies the type of URL used to identify the
-** resource. Since the same resource may have more than one type of
-** URL which can identify it, dav_resource_type cannot be used
-** alone to determine the type of the resource; attributes of the
-** dav_resource object must also be consulted.
-*/
-typedef enum {
- DAV_RESOURCE_TYPE_UNKNOWN,
-
- DAV_RESOURCE_TYPE_REGULAR, /* file or collection; could be
- * unversioned, or version selector,
- * or baseline selector */
-
- DAV_RESOURCE_TYPE_VERSION, /* version or baseline URL */
-
- DAV_RESOURCE_TYPE_HISTORY, /* version or baseline history URL */
-
- DAV_RESOURCE_TYPE_WORKING, /* working resource URL */
-
- DAV_RESOURCE_TYPE_WORKSPACE, /* workspace URL */
-
- DAV_RESOURCE_TYPE_ACTIVITY, /* activity URL */
-
- DAV_RESOURCE_TYPE_PRIVATE /* repository-private type */
-
-} dav_resource_type;
-
-/*
-** Opaque, repository-specific information for a resource.
-*/
-typedef struct dav_resource_private dav_resource_private;
-
-/*
-** Resource descriptor, generated by a repository provider.
-**
-** Note: the lock-null state is not explicitly represented here,
-** since it may be expensive to compute. Use dav_get_resource_state()
-** to determine whether a non-existent resource is a lock-null resource.
-**
-** A quick explanation of how the flags can apply to different resources:
-**
-** unversioned file or collection:
-** type = DAV_RESOURCE_TYPE_REGULAR
-** exists = ? (1 if exists)
-** collection = ? (1 if collection)
-** versioned = 0
-** baselined = 0
-** working = 0
-**
-** version-controlled resource or configuration:
-** type = DAV_RESOURCE_TYPE_REGULAR
-** exists = 1
-** collection = ? (1 if collection)
-** versioned = 1
-** baselined = ? (1 if configuration)
-** working = ? (1 if checked out)
-**
-** version/baseline history:
-** type = DAV_RESOURCE_TYPE_HISTORY
-** exists = 1
-** collection = 0
-** versioned = 0
-** baselined = 0
-** working = 0
-**
-** version/baseline:
-** type = DAV_RESOURCE_TYPE_VERSION
-** exists = 1
-** collection = ? (1 if collection)
-** versioned = 1
-** baselined = ? (1 if baseline)
-** working = 0
-**
-** working resource:
-** type = DAV_RESOURCE_TYPE_WORKING
-** exists = 1
-** collection = ? (1 if collection)
-** versioned = 1
-** baselined = 0
-** working = 1
-**
-** workspace:
-** type = DAV_RESOURCE_TYPE_WORKSPACE
-** exists = ? (1 if exists)
-** collection = 1
-** versioned = ? (1 if version-controlled)
-** baselined = ? (1 if baseline-controlled)
-** working = ? (1 if checked out)
-**
-** activity:
-** type = DAV_RESOURCE_TYPE_ACTIVITY
-** exists = ? (1 if exists)
-** collection = 0
-** versioned = 0
-** baselined = 0
-** working = 0
-*/
-typedef struct dav_resource {
- dav_resource_type type;
-
- int exists; /* 0 => null resource */
-
- int collection; /* 0 => file; can be 1 for
- * REGULAR, VERSION, and WORKING resources,
- * and is always 1 for WORKSPACE */
-
- int versioned; /* 0 => unversioned; can be 1 for
- * REGULAR and WORKSPACE resources,
- * and is always 1 for VERSION and WORKING */
-
- int baselined; /* 0 => not baselined; can be 1 for
- * REGULAR, VERSION, and WORKSPACE resources;
- * versioned == 1 when baselined == 1 */
-
- int working; /* 0 => not checked out; can be 1 for
- * REGULAR and WORKSPACE resources,
- * and is always 1 for WORKING */
-
- const char *uri; /* the URI for this resource */
-
- dav_resource_private *info; /* the provider's private info */
-
- const dav_hooks_repository *hooks; /* hooks used for this resource */
-
- /* When allocating items related specifically to this resource, the
- following pool should be used. Its lifetime will be at least as
- long as the dav_resource structure. */
- apr_pool_t *pool;
-
-} dav_resource;
-
-/*
-** Lock token type. Lock providers define the details of a lock token.
-** However, all providers are expected to at least be able to parse
-** the "opaquelocktoken" scheme, which is represented by a uuid_t.
-*/
-typedef struct dav_locktoken dav_locktoken;
-
-
-/* --------------------------------------------------------------------
-**
-** BUFFER HANDLING
-**
-** These buffers are used as a lightweight buffer reuse mechanism. Apache
-** provides sub-pool creation and destruction to much the same effect, but
-** the sub-pools are a bit more general and heavyweight than these buffers.
-*/
-
-/* buffer for reuse; can grow to accomodate needed size */
-typedef struct
-{
- apr_size_t alloc_len; /* how much has been allocated */
- apr_size_t cur_len; /* how much is currently being used */
- char *buf; /* buffer contents */
-} dav_buffer;
-#define DAV_BUFFER_MINSIZE 256 /* minimum size for buffer */
-#define DAV_BUFFER_PAD 64 /* amount of pad when growing */
-
-/* set the cur_len to the given size and ensure space is available */
-DAV_DECLARE(void) dav_set_bufsize(apr_pool_t *p, dav_buffer *pbuf,
- apr_size_t size);
-
-/* initialize a buffer and copy the specified (null-term'd) string into it */
-DAV_DECLARE(void) dav_buffer_init(apr_pool_t *p, dav_buffer *pbuf,
- const char *str);
-
-/* check that the buffer can accomodate <extra_needed> more bytes */
-DAV_DECLARE(void) dav_check_bufsize(apr_pool_t *p, dav_buffer *pbuf,
- apr_size_t extra_needed);
-
-/* append a string to the end of the buffer, adjust length */
-DAV_DECLARE(void) dav_buffer_append(apr_pool_t *p, dav_buffer *pbuf,
- const char *str);
-
-/* place a string on the end of the buffer, do NOT adjust length */
-DAV_DECLARE(void) dav_buffer_place(apr_pool_t *p, dav_buffer *pbuf,
- const char *str);
-
-/* place some memory on the end of a buffer; do NOT adjust length */
-DAV_DECLARE(void) dav_buffer_place_mem(apr_pool_t *p, dav_buffer *pbuf,
- const void *mem, apr_size_t amt,
- apr_size_t pad);
-
-
-/* --------------------------------------------------------------------
-**
-** HANDY UTILITIES
-*/
-
-/* contains results from one of the getprop functions */
-typedef struct
-{
- ap_text * propstats; /* <propstat> element text */
- ap_text * xmlns; /* namespace decls for <response> elem */
-} dav_get_props_result;
-
-/* holds the contents of a <response> element */
-typedef struct dav_response
-{
- const char *href; /* always */
- const char *desc; /* optional description at <response> level */
-
- /* use status if propresult.propstats is NULL. */
- dav_get_props_result propresult;
-
- int status;
-
- struct dav_response *next;
-} dav_response;
-
-typedef struct
-{
- request_rec *rnew; /* new subrequest */
- dav_error err; /* potential error response */
-} dav_lookup_result;
-
-
-dav_lookup_result dav_lookup_uri(const char *uri, request_rec *r,
- int must_be_absolute);
-
-/* defines type of property info a provider is to return */
-typedef enum {
- DAV_PROP_INSERT_NOTDEF, /* property is defined by this provider,
- but nothing was inserted because the
- (live) property is not defined for this
- resource (it may be present as a dead
- property). */
- DAV_PROP_INSERT_NOTSUPP, /* property is recognized by this provider,
- but it is not supported, and cannot be
- treated as a dead property */
- DAV_PROP_INSERT_NAME, /* a property name (empty elem) was
- inserted into the text block */
- DAV_PROP_INSERT_VALUE, /* a property name/value pair was inserted
- into the text block */
- DAV_PROP_INSERT_SUPPORTED /* a supported live property was added to
- the text block as a
- <DAV:supported-live-property> element */
-} dav_prop_insert;
-
-/* ### this stuff is private to dav/fs/repos.c; move it... */
-/* format a time string (buf must be at least DAV_TIMEBUF_SIZE chars) */
-#define DAV_STYLE_ISO8601 1
-#define DAV_STYLE_RFC822 2
-#define DAV_TIMEBUF_SIZE 30
-
-int dav_get_depth(request_rec *r, int def_depth);
-
-int dav_validate_root(const ap_xml_doc *doc, const char *tagname);
-ap_xml_elem *dav_find_child(const ap_xml_elem *elem, const char *tagname);
-
-/* gather up all the CDATA into a single string */
-const char *dav_xml_get_cdata(const ap_xml_elem *elem, apr_pool_t *pool,
- int strip_white);
-
-
-/* --------------------------------------------------------------------
-**
-** DAV PLUGINS
-*/
-
-/* ### docco ... */
-
-/*
-** dav_provider
-**
-** This structure wraps up all of the hooks that a mod_dav provider can
-** supply. The provider MUST supply <repos> and <propdb>. The rest are
-** optional and should contain NULL if that feature is not supplied.
-**
-** Note that a provider cannot pick and choose portions. There are too many
-** dependencies between a dav_resource (defined by <repos>) and the other
-** functionality.
-**
-** Live properties are not part of the dav_provider structure because they
-** are handled through the APR_HOOK interface (to allow for multiple liveprop
-** providers). The core always provides some properties, and then a given
-** provider will add more properties.
-*/
-typedef struct {
- const dav_hooks_repository *repos;
- const dav_hooks_propdb *propdb;
- const dav_hooks_locks *locks;
- const dav_hooks_vsn *vsn;
- const dav_hooks_binding *binding;
-
-} dav_provider;
-
-/*
-** gather_propsets: gather all live property propset-URIs
-**
-** The hook implementor should push one or more URIs into the specified
-** array. These URIs are returned in the DAV: header to let clients know
-** what sets of live properties are supported by the installation. mod_dav
-** will place open/close angle brackets around each value (much like
-** a Coded-URL); quotes and brackets should not be in the value.
-**
-** Example: http://apache.org/dav/props/
-**
-** (of course, use your own domain to ensure a unique value)
-*/
-APR_DECLARE_EXTERNAL_HOOK(dav, DAV, void, gather_propsets,
- (apr_array_header_t *uris))
-
-/*
-** find_liveprop: find a live property, returning a non-zero, unique,
-** opaque identifier.
-**
-** If the hook implementor determines the specified URI/name refers to
-** one of its properties, then it should fill in HOOKS and return a
-** non-zero value. The returned value is the "property ID" and will
-** be passed to the various liveprop hook functions.
-**
-** Return 0 if the property is not defined by the hook implementor.
-*/
-APR_DECLARE_EXTERNAL_HOOK(dav, DAV, int, find_liveprop,
- (const dav_resource *resource,
- const char *ns_uri, const char *name,
- const dav_hooks_liveprop **hooks))
-
-/*
-** insert_all_liveprops: insert all (known) live property names/values.
-**
-** The hook implementor should append XML text to PHDR, containing liveprop
-** names. If INSVALUE is true, then the property values should also be
-** inserted into the output XML stream.
-**
-** The liveprop provider should insert *all* known and *defined* live
-** properties on the specified resource. If a particular liveprop is
-** not defined for this resource, then it should not be inserted.
-*/
-APR_DECLARE_EXTERNAL_HOOK(dav, DAV, void, insert_all_liveprops,
- (request_rec *r, const dav_resource *resource,
- dav_prop_insert what, ap_text_header *phdr))
-
-const dav_hooks_locks *dav_get_lock_hooks(request_rec *r);
-const dav_hooks_propdb *dav_get_propdb_hooks(request_rec *r);
-const dav_hooks_vsn *dav_get_vsn_hooks(request_rec *r);
-const dav_hooks_binding *dav_get_binding_hooks(request_rec *r);
-
-DAV_DECLARE(void) dav_register_provider(apr_pool_t *p, const char *name,
- const dav_provider *hooks);
-const dav_provider * dav_lookup_provider(const char *name);
-
-
-/* ### deprecated */
-#define DAV_GET_HOOKS_PROPDB(r) dav_get_propdb_hooks(r)
-#define DAV_GET_HOOKS_LOCKS(r) dav_get_lock_hooks(r)
-#define DAV_GET_HOOKS_VSN(r) dav_get_vsn_hooks(r)
-#define DAV_GET_HOOKS_BINDING(r) dav_get_binding_hooks(r)
-
-
-/* --------------------------------------------------------------------
-**
-** IF HEADER PROCESSING
-**
-** Here is the definition of the If: header from RFC 2518, S9.4:
-**
-** If = "If" ":" (1*No-tag-list | 1*Tagged-list)
-** No-tag-list = List
-** Tagged-list = Resource 1*List
-** Resource = Coded-URL
-** List = "(" 1*(["Not"](State-token | "[" entity-tag "]")) ")"
-** State-token = Coded-URL
-** Coded-URL = "<" absoluteURI ">" ; absoluteURI from RFC 2616
-**
-** List corresponds to dav_if_state_list. No-tag-list corresponds to
-** dav_if_header with uri==NULL. Tagged-list corresponds to a sequence of
-** dav_if_header structures with (duplicate) uri==Resource -- one
-** dav_if_header per state_list. A second Tagged-list will start a new
-** sequence of dav_if_header structures with the new URI.
-**
-** A summary of the semantics, mapped into our structures:
-** - Chained dav_if_headers: OR
-** - Chained dav_if_state_lists: AND
-** - NULL uri matches all resources
-*/
-
-typedef enum
-{
- dav_if_etag,
- dav_if_opaquelock
-} dav_if_state_type;
-
-typedef struct dav_if_state_list
-{
- dav_if_state_type type;
-
- int condition;
-#define DAV_IF_COND_NORMAL 0
-#define DAV_IF_COND_NOT 1 /* "Not" was applied */
-
- const char *etag; /* etag */
- dav_locktoken *locktoken; /* locktoken */
-
- struct dav_if_state_list *next;
-} dav_if_state_list;
-
-typedef struct dav_if_header
-{
- const char *uri;
- apr_size_t uri_len;
- struct dav_if_state_list *state;
- struct dav_if_header *next;
-
- int dummy_header; /* used internally by the lock/etag validation */
-} dav_if_header;
-
-typedef struct dav_locktoken_list
-{
- dav_locktoken *locktoken;
- struct dav_locktoken_list *next;
-} dav_locktoken_list;
-
-dav_error * dav_get_locktoken_list(request_rec *r, dav_locktoken_list **ltl);
-
-
-/* --------------------------------------------------------------------
-**
-** LIVE PROPERTY HANDLING
-*/
-
-/* opaque type for PROPPATCH rollback information */
-typedef struct dav_liveprop_rollback dav_liveprop_rollback;
-
-struct dav_hooks_liveprop
-{
- /*
- ** Insert property information into a text block. The property to
- ** insert is identified by the propid value. The information to insert
- ** is identified by the "what" argument, as follows:
- ** DAV_PROP_INSERT_NAME
- ** property name, as an empty XML element
- ** DAV_PROP_INSERT_VALUE
- ** property name/value, as an XML element
- ** DAV_PROP_INSERT_SUPPORTED
- ** if the property is defined on the resource, then
- ** a DAV:supported-live-property element, as defined
- ** by the DeltaV extensions to RFC2518.
- **
- ** Providers should return DAV_PROP_INSERT_NOTDEF if the property is
- ** known and not defined for this resource, so should be handled as a
- ** dead property. If a provider recognizes, but does not support, a
- ** property, and does not want it handled as a dead property, it should
- ** return DAV_PROP_INSERT_NOTSUPP.
- **
- ** Returns one of DAV_PROP_INSERT_* based on what happened.
- **
- ** ### we may need more context... ie. the lock database
- */
- dav_prop_insert (*insert_prop)(const dav_resource *resource,
- int propid, dav_prop_insert what,
- ap_text_header *phdr);
-
- /*
- ** Determine whether a given property is writable.
- **
- ** ### we may want a different semantic. i.e. maybe it should be
- ** ### "can we write <value> into this property?"
- **
- ** Returns 1 if the live property can be written, 0 if read-only.
- */
- int (*is_writable)(const dav_resource *resource, int propid);
-
- /*
- ** This member defines the set of namespace URIs that the provider
- ** uses for its properties. When insert_all is called, it will be
- ** passed a list of integers that map from indices into this list
- ** to namespace IDs for output generation.
- **
- ** The last entry in this list should be a NULL value (sentinel).
- */
- const char * const * namespace_uris;
-
- /*
- ** ### this is not the final design. we want an open-ended way for
- ** ### liveprop providers to attach *new* properties. To this end,
- ** ### we'll have a "give me a list of the props you define", a way
- ** ### to check for a prop's existence, a way to validate a set/remove
- ** ### of a prop, and a way to execute/commit/rollback that change.
- */
-
- /*
- ** Validate that the live property can be assigned a value, and that
- ** the provided value is valid.
- **
- ** elem will point to the XML element that names the property. For
- ** example:
- ** <lp1:executable>T</lp1:executable>
- **
- ** The provider can access the cdata fields and the child elements
- ** to extract the relevant pieces.
- **
- ** operation is one of DAV_PROP_OP_SET or _DELETE.
- **
- ** The provider may return a value in *context which will be passed
- ** to each of the exec/commit/rollback functions. For example, this
- ** may contain an internal value which has been processed from the
- ** input element.
- **
- ** The provider must set defer_to_dead to true (non-zero) or false.
- ** If true, then the set/remove is deferred to the dead property
- ** database. Note: it will be set to zero on entry.
- */
- dav_error * (*patch_validate)(const dav_resource *resource,
- const ap_xml_elem *elem,
- int operation,
- void **context,
- int *defer_to_dead);
-
- /* ### doc... */
- dav_error * (*patch_exec)(const dav_resource *resource,
- const ap_xml_elem *elem,
- int operation,
- void *context,
- dav_liveprop_rollback **rollback_ctx);
-
- /* ### doc... */
- void (*patch_commit)(const dav_resource *resource,
- int operation,
- void *context,
- dav_liveprop_rollback *rollback_ctx);
-
- /* ### doc... */
- dav_error * (*patch_rollback)(const dav_resource *resource,
- int operation,
- void *context,
- dav_liveprop_rollback *rollback_ctx);
-};
-
-/*
-** dav_liveprop_spec: specify a live property
-**
-** This structure is used as a standard way to determine if a particular
-** property is a live property. Its use is not part of the mandated liveprop
-** interface, but can be used by liveprop providers in conjuction with the
-** utility routines below.
-**
-** spec->name == NULL is the defined end-sentinel for a list of specs.
-*/
-typedef struct {
- int ns; /* provider-local namespace index */
- const char *name; /* name of the property */
-
- int propid; /* provider-local property ID */
-
- int is_writable; /* is the property writable? */
-
-} dav_liveprop_spec;
-
-/*
-** dav_liveprop_group: specify a group of liveprops
-**
-** This structure specifies a group of live properties, their namespaces,
-** and how to handle them.
-*/
-typedef struct {
- const dav_liveprop_spec *specs;
- const char * const *namespace_uris;
- const dav_hooks_liveprop *hooks;
-
-} dav_liveprop_group;
-
-/* ### docco */
-DAV_DECLARE(int) dav_do_find_liveprop(const char *ns_uri, const char *name,
- const dav_liveprop_group *group,
- const dav_hooks_liveprop **hooks);
-
-/* ### docco */
-DAV_DECLARE(int) dav_get_liveprop_info(int propid,
- const dav_liveprop_group *group,
- const dav_liveprop_spec **info);
-
-/* ### docco */
-DAV_DECLARE(void) dav_register_liveprop_group(apr_pool_t *pool,
- const dav_liveprop_group *group);
-
-/* ### docco */
-DAV_DECLARE(int) dav_get_liveprop_ns_index(const char *uri);
-
-/* ### docco */
-int dav_get_liveprop_ns_count(void);
-
-/* ### docco */
-void dav_add_all_liveprop_xmlns(apr_pool_t *p, ap_text_header *phdr);
-
-/*
-** The following three functions are part of mod_dav's internal handling
-** for the core WebDAV properties. They are not part of mod_dav's API.
-*/
-int dav_core_find_liveprop(const dav_resource *resource,
- const char *ns_uri, const char *name,
- const dav_hooks_liveprop **hooks);
-void dav_core_insert_all_liveprops(request_rec *r,
- const dav_resource *resource,
- dav_prop_insert what, ap_text_header *phdr);
-void dav_core_register_uris(apr_pool_t *p);
-
-
-/*
-** Standard WebDAV Property Identifiers
-**
-** A live property provider does not need to use these; they are simply
-** provided for convenience.
-**
-** Property identifiers need to be unique within a given provider, but not
-** *across* providers (note: this uniqueness constraint was different in
-** older versions of mod_dav).
-**
-** The identifiers start at 20000 to make it easier for providers to avoid
-** conflicts with the standard properties. The properties are arranged
-** alphabetically, and may be reordered from time to time (as properties
-** are introduced).
-**
-** NOTE: there is no problem with reordering (e.g. binary compat) since the
-** identifiers are only used within a given provider, which would pick up
-** the entire set of changes upon a recompile.
-*/
-enum {
- DAV_PROPID_BEGIN = 20000,
-
- /* Standard WebDAV properties (RFC 2518) */
- DAV_PROPID_creationdate,
- DAV_PROPID_displayname,
- DAV_PROPID_getcontentlanguage,
- DAV_PROPID_getcontentlength,
- DAV_PROPID_getcontenttype,
- DAV_PROPID_getetag,
- DAV_PROPID_getlastmodified,
- DAV_PROPID_lockdiscovery,
- DAV_PROPID_resourcetype,
- DAV_PROPID_source,
- DAV_PROPID_supportedlock,
-
- /* DeltaV properties (from the I-D (#14)) */
- DAV_PROPID_activity_checkout_set,
- DAV_PROPID_activity_set,
- DAV_PROPID_activity_version_set,
- DAV_PROPID_auto_merge_set,
- DAV_PROPID_auto_version,
- DAV_PROPID_baseline_collection,
- DAV_PROPID_baseline_controlled_collection,
- DAV_PROPID_baseline_controlled_collection_set,
- DAV_PROPID_checked_in,
- DAV_PROPID_checked_out,
- DAV_PROPID_checkin_fork,
- DAV_PROPID_checkout_fork,
- DAV_PROPID_checkout_set,
- DAV_PROPID_comment,
- DAV_PROPID_creator_displayname,
- DAV_PROPID_current_activity_set,
- DAV_PROPID_current_workspace_set,
- DAV_PROPID_default_variant,
- DAV_PROPID_eclipsed_set,
- DAV_PROPID_label_name_set,
- DAV_PROPID_merge_set,
- DAV_PROPID_precursor_set,
- DAV_PROPID_predecessor_set,
- DAV_PROPID_root_version,
- DAV_PROPID_subactivity_set,
- DAV_PROPID_subbaseline_set,
- DAV_PROPID_successor_set,
- DAV_PROPID_supported_method_set,
- DAV_PROPID_supported_live_property_set,
- DAV_PROPID_supported_report_set,
- DAV_PROPID_unreserved,
- DAV_PROPID_variant_set,
- DAV_PROPID_version_controlled_binding_set,
- DAV_PROPID_version_controlled_configuration,
- DAV_PROPID_version_history,
- DAV_PROPID_version_name,
- DAV_PROPID_workspace,
- DAV_PROPID_workspace_checkout_set,
-
- DAV_PROPID_END
-};
-
-/*
-** Property Identifier Registration
-**
-** At the moment, mod_dav requires live property providers to ensure that
-** each property returned has a unique value. For now, this is done through
-** central registration (there are no known providers other than the default,
-** so this remains manageable).
-**
-** WARNING: the TEST ranges should never be "shipped".
-*/
-#define DAV_PROPID_CORE 10000 /* ..10099. defined by mod_dav */
-#define DAV_PROPID_FS 10100 /* ..10299.
- mod_dav filesystem provider. */
-#define DAV_PROPID_TEST1 10300 /* ..10399 */
-#define DAV_PROPID_TEST2 10400 /* ..10499 */
-#define DAV_PROPID_TEST3 10500 /* ..10599 */
-/* Next: 10600 */
-
-
-/* --------------------------------------------------------------------
-**
-** DATABASE FUNCTIONS
-*/
-
-typedef struct dav_db dav_db;
-typedef apr_datum_t dav_datum;
-
-/* hook functions to enable pluggable databases */
-struct dav_hooks_propdb
-{
- dav_error * (*open)(apr_pool_t *p, const dav_resource *resource, int ro,
- dav_db **pdb);
- void (*close)(dav_db *db);
-
- /*
- ** Fetch the value from the database. If the value does not exist,
- ** then *pvalue should be zeroed.
- **
- ** Note: it is NOT an error for the key/value pair to not exist.
- */
- dav_error * (*fetch)(dav_db *db, dav_datum key, dav_datum *pvalue);
-
- dav_error * (*store)(dav_db *db, dav_datum key, dav_datum value);
- dav_error * (*remove)(dav_db *db, dav_datum key);
-
- /* returns 1 if the record specified by "key" exists; 0 otherwise */
- int (*exists)(dav_db *db, dav_datum key);
-
- dav_error * (*firstkey)(dav_db *db, dav_datum *pkey);
- dav_error * (*nextkey)(dav_db *db, dav_datum *pkey);
-
- void (*freedatum)(dav_db *db, dav_datum data);
-};
-
-
-/* --------------------------------------------------------------------
-**
-** LOCK FUNCTIONS
-*/
-
-/* Used to represent a Timeout header of "Infinity" */
-#define DAV_TIMEOUT_INFINITE 0
-
-time_t dav_get_timeout(request_rec *r);
-
-/*
-** Opaque, provider-specific information for a lock database.
-*/
-typedef struct dav_lockdb_private dav_lockdb_private;
-
-/*
-** Opaque, provider-specific information for a lock record.
-*/
-typedef struct dav_lock_private dav_lock_private;
-
-/*
-** Lock database type. Lock providers are urged to implement a "lazy" open, so
-** doing an "open" is cheap until something is actually needed from the DB.
-*/
-typedef struct
-{
- const dav_hooks_locks *hooks; /* the hooks used for this lockdb */
- int ro; /* was it opened readonly? */
-
- dav_lockdb_private *info;
-
-} dav_lockdb;
-
-typedef enum {
- DAV_LOCKSCOPE_UNKNOWN,
- DAV_LOCKSCOPE_EXCLUSIVE,
- DAV_LOCKSCOPE_SHARED
-} dav_lock_scope;
-
-typedef enum {
- DAV_LOCKTYPE_UNKNOWN,
- DAV_LOCKTYPE_WRITE
-} dav_lock_type;
-
-typedef enum {
- DAV_LOCKREC_DIRECT, /* lock asserted on this resource */
- DAV_LOCKREC_INDIRECT, /* lock inherited from a parent */
- DAV_LOCKREC_INDIRECT_PARTIAL /* most info is not filled in */
-} dav_lock_rectype;
-
-/*
-** dav_lock: hold information about a lock on a resource.
-**
-** This structure is used for both direct and indirect locks. A direct lock
-** is a lock applied to a specific resource by the client. An indirect lock
-** is one that is inherited from a parent resource by virtue of a non-zero
-** Depth: header when the lock was applied.
-**
-** mod_dav records both types of locks in the lock database, managing their
-** addition/removal as resources are moved about the namespace.
-**
-** Note that the lockdb is free to marshal this structure in any form that
-** it likes.
-**
-** For a "partial" lock, the <rectype> and <locktoken> fields must be filled
-** in. All other (user) fields should be zeroed. The lock provider will
-** usually fill in the <info> field, and the <next> field may be used to
-** construct a list of partial locks.
-**
-** The lock provider MUST use the info field to store a value such that a
-** dav_lock structure can locate itself in the underlying lock database.
-** This requirement is needed for refreshing: when an indirect dav_lock is
-** refreshed, its reference to the direct lock does not specify the direct's
-** resource, so the only way to locate the (refreshed, direct) lock in the
-** database is to use the info field.
-**
-** Note that <is_locknull> only refers to the resource where this lock was
-** found.
-** ### hrm. that says the abstraction is wrong. is_locknull may disappear.
-*/
-typedef struct dav_lock
-{
- dav_lock_rectype rectype; /* type of lock record */
- int is_locknull; /* lock establishes a locknull resource */
-
- /* ### put the resource in here? */
-
- dav_lock_scope scope; /* scope of the lock */
- dav_lock_type type; /* type of lock */
- int depth; /* depth of the lock */
- time_t timeout; /* when the lock will timeout */
-
- const dav_locktoken *locktoken; /* the token that was issued */
-
- const char *owner; /* (XML) owner of the lock */
- const char *auth_user; /* auth'd username owning lock */
-
- dav_lock_private *info; /* private to the lockdb */
-
- struct dav_lock *next; /* for managing a list of locks */
-} dav_lock;
-
-/* Property-related public lock functions */
-const char *dav_lock_get_activelock(request_rec *r, dav_lock *locks,
- dav_buffer *pbuf);
-
-/* LockDB-related public lock functions */
-dav_error * dav_lock_parse_lockinfo(request_rec *r,
- const dav_resource *resrouce,
- dav_lockdb *lockdb,
- const ap_xml_doc *doc,
- dav_lock **lock_request);
-int dav_unlock(request_rec *r, const dav_resource *resource,
- const dav_locktoken *locktoken);
-dav_error * dav_add_lock(request_rec *r, const dav_resource *resource,
- dav_lockdb *lockdb, dav_lock *request,
- dav_response **response);
-dav_error * dav_notify_created(request_rec *r,
- dav_lockdb *lockdb,
- const dav_resource *resource,
- int resource_state,
- int depth);
-
-DAV_DECLARE(dav_error*) dav_lock_query(dav_lockdb *lockdb,
- const dav_resource *resource,
- dav_lock **locks);
-
-dav_error * dav_validate_request(request_rec *r, dav_resource *resource,
- int depth, dav_locktoken *locktoken,
- dav_response **response, int flags,
- dav_lockdb *lockdb);
-/*
-** flags:
-** 0x0F -- reserved for <dav_lock_scope> values
-**
-** other flags, detailed below
-*/
-#define DAV_VALIDATE_RESOURCE 0x0010 /* validate just the resource */
-#define DAV_VALIDATE_PARENT 0x0020 /* validate resource AND its parent */
-#define DAV_VALIDATE_ADD_LD 0x0040 /* add DAV:lockdiscovery into
- the 424 DAV:response */
-#define DAV_VALIDATE_USE_424 0x0080 /* return 424 status, not 207 */
-#define DAV_VALIDATE_IS_PARENT 0x0100 /* for internal use */
-
-/* Lock-null related public lock functions */
-int dav_get_resource_state(request_rec *r, const dav_resource *resource);
-
-/* Lock provider hooks. Locking is optional, so there may be no
- * lock provider for a given repository.
- */
-struct dav_hooks_locks
-{
- /* Return the supportedlock property for a resource */
- const char * (*get_supportedlock)(
- const dav_resource *resource
- );
-
- /* Parse a lock token URI, returning a lock token object allocated
- * in the given pool.
- */
- dav_error * (*parse_locktoken)(
- apr_pool_t *p,
- const char *char_token,
- dav_locktoken **locktoken_p
- );
-
- /* Format a lock token object into a URI string, allocated in
- * the given pool.
- *
- * Always returns non-NULL.
- */
- const char * (*format_locktoken)(
- apr_pool_t *p,
- const dav_locktoken *locktoken
- );
-
- /* Compare two lock tokens.
- *
- * Result < 0 => lt1 < lt2
- * Result == 0 => lt1 == lt2
- * Result > 0 => lt1 > lt2
- */
- int (*compare_locktoken)(
- const dav_locktoken *lt1,
- const dav_locktoken *lt2
- );
-
- /* Open the provider's lock database.
- *
- * The provider may or may not use a "real" database for locks
- * (a lock could be an attribute on a resource, for example).
- *
- * The provider may choose to use the value of the DAVLockDB directive
- * (as returned by dav_get_lockdb_path()) to decide where to place
- * any storage it may need.
- *
- * The request storage pool should be associated with the lockdb,
- * so it can be used in subsequent operations.
- *
- * If ro != 0, only readonly operations will be performed.
- * If force == 0, the open can be "lazy"; no subsequent locking operations
- * may occur.
- * If force != 0, locking operations will definitely occur.
- */
- dav_error * (*open_lockdb)(
- request_rec *r,
- int ro,
- int force,
- dav_lockdb **lockdb
- );
-
- /* Indicates completion of locking operations */
- void (*close_lockdb)(
- dav_lockdb *lockdb
- );
-
- /* Take a resource out of the lock-null state. */
- dav_error * (*remove_locknull_state)(
- dav_lockdb *lockdb,
- const dav_resource *resource
- );
-
- /*
- ** Create a (direct) lock structure for the given resource. A locktoken
- ** will be created.
- **
- ** The lock provider may store private information into lock->info.
- */
- dav_error * (*create_lock)(dav_lockdb *lockdb,
- const dav_resource *resource,
- dav_lock **lock);
-
- /*
- ** Get the locks associated with the specified resource.
- **
- ** If resolve_locks is true (non-zero), then any indirect locks are
- ** resolved to their actual, direct lock (i.e. the reference to followed
- ** to the original lock).
- **
- ** The locks, if any, are returned as a linked list in no particular
- ** order. If no locks are present, then *locks will be NULL.
- */
- dav_error * (*get_locks)(dav_lockdb *lockdb,
- const dav_resource *resource,
- int calltype,
- dav_lock **locks);
-
-#define DAV_GETLOCKS_RESOLVED 0 /* resolve indirects to directs */
-#define DAV_GETLOCKS_PARTIAL 1 /* leave indirects partially filled */
-#define DAV_GETLOCKS_COMPLETE 2 /* fill out indirect locks */
-
- /*
- ** Find a particular lock on a resource (specified by its locktoken).
- **
- ** *lock will be set to NULL if the lock is not found.
- **
- ** Note that the provider can optimize the unmarshalling -- only one
- ** lock (or none) must be constructed and returned.
- **
- ** If partial_ok is true (non-zero), then an indirect lock can be
- ** partially filled in. Otherwise, another lookup is done and the
- ** lock structure will be filled out as a DAV_LOCKREC_INDIRECT.
- */
- dav_error * (*find_lock)(dav_lockdb *lockdb,
- const dav_resource *resource,
- const dav_locktoken *locktoken,
- int partial_ok,
- dav_lock **lock);
-
- /*
- ** Quick test to see if the resource has *any* locks on it.
- **
- ** This is typically used to determine if a non-existent resource
- ** has a lock and is (therefore) a locknull resource.
- **
- ** WARNING: this function may return TRUE even when timed-out locks
- ** exist (i.e. it may not perform timeout checks).
- */
- dav_error * (*has_locks)(dav_lockdb *lockdb,
- const dav_resource *resource,
- int *locks_present);
-
- /*
- ** Append the specified lock(s) to the set of locks on this resource.
- **
- ** If "make_indirect" is true (non-zero), then the specified lock(s)
- ** should be converted to an indirect lock (if it is a direct lock)
- ** before appending. Note that the conversion to an indirect lock does
- ** not alter the passed-in lock -- the change is internal the
- ** append_locks function.
- **
- ** Multiple locks are specified using the lock->next links.
- */
- dav_error * (*append_locks)(dav_lockdb *lockdb,
- const dav_resource *resource,
- int make_indirect,
- const dav_lock *lock);
-
- /*
- ** Remove any lock that has the specified locktoken.
- **
- ** If locktoken == NULL, then ALL locks are removed.
- */
- dav_error * (*remove_lock)(dav_lockdb *lockdb,
- const dav_resource *resource,
- const dav_locktoken *locktoken);
-
- /*
- ** Refresh all locks, found on the specified resource, which has a
- ** locktoken in the provided list.
- **
- ** If the lock is indirect, then the direct lock is referenced and
- ** refreshed.
- **
- ** Each lock that is updated is returned in the <locks> argument.
- ** Note that the locks will be fully resolved.
- */
- dav_error * (*refresh_locks)(dav_lockdb *lockdb,
- const dav_resource *resource,
- const dav_locktoken_list *ltl,
- time_t new_time,
- dav_lock **locks);
-
- /*
- ** Look up the resource associated with a particular locktoken.
- **
- ** The search begins at the specified <start_resource> and the lock
- ** specified by <locktoken>.
- **
- ** If the resource/token specifies an indirect lock, then the direct
- ** lock will be looked up, and THAT resource will be returned. In other
- ** words, this function always returns the resource where a particular
- ** lock (token) was asserted.
- **
- ** NOTE: this function pointer is allowed to be NULL, indicating that
- ** the provider does not support this type of functionality. The
- ** caller should then traverse up the repository hierarchy looking
- ** for the resource defining a lock with this locktoken.
- */
- dav_error * (*lookup_resource)(dav_lockdb *lockdb,
- const dav_locktoken *locktoken,
- const dav_resource *start_resource,
- const dav_resource **resource);
-};
-
-/* what types of resources can be discovered by dav_get_resource_state() */
-#define DAV_RESOURCE_LOCK_NULL 10 /* resource lock-null */
-#define DAV_RESOURCE_NULL 11 /* resource null */
-#define DAV_RESOURCE_EXISTS 12 /* resource exists */
-#define DAV_RESOURCE_ERROR 13 /* an error occurred */
-
-
-/* --------------------------------------------------------------------
-**
-** PROPERTY HANDLING
-*/
-
-typedef struct dav_propdb dav_propdb;
-
-
-dav_error *dav_open_propdb(
- request_rec *r,
- dav_lockdb *lockdb,
- const dav_resource *resource,
- int ro,
- apr_array_header_t *ns_xlate,
- dav_propdb **propdb);
-
-void dav_close_propdb(dav_propdb *db);
-
-dav_get_props_result dav_get_props(
- dav_propdb *db,
- ap_xml_doc *doc);
-
-dav_get_props_result dav_get_allprops(
- dav_propdb *db,
- dav_prop_insert what);
-
-void dav_get_liveprop_supported(
- dav_propdb *propdb,
- const char *ns_uri,
- const char *propname,
- ap_text_header *body);
-
-/*
-** 3-phase property modification.
-**
-** 1) validate props. readable? unlocked? ACLs allow access?
-** 2) execute operation (set/delete)
-** 3) commit or rollback
-**
-** ### eventually, auth must be available. a ref to the request_rec (which
-** ### contains the auth info) should be in the shared context struct.
-**
-** Each function may alter the error values and information contained within
-** the context record. This should be done as an "increasing" level of
-** error, rather than overwriting any previous error.
-**
-** Note that commit() cannot generate errors. It should simply free the
-** rollback information.
-**
-** rollback() may generate additional errors because the rollback operation
-** can sometimes fail(!).
-**
-** The caller should allocate an array of these, one per operation. It should
-** be zero-initialized, then the db, operation, and prop fields should be
-** filled in before calling dav_prop_validate. Note that the set/delete
-** operations are order-dependent. For a given (logical) context, the same
-** pointer must be passed to each phase.
-**
-** error_type is an internal value, but will have the same numeric value
-** for each possible "desc" value. This allows the caller to group the
-** descriptions via the error_type variable, rather than through string
-** comparisons. Note that "status" does not provide enough granularity to
-** differentiate/group the "desc" values.
-**
-** Note that the propdb will maintain some (global) context across all
-** of the property change contexts. This implies that you can have only
-** one open transaction per propdb.
-*/
-typedef struct dav_prop_ctx
-{
- dav_propdb *propdb;
-
- int operation;
-#define DAV_PROP_OP_SET 1 /* set a property value */
-#define DAV_PROP_OP_DELETE 2 /* delete a prop value */
-/* ### add a GET? */
-
- ap_xml_elem *prop; /* property to affect */
-
- dav_error *err; /* error (if any) */
-
- /* private items to the propdb */
- int is_liveprop;
- void *liveprop_ctx;
- struct dav_rollback_item *rollback; /* optional rollback info */
-
- /* private to mod_dav.c */
- request_rec *r;
-
-} dav_prop_ctx;
-
-void dav_prop_validate(dav_prop_ctx *ctx);
-void dav_prop_exec(dav_prop_ctx *ctx);
-void dav_prop_commit(dav_prop_ctx *ctx);
-void dav_prop_rollback(dav_prop_ctx *ctx);
-
-#define DAV_PROP_CTX_HAS_ERR(dpc) ((dpc).err && (dpc).err->status >= 300)
-
-
-/* --------------------------------------------------------------------
-**
-** WALKER STRUCTURE
-*/
-
-enum {
- DAV_CALLTYPE_MEMBER = 1, /* called for a member resource */
- DAV_CALLTYPE_COLLECTION, /* called for a collection */
- DAV_CALLTYPE_LOCKNULL /* called for a locknull resource */
-};
-
-typedef struct
-{
- /* the client-provided context */
- void *walk_ctx;
-
- /* pool to use for allocations in the callback */
- apr_pool_t *pool;
-
- /* the current resource */
- const dav_resource *resource;
-
- /* OUTPUT: add responses to this */
- dav_response *response;
-
-} dav_walk_resource;
-
-typedef struct
-{
- int walk_type;
-#define DAV_WALKTYPE_AUTH 0x0001 /* limit to authorized files */
-#define DAV_WALKTYPE_NORMAL 0x0002 /* walk normal files */
-#define DAV_WALKTYPE_LOCKNULL 0x0004 /* walk locknull resources */
-
- /* callback function and a client context for the walk */
- dav_error * (*func)(dav_walk_resource *wres, int calltype);
- void *walk_ctx;
-
- /* what pool to use for allocations needed by walk logic */
- apr_pool_t *pool;
-
- /* beginning root of the walk */
- const dav_resource *root;
-
- /* lock database to enable walking LOCKNULL resources */
- dav_lockdb *lockdb;
-
-} dav_walk_params;
-
-/* directory tree walking context */
-typedef struct dav_walker_ctx
-{
- /* input: */
- dav_walk_params w;
-
-
- /* ### client data... phasing out this big glom */
-
- request_rec *r; /* original request */
-
- /* for PROPFIND operations */
- ap_xml_doc *doc;
- int propfind_type;
-#define DAV_PROPFIND_IS_ALLPROP 1
-#define DAV_PROPFIND_IS_PROPNAME 2
-#define DAV_PROPFIND_IS_PROP 3
-
- ap_text *propstat_404; /* (cached) propstat giving a 404 error */
-
- const dav_if_header *if_header; /* for validation */
- const dav_locktoken *locktoken; /* for UNLOCK */
- const dav_lock *lock; /* for LOCK */
- int skip_root; /* for dav_inherit_locks() */
-
- int flags;
-
- dav_buffer work_buf; /* for dav_validate_request() */
-
-} dav_walker_ctx;
-
-DAV_DECLARE(void) dav_add_response(dav_walk_resource *wres,
- int status,
- dav_get_props_result *propstats);
-
-
-/* --------------------------------------------------------------------
-**
-** "STREAM" STRUCTURE
-**
-** mod_dav uses this abstraction for interacting with the repository
-** while fetching/storing resources. mod_dav views resources as a stream
-** of bytes.
-**
-** Note that the structure is opaque -- it is private to the repository
-** that created the stream in the repository's "open" function.
-*/
-
-typedef struct dav_stream dav_stream;
-
-typedef enum {
- DAV_MODE_READ, /* open for reading */
- DAV_MODE_READ_SEEKABLE, /* open for random access reading */
- DAV_MODE_WRITE_TRUNC, /* truncate and open for writing */
- DAV_MODE_WRITE_SEEKABLE /* open for writing; random access */
-} dav_stream_mode;
-
-
-/* --------------------------------------------------------------------
-**
-** REPOSITORY FUNCTIONS
-*/
-
-/* Repository provider hooks */
-struct dav_hooks_repository
-{
- /* Flag for whether repository requires special GET handling.
- * If resources in the repository are not visible in the
- * filesystem location which URLs map to, then special handling
- * is required to first fetch a resource from the repository,
- * respond to the GET request, then free the resource copy.
- */
- int handle_get;
-
- /* Get a resource descriptor for the URI in a request. A descriptor
- * should always be returned even if the resource does not exist. This
- * repository has been identified as handling the resource given by
- * the URI, so an answer must be given. If there is a problem with the
- * URI or accessing the resource or whatever, then an error should be
- * returned.
- *
- * root_dir:
- * the root of the directory for which this repository is configured.
- *
- * label:
- * if a Label: header is present (and allowed), this is the label
- * to use to identify a version resource from the resource's
- * corresponding version history. Otherwise, it will be NULL.
- *
- * use_checked_in:
- * use the DAV:checked-in property of the resource identified by the
- * Request-URI to identify and return a version resource
- *
- * The provider may associate the request storage pool with the resource
- * (in the resource->pool field), to use in other operations on that
- * resource.
- */
- dav_error * (*get_resource)(
- request_rec *r,
- const char *root_dir,
- const char *label,
- int use_checked_in,
- dav_resource **resource
- );
-
- /* Get a resource descriptor for the parent of the given resource.
- * The resources need not exist. NULL is returned if the resource
- * is the root collection.
- *
- * An error should be returned only if there is a fatal error in
- * fetching information about the parent resource.
- */
- dav_error * (*get_parent_resource)(
- const dav_resource *resource,
- dav_resource **parent_resource
- );
-
- /* Determine whether two resource descriptors refer to the same resource.
- *
- * Result != 0 => the resources are the same.
- */
- int (*is_same_resource)(
- const dav_resource *res1,
- const dav_resource *res2
- );
-
- /* Determine whether one resource is a parent (immediate or otherwise)
- * of another.
- *
- * Result != 0 => res1 is a parent of res2.
- */
- int (*is_parent_resource)(
- const dav_resource *res1,
- const dav_resource *res2
- );
-
- /*
- ** Open a stream for this resource, using the specified mode. The
- ** stream will be returned in *stream.
- */
- dav_error * (*open_stream)(const dav_resource *resource,
- dav_stream_mode mode,
- dav_stream **stream);
-
- /*
- ** Close the specified stream.
- **
- ** mod_dav will (ideally) make sure to call this. For safety purposes,
- ** a provider should (ideally) register a cleanup function with the
- ** request pool to get this closed and cleaned up.
- **
- ** Note the possibility of an error from the close -- it is entirely
- ** feasible that the close does a "commit" of some kind, which can
- ** produce an error.
- **
- ** commit should be TRUE (non-zero) or FALSE (0) if the stream was
- ** opened for writing. This flag states whether to retain the file
- ** or not.
- ** Note: the commit flag is ignored for streams opened for reading.
- */
- dav_error * (*close_stream)(dav_stream *stream, int commit);
-
- /*
- ** Read data from the stream.
- **
- ** The size of the buffer is passed in *bufsize, and the amount read
- ** is returned in *bufsize.
- **
- ** *bufsize should be set to zero when the end of file is reached.
- ** As a corollary, this function should always read at least one byte
- ** on each call, until the EOF condition is met.
- */
- dav_error * (*read_stream)(dav_stream *stream,
- void *buf, apr_size_t *bufsize);
-
- /*
- ** Write data to the stream.
- **
- ** All of the bytes must be written, or an error should be returned.
- */
- dav_error * (*write_stream)(dav_stream *stream,
- const void *buf, apr_size_t bufsize);
-
- /*
- ** Seek to an absolute position in the stream. This is used to support
- ** Content-Range in a GET/PUT.
- **
- ** NOTE: if this function is NULL (which is allowed), then any
- ** operations using Content-Range will be refused.
- */
- dav_error * (*seek_stream)(dav_stream *stream, apr_off_t abs_position);
-
- /*
- ** If a GET is processed using a stream (open_stream, read_stream)
- ** rather than via a sub-request (on get_pathname), then this function
- ** is used to provide the repository with a way to set the headers
- ** in the response.
- **
- ** It may be NULL if get_pathname is provided.
- */
- dav_error * (*set_headers)(request_rec *r,
- const dav_resource *resource);
-
- /* Get a pathname for the file represented by the resource descriptor.
- * A provider may need to create a temporary copy of the file, if it is
- * not directly accessible in a filesystem. free_handle_p will be set by
- * the provider to point to information needed to clean up any temporary
- * storage used.
- *
- * Returns NULL if the file could not be made accessible.
- */
- const char * (*get_pathname)(
- const dav_resource *resource,
- void **free_handle_p
- );
-
- /* Free any temporary storage associated with a file made accessible by
- * get_pathname().
- */
- void (*free_file)(
- void *free_handle
- );
-
- /* Create a collection resource. The resource must not already exist.
- *
- * Result == NULL if the collection was created successfully. Also, the
- * resource object is updated to reflect that the resource exists, and
- * is a collection.
- */
- dav_error * (*create_collection)(
- dav_resource *resource
- );
-
- /* Copy one resource to another. The destination may exist, if it is
- * versioned.
- * Handles both files and collections. Properties are copied as well.
- * If the destination exists and is versioned, the provider must update
- * the destination to have identical content to the source,
- * recursively for collections.
- * The depth argument is ignored for a file, and can be either 0 or
- * DAV_INFINITY for a collection.
- * If an error occurs in a child resource, then the return value is
- * non-NULL, and *response is set to a multistatus response.
- * If the copy is successful, the dst resource object is
- * updated to reflect that the resource exists.
- */
- dav_error * (*copy_resource)(
- const dav_resource *src,
- dav_resource *dst,
- int depth,
- dav_response **response
- );
-
- /* Move one resource to another. The destination must not exist.
- * Handles both files and collections. Properties are moved as well.
- * If an error occurs in a child resource, then the return value is
- * non-NULL, and *response is set to a multistatus response.
- * If the move is successful, the src and dst resource objects are
- * updated to reflect that the source no longer exists, and the
- * destination does.
- */
- dav_error * (*move_resource)(
- dav_resource *src,
- dav_resource *dst,
- dav_response **response
- );
-
- /* Remove a resource. Handles both files and collections.
- * Removes any associated properties as well.
- * If an error occurs in a child resource, then the return value is
- * non-NULL, and *response is set to a multistatus response.
- * If the delete is successful, the resource object is updated to
- * reflect that the resource no longer exists.
- */
- dav_error * (*remove_resource)(
- dav_resource *resource,
- dav_response **response
- );
-
- /* Walk a resource hierarchy.
- *
- * Iterates over the resource hierarchy specified by params->root.
- * Control of the walk and the callback are specified by 'params'.
- *
- * An error may be returned. *response will contain multistatus
- * responses (if any) suitable for the body of the error. It is also
- * possible to return NULL, yet still have multistatus responses.
- * In this case, typically the caller should return a 207 (Multistatus)
- * and the responses (in the body) as the HTTP response.
- */
- dav_error * (*walk)(const dav_walk_params *params, int depth,
- dav_response **response);
-
- /* Get the entity tag for a resource */
- const char * (*getetag)(const dav_resource *resource);
-};
-
-
-/* --------------------------------------------------------------------
-**
-** VERSIONING FUNCTIONS
-*/
-
-
-/* dav_add_vary_header
- *
- * If there were any headers in the request which require a Vary header
- * in the response, add it.
- */
-void dav_add_vary_header(request_rec *in_req,
- request_rec *out_req,
- const dav_resource *resource);
-
-/*
-** Flags specifying auto-versioning behavior, returned by
-** the auto_versionable hook. The value returned depends
-** on both the state of the resource and the value of the
-** DAV:auto-versioning property for the resource.
-**
-** If the resource does not exist (null or lock-null),
-** DAV_AUTO_VERSION_ALWAYS causes creation of a new version-controlled resource
-**
-** If the resource is checked in,
-** DAV_AUTO_VERSION_ALWAYS causes it to be checked out always,
-** DAV_AUTO_VERSION_LOCKED causes it to be checked out only when locked
-**
-** If the resource is checked out,
-** DAV_AUTO_VERSION_ALWAYS causes it to be checked in always,
-** DAV_AUTO_VERSION_LOCKED causes it to be checked in when unlocked
-** (note: a provider should allow auto-checkin only for resources which
-** were automatically checked out)
-**
-** In all cases, DAV_AUTO_VERSION_NEVER results in no auto-versioning behavior.
-*/
-typedef enum {
- DAV_AUTO_VERSION_NEVER,
- DAV_AUTO_VERSION_ALWAYS,
- DAV_AUTO_VERSION_LOCKED
-} dav_auto_version;
-
-/*
-** This structure is used to record what auto-versioning operations
-** were done to make a resource writable, so that they can be undone
-** at the end of a request.
-*/
-typedef struct {
- int resource_versioned; /* 1 => resource was auto-version-controlled */
- int resource_checkedout; /* 1 => resource was auto-checked-out */
- int parent_checkedout; /* 1 => parent was auto-checked-out */
- dav_resource *parent_resource; /* parent resource, if it was needed */
-} dav_auto_version_info;
-
-/* Ensure that a resource is writable. If there is no versioning
- * provider, then this is essentially a no-op. Versioning repositories
- * require explicit resource creation and checkout before they can
- * be written to. If a new resource is to be created, or an existing
- * resource deleted, the parent collection must be checked out as well.
- *
- * Set the parent_only flag to only make the parent collection writable.
- * Otherwise, both parent and child are made writable as needed. If the
- * child does not exist, then a new versioned resource is created and
- * checked out.
- *
- * If auto-versioning is not enabled for a versioned resource, then an error is
- * returned, since the resource cannot be modified.
- *
- * The dav_auto_version_info structure is filled in with enough information
- * to restore both parent and child resources to the state they were in
- * before the auto-versioning operations occurred.
- */
-dav_error *dav_auto_checkout(
- request_rec *r,
- dav_resource *resource,
- int parent_only,
- dav_auto_version_info *av_info);
-
-/* Revert the writability of resources back to what they were
- * before they were modified. If undo == 0, then the resource
- * modifications are maintained (i.e. they are checked in).
- * If undo != 0, then resource modifications are discarded
- * (i.e. they are unchecked out).
- *
- * Set the unlock flag to indicate that the resource is about
- * to be unlocked; it will be checked in if the resource
- * auto-versioning property indicates it should be. In this case,
- * av_info is ignored, so it can be NULL.
- *
- * The resource argument may be NULL if only the parent resource
- * was checked out (i.e. the parent_only was != 0 in the
- * dav_auto_checkout call).
- */
-dav_error *dav_auto_checkin(
- request_rec *r,
- dav_resource *resource,
- int undo,
- int unlock,
- dav_auto_version_info *av_info);
-
-/*
-** This structure is used to describe available reports
-**
-** "nmspace" should be valid XML and URL-quoted. mod_dav will place
-** double-quotes around it and use it in an xmlns declaration.
-*/
-typedef struct {
- const char *nmspace; /* namespace of the XML report element */
- const char *name; /* element name for the XML report */
-} dav_report_elem;
-
-
-/* Versioning provider hooks */
-struct dav_hooks_vsn
-{
- /*
- ** MANDATORY HOOKS
- ** The following hooks are mandatory for all versioning providers;
- ** they define the functionality needed to implement "core" versioning.
- */
-
- /* Return supported versioning options.
- * Each dav_text item in the list will be returned as a separate
- * DAV header. Providers are advised to limit the length of an
- * individual text item to 63 characters, to conform to the limit
- * used by MS Web Folders.
- */
- void (*get_vsn_options)(apr_pool_t *p, ap_text_header *phdr);
-
- /* Get the value of a specific option for an OPTIONS request.
- * The option being requested is given by the parsed XML
- * element object "elem". The value of the option should be
- * appended to the "option" text object.
- */
- dav_error * (*get_option)(const dav_resource *resource,
- const ap_xml_elem *elem,
- ap_text_header *option);
-
- /* Determine whether a non-versioned (or non-existent) resource
- * is versionable. Returns != 0 if resource can be versioned.
- */
- int (*versionable)(const dav_resource *resource);
-
- /* Determine whether auto-versioning is enabled for a resource
- * (which may not exist, or may not be versioned). If the resource
- * is a checked-out resource, the provider must only enable
- * auto-checkin if the resource was automatically checked out.
- *
- * The value returned depends on both the state of the resource
- * and the value of its DAV:auto-version property. See the description
- * of the dav_auto_version enumeration above for the details.
- */
- dav_auto_version (*auto_versionable)(const dav_resource *resource);
-
- /* Put a resource under version control. If the resource already
- * exists unversioned, then it becomes the initial version of the
- * new version history, and it is replaced by a version selector
- * which targets the new version.
- *
- * If the resource does not exist, then a new version-controlled
- * resource is created which either targets an existing version (if the
- * "target" argument is not NULL), or the initial, empty version
- * in a new history resource (if the "target" argument is NULL).
- *
- * If successful, the resource object state is updated appropriately
- * (that is, changed to refer to the new version-controlled resource).
- */
- dav_error * (*vsn_control)(dav_resource *resource,
- const char *target);
-
- /* Checkout a resource. If successful, the resource
- * object state is updated appropriately.
- *
- * The auto_checkout flag will be set if this checkout is being
- * done automatically, as part of some method which modifies
- * the resource. The provider must remember that the resource
- * was automatically checked out, so it can determine whether it
- * can be automatically checked in. (Auto-checkin should only be
- * enabled for resources which were automatically checked out.)
- *
- * If the working resource has a different URL from the
- * target resource, a dav_resource descriptor is returned
- * for the new working resource. Otherwise, the original
- * resource descriptor will refer to the working resource.
- * The working_resource argument can be NULL if the caller
- * is not interested in the working resource.
- *
- * If the client has specified DAV:unreserved or DAV:fork-ok in the
- * checkout request, then the corresponding flags are set. If
- * DAV:activity-set has been specified, then create_activity is set
- * if DAV:new was specified; otherwise, the DAV:href elements' CDATA
- * (the actual href text) is passed in the "activities" array (each
- * element of the array is a const char *). activities will be NULL
- * no DAV:activity-set was provided or when create_activity is set.
- */
- dav_error * (*checkout)(dav_resource *resource,
- int auto_checkout,
- int is_unreserved, int is_fork_ok,
- int create_activity,
- apr_array_header_t *activities,
- dav_resource **working_resource);
-
- /* Uncheckout a checked-out resource. If successful, the resource
- * object state is updated appropriately.
- */
- dav_error * (*uncheckout)(dav_resource *resource);
-
- /* Checkin a checked-out resource. If successful, the resource
- * object state is updated appropriately, and the
- * version_resource descriptor will refer to the new version.
- * The version_resource argument can be NULL if the caller
- * is not interested in the new version resource.
- *
- * If the client has specified DAV:keep-checked-out in the checkin
- * request, then the keep_checked_out flag is set. The provider
- * should create a new version, but keep the resource in the
- * checked-out state.
- */
- dav_error * (*checkin)(dav_resource *resource,
- int keep_checked_out,
- dav_resource **version_resource);
-
- /*
- ** Return the set of reports available at this resource.
- **
- ** An array of report elements should be returned, with an end-marker
- ** element containing namespace==NULL. The value of the
- ** DAV:supported-report-set property will be constructed and
- ** returned.
- */
- dav_error * (*avail_reports)(const dav_resource *resource,
- const dav_report_elem **reports);
-
- /*
- ** Determine whether a Label header can be used
- ** with a particular report. The dav_xml_doc structure
- ** contains the parsed report request body.
- ** Returns 0 if the Label header is not allowed.
- */
- int (*report_label_header_allowed)(const ap_xml_doc *doc);
-
- /*
- ** Generate a report on a resource. Since a provider is free
- ** to define its own reports, and the value of request headers
- ** may affect the interpretation of a report, the request record
- ** must be passed to this routine.
- **
- ** The dav_xml_doc structure contains the parsed report request
- ** body. The report response is generated into the ap_text_header
- ** structure.
- **
- ** ### shouldn't generate large responses to memory ###
- */
- dav_error * (*get_report)(request_rec *r,
- const dav_resource *resource,
- const ap_xml_doc *doc,
- ap_text_header *report);
-
- /*
- ** OPTIONAL HOOKS
- ** The following hooks are optional; if not defined, then the
- ** corresponding protocol methods will be unsupported.
- */
-
- /*
- ** Set the state of a checked-in version-controlled resource.
- **
- ** If the request specified a version, the version resource
- ** represents that version. If the request specified a label,
- ** then "version" is NULL, and "label" is the label.
- **
- ** The depth argument is ignored for a file, and can be 0, 1, or
- ** DAV_INFINITY for a collection. The depth argument only applies
- ** with a label, not a version.
- **
- ** If an error occurs in a child resource, then the return value is
- ** non-NULL, and *response is set to a multistatus response.
- **
- ** This hook is optional; if not defined, then the UPDATE method
- ** will not be supported.
- */
- dav_error * (*update)(const dav_resource *resource,
- const dav_resource *version,
- const char *label,
- int depth,
- dav_response **response);
-
- /*
- ** Add a label to a version. The resource is either a specific
- ** version, or a version selector, in which case the label should
- ** be added to the current target of the version selector. The
- ** version selector cannot be checked out.
- **
- ** If replace != 0, any existing label by the same name is
- ** effectively deleted first. Otherwise, it is an error to
- ** attempt to add a label which already exists on some version
- ** of the same history resource.
- **
- ** This hook is optional; if not defined, then the LABEL method
- ** will not be supported. If it is defined, then the remove_label
- ** hook must be defined also.
- */
- dav_error * (*add_label)(const dav_resource *resource,
- const char *label,
- int replace);
-
- /*
- ** Remove a label from a version. The resource is either a specific
- ** version, or a version selector, in which case the label should
- ** be added to the current target of the version selector. The
- ** version selector cannot be checked out.
- **
- ** It is an error if no such label exists on the specified version.
- **
- ** This hook is optional, but if defined, the add_label hook
- ** must be defined also.
- */
- dav_error * (*remove_label)(const dav_resource *resource,
- const char *label);
-
- /*
- ** Determine whether a null resource can be created as a workspace.
- ** The provider may restrict workspaces to certain locations.
- ** Returns 0 if the resource cannot be a workspace.
- **
- ** This hook is optional; if the provider does not support workspaces,
- ** it should be set to NULL.
- */
- int (*can_be_workspace)(const dav_resource *resource);
-
- /*
- ** Create a workspace resource. The resource must not already
- ** exist. Any <DAV:mkworkspace> element is passed to the provider
- ** in the "doc" structure; it may be empty.
- **
- ** If workspace creation is succesful, the state of the resource
- ** object is updated appropriately.
- **
- ** This hook is optional; if the provider does not support workspaces,
- ** it should be set to NULL.
- */
- dav_error * (*make_workspace)(dav_resource *resource,
- ap_xml_doc *doc);
-
- /*
- ** Determine whether a null resource can be created as an activity.
- ** The provider may restrict activities to certain locations.
- ** Returns 0 if the resource cannot be an activity.
- **
- ** This hook is optional; if the provider does not support activities,
- ** it should be set to NULL.
- */
- int (*can_be_activity)(const dav_resource *resource);
-
- /*
- ** Create an activity resource. The resource must not already
- ** exist.
- **
- ** If activity creation is succesful, the state of the resource
- ** object is updated appropriately.
- **
- ** This hook is optional; if the provider does not support activities,
- ** it should be set to NULL.
- */
- dav_error * (*make_activity)(dav_resource *resource);
-
- /*
- ** Merge a resource (tree) into target resource (tree).
- **
- ** ### more doc...
- **
- ** This hook is optional; if the provider does not support merging,
- ** then this should be set to NULL.
- */
- dav_error * (*merge)(dav_resource *target, dav_resource *source,
- int no_auto_merge, int no_checkout,
- ap_xml_elem *prop_elem,
- ap_filter_t *output);
-};
-
-
-/* --------------------------------------------------------------------
-**
-** BINDING FUNCTIONS
-*/
-
-/* binding provider hooks */
-struct dav_hooks_binding {
-
- /* Determine whether a resource can be the target of a binding.
- * Returns 0 if the resource cannot be a binding target.
- */
- int (*is_bindable)(const dav_resource *resource);
-
- /* Create a binding to a resource.
- * The resource argument is the target of the binding;
- * the binding argument must be a resource which does not already
- * exist.
- */
- dav_error * (*bind_resource)(const dav_resource *resource,
- dav_resource *binding);
-
-};
-
-
-/* --------------------------------------------------------------------
-**
-** MISCELLANEOUS STUFF
-*/
-
-/* allow providers access to the per-directory parameters */
-apr_table_t *dav_get_dir_params(const request_rec *r);
-
-/* fetch the "LimitXMLRequestBody" in force for this resource */
-apr_size_t dav_get_limit_xml_body(const request_rec *r);
-
-typedef struct {
- int propid; /* live property ID */
- const dav_hooks_liveprop *provider; /* the provider defining this prop */
-} dav_elem_private;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _MOD_DAV_H_ */
diff --git a/modules/dav/main/mod_dav.mak b/modules/dav/main/mod_dav.mak
deleted file mode 100644
index 531297978c..0000000000
--- a/modules/dav/main/mod_dav.mak
+++ /dev/null
@@ -1,659 +0,0 @@
-# Microsoft Developer Studio Generated NMAKE File, Based on mod_dav.dsp
-!IF "$(CFG)" == ""
-CFG=mod_dav - Win32 Release
-!MESSAGE No configuration specified. Defaulting to mod_dav - Win32 Release.
-!ENDIF
-
-!IF "$(CFG)" != "mod_dav - Win32 Release" && "$(CFG)" !=\
- "mod_dav - Win32 Debug"
-!MESSAGE Invalid configuration "$(CFG)" specified.
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_dav.mak" CFG="mod_dav - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_dav - Win32 Release" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_dav - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-!ERROR An invalid configuration is specified.
-!ENDIF
-
-!IF "$(OS)" == "Windows_NT"
-NULL=
-!ELSE
-NULL=nul
-!ENDIF
-
-!IF "$(CFG)" == "mod_dav - Win32 Release"
-
-OUTDIR=.\Release
-INTDIR=.\Release
-# Begin Custom Macros
-OutDir=.\Release
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_dav.so"
-
-!ELSE
-
-ALL : "libhttpd - Win32 Release" "libaprutil - Win32 Release"\
- "libapr - Win32 Release" "$(OUTDIR)\mod_dav.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libapr - Win32 ReleaseCLEAN" "libaprutil - Win32 ReleaseCLEAN"\
- "libhttpd - Win32 ReleaseCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\liveprop.obj"
- -@erase "$(INTDIR)\mod_dav.idb"
- -@erase "$(INTDIR)\mod_dav.obj"
- -@erase "$(INTDIR)\props.obj"
- -@erase "$(INTDIR)\providers.obj"
- -@erase "$(INTDIR)\std_liveprop.obj"
- -@erase "$(INTDIR)\util.obj"
- -@erase "$(INTDIR)\util_lock.obj"
- -@erase "$(OUTDIR)\mod_dav.exp"
- -@erase "$(OUTDIR)\mod_dav.lib"
- -@erase "$(OUTDIR)\mod_dav.map"
- -@erase "$(OUTDIR)\mod_dav.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MD /W3 /O2 /I "..\..\..\srclib\aputil" /I\
- "..\..\..\srclib\sdbm" /I "..\..\..\srclib\expat-lite" /I\
- "..\..\..\srclib\apr\include" /I "../../../srclib/apr-util/include" /I\
- "..\..\..\include" /I "..\..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS"\
- /D "DAV_DECLARE_EXPORT" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_dav" /FD /c
-CPP_OBJS=.\Release/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_dav.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows\
- /dll /incremental:no /pdb:"$(OUTDIR)\mod_dav.pdb" /map:"$(INTDIR)\mod_dav.map"\
- /machine:I386 /out:"$(OUTDIR)\mod_dav.so" /implib:"$(OUTDIR)\mod_dav.lib"\
- /base:@..\..\..\os\win32\BaseAddr.ref,mod_dav
-LINK32_OBJS= \
- "$(INTDIR)\liveprop.obj" \
- "$(INTDIR)\mod_dav.obj" \
- "$(INTDIR)\props.obj" \
- "$(INTDIR)\providers.obj" \
- "$(INTDIR)\std_liveprop.obj" \
- "$(INTDIR)\util.obj" \
- "$(INTDIR)\util_lock.obj" \
- "..\..\..\Release\libhttpd.lib" \
- "..\..\..\srclib\apr-util\Release\libaprutil.lib" \
- "..\..\..\srclib\apr\Release\libapr.lib"
-
-"$(OUTDIR)\mod_dav.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ELSEIF "$(CFG)" == "mod_dav - Win32 Debug"
-
-OUTDIR=.\Debug
-INTDIR=.\Debug
-# Begin Custom Macros
-OutDir=.\Debug
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_dav.so"
-
-!ELSE
-
-ALL : "libhttpd - Win32 Debug" "libaprutil - Win32 Debug"\
- "libapr - Win32 Debug" "$(OUTDIR)\mod_dav.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libapr - Win32 DebugCLEAN" "libaprutil - Win32 DebugCLEAN"\
- "libhttpd - Win32 DebugCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\liveprop.obj"
- -@erase "$(INTDIR)\mod_dav.idb"
- -@erase "$(INTDIR)\mod_dav.obj"
- -@erase "$(INTDIR)\props.obj"
- -@erase "$(INTDIR)\providers.obj"
- -@erase "$(INTDIR)\std_liveprop.obj"
- -@erase "$(INTDIR)\util.obj"
- -@erase "$(INTDIR)\util_lock.obj"
- -@erase "$(OUTDIR)\mod_dav.exp"
- -@erase "$(OUTDIR)\mod_dav.ilk"
- -@erase "$(OUTDIR)\mod_dav.lib"
- -@erase "$(OUTDIR)\mod_dav.map"
- -@erase "$(OUTDIR)\mod_dav.pdb"
- -@erase "$(OUTDIR)\mod_dav.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\..\srclib\aputil" /I\
- "..\..\..\srclib\sdbm" /I "..\..\..\srclib\expat-lite" /I\
- "..\..\..\srclib\apr\include" /I "../../../srclib/apr-util/include" /I\
- "..\..\..\include" /I "..\..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS"\
- /D "DAV_DECLARE_EXPORT" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_dav" /FD /c
-CPP_OBJS=.\Debug/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_dav.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows\
- /dll /incremental:yes /pdb:"$(OUTDIR)\mod_dav.pdb" /map:"$(INTDIR)\mod_dav.map"\
- /debug /machine:I386 /out:"$(OUTDIR)\mod_dav.so"\
- /implib:"$(OUTDIR)\mod_dav.lib" /base:@..\..\..\os\win32\BaseAddr.ref,mod_dav
-LINK32_OBJS= \
- "$(INTDIR)\liveprop.obj" \
- "$(INTDIR)\mod_dav.obj" \
- "$(INTDIR)\props.obj" \
- "$(INTDIR)\providers.obj" \
- "$(INTDIR)\std_liveprop.obj" \
- "$(INTDIR)\util.obj" \
- "$(INTDIR)\util_lock.obj" \
- "..\..\..\Debug\libhttpd.lib" \
- "..\..\..\srclib\apr-util\Debug\libaprutil.lib" \
- "..\..\..\srclib\apr\Debug\libapr.lib"
-
-"$(OUTDIR)\mod_dav.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ENDIF
-
-
-!IF "$(CFG)" == "mod_dav - Win32 Release" || "$(CFG)" ==\
- "mod_dav - Win32 Debug"
-SOURCE=.\liveprop.c
-DEP_CPP_LIVEP=\
- "..\..\..\include\ap_config.h"\
- "..\..\..\include\ap_mmn.h"\
- "..\..\..\include\ap_release.h"\
- "..\..\..\include\httpd.h"\
- "..\..\..\include\pcreposix.h"\
- "..\..\..\include\util_uri.h"\
- "..\..\..\include\util_xml.h"\
- "..\..\..\os\win32\os.h"\
- "..\..\..\srclib\apr-util\include\apr_dbm.h"\
- "..\..\..\srclib\apr-util\include\apr_hooks.h"\
- "..\..\..\srclib\apr-util\include\apr_xml.h"\
- "..\..\..\srclib\apr-util\include\apu.h"\
- "..\..\..\srclib\apr-util\include\apu_compat.h"\
- "..\..\..\srclib\apr\include\apr.h"\
- "..\..\..\srclib\apr\include\apr_compat.h"\
- "..\..\..\srclib\apr\include\apr_errno.h"\
- "..\..\..\srclib\apr\include\apr_file_info.h"\
- "..\..\..\srclib\apr\include\apr_file_io.h"\
- "..\..\..\srclib\apr\include\apr_general.h"\
- "..\..\..\srclib\apr\include\apr_hash.h"\
- "..\..\..\srclib\apr\include\apr_network_io.h"\
- "..\..\..\srclib\apr\include\apr_pools.h"\
- "..\..\..\srclib\apr\include\apr_strings.h"\
- "..\..\..\srclib\apr\include\apr_tables.h"\
- "..\..\..\srclib\apr\include\apr_time.h"\
- "..\..\..\srclib\apr\include\apr_user.h"\
- "..\..\..\srclib\apr\include\apr_want.h"\
- ".\mod_dav.h"\
-
-NODEP_CPP_LIVEP=\
- "..\..\..\include\ap_config_auto.h"\
-
-
-"$(INTDIR)\liveprop.obj" : $(SOURCE) $(DEP_CPP_LIVEP) "$(INTDIR)"
-
-
-SOURCE=.\mod_dav.c
-DEP_CPP_MOD_D=\
- "..\..\..\include\ap_config.h"\
- "..\..\..\include\ap_mmn.h"\
- "..\..\..\include\ap_release.h"\
- "..\..\..\include\http_config.h"\
- "..\..\..\include\http_core.h"\
- "..\..\..\include\http_log.h"\
- "..\..\..\include\http_main.h"\
- "..\..\..\include\http_protocol.h"\
- "..\..\..\include\http_request.h"\
- "..\..\..\include\httpd.h"\
- "..\..\..\include\pcreposix.h"\
- "..\..\..\include\util_cfgtree.h"\
- "..\..\..\include\util_filter.h"\
- "..\..\..\include\util_script.h"\
- "..\..\..\include\util_uri.h"\
- "..\..\..\include\util_xml.h"\
- "..\..\..\os\win32\os.h"\
- "..\..\..\srclib\apr-util\include\apr_buckets.h"\
- "..\..\..\srclib\apr-util\include\apr_dbm.h"\
- "..\..\..\srclib\apr-util\include\apr_hooks.h"\
- "..\..\..\srclib\apr-util\include\apr_ring.h"\
- "..\..\..\srclib\apr-util\include\apr_xml.h"\
- "..\..\..\srclib\apr-util\include\apu.h"\
- "..\..\..\srclib\apr-util\include\apu_compat.h"\
- "..\..\..\srclib\apr\include\apr.h"\
- "..\..\..\srclib\apr\include\apr_compat.h"\
- "..\..\..\srclib\apr\include\apr_dso.h"\
- "..\..\..\srclib\apr\include\apr_errno.h"\
- "..\..\..\srclib\apr\include\apr_file_info.h"\
- "..\..\..\srclib\apr\include\apr_file_io.h"\
- "..\..\..\srclib\apr\include\apr_general.h"\
- "..\..\..\srclib\apr\include\apr_hash.h"\
- "..\..\..\srclib\apr\include\apr_lib.h"\
- "..\..\..\srclib\apr\include\apr_lock.h"\
- "..\..\..\srclib\apr\include\apr_mmap.h"\
- "..\..\..\srclib\apr\include\apr_network_io.h"\
- "..\..\..\srclib\apr\include\apr_pools.h"\
- "..\..\..\srclib\apr\include\apr_portable.h"\
- "..\..\..\srclib\apr\include\apr_strings.h"\
- "..\..\..\srclib\apr\include\apr_tables.h"\
- "..\..\..\srclib\apr\include\apr_thread_proc.h"\
- "..\..\..\srclib\apr\include\apr_time.h"\
- "..\..\..\srclib\apr\include\apr_user.h"\
- "..\..\..\srclib\apr\include\apr_want.h"\
- ".\mod_dav.h"\
-
-NODEP_CPP_MOD_D=\
- "..\..\..\include\ap_config_auto.h"\
-
-
-"$(INTDIR)\mod_dav.obj" : $(SOURCE) $(DEP_CPP_MOD_D) "$(INTDIR)"
-
-
-SOURCE=.\props.c
-DEP_CPP_PROPS=\
- "..\..\..\include\ap_config.h"\
- "..\..\..\include\ap_mmn.h"\
- "..\..\..\include\ap_release.h"\
- "..\..\..\include\http_log.h"\
- "..\..\..\include\http_request.h"\
- "..\..\..\include\httpd.h"\
- "..\..\..\include\pcreposix.h"\
- "..\..\..\include\util_filter.h"\
- "..\..\..\include\util_uri.h"\
- "..\..\..\include\util_xml.h"\
- "..\..\..\os\win32\os.h"\
- "..\..\..\srclib\apr-util\include\apr_buckets.h"\
- "..\..\..\srclib\apr-util\include\apr_dbm.h"\
- "..\..\..\srclib\apr-util\include\apr_hooks.h"\
- "..\..\..\srclib\apr-util\include\apr_ring.h"\
- "..\..\..\srclib\apr-util\include\apr_xml.h"\
- "..\..\..\srclib\apr-util\include\apu.h"\
- "..\..\..\srclib\apr-util\include\apu_compat.h"\
- "..\..\..\srclib\apr\include\apr.h"\
- "..\..\..\srclib\apr\include\apr_compat.h"\
- "..\..\..\srclib\apr\include\apr_errno.h"\
- "..\..\..\srclib\apr\include\apr_file_info.h"\
- "..\..\..\srclib\apr\include\apr_file_io.h"\
- "..\..\..\srclib\apr\include\apr_general.h"\
- "..\..\..\srclib\apr\include\apr_hash.h"\
- "..\..\..\srclib\apr\include\apr_mmap.h"\
- "..\..\..\srclib\apr\include\apr_network_io.h"\
- "..\..\..\srclib\apr\include\apr_pools.h"\
- "..\..\..\srclib\apr\include\apr_strings.h"\
- "..\..\..\srclib\apr\include\apr_tables.h"\
- "..\..\..\srclib\apr\include\apr_thread_proc.h"\
- "..\..\..\srclib\apr\include\apr_time.h"\
- "..\..\..\srclib\apr\include\apr_user.h"\
- "..\..\..\srclib\apr\include\apr_want.h"\
- ".\mod_dav.h"\
-
-NODEP_CPP_PROPS=\
- "..\..\..\include\ap_config_auto.h"\
-
-
-"$(INTDIR)\props.obj" : $(SOURCE) $(DEP_CPP_PROPS) "$(INTDIR)"
-
-
-SOURCE=.\providers.c
-DEP_CPP_PROVI=\
- "..\..\..\include\ap_config.h"\
- "..\..\..\include\ap_mmn.h"\
- "..\..\..\include\ap_release.h"\
- "..\..\..\include\httpd.h"\
- "..\..\..\include\pcreposix.h"\
- "..\..\..\include\util_uri.h"\
- "..\..\..\include\util_xml.h"\
- "..\..\..\os\win32\os.h"\
- "..\..\..\srclib\apr-util\include\apr_dbm.h"\
- "..\..\..\srclib\apr-util\include\apr_hooks.h"\
- "..\..\..\srclib\apr-util\include\apr_xml.h"\
- "..\..\..\srclib\apr-util\include\apu.h"\
- "..\..\..\srclib\apr-util\include\apu_compat.h"\
- "..\..\..\srclib\apr\include\apr.h"\
- "..\..\..\srclib\apr\include\apr_compat.h"\
- "..\..\..\srclib\apr\include\apr_errno.h"\
- "..\..\..\srclib\apr\include\apr_file_info.h"\
- "..\..\..\srclib\apr\include\apr_file_io.h"\
- "..\..\..\srclib\apr\include\apr_general.h"\
- "..\..\..\srclib\apr\include\apr_hash.h"\
- "..\..\..\srclib\apr\include\apr_network_io.h"\
- "..\..\..\srclib\apr\include\apr_pools.h"\
- "..\..\..\srclib\apr\include\apr_tables.h"\
- "..\..\..\srclib\apr\include\apr_time.h"\
- "..\..\..\srclib\apr\include\apr_user.h"\
- "..\..\..\srclib\apr\include\apr_want.h"\
- ".\mod_dav.h"\
-
-NODEP_CPP_PROVI=\
- "..\..\..\include\ap_config_auto.h"\
-
-
-"$(INTDIR)\providers.obj" : $(SOURCE) $(DEP_CPP_PROVI) "$(INTDIR)"
-
-
-SOURCE=.\std_liveprop.c
-DEP_CPP_STD_L=\
- "..\..\..\include\ap_config.h"\
- "..\..\..\include\ap_mmn.h"\
- "..\..\..\include\ap_release.h"\
- "..\..\..\include\httpd.h"\
- "..\..\..\include\pcreposix.h"\
- "..\..\..\include\util_uri.h"\
- "..\..\..\include\util_xml.h"\
- "..\..\..\os\win32\os.h"\
- "..\..\..\srclib\apr-util\include\apr_dbm.h"\
- "..\..\..\srclib\apr-util\include\apr_hooks.h"\
- "..\..\..\srclib\apr-util\include\apr_xml.h"\
- "..\..\..\srclib\apr-util\include\apu.h"\
- "..\..\..\srclib\apr-util\include\apu_compat.h"\
- "..\..\..\srclib\apr\include\apr.h"\
- "..\..\..\srclib\apr\include\apr_compat.h"\
- "..\..\..\srclib\apr\include\apr_errno.h"\
- "..\..\..\srclib\apr\include\apr_file_info.h"\
- "..\..\..\srclib\apr\include\apr_file_io.h"\
- "..\..\..\srclib\apr\include\apr_general.h"\
- "..\..\..\srclib\apr\include\apr_hash.h"\
- "..\..\..\srclib\apr\include\apr_network_io.h"\
- "..\..\..\srclib\apr\include\apr_pools.h"\
- "..\..\..\srclib\apr\include\apr_strings.h"\
- "..\..\..\srclib\apr\include\apr_tables.h"\
- "..\..\..\srclib\apr\include\apr_time.h"\
- "..\..\..\srclib\apr\include\apr_user.h"\
- "..\..\..\srclib\apr\include\apr_want.h"\
- ".\mod_dav.h"\
-
-NODEP_CPP_STD_L=\
- "..\..\..\include\ap_config_auto.h"\
-
-
-"$(INTDIR)\std_liveprop.obj" : $(SOURCE) $(DEP_CPP_STD_L) "$(INTDIR)"
-
-
-SOURCE=.\util.c
-DEP_CPP_UTIL_=\
- "..\..\..\include\ap_config.h"\
- "..\..\..\include\ap_mmn.h"\
- "..\..\..\include\ap_release.h"\
- "..\..\..\include\http_config.h"\
- "..\..\..\include\http_log.h"\
- "..\..\..\include\http_protocol.h"\
- "..\..\..\include\http_request.h"\
- "..\..\..\include\http_vhost.h"\
- "..\..\..\include\httpd.h"\
- "..\..\..\include\pcreposix.h"\
- "..\..\..\include\util_cfgtree.h"\
- "..\..\..\include\util_filter.h"\
- "..\..\..\include\util_uri.h"\
- "..\..\..\include\util_xml.h"\
- "..\..\..\os\win32\os.h"\
- "..\..\..\srclib\apr-util\include\apr_buckets.h"\
- "..\..\..\srclib\apr-util\include\apr_dbm.h"\
- "..\..\..\srclib\apr-util\include\apr_hooks.h"\
- "..\..\..\srclib\apr-util\include\apr_ring.h"\
- "..\..\..\srclib\apr-util\include\apr_xml.h"\
- "..\..\..\srclib\apr-util\include\apu.h"\
- "..\..\..\srclib\apr-util\include\apu_compat.h"\
- "..\..\..\srclib\apr\include\apr.h"\
- "..\..\..\srclib\apr\include\apr_compat.h"\
- "..\..\..\srclib\apr\include\apr_dso.h"\
- "..\..\..\srclib\apr\include\apr_errno.h"\
- "..\..\..\srclib\apr\include\apr_file_info.h"\
- "..\..\..\srclib\apr\include\apr_file_io.h"\
- "..\..\..\srclib\apr\include\apr_general.h"\
- "..\..\..\srclib\apr\include\apr_hash.h"\
- "..\..\..\srclib\apr\include\apr_lib.h"\
- "..\..\..\srclib\apr\include\apr_lock.h"\
- "..\..\..\srclib\apr\include\apr_mmap.h"\
- "..\..\..\srclib\apr\include\apr_network_io.h"\
- "..\..\..\srclib\apr\include\apr_pools.h"\
- "..\..\..\srclib\apr\include\apr_portable.h"\
- "..\..\..\srclib\apr\include\apr_strings.h"\
- "..\..\..\srclib\apr\include\apr_tables.h"\
- "..\..\..\srclib\apr\include\apr_thread_proc.h"\
- "..\..\..\srclib\apr\include\apr_time.h"\
- "..\..\..\srclib\apr\include\apr_user.h"\
- "..\..\..\srclib\apr\include\apr_want.h"\
- ".\mod_dav.h"\
-
-NODEP_CPP_UTIL_=\
- "..\..\..\include\ap_config_auto.h"\
-
-
-"$(INTDIR)\util.obj" : $(SOURCE) $(DEP_CPP_UTIL_) "$(INTDIR)"
-
-
-SOURCE=.\util_lock.c
-DEP_CPP_UTIL_L=\
- "..\..\..\include\ap_config.h"\
- "..\..\..\include\ap_mmn.h"\
- "..\..\..\include\ap_release.h"\
- "..\..\..\include\http_config.h"\
- "..\..\..\include\http_core.h"\
- "..\..\..\include\http_log.h"\
- "..\..\..\include\http_protocol.h"\
- "..\..\..\include\httpd.h"\
- "..\..\..\include\pcreposix.h"\
- "..\..\..\include\util_cfgtree.h"\
- "..\..\..\include\util_filter.h"\
- "..\..\..\include\util_uri.h"\
- "..\..\..\include\util_xml.h"\
- "..\..\..\os\win32\os.h"\
- "..\..\..\srclib\apr-util\include\apr_buckets.h"\
- "..\..\..\srclib\apr-util\include\apr_dbm.h"\
- "..\..\..\srclib\apr-util\include\apr_hooks.h"\
- "..\..\..\srclib\apr-util\include\apr_ring.h"\
- "..\..\..\srclib\apr-util\include\apr_xml.h"\
- "..\..\..\srclib\apr-util\include\apu.h"\
- "..\..\..\srclib\apr-util\include\apu_compat.h"\
- "..\..\..\srclib\apr\include\apr.h"\
- "..\..\..\srclib\apr\include\apr_compat.h"\
- "..\..\..\srclib\apr\include\apr_dso.h"\
- "..\..\..\srclib\apr\include\apr_errno.h"\
- "..\..\..\srclib\apr\include\apr_file_info.h"\
- "..\..\..\srclib\apr\include\apr_file_io.h"\
- "..\..\..\srclib\apr\include\apr_general.h"\
- "..\..\..\srclib\apr\include\apr_hash.h"\
- "..\..\..\srclib\apr\include\apr_lock.h"\
- "..\..\..\srclib\apr\include\apr_mmap.h"\
- "..\..\..\srclib\apr\include\apr_network_io.h"\
- "..\..\..\srclib\apr\include\apr_pools.h"\
- "..\..\..\srclib\apr\include\apr_portable.h"\
- "..\..\..\srclib\apr\include\apr_strings.h"\
- "..\..\..\srclib\apr\include\apr_tables.h"\
- "..\..\..\srclib\apr\include\apr_thread_proc.h"\
- "..\..\..\srclib\apr\include\apr_time.h"\
- "..\..\..\srclib\apr\include\apr_user.h"\
- "..\..\..\srclib\apr\include\apr_want.h"\
- ".\mod_dav.h"\
-
-NODEP_CPP_UTIL_L=\
- "..\..\..\include\ap_config_auto.h"\
-
-
-"$(INTDIR)\util_lock.obj" : $(SOURCE) $(DEP_CPP_UTIL_L) "$(INTDIR)"
-
-
-!IF "$(CFG)" == "mod_dav - Win32 Release"
-
-"libapr - Win32 Release" :
- cd "..\../..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F .\libapr.mak CFG="libapr - Win32 Release"
- cd "..\..\modules\dav\main"
-
-"libapr - Win32 ReleaseCLEAN" :
- cd "..\../..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libapr.mak CFG="libapr - Win32 Release"\
- RECURSE=1
- cd "..\..\modules\dav\main"
-
-!ELSEIF "$(CFG)" == "mod_dav - Win32 Debug"
-
-"libapr - Win32 Debug" :
- cd "..\../..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F .\libapr.mak CFG="libapr - Win32 Debug"
- cd "..\..\modules\dav\main"
-
-"libapr - Win32 DebugCLEAN" :
- cd "..\../..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libapr.mak CFG="libapr - Win32 Debug"\
- RECURSE=1
- cd "..\..\modules\dav\main"
-
-!ENDIF
-
-!IF "$(CFG)" == "mod_dav - Win32 Release"
-
-"libaprutil - Win32 Release" :
- cd "..\../..\srclib\apr-util"
- $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release"\
-
- cd "..\..\modules\dav\main"
-
-"libaprutil - Win32 ReleaseCLEAN" :
- cd "..\../..\srclib\apr-util"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F ".\libaprutil.mak"\
- CFG="libaprutil - Win32 Release" RECURSE=1
- cd "..\..\modules\dav\main"
-
-!ELSEIF "$(CFG)" == "mod_dav - Win32 Debug"
-
-"libaprutil - Win32 Debug" :
- cd "..\../..\srclib\apr-util"
- $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug"
- cd "..\..\modules\dav\main"
-
-"libaprutil - Win32 DebugCLEAN" :
- cd "..\../..\srclib\apr-util"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F ".\libaprutil.mak"\
- CFG="libaprutil - Win32 Debug" RECURSE=1
- cd "..\..\modules\dav\main"
-
-!ENDIF
-
-!IF "$(CFG)" == "mod_dav - Win32 Release"
-
-"libhttpd - Win32 Release" :
- cd "..\../.."
- $(MAKE) /$(MAKEFLAGS) /F .\libhttpd.mak CFG="libhttpd - Win32 Release"
- cd ".\modules\dav\main"
-
-"libhttpd - Win32 ReleaseCLEAN" :
- cd "..\../.."
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libhttpd.mak CFG="libhttpd - Win32 Release"\
- RECURSE=1
- cd ".\modules\dav\main"
-
-!ELSEIF "$(CFG)" == "mod_dav - Win32 Debug"
-
-"libhttpd - Win32 Debug" :
- cd "..\../.."
- $(MAKE) /$(MAKEFLAGS) /F .\libhttpd.mak CFG="libhttpd - Win32 Debug"
- cd ".\modules\dav\main"
-
-"libhttpd - Win32 DebugCLEAN" :
- cd "..\../.."
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libhttpd.mak CFG="libhttpd - Win32 Debug"\
- RECURSE=1
- cd ".\modules\dav\main"
-
-!ENDIF
-
-
-!ENDIF
-
diff --git a/modules/dav/main/props.c b/modules/dav/main/props.c
deleted file mode 100644
index 2929a9a297..0000000000
--- a/modules/dav/main/props.c
+++ /dev/null
@@ -1,1590 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-/*
-** DAV extension module for Apache 2.0.*
-** - Property database handling (repository-independent)
-**
-** NOTES:
-**
-** PROPERTY DATABASE
-**
-** This version assumes that there is a per-resource database provider
-** to record properties. The database provider decides how and where to
-** store these databases.
-**
-** The DBM keys for the properties have the following form:
-**
-** namespace ":" propname
-**
-** For example: 5:author
-**
-** The namespace provides an integer index into the namespace table
-** (see below). propname is simply the property name, without a namespace
-** prefix.
-**
-** A special case exists for properties that had a prefix starting with
-** "xml". The XML Specification reserves these for future use. mod_dav
-** stores and retrieves them unchanged. The keys for these properties
-** have the form:
-**
-** ":" propname
-**
-** The propname will contain the prefix and the property name. For
-** example, a key might be ":xmlfoo:name"
-**
-** The ":name" style will also be used for properties that do not
-** exist within a namespace.
-**
-** The DBM values consist of two null-terminated strings, appended
-** together (the null-terms are retained and stored in the database).
-** The first string is the xml:lang value for the property. An empty
-** string signifies that a lang value was not in context for the value.
-** The second string is the property value itself.
-**
-**
-** NAMESPACE TABLE
-**
-** The namespace table is an array that lists each of the namespaces
-** that are in use by the properties in the given propdb. Each entry
-** in the array is a simple URI.
-**
-** For example: http://www.foo.bar/standards/props/
-**
-** The prefix used for the property is stripped and the URI for it
-** is entered into the namespace table. Also, any namespaces used
-** within the property value will be entered into the table (and
-** stripped from the child elements).
-**
-** The namespaces are stored in the DBM database under the "METADATA" key.
-**
-**
-** STRIPPING NAMESPACES
-**
-** Within the property values, the namespace declarations (xmlns...)
-** are stripped. Each element and attribute will have its prefix removed
-** and a new prefix inserted.
-**
-** This must be done so that we can return multiple properties in a
-** PROPFIND which may have (originally) used conflicting prefixes. For
-** that case, we must bind all property value elements to new namespace
-** values.
-**
-** This implies that clients must NOT be sensitive to the namespace
-** prefix used for their properties. It WILL change when the properties
-** are returned (we return them as "ns<index>", e.g. "ns5"). Also, the
-** property value can contain ONLY XML elements and CDATA. PI and comment
-** elements will be stripped. CDATA whitespace will be preserved, but
-** whitespace within element tags will be altered. Attribute ordering
-** may be altered. Element and CDATA ordering will be preserved.
-**
-**
-** ATTRIBUTES ON PROPERTY NAME ELEMENTS
-**
-** When getting/setting properties, the XML used looks like:
-**
-** <prop>
-** <propname1>value</propname1>
-** <propname2>value</propname1>
-** </prop>
-**
-** This implementation (mod_dav) DOES NOT save any attributes that are
-** associated with the <propname1> element. The property value is deemed
-** to be only the contents ("value" in the above example).
-**
-** We do store the xml:lang value (if any) that applies to the context
-** of the <propname1> element. Whether the xml:lang attribute is on
-** <propname1> itself, or from a higher level element, we will store it
-** with the property value.
-**
-**
-** VERSIONING
-**
-** The DBM db contains a key named "METADATA" that holds database-level
-** information, such as the namespace table. The record also contains the
-** db's version number as the very first 16-bit value. This first number
-** is actually stored as two single bytes: the first byte is a "major"
-** version number. The second byte is a "minor" number.
-**
-** If the major number is not what mod_dav expects, then the db is closed
-** immediately and an error is returned. A minor number change is
-** acceptable -- it is presumed that old/new dav_props.c can deal with
-** the database format. For example, a newer dav_props might update the
-** minor value and append information to the end of the metadata record
-** (which would be ignored by previous versions).
-**
-**
-** ISSUES:
-**
-** At the moment, for the dav_get_allprops() and dav_get_props() functions,
-** we must return a set of xmlns: declarations for ALL known namespaces
-** in the file. There isn't a way to filter this because we don't know
-** which are going to be used or not. Examining property names is not
-** sufficient because the property values could use entirely different
-** namespaces.
-**
-** ==> we must devise a scheme where we can "garbage collect" the namespace
-** entries from the property database.
-*/
-
-#include "apr.h"
-#include "apr_strings.h"
-
-#define APR_WANT_STDIO
-#define APR_WANT_BYTEFUNC
-#include "apr_want.h"
-
-#include "mod_dav.h"
-
-#include "http_log.h"
-#include "http_request.h"
-
-/*
-** There is some rough support for writable DAV:getcontenttype and
-** DAV:getcontentlanguage properties. If this #define is (1), then
-** this support is disabled.
-**
-** We are disabling it because of a lack of support in GET and PUT
-** operations. For GET, it would be "expensive" to look for a propdb,
-** open it, and attempt to extract the Content-Type and Content-Language
-** values for the response.
-** (Handling the PUT would not be difficult, though)
-*/
-#define DAV_DISABLE_WRITABLE_PROPS 1
-
-#define DAV_GDBM_NS_KEY "METADATA"
-#define DAV_GDBM_NS_KEY_LEN 8
-
-#define DAV_EMPTY_VALUE "\0" /* TWO null terms */
-
-/* the namespace URI was not found; no ID is available */
-#define AP_XML_NS_ERROR_NOT_FOUND (AP_XML_NS_ERROR_BASE)
-
-typedef struct {
- unsigned char major;
-#define DAV_DBVSN_MAJOR 4
- /*
- ** V4 -- 0.9.9 ..
- ** Prior versions could have keys or values with invalid
- ** namespace prefixes as a result of the xmlns="" form not
- ** resetting the default namespace to be "no namespace". The
- ** namespace would be set to "" which is invalid; it should
- ** be set to "no namespace".
- **
- ** V3 -- 0.9.8
- ** Prior versions could have values with invalid namespace
- ** prefixes due to an incorrect mapping of input to propdb
- ** namespace indices. Version bumped to obsolete the old
- ** values.
- **
- ** V2 -- 0.9.7
- ** This introduced the xml:lang value into the property value's
- ** record in the propdb.
- **
- ** V1 -- .. 0.9.6
- ** Initial version.
- */
-
-
- unsigned char minor;
-#define DAV_DBVSN_MINOR 0
-
- short ns_count;
-
-} dav_propdb_metadata;
-
-struct dav_propdb {
- int version; /* *minor* version of this db */
-
- apr_pool_t *p; /* the pool we should use */
- request_rec *r; /* the request record */
-
- const dav_resource *resource; /* the target resource */
-
- int deferred; /* open of db has been deferred */
- dav_db *db; /* underlying database containing props */
-
- dav_buffer ns_table; /* table of namespace URIs */
- short ns_count; /* number of entries in table */
- int ns_table_dirty; /* ns_table was modified */
-
- apr_array_header_t *ns_xlate; /* translation of an elem->ns to URI */
- int *ns_map; /* map elem->ns to propdb ns values */
- int incomplete_map; /* some mappings do not exist */
-
- dav_lockdb *lockdb; /* the lock database */
-
- dav_buffer wb_key; /* work buffer for dav_gdbm_key */
- dav_buffer wb_lock; /* work buffer for lockdiscovery property */
-
- /* if we ever run a GET subreq, it will be stored here */
- request_rec *subreq;
-
- /* hooks we should use for processing (based on the target resource) */
- const dav_hooks_db *db_hooks;
-
-};
-
-/* NOTE: dav_core_props[] and the following enum must stay in sync. */
-/* ### move these into a "core" liveprop provider? */
-static const char * const dav_core_props[] =
-{
- "getcontenttype",
- "getcontentlanguage",
- "lockdiscovery",
- "supportedlock",
-
- NULL /* sentinel */
-};
-enum {
- DAV_PROPID_CORE_getcontenttype = DAV_PROPID_CORE,
- DAV_PROPID_CORE_getcontentlanguage,
- DAV_PROPID_CORE_lockdiscovery,
- DAV_PROPID_CORE_supportedlock,
-
- DAV_PROPID_CORE_UNKNOWN
-};
-
-/*
-** This structure is used to track information needed for a rollback.
-** If a SET was performed and no prior value existed, then value.dptr
-** will be NULL.
-*/
-typedef struct dav_rollback_item {
- dav_datum key; /* key for the item being saved */
- dav_datum value; /* value before set/replace/delete */
-
- /* or use the following (choice selected by dav_prop_ctx.is_liveprop) */
- struct dav_liveprop_rollback *liveprop; /* liveprop rollback ctx */
-
-} dav_rollback_item;
-
-
-#if 0
-/* ### unused */
-static const char *dav_get_ns_table_uri(dav_propdb *propdb, int ns)
-{
- const char *p = propdb->ns_table.buf + sizeof(dav_propdb_metadata);
-
- while (ns--)
- p += strlen(p) + 1;
-
- return p;
-}
-#endif
-
-static int dav_find_liveprop_provider(dav_propdb *propdb,
- const char *ns_uri,
- const char *propname,
- const dav_hooks_liveprop **provider)
-{
- int propid;
-
- *provider = NULL;
-
- if (ns_uri == NULL) {
- /* policy: liveprop providers cannot define no-namespace properties */
- return DAV_PROPID_CORE_UNKNOWN;
- }
-
- /* check liveprop providers first, so they can define core properties */
- propid = dav_run_find_liveprop(propdb->resource, ns_uri, propname,
- provider);
- if (propid != 0) {
- return propid;
- }
-
- /* check for core property */
- if (strcmp(ns_uri, "DAV:") == 0) {
- const char * const *p = dav_core_props;
-
- for (propid = DAV_PROPID_CORE; *p != NULL; ++p, ++propid)
- if (strcmp(propname, *p) == 0) {
- return propid;
- }
- }
-
- /* no provider for this property */
- return DAV_PROPID_CORE_UNKNOWN;
-}
-
-static void dav_find_liveprop(dav_propdb *propdb, ap_xml_elem *elem)
-{
- const char *ns_uri;
- dav_elem_private *priv = elem->private;
- const dav_hooks_liveprop *hooks;
-
-
- if (elem->ns == AP_XML_NS_NONE)
- ns_uri = NULL;
- else if (elem->ns == AP_XML_NS_DAV_ID)
- ns_uri = "DAV:";
- else
- ns_uri = AP_XML_GET_URI_ITEM(propdb->ns_xlate, elem->ns);
-
- priv->propid = dav_find_liveprop_provider(propdb, ns_uri, elem->name,
- &hooks);
-
- /* ### this test seems redundant... */
- if (priv->propid != DAV_PROPID_CORE_UNKNOWN) {
- priv->provider = hooks;
- }
-}
-
-/* is the live property read/write? */
-static int dav_rw_liveprop(dav_propdb *propdb, dav_elem_private *priv)
-{
- int propid = priv->propid;
-
- /*
- ** Check the liveprop provider (if this is a provider-defined prop)
- */
- if (priv->provider != NULL) {
- return (*priv->provider->is_writable)(propdb->resource, propid);
- }
-
- /* these are defined as read-only */
- if (propid == DAV_PROPID_CORE_lockdiscovery
-#if DAV_DISABLE_WRITABLE_PROPS
- || propid == DAV_PROPID_CORE_getcontenttype
- || propid == DAV_PROPID_CORE_getcontentlanguage
-#endif
- || propid == DAV_PROPID_CORE_supportedlock
- ) {
-
- return 0;
- }
-
- /* these are defined as read/write */
- if (propid == DAV_PROPID_CORE_getcontenttype
- || propid == DAV_PROPID_CORE_getcontentlanguage
- || propid == DAV_PROPID_CORE_UNKNOWN) {
-
- return 1;
- }
-
- /*
- ** We don't recognize the property, so it must be dead (and writable)
- */
- return 1;
-}
-
-/* do a sub-request to fetch properties for the target resource's URI. */
-static void dav_do_prop_subreq(dav_propdb *propdb)
-{
- /* perform a "GET" on the resource's URI (note that the resource
- may not correspond to the current request!). */
- propdb->subreq = ap_sub_req_lookup_uri(propdb->resource->uri, propdb->r,
- NULL);
-}
-
-static dav_error * dav_insert_coreprop(dav_propdb *propdb,
- int propid, const char *name,
- dav_prop_insert what,
- ap_text_header *phdr,
- dav_prop_insert *inserted)
-{
- const char *value = NULL;
- dav_error *err;
-
- *inserted = DAV_PROP_INSERT_NOTDEF;
-
- /* fast-path the common case */
- if (propid == DAV_PROPID_CORE_UNKNOWN)
- return NULL;
-
- switch (propid) {
-
- case DAV_PROPID_CORE_lockdiscovery:
- if (propdb->lockdb != NULL) {
- dav_lock *locks;
-
- if ((err = dav_lock_query(propdb->lockdb, propdb->resource,
- &locks)) != NULL) {
- return dav_push_error(propdb->p, err->status, 0,
- "DAV:lockdiscovery could not be "
- "determined due to a problem fetching "
- "the locks for this resource.",
- err);
- }
-
- /* fast-path the no-locks case */
- if (locks == NULL) {
- value = "";
- }
- else {
- /*
- ** This may modify the buffer. value may point to
- ** wb_lock.pbuf or a string constant.
- */
- value = dav_lock_get_activelock(propdb->r, locks,
- &propdb->wb_lock);
-
- /* make a copy to isolate it from changes to wb_lock */
- value = apr_pstrdup(propdb->p, propdb->wb_lock.buf);
- }
- }
- break;
-
- case DAV_PROPID_CORE_supportedlock:
- if (propdb->lockdb != NULL) {
- value = (*propdb->lockdb->hooks->get_supportedlock)(propdb->resource);
- }
- break;
-
- case DAV_PROPID_CORE_getcontenttype:
- if (propdb->subreq == NULL) {
- dav_do_prop_subreq(propdb);
- }
- if (propdb->subreq->content_type != NULL) {
- value = propdb->subreq->content_type;
- }
- break;
-
- case DAV_PROPID_CORE_getcontentlanguage:
- {
- const char *lang;
-
- if (propdb->subreq == NULL) {
- dav_do_prop_subreq(propdb);
- }
- if ((lang = apr_table_get(propdb->subreq->headers_out,
- "Content-Language")) != NULL) {
- value = lang;
- }
- break;
- }
-
- default:
- /* fall through to interpret as a dead property */
- break;
- }
-
- /* if something was supplied, then insert it */
- if (value != NULL) {
- const char *s;
-
- if (what == DAV_PROP_INSERT_SUPPORTED) {
- /* use D: prefix to refer to the DAV: namespace URI,
- * and let the namespace attribute default to "DAV:"
- */
- s = apr_psprintf(propdb->p,
- "<D:supported-live-property D:name=\"%s\"/>" DEBUG_CR,
- name);
- }
- else if (what == DAV_PROP_INSERT_VALUE && *value != '\0') {
- /* use D: prefix to refer to the DAV: namespace URI */
- s = apr_psprintf(propdb->p, "<D:%s>%s</D:%s>" DEBUG_CR,
- name, value, name);
- }
- else {
- /* use D: prefix to refer to the DAV: namespace URI */
- s = apr_psprintf(propdb->p, "<D:%s/>" DEBUG_CR, name);
- }
- ap_text_append(propdb->p, phdr, s);
-
- *inserted = what;
- }
-
- return NULL;
-}
-
-static dav_error * dav_insert_liveprop(dav_propdb *propdb,
- const ap_xml_elem *elem,
- dav_prop_insert what,
- ap_text_header *phdr,
- dav_prop_insert *inserted)
-{
- dav_elem_private *priv = elem->private;
-
- *inserted = DAV_PROP_INSERT_NOTDEF;
-
- if (priv->provider == NULL) {
- /* this is a "core" property that we define */
- return dav_insert_coreprop(propdb, priv->propid, elem->name,
- what, phdr, inserted);
- }
-
- /* ask the provider (that defined this prop) to insert the prop */
- *inserted = (*priv->provider->insert_prop)(propdb->resource, priv->propid,
- what, phdr);
-
- return NULL;
-}
-
-static void dav_append_prop(dav_propdb *propdb,
- const char *name, const char *value,
- ap_text_header *phdr)
-{
- const char *s;
- const char *lang = value;
-
- /* skip past the xml:lang value */
- value += strlen(lang) + 1;
-
- if (*value == '\0') {
- /* the property is an empty value */
- if (*name == ':') {
- /* "no namespace" case */
- s = apr_psprintf(propdb->p, "<%s/>" DEBUG_CR, name+1);
- }
- else {
- s = apr_psprintf(propdb->p, "<ns%s/>" DEBUG_CR, name);
- }
- }
- else if (*lang != '\0') {
- if (*name == ':') {
- /* "no namespace" case */
- s = apr_psprintf(propdb->p, "<%s xml:lang=\"%s\">%s</%s>" DEBUG_CR,
- name+1, lang, value, name+1);
- }
- else {
- s = apr_psprintf(propdb->p, "<ns%s xml:lang=\"%s\">%s</ns%s>" DEBUG_CR,
- name, lang, value, name);
- }
- }
- else if (*name == ':') {
- /* "no namespace" case */
- s = apr_psprintf(propdb->p, "<%s>%s</%s>" DEBUG_CR, name+1, value, name+1);
- }
- else {
- s = apr_psprintf(propdb->p, "<ns%s>%s</ns%s>" DEBUG_CR, name, value, name);
- }
- ap_text_append(propdb->p, phdr, s);
-}
-
-/*
-** Prepare the ns_map variable in the propdb structure. This entails copying
-** all URIs from the "input" namespace list (in propdb->ns_xlate) into the
-** propdb's list of namespaces. As each URI is copied (or pre-existing
-** URI looked up), the index mapping is stored into the ns_map variable.
-**
-** Note: we must copy all declared namespaces because we cannot easily
-** determine which input namespaces were actually used within the property
-** values that are being stored within the propdb. Theoretically, we can
-** determine this at the point where we serialize the property values
-** back into strings. This would require a bit more work, and will be
-** left to future optimizations.
-**
-** ### we should always initialize the propdb namespace array with "DAV:"
-** ### since we know it will be entered anyhow (by virtue of it always
-** ### occurring in the ns_xlate array). That will allow us to use
-** ### AP_XML_NS_DAV_ID for propdb ns values, too.
-*/
-static void dav_prep_ns_map(dav_propdb *propdb, int add_ns)
-{
- int i;
- const char **puri;
- const int orig_count = propdb->ns_count;
- int *pmap;
- int updating = 0; /* are we updating an existing ns_map? */
-
- if (propdb->ns_map) {
- if (add_ns && propdb->incomplete_map) {
- /* we must revisit the map and insert new entries */
- updating = 1;
- propdb->incomplete_map = 0;
- }
- else {
- /* nothing to do: we have a proper ns_map */
- return;
- }
- }
- else {
- propdb->ns_map = apr_palloc(propdb->p, propdb->ns_xlate->nelts * sizeof(*propdb->ns_map));
- }
-
- pmap = propdb->ns_map;
-
- /* ### stupid O(n * orig_count) algorithm */
- for (i = propdb->ns_xlate->nelts, puri = (const char **)propdb->ns_xlate->elts;
- i-- > 0;
- ++puri, ++pmap) {
-
- const char *uri = *puri;
- const size_t uri_len = strlen(uri);
-
- if (updating) {
- /* updating an existing mapping... we can skip a lot of stuff */
-
- if (*pmap != AP_XML_NS_ERROR_NOT_FOUND) {
- /* This entry has been filled in, so we can skip it */
- continue;
- }
- }
- else {
- int j;
- size_t len;
- const char *p;
-
- /*
- ** GIVEN: uri (a namespace URI from the request input)
- **
- ** FIND: an equivalent URI in the propdb namespace table
- */
-
- /* only scan original entries (we may have added some in here) */
- for (p = propdb->ns_table.buf + sizeof(dav_propdb_metadata),
- j = 0;
- j < orig_count;
- ++j, p += len + 1) {
-
- len = strlen(p);
-
- if (uri_len != len)
- continue;
- if (memcmp(uri, p, len) == 0) {
- *pmap = j;
- goto next_input_uri;
- }
- }
-
- if (!add_ns) {
- *pmap = AP_XML_NS_ERROR_NOT_FOUND;
-
- /*
- ** This flag indicates that we have an ns_map with missing
- ** entries. If dav_prep_ns_map() is called with add_ns==1 AND
- ** this flag is set, then we zip thru the array and add those
- ** URIs (effectively updating the ns_map as if add_ns=1 was
- ** passed when the initial prep was called).
- */
- propdb->incomplete_map = 1;
-
- continue;
- }
- }
-
- /*
- ** The input URI was not found in the propdb namespace table, and
- ** we are supposed to add it. Append it to the table and store
- ** the index into the ns_map.
- */
- dav_check_bufsize(propdb->p, &propdb->ns_table, uri_len + 1);
- memcpy(propdb->ns_table.buf + propdb->ns_table.cur_len, uri, uri_len + 1);
- propdb->ns_table.cur_len += uri_len + 1;
-
- propdb->ns_table_dirty = 1;
-
- *pmap = propdb->ns_count++;
-
- next_input_uri:
- ;
- }
-}
-
-/* find the "DAV:" namespace in our table and return its ID. */
-static int dav_find_dav_id(dav_propdb *propdb)
-{
- const char *p = propdb->ns_table.buf + sizeof(dav_propdb_metadata);
- int ns;
-
- for (ns = 0; ns < propdb->ns_count; ++ns) {
- size_t len = strlen(p);
-
- if (len == 4 && memcmp(p, "DAV:", 5) == 0)
- return ns;
- p += len + 1;
- }
-
- /* the "DAV:" namespace is not present */
- return -1;
-}
-
-static void dav_insert_xmlns(apr_pool_t *p, const char *pre_prefix, int ns,
- const char *ns_uri, ap_text_header *phdr)
-{
- const char *s;
-
- s = apr_psprintf(p, " xmlns:%s%d=\"%s\"", pre_prefix, ns, ns_uri);
- ap_text_append(p, phdr, s);
-}
-
-/* return all known namespaces (in this propdb) */
-static void dav_get_propdb_xmlns(dav_propdb *propdb, ap_text_header *phdr)
-{
- int i;
- const char *p = propdb->ns_table.buf + sizeof(dav_propdb_metadata);
- size_t len;
-
- /* note: ns_count == 0 when we have no propdb file */
- for (i = 0; i < propdb->ns_count; ++i, p += len + 1) {
-
- len = strlen(p);
-
- dav_insert_xmlns(propdb->p, "ns", i, p, phdr);
- }
-}
-
-/* add a namespace decl from one of the namespace tables */
-static void dav_add_marked_xmlns(dav_propdb *propdb, char *marks, int ns,
- apr_array_header_t *ns_table,
- const char *pre_prefix,
- ap_text_header *phdr)
-{
- if (marks[ns])
- return;
- marks[ns] = 1;
-
- dav_insert_xmlns(propdb->p,
- pre_prefix, ns, AP_XML_GET_URI_ITEM(ns_table, ns),
- phdr);
-}
-
-/*
-** Internal function to build a key
-**
-** WARNING: returns a pointer to a "static" buffer holding the key. The
-** value must be copied or no longer used if this function is
-** called again.
-*/
-static dav_datum dav_gdbm_key(dav_propdb *propdb, const ap_xml_elem *elem)
-{
- int ns;
- char nsbuf[20];
- size_t l_ns;
- size_t l_name = strlen(elem->name);
- dav_datum key = { 0 };
-
- /*
- * Convert namespace ID to a string. "no namespace" is an empty string,
- * so the keys will have the form ":name". Otherwise, the keys will
- * have the form "#:name".
- */
- if (elem->ns == AP_XML_NS_NONE) {
- nsbuf[0] = '\0';
- l_ns = 0;
- }
- else {
- if (propdb->ns_map == NULL) {
- /*
- * Note that we prep the map and do NOT add namespaces. If that
- * is required, then the caller should have called prep
- * beforehand, passing the correct values.
- */
- dav_prep_ns_map(propdb, 0);
- }
-
- ns = propdb->ns_map[elem->ns];
- if (AP_XML_NS_IS_ERROR(ns))
- return key; /* zeroed */
-
- l_ns = sprintf(nsbuf, "%d", ns);
- }
-
- /* assemble: #:name */
- dav_set_bufsize(propdb->p, &propdb->wb_key, l_ns + 1 + l_name + 1);
- memcpy(propdb->wb_key.buf, nsbuf, l_ns);
- propdb->wb_key.buf[l_ns] = ':';
- memcpy(&propdb->wb_key.buf[l_ns + 1], elem->name, l_name + 1);
-
- /* build the database key */
- key.dsize = l_ns + 1 + l_name + 1;
- key.dptr = propdb->wb_key.buf;
-
- return key;
-}
-
-static dav_error *dav_really_open_db(dav_propdb *propdb, int ro)
-{
- dav_error *err;
- dav_datum key;
- dav_datum value = { 0 };
-
- /* we're trying to open the db; turn off the 'deferred' flag */
- propdb->deferred = 0;
-
- /* ask the DB provider to open the thing */
- err = (*propdb->db_hooks->open)(propdb->p, propdb->resource, ro,
- &propdb->db);
- if (err != NULL) {
- return dav_push_error(propdb->p, HTTP_INTERNAL_SERVER_ERROR,
- DAV_ERR_PROP_OPENING,
- "Could not open the property database.",
- err);
- }
-
- /*
- ** NOTE: propdb->db could be NULL if we attempted to open a readonly
- ** database that doesn't exist. If we require read/write
- ** access, then a database was created and opened.
- */
-
- if (propdb->db != NULL) {
- key.dptr = DAV_GDBM_NS_KEY;
- key.dsize = DAV_GDBM_NS_KEY_LEN;
- if ((err = (*propdb->db_hooks->fetch)(propdb->db, key,
- &value)) != NULL) {
- /* ### push a higher-level description? */
- return err;
- }
- }
- if (value.dptr == NULL) {
- dav_propdb_metadata m = {
- DAV_DBVSN_MAJOR, DAV_DBVSN_MINOR, 0
- };
-
- if (propdb->db != NULL) {
- /*
- * If there is no METADATA key, then the database may be
- * from versions 0.9.0 .. 0.9.4 (which would be incompatible).
- * These can be identified by the presence of an NS_TABLE entry.
- */
- key.dptr = "NS_TABLE";
- key.dsize = 8;
- if ((*propdb->db_hooks->exists)(propdb->db, key)) {
- (*propdb->db_hooks->close)(propdb->db);
-
- /* call it a major version error */
- return dav_new_error(propdb->p, HTTP_INTERNAL_SERVER_ERROR,
- DAV_ERR_PROP_BAD_MAJOR,
- "Prop database has the wrong major "
- "version number and cannot be used.");
- }
- }
-
- /* initialize a new metadata structure */
- dav_set_bufsize(propdb->p, &propdb->ns_table, sizeof(m));
- memcpy(propdb->ns_table.buf, &m, sizeof(m));
- }
- else {
- dav_propdb_metadata m;
-
- dav_set_bufsize(propdb->p, &propdb->ns_table, value.dsize);
- memcpy(propdb->ns_table.buf, value.dptr, value.dsize);
-
- memcpy(&m, value.dptr, sizeof(m));
- if (m.major != DAV_DBVSN_MAJOR) {
- (*propdb->db_hooks->close)(propdb->db);
-
- return dav_new_error(propdb->p, HTTP_INTERNAL_SERVER_ERROR,
- DAV_ERR_PROP_BAD_MAJOR,
- "Prop database has the wrong major "
- "version number and cannot be used.");
- }
- propdb->version = m.minor;
- propdb->ns_count = ntohs(m.ns_count);
-
- (*propdb->db_hooks->freedatum)(propdb->db, value);
- }
-
- return NULL;
-}
-
-dav_error *dav_open_propdb(request_rec *r, dav_lockdb *lockdb,
- const dav_resource *resource,
- int ro,
- apr_array_header_t * ns_xlate,
- dav_propdb **p_propdb)
-{
- dav_propdb *propdb = apr_pcalloc(r->pool, sizeof(*propdb));
-
- *p_propdb = NULL;
-
-#if DAV_DEBUG
- if (resource->uri == NULL) {
- return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
- "INTERNAL DESIGN ERROR: resource must define "
- "its URI.");
- }
-#endif
-
- propdb->version = DAV_DBVSN_MINOR;
- propdb->r = r;
- propdb->p = r->pool; /* ### get rid of this */
- propdb->resource = resource;
- propdb->ns_xlate = ns_xlate;
-
- propdb->db_hooks = DAV_GET_HOOKS_PROPDB(r);
-
- propdb->lockdb = lockdb;
-
- /* always defer actual open, to avoid expense of accessing db
- * when only live properties are involved
- */
- propdb->deferred = 1;
-
- /* ### what to do about closing the propdb on server failure? */
-
- *p_propdb = propdb;
- return NULL;
-}
-
-void dav_close_propdb(dav_propdb *propdb)
-{
- if (propdb->db == NULL)
- return;
-
- if (propdb->ns_table_dirty) {
- dav_propdb_metadata m;
- dav_datum key;
- dav_datum value;
- dav_error *err;
-
- key.dptr = DAV_GDBM_NS_KEY;
- key.dsize = DAV_GDBM_NS_KEY_LEN;
-
- value.dptr = propdb->ns_table.buf;
- value.dsize = propdb->ns_table.cur_len;
-
- /* fill in the metadata that we store into the prop db. */
- m.major = DAV_DBVSN_MAJOR;
- m.minor = propdb->version; /* ### keep current minor version? */
- m.ns_count = htons(propdb->ns_count);
-
- memcpy(propdb->ns_table.buf, &m, sizeof(m));
-
- err = (*propdb->db_hooks->store)(propdb->db, key, value);
- /* ### what to do with the error? */
- }
-
- (*propdb->db_hooks->close)(propdb->db);
-}
-
-dav_get_props_result dav_get_allprops(dav_propdb *propdb, dav_prop_insert what)
-{
- const dav_hooks_db *db_hooks = propdb->db_hooks;
- ap_text_header hdr = { 0 };
- ap_text_header hdr_ns = { 0 };
- dav_get_props_result result = { 0 };
- int found_contenttype = 0;
- int found_contentlang = 0;
- dav_prop_insert unused_inserted;
-
- /* if not just getting supported live properties,
- * scan all properties in the dead prop database
- */
- if (what != DAV_PROP_INSERT_SUPPORTED) {
- if (propdb->deferred) {
- /* ### what to do with db open error? */
- (void) dav_really_open_db(propdb, 1 /*ro*/);
- }
-
- /* generate all the namespaces that are in the propdb */
- dav_get_propdb_xmlns(propdb, &hdr_ns);
-
- /* initialize the result with some start tags... */
- ap_text_append(propdb->p, &hdr,
- "<D:propstat>" DEBUG_CR
- "<D:prop>" DEBUG_CR);
-
- /* if there ARE properties, then scan them */
- if (propdb->db != NULL) {
- dav_datum key;
- int dav_id = dav_find_dav_id(propdb);
-
- (void) (*db_hooks->firstkey)(propdb->db, &key);
- while (key.dptr) {
- dav_datum prevkey;
-
- /* any keys with leading capital letters should be skipped
- (real keys start with a number or a colon) */
- if (*key.dptr >= 'A' && *key.dptr <= 'Z')
- goto next_key;
-
- /*
- ** We also look for <DAV:getcontenttype> and
- ** <DAV:getcontentlanguage>. If they are not stored as dead
- ** properties, then we need to perform a subrequest to get
- ** their values (if any).
- */
- if (dav_id != -1
- && *key.dptr != ':'
- && dav_id == atoi(key.dptr)) {
-
- const char *colon;
-
- /* find the colon */
- if ( key.dptr[1] == ':' ) {
- colon = key.dptr + 1;
- }
- else {
- colon = strchr(key.dptr + 2, ':');
- }
-
- if (colon[1] == 'g') {
- if (strcmp(colon + 1, "getcontenttype") == 0) {
- found_contenttype = 1;
- }
- else if (strcmp(colon + 1, "getcontentlanguage") == 0) {
- found_contentlang = 1;
- }
- }
- }
-
- if (what == DAV_PROP_INSERT_VALUE) {
- dav_datum value;
-
- (void) (*db_hooks->fetch)(propdb->db, key, &value);
- if (value.dptr == NULL) {
- /* ### anything better to do? */
- /* ### probably should enter a 500 error */
- goto next_key;
- }
-
- /* put the prop name and value into the result */
- dav_append_prop(propdb, key.dptr, value.dptr, &hdr);
-
- (*db_hooks->freedatum)(propdb->db, value);
- }
- else {
- /* simple, empty element if a value isn't needed */
- dav_append_prop(propdb, key.dptr, DAV_EMPTY_VALUE, &hdr);
- }
-
- next_key:
- prevkey = key;
- (void) (*db_hooks->nextkey)(propdb->db, &key);
- (*db_hooks->freedatum)(propdb->db, prevkey);
- }
- }
-
- /* add namespaces for all the liveprop providers */
- dav_add_all_liveprop_xmlns(propdb->p, &hdr_ns);
- }
-
- /* ask the liveprop providers to insert their properties */
- dav_run_insert_all_liveprops(propdb->r, propdb->resource, what, &hdr);
-
- /* insert the standard properties */
- /* ### should be handling the return errors here */
- (void)dav_insert_coreprop(propdb,
- DAV_PROPID_CORE_supportedlock, "supportedlock",
- what, &hdr, &unused_inserted);
- (void)dav_insert_coreprop(propdb,
- DAV_PROPID_CORE_lockdiscovery, "lockdiscovery",
- what, &hdr, &unused_inserted);
-
- /* if we didn't find these, then do the whole subreq thing. */
- if (!found_contenttype) {
- /* ### should be handling the return error here */
- (void)dav_insert_coreprop(propdb,
- DAV_PROPID_CORE_getcontenttype,
- "getcontenttype",
- what, &hdr, &unused_inserted);
- }
- if (!found_contentlang) {
- /* ### should be handling the return error here */
- (void)dav_insert_coreprop(propdb,
- DAV_PROPID_CORE_getcontentlanguage,
- "getcontentlanguage",
- what, &hdr, &unused_inserted);
- }
-
- /* if not just reporting on supported live props,
- * terminate the result */
- if (what != DAV_PROP_INSERT_SUPPORTED) {
- ap_text_append(propdb->p, &hdr,
- "</D:prop>" DEBUG_CR
- "<D:status>HTTP/1.1 200 OK</D:status>" DEBUG_CR
- "</D:propstat>" DEBUG_CR);
- }
-
- result.propstats = hdr.first;
- result.xmlns = hdr_ns.first;
- return result;
-}
-
-dav_get_props_result dav_get_props(dav_propdb *propdb, ap_xml_doc *doc)
-{
- const dav_hooks_db *db_hooks = propdb->db_hooks;
- ap_xml_elem *elem = dav_find_child(doc->root, "prop");
- ap_text_header hdr_good = { 0 };
- ap_text_header hdr_bad = { 0 };
- ap_text_header hdr_ns = { 0 };
- int have_good = 0;
- int propdb_xmlns_done = 0;
- dav_get_props_result result = { 0 };
- char *marks_input;
- char *marks_liveprop;
-
- /* ### NOTE: we should pass in TWO buffers -- one for keys, one for
- the marks */
-
- /* we will ALWAYS provide a "good" result, even if it is EMPTY */
- ap_text_append(propdb->p, &hdr_good,
- "<D:propstat>" DEBUG_CR
- "<D:prop>" DEBUG_CR);
-
- /* ### the marks should be in a buffer! */
- /* allocate zeroed-memory for the marks. These marks indicate which
- input namespaces we've generated into the output xmlns buffer */
- marks_input = apr_pcalloc(propdb->p, propdb->ns_xlate->nelts);
-
- /* same for the liveprops */
- marks_liveprop = apr_pcalloc(propdb->p, dav_get_liveprop_ns_count() + 1);
-
- for (elem = elem->first_child; elem; elem = elem->next) {
- dav_datum key = { 0 };
- dav_datum value = { 0 };
- dav_elem_private *priv;
- dav_error *err;
- dav_prop_insert inserted;
- int is_liveprop = 0;
-
- /*
- ** First try live property providers; if they don't handle
- ** the property, then try looking it up in the propdb.
- */
-
- if (elem->private == NULL) {
- elem->private = apr_pcalloc(propdb->p, sizeof(*priv));
- }
- priv = elem->private;
-
- /* cache the propid; dav_get_props() could be called many times */
- if (priv->propid == 0)
- dav_find_liveprop(propdb, elem);
-
- if (priv->propid != DAV_PROPID_CORE_UNKNOWN) {
- is_liveprop = 1;
-
- /* insert the property. returns 1 if an insertion was done. */
- if ((err = dav_insert_liveprop(propdb, elem, DAV_PROP_INSERT_VALUE,
- &hdr_good, &inserted)) != NULL) {
- /* ### need to propagate the error to the caller... */
- /* ### skip it for now, as if nothing was inserted */
- }
- if (inserted == DAV_PROP_INSERT_VALUE) {
- have_good = 1;
-
- /*
- ** Add the liveprop's namespace URIs. Note that provider==NULL
- ** for core properties.
- */
- if (priv->provider != NULL) {
- const char * const * scan_ns_uri;
-
- for (scan_ns_uri = priv->provider->namespace_uris;
- *scan_ns_uri != NULL;
- ++scan_ns_uri) {
- int ns;
-
- ns = dav_get_liveprop_ns_index(*scan_ns_uri);
- if (marks_liveprop[ns])
- continue;
- marks_liveprop[ns] = 1;
-
- dav_insert_xmlns(propdb->p, "lp", ns, *scan_ns_uri,
- &hdr_ns);
- }
- }
-
- continue;
- }
- else if (inserted == DAV_PROP_INSERT_NOTDEF) {
- /* allow property to be handled as a dead property */
- is_liveprop = 0;
- }
- }
-
- /*
- ** If not handled as a live property, look in the dead property
- ** database.
- */
- if (!is_liveprop) {
- /* make sure propdb is really open */
- if (propdb->deferred) {
- /* ### what to do with db open error? */
- (void) dav_really_open_db(propdb, 1 /*ro*/);
- }
-
- /* if not done yet,
- * generate all the namespaces that are in the propdb
- */
- if (!propdb_xmlns_done) {
- dav_get_propdb_xmlns(propdb, &hdr_ns);
- propdb_xmlns_done = 1;
- }
-
- /*
- ** Note: the key may be NULL if we have no properties that are in
- ** a namespace that matches the requested prop's namespace.
- */
- key = dav_gdbm_key(propdb, elem);
-
- /* fetch IF we have a db and a key. otherwise, value is NULL */
- if (propdb->db != NULL && key.dptr != NULL) {
- (void) (*db_hooks->fetch)(propdb->db, key, &value);
- }
- }
-
- if (value.dptr == NULL) {
- /* not found. add a record to the "bad" propstats */
-
- /* make sure we've started our "bad" propstat */
- if (hdr_bad.first == NULL) {
- ap_text_append(propdb->p, &hdr_bad,
- "<D:propstat>" DEBUG_CR
- "<D:prop>" DEBUG_CR);
- }
-
- /* note: key.dptr may be NULL if the propdb doesn't have an
- equivalent namespace stored */
- if (key.dptr == NULL) {
- const char *s;
-
- if (elem->ns == AP_XML_NS_NONE) {
- /*
- * elem has a prefix already (xml...:name) or the elem
- * simply has no namespace.
- */
- s = apr_psprintf(propdb->p, "<%s/>" DEBUG_CR, elem->name);
- }
- else {
- /* ensure that an xmlns is generated for the
- input namespace */
- dav_add_marked_xmlns(propdb, marks_input, elem->ns,
- propdb->ns_xlate, "i", &hdr_ns);
- s = apr_psprintf(propdb->p, "<i%d:%s/>" DEBUG_CR,
- elem->ns, elem->name);
- }
- ap_text_append(propdb->p, &hdr_bad, s);
- }
- else {
- /* add in the bad prop using our namespace decl */
- dav_append_prop(propdb, key.dptr, DAV_EMPTY_VALUE, &hdr_bad);
- }
- }
- else {
- /* found it. put the value into the "good" propstats */
-
- have_good = 1;
-
- dav_append_prop(propdb, key.dptr, value.dptr, &hdr_good);
-
- (*db_hooks->freedatum)(propdb->db, value);
- }
- }
-
- ap_text_append(propdb->p, &hdr_good,
- "</D:prop>" DEBUG_CR
- "<D:status>HTTP/1.1 200 OK</D:status>" DEBUG_CR
- "</D:propstat>" DEBUG_CR);
-
- /* default to start with the good */
- result.propstats = hdr_good.first;
-
- /* we may not have any "bad" results */
- if (hdr_bad.first != NULL) {
- ap_text_append(propdb->p, &hdr_bad,
- "</D:prop>" DEBUG_CR
- "<D:status>HTTP/1.1 404 Not Found</D:status>" DEBUG_CR
- "</D:propstat>" DEBUG_CR);
-
- /* if there are no good props, then just return the bad */
- if (!have_good) {
- result.propstats = hdr_bad.first;
- }
- else {
- /* hook the bad propstat to the end of the good one */
- hdr_good.last->next = hdr_bad.first;
- }
- }
-
- result.xmlns = hdr_ns.first;
- return result;
-}
-
-void dav_get_liveprop_supported(dav_propdb *propdb,
- const char *ns_uri,
- const char *propname,
- ap_text_header *body)
-{
- int propid;
- const dav_hooks_liveprop *hooks;
-
- propid = dav_find_liveprop_provider(propdb, ns_uri, propname, &hooks);
-
- if (propid != DAV_PROPID_CORE_UNKNOWN) {
- if (hooks == NULL) {
- /* this is a "core" property that we define */
- dav_prop_insert unused_inserted;
- dav_insert_coreprop(propdb, propid, propname,
- DAV_PROP_INSERT_SUPPORTED, body, &unused_inserted);
- }
- else {
- (*hooks->insert_prop)(propdb->resource, propid,
- DAV_PROP_INSERT_SUPPORTED, body);
- }
- }
-}
-
-void dav_prop_validate(dav_prop_ctx *ctx)
-{
- dav_propdb *propdb = ctx->propdb;
- ap_xml_elem *prop = ctx->prop;
- dav_elem_private *priv;
-
- priv = ctx->prop->private = apr_pcalloc(propdb->p, sizeof(*priv));
-
- /*
- ** Check to see if this is a live property, and fill the fields
- ** in the XML elem, as appropriate.
- **
- ** Verify that the property is read/write. If not, then it cannot
- ** be SET or DELETEd.
- */
- if (priv->propid == 0) {
- dav_find_liveprop(propdb, prop);
-
- /* it's a liveprop if a provider was found */
- /* ### actually the "core" props should really be liveprops, but
- ### there is no "provider" for those and the r/w props are
- ### treated as dead props anyhow */
- ctx->is_liveprop = priv->provider != NULL;
- }
-
- if (!dav_rw_liveprop(propdb, priv)) {
- ctx->err = dav_new_error(propdb->p, HTTP_CONFLICT,
- DAV_ERR_PROP_READONLY,
- "Property is read-only.");
- return;
- }
-
- if (ctx->is_liveprop) {
- int defer_to_dead = 0;
-
- ctx->err = (*priv->provider->patch_validate)(propdb->resource,
- prop, ctx->operation,
- &ctx->liveprop_ctx,
- &defer_to_dead);
- if (ctx->err != NULL || !defer_to_dead)
- return;
-
- /* clear is_liveprop -- act as a dead prop now */
- ctx->is_liveprop = 0;
- }
-
- /*
- ** The property is supposed to be stored into the dead-property
- ** database. Make sure the thing is truly open (and writable).
- */
- if (propdb->deferred
- && (ctx->err = dav_really_open_db(propdb, 0 /* ro */)) != NULL) {
- return;
- }
-
- /*
- ** There should be an open, writable database in here!
- **
- ** Note: the database would be NULL if it was opened readonly and it
- ** did not exist.
- */
- if (propdb->db == NULL) {
- ctx->err = dav_new_error(propdb->p, HTTP_INTERNAL_SERVER_ERROR,
- DAV_ERR_PROP_NO_DATABASE,
- "Attempted to set/remove a property "
- "without a valid, open, read/write "
- "property database.");
- return;
- }
-
- if (ctx->operation == DAV_PROP_OP_SET) {
- /*
- ** Prep the element => propdb namespace index mapping, inserting
- ** namespace URIs into the propdb that don't exist.
- */
- dav_prep_ns_map(propdb, 1);
- }
- else if (ctx->operation == DAV_PROP_OP_DELETE) {
- /*
- ** There are no checks to perform here. If a property exists, then
- ** we will delete it. If it does not exist, then it does not matter
- ** (see S12.13.1).
- **
- ** Note that if a property does not exist, that does not rule out
- ** that a SET will occur during this PROPPATCH (thusly creating it).
- */
- }
-}
-
-void dav_prop_exec(dav_prop_ctx *ctx)
-{
- dav_propdb *propdb = ctx->propdb;
- dav_error *err = NULL;
- dav_rollback_item *rollback;
- dav_elem_private *priv = ctx->prop->private;
-
- rollback = apr_pcalloc(propdb->p, sizeof(*rollback));
- ctx->rollback = rollback;
-
- if (ctx->is_liveprop) {
- err = (*priv->provider->patch_exec)(propdb->resource,
- ctx->prop, ctx->operation,
- ctx->liveprop_ctx,
- &ctx->rollback->liveprop);
- }
- else {
- dav_datum key;
-
- /* we're going to need the key for all operations */
- key = dav_gdbm_key(propdb, ctx->prop);
-
- /* save the old value so that we can do a rollback. */
- rollback->key = key;
- if ((err = (*propdb->db_hooks->fetch)(propdb->db, key,
- &rollback->value)) != NULL)
- goto error;
-
- if (ctx->operation == DAV_PROP_OP_SET) {
-
- dav_datum value;
-
- /* Note: propdb->ns_map was set in dav_prop_validate() */
-
- /* quote all the values in the element */
- ap_xml_quote_elem(propdb->p, ctx->prop);
-
- /* generate a text blob for the xml:lang plus the contents */
- ap_xml_to_text(propdb->p, ctx->prop, AP_XML_X2T_LANG_INNER, NULL,
- propdb->ns_map,
- (const char **)&value.dptr, &value.dsize);
-
- err = (*propdb->db_hooks->store)(propdb->db, key, value);
-
- /*
- ** If an error occurred, then assume that we didn't change the
- ** value. Remove the rollback item so that we don't try to set
- ** its value during the rollback.
- */
- }
- else if (ctx->operation == DAV_PROP_OP_DELETE) {
-
- /*
- ** Delete the property. Ignore errors -- the property is there, or
- ** we are deleting it for a second time.
- */
- /* ### but what about other errors? */
- (void) (*propdb->db_hooks->remove)(propdb->db, key);
- }
- }
-
- error:
- /* push a more specific error here */
- if (err != NULL) {
- /*
- ** Use HTTP_INTERNAL_SERVER_ERROR because we shouldn't have seen
- ** any errors at this point.
- */
- ctx->err = dav_push_error(propdb->p, HTTP_INTERNAL_SERVER_ERROR,
- DAV_ERR_PROP_EXEC,
- "Could not execute PROPPATCH.", err);
- }
-}
-
-void dav_prop_commit(dav_prop_ctx *ctx)
-{
- dav_elem_private *priv = ctx->prop->private;
-
- /*
- ** Note that a commit implies ctx->err is NULL. The caller should assume
- ** a status of HTTP_OK for this case.
- */
-
- if (ctx->is_liveprop) {
- (*priv->provider->patch_commit)(ctx->propdb->resource,
- ctx->operation,
- ctx->liveprop_ctx,
- ctx->rollback->liveprop);
- }
-}
-
-void dav_prop_rollback(dav_prop_ctx *ctx)
-{
- dav_error *err = NULL;
- dav_elem_private *priv = ctx->prop->private;
-
- /* do nothing if there is no rollback information. */
- if (ctx->rollback == NULL)
- return;
-
- /*
- ** ### if we have an error, and a rollback occurs, then the namespace
- ** ### mods should not happen at all. Basically, the namespace management
- ** ### is simply a bitch.
- */
-
- if (ctx->is_liveprop) {
- err = (*priv->provider->patch_rollback)(ctx->propdb->resource,
- ctx->operation,
- ctx->liveprop_ctx,
- ctx->rollback->liveprop);
- }
- else if (ctx->rollback->value.dptr == NULL) {
- /* don't fail if the thing isn't really there */
- /* ### but what about other errors? */
- (void) (*ctx->propdb->db_hooks->remove)(ctx->propdb->db,
- ctx->rollback->key);
- }
- else {
- err = (*ctx->propdb->db_hooks->store)(ctx->propdb->db,
- ctx->rollback->key,
- ctx->rollback->value);
- }
-
- if (err != NULL) {
- if (ctx->err == NULL)
- ctx->err = err;
- else {
- dav_error *scan = err;
-
- /* hook previous errors at the end of the rollback error */
- while (scan->prev != NULL)
- scan = scan->prev;
- scan->prev = ctx->err;
- ctx->err = err;
- }
- }
-}
diff --git a/modules/dav/main/providers.c b/modules/dav/main/providers.c
deleted file mode 100644
index b0a18cf5f4..0000000000
--- a/modules/dav/main/providers.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "apr_pools.h"
-#include "apr_hash.h"
-#include "mod_dav.h"
-
-
-static apr_hash_t *dav_repos_providers = NULL;
-
-
-static apr_status_t dav_cleanup_providers(void *ctx)
-{
- dav_repos_providers = NULL;
- return APR_SUCCESS;
-}
-
-DAV_DECLARE(void) dav_register_provider(apr_pool_t *p, const char *name,
- const dav_provider *provider)
-{
- if (dav_repos_providers == NULL) {
- dav_repos_providers = apr_hash_make(p);
- apr_pool_cleanup_register(p, NULL, dav_cleanup_providers, apr_pool_cleanup_null);
- }
-
- /* just set it. no biggy if it was there before. */
- apr_hash_set(dav_repos_providers, name, APR_HASH_KEY_STRING, provider);
-}
-
-const dav_provider * dav_lookup_provider(const char *name)
-{
- return apr_hash_get(dav_repos_providers, name, APR_HASH_KEY_STRING);
-}
diff --git a/modules/dav/main/std_liveprop.c b/modules/dav/main/std_liveprop.c
deleted file mode 100644
index e10a5b1b82..0000000000
--- a/modules/dav/main/std_liveprop.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "httpd.h"
-#include "util_xml.h"
-#include "apr_strings.h"
-
-#include "mod_dav.h"
-
-/* forward-declare */
-static const dav_hooks_liveprop dav_core_hooks_liveprop;
-
-/*
-** The namespace URIs that we use. There will only ever be "DAV:".
-*/
-static const char * const dav_core_namespace_uris[] =
-{
- "DAV:",
- NULL /* sentinel */
-};
-
-/*
-** Define each of the core properties that this provider will handle.
-** Note that all of them are in the DAV: namespace, which has a
-** provider-local index of 0.
-*/
-static const dav_liveprop_spec dav_core_props[] =
-{
- { 0, "comment", DAV_PROPID_comment, 1 },
- { 0, "creator-displayname", DAV_PROPID_creator_displayname, 1 },
- { 0, "displayname", DAV_PROPID_displayname, 1 },
- { 0, "resourcetype", DAV_PROPID_resourcetype, 0 },
- { 0, "source", DAV_PROPID_source, 1 },
-
- { 0 } /* sentinel */
-};
-
-static const dav_liveprop_group dav_core_liveprop_group =
-{
- dav_core_props,
- dav_core_namespace_uris,
- &dav_core_hooks_liveprop
-};
-
-static dav_prop_insert dav_core_insert_prop(const dav_resource *resource,
- int propid, dav_prop_insert what,
- ap_text_header *phdr)
-{
- const char *value;
- const char *s;
- apr_pool_t *p = resource->pool;
- const dav_liveprop_spec *info;
- int global_ns;
-
- switch (propid)
- {
- case DAV_PROPID_resourcetype:
- switch (resource->type) {
- case DAV_RESOURCE_TYPE_VERSION:
- if (resource->baselined) {
- value = "<D:baseline/>";
- break;
- }
- /* fall through */
- case DAV_RESOURCE_TYPE_REGULAR:
- case DAV_RESOURCE_TYPE_WORKING:
- if (resource->collection) {
- value = "<D:collection/>";
- }
- else {
- /* ### should we denote lock-null resources? */
-
- value = ""; /* becomes: <D:resourcetype/> */
- }
- break;
- case DAV_RESOURCE_TYPE_HISTORY:
- value = "<D:version-history/>";
- break;
- case DAV_RESOURCE_TYPE_WORKSPACE:
- value = "<D:collection/>";
- break;
- case DAV_RESOURCE_TYPE_ACTIVITY:
- value = "<D:activity/>";
- break;
-
- default:
- /* ### bad juju */
- return DAV_PROP_INSERT_NOTDEF;
- }
- break;
-
- case DAV_PROPID_comment:
- case DAV_PROPID_creator_displayname:
- case DAV_PROPID_displayname:
- case DAV_PROPID_source:
- default:
- /*
- ** This property is known, but not defined as a liveprop. However,
- ** it may be a dead property.
- */
- return DAV_PROP_INSERT_NOTDEF;
- }
-
- /* assert: value != NULL */
-
- /* get the information and global NS index for the property */
- global_ns = dav_get_liveprop_info(propid, &dav_core_liveprop_group, &info);
-
- /* assert: info != NULL && info->name != NULL */
-
- if (what == DAV_PROP_INSERT_SUPPORTED) {
- s = apr_psprintf(p,
- "<D:supported-live-property D:name=\"%s\" "
- "D:namespace=\"%s\"/>" DEBUG_CR,
- info->name, dav_core_namespace_uris[info->ns]);
- }
- else if (what == DAV_PROP_INSERT_VALUE && *value != '\0') {
- s = apr_psprintf(p, "<lp%d:%s>%s</lp%d:%s>" DEBUG_CR,
- global_ns, info->name, value, global_ns, info->name);
- }
- else {
- s = apr_psprintf(p, "<lp%d:%s/>" DEBUG_CR, global_ns, info->name);
- }
- ap_text_append(p, phdr, s);
-
- /* we inserted what was asked for */
- return what;
-}
-
-static int dav_core_is_writable(const dav_resource *resource, int propid)
-{
- const dav_liveprop_spec *info;
-
- (void) dav_get_liveprop_info(propid, &dav_core_liveprop_group, &info);
- return info->is_writable;
-}
-
-static dav_error * dav_core_patch_validate(const dav_resource *resource,
- const ap_xml_elem *elem,
- int operation, void **context,
- int *defer_to_dead)
-{
- /* all of our writable props go in the dead prop database */
- *defer_to_dead = 1;
-
- return NULL;
-}
-
-static const dav_hooks_liveprop dav_core_hooks_liveprop = {
- dav_core_insert_prop,
- dav_core_is_writable,
- dav_core_namespace_uris,
- dav_core_patch_validate,
- NULL, /* patch_exec */
- NULL, /* patch_commit */
- NULL, /* patch_rollback */
-};
-
-int dav_core_find_liveprop(const dav_resource *resource,
- const char *ns_uri, const char *name,
- const dav_hooks_liveprop **hooks)
-{
- return dav_do_find_liveprop(ns_uri, name, &dav_core_liveprop_group, hooks);
-}
-
-void dav_core_insert_all_liveprops(request_rec *r,
- const dav_resource *resource,
- dav_prop_insert what, ap_text_header *phdr)
-{
- (void) dav_core_insert_prop(resource, DAV_PROPID_resourcetype,
- what, phdr);
-}
-
-void dav_core_register_uris(apr_pool_t *p)
-{
- /* register the namespace URIs */
- dav_register_liveprop_group(p, &dav_core_liveprop_group);
-}
diff --git a/modules/dav/main/util.c b/modules/dav/main/util.c
deleted file mode 100644
index 5a8d4728e0..0000000000
--- a/modules/dav/main/util.c
+++ /dev/null
@@ -1,1958 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-/*
-** DAV extension module for Apache 2.0.*
-** - various utilities, repository-independent
-*/
-
-#include "apr_strings.h"
-#include "apr_lib.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#include "mod_dav.h"
-
-#include "http_request.h"
-#include "http_config.h"
-#include "http_vhost.h"
-#include "http_log.h"
-#include "http_protocol.h"
-
-DAV_DECLARE(dav_error*) dav_new_error(apr_pool_t *p, int status,
- int error_id, const char *desc)
-{
- int save_errno = errno;
- dav_error *err = apr_pcalloc(p, sizeof(*err));
-
- /* DBG3("dav_new_error: %d %d %s", status, error_id, desc ? desc : "(no desc)"); */
-
- err->status = status;
- err->error_id = error_id;
- err->desc = desc;
- err->save_errno = save_errno;
-
- return err;
-}
-
-DAV_DECLARE(dav_error*) dav_push_error(apr_pool_t *p, int status,
- int error_id, const char *desc,
- dav_error *prev)
-{
- dav_error *err = apr_pcalloc(p, sizeof(*err));
-
- err->status = status;
- err->error_id = error_id;
- err->desc = desc;
- err->prev = prev;
-
- return err;
-}
-
-DAV_DECLARE(void) dav_check_bufsize(apr_pool_t * p, dav_buffer *pbuf,
- apr_size_t extra_needed)
-{
- /* grow the buffer if necessary */
- if (pbuf->cur_len + extra_needed > pbuf->alloc_len) {
- char *newbuf;
-
- pbuf->alloc_len += extra_needed + DAV_BUFFER_PAD;
- newbuf = apr_palloc(p, pbuf->alloc_len);
- memcpy(newbuf, pbuf->buf, pbuf->cur_len);
- pbuf->buf = newbuf;
- }
-}
-
-DAV_DECLARE(void) dav_set_bufsize(apr_pool_t * p, dav_buffer *pbuf,
- apr_size_t size)
-{
- /* NOTE: this does not retain prior contents */
-
- /* NOTE: this function is used to init the first pointer, too, since
- the PAD will be larger than alloc_len (0) for zeroed structures */
-
- /* grow if we don't have enough for the requested size plus padding */
- if (size + DAV_BUFFER_PAD > pbuf->alloc_len) {
- /* set the new length; min of MINSIZE */
- pbuf->alloc_len = size + DAV_BUFFER_PAD;
- if (pbuf->alloc_len < DAV_BUFFER_MINSIZE)
- pbuf->alloc_len = DAV_BUFFER_MINSIZE;
-
- pbuf->buf = apr_palloc(p, pbuf->alloc_len);
- }
- pbuf->cur_len = size;
-}
-
-
-/* initialize a buffer and copy the specified (null-term'd) string into it */
-DAV_DECLARE(void) dav_buffer_init(apr_pool_t *p, dav_buffer *pbuf,
- const char *str)
-{
- dav_set_bufsize(p, pbuf, strlen(str));
- memcpy(pbuf->buf, str, pbuf->cur_len + 1);
-}
-
-/* append a string to the end of the buffer, adjust length */
-DAV_DECLARE(void) dav_buffer_append(apr_pool_t *p, dav_buffer *pbuf,
- const char *str)
-{
- size_t len = strlen(str);
-
- dav_check_bufsize(p, pbuf, len + 1);
- memcpy(pbuf->buf + pbuf->cur_len, str, len + 1);
- pbuf->cur_len += len;
-}
-
-/* place a string on the end of the buffer, do NOT adjust length */
-DAV_DECLARE(void) dav_buffer_place(apr_pool_t *p, dav_buffer *pbuf,
- const char *str)
-{
- size_t len = strlen(str);
-
- dav_check_bufsize(p, pbuf, len + 1);
- memcpy(pbuf->buf + pbuf->cur_len, str, len + 1);
-}
-
-/* place some memory on the end of a buffer; do NOT adjust length */
-DAV_DECLARE(void) dav_buffer_place_mem(apr_pool_t *p, dav_buffer *pbuf,
- const void *mem, apr_size_t amt,
- apr_size_t pad)
-{
- dav_check_bufsize(p, pbuf, amt + pad);
- memcpy(pbuf->buf + pbuf->cur_len, mem, amt);
-}
-
-/*
-** dav_lookup_uri()
-**
-** Extension for ap_sub_req_lookup_uri() which can't handle absolute
-** URIs properly.
-**
-** If NULL is returned, then an error occurred with parsing the URI or
-** the URI does not match the current server.
-*/
-dav_lookup_result dav_lookup_uri(const char *uri, request_rec * r,
- int must_be_absolute)
-{
- dav_lookup_result result = { 0 };
- const char *scheme;
- apr_port_t port;
- uri_components comp;
- char *new_file;
- const char *domain;
-
- /* first thing to do is parse the URI into various components */
- if (ap_parse_uri_components(r->pool, uri, &comp) != HTTP_OK) {
- result.err.status = HTTP_BAD_REQUEST;
- result.err.desc = "Invalid syntax in Destination URI.";
- return result;
- }
-
- /* the URI must be an absoluteURI (WEBDAV S9.3) */
- if (comp.scheme == NULL && must_be_absolute) {
- result.err.status = HTTP_BAD_REQUEST;
- result.err.desc = "Destination URI must be an absolute URI.";
- return result;
- }
-
- /* the URI must not have a query (args) or a fragment */
- if (comp.query != NULL || comp.fragment != NULL) {
- result.err.status = HTTP_BAD_REQUEST;
- result.err.desc =
- "Destination URI contains invalid components "
- "(a query or a fragment).";
- return result;
- }
-
- /* If the scheme or port was provided, then make sure that it matches
- the scheme/port of this request. If the request must be absolute,
- then require the (explicit/implicit) scheme/port be matching.
-
- ### hmm. if a port wasn't provided (does the parse return port==0?),
- ### but we're on a non-standard port, then we won't detect that the
- ### URI's port implies the wrong one.
- */
- if (comp.scheme != NULL || comp.port != 0 || must_be_absolute)
- {
- /* ### not sure this works if the current request came in via https: */
- scheme = r->parsed_uri.scheme;
- if (scheme == NULL)
- scheme = ap_http_method(r);
-
- /* insert a port if the URI did not contain one */
- if (comp.port == 0)
- comp.port = ap_default_port_for_scheme(comp.scheme);
-
- /* now, verify that the URI uses the same scheme as the current.
- request. the port must match our port.
- */
- apr_sockaddr_port_get(&port, r->connection->local_addr);
- if (strcasecmp(comp.scheme, scheme) != 0 ||
- comp.port != port) {
- result.err.status = HTTP_BAD_GATEWAY;
- result.err.desc = apr_psprintf(r->pool,
- "Destination URI refers to "
- "different scheme or port "
- "(%s://hostname:%d)" APR_EOL_STR
- "(want: %s://hostname:%d)",
- comp.scheme ? comp.scheme : scheme,
- comp.port ? comp.port : port,
- scheme, port);
- return result;
- }
- }
-
- /* we have verified the scheme, port, and general structure */
-
- /*
- ** Hrm. IE5 will pass unqualified hostnames for both the
- ** Host: and Destination: headers. This breaks the
- ** http_vhost.c::matches_aliases function.
- **
- ** For now, qualify unqualified comp.hostnames with
- ** r->server->server_hostname.
- **
- ** ### this is a big hack. Apache should provide a better way.
- ** ### maybe the admin should list the unqualified hosts in a
- ** ### <ServerAlias> block?
- */
- if (comp.hostname != NULL
- && strrchr(comp.hostname, '.') == NULL
- && (domain = strchr(r->server->server_hostname, '.')) != NULL) {
- comp.hostname = apr_pstrcat(r->pool, comp.hostname, domain, NULL);
- }
-
- /* now, if a hostname was provided, then verify that it represents the
- same server as the current connection. note that we just use our
- port, since we've verified the URI matches ours */
- if (comp.hostname != NULL &&
- !ap_matches_request_vhost(r, comp.hostname, port)) {
- result.err.status = HTTP_BAD_GATEWAY;
- result.err.desc = "Destination URI refers to a different server.";
- return result;
- }
-
- /* we have verified that the requested URI denotes the same server as
- the current request. Therefore, we can use ap_sub_req_lookup_uri() */
-
- /* reconstruct a URI as just the path */
- new_file = ap_unparse_uri_components(r->pool, &comp, UNP_OMITSITEPART);
-
- /*
- * Lookup the URI and return the sub-request. Note that we use the
- * same HTTP method on the destination. This allows the destination
- * to apply appropriate restrictions (e.g. readonly).
- */
- result.rnew = ap_sub_req_method_uri(r->method, new_file, r, NULL);
-
- return result;
-}
-
-/* ---------------------------------------------------------------
-**
-** XML UTILITY FUNCTIONS
-*/
-
-/* validate that the root element uses a given DAV: tagname (TRUE==valid) */
-int dav_validate_root(const ap_xml_doc *doc, const char *tagname)
-{
- return doc->root &&
- doc->root->ns == AP_XML_NS_DAV_ID &&
- strcmp(doc->root->name, tagname) == 0;
-}
-
-/* find and return the (unique) child with a given DAV: tagname */
-ap_xml_elem *dav_find_child(const ap_xml_elem *elem, const char *tagname)
-{
- ap_xml_elem *child = elem->first_child;
-
- for (; child; child = child->next)
- if (child->ns == AP_XML_NS_DAV_ID && !strcmp(child->name, tagname))
- return child;
- return NULL;
-}
-
-/* gather up all the CDATA into a single string */
-const char *dav_xml_get_cdata(const ap_xml_elem *elem, apr_pool_t *pool,
- int strip_white)
-{
- apr_size_t len = 0;
- ap_text *scan;
- const ap_xml_elem *child;
- char *cdata;
- char *s;
- apr_size_t tlen;
- const char *found_text = NULL; /* initialize to avoid gcc warning */
- int found_count = 0;
-
- for (scan = elem->first_cdata.first; scan != NULL; scan = scan->next) {
- found_text = scan->text;
- ++found_count;
- len += strlen(found_text);
- }
-
- for (child = elem->first_child; child != NULL; child = child->next) {
- for (scan = child->following_cdata.first;
- scan != NULL;
- scan = scan->next) {
- found_text = scan->text;
- ++found_count;
- len += strlen(found_text);
- }
- }
-
- /* some fast-path cases:
- * 1) zero-length cdata
- * 2) a single piece of cdata with no whitespace to strip
- */
- if (len == 0)
- return "";
- if (found_count == 1) {
- if (!strip_white
- || (!apr_isspace(*found_text)
- && !apr_isspace(found_text[len - 1])))
- return found_text;
- }
-
- cdata = s = apr_palloc(pool, len + 1);
-
- for (scan = elem->first_cdata.first; scan != NULL; scan = scan->next) {
- tlen = strlen(scan->text);
- memcpy(s, scan->text, tlen);
- s += tlen;
- }
-
- for (child = elem->first_child; child != NULL; child = child->next) {
- for (scan = child->following_cdata.first;
- scan != NULL;
- scan = scan->next) {
- tlen = strlen(scan->text);
- memcpy(s, scan->text, tlen);
- s += tlen;
- }
- }
-
- *s = '\0';
-
- if (strip_white) {
- /* trim leading whitespace */
- while (apr_isspace(*cdata)) /* assume: return false for '\0' */
- ++cdata;
-
- /* trim trailing whitespace */
- while (len-- > 0 && apr_isspace(cdata[len]))
- continue;
- cdata[len + 1] = '\0';
- }
-
- return cdata;
-}
-
-/* ---------------------------------------------------------------
-**
-** Timeout header processing
-**
-*/
-
-/* dav_get_timeout: If the Timeout: header exists, return a time_t
- * when this lock is expected to expire. Otherwise, return
- * a time_t of DAV_TIMEOUT_INFINITE.
- *
- * It's unclear if DAV clients are required to understand
- * Seconds-xxx and Infinity time values. We assume that they do.
- * In addition, for now, that's all we understand, too.
- */
-time_t dav_get_timeout(request_rec *r)
-{
- time_t now, expires = DAV_TIMEOUT_INFINITE;
-
- const char *timeout_const = apr_table_get(r->headers_in, "Timeout");
- const char *timeout = apr_pstrdup(r->pool, timeout_const), *val;
-
- if (timeout == NULL)
- return DAV_TIMEOUT_INFINITE;
-
- /* Use the first thing we understand, or infinity if
- * we don't understand anything.
- */
-
- while ((val = ap_getword_white(r->pool, &timeout)) && strlen(val)) {
- if (!strncmp(val, "Infinite", 8)) {
- return DAV_TIMEOUT_INFINITE;
- }
-
- if (!strncmp(val, "Second-", 7)) {
- val += 7;
- /* ### We need to handle overflow better:
- * ### timeout will be <= 2^32 - 1
- */
- expires = atol(val);
- now = time(NULL);
- return now + expires;
- }
- }
-
- return DAV_TIMEOUT_INFINITE;
-}
-
-/* ---------------------------------------------------------------
-**
-** If Header processing
-**
-*/
-
-/* add_if_resource returns a new if_header, linking it to next_ih.
- */
-static dav_if_header *dav_add_if_resource(apr_pool_t *p, dav_if_header *next_ih,
- const char *uri, size_t uri_len)
-{
- dav_if_header *ih;
-
- if ((ih = apr_pcalloc(p, sizeof(*ih))) == NULL)
- return NULL;
-
- ih->uri = uri;
- ih->uri_len = uri_len;
- ih->next = next_ih;
-
- return ih;
-}
-
-/* add_if_state adds a condition to an if_header.
- */
-static dav_error * dav_add_if_state(apr_pool_t *p, dav_if_header *ih,
- const char *state_token,
- dav_if_state_type t, int condition,
- const dav_hooks_locks *locks_hooks)
-{
- dav_if_state_list *new_sl;
-
- new_sl = apr_pcalloc(p, sizeof(*new_sl));
-
- new_sl->condition = condition;
- new_sl->type = t;
-
- if (t == dav_if_opaquelock) {
- dav_error *err;
-
- if ((err = (*locks_hooks->parse_locktoken)(p, state_token,
- &new_sl->locktoken)) != NULL) {
- /* ### maybe add a higher-level description */
- return err;
- }
- }
- else
- new_sl->etag = state_token;
-
- new_sl->next = ih->state;
- ih->state = new_sl;
-
- return NULL;
-}
-
-/* fetch_next_token returns the substring from str+1
- * to the next occurence of char term, or \0, whichever
- * occurs first. Leading whitespace is ignored.
- */
-static char *dav_fetch_next_token(char **str, char term)
-{
- char *sp;
- char *token;
-
- token = *str + 1;
-
- while (*token && (*token == ' ' || *token == '\t'))
- token++;
-
- if ((sp = strchr(token, term)) == NULL)
- return NULL;
-
- *sp = '\0';
- *str = sp;
- return token;
-}
-
-/* dav_process_if_header:
- *
- * If NULL (no error) is returned, then **if_header points to the
- * "If" productions structure (or NULL if "If" is not present).
- *
- * ### this part is bogus:
- * If an error is encountered, the error is logged. Parent should
- * return err->status.
- */
-static dav_error * dav_process_if_header(request_rec *r, dav_if_header **p_ih)
-{
- dav_error *err;
- char *str;
- char *list;
- const char *state_token;
- const char *uri = NULL; /* scope of current production; NULL=no-tag */
- size_t uri_len = 0;
- dav_if_header *ih = NULL;
- uri_components parsed_uri;
- const dav_hooks_locks *locks_hooks = DAV_GET_HOOKS_LOCKS(r);
- enum {no_tagged, tagged, unknown} list_type = unknown;
- int condition;
-
- *p_ih = NULL;
-
- if ((str = apr_pstrdup(r->pool, apr_table_get(r->headers_in, "If"))) == NULL)
- return NULL;
-
- while (*str) {
- switch(*str) {
- case '<':
- /* Tagged-list production - following states apply to this uri */
- if (list_type == no_tagged
- || ((uri = dav_fetch_next_token(&str, '>')) == NULL)) {
- return dav_new_error(r->pool, HTTP_BAD_REQUEST,
- DAV_ERR_IF_TAGGED,
- "Invalid If-header: unclosed \"<\" or "
- "unexpected tagged-list production.");
- }
-
- /* 2518 specifies this must be an absolute URI; just take the
- * relative part for later comparison against r->uri */
- if (ap_parse_uri_components(r->pool, uri, &parsed_uri) != HTTP_OK) {
- return dav_new_error(r->pool, HTTP_BAD_REQUEST,
- DAV_ERR_IF_TAGGED,
- "Invalid URI in tagged If-header.");
- }
- /* note that parsed_uri.path is allocated; we can trash it */
-
- /* clean up the URI a bit */
- ap_getparents(parsed_uri.path);
- uri_len = strlen(parsed_uri.path);
- if (uri_len > 1 && parsed_uri.path[uri_len - 1] == '/')
- parsed_uri.path[--uri_len] = '\0';
-
- uri = parsed_uri.path;
- list_type = tagged;
- break;
-
- case '(':
- /* List production */
-
- /* If a uri has not been encountered, this is a No-Tagged-List */
- if (list_type == unknown)
- list_type = no_tagged;
-
- if ((list = dav_fetch_next_token(&str, ')')) == NULL) {
- return dav_new_error(r->pool, HTTP_BAD_REQUEST,
- DAV_ERR_IF_UNCLOSED_PAREN,
- "Invalid If-header: unclosed \"(\".");
- }
-
- if ((ih = dav_add_if_resource(r->pool, ih, uri, uri_len)) == NULL) {
- /* ### dav_add_if_resource() should return an error for us! */
- return dav_new_error(r->pool, HTTP_BAD_REQUEST,
- DAV_ERR_IF_PARSE,
- "Internal server error parsing \"If:\" "
- "header.");
- }
-
- condition = DAV_IF_COND_NORMAL;
-
- while (*list) {
- /* List is the entire production (in a uri scope) */
-
- switch (*list) {
- case '<':
- if ((state_token = dav_fetch_next_token(&list, '>')) == NULL) {
- /* ### add a description to this error */
- return dav_new_error(r->pool, HTTP_BAD_REQUEST,
- DAV_ERR_IF_PARSE, NULL);
- }
-
- if ((err = dav_add_if_state(r->pool, ih, state_token, dav_if_opaquelock,
- condition, locks_hooks)) != NULL) {
- /* ### maybe add a higher level description */
- return err;
- }
- condition = DAV_IF_COND_NORMAL;
- break;
-
- case '[':
- if ((state_token = dav_fetch_next_token(&list, ']')) == NULL) {
- /* ### add a description to this error */
- return dav_new_error(r->pool, HTTP_BAD_REQUEST,
- DAV_ERR_IF_PARSE, NULL);
- }
-
- if ((err = dav_add_if_state(r->pool, ih, state_token, dav_if_etag,
- condition, locks_hooks)) != NULL) {
- /* ### maybe add a higher level description */
- return err;
- }
- condition = DAV_IF_COND_NORMAL;
- break;
-
- case 'N':
- if (list[1] == 'o' && list[2] == 't') {
- if (condition != DAV_IF_COND_NORMAL) {
- return dav_new_error(r->pool, HTTP_BAD_REQUEST,
- DAV_ERR_IF_MULTIPLE_NOT,
- "Invalid \"If:\" header: "
- "Multiple \"not\" entries "
- "for the same state.");
- }
- condition = DAV_IF_COND_NOT;
- }
- list += 2;
- break;
-
- case ' ':
- case '\t':
- break;
-
- default:
- return dav_new_error(r->pool, HTTP_BAD_REQUEST,
- DAV_ERR_IF_UNK_CHAR,
- apr_psprintf(r->pool,
- "Invalid \"If:\" "
- "header: Unexpected "
- "character encountered "
- "(0x%02x, '%c').",
- *list, *list));
- }
-
- list++;
- }
- break;
-
- case ' ':
- case '\t':
- break;
-
- default:
- return dav_new_error(r->pool, HTTP_BAD_REQUEST,
- DAV_ERR_IF_UNK_CHAR,
- apr_psprintf(r->pool,
- "Invalid \"If:\" header: "
- "Unexpected character "
- "encountered (0x%02x, '%c').",
- *str, *str));
- }
-
- str++;
- }
-
- *p_ih = ih;
- return NULL;
-}
-
-static int dav_find_submitted_locktoken(const dav_if_header *if_header,
- const dav_lock *lock_list,
- const dav_hooks_locks *locks_hooks)
-{
- for (; if_header != NULL; if_header = if_header->next) {
- const dav_if_state_list *state_list;
-
- for (state_list = if_header->state;
- state_list != NULL;
- state_list = state_list->next) {
-
- if (state_list->type == dav_if_opaquelock) {
- const dav_lock *lock;
-
- /* given state_list->locktoken, match it */
-
- /*
- ** The resource will have one or more lock tokens. We only
- ** need to match one of them against any token in the
- ** If: header.
- **
- ** One token case: It is an exclusive or shared lock. Either
- ** way, we must find it.
- **
- ** N token case: They are shared locks. By policy, we need
- ** to match only one. The resource's other
- ** tokens may belong to somebody else (so we
- ** shouldn't see them in the If: header anyway)
- */
- for (lock = lock_list; lock != NULL; lock = lock->next) {
-
- if (!(*locks_hooks->compare_locktoken)(state_list->locktoken, lock->locktoken)) {
- return 1;
- }
- }
- }
- }
- }
-
- return 0;
-}
-
-/* dav_validate_resource_state:
- * Returns NULL if path/uri meets if-header and lock requirements
- */
-static dav_error * dav_validate_resource_state(apr_pool_t *p,
- const dav_resource *resource,
- dav_lockdb *lockdb,
- const dav_if_header *if_header,
- int flags,
- dav_buffer *pbuf,
- request_rec *r)
-{
- dav_error *err;
- const char *uri;
- const char *etag;
- const dav_hooks_locks *locks_hooks = (lockdb ? lockdb->hooks : NULL);
- const dav_if_header *ifhdr_scan;
- dav_if_state_list *state_list;
- dav_lock *lock_list;
- dav_lock *lock;
- int num_matched;
- int num_that_apply;
- int seen_locktoken;
- apr_size_t uri_len;
- const char *reason = NULL;
-
- /* DBG1("validate: <%s>", resource->uri); */
-
- /*
- ** The resource will have one of three states:
- **
- ** 1) No locks. We have no special requirements that the user supply
- ** specific locktokens. One of the state lists must match, and
- ** we're done.
- **
- ** 2) One exclusive lock. The locktoken must appear *anywhere* in the
- ** If: header. Of course, asserting the token in a "Not" term will
- ** quickly fail that state list :-). If the locktoken appears in
- ** one of the state lists *and* one state list matches, then we're
- ** done.
- **
- ** 3) One or more shared locks. One of the locktokens must appear
- ** *anywhere* in the If: header. If one of the locktokens appears,
- ** and we match one state list, then we are done.
- **
- ** The <seen_locktoken> variable determines whether we have seen one
- ** of this resource's locktokens in the If: header.
- */
-
- /*
- ** If this is a new lock request, <flags> will contain the requested
- ** lock scope. Three rules apply:
- **
- ** 1) Do not require a (shared) locktoken to be seen (when we are
- ** applying another shared lock)
- ** 2) If the scope is exclusive and we see any locks, fail.
- ** 3) If the scope is shared and we see an exclusive lock, fail.
- */
-
- if (lockdb == NULL) {
- /* we're in State 1. no locks. */
- lock_list = NULL;
- }
- else {
- /*
- ** ### hrm... we don't need to have these fully
- ** ### resolved since we're only looking at the
- ** ### locktokens...
- **
- ** ### use get_locks w/ calltype=PARTIAL
- */
- if ((err = dav_lock_query(lockdb, resource, &lock_list)) != NULL) {
- return dav_push_error(p,
- HTTP_INTERNAL_SERVER_ERROR, 0,
- "The locks could not be queried for "
- "verification against a possible \"If:\" "
- "header.",
- err);
- }
-
- /* lock_list now determines whether we're in State 1, 2, or 3. */
- }
-
- /*
- ** For a new, exclusive lock: if any locks exist, fail.
- ** For a new, shared lock: if an exclusive lock exists, fail.
- ** else, do not require a token to be seen.
- */
- if (flags & DAV_LOCKSCOPE_EXCLUSIVE) {
- if (lock_list != NULL) {
- return dav_new_error(p, HTTP_LOCKED, 0,
- "Existing lock(s) on the requested resource "
- "prevent an exclusive lock.");
- }
-
- /*
- ** There are no locks, so we can pretend that we've already met
- ** any requirement to find the resource's locks in an If: header.
- */
- seen_locktoken = 1;
- }
- else if (flags & DAV_LOCKSCOPE_SHARED) {
- /*
- ** Strictly speaking, we don't need this loop. Either the first
- ** (and only) lock will be EXCLUSIVE, or none of them will be.
- */
- for (lock = lock_list; lock != NULL; lock = lock->next) {
- if (lock->scope == DAV_LOCKSCOPE_EXCLUSIVE) {
- return dav_new_error(p, HTTP_LOCKED, 0,
- "The requested resource is already "
- "locked exclusively.");
- }
- }
-
- /*
- ** The locks on the resource (if any) are all shared. Set the
- ** <seen_locktoken> flag to indicate that we do not need to find
- ** the locks in an If: header.
- */
- seen_locktoken = 1;
- }
- else {
- /*
- ** For methods other than LOCK:
- **
- ** If we have no locks, then <seen_locktoken> can be set to true --
- ** pretending that we've already met the requirement of seeing one
- ** of the resource's locks in the If: header.
- **
- ** Otherwise, it must be cleared and we'll look for one.
- */
- seen_locktoken = (lock_list == NULL);
- }
-
- /*
- ** If there is no If: header, then we can shortcut some logic:
- **
- ** 1) if we do not need to find a locktoken in the (non-existent) If:
- ** header, then we are successful.
- **
- ** 2) if we must find a locktoken in the (non-existent) If: header, then
- ** we fail.
- */
- if (if_header == NULL) {
- if (seen_locktoken)
- return NULL;
-
- return dav_new_error(p, HTTP_LOCKED, 0,
- "This resource is locked and an \"If:\" header "
- "was not supplied to allow access to the "
- "resource.");
- }
- /* the If: header is present */
-
- /*
- ** If a dummy header is present (because of a Lock-Token: header), then
- ** we are required to find that token in this resource's set of locks.
- ** If we have no locks, then we immediately fail.
- **
- ** This is a 400 (Bad Request) since they should only submit a locktoken
- ** that actually exists.
- **
- ** Don't issue this response if we're talking about the parent resource.
- ** It is okay for that resource to NOT have this locktoken.
- ** (in fact, it certainly will not: a dummy_header only occurs for the
- ** UNLOCK method, the parent is checked only for locknull resources,
- ** and the parent certainly does not have the (locknull's) locktoken)
- */
- if (lock_list == NULL && if_header->dummy_header) {
- if (flags & DAV_VALIDATE_IS_PARENT)
- return NULL;
- return dav_new_error(p, HTTP_BAD_REQUEST, 0,
- "The locktoken specified in the \"Lock-Token:\" "
- "header is invalid because this resource has no "
- "outstanding locks.");
- }
-
- /*
- ** Prepare the input URI. We want the URI to never have a trailing slash.
- **
- ** When URIs are placed into the dav_if_header structure, they are
- ** guaranteed to never have a trailing slash. If the URIs are equivalent,
- ** then it doesn't matter if they both lack a trailing slash -- they're
- ** still equivalent.
- **
- ** Note: we could also ensure that a trailing slash is present on both
- ** URIs, but the majority of URIs provided to us via a resource walk
- ** will not contain that trailing slash.
- */
- uri = resource->uri;
- uri_len = strlen(uri);
- if (uri[uri_len - 1] == '/') {
- dav_set_bufsize(p, pbuf, uri_len);
- memcpy(pbuf->buf, uri, uri_len);
- pbuf->buf[--uri_len] = '\0';
- uri = pbuf->buf;
- }
-
- /* get the resource's etag; we may need it during the checks */
- etag = (*resource->hooks->getetag)(resource);
-
- /* how many state_lists apply to this URI? */
- num_that_apply = 0;
-
- /* If there are if-headers, fail if this resource
- * does not match at least one state_list.
- */
- for (ifhdr_scan = if_header;
- ifhdr_scan != NULL;
- ifhdr_scan = ifhdr_scan->next) {
-
- /* DBG2("uri=<%s> if_uri=<%s>", uri, ifhdr_scan->uri ? ifhdr_scan->uri : "(no uri)"); */
-
- if (ifhdr_scan->uri != NULL
- && (uri_len != ifhdr_scan->uri_len
- || memcmp(uri, ifhdr_scan->uri, uri_len) != 0)) {
- /*
- ** A tagged-list's URI doesn't match this resource's URI.
- ** Skip to the next state_list to see if it will match.
- */
- continue;
- }
-
- /* this state_list applies to this resource */
-
- /*
- ** ### only one state_list should ever apply! a no-tag, or a tagged
- ** ### where S9.4.2 states only one can match.
- **
- ** ### revamp this code to loop thru ifhdr_scan until we find the
- ** ### matching state_list. process it. stop.
- */
- ++num_that_apply;
-
- /* To succeed, resource must match *all* of the states
- * specified in the state_list.
- */
- for (state_list = ifhdr_scan->state;
- state_list != NULL;
- state_list = state_list->next) {
-
- switch(state_list->type) {
- case dav_if_etag:
- {
- int mismatch = strcmp(state_list->etag, etag);
-
- if (state_list->condition == DAV_IF_COND_NORMAL && mismatch) {
- /*
- ** The specified entity-tag does not match the
- ** entity-tag on the resource. This state_list is
- ** not going to match. Bust outta here.
- */
- reason =
- "an entity-tag was specified, but the resource's "
- "actual ETag does not match.";
- goto state_list_failed;
- }
- else if (state_list->condition == DAV_IF_COND_NOT
- && !mismatch) {
- /*
- ** The specified entity-tag DOES match the
- ** entity-tag on the resource. This state_list is
- ** not going to match. Bust outta here.
- */
- reason =
- "an entity-tag was specified using the \"Not\" form, "
- "but the resource's actual ETag matches the provided "
- "entity-tag.";
- goto state_list_failed;
- }
- break;
- }
-
- case dav_if_opaquelock:
- if (lockdb == NULL) {
- if (state_list->condition == DAV_IF_COND_NOT) {
- /* the locktoken is definitely not there! (success) */
- continue;
- }
-
- /* condition == DAV_IF_COND_NORMAL */
-
- /*
- ** If no lockdb is provided, then validation fails for
- ** this state_list (NORMAL means we were supposed to
- ** find the token, which we obviously cannot do without
- ** a lock database).
- **
- ** Go and try the next state list.
- */
- reason =
- "a State-token was supplied, but a lock database "
- "is not available for to provide the required lock.";
- goto state_list_failed;
- }
-
- /* Resource validation 'fails' if:
- * ANY of the lock->locktokens match
- * a NOT state_list->locktoken,
- * OR
- * NONE of the lock->locktokens match
- * a NORMAL state_list->locktoken.
- */
- num_matched = 0;
- for (lock = lock_list; lock != NULL; lock = lock->next) {
-
- /*
- DBG2("compare: rsrc=%s ifhdr=%s",
- (*locks_hooks->format_locktoken)(p, lock->locktoken),
- (*locks_hooks->format_locktoken)(p, state_list->locktoken));
- */
-
- /* nothing to do if the locktokens do not match. */
- if ((*locks_hooks->compare_locktoken)(state_list->locktoken, lock->locktoken)) {
- continue;
- }
-
- /*
- ** We have now matched up one of the resource's locktokens
- ** to a locktoken in a State-token in the If: header.
- ** Note this fact, so that we can pass the overall
- ** requirement of seeing at least one of the resource's
- ** locktokens.
- */
- seen_locktoken = 1;
-
- if (state_list->condition == DAV_IF_COND_NOT) {
- /*
- ** This state requires that the specified locktoken
- ** is NOT present on the resource. But we just found
- ** it. There is no way this state-list can now
- ** succeed, so go try another one.
- */
- reason =
- "a State-token was supplied, which used a "
- "\"Not\" condition. The State-token was found "
- "in the locks on this resource";
- goto state_list_failed;
- }
-
- /* condition == DAV_IF_COND_NORMAL */
-
- /* Validate auth_user: If an authenticated user created
- ** the lock, only the same user may submit that locktoken
- ** to manipulate a resource.
- */
- if (lock->auth_user &&
- (!r->user ||
- strcmp(lock->auth_user, r->user))) {
- const char *errmsg;
-
- errmsg = apr_pstrcat(p, "User \"",
- r->user,
- "\" submitted a locktoken created "
- "by user \"",
- lock->auth_user, "\".", NULL);
- return dav_new_error(p, HTTP_UNAUTHORIZED, 0, errmsg);
- }
-
- /*
- ** We just matched a specified State-Token to one of the
- ** resource's locktokens.
- **
- ** Break out of the lock scan -- we only needed to find
- ** one match (actually, there shouldn't be any other
- ** matches in the lock list).
- */
- num_matched = 1;
- break;
- }
-
- if (num_matched == 0
- && state_list->condition == DAV_IF_COND_NORMAL) {
- /*
- ** We had a NORMAL state, meaning that we should have
- ** found the State-Token within the locks on this
- ** resource. We didn't, so this state_list must fail.
- */
- reason =
- "a State-token was supplied, but it was not found "
- "in the locks on this resource.";
- goto state_list_failed;
- }
-
- break;
-
- } /* switch */
- } /* foreach ( state_list ) */
-
- /*
- ** We've checked every state in this state_list and none of them
- ** have failed. Since all of them succeeded, then we have a matching
- ** state list and we may be done.
- **
- ** The next requirement is that we have seen one of the resource's
- ** locktokens (if any). If we have, then we can just exit. If we
- ** haven't, then we need to keep looking.
- */
- if (seen_locktoken) {
- /* woo hoo! */
- return NULL;
- }
-
- /*
- ** Haven't seen one. Let's break out of the search and just look
- ** for a matching locktoken.
- */
- break;
-
- /*
- ** This label is used when we detect that a state_list is not
- ** going to match this resource. We bust out and try the next
- ** state_list.
- */
- state_list_failed:
- ;
-
- } /* foreach ( ifhdr_scan ) */
-
- /*
- ** The above loop exits for one of two reasons:
- ** 1) a state_list matched and seen_locktoken is false.
- ** 2) all if_header structures were scanned, without (1) occurring
- */
-
- if (ifhdr_scan == NULL) {
- /*
- ** We finished the loop without finding any matching state lists.
- */
-
- /*
- ** If none of the state_lists apply to this resource, then we
- ** may have succeeded. Note that this scenario implies a
- ** tagged-list with no matching state_lists. If the If: header
- ** was a no-tag-list, then it would have applied to this resource.
- **
- ** S9.4.2 states that when no state_lists apply, then the header
- ** should be ignored.
- **
- ** If we saw one of the resource's locktokens, then we're done.
- ** If we did not see a locktoken, then we fail.
- */
- if (num_that_apply == 0) {
- if (seen_locktoken)
- return NULL;
-
- /*
- ** We may have aborted the scan before seeing the locktoken.
- ** Rescan the If: header to see if we can find the locktoken
- ** somewhere.
- **
- ** Note that seen_locktoken == 0 implies lock_list != NULL
- ** which implies locks_hooks != NULL.
- */
- if (dav_find_submitted_locktoken(if_header, lock_list,
- locks_hooks)) {
- /*
- ** We found a match! We're set... none of the If: header
- ** assertions apply (implicit success), and the If: header
- ** specified the locktoken somewhere. We're done.
- */
- return NULL;
- }
-
- return dav_new_error(p, HTTP_LOCKED, 0 /* error_id */,
- "This resource is locked and the \"If:\" "
- "header did not specify one of the "
- "locktokens for this resource's lock(s).");
- }
- /* else: one or more state_lists were applicable, but failed. */
-
- /*
- ** If the dummy_header did not match, then they specified an
- ** incorrect token in the Lock-Token header. Forget whether the
- ** If: statement matched or not... we'll tell them about the
- ** bad Lock-Token first. That is considered a 400 (Bad Request).
- */
- if (if_header->dummy_header) {
- return dav_new_error(p, HTTP_BAD_REQUEST, 0,
- "The locktoken specified in the "
- "\"Lock-Token:\" header did not specify one "
- "of this resource's locktoken(s).");
- }
-
- if (reason == NULL) {
- return dav_new_error(p, HTTP_PRECONDITION_FAILED, 0,
- "The preconditions specified by the \"If:\" "
- "header did not match this resource.");
- }
-
- return dav_new_error(p, HTTP_PRECONDITION_FAILED, 0,
- apr_psprintf(p,
- "The precondition(s) specified by "
- "the \"If:\" header did not match "
- "this resource. At least one "
- "failure is because: %s", reason));
- }
-
- /* assert seen_locktoken == 0 */
-
- /*
- ** ifhdr_scan != NULL implies we found a matching state_list.
- **
- ** Since we're still here, it also means that we have not yet found
- ** one the resource's locktokens in the If: header.
- **
- ** Scan all the if_headers and states looking for one of this
- ** resource's locktokens. Note that we need to go back and scan them
- ** all -- we may have aborted a scan with a failure before we saw a
- ** matching token.
- **
- ** Note that seen_locktoken == 0 implies lock_list != NULL which implies
- ** locks_hooks != NULL.
- */
- if (dav_find_submitted_locktoken(if_header, lock_list, locks_hooks)) {
- /*
- ** We found a match! We're set... we have a matching state list,
- ** and the If: header specified the locktoken somewhere. We're done.
- */
- return NULL;
- }
-
- /*
- ** We had a matching state list, but the user agent did not specify one
- ** of this resource's locktokens. Tell them so.
- **
- ** Note that we need to special-case the message on whether a "dummy"
- ** header exists. If it exists, yet we didn't see a needed locktoken,
- ** then that implies the dummy header (Lock-Token header) did NOT
- ** specify one of this resource's locktokens. (this implies something
- ** in the real If: header matched)
- **
- ** We want to note the 400 (Bad Request) in favor of a 423 (Locked).
- */
- if (if_header->dummy_header) {
- return dav_new_error(p, HTTP_BAD_REQUEST, 0,
- "The locktoken specified in the "
- "\"Lock-Token:\" header did not specify one "
- "of this resource's locktoken(s).");
- }
-
- return dav_new_error(p, HTTP_LOCKED, 1 /* error_id */,
- "This resource is locked and the \"If:\" header "
- "did not specify one of the "
- "locktokens for this resource's lock(s).");
-}
-
-/* dav_validate_walker: Walker callback function to validate resource state */
-static dav_error * dav_validate_walker(dav_walk_resource *wres, int calltype)
-{
- dav_walker_ctx *ctx = wres->walk_ctx;
- dav_error *err;
-
- if ((err = dav_validate_resource_state(ctx->w.pool, wres->resource,
- ctx->w.lockdb,
- ctx->if_header, ctx->flags,
- &ctx->work_buf, ctx->r)) == NULL) {
- /* There was no error, so just bug out. */
- return NULL;
- }
-
- /*
- ** If we have a serious server error, or if the request itself failed,
- ** then just return error (not a multistatus).
- */
- if (ap_is_HTTP_SERVER_ERROR(err->status)
- || (*wres->resource->hooks->is_same_resource)(wres->resource,
- ctx->w.root)) {
- /* ### maybe push a higher-level description? */
- return err;
- }
-
- /* associate the error with the current URI */
- dav_add_response(wres, err->status, NULL);
-
- return NULL;
-}
-
-/*
-** dav_validate_request: Validate if-headers (and check for locks) on:
-** (1) r->filename @ depth;
-** (2) Parent of r->filename if check_parent == 1
-**
-** The check of parent should be done when it is necessary to verify that
-** the parent collection will accept a new member (ie current resource
-** state is null).
-**
-** Return OK on successful validation.
-** On error, return appropriate HTTP_* code, and log error. If a multi-stat
-** error is necessary, response will point to it, else NULL.
-*/
-dav_error * dav_validate_request(request_rec *r, dav_resource *resource,
- int depth, dav_locktoken *locktoken,
- dav_response **response, int flags,
- dav_lockdb *lockdb)
-{
- dav_error *err;
- int result;
- dav_if_header *if_header;
- int lock_db_opened_locally = 0;
- const dav_hooks_locks *locks_hooks = DAV_GET_HOOKS_LOCKS(r);
- const dav_hooks_repository *repos_hooks = resource->hooks;
- dav_buffer work_buf = { 0 };
- dav_response *new_response;
-
-#if DAV_DEBUG
- if (depth && response == NULL) {
- /*
- ** ### bleck. we can't return errors for other URIs unless we have
- ** ### a "response" ptr.
- */
- return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
- "DESIGN ERROR: dav_validate_request called "
- "with depth>0, but no response ptr.");
- }
-#endif
-
- if (response != NULL)
- *response = NULL;
-
- /* Do the standard checks for conditional requests using
- * If-..-Since, If-Match etc */
- if ((result = ap_meets_conditions(r)) != OK) {
- /* ### fix this up... how? */
- return dav_new_error(r->pool, result, 0, NULL);
- }
-
- /* always parse (and later process) the If: header */
- if ((err = dav_process_if_header(r, &if_header)) != NULL) {
- /* ### maybe add higher-level description */
- return err;
- }
-
- /* If a locktoken was specified, create a dummy if_header with which
- * to validate resources. In the interim, figure out why DAV uses
- * locktokens in an if-header without a Lock-Token header to refresh
- * locks, but a Lock-Token header without an if-header to remove them.
- */
- if (locktoken != NULL) {
- dav_if_header *ifhdr_new;
-
- ifhdr_new = apr_pcalloc(r->pool, sizeof(*ifhdr_new));
- ifhdr_new->uri = resource->uri;
- ifhdr_new->uri_len = strlen(resource->uri);
- ifhdr_new->dummy_header = 1;
-
- ifhdr_new->state = apr_pcalloc(r->pool, sizeof(*ifhdr_new->state));
- ifhdr_new->state->type = dav_if_opaquelock;
- ifhdr_new->state->condition = DAV_IF_COND_NORMAL;
- ifhdr_new->state->locktoken = locktoken;
-
- ifhdr_new->next = if_header;
- if_header = ifhdr_new;
- }
-
- /*
- ** If necessary, open the lock database (read-only, lazily);
- ** the validation process may need to retrieve or update lock info.
- ** Otherwise, assume provided lockdb is valid and opened rw.
- */
- if (lockdb == NULL) {
- if (locks_hooks != NULL) {
- if ((err = (*locks_hooks->open_lockdb)(r, 0, 0, &lockdb)) != NULL) {
- /* ### maybe insert higher-level comment */
- return err;
- }
- lock_db_opened_locally = 1;
- }
- }
-
- /* (1) Validate the specified resource, at the specified depth */
- if (resource->exists && depth > 0) {
- dav_walker_ctx ctx = { { 0 } };
- dav_response *multi_status;
-
- ctx.w.walk_type = DAV_WALKTYPE_NORMAL;
- ctx.w.func = dav_validate_walker;
- ctx.w.walk_ctx = &ctx;
- ctx.w.pool = r->pool;
- ctx.w.root = resource;
-
- ctx.if_header = if_header;
- ctx.r = r;
- ctx.flags = flags;
-
- if (lockdb != NULL) {
- ctx.w.lockdb = lockdb;
- ctx.w.walk_type |= DAV_WALKTYPE_LOCKNULL;
- }
-
- err = (*repos_hooks->walk)(&ctx.w, DAV_INFINITY, &multi_status);
- if (err == NULL) {
- *response = multi_status;;
- }
- /* else: implies a 5xx status code occurred. */
- }
- else {
- err = dav_validate_resource_state(r->pool, resource, lockdb,
- if_header, flags, &work_buf, r);
- }
-
- /* (2) Validate the parent resource if requested */
- if (err == NULL && (flags & DAV_VALIDATE_PARENT)) {
- dav_resource *parent_resource;
-
- err = (*repos_hooks->get_parent_resource)(resource, &parent_resource);
-
- if (err == NULL && parent_resource == NULL) {
- err = dav_new_error(r->pool, HTTP_FORBIDDEN, 0,
- "Cannot access parent of repository root.");
- }
- else if (err == NULL) {
- err = dav_validate_resource_state(r->pool, parent_resource, lockdb,
- if_header,
- flags | DAV_VALIDATE_IS_PARENT,
- &work_buf, r);
-
- /*
- ** This error occurred on the parent resource. This implies that
- ** we have to create a multistatus response (to report the error
- ** against a URI other than the Request-URI). "Convert" this error
- ** into a multistatus response.
- */
- if (err != NULL) {
- new_response = apr_pcalloc(r->pool, sizeof(*new_response));
-
- new_response->href = parent_resource->uri;
- new_response->status = err->status;
- new_response->desc =
- "A validation error has occurred on the parent resource, "
- "preventing the operation on the resource specified by "
- "the Request-URI.";
- if (err->desc != NULL) {
- new_response->desc = apr_pstrcat(r->pool,
- new_response->desc,
- " The error was: ",
- err->desc, NULL);
- }
-
- /* assert: DAV_VALIDATE_PARENT implies response != NULL */
- new_response->next = *response;
- *response = new_response;
-
- err = NULL;
- }
- }
- }
-
- if (lock_db_opened_locally)
- (*locks_hooks->close_lockdb)(lockdb);
-
- /*
- ** If we don't have a (serious) error, and we have multistatus responses,
- ** then we need to construct an "error". This error will be the overall
- ** status returned, and the multistatus responses will go into its body.
- **
- ** For certain methods, the overall error will be a 424. The default is
- ** to construct a standard 207 response.
- */
- if (err == NULL && response != NULL && *response != NULL) {
- ap_text *propstat = NULL;
-
- if ((flags & DAV_VALIDATE_USE_424) != 0) {
- /* manufacture a 424 error to hold the multistatus response(s) */
- return dav_new_error(r->pool, HTTP_FAILED_DEPENDENCY, 0,
- "An error occurred on another resource, "
- "preventing the requested operation on "
- "this resource.");
- }
-
- /*
- ** Whatever caused the error, the Request-URI should have a 424
- ** associated with it since we cannot complete the method.
- **
- ** For a LOCK operation, insert an empty DAV:lockdiscovery property.
- ** For other methods, return a simple 424.
- */
- if ((flags & DAV_VALIDATE_ADD_LD) != 0) {
- propstat = apr_pcalloc(r->pool, sizeof(*propstat));
- propstat->text =
- "<D:propstat>" DEBUG_CR
- "<D:prop><D:lockdiscovery/></D:prop>" DEBUG_CR
- "<D:status>HTTP/1.1 424 Failed Dependency</D:status>" DEBUG_CR
- "</D:propstat>" DEBUG_CR;
- }
-
- /* create the 424 response */
- new_response = apr_pcalloc(r->pool, sizeof(*new_response));
- new_response->href = resource->uri;
- new_response->status = HTTP_FAILED_DEPENDENCY;
- new_response->propresult.propstats = propstat;
- new_response->desc =
- "An error occurred on another resource, preventing the "
- "requested operation on this resource.";
-
- new_response->next = *response;
- *response = new_response;
-
- /* manufacture a 207 error for the multistatus response(s) */
- return dav_new_error(r->pool, HTTP_MULTI_STATUS, 0,
- "Error(s) occurred on resources during the "
- "validation process.");
- }
-
- return err;
-}
-
-/* dav_get_locktoken_list:
- *
- * Sets ltl to a locktoken_list of all positive locktokens in header,
- * else NULL if no If-header, or no positive locktokens.
- */
-dav_error * dav_get_locktoken_list(request_rec *r, dav_locktoken_list **ltl)
-{
- dav_error *err;
- dav_if_header *if_header;
- dav_if_state_list *if_state;
- dav_locktoken_list *lock_token = NULL;
-
- *ltl = NULL;
-
- if ((err = dav_process_if_header(r, &if_header)) != NULL) {
- /* ### add a higher-level description? */
- return err;
- }
-
- while (if_header != NULL) {
- if_state = if_header->state; /* Begining of the if_state linked list */
- while (if_state != NULL) {
- if (if_state->condition == DAV_IF_COND_NORMAL
- && if_state->type == dav_if_opaquelock) {
- lock_token = apr_pcalloc(r->pool, sizeof(dav_locktoken_list));
- lock_token->locktoken = if_state->locktoken;
- lock_token->next = *ltl;
- *ltl = lock_token;
- }
- if_state = if_state->next;
- }
- if_header = if_header->next;
- }
- if (*ltl == NULL) {
- /* No nodes added */
- return dav_new_error(r->pool, HTTP_BAD_REQUEST, DAV_ERR_IF_ABSENT,
- "No locktokens were specified in the \"If:\" "
- "header, so the refresh could not be performed.");
- }
-
- return NULL;
-}
-
-#if 0 /* not needed right now... */
-
-static const char *strip_white(const char *s, apr_pool_t *pool)
-{
- apr_size_t idx;
-
- /* trim leading whitespace */
- while (apr_isspace(*s)) /* assume: return false for '\0' */
- ++s;
-
- /* trim trailing whitespace */
- idx = strlen(s) - 1;
- if (apr_isspace(s[idx])) {
- char *s2 = apr_pstrdup(pool, s);
-
- while (apr_isspace(s2[idx]) && idx > 0)
- --idx;
- s2[idx + 1] = '\0';
- return s2;
- }
-
- return s;
-}
-#endif
-
-#define DAV_LABEL_HDR "Label"
-
-/* dav_add_vary_header
- *
- * If there were any headers in the request which require a Vary header
- * in the response, add it.
- */
-void dav_add_vary_header(request_rec *in_req,
- request_rec *out_req,
- const dav_resource *resource)
-{
- const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(in_req);
-
- /* ### this is probably all wrong... I think there is a function in
- ### the Apache API to add things to the Vary header. need to check */
-
- /* Only versioning headers require a Vary response header,
- * so only do this check if there is a versioning provider */
- if (vsn_hooks != NULL) {
- const char *target = apr_table_get(in_req->headers_in, DAV_LABEL_HDR);
- const char *vary = apr_table_get(out_req->headers_out, "Vary");
-
- /* If Target-Selector specified, add it to the Vary header */
- if (target != NULL) {
- if (vary == NULL)
- vary = DAV_LABEL_HDR;
- else
- vary = apr_pstrcat(out_req->pool, vary, "," DAV_LABEL_HDR,
- NULL);
-
- apr_table_setn(out_req->headers_out, "Vary", vary);
- }
- }
-}
-
-/* dav_can_auto_checkout
- *
- * Determine whether auto-checkout is enabled for a resource.
- * r - the request_rec
- * resource - the resource
- * auto_version - the value of the auto_versionable hook for the resource
- * lockdb - pointer to lock database (opened if necessary)
- * auto_checkout - set to 1 if auto-checkout enabled
- */
-static dav_error * dav_can_auto_checkout(
- request_rec *r,
- dav_resource *resource,
- dav_auto_version auto_version,
- dav_lockdb **lockdb,
- int *auto_checkout)
-{
- dav_error *err;
- dav_lock *lock_list;
-
- *auto_checkout = 0;
-
- if (auto_version == DAV_AUTO_VERSION_ALWAYS) {
- *auto_checkout = 1;
- }
- else if (auto_version == DAV_AUTO_VERSION_LOCKED) {
- if (*lockdb == NULL) {
- const dav_hooks_locks *locks_hooks = DAV_GET_HOOKS_LOCKS(r);
-
- if (locks_hooks == NULL) {
- return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
- "Auto-checkout is only enabled for locked resources, "
- "but there is no lock provider.");
- }
-
- if ((err = (*locks_hooks->open_lockdb)(r, 0, 0, lockdb)) != NULL) {
- return dav_push_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
- "Cannot open lock database to determine "
- "auto-versioning behavior.",
- err);
- }
- }
-
- if ((err = dav_lock_query(*lockdb, resource, &lock_list)) != NULL) {
- return dav_push_error(r->pool,
- HTTP_INTERNAL_SERVER_ERROR, 0,
- "The locks could not be queried for "
- "determining auto-versioning behavior.",
- err);
- }
-
- if (lock_list != NULL)
- *auto_checkout = 1;
- }
-
- return NULL;
-}
-
-/* see mod_dav.h for docco */
-dav_error *dav_auto_checkout(
- request_rec *r,
- dav_resource *resource,
- int parent_only,
- dav_auto_version_info *av_info)
-{
- const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
- dav_lockdb *lockdb = NULL;
- dav_error *err = NULL;
-
- /* Initialize results */
- memset(av_info, 0, sizeof(*av_info));
-
- /* if no versioning provider, just return */
- if (vsn_hooks == NULL)
- return NULL;
-
- /* check parent resource if requested or if resource must be created */
- if (!resource->exists || parent_only) {
- dav_resource *parent;
-
- if ((err = (*resource->hooks->get_parent_resource)(resource,
- &parent)) != NULL)
- goto done;
-
- if (parent == NULL || !parent->exists) {
- err = dav_new_error(r->pool, HTTP_CONFLICT, 0,
- apr_psprintf(r->pool,
- "Missing one or more intermediate "
- "collections. Cannot create resource %s.",
- ap_escape_html(r->pool, resource->uri)));
- goto done;
- }
-
- av_info->parent_resource = parent;
-
- /* if parent versioned and not checked out, see if it can be */
- if (parent->versioned && !parent->working) {
- int checkout_parent;
-
- if ((err = dav_can_auto_checkout(r, parent,
- (*vsn_hooks->auto_versionable)(parent),
- &lockdb, &checkout_parent))
- != NULL) {
- goto done;
- }
-
- if (!checkout_parent) {
- err = dav_new_error(r->pool, HTTP_CONFLICT, 0,
- "<DAV:cannot-modify-checked-in-parent>");
- goto done;
- }
-
- /* Try to checkout the parent collection.
- * Note that auto-versioning can only be applied to a version selector,
- * so no separate working resource will be created.
- */
- if ((err = (*vsn_hooks->checkout)(parent, 1 /*auto_checkout*/,
- 0, 0, 0, NULL, NULL))
- != NULL)
- {
- err = dav_push_error(r->pool, HTTP_CONFLICT, 0,
- apr_psprintf(r->pool,
- "Unable to auto-checkout parent collection. "
- "Cannot create resource %s.",
- ap_escape_html(r->pool, resource->uri)),
- err);
- goto done;
- }
-
- /* remember that parent was checked out */
- av_info->parent_checkedout = 1;
- }
- }
-
- /* if only checking parent, we're done */
- if (parent_only)
- goto done;
-
- /* if creating a new resource, see if it should be version-controlled */
- if (!resource->exists
- && (*vsn_hooks->auto_versionable)(resource) == DAV_AUTO_VERSION_ALWAYS) {
-
- if ((err = (*vsn_hooks->vsn_control)(resource, NULL)) != NULL) {
- err = dav_push_error(r->pool, HTTP_CONFLICT, 0,
- apr_psprintf(r->pool,
- "Unable to create versioned resource %s.",
- ap_escape_html(r->pool, resource->uri)),
- err);
- goto done;
- }
-
- /* remember that resource was created */
- av_info->resource_versioned = 1;
- }
-
- /* if resource is versioned, make sure it is checked out */
- if (resource->versioned && !resource->working) {
- int checkout_resource;
-
- if ((err = dav_can_auto_checkout(r, resource,
- (*vsn_hooks->auto_versionable)(resource),
- &lockdb, &checkout_resource)) != NULL) {
- goto done;
- }
-
- if (!checkout_resource) {
- err = dav_new_error(r->pool, HTTP_CONFLICT, 0,
- "<DAV:cannot-modify-version-controlled-content>");
- goto done;
- }
-
- /* Auto-versioning can only be applied to version selectors, so
- * no separate working resource will be created. */
- if ((err = (*vsn_hooks->checkout)(resource, 1 /*auto_checkout*/,
- 0, 0, 0, NULL, NULL))
- != NULL)
- {
- err = dav_push_error(r->pool, HTTP_CONFLICT, 0,
- apr_psprintf(r->pool,
- "Unable to checkout resource %s.",
- ap_escape_html(r->pool, resource->uri)),
- err);
- goto done;
- }
-
- /* remember that resource was checked out */
- av_info->resource_checkedout = 1;
- }
-
-done:
-
- /* make sure lock database is closed */
- if (lockdb != NULL)
- (*lockdb->hooks->close_lockdb)(lockdb);
-
- /* if an error occurred, undo any auto-versioning operations already done */
- if (err != NULL) {
- dav_auto_checkin(r, resource, 1 /*undo*/, 0 /*unlock*/, av_info);
- return err;
- }
-
- return NULL;
-}
-
-/* see mod_dav.h for docco */
-dav_error *dav_auto_checkin(
- request_rec *r,
- dav_resource *resource,
- int undo,
- int unlock,
- dav_auto_version_info *av_info)
-{
- const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
- dav_error *err = NULL;
- dav_auto_version auto_version;
-
- /* If no versioning provider, this is a no-op */
- if (vsn_hooks == NULL)
- return NULL;
-
- /* If undoing auto-checkouts, then do uncheckouts */
- if (undo) {
- if (resource != NULL) {
- if (av_info->resource_checkedout) {
- if ((err = (*vsn_hooks->uncheckout)(resource)) != NULL) {
- return dav_push_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
- apr_psprintf(r->pool,
- "Unable to undo auto-checkout "
- "of resource %s.",
- ap_escape_html(r->pool, resource->uri)),
- err);
- }
- }
-
- if (av_info->resource_versioned) {
- dav_response *response;
-
- /* ### should we do anything with the response? */
- if ((err = (*resource->hooks->remove_resource)(resource,
- &response)) != NULL) {
- return dav_push_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
- apr_psprintf(r->pool,
- "Unable to undo auto-version-control "
- "of resource %s.",
- ap_escape_html(r->pool, resource->uri)),
- err);
- }
- }
- }
-
- if (av_info->parent_resource != NULL && av_info->parent_checkedout) {
- if ((err = (*vsn_hooks->uncheckout)(av_info->parent_resource)) != NULL) {
- return dav_push_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
- apr_psprintf(r->pool,
- "Unable to undo auto-checkout "
- "of parent collection %s.",
- ap_escape_html(r->pool, av_info->parent_resource->uri)),
- err);
- }
- }
-
- return NULL;
- }
-
- /* If the resource was checked out, and auto-checkin is enabled,
- * then check it in.
- */
- if (resource != NULL && resource->working
- && (unlock || av_info->resource_checkedout)) {
-
- auto_version = (*vsn_hooks->auto_versionable)(resource);
-
- if (auto_version == DAV_AUTO_VERSION_ALWAYS ||
- (unlock && (auto_version == DAV_AUTO_VERSION_LOCKED))) {
-
- if ((err = (*vsn_hooks->checkin)(resource,
- 0 /*keep_checked_out*/, NULL))
- != NULL) {
- return dav_push_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
- apr_psprintf(r->pool,
- "Unable to auto-checkin resource %s.",
- ap_escape_html(r->pool, resource->uri)),
- err);
- }
- }
- }
-
- /* If parent resource was checked out, and auto-checkin is enabled,
- * then check it in.
- */
- if (av_info->parent_resource != NULL && av_info->parent_resource->working
- && (unlock || av_info->parent_checkedout)) {
-
- auto_version = (*vsn_hooks->auto_versionable)(av_info->parent_resource);
-
- if (auto_version == DAV_AUTO_VERSION_ALWAYS ||
- (unlock && (auto_version == DAV_AUTO_VERSION_LOCKED))) {
-
- if ((err = (*vsn_hooks->checkin)(av_info->parent_resource,
- 0 /*keep_checked_out*/, NULL))
- != NULL) {
- return dav_push_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
- apr_psprintf(r->pool,
- "Unable to auto-checkin parent collection %s.",
- ap_escape_html(r->pool, av_info->parent_resource->uri)),
- err);
- }
- }
- }
-
- return NULL;
-}
diff --git a/modules/dav/main/util_lock.c b/modules/dav/main/util_lock.c
deleted file mode 100644
index ff59b58e4a..0000000000
--- a/modules/dav/main/util_lock.c
+++ /dev/null
@@ -1,826 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-/*
-** DAV repository-independent lock functions
-*/
-
-#include "apr.h"
-#include "apr_strings.h"
-
-#if APR_HAVE_STDIO_H
-#include <stdio.h> /* for sprintf() */
-#endif
-
-#include "mod_dav.h"
-#include "http_log.h"
-#include "http_config.h"
-#include "http_protocol.h"
-#include "http_core.h"
-
-
-/* ---------------------------------------------------------------
-**
-** Property-related lock functions
-**
-*/
-
-/*
-** dav_lock_get_activelock: Returns a <lockdiscovery> containing
-** an activelock element for every item in the lock_discovery tree
-*/
-const char *dav_lock_get_activelock(request_rec *r, dav_lock *lock,
- dav_buffer *pbuf)
-{
- dav_lock *lock_scan;
- const dav_hooks_locks *hooks = DAV_GET_HOOKS_LOCKS(r);
- int count = 0;
- dav_buffer work_buf = { 0 };
- apr_pool_t *p = r->pool;
-
- /* If no locks or no lock provider, there are no locks */
- if (lock == NULL || hooks == NULL) {
- /*
- ** Since resourcediscovery is defined with (activelock)*,
- ** <D:activelock/> shouldn't be necessary for an empty lock.
- */
- return "";
- }
-
- /*
- ** Note: it could be interesting to sum the lengths of the owners
- ** and locktokens during this loop. However, the buffer
- ** mechanism provides some rough padding so that we don't
- ** really need to have an exact size. Further, constructing
- ** locktoken strings could be relatively expensive.
- */
- for (lock_scan = lock; lock_scan != NULL; lock_scan = lock_scan->next)
- count++;
-
- /* if a buffer was not provided, then use an internal buffer */
- if (pbuf == NULL)
- pbuf = &work_buf;
-
- /* reset the length before we start appending stuff */
- pbuf->cur_len = 0;
-
- /* prep the buffer with a "good" size */
- dav_check_bufsize(p, pbuf, count * 300);
-
- for (; lock != NULL; lock = lock->next) {
- char tmp[100];
-
-#if DAV_DEBUG
- if (lock->rectype == DAV_LOCKREC_INDIRECT_PARTIAL) {
- /* ### crap. design error */
- dav_buffer_append(p, pbuf,
- "DESIGN ERROR: attempted to product an "
- "activelock element from a partial, indirect "
- "lock record. Creating an XML parsing error "
- "to ease detection of this situation: <");
- }
-#endif
-
- dav_buffer_append(p, pbuf, "<D:activelock>" DEBUG_CR "<D:locktype>");
- switch (lock->type) {
- case DAV_LOCKTYPE_WRITE:
- dav_buffer_append(p, pbuf, "<D:write/>");
- break;
- default:
- /* ### internal error. log something? */
- break;
- }
- dav_buffer_append(p, pbuf, "</D:locktype>" DEBUG_CR "<D:lockscope>");
- switch (lock->scope) {
- case DAV_LOCKSCOPE_EXCLUSIVE:
- dav_buffer_append(p, pbuf, "<D:exclusive/>");
- break;
- case DAV_LOCKSCOPE_SHARED:
- dav_buffer_append(p, pbuf, "<D:shared/>");
- break;
- default:
- /* ### internal error. log something? */
- break;
- }
- dav_buffer_append(p, pbuf, "</D:lockscope>" DEBUG_CR);
- sprintf(tmp, "<D:depth>%s</D:depth>" DEBUG_CR,
- lock->depth == DAV_INFINITY ? "infinity" : "0");
- dav_buffer_append(p, pbuf, tmp);
-
- if (lock->owner) {
- /*
- ** This contains a complete, self-contained <DAV:owner> element,
- ** with namespace declarations and xml:lang handling. Just drop
- ** it in.
- */
- dav_buffer_append(p, pbuf, lock->owner);
- }
-
- dav_buffer_append(p, pbuf, "<D:timeout>");
- if (lock->timeout == DAV_TIMEOUT_INFINITE) {
- dav_buffer_append(p, pbuf, "Infinite");
- }
- else {
- time_t now = time(NULL);
- sprintf(tmp, "Second-%lu", (long unsigned int)(lock->timeout - now));
- dav_buffer_append(p, pbuf, tmp);
- }
-
- dav_buffer_append(p, pbuf,
- "</D:timeout>" DEBUG_CR
- "<D:locktoken>" DEBUG_CR
- "<D:href>");
- dav_buffer_append(p, pbuf,
- (*hooks->format_locktoken)(p, lock->locktoken));
- dav_buffer_append(p, pbuf,
- "</D:href>" DEBUG_CR
- "</D:locktoken>" DEBUG_CR
- "</D:activelock>" DEBUG_CR);
- }
-
- return pbuf->buf;
-}
-
-/*
-** dav_lock_parse_lockinfo: Validates the given xml_doc to contain a
-** lockinfo XML element, then populates a dav_lock structure
-** with its contents.
-*/
-dav_error * dav_lock_parse_lockinfo(request_rec *r,
- const dav_resource *resource,
- dav_lockdb *lockdb,
- const ap_xml_doc *doc,
- dav_lock **lock_request)
-{
- apr_pool_t *p = r->pool;
- dav_error *err;
- ap_xml_elem *child;
- dav_lock *lock;
-
- if (!dav_validate_root(doc, "lockinfo")) {
- return dav_new_error(p, HTTP_BAD_REQUEST, 0,
- "The request body contains an unexpected "
- "XML root element.");
- }
-
- if ((err = (*lockdb->hooks->create_lock)(lockdb, resource,
- &lock)) != NULL) {
- return dav_push_error(p, err->status, 0,
- "Could not parse the lockinfo due to an "
- "internal problem creating a lock structure.",
- err);
- }
-
- lock->depth = dav_get_depth(r, DAV_INFINITY);
- if (lock->depth == -1) {
- return dav_new_error(p, HTTP_BAD_REQUEST, 0,
- "An invalid Depth header was specified.");
- }
- lock->timeout = dav_get_timeout(r);
-
- /* Parse elements in the XML body */
- for (child = doc->root->first_child; child; child = child->next) {
- if (strcmp(child->name, "locktype") == 0
- && child->first_child
- && lock->type == DAV_LOCKTYPE_UNKNOWN) {
- if (strcmp(child->first_child->name, "write") == 0) {
- lock->type = DAV_LOCKTYPE_WRITE;
- continue;
- }
- }
- if (strcmp(child->name, "lockscope") == 0
- && child->first_child
- && lock->scope == DAV_LOCKSCOPE_UNKNOWN) {
- if (strcmp(child->first_child->name, "exclusive") == 0)
- lock->scope = DAV_LOCKSCOPE_EXCLUSIVE;
- else if (strcmp(child->first_child->name, "shared") == 0)
- lock->scope = DAV_LOCKSCOPE_SHARED;
- if (lock->scope != DAV_LOCKSCOPE_UNKNOWN)
- continue;
- }
-
- if (strcmp(child->name, "owner") == 0 && lock->owner == NULL) {
- const char *text;
-
- /* quote all the values in the <DAV:owner> element */
- ap_xml_quote_elem(p, child);
-
- /*
- ** Store a full <DAV:owner> element with namespace definitions
- ** and an xml:lang definition, if applicable.
- */
- ap_xml_to_text(p, child, AP_XML_X2T_FULL_NS_LANG, doc->namespaces,
- NULL, &text, NULL);
- lock->owner = text;
-
- continue;
- }
-
- return dav_new_error(p, HTTP_PRECONDITION_FAILED, 0,
- apr_psprintf(p,
- "The server cannot satisfy the "
- "LOCK request due to an unknown XML "
- "element (\"%s\") within the "
- "DAV:lockinfo element.",
- child->name));
- }
-
- *lock_request = lock;
- return NULL;
-}
-
-/* ---------------------------------------------------------------
-**
-** General lock functions
-**
-*/
-
-/* dav_lock_walker: Walker callback function to record indirect locks */
-static dav_error * dav_lock_walker(dav_walk_resource *wres, int calltype)
-{
- dav_walker_ctx *ctx = wres->walk_ctx;
- dav_error *err;
-
- /* We don't want to set indirects on the target */
- if ((*wres->resource->hooks->is_same_resource)(wres->resource,
- ctx->w.root))
- return NULL;
-
- if ((err = (*ctx->w.lockdb->hooks->append_locks)(ctx->w.lockdb,
- wres->resource, 1,
- ctx->lock)) != NULL) {
- if (ap_is_HTTP_SERVER_ERROR(err->status)) {
- /* ### add a higher-level description? */
- return err;
- }
-
- /* add to the multistatus response */
- dav_add_response(wres, err->status, NULL);
-
- /*
- ** ### actually, this is probably wrong: we want to fail the whole
- ** ### LOCK process if something goes bad. maybe the caller should
- ** ### do a dav_unlock() (e.g. a rollback) if any errors occurred.
- */
- }
-
- return NULL;
-}
-
-/*
-** dav_add_lock: Add a direct lock for resource, and indirect locks for
-** all children, bounded by depth.
-** ### assume request only contains one lock
-*/
-dav_error * dav_add_lock(request_rec *r, const dav_resource *resource,
- dav_lockdb *lockdb, dav_lock *lock,
- dav_response **response)
-{
- dav_error *err;
- int depth = lock->depth;
-
- *response = NULL;
-
- /* Requested lock can be:
- * Depth: 0 for null resource, existing resource, or existing collection
- * Depth: Inf for existing collection
- */
-
- /*
- ** 2518 9.2 says to ignore depth if target is not a collection (it has
- ** no internal children); pretend the client gave the correct depth.
- */
- if (!resource->collection) {
- depth = 0;
- }
-
- /* In all cases, first add direct entry in lockdb */
-
- /*
- ** Append the new (direct) lock to the resource's existing locks.
- **
- ** Note: this also handles locknull resources
- */
- if ((err = (*lockdb->hooks->append_locks)(lockdb, resource, 0,
- lock)) != NULL) {
- /* ### maybe add a higher-level description */
- return err;
- }
-
- if (depth > 0) {
- /* Walk existing collection and set indirect locks */
- dav_walker_ctx ctx = { { 0 } };
- dav_response *multi_status;
-
- ctx.w.walk_type = DAV_WALKTYPE_NORMAL | DAV_WALKTYPE_AUTH;
- ctx.w.func = dav_lock_walker;
- ctx.w.walk_ctx = &ctx;
- ctx.w.pool = r->pool;
- ctx.w.root = resource;
- ctx.w.lockdb = lockdb;
-
- ctx.r = r;
- ctx.lock = lock;
-
- err = (*resource->hooks->walk)(&ctx.w, DAV_INFINITY, &multi_status);
- if (err != NULL) {
- /* implies a 5xx status code occurred. screw the multistatus */
- return err;
- }
-
- if (multi_status != NULL) {
- /* manufacture a 207 error for the multistatus response */
- *response = multi_status;
- return dav_new_error(r->pool, HTTP_MULTI_STATUS, 0,
- "Error(s) occurred on resources during the "
- "addition of a depth lock.");
- }
- }
-
- return NULL;
-}
-
-/*
-** dav_lock_query: Opens the lock database. Returns a linked list of
-** dav_lock structures for all direct locks on path.
-*/
-DAV_DECLARE(dav_error*) dav_lock_query(dav_lockdb *lockdb,
- const dav_resource *resource,
- dav_lock **locks)
-{
- /* If no lock database, return empty result */
- if (lockdb == NULL) {
- *locks = NULL;
- return NULL;
- }
-
- /* ### insert a higher-level description? */
- return (*lockdb->hooks->get_locks)(lockdb, resource,
- DAV_GETLOCKS_RESOLVED,
- locks);
-}
-
-/* dav_unlock_walker: Walker callback function to remove indirect locks */
-static dav_error * dav_unlock_walker(dav_walk_resource *wres, int calltype)
-{
- dav_walker_ctx *ctx = wres->walk_ctx;
- dav_error *err;
-
- /* Before removing the lock, do any auto-checkin required */
- if (wres->resource->working) {
- /* ### get rid of this typecast */
- if ((err = dav_auto_checkin(ctx->r, (dav_resource *) wres->resource,
- 0 /*undo*/, 1 /*unlock*/, NULL))
- != NULL) {
- return err;
- }
- }
-
- if ((err = (*ctx->w.lockdb->hooks->remove_lock)(ctx->w.lockdb,
- wres->resource,
- ctx->locktoken)) != NULL) {
- /* ### should we stop or return a multistatus? looks like STOP */
- /* ### add a higher-level description? */
- return err;
- }
-
- return NULL;
-}
-
-/*
-** dav_get_direct_resource:
-**
-** Find a lock on the specified resource, then return the resource the
-** lock was applied to (in other words, given a (possibly) indirect lock,
-** return the direct lock's corresponding resource).
-**
-** If the lock is an indirect lock, this usually means traversing up the
-** namespace [repository] hierarchy. Note that some lock providers may be
-** able to return this information with a traversal.
-*/
-static dav_error * dav_get_direct_resource(apr_pool_t *p,
- dav_lockdb *lockdb,
- const dav_locktoken *locktoken,
- const dav_resource *resource,
- const dav_resource **direct_resource)
-{
- if (lockdb->hooks->lookup_resource != NULL) {
- return (*lockdb->hooks->lookup_resource)(lockdb, locktoken,
- resource, direct_resource);
- }
-
- *direct_resource = NULL;
-
- /* Find the top of this lock-
- * If r->filename's direct locks include locktoken, use r->filename.
- * If r->filename's indirect locks include locktoken, retry r->filename/..
- * Else fail.
- */
- while (resource != NULL) {
- dav_error *err;
- dav_lock *lock;
- dav_resource *parent;
-
- /*
- ** Find the lock specified by <locktoken> on <resource>. If it is
- ** an indirect lock, then partial results are okay. We're just
- ** trying to find the thing and know whether it is a direct or
- ** an indirect lock.
- */
- if ((err = (*lockdb->hooks->find_lock)(lockdb, resource, locktoken,
- 1, &lock)) != NULL) {
- /* ### add a higher-level desc? */
- return err;
- }
-
- /* not found! that's an error. */
- if (lock == NULL) {
- return dav_new_error(p, HTTP_BAD_REQUEST, 0,
- "The specified locktoken does not correspond "
- "to an existing lock on this resource.");
- }
-
- if (lock->rectype == DAV_LOCKREC_DIRECT) {
- /* we found the direct lock. return this resource. */
-
- *direct_resource = resource;
- return NULL;
- }
-
- /* the lock was indirect. move up a level in the URL namespace */
- if ((err = (*resource->hooks->get_parent_resource)(resource,
- &parent)) != NULL) {
- /* ### add a higher-level desc? */
- return err;
- }
- resource = parent;
- }
-
- return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
- "The lock database is corrupt. A direct lock could "
- "not be found for the corresponding indirect lock "
- "on this resource.");
-}
-
-/*
-** dav_unlock: Removes all direct and indirect locks for r->filename,
-** with given locktoken. If locktoken == null_locktoken, all locks
-** are removed. If r->filename represents an indirect lock,
-** we must unlock the appropriate direct lock.
-** Returns OK or appropriate HTTP_* response and logs any errors.
-**
-** ### We've already crawled the tree to ensure everything was locked
-** by us; there should be no need to incorporate a rollback.
-*/
-int dav_unlock(request_rec *r, const dav_resource *resource,
- const dav_locktoken *locktoken)
-{
- int result;
- dav_lockdb *lockdb;
- const dav_resource *lock_resource = resource;
- const dav_hooks_locks *hooks = DAV_GET_HOOKS_LOCKS(r);
- const dav_hooks_repository *repos_hooks = resource->hooks;
- dav_walker_ctx ctx = { { 0 } };
- dav_response *multi_status;
- dav_error *err;
-
- /* If no locks provider, then there is nothing to unlock. */
- if (hooks == NULL) {
- return OK;
- }
-
- /* 2518 requires the entire lock to be removed if resource/locktoken
- * point to an indirect lock. We need resource of the _direct_
- * lock in order to walk down the tree and remove the locks. So,
- * If locktoken != null_locktoken,
- * Walk up the resource hierarchy until we see a direct lock.
- * Or, we could get the direct lock's db/key, pick out the URL
- * and do a subrequest. I think walking up is faster and will work
- * all the time.
- * Else
- * Just start removing all locks at and below resource.
- */
-
- if ((err = (*hooks->open_lockdb)(r, 0, 1, &lockdb)) != NULL) {
- /* ### return err! maybe add a higher-level desc */
- /* ### map result to something nice; log an error */
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (locktoken != NULL
- && (err = dav_get_direct_resource(r->pool, lockdb,
- locktoken, resource,
- &lock_resource)) != NULL) {
- /* ### add a higher-level desc? */
- /* ### should return err! */
- return err->status;
- }
-
- /* At this point, lock_resource/locktoken refers to a direct lock (key), ie
- * the root of a depth > 0 lock, or locktoken is null.
- */
- ctx.w.walk_type = DAV_WALKTYPE_NORMAL | DAV_WALKTYPE_LOCKNULL;
- ctx.w.func = dav_unlock_walker;
- ctx.w.walk_ctx = &ctx;
- ctx.w.pool = r->pool;
- ctx.w.root = lock_resource;
- ctx.w.lockdb = lockdb;
-
- ctx.r = r;
- ctx.locktoken = locktoken;
-
- err = (*repos_hooks->walk)(&ctx.w, DAV_INFINITY, &multi_status);
-
- /* ### fix this! */
- /* ### do something with multi_status */
- result = err == NULL ? OK : err->status;
-
- (*hooks->close_lockdb)(lockdb);
-
- return result;
-}
-
-/* dav_inherit_walker: Walker callback function to inherit locks */
-static dav_error * dav_inherit_walker(dav_walk_resource *wres, int calltype)
-{
- dav_walker_ctx *ctx = wres->walk_ctx;
-
- if (ctx->skip_root
- && (*wres->resource->hooks->is_same_resource)(wres->resource,
- ctx->w.root)) {
- return NULL;
- }
-
- /* ### maybe add a higher-level desc */
- return (*ctx->w.lockdb->hooks->append_locks)(ctx->w.lockdb,
- wres->resource, 1,
- ctx->lock);
-}
-
-/*
-** dav_inherit_locks: When a resource or collection is added to a collection,
-** locks on the collection should be inherited to the resource/collection.
-** (MOVE, MKCOL, etc) Here we propagate any direct or indirect locks from
-** parent of resource to resource and below.
-*/
-static dav_error * dav_inherit_locks(request_rec *r, dav_lockdb *lockdb,
- const dav_resource *resource,
- int use_parent)
-{
- dav_error *err;
- const dav_resource *which_resource;
- dav_lock *locks;
- dav_lock *scan;
- dav_lock *prev;
- dav_walker_ctx ctx = { { 0 } };
- const dav_hooks_repository *repos_hooks = resource->hooks;
- dav_response *multi_status;
-
- if (use_parent) {
- dav_resource *parent;
- if ((err = (*repos_hooks->get_parent_resource)(resource,
- &parent)) != NULL) {
- /* ### add a higher-level desc? */
- return err;
- }
- if (parent == NULL) {
- /* ### map result to something nice; log an error */
- return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
- "Could not fetch parent resource. Unable to "
- "inherit locks from the parent and apply "
- "them to this resource.");
- }
- which_resource = parent;
- }
- else {
- which_resource = resource;
- }
-
- if ((err = (*lockdb->hooks->get_locks)(lockdb, which_resource,
- DAV_GETLOCKS_PARTIAL,
- &locks)) != NULL) {
- /* ### maybe add a higher-level desc */
- return err;
- }
-
- if (locks == NULL) {
- /* No locks to propagate, just return */
- return NULL;
- }
-
- /*
- ** (1) Copy all indirect locks from our parent;
- ** (2) Create indirect locks for the depth infinity, direct locks
- ** in our parent.
- **
- ** The append_locks call in the walker callback will do the indirect
- ** conversion, but we need to remove any direct locks that are NOT
- ** depth "infinity".
- */
- for (scan = locks, prev = NULL;
- scan != NULL;
- prev = scan, scan = scan->next) {
-
- if (scan->rectype == DAV_LOCKREC_DIRECT
- && scan->depth != DAV_INFINITY) {
-
- if (prev == NULL)
- locks = scan->next;
- else
- prev->next = scan->next;
- }
- }
-
- /* <locks> has all our new locks. Walk down and propagate them. */
-
- ctx.w.walk_type = DAV_WALKTYPE_NORMAL | DAV_WALKTYPE_LOCKNULL;
- ctx.w.func = dav_inherit_walker;
- ctx.w.walk_ctx = &ctx;
- ctx.w.pool = r->pool;
- ctx.w.root = resource;
- ctx.w.lockdb = lockdb;
-
- ctx.r = r;
- ctx.lock = locks;
- ctx.skip_root = !use_parent;
-
- /* ### do something with multi_status */
- return (*repos_hooks->walk)(&ctx.w, DAV_INFINITY, &multi_status);
-}
-
-/* ---------------------------------------------------------------
-**
-** Functions dealing with lock-null resources
-**
-*/
-
-/*
-** dav_get_resource_state: Returns the state of the resource
-** r->filename: DAV_RESOURCE_NULL, DAV_RESOURCE_LOCK_NULL,
-** or DAV_RESOURCE_EXIST.
-**
-** Returns DAV_RESOURCE_ERROR if an error occurs.
-*/
-int dav_get_resource_state(request_rec *r, const dav_resource *resource)
-{
- const dav_hooks_locks *hooks = DAV_GET_HOOKS_LOCKS(r);
-
- if (resource->exists)
- return DAV_RESOURCE_EXISTS;
-
- if (hooks != NULL) {
- dav_error *err;
- dav_lockdb *lockdb;
- int locks_present;
-
- /*
- ** A locknull resource has the form:
- **
- ** known-dir "/" locknull-file
- **
- ** It would be nice to look into <resource> to verify this form,
- ** but it does not have enough information for us. Instead, we
- ** can look at the path_info. If the form does not match, then
- ** there is no way we could have a locknull resource -- it must
- ** be a plain, null resource.
- **
- ** Apache sets r->filename to known-dir/unknown-file and r->path_info
- ** to "" for the "proper" case. If anything is in path_info, then
- ** it can't be a locknull resource.
- **
- ** ### I bet this path_info hack doesn't work for repositories.
- ** ### Need input from repository implementors! What kind of
- ** ### restructure do we need? New provider APIs?
- */
- if (r->path_info != NULL && *r->path_info != '\0') {
- return DAV_RESOURCE_NULL;
- }
-
- if ((err = (*hooks->open_lockdb)(r, 1, 1, &lockdb)) == NULL) {
- /* note that we might see some expired locks... *shrug* */
- err = (*hooks->has_locks)(lockdb, resource, &locks_present);
- (*hooks->close_lockdb)(lockdb);
- }
-
- if (err != NULL) {
- /* ### don't log an error. return err. add higher-level desc. */
-
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "Failed to query lock-null status for %s",
- r->filename);
-
- return DAV_RESOURCE_ERROR;
- }
-
- if (locks_present)
- return DAV_RESOURCE_LOCK_NULL;
- }
-
- return DAV_RESOURCE_NULL;
-}
-
-dav_error * dav_notify_created(request_rec *r,
- dav_lockdb *lockdb,
- const dav_resource *resource,
- int resource_state,
- int depth)
-{
- dav_error *err;
-
- if (resource_state == DAV_RESOURCE_LOCK_NULL) {
-
- /*
- ** The resource is no longer a locknull resource. This will remove
- ** the special marker.
- **
- ** Note that a locknull resource has already inherited all of the
- ** locks from the parent. We do not need to call dav_inherit_locks.
- **
- ** NOTE: some lock providers record locks for locknull resources using
- ** a different key than for regular resources. this will shift
- ** the lock information between the two key types.
- */
- (void)(*lockdb->hooks->remove_locknull_state)(lockdb, resource);
-
- /*
- ** There are resources under this one, which are new. We must
- ** propagate the locks down to the new resources.
- */
- if (depth > 0 &&
- (err = dav_inherit_locks(r, lockdb, resource, 0)) != NULL) {
- /* ### add a higher level desc? */
- return err;
- }
- }
- else if (resource_state == DAV_RESOURCE_NULL) {
-
- /* ### should pass depth to dav_inherit_locks so that it can
- ** ### optimize for the depth==0 case.
- */
-
- /* this resource should inherit locks from its parent */
- if ((err = dav_inherit_locks(r, lockdb, resource, 1)) != NULL) {
-
- err = dav_push_error(r->pool, err->status, 0,
- "The resource was created successfully, but "
- "there was a problem inheriting locks from "
- "the parent resource.",
- err);
- return err;
- }
- }
- /* else the resource already exists and its locks are correct. */
-
- return NULL;
-}
diff --git a/modules/echo/.cvsignore b/modules/echo/.cvsignore
deleted file mode 100644
index 65f0cc30cf..0000000000
--- a/modules/echo/.cvsignore
+++ /dev/null
@@ -1,10 +0,0 @@
-.deps
-.libs
-*.la
-modules.mk
-Makefile
-*.lo
-*.slo
-*.so
-Debug
-Release
diff --git a/modules/echo/.indent.pro b/modules/echo/.indent.pro
deleted file mode 100644
index a9fbe9f9a1..0000000000
--- a/modules/echo/.indent.pro
+++ /dev/null
@@ -1,54 +0,0 @@
--i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1
--TBUFF
--TFILE
--TTRANS
--TUINT4
--T_trans
--Tallow_options_t
--Tapache_sfio
--Tarray_header
--Tbool_int
--Tbuf_area
--Tbuff_struct
--Tbuffy
--Tcmd_how
--Tcmd_parms
--Tcommand_rec
--Tcommand_struct
--Tconn_rec
--Tcore_dir_config
--Tcore_server_config
--Tdir_maker_func
--Tevent
--Tglobals_s
--Thandler_func
--Thandler_rec
--Tjoblist_s
--Tlisten_rec
--Tmerger_func
--Tmode_t
--Tmodule
--Tmodule_struct
--Tmutex
--Tn_long
--Tother_child_rec
--Toverrides_t
--Tparent_score
--Tpid_t
--Tpiped_log
--Tpool
--Trequest_rec
--Trequire_line
--Trlim_t
--Tscoreboard
--Tsemaphore
--Tserver_addr_rec
--Tserver_rec
--Tserver_rec_chain
--Tshort_score
--Ttable
--Ttable_entry
--Tthread
--Tu_wide_int
--Tvtime_t
--Twide_int
diff --git a/modules/echo/Makefile.in b/modules/echo/Makefile.in
deleted file mode 100644
index 167b343d0d..0000000000
--- a/modules/echo/Makefile.in
+++ /dev/null
@@ -1,3 +0,0 @@
-
-include $(top_srcdir)/build/special.mk
-
diff --git a/modules/echo/config.m4 b/modules/echo/config.m4
deleted file mode 100644
index 504a89c44a..0000000000
--- a/modules/echo/config.m4
+++ /dev/null
@@ -1,11 +0,0 @@
-dnl modules enabled in this directory by default
-
-dnl APACHE_MODULE(name, helptext[, objects[, structname[, default[, config]]]])
-
-APACHE_MODPATH_INIT(echo)
-
-APACHE_MODULE(echo, ECHO server, , , no)
-
-APR_ADDTO(LTFLAGS,-export-dynamic)
-
-APACHE_MODPATH_FINISH
diff --git a/modules/echo/mod_echo.c b/modules/echo/mod_echo.c
deleted file mode 100644
index f182123213..0000000000
--- a/modules/echo/mod_echo.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "ap_config.h"
-#include "ap_mmn.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_connection.h"
-
-AP_DECLARE_DATA module echo_module;
-
-typedef struct {
- int bEnabled;
-} EchoConfig;
-
-static void *create_echo_server_config(apr_pool_t *p, server_rec *s)
-{
- EchoConfig *pConfig = apr_pcalloc(p, sizeof *pConfig);
-
- pConfig->bEnabled = 0;
-
- return pConfig;
-}
-
-static const char *echo_on(cmd_parms *cmd, void *dummy, int arg)
-{
- EchoConfig *pConfig = ap_get_module_config(cmd->server->module_config,
- &echo_module);
- pConfig->bEnabled = arg;
-
- return NULL;
-}
-
-static int process_echo_connection(conn_rec *c)
-{
- char buf[1024];
- EchoConfig *pConfig = ap_get_module_config(c->base_server->module_config,
- &echo_module);
-
- if (!pConfig->bEnabled) {
- return DECLINED;
- }
-
- for ( ; ; ) {
- apr_ssize_t r, w;
- r = sizeof(buf);
- apr_recv(c->client_socket, buf, &r);
- if (r <= 0) {
- break;
- }
- w = r;
- apr_send(c->client_socket, buf, &w);
- if (w != r) {
- break;
- }
- }
- return OK;
-}
-
-static const command_rec echo_cmds[] =
-{
- AP_INIT_FLAG("ProtocolEcho", echo_on, NULL, RSRC_CONF,
- "Run an echo server on this host"),
- { NULL }
-};
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_process_connection(process_echo_connection, NULL, NULL,
- APR_HOOK_MIDDLE);
-}
-
-AP_DECLARE_DATA module echo_module = {
- STANDARD20_MODULE_STUFF,
- NULL, /* create per-directory config structure */
- NULL, /* merge per-directory config structures */
- create_echo_server_config, /* create per-server config structure */
- NULL, /* merge per-server config structures */
- echo_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
diff --git a/modules/experimental/.cvsignore b/modules/experimental/.cvsignore
deleted file mode 100644
index 15cf55fd3f..0000000000
--- a/modules/experimental/.cvsignore
+++ /dev/null
@@ -1,11 +0,0 @@
-.deps
-.libs
-*.la
-modules.mk
-Makefile
-*.lo
-*.slo
-*.so
-Debug
-Release
-*.plg
diff --git a/modules/experimental/.indent.pro b/modules/experimental/.indent.pro
deleted file mode 100644
index a9fbe9f9a1..0000000000
--- a/modules/experimental/.indent.pro
+++ /dev/null
@@ -1,54 +0,0 @@
--i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1
--TBUFF
--TFILE
--TTRANS
--TUINT4
--T_trans
--Tallow_options_t
--Tapache_sfio
--Tarray_header
--Tbool_int
--Tbuf_area
--Tbuff_struct
--Tbuffy
--Tcmd_how
--Tcmd_parms
--Tcommand_rec
--Tcommand_struct
--Tconn_rec
--Tcore_dir_config
--Tcore_server_config
--Tdir_maker_func
--Tevent
--Tglobals_s
--Thandler_func
--Thandler_rec
--Tjoblist_s
--Tlisten_rec
--Tmerger_func
--Tmode_t
--Tmodule
--Tmodule_struct
--Tmutex
--Tn_long
--Tother_child_rec
--Toverrides_t
--Tparent_score
--Tpid_t
--Tpiped_log
--Tpool
--Trequest_rec
--Trequire_line
--Trlim_t
--Tscoreboard
--Tsemaphore
--Tserver_addr_rec
--Tserver_rec
--Tserver_rec_chain
--Tshort_score
--Ttable
--Ttable_entry
--Tthread
--Tu_wide_int
--Tvtime_t
--Twide_int
diff --git a/modules/experimental/Makefile.in b/modules/experimental/Makefile.in
deleted file mode 100644
index 7c5c149d85..0000000000
--- a/modules/experimental/Makefile.in
+++ /dev/null
@@ -1,3 +0,0 @@
-# a modules Makefile has no explicit targets -- they will be defined by
-# whatever modules are enabled. just grab special.mk to deal with this.
-include $(top_srcdir)/build/special.mk
diff --git a/modules/experimental/README b/modules/experimental/README
deleted file mode 100644
index 1d80fa5855..0000000000
--- a/modules/experimental/README
+++ /dev/null
@@ -1,41 +0,0 @@
-README for Apache 2.0 Example Module
-[April, 1997, updated May 2000]
-
-The files in the src/modules/example directory under the Apache
-distribution directory tree are provided as an example to those that
-wish to write modules that use the Apache API.
-
-The main file is mod_example.c, which illustrates all the different
-callback mechanisms and call syntaces. By no means does an add-on
-module need to include routines for all of the callbacks - quite the
-contrary!
-
-The example module is an actual working module. If you link it into
-your server, enable the "example-handler" handler for a location, and then
-browse to that location, you will see a display of some of the tracing
-the example module did as the various callbacks were made.
-
-To include the example module in your server run `./configure
---enable-example` in the src directory before running `make`.
-
-To add another module of your own:
-
- A. mkdir src/modules/mymodule
- B. cp src/modules/example/* src/modules/mymodule
- C. Modify the files in the new directory
- D. Build the server as above, with appropriate changes.
-
-To activate the example module, include a block similar to the
-following in your httpd.conf file:
-
- <Location /example-info>
- SetHandler example-handler
- </Location>
-
-As an alternative, you can put the following into a .htaccess file and
-then request the file "test.example" from that location:
-
- AddHandler example-handler .example
-
-After reloading/restarting your server, you should be able to browse
-to this location and see the brief display mentioned earlier.
diff --git a/modules/experimental/config.m4 b/modules/experimental/config.m4
deleted file mode 100644
index 975e9d8329..0000000000
--- a/modules/experimental/config.m4
+++ /dev/null
@@ -1,14 +0,0 @@
-
-APACHE_MODPATH_INIT(experimental)
-
-APACHE_MODULE(charset_lite, character set translation, , , no)
-APACHE_MODULE(cache, dynamic file caching, , , no)
-APACHE_MODULE(disk_cache, disk caching module, , , no)
-APACHE_MODULE(ext_filter, external filter module, , , no)
-APACHE_MODULE(case_filter, example uppercase conversion filter, , , no)
-APACHE_MODULE(generic_hook_export, example hook exporter, , , no)
-APACHE_MODULE(generic_hook_import, example hook importer, , , no)
-APACHE_MODULE(optional_fn_import, example optional function importer, , , no)
-APACHE_MODULE(optional_fn_export, example optional function exporter, , , no)
-
-APACHE_MODPATH_FINISH
diff --git a/modules/experimental/mod_cache.c b/modules/experimental/mod_cache.c
deleted file mode 100644
index 49871abe58..0000000000
--- a/modules/experimental/mod_cache.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "apr_strings.h"
-#include "ap_config.h"
-#include "util_filter.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_request.h"
-#include "http_core.h"
-#include "http_protocol.h"
-#include "http_log.h"
-#include "http_main.h"
-#include "util_script.h"
-#include "http_core.h"
-#include "mod_cache.h"
-#include "apr_hooks.h"
-
-module AP_DECLARE_DATA cache_module;
-
-APR_HOOK_STRUCT(
- APR_HOOK_LINK(serve_cache)
- APR_HOOK_LINK(store_cache)
-)
-
-AP_IMPLEMENT_HOOK_RUN_FIRST(int,serve_cache,(request_rec *r),(r),DECLINED)
-AP_IMPLEMENT_HOOK_RUN_FIRST(int,store_cache,(request_rec *r, apr_bucket_brigade *bb, void **cf),
- (r, bb, cf),DECLINED)
-
-static int cache_handler(request_rec *r)
-{
- /* I am sure there is common error checking that belongs in this function,
- * but I'm not sure what it is.
- */
- return ap_run_serve_cache(r);
-}
-
-typedef struct cache_struct {
- void *cf;
-} cache_struct;
-
-static int cache_filter(ap_filter_t *f, apr_bucket_brigade *bb)
-{
- cache_struct *ctx = f->ctx;
-
- if (ctx == NULL) {
- f->ctx = ctx = apr_pcalloc(f->r->pool, sizeof(*ctx));
- }
-
- ap_run_store_cache(f->r, bb, &ctx->cf);
- ap_pass_brigade(f->next, bb);
- return APR_SUCCESS;
-}
-
-static void cache_register_hook(apr_pool_t *p)
-{
- ap_hook_handler(cache_handler, NULL, NULL, APR_HOOK_MIDDLE);
- ap_register_output_filter("CACHE", cache_filter, AP_FTYPE_HTTP_HEADER);
-}
-
-module AP_DECLARE_DATA cache_module = {
- STANDARD20_MODULE_STUFF,
- NULL, /* create per-directory config structure */
- NULL, /* merge per-directory config structures */
- NULL, /* create per-server config structure */
- NULL, /* merge per-server config structures */
- NULL, /* command apr_table_t */
- cache_register_hook /* register hooks */
-};
diff --git a/modules/experimental/mod_cache.h b/modules/experimental/mod_cache.h
deleted file mode 100644
index 7f2cf9b0c1..0000000000
--- a/modules/experimental/mod_cache.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "apr_buckets.h"
-#include "apr_hooks.h"
-#include "httpd.h"
-
-AP_DECLARE_HOOK(int,serve_cache,(request_rec *r));
-AP_DECLARE_HOOK(int,store_cache,(request_rec *r, apr_bucket_brigade *bb, void **cf));
-
diff --git a/modules/experimental/mod_case_filter.c b/modules/experimental/mod_case_filter.c
deleted file mode 100644
index bb59985ae4..0000000000
--- a/modules/experimental/mod_case_filter.c
+++ /dev/null
@@ -1,113 +0,0 @@
-// Ben messing around...
-
-#include "httpd.h"
-#include "http_config.h"
-#include "apr_general.h"
-#include "util_filter.h"
-#include "apr_buckets.h"
-#include "http_request.h"
-
-static const char s_szCaseFilterName[]="CaseFilter";
-module case_filter_module;
-
-typedef struct
- {
- int bEnabled;
- } CaseFilterConfig;
-
-static void *CaseFilterCreateServerConfig(apr_pool_t *p,server_rec *s)
- {
- CaseFilterConfig *pConfig=apr_pcalloc(p,sizeof *pConfig);
-
- pConfig->bEnabled=0;
-
- return pConfig;
- }
-
-static void CaseFilterInsertFilter(request_rec *r)
- {
- CaseFilterConfig *pConfig=ap_get_module_config(r->server->module_config,
- &case_filter_module);
-
- if(!pConfig->bEnabled)
- return;
-
- ap_add_output_filter(s_szCaseFilterName,NULL,r,r->connection);
- }
-
-static apr_status_t CaseFilterOutFilter(ap_filter_t *f,
- apr_bucket_brigade *pbbIn)
- {
- apr_bucket *pbktIn;
- apr_bucket_brigade *pbbOut;
-
- // XXX: is this the most appropriate pool?
- pbbOut=apr_brigade_create(f->r->pool);
- APR_BRIGADE_FOREACH(pbktIn,pbbIn)
- {
- const char *data;
- apr_size_t len;
- char *buf;
- apr_size_t n;
- apr_bucket *pbktOut;
-
- if(APR_BUCKET_IS_EOS(pbktIn))
- {
- // XXX: why can't I reuse pbktIn???
- apr_bucket *pbktEOS=apr_bucket_eos_create();
- APR_BRIGADE_INSERT_TAIL(pbbOut,pbktEOS);
- break;
- }
-
- // read
- apr_bucket_read(pbktIn,&data,&len,APR_BLOCK_READ);
-
- // write
- buf=apr_palloc(f->r->pool,len);
- for(n=0 ; n < len ; ++n)
- buf[n]=toupper(data[n]);
-
- // XXX: should we use a heap bucket instead? Or a transient (in
- // which case we need a separate brigade for each bucket)?
- pbktOut=apr_bucket_pool_create(buf,len,f->r->pool);
- APR_BRIGADE_INSERT_TAIL(pbbOut,pbktOut);
- }
-
- // XXX: is there any advantage to passing a brigade for each bucket?
- return ap_pass_brigade(f->next,pbbOut);
- }
-
-static const char *CaseFilterEnable(cmd_parms *cmd, void *dummy, int arg)
- {
- CaseFilterConfig *pConfig=ap_get_module_config(cmd->server->module_config,
- &case_filter_module);
- pConfig->bEnabled=arg;
-
- return NULL;
- }
-
-static const command_rec CaseFilterCmds[] =
- {
- AP_INIT_FLAG("CaseFilter", CaseFilterEnable, NULL, RSRC_CONF,
- "Run a case filter on this host"),
- { NULL }
- };
-
-static void CaseFilterRegisterHooks(void)
- {
- ap_hook_insert_filter(CaseFilterInsertFilter,NULL,NULL,APR_HOOK_MIDDLE);
- ap_register_output_filter(s_szCaseFilterName,CaseFilterOutFilter,
- AP_FTYPE_CONTENT);
- }
-
-module case_filter_module =
-{
- STANDARD20_MODULE_STUFF,
- NULL,
- NULL,
- CaseFilterCreateServerConfig,
- NULL,
- CaseFilterCmds,
- NULL,
- CaseFilterRegisterHooks
-};
diff --git a/modules/experimental/mod_charset_lite.c b/modules/experimental/mod_charset_lite.c
deleted file mode 100644
index 79830eed08..0000000000
--- a/modules/experimental/mod_charset_lite.c
+++ /dev/null
@@ -1,1142 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * simple hokey charset recoding configuration module
- *
- * See mod_ebcdic and mod_charset for more thought-out examples. This
- * one is just so Jeff can learn how a module works and experiment with
- * basic character set recoding configuration.
- *
- * !!!This is an extremely cheap ripoff of mod_charset.c from Russian Apache!!!
- */
-
-#include "httpd.h"
-#include "http_config.h"
-#define CORE_PRIVATE
-#include "http_core.h"
-#include "http_log.h"
-#include "http_main.h"
-#include "http_protocol.h"
-#include "http_request.h"
-#include "util_charset.h"
-#include "apr_buckets.h"
-#include "util_filter.h"
-#include "apr_strings.h"
-#include "apr_lib.h"
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#ifndef APACHE_XLATE
-#error mod_charset_lite cannot work without APACHE_XLATE enabled
-#endif
-
-#define OUTPUT_XLATE_BUF_SIZE (16*1024) /* size of translation buffer used on output */
-#define INPUT_XLATE_BUF_SIZE (8*1024) /* size of translation buffer used on input */
-
-/* XXX this works around an issue with the heap bucket: apr_bucket_heap_create will
- * copy only the first 4096 bytes
- */
-#undef INPUT_XLATE_BUF_SIZE /* XXX */
-#define INPUT_XLATE_BUF_SIZE (4096) /* XXX must match DEFAULT_BUCKET_SIZE */
-
-#define XLATE_MIN_BUFF_LEFT 128 /* flush once there is no more than this much
- * space is left in the translation buffer
- */
-
-#define FATTEST_CHAR 8 /* we don't handle chars wider than this that straddle
- * two buckets
- */
-
-/* extended error status codes; this is used in addition to an apr_status_t to
- * track errors in the translation filter
- */
-typedef enum {
- EES_INIT = 0, /* no error info yet; value must be 0 for easy init */
- EES_LIMIT, /* built-in restriction encountered */
- EES_INCOMPLETE_CHAR, /* incomplete multi-byte char at end of content */
- EES_BUCKET_READ,
- EES_DOWNSTREAM, /* something bad happened in a filter below xlate */
- EES_BAD_INPUT /* input data invalid */
-} ees_t;
-
-/* registered name of the output translation filter */
-#define XLATEOUT_FILTER_NAME "XLATEOUT"
-/* registered name of input translation filter */
-#define XLATEIN_FILTER_NAME "XLATEIN"
-
-typedef struct charset_dir_t {
- /** debug level; -1 means uninitialized, 0 means no debug */
- int debug;
- const char *charset_source; /* source encoding */
- const char *charset_default; /* how to ship on wire */
- /** module does ap_add_*_filter()? */
- enum {IA_INIT, IA_IMPADD, IA_NOIMPADD} implicit_add;
-} charset_dir_t;
-
-/* charset_filter_ctx_t is created for each filter instance; because the same
- * filter code is used for translating in both directions, we need this context
- * data to tell the filter which translation handle to use; it also can hold a
- * character which was split between buckets
- */
-typedef struct charset_filter_ctx_t {
- apr_xlate_t *xlate;
- charset_dir_t *dc;
- ees_t ees; /* extended error status */
- apr_size_t saved;
- char buf[FATTEST_CHAR]; /* we want to be able to build a complete char here */
- int ran; /* has filter instance run before? */
- int noop; /* should we pass brigades through unchanged? */
- char *tmp; /* buffer for input filtering */
- apr_bucket_brigade *bb; /* input buckets we couldn't finish translating */
-} charset_filter_ctx_t;
-
-/* charset_req_t is available via r->request_config if any translation is
- * being performed
- */
-typedef struct charset_req_t {
- charset_dir_t *dc;
- charset_filter_ctx_t *output_ctx, *input_ctx;
-} charset_req_t;
-
-/* debug level definitions */
-#define DBGLVL_GORY 9 /* gory details */
-#define DBGLVL_FLOW 4 /* enough messages to see what happens on
- * each request */
-#define DBGLVL_PMC 2 /* messages about possible misconfiguration */
-
-module charset_lite_module;
-
-static void *create_charset_dir_conf(apr_pool_t *p,char *dummy)
-{
- charset_dir_t *dc = (charset_dir_t *)apr_pcalloc(p,sizeof(charset_dir_t));
-
- dc->debug = -1;
- return dc;
-}
-
-static void *merge_charset_dir_conf(apr_pool_t *p, void *basev, void *overridesv)
-{
- charset_dir_t *a = (charset_dir_t *)apr_pcalloc (p, sizeof(charset_dir_t));
- charset_dir_t *base = (charset_dir_t *)basev,
- *over = (charset_dir_t *)overridesv;
-
- /* If it is defined in the current container, use it. Otherwise, use the one
- * from the enclosing container.
- */
-
- a->debug =
- over->debug != -1 ? over->debug : base->debug;
- a->charset_default =
- over->charset_default ? over->charset_default : base->charset_default;
- a->charset_source =
- over->charset_source ? over->charset_source : base->charset_source;
- a->implicit_add =
- over->implicit_add != IA_INIT ? over->implicit_add : base->implicit_add;
- return a;
-}
-
-/* CharsetSourceEnc charset
- */
-static const char *add_charset_source(cmd_parms *cmd, void *in_dc,
- const char *name)
-{
- charset_dir_t *dc = in_dc;
-
- dc->charset_source = name;
- return NULL;
-}
-
-/* CharsetDefault charset
- */
-static const char *add_charset_default(cmd_parms *cmd, void *in_dc,
- const char *name)
-{
- charset_dir_t *dc = in_dc;
-
- dc->charset_default = name;
- return NULL;
-}
-
-/* CharsetOptions optionflag...
- */
-static const char *add_charset_options(cmd_parms *cmd, void *in_dc,
- const char *flag)
-{
- charset_dir_t *dc = in_dc;
-
- if (!strcasecmp(flag, "ImplicitAdd")) {
- dc->implicit_add = IA_IMPADD;
- }
- else if (!strcasecmp(flag, "NoImplicitAdd")) {
- dc->implicit_add = IA_NOIMPADD;
- }
- else if (!strncasecmp(flag, "DebugLevel=", 11)) {
- dc->debug = atoi(flag + 11);
- }
- else {
- return apr_pstrcat(cmd->temp_pool,
- "Invalid CharsetOptions option: ",
- flag,
- NULL);
- }
-
- return NULL;
-}
-
-/* find_code_page() is a fixup hook that decides if translation should be
- * enabled; if so, it sets up request data for use by the filter registration
- * hook so that it knows what to do
- */
-static int find_code_page(request_rec *r)
-{
- charset_dir_t *dc = ap_get_module_config(r->per_dir_config,
- &charset_lite_module);
- charset_req_t *reqinfo;
- charset_filter_ctx_t *input_ctx, *output_ctx;
- apr_status_t rv;
- const char *mime_type;
-
- if (dc->debug >= DBGLVL_FLOW) {
- ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO, 0, r,
- "uri: %s file: %s method: %d "
- "imt: %s flags: %s%s%s %s->%s",
- r->uri, r->filename, r->method_number,
- r->content_type ? r->content_type : "(unknown)",
- r->main ? "S" : "", /* S if subrequest */
- r->prev ? "R" : "", /* R if redirect */
- r->proxyreq ? "P" : "", /* P if proxy */
- dc->charset_source, dc->charset_default);
- }
-
- /* If we don't have a full directory configuration, bail out.
- */
- if (!dc->charset_source || !dc->charset_default) {
- if (dc->debug >= DBGLVL_PMC) {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
- "incomplete configuration: src %s, dst %s",
- dc->charset_source ? dc->charset_source : "unspecified",
- dc->charset_default ? dc->charset_default : "unspecified");
- }
- return DECLINED;
- }
-
- /* catch proxy requests */
- if (r->proxyreq) return DECLINED;
- /* mod_rewrite indicators */
- if (!strncmp(r->filename, "redirect:", 9)) return DECLINED;
- if (!strncmp(r->filename, "gone:", 5)) return DECLINED;
- if (!strncmp(r->filename, "passthrough:", 12)) return DECLINED;
- if (!strncmp(r->filename, "forbidden:", 10)) return DECLINED;
-
- mime_type = r->content_type ? r->content_type : ap_default_type(r);
-
- /* If mime type isn't text or message, bail out.
- */
-
-/* XXX When we handle translation of the request body, watch out here as
- * 1.3 allowed additional mime types: multipart and
- * application/x-www-form-urlencoded
- */
-
- if (strncasecmp(mime_type, "text/", 5) &&
-#if APR_CHARSET_EBCDIC
- /* On an EBCDIC machine, be willing to translate mod_autoindex-
- * generated output. Otherwise, it doesn't look too cool.
- *
- * XXX This isn't a perfect fix because this doesn't trigger us
- * to convert from the charset of the source code to ASCII. The
- * general solution seems to be to allow a generator to set an
- * indicator in the r specifying that the body is coded in the
- * implementation character set (i.e., the charset of the source
- * code). This would get several different types of documents
- * translated properly: mod_autoindex output, mod_status output,
- * mod_info output, hard-coded error documents, etc.
- */
- strcmp(mime_type, DIR_MAGIC_TYPE) &&
-#endif
- strncasecmp(mime_type, "message/", 8)) {
- if (dc->debug >= DBGLVL_GORY) {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
- "mime type is %s; no translation selected",
- mime_type);
- }
- return DECLINED;
- }
-
- if (dc->debug >= DBGLVL_GORY) {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
- "charset_source: %s charset_default: %s",
- dc && dc->charset_source ? dc->charset_source : "(none)",
- dc && dc->charset_default ? dc->charset_default : "(none)");
- }
-
- /* Get storage for the request data and the output filter context.
- * We rarely need the input filter context, so allocate that separately.
- */
- reqinfo = (charset_req_t *)apr_pcalloc(r->pool,
- sizeof(charset_req_t) +
- sizeof(charset_filter_ctx_t));
- output_ctx = (charset_filter_ctx_t *)(reqinfo + 1);
-
- reqinfo->dc = dc;
- output_ctx->dc = dc;
- ap_set_module_config(r->request_config, &charset_lite_module, reqinfo);
-
- reqinfo->output_ctx = output_ctx;
- rv = apr_xlate_open(&output_ctx->xlate,
- dc->charset_default, dc->charset_source, r->pool);
- if (rv != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "can't open translation %s->%s",
- dc->charset_source, dc->charset_default);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- switch (r->method_number) {
- case M_PUT:
- case M_POST:
- /* Set up input translation. Note: A request body can be included
- * with the OPTIONS method, but for now we don't set up translation
- * of it.
- */
- input_ctx = apr_pcalloc(r->pool, sizeof(charset_filter_ctx_t));
- input_ctx->bb = apr_brigade_create(r->pool);
- input_ctx->tmp = apr_palloc(r->pool, INPUT_XLATE_BUF_SIZE);
- input_ctx->dc = dc;
- reqinfo->input_ctx = input_ctx;
- rv = apr_xlate_open(&input_ctx->xlate, dc->charset_source,
- dc->charset_default, r->pool);
- if (rv != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "can't open translation %s->%s",
- dc->charset_default, dc->charset_source);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
- }
-
- return DECLINED;
-}
-
-static int configured_on_input(request_rec *r, const char *filter_name)
-{
- int i;
- core_dir_config *conf =
- (core_dir_config *)ap_get_module_config(r->per_dir_config,
- &core_module);
- char **items = (char **)conf->input_filters->elts;
-
- for (i = 0; i < conf->input_filters->nelts; i++) {
- if (!strcmp(items[i], filter_name))
- return 1;
- }
- return 0;
-}
-
-static int configured_on_output(request_rec *r, const char *filter_name)
-{
- int i;
- core_dir_config *conf =
- (core_dir_config *)ap_get_module_config(r->per_dir_config,
- &core_module);
- char **items = (char **)conf->output_filters->elts;
-
- for (i = 0; i < conf->output_filters->nelts; i++) {
- if (!strcmp(items[i], filter_name))
- return 1;
- }
- return 0;
-}
-
-/* xlate_insert_filter() is a filter hook which decides whether or not
- * to insert a translation filter for the current request.
- */
-static void xlate_insert_filter(request_rec *r)
-{
- /* Hey... don't be so quick to use reqinfo->dc here; reqinfo may be NULL */
- charset_req_t *reqinfo = ap_get_module_config(r->request_config,
- &charset_lite_module);
- charset_dir_t *dc = ap_get_module_config(r->per_dir_config,
- &charset_lite_module);
-
- if (reqinfo) {
- if (reqinfo->output_ctx && !configured_on_output(r, XLATEOUT_FILTER_NAME)) {
- ap_add_output_filter(XLATEOUT_FILTER_NAME, reqinfo->output_ctx, r,
- r->connection);
- }
- else if (dc->debug >= DBGLVL_FLOW) {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
- "xlate output filter not added implicitly because %s",
- !reqinfo->output_ctx ?
- "no output configuration available" :
- "SetOutputFilter was used to add the filter");
- }
-
- if (reqinfo->input_ctx && !configured_on_input(r, XLATEIN_FILTER_NAME)) {
- ap_add_input_filter(XLATEIN_FILTER_NAME, reqinfo->input_ctx, r,
- r->connection);
- }
- else if (dc->debug >= DBGLVL_FLOW) {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r,
- "xlate input filter not added implicitly because %s",
- !reqinfo->input_ctx ?
- "no input configuration available" :
- "SetInputFilter was used to add the filter");
- }
- }
-}
-
-/* stuff that sucks that I know of:
- *
- * bucket handling:
- * why create an eos bucket when we see it come down the stream? just send the one
- * passed as input... news flash: this will be fixed when xlate_out_filter() starts
- * using the more generic xlate_brigade()
- *
- * translation mechanics:
- * we don't handle characters that straddle more than two buckets; an error
- * will be generated
- */
-
-/* send_downstream() is passed the translated data; it puts it in a single-
- * bucket brigade and passes the brigade to the next filter
- */
-static apr_status_t send_downstream(ap_filter_t *f, const char *tmp, apr_size_t len)
-{
- apr_bucket_brigade *bb;
- apr_bucket *b;
- charset_filter_ctx_t *ctx = f->ctx;
- apr_status_t rv;
-
- bb = apr_brigade_create(f->r->pool);
- b = apr_bucket_transient_create(tmp, len);
- APR_BRIGADE_INSERT_TAIL(bb, b);
- rv = ap_pass_brigade(f->next, bb);
- if (rv != APR_SUCCESS) {
- ctx->ees = EES_DOWNSTREAM;
- }
- return rv;
-}
-
-static apr_status_t send_eos(ap_filter_t *f)
-{
- apr_bucket_brigade *bb;
- apr_bucket *b;
- charset_filter_ctx_t *ctx = f->ctx;
- apr_status_t rv;
-
- bb = apr_brigade_create(f->r->pool);
- b = apr_bucket_eos_create();
- APR_BRIGADE_INSERT_TAIL(bb, b);
- rv = ap_pass_brigade(f->next, bb);
- if (rv != APR_SUCCESS) {
- ctx->ees = EES_DOWNSTREAM;
- }
- return rv;
-}
-
-static apr_status_t set_aside_partial_char(charset_filter_ctx_t *ctx,
- const char *partial,
- apr_size_t partial_len)
-{
- apr_status_t rv;
-
- if (sizeof(ctx->buf) > partial_len) {
- ctx->saved = partial_len;
- memcpy(ctx->buf, partial, partial_len);
- rv = APR_SUCCESS;
- }
- else {
- rv = APR_INCOMPLETE;
- ctx->ees = EES_LIMIT; /* we don't handle chars this wide which straddle
- * buckets
- */
- }
- return rv;
-}
-
-static apr_status_t finish_partial_char(charset_filter_ctx_t *ctx,
- /* input buffer: */
- const char **cur_str,
- apr_size_t *cur_len,
- /* output buffer: */
- char **out_str,
- apr_size_t *out_len)
-{
- apr_status_t rv;
- apr_size_t tmp_input_len;
-
- /* Keep adding bytes from the input string to the saved string until we
- * 1) finish the input char
- * 2) get an error
- * or 3) run out of bytes to add
- */
-
- do {
- ctx->buf[ctx->saved] = **cur_str;
- ++ctx->saved;
- ++*cur_str;
- --*cur_len;
- tmp_input_len = ctx->saved;
- rv = apr_xlate_conv_buffer(ctx->xlate,
- ctx->buf,
- &tmp_input_len,
- *out_str,
- out_len);
- } while (rv == APR_INCOMPLETE && *cur_len);
-
- if (rv == APR_SUCCESS) {
- ctx->saved = 0;
- }
- else {
- ctx->ees = EES_LIMIT; /* code isn't smart enough to handle chars
- * straddling more than two buckets
- */
- }
-
- return rv;
-}
-
-static void log_xlate_error(ap_filter_t *f, apr_status_t rv)
-{
- charset_filter_ctx_t *ctx = f->ctx;
- const char *msg;
- char msgbuf[100];
- int cur;
- int flags = APLOG_ERR;
-
- switch(ctx->ees) {
- case EES_LIMIT:
- flags |= APLOG_NOERRNO;
- msg = "xlate filter - a built-in restriction was encountered";
- break;
- case EES_BAD_INPUT:
- flags |= APLOG_NOERRNO;
- msg = "xlate filter - an input character was invalid";
- break;
- case EES_BUCKET_READ:
- msg = "xlate filter - bucket read routine failed";
- break;
- case EES_INCOMPLETE_CHAR:
- flags |= APLOG_NOERRNO;
- strcpy(msgbuf, "xlate filter - incomplete char at end of input - ");
- cur = 0;
- while (cur < ctx->saved) {
- apr_snprintf(msgbuf + strlen(msgbuf), sizeof(msgbuf) - strlen(msgbuf),
- "%02X", (unsigned)ctx->buf[cur]);
- ++cur;
- }
- msg = msgbuf;
- break;
- case EES_DOWNSTREAM:
- msg = "xlate filter - an error occurred in a lower filter";
- break;
- default:
- msg = "xlate filter - returning error";
- }
- ap_log_rerror(APLOG_MARK, flags, rv, f->r,
- "%s", msg);
-}
-
-/* chk_filter_chain() is called once per filter instance; it tries to
- * determine if the current filter instance should be disabled because
- * its translation is incompatible with the translation of an existing
- * instance of the translate filter
- *
- * Example bad scenario:
- *
- * configured filter chain for the request:
- * INCLUDES XLATEOUT(8859-1->UTS-16)
- * configured filter chain for the subrequest:
- * XLATEOUT(8859-1->UTS-16)
- *
- * When the subrequest is processed, the filter chain will be
- * XLATEOUT(8859-1->UTS-16) XLATEOUT(8859-1->UTS-16)
- * This makes no sense, so the instance of XLATEOUT added for the
- * subrequest will be noop-ed.
- *
- * Example good scenario:
- *
- * configured filter chain for the request:
- * INCLUDES XLATEOUT(8859-1->UTS-16)
- * configured filter chain for the subrequest:
- * XLATEOUT(IBM-1047->8859-1)
- *
- * When the subrequest is processed, the filter chain will be
- * XLATEOUT(IBM-1047->8859-1) XLATEOUT(8859-1->UTS-16)
- * This makes sense, so the instance of XLATEOUT added for the
- * subrequest will be left alone and it will translate from
- * IBM-1047->8859-1.
- */
-static void chk_filter_chain(ap_filter_t *f)
-{
- ap_filter_t *curf;
- charset_filter_ctx_t *curctx, *last_xlate_ctx = NULL,
- *ctx = f->ctx;
- int debug = ctx->dc->debug;
- int output = !strcmp(f->frec->name, XLATEOUT_FILTER_NAME);
-
- if (ctx->noop) {
- return;
- }
-
- /* walk the filter chain; see if it makes sense for our filter to
- * do any translation
- */
- curf = output ? f->r->output_filters : f->r->input_filters;
- while (curf) {
- if (!strcmp(curf->frec->name, f->frec->name) &&
- curf->ctx) {
- curctx = (charset_filter_ctx_t *)curf->ctx;
- if (!last_xlate_ctx) {
- last_xlate_ctx = curctx;
- }
- else {
- if (strcmp(last_xlate_ctx->dc->charset_default,
- curctx->dc->charset_source)) {
- /* incompatible translation
- * if our filter instance is incompatible with an instance
- * already in place, noop our instance
- * Notes:
- * . We are only willing to noop our own instance.
- * . It is possible to noop another instance which has not
- * yet run, but this is not currently implemented.
- * Hopefully it will not be needed.
- * . It is not possible to noop an instance which has
- * already run.
- */
- if (last_xlate_ctx == f->ctx) {
- last_xlate_ctx->noop = 1;
- if (debug >= DBGLVL_PMC) {
- const char *symbol = output ? "->" : "<-";
-
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO,
- 0, f->r,
- "%s %s - disabling "
- "translation %s%s%s; existing "
- "translation %s%s%s",
- f->r->uri ? "uri" : "file",
- f->r->uri ? f->r->uri : f->r->filename,
- last_xlate_ctx->dc->charset_source,
- symbol,
- last_xlate_ctx->dc->charset_default,
- curctx->dc->charset_source,
- symbol,
- curctx->dc->charset_default);
- }
- }
- else {
- const char *symbol = output ? "->" : "<-";
-
- ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO,
- 0, f->r,
- "chk_filter_chain() - can't disable "
- "translation %s%s%s; existing "
- "translation %s%s%s",
- last_xlate_ctx->dc->charset_source,
- symbol,
- last_xlate_ctx->dc->charset_default,
- curctx->dc->charset_source,
- symbol,
- curctx->dc->charset_default);
- }
- break;
- }
- }
- }
- curf = curf->next;
- }
-}
-
-/* xlate_brigade() is used to filter request and response bodies
- *
- * we'll stop when one of the following occurs:
- * . we run out of buckets
- * . we run out of space in the output buffer
- * . we hit an error
- *
- * inputs:
- * bb: brigade to process
- * buffer: storage to hold the translated characters
- * buffer_size: size of buffer
- * (and a few more uninteresting parms)
- *
- * outputs:
- * return value: APR_SUCCESS or some error code
- * bb: we've removed any buckets representing the
- * translated characters; the eos bucket, if
- * present, will be left in the brigade
- * buffer: filled in with translated characters
- * buffer_size: updated with the bytes remaining
- * hit_eos: did we hit an EOS bucket?
- */
-static apr_status_t xlate_brigade(charset_filter_ctx_t *ctx,
- apr_bucket_brigade *bb,
- char *buffer,
- apr_size_t *buffer_avail,
- int *hit_eos)
-{
- apr_bucket *b, *consumed_bucket;
- const char *bucket;
- apr_size_t bytes_in_bucket; /* total bytes read from current bucket */
- apr_size_t bucket_avail; /* bytes left in current bucket */
- apr_status_t rv = APR_SUCCESS;
-
- *hit_eos = 0;
- bucket_avail = 0;
- consumed_bucket = NULL;
- while (1) {
- if (!bucket_avail) { /* no bytes left to process in the current bucket... */
- if (consumed_bucket) {
- apr_bucket_delete(consumed_bucket);
- consumed_bucket = NULL;
- }
- b = APR_BRIGADE_FIRST(bb);
- if (b == APR_BRIGADE_SENTINEL(bb) ||
- APR_BUCKET_IS_EOS(b)) {
- break;
- }
- rv = apr_bucket_read(b, &bucket, &bytes_in_bucket, APR_BLOCK_READ);
- if (rv != APR_SUCCESS) {
- ctx->ees = EES_BUCKET_READ;
- break;
- }
- bucket_avail = bytes_in_bucket;
- consumed_bucket = b; /* for axing when we're done reading it */
- }
- if (bucket_avail) {
- /* We've got data, so translate it. */
- if (ctx->saved) {
- /* Rats... we need to finish a partial character from the previous
- * bucket.
- *
- * Strangely, finish_partial_char() increments the input buffer
- * pointer but does not increment the output buffer pointer.
- */
- apr_size_t old_buffer_avail = *buffer_avail;
- rv = finish_partial_char(ctx,
- &bucket, &bucket_avail,
- &buffer, buffer_avail);
- buffer += old_buffer_avail - *buffer_avail;
- }
- else {
- apr_size_t old_buffer_avail = *buffer_avail;
- apr_size_t old_bucket_avail = bucket_avail;
- rv = apr_xlate_conv_buffer(ctx->xlate,
- bucket, &bucket_avail,
- buffer,
- buffer_avail);
- buffer += old_buffer_avail - *buffer_avail;
- bucket += old_bucket_avail - bucket_avail;
-
- if (rv == APR_INCOMPLETE) { /* partial character at end of input */
- /* We need to save the final byte(s) for next time; we can't
- * convert it until we look at the next bucket.
- */
- rv = set_aside_partial_char(ctx, bucket, bucket_avail);
- bucket_avail = 0;
- }
- }
- if (rv != APR_SUCCESS) {
- /* bad input byte or partial char too big to store */
- break;
- }
- if (*buffer_avail < XLATE_MIN_BUFF_LEFT) {
- /* if any data remains in the current bucket, split there */
- if (bucket_avail) {
- apr_bucket_split(b, bytes_in_bucket - bucket_avail);
- }
- apr_bucket_delete(b);
- break;
- }
- }
- }
-
- if (!APR_BRIGADE_EMPTY(bb)) {
- b = APR_BRIGADE_FIRST(bb);
- if (APR_BUCKET_IS_EOS(b)) {
- /* Leave the eos bucket in the brigade for reporting to
- * subsequent filters.
- */
- *hit_eos = 1;
- if (ctx->saved) {
- /* Oops... we have a partial char from the previous bucket
- * that won't be completed because there's no more data.
- */
- rv = APR_INCOMPLETE;
- ctx->ees = EES_INCOMPLETE_CHAR;
- }
- }
- }
-
- return rv;
-}
-
-/* xlate_out_filter() handles (almost) arbitrary conversions from one charset
- * to another...
- * translation is determined in the fixup hook (find_code_page), which is
- * where the filter's context data is set up... the context data gives us
- * the translation handle
- */
-static apr_status_t xlate_out_filter(ap_filter_t *f, apr_bucket_brigade *bb)
-{
- charset_req_t *reqinfo = ap_get_module_config(f->r->request_config,
- &charset_lite_module);
- charset_dir_t *dc = ap_get_module_config(f->r->per_dir_config,
- &charset_lite_module);
- charset_filter_ctx_t *ctx = f->ctx;
- apr_bucket *dptr, *consumed_bucket;
- const char *cur_str;
- apr_size_t cur_len, cur_avail;
- char tmp[OUTPUT_XLATE_BUF_SIZE];
- apr_size_t space_avail;
- int done;
- apr_status_t rv = APR_SUCCESS;
-
- if (!ctx) {
- /* this is SetOutputFilter path; grab the preallocated context,
- * if any; note that if we decided not to do anything in an earlier
- * handler, we won't even have a reqinfo
- */
- if (reqinfo) {
- ctx = f->ctx = reqinfo->output_ctx;
- reqinfo->output_ctx = NULL; /* prevent SNAFU if user coded us twice
- * in the filter chain; we can't have two
- * instances using the same context
- */
- }
- if (!ctx) { /* no idea how to translate; don't do anything */
- ctx = f->ctx = apr_pcalloc(f->r->pool, sizeof(charset_filter_ctx_t));
- ctx->dc = dc;
- ctx->noop = 1;
- }
- }
-
- if (dc->debug >= DBGLVL_GORY) {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, f->r,
- "xlate_out_filter() - "
- "charset_source: %s charset_default: %s",
- dc && dc->charset_source ? dc->charset_source : "(none)",
- dc && dc->charset_default ? dc->charset_default : "(none)");
- }
-
- if (!ctx->ran) { /* filter never ran before */
- chk_filter_chain(f);
- ctx->ran = 1;
- }
-
- if (ctx->noop) {
- return ap_pass_brigade(f->next, bb);
- }
-
- dptr = APR_BRIGADE_FIRST(bb);
- done = 0;
- cur_len = 0;
- space_avail = sizeof(tmp);
- consumed_bucket = NULL;
- while (!done) {
- if (!cur_len) { /* no bytes left to process in the current bucket... */
- if (consumed_bucket) {
- apr_bucket_delete(consumed_bucket);
- consumed_bucket = NULL;
- }
- if (dptr == APR_BRIGADE_SENTINEL(bb)) {
- done = 1;
- break;
- }
- if (APR_BUCKET_IS_EOS(dptr)) {
- done = 1;
- cur_len = -1; /* XXX yuck, but that tells us to send
- * eos down; when we minimize our bb construction
- * we'll fix this crap */
- if (ctx->saved) {
- /* Oops... we have a partial char from the previous bucket
- * that won't be completed because there's no more data.
- */
- rv = APR_INCOMPLETE;
- ctx->ees = EES_INCOMPLETE_CHAR;
- }
- break;
- }
- rv = apr_bucket_read(dptr, &cur_str, &cur_len, APR_BLOCK_READ);
- if (rv != APR_SUCCESS) {
- done = 1;
- ctx->ees = EES_BUCKET_READ;
- break;
- }
- consumed_bucket = dptr; /* for axing when we're done reading it */
- dptr = APR_BUCKET_NEXT(dptr); /* get ready for when we access the
- * next bucket */
- }
- /* Try to fill up our tmp buffer with translated data. */
- cur_avail = cur_len;
-
- if (cur_len) { /* maybe we just hit the end of a pipe (len = 0) ? */
- if (ctx->saved) {
- /* Rats... we need to finish a partial character from the previous
- * bucket.
- */
- char *tmp_tmp;
-
- tmp_tmp = tmp + sizeof(tmp) - space_avail;
- rv = finish_partial_char(ctx,
- &cur_str, &cur_len,
- &tmp_tmp, &space_avail);
- }
- else {
- rv = apr_xlate_conv_buffer(ctx->xlate,
- cur_str, &cur_avail,
- tmp + sizeof(tmp) - space_avail, &space_avail);
-
- /* Update input ptr and len after consuming some bytes */
- cur_str += cur_len - cur_avail;
- cur_len = cur_avail;
-
- if (rv == APR_INCOMPLETE) { /* partial character at end of input */
- /* We need to save the final byte(s) for next time; we can't
- * convert it until we look at the next bucket.
- */
- rv = set_aside_partial_char(ctx, cur_str, cur_len);
- cur_len = 0;
- }
- }
- }
-
- if (rv != APR_SUCCESS) {
- /* bad input byte or partial char too big to store */
- done = 1;
- }
-
- if (space_avail < XLATE_MIN_BUFF_LEFT) {
- /* It is time to flush, as there is not enough space left in the
- * current output buffer to bother with converting more data.
- */
- rv = send_downstream(f, tmp, sizeof(tmp) - space_avail);
- if (rv != APR_SUCCESS) {
- done = 1;
- }
-
- /* tmp is now empty */
- space_avail = sizeof(tmp);
- }
- }
-
- if (rv == APR_SUCCESS) {
- if (space_avail < sizeof(tmp)) { /* gotta write out what we converted */
- rv = send_downstream(f, tmp, sizeof(tmp) - space_avail);
- }
- }
- if (rv == APR_SUCCESS) {
- if (cur_len == -1) {
- rv = send_eos(f);
- }
- }
- else {
- log_xlate_error(f, rv);
- }
-
- return rv;
-}
-
-static void transfer_brigade(apr_bucket_brigade *in, apr_bucket_brigade *out)
-{
- apr_bucket *b;
-
- while (!APR_BRIGADE_EMPTY(in)) {
- b = APR_BRIGADE_FIRST(in);
- APR_BUCKET_REMOVE(b);
- APR_BRIGADE_INSERT_TAIL(out, b);
- }
-}
-
-static int xlate_in_filter(ap_filter_t *f, apr_bucket_brigade *bb,
- ap_input_mode_t mode, apr_size_t *readbytes)
-{
- apr_status_t rv;
- charset_req_t *reqinfo = ap_get_module_config(f->r->request_config,
- &charset_lite_module);
- charset_dir_t *dc = ap_get_module_config(f->r->per_dir_config,
- &charset_lite_module);
- charset_filter_ctx_t *ctx = f->ctx;
- apr_size_t buffer_size;
- int hit_eos;
-
- if (!ctx) {
- /* this is SetInputFilter path; grab the preallocated context,
- * if any; note that if we decided not to do anything in an earlier
- * handler, we won't even have a reqinfo
- */
- if (reqinfo) {
- ctx = f->ctx = reqinfo->input_ctx;
- reqinfo->input_ctx = NULL; /* prevent SNAFU if user coded us twice
- * in the filter chain; we can't have two
- * instances using the same context
- */
- }
- if (!ctx) { /* no idea how to translate; don't do anything */
- ctx = f->ctx = apr_pcalloc(f->r->pool, sizeof(charset_filter_ctx_t));
- ctx->dc = dc;
- ctx->noop = 1;
- }
- }
-
- if (dc->debug >= DBGLVL_GORY) {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, f->r,
- "xlate_in_filter() - "
- "charset_source: %s charset_default: %s",
- dc && dc->charset_source ? dc->charset_source : "(none)",
- dc && dc->charset_default ? dc->charset_default : "(none)");
- }
-
- if (!ctx->ran) { /* filter never ran before */
- chk_filter_chain(f);
- ctx->ran = 1;
- }
-
- if (ctx->noop) {
- return ap_get_brigade(f->next, bb, mode, readbytes);
- }
-
- if (APR_BRIGADE_EMPTY(ctx->bb)) {
- if ((rv = ap_get_brigade(f->next, bb, mode, readbytes)) != APR_SUCCESS) {
- return rv;
- }
- }
- else {
- transfer_brigade(ctx->bb, bb); /* first use the leftovers */
- }
-
- buffer_size = INPUT_XLATE_BUF_SIZE;
- rv = xlate_brigade(ctx, bb, ctx->tmp, &buffer_size, &hit_eos);
- if (rv == APR_SUCCESS) {
- if (!hit_eos) {
- /* move anything leftover into our context for next time;
- * we don't currently "set aside" since the data came from
- * down below, but I suspect that for long-term we need to
- * do that
- */
- transfer_brigade(bb, ctx->bb);
- }
- if (buffer_size < INPUT_XLATE_BUF_SIZE) { /* do we have output? */
- apr_bucket *e;
-
- e = apr_bucket_heap_create(ctx->tmp,
- INPUT_XLATE_BUF_SIZE - buffer_size, 1,
- NULL);
- /* make sure we insert at the head, because there may be
- * an eos bucket already there, and the eos bucket should
- * come after the data
- */
- APR_BRIGADE_INSERT_HEAD(bb, e);
- }
- else {
- /* XXX need to get some more data... what if the last brigade
- * we got had only the first byte of a multibyte char? we need
- * to grab more data from the network instead of returning an
- * empty brigade
- */
- }
- }
- else {
- log_xlate_error(f, rv);
- }
-
- return rv;
-}
-
-static const command_rec cmds[] =
-{
- AP_INIT_TAKE1("CharsetSourceEnc",
- add_charset_source,
- NULL,
- OR_FILEINFO,
- "source (html,cgi,ssi) file charset"),
- AP_INIT_TAKE1("CharsetDefault",
- add_charset_default,
- NULL,
- OR_FILEINFO,
- "name of default charset"),
- AP_INIT_ITERATE("CharsetOptions",
- add_charset_options,
- NULL,
- OR_FILEINFO,
- "valid options: ImplicitAdd, NoImplicitAdd, DebugLevel=n"),
- {NULL}
-};
-
-static void charset_register_hooks(apr_pool_t *p)
-{
- ap_hook_fixups(find_code_page, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_insert_filter(xlate_insert_filter, NULL, NULL, APR_HOOK_MIDDLE);
- ap_register_output_filter(XLATEOUT_FILTER_NAME, xlate_out_filter,
- AP_FTYPE_CONTENT);
- ap_register_input_filter(XLATEIN_FILTER_NAME, xlate_in_filter,
- AP_FTYPE_CONTENT);
-}
-
-module charset_lite_module =
-{
- STANDARD20_MODULE_STUFF,
- create_charset_dir_conf,
- merge_charset_dir_conf,
- NULL,
- NULL,
- cmds,
- charset_register_hooks
-};
-
diff --git a/modules/experimental/mod_disk_cache.c b/modules/experimental/mod_disk_cache.c
deleted file mode 100644
index cbd28bf04a..0000000000
--- a/modules/experimental/mod_disk_cache.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "mod_cache.h"
-#include "apr_file_io.h"
-#include "apr_strings.h"
-#include "http_config.h"
-#include "http_log.h"
-#include "util_filter.h"
-
-module MODULE_VAR_EXPORT disk_cache_module;
-
-static int disk_serve(request_rec *r)
-{
- apr_bucket *e;
- apr_bucket_brigade *bb = apr_brigade_create(r->pool);
- const char *filename;
- apr_file_t *fd = NULL;
- apr_status_t rv;
- ap_filter_t *f;
- char str[256];
- apr_off_t offset = 0;
-
- filename = ap_server_root_relative(r->pool,
- apr_pstrcat(r->pool, "proxy", r->uri, NULL));
- if ((rv = apr_file_open(&fd, filename, APR_READ,
- APR_UREAD, r->connection->pool)) != APR_SUCCESS) {
- return DECLINED;
- }
-
- /* skip the cached headers. */
- do {
- apr_file_gets(str, 256, fd);
- offset += strlen(str);
- } while (strcmp(str, CRLF));
-
- /* If we are serving from the cache, we don't want to try to cache it
- * again.
- */
- for ((f = r->output_filters); (f = f->next);) {
- if (!strcmp(f->frec->name, "CACHE")) {
- ap_remove_output_filter(f);
- }
- }
-
- e = apr_bucket_file_create(fd, offset, r->finfo.size);
-
- APR_BRIGADE_INSERT_HEAD(bb, e);
- e = apr_bucket_eos_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
-
- ap_pass_brigade(r->output_filters, bb);
- return OK;
-}
-
-typedef struct cache_struct {
- const char *filename;
- apr_file_t *fd;
- int state;
-} cache_struct;
-
-static int disk_cache(request_rec *r, apr_bucket_brigade *bb, void **cf)
-{
- cache_struct *ctx = *cf;
- apr_bucket *e;
-
- if (ctx == NULL) {
- *cf = ctx = apr_pcalloc(r->pool, sizeof(*ctx));
- }
- if (ctx->filename == NULL) {
- apr_status_t rv;
- apr_dir_make(ap_server_root_relative(r->pool, "proxy"), APR_UREAD | APR_UWRITE | APR_UEXECUTE | APR_GREAD | APR_GWRITE, r->pool);
-
- /* currently, we are using the uri as the cache key. This is
- * probably wrong, but it is much better than a hard-coded filename.
- */
- ctx->filename = ap_server_root_relative(r->pool,
- apr_pstrcat(r->pool, "proxy", r->uri, NULL));
- if ((rv = apr_file_open(&ctx->fd, ctx->filename,
- APR_WRITE | APR_CREATE | APR_TRUNCATE | APR_BUFFERED,
- APR_UREAD | APR_UWRITE, r->pool)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "Could not create cache file");
- *cf = NULL;
- return DECLINED;
- }
- }
- APR_BRIGADE_FOREACH(e, bb) {
- const char *str;
- apr_ssize_t length;
-
- apr_bucket_read(e, &str, &length, APR_BLOCK_READ);
- apr_file_write(ctx->fd, str, &length);
- }
- if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
- apr_file_close(ctx->fd);
- }
- return OK;
-}
-
-static void disk_cache_register_hook(apr_pool_t *p)
-{
- ap_hook_store_cache(disk_cache, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_serve_cache(disk_serve, NULL, NULL, APR_HOOK_MIDDLE);
-}
-
-module MODULE_VAR_EXPORT disk_cache_module = {
- STANDARD20_MODULE_STUFF,
- NULL, /* create per-directory config structure */
- NULL, /* merge per-directory config structures */
- NULL, /* create per-server config structure */
- NULL, /* merge per-server config structures */
- NULL, /* command apr_table_t */
- disk_cache_register_hook /* register hooks */
-};
diff --git a/modules/experimental/mod_example.c b/modules/experimental/mod_example.c
deleted file mode 100644
index 5d8de38777..0000000000
--- a/modules/experimental/mod_example.c
+++ /dev/null
@@ -1,1198 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * Apache example module. Provide demonstrations of how modules do things.
- *
- */
-
-#include "httpd.h"
-#include "http_config.h"
-#include "http_core.h"
-#include "http_log.h"
-#include "http_main.h"
-#include "http_protocol.h"
-#include "http_request.h"
-#include "util_script.h"
-
-#include "apr_strings.h"
-
-#include <stdio.h>
-
-/*--------------------------------------------------------------------------*/
-/* */
-/* Data declarations. */
-/* */
-/* Here are the static cells and structure declarations private to our */
-/* module. */
-/* */
-/*--------------------------------------------------------------------------*/
-
-/*
- * Sample configuration record. Used for both per-directory and per-server
- * configuration data.
- *
- * It's perfectly reasonable to have two different structures for the two
- * different environments. The same command handlers will be called for
- * both, though, so the handlers need to be able to tell them apart. One
- * possibility is for both structures to start with an int which is zero for
- * one and 1 for the other.
- *
- * Note that while the per-directory and per-server configuration records are
- * available to most of the module handlers, they should be treated as
- * READ-ONLY by all except the command and merge handlers. Sometimes handlers
- * are handed a record that applies to the current location by implication or
- * inheritance, and modifying it will change the rules for other locations.
- */
-typedef struct excfg {
- int cmode; /* Environment to which record applies (directory,
- * server, or combination).
- */
-#define CONFIG_MODE_SERVER 1
-#define CONFIG_MODE_DIRECTORY 2
-#define CONFIG_MODE_COMBO 3 /* Shouldn't ever happen. */
- int local; /* Boolean: "Example" directive declared here? */
- int congenital; /* Boolean: did we inherit an "Example"? */
- char *trace; /* Pointer to trace string. */
- char *loc; /* Location to which this record applies. */
-} excfg;
-
-/*
- * Let's set up a module-local static cell to point to the accreting callback
- * trace. As each API callback is made to us, we'll tack on the particulars
- * to whatever we've already recorded. To avoid massive memory bloat as
- * directories are walked again and again, we record the routine/environment
- * the first time (non-request context only), and ignore subsequent calls for
- * the same routine/environment.
- */
-static const char *trace = NULL;
-static apr_table_t *static_calls_made = NULL;
-
-/*
- * To avoid leaking memory from pools other than the per-request one, we
- * allocate a module-private pool, and then use a sub-pool of that which gets
- * freed each time we modify the trace. That way previous layers of trace
- * data don't get lost.
- */
-static apr_pool_t *example_pool = NULL;
-static apr_pool_t *example_subpool = NULL;
-
-/*
- * Declare ourselves so the configuration routines can find and know us.
- * We'll fill it in at the end of the module.
- */
-module example_module;
-
-/*--------------------------------------------------------------------------*/
-/* */
-/* The following pseudo-prototype declarations illustrate the parameters */
-/* passed to command handlers for the different types of directive */
-/* syntax. If an argument was specified in the directive definition */
-/* (look for "command_rec" below), it's available to the command handler */
-/* via the (void *) info field in the cmd_parms argument passed to the */
-/* handler (cmd->info for the examples below). */
-/* */
-/*--------------------------------------------------------------------------*/
-
-/*
- * Command handler for a NO_ARGS directive.
- *
- * static const char *handle_NO_ARGS(cmd_parms *cmd, void *mconfig);
- */
-
-/*
- * Command handler for a RAW_ARGS directive. The "args" argument is the text
- * of the commandline following the directive itself.
- *
- * static const char *handle_RAW_ARGS(cmd_parms *cmd, void *mconfig,
- * const char *args);
- */
-
-/*
- * Command handler for a FLAG directive. The single parameter is passed in
- * "bool", which is either zero or not for Off or On respectively.
- *
- * static const char *handle_FLAG(cmd_parms *cmd, void *mconfig, int bool);
- */
-
-/*
- * Command handler for a TAKE1 directive. The single parameter is passed in
- * "word1".
- *
- * static const char *handle_TAKE1(cmd_parms *cmd, void *mconfig,
- * char *word1);
- */
-
-/*
- * Command handler for a TAKE2 directive. TAKE2 commands must always have
- * exactly two arguments.
- *
- * static const char *handle_TAKE2(cmd_parms *cmd, void *mconfig,
- * char *word1, char *word2);
- */
-
-/*
- * Command handler for a TAKE3 directive. Like TAKE2, these must have exactly
- * three arguments, or the parser complains and doesn't bother calling us.
- *
- * static const char *handle_TAKE3(cmd_parms *cmd, void *mconfig,
- * char *word1, char *word2, char *word3);
- */
-
-/*
- * Command handler for a TAKE12 directive. These can take either one or two
- * arguments.
- * - word2 is a NULL pointer if no second argument was specified.
- *
- * static const char *handle_TAKE12(cmd_parms *cmd, void *mconfig,
- * char *word1, char *word2);
- */
-
-/*
- * Command handler for a TAKE123 directive. A TAKE123 directive can be given,
- * as might be expected, one, two, or three arguments.
- * - word2 is a NULL pointer if no second argument was specified.
- * - word3 is a NULL pointer if no third argument was specified.
- *
- * static const char *handle_TAKE123(cmd_parms *cmd, void *mconfig,
- * char *word1, char *word2, char *word3);
- */
-
-/*
- * Command handler for a TAKE13 directive. Either one or three arguments are
- * permitted - no two-parameters-only syntax is allowed.
- * - word2 and word3 are NULL pointers if only one argument was specified.
- *
- * static const char *handle_TAKE13(cmd_parms *cmd, void *mconfig,
- * char *word1, char *word2, char *word3);
- */
-
-/*
- * Command handler for a TAKE23 directive. At least two and as many as three
- * arguments must be specified.
- * - word3 is a NULL pointer if no third argument was specified.
- *
- * static const char *handle_TAKE23(cmd_parms *cmd, void *mconfig,
- * char *word1, char *word2, char *word3);
- */
-
-/*
- * Command handler for a ITERATE directive.
- * - Handler is called once for each of n arguments given to the directive.
- * - word1 points to each argument in turn.
- *
- * static const char *handle_ITERATE(cmd_parms *cmd, void *mconfig,
- * char *word1);
- */
-
-/*
- * Command handler for a ITERATE2 directive.
- * - Handler is called once for each of the second and subsequent arguments
- * given to the directive.
- * - word1 is the same for each call for a particular directive instance (the
- * first argument).
- * - word2 points to each of the second and subsequent arguments in turn.
- *
- * static const char *handle_ITERATE2(cmd_parms *cmd, void *mconfig,
- * char *word1, char *word2);
- */
-
-/*--------------------------------------------------------------------------*/
-/* */
-/* These routines are strictly internal to this module, and support its */
-/* operation. They are not referenced by any external portion of the */
-/* server. */
-/* */
-/*--------------------------------------------------------------------------*/
-
-/*
- * Locate our directory configuration record for the current request.
- */
-static excfg *our_dconfig(request_rec *r)
-{
-
- return (excfg *) ap_get_module_config(r->per_dir_config, &example_module);
-}
-
-#if 0
-/*
- * Locate our server configuration record for the specified server.
- */
-static excfg *our_sconfig(server_rec *s)
-{
-
- return (excfg *) ap_get_module_config(s->module_config, &example_module);
-}
-
-/*
- * Likewise for our configuration record for the specified request.
- */
-static excfg *our_rconfig(request_rec *r)
-{
-
- return (excfg *) ap_get_module_config(r->request_config, &example_module);
-}
-#endif
-
-/*
- * This routine sets up some module-wide cells if they haven't been already.
- */
-static void setup_module_cells(void)
-{
- /*
- * If we haven't already allocated our module-private pool, do so now.
- */
- if (example_pool == NULL) {
- apr_pool_create(&example_pool, NULL);
- };
- /*
- * Likewise for the apr_table_t of routine/environment pairs we visit outside of
- * request context.
- */
- if (static_calls_made == NULL) {
- static_calls_made = apr_table_make(example_pool, 16);
- };
-}
-
-/*
- * This routine is used to add a trace of a callback to the list. We're
- * passed the server record (if available), the request record (if available),
- * a pointer to our private configuration record (if available) for the
- * environment to which the callback is supposed to apply, and some text. We
- * turn this into a textual representation and add it to the tail of the list.
- * The list can be displayed by the example_handler() routine.
- *
- * If the call occurs within a request context (i.e., we're passed a request
- * record), we put the trace into the request apr_pool_t and attach it to the
- * request via the notes mechanism. Otherwise, the trace gets added
- * to the static (non-request-specific) list.
- *
- * Note that the r->notes apr_table_t is only for storing strings; if you need to
- * maintain per-request data of any other type, you need to use another
- * mechanism.
- */
-
-#define TRACE_NOTE "example-trace"
-
-static void trace_add(server_rec *s, request_rec *r, excfg *mconfig,
- const char *note)
-{
-
- const char *sofar;
- char *addon;
- char *where;
- apr_pool_t *p;
- const char *trace_copy;
-
- /*
- * Make sure our pools and tables are set up - we need 'em.
- */
- setup_module_cells();
- /*
- * Now, if we're in request-context, we use the request pool.
- */
- if (r != NULL) {
- p = r->pool;
- if ((trace_copy = apr_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.
- */
- apr_pool_create(&p, example_pool);
- if (trace != NULL) {
- trace = apr_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) {
- apr_pool_destroy(example_subpool);
- }
- example_subpool = p;
- trace_copy = trace;
- }
- /*
- * If we weren't passed a configuration record, we can't figure out to
- * what location this call applies. This only happens for co-routines
- * that don't operate in a particular directory or server context. If we
- * got a valid record, extract the location (directory or server) to which
- * it applies.
- */
- where = (mconfig != NULL) ? mconfig->loc : "nowhere";
- where = (where != NULL) ? where : "";
- /*
- * Now, if we're not in request context, see if we've been called with
- * this particular combination before. The apr_table_t is allocated in the
- * module's private pool, which doesn't get destroyed.
- */
- if (r == NULL) {
- char *key;
-
- key = apr_pstrcat(p, note, ":", where, NULL);
- if (apr_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.
- */
- apr_table_set(static_calls_made, key, "been here");
- }
- }
- addon = apr_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 = apr_pstrcat(p, sofar, addon, NULL);
- if (r != NULL) {
- apr_table_set(r->notes, TRACE_NOTE, trace_copy);
- }
- else {
- trace = trace_copy;
- }
- /*
- * You *could* change the following if you wanted to see the calling
- * sequence reported in the server's error_log, but beware - almost all of
- * these co-routines are called for every single request, and the impact
- * on the size (and readability) of the error_log is considerable.
- */
-#define EXAMPLE_LOG_EACH 0
- if (EXAMPLE_LOG_EACH && (s != NULL)) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "mod_example: %s", note);
- }
-}
-
-/*--------------------------------------------------------------------------*/
-/* We prototyped the various syntax for command handlers (routines that */
-/* are called when the configuration parser detects a directive declared */
-/* by our module) earlier. Now we actually declare a "real" routine that */
-/* will be invoked by the parser when our "real" directive is */
-/* encountered. */
-/* */
-/* If a command handler encounters a problem processing the directive, it */
-/* signals this fact by returning a non-NULL pointer to a string */
-/* describing the problem. */
-/* */
-/* The magic return value DECLINE_CMD is used to deal with directives */
-/* that might be declared by multiple modules. If the command handler */
-/* returns NULL, the directive was processed; if it returns DECLINE_CMD, */
-/* the next module (if any) that declares the directive is given a chance */
-/* at it. If it returns any other value, it's treated as the text of an */
-/* error message. */
-/*--------------------------------------------------------------------------*/
-/*
- * Command handler for the NO_ARGS "Example" directive. All we do is mark the
- * call in the trace log, and flag the applicability of the directive to the
- * current location in that location's configuration record.
- */
-static const char *cmd_example(cmd_parms *cmd, void *mconfig)
-{
-
- excfg *cfg = (excfg *) mconfig;
-
- /*
- * "Example Wuz Here"
- */
- cfg->local = 1;
- trace_add(cmd->server, NULL, cfg, "cmd_example()");
- return NULL;
-}
-
-/*--------------------------------------------------------------------------*/
-/* */
-/* Now we declare our content handlers, which are invoked when the server */
-/* encounters a document which our module is supposed to have a chance to */
-/* see. (See mod_mime's SetHandler and AddHandler directives, and the */
-/* mod_info and mod_status examples, for more details.) */
-/* */
-/* Since content handlers are dumping data directly into the connexion */
-/* (using the r*() routines, such as rputs() and rprintf()) without */
-/* intervention by other parts of the server, they need to make */
-/* sure any accumulated HTTP headers are sent first. This is done by */
-/* calling send_http_header(). Otherwise, no header will be sent at all, */
-/* and the output sent to the client will actually be HTTP-uncompliant. */
-/*--------------------------------------------------------------------------*/
-/*
- * Sample content handler. All this does is display the call list that has
- * been built up so far.
- *
- * The return value instructs the caller concerning what happened and what to
- * do next:
- * OK ("we did our thing")
- * DECLINED ("this isn't something with which we want to get involved")
- * HTTP_mumble ("an error status should be reported")
- */
-static int example_handler(request_rec *r)
-{
-
- excfg *dcfg;
-
- dcfg = our_dconfig(r);
- trace_add(r->server, r, dcfg, "example_handler()");
- /*
- * We're about to start sending content, so we need to force the HTTP
- * headers to be sent at this point. Otherwise, no headers will be sent
- * at all. We can set any we like first, of course. **NOTE** Here's
- * where you set the "Content-type" header, and you do so by putting it in
- * r->content_type, *not* r->headers_out("Content-type"). If you don't
- * set it, it will be filled in with the server's default type (typically
- * "text/plain"). You *must* also ensure that r->content_type is lower
- * case.
- *
- * We also need to start a timer so the server can know if the connexion
- * is broken.
- */
- r->content_type = "text/html";
- /*
- * If we're only supposed to send header information (HEAD request), we're
- * already there.
- */
- if (r->header_only) {
- return OK;
- }
-
- /*
- * Now send our actual output. Since we tagged this as being
- * "text/html", we need to embed any HTML.
- */
- ap_rputs(DOCTYPE_HTML_3_2, r);
- ap_rputs("<HTML>\n", r);
- ap_rputs(" <HEAD>\n", r);
- ap_rputs(" <TITLE>mod_example Module Content-Handler Output\n", r);
- ap_rputs(" </TITLE>\n", r);
- ap_rputs(" </HEAD>\n", r);
- ap_rputs(" <BODY>\n", r);
- ap_rputs(" <H1><SAMP>mod_example</SAMP> Module Content-Handler Output\n", r);
- ap_rputs(" </H1>\n", r);
- ap_rputs(" <P>\n", r);
- ap_rprintf(r, " Apache HTTP Server version: \"%s\"\n",
- ap_get_server_version());
- ap_rputs(" <BR>\n", r);
- ap_rprintf(r, " Server built: \"%s\"\n", ap_get_server_built());
- ap_rputs(" </P>\n", r);;
- ap_rputs(" <P>\n", r);
- ap_rputs(" The format for the callback trace is:\n", r);
- ap_rputs(" </P>\n", r);
- ap_rputs(" <DL>\n", r);
- ap_rputs(" <DT><EM>n</EM>.<SAMP>&lt;routine-name&gt;", r);
- ap_rputs("(&lt;routine-data&gt;)</SAMP>\n", r);
- ap_rputs(" </DT>\n", r);
- ap_rputs(" <DD><SAMP>[&lt;applies-to&gt;]</SAMP>\n", r);
- ap_rputs(" </DD>\n", r);
- ap_rputs(" </DL>\n", r);
- ap_rputs(" <P>\n", r);
- ap_rputs(" The <SAMP>&lt;routine-data&gt;</SAMP> is supplied by\n", r);
- ap_rputs(" the routine when it requests the trace,\n", r);
- ap_rputs(" and the <SAMP>&lt;applies-to&gt;</SAMP> is extracted\n", r);
- ap_rputs(" from the configuration record at the time of the trace.\n", r);
- ap_rputs(" <STRONG>SVR()</STRONG> indicates a server environment\n", r);
- ap_rputs(" (blank means the main or default server, otherwise it's\n", r);
- ap_rputs(" the name of the VirtualHost); <STRONG>DIR()</STRONG>\n", r);
- ap_rputs(" indicates a location in the URL or filesystem\n", r);
- ap_rputs(" namespace.\n", r);
- ap_rputs(" </P>\n", r);
- ap_rprintf(r, " <H2>Static callbacks so far:</H2>\n <OL>\n%s </OL>\n",
- trace);
- ap_rputs(" <H2>Request-specific callbacks so far:</H2>\n", r);
- ap_rprintf(r, " <OL>\n%s </OL>\n", apr_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.
- */
- /*
- * We did what we wanted to do, so tell the rest of the server we
- * succeeded.
- */
- return OK;
-}
-
-/*--------------------------------------------------------------------------*/
-/* */
-/* Now let's declare routines for each of the callback phase in order. */
-/* (That's the order in which they're listed in the callback list, *not */
-/* the order in which the server calls them! See the command_rec */
-/* declaration near the bottom of this file.) Note that these may be */
-/* called for situations that don't relate primarily to our function - in */
-/* other words, the fixup handler shouldn't assume that the request has */
-/* to do with "example" stuff. */
-/* */
-/* With the exception of the content handler, all of our routines will be */
-/* called for each request, unless an earlier handler from another module */
-/* aborted the sequence. */
-/* */
-/* Handlers that are declared as "int" can return the following: */
-/* */
-/* OK Handler accepted the request and did its thing with it. */
-/* DECLINED Handler took no action. */
-/* HTTP_mumble Handler looked at request and found it wanting. */
-/* */
-/* What the server does after calling a module handler depends upon the */
-/* handler's return value. In all cases, if the handler returns */
-/* DECLINED, the server will continue to the next module with an handler */
-/* for the current phase. However, if the handler return a non-OK, */
-/* non-DECLINED status, the server aborts the request right there. If */
-/* the handler returns OK, the server's next action is phase-specific; */
-/* see the individual handler comments below for details. */
-/* */
-/*--------------------------------------------------------------------------*/
-/*
- * This function is called during server initialisation. Any information
- * that needs to be recorded must be in static cells, since there's no
- * configuration record.
- *
- * There is no return value.
- */
-
-/*
- * All our module initialiser does is add its trace to the log.
- */
-static void example_init(apr_pool_t *p, apr_pool_t *ptemp,
- apr_pool_t *plog, server_rec *s)
-{
-
- 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 = apr_pstrcat(p, "example_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 apr_status_t example_child_exit(void *sv)
-{
- server_rec *s = sv;
- 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 = apr_pstrcat(s->process->pool, "example_child_exit(", sname, ")", NULL);
- trace_add(s, NULL, NULL, note);
- return APR_SUCCESS;
-}
-
-/*
- * 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(apr_pool_t *p, server_rec *s)
-{
-
- 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 = apr_pstrcat(p, "example_child_init(", sname, ")", NULL);
- trace_add(s, NULL, NULL, note);
-
- apr_pool_cleanup_register(p, s, example_child_exit, example_child_exit);
-}
-
-/*
- * This function gets called to create a per-directory configuration
- * record. This will be called for the "default" server environment, and for
- * each directory for which the parser finds any of our directives applicable.
- * If a directory doesn't have any of our directives involved (i.e., they
- * aren't in the .htaccess file, or a <Location>, <Directory>, or related
- * block), this routine will *not* be called - the configuration for the
- * closest ancestor is used.
- *
- * The return value is a pointer to the created module-specific
- * structure.
- */
-static void *example_create_dir_config(apr_pool_t *p, char *dirspec)
-{
-
- excfg *cfg;
- char *dname = dirspec;
-
- /*
- * Allocate the space for our record from the pool supplied.
- */
- cfg = (excfg *) apr_pcalloc(p, sizeof(excfg));
- /*
- * Now fill in the defaults. If there are any `parent' configuration
- * records, they'll get merged as part of a separate callback.
- */
- cfg->local = 0;
- cfg->congenital = 0;
- cfg->cmode = CONFIG_MODE_DIRECTORY;
- /*
- * Finally, add our trace to the callback list.
- */
- dname = (dname != NULL) ? dname : "";
- cfg->loc = apr_pstrcat(p, "DIR(", dname, ")", NULL);
- trace_add(NULL, NULL, cfg, "example_create_dir_config()");
- return (void *) cfg;
-}
-
-/*
- * This function gets called to merge two per-directory configuration
- * records. This is typically done to cope with things like .htaccess files
- * or <Location> directives for directories that are beneath one for which a
- * configuration record was already created. The routine has the
- * responsibility of creating a new record and merging the contents of the
- * other two into it appropriately. If the module doesn't declare a merge
- * routine, the record for the closest ancestor location (that has one) is
- * used exclusively.
- *
- * The routine MUST NOT modify any of its arguments!
- *
- * The return value is a pointer to the created module-specific structure
- * containing the merged values.
- */
-static void *example_merge_dir_config(apr_pool_t *p, void *parent_conf,
- void *newloc_conf)
-{
-
- excfg *merged_config = (excfg *) apr_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 = apr_pstrdup(p, nconf->loc);
- /*
- * Others, like the setting of the `congenital' flag, get ORed in. The
- * setting of that particular flag, for instance, is TRUE if it was ever
- * true anywhere in the upstream configuration.
- */
- merged_config->congenital = (pconf->congenital | pconf->local);
- /*
- * If we're merging records for two different types of environment (server
- * and directory), mark the new record appropriately. Otherwise, inherit
- * the current value.
- */
- merged_config->cmode =
- (pconf->cmode == nconf->cmode) ? pconf->cmode : CONFIG_MODE_COMBO;
- /*
- * Now just record our being called in the trace list. Include the
- * locations we were asked to merge.
- */
- note = apr_pstrcat(p, "example_merge_dir_config(\"", pconf->loc, "\",\"",
- nconf->loc, "\")", NULL);
- trace_add(NULL, NULL, merged_config, note);
- return (void *) merged_config;
-}
-
-/*
- * This function gets called to create a per-server configuration
- * record. It will always be called for the "default" server.
- *
- * The return value is a pointer to the created module-specific
- * structure.
- */
-static void *example_create_server_config(apr_pool_t *p, server_rec *s)
-{
-
- excfg *cfg;
- char *sname = s->server_hostname;
-
- /*
- * As with the example_create_dir_config() reoutine, we allocate and fill
- * in an empty record.
- */
- cfg = (excfg *) apr_pcalloc(p, sizeof(excfg));
- cfg->local = 0;
- cfg->congenital = 0;
- cfg->cmode = CONFIG_MODE_SERVER;
- /*
- * Note that we were called in the trace list.
- */
- sname = (sname != NULL) ? sname : "";
- cfg->loc = apr_pstrcat(p, "SVR(", sname, ")", NULL);
- trace_add(s, NULL, cfg, "example_create_server_config()");
- return (void *) cfg;
-}
-
-/*
- * This function gets called to merge two per-server configuration
- * records. This is typically done to cope with things like virtual hosts and
- * the default server configuration The routine has the responsibility of
- * creating a new record and merging the contents of the other two into it
- * appropriately. If the module doesn't declare a merge routine, the more
- * specific existing record is used exclusively.
- *
- * The routine MUST NOT modify any of its arguments!
- *
- * The return value is a pointer to the created module-specific structure
- * containing the merged values.
- */
-static void *example_merge_server_config(apr_pool_t *p, void *server1_conf,
- void *server2_conf)
-{
-
- excfg *merged_config = (excfg *) apr_pcalloc(p, sizeof(excfg));
- excfg *s1conf = (excfg *) server1_conf;
- excfg *s2conf = (excfg *) server2_conf;
- char *note;
-
- /*
- * Our inheritance rules are our own, and part of our module's semantics.
- * Basically, just note whence we came.
- */
- merged_config->cmode =
- (s1conf->cmode == s2conf->cmode) ? s1conf->cmode : CONFIG_MODE_COMBO;
- merged_config->local = s2conf->local;
- merged_config->congenital = (s1conf->congenital | s1conf->local);
- merged_config->loc = apr_pstrdup(p, s2conf->loc);
- /*
- * Trace our call, including what we were asked to merge.
- */
- note = apr_pstrcat(p, "example_merge_server_config(\"", s1conf->loc, "\",\"",
- s2conf->loc, "\")", NULL);
- trace_add(NULL, NULL, merged_config, note);
- return (void *) merged_config;
-}
-
-/*
- * This routine is called after the request has been read but before any other
- * phases have been processed. This allows us to make decisions based upon
- * the input header fields.
- *
- * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, no
- * further modules are called for this phase.
- */
-static int example_post_read_request(request_rec *r)
-{
-
- excfg *cfg;
-
- cfg = our_dconfig(r);
- /*
- * We don't actually *do* anything here, except note the fact that we were
- * called.
- */
- trace_add(r->server, r, cfg, "example_post_read_request()");
- return DECLINED;
-}
-
-/*
- * This routine gives our module an opportunity to translate the URI into an
- * actual filename. If we don't do anything special, the server's default
- * rules (Alias directives and the like) will continue to be followed.
- *
- * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, no
- * further modules are called for this phase.
- */
-static int example_translate_handler(request_rec *r)
-{
-
- excfg *cfg;
-
- cfg = our_dconfig(r);
- /*
- * We don't actually *do* anything here, except note the fact that we were
- * called.
- */
- trace_add(r->server, r, cfg, "example_translate_handler()");
- return DECLINED;
-}
-
-/*
- * This routine is called to check the authentication information sent with
- * the request (such as looking up the user in a database and verifying that
- * the [encrypted] password sent matches the one in the database).
- *
- * The return value is OK, DECLINED, or some HTTP_mumble error (typically
- * HTTP_UNAUTHORIZED). If we return OK, no other modules are given a chance
- * at the request during this phase.
- */
-static int example_check_user_id(request_rec *r)
-{
-
- excfg *cfg;
-
- cfg = our_dconfig(r);
- /*
- * Don't do anything except log the call.
- */
- trace_add(r->server, r, cfg, "example_check_user_id()");
- return DECLINED;
-}
-
-/*
- * This routine is called to check to see if the resource being requested
- * requires authorisation.
- *
- * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, no
- * other modules are called during this phase.
- *
- * If *all* modules return DECLINED, the request is aborted with a server
- * error.
- */
-static int example_auth_checker(request_rec *r)
-{
-
- excfg *cfg;
-
- cfg = our_dconfig(r);
- /*
- * Log the call and return OK, or access will be denied (even though we
- * didn't actually do anything).
- */
- trace_add(r->server, r, cfg, "example_auth_checker()");
- return DECLINED;
-}
-
-/*
- * This routine is called to check for any module-specific restrictions placed
- * upon the requested resource. (See the mod_access module for an example.)
- *
- * The return value is OK, DECLINED, or HTTP_mumble. All modules with an
- * handler for this phase are called regardless of whether their predecessors
- * return OK or DECLINED. The first one to return any other status, however,
- * will abort the sequence (and the request) as usual.
- */
-static int example_access_checker(request_rec *r)
-{
-
- excfg *cfg;
-
- cfg = our_dconfig(r);
- trace_add(r->server, r, cfg, "example_access_checker()");
- return DECLINED;
-}
-
-/*
- * This routine is called to determine and/or set the various document type
- * information bits, like Content-type (via r->content_type), language, et
- * cetera.
- *
- * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, no
- * further modules are given a chance at the request for this phase.
- */
-static int example_type_checker(request_rec *r)
-{
-
- excfg *cfg;
-
- cfg = our_dconfig(r);
- /*
- * Log the call, but don't do anything else - and report truthfully that
- * we didn't do anything.
- */
- trace_add(r->server, r, cfg, "example_type_checker()");
- return DECLINED;
-}
-
-/*
- * This routine is called to perform any module-specific fixing of header
- * fields, et cetera. It is invoked just before any content-handler.
- *
- * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, the
- * server will still call any remaining modules with an handler for this
- * phase.
- */
-static int example_fixer_upper(request_rec *r)
-{
-
- excfg *cfg;
-
- cfg = our_dconfig(r);
- /*
- * Log the call and exit.
- */
- trace_add(r->server, r, cfg, "example_fixer_upper()");
- return OK;
-}
-
-/*
- * This routine is called to perform any module-specific logging activities
- * over and above the normal server things.
- *
- * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, any
- * remaining modules with an handler for this phase will still be called.
- */
-static int example_logger(request_rec *r)
-{
-
- excfg *cfg;
-
- cfg = our_dconfig(r);
- trace_add(r->server, r, cfg, "example_logger()");
- return DECLINED;
-}
-
-/*
- * This routine is called to give the module a chance to look at the request
- * headers and take any appropriate specific actions early in the processing
- * sequence.
- *
- * The return value is OK, DECLINED, or HTTP_mumble. If we return OK, any
- * remaining modules with handlers for this phase will still be called.
- */
-static int example_header_parser(request_rec *r)
-{
-
- excfg *cfg;
-
- cfg = our_dconfig(r);
- trace_add(r->server, r, cfg, "example_header_parser()");
- return DECLINED;
-}
-
-/*--------------------------------------------------------------------------*/
-/* */
-/* Which functions are responsible for which hooks in the server. */
-/* */
-/*--------------------------------------------------------------------------*/
-/*
- * Each function our module provides to handle a particular hook is
- * specified here. The functions are registered using
- * ap_hook_foo(name, predecessors, successors, position)
- * where foo is the name of the hook.
- *
- * The args are as follows:
- * name -> the name of the function to call.
- * predecessors -> a list of modules whose calls to this hook must come
- * before this module.
- * successors -> a list of modules whose calls to this hook must come
- * after this module.
- * position -> The relative position of this module. One of APR_HOOK_FIRST,
- * APR_HOOK_MIDDLE, or APR_HOOK_LAST. Most modules will use
- * APR_HOOK_MIDDLE. If multiple modules use the same relative
- * position, Apache will determine which to call first.
- * If your module relies on another module to run first,
- * or another module running after yours, use the
- * predecessors and/or successors.
- *
- * The number in brackets indicates the order in which the routine is called
- * during request processing. Note that not all routines are necessarily
- * called (such as if a resource doesn't have access restrictions).
- * The actual delivery of content to the browser [9] is not handled by
- * a hook; see the handler declarations below.
- */
-static void example_register_hooks(apr_pool_t *p)
-{
- /* module initializer */
- ap_hook_post_config(example_init,
- NULL, NULL, APR_HOOK_MIDDLE);
- /* [1] post read_request handling */
- ap_hook_post_read_request(example_post_read_request,
- NULL, NULL, APR_HOOK_MIDDLE);
- /* [2] filename-to-URI translation */
- ap_hook_translate_name(example_translate_handler,
- NULL, NULL, APR_HOOK_MIDDLE);
- /* [3] header parser */
- ap_hook_header_parser(example_header_parser,
- NULL, NULL, APR_HOOK_MIDDLE);
- /* [4] check access by host address */
- ap_hook_access_checker(example_access_checker,
- NULL, NULL, APR_HOOK_MIDDLE);
- /* [5] check/validate user_id */
- ap_hook_check_user_id(example_check_user_id,
- NULL, NULL, APR_HOOK_MIDDLE);
- /* [6] check user_id is valid *here* */
- ap_hook_auth_checker(example_auth_checker,
- NULL, NULL, APR_HOOK_MIDDLE);
- /* [7] MIME type checker/setter */
- ap_hook_type_checker(example_type_checker,
- NULL, NULL, APR_HOOK_MIDDLE);
- /* [8] fixups */
- ap_hook_fixups(example_fixer_upper,
- NULL, NULL, APR_HOOK_MIDDLE);
- /* [9] is for the handlers; see below */
-
- /* [10] logger */
- ap_hook_log_transaction(example_logger,
- NULL, NULL, APR_HOOK_MIDDLE);
- /* process initializer */
- ap_hook_child_init(example_child_init,
- NULL, NULL, APR_HOOK_MIDDLE);
-}
-
-/*--------------------------------------------------------------------------*/
-/* */
-/* All of the routines have been declared now. Here's the list of */
-/* directives specific to our module, and information about where they */
-/* may appear and how the command parser should pass them to us for */
-/* processing. Note that care must be taken to ensure that there are NO */
-/* collisions of directive names between modules. */
-/* */
-/*--------------------------------------------------------------------------*/
-/*
- * List of directives specific to our module.
- */
-static const command_rec example_cmds[] =
-{
- AP_INIT_NO_ARGS(
- "Example", /* directive name */
- cmd_example, /* config action routine */
- NULL, /* argument to include in call */
- OR_OPTIONS, /* where available */
- "Example directive - no arguments" /* directive description */
- ),
- {NULL}
-};
-
-/*--------------------------------------------------------------------------*/
-/* */
-/* Now the list of content handlers available from this module. */
-/* */
-/*--------------------------------------------------------------------------*/
-/*
- * List of content handlers our module supplies. Each handler is defined by
- * two parts: a name by which it can be referenced (such as by
- * {Add,Set}Handler), and the actual routine name. The list is terminated by
- * a NULL block, since it can be of variable length.
- *
- * Note that content-handlers are invoked on a most-specific to least-specific
- * basis; that is, a handler that is declared for "text/plain" will be
- * invoked before one that was declared for "text / *". Note also that
- * if a content-handler returns anything except DECLINED, no other
- * content-handlers will be called.
- */
-static const handler_rec example_handlers[] =
-{
- {"example-handler", example_handler},
- {NULL}
-};
-
-/*--------------------------------------------------------------------------*/
-/* */
-/* Finally, the list of callback routines and data structures that provide */
-/* the static hooks into our module from the other parts of the server. */
-/* */
-/*--------------------------------------------------------------------------*/
-/*
- * Module definition for configuration. If a particular callback is not
- * needed, replace its routine name below with the word NULL.
- */
-module example_module =
-{
- STANDARD20_MODULE_STUFF,
- 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, /* list of content delivery handlers */
- example_register_hooks, /* set up other request processing hooks */
-};
diff --git a/modules/experimental/mod_ext_filter.c b/modules/experimental/mod_ext_filter.c
deleted file mode 100644
index 46b4b1e527..0000000000
--- a/modules/experimental/mod_ext_filter.c
+++ /dev/null
@@ -1,793 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * mod_ext_filter allows Unix-style filters to filter http content.
- */
-
-#include "httpd.h"
-#include "http_config.h"
-#include "http_log.h"
-#define CORE_PRIVATE
-#include "http_core.h"
-#include "apr_buckets.h"
-#include "util_filter.h"
-#include "apr_strings.h"
-#include "apr_hash.h"
-#include "apr_lib.h"
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-typedef struct ef_server_t {
- apr_pool_t *p;
- apr_hash_t *h;
-} ef_server_t;
-
-typedef struct ef_filter_t {
- const char *name;
- enum {INPUT_FILTER=1, OUTPUT_FILTER} mode;
- const char *command;
- int numArgs;
- char *args[30];
- const char *intype; /* list of IMTs we process (well, just one for now) */
-#define INTYPE_ALL (char *)1
- const char *outtype; /* IMT of filtered output */
-#define OUTTYPE_UNCHANGED (char *)1
- int preserves_content_length;
-} ef_filter_t;
-
-typedef struct ef_dir_t {
- int debug;
- int log_stderr;
-} ef_dir_t;
-
-typedef struct ef_ctx_t {
- apr_pool_t *p;
- apr_proc_t *proc;
- apr_procattr_t *procattr;
- ef_dir_t *dc;
- ef_filter_t *filter;
- int noop;
-#if APR_FILES_AS_SOCKETS
- apr_pollfd_t *pollset;
-#endif
-} ef_ctx_t;
-
-module ext_filter_module;
-
-static apr_status_t ef_output_filter(ap_filter_t *, apr_bucket_brigade *);
-
-#define DBGLVL_SHOWOPTIONS 1
-#define DBGLVL_GORY 9
-
-static void *create_ef_dir_conf(apr_pool_t *p, char *dummy)
-{
- ef_dir_t *dc = (ef_dir_t *)apr_pcalloc(p, sizeof(ef_dir_t));
-
- dc->debug = -1;
- dc->log_stderr = -1;
-
- return dc;
-}
-
-static void *create_ef_server_conf(apr_pool_t *p, server_rec *s)
-{
- ef_server_t *conf;
-
- conf = (ef_server_t *)apr_pcalloc(p, sizeof(ef_server_t));
- conf->p = p;
- conf->h = apr_hash_make(conf->p);
- return conf;
-}
-
-static void *merge_ef_dir_conf(apr_pool_t *p, void *basev, void *overridesv)
-{
- ef_dir_t *a = (ef_dir_t *)apr_pcalloc (p, sizeof(ef_dir_t));
- ef_dir_t *base = (ef_dir_t *)basev, *over = (ef_dir_t *)overridesv;
-
- if (over->debug != -1) { /* if admin coded something... */
- a->debug = over->debug;
- }
- else {
- a->debug = base->debug;
- }
-
- if (over->log_stderr != -1) { /* if admin coded something... */
- a->log_stderr = over->log_stderr;
- }
- else {
- a->log_stderr = base->log_stderr;
- }
-
- return a;
-}
-
-static const char *add_options(cmd_parms *cmd, void *in_dc,
- const char *arg)
-{
- ef_dir_t *dc = in_dc;
-
- if (!strncasecmp(arg, "DebugLevel=", 11)) {
- dc->debug = atoi(arg + 11);
- }
- else if (!strcasecmp(arg, "LogStderr")) {
- dc->log_stderr = 1;
- }
- else if (!strcasecmp(arg, "NoLogStderr")) {
- dc->log_stderr = 0;
- }
- else {
- return apr_pstrcat(cmd->temp_pool,
- "Invalid ExtFilterOptions option: ",
- arg,
- NULL);
- }
-
- return NULL;
-}
-
-static const char *parse_cmd(apr_pool_t *p, const char **args, ef_filter_t *filter)
-{
- if (**args == '"') {
- const char *start = *args + 1;
- char *parms;
-
- ++*args; /* move past leading " */
- while (**args && **args != '"') {
- ++*args;
- }
- if (**args != '"') {
- return "Expected cmd= delimiter";
- }
- parms = apr_pstrndup(p, start, *args - start);
- ++*args; /* move past trailing " */
-
- /* parms now has the command-line to parse */
- while (filter->numArgs < 30 &&
- strlen(filter->args[filter->numArgs] = ap_getword_white_nc(p, &parms))) {
- ++filter->numArgs;
- }
- if (filter->numArgs < 1) {
- return "cmd= parse error";
- }
- filter->args[filter->numArgs] = NULL; /* we stored "" in the while() loop */
- filter->command = filter->args[0];
- }
- else
- {
- /* simple path */
- filter->args[0] = ap_getword_white(p, args);
- if (!filter->args[0]) {
- return "Invalid cmd= parameter";
- }
- filter->numArgs = 1;
- filter->command = filter->args[0];
- }
- return NULL;
-}
-
-static const char *define_filter(cmd_parms *cmd, void *dummy, const char *args)
-{
- ef_server_t *conf = ap_get_module_config(cmd->server->module_config,
- &ext_filter_module);
- const char *token;
- const char *name;
- ef_filter_t *filter;
-
- name = ap_getword_white(cmd->pool, &args);
- if (!name) {
- return "Filter name not found";
- }
-
- if (apr_hash_get(conf->h, name, APR_HASH_KEY_STRING)) {
- return apr_psprintf(cmd->pool, "ExtFilter %s is already defined",
- name);
- }
-
- filter = (ef_filter_t *)apr_pcalloc(conf->p, sizeof(ef_filter_t));
- filter->name = name;
- filter->mode = OUTPUT_FILTER;
- apr_hash_set(conf->h, name, APR_HASH_KEY_STRING, filter);
-
- while (*args) {
- while (apr_isspace(*args)) {
- ++args;
- }
-
- /* Nasty parsing... I wish I could simply use ap_getword_white()
- * here and then look at the token, but ap_getword_white() doesn't
- * do the right thing when we have cmd="word word word"
- */
- if (!strncasecmp(args, "preservescontentlength", 22)) {
- token = ap_getword_white(cmd->pool, &args);
- if (!strcasecmp(token, "preservescontentlength")) {
- filter->preserves_content_length = 1;
- }
- else {
- return apr_psprintf(cmd->pool,
- "mangled argument `%s'",
- token);
- }
- continue;
- }
-
- if (!strncasecmp(args, "mode=", 5)) {
- args += 5;
- token = ap_getword_white(cmd->pool, &args);
- if (!strcasecmp(token, "output")) {
- filter->mode = OUTPUT_FILTER;
- }
- else if (!strcasecmp(token, "input")) {
- filter->mode = INPUT_FILTER;
- }
- else {
- return apr_psprintf(cmd->pool, "Invalid mode: `%s'",
- token);
- }
- continue;
- }
-
- if (!strncasecmp(args, "intype=", 7)) {
- args += 7;
- filter->intype = ap_getword_white(cmd->pool, &args);
- continue;
- }
-
- if (!strncasecmp(args, "outtype=", 8)) {
- args += 8;
- filter->outtype = ap_getword_white(cmd->pool, &args);
- continue;
- }
-
- if (!strncasecmp(args, "cmd=", 4)) {
- args += 4;
- if ((token = parse_cmd(cmd->pool, &args, filter))) {
- return token;
- }
- continue;
- }
-
- return apr_psprintf(cmd->pool, "Unexpected parameter: `%s'",
- args);
- }
-
- /* parsing is done... register the filter
- */
- if (filter->mode == OUTPUT_FILTER) {
- /* XXX need a way to ensure uniqueness among all filters */
- ap_register_output_filter(filter->name, ef_output_filter, AP_FTYPE_CONTENT);
- }
-#if 0 /* no input filters yet */
- else if (filter->mode == INPUT_FILTER) {
- /* XXX need a way to ensure uniqueness among all filters */
- ap_register_input_filter(filter->name, ef_input_filter, AP_FTYPE_CONTENT);
- }
-#endif
- else {
- ap_assert(1 != 1); /* we set the field wrong somehow */
- }
-
- return NULL;
-}
-
-static const command_rec cmds[] =
-{
- AP_INIT_ITERATE("ExtFilterOptions",
- add_options,
- NULL,
- ACCESS_CONF, /* same as SetInputFilter/SetOutputFilter */
- "valid options: DebugLevel=n, LogStderr, NoLogStderr"),
- AP_INIT_RAW_ARGS("ExtFilterDefine",
- define_filter,
- NULL,
- RSRC_CONF,
- "Define an external filter"),
- {NULL}
-};
-
-static apr_status_t set_resource_limits(request_rec *r,
- apr_procattr_t *procattr)
-{
-#if defined(RLIMIT_CPU) || defined(RLIMIT_NPROC) || \
- defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined (RLIMIT_AS)
- core_dir_config *conf =
- (core_dir_config *)ap_get_module_config(r->per_dir_config,
- &core_module);
- apr_status_t rv;
-
-#ifdef RLIMIT_CPU
- rv = apr_procattr_limit_set(procattr, APR_LIMIT_CPU, conf->limit_cpu);
- ap_assert(rv == APR_SUCCESS); /* otherwise, we're out of sync with APR */
-#endif
-#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
- rv = apr_procattr_limit_set(procattr, APR_LIMIT_MEM, conf->limit_mem);
- ap_assert(rv == APR_SUCCESS); /* otherwise, we're out of sync with APR */
-#endif
-#ifdef RLIMIT_NPROC
- rv = apr_procattr_limit_set(procattr, APR_LIMIT_NPROC, conf->limit_nproc);
- ap_assert(rv == APR_SUCCESS); /* otherwise, we're out of sync with APR */
-#endif
-
-#endif /* if at least one limit defined */
-
- return APR_SUCCESS;
-}
-
-static apr_status_t ef_close_file(void *vfile)
-{
- return apr_file_close(vfile);
-}
-
-/* init_ext_filter_process: get the external filter process going
- * This is per-filter-instance (i.e., per-request) initialization.
- */
-static apr_status_t init_ext_filter_process(ap_filter_t *f)
-{
- ef_ctx_t *ctx = f->ctx;
- apr_status_t rc;
- ef_dir_t *dc = ctx->dc;
-
- ctx->proc = apr_pcalloc(ctx->p, sizeof(*ctx->proc));
-
- rc = apr_procattr_create(&ctx->procattr, ctx->p);
- ap_assert(rc == APR_SUCCESS);
-
- rc = apr_procattr_io_set(ctx->procattr,
- APR_CHILD_BLOCK,
- APR_CHILD_BLOCK,
- APR_CHILD_BLOCK);
- ap_assert(rc == APR_SUCCESS);
-
- rc = set_resource_limits(f->r, ctx->procattr);
- ap_assert(rc == APR_SUCCESS);
-
- if (dc->log_stderr > 0) {
- rc = apr_procattr_child_err_set(ctx->procattr,
- f->r->server->error_log, /* stderr in child */
- NULL);
- ap_assert(rc == APR_SUCCESS);
- }
-
- rc = apr_proc_create(ctx->proc,
- ctx->filter->command,
- (const char * const *)ctx->filter->args,
- NULL, /* environment */
- ctx->procattr,
- ctx->p);
- if (rc != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, f->r,
- "couldn't create child process to run `%s'",
- ctx->filter->command);
- return rc;
- }
-
- apr_pool_note_subprocess(ctx->p, ctx->proc, kill_after_timeout);
-
- /* We don't want the handle to the child's stdin inherited by any
- * other processes created by httpd. Otherwise, when we close our
- * handle, the child won't see EOF because another handle will still
- * be open.
- */
-
- apr_pool_cleanup_register(ctx->p, ctx->proc->in,
- apr_pool_cleanup_null, /* other mechanism */
- ef_close_file);
-
-#if APR_FILES_AS_SOCKETS
- {
- apr_socket_t *newsock;
-
- rc = apr_poll_setup(&ctx->pollset, 2, ctx->p);
- ap_assert(rc == APR_SUCCESS);
- rc = apr_socket_from_file(&newsock, ctx->proc->in);
- ap_assert(rc == APR_SUCCESS);
- rc = apr_poll_socket_add(ctx->pollset, newsock, APR_POLLOUT);
- ap_assert(rc == APR_SUCCESS);
- rc = apr_socket_from_file(&newsock, ctx->proc->out);
- ap_assert(rc == APR_SUCCESS);
- rc = apr_poll_socket_add(ctx->pollset, newsock, APR_POLLIN);
- ap_assert(rc == APR_SUCCESS);
- }
-#endif
-
- return APR_SUCCESS;
-}
-
-static const char *get_cfg_string(ef_dir_t *dc, ef_filter_t *filter, apr_pool_t *p)
-{
- const char *debug_str = dc->debug == -1 ?
- "DebugLevel=0" : apr_psprintf(p, "DebugLevel=%d", dc->debug);
- const char *log_stderr_str = dc->log_stderr < 1 ?
- "NoLogStderr" : "LogStderr";
- const char *preserve_content_length_str = filter->preserves_content_length ?
- "PreservesContentLength" : "!PreserveContentLength";
- const char *intype_str = !filter->intype ?
- "*/*" : filter->intype;
- const char *outtype_str = !filter->outtype ?
- "(unchanged)" : filter->outtype;
-
- return apr_psprintf(p,
- "ExtFilterOptions %s %s %s ExtFilterInType %s "
- "ExtFilterOuttype %s",
- debug_str, log_stderr_str, preserve_content_length_str,
- intype_str, outtype_str);
-}
-
-static apr_status_t init_filter_instance(ap_filter_t *f)
-{
- ef_ctx_t *ctx;
- ef_dir_t *dc;
- ef_server_t *sc;
- apr_status_t rv;
-
- f->ctx = ctx = apr_pcalloc(f->r->pool, sizeof(ef_ctx_t));
- dc = ap_get_module_config(f->r->per_dir_config,
- &ext_filter_module);
- sc = ap_get_module_config(f->r->server->module_config,
- &ext_filter_module);
- ctx->dc = dc;
- /* look for the user-defined filter */
- ctx->filter = apr_hash_get(sc->h, f->frec->name, APR_HASH_KEY_STRING);
- if (!ctx->filter) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, f->r,
- "couldn't find definition of filter '%s'",
- f->frec->name);
- return APR_EINVAL;
- }
- ctx->p = f->r->pool;
- if (ctx->filter->intype &&
- ctx->filter->intype != INTYPE_ALL &&
- strcasecmp(ctx->filter->intype, f->r->content_type)) {
- /* wrong IMT for us; don't mess with the output */
- ctx->noop = 1;
- }
- else {
- rv = init_ext_filter_process(f);
- if (rv != APR_SUCCESS) {
- return rv;
- }
- if (ctx->filter->outtype &&
- ctx->filter->outtype != OUTTYPE_UNCHANGED) {
- f->r->content_type = ctx->filter->outtype;
- }
- if (ctx->filter->preserves_content_length != 1) {
- /* nasty, but needed to avoid confusing the browser
- */
- apr_table_unset(f->r->headers_out, "Content-Length");
- }
- }
-
- if (dc->debug >= DBGLVL_SHOWOPTIONS) {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, f->r,
- "%sfiltering `%s' through `%s', cfg %s",
- ctx->noop ? "skipping: " : "",
- f->r->uri ? f->r->uri : f->r->filename,
- ctx->filter->command,
- get_cfg_string(dc, ctx->filter, f->r->pool));
- }
-
- return APR_SUCCESS;
-}
-
-/* drain_available_output():
- *
- * if any data is available from the filter, read it and pass it
- * to the next filter
- */
-static apr_status_t drain_available_output(ap_filter_t *f)
-{
- ef_ctx_t *ctx = f->ctx;
- ef_dir_t *dc = ctx->dc;
- apr_size_t len;
- char buf[4096];
- apr_status_t rv;
- apr_bucket_brigade *bb;
- apr_bucket *b;
-
- while (1) {
- len = sizeof(buf);
- rv = apr_file_read(ctx->proc->out,
- buf,
- &len);
- if ((rv && !APR_STATUS_IS_EAGAIN(rv)) ||
- dc->debug >= DBGLVL_GORY) {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, f->r,
- "apr_file_read(child output), len %" APR_SIZE_T_FMT,
- !rv ? len : -1);
- }
- if (rv != APR_SUCCESS) {
- return rv;
- }
- bb = apr_brigade_create(f->r->pool);
- b = apr_bucket_transient_create(buf, len);
- APR_BRIGADE_INSERT_TAIL(bb, b);
- if ((rv = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r,
- "ap_pass_brigade()");
- return rv;
- }
- }
- /* we should never get here; if we do, a bogus error message would be
- * the least of our problems
- */
- return APR_ANONYMOUS;
-}
-
-static apr_status_t pass_data_to_filter(ap_filter_t *f, const char *data,
- apr_ssize_t len)
-{
- ef_ctx_t *ctx = f->ctx;
- ef_dir_t *dc = ctx->dc;
- apr_status_t rv;
- apr_size_t bytes_written = 0;
- apr_size_t tmplen;
-
- do {
- tmplen = len - bytes_written;
- rv = apr_file_write(ctx->proc->in,
- (const char *)data + bytes_written,
- &tmplen);
- bytes_written += tmplen;
- if (rv != APR_SUCCESS && !APR_STATUS_IS_EAGAIN(rv)) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r,
- "apr_file_write(child input), len %" APR_SIZE_T_FMT,
- tmplen);
- return rv;
- }
- if (APR_STATUS_IS_EAGAIN(rv)) {
- /* XXX handle blocking conditions here... if we block, we need
- * to read data from the child process and pass it down to the
- * next filter!
- */
- rv = drain_available_output(f);
- if (APR_STATUS_IS_EAGAIN(rv)) {
-#if APR_FILES_AS_SOCKETS
- int num_events;
-
- rv = apr_poll(ctx->pollset,
- &num_events,
- f->r->server->timeout * APR_USEC_PER_SEC);
- if (rv || dc->debug >= DBGLVL_GORY) {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG,
- rv, f->r, "apr_poll()");
- }
- if (rv != APR_SUCCESS && !APR_STATUS_IS_EINTR(rv)) {
- /* some error such as APR_TIMEUP */
- return rv;
- }
-#else /* APR_FILES_AS_SOCKETS */
- /* Yuck... I'd really like to wait until I can read
- * or write, but instead I have to sleep and try again
- */
- apr_sleep(100000); /* 100 milliseconds */
- if (dc->debug >= DBGLVL_GORY) {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO,
- 0, f->r, "apr_sleep()");
- }
-#endif /* APR_FILES_AS_SOCKETS */
- }
- else if (rv != APR_SUCCESS) {
- return rv;
- }
- }
- } while (bytes_written < len);
- return rv;
-}
-
-static apr_status_t ef_output_filter(ap_filter_t *f, apr_bucket_brigade *bb)
-{
- ef_ctx_t *ctx = f->ctx;
- apr_bucket *b;
- ef_dir_t *dc;
- apr_size_t len;
- const char *data;
- apr_status_t rv;
- char buf[4096];
- apr_bucket *eos = NULL;
-
- if (!ctx) {
- if ((rv = init_filter_instance(f)) != APR_SUCCESS) {
- return rv;
- }
- ctx = f->ctx;
- }
- if (ctx->noop) {
- ap_remove_output_filter(f);
- return ap_pass_brigade(f->next, bb);
- }
- dc = ctx->dc;
-
- APR_BRIGADE_FOREACH(b, bb) {
-
- if (APR_BUCKET_IS_EOS(b)) {
- eos = b;
- break;
- }
-
- rv = apr_bucket_read(b, &data, &len, APR_BLOCK_READ);
- if (rv != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r, "apr_bucket_read()");
- return rv;
- }
-
- if (len > 0 &&
- (rv = pass_data_to_filter(f, data, len)) != APR_SUCCESS) {
- return rv;
- }
- }
-
- apr_brigade_destroy(bb);
-
- /* XXX What we *really* need to do once we've hit eos is create a pipe bucket
- * from the child output pipe and pass down the pipe bucket + eos.
- */
- if (eos) {
- /* close the child's stdin to signal that no more data is coming;
- * that will cause the child to finish generating output
- */
- if ((rv = apr_file_close(ctx->proc->in)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r,
- "apr_file_close(child input)");
- return rv;
- }
- /* since we've seen eos and closed the child's stdin, set the proper pipe
- * timeout; we don't care if we don't return from apr_file_read() for a while...
- */
- rv = apr_file_pipe_timeout_set(ctx->proc->out,
- f->r->server->timeout * APR_USEC_PER_SEC);
- if (rv) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r,
- "apr_file_pipe_timeout_set(child output)");
- return rv;
- }
- }
-
- do {
- len = sizeof(buf);
- rv = apr_file_read(ctx->proc->out,
- buf,
- &len);
- if ((rv && !APR_STATUS_IS_EOF(rv) && !APR_STATUS_IS_EAGAIN(rv)) ||
- dc->debug >= DBGLVL_GORY) {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, f->r,
- "apr_file_read(child output), len %" APR_SIZE_T_FMT,
- !rv ? len : -1);
- }
- if (APR_STATUS_IS_EAGAIN(rv)) {
- if (eos) {
- /* should not occur, because we have an APR timeout in place */
- AP_DEBUG_ASSERT(1 != 1);
- }
- return APR_SUCCESS;
- }
-
- if (rv == APR_SUCCESS) {
- bb = apr_brigade_create(f->r->pool);
- b = apr_bucket_transient_create(buf, len);
- APR_BRIGADE_INSERT_TAIL(bb, b);
- if ((rv = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r,
- "ap_pass_brigade(filtered buffer) failed");
- return rv;
- }
- }
- } while (rv == APR_SUCCESS);
-
- if (!APR_STATUS_IS_EOF(rv)) {
- return rv;
- }
-
- if (eos) {
- /* pass down eos */
- bb = apr_brigade_create(f->r->pool);
- b = apr_bucket_eos_create();
- APR_BRIGADE_INSERT_TAIL(bb, b);
- if ((rv = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r,
- "ap_pass_brigade(eos) failed");
- return rv;
- }
- }
-
- return APR_SUCCESS;
-}
-
-#if 0
-static int ef_input_filter(ap_filter_t *f, apr_bucket_brigade *bb,
- ap_input_mode_t mode, apr_size_t *readbytes)
-{
- apr_status_t rv;
- apr_bucket *b;
- char *buf;
- apr_ssize_t len;
- char *zero;
-
- rv = ap_get_brigade(f->next, bb, mode, readbytes);
- if (rv != APR_SUCCESS) {
- return rv;
- }
-
- APR_BRIGADE_FOREACH(b, bb) {
- if (!APR_BUCKET_IS_EOS(b)) {
- if ((rv = apr_bucket_read(b, (const char **)&buf, &len, APR_BLOCK_READ)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r, "apr_bucket_read() failed");
- return rv;
- }
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "apr_bucket_read -> %d bytes",
- len);
- while ((zero = memchr(buf, '0', len))) {
- *zero = 'a';
- }
- }
- else
- ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "got eos bucket");
- }
-
- return rv;
-}
-#endif
-
-module ext_filter_module =
-{
- STANDARD20_MODULE_STUFF,
- create_ef_dir_conf,
- merge_ef_dir_conf,
- create_ef_server_conf,
- NULL,
- cmds,
-};
diff --git a/modules/experimental/mod_generic_hook_export.c b/modules/experimental/mod_generic_hook_export.c
deleted file mode 100644
index 38ee86815d..0000000000
--- a/modules/experimental/mod_generic_hook_export.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "httpd.h"
-#include "http_config.h"
-#include "mod_generic_hook_export.h"
-#include "http_protocol.h"
-
-APR_IMPLEMENT_GENERIC_HOOK_RUN_ALL(ap,AP_MODULE,int,generic_hook_test,(const char *szStr),
- (szStr),OK,DECLINED)
-
-static int ExportLogTransaction(request_rec *r)
-{
- return ap_run_generic_hook_test(r->the_request);
-}
-
-static void ExportRegisterHooks(apr_pool_t *p)
-{
- ap_hook_log_transaction(ExportLogTransaction,NULL,NULL,APR_HOOK_MIDDLE);
-}
-
-module generic_hook_export_module =
-{
- STANDARD20_MODULE_STUFF,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- ExportRegisterHooks
-};
diff --git a/modules/experimental/mod_generic_hook_export.dsp b/modules/experimental/mod_generic_hook_export.dsp
deleted file mode 100644
index 711a041565..0000000000
--- a/modules/experimental/mod_generic_hook_export.dsp
+++ /dev/null
@@ -1,95 +0,0 @@
-# Microsoft Developer Studio Project File - Name="mod_generic_hook_export" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=mod_generic_hook_export - Win32 Release
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "mod_generic_hook_export.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_generic_hook_export.mak" CFG="mod_generic_hook_export - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_generic_hook_export - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_generic_hook_export - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "mod_generic_hook_export - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\os\win32" /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_generic_hook_export" /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "NDEBUG"
-# ADD RSC /l 0x809 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_generic_hook_export.so" /machine:I386
-# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_generic_hook_export.so" /machine:I386
-
-!ELSEIF "$(CFG)" == "mod_generic_hook_export - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\..\include" /I "..\..\os\win32" /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_generic_hook_export" /FD /c
-# ADD BASE MTL /nologo /D "_DEBUG" /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "_DEBUG"
-# ADD RSC /l 0x809 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /out:"Debug/mod_generic_hook_export.so" /machine:I386
-# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map/debug /out:"Debug/mod_generic_hook_export.so" /machine:I386
-
-!ENDIF
-
-# Begin Target
-
-# Name "mod_generic_hook_export - Win32 Release"
-# Name "mod_generic_hook_export - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\mod_generic_hook_export.c
-# End Source File
-# End Target
-# End Project
diff --git a/modules/experimental/mod_generic_hook_export.h b/modules/experimental/mod_generic_hook_export.h
deleted file mode 100644
index a55d2f227c..0000000000
--- a/modules/experimental/mod_generic_hook_export.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef MOD_GENERIC_HOOK_EXPORT_H
-#define MOD_GENERIC_HOOK_EXPORT_H
-
-#include "apr_generic_hook.h"
-
-APR_DECLARE_EXTERNAL_HOOK(ap,AP_MODULE,int,generic_hook_test,(const char *))
-
-#endif /* def MOD_GENERIC_HOOK_EXPORT_H */
diff --git a/modules/experimental/mod_generic_hook_import.c b/modules/experimental/mod_generic_hook_import.c
deleted file mode 100644
index f46fa44df5..0000000000
--- a/modules/experimental/mod_generic_hook_import.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "httpd.h"
-#include "http_config.h"
-#include "http_log.h"
-#include "mod_generic_hook_export.h"
-
-static int ImportGenericHookTestHook(const char *szStr)
-{
- ap_log_error(APLOG_MARK,APLOG_ERR,OK,NULL,"Generic hook test said: %s",
- szStr);
-
- return OK;
-}
-
-static void ImportRegisterHooks(apr_pool_t *p)
-{
- APR_HOOK_GENERIC(ap,generic_hook_test,ImportGenericHookTestHook,NULL,NULL,
- APR_HOOK_MIDDLE);
-}
-
-module generic_hook_import_module=
-{
- STANDARD20_MODULE_STUFF,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- ImportRegisterHooks
-};
diff --git a/modules/experimental/mod_generic_hook_import.dsp b/modules/experimental/mod_generic_hook_import.dsp
deleted file mode 100644
index 78068294ab..0000000000
--- a/modules/experimental/mod_generic_hook_import.dsp
+++ /dev/null
@@ -1,95 +0,0 @@
-# Microsoft Developer Studio Project File - Name="mod_generic_hook_import" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=mod_generic_hook_import - Win32 Release
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "mod_generic_hook_import.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_generic_hook_import.mak" CFG="mod_generic_hook_import - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_generic_hook_import - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_generic_hook_import - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "mod_generic_hook_import - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\os\win32" /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_generic_hook_import" /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "NDEBUG"
-# ADD RSC /l 0x809 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_generic_hook_import.so" /machine:I386
-# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_generic_hook_import.so" /machine:I386
-
-!ELSEIF "$(CFG)" == "mod_generic_hook_import - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\..\include" /I "..\..\os\win32" /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_generic_hook_import" /FD /c
-# ADD BASE MTL /nologo /D "_DEBUG" /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "_DEBUG"
-# ADD RSC /l 0x809 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /out:"Debug/mod_generic_hook_import.so" /machine:I386
-# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map/debug /out:"Debug/mod_generic_hook_import.so" /machine:I386
-
-!ENDIF
-
-# Begin Target
-
-# Name "mod_generic_hook_import - Win32 Release"
-# Name "mod_generic_hook_import - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\mod_generic_hook_import.c
-# End Source File
-# End Target
-# End Project
diff --git a/modules/experimental/mod_optional_fn_export.c b/modules/experimental/mod_optional_fn_export.c
deleted file mode 100644
index b214a36621..0000000000
--- a/modules/experimental/mod_optional_fn_export.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "httpd.h"
-#include "http_config.h"
-#include "http_log.h"
-#include "mod_optional_fn_export.h"
-
-/* The alert will note a strange mirror-image style resemblance to
- * mod_generic_hook_import.c. Yes, I _did_ mean import. Think about it.
- */
-
-static int TestOptionalFn(const char *szStr)
-{
- ap_log_error(APLOG_MARK,APLOG_ERR,OK,NULL,
- "Optional function test said: %s",szStr);
-
- return OK;
-}
-
-static void ExportRegisterHooks(apr_pool_t *p)
-{
- APR_REGISTER_OPTIONAL_FN(TestOptionalFn);
-}
-
-module optional_fn_export_module=
-{
- STANDARD20_MODULE_STUFF,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- ExportRegisterHooks
-};
diff --git a/modules/experimental/mod_optional_fn_export.h b/modules/experimental/mod_optional_fn_export.h
deleted file mode 100644
index a1950f373b..0000000000
--- a/modules/experimental/mod_optional_fn_export.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#include "apr_optional.h"
-
-APR_DECLARE_OPTIONAL_FN(int,TestOptionalFn,(const char *));
diff --git a/modules/experimental/mod_optional_fn_import.c b/modules/experimental/mod_optional_fn_import.c
deleted file mode 100644
index 3be3b6be6d..0000000000
--- a/modules/experimental/mod_optional_fn_import.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "httpd.h"
-#include "http_config.h"
-#include "mod_optional_fn_export.h"
-#include "http_protocol.h"
-
-/* The alert will note a strange mirror-image style resemblance to
- * mod_generic_hook_export.c. Yes, I _did_ mean export. Think about it.
- */
-
-static APR_OPTIONAL_FN_TYPE(TestOptionalFn) *pfn;
-
-static int ImportLogTransaction(request_rec *r)
-{
- if(pfn)
- return pfn(r->the_request);
- return DECLINED;
-}
-
-static void ImportFnRetrieve(void)
-{
- pfn=APR_RETRIEVE_OPTIONAL_FN(TestOptionalFn);
-}
-
-static void ImportRegisterHooks(apr_pool_t *p)
-{
- ap_hook_log_transaction(ImportLogTransaction,NULL,NULL,APR_HOOK_MIDDLE);
- ap_hook_optional_fn_retrieve(ImportFnRetrieve,NULL,NULL,APR_HOOK_MIDDLE);
-}
-
-module optional_fn_import_module =
-{
- STANDARD20_MODULE_STUFF,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- ImportRegisterHooks
-};
diff --git a/modules/filters/.cvsignore b/modules/filters/.cvsignore
deleted file mode 100644
index 65f0cc30cf..0000000000
--- a/modules/filters/.cvsignore
+++ /dev/null
@@ -1,10 +0,0 @@
-.deps
-.libs
-*.la
-modules.mk
-Makefile
-*.lo
-*.slo
-*.so
-Debug
-Release
diff --git a/modules/filters/.indent.pro b/modules/filters/.indent.pro
deleted file mode 100644
index a9fbe9f9a1..0000000000
--- a/modules/filters/.indent.pro
+++ /dev/null
@@ -1,54 +0,0 @@
--i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1
--TBUFF
--TFILE
--TTRANS
--TUINT4
--T_trans
--Tallow_options_t
--Tapache_sfio
--Tarray_header
--Tbool_int
--Tbuf_area
--Tbuff_struct
--Tbuffy
--Tcmd_how
--Tcmd_parms
--Tcommand_rec
--Tcommand_struct
--Tconn_rec
--Tcore_dir_config
--Tcore_server_config
--Tdir_maker_func
--Tevent
--Tglobals_s
--Thandler_func
--Thandler_rec
--Tjoblist_s
--Tlisten_rec
--Tmerger_func
--Tmode_t
--Tmodule
--Tmodule_struct
--Tmutex
--Tn_long
--Tother_child_rec
--Toverrides_t
--Tparent_score
--Tpid_t
--Tpiped_log
--Tpool
--Trequest_rec
--Trequire_line
--Trlim_t
--Tscoreboard
--Tsemaphore
--Tserver_addr_rec
--Tserver_rec
--Tserver_rec_chain
--Tshort_score
--Ttable
--Ttable_entry
--Tthread
--Tu_wide_int
--Tvtime_t
--Twide_int
diff --git a/modules/filters/Makefile.in b/modules/filters/Makefile.in
deleted file mode 100644
index 167b343d0d..0000000000
--- a/modules/filters/Makefile.in
+++ /dev/null
@@ -1,3 +0,0 @@
-
-include $(top_srcdir)/build/special.mk
-
diff --git a/modules/filters/config.m4 b/modules/filters/config.m4
deleted file mode 100644
index 10fc0231ef..0000000000
--- a/modules/filters/config.m4
+++ /dev/null
@@ -1,11 +0,0 @@
-dnl modules enabled in this directory by default
-
-dnl APACHE_MODULE(name, helptext[, objects[, structname[, default[, config]]]])
-
-APACHE_MODPATH_INIT(filters)
-
-APACHE_MODULE(include, Server Side Includes, , , yes)
-
-APR_ADDTO(LTFLAGS,-export-dynamic)
-
-APACHE_MODPATH_FINISH
diff --git a/modules/filters/mod_include.c b/modules/filters/mod_include.c
deleted file mode 100644
index ff3a1af295..0000000000
--- a/modules/filters/mod_include.c
+++ /dev/null
@@ -1,2854 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * http_include.c: Handles the server-parsed HTML documents
- *
- * Original by Rob McCool; substantial fixups by David Robinson;
- * incorporated into the Apache module framework by rst.
- *
- */
-
-#include "apr.h"
-#include "apr_strings.h"
-#include "apr_thread_proc.h"
-#include "apr_hash.h"
-#include "apr_user.h"
-#include "apr_lib.h"
-#include "apr_optional.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#define CORE_PRIVATE
-
-#include "ap_config.h"
-#include "util_filter.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_core.h"
-#include "http_request.h"
-#include "http_core.h"
-#include "http_protocol.h"
-#include "http_log.h"
-#include "http_main.h"
-#include "util_script.h"
-#include "http_core.h"
-#include "mod_include.h"
-#include "util_ebcdic.h"
-
-module AP_MODULE_DECLARE_DATA include_module;
-static apr_hash_t *include_hash;
-static APR_OPTIONAL_FN_TYPE(ap_register_include_handler) *ssi_pfn_register;
-
-#define BYTE_COUNT_THRESHOLD AP_MIN_BYTES_TO_WRITE
-
-/* ------------------------ Environment function -------------------------- */
-
-/* XXX: could use ap_table_overlap here */
-static void add_include_vars(request_rec *r, char *timefmt)
-{
- char *pwname;
- apr_table_t *e = r->subprocess_env;
- char *t;
- apr_time_t date = r->request_time;
-
- apr_table_setn(e, "DATE_LOCAL", ap_ht_time(r->pool, date, timefmt, 0));
- apr_table_setn(e, "DATE_GMT", ap_ht_time(r->pool, date, timefmt, 1));
- apr_table_setn(e, "LAST_MODIFIED",
- ap_ht_time(r->pool, r->finfo.mtime, timefmt, 0));
- apr_table_setn(e, "DOCUMENT_URI", r->uri);
- apr_table_setn(e, "DOCUMENT_PATH_INFO", r->path_info);
- if (apr_get_username(&pwname, r->finfo.user, r->pool) == APR_SUCCESS) {
- apr_table_setn(e, "USER_NAME", pwname);
- }
- else {
- apr_table_setn(e, "USER_NAME", "<unknown>");
- }
- if ((t = strrchr(r->filename, '/'))) {
- apr_table_setn(e, "DOCUMENT_NAME", ++t);
- }
- else {
- apr_table_setn(e, "DOCUMENT_NAME", r->uri);
- }
- if (r->args) {
- char *arg_copy = apr_pstrdup(r->pool, r->args);
-
- ap_unescape_url(arg_copy);
- apr_table_setn(e, "QUERY_STRING_UNESCAPED",
- ap_escape_shell_cmd(r->pool, arg_copy));
- }
-}
-
-
-
-/* --------------------------- Parser functions --------------------------- */
-
-/* This function returns either a pointer to the split bucket containing the
- * first byte of the BEGINNING_SEQUENCE (after finding a complete match) or it
- * returns NULL if no match found.
- */
-static apr_bucket *find_start_sequence(apr_bucket *dptr, include_ctx_t *ctx,
- apr_bucket_brigade *bb, int *do_cleanup)
-{
- apr_size_t len;
- const char *c;
- const char *buf;
- const char *str = STARTING_SEQUENCE;
- apr_bucket *tmp_bkt;
- apr_size_t start_index;
-
- *do_cleanup = 0;
-
- do {
- if (APR_BUCKET_IS_EOS(dptr)) {
- break;
- }
- apr_bucket_read(dptr, &buf, &len, APR_BLOCK_READ);
- /* XXX handle retcodes */
- if (len == 0) { /* end of pipe? */
- break;
- }
- c = buf;
- while (c - buf != len) {
- if (ctx->bytes_parsed >= BYTE_COUNT_THRESHOLD) {
- apr_bucket *start_bucket;
-
- if (ctx->head_start_index > 0) {
- start_index = ctx->head_start_index;
- start_bucket = ctx->head_start_bucket;
- }
- else {
- start_index = (c - buf);
- start_bucket = dptr;
- }
- apr_bucket_split(start_bucket, start_index);
- tmp_bkt = APR_BUCKET_NEXT(start_bucket);
- if (ctx->head_start_index > 0) {
- ctx->head_start_index = 0;
- ctx->head_start_bucket = tmp_bkt;
- }
-
- return tmp_bkt;
- }
-
- if (*c == str[ctx->parse_pos]) {
- if (ctx->state == PRE_HEAD) {
- ctx->state = PARSE_HEAD;
- ctx->head_start_bucket = dptr;
- ctx->head_start_index = c - buf;
- }
- ctx->parse_pos++;
- }
- else {
- if (str[ctx->parse_pos] == '\0') {
- /* We want to split the bucket at the '<'. */
- ctx->bytes_parsed++;
- ctx->state = PARSE_DIRECTIVE;
- ctx->tag_length = 0;
- ctx->parse_pos = 0;
- ctx->tag_start_bucket = dptr;
- ctx->tag_start_index = c - buf;
- if (ctx->head_start_index > 0) {
- start_index = (c - buf) - ctx->head_start_index;
- apr_bucket_split(ctx->head_start_bucket, ctx->head_start_index);
- tmp_bkt = APR_BUCKET_NEXT(ctx->head_start_bucket);
- if (dptr == ctx->head_start_bucket) {
- ctx->tag_start_bucket = tmp_bkt;
- ctx->tag_start_index = start_index;
- }
- ctx->head_start_bucket = tmp_bkt;
- ctx->head_start_index = 0;
- }
- return ctx->head_start_bucket;
- }
- else if (ctx->parse_pos != 0) {
- /* The reason for this, is that we need to make sure
- * that we catch cases like <<!--#. This makes the
- * second check after the original check fails.
- * If parse_pos was already 0 then we already checked this.
- */
- *do_cleanup = 1;
- if (*c == str[0]) {
- ctx->parse_pos = 1;
- ctx->state = PARSE_HEAD;
- ctx->head_start_bucket = dptr;
- ctx->head_start_index = c - buf;
- }
- else {
- ctx->parse_pos = 0;
- ctx->state = PRE_HEAD;
- ctx->head_start_bucket = NULL;
- ctx->head_start_index = 0;
- }
- }
- }
- c++;
- ctx->bytes_parsed++;
- }
- dptr = APR_BUCKET_NEXT(dptr);
- } while (dptr != APR_BRIGADE_SENTINEL(bb));
- return NULL;
-}
-
-static apr_bucket *find_end_sequence(apr_bucket *dptr, include_ctx_t *ctx, apr_bucket_brigade *bb)
-{
- apr_size_t len;
- const char *c;
- const char *buf;
- const char *str = ENDING_SEQUENCE;
-
- do {
- if (APR_BUCKET_IS_EOS(dptr)) {
- break;
- }
- apr_bucket_read(dptr, &buf, &len, APR_BLOCK_READ);
- /* XXX handle retcodes */
- if (len == 0) { /* end of pipe? */
- break;
- }
- if (dptr == ctx->tag_start_bucket) {
- c = buf + ctx->tag_start_index;
- }
- else {
- c = buf;
- }
- while (c - buf != len) {
- if (ctx->bytes_parsed >= BYTE_COUNT_THRESHOLD) {
- return dptr;
- }
-
- if (*c == str[ctx->parse_pos]) {
- if (ctx->state != PARSE_TAIL) {
- ctx->state = PARSE_TAIL;
- ctx->tail_start_bucket = dptr;
- ctx->tail_start_index = c - buf;
- }
- ctx->parse_pos++;
- }
- else {
- if (ctx->state == PARSE_DIRECTIVE) {
- if (ctx->tag_length == 0) {
- if (!apr_isspace(*c)) {
- ctx->tag_start_bucket = dptr;
- ctx->tag_start_index = c - buf;
- ctx->tag_length = 1;
- ctx->directive_length = 1;
- }
- }
- else {
- if (!apr_isspace(*c)) {
- ctx->directive_length++;
- }
- else {
- ctx->state = PARSE_TAG;
- }
- ctx->tag_length++;
- }
- }
- else if (ctx->state == PARSE_TAG) {
- ctx->tag_length++;
- }
- else {
- if (str[ctx->parse_pos] == '\0') {
- apr_bucket *tmp_buck = dptr;
-
- /* We want to split the bucket at the '>'. The
- * end of the END_SEQUENCE is in the current bucket.
- * The beginning might be in a previous bucket.
- */
- ctx->bytes_parsed++;
- ctx->state = PARSED;
- if ((c - buf) > 0) {
- apr_bucket_split(dptr, c - buf);
- tmp_buck = APR_BUCKET_NEXT(dptr);
- }
- return (tmp_buck);
- }
- else if (ctx->parse_pos != 0) {
- /* The reason for this, is that we need to make sure
- * that we catch cases like --->. This makes the
- * second check after the original check fails.
- * If parse_pos was already 0 then we already checked this.
- */
- ctx->tag_length += ctx->parse_pos;
-
- if (*c == str[0]) {
- ctx->state = PARSE_TAIL;
- ctx->tail_start_bucket = dptr;
- ctx->tail_start_index = c - buf;
- ctx->tag_length += ctx->parse_pos;
- ctx->parse_pos = 1;
- }
- else {
- if (ctx->tag_length > ctx->directive_length) {
- ctx->state = PARSE_TAG;
- }
- else {
- ctx->state = PARSE_DIRECTIVE;
- ctx->directive_length += ctx->parse_pos;
- }
- ctx->tail_start_bucket = NULL;
- ctx->tail_start_index = 0;
- ctx->tag_length += ctx->parse_pos;
- ctx->parse_pos = 0;
- }
- }
- }
- }
- c++;
- ctx->bytes_parsed++;
- }
- dptr = APR_BUCKET_NEXT(dptr);
- } while (dptr != APR_BRIGADE_SENTINEL(bb));
- return NULL;
-}
-
-/* This function culls through the buckets that have been set aside in the
- * ssi_tag_brigade and copies just the directive part of the SSI tag (none
- * of the start and end delimiter bytes are copied).
- */
-static apr_status_t get_combined_directive (include_ctx_t *ctx,
- request_rec *r,
- apr_bucket_brigade *bb,
- char *tmp_buf, int tmp_buf_size)
-{
- int done = 0;
- apr_bucket *dptr;
- const char *tmp_from;
- apr_size_t tmp_from_len;
-
- /* If the tag length is longer than the tmp buffer, allocate space. */
- if (ctx->tag_length > tmp_buf_size-1) {
- if ((ctx->combined_tag = apr_pcalloc(r->pool, ctx->tag_length + 1)) == NULL) {
- return (APR_ENOMEM);
- }
- } /* Else, just use the temp buffer. */
- else {
- ctx->combined_tag = tmp_buf;
- }
-
- /* Prime the pump. Start at the beginning of the tag... */
- dptr = ctx->tag_start_bucket;
- apr_bucket_read (dptr, &tmp_from, &tmp_from_len, 0); /* Read the bucket... */
-
- /* Adjust the pointer to start at the tag within the bucket... */
- if (dptr == ctx->tail_start_bucket) {
- tmp_from_len -= (tmp_from_len - ctx->tail_start_index);
- }
- tmp_from = &tmp_from[ctx->tag_start_index];
- tmp_from_len -= ctx->tag_start_index;
- ctx->curr_tag_pos = ctx->combined_tag;
-
- /* Loop through the buckets from the tag_start_bucket until before
- * the tail_start_bucket copying the contents into the buffer.
- */
- do {
- memcpy (ctx->curr_tag_pos, tmp_from, tmp_from_len);
- ctx->curr_tag_pos += tmp_from_len;
-
- if (dptr == ctx->tail_start_bucket) {
- done = 1;
- }
- else {
- dptr = APR_BUCKET_NEXT (dptr);
- apr_bucket_read (dptr, &tmp_from, &tmp_from_len, 0);
- /* Adjust the count to stop at the beginning of the tail. */
- if (dptr == ctx->tail_start_bucket) {
- tmp_from_len -= (tmp_from_len - ctx->tail_start_index);
- }
- }
- } while ((!done) &&
- ((ctx->curr_tag_pos - ctx->combined_tag) < ctx->tag_length));
-
- ctx->combined_tag[ctx->tag_length] = '\0';
- ctx->curr_tag_pos = ctx->combined_tag;
-
- return (APR_SUCCESS);
-}
-
-/*
- * decodes a string containing html entities or numeric character references.
- * 's' is overwritten with the decoded string.
- * If 's' is syntatically incorrect, then the followed fixups will be made:
- * unknown entities will be left undecoded;
- * references to unused numeric characters will be deleted.
- * In particular, &#00; will not be decoded, but will be deleted.
- *
- * drtr
- */
-
-/* maximum length of any ISO-LATIN-1 HTML entity name. */
-#define MAXENTLEN (6)
-
-/* The following is a shrinking transformation, therefore safe. */
-
-static void decodehtml(char *s)
-{
- int val, i, j;
- char *p = s;
- const char *ents;
- static const char * const entlist[MAXENTLEN + 1] =
- {
- NULL, /* 0 */
- NULL, /* 1 */
- "lt\074gt\076", /* 2 */
- "amp\046ETH\320eth\360", /* 3 */
- "quot\042Auml\304Euml\313Iuml\317Ouml\326Uuml\334auml\344euml\353\
-iuml\357ouml\366uuml\374yuml\377", /* 4 */
- "Acirc\302Aring\305AElig\306Ecirc\312Icirc\316Ocirc\324Ucirc\333\
-THORN\336szlig\337acirc\342aring\345aelig\346ecirc\352icirc\356ocirc\364\
-ucirc\373thorn\376", /* 5 */
- "Agrave\300Aacute\301Atilde\303Ccedil\307Egrave\310Eacute\311\
-Igrave\314Iacute\315Ntilde\321Ograve\322Oacute\323Otilde\325Oslash\330\
-Ugrave\331Uacute\332Yacute\335agrave\340aacute\341atilde\343ccedil\347\
-egrave\350eacute\351igrave\354iacute\355ntilde\361ograve\362oacute\363\
-otilde\365oslash\370ugrave\371uacute\372yacute\375" /* 6 */
- };
-
- for (; *s != '\0'; s++, p++) {
- if (*s != '&') {
- *p = *s;
- continue;
- }
- /* find end of entity */
- for (i = 1; s[i] != ';' && s[i] != '\0'; i++) {
- continue;
- }
-
- if (s[i] == '\0') { /* treat as normal data */
- *p = *s;
- continue;
- }
-
- /* is it numeric ? */
- if (s[1] == '#') {
- for (j = 2, val = 0; j < i && apr_isdigit(s[j]); j++) {
- val = val * 10 + s[j] - '0';
- }
- s += i;
- if (j < i || val <= 8 || (val >= 11 && val <= 31) ||
- (val >= 127 && val <= 160) || val >= 256) {
- p--; /* no data to output */
- }
- else {
- *p = RAW_ASCII_CHAR(val);
- }
- }
- else {
- j = i - 1;
- if (j > MAXENTLEN || entlist[j] == NULL) {
- /* wrong length */
- *p = '&';
- continue; /* skip it */
- }
- for (ents = entlist[j]; *ents != '\0'; ents += i) {
- if (strncmp(s + 1, ents, j) == 0) {
- break;
- }
- }
-
- if (*ents == '\0') {
- *p = '&'; /* unknown */
- }
- else {
- *p = RAW_ASCII_CHAR(((const unsigned char *) ents)[j]);
- s += i;
- }
- }
- }
-
- *p = '\0';
-}
-
-/*
- * Extract the next tag name and value.
- * If there are no more tags, set the tag name to NULL.
- * The tag value is html decoded if dodecode is non-zero.
- * The tag value may be NULL if there is no tag value..
- * format:
- * [WS]<Tag>[WS]=[WS]['|"]<Value>['|"|WS]
- */
-
-#define SKIP_TAG_WHITESPACE(ptr) while ((*ptr != '\0') && (apr_isspace (*ptr))) ptr++
-
-static void ap_ssi_get_tag_and_value(include_ctx_t *ctx, char **tag,
- char **tag_val, int dodecode)
-{
- char *c = ctx->curr_tag_pos;
- int shift_val = 0;
- char term = '\0';
-
- *tag_val = NULL;
- SKIP_TAG_WHITESPACE(c);
- *tag = c; /* First non-whitespace character (could be NULL). */
-
- while ((*c != '\0') && (*c != '=') && (!apr_isspace(*c))) {
- *c = apr_tolower(*c); /* find end of tag, lowercasing as we go... */
- c++;
- }
-
- if ((*c == '\0') || (**tag == '=')) {
- if ((**tag == '\0') || (**tag == '=')) {
- *tag = NULL;
- }
- ctx->curr_tag_pos = c;
- return; /* We have found the end of the buffer. */
- } /* We might have a tag, but definitely no value. */
-
- if (*c == '=') {
- *c++ = '\0'; /* Overwrite the '=' with a terminating byte after tag. */
- }
- else { /* Try skipping WS to find the '='. */
- *c++ = '\0'; /* Terminate the tag... */
- SKIP_TAG_WHITESPACE(c);
-
- if (*c != '=') { /* There needs to be an equal sign if there's a value. */
- ctx->curr_tag_pos = c;
- return; /* There apparently was no value. */
- }
- else {
- c++; /* Skip the equals sign. */
- }
- }
-
- SKIP_TAG_WHITESPACE(c);
- if (*c == '"' || *c == '\'') { /* Allow quoted values for space inclusion. */
- term = *c++; /* NOTE: This does not pass the quotes on return. */
- }
-
- *tag_val = c;
- while ((*c != '\0') &&
- (((term != '\0') && (*c != term)) ||
- ((term == '\0') && (!apr_isspace(*c))))) {
- if (*c == '\\') { /* Accept \" and \' as valid char in string. */
- c++;
- if (*c == term) { /* Overwrite the "\" during the embedded */
- shift_val++; /* escape sequence of '\"' or "\'". Shift */
- } /* bytes from here to next delimiter. */
- if (shift_val > 0) {
- *(c-shift_val) = *c;
- }
- }
-
- c++;
- if (shift_val > 0) {
- *(c-shift_val) = *c;
- }
- }
-
- *c++ = '\0'; /* Overwrites delimiter (term or WS) with NULL. */
- ctx->curr_tag_pos = c;
- if (dodecode) {
- decodehtml(*tag_val);
- }
-
- return;
-}
-
-
-/*
- * Do variable substitution on strings
- */
-static void ap_ssi_parse_string(request_rec *r, const char *in, char *out,
- size_t length, int leave_name)
-{
- char ch;
- char *next = out;
- char *end_out;
-
- /* leave room for nul terminator */
- end_out = out + length - 1;
-
- while ((ch = *in++) != '\0') {
- switch (ch) {
- case '\\':
- if (next == end_out) {
- /* truncated */
- *next = '\0';
- return;
- }
- if (*in == '$') {
- *next++ = *in++;
- }
- else {
- *next++ = ch;
- }
- break;
- case '$':
- {
- const char *start_of_var_name;
- char *end_of_var_name; /* end of var name + 1 */
- const char *expansion, *temp_end, *val;
- char tmp_store;
- size_t l;
-
- /* guess that the expansion won't happen */
- expansion = in - 1;
- if (*in == '{') {
- ++in;
- start_of_var_name = in;
- in = ap_strchr_c(in, '}');
- if (in == NULL) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR,
- 0, r, "Missing '}' on variable \"%s\"",
- expansion);
- *next = '\0';
- return;
- }
- temp_end = in;
- end_of_var_name = (char *)temp_end;
- ++in;
- }
- else {
- start_of_var_name = in;
- while (apr_isalnum(*in) || *in == '_') {
- ++in;
- }
- temp_end = in;
- end_of_var_name = (char *)temp_end;
- }
- /* what a pain, too bad there's no table_getn where you can
- * pass a non-nul terminated string */
- l = end_of_var_name - start_of_var_name;
- if (l != 0) {
- tmp_store = *end_of_var_name;
- *end_of_var_name = '\0';
- val = apr_table_get(r->subprocess_env, start_of_var_name);
- *end_of_var_name = tmp_store;
-
- if (val) {
- expansion = val;
- l = strlen(expansion);
- }
- else if (leave_name) {
- l = in - expansion;
- }
- else {
- break; /* no expansion to be done */
- }
- }
- else {
- /* zero-length variable name causes just the $ to be copied */
- l = 1;
- }
- l = ((int)l > end_out - next) ? (end_out - next) : l;
- memcpy(next, expansion, l);
- next += l;
- break;
- }
- default:
- if (next == end_out) {
- /* truncated */
- *next = '\0';
- return;
- }
- *next++ = ch;
- break;
- }
- }
- *next = '\0';
- return;
-}
-
-/* --------------------------- Action handlers ---------------------------- */
-
-/* ensure that path is relative, and does not contain ".." elements
- * ensentially ensure that it does not match the regex:
- * (^/|(^|/)\.\.(/|$))
- * XXX: Needs to become apr_is_path_relative() test
- */
-static int is_only_below(const char *path)
-{
-#ifdef HAVE_DRIVE_LETTERS
- if (path[1] == ':')
- return 0;
-#endif
-#ifdef NETWARE
- if (strchr(path, ':')
- return 0;
-#endif
- if (path[0] == '/') {
- return 0;
- }
- while (*path) {
- int dots = 0;
- while (path[dots] == '.')
- ++dots;
-#if defined(WIN32)
- /* If the name is canonical this is redundant
- * but in security, redundancy is worthwhile.
- * Does OS2 belong here (accepts ... for ..)?
- */
- if (dots > 1 && (!path[dots] || path[dots] == '/'))
- return 0;
-#else
- if (dots == 2 && (!path[dots] || path[dots] == '/'))
- return 0;
-#endif
- path += dots;
- while (*path && *(path++) != '/')
- ++path;
- }
- return 1;
-}
-
-static int handle_include(include_ctx_t *ctx, apr_bucket_brigade **bb, request_rec *r,
- ap_filter_t *f, apr_bucket *head_ptr, apr_bucket **inserted_head)
-{
- char *tag = NULL;
- char *tag_val = NULL;
- apr_bucket *tmp_buck;
- char parsed_string[MAX_STRING_LEN];
-
- *inserted_head = NULL;
- if (ctx->flags & FLAG_PRINTING) {
- while (1) {
- ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 1);
- if (tag_val == NULL) {
- if (tag == NULL) {
- return (0);
- }
- else {
- return (1);
- }
- }
- if (!strcmp(tag, "file") || !strcmp(tag, "virtual")) {
- request_rec *rr = NULL;
- char *error_fmt = NULL;
-
- ap_ssi_parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
- if (tag[0] == 'f') {
- /* be safe; only files in this directory or below allowed */
- if (!is_only_below(parsed_string)) {
- error_fmt = "unable to include file \"%s\" "
- "in parsed file %s";
- }
- else {
- rr = ap_sub_req_lookup_file(parsed_string, r, f->next);
- }
- }
- else {
- rr = ap_sub_req_lookup_uri(parsed_string, r, f->next);
- }
-
- if (!error_fmt && rr->status != HTTP_OK) {
- error_fmt = "unable to include \"%s\" in parsed file %s";
- }
-
- if (!error_fmt && (ctx->flags & FLAG_NO_EXEC) && rr->content_type
- && (strncmp(rr->content_type, "text/", 5))) {
- error_fmt = "unable to include potential exec \"%s\" "
- "in parsed file %s";
- }
- if (error_fmt == NULL) {
- /* try to avoid recursive includes. We do this by walking
- * up the r->main list of subrequests, and at each level
- * walking back through any internal redirects. At each
- * step, we compare the filenames and the URIs.
- *
- * The filename comparison catches a recursive include
- * with an ever-changing URL, eg.
- * <!--#include virtual=
- * "$REQUEST_URI/$QUERY_STRING?$QUERY_STRING/x"-->
- * which, although they would eventually be caught because
- * we have a limit on the length of files, etc., can
- * recurse for a while.
- *
- * The URI comparison catches the case where the filename
- * is changed while processing the request, so the
- * current name is never the same as any previous one.
- * This can happen with "DocumentRoot /foo" when you
- * request "/" on the server and it includes "/".
- * This only applies to modules such as mod_dir that
- * (somewhat improperly) mess with r->filename outside
- * of a filename translation phase.
- */
- int founddupe = 0;
- request_rec *p;
- for (p = r; p != NULL && !founddupe; p = p->main) {
- request_rec *q;
- for (q = p; q != NULL; q = q->prev) {
- if ( (strcmp(q->filename, rr->filename) == 0) ||
- (strcmp(q->uri, rr->uri) == 0) ){
- founddupe = 1;
- break;
- }
- }
- }
-
- if (p != NULL) {
- error_fmt = "Recursive include of \"%s\" "
- "in parsed file %s";
- }
- }
-
- /* See the Kludge in send_parsed_file for why */
- /* Basically, it puts a bread crumb in here, then looks */
- /* for the crumb later to see if its been here. */
- if (rr)
- ap_set_module_config(rr->request_config, &include_module, r);
-
- if (!error_fmt) {
- SPLIT_AND_PASS_PRETAG_BUCKETS(*bb, ctx, f->next);
-
- if (ap_run_sub_req(rr)) {
- error_fmt = "unable to include \"%s\" in parsed file %s";
- }
- }
- if (error_fmt) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR,
- 0, r, error_fmt, tag_val, r->filename);
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- }
-
- /* destroy the sub request if it's not a nested include (crumb) */
- if (rr != NULL
- && ap_get_module_config(rr->request_config, &include_module)
- != NESTED_INCLUDE_MAGIC) {
- ap_destroy_sub_req(rr);
- }
- }
- else {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "unknown parameter \"%s\" to tag include in %s",
- tag, r->filename);
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- }
- }
- }
- return 0;
-}
-
-
-static int handle_echo(include_ctx_t *ctx, apr_bucket_brigade **bb, request_rec *r,
- ap_filter_t *f, apr_bucket *head_ptr, apr_bucket **inserted_head)
-{
- char *tag = NULL;
- char *tag_val = NULL;
- const char *echo_text = NULL;
- apr_bucket *tmp_buck;
- apr_size_t e_len, e_wrt;
- enum {E_NONE, E_URL, E_ENTITY} encode;
-
- encode = E_ENTITY;
-
- *inserted_head = NULL;
- if (ctx->flags & FLAG_PRINTING) {
- while (1) {
- ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 1);
- if (tag_val == NULL) {
- if (tag != NULL) {
- return 1;
- }
- else {
- return 0;
- }
- }
- if (!strcmp(tag, "var")) {
- const char *val = apr_table_get(r->subprocess_env, tag_val);
-
- if (val) {
- switch(encode) {
- case E_NONE: echo_text = val; break;
- case E_URL: echo_text = ap_escape_uri(r->pool, val); break;
- case E_ENTITY: echo_text = ap_escape_html(r->pool, val); break;
- }
-
- e_len = strlen(echo_text);
- tmp_buck = apr_bucket_heap_create(echo_text, e_len, 1, &e_wrt);
- }
- else {
- tmp_buck = apr_bucket_immortal_create("(none)", sizeof("none"));
- }
- APR_BUCKET_INSERT_BEFORE(head_ptr, tmp_buck);
- if (*inserted_head == NULL) {
- *inserted_head = tmp_buck;
- }
- }
- else if (!strcmp(tag, "encoding")) {
- if (!strcasecmp(tag_val, "none")) encode = E_NONE;
- else if (!strcasecmp(tag_val, "url")) encode = E_URL;
- else if (!strcasecmp(tag_val, "entity")) encode = E_ENTITY;
- else {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "unknown value \"%s\" to parameter \"encoding\" of "
- "tag echo in %s", tag_val, r->filename);
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- }
- }
- else {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "unknown parameter \"%s\" in tag echo of %s",
- tag, r->filename);
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- }
-
- }
- }
- return 0;
-}
-
-/* error and tf must point to a string with room for at
- * least MAX_STRING_LEN characters
- */
-static int handle_config(include_ctx_t *ctx, apr_bucket_brigade **bb, request_rec *r,
- ap_filter_t *f, apr_bucket *head_ptr, apr_bucket **inserted_head)
-{
- char *tag = NULL;
- char *tag_val = NULL;
- char parsed_string[MAX_STRING_LEN];
- apr_table_t *env = r->subprocess_env;
-
- *inserted_head = NULL;
- if (ctx->flags & FLAG_PRINTING) {
- while (1) {
- ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 0);
- if (tag_val == NULL) {
- if (tag == NULL) {
- return 0; /* Reached the end of the string. */
- }
- else {
- return 1; /* tags must have values. */
- }
- }
- if (!strcmp(tag, "errmsg")) {
- ap_ssi_parse_string(r, tag_val, ctx->error_str, MAX_STRING_LEN, 0);
- ctx->error_length = strlen(ctx->error_str);
- }
- else if (!strcmp(tag, "timefmt")) {
- apr_time_t date = r->request_time;
-
- ap_ssi_parse_string(r, tag_val, ctx->time_str, MAX_STRING_LEN, 0);
- apr_table_setn(env, "DATE_LOCAL", ap_ht_time(r->pool, date, ctx->time_str, 0));
- apr_table_setn(env, "DATE_GMT", ap_ht_time(r->pool, date, ctx->time_str, 1));
- apr_table_setn(env, "LAST_MODIFIED",
- ap_ht_time(r->pool, r->finfo.mtime, ctx->time_str, 0));
- }
- else if (!strcmp(tag, "sizefmt")) {
- ap_ssi_parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
- decodehtml(parsed_string);
- if (!strcmp(parsed_string, "bytes")) {
- ctx->flags |= FLAG_SIZE_IN_BYTES;
- }
- else if (!strcmp(parsed_string, "abbrev")) {
- ctx->flags &= FLAG_SIZE_ABBREV;
- }
- }
- else {
- apr_bucket *tmp_buck;
-
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "unknown parameter \"%s\" to tag config in %s",
- tag, r->filename);
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- }
- }
- }
- return 0;
-}
-
-
-static int find_file(request_rec *r, const char *directive, const char *tag,
- char *tag_val, apr_finfo_t *finfo)
-{
- char *to_send = tag_val;
- request_rec *rr = NULL;
- int ret=0;
- char *error_fmt = NULL;
- apr_status_t rv = APR_SUCCESS;
-
- if (!strcmp(tag, "file")) {
- /* be safe; only files in this directory or below allowed */
- if (!is_only_below(tag_val)) {
- error_fmt = "unable to access file \"%s\" "
- "in parsed file %s";
- }
- else {
- ap_getparents(tag_val); /* get rid of any nasties */
-
- /* note: it is okay to pass NULL for the "next filter" since
- we never attempt to "run" this sub request. */
- rr = ap_sub_req_lookup_file(tag_val, r, NULL);
-
- if (rr->status == HTTP_OK && rr->finfo.filetype != 0) {
- to_send = rr->filename;
- if ((rv = apr_stat(finfo, to_send, APR_FINFO_GPROT
- | APR_FINFO_MIN, rr->pool)) != APR_SUCCESS
- && rv != APR_INCOMPLETE) {
- error_fmt = "unable to get information about \"%s\" "
- "in parsed file %s";
- }
- }
- else {
- error_fmt = "unable to lookup information about \"%s\" "
- "in parsed file %s";
- }
- }
-
- if (error_fmt) {
- ret = -1;
- ap_log_rerror(APLOG_MARK, APLOG_ERR | (rv ? 0 : APLOG_NOERRNO),
- rv, r, error_fmt, to_send, r->filename);
- }
-
- if (rr) ap_destroy_sub_req(rr);
-
- return ret;
- }
- else if (!strcmp(tag, "virtual")) {
- /* note: it is okay to pass NULL for the "next filter" since
- we never attempt to "run" this sub request. */
- rr = ap_sub_req_lookup_uri(tag_val, r, NULL);
-
- if (rr->status == HTTP_OK && rr->finfo.filetype != 0) {
- memcpy((char *) finfo, (const char *) &rr->finfo,
- sizeof(rr->finfo));
- ap_destroy_sub_req(rr);
- return 0;
- }
- else {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "unable to get information about \"%s\" "
- "in parsed file %s",
- tag_val, r->filename);
- ap_destroy_sub_req(rr);
- return -1;
- }
- }
- else {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "unknown parameter \"%s\" to tag %s in %s",
- tag, directive, r->filename);
- return -1;
- }
-}
-
-#define NEG_SIGN " -"
-#define ZERO_K " 0k"
-#define ONE_K " 1k"
-
-static void generate_size(apr_ssize_t size, char *buff, apr_size_t buff_size)
-{
- /* XXX: this -1 thing is a gross hack */
- if (size == (apr_ssize_t)-1) {
- memcpy (buff, NEG_SIGN, sizeof(NEG_SIGN)+1);
- }
- else if (!size) {
- memcpy (buff, ZERO_K, sizeof(ZERO_K)+1);
- }
- else if (size < 1024) {
- memcpy (buff, ONE_K, sizeof(ONE_K)+1);
- }
- else if (size < 1048576) {
- apr_snprintf(buff, buff_size, "%4" APR_SSIZE_T_FMT "k", (size + 512) / 1024);
- }
- else if (size < 103809024) {
- apr_snprintf(buff, buff_size, "%4.1fM", size / 1048576.0);
- }
- else {
- apr_snprintf(buff, buff_size, "%4" APR_SSIZE_T_FMT "M", (size + 524288) / 1048576);
- }
-}
-
-static int handle_fsize(include_ctx_t *ctx, apr_bucket_brigade **bb, request_rec *r,
- ap_filter_t *f, apr_bucket *head_ptr, apr_bucket **inserted_head)
-{
- char *tag = NULL;
- char *tag_val = NULL;
- apr_finfo_t finfo;
- apr_size_t s_len, s_wrt;
- apr_bucket *tmp_buck;
- char parsed_string[MAX_STRING_LEN];
-
- *inserted_head = NULL;
- if (ctx->flags & FLAG_PRINTING) {
- while (1) {
- ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 1);
- if (tag_val == NULL) {
- if (tag == NULL) {
- return 0;
- }
- else {
- return 1;
- }
- }
- else {
- ap_ssi_parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
- if (!find_file(r, "fsize", tag, parsed_string, &finfo)) {
- char buff[50];
-
- if (!(ctx->flags & FLAG_SIZE_IN_BYTES)) {
- generate_size(finfo.size, buff, sizeof(buff));
- s_len = strlen (buff);
- }
- else {
- int l, x, pos = 0;
- char tmp_buff[50];
-
- apr_snprintf(tmp_buff, sizeof(tmp_buff), "%" APR_OFF_T_FMT, finfo.size);
- l = strlen(tmp_buff); /* grrr */
- for (x = 0; x < l; x++) {
- if (x && (!((l - x) % 3))) {
- buff[pos++] = ',';
- }
- buff[pos++] = tmp_buff[x];
- }
- buff[pos] = '\0';
- s_len = pos;
- }
-
- tmp_buck = apr_bucket_heap_create(buff, s_len, 1, &s_wrt);
- APR_BUCKET_INSERT_BEFORE(head_ptr, tmp_buck);
- if (*inserted_head == NULL) {
- *inserted_head = tmp_buck;
- }
- }
- else {
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- }
- }
- }
- }
- return 0;
-}
-
-static int handle_flastmod(include_ctx_t *ctx, apr_bucket_brigade **bb, request_rec *r,
- ap_filter_t *f, apr_bucket *head_ptr, apr_bucket **inserted_head)
-{
- char *tag = NULL;
- char *tag_val = NULL;
- apr_finfo_t finfo;
- apr_size_t t_len, t_wrt;
- apr_bucket *tmp_buck;
- char parsed_string[MAX_STRING_LEN];
-
- *inserted_head = NULL;
- if (ctx->flags & FLAG_PRINTING) {
- while (1) {
- ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 1);
- if (tag_val == NULL) {
- if (tag == NULL) {
- return 0;
- }
- else {
- return 1;
- }
- }
- else {
- ap_ssi_parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
- if (!find_file(r, "flastmod", tag, parsed_string, &finfo)) {
- char *t_val;
-
- t_val = ap_ht_time(r->pool, finfo.mtime, ctx->time_str, 0);
- t_len = strlen(t_val);
-
- tmp_buck = apr_bucket_heap_create(t_val, t_len, 1, &t_wrt);
- APR_BUCKET_INSERT_BEFORE(head_ptr, tmp_buck);
- if (*inserted_head == NULL) {
- *inserted_head = tmp_buck;
- }
- }
- else {
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- }
- }
- }
- }
- return 0;
-}
-
-static int re_check(request_rec *r, char *string, char *rexp)
-{
- regex_t *compiled;
- int regex_error;
-
- compiled = ap_pregcomp(r->pool, rexp, REG_EXTENDED | REG_NOSUB);
- if (compiled == NULL) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "unable to compile pattern \"%s\"", rexp);
- return -1;
- }
- regex_error = ap_regexec(compiled, string, 0, (regmatch_t *) NULL, 0);
- ap_pregfree(r->pool, compiled);
- return (!regex_error);
-}
-
-enum token_type {
- token_string,
- token_and, token_or, token_not, token_eq, token_ne,
- token_rbrace, token_lbrace, token_group,
- token_ge, token_le, token_gt, token_lt
-};
-struct token {
- enum token_type type;
- char value[MAX_STRING_LEN];
-};
-
-/* there is an implicit assumption here that string is at most MAX_STRING_LEN-1
- * characters long...
- */
-static const char *get_ptoken(request_rec *r, const char *string, struct token *token,
- int *unmatched)
-{
- char ch;
- int next = 0;
- int qs = 0;
- int tkn_fnd = 0;
-
- /* Skip leading white space */
- if (string == (char *) NULL) {
- return (char *) NULL;
- }
- while ((ch = *string++)) {
- if (!apr_isspace(ch)) {
- break;
- }
- }
- if (ch == '\0') {
- return (char *) NULL;
- }
-
- token->type = token_string; /* the default type */
- switch (ch) {
- case '(':
- token->type = token_lbrace;
- return (string);
- case ')':
- token->type = token_rbrace;
- return (string);
- case '=':
- token->type = token_eq;
- return (string);
- case '!':
- if (*string == '=') {
- token->type = token_ne;
- return (string + 1);
- }
- else {
- token->type = token_not;
- return (string);
- }
- case '\'':
- token->type = token_string;
- qs = 1;
- break;
- case '|':
- if (*string == '|') {
- token->type = token_or;
- return (string + 1);
- }
- break;
- case '&':
- if (*string == '&') {
- token->type = token_and;
- return (string + 1);
- }
- break;
- case '>':
- if (*string == '=') {
- token->type = token_ge;
- return (string + 1);
- }
- else {
- token->type = token_gt;
- return (string);
- }
- case '<':
- if (*string == '=') {
- token->type = token_le;
- return (string + 1);
- }
- else {
- token->type = token_lt;
- return (string);
- }
- default:
- token->type = token_string;
- break;
- }
- /* We should only be here if we are in a string */
- if (!qs) {
- token->value[next++] = ch;
- }
-
- /*
- * Yes I know that goto's are BAD. But, c doesn't allow me to
- * exit a loop from a switch statement. Yes, I could use a flag,
- * but that is (IMHO) even less readable/maintainable than the goto.
- */
- /*
- * I used the ++string throughout this section so that string
- * ends up pointing to the next token and I can just return it
- */
- for (ch = *string; ((ch != '\0') && (!tkn_fnd)); ch = *++string) {
- if (ch == '\\') {
- if ((ch = *++string) == '\0') {
- tkn_fnd = 1;
- }
- else {
- token->value[next++] = ch;
- }
- }
- else {
- if (!qs) {
- if (apr_isspace(ch)) {
- tkn_fnd = 1;
- }
- else {
- switch (ch) {
- case '(':
- case ')':
- case '=':
- case '!':
- case '<':
- case '>':
- tkn_fnd = 1;
- break;
- case '|':
- if (*(string + 1) == '|') {
- tkn_fnd = 1;
- }
- break;
- case '&':
- if (*(string + 1) == '&') {
- tkn_fnd = 1;
- }
- break;
- }
- if (!tkn_fnd) {
- token->value[next++] = ch;
- }
- }
- }
- else {
- if (ch == '\'') {
- qs = 0;
- ++string;
- tkn_fnd = 1;
- }
- else {
- token->value[next++] = ch;
- }
- }
- }
- }
-
- /* If qs is still set, I have an unmatched ' */
- if (qs) {
- *unmatched = 1;
- next = 0;
- }
- token->value[next] = '\0';
- return (string);
-}
-
-
-/*
- * Hey I still know that goto's are BAD. I don't think that I've ever
- * used two in the same project, let alone the same file before. But,
- * I absolutely want to make sure that I clean up the memory in all
- * cases. And, without rewriting this completely, the easiest way
- * is to just branch to the return code which cleans it up.
- */
-/* there is an implicit assumption here that expr is at most MAX_STRING_LEN-1
- * characters long...
- */
-static int parse_expr(request_rec *r, const char *expr, int *was_error,
- int *was_unmatched, char *debug)
-{
- struct parse_node {
- struct parse_node *left, *right, *parent;
- struct token token;
- int value, done;
- } *root, *current, *new;
- const char *parse;
- char buffer[MAX_STRING_LEN];
- apr_pool_t *expr_pool;
- int retval = 0;
- apr_size_t debug_pos = 0;
-
- debug[debug_pos] = '\0';
- *was_error = 0;
- *was_unmatched = 0;
- if ((parse = expr) == (char *) NULL) {
- return (0);
- }
- root = current = (struct parse_node *) NULL;
- if (apr_pool_create(&expr_pool, r->pool) != APR_SUCCESS)
- return 0;
-
- /* Create Parse Tree */
- while (1) {
- new = (struct parse_node *) apr_palloc(expr_pool,
- sizeof(struct parse_node));
- new->parent = new->left = new->right = (struct parse_node *) NULL;
- new->done = 0;
- if ((parse = get_ptoken(r, parse, &new->token, was_unmatched)) == (char *) NULL) {
- break;
- }
- switch (new->token.type) {
-
- case token_string:
-#ifdef DEBUG_INCLUDE
- debug_pos += sprintf (&debug[debug_pos], " Token: string (%s)\n",
- new->token.value);
-#endif
- if (current == (struct parse_node *) NULL) {
- root = current = new;
- break;
- }
- switch (current->token.type) {
- case token_string:
- if (current->token.value[0] != '\0') {
- strncat(current->token.value, " ",
- sizeof(current->token.value)
- - strlen(current->token.value) - 1);
- }
- strncat(current->token.value, new->token.value,
- sizeof(current->token.value)
- - strlen(current->token.value) - 1);
- current->token.value[sizeof(current->token.value) - 1] = '\0';
- break;
- case token_eq:
- case token_ne:
- case token_and:
- case token_or:
- case token_lbrace:
- case token_not:
- case token_ge:
- case token_gt:
- case token_le:
- case token_lt:
- new->parent = current;
- current = current->right = new;
- break;
- default:
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Invalid expression \"%s\" in file %s",
- expr, r->filename);
- *was_error = 1;
- goto RETURN;
- }
- break;
-
- case token_and:
- case token_or:
-#ifdef DEBUG_INCLUDE
- memcpy (&debug[debug_pos], " Token: and/or\n",
- sizeof (" Token: and/or\n"));
- debug_pos += sizeof (" Token: and/or\n");
-#endif
- if (current == (struct parse_node *) NULL) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Invalid expression \"%s\" in file %s",
- expr, r->filename);
- *was_error = 1;
- goto RETURN;
- }
- /* Percolate upwards */
- while (current != (struct parse_node *) NULL) {
- switch (current->token.type) {
- case token_string:
- case token_group:
- case token_not:
- case token_eq:
- case token_ne:
- case token_and:
- case token_or:
- case token_ge:
- case token_gt:
- case token_le:
- case token_lt:
- current = current->parent;
- continue;
- case token_lbrace:
- break;
- default:
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Invalid expression \"%s\" in file %s",
- expr, r->filename);
- *was_error = 1;
- goto RETURN;
- }
- break;
- }
- if (current == (struct parse_node *) NULL) {
- new->left = root;
- new->left->parent = new;
- new->parent = (struct parse_node *) NULL;
- root = new;
- }
- else {
- new->left = current->right;
- current->right = new;
- new->parent = current;
- }
- current = new;
- break;
-
- case token_not:
-#ifdef DEBUG_INCLUDE
- memcpy (&debug[debug_pos], " Token: not\n",
- sizeof (" Token: not\n"));
- debug_pos += sizeof (" Token: not\n");
-#endif
- if (current == (struct parse_node *) NULL) {
- root = current = new;
- break;
- }
- /* Percolate upwards */
- while (current != (struct parse_node *) NULL) {
- switch (current->token.type) {
- case token_not:
- case token_eq:
- case token_ne:
- case token_and:
- case token_or:
- case token_lbrace:
- case token_ge:
- case token_gt:
- case token_le:
- case token_lt:
- break;
- default:
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Invalid expression \"%s\" in file %s",
- expr, r->filename);
- *was_error = 1;
- goto RETURN;
- }
- break;
- }
- if (current == (struct parse_node *) NULL) {
- new->left = root;
- new->left->parent = new;
- new->parent = (struct parse_node *) NULL;
- root = new;
- }
- else {
- new->left = current->right;
- current->right = new;
- new->parent = current;
- }
- current = new;
- break;
-
- case token_eq:
- case token_ne:
- case token_ge:
- case token_gt:
- case token_le:
- case token_lt:
-#ifdef DEBUG_INCLUDE
- memcpy (&debug[debug_pos], " Token: eq/ne/ge/gt/le/lt\n",
- sizeof (" Token: eq/ne/ge/gt/le/lt\n"));
- debug_pos += sizeof (" Token: eq/ne/ge/gt/le/lt\n");
-#endif
- if (current == (struct parse_node *) NULL) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Invalid expression \"%s\" in file %s",
- expr, r->filename);
- *was_error = 1;
- goto RETURN;
- }
- /* Percolate upwards */
- while (current != (struct parse_node *) NULL) {
- switch (current->token.type) {
- case token_string:
- case token_group:
- current = current->parent;
- continue;
- case token_lbrace:
- case token_and:
- case token_or:
- break;
- case token_not:
- case token_eq:
- case token_ne:
- case token_ge:
- case token_gt:
- case token_le:
- case token_lt:
- default:
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Invalid expression \"%s\" in file %s",
- expr, r->filename);
- *was_error = 1;
- goto RETURN;
- }
- break;
- }
- if (current == (struct parse_node *) NULL) {
- new->left = root;
- new->left->parent = new;
- new->parent = (struct parse_node *) NULL;
- root = new;
- }
- else {
- new->left = current->right;
- current->right = new;
- new->parent = current;
- }
- current = new;
- break;
-
- case token_rbrace:
-#ifdef DEBUG_INCLUDE
- memcpy (&debug[debug_pos], " Token: rbrace\n",
- sizeof (" Token: rbrace\n"));
- debug_pos += sizeof (" Token: rbrace\n");
-#endif
- while (current != (struct parse_node *) NULL) {
- if (current->token.type == token_lbrace) {
- current->token.type = token_group;
- break;
- }
- current = current->parent;
- }
- if (current == (struct parse_node *) NULL) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Unmatched ')' in \"%s\" in file %s",
- expr, r->filename);
- *was_error = 1;
- goto RETURN;
- }
- break;
-
- case token_lbrace:
-#ifdef DEBUG_INCLUDE
- memcpy (&debug[debug_pos], " Token: lbrace\n",
- sizeof (" Token: lbrace\n"));
- debug_pos += sizeof (" Token: lbrace\n");
-#endif
- if (current == (struct parse_node *) NULL) {
- root = current = new;
- break;
- }
- /* Percolate upwards */
- while (current != (struct parse_node *) NULL) {
- switch (current->token.type) {
- case token_not:
- case token_eq:
- case token_ne:
- case token_and:
- case token_or:
- case token_lbrace:
- case token_ge:
- case token_gt:
- case token_le:
- case token_lt:
- break;
- case token_string:
- case token_group:
- default:
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Invalid expression \"%s\" in file %s",
- expr, r->filename);
- *was_error = 1;
- goto RETURN;
- }
- break;
- }
- if (current == (struct parse_node *) NULL) {
- new->left = root;
- new->left->parent = new;
- new->parent = (struct parse_node *) NULL;
- root = new;
- }
- else {
- new->left = current->right;
- current->right = new;
- new->parent = current;
- }
- current = new;
- break;
- default:
- break;
- }
- }
-
- /* Evaluate Parse Tree */
- current = root;
- while (current != (struct parse_node *) NULL) {
- switch (current->token.type) {
- case token_string:
-#ifdef DEBUG_INCLUDE
- memcpy (&debug[debug_pos], " Evaluate string\n",
- sizeof (" Evaluate string\n"));
- debug_pos += sizeof (" Evaluate string\n");
-#endif
- ap_ssi_parse_string(r, current->token.value, buffer, sizeof(buffer), 0);
- apr_cpystrn(current->token.value, buffer, sizeof(current->token.value));
- current->value = (current->token.value[0] != '\0');
- current->done = 1;
- current = current->parent;
- break;
-
- case token_and:
- case token_or:
-#ifdef DEBUG_INCLUDE
- memcpy (&debug[debug_pos], " Evaluate and/or\n",
- sizeof (" Evaluate and/or\n"));
- debug_pos += sizeof (" Evaluate and/or\n");
-#endif
- if (current->left == (struct parse_node *) NULL ||
- current->right == (struct parse_node *) NULL) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Invalid expression \"%s\" in file %s",
- expr, r->filename);
- *was_error = 1;
- goto RETURN;
- }
- if (!current->left->done) {
- switch (current->left->token.type) {
- case token_string:
- ap_ssi_parse_string(r, current->left->token.value,
- buffer, sizeof(buffer), 0);
- apr_cpystrn(current->left->token.value, buffer,
- sizeof(current->left->token.value));
- current->left->value = (current->left->token.value[0] != '\0');
- current->left->done = 1;
- break;
- default:
- current = current->left;
- continue;
- }
- }
- if (!current->right->done) {
- switch (current->right->token.type) {
- case token_string:
- ap_ssi_parse_string(r, current->right->token.value,
- buffer, sizeof(buffer), 0);
- apr_cpystrn(current->right->token.value, buffer,
- sizeof(current->right->token.value));
- current->right->value = (current->right->token.value[0] != '\0');
- current->right->done = 1;
- break;
- default:
- current = current->right;
- continue;
- }
- }
-#ifdef DEBUG_INCLUDE
- debug_pos += sprintf (&debug[debug_pos], " Left: %c\n",
- current->left->value ? '1' : '0');
- debug_pos += sprintf (&debug[debug_pos], " Right: %c\n",
- current->right->value ? '1' : '0');
-#endif
- if (current->token.type == token_and) {
- current->value = current->left->value && current->right->value;
- }
- else {
- current->value = current->left->value || current->right->value;
- }
-#ifdef DEBUG_INCLUDE
- debug_pos += sprintf (&debug[debug_pos], " Returning %c\n",
- current->value ? '1' : '0');
-#endif
- current->done = 1;
- current = current->parent;
- break;
-
- case token_eq:
- case token_ne:
-#ifdef DEBUG_INCLUDE
- memcpy (&debug[debug_pos], " Evaluate eq/ne\n",
- sizeof (" Evaluate eq/ne\n"));
- debug_pos += sizeof (" Evaluate eq/ne\n");
-#endif
- if ((current->left == (struct parse_node *) NULL) ||
- (current->right == (struct parse_node *) NULL) ||
- (current->left->token.type != token_string) ||
- (current->right->token.type != token_string)) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Invalid expression \"%s\" in file %s",
- expr, r->filename);
- *was_error = 1;
- goto RETURN;
- }
- ap_ssi_parse_string(r, current->left->token.value,
- buffer, sizeof(buffer), 0);
- apr_cpystrn(current->left->token.value, buffer,
- sizeof(current->left->token.value));
- ap_ssi_parse_string(r, current->right->token.value,
- buffer, sizeof(buffer), 0);
- apr_cpystrn(current->right->token.value, buffer,
- sizeof(current->right->token.value));
- if (current->right->token.value[0] == '/') {
- int len;
- len = strlen(current->right->token.value);
- if (current->right->token.value[len - 1] == '/') {
- current->right->token.value[len - 1] = '\0';
- }
- else {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Invalid rexp \"%s\" in file %s",
- current->right->token.value, r->filename);
- *was_error = 1;
- goto RETURN;
- }
-#ifdef DEBUG_INCLUDE
- debug_pos += sprintf (&debug[debug_pos],
- " Re Compare (%s) with /%s/\n",
- current->left->token.value,
- &current->right->token.value[1]);
-#endif
- current->value =
- re_check(r, current->left->token.value,
- &current->right->token.value[1]);
- }
- else {
-#ifdef DEBUG_INCLUDE
- debug_pos += sprintf (&debug[debug_pos],
- " Compare (%s) with (%s)\n",
- current->left->token.value,
- current->right->token.value);
-#endif
- current->value =
- (strcmp(current->left->token.value,
- current->right->token.value) == 0);
- }
- if (current->token.type == token_ne) {
- current->value = !current->value;
- }
-#ifdef DEBUG_INCLUDE
- debug_pos += sprintf (&debug[debug_pos], " Returning %c\n",
- current->value ? '1' : '0');
-#endif
- current->done = 1;
- current = current->parent;
- break;
- case token_ge:
- case token_gt:
- case token_le:
- case token_lt:
-#ifdef DEBUG_INCLUDE
- memcpy (&debug[debug_pos], " Evaluate ge/gt/le/lt\n",
- sizeof (" Evaluate ge/gt/le/lt\n"));
- debug_pos += sizeof (" Evaluate ge/gt/le/lt\n");
-#endif
- if ((current->left == (struct parse_node *) NULL) ||
- (current->right == (struct parse_node *) NULL) ||
- (current->left->token.type != token_string) ||
- (current->right->token.type != token_string)) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Invalid expression \"%s\" in file %s",
- expr, r->filename);
- *was_error = 1;
- goto RETURN;
- }
- ap_ssi_parse_string(r, current->left->token.value,
- buffer, sizeof(buffer), 0);
- apr_cpystrn(current->left->token.value, buffer,
- sizeof(current->left->token.value));
- ap_ssi_parse_string(r, current->right->token.value,
- buffer, sizeof(buffer), 0);
- apr_cpystrn(current->right->token.value, buffer,
- sizeof(current->right->token.value));
-#ifdef DEBUG_INCLUDE
- debug_pos += sprintf (&debug[debug_pos],
- " Compare (%s) with (%s)\n",
- current->left->token.value,
- current->right->token.value);
-#endif
- current->value =
- strcmp(current->left->token.value,
- current->right->token.value);
- if (current->token.type == token_ge) {
- current->value = current->value >= 0;
- }
- else if (current->token.type == token_gt) {
- current->value = current->value > 0;
- }
- else if (current->token.type == token_le) {
- current->value = current->value <= 0;
- }
- else if (current->token.type == token_lt) {
- current->value = current->value < 0;
- }
- else {
- current->value = 0; /* Don't return -1 if unknown token */
- }
-#ifdef DEBUG_INCLUDE
- debug_pos += sprintf (&debug[debug_pos], " Returning %c\n",
- current->value ? '1' : '0');
-#endif
- current->done = 1;
- current = current->parent;
- break;
-
- case token_not:
- if (current->right != (struct parse_node *) NULL) {
- if (!current->right->done) {
- current = current->right;
- continue;
- }
- current->value = !current->right->value;
- }
- else {
- current->value = 0;
- }
-#ifdef DEBUG_INCLUDE
- debug_pos += sprintf (&debug[debug_pos], " Evaluate !: %c\n",
- current->value ? '1' : '0');
-#endif
- current->done = 1;
- current = current->parent;
- break;
-
- case token_group:
- if (current->right != (struct parse_node *) NULL) {
- if (!current->right->done) {
- current = current->right;
- continue;
- }
- current->value = current->right->value;
- }
- else {
- current->value = 1;
- }
-#ifdef DEBUG_INCLUDE
- debug_pos += sprintf (&debug[debug_pos], " Evaluate (): %c\n",
- current->value ? '1' : '0');
-#endif
- current->done = 1;
- current = current->parent;
- break;
-
- case token_lbrace:
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Unmatched '(' in \"%s\" in file %s",
- expr, r->filename);
- *was_error = 1;
- goto RETURN;
-
- case token_rbrace:
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Unmatched ')' in \"%s\" in file %s",
- expr, r->filename);
- *was_error = 1;
- goto RETURN;
-
- default:
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "bad token type");
- *was_error = 1;
- goto RETURN;
- }
- }
-
- retval = (root == (struct parse_node *) NULL) ? 0 : root->value;
- RETURN:
- apr_pool_destroy(expr_pool);
- return (retval);
-}
-
-/*-------------------------------------------------------------------------*/
-#ifdef DEBUG_INCLUDE
-
-/* XXX overlaying the static string pointed to by cond_txt isn't cool */
-
-#define MAX_DEBUG_SIZE MAX_STRING_LEN
-#define LOG_COND_STATUS(cntx, t_buck, h_ptr, ins_head, tag_text) \
-{ \
- char *cond_txt = "**** X conditional_status=\"0\"\n"; \
- apr_size_t c_wrt; \
- \
- if (cntx->flags & FLAG_COND_TRUE) { \
- cond_txt[31] = '1'; \
- } \
- memcpy(&cond_txt[5], tag_text, sizeof(tag_text)); \
- t_buck = apr_bucket_heap_create(cond_txt, sizeof(cond_txt), 1, &c_wrt); \
- APR_BUCKET_INSERT_BEFORE(h_ptr, t_buck); \
- \
- if (ins_head == NULL) { \
- ins_head = t_buck; \
- } \
-}
-#define DUMP_PARSE_EXPR_DEBUG(t_buck, h_ptr, d_buf, ins_head) \
-{ \
- apr_size_t b_wrt; \
- if (d_buf[0] != '\0') { \
- t_buck = apr_bucket_heap_create(d_buf, strlen(d_buf), 1, &b_wrt); \
- APR_BUCKET_INSERT_BEFORE(h_ptr, t_buck); \
- \
- if (ins_head == NULL) { \
- ins_head = t_buck; \
- } \
- } \
-}
-#else
-
-#define MAX_DEBUG_SIZE 10
-#define LOG_COND_STATUS(cntx, t_buck, h_ptr, ins_head, tag_text)
-#define DUMP_PARSE_EXPR_DEBUG(t_buck, h_ptr, d_buf, ins_head)
-
-#endif
-/*-------------------------------------------------------------------------*/
-
-/* pjr - These seem to allow expr="fred" expr="joe" where joe overwrites fred. */
-static int handle_if(include_ctx_t *ctx, apr_bucket_brigade **bb, request_rec *r,
- ap_filter_t *f, apr_bucket *head_ptr, apr_bucket **inserted_head)
-{
- char *tag = NULL;
- char *tag_val = NULL;
- char *expr = NULL;
- int expr_ret, was_error, was_unmatched;
- apr_bucket *tmp_buck;
- char debug_buf[MAX_DEBUG_SIZE];
-
- *inserted_head = NULL;
- if (!ctx->flags & FLAG_PRINTING) {
- ctx->if_nesting_level++;
- }
- else {
- while (1) {
- ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 0);
- if (tag == NULL) {
- if (expr == NULL) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "missing expr in if statement: %s", r->filename);
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- return 1;
- }
- expr_ret = parse_expr(r, expr, &was_error, &was_unmatched, debug_buf);
- if (was_error) {
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- return 1;
- }
- if (was_unmatched) {
- DUMP_PARSE_EXPR_DEBUG(tmp_buck, head_ptr, "\nUnmatched '\n",
- *inserted_head);
- }
- DUMP_PARSE_EXPR_DEBUG(tmp_buck, head_ptr, debug_buf, *inserted_head);
-
- if (expr_ret) {
- ctx->flags |= (FLAG_PRINTING | FLAG_COND_TRUE);
- }
- else {
- ctx->flags &= FLAG_CLEAR_PRINT_COND;
- }
- LOG_COND_STATUS(ctx, tmp_buck, head_ptr, *inserted_head, " if");
- ctx->if_nesting_level = 0;
- return 0;
- }
- else if (!strcmp(tag, "expr")) {
- expr = tag_val;
-#ifdef DEBUG_INCLUDE
- if (1) {
- apr_size_t d_len = 0, d_wrt = 0;
- d_len = sprintf(debug_buf, "**** if expr=\"%s\"\n", expr);
- tmp_buck = apr_bucket_heap_create(debug_buf, d_len, 1, &d_wrt);
- APR_BUCKET_INSERT_BEFORE(head_ptr, tmp_buck);
-
- if (*inserted_head == NULL) {
- *inserted_head = tmp_buck;
- }
- }
-#endif
- }
- else {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "unknown parameter \"%s\" to tag if in %s", tag, r->filename);
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- }
-
- }
- }
- return 0;
-}
-
-static int handle_elif(include_ctx_t *ctx, apr_bucket_brigade **bb, request_rec *r,
- ap_filter_t *f, apr_bucket *head_ptr, apr_bucket **inserted_head)
-{
- char *tag = NULL;
- char *tag_val = NULL;
- char *expr = NULL;
- int expr_ret, was_error, was_unmatched;
- apr_bucket *tmp_buck;
- char debug_buf[MAX_DEBUG_SIZE];
-
- *inserted_head = NULL;
- if (!ctx->if_nesting_level) {
- while (1) {
- ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 0);
- if (tag == '\0') {
- LOG_COND_STATUS(ctx, tmp_buck, head_ptr, *inserted_head, " elif");
-
- if (ctx->flags & FLAG_COND_TRUE) {
- ctx->flags &= FLAG_CLEAR_PRINTING;
- return (0);
- }
- if (expr == NULL) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "missing expr in elif statement: %s", r->filename);
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- return (1);
- }
- expr_ret = parse_expr(r, expr, &was_error, &was_unmatched, debug_buf);
- if (was_error) {
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- return 1;
- }
- if (was_unmatched) {
- DUMP_PARSE_EXPR_DEBUG(tmp_buck, head_ptr, "\nUnmatched '\n",
- *inserted_head);
- }
- DUMP_PARSE_EXPR_DEBUG(tmp_buck, head_ptr, debug_buf, *inserted_head);
-
- if (expr_ret) {
- ctx->flags |= (FLAG_PRINTING | FLAG_COND_TRUE);
- }
- else {
- ctx->flags &= FLAG_CLEAR_PRINT_COND;
- }
- LOG_COND_STATUS(ctx, tmp_buck, head_ptr, *inserted_head, " elif");
- return (0);
- }
- else if (!strcmp(tag, "expr")) {
- expr = tag_val;
-#ifdef DEBUG_INCLUDE
- if (1) {
- apr_size_t d_len = 0, d_wrt = 0;
- d_len = sprintf(debug_buf, "**** elif expr=\"%s\"\n", expr);
- tmp_buck = apr_bucket_heap_create(debug_buf, d_len, 1, &d_wrt);
- APR_BUCKET_INSERT_BEFORE(head_ptr, tmp_buck);
-
- if (*inserted_head == NULL) {
- *inserted_head = tmp_buck;
- }
- }
-#endif
- }
- else {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "unknown parameter \"%s\" to tag if in %s", tag, r->filename);
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- }
- }
- }
- return 0;
-}
-
-static int handle_else(include_ctx_t *ctx, apr_bucket_brigade **bb, request_rec *r,
- ap_filter_t *f, apr_bucket *head_ptr, apr_bucket **inserted_head)
-{
- char *tag = NULL;
- char *tag_val = NULL;
- apr_bucket *tmp_buck;
-
- *inserted_head = NULL;
- if (!ctx->if_nesting_level) {
- ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 1);
- if ((tag != NULL) || (tag_val != NULL)) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "else directive does not take tags in %s", r->filename);
- if (ctx->flags & FLAG_PRINTING) {
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- }
- return -1;
- }
- else {
- LOG_COND_STATUS(ctx, tmp_buck, head_ptr, *inserted_head, " else");
-
- if (ctx->flags & FLAG_COND_TRUE) {
- ctx->flags &= FLAG_CLEAR_PRINTING;
- }
- else {
- ctx->flags |= (FLAG_PRINTING | FLAG_COND_TRUE);
- }
- return 0;
- }
- }
- return 0;
-}
-
-static int handle_endif(include_ctx_t *ctx, apr_bucket_brigade **bb, request_rec *r,
- ap_filter_t *f, apr_bucket *head_ptr, apr_bucket **inserted_head)
-{
- char *tag = NULL;
- char *tag_val = NULL;
- apr_bucket *tmp_buck;
-
- *inserted_head = NULL;
- if (!ctx->if_nesting_level) {
- ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 1);
- if ((tag != NULL) || (tag_val != NULL)) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "endif directive does not take tags in %s", r->filename);
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- return -1;
- }
- else {
- LOG_COND_STATUS(ctx, tmp_buck, head_ptr, *inserted_head, "endif");
- ctx->flags |= (FLAG_PRINTING | FLAG_COND_TRUE);
- return 0;
- }
- }
- else {
- ctx->if_nesting_level--;
- return 0;
- }
-}
-
-static int handle_set(include_ctx_t *ctx, apr_bucket_brigade **bb, request_rec *r,
- ap_filter_t *f, apr_bucket *head_ptr, apr_bucket **inserted_head)
-{
- char *tag = NULL;
- char *tag_val = NULL;
- char *var = NULL;
- apr_bucket *tmp_buck;
- char parsed_string[MAX_STRING_LEN];
-
- *inserted_head = NULL;
- if (ctx->flags & FLAG_PRINTING) {
- while (1) {
- ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 1);
- if ((tag == NULL) && (tag_val == NULL)) {
- return 0;
- }
- else if (tag_val == NULL) {
- return 1;
- }
- else if (!strcmp(tag, "var")) {
- var = tag_val;
- }
- else if (!strcmp(tag, "value")) {
- if (var == (char *) NULL) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "variable must precede value in set directive in %s",
- r->filename);
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- return (-1);
- }
- ap_ssi_parse_string(r, tag_val, parsed_string, sizeof(parsed_string), 0);
- apr_table_setn(r->subprocess_env, apr_pstrdup(r->pool, var),
- apr_pstrdup(r->pool, parsed_string));
- }
- else {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Invalid tag for set directive in %s", r->filename);
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- return -1;
- }
- }
- }
- return 0;
-}
-
-static int handle_printenv(include_ctx_t *ctx, apr_bucket_brigade **bb, request_rec *r,
- ap_filter_t *f, apr_bucket *head_ptr, apr_bucket **inserted_head)
-{
- char *tag = NULL;
- char *tag_val = NULL;
- apr_bucket *tmp_buck;
-
- if (ctx->flags & FLAG_PRINTING) {
- ap_ssi_get_tag_and_value(ctx, &tag, &tag_val, 1);
- if ((tag == NULL) && (tag_val == NULL)) {
- apr_array_header_t *arr = apr_table_elts(r->subprocess_env);
- apr_table_entry_t *elts = (apr_table_entry_t *)arr->elts;
- int i;
- char *key_text, *val_text;
- apr_size_t k_len, v_len, t_wrt;
-
- *inserted_head = NULL;
- for (i = 0; i < arr->nelts; ++i) {
- key_text = ap_escape_html(r->pool, elts[i].key);
- val_text = ap_escape_html(r->pool, elts[i].val);
- k_len = strlen(key_text);
- v_len = strlen(val_text);
-
- /* Key_text */
- tmp_buck = apr_bucket_heap_create(key_text, k_len, 1, &t_wrt);
- APR_BUCKET_INSERT_BEFORE(head_ptr, tmp_buck);
- if (*inserted_head == NULL) {
- *inserted_head = tmp_buck;
- }
- /* = */
- tmp_buck = apr_bucket_immortal_create("=", 1);
- APR_BUCKET_INSERT_BEFORE(head_ptr, tmp_buck);
- /* Value_text */
- tmp_buck = apr_bucket_heap_create(val_text, v_len, 1, &t_wrt);
- APR_BUCKET_INSERT_BEFORE(head_ptr, tmp_buck);
- /* newline... */
- tmp_buck = apr_bucket_immortal_create("\n", 1);
- APR_BUCKET_INSERT_BEFORE(head_ptr, tmp_buck);
- }
- return 0;
- }
- else {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "printenv directive does not take tags in %s", r->filename);
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- return -1;
- }
- }
- return 0;
-}
-
-/* -------------------------- The main function --------------------------- */
-
-static void send_parsed_content(apr_bucket_brigade **bb, request_rec *r,
- ap_filter_t *f)
-{
- include_ctx_t *ctx = f->ctx;
- apr_bucket *dptr = APR_BRIGADE_FIRST(*bb);
- apr_bucket *tmp_dptr;
- apr_bucket_brigade *tag_and_after;
- int ret;
-
- if (r->args) { /* add QUERY stuff to env cause it ain't yet */
- char *arg_copy = apr_pstrdup(r->pool, r->args);
-
- apr_table_setn(r->subprocess_env, "QUERY_STRING", r->args);
- ap_unescape_url(arg_copy);
- apr_table_setn(r->subprocess_env, "QUERY_STRING_UNESCAPED",
- ap_escape_shell_cmd(r->pool, arg_copy));
- }
-
- while (dptr != APR_BRIGADE_SENTINEL(*bb)) {
- /* State to check for the STARTING_SEQUENCE. */
- if ((ctx->state == PRE_HEAD) || (ctx->state == PARSE_HEAD)) {
- int do_cleanup = 0;
- apr_size_t cleanup_bytes = ctx->parse_pos;
-
- tmp_dptr = find_start_sequence(dptr, ctx, *bb, &do_cleanup);
-
- /* The few bytes stored in the ssi_tag_brigade turned out not to
- * be a tag after all. This can only happen if the starting
- * tag actually spans brigades. This should be very rare.
- */
- if ((do_cleanup) && (!APR_BRIGADE_EMPTY(ctx->ssi_tag_brigade))) {
- apr_bucket *tmp_bkt;
-
- tmp_bkt = apr_bucket_immortal_create(STARTING_SEQUENCE,
- cleanup_bytes);
- APR_BRIGADE_INSERT_HEAD(*bb, tmp_bkt);
- apr_brigade_cleanup(ctx->ssi_tag_brigade);
- }
-
- /* If I am inside a conditional (if, elif, else) that is false
- * then I need to throw away anything contained in it.
- */
- if ((!(ctx->flags & FLAG_PRINTING)) && (tmp_dptr != NULL) &&
- (dptr != APR_BRIGADE_SENTINEL(*bb))) {
- while ((dptr != APR_BRIGADE_SENTINEL(*bb)) &&
- (dptr != tmp_dptr)) {
- apr_bucket *free_bucket = dptr;
-
- dptr = APR_BUCKET_NEXT (dptr);
- apr_bucket_delete(free_bucket);
- }
- }
-
- /* Adjust the current bucket position based on what was found... */
- if ((tmp_dptr != NULL) && (ctx->state == PARSE_DIRECTIVE)) {
- if (ctx->tag_start_bucket != NULL) {
- dptr = ctx->tag_start_bucket;
- }
- else {
- dptr = APR_BRIGADE_SENTINEL(*bb);
- }
- }
- else if ((tmp_dptr != NULL) && (ctx->bytes_parsed >= BYTE_COUNT_THRESHOLD)) {
- /* Send the large chunk of pre-tag bytes... */
- tag_and_after = apr_brigade_split(*bb, tmp_dptr);
- ap_pass_brigade(f->next, *bb);
- *bb = tag_and_after;
- dptr = tmp_dptr;
- ctx->bytes_parsed = 0;
- }
- else if (tmp_dptr == NULL) { /* There was no possible SSI tag in the */
- dptr = APR_BRIGADE_SENTINEL(*bb); /* remainder of this brigade... */
- }
- }
-
- /* State to check for the ENDING_SEQUENCE. */
- if (((ctx->state == PARSE_DIRECTIVE) ||
- (ctx->state == PARSE_TAG) ||
- (ctx->state == PARSE_TAIL)) &&
- (dptr != APR_BRIGADE_SENTINEL(*bb))) {
- tmp_dptr = find_end_sequence(dptr, ctx, *bb);
-
- if (tmp_dptr != NULL) {
- dptr = tmp_dptr; /* Adjust bucket pos... */
-
- /* If some of the tag has already been set aside then set
- * aside remainder of tag. Now the full tag is in ssi_tag_brigade.
- * If none has yet been set aside, then leave it all where it is.
- * In any event after this the entire set of tag buckets will be
- * in one place or another.
- */
- if (!APR_BRIGADE_EMPTY(ctx->ssi_tag_brigade)) {
- tag_and_after = apr_brigade_split(*bb, dptr);
- APR_BRIGADE_CONCAT(ctx->ssi_tag_brigade, *bb);
- *bb = tag_and_after;
- }
- else if (ctx->bytes_parsed >= BYTE_COUNT_THRESHOLD) {
- SPLIT_AND_PASS_PRETAG_BUCKETS(*bb, ctx, f->next);
- }
- }
- else {
- dptr = APR_BRIGADE_SENTINEL(*bb); /* remainder of this brigade... */
- }
- }
-
- /* State to processed the directive... */
- if (ctx->state == PARSED) {
- apr_bucket *content_head = NULL, *tmp_bkt;
- apr_size_t tmp_i;
- char tmp_buf[TMP_BUF_SIZE];
- int (*handle_func)(include_ctx_t *, apr_bucket_brigade **, request_rec *,
- ap_filter_t *, apr_bucket *, apr_bucket **);
-
- /* By now the full tag (all buckets) should either be set aside into
- * ssi_tag_brigade or contained within the current bb. All tag
- * processing from here on can assume that.
- */
-
- /* At this point, everything between ctx->head_start_bucket and
- * ctx->tail_start_bucket is an SSI
- * directive, we just have to deal with it now.
- */
- if (get_combined_directive(ctx, r, *bb, tmp_buf,
- TMP_BUF_SIZE) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "mod_include: error copying directive in %s",
- r->filename);
- CREATE_ERROR_BUCKET(ctx, tmp_bkt, dptr, content_head);
-
- /* DO CLEANUP HERE!!!!! */
- tmp_dptr = ctx->head_start_bucket;
- if (!APR_BRIGADE_EMPTY(ctx->ssi_tag_brigade)) {
- apr_brigade_cleanup(ctx->ssi_tag_brigade);
- }
- else {
- do {
- tmp_bkt = tmp_dptr;
- tmp_dptr = APR_BUCKET_NEXT (tmp_dptr);
- apr_bucket_delete(tmp_bkt);
- } while ((tmp_dptr != dptr) &&
- (tmp_dptr != APR_BRIGADE_SENTINEL(*bb)));
- }
-
- return;
- }
-
- /* Can't destroy the tag buckets until I'm done processing
- * because the combined_tag might just be pointing to
- * the contents of a single bucket!
- */
-
- /* Retrieve the handler function to be called for this directive from the
- * functions registered in the hash table.
- * Need to lower case the directive for proper matching. Also need to have
- * it NULL terminated (and include the NULL in the length) for proper
- * hash matching.
- */
- for (tmp_i = 0; tmp_i < ctx->directive_length; tmp_i++) {
- ctx->combined_tag[tmp_i] = apr_tolower(ctx->combined_tag[tmp_i]);
- }
- ctx->combined_tag[ctx->directive_length] = '\0';
- ctx->curr_tag_pos = &ctx->combined_tag[ctx->directive_length+1];
-
- handle_func =
- (include_handler_fn_t *)apr_hash_get(include_hash,
- ctx->combined_tag,
- ctx->directive_length+1);
- if (handle_func != NULL) {
- ret = (*handle_func)(ctx, bb, r, f, dptr, &content_head);
- }
- else {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "unknown directive \"%s\" in parsed doc %s",
- ctx->combined_tag, r->filename);
- CREATE_ERROR_BUCKET(ctx, tmp_bkt, dptr, content_head);
- }
-
- /* This chunk of code starts at the first bucket in the chain
- * of tag buckets (assuming that by this point the bucket for
- * the STARTING_SEQUENCE has been split) and loops through to
- * the end of the tag buckets freeing them all.
- *
- * Remember that some part of this may have been set aside
- * into the ssi_tag_brigade and the remainder (possibly as
- * little as one byte) will be in the current brigade.
- *
- * The value of dptr should have been set during the
- * PARSE_TAIL state to the first bucket after the
- * ENDING_SEQUENCE.
- *
- * The value of content_head may have been set during processing
- * of the directive. If so, the content was inserted in front
- * of the dptr bucket. The inserted buckets should not be thrown
- * away here, but they should also not be parsed later.
- */
- if (content_head == NULL) {
- content_head = dptr;
- }
- tmp_dptr = ctx->head_start_bucket;
- if (!APR_BRIGADE_EMPTY(ctx->ssi_tag_brigade)) {
- apr_brigade_cleanup(ctx->ssi_tag_brigade);
- }
- else {
- do {
- tmp_bkt = tmp_dptr;
- tmp_dptr = APR_BUCKET_NEXT (tmp_dptr);
- apr_bucket_delete(tmp_bkt);
- } while ((tmp_dptr != content_head) &&
- (tmp_dptr != APR_BRIGADE_SENTINEL(*bb)));
- }
- if (ctx->combined_tag == tmp_buf) {
- memset (ctx->combined_tag, '\0', ctx->tag_length);
- ctx->combined_tag = NULL;
- }
-
- /* Don't reset the flags or the nesting level!!! */
- ctx->parse_pos = 0;
- ctx->head_start_bucket = NULL;
- ctx->head_start_index = 0;
- ctx->tag_start_bucket = NULL;
- ctx->tag_start_index = 0;
- ctx->tail_start_bucket = NULL;
- ctx->tail_start_index = 0;
- ctx->curr_tag_pos = NULL;
- ctx->tag_length = 0;
- ctx->directive_length = 0;
-
- if (!APR_BRIGADE_EMPTY(ctx->ssi_tag_brigade)) {
- apr_brigade_cleanup(ctx->ssi_tag_brigade);
- }
-
- ctx->state = PRE_HEAD;
- }
- }
-
- /* If I am in the middle of parsing an SSI tag then I need to set aside
- * the pertinent trailing buckets and pass on the initial part of the
- * brigade. The pertinent parts of the next brigades will be added to
- * these set aside buckets to form the whole tag and will be processed
- * once the whole tag has been found.
- */
- if (ctx->state == PRE_HEAD) {
- /* Inside a false conditional (if, elif, else), so toss it all... */
- if ((dptr != APR_BRIGADE_SENTINEL(*bb)) &&
- (!(ctx->flags & FLAG_PRINTING))) {
- apr_bucket *free_bucket;
- do {
- free_bucket = dptr;
- dptr = APR_BUCKET_NEXT (dptr);
- apr_bucket_delete(free_bucket);
- } while (dptr != APR_BRIGADE_SENTINEL(*bb));
- }
- else { /* Otherwise pass it along... */
- ap_pass_brigade(f->next, *bb); /* No SSI tags in this brigade... */
- ctx->bytes_parsed = 0;
- }
- }
- else if (ctx->state == PARSED) { /* Invalid internal condition... */
- apr_bucket *content_head = NULL, *tmp_bkt;
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Invalid mod_include state during file %s", r->filename);
- CREATE_ERROR_BUCKET(ctx, tmp_bkt, APR_BRIGADE_FIRST(*bb), content_head);
- }
- else { /* Entire brigade is middle chunk of SSI tag... */
- if (!APR_BRIGADE_EMPTY(ctx->ssi_tag_brigade)) {
- APR_BRIGADE_CONCAT(ctx->ssi_tag_brigade, *bb);
- }
- else { /* End of brigade contains part of SSI tag... */
- if (ctx->head_start_index > 0) {
- apr_bucket_split(ctx->head_start_bucket, ctx->head_start_index);
- ctx->head_start_bucket = APR_BUCKET_NEXT(ctx->head_start_bucket);
- ctx->head_start_index = 0;
- }
- /* Set aside tag, pass pre-tag... */
- tag_and_after = apr_brigade_split(*bb, ctx->head_start_bucket);
- ap_save_brigade(f, &ctx->ssi_tag_brigade, &tag_and_after);
- ap_pass_brigade(f->next, *bb);
- ctx->bytes_parsed = 0;
- }
- }
-}
-
-/*****************************************************************
- *
- * XBITHACK. Sigh... NB it's configurable per-directory; the compile-time
- * option only changes the default.
- */
-
-module include_module;
-enum xbithack {
- xbithack_off, xbithack_on, xbithack_full
-};
-
-typedef struct {
- char *default_error_msg;
- char *default_time_fmt;
- enum xbithack *xbithack;
-} include_dir_config;
-
-#ifdef XBITHACK
-#define DEFAULT_XBITHACK xbithack_full
-#else
-#define DEFAULT_XBITHACK xbithack_off
-#endif
-
-static void *create_includes_dir_config(apr_pool_t *p, char *dummy)
-{
- include_dir_config *result =
- (include_dir_config *)apr_palloc(p, sizeof(include_dir_config));
- enum xbithack *xbh = (enum xbithack *) apr_palloc(p, sizeof(enum xbithack));
- *xbh = DEFAULT_XBITHACK;
- result->default_error_msg = DEFAULT_ERROR_MSG;
- result->default_time_fmt = DEFAULT_TIME_FORMAT;
- result->xbithack = xbh;
- return result;
- return result;
-}
-
-static const char *set_xbithack(cmd_parms *cmd, void *xbp, const char *arg)
-{
- include_dir_config *conf = (include_dir_config *)xbp;
-
- if (!strcasecmp(arg, "off")) {
- *conf->xbithack = xbithack_off;
- }
- else if (!strcasecmp(arg, "on")) {
- *conf->xbithack = xbithack_on;
- }
- else if (!strcasecmp(arg, "full")) {
- *conf->xbithack = xbithack_full;
- }
- else {
- return "XBitHack must be set to Off, On, or Full";
- }
-
- return NULL;
-}
-
-static int includes_filter(ap_filter_t *f, apr_bucket_brigade *b)
-{
- request_rec *r = f->r;
- include_ctx_t *ctx = f->ctx;
- request_rec *parent;
- include_dir_config *conf =
- (include_dir_config *)ap_get_module_config(r->per_dir_config,
- &include_module);
-
- if (!(ap_allow_options(r) & OPT_INCLUDES)) {
- return ap_pass_brigade(f->next, b);
- }
- r->allowed |= (1 << M_GET);
- if (r->method_number != M_GET) {
- return ap_pass_brigade(f->next, b);
- }
-
- if (!f->ctx) {
- f->ctx = ctx = apr_pcalloc(f->c->pool, sizeof(*ctx));
- if (ctx != NULL) {
- ctx->state = PRE_HEAD;
- ctx->flags = (FLAG_PRINTING | FLAG_COND_TRUE);
- if (ap_allow_options(r) & OPT_INCNOEXEC) {
- ctx->flags |= FLAG_NO_EXEC;
- }
- ctx->ssi_tag_brigade = apr_brigade_create(f->c->pool);
-
- apr_cpystrn(ctx->error_str, conf->default_error_msg, sizeof(ctx->error_str));
- apr_cpystrn(ctx->time_str, conf->default_time_fmt, sizeof(ctx->time_str));
- ctx->error_length = strlen(ctx->error_str);
- }
- else {
- ap_pass_brigade(f->next, b);
- return APR_ENOMEM;
- }
- }
- else {
- ctx->bytes_parsed = 0;
- }
-
- /* Assure the platform supports Group protections */
- if ((*conf->xbithack == xbithack_full)
- && (r->finfo.valid & APR_FINFO_GPROT)
- && (r->finfo.protection & APR_GEXECUTE)) {
- ap_update_mtime(r, r->finfo.mtime);
- ap_set_last_modified(r);
- }
-
- if ((parent = ap_get_module_config(r->request_config, &include_module))) {
- /* Kludge --- for nested includes, we want to keep the subprocess
- * environment of the base document (for compatibility); that means
- * torquing our own last_modified date as well so that the
- * LAST_MODIFIED variable gets reset to the proper value if the
- * nested document resets <!--#config timefmt-->.
- * We also insist that the memory for this subrequest not be
- * destroyed, that's dealt with in handle_include().
- */
- r->subprocess_env = r->main->subprocess_env;
- apr_pool_join(r->main->pool, r->pool);
- r->finfo.mtime = r->main->finfo.mtime;
- }
- else {
- /* we're not a nested include, so we create an initial
- * environment */
- ap_add_common_vars(r);
- ap_add_cgi_vars(r);
- add_include_vars(r, conf->default_time_fmt);
- }
- /* XXX: this is bogus, at some point we're going to do a subrequest,
- * and when we do it we're going to be subjecting code that doesn't
- * expect to be signal-ready to SIGALRM. There is no clean way to
- * fix this, except to put alarm support into BUFF. -djg
- */
-
-
- /* Always unset the content-length. There is no way to know if
- * the content will be modified at some point by send_parsed_content.
- * It is very possible for us to not find any content in the first
- * 9k of the file, but still have to modify the content of the file.
- * If we are going to pass the file through send_parsed_content, then
- * the content-length should just be unset.
- */
- apr_table_unset(f->r->headers_out, "Content-Length");
-
- send_parsed_content(&b, r, f);
-
- if (parent) {
- /* signify that the sub request should not be killed */
- ap_set_module_config(r->request_config, &include_module,
- NESTED_INCLUDE_MAGIC);
- }
-
- return OK;
-}
-
-static void ap_register_include_handler(char *tag, include_handler_fn_t *func)
-{
- apr_hash_set(include_hash, tag, strlen(tag) + 1, (const void *)func);
-}
-
-static void include_post_config(apr_pool_t *p, apr_pool_t *plog,
- apr_pool_t *ptemp, server_rec *s)
-{
- include_hash = apr_hash_make(p);
-
- ssi_pfn_register = APR_RETRIEVE_OPTIONAL_FN(ap_register_include_handler);
-
- if(ssi_pfn_register) {
- ssi_pfn_register("if", handle_if);
- ssi_pfn_register("set", handle_set);
- ssi_pfn_register("else", handle_else);
- ssi_pfn_register("elif", handle_elif);
- ssi_pfn_register("echo", handle_echo);
- ssi_pfn_register("endif", handle_endif);
- ssi_pfn_register("fsize", handle_fsize);
- ssi_pfn_register("config", handle_config);
- ssi_pfn_register("include", handle_include);
- ssi_pfn_register("flastmod", handle_flastmod);
- ssi_pfn_register("printenv", handle_printenv);
- }
-}
-
-static const char *set_default_error_msg(cmd_parms *cmd, void *mconfig, const char *msg)
-{
- include_dir_config *conf = (include_dir_config *)mconfig;
- conf->default_error_msg = apr_pstrdup(cmd->pool, msg);
- return NULL;
-}
-
-static const char *set_default_time_fmt(cmd_parms *cmd, void *mconfig, const char *fmt)
-{
- include_dir_config *conf = (include_dir_config *)mconfig;
- conf->default_time_fmt = apr_pstrdup(cmd->pool, fmt);
- return NULL;
-}
-
-/*
- * Module definition and configuration data structs...
- */
-static const command_rec includes_cmds[] =
-{
- AP_INIT_TAKE1("XBitHack", set_xbithack, NULL, OR_OPTIONS,
- "Off, On, or Full"),
- AP_INIT_TAKE1("SSIErrorMsg", set_default_error_msg, NULL, OR_ALL,
- "a string"),
- AP_INIT_TAKE1("SSITimeFormat", set_default_time_fmt, NULL, OR_ALL,
- "a strftime(3) formatted string"),
- {NULL}
-};
-
-static void register_hooks(apr_pool_t *p)
-{
- APR_REGISTER_OPTIONAL_FN(ap_ssi_get_tag_and_value);
- APR_REGISTER_OPTIONAL_FN(ap_ssi_parse_string);
- APR_REGISTER_OPTIONAL_FN(ap_register_include_handler);
- ap_hook_post_config(include_post_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
- ap_register_output_filter("INCLUDES", includes_filter, AP_FTYPE_CONTENT);
-}
-
-module AP_MODULE_DECLARE_DATA include_module =
-{
- STANDARD20_MODULE_STUFF,
- create_includes_dir_config, /* dir config creater */
- NULL, /* dir merger --- default is to override */
- NULL, /* server config */
- NULL, /* merge server config */
- includes_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
diff --git a/modules/filters/mod_include.exp b/modules/filters/mod_include.exp
deleted file mode 100644
index 335da742da..0000000000
--- a/modules/filters/mod_include.exp
+++ /dev/null
@@ -1 +0,0 @@
-includes_module
diff --git a/modules/filters/mod_include.h b/modules/filters/mod_include.h
deleted file mode 100644
index 6a92e0a57b..0000000000
--- a/modules/filters/mod_include.h
+++ /dev/null
@@ -1,214 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#ifndef _MOD_INCLUDE_H
-#define _MOD_INCLUDE_H 1
-
-#define STARTING_SEQUENCE "<!--#"
-#define ENDING_SEQUENCE "-->"
-
-#define DEFAULT_ERROR_MSG "[an error occurred while processing this directive]"
-#define DEFAULT_TIME_FORMAT "%A, %d-%b-%Y %H:%M:%S %Z"
-#define SIZEFMT_BYTES 0
-#define SIZEFMT_KMG 1
-#define TMP_BUF_SIZE 1024
-#if APR_CHARSET_EBCDIC
-#define RAW_ASCII_CHAR(ch) apr_xlate_conv_byte(ap_hdrs_from_ascii, (unsigned char)ch)
-#else /*APR_CHARSET_EBCDIC*/
-#define RAW_ASCII_CHAR(ch) (ch)
-#endif /*APR_CHARSET_EBCDIC*/
-
-/* just need some arbitrary non-NULL pointer which can't also be a request_rec */
-#define NESTED_INCLUDE_MAGIC (&include_module)
-
-/****************************************************************************
- * Used to keep context information during parsing of a request for SSI tags.
- * This is especially useful if the tag stretches across multiple buckets or
- * brigades. This keeps track of which buckets need to be replaced with the
- * content generated by the SSI tag.
- *
- * state: PRE_HEAD - State prior to finding the first character of the
- * STARTING_SEQUENCE. Next state is PARSE_HEAD.
- * PARSE_HEAD - State entered once the first character of the
- * STARTING_SEQUENCE is found and exited when the
- * the full STARTING_SEQUENCE has been matched or
- * a match failure occurs. Next state is PRE_HEAD
- * or PARSE_TAG.
- * PARSE_TAG - State entered once the STARTING sequence has been
- * matched. It is exited when the first character in
- * ENDING_SEQUENCE is found. Next state is PARSE_TAIL.
- * PARSE_TAIL - State entered from PARSE_TAG state when the first
- * character in ENDING_SEQUENCE is encountered. This
- * state is exited when the ENDING_SEQUENCE has been
- * completely matched, or when a match failure occurs.
- * Next state is PARSE_TAG or PARSED.
- * PARSED - State entered from PARSE_TAIL once the complete
- * ENDING_SEQUENCE has been matched. The SSI tag is
- * processed and the SSI buckets are replaced with the
- * SSI content during this state.
- * parse_pos: Current matched position within the STARTING_SEQUENCE or
- * ENDING_SEQUENCE during the PARSE_HEAD and PARSE_TAIL states.
- * This is especially useful when the sequence spans brigades.
- * X_start_bucket: These point to the buckets containing the first character
- * of the STARTING_SEQUENCE, the first non-whitespace
- * character of the tag, and the first character in the
- * ENDING_SEQUENCE (head_, tag_, and tail_ respectively).
- * The buckets are kept intact until the PARSED state is
- * reached, at which time the tag is consolidated and the
- * buckets are released. The buckets that these point to
- * have all been set aside in the ssi_tag_brigade (along
- * with all of the intervening buckets).
- * X_start_index: The index points within the specified bucket contents
- * where the first character of the STARTING_SEQUENCE,
- * the first non-whitespace character of the tag, and the
- * first character in the ENDING_SEQUENCE can be found
- * (head_, tag_, and tail_ respectively).
- * combined_tag: Once the PARSED state is reached the tag is collected from
- * the bucket(s) in the ssi_tag_brigade into this contiguous
- * buffer. The buckets in the ssi_tag_brigade are released
- * and the tag is processed.
- * curr_tag_pos: Ptr to the combined_tag buffer indicating the current
- * parse position.
- * tag_length: The number of bytes in the actual tag (excluding the
- * STARTING_SEQUENCE, leading and trailing whitespace,
- * and ENDING_SEQUENCE). This length is computed as the
- * buckets are parsed and set aside during the PARSE_TAG state.
- * ssi_tag_brigade: The temporary brigade used by this filter to set aside
- * the buckets containing parts of the ssi tag and headers.
- */
-typedef enum {PRE_HEAD, PARSE_HEAD, PARSE_DIRECTIVE, PARSE_TAG, PARSE_TAIL, PARSED} states;
-typedef struct include_filter_ctx {
- states state;
- long flags; /* See the FLAG_XXXXX definitions. */
- int if_nesting_level;
- apr_size_t parse_pos;
- int bytes_parsed;
-
- apr_bucket *head_start_bucket;
- apr_size_t head_start_index;
-
- apr_bucket *tag_start_bucket;
- apr_size_t tag_start_index;
-
- apr_bucket *tail_start_bucket;
- apr_size_t tail_start_index;
-
- char *combined_tag;
- char *curr_tag_pos;
- apr_size_t directive_length;
- apr_size_t tag_length;
-
- apr_size_t error_length;
- char error_str[MAX_STRING_LEN];
- char time_str[MAX_STRING_LEN];
-
- apr_bucket_brigade *ssi_tag_brigade;
-} include_ctx_t;
-
-/* These flags are used to set flag bits. */
-#define FLAG_PRINTING 0x00000001 /* Printing conditional lines. */
-#define FLAG_COND_TRUE 0x00000002 /* Conditional eval'd to true. */
-#define FLAG_SIZE_IN_BYTES 0x00000004 /* Sizes displayed in bytes. */
-#define FLAG_NO_EXEC 0x00000008 /* No Exec in current context. */
-
-/* These flags are used to clear flag bits. */
-#define FLAG_SIZE_ABBREV 0xFFFFFFFB /* Reset SIZE_IN_BYTES bit. */
-#define FLAG_CLEAR_PRINT_COND 0xFFFFFFFC /* Reset PRINTING and COND_TRUE*/
-#define FLAG_CLEAR_PRINTING 0xFFFFFFFE /* Reset just PRINTING bit. */
-
-#define CREATE_ERROR_BUCKET(cntx, t_buck, h_ptr, ins_head) \
-{ \
- apr_size_t e_wrt; \
- t_buck = apr_bucket_heap_create(cntx->error_str, \
- cntx->error_length, 1, &e_wrt); \
- APR_BUCKET_INSERT_BEFORE(h_ptr, t_buck); \
- \
- if (ins_head == NULL) { \
- ins_head = t_buck; \
- } \
-}
-
-#define SPLIT_AND_PASS_PRETAG_BUCKETS(brgd, cntxt, next) \
-if ((APR_BRIGADE_EMPTY(cntxt->ssi_tag_brigade)) && \
- (cntxt->head_start_bucket != NULL)) { \
- apr_bucket_brigade *tag_plus; \
- \
- tag_plus = apr_brigade_split(brgd, cntxt->head_start_bucket); \
- ap_pass_brigade(next, brgd); \
- cntxt->bytes_parsed = 0; \
- brgd = tag_plus; \
-}
-
-
-typedef int (include_handler_fn_t)(include_ctx_t *ctx, apr_bucket_brigade **bb,
- request_rec *r, ap_filter_t *f, apr_bucket *head_ptr,
- apr_bucket **inserted_head);
-
-APR_DECLARE_OPTIONAL_FN(void, ap_ssi_get_tag_and_value, (include_ctx_t *ctx,
- char **tag,
- char **tag_val,
- int dodecode));
-APR_DECLARE_OPTIONAL_FN(void, ap_ssi_parse_string, (request_rec *r,
- const char *in,
- char *out,
- size_t length,
- int leave_name));
-APR_DECLARE_OPTIONAL_FN(void, ap_register_include_handler,
- (char *tag, include_handler_fn_t *func));
-
-#endif /* MOD_INCLUDE */
diff --git a/modules/generators/.cvsignore b/modules/generators/.cvsignore
deleted file mode 100644
index 65f0cc30cf..0000000000
--- a/modules/generators/.cvsignore
+++ /dev/null
@@ -1,10 +0,0 @@
-.deps
-.libs
-*.la
-modules.mk
-Makefile
-*.lo
-*.slo
-*.so
-Debug
-Release
diff --git a/modules/generators/.indent.pro b/modules/generators/.indent.pro
deleted file mode 100644
index a9fbe9f9a1..0000000000
--- a/modules/generators/.indent.pro
+++ /dev/null
@@ -1,54 +0,0 @@
--i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1
--TBUFF
--TFILE
--TTRANS
--TUINT4
--T_trans
--Tallow_options_t
--Tapache_sfio
--Tarray_header
--Tbool_int
--Tbuf_area
--Tbuff_struct
--Tbuffy
--Tcmd_how
--Tcmd_parms
--Tcommand_rec
--Tcommand_struct
--Tconn_rec
--Tcore_dir_config
--Tcore_server_config
--Tdir_maker_func
--Tevent
--Tglobals_s
--Thandler_func
--Thandler_rec
--Tjoblist_s
--Tlisten_rec
--Tmerger_func
--Tmode_t
--Tmodule
--Tmodule_struct
--Tmutex
--Tn_long
--Tother_child_rec
--Toverrides_t
--Tparent_score
--Tpid_t
--Tpiped_log
--Tpool
--Trequest_rec
--Trequire_line
--Trlim_t
--Tscoreboard
--Tsemaphore
--Tserver_addr_rec
--Tserver_rec
--Tserver_rec_chain
--Tshort_score
--Ttable
--Ttable_entry
--Tthread
--Tu_wide_int
--Tvtime_t
--Twide_int
diff --git a/modules/generators/Makefile.in b/modules/generators/Makefile.in
deleted file mode 100644
index 167b343d0d..0000000000
--- a/modules/generators/Makefile.in
+++ /dev/null
@@ -1,3 +0,0 @@
-
-include $(top_srcdir)/build/special.mk
-
diff --git a/modules/generators/config5.m4 b/modules/generators/config5.m4
deleted file mode 100644
index 4e4379a681..0000000000
--- a/modules/generators/config5.m4
+++ /dev/null
@@ -1,29 +0,0 @@
-dnl modules enabled in this directory by default
-
-dnl APACHE_MODULE(name, helptext[, objects[, structname[, default[, config]]]])
-
-APACHE_MODPATH_INIT(generators)
-
-APACHE_MODULE(status, process/thread monitoring, , , yes)
-APACHE_MODULE(autoindex, directory listing, , , yes)
-APACHE_MODULE(asis, as-is filetypes, , , yes)
-APACHE_MODULE(info, server information, , , most)
-APACHE_MODULE(suexec, set uid and gid for spawned processes, , , no, [
- other_targets=suexec ] )
-
-APR_ADDTO(LTFLAGS,-export-dynamic)
-
-if test "$apache_cv_mpm" = "threaded" -o "$apache_cv_mpm" = "perchild"; then
-# if we are using a threaded MPM, we will get better performance with
-# mod_cgid, so make it the default.
- APACHE_MODULE(cgid, CGI scripts, , , yes)
- APACHE_MODULE(cgi, CGI scripts, , , no)
-else
-# if we are using a non-threaded MPM, it makes little sense to use
-# mod_cgid, and it just opens up holes we don't need. Make mod_cgi the
-# default
- APACHE_MODULE(cgi, CGI scripts, , , yes)
- APACHE_MODULE(cgid, CGI scripts, , , no)
-fi
-
-APACHE_MODPATH_FINISH
diff --git a/modules/generators/mod_asis.c b/modules/generators/mod_asis.c
deleted file mode 100644
index 63594236d5..0000000000
--- a/modules/generators/mod_asis.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "apr_strings.h"
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_protocol.h"
-#include "http_log.h"
-#include "util_script.h"
-#include "http_main.h"
-#include "http_request.h"
-
-#include "mod_core.h"
-
-#define ASIS_MAGIC_TYPE "httpd/send-as-is"
-
-static int asis_handler(request_rec *r)
-{
- apr_file_t *f = NULL;
- apr_status_t status;
- const char *location;
- apr_size_t nbytes;
-
- if(strcmp(r->handler,ASIS_MAGIC_TYPE) && strcmp(r->handler,"send-as-is"))
- return DECLINED;
-
- r->allowed |= (1 << M_GET);
- if (r->method_number != M_GET)
- return DECLINED;
- if (r->finfo.filetype == 0) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "File does not exist: %s", r->filename);
- return HTTP_NOT_FOUND;
- }
-
- if ((status = apr_file_open(&f, r->filename, APR_READ,
- APR_OS_DEFAULT, r->pool)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
- "file permissions deny server access: %s", r->filename);
- return HTTP_FORBIDDEN;
- }
-
- ap_scan_script_header_err(r, f, NULL);
- location = apr_table_get(r->headers_out, "Location");
-
- if (location && location[0] == '/' &&
- ((r->status == HTTP_OK) || ap_is_HTTP_REDIRECT(r->status))) {
-
- apr_file_close(f);
-
- /* Internal redirect -- fake-up a pseudo-request */
- r->status = HTTP_OK;
-
- /* This redirect needs to be a GET no matter what the original
- * method was.
- */
- r->method = apr_pstrdup(r->pool, "GET");
- r->method_number = M_GET;
-
- ap_internal_redirect_handler(location, r);
- return OK;
- }
-
- if (!r->header_only) {
- ap_send_fd(f, r, 0, r->finfo.size, &nbytes);
- }
-
- apr_file_close(f);
- return OK;
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_handler(asis_handler,NULL,NULL,APR_HOOK_MIDDLE);
-}
-
-module AP_MODULE_DECLARE_DATA asis_module =
-{
- STANDARD20_MODULE_STUFF,
- NULL, /* create per-directory config structure */
- NULL, /* merge per-directory config structures */
- NULL, /* create per-server config structure */
- NULL, /* merge per-server config structures */
- NULL, /* command apr_table_t */
- register_hooks /* register hooks */
-};
diff --git a/modules/generators/mod_asis.exp b/modules/generators/mod_asis.exp
deleted file mode 100644
index 4f347d921e..0000000000
--- a/modules/generators/mod_asis.exp
+++ /dev/null
@@ -1 +0,0 @@
-asis_module
diff --git a/modules/generators/mod_autoindex.c b/modules/generators/mod_autoindex.c
deleted file mode 100644
index 8ede153343..0000000000
--- a/modules/generators/mod_autoindex.c
+++ /dev/null
@@ -1,1713 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * mod_autoindex.c: Handles the on-the-fly html index generation
- *
- * Rob McCool
- * 3/23/93
- *
- * Adapted to Apache by rst.
- *
- * Version sort added by Martin Pool <mbp@humbug.org.au>.
- */
-
-#include "apr_strings.h"
-#include "apr_fnmatch.h"
-#include "apr_strings.h"
-#include "apr_lib.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_core.h"
-#include "http_request.h"
-#include "http_protocol.h"
-#include "http_log.h"
-#include "http_main.h"
-#include "util_script.h"
-
-#include "mod_core.h"
-
-module AP_MODULE_DECLARE_DATA autoindex_module;
-
-/****************************************************************
- *
- * Handling configuration directives...
- */
-
-#define HRULE 1
-#define NO_HRULE 0
-#define FRONT_MATTER 1
-#define END_MATTER 0
-
-#define FANCY_INDEXING 1 /* Indexing options */
-#define ICONS_ARE_LINKS 2
-#define SCAN_HTML_TITLES 4
-#define SUPPRESS_LAST_MOD 8
-#define SUPPRESS_SIZE 16
-#define SUPPRESS_DESC 32
-#define SUPPRESS_PREAMBLE 64
-#define SUPPRESS_COLSORT 128
-#define NO_OPTIONS 256
-#define VERSION_SORT 512
-
-#define K_PAD 1
-#define K_NOPAD 0
-
-#define K_NOADJUST 0
-#define K_ADJUST 1
-#define K_UNSET 2
-
-/*
- * Define keys for sorting.
- */
-#define K_NAME 'N' /* Sort by file name (default) */
-#define K_LAST_MOD 'M' /* Last modification date */
-#define K_SIZE 'S' /* Size (absolute, not as displayed) */
-#define K_DESC 'D' /* Description */
-
-#define D_ASCENDING 'A'
-#define D_DESCENDING 'D'
-
-/*
- * These are the dimensions of the default icons supplied with Apache.
- */
-#define DEFAULT_ICON_WIDTH 20
-#define DEFAULT_ICON_HEIGHT 22
-
-/*
- * Other default dimensions.
- */
-#define DEFAULT_NAME_WIDTH 23
-
-struct item {
- char *type;
- char *apply_to;
- char *apply_path;
- char *data;
-};
-
-typedef struct ai_desc_t {
- char *pattern;
- char *description;
- int full_path;
- int wildcards;
-} ai_desc_t;
-
-typedef struct autoindex_config_struct {
-
- char *default_icon;
- int opts;
- int incremented_opts;
- int decremented_opts;
- int name_width;
- int name_adjust;
- int icon_width;
- int icon_height;
- char *default_order;
-
- apr_array_header_t *icon_list;
- apr_array_header_t *alt_list;
- apr_array_header_t *desc_list;
- apr_array_header_t *ign_list;
- apr_array_header_t *hdr_list;
- apr_array_header_t *rdme_list;
-
-} autoindex_config_rec;
-
-static char c_by_encoding, c_by_type, c_by_path;
-
-#define BY_ENCODING &c_by_encoding
-#define BY_TYPE &c_by_type
-#define BY_PATH &c_by_path
-
-/*
- * Return true if the specified string refers to the parent directory (i.e.,
- * matches ".." or "../"). Hopefully this one call is significantly less
- * expensive than multiple strcmp() calls.
- */
-static APR_INLINE int is_parent(const char *name)
-{
- /*
- * Now, IFF the first two bytes are dots, and the third byte is either
- * EOS (\0) or a slash followed by EOS, we have a match.
- */
- if (((name[0] == '.') && (name[1] == '.'))
- && ((name[2] == '\0')
- || ((name[2] == '/') && (name[3] == '\0')))) {
- return 1;
- }
- return 0;
-}
-
-/*
- * This routine puts the standard HTML header at the top of the index page.
- * We include the DOCTYPE because we may be using features therefrom (i.e.,
- * HEIGHT and WIDTH attributes on the icons if we're FancyIndexing).
- */
-static void emit_preamble(request_rec *r, char *title)
-{
- ap_rvputs(r, DOCTYPE_HTML_3_2,
- "<HTML>\n <HEAD>\n <TITLE>Index of ", title,
- "</TITLE>\n </HEAD>\n <BODY>\n", NULL);
-}
-
-static void push_item(apr_array_header_t *arr, char *type, const char *to,
- const char *path, const char *data)
-{
- struct item *p = (struct item *) apr_array_push(arr);
-
- if (!to) {
- to = "";
- }
- if (!path) {
- path = "";
- }
-
- p->type = type;
- p->data = data ? apr_pstrdup(arr->cont, data) : NULL;
- p->apply_path = apr_pstrcat(arr->cont, path, "*", NULL);
-
- if ((type == BY_PATH) && (!ap_is_matchexp(to))) {
- p->apply_to = apr_pstrcat(arr->cont, "*", to, NULL);
- }
- else if (to) {
- p->apply_to = apr_pstrdup(arr->cont, to);
- }
- else {
- p->apply_to = NULL;
- }
-}
-
-static const char *add_alt(cmd_parms *cmd, void *d, const char *alt,
- const char *to)
-{
- if (cmd->info == BY_PATH) {
- if (!strcmp(to, "**DIRECTORY**")) {
- to = "^^DIRECTORY^^";
- }
- }
- if (cmd->info == BY_ENCODING) {
- char *tmp = apr_pstrdup(cmd->pool, to);
- ap_str_tolower(tmp);
- to = tmp;
- }
-
- push_item(((autoindex_config_rec *) d)->alt_list, cmd->info, to,
- cmd->path, alt);
- return NULL;
-}
-
-static const char *add_icon(cmd_parms *cmd, void *d, const char *icon,
- const char *to)
-{
- char *iconbak = apr_pstrdup(cmd->pool, icon);
-
- if (icon[0] == '(') {
- char *alt;
- char *cl = strchr(iconbak, ')');
-
- if (cl == NULL) {
- return "missing closing paren";
- }
- alt = ap_getword_nc(cmd->pool, &iconbak, ',');
- *cl = '\0'; /* Lose closing paren */
- add_alt(cmd, d, &alt[1], to);
- }
- if (cmd->info == BY_PATH) {
- if (!strcmp(to, "**DIRECTORY**")) {
- to = "^^DIRECTORY^^";
- }
- }
- if (cmd->info == BY_ENCODING) {
- char *tmp = apr_pstrdup(cmd->pool, to);
- ap_str_tolower(tmp);
- to = tmp;
- }
-
- push_item(((autoindex_config_rec *) d)->icon_list, cmd->info, to,
- cmd->path, iconbak);
- return NULL;
-}
-
-/*
- * Add description text for a filename pattern. If the pattern has
- * wildcards already (or we need to add them), add leading and
- * trailing wildcards to it to ensure substring processing. If the
- * pattern contains a '/' anywhere, force wildcard matching mode,
- * add a slash to the prefix so that "bar/bletch" won't be matched
- * by "foobar/bletch", and make a note that there's a delimiter;
- * the matching routine simplifies to just the actual filename
- * whenever it can. This allows definitions in parent directories
- * to be made for files in subordinate ones using relative paths.
- */
-
-/*
- * Absent a strcasestr() function, we have to force wildcards on
- * systems for which "AAA" and "aaa" mean the same file.
- */
-#ifdef CASE_BLIND_FILESYSTEM
-#define WILDCARDS_REQUIRED 1
-#else
-#define WILDCARDS_REQUIRED 0
-#endif
-
-static const char *add_desc(cmd_parms *cmd, void *d, const char *desc,
- const char *to)
-{
- autoindex_config_rec *dcfg = (autoindex_config_rec *) d;
- ai_desc_t *desc_entry;
- char *prefix = "";
-
- desc_entry = (ai_desc_t *) apr_array_push(dcfg->desc_list);
- desc_entry->full_path = (ap_strchr_c(to, '/') == NULL) ? 0 : 1;
- desc_entry->wildcards = (WILDCARDS_REQUIRED
- || desc_entry->full_path
- || apr_is_fnmatch(to));
- if (desc_entry->wildcards) {
- prefix = desc_entry->full_path ? "*/" : "*";
- desc_entry->pattern = apr_pstrcat(dcfg->desc_list->cont,
- prefix, to, "*", NULL);
- }
- else {
- desc_entry->pattern = apr_pstrdup(dcfg->desc_list->cont, to);
- }
- desc_entry->description = apr_pstrdup(dcfg->desc_list->cont, desc);
- return NULL;
-}
-
-static const char *add_ignore(cmd_parms *cmd, void *d, const char *ext)
-{
- push_item(((autoindex_config_rec *) d)->ign_list, 0, ext, cmd->path, NULL);
- return NULL;
-}
-
-static const char *add_header(cmd_parms *cmd, void *d, const char *name)
-{
- push_item(((autoindex_config_rec *) d)->hdr_list, 0, NULL, cmd->path,
- name);
- return NULL;
-}
-
-static const char *add_readme(cmd_parms *cmd, void *d, const char *name)
-{
- push_item(((autoindex_config_rec *) d)->rdme_list, 0, NULL, cmd->path,
- name);
- return NULL;
-}
-
-/* A legacy directive, FancyIndexing is superseded by the IndexOptions
- * keyword. But for compatibility..
- */
-static const char *fancy_indexing(cmd_parms *cmd, void *d, int arg)
-{
- int curopts;
- int newopts;
- autoindex_config_rec *cfg;
-
- cfg = (autoindex_config_rec *) d;
- curopts = cfg->opts;
- if (curopts & NO_OPTIONS) {
- return "FancyIndexing directive conflicts with existing "
- "IndexOptions None";
- }
- newopts = (arg ? (curopts | FANCY_INDEXING) : (curopts & ~FANCY_INDEXING));
- cfg->opts = newopts;
- return NULL;
-}
-
-static const char *add_opts(cmd_parms *cmd, void *d, const char *optstr)
-{
- char *w;
- int opts;
- int opts_add;
- int opts_remove;
- char action;
- autoindex_config_rec *d_cfg = (autoindex_config_rec *) d;
-
- opts = d_cfg->opts;
- opts_add = d_cfg->incremented_opts;
- opts_remove = d_cfg->decremented_opts;
- while (optstr[0]) {
- int option = 0;
-
- w = ap_getword_conf(cmd->pool, &optstr);
- if ((*w == '+') || (*w == '-')) {
- action = *(w++);
- }
- else {
- action = '\0';
- }
- if (!strcasecmp(w, "FancyIndexing")) {
- option = FANCY_INDEXING;
- }
- else if (!strcasecmp(w, "IconsAreLinks")) {
- option = ICONS_ARE_LINKS;
- }
- else if (!strcasecmp(w, "ScanHTMLTitles")) {
- option = SCAN_HTML_TITLES;
- }
- else if (!strcasecmp(w, "SuppressLastModified")) {
- option = SUPPRESS_LAST_MOD;
- }
- else if (!strcasecmp(w, "SuppressSize")) {
- option = SUPPRESS_SIZE;
- }
- else if (!strcasecmp(w, "SuppressDescription")) {
- option = SUPPRESS_DESC;
- }
- else if (!strcasecmp(w, "SuppressHTMLPreamble")) {
- option = SUPPRESS_PREAMBLE;
- }
- else if (!strcasecmp(w, "SuppressColumnSorting")) {
- option = SUPPRESS_COLSORT;
- }
- else if (!strcasecmp(w, "VersionSort")) {
- option = VERSION_SORT;
- }
- else if (!strcasecmp(w, "None")) {
- if (action != '\0') {
- return "Cannot combine '+' or '-' with 'None' keyword";
- }
- opts = NO_OPTIONS;
- opts_add = 0;
- opts_remove = 0;
- }
- else if (!strcasecmp(w, "IconWidth")) {
- if (action != '-') {
- d_cfg->icon_width = DEFAULT_ICON_WIDTH;
- }
- else {
- d_cfg->icon_width = 0;
- }
- }
- else if (!strncasecmp(w, "IconWidth=", 10)) {
- if (action == '-') {
- return "Cannot combine '-' with IconWidth=n";
- }
- d_cfg->icon_width = atoi(&w[10]);
- }
- else if (!strcasecmp(w, "IconHeight")) {
- if (action != '-') {
- d_cfg->icon_height = DEFAULT_ICON_HEIGHT;
- }
- else {
- d_cfg->icon_height = 0;
- }
- }
- else if (!strncasecmp(w, "IconHeight=", 11)) {
- if (action == '-') {
- return "Cannot combine '-' with IconHeight=n";
- }
- d_cfg->icon_height = atoi(&w[11]);
- }
- else if (!strcasecmp(w, "NameWidth")) {
- if (action != '-') {
- return "NameWidth with no value may only appear as "
- "'-NameWidth'";
- }
- d_cfg->name_width = DEFAULT_NAME_WIDTH;
- d_cfg->name_adjust = K_NOADJUST;
- }
- else if (!strncasecmp(w, "NameWidth=", 10)) {
- if (action == '-') {
- return "Cannot combine '-' with NameWidth=n";
- }
- if (w[10] == '*') {
- d_cfg->name_adjust = K_ADJUST;
- }
- else {
- int width = atoi(&w[10]);
-
- if (width < 5) {
- return "NameWidth value must be greater than 5";
- }
- d_cfg->name_width = width;
- d_cfg->name_adjust = K_NOADJUST;
- }
- }
- else {
- return "Invalid directory indexing option";
- }
- if (action == '\0') {
- opts |= option;
- opts_add = 0;
- opts_remove = 0;
- }
- else if (action == '+') {
- opts_add |= option;
- opts_remove &= ~option;
- }
- else {
- opts_remove |= option;
- opts_add &= ~option;
- }
- }
- if ((opts & NO_OPTIONS) && (opts & ~NO_OPTIONS)) {
- return "Cannot combine other IndexOptions keywords with 'None'";
- }
- d_cfg->incremented_opts = opts_add;
- d_cfg->decremented_opts = opts_remove;
- d_cfg->opts = opts;
- return NULL;
-}
-
-static const char *set_default_order(cmd_parms *cmd, void *m, const char *direction,
- const char *key)
-{
- char temp[4];
- autoindex_config_rec *d_cfg = (autoindex_config_rec *) m;
-
- apr_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 = apr_palloc(cmd->pool, 4);
- d_cfg->default_order[3] = '\0';
- }
- apr_cpystrn(d_cfg->default_order, temp, sizeof(temp));
- return NULL;
-}
-
-#define DIR_CMD_PERMS OR_INDEXES
-
-static const command_rec autoindex_cmds[] =
-{
- AP_INIT_ITERATE2("AddIcon", add_icon, BY_PATH, DIR_CMD_PERMS,
- "an icon URL followed by one or more filenames"),
- AP_INIT_ITERATE2("AddIconByType", add_icon, BY_TYPE, DIR_CMD_PERMS,
- "an icon URL followed by one or more MIME types"),
- AP_INIT_ITERATE2("AddIconByEncoding", add_icon, BY_ENCODING, DIR_CMD_PERMS,
- "an icon URL followed by one or more content encodings"),
- AP_INIT_ITERATE2("AddAlt", add_alt, BY_PATH, DIR_CMD_PERMS,
- "alternate descriptive text followed by one or more filenames"),
- AP_INIT_ITERATE2("AddAltByType", add_alt, BY_TYPE, DIR_CMD_PERMS,
- "alternate descriptive text followed by one or more MIME types"),
- AP_INIT_ITERATE2("AddAltByEncoding", add_alt, BY_ENCODING, DIR_CMD_PERMS,
- "alternate descriptive text followed by one or more content encodings"),
- AP_INIT_RAW_ARGS("IndexOptions", add_opts, NULL, DIR_CMD_PERMS,
- "one or more index options"),
- AP_INIT_TAKE2("IndexOrderDefault", set_default_order, NULL, DIR_CMD_PERMS,
- "{Ascending,Descending} {Name,Size,Description,Date}"),
- AP_INIT_ITERATE("IndexIgnore", add_ignore, NULL, DIR_CMD_PERMS,
- "one or more file extensions"),
- AP_INIT_ITERATE2("AddDescription", add_desc, BY_PATH, DIR_CMD_PERMS,
- "Descriptive text followed by one or more filenames"),
- AP_INIT_TAKE1("HeaderName", add_header, NULL, DIR_CMD_PERMS,
- "a filename"),
- AP_INIT_TAKE1("ReadmeName", add_readme, NULL, DIR_CMD_PERMS,
- "a filename"),
- AP_INIT_FLAG("FancyIndexing", fancy_indexing, NULL, DIR_CMD_PERMS,
- "Limited to 'on' or 'off' (superseded by IndexOptions FancyIndexing)"),
- AP_INIT_TAKE1("DefaultIcon", ap_set_string_slot,
- (void *) XtOffsetOf(autoindex_config_rec, default_icon),
- DIR_CMD_PERMS, "an icon URL"),
- {NULL}
-};
-
-static void *create_autoindex_config(apr_pool_t *p, char *dummy)
-{
- autoindex_config_rec *new =
- (autoindex_config_rec *) apr_pcalloc(p, sizeof(autoindex_config_rec));
-
- new->icon_width = 0;
- new->icon_height = 0;
- new->name_width = DEFAULT_NAME_WIDTH;
- new->name_adjust = K_UNSET;
- new->icon_list = apr_array_make(p, 4, sizeof(struct item));
- new->alt_list = apr_array_make(p, 4, sizeof(struct item));
- new->desc_list = apr_array_make(p, 4, sizeof(ai_desc_t));
- new->ign_list = apr_array_make(p, 4, sizeof(struct item));
- new->hdr_list = apr_array_make(p, 4, sizeof(struct item));
- new->rdme_list = apr_array_make(p, 4, sizeof(struct item));
- new->opts = 0;
- new->incremented_opts = 0;
- new->decremented_opts = 0;
- new->default_order = NULL;
-
- return (void *) new;
-}
-
-static void *merge_autoindex_configs(apr_pool_t *p, void *basev, void *addv)
-{
- autoindex_config_rec *new;
- autoindex_config_rec *base = (autoindex_config_rec *) basev;
- autoindex_config_rec *add = (autoindex_config_rec *) addv;
-
- new = (autoindex_config_rec *) apr_pcalloc(p, sizeof(autoindex_config_rec));
- new->default_icon = add->default_icon ? add->default_icon
- : base->default_icon;
- new->icon_height = add->icon_height ? add->icon_height : base->icon_height;
- new->icon_width = add->icon_width ? add->icon_width : base->icon_width;
-
- new->alt_list = apr_array_append(p, add->alt_list, base->alt_list);
- new->ign_list = apr_array_append(p, add->ign_list, base->ign_list);
- new->hdr_list = apr_array_append(p, add->hdr_list, base->hdr_list);
- new->desc_list = apr_array_append(p, add->desc_list, base->desc_list);
- new->icon_list = apr_array_append(p, add->icon_list, base->icon_list);
- new->rdme_list = apr_array_append(p, add->rdme_list, base->rdme_list);
- if (add->opts & NO_OPTIONS) {
- /*
- * If the current directory says 'no options' then we also
- * clear any incremental mods from being inheritable further down.
- */
- new->opts = NO_OPTIONS;
- new->incremented_opts = 0;
- new->decremented_opts = 0;
- }
- else {
- /*
- * If there were any nonincremental options selected for
- * this directory, they dominate and we don't inherit *anything.*
- * Contrariwise, we *do* inherit if the only settings here are
- * incremental ones.
- */
- if (add->opts == 0) {
- new->incremented_opts = (base->incremented_opts
- | add->incremented_opts)
- & ~add->decremented_opts;
- new->decremented_opts = (base->decremented_opts
- | add->decremented_opts);
- /*
- * We may have incremental settings, so make sure we don't
- * inadvertently inherit an IndexOptions None from above.
- */
- new->opts = (base->opts & ~NO_OPTIONS);
- }
- else {
- /*
- * There are local nonincremental settings, which clear
- * all inheritance from above. They *are* the new base settings.
- */
- new->opts = add->opts;;
- }
- /*
- * We're guaranteed that there'll be no overlap between
- * the add-options and the remove-options.
- */
- new->opts |= new->incremented_opts;
- new->opts &= ~new->decremented_opts;
- }
- /*
- * Inherit the NameWidth settings if there aren't any specific to
- * the new location; otherwise we'll end up using the defaults set in the
- * config-rec creation routine.
- */
- if (add->name_adjust == K_UNSET) {
- new->name_width = base->name_width;
- new->name_adjust = base->name_adjust;
- }
- else {
- new->name_width = add->name_width;
- new->name_adjust = add->name_adjust;
- }
-
- new->default_order = (add->default_order != NULL)
- ? add->default_order : base->default_order;
- return new;
-}
-
-/****************************************************************
- *
- * Looking things up in config entries...
- */
-
-/* Structure used to hold entries when we're actually building an index */
-
-struct ent {
- char *name;
- char *icon;
- char *alt;
- char *desc;
- off_t size;
- apr_time_t lm;
- struct ent *next;
- int ascending, version_sort;
- char key;
-};
-
-static char *find_item(request_rec *r, apr_array_header_t *list, int path_only)
-{
- const char *content_type = ap_field_noparam(r->pool, r->content_type);
- const char *content_encoding = r->content_encoding;
- char *path = r->filename;
-
- struct item *items = (struct item *) list->elts;
- int i;
-
- for (i = 0; i < list->nelts; ++i) {
- struct item *p = &items[i];
-
- /* Special cased for ^^DIRECTORY^^ and ^^BLANKICON^^ */
- if ((path[0] == '^') || (!ap_strcmp_match(path, p->apply_path))) {
- if (!*(p->apply_to)) {
- return p->data;
- }
- else if (p->type == BY_PATH || path[0] == '^') {
- if (!ap_strcmp_match(path, p->apply_to)) {
- return p->data;
- }
- }
- else if (!path_only) {
- if (!content_encoding) {
- if (p->type == BY_TYPE) {
- if (content_type
- && !ap_strcasecmp_match(content_type,
- p->apply_to)) {
- return p->data;
- }
- }
- }
- else {
- if (p->type == BY_ENCODING) {
- if (!ap_strcasecmp_match(content_encoding,
- p->apply_to)) {
- return p->data;
- }
- }
- }
- }
- }
- }
- return NULL;
-}
-
-#define find_icon(d,p,t) find_item(p,d->icon_list,t)
-#define find_alt(d,p,t) find_item(p,d->alt_list,t)
-#define find_header(d,p) find_item(p,d->hdr_list,0)
-#define find_readme(d,p) find_item(p,d->rdme_list,0)
-
-static char *find_default_icon(autoindex_config_rec *d, char *bogus_name)
-{
- request_rec r;
-
- /* Bleah. I tried to clean up find_item, and it lead to this bit
- * of ugliness. Note that the fields initialized are precisely
- * those that find_item looks at...
- */
-
- r.filename = bogus_name;
- r.content_type = r.content_encoding = NULL;
-
- return find_item(&r, d->icon_list, 1);
-}
-
-/*
- * Look through the list of pattern/description pairs and return the first one
- * if any) that matches the filename in the request. If multiple patterns
- * match, only the first one is used; since the order in the array is the
- * same as the order in which directives were processed, earlier matching
- * directives will dominate.
- */
-
-#ifdef CASE_BLIND_FILESYSTEM
-#define MATCH_FLAGS FNM_CASE_BLIND
-#else
-#define MATCH_FLAGS 0
-#endif
-
-static char *find_desc(autoindex_config_rec *dcfg, request_rec *r)
-{
- int i;
- ai_desc_t *list = (ai_desc_t *) dcfg->desc_list->elts;
- const char *filename_full = r->filename;
- const char *filename_only;
- const char *filename;
-
- /*
- * If the filename includes a path, extract just the name itself
- * for the simple matches.
- */
- if ((filename_only = ap_strrchr_c(filename_full, '/')) == NULL) {
- filename_only = filename_full;
- }
- else {
- filename_only++;
- }
- for (i = 0; i < dcfg->desc_list->nelts; ++i) {
- ai_desc_t *tuple = &list[i];
- int found;
-
- /*
- * Only use the full-path filename if the pattern contains '/'s.
- */
- filename = (tuple->full_path) ? filename_full : filename_only;
- /*
- * Make the comparison using the cheapest method; only do
- * wildcard checking if we must.
- */
- if (tuple->wildcards) {
- found = (apr_fnmatch(tuple->pattern, filename, MATCH_FLAGS) == 0);
- }
- else {
- found = (ap_strstr_c(filename, tuple->pattern) != NULL);
- }
- if (found) {
- return tuple->description;
- }
- }
- return NULL;
-}
-
-static int ignore_entry(autoindex_config_rec *d, char *path)
-{
- apr_array_header_t *list = d->ign_list;
- struct item *items = (struct item *) list->elts;
- char *tt;
- int i;
-
- if ((tt = strrchr(path, '/')) == NULL) {
- tt = path;
- }
- else {
- tt++;
- }
-
- for (i = 0; i < list->nelts; ++i) {
- struct item *p = &items[i];
- char *ap;
-
- if ((ap = strrchr(p->apply_to, '/')) == NULL) {
- ap = p->apply_to;
- }
- else {
- ap++;
- }
-
-#ifndef CASE_BLIND_FILESYSTEM
- if (!ap_strcmp_match(path, p->apply_path)
- && !ap_strcmp_match(tt, ap)) {
- return 1;
- }
-#else /* !CASE_BLIND_FILESYSTEM */
- /*
- * On some platforms, the match must be case-blind. This is really
- * a factor of the filesystem involved, but we can't detect that
- * reliably - so we have to granularise at the OS level.
- */
- if (!ap_strcasecmp_match(path, p->apply_path)
- && !ap_strcasecmp_match(tt, ap)) {
- return 1;
- }
-#endif /* !CASE_BLIND_FILESYSTEM */
- }
- return 0;
-}
-
-/*****************************************************************
- *
- * Actually generating output
- */
-
-/*
- * Elements of the emitted document:
- * Preamble
- * Emitted unless SUPPRESS_PREAMBLE is set AND ap_run_sub_req
- * succeeds for the (content_type == text/html) header file.
- * Header file
- * Emitted if found (and able).
- * H1 tag line
- * Emitted if a header file is NOT emitted.
- * Directory stuff
- * Always emitted.
- * HR
- * Emitted if FANCY_INDEXING is set.
- * Readme file
- * Emitted if found (and able).
- * ServerSig
- * Emitted if ServerSignature is not Off AND a readme file
- * is NOT emitted.
- * Postamble
- * Emitted unless SUPPRESS_PREAMBLE is set AND ap_run_sub_req
- * succeeds for the (content_type == text/html) readme file.
- */
-
-
-/*
- * emit a plain text file
- */
-static void do_emit_plain(request_rec *r, apr_file_t *f)
-{
- char buf[AP_IOBUFSIZE + 1];
- int i, c, ch;
- apr_size_t n;
- apr_status_t stat;
-
- ap_rputs("<PRE>\n", r);
- while (!apr_file_eof(f)) {
- do {
- n = sizeof(char) * AP_IOBUFSIZE;
- stat = apr_file_read(f, buf, &n);
- }
- while (stat != APR_SUCCESS && APR_STATUS_IS_EINTR(stat));
- if (n == -1 || n == 0) {
- break;
- }
- buf[n] = '\0';
- c = 0;
- while (c < n) {
- for (i = c; i < n; i++) {
- if (buf[i] == '<' || buf[i] == '>' || buf[i] == '&') {
- break;
- }
- }
- ch = buf[i];
- buf[i] = '\0';
- ap_rputs(&buf[c], r);
- if (ch == '<') {
- ap_rputs("&lt;", r);
- }
- else if (ch == '>') {
- ap_rputs("&gt;", r);
- }
- else if (ch == '&') {
- ap_rputs("&amp;", r);
- }
- c = i + 1;
- }
- }
- ap_rputs("</PRE>\n", r);
-}
-
-/*
- * Handle the preamble through the H1 tag line, inclusive. Locate
- * the file with a subrequests. Process text/html documents by actually
- * running the subrequest; text/xxx documents get copied verbatim,
- * and any other content type is ignored. This means that a non-text
- * document (such as HEADER.gif) might get multiviewed as the result
- * instead of a text document, meaning nothing will be displayed, but
- * oh well.
- */
-static void emit_head(request_rec *r, char *header_fname, int suppress_amble,
- char *title)
-{
- apr_file_t *f = NULL;
- request_rec *rr = NULL;
- int emit_amble = 1;
- int emit_H1 = 1;
-
- /*
- * If there's a header file, send a subrequest to look for it. If it's
- * found and a text file, handle it -- otherwise fall through and
- * pretend there's nothing there.
- */
- if ((header_fname != NULL)
- && (rr = ap_sub_req_lookup_uri(header_fname, r, NULL))
- && (rr->status == HTTP_OK)
- && (rr->filename != NULL)
- && rr->finfo.filetype == APR_REG) {
- /*
- * Check for the two specific cases we allow: text/html and
- * text/anything-else. The former is allowed to be processed for
- * SSIs.
- */
- if (rr->content_type != NULL) {
- if (!strcasecmp(ap_field_noparam(r->pool, rr->content_type),
- "text/html")) {
- /* Hope everything will work... */
- emit_amble = 0;
- emit_H1 = 0;
-
- if (! suppress_amble) {
- emit_preamble(r, title);
- }
- /*
- * If there's a problem running the subrequest, display the
- * preamble if we didn't do it before -- the header file
- * didn't get displayed.
- */
- if (ap_run_sub_req(rr) != OK) {
- /* It didn't work */
- emit_amble = suppress_amble;
- emit_H1 = 1;
- }
- }
- else if (!strncasecmp("text/", rr->content_type, 5)) {
- /*
- * If we can open the file, prefix it with the preamble
- * regardless; since we'll be sending a <PRE> block around
- * the file's contents, any HTML header it had won't end up
- * where it belongs.
- */
- if (apr_file_open(&f, rr->filename, APR_READ,
- APR_OS_DEFAULT, r->pool) == APR_SUCCESS) {
- emit_preamble(r, title);
- emit_amble = 0;
- do_emit_plain(r, f);
- apr_file_close(f);
- emit_H1 = 0;
- }
- }
- }
- }
-
- if (emit_amble) {
- emit_preamble(r, title);
- }
- if (emit_H1) {
- ap_rvputs(r, "<H1>Index of ", title, "</H1>\n", NULL);
- }
- if (rr != NULL) {
- ap_destroy_sub_req(rr);
- }
-}
-
-
-/*
- * Handle the Readme file through the postamble, inclusive. Locate
- * the file with a subrequests. Process text/html documents by actually
- * running the subrequest; text/xxx documents get copied verbatim,
- * and any other content type is ignored. This means that a non-text
- * document (such as FOOTER.gif) might get multiviewed as the result
- * instead of a text document, meaning nothing will be displayed, but
- * oh well.
- */
-static void emit_tail(request_rec *r, char *readme_fname, int suppress_amble)
-{
- apr_file_t *f = NULL;
- request_rec *rr = NULL;
- int suppress_post = 0;
- int suppress_sig = 0;
-
- /*
- * If there's a readme file, send a subrequest to look for it. If it's
- * found and a text file, handle it -- otherwise fall through and
- * pretend there's nothing there.
- */
- if ((readme_fname != NULL)
- && (rr = ap_sub_req_lookup_uri(readme_fname, r, NULL))
- && (rr->status == HTTP_OK)
- && (rr->filename != NULL)
- && rr->finfo.filetype == APR_REG) {
- /*
- * Check for the two specific cases we allow: text/html and
- * text/anything-else. The former is allowed to be processed for
- * SSIs.
- */
- if (rr->content_type != NULL) {
- if (!strcasecmp(ap_field_noparam(r->pool, rr->content_type),
- "text/html")) {
- if (ap_run_sub_req(rr) == OK) {
- /* worked... */
- suppress_sig = 1;
- suppress_post = suppress_amble;
- }
- }
- else if (!strncasecmp("text/", rr->content_type, 5)) {
- /*
- * If we can open the file, suppress the signature.
- */
- if (apr_file_open(&f, rr->filename, APR_READ,
- APR_OS_DEFAULT, r->pool) == APR_SUCCESS) {
- do_emit_plain(r, f);
- apr_file_close(f);
- suppress_sig = 1;
- }
- }
- }
- }
-
- if (!suppress_sig) {
- ap_rputs(ap_psignature("", r), r);
- }
- if (!suppress_post) {
- ap_rputs("</BODY></HTML>\n", r);
- }
- if (rr != NULL) {
- ap_destroy_sub_req(rr);
- }
-}
-
-
-static char *find_title(request_rec *r)
-{
- char titlebuf[MAX_STRING_LEN], *find = "<TITLE>";
- apr_file_t *thefile = NULL;
- int x, y, p;
- apr_size_t n;
-
- if (r->status != HTTP_OK) {
- return NULL;
- }
- if ((r->content_type != NULL)
- && (!strcasecmp(ap_field_noparam(r->pool, r->content_type),
- "text/html")
- || !strcmp(r->content_type, INCLUDES_MAGIC_TYPE))
- && !r->content_encoding) {
- if (apr_file_open(&thefile, r->filename, APR_READ,
- APR_OS_DEFAULT, r->pool) != APR_SUCCESS) {
- return NULL;
- }
- n = sizeof(char) * (MAX_STRING_LEN - 1);
- apr_file_read(thefile, titlebuf, &n);
- if (n <= 0) {
- apr_file_close(thefile);
- return NULL;
- }
- titlebuf[n] = '\0';
- for (x = 0, p = 0; titlebuf[x]; x++) {
- if (apr_toupper(titlebuf[x]) == find[p]) {
- if (!find[++p]) {
- if ((p = ap_ind(&titlebuf[++x], '<')) != -1) {
- titlebuf[x + p] = '\0';
- }
- /* Scan for line breaks for Tanmoy's secretary */
- for (y = x; titlebuf[y]; y++) {
- if ((titlebuf[y] == CR) || (titlebuf[y] == LF)) {
- if (y == x) {
- x++;
- }
- else {
- titlebuf[y] = ' ';
- }
- }
- }
- apr_file_close(thefile);
- return apr_pstrdup(r->pool, &titlebuf[x]);
- }
- }
- else {
- p = 0;
- }
- }
- apr_file_close(thefile);
- }
- return NULL;
-}
-
-static struct ent *make_autoindex_entry(const char *name, int autoindex_opts,
- autoindex_config_rec *d,
- request_rec *r, char keyid,
- char direction)
-{
- struct ent *p;
-
- if ((name[0] == '.') && (!name[1])) {
- return (NULL);
- }
-
- if (ignore_entry(d, ap_make_full_path(r->pool, r->filename, name))) {
- return (NULL);
- }
-
- p = (struct ent *) apr_pcalloc(r->pool, sizeof(struct ent));
- p->name = apr_pstrdup(r->pool, name);
- p->size = -1;
- p->icon = NULL;
- p->alt = NULL;
- p->desc = NULL;
- p->lm = -1;
- p->key = apr_toupper(keyid);
- p->ascending = (apr_toupper(direction) == D_ASCENDING);
- p->version_sort = autoindex_opts & VERSION_SORT;
-
- if (autoindex_opts & FANCY_INDEXING) {
- request_rec *rr = ap_sub_req_lookup_file(name, r, NULL);
-
- if (rr->finfo.filetype != 0) {
- p->lm = rr->finfo.mtime;
- if (rr->finfo.filetype == APR_DIR) {
- if (!(p->icon = find_icon(d, rr, 1))) {
- p->icon = find_default_icon(d, "^^DIRECTORY^^");
- }
- if (!(p->alt = find_alt(d, rr, 1))) {
- p->alt = "DIR";
- }
- p->size = -1;
- p->name = apr_pstrcat(r->pool, name, "/", NULL);
- }
- else {
- p->icon = find_icon(d, rr, 0);
- p->alt = find_alt(d, rr, 0);
- p->size = rr->finfo.size;
- }
- }
-
- p->desc = find_desc(d, rr);
-
- if ((!p->desc) && (autoindex_opts & SCAN_HTML_TITLES)) {
- p->desc = apr_pstrdup(r->pool, find_title(rr));
- }
-
- ap_destroy_sub_req(rr);
- }
- /*
- * We don't need to take any special action for the file size key. If
- * we did, it would go here.
- */
- if (keyid == K_LAST_MOD) {
- if (p->lm < 0) {
- p->lm = 0;
- }
- }
- return (p);
-}
-
-static char *terminate_description(autoindex_config_rec *d, char *desc,
- int autoindex_opts)
-{
- int maxsize = 23;
- register int x;
-
- if (autoindex_opts & SUPPRESS_LAST_MOD) {
- maxsize += 19;
- }
- if (autoindex_opts & SUPPRESS_SIZE) {
- maxsize += 7;
- }
-
- for (x = 0; desc[x] && (maxsize > 0 || desc[x]=='<'); x++) {
- if (desc[x] == '<') {
- while (desc[x] != '>') {
- if (!desc[x]) {
- maxsize = 0;
- break;
- }
- ++x;
- }
- }
- else if (desc[x] == '&') {
- /* entities like &auml; count as one character */
- --maxsize;
- for ( ; desc[x] != ';'; ++x) {
- if (desc[x] == '\0') {
- maxsize = 0;
- break;
- }
- }
- }
- else {
- --maxsize;
- }
- }
- if (!maxsize && desc[x] != '\0') {
- desc[x - 1] = '>'; /* Grump. */
- desc[x] = '\0'; /* Double Grump! */
- }
- return desc;
-}
-
-/*
- * Emit the anchor for the specified field. If a field is the key for the
- * current request, the link changes its meaning to reverse the order when
- * selected again. Non-active fields always start in ascending order.
- */
-static void emit_link(request_rec *r, char *anchor, char fname, char curkey,
- char curdirection, int nosort)
-{
- char qvalue[5];
- int reverse;
-
- if (!nosort) {
- qvalue[0] = '?';
- qvalue[1] = fname;
- qvalue[2] = '=';
- qvalue[4] = '\0';
- reverse = ((curkey == fname) && (curdirection == D_ASCENDING));
- qvalue[3] = reverse ? D_DESCENDING : D_ASCENDING;
- ap_rvputs(r, "<A HREF=\"", qvalue, "\">", anchor, "</A>", NULL);
- }
- else {
- ap_rputs(anchor, r);
- }
-}
-
-static void output_directories(struct ent **ar, int n,
- autoindex_config_rec *d, request_rec *r,
- int autoindex_opts, char keyid, char direction)
-{
- int x;
- apr_size_t rv;
- char *name = r->uri;
- char *tp;
- int static_columns = (autoindex_opts & SUPPRESS_COLSORT);
- apr_pool_t *scratch;
- int name_width;
- char *name_scratch;
- char *pad_scratch;
-
- apr_pool_create(&scratch, r->pool);
- if (name[0] == '\0') {
- name = "/";
- }
-
- name_width = d->name_width;
- if (d->name_adjust == K_ADJUST) {
- for (x = 0; x < n; x++) {
- int t = strlen(ar[x]->name);
- if (t > name_width) {
- name_width = t;
- }
- }
- }
- name_scratch = apr_palloc(r->pool, name_width + 1);
- pad_scratch = apr_palloc(r->pool, name_width + 1);
- memset(pad_scratch, ' ', name_width);
- pad_scratch[name_width] = '\0';
-
- if (autoindex_opts & FANCY_INDEXING) {
- ap_rputs("<PRE>", r);
- if ((tp = find_default_icon(d, "^^BLANKICON^^"))) {
- ap_rvputs(r, "<IMG SRC=\"", ap_escape_html(scratch, tp),
- "\" ALT=\" \"", NULL);
- if (d->icon_width && d->icon_height) {
- ap_rprintf
- (
- r,
- " HEIGHT=\"%d\" WIDTH=\"%d\"",
- d->icon_height,
- d->icon_width
- );
- }
- ap_rputs("> ", r);
- }
- emit_link(r, "Name", K_NAME, keyid, direction, static_columns);
- ap_rputs(pad_scratch + 4, r);
- /*
- * Emit the guaranteed-at-least-one-space-between-columns byte.
- */
- ap_rputs(" ", r);
- if (!(autoindex_opts & SUPPRESS_LAST_MOD)) {
- emit_link(r, "Last modified", K_LAST_MOD, keyid, direction,
- static_columns);
- ap_rputs(" ", r);
- }
- if (!(autoindex_opts & SUPPRESS_SIZE)) {
- emit_link(r, "Size", K_SIZE, keyid, direction, static_columns);
- ap_rputs(" ", r);
- }
- if (!(autoindex_opts & SUPPRESS_DESC)) {
- emit_link(r, "Description", K_DESC, keyid, direction,
- static_columns);
- }
- ap_rputs("\n<HR>\n", r);
- }
- else {
- ap_rputs("<UL>", r);
- }
-
- for (x = 0; x < n; x++) {
- char *anchor, *t, *t2;
- int nwidth;
-
- apr_pool_clear(scratch);
-
- if (is_parent(ar[x]->name)) {
- t = ap_make_full_path(scratch, name, "../");
- ap_getparents(t);
- if (t[0] == '\0') {
- t = "/";
- }
- t2 = "Parent Directory";
- anchor = ap_escape_html(scratch, ap_os_escape_path(scratch, t, 0));
- }
- else {
- t = ar[x]->name;
- t2 = t;
- anchor = ap_escape_html(scratch, ap_os_escape_path(scratch, t, 0));
- }
-
- if (autoindex_opts & FANCY_INDEXING) {
- if (autoindex_opts & ICONS_ARE_LINKS) {
- ap_rvputs(r, "<A HREF=\"", anchor, "\">", NULL);
- }
- if ((ar[x]->icon) || d->default_icon) {
- ap_rvputs(r, "<IMG SRC=\"",
- ap_escape_html(scratch,
- ar[x]->icon ? ar[x]->icon
- : d->default_icon),
- "\" ALT=\"[", (ar[x]->alt ? ar[x]->alt : " "),
- "]\"", NULL);
- if (d->icon_width && d->icon_height) {
- ap_rprintf(r, " HEIGHT=\"%d\" WIDTH=\"%d\"",
- d->icon_height, d->icon_width);
- }
- ap_rputs(">", r);
- }
- if (autoindex_opts & ICONS_ARE_LINKS) {
- ap_rputs("</A>", r);
- }
-
- nwidth = strlen(t2);
- if (nwidth > name_width) {
- memcpy(name_scratch, t2, name_width - 3);
- name_scratch[name_width - 3] = '.';
- name_scratch[name_width - 2] = '.';
- name_scratch[name_width - 1] = '>';
- name_scratch[name_width] = 0;
- t2 = name_scratch;
- nwidth = name_width;
- }
- ap_rvputs(r, " <A HREF=\"", anchor, "\">",
- ap_escape_html(scratch, t2), "</A>", pad_scratch + nwidth,
- NULL);
- /*
- * The blank before the storm.. er, before the next field.
- */
- ap_rputs(" ", r);
- if (!(autoindex_opts & SUPPRESS_LAST_MOD)) {
- if (ar[x]->lm != -1) {
- char time_str[MAX_STRING_LEN];
- apr_exploded_time_t ts;
- apr_explode_localtime(&ts, ar[x]->lm);
- apr_strftime(time_str, &rv, MAX_STRING_LEN,
- "%d-%b-%Y %H:%M ", &ts);
- ap_rputs(time_str, r);
- }
- else {
- /*Length="22-Feb-1998 23:42 " (see 4 lines above) */
- ap_rputs(" ", r);
- }
- }
- if (!(autoindex_opts & SUPPRESS_SIZE)) {
- ap_send_size(ar[x]->size, r);
- ap_rputs(" ", r);
- }
- if (!(autoindex_opts & SUPPRESS_DESC)) {
- if (ar[x]->desc) {
- ap_rputs(terminate_description(d, ar[x]->desc,
- autoindex_opts), r);
- }
- }
- }
- else {
- ap_rvputs(r, "<LI><A HREF=\"", anchor, "\"> ", t2,
- "</A>", NULL);
- }
- ap_rputc('\n', r);
- }
- if (autoindex_opts & FANCY_INDEXING) {
- ap_rputs("</PRE>", r);
- }
- else {
- ap_rputs("</UL>", r);
- }
-}
-
-/*
- * Compare two file entries according to the sort criteria. The return
- * is essentially a signum function value.
- */
-
-static int dsortf(struct ent **e1, struct ent **e2)
-{
- struct ent *c1;
- struct ent *c2;
- int result = 0;
-
- /*
- * First, see if either of the entries is for the parent directory.
- * If so, that *always* sorts lower than anything else.
- */
- if (is_parent((*e1)->name)) {
- return -1;
- }
- if (is_parent((*e2)->name)) {
- return 1;
- }
- /*
- * All of our comparisons will be of the c1 entry against the c2 one,
- * so assign them appropriately to take care of the ordering.
- */
- if ((*e1)->ascending) {
- c1 = *e1;
- c2 = *e2;
- }
- else {
- c1 = *e2;
- c2 = *e1;
- }
-
- switch (c1->key) {
- case K_LAST_MOD:
- if (c1->lm > c2->lm) {
- return 1;
- }
- else if (c1->lm < c2->lm) {
- return -1;
- }
- break;
- case K_SIZE:
- if (c1->size > c2->size) {
- return 1;
- }
- else if (c1->size < c2->size) {
- return -1;
- }
- break;
- case K_DESC:
- if (c1->version_sort)
- result = apr_strnatcmp(c1->desc ? c1->desc : "", c2->desc ? c2->desc : "");
- else
- result = strcmp(c1->desc ? c1->desc : "", c2->desc ? c2->desc : "");
- if (result) {
- return result;
- }
- break;
- }
- if (c1->version_sort)
- return apr_strnatcmp(c1->name, c2->name);
- else
- return strcmp(c1->name, c2->name);
-}
-
-
-static int index_directory(request_rec *r,
- autoindex_config_rec *autoindex_conf)
-{
- char *title_name = ap_escape_html(r->pool, r->uri);
- char *title_endp;
- char *name = r->filename;
- apr_finfo_t dirent;
- apr_dir_t *thedir;
- apr_status_t status;
- int num_ent = 0, x;
- struct ent *head, *p;
- struct ent **ar = NULL;
- const char *qstring;
- int autoindex_opts = autoindex_conf->opts;
- char keyid;
- char direction;
-
- if ((status = apr_dir_open(&thedir, name, r->pool)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
- "Can't open directory for index: %s", r->filename);
- return HTTP_FORBIDDEN;
- }
-
-#if APR_HAS_UNICODE_FS
- r->content_type = "text/html;charset=utf-8";
-#else
- r->content_type = "text/html";
-#endif
- ap_update_mtime(r, r->finfo.mtime);
- ap_set_last_modified(r);
- ap_set_etag(r);
-
- if (r->header_only) {
- apr_dir_close(thedir);
- return 0;
- }
-
- /* Spew HTML preamble */
-
- title_endp = title_name + strlen(title_name) - 1;
-
- while (title_endp > title_name && *title_endp == '/') {
- *title_endp-- = '\0';
- }
-
- emit_head(r, find_header(autoindex_conf, r),
- autoindex_opts & SUPPRESS_PREAMBLE, title_name);
-
- /*
- * Figure out what sort of indexing (if any) we're supposed to use.
- *
- * If no QUERY_STRING was specified or column sorting has been
- * explicitly disabled, we use the default specified by the
- * IndexOrderDefault directive (if there is one); otherwise,
- * we fall back to ascending by name.
- */
- qstring = r->args;
- if ((autoindex_opts & SUPPRESS_COLSORT)
- || ((qstring == NULL) || (*qstring == '\0'))) {
- qstring = autoindex_conf->default_order;
- }
- /*
- * If there is no specific ordering defined for this directory,
- * default to ascending by filename.
- */
- if ((qstring == NULL) || (*qstring == '\0')) {
- keyid = K_NAME;
- direction = D_ASCENDING;
- }
- else {
- keyid = *qstring;
- ap_getword(r->pool, &qstring, '=');
- if (qstring != '\0') {
- direction = *qstring;
- }
- else {
- direction = D_ASCENDING;
- }
- }
-
- /*
- * Since we don't know how many dir. entries there are, put them into a
- * linked list and then arrayificate them so qsort can use them.
- */
- head = NULL;
- while (apr_dir_read(&dirent, APR_FINFO_DIRENT, thedir) == APR_SUCCESS) {
- p = make_autoindex_entry(dirent.name, autoindex_opts,
- autoindex_conf, r, keyid, direction);
- if (p != NULL) {
- p->next = head;
- head = p;
- num_ent++;
- }
- }
- if (num_ent > 0) {
- ar = (struct ent **) apr_palloc(r->pool,
- num_ent * sizeof(struct ent *));
- p = head;
- x = 0;
- while (p) {
- ar[x++] = p;
- p = p->next;
- }
-
- qsort((void *) ar, num_ent, sizeof(struct ent *),
- (int (*)(const void *, const void *)) dsortf);
- }
- output_directories(ar, num_ent, autoindex_conf, r, autoindex_opts, keyid,
- direction);
- apr_dir_close(thedir);
-
- if (autoindex_opts & FANCY_INDEXING) {
- ap_rputs("<HR>\n", r);
- }
- emit_tail(r, find_readme(autoindex_conf, r),
- autoindex_opts & SUPPRESS_PREAMBLE);
-
- return 0;
-}
-
-/* The formal handler... */
-
-static int handle_autoindex(request_rec *r)
-{
- autoindex_config_rec *d;
- int allow_opts;
-
- if(strcmp(r->handler,DIR_MAGIC_TYPE))
- return DECLINED;
-
- allow_opts = ap_allow_options(r);
-
- d = (autoindex_config_rec *) ap_get_module_config(r->per_dir_config,
- &autoindex_module);
-
- r->allowed |= (1 << M_GET);
- if (r->method_number != M_GET) {
- return DECLINED;
- }
-
- /* OK, nothing easy. Trot out the heavy artillery... */
-
- if (allow_opts & OPT_INDEXES) {
- /* KLUDGE --- make the sub_req lookups happen in the right directory.
- * Fixing this in the sub_req_lookup functions themselves is difficult,
- * and would probably break virtual includes...
- */
-
- if (r->filename[strlen(r->filename) - 1] != '/') {
- r->filename = apr_pstrcat(r->pool, r->filename, "/", NULL);
- }
- return index_directory(r, d);
- }
- else {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Directory index forbidden by rule: %s", r->filename);
- return HTTP_FORBIDDEN;
- }
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_handler(handle_autoindex,NULL,NULL,APR_HOOK_MIDDLE);
-}
-
-module AP_MODULE_DECLARE_DATA autoindex_module =
-{
- STANDARD20_MODULE_STUFF,
- create_autoindex_config, /* dir config creater */
- merge_autoindex_configs, /* dir merger --- default is to override */
- NULL, /* server config */
- NULL, /* merge server config */
- autoindex_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
diff --git a/modules/generators/mod_autoindex.exp b/modules/generators/mod_autoindex.exp
deleted file mode 100644
index 90f4057e9c..0000000000
--- a/modules/generators/mod_autoindex.exp
+++ /dev/null
@@ -1 +0,0 @@
-autoindex_module
diff --git a/modules/generators/mod_cgi.c b/modules/generators/mod_cgi.c
deleted file mode 100644
index 3431936985..0000000000
--- a/modules/generators/mod_cgi.c
+++ /dev/null
@@ -1,1005 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * http_script: keeps all script-related ramblings together.
- *
- * Compliant to CGI/1.1 spec
- *
- * Adapted by rst from original NCSA code by Rob McCool
- *
- * Apache adds some new env vars; REDIRECT_URL and REDIRECT_QUERY_STRING for
- * custom error responses, and DOCUMENT_ROOT because we found it useful.
- * It also adds SERVER_ADMIN - useful for scripts to know who to mail when
- * they fail.
- */
-
-#include "apr.h"
-#include "apr_strings.h"
-#include "apr_thread_proc.h" /* for RLIMIT stuff */
-#include "apr_optional.h"
-#include "apr_buckets.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#define CORE_PRIVATE
-
-#include "util_filter.h"
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_request.h"
-#include "http_core.h"
-#include "http_protocol.h"
-#include "http_main.h"
-#include "http_log.h"
-#include "util_script.h"
-#include "ap_mpm.h"
-#include "mod_core.h"
-#include "../filters/mod_include.h"
-
-
-module AP_MODULE_DECLARE_DATA cgi_module;
-
-static APR_OPTIONAL_FN_TYPE(ap_register_include_handler) *cgi_pfn_reg_with_ssi;
-static APR_OPTIONAL_FN_TYPE(ap_ssi_get_tag_and_value) *cgi_pfn_gtv;
-static APR_OPTIONAL_FN_TYPE(ap_ssi_parse_string) *cgi_pfn_ps;
-
-typedef enum {RUN_AS_SSI, RUN_AS_CGI} prog_types;
-
-typedef struct {
- apr_int32_t in_pipe;
- apr_int32_t out_pipe;
- apr_int32_t err_pipe;
- apr_cmdtype_e cmd_type;
- prog_types prog_type;
- apr_bucket_brigade **bb;
- include_ctx_t *ctx;
- ap_filter_t *next;
-} exec_info;
-
-/* KLUDGE --- for back-combatibility, we don't have to check ExecCGI
- * in ScriptAliased directories, which means we need to know if this
- * request came through ScriptAlias or not... so the Alias module
- * leaves a note for us.
- */
-
-static int is_scriptaliased(request_rec *r)
-{
- const char *t = apr_table_get(r->notes, "alias-forced-type");
- return t && (!strcasecmp(t, "cgi-script"));
-}
-
-/* Configuration stuff */
-
-#define DEFAULT_LOGBYTES 10385760
-#define DEFAULT_BUFBYTES 1024
-
-typedef struct {
- const char *logname;
- long logbytes;
- int bufbytes;
-} cgi_server_conf;
-
-static void *create_cgi_config(apr_pool_t *p, server_rec *s)
-{
- cgi_server_conf *c =
- (cgi_server_conf *) apr_pcalloc(p, sizeof(cgi_server_conf));
-
- c->logname = NULL;
- c->logbytes = DEFAULT_LOGBYTES;
- c->bufbytes = DEFAULT_BUFBYTES;
-
- return c;
-}
-
-static void *merge_cgi_config(apr_pool_t *p, void *basev, void *overridesv)
-{
- cgi_server_conf *base = (cgi_server_conf *) basev, *overrides = (cgi_server_conf *) overridesv;
-
- return overrides->logname ? overrides : base;
-}
-
-static const char *set_scriptlog(cmd_parms *cmd, void *dummy, const char *arg)
-{
- server_rec *s = cmd->server;
- cgi_server_conf *conf = ap_get_module_config(s->module_config,
- &cgi_module);
-
- conf->logname = arg;
- return NULL;
-}
-
-static const char *set_scriptlog_length(cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- server_rec *s = cmd->server;
- cgi_server_conf *conf = ap_get_module_config(s->module_config,
- &cgi_module);
-
- conf->logbytes = atol(arg);
- return NULL;
-}
-
-static const char *set_scriptlog_buffer(cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- server_rec *s = cmd->server;
- cgi_server_conf *conf = ap_get_module_config(s->module_config,
- &cgi_module);
-
- conf->bufbytes = atoi(arg);
- return NULL;
-}
-
-static const command_rec cgi_cmds[] =
-{
-AP_INIT_TAKE1("ScriptLog", set_scriptlog, NULL, RSRC_CONF,
- "the name of a log for script debugging info"),
-AP_INIT_TAKE1("ScriptLogLength", set_scriptlog_length, NULL, RSRC_CONF,
- "the maximum length (in bytes) of the script debug log"),
-AP_INIT_TAKE1("ScriptLogBuffer", set_scriptlog_buffer, NULL, RSRC_CONF,
- "the maximum size (in bytes) to record of a POST request"),
- {NULL}
-};
-
-static int log_scripterror(request_rec *r, cgi_server_conf * conf, int ret,
- apr_status_t rv, char *error)
-{
- apr_file_t *f = NULL;
- apr_finfo_t finfo;
- char time_str[APR_CTIME_LEN];
- int log_flags = rv ? APLOG_ERR : APLOG_NOERRNO | APLOG_ERR;
-
- ap_log_rerror(APLOG_MARK, log_flags, rv, r,
- "%s: %s", error, r->filename);
-
- if (!conf->logname ||
- ((apr_stat(&finfo, ap_server_root_relative(r->pool, conf->logname),
- APR_FINFO_SIZE, r->pool) == APR_SUCCESS)
- && (finfo.size > conf->logbytes)) ||
- (apr_file_open(&f, ap_server_root_relative(r->pool, conf->logname),
- APR_APPEND|APR_WRITE|APR_CREATE, APR_OS_DEFAULT, r->pool)
- != APR_SUCCESS)) {
- return ret;
- }
-
- /* "%% [Wed Jun 19 10:53:21 1996] GET /cgi-bin/printenv HTTP/1.0" */
- apr_ctime(time_str, apr_time_now());
- apr_file_printf(f, "%%%% [%s] %s %s%s%s %s\n", time_str, r->method, r->uri,
- r->args ? "?" : "", r->args ? r->args : "", r->protocol);
- /* "%% 500 /usr/local/apache/cgi-bin */
- apr_file_printf(f, "%%%% %d %s\n", ret, r->filename);
-
- apr_file_printf(f, "%%error\n%s\n", error);
-
- apr_file_close(f);
- return ret;
-}
-
-/* Soak up stderr from a script and redirect it to the error log.
- */
-static void log_script_err(request_rec *r, apr_file_t *script_err)
-{
- char argsbuffer[HUGE_STRING_LEN];
- char *newline;
-
- while (apr_file_gets(argsbuffer, HUGE_STRING_LEN, script_err) == 0) {
- newline = strchr(argsbuffer, '\n');
- if (newline) {
- *newline = '\0';
- }
- ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
- "%s", argsbuffer);
- }
-}
-
-static int log_script(request_rec *r, cgi_server_conf * conf, int ret,
- char *dbuf, const char *sbuf, apr_file_t *script_in,
- apr_file_t *script_err)
-{
- apr_array_header_t *hdrs_arr = apr_table_elts(r->headers_in);
- apr_table_entry_t *hdrs = (apr_table_entry_t *) hdrs_arr->elts;
- char argsbuffer[HUGE_STRING_LEN];
- apr_file_t *f = NULL;
- int i;
- apr_finfo_t finfo;
- char time_str[APR_CTIME_LEN];
-
- if (!conf->logname ||
- ((apr_stat(&finfo, ap_server_root_relative(r->pool, conf->logname),
- APR_FINFO_SIZE, r->pool) == APR_SUCCESS)
- && (finfo.size > conf->logbytes)) ||
- (apr_file_open(&f, ap_server_root_relative(r->pool, conf->logname),
- APR_APPEND|APR_WRITE|APR_CREATE, APR_OS_DEFAULT, r->pool) != APR_SUCCESS)) {
- /* Soak up script output */
- while (apr_file_gets(argsbuffer, HUGE_STRING_LEN, script_in) == 0)
- continue;
-
- log_script_err(r, script_err);
- return ret;
- }
-
- /* "%% [Wed Jun 19 10:53:21 1996] GET /cgi-bin/printenv HTTP/1.0" */
- apr_ctime(time_str, apr_time_now());
- apr_file_printf(f, "%%%% [%s] %s %s%s%s %s\n", time_str, r->method, r->uri,
- r->args ? "?" : "", r->args ? r->args : "", r->protocol);
- /* "%% 500 /usr/local/apache/cgi-bin" */
- apr_file_printf(f, "%%%% %d %s\n", ret, r->filename);
-
- apr_file_puts("%request\n", f);
- for (i = 0; i < hdrs_arr->nelts; ++i) {
- if (!hdrs[i].key)
- continue;
- apr_file_printf(f, "%s: %s\n", hdrs[i].key, hdrs[i].val);
- }
- if ((r->method_number == M_POST || r->method_number == M_PUT)
- && *dbuf) {
- apr_file_printf(f, "\n%s\n", dbuf);
- }
-
- apr_file_puts("%response\n", f);
- hdrs_arr = apr_table_elts(r->err_headers_out);
- hdrs = (apr_table_entry_t *) hdrs_arr->elts;
-
- for (i = 0; i < hdrs_arr->nelts; ++i) {
- if (!hdrs[i].key)
- continue;
- apr_file_printf(f, "%s: %s\n", hdrs[i].key, hdrs[i].val);
- }
-
- if (sbuf && *sbuf)
- apr_file_printf(f, "%s\n", sbuf);
-
- if (apr_file_gets(argsbuffer, HUGE_STRING_LEN, script_in) == 0) {
- apr_file_puts("%stdout\n", f);
- apr_file_puts(argsbuffer, f);
- while (apr_file_gets(argsbuffer, HUGE_STRING_LEN, script_in) == 0)
- apr_file_puts(argsbuffer, f);
- apr_file_puts("\n", f);
- }
-
- if (apr_file_gets(argsbuffer, HUGE_STRING_LEN, script_err) == 0) {
- apr_file_puts("%stderr\n", f);
- apr_file_puts(argsbuffer, f);
- while (apr_file_gets(argsbuffer, HUGE_STRING_LEN, script_err) == 0)
- apr_file_puts(argsbuffer, f);
- apr_file_puts("\n", f);
- }
-
- apr_file_close(script_in);
- apr_file_close(script_err);
-
- apr_file_close(f);
- return ret;
-}
-
-
-/* This is the special environment used for running the "exec cmd="
- * variety of SSI directives.
- */
-static void add_ssi_vars(request_rec *r, ap_filter_t *next)
-{
- apr_table_t *e = r->subprocess_env;
-
- if (r->path_info && r->path_info[0] != '\0') {
- request_rec *pa_req;
-
- apr_table_setn(e, "PATH_INFO", ap_escape_shell_cmd(r->pool, r->path_info));
-
- pa_req = ap_sub_req_lookup_uri(ap_escape_uri(r->pool, r->path_info), r, next);
- if (pa_req->filename) {
- apr_table_setn(e, "PATH_TRANSLATED",
- apr_pstrcat(r->pool, pa_req->filename, pa_req->path_info, NULL));
- }
- }
-
- if (r->args) {
- char *arg_copy = apr_pstrdup(r->pool, r->args);
-
- apr_table_setn(e, "QUERY_STRING", r->args);
- ap_unescape_url(arg_copy);
- apr_table_setn(e, "QUERY_STRING_UNESCAPED", ap_escape_shell_cmd(r->pool, arg_copy));
- }
-}
-
-static apr_status_t run_cgi_child(apr_file_t **script_out,
- apr_file_t **script_in,
- apr_file_t **script_err,
- const char *command,
- const char * const argv[],
- request_rec *r,
- apr_pool_t *p,
- exec_info *e_info)
-{
- const char * const *env;
- apr_procattr_t *procattr;
- apr_proc_t *procnew;
- apr_status_t rc = APR_SUCCESS;
-
-#if defined(RLIMIT_CPU) || defined(RLIMIT_NPROC) || \
- defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined (RLIMIT_AS)
-
- core_dir_config *conf = ap_get_module_config(r->per_dir_config,
- &core_module);
-#endif
-
-
-#ifdef DEBUG_CGI
-#ifdef OS2
- /* Under OS/2 need to use device con. */
- FILE *dbg = fopen("con", "w");
-#else
- FILE *dbg = fopen("/dev/tty", "w");
-#endif
- int i;
-#endif
-
- RAISE_SIGSTOP(CGI_CHILD);
-#ifdef DEBUG_CGI
- fprintf(dbg, "Attempting to exec %s as %sCGI child (argv0 = %s)\n",
- r->filename, cld->nph ? "NPH " : "", argv0);
-#endif
-
- if (e_info->prog_type == RUN_AS_CGI) {
- ap_add_cgi_vars(r);
- }
- else /* SSIs want a controlled environment and a special path. */
- {
- add_ssi_vars(r, e_info->next);
- }
- env = (const char * const *)ap_create_environment(p, r->subprocess_env);
-
-#ifdef DEBUG_CGI
- fprintf(dbg, "Environment: \n");
- for (i = 0; env[i]; ++i)
- fprintf(dbg, "'%s'\n", env[i]);
-#endif
-
- /* Transmute ourselves into the script.
- * NB only ISINDEX scripts get decoded arguments.
- */
- if (((rc = apr_procattr_create(&procattr, p)) != APR_SUCCESS) ||
- ((rc = apr_procattr_io_set(procattr,
- e_info->in_pipe,
- e_info->out_pipe,
- e_info->err_pipe)) != APR_SUCCESS) ||
- ((rc = apr_procattr_dir_set(procattr,
- ap_make_dirstr_parent(r->pool, r->filename))) != APR_SUCCESS) ||
-#ifdef RLIMIT_CPU
- ((rc = apr_procattr_limit_set(procattr, APR_LIMIT_CPU, conf->limit_cpu)) != APR_SUCCESS) ||
-#endif
-#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
- ((rc = apr_procattr_limit_set(procattr, APR_LIMIT_MEM, conf->limit_mem)) != APR_SUCCESS) ||
-#endif
-#ifdef RLIMIT_NPROC
- ((rc = apr_procattr_limit_set(procattr, APR_LIMIT_NPROC, conf->limit_nproc)) != APR_SUCCESS) ||
-#endif
- ((rc = apr_procattr_cmdtype_set(procattr, e_info->cmd_type)) != APR_SUCCESS)) {
- /* Something bad happened, tell the world. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r,
- "couldn't set child process attributes: %s", r->filename);
- }
- else {
- procnew = apr_pcalloc(p, sizeof(*procnew));
- if (e_info->prog_type == RUN_AS_SSI) {
- SPLIT_AND_PASS_PRETAG_BUCKETS(*(e_info->bb), e_info->ctx, e_info->next);
- }
-
- rc = ap_os_create_privileged_process(r, procnew, command, argv, env, procattr, p);
-
- if (rc != APR_SUCCESS) {
- /* Bad things happened. Everyone should have cleaned up. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r,
- "couldn't create child process: %d: %s", rc, r->filename);
- }
- else {
- apr_pool_note_subprocess(p, procnew, kill_after_timeout);
-
- *script_in = procnew->out;
- if (!script_in)
- return APR_EBADF;
- apr_file_pipe_timeout_set(*script_in, (int)(r->server->timeout * APR_USEC_PER_SEC));
-
- if (e_info->prog_type == RUN_AS_CGI) {
- *script_out = procnew->in;
- if (!*script_out)
- return APR_EBADF;
- apr_file_pipe_timeout_set(*script_out, (int)(r->server->timeout * APR_USEC_PER_SEC));
-
- *script_err = procnew->err;
- if (!*script_err)
- return APR_EBADF;
- apr_file_pipe_timeout_set(*script_err, (int)(r->server->timeout * APR_USEC_PER_SEC));
- }
- }
- }
- return (rc);
-}
-
-static apr_status_t build_argv_list(const char ***argv, request_rec *r,
- apr_pool_t *p)
-{
- int numwords, x, idx;
- char *w;
- const char *args = r->args;
-
- if (!args || !args[0] || ap_strchr_c(args, '=')) {
- numwords = 1;
- }
- else {
- /* count the number of keywords */
- for (x = 0, numwords = 2; args[x]; x++) {
- if (args[x] == '+') {
- ++numwords;
- }
- }
- }
- /* Everything is - 1 to account for the first parameter which is the
- * program name. We didn't used to have to do this, but APR wants it.
- */
- if (numwords > APACHE_ARG_MAX - 1) {
- numwords = APACHE_ARG_MAX - 1; /* Truncate args to prevent overrun */
- }
- *argv = apr_palloc(p, (numwords + 2) * sizeof(char *));
-
- for (x = 1, idx = 1; x < numwords; x++) {
- w = ap_getword_nulls(p, &args, '+');
- ap_unescape_url(w);
- (*argv)[idx++] = ap_escape_shell_cmd(p, w);
- }
- (*argv)[idx] = NULL;
-
- return APR_SUCCESS;
-}
-
-static apr_status_t build_command_line(const char **cmd, request_rec *r,
- apr_pool_t *p)
-{
-#ifdef WIN32
- char *quoted_filename = NULL;
- char *interpreter = NULL;
- char *arguments = NULL;
- file_type_e fileType;
-#endif
- const char *argv0;
-
- /* Allow suexec's "/" check to succeed */
- if ((argv0 = strrchr(r->filename, '/')) != NULL)
- argv0++;
- else
- argv0 = r->filename;
-
-#ifdef WIN32
- *cmd = NULL;
- fileType = ap_get_win32_interpreter(r, &interpreter, &arguments);
-
- if (fileType == eFileTypeUNKNOWN) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
- "%s is not executable; ensure interpreted scripts have "
- "\"#!\" first line",
- r->filename);
- return APR_EBADF;
- }
-
- /*
- * Build the command string to pass to ap_os_create_privileged_process()
- */
- quoted_filename = apr_pstrcat(p, "\"", r->filename, "\"", NULL);
- if (interpreter && *interpreter) {
- if (arguments && *arguments)
- *cmd = apr_pstrcat(p, interpreter, " ", quoted_filename, " ",
- arguments, NULL);
- else
- *cmd = apr_pstrcat(p, interpreter, " ", quoted_filename, " ", NULL);
- }
- else if (arguments && *arguments) {
- *cmd = apr_pstrcat(p, quoted_filename, " ", arguments, NULL);
- }
- else {
- *cmd = apr_pstrcat(p, quoted_filename, NULL);
- }
-#else
- *cmd = argv0;
-#endif
- return APR_SUCCESS;
-}
-
-static int cgi_handler(request_rec *r)
-{
- int retval, nph, dbpos = 0;
- const char *argv0;
- const char *command;
- const char **argv;
- char *dbuf = NULL;
- apr_file_t *script_out = NULL, *script_in = NULL, *script_err = NULL;
- apr_bucket_brigade *bb;
- apr_bucket *b;
- char argsbuffer[HUGE_STRING_LEN];
- int is_included = !strcmp(r->protocol, "INCLUDED");
- apr_pool_t *p;
- cgi_server_conf *conf;
- apr_status_t rv;
- exec_info e_info;
-
- if(strcmp(r->handler,CGI_MAGIC_TYPE) && strcmp(r->handler,"cgi-script"))
- return DECLINED;
-
- p = r->main ? r->main->pool : r->pool;
-
- if (r->method_number == M_OPTIONS) {
- /* 99 out of 100 CGI scripts, this is all they support */
- r->allowed |= (1 << M_GET);
- r->allowed |= (1 << M_POST);
- return DECLINED;
- }
-
- if ((argv0 = strrchr(r->filename, '/')) != NULL)
- argv0++;
- else
- argv0 = r->filename;
-
- nph = !(strncmp(argv0, "nph-", 4));
- conf = ap_get_module_config(r->server->module_config, &cgi_module);
-
- if (!(ap_allow_options(r) & OPT_EXECCGI) && !is_scriptaliased(r))
- return log_scripterror(r, conf, HTTP_FORBIDDEN, 0,
- "Options ExecCGI is off in this directory");
- if (nph && is_included)
- return log_scripterror(r, conf, HTTP_FORBIDDEN, 0,
- "attempt to include NPH CGI script");
-
-#if defined(OS2) || defined(WIN32)
- /* XXX: This is wrong. As an option, perhaps, but not by default...
- * we are back to the same argument that a url should be a unique
- * entity until the sysadmin overrides that behavior.
- * Allow for cgi files without the .EXE extension on them under OS/2
- */
- if (r->finfo.filetype == 0) {
- apr_finfo_t finfo;
- char *newfile;
- apr_status_t rv;
-
- newfile = apr_pstrcat(r->pool, r->filename, ".EXE", NULL);
- if (((rv = apr_stat(&finfo, newfile, APR_FINFO_TYPE, r->pool))
- != APR_SUCCESS) || (finfo.filetype != APR_REG)) {
- return log_scripterror(r, conf, HTTP_NOT_FOUND, rv,
- "script not found or unable to stat");
- } else {
- r->filename = newfile;
- }
- }
-#else
- if (r->finfo.filetype == 0)
- return log_scripterror(r, conf, HTTP_NOT_FOUND, 0,
- "script not found or unable to stat");
-#endif
- if (r->finfo.filetype == APR_DIR)
- return log_scripterror(r, conf, HTTP_FORBIDDEN, 0,
- "attempt to invoke directory as script");
-
-/*
- if (!ap_suexec_enabled) {
- if (!ap_can_exec(&r->finfo))
- return log_scripterror(r, conf, HTTP_FORBIDDEN, 0,
- "file permissions deny server execution");
- }
-
-*/
- if ((retval = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)))
- return retval;
-
- ap_add_common_vars(r);
-
- /* build the command line */
- if ((rv = build_command_line(&command, r, p)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "couldn't spawn child process: %s", r->filename);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
- /* build the argument list */
- else if ((rv = build_argv_list(&argv, r, p)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "couldn't spawn child process: %s", r->filename);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
- argv[0] = apr_pstrdup(p, command);
-
- e_info.cmd_type = APR_PROGRAM;
- e_info.in_pipe = APR_CHILD_BLOCK;
- e_info.out_pipe = APR_CHILD_BLOCK;
- e_info.err_pipe = APR_CHILD_BLOCK;
- e_info.prog_type = RUN_AS_CGI;
- e_info.bb = NULL;
- e_info.ctx = NULL;
- e_info.next = NULL;
-
- /* run the script in its own process */
- if ((rv = run_cgi_child(&script_out, &script_in, &script_err,
- command, argv, r, p, &e_info)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "couldn't spawn child process: %s", r->filename);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- /* Transfer any put/post args, CERN style...
- * Note that we already ignore SIGPIPE in the core server.
- */
- if (ap_should_client_block(r)) {
- int dbsize, len_read;
- apr_size_t bytes_written, bytes_to_write;
- apr_status_t rv;
-
- if (conf->logname) {
- dbuf = apr_pcalloc(r->pool, conf->bufbytes + 1);
- dbpos = 0;
- }
-
- while ((len_read =
- ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN)) > 0) {
- if (conf->logname) {
- if ((dbpos + len_read) > conf->bufbytes) {
- dbsize = conf->bufbytes - dbpos;
- }
- else {
- dbsize = len_read;
- }
- memcpy(dbuf + dbpos, argsbuffer, dbsize);
- dbpos += dbsize;
- }
- /* Keep writing data to the child until done or too much time
- * elapses with no progress or an error occurs.
- */
- bytes_written = 0;
- do {
- bytes_to_write = len_read - bytes_written;
- rv = apr_file_write(script_out, argsbuffer + bytes_written,
- &bytes_to_write);
- bytes_written += bytes_to_write;
- } while (rv == APR_SUCCESS && bytes_written < len_read);
- if (rv != APR_SUCCESS || bytes_written < len_read) {
- /* silly script stopped reading, soak up remaining message */
- while (ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN) > 0) {
- /* dump it */
- }
- break;
- }
- }
- apr_file_flush(script_out);
- }
-
- apr_file_close(script_out);
-
- /* Handle script return... */
- if (script_in && !nph) {
- const char *location;
- char sbuf[MAX_STRING_LEN];
- int ret;
-
- if ((ret = ap_scan_script_header_err(r, script_in, sbuf))) {
- return log_script(r, conf, ret, dbuf, sbuf, script_in, script_err);
- }
-
- location = apr_table_get(r->headers_out, "Location");
-
- if (location && location[0] == '/' && r->status == 200) {
-
- /* Soak up all the script output */
- while (apr_file_gets(argsbuffer, HUGE_STRING_LEN, script_in) == 0) {
- continue;
- }
- log_script_err(r, script_err);
- /* This redirect needs to be a GET no matter what the original
- * method was.
- */
- r->method = apr_pstrdup(r->pool, "GET");
- r->method_number = M_GET;
-
- /* We already read the message body (if any), so don't allow
- * the redirected request to think it has one. We can ignore
- * Transfer-Encoding, since we used REQUEST_CHUNKED_ERROR.
- */
- apr_table_unset(r->headers_in, "Content-Length");
-
- ap_internal_redirect_handler(location, r);
- return OK;
- }
- else if (location && r->status == 200) {
- /* XX Note that if a script wants to produce its own Redirect
- * body, it now has to explicitly *say* "Status: 302"
- */
- return HTTP_MOVED_TEMPORARILY;
- }
-
- if (!r->header_only) {
- bb = apr_brigade_create(r->pool);
- b = apr_bucket_pipe_create(script_in);
- APR_BRIGADE_INSERT_TAIL(bb, b);
- b = apr_bucket_eos_create();
- APR_BRIGADE_INSERT_TAIL(bb, b);
- ap_pass_brigade(r->output_filters, bb);
- }
-
- log_script_err(r, script_err);
- apr_file_close(script_err);
- }
-
- if (script_in && nph) {
- bb = apr_brigade_create(r->pool);
- b = apr_bucket_pipe_create(script_in);
- APR_BRIGADE_INSERT_TAIL(bb, b);
- b = apr_bucket_eos_create();
- APR_BRIGADE_INSERT_TAIL(bb, b);
- ap_pass_brigade(r->output_filters, bb);
- }
-
- return OK; /* NOT r->status, even if it has changed. */
-}
-
-/*============================================================================
- *============================================================================
- * This is the beginning of the cgi filter code moved from mod_include. This
- * is the code required to handle the "exec" SSI directive.
- *============================================================================
- *============================================================================*/
-static int include_cgi(char *s, request_rec *r, ap_filter_t *next,
- apr_bucket *head_ptr, apr_bucket **inserted_head)
-{
- request_rec *rr = ap_sub_req_lookup_uri(s, r, next);
- int rr_status;
- apr_bucket *tmp_buck, *tmp2_buck;
-
- if (rr->status != HTTP_OK) {
- return -1;
- }
-
- /* No hardwired path info or query allowed */
-
- if ((rr->path_info && rr->path_info[0]) || rr->args) {
- return -1;
- }
- if (rr->finfo.protection == 0) {
- return -1;
- }
-
- /* Script gets parameters of the *document*, for back compatibility */
-
- rr->path_info = r->path_info; /* hard to get right; see mod_cgi.c */
- rr->args = r->args;
-
- /* Force sub_req to be treated as a CGI request, even if ordinary
- * typing rules would have called it something else.
- */
-
- rr->content_type = CGI_MAGIC_TYPE;
-
- /* Run it. */
-
- rr_status = ap_run_sub_req(rr);
- if (ap_is_HTTP_REDIRECT(rr_status)) {
- apr_size_t len_loc, h_wrt;
- const char *location = apr_table_get(rr->headers_out, "Location");
-
- location = ap_escape_html(rr->pool, location);
- len_loc = strlen(location);
-
- tmp_buck = apr_bucket_immortal_create("<A HREF=\"", sizeof("<A HREF=\""));
- APR_BUCKET_INSERT_BEFORE(head_ptr, tmp_buck);
- tmp2_buck = apr_bucket_heap_create(location, len_loc, 1, &h_wrt);
- APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
- tmp2_buck = apr_bucket_immortal_create("\">", sizeof("\">"));
- APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
- tmp2_buck = apr_bucket_heap_create(location, len_loc, 1, &h_wrt);
- APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
- tmp2_buck = apr_bucket_immortal_create("</A>", sizeof("</A>"));
- APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
-
- if (*inserted_head == NULL) {
- *inserted_head = tmp_buck;
- }
- }
-
- ap_destroy_sub_req(rr);
-
- return 0;
-}
-
-
-static int include_cmd(include_ctx_t *ctx, apr_bucket_brigade **bb, char *command,
- request_rec *r, ap_filter_t *f)
-{
- exec_info e_info;
- const char **argv;
- apr_file_t *script_out = NULL, *script_in = NULL, *script_err = NULL;
- apr_bucket_brigade *bcgi;
- apr_bucket *b;
-
- if (build_argv_list(&argv, r, r->pool) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r,
- "couldn't spawn cmd child process: %s", r->filename);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
- argv[0] = apr_pstrdup(r->pool, command);
-
- e_info.cmd_type = APR_SHELLCMD;
- e_info.in_pipe = APR_NO_PIPE;
- e_info.out_pipe = APR_FULL_BLOCK;
- e_info.err_pipe = APR_NO_PIPE;
- e_info.prog_type = RUN_AS_SSI;
- e_info.bb = bb;
- e_info.ctx = ctx;
- e_info.next = f->next;
-
- /* run the script in its own process */
- if (run_cgi_child(&script_out, &script_in, &script_err,
- command, argv, r, r->pool, &e_info) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r,
- "couldn't spawn child process: %s", r->filename);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- bcgi = apr_brigade_create(r->pool);
- b = apr_bucket_pipe_create(script_in);
- APR_BRIGADE_INSERT_TAIL(bcgi, b);
- ap_pass_brigade(f->next, bcgi);
-
- /* We can't close the pipe here, because we may return before the
- * full CGI has been sent to the network. That's okay though,
- * because we can rely on the pool to close the pipe for us.
- */
-
- return 0;
-}
-
-static int handle_exec(include_ctx_t *ctx, apr_bucket_brigade **bb, request_rec *r,
- ap_filter_t *f, apr_bucket *head_ptr, apr_bucket **inserted_head)
-{
- char *tag = NULL;
- char *tag_val = NULL;
- char *file = r->filename;
- apr_bucket *tmp_buck;
- char parsed_string[MAX_STRING_LEN];
-
- *inserted_head = NULL;
- if (ctx->flags & FLAG_PRINTING) {
- if (ctx->flags & FLAG_NO_EXEC) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "exec used but not allowed in %s", r->filename);
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- }
- else {
- while (1) {
- cgi_pfn_gtv(ctx, &tag, &tag_val, 1);
- if (tag_val == NULL) {
- if (tag == NULL) {
- return (0);
- }
- else {
- return 1;
- }
- }
- if (!strcmp(tag, "cmd")) {
- cgi_pfn_ps(r, tag_val, parsed_string, sizeof(parsed_string), 1);
- if (include_cmd(ctx, bb, parsed_string, r, f) == -1) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "execution failure for parameter \"%s\" "
- "to tag exec in file %s", tag, r->filename);
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- }
- }
- else if (!strcmp(tag, "cgi")) {
- cgi_pfn_ps(r, tag_val, parsed_string, sizeof(parsed_string), 0);
- SPLIT_AND_PASS_PRETAG_BUCKETS(*bb, ctx, f->next);
- if (include_cgi(parsed_string, r, f->next, head_ptr, inserted_head) == -1) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "invalid CGI ref \"%s\" in %s", tag_val, file);
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- }
- }
- else {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "unknown parameter \"%s\" to tag exec in %s", tag, file);
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- }
- }
- }
- }
- return 0;
-}
-
-
-/*============================================================================
- *============================================================================
- * This is the end of the cgi filter code moved from mod_include.
- *============================================================================
- *============================================================================*/
-
-
-static void cgi_post_config(apr_pool_t *p, apr_pool_t *plog,
- apr_pool_t *ptemp, server_rec *s)
-{
- cgi_pfn_reg_with_ssi = APR_RETRIEVE_OPTIONAL_FN(ap_register_include_handler);
- cgi_pfn_gtv = APR_RETRIEVE_OPTIONAL_FN(ap_ssi_get_tag_and_value);
- cgi_pfn_ps = APR_RETRIEVE_OPTIONAL_FN(ap_ssi_parse_string);
-
- if ((cgi_pfn_reg_with_ssi) && (cgi_pfn_gtv) && (cgi_pfn_ps)) {
- /* Required by mod_include filter. This is how mod_cgi registers
- * with mod_include to provide processing of the exec directive.
- */
- cgi_pfn_reg_with_ssi("exec", handle_exec);
- }
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- static const char * const aszPre[] = { "mod_include.c", NULL };
- ap_hook_handler(cgi_handler, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_post_config(cgi_post_config, aszPre, NULL, APR_HOOK_REALLY_FIRST);
-}
-
-module AP_MODULE_DECLARE_DATA cgi_module =
-{
- STANDARD20_MODULE_STUFF,
- NULL, /* dir config creater */
- NULL, /* dir merger --- default is to override */
- create_cgi_config, /* server config */
- merge_cgi_config, /* merge server config */
- cgi_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
diff --git a/modules/generators/mod_cgi.exp b/modules/generators/mod_cgi.exp
deleted file mode 100644
index 96ea0c2348..0000000000
--- a/modules/generators/mod_cgi.exp
+++ /dev/null
@@ -1 +0,0 @@
-cgi_module
diff --git a/modules/generators/mod_cgid.c b/modules/generators/mod_cgid.c
deleted file mode 100644
index cbb09d3525..0000000000
--- a/modules/generators/mod_cgid.c
+++ /dev/null
@@ -1,1300 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * http_script: keeps all script-related ramblings together.
- *
- * Compliant to cgi/1.1 spec
- *
- * Adapted by rst from original NCSA code by Rob McCool
- *
- * Apache adds some new env vars; REDIRECT_URL and REDIRECT_QUERY_STRING for
- * custom error responses, and DOCUMENT_ROOT because we found it useful.
- * It also adds SERVER_ADMIN - useful for scripts to know who to mail when
- * they fail.
- */
-
-#include "apr_lib.h"
-#include "apr_strings.h"
-#include "apr_general.h"
-#include "apr_file_io.h"
-#include "apr_portable.h"
-#include "apr_buckets.h"
-#include "apr_optional.h"
-#include "apr_signal.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#if APR_HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#if APR_HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if APR_HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#define CORE_PRIVATE
-
-#include "util_filter.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_request.h"
-#include "http_core.h"
-#include "http_protocol.h"
-#include "http_main.h"
-#include "http_log.h"
-#include "util_script.h"
-#include "ap_mpm.h"
-#include "unixd.h"
-#include "mod_suexec.h"
-#include "../filters/mod_include.h"
-
-#include "mod_core.h"
-
-
-/* ### should be tossed in favor of APR */
-#include <sys/stat.h>
-#include <sys/un.h> /* for sockaddr_un */
-
-
-module AP_MODULE_DECLARE_DATA cgid_module;
-
-static void cgid_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *main_server);
-static int handle_exec(include_ctx_t *ctx, apr_bucket_brigade **bb, request_rec *r,
- ap_filter_t *f, apr_bucket *head_ptr, apr_bucket **inserted_head);
-
-static APR_OPTIONAL_FN_TYPE(ap_register_include_handler) *cgid_pfn_reg_with_ssi;
-static APR_OPTIONAL_FN_TYPE(ap_ssi_get_tag_and_value) *cgid_pfn_gtv;
-static APR_OPTIONAL_FN_TYPE(ap_ssi_parse_string) *cgid_pfn_ps;
-
-static apr_pool_t *pcgi;
-static int total_modules = 0;
-
-/* KLUDGE --- for back-combatibility, we don't have to check Execcgid
- * in ScriptAliased directories, which means we need to know if this
- * request came through ScriptAlias or not... so the Alias module
- * leaves a note for us.
- */
-
-static int is_scriptaliased(request_rec *r)
-{
- const char *t = apr_table_get(r->notes, "alias-forced-type");
- return t && (!strcasecmp(t, "cgi-script"));
-}
-
-/* Configuration stuff */
-
-#define DEFAULT_LOGBYTES 10385760
-#define DEFAULT_BUFBYTES 1024
-#define DEFAULT_SOCKET "logs/cgisock"
-
-#define SHELL_PATH "/bin/sh"
-
-#define CGI_REQ 1
-#define SSI_REQ 2
-
-/* DEFAULT_CGID_LISTENBACKLOG controls the max depth on the unix socket's
- * pending connection queue. If a bunch of cgi requests arrive at about
- * the same time, connections from httpd threads/processes will back up
- * in the queue while the cgid process slowly forks off a child to process
- * each connection on the unix socket. If the queue is too short, the
- * httpd process will get ECONNREFUSED when trying to connect.
- */
-#ifndef DEFAULT_CGID_LISTENBACKLOG
-#define DEFAULT_CGID_LISTENBACKLOG 100
-#endif
-
-typedef struct {
- const char *sockname;
- const char *logname;
- long logbytes;
- int bufbytes;
-} cgid_server_conf;
-
-/* If a request includes query info in the URL (stuff after "?"), and
- * the query info does not contain "=" (indicative of a FORM submission),
- * then this routine is called to create the argument list to be passed
- * to the CGI script. When suexec is enabled, the suexec path, user, and
- * group are the first three arguments to be passed; if not, all three
- * must be NULL. The query info is split into separate arguments, where
- * "+" is the separator between keyword arguments.
- *
- * XXXX: note that the WIN32 code uses one of the suexec strings
- * to pass an interpreter name. Remember this if changing the way they
- * are handled in create_argv.
- *
- */
-static char **create_argv(apr_pool_t *p, char *path, char *user, char *group,
- char *av0, const char *args)
-{
- int x, numwords;
- char **av;
- char *w;
- int idx = 0;
-
- /* count the number of keywords */
-
- for (x = 0, numwords = 1; args[x]; x++) {
- if (args[x] == '+') {
- ++numwords;
- }
- }
-
- if (numwords > APACHE_ARG_MAX - 5) {
- numwords = APACHE_ARG_MAX - 5; /* Truncate args to prevent overrun */
- }
- av = (char **) apr_pcalloc(p, (numwords + 5) * sizeof(char *));
-
- if (path) {
- av[idx++] = path;
- }
- if (user) {
- av[idx++] = user;
- }
- if (group) {
- av[idx++] = group;
- }
-
- av[idx++] = apr_pstrdup(p, av0);
-
- for (x = 1; x <= numwords; x++) {
- w = ap_getword_nulls(p, &args, '+');
- if (strcmp(w, "")) {
- ap_unescape_url(w);
- av[idx++] = ap_escape_shell_cmd(p, w);
- }
- }
- av[idx] = NULL;
- return av;
-}
-
-#if APR_HAS_OTHER_CHILD
-static void cgid_maint(int reason, void *data, apr_wait_t status)
-{
- pid_t *sd = data;
- switch (reason) {
- case APR_OC_REASON_DEATH:
- case APR_OC_REASON_LOST:
- /* stop gap to make sure everything else works. In the end,
- * we'll just restart the cgid server. */
- apr_pool_destroy(pcgi);
- kill(getpid(), SIGWINCH); /* yes, to ourself */
- break;
- case APR_OC_REASON_RESTART:
- apr_proc_other_child_unregister(data);
- break;
- case APR_OC_REASON_UNREGISTER:
- apr_pool_destroy(pcgi);
- kill(*sd, SIGHUP);
- break;
- }
-}
-#endif
-
-static void get_req(int fd, request_rec *r, char **argv0, char ***env, int *req_type)
-{
- int i, len, j;
- unsigned char *data;
- char **environ;
- core_dir_config *temp_core;
- void **dconf;
- module *suexec_mod = ap_find_linked_module("mod_suexec.c");
-
- r->server = apr_pcalloc(r->pool, sizeof(server_rec));
-
- read(fd, req_type, sizeof(int));
- read(fd, &j, sizeof(int));
- read(fd, &len, sizeof(int));
- data = apr_pcalloc(r->pool, len + 1); /* get a cleared byte for final '\0' */
- i = read(fd, data, len);
-
- r->filename = ap_getword(r->pool, (const char **)&data, '\n');
- *argv0 = ap_getword(r->pool, (const char **)&data, '\n');
-
- r->uri = ap_getword(r->pool, (const char **)&data, '\n');
-
- environ = apr_pcalloc(r->pool, (j + 2) *sizeof(char *));
- i = 0;
- for (i = 0; i < j; i++) {
- environ[i] = ap_getword(r->pool, (const char **)&data, '\n');
- }
- *env = environ;
- r->args = ap_getword(r->pool, (const char **)&data, '\n');
-
- read(fd, &i, sizeof(int));
-
- /* add 1, so that if i == 0, we still malloc something. */
-
- dconf = (void **) apr_pcalloc(r->pool, sizeof(void *) * (total_modules + DYNAMIC_MODULE_LIMIT));
-
- temp_core = (core_dir_config *)apr_palloc(r->pool, sizeof(core_module));
-
- dconf[i] = (void *)temp_core;
-
- if (suexec_mod) {
- suexec_config_t *suexec_cfg = apr_pcalloc(r->pool, sizeof(*suexec_cfg));
-
- read(fd, &i, sizeof(int));
- read(fd, &suexec_cfg->ugid.uid, sizeof(uid_t));
- read(fd, &suexec_cfg->ugid.gid, sizeof(gid_t));
- read(fd, &suexec_cfg->active, sizeof(int));
- dconf[i] = (void *)suexec_cfg;
- }
-
- r->per_dir_config = (ap_conf_vector_t *)dconf;
-#if 0
-#ifdef RLIMIT_CPU
- read(fd, &j, sizeof(int));
- if (j) {
- temp_core->limit_cpu = (struct rlimit *)apr_palloc (sizeof(struct rlimit));
- read(fd, temp_core->limit_cpu, sizeof(struct rlimit));
- }
- else {
- temp_core->limit_cpu = NULL;
- }
-#endif
-
-#if defined (RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
- read(fd, &j, sizeof(int));
- if (j) {
- temp_core->limit_mem = (struct rlimit *)apr_palloc(r->pool, sizeof(struct rlimit));
- read(fd, temp_core->limit_mem, sizeof(struct rlimit));
- }
- else {
- temp_core->limit_mem = NULL;
- }
-#endif
-
-#ifdef RLIMIT_NPROC
- read(fd, &j, sizeof(int));
- if (j) {
- temp_core->limit_nproc = (struct rlimit *)apr_palloc(r->pool, sizeof(struct rlimit));
- read(fd, temp_core->limit_nproc, sizeof(struct rlimit));
- }
- else {
- temp_core->limit_nproc = NULL;
- }
-#endif
-#endif
- /* For right now, just make the notes table. At some point we will need
- * to actually fill this out, but for now we just don't want suexec to
- * seg fault.
- */
- r->notes = apr_table_make(r->pool, 1);
-}
-
-
-
-static void send_req(int fd, request_rec *r, char *argv0, char **env, int req_type)
-{
- int len, r_type = req_type;
- int i = 0;
- char *data;
- module *suexec_mod = ap_find_linked_module("mod_suexec.c");
-
- data = apr_pstrcat(r->pool, r->filename, "\n", argv0, "\n", r->uri, "\n",
- NULL);
-
- for (i =0; env[i]; i++) {
- continue;
- }
-
- /* Write the request type (SSI "exec cmd" or cgi). */
- if (write(fd, &r_type, sizeof(int)) < 0) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r,
- "write to cgi daemon process");
- }
-
- /* Write the number of entries in the environment. */
- if (write(fd, &i, sizeof(int)) < 0) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r,
- "write to cgi daemon process");
- }
-
- for (i = 0; env[i]; i++) {
- data = apr_pstrcat(r->pool, data, env[i], "\n", NULL);
- }
- data = apr_pstrcat(r->pool, data, r->args, NULL);
- len = strlen(data);
- /* Write the length of the concatenated env string. */
- if (write(fd, &len, sizeof(int)) < 0) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r,
- "write to cgi daemon process");
- }
- /* Write the concatted env string. */
- if (write(fd, data, len) < 0) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r,
- "write to cgi daemon process");
- }
- /* Write module_index id value. */
- if (write(fd, &core_module.module_index, sizeof(int)) < 0) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, errno, r,
- "write to cgi daemon process");
- }
- if (suexec_mod) {
- suexec_config_t *suexec_cfg = ap_get_module_config(r->per_dir_config,
- suexec_mod);
-
- write(fd, &suexec_mod->module_index, sizeof(int));
- write(fd, &suexec_cfg->ugid.uid, sizeof(uid_t));
- write(fd, &suexec_cfg->ugid.gid, sizeof(gid_t));
- write(fd, &suexec_cfg->active, sizeof(int));
- }
-
-#if 0
-#ifdef RLIMIT_CPU
- if (conf->limit_cpu) {
- len = 1;
- write(fd, &len, sizeof(int));
- write(fd, conf->limit_cpu, sizeof(struct rlimit));
- }
- else {
- len = 0;
- write(fd, &len, sizeof(int));
- }
-#endif
-
-#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
- if (conf->limit_mem) {
- len = 1;
- write(fd, &len, sizeof(int));
- write(fd, conf->limit_mem, sizeof(struct rlimit));
- }
- else {
- len = 0;
- write(fd, &len, sizeof(int));
- }
-#endif
-
-#ifdef RLIMIT_NPROC
- if (conf->limit_nproc) {
- len = 1;
- write(fd, &len, sizeof(int));
- write(fd, conf->limit_nproc, sizeof(struct rlimit));
- }
- else {
- len = 0;
- write(fd, &len, sizeof(int));
- }
-#endif
-#endif
-}
-
-static int cgid_server(void *data)
-{
- struct sockaddr_un unix_addr;
- int sd, sd2, rc, req_type;
- mode_t omask;
- apr_socklen_t len;
- apr_pool_t *ptrans;
- server_rec *main_server = data;
- cgid_server_conf *sconf = ap_get_module_config(main_server->module_config,
- &cgid_module);
-
- apr_pool_create(&ptrans, pcgi);
-
- apr_signal(SIGCHLD, SIG_IGN);
- if (unlink(sconf->sockname) < 0 && errno != ENOENT) {
- ap_log_error(APLOG_MARK, APLOG_ERR, errno, main_server,
- "Couldn't unlink unix domain socket %s",
- sconf->sockname);
- /* just a warning; don't bail out */
- }
-
- if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
- ap_log_error(APLOG_MARK, APLOG_ERR, errno, main_server,
- "Couldn't create unix domain socket");
- return errno;
- }
-
- memset(&unix_addr, 0, sizeof(unix_addr));
- unix_addr.sun_family = AF_UNIX;
- strcpy(unix_addr.sun_path, sconf->sockname);
-
- omask = umask(0077); /* so that only Apache can use socket */
- rc = bind(sd, (struct sockaddr *)&unix_addr, sizeof(unix_addr));
- umask(omask); /* can't fail, so can't clobber errno */
- if (rc < 0) {
- ap_log_error(APLOG_MARK, APLOG_ERR, errno, main_server,
- "Couldn't bind unix domain socket %s",
- sconf->sockname);
- return errno;
- }
-
- if (listen(sd, DEFAULT_CGID_LISTENBACKLOG) < 0) {
- ap_log_error(APLOG_MARK, APLOG_ERR, errno, main_server,
- "Couldn't listen on unix domain socket");
- return errno;
- }
-
- if (!geteuid()) {
- if (chown(sconf->sockname, unixd_config.user_id, -1) < 0) {
- ap_log_error(APLOG_MARK, APLOG_ERR, errno, main_server,
- "Couldn't change owner of unix domain socket %s",
- sconf->sockname);
- return errno;
- }
- }
-
- unixd_setup_child(); /* if running as root, switch to configured user/group */
- while (1) {
- int errfileno = STDERR_FILENO;
- char *argv0;
- char **env;
- const char * const *argv;
- apr_int32_t in_pipe = APR_CHILD_BLOCK;
- apr_int32_t out_pipe = APR_CHILD_BLOCK;
- apr_int32_t err_pipe = APR_CHILD_BLOCK;
- apr_cmdtype_e cmd_type = APR_PROGRAM;
- request_rec *r;
- apr_procattr_t *procattr = NULL;
- apr_proc_t *procnew = NULL;
- apr_file_t *inout;
-
- apr_pool_clear(ptrans);
-
- len = sizeof(unix_addr);
- sd2 = accept(sd, (struct sockaddr *)&unix_addr, &len);
- if (sd2 < 0) {
- if (errno != EINTR) {
- ap_log_error(APLOG_MARK, APLOG_ERR, errno,
- (server_rec *)data,
- "Error accepting on cgid socket.");
- }
- continue;
- }
-
- r = apr_pcalloc(ptrans, sizeof(request_rec));
- procnew = apr_pcalloc(ptrans, sizeof(*procnew));
- r->pool = ptrans;
- get_req(sd2, r, &argv0, &env, &req_type);
- apr_os_file_put(&r->server->error_log, &errfileno, r->pool);
- apr_os_file_put(&inout, &sd2, r->pool);
-
- if (req_type == SSI_REQ) {
- in_pipe = APR_NO_PIPE;
- out_pipe = APR_FULL_BLOCK;
- err_pipe = APR_NO_PIPE;
- cmd_type = APR_SHELLCMD;
- }
-
- if (((rc = apr_procattr_create(&procattr, ptrans)) != APR_SUCCESS) ||
- ((req_type == CGI_REQ) &&
- (((rc = apr_procattr_io_set(procattr,
- in_pipe,
- out_pipe,
- err_pipe)) != APR_SUCCESS) ||
- /* XXX apr_procattr_child_*_set() is creating an unnecessary
- * pipe between this process and the child being created...
- * It is cleaned up with the temporary pool for this request.
- */
- ((rc = apr_procattr_child_err_set(procattr, r->server->error_log, NULL)) != APR_SUCCESS) ||
- ((rc = apr_procattr_child_in_set(procattr, inout, NULL)) != APR_SUCCESS))) ||
- ((rc = apr_procattr_child_out_set(procattr, inout, NULL)) != APR_SUCCESS) ||
- ((rc = apr_procattr_dir_set(procattr,
- ap_make_dirstr_parent(r->pool, r->filename))) != APR_SUCCESS) ||
- ((rc = apr_procattr_cmdtype_set(procattr, cmd_type)) != APR_SUCCESS)) {
- /* Something bad happened, tell the world. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r,
- "couldn't set child process attributes: %s", r->filename);
- }
- else {
- argv = (const char * const *)create_argv(r->pool, NULL, NULL, NULL, argv0, r->args);
-
- /* We want to sd2 close for new CGI process too.
- * If it's remained open it'll make ap_pass_brigade() block
- * waiting for EOF if CGI forked something running long.
- * close(sd2) here should be okay, as CGI channel
- * is already dup()ed by apr_procattr_child_{in,out}_set()
- * above.
- */
- close(sd2);
-
- rc = ap_os_create_privileged_process(r, procnew, argv0, argv,
- (const char * const *)env,
- procattr, ptrans);
-
- if (rc != APR_SUCCESS) {
- /* Bad things happened. Everyone should have cleaned up. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r,
- "couldn't create child process: %d: %s", rc, r->filename);
- }
- }
- }
- return -1;
-}
-
-static void cgid_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
- server_rec *main_server)
-{
- pid_t pid;
- apr_proc_t *procnew;
- void *data;
- int first_time = 0;
- const char *userdata_key = "cgid_init";
- module **m;
-
- apr_pool_userdata_get(&data, userdata_key, main_server->process->pool);
- if (!data) {
- first_time = 1;
- apr_pool_userdata_set((const void *)1, userdata_key,
- apr_pool_cleanup_null, main_server->process->pool);
- }
-
- if (!first_time) {
- apr_pool_create(&pcgi, p);
-
- total_modules = 0;
- for (m = ap_preloaded_modules; *m != NULL; m++)
- total_modules++;
-
-
- if ((pid = fork()) < 0) {
- ap_log_error(APLOG_MARK, APLOG_ERR, errno, main_server,
- "Couldn't spawn cgid daemon process");
- }
- else if (pid == 0) {
- cgid_server(main_server);
- exit(-1);
- }
- procnew = apr_pcalloc(p, sizeof(*procnew));
- procnew->pid = pid;
- procnew->err = procnew->in = procnew->out = NULL;
- apr_pool_note_subprocess(p, procnew, kill_after_timeout);
-#if APR_HAS_OTHER_CHILD
- apr_proc_other_child_register(procnew, cgid_maint, &procnew->pid, NULL, p);
-#endif
-
- cgid_pfn_reg_with_ssi = APR_RETRIEVE_OPTIONAL_FN(ap_register_include_handler);
- cgid_pfn_gtv = APR_RETRIEVE_OPTIONAL_FN(ap_ssi_get_tag_and_value);
- cgid_pfn_ps = APR_RETRIEVE_OPTIONAL_FN(ap_ssi_parse_string);
-
- if ((cgid_pfn_reg_with_ssi) && (cgid_pfn_gtv) && (cgid_pfn_ps)) {
- /* Required by mod_include filter. This is how mod_cgid registers
- * with mod_include to provide processing of the exec directive.
- */
- cgid_pfn_reg_with_ssi("exec", handle_exec);
- }
- }
-}
-
-static void *create_cgid_config(apr_pool_t *p, server_rec *s)
-{
- cgid_server_conf *c =
- (cgid_server_conf *) apr_pcalloc(p, sizeof(cgid_server_conf));
-
- c->logname = NULL;
- c->logbytes = DEFAULT_LOGBYTES;
- c->bufbytes = DEFAULT_BUFBYTES;
- c->sockname = ap_server_root_relative(p, DEFAULT_SOCKET);
- return c;
-}
-
-static void *merge_cgid_config(apr_pool_t *p, void *basev, void *overridesv)
-{
- cgid_server_conf *base = (cgid_server_conf *) basev, *overrides = (cgid_server_conf *) overridesv;
-
- return overrides->logname ? overrides : base;
-}
-
-static const char *set_scriptlog(cmd_parms *cmd, void *dummy, const char *arg)
-{
- server_rec *s = cmd->server;
- cgid_server_conf *conf = ap_get_module_config(s->module_config,
- &cgid_module);
-
- conf->logname = arg;
- return NULL;
-}
-
-static const char *set_scriptlog_length(cmd_parms *cmd, void *dummy, const char *arg)
-{
- server_rec *s = cmd->server;
- cgid_server_conf *conf = ap_get_module_config(s->module_config,
- &cgid_module);
-
- conf->logbytes = atol(arg);
- return NULL;
-}
-
-static const char *set_scriptlog_buffer(cmd_parms *cmd, void *dummy, const char *arg)
-{
- server_rec *s = cmd->server;
- cgid_server_conf *conf = ap_get_module_config(s->module_config,
- &cgid_module);
-
- conf->bufbytes = atoi(arg);
- return NULL;
-}
-
-static const char *set_script_socket(cmd_parms *cmd, void *dummy, const char *arg)
-{
- server_rec *s = cmd->server;
- cgid_server_conf *conf = ap_get_module_config(s->module_config,
- &cgid_module);
-
- conf->sockname = ap_server_root_relative(cmd->pool, arg);
- return NULL;
-}
-
-static const command_rec cgid_cmds[] =
-{
- AP_INIT_TAKE1("ScriptLog", set_scriptlog, NULL, RSRC_CONF,
- "the name of a log for script debugging info"),
- AP_INIT_TAKE1("ScriptLogLength", set_scriptlog_length, NULL, RSRC_CONF,
- "the maximum length (in bytes) of the script debug log"),
- AP_INIT_TAKE1("ScriptLogBuffer", set_scriptlog_buffer, NULL, RSRC_CONF,
- "the maximum size (in bytes) to record of a POST request"),
- AP_INIT_TAKE1("Scriptsock", set_script_socket, NULL, RSRC_CONF,
- "the name of the socket to use for communication with "
- "the cgi daemon."),
- {NULL}
-};
-
-static int log_scripterror(request_rec *r, cgid_server_conf * conf, int ret,
- apr_status_t rv, char *error)
-{
- apr_file_t *f = NULL;
- struct stat finfo;
- char time_str[APR_CTIME_LEN];
- int log_flags = rv ? APLOG_ERR : APLOG_NOERRNO | APLOG_ERR;
-
- ap_log_rerror(APLOG_MARK, log_flags, rv, r,
- "%s: %s", error, r->filename);
-
- if (!conf->logname ||
- ((stat(ap_server_root_relative(r->pool, conf->logname), &finfo) == 0)
- && (finfo.st_size > conf->logbytes)) ||
- (apr_file_open(&f, ap_server_root_relative(r->pool, conf->logname),
- APR_APPEND|APR_WRITE|APR_CREATE, APR_OS_DEFAULT, r->pool) != APR_SUCCESS)) {
- return ret;
- }
-
- /* "%% [Wed Jun 19 10:53:21 1996] GET /cgid-bin/printenv HTTP/1.0" */
- apr_ctime(time_str, apr_time_now());
- apr_file_printf(f, "%%%% [%s] %s %s%s%s %s\n", time_str, r->method, r->uri,
- r->args ? "?" : "", r->args ? r->args : "", r->protocol);
- /* "%% 500 /usr/local/apache/cgid-bin */
- apr_file_printf(f, "%%%% %d %s\n", ret, r->filename);
-
- apr_file_printf(f, "%%error\n%s\n", error);
-
- apr_file_close(f);
- return ret;
-}
-
-static int log_script(request_rec *r, cgid_server_conf * conf, int ret,
- char *dbuf, const char *sbuf, apr_file_t *script_in, apr_file_t *script_err)
-{
- apr_array_header_t *hdrs_arr = apr_table_elts(r->headers_in);
- apr_table_entry_t *hdrs = (apr_table_entry_t *) hdrs_arr->elts;
- char argsbuffer[HUGE_STRING_LEN];
- apr_file_t *f = NULL;
- int i;
- struct stat finfo;
- char time_str[APR_CTIME_LEN];
-
- if (!conf->logname ||
- ((stat(ap_server_root_relative(r->pool, conf->logname), &finfo) == 0)
- && (finfo.st_size > conf->logbytes)) ||
- (apr_file_open(&f, ap_server_root_relative(r->pool, conf->logname),
- APR_APPEND|APR_WRITE|APR_CREATE, APR_OS_DEFAULT, r->pool) != APR_SUCCESS)) {
- /* Soak up script output */
- while (apr_file_gets(argsbuffer, HUGE_STRING_LEN, script_in) == 0)
- continue;
- if (script_err) {
- while (apr_file_gets(argsbuffer, HUGE_STRING_LEN, script_err) == 0)
- continue;
- }
- return ret;
- }
-
- /* "%% [Wed Jun 19 10:53:21 1996] GET /cgid-bin/printenv HTTP/1.0" */
- apr_ctime(time_str, apr_time_now());
- apr_file_printf(f, "%%%% [%s] %s %s%s%s %s\n", time_str, r->method, r->uri,
- r->args ? "?" : "", r->args ? r->args : "", r->protocol);
- /* "%% 500 /usr/local/apache/cgid-bin" */
- apr_file_printf(f, "%%%% %d %s\n", ret, r->filename);
-
- apr_file_puts("%request\n", f);
- for (i = 0; i < hdrs_arr->nelts; ++i) {
- if (!hdrs[i].key)
- continue;
- apr_file_printf(f, "%s: %s\n", hdrs[i].key, hdrs[i].val);
- }
- if ((r->method_number == M_POST || r->method_number == M_PUT)
- && *dbuf) {
- apr_file_printf(f, "\n%s\n", dbuf);
- }
-
- apr_file_puts("%response\n", f);
- hdrs_arr = apr_table_elts(r->err_headers_out);
- hdrs = (apr_table_entry_t *) hdrs_arr->elts;
-
- for (i = 0; i < hdrs_arr->nelts; ++i) {
- if (!hdrs[i].key)
- continue;
- apr_file_printf(f, "%s: %s\n", hdrs[i].key, hdrs[i].val);
- }
-
- if (sbuf && *sbuf)
- apr_file_printf(f, "%s\n", sbuf);
-
- if (apr_file_gets(argsbuffer, HUGE_STRING_LEN, script_in) == 0) {
- apr_file_puts("%stdout\n", f);
- apr_file_puts(argsbuffer, f);
- while (apr_file_gets(argsbuffer, HUGE_STRING_LEN, script_in) == 0)
- apr_file_puts(argsbuffer, f);
- apr_file_puts("\n", f);
- }
-
- if (script_err) {
- if (apr_file_gets(argsbuffer, HUGE_STRING_LEN, script_err) == 0) {
- apr_file_puts("%stderr\n", f);
- apr_file_puts(argsbuffer, f);
- while (apr_file_gets(argsbuffer, HUGE_STRING_LEN, script_err) == 0)
- apr_file_puts(argsbuffer, f);
- apr_file_puts("\n", f);
- }
- }
-
- apr_file_close(script_in);
- if (script_err) {
- apr_file_close(script_err);
- }
-
- apr_file_close(f);
- return ret;
-}
-
-
-
-/****************************************************************
- *
- * Actual cgid handling...
- */
-static int cgid_handler(request_rec *r)
-{
- int retval, nph, dbpos = 0;
- char *argv0, *dbuf = NULL;
- apr_bucket_brigade *bb;
- apr_bucket *b;
- char argsbuffer[HUGE_STRING_LEN];
- cgid_server_conf *conf;
- int is_included;
- int sd;
- char **env;
- struct sockaddr_un unix_addr;
- apr_file_t *tempsock;
- apr_size_t nbytes;
-
- if(strcmp(r->handler,CGI_MAGIC_TYPE) && strcmp(r->handler,"cgi-script"))
- return DECLINED;
-
- if (r->method_number == M_OPTIONS) {
- /* 99 out of 100 cgid scripts, this is all they support */
- r->allowed |= (1 << M_GET);
- r->allowed |= (1 << M_POST);
- return DECLINED;
- }
-
- conf = ap_get_module_config(r->server->module_config, &cgid_module);
- is_included = !strcmp(r->protocol, "INCLUDED");
-
- if ((argv0 = strrchr(r->filename, '/')) != NULL)
- argv0++;
- else
- argv0 = r->filename;
-
- nph = !(strncmp(argv0, "nph-", 4));
-
- if ((argv0 = strrchr(r->filename, '/')) != NULL)
- argv0++;
- else
- argv0 = r->filename;
-
- if (!(ap_allow_options(r) & OPT_EXECCGI) && !is_scriptaliased(r))
- return log_scripterror(r, conf, HTTP_FORBIDDEN, 0,
- "Options ExecCGI is off in this directory");
- if (nph && is_included)
- return log_scripterror(r, conf, HTTP_FORBIDDEN, 0,
- "attempt to include NPH CGI script");
-
-#if defined(OS2) || defined(WIN32)
-#error mod_cgid does not work on this platform. If you teach it to, look
-#error at mod_cgi.c for required code in this path.
-#else
- if (r->finfo.filetype == 0)
- return log_scripterror(r, conf, HTTP_NOT_FOUND, 0,
- "script not found or unable to stat");
-#endif
- if (r->finfo.filetype == APR_DIR)
- return log_scripterror(r, conf, HTTP_FORBIDDEN, 0,
- "attempt to invoke directory as script");
-/*
- if (!ap_suexec_enabled) {
- if (!ap_can_exec(&r->finfo))
- return log_scripterror(r, conf, HTTP_FORBIDDEN, 0,
- "file permissions deny server execution");
- }
-*/
- ap_add_common_vars(r);
- ap_add_cgi_vars(r);
- env = ap_create_environment(r->pool, r->subprocess_env);
-
- if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
- return log_scripterror(r, conf, HTTP_INTERNAL_SERVER_ERROR, errno,
- "unable to create socket to cgi daemon");
- }
- memset(&unix_addr, 0, sizeof(unix_addr));
- unix_addr.sun_family = AF_UNIX;
- strcpy(unix_addr.sun_path, conf->sockname);
-
- if (connect(sd, (struct sockaddr *)&unix_addr, sizeof(unix_addr)) < 0) {
- return log_scripterror(r, conf, HTTP_INTERNAL_SERVER_ERROR, errno,
- "unable to connect to cgi daemon");
- }
-
- send_req(sd, r, argv0, env, CGI_REQ);
-
- /* We are putting the tempsock variable into a file so that we can use
- * a pipe bucket to send the data to the client.
- */
- apr_os_file_put(&tempsock, &sd, r->pool);
-
- if ((retval = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)))
- return retval;
-
- if ((argv0 = strrchr(r->filename, '/')) != NULL)
- argv0++;
- else
- argv0 = r->filename;
-
- /* Transfer any put/post args, CERN style...
- * Note that we already ignore SIGPIPE in the core server.
- */
-
- if (ap_should_client_block(r)) {
- int dbsize, len_read;
-
- if (conf->logname) {
- dbuf = apr_pcalloc(r->pool, conf->bufbytes + 1);
- dbpos = 0;
- }
-
- while ((len_read =
- ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN)) > 0) {
- if (conf->logname) {
- if ((dbpos + len_read) > conf->bufbytes) {
- dbsize = conf->bufbytes - dbpos;
- }
- else {
- dbsize = len_read;
- }
- memcpy(dbuf + dbpos, argsbuffer, dbsize);
- dbpos += dbsize;
- }
- nbytes = len_read;
- apr_file_write(tempsock, argsbuffer, &nbytes);
- if (nbytes < len_read) {
- /* silly script stopped reading, soak up remaining message */
- while (ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN) > 0) {
- /* dump it */
- }
- break;
- }
- }
- }
- /* we're done writing, or maybe we didn't write at all;
- * force EOF on child's stdin so that the cgi detects end (or
- * absence) of data
- */
- shutdown(sd, 1);
-
- /* Handle script return... */
- if (!nph) {
- const char *location;
- char sbuf[MAX_STRING_LEN];
- int ret;
-
- if ((ret = ap_scan_script_header_err(r, tempsock, sbuf))) {
- return log_script(r, conf, ret, dbuf, sbuf, tempsock, NULL);
- }
-
- location = apr_table_get(r->headers_out, "Location");
-
- if (location && location[0] == '/' && r->status == 200) {
-
- /* Soak up all the script output */
- while (apr_file_gets(argsbuffer, HUGE_STRING_LEN, tempsock) > 0) {
- continue;
- }
- /* This redirect needs to be a GET no matter what the original
- * method was.
- */
- r->method = apr_pstrdup(r->pool, "GET");
- r->method_number = M_GET;
-
- /* We already read the message body (if any), so don't allow
- * the redirected request to think it has one. We can ignore
- * Transfer-Encoding, since we used REQUEST_CHUNKED_ERROR.
- */
- apr_table_unset(r->headers_in, "Content-Length");
-
- ap_internal_redirect_handler(location, r);
- return OK;
- }
- else if (location && r->status == 200) {
- /* XX Note that if a script wants to produce its own Redirect
- * body, it now has to explicitly *say* "Status: 302"
- */
- return HTTP_MOVED_TEMPORARILY;
- }
-
- if (!r->header_only) {
- bb = apr_brigade_create(r->pool);
- b = apr_bucket_pipe_create(tempsock);
- APR_BRIGADE_INSERT_TAIL(bb, b);
- b = apr_bucket_eos_create();
- APR_BRIGADE_INSERT_TAIL(bb, b);
- ap_pass_brigade(r->output_filters, bb);
- }
- }
-
- if (nph) {
- bb = apr_brigade_create(r->pool);
- b = apr_bucket_pipe_create(tempsock);
- APR_BRIGADE_INSERT_TAIL(bb, b);
- b = apr_bucket_eos_create();
- APR_BRIGADE_INSERT_TAIL(bb, b);
- ap_pass_brigade(r->output_filters, bb);
- }
-
- apr_file_close(tempsock);
-
- return OK; /* NOT r->status, even if it has changed. */
-}
-
-
-
-
-/*============================================================================
- *============================================================================
- * This is the beginning of the cgi filter code moved from mod_include. This
- * is the code required to handle the "exec" SSI directive.
- *============================================================================
- *============================================================================*/
-static int include_cgi(char *s, request_rec *r, ap_filter_t *next,
- apr_bucket *head_ptr, apr_bucket **inserted_head)
-{
- request_rec *rr = ap_sub_req_lookup_uri(s, r, next);
- int rr_status;
- apr_bucket *tmp_buck, *tmp2_buck;
-
- if (rr->status != HTTP_OK) {
- return -1;
- }
-
- /* No hardwired path info or query allowed */
-
- if ((rr->path_info && rr->path_info[0]) || rr->args) {
- return -1;
- }
- if (rr->finfo.protection == 0) {
- return -1;
- }
-
- /* Script gets parameters of the *document*, for back compatibility */
-
- rr->path_info = r->path_info; /* hard to get right; see mod_cgi.c */
- rr->args = r->args;
-
- /* Force sub_req to be treated as a CGI request, even if ordinary
- * typing rules would have called it something else.
- */
-
- rr->content_type = CGI_MAGIC_TYPE;
-
- /* Run it. */
-
- rr_status = ap_run_sub_req(rr);
- if (ap_is_HTTP_REDIRECT(rr_status)) {
- apr_size_t len_loc, h_wrt;
- const char *location = apr_table_get(rr->headers_out, "Location");
-
- location = ap_escape_html(rr->pool, location);
- len_loc = strlen(location);
-
- tmp_buck = apr_bucket_immortal_create("<A HREF=\"", sizeof("<A HREF=\""));
- APR_BUCKET_INSERT_BEFORE(head_ptr, tmp_buck);
- tmp2_buck = apr_bucket_heap_create(location, len_loc, 1, &h_wrt);
- APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
- tmp2_buck = apr_bucket_immortal_create("\">", sizeof("\">"));
- APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
- tmp2_buck = apr_bucket_heap_create(location, len_loc, 1, &h_wrt);
- APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
- tmp2_buck = apr_bucket_immortal_create("</A>", sizeof("</A>"));
- APR_BUCKET_INSERT_BEFORE(head_ptr, tmp2_buck);
-
- if (*inserted_head == NULL) {
- *inserted_head = tmp_buck;
- }
- }
-
- ap_destroy_sub_req(rr);
-
- return 0;
-}
-
-
-/* This is the special environment used for running the "exec cmd="
- * variety of SSI directives.
- */
-static void add_ssi_vars(request_rec *r, ap_filter_t *next)
-{
- apr_table_t *e = r->subprocess_env;
-
- if (r->path_info && r->path_info[0] != '\0') {
- request_rec *pa_req;
-
- apr_table_setn(e, "PATH_INFO", ap_escape_shell_cmd(r->pool, r->path_info));
-
- pa_req = ap_sub_req_lookup_uri(ap_escape_uri(r->pool, r->path_info), r, next);
- if (pa_req->filename) {
- apr_table_setn(e, "PATH_TRANSLATED",
- apr_pstrcat(r->pool, pa_req->filename, pa_req->path_info, NULL));
- }
- }
-
- if (r->args) {
- char *arg_copy = apr_pstrdup(r->pool, r->args);
-
- apr_table_setn(e, "QUERY_STRING", r->args);
- ap_unescape_url(arg_copy);
- apr_table_setn(e, "QUERY_STRING_UNESCAPED", ap_escape_shell_cmd(r->pool, arg_copy));
- }
-}
-
-static int include_cmd(include_ctx_t *ctx, apr_bucket_brigade **bb, char *command,
- request_rec *r, ap_filter_t *f)
-{
- char **env;
- const char *location;
- int sd;
- int retval;
- apr_bucket_brigade *bcgi;
- apr_bucket *b;
- struct sockaddr_un unix_addr;
- apr_file_t *tempsock = NULL;
- cgid_server_conf *conf = ap_get_module_config(r->server->module_config,
- &cgid_module);
-
- add_ssi_vars(r, f->next);
- env = ap_create_environment(r->pool, r->subprocess_env);
-
- if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
- return log_scripterror(r, conf, HTTP_INTERNAL_SERVER_ERROR, 0,
- "unable to create socket to cgi daemon");
- }
-
- memset(&unix_addr, 0, sizeof(unix_addr));
- unix_addr.sun_family = AF_UNIX;
- strcpy(unix_addr.sun_path, conf->sockname);
-
- if (connect(sd, (struct sockaddr *)&unix_addr, sizeof(unix_addr)) < 0) {
- return log_scripterror(r, conf, HTTP_INTERNAL_SERVER_ERROR, 0,
- "unable to connect to cgi daemon");
- }
-
- SPLIT_AND_PASS_PRETAG_BUCKETS(*bb, ctx, f->next);
-
- send_req(sd, r, command, env, SSI_REQ);
-
- /* We are putting the tempsock variable into a file so that we can use
- * a pipe bucket to send the data to the client.
- */
- apr_os_file_put(&tempsock, &sd, r->pool);
-
- if ((retval = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)))
- return retval;
-
- location = apr_table_get(r->headers_out, "Location");
-
- if (location && location[0] == '/' && r->status == 200) {
- char argsbuffer[HUGE_STRING_LEN];
-
- /* Soak up all the script output */
- while (apr_file_gets(argsbuffer, HUGE_STRING_LEN, tempsock) > 0) {
- continue;
- }
- /* This redirect needs to be a GET no matter what the original
- * method was.
- */
- r->method = apr_pstrdup(r->pool, "GET");
- r->method_number = M_GET;
-
- /* We already read the message body (if any), so don't allow
- * the redirected request to think it has one. We can ignore
- * Transfer-Encoding, since we used REQUEST_CHUNKED_ERROR.
- */
- apr_table_unset(r->headers_in, "Content-Length");
-
- ap_internal_redirect_handler(location, r);
- return OK;
- }
- else if (location && r->status == 200) {
- /* XX Note that if a script wants to produce its own Redirect
- * body, it now has to explicitly *say* "Status: 302"
- */
- return HTTP_MOVED_TEMPORARILY;
- }
-
- if (!r->header_only) {
- bcgi = apr_brigade_create(r->pool);
- b = apr_bucket_pipe_create(tempsock);
- APR_BRIGADE_INSERT_TAIL(bcgi, b);
- ap_pass_brigade(f->next, bcgi);
- }
-
- return 0;
-}
-
-static int handle_exec(include_ctx_t *ctx, apr_bucket_brigade **bb, request_rec *r,
- ap_filter_t *f, apr_bucket *head_ptr, apr_bucket **inserted_head)
-{
- char *tag = NULL;
- char *tag_val = NULL;
- char *file = r->filename;
- apr_bucket *tmp_buck;
- char parsed_string[MAX_STRING_LEN];
-
- *inserted_head = NULL;
- if (ctx->flags & FLAG_PRINTING) {
- if (ctx->flags & FLAG_NO_EXEC) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "exec used but not allowed in %s", r->filename);
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- }
- else {
- while (1) {
- cgid_pfn_gtv(ctx, &tag, &tag_val, 1);
- if (tag_val == NULL) {
- if (tag == NULL) {
- return (0);
- }
- else {
- return 1;
- }
- }
- if (!strcmp(tag, "cmd")) {
- cgid_pfn_ps(r, tag_val, parsed_string, sizeof(parsed_string), 1);
- if (include_cmd(ctx, bb, parsed_string, r, f) == -1) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "execution failure for parameter \"%s\" "
- "to tag exec in file %s", tag, r->filename);
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- }
- /* just in case some stooge changed directories */
- }
- else if (!strcmp(tag, "cgi")) {
- cgid_pfn_ps(r, tag_val, parsed_string, sizeof(parsed_string), 0);
- SPLIT_AND_PASS_PRETAG_BUCKETS(*bb, ctx, f->next);
- if (include_cgi(parsed_string, r, f->next, head_ptr, inserted_head) == -1) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "invalid CGI ref \"%s\" in %s", tag_val, file);
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- }
- }
- else {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "unknown parameter \"%s\" to tag exec in %s", tag, file);
- CREATE_ERROR_BUCKET(ctx, tmp_buck, head_ptr, *inserted_head);
- }
- }
- }
- }
- return 0;
-}
-/*============================================================================
- *============================================================================
- * This is the end of the cgi filter code moved from mod_include.
- *============================================================================
- *============================================================================*/
-
-
-static void register_hook(apr_pool_t *p)
-{
- static const char * const aszPre[] = { "mod_include.c", NULL };
-
- ap_hook_post_config(cgid_init, aszPre, NULL, APR_HOOK_MIDDLE);
- ap_hook_handler(cgid_handler, NULL, NULL, APR_HOOK_MIDDLE);
-}
-
-module AP_MODULE_DECLARE_DATA cgid_module = {
- STANDARD20_MODULE_STUFF,
- NULL, /* dir config creater */
- NULL, /* dir merger --- default is to override */
- create_cgid_config, /* server config */
- merge_cgid_config, /* merge server config */
- cgid_cmds, /* command table */
- register_hook /* register_handlers */
-};
-
diff --git a/modules/generators/mod_info.c b/modules/generators/mod_info.c
deleted file mode 100644
index 3c5e014fcf..0000000000
--- a/modules/generators/mod_info.c
+++ /dev/null
@@ -1,491 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * Info Module. Display configuration information for the server and
- * all included modules.
- *
- * <Location /server-info>
- * SetHandler server-info
- * </Location>
- *
- * GET /server-info - Returns full configuration page for server and all modules
- * GET /server-info?server - Returns server configuration only
- * GET /server-info?module_name - Returns configuration for a single module
- * GET /server-info?list - Returns quick list of included modules
- *
- * Rasmus Lerdorf <rasmus@vex.net>, May 1996
- *
- * 05.01.96 Initial Version
- *
- * Lou Langholtz <ldl@usi.utah.edu>, July 1997
- *
- * 07.11.97 Addition of the AddModuleInfo directive
- *
- * Ryan Morgan <rmorgan@covalent.net>
- *
- * 8.11.00 Port to Apache 2.0. Read configuation from the configuration
- * tree rather than reparse the entire configuation file.
- *
- */
-
-#define CORE_PRIVATE
-
-#include "httpd.h"
-#include "http_config.h"
-#include "http_core.h"
-#include "http_log.h"
-#include "http_main.h"
-#include "http_protocol.h"
-#include "util_script.h"
-#include "apr_strings.h"
-#include "apr_lib.h"
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-#include "ap_mpm.h"
-
-typedef struct {
- const char *name; /* matching module name */
- const char *info; /* additional info */
-} info_entry;
-
-typedef struct {
- apr_array_header_t *more_info;
-} info_svr_conf;
-
-module AP_MODULE_DECLARE_DATA info_module;
-
-static void *create_info_config(apr_pool_t *p, server_rec *s)
-{
- info_svr_conf *conf = (info_svr_conf *) apr_pcalloc(p, sizeof(info_svr_conf));
-
- conf->more_info = apr_array_make(p, 20, sizeof(info_entry));
- return conf;
-}
-
-static void *merge_info_config(apr_pool_t *p, void *basev, void *overridesv)
-{
- info_svr_conf *new = (info_svr_conf *) apr_pcalloc(p, sizeof(info_svr_conf));
- info_svr_conf *base = (info_svr_conf *) basev;
- info_svr_conf *overrides = (info_svr_conf *) overridesv;
-
- new->more_info = apr_array_append(p, overrides->more_info, base->more_info);
- return new;
-}
-
-static char *mod_info_html_cmd_string(const char *string, char *buf, size_t buf_len, int close)
-{
- const char *s;
- char *t;
- char *end_buf;
-
- s = string;
- t = buf;
- /* keep space for \0 byte */
- end_buf = buf + buf_len - 1;
- while ((*s) && (t < end_buf)) {
- if (*s == '<') {
- if (close) {
- strncpy(t, "&lt;/,", end_buf -t);
- t += 5;
- } else {
- strncpy(t, "&lt;", end_buf - t);
- t += 4;
- }
- }
- else if (*s == '>') {
- strncpy(t, "&gt;", end_buf - t);
- t += 4;
- }
- else if (*s == '&') {
- strncpy(t, "&amp;", end_buf - t);
- t += 5;
- }
- else if (*s == ' ') {
- if (close) {
- strncpy(t, "&gt;", end_buf -t);
- t += 4;
- break;
- } else {
- *t++ = *s;
- }
- } else {
- *t++ = *s;
- }
- s++;
- }
- /* oops, overflowed... don't overwrite */
- if (t > end_buf) {
- *end_buf = '\0';
- }
- else {
- *t = '\0';
- }
- return (buf);
-}
-
-static void mod_info_module_cmds(request_rec * r, const command_rec * cmds,
- ap_directive_t * conftree)
-{
- const command_rec *cmd;
- ap_directive_t *tmptree = conftree;
-
- char buf[MAX_STRING_LEN];
- char htmlstring[MAX_STRING_LEN];
- int block_start = 0;
- int nest = 0;
-
- while (tmptree != NULL) {
- cmd = cmds;
- while (cmd->name) {
- if ((cmd->name[0] != '<') &&
- (strcasecmp(cmd->name, tmptree->directive) == 0)) {
- if (nest > block_start) {
- block_start++;
- apr_snprintf(htmlstring, sizeof(htmlstring), "%s %s",
- tmptree->parent->directive,
- tmptree->parent->args);
- ap_rprintf(r, "<dd><tt>%s</tt><br>\n",
- mod_info_html_cmd_string(htmlstring, buf,
- sizeof(buf), 0));
- }
- if (nest == 2) {
- ap_rprintf(r, "<dd><tt>&nbsp;&nbsp;&nbsp;&nbsp;%s "
- "<i>%s</i></tt><br>\n",
- tmptree->directive, tmptree->args);
- } else if (nest == 1) {
- ap_rprintf(r,
- "<dd><tt>&nbsp;&nbsp;%s <i>%s</i></tt><br>\n",
- tmptree->directive, tmptree->args);
- } else {
- ap_rprintf(r, "<dd><tt>%s <i>%s</i></tt><br>\n",
- mod_info_html_cmd_string(tmptree->directive,
- buf, sizeof(buf),
- 0), tmptree->args);
- }
- }
- ++cmd;
- }
- if (tmptree->first_child != NULL) {
- tmptree = tmptree->first_child;
- nest++;
- } else if (tmptree->next != NULL) {
- tmptree = tmptree->next;
- } else {
- if (block_start) {
- apr_snprintf(htmlstring, sizeof(htmlstring), "%s %s",
- tmptree->parent->directive,
- tmptree->parent->args);
- ap_rprintf(r, "<dd><tt>%s</tt><br>\n",
- mod_info_html_cmd_string(htmlstring, buf,
- sizeof(buf), 1));
- block_start--;
- }
- if (tmptree->parent) {
- tmptree = tmptree->parent->next;
- }
- else {
- tmptree = NULL;
- }
- nest--;
- }
-
- }
-}
-static const char *find_more_info(server_rec *s, const char *module_name)
-{
- int i;
- info_svr_conf *conf = (info_svr_conf *) ap_get_module_config(s->module_config,
- &info_module);
- info_entry *entry = (info_entry *) conf->more_info->elts;
-
- if (!module_name) {
- return 0;
- }
- for (i = 0; i < conf->more_info->nelts; i++) {
- if (!strcmp(module_name, entry->name)) {
- return entry->info;
- }
- entry++;
- }
- return 0;
-}
-
-static int display_info(request_rec *r)
-{
- module *modp = NULL;
- char buf[MAX_STRING_LEN];
- const char *more_info;
- const command_rec *cmd = NULL;
-#ifdef NEVERMORE
- const handler_rec *hand = NULL;
-#endif
- server_rec *serv = r->server;
- int comma = 0;
-
- if (strcmp(r->handler, "server-info"))
- return DECLINED;
-
- r->allowed |= (1 << M_GET);
- if (r->method_number != M_GET)
- return DECLINED;
-
- r->content_type = "text/html";
- if (r->header_only) {
- return 0;
- }
-
- ap_rputs(DOCTYPE_HTML_3_2
- "<html><head><title>Server Information</title></head>\n", r);
- ap_rputs("<body><h1 align=center>Apache Server Information</h1>\n", r);
- if (!r->args || strcasecmp(r->args, "list")) {
- if (!r->args) {
- ap_rputs("<tt><a href=\"#server\">Server Settings</a>, ", r);
- for (modp = ap_top_module; modp; modp = modp->next) {
- ap_rprintf(r, "<a href=\"#%s\">%s</a>", modp->name, modp->name);
- if (modp->next) {
- ap_rputs(", ", r);
- }
- }
- ap_rputs("</tt><hr>", r);
-
- }
- if (!r->args || !strcasecmp(r->args, "server")) {
- int max_daemons, forked, threaded;
-
- ap_rprintf(r, "<a name=\"server\"><strong>Server Version:</strong> "
- "<font size=+1><tt>%s</tt></a></font><br>\n",
- ap_get_server_version());
- ap_rprintf(r, "<strong>Server Built:</strong> "
- "<font size=+1><tt>%s</tt></a></font><br>\n",
- ap_get_server_built());
- ap_rprintf(r, "<strong>API Version:</strong> "
- "<tt>%d:%d</tt><br>\n",
- MODULE_MAGIC_NUMBER_MAJOR, MODULE_MAGIC_NUMBER_MINOR);
- ap_rprintf(r, "<strong>Hostname/port:</strong> "
- "<tt>%s:%u</tt><br>\n",
- serv->server_hostname, serv->port);
- ap_rprintf(r, "<strong>Timeouts:</strong> "
- "<tt>connection: %d &nbsp;&nbsp; "
- "keep-alive: %d</tt><br>",
- serv->timeout, serv->keep_alive_timeout);
- ap_mpm_query(AP_MPMQ_MAX_DAEMONS, &max_daemons);
- ap_mpm_query(AP_MPMQ_IS_THREADED, &threaded);
- ap_mpm_query(AP_MPMQ_IS_FORKED, &forked);
- ap_rprintf(r, "MPM used is %s<br>\n", ap_show_mpm());
- ap_rprintf(r, "<strong>MPM Information:</strong> "
- "<tt>Max Daemons: %d Threaded: %s Forked: %s</tt><br>\n",
- max_daemons, threaded ? "yes" : "no",
- forked ? "yes" : "no");
- ap_rprintf(r, "<strong>Server Root:</strong> "
- "<tt>%s</tt><br>\n", ap_server_root);
- ap_rprintf(r, "<strong>Config File:</strong> "
- "<tt>%s</tt><br>\n", SERVER_CONFIG_FILE);
- }
- ap_rputs("<hr><dl>", r);
- for (modp = ap_top_module; modp; modp = modp->next) {
- if (!r->args || !strcasecmp(modp->name, r->args)) {
- ap_rprintf(r, "<dt><a name=\"%s\"><strong>Module Name:</strong> "
- "<font size=+1><tt>%s</tt></a></font>\n",
- modp->name, modp->name);
- ap_rputs("<dt><strong>Content handlers:</strong>", r);
-#ifdef NEVERMORE
- hand = modp->handlers;
- if (hand) {
- while (hand) {
- if (hand->content_type) {
- ap_rprintf(r, " <tt>%s</tt>\n", hand->content_type);
- }
- else {
- break;
- }
- hand++;
- if (hand && hand->content_type) {
- ap_rputs(",", r);
- }
- }
- }
- else {
- ap_rputs("<tt> <EM>none</EM></tt>", r);
- }
-#else
- ap_rputs("<tt> <EM>(code broken)</EM></tt>", r);
-#endif
- ap_rputs("<dt><strong>Configuration Phase Participation:</strong> \n",
- r);
- if (modp->create_dir_config) {
- if (comma) {
- ap_rputs(", ", r);
- }
- ap_rputs("<tt>Create Directory Config</tt>", r);
- comma = 1;
- }
- if (modp->merge_dir_config) {
- if (comma) {
- ap_rputs(", ", r);
- }
- ap_rputs("<tt>Merge Directory Configs</tt>", r);
- comma = 1;
- }
- if (modp->create_server_config) {
- if (comma) {
- ap_rputs(", ", r);
- }
- ap_rputs("<tt>Create Server Config</tt>", r);
- comma = 1;
- }
- if (modp->merge_server_config) {
- if (comma) {
- ap_rputs(", ", r);
- }
- ap_rputs("<tt>Merge Server Configs</tt>", r);
- comma = 1;
- }
- if (!comma)
- ap_rputs("<tt> <EM>none</EM></tt>", r);
- comma = 0;
- ap_rputs("<dt><strong>Module Directives:</strong> ", r);
- cmd = modp->cmds;
- if (cmd) {
- while (cmd) {
- if (cmd->name) {
- ap_rprintf(r, "<dd><tt>%s - <i>",
- mod_info_html_cmd_string(cmd->name,
- buf, sizeof(buf), 0));
- if (cmd->errmsg) {
- ap_rputs(cmd->errmsg, r);
- }
- ap_rputs("</i></tt>\n", r);
- }
- else {
- break;
- }
- cmd++;
- }
- ap_rputs("<dt><strong>Current Configuration:</strong>\n", r);
- mod_info_module_cmds(r, modp->cmds, ap_conftree);
- }
- else {
- ap_rputs("<tt> none</tt>\n", r);
- }
- more_info = find_more_info(serv, modp->name);
- if (more_info) {
- ap_rputs("<dt><strong>Additional Information:</strong>\n<dd>",
- r);
- ap_rputs(more_info, r);
- }
- ap_rputs("<dt><hr>\n", r);
- if (r->args) {
- break;
- }
- }
- }
- if (!modp && r->args && strcasecmp(r->args, "server")) {
- ap_rputs("<b>No such module</b>\n", r);
- }
- }
- else {
- for (modp = ap_top_module; modp; modp = modp->next) {
- ap_rputs(modp->name, r);
- if (modp->next) {
- ap_rputs("<br>", r);
- }
- }
- }
- ap_rputs("</dl>\n", r);
- ap_rputs(ap_psignature("",r), r);
- ap_rputs("</body></html>\n", r);
- /* Done, turn off timeout, close file and return */
- return 0;
-}
-
-static const char *add_module_info(cmd_parms *cmd, void *dummy,
- const char *name, const char *info)
-{
- server_rec *s = cmd->server;
- info_svr_conf *conf = (info_svr_conf *) ap_get_module_config(s->module_config,
- &info_module);
- info_entry *new = apr_array_push(conf->more_info);
-
- new->name = name;
- new->info = info;
- return NULL;
-}
-
-static const command_rec info_cmds[] =
-{
- AP_INIT_TAKE2("AddModuleInfo", add_module_info, NULL, RSRC_CONF,
- "a module name and additional information on that module"),
- {NULL}
-};
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_handler(display_info, NULL, NULL, APR_HOOK_MIDDLE);
-}
-
-module AP_MODULE_DECLARE_DATA info_module =
-{
- STANDARD20_MODULE_STUFF,
- NULL, /* dir config creater */
- NULL, /* dir merger --- default is to override */
- create_info_config, /* server config */
- merge_info_config, /* merge server config */
- info_cmds, /* command apr_table_t */
- register_hooks
-};
diff --git a/modules/generators/mod_info.dsp b/modules/generators/mod_info.dsp
deleted file mode 100644
index e36e2df870..0000000000
--- a/modules/generators/mod_info.dsp
+++ /dev/null
@@ -1,95 +0,0 @@
-# Microsoft Developer Studio Project File - Name="mod_info" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=mod_info - Win32 Release
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "mod_info.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_info.mak" CFG="mod_info - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_info - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_info - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "mod_info - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\os\win32" /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_info" /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "NDEBUG"
-# ADD RSC /l 0x809 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_info.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_info
-# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_info.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_info
-
-!ELSEIF "$(CFG)" == "mod_info - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\..\include" /I "..\..\os\win32" /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_info" /FD /c
-# ADD BASE MTL /nologo /D "_DEBUG" /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "_DEBUG"
-# ADD RSC /l 0x809 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /out:"Debug/mod_info.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_info
-# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /out:"Debug/mod_info.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_info
-
-!ENDIF
-
-# Begin Target
-
-# Name "mod_info - Win32 Release"
-# Name "mod_info - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\mod_info.c
-# End Source File
-# End Target
-# End Project
diff --git a/modules/generators/mod_info.exp b/modules/generators/mod_info.exp
deleted file mode 100644
index c304fa776d..0000000000
--- a/modules/generators/mod_info.exp
+++ /dev/null
@@ -1 +0,0 @@
-info_module
diff --git a/modules/generators/mod_info.mak b/modules/generators/mod_info.mak
deleted file mode 100644
index 0a1411ebbd..0000000000
--- a/modules/generators/mod_info.mak
+++ /dev/null
@@ -1,326 +0,0 @@
-# Microsoft Developer Studio Generated NMAKE File, Based on mod_info.dsp
-!IF "$(CFG)" == ""
-CFG=mod_info - Win32 Release
-!MESSAGE No configuration specified. Defaulting to mod_info - Win32 Release.
-!ENDIF
-
-!IF "$(CFG)" != "mod_info - Win32 Release" && "$(CFG)" !=\
- "mod_info - Win32 Debug"
-!MESSAGE Invalid configuration "$(CFG)" specified.
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_info.mak" CFG="mod_info - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_info - Win32 Release" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_info - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-!ERROR An invalid configuration is specified.
-!ENDIF
-
-!IF "$(OS)" == "Windows_NT"
-NULL=
-!ELSE
-NULL=nul
-!ENDIF
-
-!IF "$(CFG)" == "mod_info - Win32 Release"
-
-OUTDIR=.\Release
-INTDIR=.\Release
-# Begin Custom Macros
-OutDir=.\Release
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_info.so"
-
-!ELSE
-
-ALL : "libapr - Win32 Release" "libhttpd - Win32 Release"\
- "$(OUTDIR)\mod_info.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libhttpd - Win32 ReleaseCLEAN" "libapr - Win32 ReleaseCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\mod_info.idb"
- -@erase "$(INTDIR)\mod_info.obj"
- -@erase "$(OUTDIR)\mod_info.exp"
- -@erase "$(OUTDIR)\mod_info.lib"
- -@erase "$(OUTDIR)\mod_info.map"
- -@erase "$(OUTDIR)\mod_info.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\os\win32" /I\
- "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D\
- "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_info" /FD /c
-CPP_OBJS=.\Release/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_info.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no\
- /pdb:"$(OUTDIR)\mod_info.pdb" /map:"$(INTDIR)\mod_info.map" /machine:I386\
- /out:"$(OUTDIR)\mod_info.so" /implib:"$(OUTDIR)\mod_info.lib"\
- /base:@..\..\os\win32\BaseAddr.ref,mod_info
-LINK32_OBJS= \
- "$(INTDIR)\mod_info.obj" \
- "..\..\Release\libhttpd.lib" \
- "..\..\srclib\apr\Release\libapr.lib"
-
-"$(OUTDIR)\mod_info.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ELSEIF "$(CFG)" == "mod_info - Win32 Debug"
-
-OUTDIR=.\Debug
-INTDIR=.\Debug
-# Begin Custom Macros
-OutDir=.\Debug
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_info.so"
-
-!ELSE
-
-ALL : "libapr - Win32 Debug" "libhttpd - Win32 Debug" "$(OUTDIR)\mod_info.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libhttpd - Win32 DebugCLEAN" "libapr - Win32 DebugCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\mod_info.idb"
- -@erase "$(INTDIR)\mod_info.obj"
- -@erase "$(OUTDIR)\mod_info.exp"
- -@erase "$(OUTDIR)\mod_info.lib"
- -@erase "$(OUTDIR)\mod_info.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MDd /W3 /GX /Od /I "..\..\include" /I "..\..\os\win32" /I\
- "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D\
- "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_info" /FD /ZI /c
-CPP_OBJS=.\Debug/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_info.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no\
- /pdb:"$(OUTDIR)\mod_info.pdb" /machine:I386 /out:"$(OUTDIR)\mod_info.so"\
- /implib:"$(OUTDIR)\mod_info.lib" /map/debug\
- /base:@..\..\os\win32\BaseAddr.ref,mod_info
-LINK32_OBJS= \
- "$(INTDIR)\mod_info.obj" \
- "..\..\Debug\libhttpd.lib" \
- "..\..\srclib\apr\Debug\libapr.lib"
-
-"$(OUTDIR)\mod_info.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ENDIF
-
-
-!IF "$(CFG)" == "mod_info - Win32 Release" || "$(CFG)" ==\
- "mod_info - Win32 Debug"
-
-!IF "$(CFG)" == "mod_info - Win32 Release"
-
-"libhttpd - Win32 Release" :
- cd "\clean\httpd-2.0"
- $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release"
- cd ".\modules\generators"
-
-"libhttpd - Win32 ReleaseCLEAN" :
- cd "\clean\httpd-2.0"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F ".\libhttpd.mak"\
- CFG="libhttpd - Win32 Release" RECURSE=1
- cd ".\modules\generators"
-
-!ELSEIF "$(CFG)" == "mod_info - Win32 Debug"
-
-"libhttpd - Win32 Debug" :
- cd "\clean\httpd-2.0"
- $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug"
- cd ".\modules\generators"
-
-"libhttpd - Win32 DebugCLEAN" :
- cd "\clean\httpd-2.0"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug"\
- RECURSE=1
- cd ".\modules\generators"
-
-!ENDIF
-
-!IF "$(CFG)" == "mod_info - Win32 Release"
-
-"libapr - Win32 Release" :
- cd "\clean\httpd-2.0\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release"
- cd "..\..\modules\generators"
-
-"libapr - Win32 ReleaseCLEAN" :
- cd "\clean\httpd-2.0\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F ".\libapr.mak" CFG="libapr - Win32 Release"\
- RECURSE=1
- cd "..\..\modules\generators"
-
-!ELSEIF "$(CFG)" == "mod_info - Win32 Debug"
-
-"libapr - Win32 Debug" :
- cd "\clean\httpd-2.0\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug"
- cd "..\..\modules\generators"
-
-"libapr - Win32 DebugCLEAN" :
- cd "\clean\httpd-2.0\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F ".\libapr.mak" CFG="libapr - Win32 Debug"\
- RECURSE=1
- cd "..\..\modules\generators"
-
-!ENDIF
-
-SOURCE=.\mod_info.c
-DEP_CPP_MOD_I=\
- "..\..\include\ap_config.h"\
- "..\..\include\ap_mmn.h"\
- "..\..\include\ap_mpm.h"\
- "..\..\include\ap_release.h"\
- "..\..\include\http_config.h"\
- "..\..\include\http_core.h"\
- "..\..\include\http_log.h"\
- "..\..\include\http_main.h"\
- "..\..\include\http_protocol.h"\
- "..\..\include\httpd.h"\
- "..\..\include\pcreposix.h"\
- "..\..\include\util_cfgtree.h"\
- "..\..\include\util_filter.h"\
- "..\..\include\util_script.h"\
- "..\..\include\util_uri.h"\
- "..\..\os\win32\os.h"\
- "..\..\srclib\apr-util\include\apr_buckets.h"\
- "..\..\srclib\apr-util\include\apr_hooks.h"\
- "..\..\srclib\apr-util\include\apr_ring.h"\
- "..\..\srclib\apr-util\include\apu.h"\
- "..\..\srclib\apr\include\apr.h"\
- "..\..\srclib\apr\include\apr_dso.h"\
- "..\..\srclib\apr\include\apr_errno.h"\
- "..\..\srclib\apr\include\apr_file_info.h"\
- "..\..\srclib\apr\include\apr_file_io.h"\
- "..\..\srclib\apr\include\apr_general.h"\
- "..\..\srclib\apr\include\apr_lib.h"\
- "..\..\srclib\apr\include\apr_lock.h"\
- "..\..\srclib\apr\include\apr_mmap.h"\
- "..\..\srclib\apr\include\apr_network_io.h"\
- "..\..\srclib\apr\include\apr_pools.h"\
- "..\..\srclib\apr\include\apr_portable.h"\
- "..\..\srclib\apr\include\apr_strings.h"\
- "..\..\srclib\apr\include\apr_tables.h"\
- "..\..\srclib\apr\include\apr_thread_proc.h"\
- "..\..\srclib\apr\include\apr_time.h"\
- "..\..\srclib\apr\include\apr_user.h"\
- "..\..\srclib\apr\include\apr_want.h"\
-
-NODEP_CPP_MOD_I=\
- "..\..\include\ap_config_auto.h"\
-
-
-"$(INTDIR)\mod_info.obj" : $(SOURCE) $(DEP_CPP_MOD_I) "$(INTDIR)"
-
-
-
-!ENDIF
-
diff --git a/modules/generators/mod_status.c b/modules/generators/mod_status.c
deleted file mode 100644
index 17f07e888f..0000000000
--- a/modules/generators/mod_status.c
+++ /dev/null
@@ -1,787 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/* Status Module. Display lots of internal data about how Apache is
- * performing and the state of all children processes.
- *
- * To enable this, add the following lines into any config file:
- *
- * <Location /server-status>
- * SetHandler server-status
- * </Location>
- *
- * You may want to protect this location by password or domain so no one
- * else can look at it. Then you can access the statistics with a URL like:
- *
- * http://your_server_name/server-status
- *
- * /server-status - Returns page using tables
- * /server-status?notable - Returns page for browsers without table support
- * /server-status?refresh - Returns page with 1 second refresh
- * /server-status?refresh=6 - Returns page with refresh every 6 seconds
- * /server-status?auto - Returns page with data for automatic parsing
- *
- * Mark Cox, mark@ukweb.com, November 1995
- *
- * 12.11.95 Initial version for www.telescope.org
- * 13.3.96 Updated to remove rprintf's [Mark]
- * 18.3.96 Added CPU usage, process information, and tidied [Ben Laurie]
- * 18.3.96 Make extra Scoreboard variables #definable
- * 25.3.96 Make short report have full precision [Ben Laurie suggested]
- * 25.3.96 Show uptime better [Mark/Ben Laurie]
- * 29.3.96 Better HTML and explanation [Mark/Rob Hartill suggested]
- * 09.4.96 Added message for non-STATUS compiled version
- * 18.4.96 Added per child and per slot counters [Jim Jagielski]
- * 01.5.96 Table format, cleanup, even more spiffy data [Chuck Murcko/Jim J.]
- * 18.5.96 Adapted to use new rprintf() routine, incidentally fixing a missing
- * piece in short reports [Ben Laurie]
- * 21.5.96 Additional Status codes (DNS and LOGGING only enabled if
- * extended STATUS is enabled) [George Burgyan/Jim J.]
- * 10.8.98 Allow for extended status info at runtime (no more STATUS)
- * [Jim J.]
- */
-
-#define CORE_PRIVATE
-#include "httpd.h"
-#include "http_config.h"
-#include "http_core.h"
-#include "http_protocol.h"
-#include "http_main.h"
-#include "util_script.h"
-#include <time.h>
-#include "scoreboard.h"
-#include "http_log.h"
-#if APR_HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#ifdef NEXT
-#if (NX_CURRENT_COMPILER_RELEASE == 410)
-#ifdef m68k
-#define HZ 64
-#else
-#define HZ 100
-#endif
-#else
-#include <machine/param.h>
-#endif
-#endif /* NEXT */
-
-#define STATUS_MAXLINE 64
-
-#define KBYTE 1024
-#define MBYTE 1048576L
-#define GBYTE 1073741824L
-
-#ifndef DEFAULT_TIME_FORMAT
-#define DEFAULT_TIME_FORMAT "%A, %d-%b-%Y %H:%M:%S %Z"
-#endif
-
-#define STATUS_MAGIC_TYPE "application/x-httpd-status"
-
-module AP_MODULE_DECLARE_DATA status_module;
-
-/*
- *command-related code. This is here to prevent use of ExtendedStatus
- * without status_module included.
- */
-static const char *set_extended_status(cmd_parms *cmd, void *dummy, int arg)
-{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
- ap_extended_status = arg;
- return NULL;
-}
-
-static const command_rec status_module_cmds[] =
-{
- AP_INIT_FLAG("ExtendedStatus", set_extended_status, NULL, RSRC_CONF,
- "\"On\" to enable extended status information, \"Off\" to disable"),
- {NULL}
-};
-
-/* Format the number of bytes nicely */
-static void format_byte_out(request_rec *r, unsigned long bytes)
-{
- if (bytes < (5 * KBYTE))
- ap_rprintf(r, "%d B", (int) bytes);
- else if (bytes < (MBYTE / 2))
- ap_rprintf(r, "%.1f kB", (float) bytes / KBYTE);
- else if (bytes < (GBYTE / 2))
- ap_rprintf(r, "%.1f MB", (float) bytes / MBYTE);
- else
- ap_rprintf(r, "%.1f GB", (float) bytes / GBYTE);
-}
-
-static void format_kbyte_out(request_rec *r, unsigned long kbytes)
-{
- if (kbytes < KBYTE)
- ap_rprintf(r, "%d kB", (int) kbytes);
- else if (kbytes < MBYTE)
- ap_rprintf(r, "%.1f MB", (float) kbytes / KBYTE);
- else
- ap_rprintf(r, "%.1f GB", (float) kbytes / MBYTE);
-}
-
-static void show_time(request_rec *r, apr_interval_time_t tsecs)
-{
- int days, hrs, mins, secs;
-
- secs = tsecs % 60;
- tsecs /= 60;
- mins = tsecs % 60;
- tsecs /= 60;
- hrs = tsecs % 24;
- days = tsecs / 24;
- if (days)
- ap_rprintf(r, " %d day%s", days, days == 1 ? "" : "s");
- if (hrs)
- ap_rprintf(r, " %d hour%s", hrs, hrs == 1 ? "" : "s");
- if (mins)
- ap_rprintf(r, " %d minute%s", mins, mins == 1 ? "" : "s");
- if (secs)
- ap_rprintf(r, " %d second%s", secs, secs == 1 ? "" : "s");
-}
-
-/* Main handler for x-httpd-status requests */
-
-/* ID values for command table */
-
-#define STAT_OPT_END -1
-#define STAT_OPT_REFRESH 0
-#define STAT_OPT_NOTABLE 1
-#define STAT_OPT_AUTO 2
-
-struct stat_opt {
- int id;
- const char *form_data_str;
- const char *hdr_out_str;
-};
-
-static const struct stat_opt status_options[] = /* see #defines above */
-{
- {STAT_OPT_REFRESH, "refresh", "Refresh"},
- {STAT_OPT_NOTABLE, "notable", NULL},
- {STAT_OPT_AUTO, "auto", NULL},
- {STAT_OPT_END, NULL, NULL}
-};
-
-static char status_flags[SERVER_NUM_STATUS];
-
-static int status_handler(request_rec *r)
-{
- const char *loc;
- apr_time_t nowtime;
- apr_interval_time_t up_time;
- int j, i, res;
- int ready = 0;
- int busy = 0;
- unsigned long count = 0;
- unsigned long lres, bytes;
- unsigned long my_lres, my_bytes, conn_bytes;
- unsigned short conn_lres;
- unsigned long bcount = 0;
- unsigned long kbcount = 0;
- long req_time;
-#ifdef HAVE_TIMES
-#ifdef _SC_CLK_TCK
- float tick = sysconf(_SC_CLK_TCK);
-#else
- float tick = HZ;
-#endif
-#endif
- int short_report = 0;
- int no_table_report = 0;
- short_score score_record;
- parent_score ps_record;
- char stat_buffer[HARD_SERVER_LIMIT * HARD_THREAD_LIMIT];
- int pid_buffer[HARD_SERVER_LIMIT * HARD_THREAD_LIMIT];
- clock_t tu, ts, tcu, tcs;
- server_rec *vhost;
-
- if (strcmp(r->handler, STATUS_MAGIC_TYPE) && strcmp(r->handler, "server-status")) {
- return DECLINED;
- }
-
- nowtime = apr_time_now();
- tu = ts = tcu = tcs = 0;
-
- if (!ap_exists_scoreboard_image()) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Server status unavailable in inetd mode");
- return HTTP_INTERNAL_SERVER_ERROR;
- }
- r->allowed = (1 << M_GET);
- if (r->method_number != M_GET)
- return DECLINED;
-
- r->content_type = "text/html";
-
- /*
- * Simple table-driven form data set parser that lets you alter the header
- */
-
- if (r->args) {
- i = 0;
- while (status_options[i].id != STAT_OPT_END) {
- if ((loc = ap_strstr_c(r->args, status_options[i].form_data_str)) != NULL) {
- switch (status_options[i].id) {
- case STAT_OPT_REFRESH:
- if (*(loc + strlen(status_options[i].form_data_str)) == '='
- && atol(loc + strlen(status_options[i].form_data_str)
- + 1) > 0)
- apr_table_set(r->headers_out,
- status_options[i].hdr_out_str,
- loc + strlen(status_options[i].hdr_out_str) + 1);
- else
- apr_table_set(r->headers_out,
- status_options[i].hdr_out_str, "1");
- break;
- case STAT_OPT_NOTABLE:
- no_table_report = 1;
- break;
- case STAT_OPT_AUTO:
- r->content_type = "text/plain";
- short_report = 1;
- break;
- }
- }
- i++;
- }
- }
-
- if (r->header_only)
- return 0;
-
-/* ap_sync_scoreboard_image(); */
- for (i = 0; i < HARD_SERVER_LIMIT; ++i) {
- for (j = 0; j < HARD_THREAD_LIMIT; ++j) {
- int indx = (i * HARD_THREAD_LIMIT) + j;
-
- score_record = ap_scoreboard_image->servers[i][j];
- ps_record = ap_scoreboard_image->parent[i];
- res = score_record.status;
- stat_buffer[indx] = status_flags[res];
- pid_buffer[indx] = (int) ps_record.pid;
- if (res == SERVER_READY)
- ready++;
- else if (res != SERVER_DEAD)
- busy++;
- if (ap_extended_status) {
- lres = score_record.access_count;
- bytes = score_record.bytes_served;
- if (lres != 0 || (res != SERVER_READY && res != SERVER_DEAD)) {
-#ifdef HAVE_TIMES
- tu += score_record.times.tms_utime;
- ts += score_record.times.tms_stime;
- tcu += score_record.times.tms_cutime;
- tcs += score_record.times.tms_cstime;
-#endif /* HAVE_TIMES */
- count += lres;
- bcount += bytes;
- if (bcount >= KBYTE) {
- kbcount += (bcount >> 10);
- bcount = bcount & 0x3ff;
- }
- }
- }
- }
- }
-
- /* up_time in seconds */
- up_time = (apr_uint32_t) ((nowtime - ap_restart_time)/1000000);
-
- if (!short_report) {
- ap_rputs(DOCTYPE_HTML_3_2
- "<HTML><HEAD>\n<TITLE>Apache Status</TITLE>\n</HEAD><BODY>\n",
- r);
- ap_rputs("<H1>Apache Server Status for ", r);
- ap_rvputs(r, ap_get_server_name(r), "</H1>\n\n", NULL);
- ap_rvputs(r, "Server Version: ",
- ap_get_server_version(), "<br>\n", NULL);
- ap_rvputs(r, "Server Built: ",
- ap_get_server_built(), "<br>\n<hr>\n", NULL);
- ap_rvputs(r, "Current Time: ",
- ap_ht_time(r->pool, nowtime, DEFAULT_TIME_FORMAT, 0), "<br>\n", NULL);
- ap_rvputs(r, "Restart Time: ",
- ap_ht_time(r->pool, ap_restart_time, DEFAULT_TIME_FORMAT, 0),
- "<br>\n", NULL);
- ap_rprintf(r, "Parent Server Generation: %d <br>\n", (int) ap_my_generation);
- ap_rputs("Server uptime: ", r);
- show_time(r, up_time);
- ap_rputs("<br>\n", r);
- }
-
- if (ap_extended_status) {
- if (short_report) {
- ap_rprintf(r, "Total Accesses: %lu\nTotal kBytes: %lu\n",
- count, kbcount);
-
-#ifdef HAVE_TIMES
- /* Allow for OS/2 not having CPU stats */
- if (ts || tu || tcu || tcs)
- ap_rprintf(r, "CPULoad: %g\n",
- (tu + ts + tcu + tcs) / tick / up_time * 100.);
-#endif
-
- ap_rprintf(r, "Uptime: %ld\n", (long) (up_time));
- if (up_time > 0)
- ap_rprintf(r, "ReqPerSec: %g\n",
- (float) count / (float) up_time);
-
- if (up_time > 0)
- ap_rprintf(r, "BytesPerSec: %g\n",
- KBYTE * (float) kbcount / (float) up_time);
-
- if (count > 0)
- ap_rprintf(r, "BytesPerReq: %g\n",
- KBYTE * (float) kbcount / (float) count);
- }
- else { /* !short_report */
- ap_rprintf(r, "Total accesses: %lu - Total Traffic: ", count);
- format_kbyte_out(r, kbcount);
-
-#ifdef HAVE_TIMES
- /* Allow for OS/2 not having CPU stats */
- ap_rputs("<br>\n", r);
- ap_rprintf(r, "CPU Usage: u%g s%g cu%g cs%g",
- tu / tick, ts / tick, tcu / tick, tcs / tick);
-
- if (ts || tu || tcu || tcs)
- ap_rprintf(r, " - %.3g%% CPU load",
- (tu + ts + tcu + tcs) / tick / up_time * 100.);
-#endif
-
- ap_rputs("<br>\n", r);
-
- if (up_time > 0)
- ap_rprintf(r, "%.3g requests/sec - ",
- (float) count / (float) up_time);
-
- if (up_time > 0) {
- format_byte_out(r, KBYTE * (float) kbcount / (float) up_time);
- ap_rputs("/second - ", r);
- }
-
- if (count > 0) {
- format_byte_out(r, KBYTE * (float) kbcount / (float) count);
- ap_rputs("/request", r);
- }
-
- ap_rputs("<br>\n", r);
- } /* short_report */
- } /* ap_extended_status */
-
- if (!short_report)
- ap_rprintf(r, "\n%d requests currently being processed, %d idle servers\n"
- ,busy, ready);
- else
- ap_rprintf(r, "BusyServers: %d\nIdleServers: %d\n", busy, ready);
-
- /* send the scoreboard 'table' out */
-
- if (!short_report)
- ap_rputs("<PRE>", r);
- else
- ap_rputs("Scoreboard: ", r);
-
- for (i = 0; i < HARD_SERVER_LIMIT; ++i) {
- for (j = 0; j < HARD_THREAD_LIMIT; ++j) {
- int indx = (i * HARD_THREAD_LIMIT) + j;
- ap_rputc(stat_buffer[indx], r);
- if ((indx % STATUS_MAXLINE == (STATUS_MAXLINE - 1)) && !short_report)
- ap_rputs("\n", r);
- }
- }
-
- if (short_report)
- ap_rputs("\n", r);
- else {
- ap_rputs("</PRE>\n", r);
- ap_rputs("Scoreboard Key: <br>\n", r);
- ap_rputs("\"<B><code>_</code></B>\" Waiting for Connection, \n", r);
- ap_rputs("\"<B><code>S</code></B>\" Starting up, \n", r);
- ap_rputs("\"<B><code>R</code></B>\" Reading Request,<BR>\n", r);
- ap_rputs("\"<B><code>W</code></B>\" Sending Reply, \n", r);
- ap_rputs("\"<B><code>K</code></B>\" Keepalive (read), \n", r);
- ap_rputs("\"<B><code>D</code></B>\" DNS Lookup,<BR>\n", r);
- ap_rputs("\"<B><code>L</code></B>\" Logging, \n", r);
- ap_rputs("\"<B><code>G</code></B>\" Gracefully finishing, \n", r);
- ap_rputs("\"<B><code>I</code></B>\" Idle cleanup of worker, \n", r);
- ap_rputs("\"<B><code>.</code></B>\" Open slot with no current process<P>\n", r);
- ap_rputs("<P>\n", r);
- if (!ap_extended_status) {
- int j;
- int k = 0;
- ap_rputs("PID Key: <br>\n", r);
- ap_rputs("<PRE>\n", r);
- for (i = 0; i < HARD_SERVER_LIMIT; ++i) {
- for (j = 0; j < HARD_THREAD_LIMIT; ++j) {
- int indx = (i * HARD_THREAD_LIMIT) + j;
-
- if (stat_buffer[indx] != '.') {
- ap_rprintf(r, " %d in state: %c ", pid_buffer[i],
- stat_buffer[indx]);
- if (++k >= 3) {
- ap_rputs("\n", r);
- k = 0;
- } else
- ap_rputs(",", r);
- }
- }
- }
- ap_rputs("\n", r);
- ap_rputs("</PRE>\n", r);
- }
- }
-
- if (ap_extended_status) {
- if (!short_report) {
- if (no_table_report)
- ap_rputs("<p><hr><h2>Server Details</h2>\n\n", r);
- else
-#ifndef HAVE_TIMES
- /* Allow for OS/2 not having CPU stats */
- ap_rputs("<p>\n\n<table border=0><tr><th>Srv<th>PID<th>Acc<th>M\n<th>SS<th>Req<th>Conn<th>Child<th>Slot<th>Client<th>VHost<th>Request</tr>\n\n", r);
-#else
- ap_rputs("<p>\n\n<table border=0><tr><th>Srv<th>PID<th>Acc<th>M<th>CPU\n<th>SS<th>Req<th>Conn<th>Child<th>Slot<th>Client<th>VHost<th>Request</tr>\n\n", r);
-#endif
- }
-
- for (i = 0; i < HARD_SERVER_LIMIT; ++i) {
- for (j = 0; j < HARD_THREAD_LIMIT; ++j) {
- score_record = ap_scoreboard_image->servers[i][j];
- ps_record = ap_scoreboard_image->parent[i];
- vhost = score_record.vhostrec;
- if (ps_record.generation != ap_my_generation) {
- vhost = NULL;
- }
-
-
-#if defined(NO_GETTIMEOFDAY)
-#ifdef HAVE_TIMES
- if (score_record.start_time == (clock_t) 0)
-#endif /* HAVE_TIMES */
- req_time = 0L;
-#ifdef HAVE_TIMES
- else {
- req_time = score_record.stop_time - score_record.start_time;
- req_time = (req_time * 1000) / (int) tick;
- }
-#endif /* HAVE_TIMES */
-#else
- if (score_record.start_time == 0L &&
- score_record.start_time == 0L)
- req_time = 0L;
- else
- req_time =
- ((score_record.stop_time - score_record.start_time) * 1000) +
- ((score_record.stop_time - score_record.start_time) / 1000);
-#endif
- if (req_time < 0L)
- req_time = 0L;
-
- lres = score_record.access_count;
- my_lres = score_record.my_access_count;
- conn_lres = score_record.conn_count;
- bytes = score_record.bytes_served;
- my_bytes = score_record.my_bytes_served;
- conn_bytes = score_record.conn_bytes;
- if (lres != 0 || (score_record.status != SERVER_READY
- && score_record.status != SERVER_DEAD)) {
- if (!short_report) {
- if (no_table_report) {
- if (score_record.status == SERVER_DEAD)
- ap_rprintf(r,
- "<b>Server %d-%d</b> (-): %d|%lu|%lu [",
- i, (int) ps_record.generation, (int) conn_lres,
- my_lres, lres);
- else
- ap_rprintf(r,
- "<b>Server %d-%d</b> (%d): %d|%lu|%lu [",
- i, (int) ps_record.generation,
- (int) ps_record.pid,
- (int) conn_lres, my_lres, lres);
-
- switch (score_record.status) {
- case SERVER_READY:
- ap_rputs("Ready", r);
- break;
- case SERVER_STARTING:
- ap_rputs("Starting", r);
- break;
- case SERVER_BUSY_READ:
- ap_rputs("<b>Read</b>", r);
- break;
- case SERVER_BUSY_WRITE:
- ap_rputs("<b>Write</b>", r);
- break;
- case SERVER_BUSY_KEEPALIVE:
- ap_rputs("<b>Keepalive</b>", r);
- break;
- case SERVER_BUSY_LOG:
- ap_rputs("<b>Logging</b>", r);
- break;
- case SERVER_BUSY_DNS:
- ap_rputs("<b>DNS lookup</b>", r);
- break;
- case SERVER_DEAD:
- ap_rputs("Dead", r);
- break;
- case SERVER_GRACEFUL:
- ap_rputs("Graceful", r);
- break;
- default:
- ap_rputs("?STATE?", r);
- break;
- }
-#ifndef HAVE_TIMES
- /* Allow for OS/2 not having CPU stats */
- ap_rprintf(r, "]\n %.0f %ld (",
-#else
-
- ap_rprintf(r, "] u%g s%g cu%g cs%g\n %.0f %ld (",
- score_record.times.tms_utime / tick,
- score_record.times.tms_stime / tick,
- score_record.times.tms_cutime / tick,
- score_record.times.tms_cstime / tick,
-#endif
-#ifdef OPTIMIZE_TIMEOUTS
- difftime(nowtime, ps_record.last_rtime),
-#else
- difftime(nowtime, score_record.last_used),
-#endif
- (long) req_time);
- format_byte_out(r, conn_bytes);
- ap_rputs("|", r);
- format_byte_out(r, my_bytes);
- ap_rputs("|", r);
- format_byte_out(r, bytes);
- ap_rputs(")\n", r);
- ap_rprintf(r, " <i>%s {%s}</i> <b>[%s]</b><br>\n\n",
- ap_escape_html(r->pool, score_record.client),
- ap_escape_html(r->pool, score_record.request),
- vhost ? ap_escape_html(r->pool,
- vhost->server_hostname) : "(unavailable)");
- }
- else { /* !no_table_report */
- if (score_record.status == SERVER_DEAD)
- ap_rprintf(r,
- "<tr><td><b>%d-%d</b><td>-<td>%d/%lu/%lu",
- i, (int) ps_record.generation,
- (int) conn_lres, my_lres, lres);
- else
- ap_rprintf(r,
- "<tr><td><b>%d-%d</b><td>%d<td>%d/%lu/%lu",
- i, (int) ps_record.generation,
- (int) ps_record.pid, (int) conn_lres,
- my_lres, lres);
-
- switch (score_record.status) {
- case SERVER_READY:
- ap_rputs("<td>_", r);
- break;
- case SERVER_STARTING:
- ap_rputs("<td><b>S</b>", r);
- break;
- case SERVER_BUSY_READ:
- ap_rputs("<td><b>R</b>", r);
- break;
- case SERVER_BUSY_WRITE:
- ap_rputs("<td><b>W</b>", r);
- break;
- case SERVER_BUSY_KEEPALIVE:
- ap_rputs("<td><b>K</b>", r);
- break;
- case SERVER_BUSY_LOG:
- ap_rputs("<td><b>L</b>", r);
- break;
- case SERVER_BUSY_DNS:
- ap_rputs("<td><b>D</b>", r);
- break;
- case SERVER_DEAD:
- ap_rputs("<td>.", r);
- break;
- case SERVER_GRACEFUL:
- ap_rputs("<td>G", r);
- break;
- default:
- ap_rputs("<td>?", r);
- break;
- }
-#ifndef HAVE_TIMES
- /* Allow for OS/2 not having CPU stats */
- ap_rprintf(r, "\n<td>%.0f<td>%ld",
-#else
- ap_rprintf(r, "\n<td>%.2f<td>%.0f<td>%ld",
- (score_record.times.tms_utime +
- score_record.times.tms_stime +
- score_record.times.tms_cutime +
- score_record.times.tms_cstime) / tick,
-#endif
-#ifdef OPTIMIZE_TIMEOUTS
- difftime(nowtime, ps_record.last_rtime),
-#else
- difftime(nowtime, score_record.last_used),
-#endif
- (long) req_time);
- ap_rprintf(r, "<td>%-1.1f<td>%-2.2f<td>%-2.2f\n",
- (float) conn_bytes / KBYTE, (float) my_bytes / MBYTE,
- (float) bytes / MBYTE);
- if (score_record.status == SERVER_BUSY_READ)
- ap_rprintf(r,
- "<td>?<td nowrap>?<td nowrap>..reading.. </tr>\n\n");
- else
- ap_rprintf(r,
- "<td>%s<td nowrap>%s<td nowrap>%s</tr>\n\n",
- ap_escape_html(r->pool, score_record.client),
- vhost ? ap_escape_html(r->pool,
- vhost->server_hostname) : "(unavailable)",
- ap_escape_html(r->pool, score_record.request));
- } /* no_table_report */
- } /* !short_report */
- } /* if (<active child>) */
- } /* for () */
- }
-
- if (!(short_report || no_table_report)) {
-#ifndef HAVE_TIMES
- ap_rputs("</table>\n \
-<hr> \
-<table>\n \
-<tr><th>Srv<td>Child Server number - generation\n \
-<tr><th>PID<td>OS process ID\n \
-<tr><th>Acc<td>Number of accesses this connection / this child / this slot\n \
-<tr><th>M<td>Mode of operation\n \
-<tr><th>SS<td>Seconds since beginning of most recent request\n \
-<tr><th>Req<td>Milliseconds required to process most recent request\n \
-<tr><th>Conn<td>Kilobytes transferred this connection\n \
-<tr><th>Child<td>Megabytes transferred this child\n \
-<tr><th>Slot<td>Total megabytes transferred this slot\n \
-</table>\n", r);
-#else
- ap_rputs("</table>\n \
-<hr> \
-<table>\n \
-<tr><th>Srv<td>Child Server number - generation\n \
-<tr><th>PID<td>OS process ID\n \
-<tr><th>Acc<td>Number of accesses this connection / this child / this slot\n \
-<tr><th>M<td>Mode of operation\n \
-<tr><th>CPU<td>CPU usage, number of seconds\n \
-<tr><th>SS<td>Seconds since beginning of most recent request\n \
-<tr><th>Req<td>Milliseconds required to process most recent request\n \
-<tr><th>Conn<td>Kilobytes transferred this connection\n \
-<tr><th>Child<td>Megabytes transferred this child\n \
-<tr><th>Slot<td>Total megabytes transferred this slot\n \
-</table>\n", r);
-#endif
- }
-
- } else {
-
- if (!short_report) {
- ap_rputs("<hr>To obtain a full report with current status information ", r);
- ap_rputs("you need to use the <code>ExtendedStatus On</code> directive. \n", r);
- }
-
- }
-
- if (!short_report) {
- ap_rputs(ap_psignature("<HR>\n",r), r);
- ap_rputs("</BODY></HTML>\n", r);
- }
-
- return 0;
-}
-
-
-static void status_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
-{
- status_flags[SERVER_DEAD] = '.'; /* We don't want to assume these are in */
- status_flags[SERVER_READY] = '_'; /* any particular order in scoreboard.h */
- status_flags[SERVER_STARTING] = 'S';
- status_flags[SERVER_BUSY_READ] = 'R';
- status_flags[SERVER_BUSY_WRITE] = 'W';
- status_flags[SERVER_BUSY_KEEPALIVE] = 'K';
- status_flags[SERVER_BUSY_LOG] = 'L';
- status_flags[SERVER_BUSY_DNS] = 'D';
- status_flags[SERVER_GRACEFUL] = 'G';
- status_flags[SERVER_IDLE_KILL] = 'I';
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_handler(status_handler, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_post_config(status_init, NULL, NULL, APR_HOOK_MIDDLE);
-}
-
-module AP_MODULE_DECLARE_DATA status_module =
-{
- STANDARD20_MODULE_STUFF,
- NULL, /* dir config creater */
- NULL, /* dir merger --- default is to override */
- NULL, /* server config */
- NULL, /* merge server config */
- status_module_cmds, /* command table */
- register_hooks /* register_hooks */
-};
-
diff --git a/modules/generators/mod_status.dsp b/modules/generators/mod_status.dsp
deleted file mode 100644
index 01e117238b..0000000000
--- a/modules/generators/mod_status.dsp
+++ /dev/null
@@ -1,95 +0,0 @@
-# Microsoft Developer Studio Project File - Name="mod_status" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=mod_status - Win32 Release
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "mod_status.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_status.mak" CFG="mod_status - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_status - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_status - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "mod_status - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\os\win32" /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /I "../../server/mpm/winnt" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_status" /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "NDEBUG"
-# ADD RSC /l 0x809 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /map /machine:I386 /out:"Release/mod_status.so" /base:@..\..\os\win32\BaseAddr.ref,mod_status
-# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /map /machine:I386 /out:"Release/mod_status.so" /base:@..\..\os\win32\BaseAddr.ref,mod_status
-
-!ELSEIF "$(CFG)" == "mod_status - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\..\include" /I "..\..\os\win32" /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /I "../../server/mpm/winnt" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_status" /FD /c
-# ADD BASE MTL /nologo /D "_DEBUG" /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "_DEBUG"
-# ADD RSC /l 0x809 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /out:"Debug/mod_status.so" /base:@..\..\os\win32\BaseAddr.ref,mod_status
-# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /out:"Debug/mod_status.so" /base:@..\..\os\win32\BaseAddr.ref,mod_status
-
-!ENDIF
-
-# Begin Target
-
-# Name "mod_status - Win32 Release"
-# Name "mod_status - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\mod_status.c
-# End Source File
-# End Target
-# End Project
diff --git a/modules/generators/mod_status.exp b/modules/generators/mod_status.exp
deleted file mode 100644
index 5438093686..0000000000
--- a/modules/generators/mod_status.exp
+++ /dev/null
@@ -1 +0,0 @@
-status_module
diff --git a/modules/generators/mod_status.mak b/modules/generators/mod_status.mak
deleted file mode 100644
index ec22087ff3..0000000000
--- a/modules/generators/mod_status.mak
+++ /dev/null
@@ -1,330 +0,0 @@
-# Microsoft Developer Studio Generated NMAKE File, Based on mod_status.dsp
-!IF "$(CFG)" == ""
-CFG=mod_status - Win32 Release
-!MESSAGE No configuration specified. Defaulting to mod_status - Win32 Release.
-!ENDIF
-
-!IF "$(CFG)" != "mod_status - Win32 Release" && "$(CFG)" !=\
- "mod_status - Win32 Debug"
-!MESSAGE Invalid configuration "$(CFG)" specified.
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_status.mak" CFG="mod_status - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_status - Win32 Release" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_status - Win32 Debug" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-!ERROR An invalid configuration is specified.
-!ENDIF
-
-!IF "$(OS)" == "Windows_NT"
-NULL=
-!ELSE
-NULL=nul
-!ENDIF
-
-!IF "$(CFG)" == "mod_status - Win32 Release"
-
-OUTDIR=.\Release
-INTDIR=.\Release
-# Begin Custom Macros
-OutDir=.\Release
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_status.so"
-
-!ELSE
-
-ALL : "libhttpd - Win32 Release" "libapr - Win32 Release"\
- "$(OUTDIR)\mod_status.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libapr - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\mod_status.idb"
- -@erase "$(INTDIR)\mod_status.obj"
- -@erase "$(OUTDIR)\mod_status.exp"
- -@erase "$(OUTDIR)\mod_status.lib"
- -@erase "$(OUTDIR)\mod_status.map"
- -@erase "$(OUTDIR)\mod_status.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\os\win32" /I\
- "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /I\
- "../../server/mpm/winnt" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\"\
- /Fd"$(INTDIR)\mod_status" /FD /c
-CPP_OBJS=.\Release/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_status.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no\
- /pdb:"$(OUTDIR)\mod_status.pdb" /map:"$(INTDIR)\mod_status.map" /machine:I386\
- /out:"$(OUTDIR)\mod_status.so" /implib:"$(OUTDIR)\mod_status.lib"\
- /base:@..\..\os\win32\BaseAddr.ref,mod_status
-LINK32_OBJS= \
- "$(INTDIR)\mod_status.obj" \
- "..\..\Release\libhttpd.lib" \
- "..\..\srclib\apr\Release\libapr.lib"
-
-"$(OUTDIR)\mod_status.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ELSEIF "$(CFG)" == "mod_status - Win32 Debug"
-
-OUTDIR=.\Debug
-INTDIR=.\Debug
-# Begin Custom Macros
-OutDir=.\Debug
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_status.so"
-
-!ELSE
-
-ALL : "libhttpd - Win32 Debug" "libapr - Win32 Debug" "$(OUTDIR)\mod_status.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libapr - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\mod_status.idb"
- -@erase "$(INTDIR)\mod_status.obj"
- -@erase "$(OUTDIR)\mod_status.exp"
- -@erase "$(OUTDIR)\mod_status.lib"
- -@erase "$(OUTDIR)\mod_status.map"
- -@erase "$(OUTDIR)\mod_status.pdb"
- -@erase "$(OUTDIR)\mod_status.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /I\
- "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /I\
- "../../server/mpm/winnt" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\"\
- /Fd"$(INTDIR)\mod_status" /FD /c
-CPP_OBJS=.\Debug/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_status.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no\
- /pdb:"$(OUTDIR)\mod_status.pdb" /map:"$(INTDIR)\mod_status.map" /debug\
- /machine:I386 /out:"$(OUTDIR)\mod_status.so" /implib:"$(OUTDIR)\mod_status.lib"\
- /base:@..\..\os\win32\BaseAddr.ref,mod_status
-LINK32_OBJS= \
- "$(INTDIR)\mod_status.obj" \
- "..\..\Debug\libhttpd.lib" \
- "..\..\srclib\apr\Debug\libapr.lib"
-
-"$(OUTDIR)\mod_status.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ENDIF
-
-
-!IF "$(CFG)" == "mod_status - Win32 Release" || "$(CFG)" ==\
- "mod_status - Win32 Debug"
-
-!IF "$(CFG)" == "mod_status - Win32 Release"
-
-"libapr - Win32 Release" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F .\libapr.mak CFG="libapr - Win32 Release"
- cd "..\..\modules\generators"
-
-"libapr - Win32 ReleaseCLEAN" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libapr.mak CFG="libapr - Win32 Release"\
- RECURSE=1
- cd "..\..\modules\generators"
-
-!ELSEIF "$(CFG)" == "mod_status - Win32 Debug"
-
-"libapr - Win32 Debug" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F .\libapr.mak CFG="libapr - Win32 Debug"
- cd "..\..\modules\generators"
-
-"libapr - Win32 DebugCLEAN" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libapr.mak CFG="libapr - Win32 Debug"\
- RECURSE=1
- cd "..\..\modules\generators"
-
-!ENDIF
-
-!IF "$(CFG)" == "mod_status - Win32 Release"
-
-"libhttpd - Win32 Release" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) /F .\libhttpd.mak CFG="libhttpd - Win32 Release"
- cd ".\modules\generators"
-
-"libhttpd - Win32 ReleaseCLEAN" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libhttpd.mak CFG="libhttpd - Win32 Release"\
- RECURSE=1
- cd ".\modules\generators"
-
-!ELSEIF "$(CFG)" == "mod_status - Win32 Debug"
-
-"libhttpd - Win32 Debug" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) /F .\libhttpd.mak CFG="libhttpd - Win32 Debug"
- cd ".\modules\generators"
-
-"libhttpd - Win32 DebugCLEAN" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libhttpd.mak CFG="libhttpd - Win32 Debug"\
- RECURSE=1
- cd ".\modules\generators"
-
-!ENDIF
-
-SOURCE=.\mod_status.c
-DEP_CPP_MOD_S=\
- "..\..\include\ap_config.h"\
- "..\..\include\ap_mmn.h"\
- "..\..\include\ap_release.h"\
- "..\..\include\http_config.h"\
- "..\..\include\http_core.h"\
- "..\..\include\http_log.h"\
- "..\..\include\http_main.h"\
- "..\..\include\http_protocol.h"\
- "..\..\include\httpd.h"\
- "..\..\include\pcreposix.h"\
- "..\..\include\scoreboard.h"\
- "..\..\include\util_cfgtree.h"\
- "..\..\include\util_filter.h"\
- "..\..\include\util_script.h"\
- "..\..\include\util_uri.h"\
- "..\..\os\win32\os.h"\
- "..\..\server\mpm\winnt\mpm_default.h"\
- "..\..\srclib\apr-util\include\apr_buckets.h"\
- "..\..\srclib\apr-util\include\apr_hooks.h"\
- "..\..\srclib\apr-util\include\apr_ring.h"\
- "..\..\srclib\apr-util\include\apu.h"\
- "..\..\srclib\apr\include\apr.h"\
- "..\..\srclib\apr\include\apr_dso.h"\
- "..\..\srclib\apr\include\apr_errno.h"\
- "..\..\srclib\apr\include\apr_file_info.h"\
- "..\..\srclib\apr\include\apr_file_io.h"\
- "..\..\srclib\apr\include\apr_general.h"\
- "..\..\srclib\apr\include\apr_lock.h"\
- "..\..\srclib\apr\include\apr_mmap.h"\
- "..\..\srclib\apr\include\apr_network_io.h"\
- "..\..\srclib\apr\include\apr_pools.h"\
- "..\..\srclib\apr\include\apr_portable.h"\
- "..\..\srclib\apr\include\apr_tables.h"\
- "..\..\srclib\apr\include\apr_thread_proc.h"\
- "..\..\srclib\apr\include\apr_time.h"\
- "..\..\srclib\apr\include\apr_user.h"\
- "..\..\srclib\apr\include\apr_want.h"\
-
-NODEP_CPP_MOD_S=\
- "..\..\include\ap_config_auto.h"\
-
-
-"$(INTDIR)\mod_status.obj" : $(SOURCE) $(DEP_CPP_MOD_S) "$(INTDIR)"
-
-
-
-!ENDIF
-
diff --git a/modules/generators/mod_suexec.c b/modules/generators/mod_suexec.c
deleted file mode 100644
index e902fd2b20..0000000000
--- a/modules/generators/mod_suexec.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "httpd.h"
-#include "http_config.h"
-#include "http_core.h"
-#include "http_request.h"
-#include "apr_strings.h"
-#include "unixd.h"
-#include "mpm_common.h"
-#include "mod_suexec.h"
-
-module AP_MODULE_DECLARE_DATA suexec_module;
-
-/*
- * Create a configuration specific to this module for a server or directory
- * location, and fill it with the default settings.
- */
-static void *mkconfig(apr_pool_t *p)
-{
- suexec_config_t *cfg = apr_palloc(p, sizeof(suexec_config_t));
-
- cfg->active = 0;
- return cfg;
-}
-
-/*
- * Respond to a callback to create configuration record for a server or
- * vhost environment.
- */
-static void *create_mconfig_for_server(apr_pool_t *p, server_rec *s)
-{
- return mkconfig(p);
-}
-
-/*
- * Respond to a callback to create a config record for a specific directory.
- */
-static void *create_mconfig_for_directory(apr_pool_t *p, char *dir)
-{
- return mkconfig(p);
-}
-
-static const char *set_suexec_ugid(cmd_parms *cmd, void *mconfig,
- const char *uid, const char *gid)
-{
- suexec_config_t *cfg = (suexec_config_t *) mconfig;
- const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
-
- if (err != NULL) {
- return err;
- }
- if (unixd_config.suexec_enabled) {
- cfg->ugid.uid = ap_uname2id(uid);
- cfg->ugid.gid = ap_gname2id(gid);
- cfg->active = 1;
- }
- else {
- fprintf(stderr,
- "Warning: SuexecUserGroup directive requires SUEXEC wrapper.\n");
- }
- return NULL;
-}
-
-static ap_unix_identity_t *get_suexec_id_doer(const request_rec *r)
-{
- suexec_config_t *cfg =
- (suexec_config_t *) ap_get_module_config(r->per_dir_config, &suexec_module);
-
- return cfg->active ? &cfg->ugid : NULL;
-}
-
-/*
- * Define the directives specific to this module. This structure is referenced
- * later by the 'module' structure.
- */
-static const command_rec suexec_cmds[] =
-{
- /* XXX - Another important reason not to allow this in .htaccess is that
- * the ap_[ug]name2id() is not thread-safe */
- AP_INIT_TAKE2("SuexecUserGroup", set_suexec_ugid, NULL, RSRC_CONF,
- "User and group for spawned processes"),
- { NULL }
-};
-
-static void suexec_hooks(apr_pool_t *p)
-{
- ap_hook_get_suexec_identity(get_suexec_id_doer,NULL,NULL,APR_HOOK_MIDDLE);
-}
-
-module AP_MODULE_DECLARE_DATA suexec_module =
-{
- STANDARD20_MODULE_STUFF,
- create_mconfig_for_directory, /* create per-dir config */
- NULL, /* merge per-dir config */
- create_mconfig_for_server, /* server config */
- NULL, /* merge server config */
- suexec_cmds, /* command table */
- suexec_hooks /* register hooks */
-};
diff --git a/modules/generators/mod_suexec.h b/modules/generators/mod_suexec.h
deleted file mode 100644
index 87a77eaa24..0000000000
--- a/modules/generators/mod_suexec.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-#include "unixd.h"
-
-typedef struct {
- ap_unix_identity_t ugid;
- int active;
-} suexec_config_t;
-
diff --git a/modules/http/.cvsignore b/modules/http/.cvsignore
deleted file mode 100644
index 65f0cc30cf..0000000000
--- a/modules/http/.cvsignore
+++ /dev/null
@@ -1,10 +0,0 @@
-.deps
-.libs
-*.la
-modules.mk
-Makefile
-*.lo
-*.slo
-*.so
-Debug
-Release
diff --git a/modules/http/.indent.pro b/modules/http/.indent.pro
deleted file mode 100644
index a9fbe9f9a1..0000000000
--- a/modules/http/.indent.pro
+++ /dev/null
@@ -1,54 +0,0 @@
--i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1
--TBUFF
--TFILE
--TTRANS
--TUINT4
--T_trans
--Tallow_options_t
--Tapache_sfio
--Tarray_header
--Tbool_int
--Tbuf_area
--Tbuff_struct
--Tbuffy
--Tcmd_how
--Tcmd_parms
--Tcommand_rec
--Tcommand_struct
--Tconn_rec
--Tcore_dir_config
--Tcore_server_config
--Tdir_maker_func
--Tevent
--Tglobals_s
--Thandler_func
--Thandler_rec
--Tjoblist_s
--Tlisten_rec
--Tmerger_func
--Tmode_t
--Tmodule
--Tmodule_struct
--Tmutex
--Tn_long
--Tother_child_rec
--Toverrides_t
--Tparent_score
--Tpid_t
--Tpiped_log
--Tpool
--Trequest_rec
--Trequire_line
--Trlim_t
--Tscoreboard
--Tsemaphore
--Tserver_addr_rec
--Tserver_rec
--Tserver_rec_chain
--Tshort_score
--Ttable
--Ttable_entry
--Tthread
--Tu_wide_int
--Tvtime_t
--Twide_int
diff --git a/modules/http/Makefile.in b/modules/http/Makefile.in
deleted file mode 100644
index 167b343d0d..0000000000
--- a/modules/http/Makefile.in
+++ /dev/null
@@ -1,3 +0,0 @@
-
-include $(top_srcdir)/build/special.mk
-
diff --git a/modules/http/config2.m4 b/modules/http/config2.m4
deleted file mode 100644
index 5fec30cc47..0000000000
--- a/modules/http/config2.m4
+++ /dev/null
@@ -1,10 +0,0 @@
-dnl modules enabled in this directory by default
-
-APACHE_MODPATH_INIT(http)
-
-http_objects="http_core.lo http_protocol.lo http_request.lo"
-
-APACHE_MODULE(http, HTTP protocol handling, $http_objects, , yes)
-APACHE_MODULE(mime, mapping of file-extension to MIME, , , yes)
-
-APACHE_MODPATH_FINISH
diff --git a/modules/http/http_core.c b/modules/http/http_core.c
deleted file mode 100644
index f5948973ab..0000000000
--- a/modules/http/http_core.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "apr_strings.h"
-#include "apr_thread_proc.h" /* for RLIMIT stuff */
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#define CORE_PRIVATE
-#include "httpd.h"
-#include "http_config.h"
-#include "http_connection.h"
-#include "http_protocol.h" /* For index_of_response(). Grump. */
-#include "http_request.h"
-
-#include "util_filter.h"
-#include "util_ebcdic.h"
-#include "ap_mpm.h"
-#include "scoreboard.h"
-
-#include "mod_core.h"
-
-static const char *set_keep_alive_timeout(cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
- if (err != NULL) {
- return err;
- }
-
- cmd->server->keep_alive_timeout = atoi(arg);
- return NULL;
-}
-
-static const char *set_keep_alive(cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
- if (err != NULL) {
- return err;
- }
-
- /* We've changed it to On/Off, but used to use numbers
- * so we accept anything but "Off" or "0" as "On"
- */
- if (!strcasecmp(arg, "off") || !strcmp(arg, "0")) {
- cmd->server->keep_alive = 0;
- }
- else {
- cmd->server->keep_alive = 1;
- }
- return NULL;
-}
-
-static const char *set_keep_alive_max(cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
- if (err != NULL) {
- return err;
- }
-
- cmd->server->keep_alive_max = atoi(arg);
- return NULL;
-}
-
-static const command_rec http_cmds[] = {
- AP_INIT_TAKE1("KeepAliveTimeout", set_keep_alive_timeout, NULL, RSRC_CONF,
- "Keep-Alive timeout duration (sec)"),
- AP_INIT_TAKE1("MaxKeepAliveRequests", set_keep_alive_max, NULL, RSRC_CONF,
- "Maximum number of Keep-Alive requests per connection, or 0 for infinite"),
- AP_INIT_TAKE1("KeepAlive", set_keep_alive, NULL, RSRC_CONF,
- "Whether persistent connections should be On or Off"),
- { NULL }
-};
-
-/*
- * HTTP/1.1 chunked transfer encoding filter.
- */
-static apr_status_t chunk_filter(ap_filter_t *f, apr_bucket_brigade *b)
-{
-#define ASCII_CRLF "\015\012"
-#define ASCII_ZERO "\060"
- apr_bucket_brigade *more = NULL;
- apr_bucket *e;
- apr_status_t rv;
-
- for (more = NULL; b; b = more, more = NULL) {
- apr_off_t bytes = 0;
- apr_bucket *eos = NULL;
- char chunk_hdr[20]; /* enough space for the snprintf below */
-
- APR_BRIGADE_FOREACH(e, b) {
- if (APR_BUCKET_IS_EOS(e)) {
- /* there shouldn't be anything after the eos */
- eos = e;
- break;
- }
- else if (e->length == -1) {
- /* unknown amount of data (e.g. a pipe) */
- const char *data;
- apr_size_t len;
-
- rv = apr_bucket_read(e, &data, &len, APR_BLOCK_READ);
- if (rv != APR_SUCCESS) {
- return rv;
- }
- if (len > 0) {
- /*
- * There may be a new next bucket representing the
- * rest of the data stream on which a read() may
- * block so we pass down what we have so far.
- */
- bytes += len;
- more = apr_brigade_split(b, APR_BUCKET_NEXT(e));
- break;
- }
- else {
- /* If there was nothing in this bucket then we can
- * safely move on to the next one without pausing
- * to pass down what we have counted up so far.
- */
- continue;
- }
- }
- else {
- bytes += e->length;
- }
- }
-
- /*
- * XXX: if there aren't very many bytes at this point it may
- * be a good idea to set them aside and return for more,
- * unless we haven't finished counting this brigade yet.
- */
-
- /* if there are content bytes, then wrap them in a chunk */
- if (bytes > 0) {
- apr_size_t hdr_len;
-
- /*
- * Insert the chunk header, specifying the number of bytes in
- * the chunk.
- */
- /* XXX might be nice to have APR_OFF_T_FMT_HEX */
- hdr_len = apr_snprintf(chunk_hdr, sizeof(chunk_hdr),
- "%qx" CRLF, (apr_uint64_t)bytes);
- ap_xlate_proto_to_ascii(chunk_hdr, hdr_len);
- e = apr_bucket_transient_create(chunk_hdr, hdr_len);
- APR_BRIGADE_INSERT_HEAD(b, e);
-
- /*
- * Insert the end-of-chunk CRLF before the EOS bucket, or
- * appended to the brigade
- */
- e = apr_bucket_immortal_create(ASCII_CRLF, 2);
- if (eos != NULL) {
- APR_BUCKET_INSERT_BEFORE(eos, e);
- }
- else {
- APR_BRIGADE_INSERT_TAIL(b, e);
- }
- }
-
- /* RFC 2616, Section 3.6.1
- *
- * If there is an EOS bucket, then prefix it with:
- * 1) the last-chunk marker ("0" CRLF)
- * 2) the trailer
- * 3) the end-of-chunked body CRLF
- *
- * If there is no EOS bucket, then do nothing.
- *
- * XXX: it would be nice to combine this with the end-of-chunk
- * marker above, but this is a bit more straight-forward for
- * now.
- */
- if (eos != NULL) {
- /* XXX: (2) trailers ... does not yet exist */
- e = apr_bucket_immortal_create(ASCII_ZERO ASCII_CRLF /* <trailers> */ ASCII_CRLF, 5);
- APR_BUCKET_INSERT_BEFORE(eos, e);
- }
-
- /* pass the brigade to the next filter. */
- rv = ap_pass_brigade(f->next, b);
- if (rv != APR_SUCCESS || eos != NULL) {
- return rv;
- }
- }
-
- return APR_SUCCESS;
-}
-
-static const char *http_method(const request_rec *r)
- { return "http"; }
-
-static unsigned short http_port(const request_rec *r)
- { return DEFAULT_HTTP_PORT; }
-
-static int ap_pre_http_connection(conn_rec *c)
-{
- ap_add_input_filter("HTTP_IN", NULL, NULL, c);
- ap_add_input_filter("CORE_IN", NULL, NULL, c);
- ap_add_output_filter("CORE", NULL, NULL, c);
- return OK;
-}
-
-static int ap_process_http_connection(conn_rec *c)
-{
- request_rec *r;
-
- /*
- * Read and process each request found on our connection
- * until no requests are left or we decide to close.
- */
-
- ap_update_child_status(AP_CHILD_THREAD_FROM_ID(c->id), SERVER_BUSY_READ, NULL);
- while ((r = ap_read_request(c)) != NULL) {
-
- /* process the request if it was read without error */
-
- ap_update_child_status(AP_CHILD_THREAD_FROM_ID(c->id), SERVER_BUSY_WRITE, NULL);
- if (r->status == HTTP_OK)
- ap_process_request(r);
-
- if (ap_extended_status)
- ap_increment_counts(AP_CHILD_THREAD_FROM_ID(c->id), r);
-
- if (!c->keepalive || c->aborted)
- break;
-
- ap_update_child_status(AP_CHILD_THREAD_FROM_ID(c->id), SERVER_BUSY_KEEPALIVE, NULL);
- apr_pool_destroy(r->pool);
-
- if (ap_graceful_stop_signalled())
- break;
- }
-
- return OK;
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_pre_connection(ap_pre_http_connection,NULL,NULL,
- APR_HOOK_REALLY_LAST);
- ap_hook_process_connection(ap_process_http_connection,NULL,NULL,
- APR_HOOK_REALLY_LAST);
- ap_hook_http_method(http_method,NULL,NULL,APR_HOOK_REALLY_LAST);
- ap_hook_default_port(http_port,NULL,NULL,APR_HOOK_REALLY_LAST);
-
- ap_register_input_filter("HTTP_IN", ap_http_filter, AP_FTYPE_CONNECTION);
- ap_register_input_filter("DECHUNK", ap_dechunk_filter, AP_FTYPE_TRANSCODE);
- ap_register_output_filter("HTTP_HEADER", ap_http_header_filter,
- AP_FTYPE_HTTP_HEADER);
- ap_register_output_filter("CHUNK", chunk_filter, AP_FTYPE_TRANSCODE);
- ap_register_output_filter("BYTERANGE", ap_byterange_filter,
- AP_FTYPE_HTTP_HEADER);
-}
-
-AP_DECLARE_DATA module http_module = {
- STANDARD20_MODULE_STUFF,
- NULL, /* create per-directory config structure */
- NULL, /* merge per-directory config structures */
- NULL, /* create per-server config structure */
- NULL, /* merge per-server config structures */
- http_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
diff --git a/modules/http/http_protocol.c b/modules/http/http_protocol.c
deleted file mode 100644
index a4426466be..0000000000
--- a/modules/http/http_protocol.c
+++ /dev/null
@@ -1,2439 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * http_protocol.c --- routines which directly communicate with the client.
- *
- * Code originally by Rob McCool; much redone by Robert S. Thau
- * and the Apache Software Foundation.
- */
-
-#include "apr.h"
-#include "apr_strings.h"
-#include "apr_buckets.h"
-#include "apr_lib.h"
-#include "apr_signal.h"
-
-#define APR_WANT_STDIO /* for sscanf */
-#define APR_WANT_STRFUNC
-#define APR_WANT_MEMFUNC
-#include "apr_want.h"
-
-#define CORE_PRIVATE
-#include "util_filter.h"
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_core.h"
-#include "http_protocol.h"
-#include "http_main.h"
-#include "http_request.h"
-#include "http_vhost.h"
-#include "http_log.h" /* For errors detected in basic auth common
- * support code... */
-#include "util_date.h" /* For parseHTTPdate and BAD_DATE */
-#include "util_charset.h"
-#include "util_ebcdic.h"
-
-#include "mod_core.h"
-
-#if APR_HAVE_STDARG_H
-#include <stdarg.h>
-#endif
-#if APR_HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-
-AP_DECLARE(int) ap_set_keepalive(request_rec *r)
-{
- int ka_sent = 0;
- int wimpy = ap_find_token(r->pool,
- apr_table_get(r->headers_out, "Connection"), "close");
- const char *conn = apr_table_get(r->headers_in, "Connection");
-
- /* The following convoluted conditional determines whether or not
- * the current connection should remain persistent after this response
- * (a.k.a. HTTP Keep-Alive) and whether or not the output message
- * body should use the HTTP/1.1 chunked transfer-coding. In English,
- *
- * IF we have not marked this connection as errored;
- * and the response body has a defined length due to the status code
- * being 304 or 204, the request method being HEAD, already
- * having defined Content-Length or Transfer-Encoding: chunked, or
- * the request version being HTTP/1.1 and thus capable of being set
- * as chunked [we know the (r->chunked = 1) side-effect is ugly];
- * and the server configuration enables keep-alive;
- * and the server configuration has a reasonable inter-request timeout;
- * and there is no maximum # requests or the max hasn't been reached;
- * and the response status does not require a close;
- * and the response generator has not already indicated close;
- * and the client did not request non-persistence (Connection: close);
- * and we haven't been configured to ignore the buggy twit
- * or they're a buggy twit coming through a HTTP/1.1 proxy
- * and the client is requesting an HTTP/1.0-style keep-alive
- * or the client claims to be HTTP/1.1 compliant (perhaps a proxy);
- * THEN we can be persistent, which requires more headers be output.
- *
- * Note that the condition evaluation order is extremely important.
- */
- if ((r->connection->keepalive != -1)
- && ((r->status == HTTP_NOT_MODIFIED)
- || (r->status == HTTP_NO_CONTENT)
- || r->header_only
- || apr_table_get(r->headers_out, "Content-Length")
- || ap_find_last_token(r->pool,
- apr_table_get(r->headers_out,
- "Transfer-Encoding"),
- "chunked")
- || ((r->proto_num >= HTTP_VERSION(1,1))
- && (r->chunked = 1))) /* THIS CODE IS CORRECT, see comment above. */
- && r->server->keep_alive
- && (r->server->keep_alive_timeout > 0)
- && ((r->server->keep_alive_max == 0)
- || (r->server->keep_alive_max > r->connection->keepalives))
- && !ap_status_drops_connection(r->status)
- && !wimpy
- && !ap_find_token(r->pool, conn, "close")
- && (!apr_table_get(r->subprocess_env, "nokeepalive")
- || apr_table_get(r->headers_in, "Via"))
- && ((ka_sent = ap_find_token(r->pool, conn, "keep-alive"))
- || (r->proto_num >= HTTP_VERSION(1,1)))) {
- int left = r->server->keep_alive_max - r->connection->keepalives;
-
- r->connection->keepalive = 1;
- r->connection->keepalives++;
-
- /* If they sent a Keep-Alive token, send one back */
- if (ka_sent) {
- if (r->server->keep_alive_max)
- apr_table_setn(r->headers_out, "Keep-Alive",
- apr_psprintf(r->pool, "timeout=%d, max=%d",
- r->server->keep_alive_timeout, left));
- else
- apr_table_setn(r->headers_out, "Keep-Alive",
- apr_psprintf(r->pool, "timeout=%d",
- r->server->keep_alive_timeout));
- apr_table_mergen(r->headers_out, "Connection", "Keep-Alive");
- }
-
- return 1;
- }
-
- /* Otherwise, we need to indicate that we will be closing this
- * connection immediately after the current response.
- *
- * We only really need to send "close" to HTTP/1.1 clients, but we
- * always send it anyway, because a broken proxy may identify itself
- * as HTTP/1.0, but pass our request along with our HTTP/1.1 tag
- * to a HTTP/1.1 client. Better safe than sorry.
- */
- if (!wimpy)
- apr_table_mergen(r->headers_out, "Connection", "close");
-
- r->connection->keepalive = 0;
-
- return 0;
-}
-
-AP_DECLARE(int) ap_meets_conditions(request_rec *r)
-{
- const char *etag = apr_table_get(r->headers_out, "ETag");
- const char *if_match, *if_modified_since, *if_unmodified, *if_nonematch;
- apr_time_t mtime;
-
- /* Check for conditional requests --- note that we only want to do
- * this if we are successful so far and we are not processing a
- * subrequest or an ErrorDocument.
- *
- * The order of the checks is important, since ETag checks are supposed
- * to be more accurate than checks relative to the modification time.
- * However, not all documents are guaranteed to *have* ETags, and some
- * might have Last-Modified values w/o ETags, so this gets a little
- * complicated.
- */
-
- if (!ap_is_HTTP_SUCCESS(r->status) || r->no_local_copy) {
- return OK;
- }
-
- /* XXX: we should define a "time unset" constant */
- mtime = (r->mtime != 0) ? r->mtime : apr_time_now();
-
- /* If an If-Match request-header field was given
- * AND the field value is not "*" (meaning match anything)
- * AND if our strong ETag does not match any entity tag in that field,
- * respond with a status of 412 (Precondition Failed).
- */
- if ((if_match = apr_table_get(r->headers_in, "If-Match")) != NULL) {
- if (if_match[0] != '*'
- && (etag == NULL || etag[0] == 'W'
- || !ap_find_list_item(r->pool, if_match, etag))) {
- return HTTP_PRECONDITION_FAILED;
- }
- }
- else {
- /* Else if a valid If-Unmodified-Since request-header field was given
- * AND the requested resource has been modified since the time
- * specified in this field, then the server MUST
- * respond with a status of 412 (Precondition Failed).
- */
- if_unmodified = apr_table_get(r->headers_in, "If-Unmodified-Since");
- if (if_unmodified != NULL) {
- apr_time_t ius = ap_parseHTTPdate(if_unmodified);
-
- if ((ius != BAD_DATE) && (mtime > ius)) {
- return HTTP_PRECONDITION_FAILED;
- }
- }
- }
-
- /* If an If-None-Match request-header field was given
- * AND the field value is "*" (meaning match anything)
- * OR our ETag matches any of the entity tags in that field, fail.
- *
- * If the request method was GET or HEAD, failure means the server
- * SHOULD respond with a 304 (Not Modified) response.
- * For all other request methods, failure means the server MUST
- * respond with a status of 412 (Precondition Failed).
- *
- * GET or HEAD allow weak etag comparison, all other methods require
- * strong comparison. We can only use weak if it's not a range request.
- */
- if_nonematch = apr_table_get(r->headers_in, "If-None-Match");
- if (if_nonematch != NULL) {
- if (r->method_number == M_GET) {
- if (if_nonematch[0] == '*') {
- return HTTP_NOT_MODIFIED;
- }
- if (etag != NULL) {
- if (apr_table_get(r->headers_in, "Range")) {
- if (etag[0] != 'W'
- && ap_find_list_item(r->pool, if_nonematch, etag)) {
- return HTTP_NOT_MODIFIED;
- }
- }
- else if (ap_strstr_c(if_nonematch, etag)) {
- return HTTP_NOT_MODIFIED;
- }
- }
- }
- else if (if_nonematch[0] == '*'
- || (etag != NULL
- && ap_find_list_item(r->pool, if_nonematch, etag))) {
- return HTTP_PRECONDITION_FAILED;
- }
- }
- /* Else if a valid If-Modified-Since request-header field was given
- * AND it is a GET or HEAD request
- * AND the requested resource has not been modified since the time
- * specified in this field, then the server MUST
- * respond with a status of 304 (Not Modified).
- * A date later than the server's current request time is invalid.
- */
- else if ((r->method_number == M_GET)
- && ((if_modified_since =
- apr_table_get(r->headers_in,
- "If-Modified-Since")) != NULL)) {
- apr_time_t ims = ap_parseHTTPdate(if_modified_since);
-
- if ((ims >= mtime) && (ims <= r->request_time)) {
- return HTTP_NOT_MODIFIED;
- }
- }
- return OK;
-}
-
-/* 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.
- */
-AP_DECLARE(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;
-}
-
-/*
- * Turn a known method number into a name. Doesn't work for
- * extension methods, obviously.
- */
-AP_DECLARE(const char *) ap_method_name_of(int methnum)
-{
- static const char *AP_HTTP_METHODS[METHODS] = { NULL };
-
- /*
- * This is ugly, but the previous incantation made Windows C
- * varf. I'm not even sure it was ANSI C. However, ugly as it
- * is, this works, and we only have to do it once.
- */
- if (AP_HTTP_METHODS[0] == NULL) {
- AP_HTTP_METHODS[M_GET] = "GET";
- AP_HTTP_METHODS[M_PUT] = "PUT";
- AP_HTTP_METHODS[M_POST] = "POST";
- AP_HTTP_METHODS[M_DELETE] = "DELETE";
- AP_HTTP_METHODS[M_CONNECT] = "CONNECT";
- AP_HTTP_METHODS[M_OPTIONS] = "OPTIONS";
- AP_HTTP_METHODS[M_TRACE] = "TRACE";
- AP_HTTP_METHODS[M_PATCH] = "PATCH";
- AP_HTTP_METHODS[M_PROPFIND] = "PROPFIND";
- AP_HTTP_METHODS[M_PROPPATCH] = "PROPPATCH";
- AP_HTTP_METHODS[M_MKCOL] = "MKCOL";
- AP_HTTP_METHODS[M_COPY] = "COPY";
- AP_HTTP_METHODS[M_MOVE] = "MOVE";
- AP_HTTP_METHODS[M_LOCK] = "LOCK";
- AP_HTTP_METHODS[M_UNLOCK] = "UNLOCK";
- AP_HTTP_METHODS[M_INVALID] = NULL;
- /*
- * Since we're using symbolic names, make sure we only do
- * this once by forcing a value into the first slot IFF it's
- * still NULL.
- */
- if (AP_HTTP_METHODS[0] == NULL) {
- AP_HTTP_METHODS[0] = "INVALID";
- }
- }
-
- if ((methnum == M_INVALID) || (methnum >= METHODS)) {
- return NULL;
- }
- return AP_HTTP_METHODS[methnum];
-}
-
-struct dechunk_ctx {
- apr_size_t chunk_size;
- apr_size_t bytes_delivered;
- enum {WANT_HDR /* must have value zero */, WANT_BODY, WANT_TRL} state;
-};
-
-static long get_chunk_size(char *);
-
-apr_status_t ap_dechunk_filter(ap_filter_t *f, apr_bucket_brigade *bb,
- ap_input_mode_t mode, apr_size_t *readbytes)
-{
- apr_status_t rv;
- struct dechunk_ctx *ctx = f->ctx;
- apr_bucket *b;
- const char *buf;
- apr_size_t len;
-
- if (!ctx) {
- f->ctx = ctx = apr_pcalloc(f->r->pool, sizeof(struct dechunk_ctx));
- }
-
- do {
- if (ctx->chunk_size == ctx->bytes_delivered) {
- /* Time to read another chunk header or trailer... ap_http_filter() is
- * the next filter in line and it knows how to return a brigade with
- * one line.
- */
- char line[30];
-
- if ((rv = ap_getline(line, sizeof(line), f->r, 0)) < 0) {
- return rv;
- }
- switch(ctx->state) {
- case WANT_HDR:
- ctx->chunk_size = get_chunk_size(line);
- ctx->bytes_delivered = 0;
- if (ctx->chunk_size == 0) {
- ctx->state = WANT_TRL;
- }
- else {
- ctx->state = WANT_BODY;
- }
- break;
- case WANT_TRL:
- /* XXX sanity check end chunk here */
- if (strlen(line)) {
- /* bad trailer */
- }
- if (ctx->chunk_size == 0) { /* we just finished the last chunk? */
- /* append eos bucket and get out */
- b = apr_bucket_eos_create();
- APR_BRIGADE_INSERT_TAIL(bb, b);
- return APR_SUCCESS;
- }
- ctx->state = WANT_HDR;
- break;
- default:
- ap_assert(ctx->state == WANT_HDR || ctx->state == WANT_TRL);
- }
- }
- } while (ctx->state != WANT_BODY);
-
- if (ctx->state == WANT_BODY) {
- /* Tell ap_http_filter() how many bytes to deliver. */
- apr_size_t readbytes = ctx->chunk_size - ctx->bytes_delivered;
- if ((rv = ap_get_brigade(f->next, bb, mode, &readbytes)) != APR_SUCCESS) {
- return rv;
- }
- /* Walk through the body, accounting for bytes, and removing an eos bucket if
- * ap_http_filter() delivered the entire chunk.
- */
- b = APR_BRIGADE_FIRST(bb);
- while (b != APR_BRIGADE_SENTINEL(bb) && !APR_BUCKET_IS_EOS(b)) {
- apr_bucket_read(b, &buf, &len, mode);
- AP_DEBUG_ASSERT(len <= ctx->chunk_size - ctx->bytes_delivered);
- ctx->bytes_delivered += len;
- b = APR_BUCKET_NEXT(b);
- }
- if (ctx->bytes_delivered == ctx->chunk_size) {
- AP_DEBUG_ASSERT(APR_BUCKET_IS_EOS(b));
- apr_bucket_delete(b);
- ctx->state = WANT_TRL;
- }
- }
-
- return APR_SUCCESS;
-}
-
-typedef struct http_filter_ctx {
- apr_bucket_brigade *b;
-} http_ctx_t;
-
-apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_size_t *readbytes)
-{
- apr_bucket *e;
- char *buff;
- apr_size_t len;
- char *pos;
- http_ctx_t *ctx = f->ctx;
- apr_status_t rv;
-
- if (!ctx) {
- f->ctx = ctx = apr_pcalloc(f->c->pool, sizeof(*ctx));
- ctx->b = apr_brigade_create(f->c->pool);
- }
-
- if (mode == AP_MODE_PEEK) {
- apr_bucket *e;
- const char *str;
- apr_size_t length;
-
- /* The purpose of this loop is to ignore any CRLF (or LF) at the end
- * of a request. Many browsers send extra lines at the end of POST
- * requests. We use the PEEK method to determine if there is more
- * data on the socket, so that we know if we should delay sending the
- * end of one request until we have served the second request in a
- * pipelined situation. We don't want to actually delay sending a
- * response if the server finds a CRLF (or LF), becuause that doesn't
- * mean that there is another request, just a blank line.
- */
- while (1) {
- if (APR_BRIGADE_EMPTY(ctx->b)) {
- e = NULL;
- }
- else {
- e = APR_BRIGADE_FIRST(ctx->b);
- }
- if (!e || apr_bucket_read(e, &str, &length, APR_NONBLOCK_READ) != APR_SUCCESS) {
- return APR_EOF;
- }
- else {
- const char *c = str;
- while (c - str < length) {
- if (*c == APR_ASCII_LF)
- c++;
- else if (*c == APR_ASCII_CR && *(c + 1) == APR_ASCII_LF)
- c += 2;
- else return APR_SUCCESS;
- }
- apr_bucket_delete(e);
- }
- }
- }
-
- if (APR_BRIGADE_EMPTY(ctx->b)) {
- if ((rv = ap_get_brigade(f->next, ctx->b, mode, readbytes)) != APR_SUCCESS) {
- return rv;
- }
- }
-
- if (*readbytes) {
- while (!APR_BRIGADE_EMPTY(ctx->b)) {
- const char *ignore;
-
- e = APR_BRIGADE_FIRST(ctx->b);
- if ((rv = apr_bucket_read(e, &ignore, &len, mode)) != APR_SUCCESS) {
- /* probably APR_IS_EAGAIN(rv); socket state isn't correct;
- * remove log once we get this squared away */
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, f->c->base_server,
- "apr_bucket_read");
- return rv;
- }
-
- if (len) {
- /* note: this can sometimes insert empty buckets into the
- * brigade, or the data might come in a few characters at
- * a time - don't assume that one call to apr_bucket_read()
- * will return the full string.
- */
- if (*readbytes < len) {
- apr_bucket_split(e, *readbytes);
- *readbytes = 0;
- }
- else {
- *readbytes -= len;
- }
- APR_BUCKET_REMOVE(e);
- APR_BRIGADE_INSERT_TAIL(b, e);
- break; /* once we've gotten some data, deliver it to caller */
- }
- apr_bucket_delete(e);
- }
- if (*readbytes == 0) {
- apr_bucket *eos = apr_bucket_eos_create();
-
- APR_BRIGADE_INSERT_TAIL(b, eos);
- }
- return APR_SUCCESS;
- }
-
- while (!APR_BRIGADE_EMPTY(ctx->b)) {
- e = APR_BRIGADE_FIRST(ctx->b);
- if ((rv = apr_bucket_read(e, (const char **)&buff, &len, mode)) != APR_SUCCESS) {
- return rv;
- }
-
- pos = memchr(buff, APR_ASCII_LF, len);
- if (pos != NULL) {
- apr_bucket_split(e, pos - buff + 1);
- APR_BUCKET_REMOVE(e);
- APR_BRIGADE_INSERT_TAIL(b, e);
- return APR_SUCCESS;
- }
- APR_BUCKET_REMOVE(e);
- APR_BRIGADE_INSERT_TAIL(b, e);
- }
- return APR_SUCCESS;
-}
-
-/* New Apache routine to map status codes into array indicies
- * e.g. 100 -> 0, 101 -> 1, 200 -> 2 ...
- * The number of status lines must equal the value of RESPONSE_CODES (httpd.h)
- * and must be listed in order.
- */
-
-#ifdef UTS21
-/* The second const triggers an assembler bug on UTS 2.1.
- * Another workaround is to move some code out of this file into another,
- * but this is easier. Dave Dykstra, 3/31/99
- */
-static const char * status_lines[RESPONSE_CODES] =
-#else
-static const char * const status_lines[RESPONSE_CODES] =
-#endif
-{
- "100 Continue",
- "101 Switching Protocols",
- "102 Processing",
-#define LEVEL_200 3
- "200 OK",
- "201 Created",
- "202 Accepted",
- "203 Non-Authoritative Information",
- "204 No Content",
- "205 Reset Content",
- "206 Partial Content",
- "207 Multi-Status",
-#define LEVEL_300 11
- "300 Multiple Choices",
- "301 Moved Permanently",
- "302 Found",
- "303 See Other",
- "304 Not Modified",
- "305 Use Proxy",
- "306 unused",
- "307 Temporary Redirect",
-#define LEVEL_400 19
- "400 Bad Request",
- "401 Authorization Required",
- "402 Payment Required",
- "403 Forbidden",
- "404 Not Found",
- "405 Method Not Allowed",
- "406 Not Acceptable",
- "407 Proxy Authentication Required",
- "408 Request Time-out",
- "409 Conflict",
- "410 Gone",
- "411 Length Required",
- "412 Precondition Failed",
- "413 Request Entity Too Large",
- "414 Request-URI Too Large",
- "415 Unsupported Media Type",
- "416 Requested Range Not Satisfiable",
- "417 Expectation Failed",
- "418 unused",
- "419 unused",
- "420 unused",
- "421 unused",
- "422 Unprocessable Entity",
- "423 Locked",
- "424 Failed Dependency",
-#define LEVEL_500 44
- "500 Internal Server Error",
- "501 Method Not Implemented",
- "502 Bad Gateway",
- "503 Service Temporarily Unavailable",
- "504 Gateway Time-out",
- "505 HTTP Version Not Supported",
- "506 Variant Also Negotiates",
- "507 Insufficient Storage",
- "508 unused",
- "509 unused",
- "510 Not Extended"
-};
-
-/* The index is found by its offset from the x00 code of each level.
- * Although this is fast, it will need to be replaced if some nutcase
- * decides to define a high-numbered code before the lower numbers.
- * If that sad event occurs, replace the code below with a linear search
- * from status_lines[shortcut[i]] to status_lines[shortcut[i+1]-1];
- */
-AP_DECLARE(int) ap_index_of_response(int status)
-{
- static int shortcut[6] = {0, LEVEL_200, LEVEL_300, LEVEL_400,
- LEVEL_500, RESPONSE_CODES};
- int i, pos;
-
- if (status < 100) /* Below 100 is illegal for HTTP status */
- return LEVEL_500;
-
- for (i = 0; i < 5; i++) {
- status -= 100;
- if (status < 100) {
- pos = (status + shortcut[i]);
- if (pos < shortcut[i + 1]) {
- return pos;
- }
- else {
- return LEVEL_500; /* status unknown (falls in gap) */
- }
- }
- }
- return LEVEL_500; /* 600 or above is also illegal */
-}
-
-AP_DECLARE(const char *) ap_get_status_line(int status)
-{
- return status_lines[ap_index_of_response(status)];
-}
-
-typedef struct header_struct {
- apr_pool_t *pool;
- apr_bucket_brigade *bb;
-} header_struct;
-
-/* Send a single HTTP header field to the client. Note that this function
- * is used in calls to table_do(), so their interfaces are co-dependent.
- * In other words, don't change this one without checking table_do in alloc.c.
- * It returns true unless there was a write error of some kind.
- */
-static int form_header_field(header_struct *h,
- const char *fieldname, const char *fieldval)
-{
- char *headfield;
-
- headfield = apr_pstrcat(h->pool, fieldname, ": ", fieldval, CRLF, NULL);
- ap_xlate_proto_to_ascii(headfield, strlen(headfield));
- apr_brigade_puts(h->bb, NULL, NULL, headfield);
- return 1;
-}
-
-/*
- * Determine the protocol to use for the response. Potentially downgrade
- * to HTTP/1.0 in some situations and/or turn off keepalives.
- *
- * also prepare r->status_line.
- */
-static void basic_http_header_check(request_rec *r,
- const char **protocol)
-{
- if (r->assbackwards) {
- /* no such thing as a response protocol */
- return;
- }
-
- if (!r->status_line)
- r->status_line = status_lines[ap_index_of_response(r->status)];
-
- /* kluge around broken browsers when indicated by force-response-1.0
- */
- if (r->proto_num == HTTP_VERSION(1,0)
- && apr_table_get(r->subprocess_env, "force-response-1.0")) {
-
- *protocol = "HTTP/1.0";
- r->connection->keepalive = -1;
- }
- else {
- *protocol = AP_SERVER_PROTOCOL;
- }
-}
-
-/* fill "bb" with a barebones/initial HTTP response header */
-static void basic_http_header(request_rec *r, apr_bucket_brigade *bb,
- const char *protocol)
-{
- char *date = NULL;
- char *tmp;
- header_struct h;
-
- if (r->assbackwards) {
- /* there are no headers to send */
- return;
- }
-
- /* Output the HTTP/1.x Status-Line and the Date and Server fields */
-
- tmp = apr_pstrcat(r->pool, protocol, " ", r->status_line, CRLF, NULL);
- ap_xlate_proto_to_ascii(tmp, strlen(tmp));
- apr_brigade_puts(bb, NULL, NULL, tmp);
-
- date = apr_palloc(r->pool, APR_RFC822_DATE_LEN);
- apr_rfc822_date(date, r->request_time);
-
- h.pool = r->pool;
- h.bb = bb;
- form_header_field(&h, "Date", date);
- form_header_field(&h, "Server", ap_get_server_version());
-
- apr_table_unset(r->headers_out, "Date"); /* Avoid bogosity */
- apr_table_unset(r->headers_out, "Server");
-}
-
-AP_DECLARE(void) ap_basic_http_header(request_rec *r, apr_bucket_brigade *bb)
-{
- const char *protocol;
-
- basic_http_header_check(r, &protocol);
- basic_http_header(r, bb, protocol);
-}
-
-/* Navigator versions 2.x, 3.x and 4.0 betas up to and including 4.0b2
- * have a header parsing bug. If the terminating \r\n occur starting
- * at offset 256, 257 or 258 of output then it will not properly parse
- * the headers. Curiously it doesn't exhibit this problem at 512, 513.
- * We are guessing that this is because their initial read of a new request
- * uses a 256 byte buffer, and subsequent reads use a larger buffer.
- * So the problem might exist at different offsets as well.
- *
- * This should also work on keepalive connections assuming they use the
- * same small buffer for the first read of each new request.
- *
- * At any rate, we check the bytes written so far and, if we are about to
- * tickle the bug, we instead insert a bogus padding header. Since the bug
- * manifests as a broken image in Navigator, users blame the server. :(
- * It is more expensive to check the User-Agent than it is to just add the
- * bytes, so we haven't used the BrowserMatch feature here.
- */
-static void terminate_header(apr_bucket_brigade *bb)
-{
- char tmp[] = "X-Pad: avoid browser bug" CRLF;
- char crlf[] = CRLF;
- apr_ssize_t len;
-
- (void) apr_brigade_length(bb, 1, &len);
-
- if (len >= 255 && len <= 257) {
- ap_xlate_proto_to_ascii(tmp, strlen(tmp));
- apr_brigade_puts(bb, NULL, NULL, tmp);
- }
- ap_xlate_proto_to_ascii(crlf, strlen(crlf));
- apr_brigade_puts(bb, NULL, NULL, crlf);
-}
-
-/* Build the Allow field-value from the request handler method mask.
- * Note that we always allow TRACE, since it is handled below.
- */
-static char *make_allow(request_rec *r)
-{
- char *list;
- int mask;
-
- mask = r->allowed_methods->method_mask;
- list = apr_pstrcat(r->pool,
- (mask & (1 << M_GET)) ? ", GET, HEAD" : "",
- (mask & (1 << M_POST)) ? ", POST" : "",
- (mask & (1 << M_PUT)) ? ", PUT" : "",
- (mask & (1 << M_DELETE)) ? ", DELETE" : "",
- (mask & (1 << M_CONNECT)) ? ", CONNECT" : "",
- (mask & (1 << M_OPTIONS)) ? ", OPTIONS" : "",
- (mask & (1 << M_PATCH)) ? ", PATCH" : "",
- (mask & (1 << M_PROPFIND)) ? ", PROPFIND" : "",
- (mask & (1 << M_PROPPATCH)) ? ", PROPPATCH" : "",
- (mask & (1 << M_MKCOL)) ? ", MKCOL" : "",
- (mask & (1 << M_COPY)) ? ", COPY" : "",
- (mask & (1 << M_MOVE)) ? ", MOVE" : "",
- (mask & (1 << M_LOCK)) ? ", LOCK" : "",
- (mask & (1 << M_UNLOCK)) ? ", UNLOCK" : "",
- ", TRACE",
- NULL);
- if ((mask & (1 << M_INVALID))
- && (r->allowed_methods->method_list != NULL)
- && (r->allowed_methods->method_list->nelts != 0)) {
- int i;
- char **xmethod = (char **) r->allowed_methods->method_list->elts;
-
- /*
- * Append all of the elements of r->allowed_methods->method_list
- */
- for (i = 0; i < r->allowed_methods->method_list->nelts; ++i) {
- list = apr_pstrcat(r->pool, list, ", ", xmethod[i], NULL);
- }
- }
- /*
- * Space past the leading ", ". Wastes two bytes, but that's better
- * than futzing around to find the actual length.
- */
- return list + 2;
-}
-
-AP_DECLARE(int) ap_send_http_trace(request_rec *r)
-{
- int rv;
-
- /* Get the original request */
- while (r->prev)
- r = r->prev;
-
- if ((rv = ap_setup_client_block(r, REQUEST_NO_BODY)))
- return rv;
-
- r->content_type = "message/http";
-
- /* Now we recreate the request, and echo it back */
-
- ap_rvputs(r, r->the_request, CRLF, NULL);
-
- apr_table_do((int (*) (void *, const char *, const char *))
- form_header_field, (void *) r, r->headers_in, NULL);
- ap_rputs(CRLF, r);
-
- return OK;
-}
-
-int ap_send_http_options(request_rec *r)
-{
- if (r->assbackwards)
- return DECLINED;
-
- apr_table_setn(r->headers_out, "Allow", make_allow(r));
-
- /* the request finalization will send an EOS, which will flush all
- the headers out (including the Allow header) */
-
- return OK;
-}
-
-/* This routine is called by apr_table_do and merges all instances of
- * the passed field values into a single array that will be further
- * processed by some later routine. Originally intended to help split
- * and recombine multiple Vary fields, though it is generic to any field
- * consisting of comma/space-separated tokens.
- */
-static int uniq_field_values(void *d, const char *key, const char *val)
-{
- apr_array_header_t *values;
- char *start;
- char *e;
- char **strpp;
- int i;
-
- values = (apr_array_header_t *)d;
-
- e = apr_pstrdup(values->cont, val);
-
- do {
- /* Find a non-empty fieldname */
-
- while (*e == ',' || apr_isspace(*e)) {
- ++e;
- }
- if (*e == '\0') {
- break;
- }
- start = e;
- while (*e != '\0' && *e != ',' && !apr_isspace(*e)) {
- ++e;
- }
- if (*e != '\0') {
- *e++ = '\0';
- }
-
- /* Now add it to values if it isn't already represented.
- * Could be replaced by a ap_array_strcasecmp() if we had one.
- */
- for (i = 0, strpp = (char **) values->elts; i < values->nelts;
- ++i, ++strpp) {
- if (*strpp && strcasecmp(*strpp, start) == 0) {
- break;
- }
- }
- if (i == values->nelts) { /* if not found */
- *(char **)apr_array_push(values) = start;
- }
- } while (*e != '\0');
-
- return 1;
-}
-
-/*
- * Since some clients choke violently on multiple Vary fields, or
- * Vary fields with duplicate tokens, combine any multiples and remove
- * any duplicates.
- */
-static void fixup_vary(request_rec *r)
-{
- apr_array_header_t *varies;
-
- varies = apr_array_make(r->pool, 5, sizeof(char *));
-
- /* Extract all Vary fields from the headers_out, separate each into
- * its comma-separated fieldname values, and then add them to varies
- * if not already present in the array.
- */
- apr_table_do((int (*)(void *, const char *, const char *))uniq_field_values,
- (void *) varies, r->headers_out, "Vary", NULL);
-
- /* If we found any, replace old Vary fields with unique-ified value */
-
- if (varies->nelts > 0) {
- apr_table_setn(r->headers_out, "Vary",
- apr_array_pstrcat(r->pool, varies, ','));
- }
-}
-
-AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(
- ap_filter_t *f,
- apr_bucket_brigade *b)
-{
- int i;
- char *date = NULL;
- request_rec *r = f->r;
- const char *clheader;
- const char *protocol;
- apr_bucket *e;
- apr_bucket_brigade *b2;
- header_struct h;
-
- AP_DEBUG_ASSERT(!r->main);
-
- APR_BRIGADE_FOREACH(e, b) {
- if (e->type == &ap_bucket_type_error) {
- ap_bucket_error *eb = e->data;
-
- ap_die(eb->status, r);
- return AP_FILTER_ERROR;
- }
- }
-
- if (r->assbackwards) {
- r->bytes_sent = 0;
- r->sent_bodyct = 1;
- ap_remove_output_filter(f);
- return ap_pass_brigade(f->next, b);
- }
-
- /*
- * Now that we are ready to send a response, we need to combine the two
- * header field tables into a single table. If we don't do this, our
- * later attempts to set or unset a given fieldname might be bypassed.
- */
- if (!apr_is_empty_table(r->err_headers_out))
- r->headers_out = apr_table_overlay(r->pool, r->err_headers_out,
- r->headers_out);
-
- /*
- * Remove the 'Vary' header field if the client can't handle it.
- * Since this will have nasty effects on HTTP/1.1 caches, force
- * the response into HTTP/1.0 mode.
- *
- * Note: the force-response-1.0 should come before the call to
- * basic_http_header_check()
- */
- if (apr_table_get(r->subprocess_env, "force-no-vary") != NULL) {
- apr_table_unset(r->headers_out, "Vary");
- r->proto_num = HTTP_VERSION(1,0);
- apr_table_set(r->subprocess_env, "force-response-1.0", "1");
- }
- else {
- fixup_vary(r);
- }
-
- /* determine the protocol and whether we should use keepalives. */
- basic_http_header_check(r, &protocol);
- ap_set_keepalive(r);
-
- if (r->chunked) {
- apr_table_mergen(r->headers_out, "Transfer-Encoding", "chunked");
- apr_table_unset(r->headers_out, "Content-Length");
-
- }
-
- apr_table_setn(r->headers_out, "Content-Type", ap_make_content_type(r,
- r->content_type));
-
- if (r->content_encoding) {
- apr_table_setn(r->headers_out, "Content-Encoding",
- r->content_encoding);
- }
-
- if (r->content_languages && r->content_languages->nelts) {
- for (i = 0; i < r->content_languages->nelts; ++i) {
- apr_table_mergen(r->headers_out, "Content-Language",
- ((char **) (r->content_languages->elts))[i]);
- }
- }
- else if (r->content_language) {
- apr_table_setn(r->headers_out, "Content-Language",
- r->content_language);
- }
-
- /*
- * Control cachability for non-cachable responses if not already set by
- * some other part of the server configuration.
- */
- if (r->no_cache && !apr_table_get(r->headers_out, "Expires")) {
- date = apr_palloc(r->pool, APR_RFC822_DATE_LEN);
- apr_rfc822_date(date, r->request_time);
- apr_table_addn(r->headers_out, "Expires", date);
- }
-
- /* This is a hack, but I can't find anyway around it. The idea is that
- * we don't want to send out 0 Content-Lengths if it is a head request.
- * This happens when modules try to outsmart the server, and return
- * if they see a HEAD request. Apache 1.3 handlers were supposed to
- * just return in that situation, and the core handled the HEAD. In
- * 2.0, if a handler returns, then the core sends an EOS bucket down
- * the filter stack, and the content-length filter computes a C-L of
- * zero and that gets put in the headers, and we end up sending a
- * zero C-L to the client. We can't just remove the C-L filter,
- * because well behaved 2.0 handlers will send their data down the stack,
- * and we will compute a real C-L for the head request. RBB
- */
- if (r->header_only &&
- (clheader = apr_table_get(r->headers_out, "Content-Length")) &&
- !strcmp(clheader, "0")) {
- apr_table_unset(r->headers_out, "Content-Length");
- }
-
- b2 = apr_brigade_create(r->pool);
- basic_http_header(r, b2, protocol);
-
- h.pool = r->pool;
- h.bb = b2;
-
- if (r->status == HTTP_NOT_MODIFIED) {
- apr_table_do((int (*)(void *, const char *, const char *)) form_header_field,
- (void *) &h, r->headers_out,
- "Connection",
- "Keep-Alive",
- "ETag",
- "Content-Location",
- "Expires",
- "Cache-Control",
- "Vary",
- "Warning",
- "WWW-Authenticate",
- "Proxy-Authenticate",
- NULL);
- }
- else {
- apr_table_do((int (*) (void *, const char *, const char *)) form_header_field,
- (void *) &h, r->headers_out, NULL);
- }
-
- terminate_header(b2);
-
- r->sent_bodyct = 1; /* Whatever follows is real body stuff... */
-
- ap_pass_brigade(f->next, b2);
-
- if (r->header_only) {
- apr_brigade_destroy(b);
- return OK;
- }
-
- if (r->chunked) {
- /* We can't add this filter until we have already sent the headers.
- * If we add it before this point, then the headers will be chunked
- * as well, and that is just wrong.
- */
- ap_add_output_filter("CHUNK", NULL, r, r->connection);
- }
-
- /* Don't remove this filter until after we have added the CHUNK filter.
- * Otherwise, f->next won't be the CHUNK filter and thus the first
- * brigade won't be chunked properly.
- */
- ap_remove_output_filter(f);
- return ap_pass_brigade(f->next, b);
-}
-
-/* Here we deal with getting the request message body from the client.
- * Whether or not the request contains a body is signaled by the presence
- * of a non-zero Content-Length or by a Transfer-Encoding: chunked.
- *
- * Note that this is more complicated than it was in Apache 1.1 and prior
- * versions, because chunked support means that the module does less.
- *
- * The proper procedure is this:
- *
- * 1. Call setup_client_block() near the beginning of the request
- * handler. This will set up all the necessary properties, and will
- * return either OK, or an error code. If the latter, the module should
- * return that error code. The second parameter selects the policy to
- * apply if the request message indicates a body, and how a chunked
- * transfer-coding should be interpreted. Choose one of
- *
- * REQUEST_NO_BODY Send 413 error if message has any body
- * REQUEST_CHUNKED_ERROR Send 411 error if body without Content-Length
- * REQUEST_CHUNKED_DECHUNK If chunked, remove the chunks for me.
- *
- * In order to use the last two options, the caller MUST provide a buffer
- * large enough to hold a chunk-size line, including any extensions.
- *
- * 2. When you are ready to read a body (if any), call should_client_block().
- * This will tell the module whether or not to read input. If it is 0,
- * the module should assume that there is no message body to read.
- * This step also sends a 100 Continue response to HTTP/1.1 clients,
- * so should not be called until the module is *definitely* ready to
- * read content. (otherwise, the point of the 100 response is defeated).
- * Never call this function more than once.
- *
- * 3. Finally, call get_client_block in a loop. Pass it a buffer and its size.
- * It will put data into the buffer (not necessarily a full buffer), and
- * return the length of the input block. When it is done reading, it will
- * return 0 if EOF, or -1 if there was an error.
- * If an error occurs on input, we force an end to keepalive.
- */
-
-AP_DECLARE(int) ap_setup_client_block(request_rec *r, int read_policy)
-{
- const char *tenc = apr_table_get(r->headers_in, "Transfer-Encoding");
- const char *lenp = apr_table_get(r->headers_in, "Content-Length");
- long max_body;
-
- r->read_body = read_policy;
- r->read_chunked = 0;
- r->remaining = 0;
-
- if (tenc) {
- if (strcasecmp(tenc, "chunked")) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Unknown Transfer-Encoding %s", tenc);
- return HTTP_NOT_IMPLEMENTED;
- }
- if (r->read_body == REQUEST_CHUNKED_ERROR) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "chunked Transfer-Encoding forbidden: %s", r->uri);
- return (lenp) ? HTTP_BAD_REQUEST : HTTP_LENGTH_REQUIRED;
- }
-
- r->read_chunked = 1;
- ap_add_input_filter("DECHUNK", NULL, r, r->connection);
- }
- else if (lenp) {
- const char *pos = lenp;
-
- while (apr_isdigit(*pos) || apr_isspace(*pos)) {
- ++pos;
- }
- if (*pos != '\0') {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Invalid Content-Length %s", lenp);
- return HTTP_BAD_REQUEST;
- }
-
- r->remaining = atol(lenp);
- }
-
- if ((r->read_body == REQUEST_NO_BODY) &&
- (r->read_chunked || (r->remaining > 0))) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "%s with body is not allowed for %s", r->method, r->uri);
- return HTTP_REQUEST_ENTITY_TOO_LARGE;
- }
-
- max_body = ap_get_limit_req_body(r);
- if (max_body && (r->remaining > max_body)) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Request content-length of %s is larger than "
- "the configured limit of %lu", lenp, max_body);
- return HTTP_REQUEST_ENTITY_TOO_LARGE;
- }
-
-#ifdef AP_DEBUG
- {
- /* Make sure ap_getline() didn't leave any droppings. */
- core_request_config *req_cfg =
- (core_request_config *)ap_get_module_config(r->request_config,
- &core_module);
- AP_DEBUG_ASSERT(APR_BRIGADE_EMPTY(req_cfg->bb));
- }
-#endif
-
- return OK;
-}
-
-AP_DECLARE(int) ap_should_client_block(request_rec *r)
-{
- /* First check if we have already read the request body */
-
- if (r->read_length || (!r->read_chunked && (r->remaining <= 0)))
- return 0;
-
- if (r->expecting_100 && r->proto_num >= HTTP_VERSION(1,1)) {
- char *tmp;
- apr_bucket *e;
- apr_bucket_brigade *bb;
-
- /* sending 100 Continue interim response */
- tmp = apr_pstrcat(r->pool, AP_SERVER_PROTOCOL, " ", status_lines[0],
- CRLF CRLF, NULL);
- bb = apr_brigade_create(r->pool);
- e = apr_bucket_pool_create(tmp, strlen(tmp), r->pool);
- APR_BRIGADE_INSERT_HEAD(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
-
- ap_pass_brigade(r->connection->output_filters, bb);
- }
-
- return 1;
-}
-
-static long get_chunk_size(char *b)
-{
- long chunksize = 0;
-
- while (apr_isxdigit(*b)) {
- int xvalue = 0;
-
- if (*b >= '0' && *b <= '9') {
- xvalue = *b - '0';
- }
- else if (*b >= 'A' && *b <= 'F') {
- xvalue = *b - 'A' + 0xa;
- }
- else if (*b >= 'a' && *b <= 'f') {
- xvalue = *b - 'a' + 0xa;
- }
-
- chunksize = (chunksize << 4) | xvalue;
- ++b;
- }
-
- return chunksize;
-}
-
-/* get_client_block is called in a loop to get the request message body.
- * This is quite simple if the client includes a content-length
- * (the normal case), but gets messy if the body is chunked. Note that
- * r->remaining is used to maintain state across calls and that
- * r->read_length is the total number of bytes given to the caller
- * across all invocations. It is messy because we have to be careful not
- * to read past the data provided by the client, since these reads block.
- * Returns 0 on End-of-body, -1 on error or premature chunk end.
- *
- * Reading the chunked encoding requires a buffer size large enough to
- * hold a chunk-size line, including any extensions. For now, we'll leave
- * that to the caller, at least until we can come up with a better solution.
- */
-AP_DECLARE(long) ap_get_client_block(request_rec *r, char *buffer, int bufsiz)
-{
- apr_size_t len_read, total;
- apr_status_t rv;
- apr_bucket *b, *old;
- const char *tempbuf;
- core_request_config *req_cfg =
- (core_request_config *)ap_get_module_config(r->request_config,
- &core_module);
- apr_bucket_brigade *bb = req_cfg->bb;
-
- do {
- if (APR_BRIGADE_EMPTY(bb)) {
- if (ap_get_brigade(r->input_filters, bb, AP_MODE_BLOCKING, &r->remaining) != APR_SUCCESS) {
- /* if we actually fail here, we want to just return and
- * stop trying to read data from the client.
- */
- r->connection->keepalive = -1;
- apr_brigade_destroy(bb);
- return -1;
- }
- }
- b = APR_BRIGADE_FIRST(bb);
- } while (APR_BRIGADE_EMPTY(bb));
-
- if (APR_BUCKET_IS_EOS(b)) { /* reached eos on previous invocation */
- apr_bucket_delete(b);
- return 0;
- }
-
- total = 0;
- while (total < bufsiz && b != APR_BRIGADE_SENTINEL(bb) && !APR_BUCKET_IS_EOS(b)) {
- if ((rv = apr_bucket_read(b, &tempbuf, &len_read, APR_BLOCK_READ)) != APR_SUCCESS) {
- return -1;
- }
- if (total + len_read > bufsiz) {
- apr_bucket_split(b, bufsiz - total);
- len_read = bufsiz - total;
- }
- memcpy(buffer, tempbuf, len_read);
- buffer += len_read;
- total += len_read;
- /* XXX the next two fields shouldn't be mucked with here, as they are in terms
- * of bytes in the unfiltered body; gotta see if anybody else actually uses
- * these
- */
- r->read_length += len_read; /* XXX yank me? */
- r->remaining -= len_read; /* XXX yank me? */
- old = b;
- b = APR_BUCKET_NEXT(b);
- apr_bucket_delete(old);
- }
-
- return total;
-}
-
-/* In HTTP/1.1, any method can have a body. However, most GET handlers
- * wouldn't know what to do with a request body if they received one.
- * This helper routine tests for and reads any message body in the request,
- * simply discarding whatever it receives. We need to do this because
- * failing to read the request body would cause it to be interpreted
- * as the next request on a persistent connection.
- *
- * Since we return an error status if the request is malformed, this
- * routine should be called at the beginning of a no-body handler, e.g.,
- *
- * if ((retval = ap_discard_request_body(r)) != OK)
- * return retval;
- */
-AP_DECLARE(int) ap_discard_request_body(request_rec *r)
-{
- int rv;
-
- if (r->read_length == 0) { /* if not read already */
- if ((rv = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK)))
- return rv;
- }
-
- /* In order to avoid sending 100 Continue when we already know the
- * final response status, and yet not kill the connection if there is
- * no request body to be read, we need to duplicate the test from
- * ap_should_client_block() here negated rather than call it directly.
- */
- if ((r->read_length == 0) && (r->read_chunked || (r->remaining > 0))) {
- char dumpbuf[HUGE_STRING_LEN];
-
- if (r->expecting_100) {
- r->connection->keepalive = -1;
- return OK;
- }
-
- while ((rv = ap_get_client_block(r, dumpbuf, HUGE_STRING_LEN)) > 0)
- continue;
-
- if (rv < 0)
- return HTTP_BAD_REQUEST;
- }
- return OK;
-}
-
-static const char *add_optional_notes(request_rec *r,
- const char *prefix,
- const char *key,
- const char *suffix)
-{
- const char *notes, *result;
-
- if ((notes = apr_table_get(r->notes, key)) == NULL) {
- result = prefix;
- }
- else {
- result = apr_pstrcat(r->pool, prefix, notes, suffix, NULL);
- }
-
- return result;
-}
-
-static const char *get_canned_error_string(int status,
- request_rec *r,
- const char *location)
-
-/* construct and return the default error message for a given
- * HTTP defined error code
- */
-{
- apr_pool_t *p = r->pool;
- const char *error_notes, *h1, *s1;
-
- switch (status) {
- case HTTP_MOVED_PERMANENTLY:
- case HTTP_MOVED_TEMPORARILY:
- case HTTP_TEMPORARY_REDIRECT:
- return(apr_pstrcat(p,
- "The document has moved <A HREF=\"",
- ap_escape_html(r->pool, location),
- "\">here</A>.<P>\n",
- NULL));
- case HTTP_SEE_OTHER:
- return(apr_pstrcat(p,
- "The answer to your request is located <A HREF=\"",
- ap_escape_html(r->pool, location),
- "\">here</A>.<P>\n",
- NULL));
- case HTTP_USE_PROXY:
- return(apr_pstrcat(p,
- "This resource is only accessible "
- "through the proxy\n",
- ap_escape_html(r->pool, location),
- "<BR>\nYou will need to "
- "configure your client to use that proxy.<P>\n",
- NULL));
- case HTTP_PROXY_AUTHENTICATION_REQUIRED:
- case HTTP_UNAUTHORIZED:
- return("This server could not verify that you\n"
- "are authorized to access the document\n"
- "requested. Either you supplied the wrong\n"
- "credentials (e.g., bad password), or your\n"
- "browser doesn't understand how to supply\n"
- "the credentials required.<P>\n");
- case HTTP_BAD_REQUEST:
- return(add_optional_notes(r,
- "Your browser sent a request that "
- "this server could not understand.<P>\n",
- "error-notes",
- "<P>\n"));
- case HTTP_FORBIDDEN:
- return(apr_pstrcat(p,
- "You don't have permission to access ",
- ap_escape_html(r->pool, r->uri),
- "\non this server.<P>\n",
- NULL));
- case HTTP_NOT_FOUND:
- return(apr_pstrcat(p,
- "The requested URL ",
- ap_escape_html(r->pool, r->uri),
- " was not found on this server.<P>\n",
- NULL));
- case HTTP_METHOD_NOT_ALLOWED:
- return(apr_pstrcat(p,
- "The requested method ", r->method,
- " is not allowed for the URL ",
- ap_escape_html(r->pool, r->uri),
- ".<P>\n",
- NULL));
- case HTTP_NOT_ACCEPTABLE:
- s1 = apr_pstrcat(p,
- "An appropriate representation of the "
- "requested resource ",
- ap_escape_html(r->pool, r->uri),
- " could not be found on this server.<P>\n",
- NULL);
- return(add_optional_notes(r, s1, "variant-list", ""));
- case HTTP_MULTIPLE_CHOICES:
- return(add_optional_notes(r, "", "variant-list", ""));
- case HTTP_LENGTH_REQUIRED:
- s1 = apr_pstrcat(p,
- "A request of the requested method ",
- r->method,
- " requires a valid Content-length.<P>\n",
- NULL);
- return(add_optional_notes(r, s1, "error-notes", "<P>\n"));
- case HTTP_PRECONDITION_FAILED:
- return(apr_pstrcat(p,
- "The precondition on the request for the URL ",
- ap_escape_html(r->pool, r->uri),
- " evaluated to false.<P>\n",
- NULL));
- case HTTP_NOT_IMPLEMENTED:
- s1 = apr_pstrcat(p,
- ap_escape_html(r->pool, r->method), " to ",
- ap_escape_html(r->pool, r->uri),
- " not supported.<P>\n",
- NULL);
- return(add_optional_notes(r, s1, "error-notes", "<P>\n"));
- case HTTP_BAD_GATEWAY:
- s1 = "The proxy server received an invalid" CRLF
- "response from an upstream server.<P>" CRLF;
- return(add_optional_notes(r, s1, "error-notes", "<P>\n"));
- case HTTP_VARIANT_ALSO_VARIES:
- return(apr_pstrcat(p,
- "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));
- case HTTP_REQUEST_TIME_OUT:
- return("I'm tired of waiting for your request.\n");
- case HTTP_GONE:
- return(apr_pstrcat(p,
- "The requested resource<BR>",
- ap_escape_html(r->pool, r->uri),
- "<BR>\nis no longer available on this server "
- "and there is no forwarding address.\n"
- "Please remove all references to this resource.\n",
- NULL));
- case HTTP_REQUEST_ENTITY_TOO_LARGE:
- return(apr_pstrcat(p,
- "The requested resource<BR>",
- ap_escape_html(r->pool, r->uri), "<BR>\n",
- "does not allow request data with ",
- r->method,
- " requests, or the amount of data provided in\n"
- "the request exceeds the capacity limit.\n",
- NULL));
- case HTTP_REQUEST_URI_TOO_LARGE:
- s1 = "The requested URL's length exceeds the capacity\n"
- "limit for this server.<P>\n";
- return(add_optional_notes(r, s1, "error-notes", "<P>\n"));
- case HTTP_UNSUPPORTED_MEDIA_TYPE:
- return("The supplied request data is not in a format\n"
- "acceptable for processing by this resource.\n");
- case HTTP_RANGE_NOT_SATISFIABLE:
- return("None of the range-specifier values in the Range\n"
- "request-header field overlap the current extent\n"
- "of the selected resource.\n");
- case HTTP_EXPECTATION_FAILED:
- return(apr_pstrcat(p,
- "The expectation given in the Expect request-header"
- "\nfield could not be met by this server.<P>\n"
- "The client sent<PRE>\n Expect: ",
- apr_table_get(r->headers_in, "Expect"), "\n</PRE>\n"
- "but we only allow the 100-continue expectation.\n",
- NULL));
- case HTTP_UNPROCESSABLE_ENTITY:
- return("The server understands the media type of the\n"
- "request entity, but was unable to process the\n"
- "contained instructions.\n");
- case HTTP_LOCKED:
- return("The requested resource is currently locked.\n"
- "The lock must be released or proper identification\n"
- "given before the method can be applied.\n");
- case HTTP_FAILED_DEPENDENCY:
- return("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");
- case HTTP_INSUFFICIENT_STORAGE:
- return("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");
- case HTTP_SERVICE_UNAVAILABLE:
- return("The server is temporarily unable to service your\n"
- "request due to maintenance downtime or capacity\n"
- "problems. Please try again later.\n");
- case HTTP_GATEWAY_TIME_OUT:
- return("The proxy server did not receive a timely response\n"
- "from the upstream server.\n");
- case HTTP_NOT_EXTENDED:
- return("A mandatory extension policy in the request is not\n"
- "accepted by the server for this resource.\n");
- default: /* HTTP_INTERNAL_SERVER_ERROR */
- /*
- * This comparison to expose error-notes could be modified to
- * use a configuration directive and export based on that
- * directive. For now "*" is used to designate an error-notes
- * that is totally safe for any user to see (ie lacks paths,
- * database passwords, etc.)
- */
- if (((error_notes = apr_table_get(r->notes, "error-notes")) != NULL)
- && (h1 = apr_table_get(r->notes, "verbose-error-to")) != NULL
- && (strcmp(h1, "*") == 0)) {
- return(apr_pstrcat(p, error_notes, "<P>\n", NULL));
- }
- else {
- return(apr_pstrcat(p,
- "The server encountered an internal error or\n"
- "misconfiguration and was unable to complete\n"
- "your request.<P>\n"
- "Please contact the server administrator,\n ",
- ap_escape_html(r->pool, r->server->server_admin),
- " and inform them of the time the error occurred,\n"
- "and anything you might have done that may have\n"
- "caused the error.<P>\n"
- "More information about this error may be available\n"
- "in the server error log.<P>\n",
- NULL));
- }
- /*
- * It would be nice to give the user the information they need to
- * fix the problem directly since many users don't have access to
- * the error_log (think University sites) even though they can easily
- * get this error by misconfiguring an htaccess file. However, the
- e 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 = apr_table_get(r->notes, "error-notes")) != NULL) {
- * return(apr_pstrcat(p, error_notes, "<P>\n", NULL);
- * }
- * else {
- * return "";
- * }
- */
- }
-}
-
-static void reset_filters(request_rec *r)
-{
- ap_filter_t *f = r->output_filters;
-
- while (f) {
- if (!strcasecmp(f->frec->name, "CORE") ||
- !strcasecmp(f->frec->name, "CONTENT_LENGTH") ||
- !strcasecmp(f->frec->name, "HTTP_HEADER")) {
- f = f->next;
- continue;
- }
- else {
- ap_remove_output_filter(f);
- f = f->next;
- }
- }
-}
-
-/* We should have named this send_canned_response, since it is used for any
- * response that can be generated by the server from the request record.
- * This includes all 204 (no content), 3xx (redirect), 4xx (client error),
- * and 5xx (server error) messages that have not been redirected to another
- * handler via the ErrorDocument feature.
- */
-AP_DECLARE(void) ap_send_error_response(request_rec *r, int recursive_error)
-{
- int status = r->status;
- int idx = ap_index_of_response(status);
- char *custom_response;
- const char *location = apr_table_get(r->headers_out, "Location");
-
- /* At this point, we are starting the response over, so we have to reset
- * this value.
- */
- r->eos_sent = 0;
- reset_filters(r);
-
- /*
- * It's possible that the Location field might be in r->err_headers_out
- * instead of r->headers_out; use the latter if possible, else the
- * former.
- */
- if (location == NULL) {
- location = apr_table_get(r->err_headers_out, "Location");
- }
- /* We need to special-case the handling of 204 and 304 responses,
- * since they have specific HTTP requirements and do not include a
- * message body. Note that being assbackwards here is not an option.
- */
- if (status == HTTP_NOT_MODIFIED) {
- ap_finalize_request_protocol(r);
- return;
- }
-
- if (status == HTTP_NO_CONTENT) {
- ap_finalize_request_protocol(r);
- return;
- }
-
- if (!r->assbackwards) {
- apr_table_t *tmp = r->headers_out;
-
- /* For all HTTP/1.x responses for which we generate the message,
- * we need to avoid inheriting the "normal status" header fields
- * that may have been set by the request handler before the
- * error or redirect, except for Location on external redirects.
- */
- r->headers_out = r->err_headers_out;
- r->err_headers_out = tmp;
- apr_table_clear(r->err_headers_out);
-
- if (ap_is_HTTP_REDIRECT(status) || (status == HTTP_CREATED)) {
- if ((location != NULL) && *location) {
- apr_table_setn(r->headers_out, "Location", location);
- }
- else {
- location = ""; /* avoids coredump when printing, below */
- }
- }
-
- r->content_language = NULL;
- r->content_languages = NULL;
- r->content_encoding = NULL;
- r->clength = 0;
- r->content_type = "text/html; charset=iso-8859-1";
-
- if ((status == HTTP_METHOD_NOT_ALLOWED)
- || (status == HTTP_NOT_IMPLEMENTED)) {
- apr_table_setn(r->headers_out, "Allow", make_allow(r));
- }
-
- if (r->header_only) {
- ap_finalize_request_protocol(r);
- return;
- }
- }
-
- if ((custom_response = ap_response_code_string(r, idx))) {
- /*
- * We have a custom response output. This should only be
- * a text-string to write back. But if the ErrorDocument
- * was a local redirect and the requested resource failed
- * for any reason, the custom_response will still hold the
- * redirect URL. We don't really want to output this URL
- * as a text message, so first check the custom response
- * string to ensure that it is a text-string (using the
- * same test used in ap_die(), i.e. does it start with a ").
- * If it doesn't, we've got a recursive error, so find
- * the original error and output that as well.
- */
- if (custom_response[0] == '\"') {
- ap_rputs(custom_response + 1, r);
- ap_finalize_request_protocol(r);
- return;
- }
- /*
- * Redirect failed, so get back the original error
- */
- while (r->prev && (r->prev->status != HTTP_OK))
- r = r->prev;
- }
- {
- const char *title = status_lines[idx];
- const char *h1;
-
- /* XXX This is a major hack that should be fixed cleanly. The
- * problem is that we have the information we need in a previous
- * request, but the text of the page must be sent down the last
- * request_rec's filter stack. rbb
- */
- request_rec *rlast = r;
- while (rlast->next) {
- rlast = rlast->next;
- }
-
- /* Accept a status_line set by a module, but only if it begins
- * with the 3 digit status code
- */
- if (r->status_line != NULL
- && strlen(r->status_line) > 4 /* long enough */
- && apr_isdigit(r->status_line[0])
- && apr_isdigit(r->status_line[1])
- && apr_isdigit(r->status_line[2])
- && apr_isspace(r->status_line[3])
- && apr_isalnum(r->status_line[4])) {
- title = r->status_line;
- }
-
- /* folks decided they didn't want the error code in the H1 text */
- h1 = &title[4];
-
- /* can't count on a charset filter being in place here,
- * so do ebcdic->ascii translation explicitly (if needed)
- */
-
- ap_rvputs_proto_in_ascii(rlast,
- DOCTYPE_HTML_2_0
- "<HTML><HEAD>\n<TITLE>", title,
- "</TITLE>\n</HEAD><BODY>\n<H1>", h1, "</H1>\n",
- NULL);
-
- ap_rvputs_proto_in_ascii(rlast,
- get_canned_error_string(status, r, location),
- NULL);
-
- if (recursive_error) {
- ap_rvputs_proto_in_ascii(rlast, "<P>Additionally, a ",
- status_lines[ap_index_of_response(recursive_error)],
- "\nerror was encountered while trying to use an "
- "ErrorDocument to handle the request.\n", NULL);
- }
- ap_rvputs_proto_in_ascii(rlast, ap_psignature("<HR>\n", r), NULL);
- ap_rvputs_proto_in_ascii(rlast, "</BODY></HTML>\n", NULL);
- }
- ap_finalize_request_protocol(r);
-}
-
-/*
- * Create a new method list with the specified number of preallocated
- * extension slots.
- */
-AP_DECLARE(ap_method_list_t *) ap_make_method_list(apr_pool_t *p, int nelts)
-{
- ap_method_list_t *ml;
-
- ml = (ap_method_list_t *) apr_palloc(p, sizeof(ap_method_list_t));
- ml->method_mask = 0;
- ml->method_list = apr_array_make(p, sizeof(char *), nelts);
- return ml;
-}
-
-/*
- * Make a copy of a method list (primarily for subrequests that may
- * subsequently change it; don't want them changing the parent's, too!).
- */
-AP_DECLARE(void) ap_copy_method_list(ap_method_list_t *dest,
- ap_method_list_t *src)
-{
- int i;
- char **imethods;
- char **omethods;
-
- dest->method_mask = src->method_mask;
- imethods = (char **) src->method_list->elts;
- for (i = 0; i < src->method_list->nelts; ++i) {
- omethods = (char **) apr_array_push(dest->method_list);
- *omethods = apr_pstrdup(dest->method_list->cont, imethods[i]);
- }
-}
-
-/*
- * Invoke a callback routine for each method in the specified list.
- */
-AP_DECLARE_NONSTD(void) ap_method_list_do(int (*comp) (void *urec, const char *mname,
- int mnum),
- void *rec,
- const ap_method_list_t *ml, ...)
-{
- va_list vp;
- va_start(vp, ml);
- ap_method_list_vdo(comp, rec, ml, vp);
- va_end(vp);
-}
-
-AP_DECLARE(void) ap_method_list_vdo(int (*comp) (void *mrec,
- const char *mname,
- int mnum),
- void *rec, const ap_method_list_t *ml,
- va_list vp)
-{
-
-}
-
-/*
- * Return true if the specified HTTP method is in the provided
- * method list.
- */
-AP_DECLARE(int) ap_method_in_list(ap_method_list_t *l, const char *method)
-{
- int methnum;
- int i;
- char **methods;
-
- /*
- * If it's one of our known methods, use the shortcut and check the
- * bitmask.
- */
- methnum = ap_method_number_of(method);
- if (methnum != M_INVALID) {
- return (l->method_mask & (1 << methnum));
- }
- /*
- * Otherwise, see if the method name is in the array or string names
- */
- if ((l->method_list == NULL) || (l->method_list->nelts == 0)) {
- return 0;
- }
- methods = (char **)l->method_list->elts;
- for (i = 0; i < l->method_list->nelts; ++i) {
- if (strcmp(method, methods[i]) == 0) {
- return 1;
- }
- }
- return 0;
-}
-
-/*
- * Add the specified method to a method list (if it isn't already there).
- */
-AP_DECLARE(void) ap_method_list_add(ap_method_list_t *l, const char *method)
-{
- int methnum;
- int i;
- const char **xmethod;
- char **methods;
-
- /*
- * If it's one of our known methods, use the shortcut and use the
- * bitmask.
- */
- methnum = ap_method_number_of(method);
- l->method_mask |= (1 << methnum);
- if (methnum != M_INVALID) {
- return;
- }
- /*
- * Otherwise, see if the method name is in the array of string names.
- */
- if (l->method_list->nelts != 0) {
- methods = (char **)l->method_list->elts;
- for (i = 0; i < l->method_list->nelts; ++i) {
- if (strcmp(method, methods[i]) == 0) {
- return;
- }
- }
- }
- xmethod = (const char **) apr_array_push(l->method_list);
- *xmethod = method;
-}
-
-/*
- * Remove the specified method from a method list.
- */
-AP_DECLARE(void) ap_method_list_remove(ap_method_list_t *l,
- const char *method)
-{
- int methnum;
- char **methods;
-
- /*
- * If it's one of our known methods, use the shortcut and use the
- * bitmask.
- */
- methnum = ap_method_number_of(method);
- l->method_mask |= ~(1 << methnum);
- if (methnum != M_INVALID) {
- return;
- }
- /*
- * Otherwise, see if the method name is in the array of string names.
- */
- if (l->method_list->nelts != 0) {
- register int i, j, k;
- methods = (char **)l->method_list->elts;
- for (i = 0; i < l->method_list->nelts; ) {
- if (strcmp(method, methods[i]) == 0) {
- for (j = i, k = i + 1; k < l->method_list->nelts; ++j, ++k) {
- methods[j] = methods[k];
- }
- --l->method_list->nelts;
- }
- else {
- ++i;
- }
- }
- }
-}
-
-/*
- * Reset a method list to be completely empty.
- */
-AP_DECLARE(void) ap_clear_method_list(ap_method_list_t *l)
-{
- l->method_mask = 0;
- l->method_list->nelts = 0;
-}
-
-/*
- * Construct an entity tag (ETag) from resource information. If it's a real
- * file, build in some of the file characteristics. If the modification time
- * is newer than (request-time minus 1 second), mark the ETag as weak - it
- * could be modified again in as short an interval. We rationalize the
- * modification time we're given to keep it from being in the future.
- */
-AP_DECLARE(char *) ap_make_etag(request_rec *r, int force_weak)
-{
- char *etag;
- char *weak;
-
- /*
- * Make an ETag header out of various pieces of information. We use
- * the last-modified date and, if we have a real file, the
- * length and inode number - note that this doesn't have to match
- * the content-length (i.e. includes), it just has to be unique
- * for the file.
- *
- * If the request was made within a second of the last-modified date,
- * we send a weak tag instead of a strong one, since it could
- * be modified again later in the second, and the validation
- * would be incorrect.
- */
-
- weak = ((r->request_time - r->mtime > APR_USEC_PER_SEC)
- && !force_weak) ? "" : "W/";
-
- if (r->finfo.filetype != 0) {
- etag = apr_psprintf(r->pool,
- "%s\"%lx-%lx-%lx\"", weak,
- (unsigned long) r->finfo.inode,
- (unsigned long) r->finfo.size,
- (unsigned long) r->mtime);
- }
- else {
- etag = apr_psprintf(r->pool, "%s\"%lx\"", weak,
- (unsigned long) r->mtime);
- }
-
- return etag;
-}
-
-AP_DECLARE(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 = apr_pstrcat(r->pool, variant_etag, ";", vlv, NULL);
- }
-
- apr_table_setn(r->headers_out, "ETag", etag);
-}
-
-static int parse_byterange(char *range, apr_off_t clength,
- apr_off_t *start, apr_off_t *end)
-{
- char *dash = strchr(range, '-');
-
- if (!dash)
- return 0;
-
- if ((dash == range)) {
- /* In the form "-5" */
- *start = clength - atol(dash + 1);
- *end = clength - 1;
- }
- else {
- *dash = '\0';
- dash++;
- *start = atol(range);
- if (*dash)
- *end = atol(dash);
- else /* "5-" */
- *end = clength - 1;
- }
-
- if (*start < 0)
- *start = 0;
-
- if (*end >= clength)
- *end = clength - 1;
-
- if (*start > *end)
- return -1;
-
- return (*start > 0 || *end < clength);
-}
-
-static int ap_set_byterange(request_rec *r);
-
-typedef struct byterange_ctx {
- apr_bucket_brigade *bb;
- int num_ranges;
- const char *orig_ct;
-} byterange_ctx;
-
-/*
- * Here we try to be compatible with clients that want multipart/x-byteranges
- * instead of multipart/byteranges (also see above), as per HTTP/1.1. We
- * look for the Request-Range header (e.g. Netscape 2 and 3) as an indication
- * that the browser supports an older protocol. We also check User-Agent
- * for Microsoft Internet Explorer 3, which needs this as well.
- */
-static int use_range_x(request_rec *r)
-{
- const char *ua;
- return (apr_table_get(r->headers_in, "Request-Range") ||
- ((ua = apr_table_get(r->headers_in, "User-Agent"))
- && ap_strstr_c(ua, "MSIE 3")));
-}
-
-#define BYTERANGE_FMT "%" APR_OFF_T_FMT "-%" APR_OFF_T_FMT "/%" APR_OFF_T_FMT
-
-AP_CORE_DECLARE_NONSTD(apr_status_t) ap_byterange_filter(
- ap_filter_t *f,
- apr_bucket_brigade *bb)
-{
-#define MIN_LENGTH(len1, len2) ((len1 > len2) ? len2 : len1)
- request_rec *r = f->r;
- byterange_ctx *ctx = f->ctx;
- apr_bucket *e;
- apr_bucket_brigade *bsend;
- apr_off_t range_start;
- apr_off_t range_end;
- char *current;
- char *bound_head;
- apr_ssize_t bb_length;
- apr_off_t clength = 0;
- apr_status_t rv;
- int found = 0;
-
- if (!ctx) {
- int num_ranges = ap_set_byterange(r);
-
- if (num_ranges == -1) {
- ap_remove_output_filter(f);
- bsend = apr_brigade_create(r->pool);
- e = ap_bucket_error_create(HTTP_RANGE_NOT_SATISFIABLE, NULL, r->pool);
- APR_BRIGADE_INSERT_TAIL(bsend, e);
- e = apr_bucket_eos_create();
- APR_BRIGADE_INSERT_TAIL(bsend, e);
- return ap_pass_brigade(f->next, bsend);
- }
- if (num_ranges == 0) {
- ap_remove_output_filter(f);
- return ap_pass_brigade(f->next, bb);
- }
-
- ctx = f->ctx = apr_pcalloc(r->pool, sizeof(*ctx));
- ctx->num_ranges = num_ranges;
-
- if (num_ranges > 1) {
- ctx->orig_ct = r->content_type;
- r->content_type =
- apr_pstrcat(r->pool, "multipart", use_range_x(r) ? "/x-" : "/",
- "byteranges; boundary=", r->boundary, NULL);
- }
-
- /* create a brigade in case we never call ap_save_brigade() */
- ctx->bb = apr_brigade_create(r->pool);
- }
-
- /* We can't actually deal with byte-ranges until we have the whole brigade
- * because the byte-ranges can be in any order, and according to the RFC,
- * we SHOULD return the data in the same order it was requested.
- */
- if (!APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
- ap_save_brigade(f, &ctx->bb, &bb);
- return APR_SUCCESS;
- }
-
- /* compute this once (it is an invariant) */
- bound_head = apr_pstrcat(r->pool,
- CRLF "--", r->boundary,
- CRLF "Content-type: ",
- ap_make_content_type(r, ctx->orig_ct),
- CRLF "Content-range: bytes ",
- NULL);
- ap_xlate_proto_to_ascii(bound_head, strlen(bound_head));
-
- /* If we have a saved brigade from a previous run, concat the passed
- * brigade with our saved brigade. Otherwise just continue.
- */
- if (ctx->bb) {
- APR_BRIGADE_CONCAT(ctx->bb, bb);
- bb = ctx->bb;
- ctx->bb = NULL; /* ### strictly necessary? call brigade_destroy? */
- }
-
- /* It is possible that we won't have a content length yet, so we have to
- * compute the length before we can actually do the byterange work.
- */
- (void) apr_brigade_length(bb, 1, &bb_length);
- clength = (apr_off_t)bb_length;
-
- /* this brigade holds what we will be sending */
- bsend = apr_brigade_create(r->pool);
-
- while ((current = ap_getword(r->pool, &r->range, ',')) &&
- (rv = parse_byterange(current, clength, &range_start, &range_end))) {
- apr_bucket *e2;
- apr_bucket *ec;
-
- if (rv == -1) {
- continue;
- }
- else {
- found = 1;
- }
-
- if (ctx->num_ranges > 1) {
- char *ts;
-
- e = apr_bucket_pool_create(bound_head,
- strlen(bound_head), r->pool);
- APR_BRIGADE_INSERT_TAIL(bsend, e);
-
- ts = apr_psprintf(r->pool, BYTERANGE_FMT CRLF CRLF,
- range_start, range_end, clength);
- ap_xlate_proto_to_ascii(ts, strlen(ts));
- e = apr_bucket_pool_create(ts, strlen(ts), r->pool);
- APR_BRIGADE_INSERT_TAIL(bsend, e);
- }
-
- e = apr_brigade_partition(bb, range_start);
- e2 = apr_brigade_partition(bb, range_end + 1);
-
- ec = e;
- do {
- apr_bucket *foo;
- const char *str;
- apr_size_t len;
-
- if (apr_bucket_copy(ec, &foo) != APR_SUCCESS) {
- apr_bucket_read(ec, &str, &len, APR_BLOCK_READ);
- foo = apr_bucket_heap_create(str, len, 0, NULL);
- }
- APR_BRIGADE_INSERT_TAIL(bsend, foo);
- ec = APR_BUCKET_NEXT(ec);
- } while (ec != e2);
- }
-
- if (found == 0) {
- ap_remove_output_filter(f);
- r->status = HTTP_OK;
- return HTTP_RANGE_NOT_SATISFIABLE;
- }
-
- if (ctx->num_ranges > 1) {
- char *end;
-
- /* add the final boundary */
- end = apr_pstrcat(r->pool, CRLF "--", r->boundary, "--" CRLF, NULL);
- ap_xlate_proto_to_ascii(end, strlen(end));
- e = apr_bucket_pool_create(end, strlen(end), r->pool);
- APR_BRIGADE_INSERT_TAIL(bsend, e);
- }
-
- e = apr_bucket_eos_create();
- APR_BRIGADE_INSERT_TAIL(bsend, e);
-
- /* we're done with the original content */
- apr_brigade_destroy(bb);
-
- /* send our multipart output */
- return ap_pass_brigade(f->next, bsend);
-}
-
-static int ap_set_byterange(request_rec *r)
-{
- const char *range;
- const char *if_range;
- const char *match;
- const char *ct;
- apr_off_t range_start;
- apr_off_t range_end;
- int num_ranges;
-
- if (r->assbackwards)
- return 0;
-
- /* is content already a single range? */
- if (apr_table_get(r->headers_out, "Content-Range")) {
- return 0;
- }
-
- /* is content already a multiple range? */
- if ((ct = apr_table_get(r->headers_out, "Content-Type")) &&
- (!strncasecmp(ct, "multipart/byteranges", 20) ||
- !strncasecmp(ct, "multipart/x-byteranges", 22))) {
- return 0;
- }
-
- /* Check for Range request-header (HTTP/1.1) or Request-Range for
- * backwards-compatibility with second-draft Luotonen/Franks
- * byte-ranges (e.g. Netscape Navigator 2-3).
- *
- * We support this form, with Request-Range, and (farther down) we
- * send multipart/x-byteranges instead of multipart/byteranges for
- * Request-Range based requests to work around a bug in Netscape
- * Navigator 2-3 and MSIE 3.
- */
-
- if (!(range = apr_table_get(r->headers_in, "Range")))
- range = apr_table_get(r->headers_in, "Request-Range");
-
- if (!range || strncasecmp(range, "bytes=", 6)) {
- return 0;
- }
-
- /* Check the If-Range header for Etag or Date.
- * Note that this check will return false (as required) if either
- * of the two etags are weak.
- */
- if ((if_range = apr_table_get(r->headers_in, "If-Range"))) {
- if (if_range[0] == '"') {
- if (!(match = apr_table_get(r->headers_out, "Etag")) ||
- (strcmp(if_range, match) != 0))
- return 0;
- }
- else if (!(match = apr_table_get(r->headers_out, "Last-Modified")) ||
- (strcmp(if_range, match) != 0))
- return 0;
- }
-
- /* would be nice to pick this up from f->ctx */
- ct = ap_make_content_type(r, r->content_type);
-
- if (!ap_strchr_c(range, ',')) {
- int rv;
- /* A single range */
-
- /* rvarse_byterange() modifies the contents, so make a copy */
- if ((rv = parse_byterange(apr_pstrdup(r->pool, range + 6), r->clength,
- &range_start, &range_end)) <= 0) {
- return rv;
- }
- apr_table_setn(r->headers_out, "Content-Range",
- apr_psprintf(r->pool, "bytes " BYTERANGE_FMT,
- range_start, range_end, r->clength));
- apr_table_setn(r->headers_out, "Content-Type", ct);
-
- num_ranges = 1;
- }
- else {
- /* a multiple range */
-
- num_ranges = 2;
-
- /* ### it would be nice if r->boundary was in f->ctx */
- r->boundary = apr_psprintf(r->pool, "%qx%lx",
- r->request_time, (long) getpid());
-
- apr_table_setn(r->headers_out, "Content-Type",
- apr_pstrcat(r->pool,
- "multipart", use_range_x(r) ? "/x-" : "/",
- "byteranges; boundary=", r->boundary,
- NULL));
- }
-
- r->status = HTTP_PARTIAL_CONTENT;
- r->range = range + 6;
-
- return num_ranges;
-}
-
diff --git a/modules/http/http_request.c b/modules/http/http_request.c
deleted file mode 100644
index 56064c451b..0000000000
--- a/modules/http/http_request.c
+++ /dev/null
@@ -1,574 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * http_request.c: functions to get and process requests
- *
- * Rob McCool 3/21/93
- *
- * Thoroughly revamped by rst for Apache. NB this file reads
- * best from the bottom up.
- *
- */
-
-#include "apr_strings.h"
-#include "apr_file_io.h"
-#include "apr_fnmatch.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#define CORE_PRIVATE
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_request.h"
-#include "http_core.h"
-#include "http_protocol.h"
-#include "http_log.h"
-#include "http_main.h"
-#include "util_filter.h"
-#include "util_charset.h"
-
-#include "mod_core.h"
-
-#if APR_HAVE_STDARG_H
-#include <stdarg.h>
-#endif
-
-/*****************************************************************
- *
- * Mainline request processing...
- */
-
-AP_DECLARE(void) ap_die(int type, request_rec *r)
-{
- int error_index = ap_index_of_response(type);
- char *custom_response = ap_response_code_string(r, error_index);
- int recursive_error = 0;
-
- if (type == AP_FILTER_ERROR) {
- return;
- }
-
- if (type == DONE) {
- ap_finalize_request_protocol(r);
- return;
- }
-
- /*
- * The following takes care of Apache redirects to custom response URLs
- * Note that if we are already dealing with the response to some other
- * error condition, we just report on the original error, and give up on
- * any attempt to handle the other thing "intelligently"...
- */
-
- if (r->status != HTTP_OK) {
- recursive_error = type;
-
- while (r->prev && (r->prev->status != HTTP_OK))
- r = r->prev; /* Get back to original error */
-
- type = r->status;
- custom_response = NULL; /* Do NOT retry the custom thing! */
- }
-
- r->status = type;
-
- /*
- * This test is done here so that none of the auth modules needs to know
- * about proxy authentication. They treat it like normal auth, and then
- * we tweak the status.
- */
- if (HTTP_UNAUTHORIZED == r->status && PROXYREQ_PROXY == r->proxyreq) {
- r->status = HTTP_PROXY_AUTHENTICATION_REQUIRED;
- }
-
- /*
- * If we want to keep the connection, be sure that the request body
- * (if any) has been read.
- */
- if ((r->status != HTTP_NOT_MODIFIED) && (r->status != HTTP_NO_CONTENT)
- && !ap_status_drops_connection(r->status)
- && r->connection && (r->connection->keepalive != -1)) {
-
- (void) ap_discard_request_body(r);
- }
-
- /*
- * Two types of custom redirects --- plain text, and URLs. Plain text has
- * a leading '"', so the URL code, here, is triggered on its absence
- */
-
- if (custom_response && custom_response[0] != '"') {
-
- if (ap_is_url(custom_response)) {
- /*
- * The URL isn't local, so lets drop through the rest of this
- * apache code, and continue with the usual REDIRECT handler.
- * But note that the client will ultimately see the wrong
- * status...
- */
- r->status = HTTP_MOVED_TEMPORARILY;
- apr_table_setn(r->headers_out, "Location", custom_response);
- }
- else if (custom_response[0] == '/') {
- const char *error_notes;
- r->no_local_copy = 1; /* Do NOT send HTTP_NOT_MODIFIED for
- * error documents! */
- /*
- * This redirect needs to be a GET no matter what the original
- * method was.
- */
- apr_table_setn(r->subprocess_env, "REQUEST_METHOD", r->method);
-
- /*
- * Provide a special method for modules to communicate
- * more informative (than the plain canned) messages to us.
- * Propagate them to ErrorDocuments via the ERROR_NOTES variable:
- */
- if ((error_notes = apr_table_get(r->notes, "error-notes")) != NULL) {
- apr_table_setn(r->subprocess_env, "ERROR_NOTES", error_notes);
- }
- r->method = apr_pstrdup(r->pool, "GET");
- r->method_number = M_GET;
- ap_internal_redirect(custom_response, r);
- return;
- }
- else {
- /*
- * Dumb user has given us a bad url to redirect to --- fake up
- * dying with a recursive server error...
- */
- recursive_error = HTTP_INTERNAL_SERVER_ERROR;
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Invalid error redirection directive: %s",
- custom_response);
- }
- }
- ap_send_error_response(r, recursive_error);
-}
-
-static void decl_die(int status, char *phase, request_rec *r)
-{
- if (status == DECLINED) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, 0, r,
- "configuration error: couldn't %s: %s", phase, r->uri);
- ap_die(HTTP_INTERNAL_SERVER_ERROR, r);
- }
- else
- ap_die(status, r);
-}
-
-static void process_request_internal(request_rec *r)
-{
- int access_status;
-
- /* Ignore embedded %2F's in path for proxy requests */
- if (!r->proxyreq && r->parsed_uri.path) {
- access_status = ap_unescape_url(r->parsed_uri.path);
- if (access_status) {
- ap_die(access_status, r);
- return;
- }
- }
-
- ap_getparents(r->uri); /* OK --- shrinking transformations... */
-
- if ((access_status = location_walk(r))) {
- ap_die(access_status, r);
- return;
- }
-
- if ((access_status = ap_run_translate_name(r))) {
- decl_die(access_status, "translate", r);
- return;
- }
-
- if (!r->proxyreq) {
- /*
- * We don't want TRACE to run through the normal handler set, we
- * handle it specially.
- */
- if (r->method_number == M_TRACE) {
- if ((access_status = ap_send_http_trace(r)))
- ap_die(access_status, r);
- else
- ap_finalize_request_protocol(r);
- return;
- }
- }
-
- if (r->proto_num > HTTP_VERSION(1,0) && apr_table_get(r->subprocess_env, "downgrade-1.0")) {
- r->proto_num = HTTP_VERSION(1,0);
- }
-
- /*
- * NB: directory_walk() clears the per_dir_config, so we don't inherit
- * from location_walk() above
- */
-
- if ((access_status = directory_walk(r))) {
- ap_die(access_status, r);
- return;
- }
-
- if ((access_status = file_walk(r))) {
- ap_die(access_status, r);
- return;
- }
-
- if ((access_status = location_walk(r))) {
- ap_die(access_status, r);
- return;
- }
-
- if ((access_status = ap_run_header_parser(r))) {
- ap_die(access_status, r);
- return;
- }
-
- switch (ap_satisfies(r)) {
- case SATISFY_ALL:
- case SATISFY_NOSPEC:
- if ((access_status = ap_run_access_checker(r)) != 0) {
- decl_die(access_status, "check access", r);
- return;
- }
- if (ap_some_auth_required(r)) {
- if (((access_status = ap_run_check_user_id(r)) != 0) || !ap_auth_type(r)) {
- decl_die(access_status, ap_auth_type(r)
- ? "check user. No user file?"
- : "perform authentication. AuthType not set!", r);
- return;
- }
- if (((access_status = ap_run_auth_checker(r)) != 0) || !ap_auth_type(r)) {
- decl_die(access_status, ap_auth_type(r)
- ? "check access. No groups file?"
- : "perform authentication. AuthType not set!", r);
- return;
- }
- }
- break;
- case SATISFY_ANY:
- if (((access_status = ap_run_access_checker(r)) != 0) || !ap_auth_type(r)) {
- if (!ap_some_auth_required(r)) {
- decl_die(access_status, ap_auth_type(r)
- ? "check access"
- : "perform authentication. AuthType not set!", r);
- return;
- }
- if (((access_status = ap_run_check_user_id(r)) != 0) || !ap_auth_type(r)) {
- decl_die(access_status, ap_auth_type(r)
- ? "check user. No user file?"
- : "perform authentication. AuthType not set!", r);
- return;
- }
- if (((access_status = ap_run_auth_checker(r)) != 0) || !ap_auth_type(r)) {
- decl_die(access_status, ap_auth_type(r)
- ? "check access. No groups file?"
- : "perform authentication. AuthType not set!", r);
- return;
- }
- }
- break;
- }
-
- if (! (r->proxyreq
- && r->parsed_uri.scheme != NULL
- && strcmp(r->parsed_uri.scheme, "http") == 0) ) {
- if ((access_status = ap_run_type_checker(r)) != 0) {
- decl_die(access_status, "find types", r);
- return;
- }
- }
-
- if ((access_status = ap_run_fixups(r)) != 0) {
- ap_die(access_status, r);
- return;
- }
-
- /* The new insert_filter stage makes sense here IMHO. We are sure that
- * we are going to run the request now, so we may as well insert filters
- * if any are available. Since the goal of this phase is to allow all
- * modules to insert a filter if they want to, this filter returns
- * void. I just can't see any way that this filter can reasonably
- * fail, either your modules inserts something or it doesn't. rbb
- */
- ap_run_insert_filter(r);
-
- if ((access_status = ap_invoke_handler(r)) != 0) {
- ap_die(access_status, r);
- return;
- }
-
- /* Take care of little things that need to happen when we're done */
- ap_finalize_request_protocol(r);
-}
-
-static void check_pipeline_flush(request_rec *r)
-{
- /* ### if would be nice if we could PEEK without a brigade. that would
- ### allow us to defer creation of the brigade to when we actually
- ### need to send a FLUSH. */
- apr_bucket_brigade *bb = apr_brigade_create(r->pool);
- apr_size_t zero = 0;
-
- /* Flush the filter contents if:
- *
- * 1) the connection will be closed
- * 2) there isn't a request ready to be read
- */
- /* ### shouldn't this read from the connection input filters? */
- if (!r->connection->keepalive ||
- ap_get_brigade(r->input_filters, bb, AP_MODE_PEEK, &zero) != APR_SUCCESS) {
- apr_bucket *e = apr_bucket_flush_create();
-
- /* We just send directly to the connection based filters. At
- * this point, we know that we have seen all of the data
- * (request finalization sent an EOS bucket, which empties all
- * of the request filters). We just want to flush the buckets
- * if something hasn't been sent to the network yet.
- */
- APR_BRIGADE_INSERT_HEAD(bb, e);
- ap_pass_brigade(r->connection->output_filters, bb);
- }
-}
-
-void ap_process_request(request_rec *r)
-{
- int access_status;
-
- /* Give quick handlers a shot at serving the request on the fast
- * path, bypassing all of the other Apache hooks.
- *
- * This hook was added to enable serving files out of a URI keyed
- * content cache ( e.g., Mike Abbott's Quick Shortcut Cache,
- * described here: http://oss.sgi.com/projects/apache/mod_qsc.html )
- *
- * It may have other uses as well, such as routing requests directly to
- * content handlers that have the ability to grok HTTP and do their
- * own access checking, etc (e.g. servlet engines).
- *
- * Use this hook with extreme care and only if you know what you are
- * doing.
- *
- * Consider moving this hook to after the first location_walk in order
- * to enable the quick handler to make decisions based on config
- * directives in Location blocks.
- */
- access_status = ap_run_quick_handler(r);
- if (access_status == OK) {
- ap_finalize_request_protocol(r);
- }
- else if (access_status == DECLINED) {
- process_request_internal(r);
- }
- else {
- ap_die(access_status, r);
- }
-
- /*
- * We want to flush the last packet if this isn't a pipelining connection
- * *before* we start into logging. Suppose that the logging causes a DNS
- * lookup to occur, which may have a high latency. If we hold off on
- * this packet, then it'll appear like the link is stalled when really
- * it's the application that's stalled.
- */
- check_pipeline_flush(r);
- ap_run_log_transaction(r);
-}
-
-static apr_table_t *rename_original_env(apr_pool_t *p, apr_table_t *t)
-{
- apr_array_header_t *env_arr = apr_table_elts(t);
- apr_table_entry_t *elts = (apr_table_entry_t *) env_arr->elts;
- apr_table_t *new = apr_table_make(p, env_arr->nalloc);
- int i;
-
- for (i = 0; i < env_arr->nelts; ++i) {
- if (!elts[i].key)
- continue;
- apr_table_setn(new, apr_pstrcat(p, "REDIRECT_", elts[i].key, NULL),
- elts[i].val);
- }
-
- return new;
-}
-
-static request_rec *internal_internal_redirect(const char *new_uri,
- request_rec *r) {
- int access_status;
- request_rec *new = (request_rec *) apr_pcalloc(r->pool,
- sizeof(request_rec));
-
- new->connection = r->connection;
- new->server = r->server;
- new->pool = r->pool;
-
- /*
- * A whole lot of this really ought to be shared with http_protocol.c...
- * another missing cleanup. It's particularly inappropriate to be
- * setting header_only, etc., here.
- */
-
- new->method = r->method;
- new->method_number = r->method_number;
- new->allowed_methods = ap_make_method_list(new->pool, 2);
- ap_parse_uri(new, new_uri);
-
- new->request_config = ap_create_request_config(r->pool);
-
- new->per_dir_config = r->server->lookup_defaults;
-
- new->prev = r;
- r->next = new;
-
- /* Must have prev and next pointers set before calling create_request
- * hook.
- */
- ap_run_create_request(new);
-
- /* Inherit the rest of the protocol info... */
-
- new->the_request = r->the_request;
-
- new->allowed = r->allowed;
-
- new->status = r->status;
- new->assbackwards = r->assbackwards;
- new->header_only = r->header_only;
- new->protocol = r->protocol;
- new->proto_num = r->proto_num;
- new->hostname = r->hostname;
- new->request_time = r->request_time;
- new->main = r->main;
-
- new->headers_in = r->headers_in;
- new->headers_out = apr_table_make(r->pool, 12);
- new->err_headers_out = r->err_headers_out;
- new->subprocess_env = rename_original_env(r->pool, r->subprocess_env);
- new->notes = apr_table_make(r->pool, 5);
- new->allowed_methods = ap_make_method_list(new->pool, 2);
-
- new->htaccess = r->htaccess;
- new->no_cache = r->no_cache;
- new->expecting_100 = r->expecting_100;
- new->no_local_copy = r->no_local_copy;
- new->read_length = r->read_length; /* We can only read it once */
- new->vlist_validator = r->vlist_validator;
-
- new->output_filters = r->connection->output_filters;
- new->input_filters = r->connection->input_filters;
-
- ap_add_output_filter("BYTERANGE", NULL, new, new->connection);
- ap_add_output_filter("CONTENT_LENGTH", NULL, new, new->connection);
- ap_add_output_filter("HTTP_HEADER", NULL, new, new->connection);
-
- apr_table_setn(new->subprocess_env, "REDIRECT_STATUS",
- apr_psprintf(r->pool, "%d", r->status));
-
- /*
- * XXX: hmm. This is because mod_setenvif and mod_unique_id really need
- * to do their thing on internal redirects as well. Perhaps this is a
- * misnamed function.
- */
- if ((access_status = ap_run_post_read_request(new))) {
- ap_die(access_status, new);
- return NULL;
- }
-
- return new;
-}
-
-AP_DECLARE(void) ap_internal_redirect(const char *new_uri, request_rec *r)
-{
- request_rec *new = internal_internal_redirect(new_uri, r);
- process_request_internal(new);
-}
-
-/* This function is designed for things like actions or CGI scripts, when
- * using AddHandler, and you want to preserve the content type across
- * an internal redirect.
- */
-AP_DECLARE(void) ap_internal_redirect_handler(const char *new_uri, request_rec *r)
-{
- request_rec *new = internal_internal_redirect(new_uri, r);
- if (r->handler)
- new->content_type = r->content_type;
- process_request_internal(new);
-}
-
-AP_DECLARE(void) ap_allow_methods(request_rec *r, int reset, ...)
-{
- const char *method;
- va_list methods;
-
- /*
- * Get rid of any current settings if requested; not just the
- * well-known methods but any extensions as well.
- */
- if (reset) {
- ap_clear_method_list(r->allowed_methods);
- }
-
- va_start(methods, reset);
- while ((method = va_arg(methods, const char *)) != NULL) {
- ap_method_list_add(r->allowed_methods, method);
- }
-}
diff --git a/modules/http/mod_core.h b/modules/http/mod_core.h
deleted file mode 100644
index 29fef07b65..0000000000
--- a/modules/http/mod_core.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#ifndef MOD_CORE_H
-#define MOD_CORE_H
-
-#include "apr.h"
-#include "apr_buckets.h"
-
-#include "httpd.h"
-#include "util_filter.h"
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * @package mod_core private header file
- */
-
-/*
- * These (input) filters are internal to the mod_core operation.
- */
-apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_size_t *readbytes);
-apr_status_t ap_dechunk_filter(ap_filter_t *f, apr_bucket_brigade *b, ap_input_mode_t mode, apr_size_t *readbytes);
-
-char *ap_response_code_string(request_rec *r, int error_index);
-
-/**
- * Send the minimal part of an HTTP response header.
- * @param r The current request
- * @param bb The brigade to add the header to.
- * @warning Modules should be very careful about using this, and should
- * the default behavior. Much of the HTTP/1.1 implementation
- * correctness depends on the full headers.
- * @deffunc void ap_basic_http_header(request_rec *r, apr_bucket_brigade *bb)
- */
-AP_DECLARE(void) ap_basic_http_header(request_rec *r, apr_bucket_brigade *bb);
-
-AP_DECLARE(int) ap_send_http_trace(request_rec *r);
-int ap_send_http_options(request_rec *r);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !MOD_CORE_H */
diff --git a/modules/http/mod_mime.c b/modules/http/mod_mime.c
deleted file mode 100644
index bbeee8fe3d..0000000000
--- a/modules/http/mod_mime.c
+++ /dev/null
@@ -1,823 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * http_mime.c: Sends/gets MIME headers for requests
- *
- * Rob McCool
- *
- */
-
-#include "apr.h"
-#include "apr_strings.h"
-#include "apr_lib.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_log.h"
-#include "http_request.h"
-
-
-/* XXXX - fix me / EBCDIC
- * there was a cludge here which would use its
- * own version apr_isascii(). Indicating that
- * on some platforms that might be needed.
- *
- * #define OS_ASC(c) (c) -- for mere mortals
- * or
- * #define OS_ASC(c) (ebcdic2ascii[c]) -- for dino's
- *
- * #define apr_isascii(c) ((OS_ASC(c) & 0x80) == 0)
- */
-
-/* XXXXX - fix me - See note with NOT_PROXY
- */
-
-typedef struct attrib_info {
- char *name;
-} attrib_info;
-
-typedef struct {
- apr_table_t *forced_types; /* Additional AddTyped stuff */
- apr_table_t *encoding_types; /* Added with AddEncoding... */
- apr_table_t *language_types; /* Added with AddLanguage... */
- apr_table_t *handlers; /* Added with AddHandler... */
- apr_table_t *charset_types; /* Added with AddCharset... */
- apr_array_header_t *handlers_remove; /* List of handlers to remove */
- apr_array_header_t *types_remove; /* List of MIME types to remove */
- apr_array_header_t *encodings_remove; /* List of encodings to remove */
-
- char *type; /* Type forced with ForceType */
- char *handler; /* Handler forced with SetHandler */
- char *default_language; /* Language if no AddLanguage ext found */
- /* Due to the FUD about JS and charsets
- * default_charset is actually in src/main */
-} mime_dir_config;
-
-typedef struct param_s {
- char *attr;
- char *val;
- struct param_s *next;
-} param;
-
-typedef struct {
- char *type;
- char *subtype;
- param *param;
-} content_type;
-
-static char tspecial[] = {
- '(', ')', '<', '>', '@', ',', ';', ':',
- '\\', '"', '/', '[', ']', '?', '=',
- '\0'
-};
-
-module AP_MODULE_DECLARE_DATA mime_module;
-
-static void *create_mime_dir_config(apr_pool_t *p, char *dummy)
-{
- mime_dir_config *new =
- (mime_dir_config *) apr_palloc(p, sizeof(mime_dir_config));
-
- new->forced_types = apr_table_make(p, 4);
- new->encoding_types = apr_table_make(p, 4);
- new->charset_types = apr_table_make(p, 4);
- new->language_types = apr_table_make(p, 4);
- new->handlers = apr_table_make(p, 4);
- new->handlers_remove = apr_array_make(p, 4, sizeof(attrib_info));
- new->types_remove = apr_array_make(p, 4, sizeof(attrib_info));
- new->encodings_remove = apr_array_make(p, 4, sizeof(attrib_info));
-
- new->type = NULL;
- new->handler = NULL;
- new->default_language = NULL;
-
- return new;
-}
-
-static void *merge_mime_dir_configs(apr_pool_t *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 *) apr_palloc(p, sizeof(mime_dir_config));
- int i;
- attrib_info *suffix;
-
- new->forced_types = apr_table_overlay(p, add->forced_types,
- base->forced_types);
- new->encoding_types = apr_table_overlay(p, add->encoding_types,
- base->encoding_types);
- new->charset_types = apr_table_overlay(p, add->charset_types,
- base->charset_types);
- new->language_types = apr_table_overlay(p, add->language_types,
- base->language_types);
- new->handlers = apr_table_overlay(p, add->handlers,
- base->handlers);
-
- suffix = (attrib_info *) add->handlers_remove->elts;
- for (i = 0; i < add->handlers_remove->nelts; i++) {
- apr_table_unset(new->handlers, suffix[i].name);
- }
-
- suffix = (attrib_info *) add->types_remove->elts;
- for (i = 0; i < add->types_remove->nelts; i++) {
- apr_table_unset(new->forced_types, suffix[i].name);
- }
-
- suffix = (attrib_info *) add->encodings_remove->elts;
- for (i = 0; i < add->encodings_remove->nelts; i++) {
- apr_table_unset(new->encoding_types, suffix[i].name);
- }
-
-
- new->type = add->type ? add->type : base->type;
- new->handler = add->handler ? add->handler : base->handler;
- new->default_language = add->default_language ?
- add->default_language : base->default_language;
-
- return new;
-}
-
-static const char *add_type(cmd_parms *cmd, void *m_, const char *ct_,
- const char *ext)
-{
- mime_dir_config *m=m_;
- char *ct=apr_pstrdup(cmd->pool,ct_);
-
- if (*ext == '.')
- ++ext;
-
- ap_str_tolower(ct);
- apr_table_setn(m->forced_types, ext, ct);
- return NULL;
-}
-
-static const char *add_encoding(cmd_parms *cmd, void *m_, const char *enc_,
- const char *ext)
-{
- mime_dir_config *m=m_;
- char *enc=apr_pstrdup(cmd->pool,enc_);
-
- if (*ext == '.')
- ++ext;
- ap_str_tolower(enc);
- apr_table_setn(m->encoding_types, ext, enc);
- return NULL;
-}
-
-static const char *add_charset(cmd_parms *cmd, void *m_, const char *charset_,
- const char *ext)
-{
- mime_dir_config *m=m_;
- char *charset=apr_pstrdup(cmd->pool,charset_);
-
- if (*ext == '.') {
- ++ext;
- }
- ap_str_tolower(charset);
- apr_table_setn(m->charset_types, ext, charset);
- return NULL;
-}
-
-static const char *add_language(cmd_parms *cmd, void *m_, const char *lang_,
- const char *ext)
-{
- mime_dir_config *m=m_;
- char *lang=apr_pstrdup(cmd->pool,lang_);
-
- if (*ext == '.') {
- ++ext;
- }
- ap_str_tolower(lang);
- apr_table_setn(m->language_types, ext, lang);
- return NULL;
-}
-
-static const char *add_handler(cmd_parms *cmd, void *m_, const char *hdlr_,
- const char *ext)
-{
- mime_dir_config *m=m_;
- char *hdlr=apr_pstrdup(cmd->pool,hdlr_);
-
- if (*ext == '.')
- ++ext;
- ap_str_tolower(hdlr);
- apr_table_setn(m->handlers, ext, hdlr);
- return NULL;
-}
-
-/*
- * Note handler names that should be un-added for this location. This
- * will keep the association from being inherited, as well, but not
- * from being re-added at a subordinate level.
- */
-static const char *remove_handler(cmd_parms *cmd, void *m, const char *ext)
-{
- mime_dir_config *mcfg = (mime_dir_config *) m;
- attrib_info *suffix;
-
- if (*ext == '.') {
- ++ext;
- }
- suffix = (attrib_info *) apr_array_push(mcfg->handlers_remove);
- suffix->name = apr_pstrdup(cmd->pool, ext);
- return NULL;
-}
-
-/*
- * Just like the previous function, except that it records encoding
- * associations to be undone.
- */
-static const char *remove_encoding(cmd_parms *cmd, void *m, const char *ext)
-{
- mime_dir_config *mcfg = (mime_dir_config *) m;
- attrib_info *suffix;
-
- if (*ext == '.') {
- ++ext;
- }
- suffix = (attrib_info *) apr_array_push(mcfg->encodings_remove);
- suffix->name = apr_pstrdup(cmd->pool, ext);
- return NULL;
-}
-
-/*
- * Similar to the previous functions, except that it deals with filename
- * suffix/MIME-type associations.
- */
-static const char *remove_type(cmd_parms *cmd, void *m, const char *ext)
-{
- mime_dir_config *mcfg = (mime_dir_config *) m;
- attrib_info *suffix;
-
- if (*ext == '.') {
- ++ext;
- }
- suffix = (attrib_info *) apr_array_push(mcfg->types_remove);
- suffix->name = apr_pstrdup(cmd->pool, ext);
- return NULL;
-}
-
-/* The sole bit of server configuration that the MIME module has is
- * the name of its config file, so...
- */
-
-static const char *set_types_config(cmd_parms *cmd, void *dummy,
- const char *arg)
-{
- ap_set_module_config(cmd->server->module_config, &mime_module,
- (void *)arg);
- return NULL;
-}
-
-static const command_rec mime_cmds[] =
-{
-AP_INIT_ITERATE2("AddType", add_type, NULL, OR_FILEINFO,
- "a mime type followed by one or more file extensions"),
-AP_INIT_ITERATE2("AddEncoding", add_encoding, NULL, OR_FILEINFO,
- "an encoding (e.g., gzip), followed by one or more file extensions"),
-AP_INIT_ITERATE2("AddCharset", add_charset, NULL, OR_FILEINFO,
- "a charset (e.g., iso-2022-jp), followed by one or more file extensions"),
-AP_INIT_ITERATE2("AddLanguage", add_language, NULL, OR_FILEINFO,
- "a language (e.g., fr), followed by one or more file extensions"),
-AP_INIT_ITERATE2("AddHandler", add_handler, NULL, OR_FILEINFO,
- "a handler name followed by one or more file extensions"),
-AP_INIT_TAKE1("ForceType", ap_set_string_slot_lower,
- (void *)XtOffsetOf(mime_dir_config, type), OR_FILEINFO,
- "a media type"),
-AP_INIT_ITERATE("RemoveHandler", remove_handler, NULL, OR_FILEINFO,
- "one or more file extensions"),
-AP_INIT_ITERATE("RemoveEncoding", remove_encoding, NULL, OR_FILEINFO,
- "one or more file extensions"),
-AP_INIT_ITERATE("RemoveType", remove_type, NULL, OR_FILEINFO,
- "one or more file extensions"),
-AP_INIT_TAKE1("SetHandler", ap_set_string_slot_lower,
- (void *)XtOffsetOf(mime_dir_config, handler), OR_FILEINFO,
- "a handler name"),
-AP_INIT_TAKE1("TypesConfig", set_types_config, NULL, RSRC_CONF,
- "the MIME types config file"),
-AP_INIT_TAKE1("DefaultLanguage", ap_set_string_slot,
- (void*)XtOffsetOf(mime_dir_config, default_language), OR_FILEINFO,
- "language to use for documents with no other language file extension"),
- {NULL}
-};
-
-/* Hash apr_table_t --- only one of these per daemon; virtual hosts can
- * get private versions through AddType...
- */
-
-#define MIME_HASHSIZE (32)
-#define hash(i) (apr_tolower(i) % MIME_HASHSIZE)
-
-static apr_table_t *hash_buckets[MIME_HASHSIZE];
-
-static void mime_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
-{
- ap_configfile_t *f;
- char l[MAX_STRING_LEN];
- int x;
- const char *types_confname = ap_get_module_config(s->module_config, &mime_module);
- apr_status_t status;
-
- if (!types_confname)
- types_confname = AP_TYPES_CONFIG_FILE;
-
- types_confname = ap_server_root_relative(p, types_confname);
-
- if ((status = ap_pcfg_openfile(&f, p, types_confname)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, status, s,
- "could not open mime types config file %s.", types_confname);
- exit(1);
- }
-
- for (x = 0; x < MIME_HASHSIZE; x++)
- hash_buckets[x] = apr_table_make(p, 10);
-
- while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) {
- const char *ll = l, *ct;
-
- if (l[0] == '#')
- continue;
- ct = ap_getword_conf(p, &ll);
-
- while (ll[0]) {
- char *ext = ap_getword_conf(p, &ll);
- ap_str_tolower(ext); /* ??? */
- apr_table_setn(hash_buckets[hash(ext[0])], ext, ct);
- }
- }
- ap_cfg_closefile(f);
-}
-
-static char *zap_sp(char *s)
-{
- char *tp;
-
- if (s == NULL) {
- return (NULL);
- }
- if (*s == '\0') {
- return (s);
- }
-
- /* delete prefixed white space */
- for (; *s == ' ' || *s == '\t' || *s == '\n'; s++);
-
- /* delete postfixed white space */
- for (tp = s; *tp != '\0'; tp++);
- for (tp--; tp != s && (*tp == ' ' || *tp == '\t' || *tp == '\n'); tp--) {
- *tp = '\0';
- }
- return (s);
-}
-
-static int is_token(char c)
-{
- int res;
-
- res = (apr_isascii(c) && apr_isgraph(c)
- && (strchr(tspecial, c) == NULL)) ? 1 : -1;
- return res;
-}
-
-static int is_qtext(char c)
-{
- int res;
-
- res = (apr_isascii(c) && (c != '"') && (c != '\\') && (c != '\n'))
- ? 1 : -1;
- return res;
-}
-
-static int is_quoted_pair(char *s)
-{
- int res = -1;
- int c;
-
- if (((s + 1) != NULL) && (*s == '\\')) {
- c = (int) *(s + 1);
- if (apr_isascii(c)) {
- res = 1;
- }
- }
- return (res);
-}
-
-static content_type *analyze_ct(request_rec *r, char *s)
-{
- char *tp, *mp, *cp;
- char *attribute, *value;
- int quoted = 0;
- server_rec * ss = r->server;
- apr_pool_t * p = r->pool;
-
- content_type *ctp;
- param *pp, *npp;
-
- /* initialize ctp */
- ctp = (content_type *) apr_palloc(p, sizeof(content_type));
- ctp->type = NULL;
- ctp->subtype = NULL;
- ctp->param = NULL;
-
- tp = apr_pstrdup(p, s);
-
- mp = tp;
- cp = mp;
-
- /* getting a type */
- if (!(cp = strchr(mp, '/'))) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss,
- "mod_mime: analyze_ct: cannot get media type from '%s'",
- (const char *) mp);
- return (NULL);
- }
- ctp->type = apr_pstrndup(p, mp, cp - mp);
- ctp->type = zap_sp(ctp->type);
- if (ctp->type == NULL || *(ctp->type) == '\0' ||
- strchr(ctp->type, ';') || strchr(ctp->type, ' ') ||
- strchr(ctp->type, '\t')) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss,
- "Cannot get media subtype.");
- return (NULL);
- }
-
- /* getting a subtype */
- cp++;
- mp = cp;
-
- for (; *cp != ';' && *cp != '\0'; cp++)
- continue;
- ctp->subtype = apr_pstrndup(p, mp, cp - mp);
- ctp->subtype = zap_sp(ctp->subtype);
- if ((ctp->subtype == NULL) || (*(ctp->subtype) == '\0') ||
- strchr(ctp->subtype, ' ') || strchr(ctp->subtype, '\t')) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss,
- "Cannot get media subtype.");
- return (NULL);
- }
- cp = zap_sp(cp);
- if (cp == NULL || *cp == '\0') {
- return (ctp);
- }
-
- /* getting parameters */
- cp++;
- cp = zap_sp(cp);
- if (cp == NULL || *cp == '\0') {
- ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss,
- "Cannot get media parameter.");
- return (NULL);
- }
- mp = cp;
- attribute = NULL;
- value = NULL;
-
- while (cp != NULL && *cp != '\0') {
- if (attribute == NULL) {
- if (is_token(*cp) > 0) {
- cp++;
- continue;
- }
- else if (*cp == ' ' || *cp == '\t' || *cp == '\n') {
- cp++;
- continue;
- }
- else if (*cp == '=') {
- attribute = apr_pstrndup(p, mp, cp - mp);
- attribute = zap_sp(attribute);
- if (attribute == NULL || *attribute == '\0') {
- ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss,
- "Cannot get media parameter.");
- return (NULL);
- }
- cp++;
- cp = zap_sp(cp);
- if (cp == NULL || *cp == '\0') {
- ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss,
- "Cannot get media parameter.");
- return (NULL);
- }
- mp = cp;
- continue;
- }
- else {
- ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss,
- "Cannot get media parameter.");
- return (NULL);
- }
- }
- else {
- if (mp == cp) {
- if (*cp == '"') {
- quoted = 1;
- cp++;
- }
- else {
- quoted = 0;
- }
- }
- if (quoted > 0) {
- while (quoted && *cp != '\0') {
- if (is_qtext(*cp) > 0) {
- cp++;
- }
- else if (is_quoted_pair(cp) > 0) {
- cp += 2;
- }
- else if (*cp == '"') {
- cp++;
- while (*cp == ' ' || *cp == '\t' || *cp == '\n') {
- cp++;
- }
- if (*cp != ';' && *cp != '\0') {
- ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss,
- "Cannot get media parameter.");
- return(NULL);
- }
- quoted = 0;
- }
- else {
- ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss,
- "Cannot get media parameter.");
- return (NULL);
- }
- }
- }
- else {
- while (1) {
- if (is_token(*cp) > 0) {
- cp++;
- }
- else if (*cp == '\0' || *cp == ';') {
- break;
- }
- else {
- ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss,
- "Cannot get media parameter.");
- return (NULL);
- }
- }
- }
- value = apr_pstrndup(p, mp, cp - mp);
- value = zap_sp(value);
- if (value == NULL || *value == '\0') {
- ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ss,
- "Cannot get media parameter.");
- return (NULL);
- }
-
- pp = apr_palloc(p, sizeof(param));
- pp->attr = attribute;
- pp->val = value;
- pp->next = NULL;
-
- if (ctp->param == NULL) {
- ctp->param = pp;
- }
- else {
- npp = ctp->param;
- while (npp->next) {
- npp = npp->next;
- }
- npp->next = pp;
- }
- quoted = 0;
- attribute = NULL;
- value = NULL;
- if (*cp == '\0') {
- break;
- }
- cp++;
- mp = cp;
- }
- }
- return (ctp);
-}
-
-static int find_ct(request_rec *r)
-{
- const char *fn = strrchr(r->filename, '/');
- mime_dir_config *conf =
- (mime_dir_config *) ap_get_module_config(r->per_dir_config, &mime_module);
- char *ext;
- const char *orighandler = r->handler;
- const char *type;
- const char *charset = NULL;
-
- if (r->finfo.filetype == APR_DIR) {
- r->content_type = DIR_MAGIC_TYPE;
- return OK;
- }
-
- /* TM -- FIXME
- * if r->filename does not contain a '/', the following passes a null
- * pointer to getword, causing a SEGV ..
- */
-
- if (fn == NULL) {
- fn = r->filename;
- }
-
- /* Parse filename extensions, which can be in any order */
- while ((ext = ap_getword(r->pool, &fn, '.')) && *ext) {
- int found = 0;
-
- /* Check for Content-Type */
- if ((type = apr_table_get(conf->forced_types, ext))
- || (type = apr_table_get(hash_buckets[hash(*ext)], ext))) {
- r->content_type = type;
- found = 1;
- }
-
- /* Add charset to Content-Type */
- if ((type = apr_table_get(conf->charset_types, ext))) {
- charset = type;
- found = 1;
- }
-
- /* Check for Content-Language */
- if ((type = apr_table_get(conf->language_types, ext))) {
- const char **new;
-
- r->content_language = type; /* back compat. only */
- if (!r->content_languages)
- r->content_languages = apr_array_make(r->pool, 2, sizeof(char *));
- new = (const char **) apr_array_push(r->content_languages);
- *new = type;
- found = 1;
- }
-
- /* Check for Content-Encoding */
- if ((type = apr_table_get(conf->encoding_types, ext))) {
- if (!r->content_encoding)
- r->content_encoding = type;
- else
- r->content_encoding = apr_pstrcat(r->pool, r->content_encoding,
- ", ", type, NULL);
- found = 1;
- }
-
- /* Check for a special handler, but not for proxy request */
- if ((type = apr_table_get(conf->handlers, ext))
- && (PROXYREQ_NONE == r->proxyreq)
- ) {
- r->handler = type;
- found = 1;
- }
-
- /* This is to deal with cases such as foo.gif.bak, which we want
- * to not have a type. So if we find an unknown extension, we
- * zap the type/language/encoding and reset the handler
- */
-
- if (!found) {
- r->content_type = NULL;
- r->content_language = NULL;
- r->content_languages = NULL;
- r->content_encoding = NULL;
- r->handler = orighandler;
- charset = NULL;
- }
- }
-
- if (r->content_type) {
- content_type *ctp;
- char *ct;
- int override = 0;
-
- ct = (char *) apr_palloc(r->pool,
- sizeof(char) * (strlen(r->content_type) + 1));
- strcpy(ct, r->content_type);
-
- if ((ctp = analyze_ct(r, ct))) {
- param *pp = ctp->param;
- r->content_type = apr_pstrcat(r->pool, ctp->type, "/",
- ctp->subtype, NULL);
- while (pp != NULL) {
- if (charset && !strcmp(pp->attr, "charset")) {
- if (!override) {
- r->content_type = apr_pstrcat(r->pool, r->content_type,
- "; charset=", charset,
- NULL);
- override = 1;
- }
- }
- else {
- r->content_type = apr_pstrcat(r->pool, r->content_type,
- "; ", pp->attr,
- "=", pp->val,
- NULL);
- }
- pp = pp->next;
- }
- if (charset && !override) {
- r->content_type = apr_pstrcat(r->pool, r->content_type,
- "; charset=", charset,
- NULL);
- }
- }
- }
-
- /* Set default language, if none was specified by the extensions
- * and we have a DefaultLanguage setting in force
- */
-
- if (!r->content_languages && conf->default_language) {
- const char **new;
-
- r->content_language = conf->default_language; /* back compat. only */
- if (!r->content_languages)
- r->content_languages = apr_array_make(r->pool, 2, sizeof(char *));
- new = (const char **) apr_array_push(r->content_languages);
- *new = conf->default_language;
- }
-
- /* Check for overrides with ForceType/SetHandler */
-
- if (conf->type && strcmp(conf->type, "none"))
- r->content_type = conf->type;
- if (conf->handler && strcmp(conf->handler, "none"))
- r->handler = conf->handler;
-
- if (!r->content_type)
- return DECLINED;
-
- return OK;
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_type_checker(find_ct,NULL,NULL,APR_HOOK_MIDDLE);
- ap_hook_post_config(mime_post_config,NULL,NULL,APR_HOOK_MIDDLE);
-}
-
-module AP_MODULE_DECLARE_DATA mime_module = {
- STANDARD20_MODULE_STUFF,
- create_mime_dir_config, /* create per-directory config structure */
- merge_mime_dir_configs, /* merge per-directory config structures */
- NULL, /* create per-server config structure */
- NULL, /* merge per-server config structures */
- mime_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
diff --git a/modules/http/mod_mime.exp b/modules/http/mod_mime.exp
deleted file mode 100644
index f2e38dbdda..0000000000
--- a/modules/http/mod_mime.exp
+++ /dev/null
@@ -1 +0,0 @@
-mime_module
diff --git a/modules/loggers/.cvsignore b/modules/loggers/.cvsignore
deleted file mode 100644
index 65f0cc30cf..0000000000
--- a/modules/loggers/.cvsignore
+++ /dev/null
@@ -1,10 +0,0 @@
-.deps
-.libs
-*.la
-modules.mk
-Makefile
-*.lo
-*.slo
-*.so
-Debug
-Release
diff --git a/modules/loggers/.indent.pro b/modules/loggers/.indent.pro
deleted file mode 100644
index a9fbe9f9a1..0000000000
--- a/modules/loggers/.indent.pro
+++ /dev/null
@@ -1,54 +0,0 @@
--i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1
--TBUFF
--TFILE
--TTRANS
--TUINT4
--T_trans
--Tallow_options_t
--Tapache_sfio
--Tarray_header
--Tbool_int
--Tbuf_area
--Tbuff_struct
--Tbuffy
--Tcmd_how
--Tcmd_parms
--Tcommand_rec
--Tcommand_struct
--Tconn_rec
--Tcore_dir_config
--Tcore_server_config
--Tdir_maker_func
--Tevent
--Tglobals_s
--Thandler_func
--Thandler_rec
--Tjoblist_s
--Tlisten_rec
--Tmerger_func
--Tmode_t
--Tmodule
--Tmodule_struct
--Tmutex
--Tn_long
--Tother_child_rec
--Toverrides_t
--Tparent_score
--Tpid_t
--Tpiped_log
--Tpool
--Trequest_rec
--Trequire_line
--Trlim_t
--Tscoreboard
--Tsemaphore
--Tserver_addr_rec
--Tserver_rec
--Tserver_rec_chain
--Tshort_score
--Ttable
--Ttable_entry
--Tthread
--Tu_wide_int
--Tvtime_t
--Twide_int
diff --git a/modules/loggers/Makefile.in b/modules/loggers/Makefile.in
deleted file mode 100644
index 167b343d0d..0000000000
--- a/modules/loggers/Makefile.in
+++ /dev/null
@@ -1,3 +0,0 @@
-
-include $(top_srcdir)/build/special.mk
-
diff --git a/modules/loggers/config.m4 b/modules/loggers/config.m4
deleted file mode 100644
index 8d4304abc4..0000000000
--- a/modules/loggers/config.m4
+++ /dev/null
@@ -1,9 +0,0 @@
-dnl modules enabled in this directory by default
-
-dnl APACHE_MODULE(name, helptext[, objects[, structname[, default[, config]]]])
-
-APACHE_MODPATH_INIT(loggers)
-
-APACHE_MODULE(log_config, logging configuration, , , yes)
-
-APACHE_MODPATH_FINISH
diff --git a/modules/loggers/mod_log_config.c b/modules/loggers/mod_log_config.c
deleted file mode 100644
index c2b655c455..0000000000
--- a/modules/loggers/mod_log_config.c
+++ /dev/null
@@ -1,1229 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * Modified by djm@va.pubnix.com:
- * If no TransferLog is given explicitly, decline to log.
- *
- * This is module implements the TransferLog directive (same as the
- * common log module), and additional directives, LogFormat and CustomLog.
- *
- *
- * Syntax:
- *
- * TransferLog fn Logs transfers to fn in standard log format, unless
- * a custom format is set with LogFormat
- * LogFormat format Set a log format from TransferLog files
- * CustomLog fn format
- * Log to file fn with format given by the format
- * argument
- *
- * CookieLog fn For backwards compatability with old Cookie
- * logging module - now deprecated.
- *
- * There can be any number of TransferLog and CustomLog
- * commands. Each request will be logged to _ALL_ the
- * named files, in the appropriate format.
- *
- * If no TransferLog or CustomLog directive appears in a VirtualHost,
- * the request will be logged to the log file(s) defined outside
- * the virtual host section. If a TransferLog or CustomLog directive
- * appears in the VirtualHost section, the log files defined outside
- * the VirtualHost will _not_ be used. This makes this module compatable
- * with the CLF and config log modules, where the use of TransferLog
- * inside the VirtualHost section overrides its use outside.
- *
- * Examples:
- *
- * TransferLog logs/access_log
- * <VirtualHost>
- * LogFormat "... custom format ..."
- * TransferLog log/virtual_only
- * CustomLog log/virtual_useragents "%t %{user-agent}i"
- * </VirtualHost>
- *
- * This will log using CLF to access_log any requests handled by the
- * main server, while any requests to the virtual host will be logged
- * with the "... custom format..." to virtual_only _AND_ using
- * the custom user-agent log to virtual_useragents.
- *
- * Note that the NCSA referer and user-agent logs are easily added with
- * CustomLog:
- * CustomLog logs/referer "%{referer}i -> %U"
- * CustomLog logs/agent "%{user-agent}i"
- *
- * RefererIgnore functionality can be obtained with conditional
- * logging (SetEnvIf and CustomLog ... env=!VAR).
- *
- * But using this method allows much easier modification of the
- * log format, e.g. to log hosts along with UA:
- * CustomLog logs/referer "%{referer}i %U %h"
- *
- * The argument to LogFormat and CustomLog is a string, which can include
- * literal characters copied into the log files, and '%' directives as
- * follows:
- *
- * %...B: bytes sent, excluding HTTP headers.
- * %...b: bytes sent, excluding HTTP headers in CLF format, i.e. a '-'
- * when no bytes where sent (rather than a '0'.
- * %...c: Status of the connection.
- * 'X' = connection aborted before the response completed.
- * '+' = connection may be kept alive after the response is sent.
- * '-' = connection will be closed after the response is sent.
- * %...{FOOBAR}C: The contents of the HTTP cookie FOOBAR
- * %...{FOOBAR}e: The contents of the environment variable FOOBAR
- * %...f: filename
- * %...h: remote host
- * %...a: remote IP-address
- * %...A: local IP-address
- * %...{Foobar}i: The contents of Foobar: header line(s) in the request
- * sent to the client.
- * %...l: remote logname (from identd, if supplied)
- * %...{Foobar}n: The contents of note "Foobar" from another module.
- * %...{Foobar}o: The contents of Foobar: header line(s) in the reply.
- * %...p: the port the request was served to
- * %...P: the process ID of the child that serviced the request.
- * %...r: first line of request
- * %...s: status. For requests that got internally redirected, this
- * is status of the *original* request --- %...>s for the last.
- * %...t: time, in common log format time format
- * %...{format}t: The time, in the form given by format, which should
- * be in strftime(3) format.
- * %...T: the time taken to serve the request, in seconds.
- * %...D: the time taken to serve the request, in micro seconds.
- * %...u: remote user (from auth; may be bogus if return status (%s) is 401)
- * %...U: the URL path requested.
- * %...v: the configured name of the server (i.e. which virtual host?)
- * %...V: the server name according to the UseCanonicalName setting
- * %...m: the request method
- * %...H: the request protocol
- * %...q: the query string prepended by "?", or empty if no query string
- *
- * The '...' can be nothing at all (e.g. "%h %u %r %s %b"), or it can
- * indicate conditions for inclusion of the item (which will cause it
- * to be replaced with '-' if the condition is not met). Note that
- * there is no escaping performed on the strings from %r, %...i and
- * %...o; some with long memories may remember that I thought this was
- * a bad idea, once upon a time, and I'm still not comfortable with
- * it, but it is difficult to see how to "do the right thing" with all
- * of '%..i', unless we URL-escape everything and break with CLF.
- *
- * The forms of condition are a list of HTTP status codes, which may
- * or may not be preceded by '!'. Thus, '%400,501{User-agent}i' logs
- * User-agent: on 400 errors and 501 errors (Bad Request, Not
- * Implemented) only; '%!200,304,302{Referer}i' logs Referer: on all
- * requests which did *not* return some sort of normal status.
- *
- * The default LogFormat reproduces CLF; see below.
- *
- * The way this is supposed to work with virtual hosts is as follows:
- * a virtual host can have its own LogFormat, or its own TransferLog.
- * If it doesn't have its own LogFormat, it inherits from the main
- * server. If it doesn't have its own TransferLog, it writes to the
- * same descriptor (meaning the same process for "| ...").
- *
- * --- rst */
-
-#include "apr_strings.h"
-#include "apr_lib.h"
-#include "apr_hash.h"
-#include "apr_optional.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#include "ap_config.h"
-#include "mod_log_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_core.h" /* For REMOTE_NAME */
-#include "http_log.h"
-#include "http_protocol.h"
-
-#if APR_HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#endif
-
-#define DEFAULT_LOG_FORMAT "%h %l %u %t \"%r\" %>s %b"
-
-module AP_MODULE_DECLARE_DATA log_config_module;
-
-static int xfer_flags = (APR_WRITE | APR_APPEND | APR_CREATE);
-static apr_fileperms_t xfer_perms = APR_OS_DEFAULT;
-static apr_hash_t *log_hash;
-
-/* POSIX.1 defines PIPE_BUF as the maximum number of bytes that is
- * guaranteed to be atomic when writing a pipe. And PIPE_BUF >= 512
- * is guaranteed. So we'll just guess 512 in the event the system
- * doesn't have this. Now, for file writes there is actually no limit,
- * the entire write is atomic. Whether all systems implement this
- * correctly is another question entirely ... so we'll just use PIPE_BUF
- * because it's probably a good guess as to what is implemented correctly
- * everywhere.
- */
-#ifdef PIPE_BUF
-#define LOG_BUFSIZE PIPE_BUF
-#else
-#define LOG_BUFSIZE (512)
-#endif
-
-/*
- * multi_log_state is our per-(virtual)-server configuration. We store
- * an array of the logs we are going to use, each of type config_log_state.
- * If a default log format is given by LogFormat, store in default_format
- * (backward compat. with mod_log_config). We also store for each virtual
- * server a pointer to the logs specified for the main server, so that if this
- * vhost has no logs defined, we can use the main server's logs instead.
- *
- * So, for the main server, config_logs contains a list of the log files
- * and server_config_logs in empty. For a vhost, server_config_logs
- * points to the same array as config_logs in the main server, and
- * config_logs points to the array of logs defined inside this vhost,
- * which might be empty.
- */
-
-typedef struct {
- const char *default_format_string;
- apr_array_header_t *default_format;
- apr_array_header_t *config_logs;
- apr_array_header_t *server_config_logs;
- apr_table_t *formats;
-} multi_log_state;
-
-/*
- * config_log_state holds the status of a single log file. fname might
- * be NULL, which means this module does no logging for this
- * request. format might be NULL, in which case the default_format
- * from the multi_log_state should be used, or if that is NULL as
- * well, use the CLF. log_fd is NULL before the log file is opened and
- * set to a valid fd after it is opened.
- */
-
-typedef struct {
- const char *fname;
- const char *format_string;
- apr_array_header_t *format;
- apr_file_t *log_fd;
- char *condition_var;
-#ifdef BUFFERED_LOGS
- apr_size_t outcnt;
- char outbuf[LOG_BUFSIZE];
-#endif
-} config_log_state;
-
-/*
- * Format items...
- * Note that many of these could have ap_sprintfs replaced with static buffers.
- */
-
-typedef struct {
- ap_log_handler_fn_t *func;
- char *arg;
- int condition_sense;
- int want_orig;
- apr_array_header_t *conditions;
-} log_format_item;
-
-static char *format_integer(apr_pool_t *p, int i)
-{
- return apr_psprintf(p, "%d", i);
-}
-
-static char *pfmt(apr_pool_t *p, int i)
-{
- if (i <= 0) {
- return "-";
- }
- else {
- return format_integer(p, i);
- }
-}
-
-static const char *constant_item(request_rec *dummy, char *stuff)
-{
- return stuff;
-}
-
-static const char *log_remote_host(request_rec *r, char *a)
-{
- return ap_get_remote_host(r->connection, r->per_dir_config,
- REMOTE_NAME, NULL);
-}
-
-static const char *log_remote_address(request_rec *r, char *a)
-{
- return r->connection->remote_ip;
-}
-
-static const char *log_local_address(request_rec *r, char *a)
-{
- return r->connection->local_ip;
-}
-
-static const char *log_remote_logname(request_rec *r, char *a)
-{
- return ap_get_remote_logname(r);
-}
-
-static const char *log_remote_user(request_rec *r, char *a)
-{
- char *rvalue = r->user;
-
- if (rvalue == NULL) {
- rvalue = "-";
- }
- else if (strlen(rvalue) == 0) {
- rvalue = "\"\"";
- }
- return rvalue;
-}
-
-static const char *log_request_line(request_rec *r, char *a)
-{
- /* NOTE: If the original request contained a password, we
- * re-write the request line here to contain XXXXXX instead:
- * (note the truncation before the protocol string for HTTP/0.9 requests)
- * (note also that r->the_request contains the unmodified request)
- */
- return (r->parsed_uri.password) ? apr_pstrcat(r->pool, r->method, " ",
- ap_unparse_uri_components(r->pool, &r->parsed_uri, 0),
- r->assbackwards ? NULL : " ", r->protocol, NULL)
- : r->the_request;
-}
-
-static const char *log_request_file(request_rec *r, char *a)
-{
- return r->filename;
-}
-static const char *log_request_uri(request_rec *r, char *a)
-{
- return r->uri;
-}
-static const char *log_request_method(request_rec *r, char *a)
-{
- return r->method;
-}
-static const char *log_request_protocol(request_rec *r, char *a)
-{
- return r->protocol;
-}
-static const char *log_request_query(request_rec *r, char *a)
-{
- return (r->args != NULL) ? apr_pstrcat(r->pool, "?", r->args, NULL)
- : "";
-}
-static const char *log_status(request_rec *r, char *a)
-{
- return pfmt(r->pool, r->status);
-}
-
-static const char *clf_log_bytes_sent(request_rec *r, char *a)
-{
- if (!r->sent_bodyct) {
- return "-";
- }
- else {
- return apr_psprintf(r->pool, "%ld", r->bytes_sent);
- }
-}
-
-static const char *log_bytes_sent(request_rec *r, char *a)
-{
- if (!r->sent_bodyct) {
- return "0";
- }
- else {
- return apr_psprintf(r->pool, "%ld", r->bytes_sent);
- }
-}
-
-
-static const char *log_header_in(request_rec *r, char *a)
-{
- return apr_table_get(r->headers_in, a);
-}
-
-static const char *log_header_out(request_rec *r, char *a)
-{
- const char *cp = apr_table_get(r->headers_out, a);
- if (!strcasecmp(a, "Content-type") && r->content_type) {
- cp = ap_field_noparam(r->pool, r->content_type);
- }
- if (cp) {
- return cp;
- }
- return apr_table_get(r->err_headers_out, a);
-}
-
-static const char *log_note(request_rec *r, char *a)
-{
- return apr_table_get(r->notes, a);
-}
-static const char *log_env_var(request_rec *r, char *a)
-{
- return apr_table_get(r->subprocess_env, a);
-}
-
-static const char *log_cookie(request_rec *r, char *a)
-{
- const char *cookies;
- const char *start_cookie;
-
- if ((cookies = apr_table_get(r->headers_in, "Cookie"))) {
- if ((start_cookie = ap_strstr_c(cookies,a))) {
- char *cookie, *end_cookie;
- start_cookie += strlen(a) + 1; /* cookie_name + '=' */
- cookie = apr_pstrdup(r->pool, start_cookie);
- /* kill everything in cookie after ';' */
- end_cookie = strchr(cookie, ';');
- if (end_cookie) {
- *end_cookie = '\0';
- }
- return cookie;
- }
- }
- return NULL;
-}
-
-static const char *log_request_time(request_rec *r, char *a)
-{
- apr_exploded_time_t xt;
- apr_size_t retcode;
- char tstr[MAX_STRING_LEN];
-
- /*
- hi. i think getting the time again at the end of the request
- just for logging is dumb. i know it's "required" for CLF.
- folks writing log parsing tools don't realise that out of order
- times have always been possible (consider what happens if one
- process calculates the time to log, but then there's a context
- switch before it writes and before that process is run again the
- log rotation occurs) and they should just fix their tools rather
- than force the server to pay extra cpu cycles. if you've got
- a problem with this, you can set the define. -djg
- */
-#ifdef I_INSIST_ON_EXTRA_CYCLES_FOR_CLF_COMPLIANCE
- apr_explode_localtime(&xt, apr_time_now());
-#else
- apr_explode_localtime(&xt, r->request_time);
-#endif
- if (a && *a) { /* Custom format */
- apr_strftime(tstr, &retcode, MAX_STRING_LEN, a, &xt);
- }
- else { /* CLF format */
- char sign;
- int timz;
-
- timz = xt.tm_gmtoff;
- if (timz < 0) {
- timz = -timz;
- sign = '-';
- }
- else {
- sign = '+';
- }
-
- apr_snprintf(tstr, sizeof(tstr), "[%02d/%s/%d:%02d:%02d:%02d %c%.2d%.2d]",
- xt.tm_mday, apr_month_snames[xt.tm_mon], xt.tm_year+1900,
- xt.tm_hour, xt.tm_min, xt.tm_sec,
- sign, timz / (60*60), timz % (60*60));
- }
-
- return apr_pstrdup(r->pool, tstr);
-}
-
-static const char *log_request_duration(request_rec *r, char *a)
-{
- return apr_psprintf(r->pool, "%qd", (apr_time_now() - r->request_time)
- / APR_USEC_PER_SEC);
-}
-
-static const char *log_request_duration_microseconds(request_rec *r, char *a)
-{
- return apr_psprintf(r->pool, "%qd", (apr_time_now() - r->request_time));
-}
-
-/* These next two routines use the canonical name:port so that log
- * parsers don't need to duplicate all the vhost parsing crud.
- */
-static const char *log_virtual_host(request_rec *r, char *a)
-{
- return r->server->server_hostname;
-}
-
-static const char *log_server_port(request_rec *r, char *a)
-{
- return apr_psprintf(r->pool, "%u",
- r->server->port ? r->server->port : ap_default_port(r));
-}
-
-/* This respects the setting of UseCanonicalName so that
- * the dynamic mass virtual hosting trick works better.
- */
-static const char *log_server_name(request_rec *r, char *a)
-{
- return ap_get_server_name(r);
-}
-
-static const char *log_child_pid(request_rec *r, char *a)
-{
- return apr_psprintf(r->pool, "%ld", (long) getpid());
-}
-
-static const char *log_connection_status(request_rec *r, char *a)
-{
- if (r->connection->aborted)
- return "X";
-
- if (r->connection->keepalive &&
- (!r->server->keep_alive_max ||
- (r->server->keep_alive_max - r->connection->keepalives) > 0)) {
- return "+";
- }
- return "-";
-}
-
-/*****************************************************************
- *
- * Parsing the log format string
- */
-
-static char *parse_log_misc_string(apr_pool_t *p, log_format_item *it,
- const char **sa)
-{
- const char *s;
- char *d;
-
- it->func = constant_item;
- it->conditions = NULL;
-
- s = *sa;
- while (*s && *s != '%') {
- s++;
- }
- /*
- * This might allocate a few chars extra if there's a backslash
- * escape in the format string.
- */
- it->arg = apr_palloc(p, s - *sa + 1);
-
- d = it->arg;
- s = *sa;
- while (*s && *s != '%') {
- if (*s != '\\') {
- *d++ = *s++;
- }
- else {
- s++;
- switch (*s) {
- case '\\':
- *d++ = '\\';
- s++;
- break;
- case 'r':
- *d++ = '\r';
- s++;
- break;
- case 'n':
- *d++ = '\n';
- s++;
- break;
- case 't':
- *d++ = '\t';
- s++;
- break;
- default:
- /* copy verbatim */
- *d++ = '\\';
- /*
- * Allow the loop to deal with this *s in the normal
- * fashion so that it handles end of string etc.
- * properly.
- */
- break;
- }
- }
- }
- *d = '\0';
-
- *sa = s;
- return NULL;
-}
-
-static char *parse_log_item(apr_pool_t *p, log_format_item *it, const char **sa)
-{
- const char *s = *sa;
- ap_log_handler *handler;
-
- if (*s != '%') {
- return parse_log_misc_string(p, it, sa);
- }
-
- ++s;
- it->condition_sense = 0;
- it->conditions = NULL;
- it->want_orig = -1;
- it->arg = ""; /* For safety's sake... */
-
- while (*s) {
- int i;
-
- switch (*s) {
- case '!':
- ++s;
- it->condition_sense = !it->condition_sense;
- break;
-
- case '<':
- ++s;
- it->want_orig = 1;
- break;
-
- case '>':
- ++s;
- it->want_orig = 0;
- break;
-
- case ',':
- ++s;
- break;
-
- case '{':
- ++s;
- it->arg = ap_getword(p, &s, '}');
- break;
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- i = *s - '0';
- while (apr_isdigit(*++s)) {
- i = i * 10 + (*s) - '0';
- }
- if (!it->conditions) {
- it->conditions = apr_array_make(p, 4, sizeof(int));
- }
- *(int *) apr_array_push(it->conditions) = i;
- break;
-
- default:
- handler = (ap_log_handler *)apr_hash_get(log_hash, s++, 1);
- if (!handler) {
- char dummy[2];
-
- dummy[0] = s[-1];
- dummy[1] = '\0';
- return apr_pstrcat(p, "Unrecognized LogFormat directive %",
- dummy, NULL);
- }
- it->func = handler->func;
- if (it->want_orig == -1) {
- it->want_orig = handler->want_orig_default;
- }
- *sa = s;
- return NULL;
- }
- }
-
- return "Ran off end of LogFormat parsing args to some directive";
-}
-
-static apr_array_header_t *parse_log_string(apr_pool_t *p, const char *s, const char **err)
-{
- apr_array_header_t *a = apr_array_make(p, 30, sizeof(log_format_item));
- char *res;
-
- while (*s) {
- if ((res = parse_log_item(p, (log_format_item *) apr_array_push(a), &s))) {
- *err = res;
- return NULL;
- }
- }
-
- s = APR_EOL_STR;
- parse_log_item(p, (log_format_item *) apr_array_push(a), &s);
- return a;
-}
-
-/*****************************************************************
- *
- * Actually logging.
- */
-
-static const char *process_item(request_rec *r, request_rec *orig,
- log_format_item *item)
-{
- const char *cp;
-
- /* First, see if we need to process this thing at all... */
-
- if (item->conditions && item->conditions->nelts != 0) {
- int i;
- int *conds = (int *) item->conditions->elts;
- int in_list = 0;
-
- for (i = 0; i < item->conditions->nelts; ++i) {
- if (r->status == conds[i]) {
- in_list = 1;
- break;
- }
- }
-
- if ((item->condition_sense && in_list)
- || (!item->condition_sense && !in_list)) {
- return "-";
- }
- }
-
- /* We do. Do it... */
-
- cp = (*item->func) (item->want_orig ? orig : r, item->arg);
- return cp ? cp : "-";
-}
-
-#ifdef BUFFERED_LOGS
-static void flush_log(config_log_state *cls)
-{
- if (cls->outcnt && cls->log_fd != NULL) {
- apr_file_write(cls->log_fd, cls->outbuf, &cls->outcnt);
- cls->outcnt = 0;
- }
-}
-#endif
-
-static int config_log_transaction(request_rec *r, config_log_state *cls,
- apr_array_header_t *default_format)
-{
- log_format_item *items;
- char *str, *s;
- const char **strs;
- int *strl;
- request_rec *orig;
- int i;
- apr_size_t len = 0;
- apr_array_header_t *format;
- char *envar;
-
- if (cls->fname == NULL) {
- return DECLINED;
- }
-
- /*
- * See if we've got any conditional envariable-controlled logging decisions
- * to make.
- */
- if (cls->condition_var != NULL) {
- envar = cls->condition_var;
- if (*envar != '!') {
- if (apr_table_get(r->subprocess_env, envar) == NULL) {
- return DECLINED;
- }
- }
- else {
- if (apr_table_get(r->subprocess_env, &envar[1]) != NULL) {
- return DECLINED;
- }
- }
- }
-
- format = cls->format ? cls->format : default_format;
-
- strs = apr_palloc(r->pool, sizeof(char *) * (format->nelts));
- strl = apr_palloc(r->pool, sizeof(int) * (format->nelts));
- items = (log_format_item *) format->elts;
-
- orig = r;
- while (orig->prev) {
- orig = orig->prev;
- }
- while (r->next) {
- r = r->next;
- }
-
- for (i = 0; i < format->nelts; ++i) {
- strs[i] = process_item(r, orig, &items[i]);
- }
-
- for (i = 0; i < format->nelts; ++i) {
- len += strl[i] = strlen(strs[i]);
- }
-
-#ifdef BUFFERED_LOGS
- if (len + cls->outcnt > LOG_BUFSIZE) {
- flush_log(cls);
- }
- if (len >= LOG_BUFSIZE) {
- apr_size_t w;
-
- str = apr_palloc(r->pool, len + 1);
- for (i = 0, s = str; i < format->nelts; ++i) {
- memcpy(s, strs[i], strl[i]);
- s += strl[i];
- }
- w = len;
- apr_file_write(cls->log_fd, str, &w);
- }
- else {
- for (i = 0, s = &cls->outbuf[cls->outcnt]; i < format->nelts; ++i) {
- memcpy(s, strs[i], strl[i]);
- s += strl[i];
- }
- cls->outcnt += len;
- }
-#else
- str = apr_palloc(r->pool, len + 1);
-
- for (i = 0, s = str; i < format->nelts; ++i) {
- memcpy(s, strs[i], strl[i]);
- s += strl[i];
- }
-
- apr_file_write(cls->log_fd, str, &len);
-#endif
-
- return OK;
-}
-
-static int multi_log_transaction(request_rec *r)
-{
- multi_log_state *mls = ap_get_module_config(r->server->module_config,
- &log_config_module);
- config_log_state *clsarray;
- int i;
-
- /*
- * Log this transaction..
- */
- if (mls->config_logs->nelts) {
- clsarray = (config_log_state *) mls->config_logs->elts;
- for (i = 0; i < mls->config_logs->nelts; ++i) {
- config_log_state *cls = &clsarray[i];
-
- config_log_transaction(r, cls, mls->default_format);
- }
- }
- else if (mls->server_config_logs) {
- clsarray = (config_log_state *) mls->server_config_logs->elts;
- for (i = 0; i < mls->server_config_logs->nelts; ++i) {
- config_log_state *cls = &clsarray[i];
-
- config_log_transaction(r, cls, mls->default_format);
- }
- }
-
- return OK;
-}
-
-/*****************************************************************
- *
- * Module glue...
- */
-
-static void *make_config_log_state(apr_pool_t *p, server_rec *s)
-{
- multi_log_state *mls;
-
- mls = (multi_log_state *) apr_palloc(p, sizeof(multi_log_state));
- mls->config_logs = apr_array_make(p, 1, sizeof(config_log_state));
- mls->default_format_string = NULL;
- mls->default_format = NULL;
- mls->server_config_logs = NULL;
- mls->formats = apr_table_make(p, 4);
- apr_table_setn(mls->formats, "CLF", DEFAULT_LOG_FORMAT);
-
- return mls;
-}
-
-/*
- * Use the merger to simply add a pointer from the vhost log state
- * to the log of logs specified for the non-vhost configuration. Make sure
- * vhosts inherit any globally-defined format names.
- */
-
-static void *merge_config_log_state(apr_pool_t *p, void *basev, void *addv)
-{
- multi_log_state *base = (multi_log_state *) basev;
- multi_log_state *add = (multi_log_state *) addv;
-
- add->server_config_logs = base->config_logs;
- if (!add->default_format) {
- add->default_format_string = base->default_format_string;
- add->default_format = base->default_format;
- }
- add->formats = apr_table_overlay(p, base->formats, add->formats);
-
- return add;
-}
-
-/*
- * Set the default logfile format, or define a nickname for a format string.
- */
-static const char *log_format(cmd_parms *cmd, void *dummy, const char *fmt,
- const char *name)
-{
- const char *err_string = NULL;
- multi_log_state *mls = ap_get_module_config(cmd->server->module_config,
- &log_config_module);
-
- /*
- * If we were given two arguments, the second is a name to be given to the
- * format. This syntax just defines the nickname - it doesn't actually
- * make the format the default.
- */
- if (name != NULL) {
- parse_log_string(cmd->pool, fmt, &err_string);
- if (err_string == NULL) {
- apr_table_setn(mls->formats, name, fmt);
- }
- }
- else {
- mls->default_format_string = fmt;
- mls->default_format = parse_log_string(cmd->pool, fmt, &err_string);
- }
- return err_string;
-}
-
-
-static const char *add_custom_log(cmd_parms *cmd, void *dummy, const char *fn,
- const char *fmt, const char *envclause)
-{
- const char *err_string = NULL;
- multi_log_state *mls = ap_get_module_config(cmd->server->module_config,
- &log_config_module);
- config_log_state *cls;
-
- cls = (config_log_state *) apr_array_push(mls->config_logs);
- cls->condition_var = NULL;
- if (envclause != NULL) {
- if (strncasecmp(envclause, "env=", 4) != 0) {
- return "error in condition clause";
- }
- if ((envclause[4] == '\0')
- || ((envclause[4] == '!') && (envclause[5] == '\0'))) {
- return "missing environment variable name";
- }
- cls->condition_var = apr_pstrdup(cmd->pool, &envclause[4]);
- }
-
- cls->fname = fn;
- cls->format_string = fmt;
- if (fmt == NULL) {
- cls->format = NULL;
- }
- else {
- cls->format = parse_log_string(cmd->pool, fmt, &err_string);
- }
- cls->log_fd = NULL;
-
- return err_string;
-}
-
-static const char *set_transfer_log(cmd_parms *cmd, void *dummy,
- const char *fn)
-{
- return add_custom_log(cmd, dummy, fn, NULL, NULL);
-}
-
-static const char *set_cookie_log(cmd_parms *cmd, void *dummy, const char *fn)
-{
- return add_custom_log(cmd, dummy, fn, "%{Cookie}n \"%r\" %t", NULL);
-}
-
-static const command_rec config_log_cmds[] =
-{
-AP_INIT_TAKE23("CustomLog", add_custom_log, NULL, RSRC_CONF,
- "a file name, a custom log format string or format name, "
- "and an optional \"env=\" clause (see docs)"),
-AP_INIT_TAKE1("TransferLog", set_transfer_log, NULL, RSRC_CONF,
- "the filename of the access log"),
-AP_INIT_TAKE12("LogFormat", log_format, NULL, RSRC_CONF,
- "a log format string (see docs) and an optional format name"),
-AP_INIT_TAKE1("CookieLog", set_cookie_log, NULL, RSRC_CONF,
- "the filename of the cookie log"),
- {NULL}
-};
-
-static config_log_state *open_config_log(server_rec *s, apr_pool_t *p,
- config_log_state *cls,
- apr_array_header_t *default_format)
-{
- apr_status_t status;
-
- if (cls->log_fd != NULL) {
- return cls; /* virtual config shared w/main server */
- }
-
- if (cls->fname == NULL) {
- return cls; /* Leave it NULL to decline. */
- }
-
- if (*cls->fname == '|') {
- piped_log *pl;
-
- pl = ap_open_piped_log(p, cls->fname + 1);
- if (pl == NULL) {
- exit(1);
- }
- cls->log_fd = ap_piped_log_write_fd(pl);
- }
- else {
- const char *fname = ap_server_root_relative(p, cls->fname);
- if ((status = apr_file_open(&cls->log_fd, fname, xfer_flags, xfer_perms, p))
- != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, status, s,
- "could not open transfer log file %s.", fname);
- exit(1);
- }
- }
-#ifdef BUFFERED_LOGS
- cls->outcnt = 0;
-#endif
-
- return cls;
-}
-
-static config_log_state *open_multi_logs(server_rec *s, apr_pool_t *p)
-{
- int i;
- multi_log_state *mls = ap_get_module_config(s->module_config,
- &log_config_module);
- config_log_state *clsarray;
- const char *dummy;
- const char *format;
-
- if (mls->default_format_string) {
- format = apr_table_get(mls->formats, mls->default_format_string);
- if (format) {
- mls->default_format = parse_log_string(p, format, &dummy);
- }
- }
-
- if (!mls->default_format) {
- mls->default_format = parse_log_string(p, DEFAULT_LOG_FORMAT, &dummy);
- }
-
- if (mls->config_logs->nelts) {
- clsarray = (config_log_state *) mls->config_logs->elts;
- for (i = 0; i < mls->config_logs->nelts; ++i) {
- config_log_state *cls = &clsarray[i];
-
- if (cls->format_string) {
- format = apr_table_get(mls->formats, cls->format_string);
- if (format) {
- cls->format = parse_log_string(p, format, &dummy);
- }
- }
-
- cls = open_config_log(s, p, cls, mls->default_format);
- }
- }
- else if (mls->server_config_logs) {
- clsarray = (config_log_state *) mls->server_config_logs->elts;
- for (i = 0; i < mls->server_config_logs->nelts; ++i) {
- config_log_state *cls = &clsarray[i];
-
- if (cls->format_string) {
- format = apr_table_get(mls->formats, cls->format_string);
- if (format) {
- cls->format = parse_log_string(p, format, &dummy);
- }
- }
-
- cls = open_config_log(s, p, cls, mls->default_format);
- }
- }
-
- return NULL;
-}
-
-#ifdef BUFFERED_LOGS
-static apr_status_t flush_all_logs(void *data)
-{
- server_rec *s = data;
- multi_log_state *mls;
- apr_array_header_t *log_list;
- config_log_state *clsarray;
- int i;
-
- for (; s; s = s->next) {
- mls = ap_get_module_config(s->module_config, &log_config_module);
- log_list = NULL;
- if (mls->config_logs->nelts) {
- log_list = mls->config_logs;
- }
- else if (mls->server_config_logs) {
- log_list = mls->server_config_logs;
- }
- if (log_list) {
- clsarray = (config_log_state *) log_list->elts;
- for (i = 0; i < log_list->nelts; ++i) {
- flush_log(&clsarray[i]);
- }
- }
- }
- return APR_SUCCESS;
-}
-#endif
-
-static void init_config_log(apr_pool_t *pc, apr_pool_t *p, apr_pool_t *pt, server_rec *s)
-{
- /* First, do "physical" server, which gets default log fd and format
- * for the virtual servers, if they don't override...
- */
-
- open_multi_logs(s, p);
-
- /* Then, virtual servers */
-
- for (s = s->next; s; s = s->next) {
- open_multi_logs(s, p);
- }
-}
-
-static void init_child(apr_pool_t *p, server_rec *s)
-{
-#ifdef BUFFERED_LOGS
- /* Now register the last buffer flush with the cleanup engine */
- apr_pool_cleanup_register(p, s, flush_all_logs, flush_all_logs);
-#endif
-}
-
-static void ap_register_log_handler(apr_pool_t *p, char *tag,
- ap_log_handler_fn_t *handler, int def)
-{
- ap_log_handler *log_struct = apr_palloc(p, sizeof(*log_struct));
- log_struct->func = handler;
- log_struct->want_orig_default = def;
-
- apr_hash_set(log_hash, tag, 1, (const void *)log_struct);
-}
-
-static void log_pre_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp)
-{
- static APR_OPTIONAL_FN_TYPE(ap_register_log_handler) *log_pfn_register;
-
- log_pfn_register = APR_RETRIEVE_OPTIONAL_FN(ap_register_log_handler);
-
- if (log_pfn_register) {
- log_pfn_register(p, "h", log_remote_host, 0);
- log_pfn_register(p, "a", log_remote_address, 0 );
- log_pfn_register(p, "A", log_local_address, 0 );
- log_pfn_register(p, "l", log_remote_logname, 0);
- log_pfn_register(p, "u", log_remote_user, 0);
- log_pfn_register(p, "t", log_request_time, 0);
- log_pfn_register(p, "f", log_request_file, 0);
- log_pfn_register(p, "b", clf_log_bytes_sent, 0);
- log_pfn_register(p, "B", log_bytes_sent, 0);
- log_pfn_register(p, "i", log_header_in, 0);
- log_pfn_register(p, "o", log_header_out, 0);
- log_pfn_register(p, "n", log_note, 0);
- log_pfn_register(p, "e", log_env_var, 0);
- log_pfn_register(p, "V", log_server_name, 0);
- log_pfn_register(p, "v", log_virtual_host, 0);
- log_pfn_register(p, "p", log_server_port, 0);
- log_pfn_register(p, "P", log_child_pid, 0);
- log_pfn_register(p, "H", log_request_protocol, 0);
- log_pfn_register(p, "m", log_request_method, 0);
- log_pfn_register(p, "q", log_request_query, 0);
- log_pfn_register(p, "c", log_connection_status, 0);
- log_pfn_register(p, "C", log_cookie, 0);
- log_pfn_register(p, "r", log_request_line, 1);
- log_pfn_register(p, "D", log_request_duration_microseconds, 1);
- log_pfn_register(p, "T", log_request_duration, 1);
- log_pfn_register(p, "U", log_request_uri, 1);
- log_pfn_register(p, "s", log_status, 1);
- }
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_pre_config(log_pre_config,NULL,NULL,APR_HOOK_REALLY_FIRST);
- ap_hook_child_init(init_child,NULL,NULL,APR_HOOK_MIDDLE);
- ap_hook_open_logs(init_config_log,NULL,NULL,APR_HOOK_MIDDLE);
- ap_hook_log_transaction(multi_log_transaction,NULL,NULL,APR_HOOK_MIDDLE);
-
- /* Init log_hash before we register the optional function. It is
- * possible for the optional function, ap_register_log_handler,
- * to be called before any other mod_log_config hooks are called.
- * As a policy, we should init everything required by an optional function
- * before calling APR_REGISTER_OPTIONAL_FN.
- */
- log_hash = apr_hash_make(p);
- APR_REGISTER_OPTIONAL_FN(ap_register_log_handler);
-}
-
-module AP_MODULE_DECLARE_DATA log_config_module =
-{
- STANDARD20_MODULE_STUFF,
- NULL, /* create per-dir config */
- NULL, /* merge per-dir config */
- make_config_log_state, /* server config */
- merge_config_log_state, /* merge server config */
- config_log_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
diff --git a/modules/loggers/mod_log_config.exp b/modules/loggers/mod_log_config.exp
deleted file mode 100644
index 01b926f4bb..0000000000
--- a/modules/loggers/mod_log_config.exp
+++ /dev/null
@@ -1 +0,0 @@
-config_log_module
diff --git a/modules/loggers/mod_log_config.h b/modules/loggers/mod_log_config.h
deleted file mode 100644
index d30409f804..0000000000
--- a/modules/loggers/mod_log_config.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "apr_optional.h"
-#include "httpd.h"
-
-#ifndef _MOD_LOG_CONFIG_H
-#define _MOD_LOG_CONFIG_H 1
-
-typedef const char *ap_log_handler_fn_t(request_rec *r, char *a);
-
-typedef struct ap_log_handler {
- ap_log_handler_fn_t *func;
- int want_orig_default;
-} ap_log_handler;
-
-APR_DECLARE_OPTIONAL_FN(void, ap_register_log_handler,
- (apr_pool_t *p, char *tag, ap_log_handler_fn_t *func, int def));
-
-#endif /* MOD_LOG_CONFIG */
diff --git a/modules/mappers/.cvsignore b/modules/mappers/.cvsignore
deleted file mode 100644
index 65f0cc30cf..0000000000
--- a/modules/mappers/.cvsignore
+++ /dev/null
@@ -1,10 +0,0 @@
-.deps
-.libs
-*.la
-modules.mk
-Makefile
-*.lo
-*.slo
-*.so
-Debug
-Release
diff --git a/modules/mappers/.indent.pro b/modules/mappers/.indent.pro
deleted file mode 100644
index a9fbe9f9a1..0000000000
--- a/modules/mappers/.indent.pro
+++ /dev/null
@@ -1,54 +0,0 @@
--i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1
--TBUFF
--TFILE
--TTRANS
--TUINT4
--T_trans
--Tallow_options_t
--Tapache_sfio
--Tarray_header
--Tbool_int
--Tbuf_area
--Tbuff_struct
--Tbuffy
--Tcmd_how
--Tcmd_parms
--Tcommand_rec
--Tcommand_struct
--Tconn_rec
--Tcore_dir_config
--Tcore_server_config
--Tdir_maker_func
--Tevent
--Tglobals_s
--Thandler_func
--Thandler_rec
--Tjoblist_s
--Tlisten_rec
--Tmerger_func
--Tmode_t
--Tmodule
--Tmodule_struct
--Tmutex
--Tn_long
--Tother_child_rec
--Toverrides_t
--Tparent_score
--Tpid_t
--Tpiped_log
--Tpool
--Trequest_rec
--Trequire_line
--Trlim_t
--Tscoreboard
--Tsemaphore
--Tserver_addr_rec
--Tserver_rec
--Tserver_rec_chain
--Tshort_score
--Ttable
--Ttable_entry
--Tthread
--Tu_wide_int
--Tvtime_t
--Twide_int
diff --git a/modules/mappers/Makefile.in b/modules/mappers/Makefile.in
deleted file mode 100644
index 167b343d0d..0000000000
--- a/modules/mappers/Makefile.in
+++ /dev/null
@@ -1,3 +0,0 @@
-
-include $(top_srcdir)/build/special.mk
-
diff --git a/modules/mappers/config9.m4 b/modules/mappers/config9.m4
deleted file mode 100644
index 170a2944db..0000000000
--- a/modules/mappers/config9.m4
+++ /dev/null
@@ -1,33 +0,0 @@
-dnl modules enabled in this directory by default
-
-dnl APACHE_MODULE(name, helptext[, objects[, structname[, default[, config]]]])
-
-APACHE_MODPATH_INIT(mappers)
-
-APACHE_MODULE(vhost_alias, mass hosting module, , , most)
-APACHE_MODULE(negotiation, content negoatiation, , , yes)
-APACHE_MODULE(dir, directory request handling, , , yes)
-APACHE_MODULE(imap, internal imagemaps, , , yes)
-APACHE_MODULE(actions, Action triggering on requests, , , yes)
-APACHE_MODULE(speling, correct common URL misspellings, , , most)
-APACHE_MODULE(userdir, mapping of user requests, , , yes)
-APACHE_MODULE(alias, translation of requests, , , yes)
-
-APACHE_MODULE(rewrite, regex URL translation, , , most, [
- APR_ADDTO(CFLAGS,-DNO_DBM_REWRITEMAP)
-])
-
-dnl ### this isn't going to work quite right because of ordering issues
-dnl ### among the config.m4 files. it is possible that a *later* module
-dnl ### is marked as shared (thus setting sharedobjs), so we won't see
-dnl ### it here. we need to shift *this* config.m4 to be "last" or we
-dnl ### need to find a different way to set up this default and module spec.
-if test "$sharedobjs" = "yes"; then
- APACHE_MODULE(so, DSO capability, , , yes)
-else
- APACHE_MODULE(so, DSO capability, , , no)
-fi
-dnl ### why save the cache?
-AC_CACHE_SAVE
-
-APACHE_MODPATH_FINISH
diff --git a/modules/mappers/mod_actions.c b/modules/mappers/mod_actions.c
deleted file mode 100644
index d6a31ddeb1..0000000000
--- a/modules/mappers/mod_actions.c
+++ /dev/null
@@ -1,226 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * mod_actions.c: executes scripts based on MIME type or HTTP method
- *
- * by Alexei Kosut; based on mod_cgi.c, mod_mime.c and mod_includes.c,
- * adapted by rst from original NCSA code by Rob McCool
- *
- * Usage instructions:
- *
- * Action mime/type /cgi-bin/script
- *
- * will activate /cgi-bin/script when a file of content type mime/type is
- * requested. It sends the URL and file path of the requested document using
- * the standard CGI PATH_INFO and PATH_TRANSLATED environment variables.
- *
- * Script PUT /cgi-bin/script
- *
- * will activate /cgi-bin/script when a request is received with the
- * HTTP method "PUT". The available method names are defined in httpd.h.
- * If the method is GET, the script will only be activated if the requested
- * URI includes query information (stuff after a ?-mark).
- */
-
-#include "apr_strings.h"
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_request.h"
-#include "http_core.h"
-#include "http_protocol.h"
-#include "http_main.h"
-#include "http_log.h"
-#include "util_script.h"
-
-typedef struct {
- apr_table_t *action_types; /* Added with Action... */
- const char *scripted[METHODS]; /* Added with Script... */
-} action_dir_config;
-
-module actions_module;
-
-static void *create_action_dir_config(apr_pool_t *p, char *dummy)
-{
- action_dir_config *new =
- (action_dir_config *) apr_pcalloc(p, sizeof(action_dir_config));
-
- new->action_types = apr_table_make(p, 4);
-
- return new;
-}
-
-static void *merge_action_dir_configs(apr_pool_t *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 *) apr_palloc(p,
- sizeof(action_dir_config));
- int i;
-
- new->action_types = apr_table_overlay(p, add->action_types,
- base->action_types);
-
- for (i = 0; i < METHODS; ++i) {
- new->scripted[i] = add->scripted[i] ? add->scripted[i]
- : base->scripted[i];
- }
- return new;
-}
-
-static const char *add_action(cmd_parms *cmd, void *m_v,
- const char *type, const char *script)
-{
- action_dir_config *m = (action_dir_config *)m_v;
- apr_table_setn(m->action_types, type, script);
- return NULL;
-}
-
-static const char *set_script(cmd_parms *cmd, void *m_v,
- const char *method, const char *script)
-{
- action_dir_config *m = (action_dir_config *)m_v;
- 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
- m->scripted[methnum] = script;
-
- return NULL;
-}
-
-static const command_rec action_cmds[] =
-{
- AP_INIT_TAKE2("Action", add_action, NULL, OR_FILEINFO,
- "a media type followed by a script name"),
- AP_INIT_TAKE2("Script", set_script, NULL, ACCESS_CONF | RSRC_CONF,
- "a method followed by a script name"),
- {NULL}
-};
-
-static int action_handler(request_rec *r)
-{
- action_dir_config *conf = (action_dir_config *)
- ap_get_module_config(r->per_dir_config, &actions_module);
- const char *t, *action = r->handler ? r->handler :
- ap_field_noparam(r->pool, r->content_type);
- const char *script;
- int i;
-
- /* Note that this handler handles _all_ types, so handler is unchecked */
-
- /* Set allowed stuff */
- for (i = 0; i < METHODS; ++i) {
- if (conf->scripted[i])
- r->allowed |= (1 << i);
- }
-
- /* First, check for the method-handling scripts */
- if (r->method_number == M_GET) {
- if (r->args)
- script = conf->scripted[M_GET];
- else
- script = NULL;
- }
- else {
- 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)
- return DECLINED;
-
- /* Second, check for actions (which override the method scripts) */
- if ((t = apr_table_get(conf->action_types,
- action ? action : ap_default_type(r)))) {
- script = t;
- if (r->finfo.filetype == 0) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "File does not exist: %s", r->filename);
- return HTTP_NOT_FOUND;
- }
- }
-
- if (script == NULL)
- return DECLINED;
-
- ap_internal_redirect_handler(apr_pstrcat(r->pool, script, ap_escape_uri(r->pool,
- r->uri), r->args ? "?" : NULL, r->args, NULL), r);
- return OK;
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_handler(action_handler,NULL,NULL,APR_HOOK_LAST);
-}
-
-module actions_module =
-{
- STANDARD20_MODULE_STUFF,
- create_action_dir_config, /* dir config creater */
- merge_action_dir_configs, /* dir merger --- default is to override */
- NULL, /* server config */
- NULL, /* merge server config */
- action_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
diff --git a/modules/mappers/mod_actions.exp b/modules/mappers/mod_actions.exp
deleted file mode 100644
index 815dff29a8..0000000000
--- a/modules/mappers/mod_actions.exp
+++ /dev/null
@@ -1 +0,0 @@
-action_module
diff --git a/modules/mappers/mod_alias.c b/modules/mappers/mod_alias.c
deleted file mode 100644
index a5752e3c1e..0000000000
--- a/modules/mappers/mod_alias.c
+++ /dev/null
@@ -1,443 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * http_alias.c: Stuff for dealing with directory aliases
- *
- * Original by Rob McCool, rewritten in succession by David Robinson
- * and rst.
- *
- */
-
-#include "apr_strings.h"
-#include "apr_lib.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_request.h"
-
-
-typedef struct {
- const char *real;
- const char *fake;
- char *handler;
- regex_t *regexp;
- int redir_status; /* 301, 302, 303, 410, etc */
-} alias_entry;
-
-typedef struct {
- apr_array_header_t *aliases;
- apr_array_header_t *redirects;
-} alias_server_conf;
-
-typedef struct {
- apr_array_header_t *redirects;
-} alias_dir_conf;
-
-module AP_MODULE_DECLARE_DATA alias_module;
-
-static void *create_alias_config(apr_pool_t *p, server_rec *s)
-{
- alias_server_conf *a =
- (alias_server_conf *) apr_pcalloc(p, sizeof(alias_server_conf));
-
- a->aliases = apr_array_make(p, 20, sizeof(alias_entry));
- a->redirects = apr_array_make(p, 20, sizeof(alias_entry));
- return a;
-}
-
-static void *create_alias_dir_config(apr_pool_t *p, char *d)
-{
- alias_dir_conf *a =
- (alias_dir_conf *) apr_pcalloc(p, sizeof(alias_dir_conf));
- a->redirects = apr_array_make(p, 2, sizeof(alias_entry));
- return a;
-}
-
-static void *merge_alias_config(apr_pool_t *p, void *basev, void *overridesv)
-{
- alias_server_conf *a =
- (alias_server_conf *) apr_pcalloc(p, sizeof(alias_server_conf));
- alias_server_conf *base = (alias_server_conf *) basev, *overrides = (alias_server_conf *) overridesv;
-
- a->aliases = apr_array_append(p, overrides->aliases, base->aliases);
- a->redirects = apr_array_append(p, overrides->redirects, base->redirects);
- return a;
-}
-
-static void *merge_alias_dir_config(apr_pool_t *p, void *basev, void *overridesv)
-{
- alias_dir_conf *a =
- (alias_dir_conf *) apr_pcalloc(p, sizeof(alias_dir_conf));
- alias_dir_conf *base = (alias_dir_conf *) basev, *overrides = (alias_dir_conf *) overridesv;
- a->redirects = apr_array_append(p, overrides->redirects, base->redirects);
- return a;
-}
-
-static const char *add_alias_internal(cmd_parms *cmd, void *dummy,
- const char *f, const char *r,
- int use_regex)
-{
- server_rec *s = cmd->server;
- alias_server_conf *conf = ap_get_module_config(s->module_config,
- &alias_module);
- alias_entry *new = apr_array_push(conf->aliases);
-
- /* XX r can NOT be relative to DocumentRoot here... compat bug. */
-
- if (use_regex) {
- new->regexp = ap_pregcomp(cmd->pool, f, REG_EXTENDED);
- if (new->regexp == NULL)
- return "Regular expression could not be compiled.";
- new->real = r;
- }
-#ifndef OS2
- else
- new->real = ap_os_canonical_filename(cmd->pool, r);
-#else
- new->real = r;
-#endif
-
- new->fake = f;
- new->handler = cmd->info;
-
- return NULL;
-}
-
-static const char *add_alias(cmd_parms *cmd, void *dummy, const char *f,
- const char *r)
-{
- return add_alias_internal(cmd, dummy, f, r, 0);
-}
-
-static const char *add_alias_regex(cmd_parms *cmd, void *dummy, const char *f,
- const char *r)
-{
- return add_alias_internal(cmd, dummy, f, r, 1);
-}
-
-static const char *add_redirect_internal(cmd_parms *cmd,
- alias_dir_conf *dirconf,
- const char *arg1, const char *arg2,
- const char *arg3, int use_regex)
-{
- alias_entry *new;
- server_rec *s = cmd->server;
- alias_server_conf *serverconf = ap_get_module_config(s->module_config,
- &alias_module);
- int status = (int) (long) cmd->info;
- regex_t *r = NULL;
- const char *f = arg2;
- const char *url = arg3;
-
- if (!strcasecmp(arg1, "gone"))
- status = HTTP_GONE;
- else if (!strcasecmp(arg1, "permanent"))
- status = HTTP_MOVED_PERMANENTLY;
- else if (!strcasecmp(arg1, "temp"))
- status = HTTP_MOVED_TEMPORARILY;
- else if (!strcasecmp(arg1, "seeother"))
- status = HTTP_SEE_OTHER;
- else if (apr_isdigit(*arg1))
- status = atoi(arg1);
- else {
- f = arg1;
- url = arg2;
- }
-
- if (use_regex) {
- r = ap_pregcomp(cmd->pool, f, REG_EXTENDED);
- if (r == NULL)
- return "Regular expression could not be compiled.";
- }
-
- if (ap_is_HTTP_REDIRECT(status)) {
- if (!url)
- return "URL to redirect to is missing";
- if (!use_regex && !ap_is_url(url))
- return "Redirect to non-URL";
- }
- else {
- if (url)
- return "Redirect URL not valid for this status";
- }
-
- if (cmd->path)
- new = apr_array_push(dirconf->redirects);
- else
- new = apr_array_push(serverconf->redirects);
-
- new->fake = f;
- new->real = url;
- new->regexp = r;
- new->redir_status = status;
- return NULL;
-}
-
-static const char *add_redirect(cmd_parms *cmd, void *dirconf,
- const char *arg1, const char *arg2,
- const char *arg3)
-{
- return add_redirect_internal(cmd, dirconf, arg1, arg2, arg3, 0);
-}
-
-static const char *add_redirect2(cmd_parms *cmd, void *dirconf,
- const char *arg1, const char *arg2)
-{
- return add_redirect_internal(cmd, dirconf, arg1, arg2, NULL, 0);
-}
-
-static const char *add_redirect_regex(cmd_parms *cmd, void *dirconf,
- const char *arg1, const char *arg2,
- const char *arg3)
-{
- return add_redirect_internal(cmd, dirconf, arg1, arg2, arg3, 1);
-}
-
-static const command_rec alias_cmds[] =
-{
- AP_INIT_TAKE2("Alias", add_alias, NULL, RSRC_CONF,
- "a fakename and a realname"),
- AP_INIT_TAKE2("ScriptAlias", add_alias, "cgi-script", RSRC_CONF,
- "a fakename and a realname"),
- AP_INIT_TAKE23("Redirect", add_redirect, (void *) HTTP_MOVED_TEMPORARILY,
- OR_FILEINFO,
- "an optional status, then document to be redirected and "
- "destination URL"),
- AP_INIT_TAKE2("AliasMatch", add_alias_regex, NULL, RSRC_CONF,
- "a regular expression and a filename"),
- AP_INIT_TAKE2("ScriptAliasMatch", add_alias_regex, "cgi-script", RSRC_CONF,
- "a regular expression and a filename"),
- AP_INIT_TAKE23("RedirectMatch", add_redirect_regex,
- (void *) HTTP_MOVED_TEMPORARILY, OR_FILEINFO,
- "an optional status, then a regular expression and "
- "destination URL"),
- AP_INIT_TAKE2("RedirectTemp", add_redirect2,
- (void *) HTTP_MOVED_TEMPORARILY, OR_FILEINFO,
- "a document to be redirected, then the destination URL"),
- AP_INIT_TAKE2("RedirectPermanent", add_redirect2,
- (void *) HTTP_MOVED_PERMANENTLY, OR_FILEINFO,
- "a document to be redirected, then the destination URL"),
- {NULL}
-};
-
-static int alias_matches(const char *uri, const char *alias_fakename)
-{
- const char *end_fakename = alias_fakename + strlen(alias_fakename);
- const char *aliasp = alias_fakename, *urip = uri;
-
- while (aliasp < end_fakename) {
- if (*aliasp == '/') {
- /* any number of '/' in the alias matches any number in
- * the supplied URI, but there must be at least one...
- */
- if (*urip != '/')
- return 0;
-
- while (*aliasp == '/')
- ++aliasp;
- while (*urip == '/')
- ++urip;
- }
- else {
- /* Other characters are compared literally */
- if (*urip++ != *aliasp++)
- return 0;
- }
- }
-
- /* Check last alias path component matched all the way */
-
- if (aliasp[-1] != '/' && *urip != '\0' && *urip != '/')
- return 0;
-
- /* Return number of characters from URI which matched (may be
- * greater than length of alias, since we may have matched
- * doubled slashes)
- */
-
- return urip - uri;
-}
-
-static char *try_alias_list(request_rec *r, apr_array_header_t *aliases, int doesc, int *status)
-{
- alias_entry *entries = (alias_entry *) aliases->elts;
- regmatch_t regm[10];
- char *found = NULL;
- int i;
-
- for (i = 0; i < aliases->nelts; ++i) {
- alias_entry *p = &entries[i];
- int l;
-
- if (p->regexp) {
- if (!ap_regexec(p->regexp, r->uri, p->regexp->re_nsub + 1, regm, 0)) {
- if (p->real) {
- found = ap_pregsub(r->pool, p->real, r->uri,
- p->regexp->re_nsub + 1, regm);
- if (found && doesc) {
- found = ap_escape_uri(r->pool, found);
- }
- }
- else {
- /* need something non-null */
- found = apr_pstrdup(r->pool, "");
- }
- }
- }
- else {
- l = alias_matches(r->uri, p->fake);
-
- if (l > 0) {
- if (doesc) {
- char *escurl;
- escurl = ap_os_escape_path(r->pool, r->uri + l, 1);
-
- found = apr_pstrcat(r->pool, p->real, escurl, NULL);
- }
- else
- found = apr_pstrcat(r->pool, p->real, r->uri + l, NULL);
- }
- }
-
- if (found) {
- if (p->handler) { /* Set handler, and leave a note for mod_cgi */
- r->handler = p->handler;
- apr_table_setn(r->notes, "alias-forced-type", r->handler);
- }
-
- *status = p->redir_status;
-
- return found;
- }
-
- }
-
- return NULL;
-}
-
-static int translate_alias_redir(request_rec *r)
-{
- ap_conf_vector_t *sconf = r->server->module_config;
- alias_server_conf *serverconf = ap_get_module_config(sconf, &alias_module);
- char *ret;
- int status;
-
- if (r->uri[0] != '/' && r->uri[0] != '\0')
- return DECLINED;
-
- if ((ret = try_alias_list(r, serverconf->redirects, 1, &status)) != NULL) {
- if (ap_is_HTTP_REDIRECT(status)) {
- /* include QUERY_STRING if any */
- if (r->args) {
- ret = apr_pstrcat(r->pool, ret, "?", r->args, NULL);
- }
- apr_table_setn(r->headers_out, "Location", ret);
- }
- return status;
- }
-
- if ((ret = try_alias_list(r, serverconf->aliases, 0, &status)) != NULL) {
- r->filename = ret;
- return OK;
- }
-
- return DECLINED;
-}
-
-static int fixup_redir(request_rec *r)
-{
- void *dconf = r->per_dir_config;
- alias_dir_conf *dirconf =
- (alias_dir_conf *) ap_get_module_config(dconf, &alias_module);
- char *ret;
- int status;
-
- /* It may have changed since last time, so try again */
-
- if ((ret = try_alias_list(r, dirconf->redirects, 1, &status)) != NULL) {
- if (ap_is_HTTP_REDIRECT(status))
- apr_table_setn(r->headers_out, "Location", ret);
- return status;
- }
-
- return DECLINED;
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- static const char * const aszPre[]={ "mod_userdir.c",NULL };
-
- ap_hook_translate_name(translate_alias_redir,aszPre,NULL,APR_HOOK_MIDDLE);
- ap_hook_fixups(fixup_redir,NULL,NULL,APR_HOOK_MIDDLE);
-}
-
-module AP_MODULE_DECLARE_DATA alias_module =
-{
- STANDARD20_MODULE_STUFF,
- create_alias_dir_config, /* dir config creater */
- merge_alias_dir_config, /* dir merger --- default is to override */
- create_alias_config, /* server config */
- merge_alias_config, /* merge server configs */
- alias_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
diff --git a/modules/mappers/mod_alias.exp b/modules/mappers/mod_alias.exp
deleted file mode 100644
index ac386ec3fa..0000000000
--- a/modules/mappers/mod_alias.exp
+++ /dev/null
@@ -1 +0,0 @@
-alias_module
diff --git a/modules/mappers/mod_dir.c b/modules/mappers/mod_dir.c
deleted file mode 100644
index b216622018..0000000000
--- a/modules/mappers/mod_dir.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * mod_dir.c: handle default index files, and trailing-/ redirects
- */
-
-#include "apr_strings.h"
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_core.h"
-#include "http_request.h"
-#include "http_protocol.h"
-#include "http_log.h"
-#include "http_main.h"
-#include "util_script.h"
-
-module AP_MODULE_DECLARE_DATA dir_module;
-
-typedef struct dir_config_struct {
- apr_array_header_t *index_names;
-} dir_config_rec;
-
-#define DIR_CMD_PERMS OR_INDEXES
-
-static const char *add_index(cmd_parms *cmd, void *dummy, const char *arg)
-{
- dir_config_rec *d = dummy;
-
- if (!d->index_names) {
- d->index_names = apr_array_make(cmd->pool, 2, sizeof(char *));
- }
- *(const char **)apr_array_push(d->index_names) = arg;
- return NULL;
-}
-
-static const command_rec dir_cmds[] =
-{
- AP_INIT_ITERATE("DirectoryIndex", add_index, NULL, DIR_CMD_PERMS,
- "a list of file names"),
- {NULL}
-};
-
-static void *create_dir_config(apr_pool_t *p, char *dummy)
-{
- dir_config_rec *new =
- (dir_config_rec *) apr_pcalloc(p, sizeof(dir_config_rec));
-
- new->index_names = NULL;
- return (void *) new;
-}
-
-static void *merge_dir_configs(apr_pool_t *p, void *basev, void *addv)
-{
- dir_config_rec *new = (dir_config_rec *) apr_pcalloc(p, sizeof(dir_config_rec));
- dir_config_rec *base = (dir_config_rec *) basev;
- dir_config_rec *add = (dir_config_rec *) addv;
-
- new->index_names = add->index_names ? add->index_names : base->index_names;
- return new;
-}
-
-static int fixup_dir(request_rec *r)
-{
- /* only (potentially) redirect for GET requests against directories */
- if (r->method_number != M_GET || r->finfo.filetype != APR_DIR) {
- return DECLINED;
- }
-
- if (r->uri[0] == '\0' || r->uri[strlen(r->uri) - 1] != '/') {
- char *ifile;
- if (r->args != NULL)
- ifile = apr_pstrcat(r->pool, ap_escape_uri(r->pool, r->uri),
- "/", "?", r->args, NULL);
- else
- ifile = apr_pstrcat(r->pool, ap_escape_uri(r->pool, r->uri),
- "/", NULL);
-
- apr_table_setn(r->headers_out, "Location",
- ap_construct_url(r->pool, ifile, r));
- return HTTP_MOVED_PERMANENTLY;
- }
-
- return OK;
-}
-
-static int handle_dir(request_rec *r)
-{
- dir_config_rec *d;
- char *dummy_ptr[1];
- char **names_ptr;
- int num_names;
- int error_notfound = 0;
-
- if (strcmp(r->handler,DIR_MAGIC_TYPE)) {
- return DECLINED;
- }
-
- d = (dir_config_rec *) ap_get_module_config(r->per_dir_config,
- &dir_module);
-
- /* KLUDGE --- make the sub_req lookups happen in the right directory.
- * Fixing this in the sub_req_lookup functions themselves is difficult,
- * and would probably break virtual includes...
- */
-
- if (r->filename[strlen(r->filename) - 1] != '/') {
- r->filename = apr_pstrcat(r->pool, r->filename, "/", NULL);
- }
-
- if (d->index_names) {
- names_ptr = (char **)d->index_names->elts;
- num_names = d->index_names->nelts;
- }
- else {
- dummy_ptr[0] = AP_DEFAULT_INDEX;
- names_ptr = dummy_ptr;
- num_names = 1;
- }
-
- for (; num_names; ++names_ptr, --num_names) {
- char *name_ptr = *names_ptr;
- request_rec *rr = ap_sub_req_lookup_uri(name_ptr, r, NULL);
-
- if (rr->status == HTTP_OK && rr->finfo.filetype == APR_REG) {
- char *new_uri = ap_escape_uri(r->pool, rr->uri);
-
- if (rr->args != NULL)
- new_uri = apr_pstrcat(r->pool, new_uri, "?", rr->args, NULL);
- else if (r->args != NULL)
- new_uri = apr_pstrcat(r->pool, new_uri, "?", r->args, NULL);
-
- ap_destroy_sub_req(rr);
- ap_internal_redirect(new_uri, r);
- return OK;
- }
-
- /* If the request returned a redirect, propagate it to the client */
-
- if (ap_is_HTTP_REDIRECT(rr->status) ||
- (rr->status == HTTP_NOT_ACCEPTABLE && num_names == 1) ||
- (rr->status == HTTP_UNAUTHORIZED && num_names == 1)) {
-
- apr_pool_join(r->pool, rr->pool);
- error_notfound = rr->status;
- r->notes = apr_table_overlay(r->pool, r->notes, rr->notes);
- r->headers_out = apr_table_overlay(r->pool, r->headers_out,
- rr->headers_out);
- r->err_headers_out = apr_table_overlay(r->pool, r->err_headers_out,
- rr->err_headers_out);
- return error_notfound;
- }
-
- /* If the request returned something other than 404 (or 200),
- * it means the module encountered some sort of problem. To be
- * secure, we should return the error, rather than create
- * along a (possibly unsafe) directory index.
- *
- * So we store the error, and if none of the listed files
- * exist, we return the last error response we got, instead
- * of a directory listing.
- */
- if (rr->status && rr->status != HTTP_NOT_FOUND && rr->status != HTTP_OK)
- error_notfound = rr->status;
-
- ap_destroy_sub_req(rr);
- }
-
- if (error_notfound)
- return error_notfound;
-
- if (r->method_number != M_GET)
- return DECLINED;
-
- /* nothing for us to do, pass on through */
-
- return DECLINED;
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- static const char * const aszSucc[]={"mod_autoindex.c", NULL};
-
- ap_hook_fixups(fixup_dir,NULL,NULL,APR_HOOK_MIDDLE);
- ap_hook_handler(handle_dir,NULL,aszSucc,APR_HOOK_MIDDLE);
-}
-
-module AP_MODULE_DECLARE_DATA dir_module = {
- STANDARD20_MODULE_STUFF,
- create_dir_config, /* create per-directory config structure */
- merge_dir_configs, /* merge per-directory config structures */
- NULL, /* create per-server config structure */
- NULL, /* merge per-server config structures */
- dir_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
diff --git a/modules/mappers/mod_dir.exp b/modules/mappers/mod_dir.exp
deleted file mode 100644
index 5fbf772991..0000000000
--- a/modules/mappers/mod_dir.exp
+++ /dev/null
@@ -1 +0,0 @@
-dir_module
diff --git a/modules/mappers/mod_imap.c b/modules/mappers/mod_imap.c
deleted file mode 100644
index c29567e90f..0000000000
--- a/modules/mappers/mod_imap.c
+++ /dev/null
@@ -1,925 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * This imagemap module started as a port of the original imagemap.c
- * written by Rob McCool (11/13/93 robm@ncsa.uiuc.edu).
- * This version includes the mapping algorithms found in version 1.3
- * of imagemap.c.
- *
- * Contributors to this code include:
- *
- * Kevin Hughes, kevinh@pulua.hcc.hawaii.edu
- *
- * Eric Haines, erich@eye.com
- * "macmartinized" polygon code copyright 1992 by Eric Haines, erich@eye.com
- *
- * Randy Terbush, randy@zyzzyva.com
- * port to Apache module format, "base_uri" and support for relative URLs
- *
- * James H. Cloos, Jr., cloos@jhcloos.com
- * Added point datatype, using code in NCSA's version 1.8 imagemap.c
- * program, as distributed with version 1.4.1 of their server.
- * The point code is originally added by Craig Milo Rogers, Rogers@ISI.Edu
- *
- * Nathan Kurz, nate@tripod.com
- * Rewrite/reorganization. New handling of default, base and relative URLs.
- * New Configuration directives:
- * ImapMenu {none, formatted, semiformatted, unformatted}
- * ImapDefault {error, nocontent, referer, menu, URL}
- * ImapBase {map, referer, URL}
- * Support for creating non-graphical menu added. (backwards compatible):
- * Old: directive URL [x,y ...]
- * New: directive URL "Menu text" [x,y ...]
- * or: directive URL x,y ... "Menu text"
- * Map format and menu concept courtesy Joshua Bell, jsbell@acs.ucalgary.ca.
- *
- * Mark Cox, mark@ukweb.com, Allow relative URLs even when no base specified
- */
-
-#include "apr.h"
-#include "apr_strings.h"
-#include "apr_lib.h"
-
-#define APR_WANT_STDIO /* for sscanf() */
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_request.h"
-#include "http_core.h"
-#include "http_protocol.h"
-#include "http_main.h"
-#include "http_log.h"
-#include "util_script.h"
-#include "mod_core.h"
-
-
-#define IMAP_MAGIC_TYPE "application/x-httpd-imap"
-#define MAXVERTS 100
-#define X 0
-#define Y 1
-
-#define IMAP_MENU_DEFAULT "formatted"
-#define IMAP_DEFAULT_DEFAULT "nocontent"
-#define IMAP_BASE_DEFAULT "map"
-
-#ifdef SUNOS4
-double strtod(); /* SunOS needed this */
-#endif
-
-module AP_MODULE_DECLARE_DATA imap_module;
-
-typedef struct {
- char *imap_menu;
- char *imap_default;
- char *imap_base;
-} imap_conf_rec;
-
-static void *create_imap_dir_config(apr_pool_t *p, char *dummy)
-{
- imap_conf_rec *icr =
- (imap_conf_rec *) apr_palloc(p, sizeof(imap_conf_rec));
-
- icr->imap_menu = NULL;
- icr->imap_default = NULL;
- icr->imap_base = NULL;
-
- return icr;
-}
-
-static void *merge_imap_dir_configs(apr_pool_t *p, void *basev, void *addv)
-{
- imap_conf_rec *new = (imap_conf_rec *) apr_pcalloc(p, sizeof(imap_conf_rec));
- imap_conf_rec *base = (imap_conf_rec *) basev;
- imap_conf_rec *add = (imap_conf_rec *) addv;
-
- new->imap_menu = add->imap_menu ? add->imap_menu : base->imap_menu;
- new->imap_default = add->imap_default ? add->imap_default
- : base->imap_default;
- new->imap_base = add->imap_base ? add->imap_base : base->imap_base;
-
- return new;
-}
-
-
-static const command_rec imap_cmds[] =
-{
- AP_INIT_TAKE1("ImapMenu", ap_set_string_slot,
- (void *) XtOffsetOf(imap_conf_rec, imap_menu), OR_INDEXES,
- "the type of menu generated: none, formatted, semiformatted, "
- "unformatted"),
- AP_INIT_TAKE1("ImapDefault", ap_set_string_slot,
- (void *) XtOffsetOf(imap_conf_rec, imap_default), OR_INDEXES,
- "the action taken if no match: error, nocontent, referer, "
- "menu, URL"),
- AP_INIT_TAKE1("ImapBase", ap_set_string_slot,
- (void *) XtOffsetOf(imap_conf_rec, imap_base), OR_INDEXES,
- "the base for all URL's: map, referer, URL (or start of)"),
- {NULL}
-};
-
-static int pointinrect(const double point[2], double coords[MAXVERTS][2])
-{
- double max[2], min[2];
- if (coords[0][X] > coords[1][X]) {
- max[0] = coords[0][X];
- min[0] = coords[1][X];
- }
- else {
- max[0] = coords[1][X];
- min[0] = coords[0][X];
- }
-
- if (coords[0][Y] > coords[1][Y]) {
- max[1] = coords[0][Y];
- min[1] = coords[1][Y];
- }
- else {
- max[1] = coords[1][Y];
- min[1] = coords[0][Y];
- }
-
- return ((point[X] >= min[0] && point[X] <= max[0]) &&
- (point[Y] >= min[1] && point[Y] <= max[1]));
-}
-
-static int pointincircle(const double point[2], double coords[MAXVERTS][2])
-{
- double radius1, radius2;
-
- radius1 = ((coords[0][Y] - coords[1][Y]) * (coords[0][Y] - coords[1][Y]))
- + ((coords[0][X] - coords[1][X]) * (coords[0][X] - coords[1][X]));
-
- radius2 = ((coords[0][Y] - point[Y]) * (coords[0][Y] - point[Y]))
- + ((coords[0][X] - point[X]) * (coords[0][X] - point[X]));
-
- return (radius2 <= radius1);
-}
-
-#define fmin(a,b) (((a)>(b))?(b):(a))
-#define fmax(a,b) (((a)>(b))?(a):(b))
-
-static int pointinpoly(const double point[2], double pgon[MAXVERTS][2])
-{
- int i, numverts, crossings = 0;
- double x = point[X], y = point[Y];
-
- for (numverts = 0; pgon[numverts][X] != -1 && numverts < MAXVERTS;
- numverts++) {
- /* just counting the vertexes */
- }
-
- for (i = 0; i < numverts; i++) {
- double x1=pgon[i][X];
- double y1=pgon[i][Y];
- double x2=pgon[(i + 1) % numverts][X];
- double y2=pgon[(i + 1) % numverts][Y];
- double d=(y - y1) * (x2 - x1) - (x - x1) * (y2 - y1);
-
- if ((y1 >= y) != (y2 >= y)) {
- crossings +=y2 - y1 >= 0 ? d >= 0 : d <= 0;
- }
- if (!d && fmin(x1,x2) <= x && x <= fmax(x1,x2)
- && fmin(y1,y2) <= y && y <= fmax(y1,y2)) {
- return 1;
- }
- }
- return crossings & 0x01;
-}
-
-
-static int is_closer(const double point[2], double coords[MAXVERTS][2],
- double *closest)
-{
- double dist_squared = ((point[X] - coords[0][X])
- * (point[X] - coords[0][X]))
- + ((point[Y] - coords[0][Y])
- * (point[Y] - coords[0][Y]));
-
- if (point[X] < 0 || point[Y] < 0) {
- return (0); /* don't mess around with negative coordinates */
- }
-
- if (*closest < 0 || dist_squared < *closest) {
- *closest = dist_squared;
- return (1); /* if this is the first point or is the closest yet
- set 'closest' equal to this distance^2 */
- }
-
- return (0); /* if it's not the first or closest */
-
-}
-
-static double get_x_coord(const char *args)
-{
- char *endptr; /* we want it non-null */
- double x_coord = -1; /* -1 is returned if no coordinate is given */
-
- if (args == NULL) {
- return (-1); /* in case we aren't passed anything */
- }
-
- while (*args && !apr_isdigit(*args) && *args != ',') {
- args++; /* jump to the first digit, but not past
- a comma or end */
- }
-
- x_coord = strtod(args, &endptr);
-
- if (endptr > args) { /* if a conversion was made */
- return (x_coord);
- }
-
- return (-1); /* else if no conversion was made,
- or if no args was given */
-}
-
-static double get_y_coord(const char *args)
-{
- char *endptr; /* we want it non-null */
- const char *start_of_y = NULL;
- double y_coord = -1; /* -1 is returned on error */
-
- if (args == NULL) {
- return (-1); /* in case we aren't passed anything */
- }
-
- start_of_y = ap_strchr_c(args, ','); /* the comma */
-
- if (start_of_y) {
-
- start_of_y++; /* start looking at the character after
- the comma */
-
- while (*start_of_y && !apr_isdigit(*start_of_y)) {
- start_of_y++; /* jump to the first digit, but not
- past the end */
- }
-
- y_coord = strtod(start_of_y, &endptr);
-
- if (endptr > start_of_y) {
- return (y_coord);
- }
- }
-
- return (-1); /* if no conversion was made, or
- no comma was found in args */
-}
-
-
-/* See if string has a "quoted part", and if so set *quoted_part to
- * the first character of the quoted part, then hammer a \0 onto the
- * trailing quote, and set *string to point at the first character
- * past the second quote.
- *
- * Otherwise set *quoted_part to NULL, and leave *string alone.
- */
-static void read_quoted(char **string, char **quoted_part)
-{
- char *strp = *string;
-
- /* assume there's no quoted part */
- *quoted_part = NULL;
-
- while (apr_isspace(*strp)) {
- strp++; /* go along string until non-whitespace */
- }
-
- if (*strp == '"') { /* if that character is a double quote */
- strp++; /* step over it */
- *quoted_part = strp; /* note where the quoted part begins */
-
- while (*strp && *strp != '"') {
- ++strp; /* skip the quoted portion */
- }
-
- *strp = '\0'; /* end the string with a NUL */
-
- strp++; /* step over the last double quote */
- *string = strp;
- }
-}
-
-/*
- * returns the mapped URL or NULL.
- */
-static char *imap_url(request_rec *r, const char *base, const char *value)
-{
-/* translates a value into a URL. */
- int slen, clen;
- char *string_pos = NULL;
- const char *string_pos_const = NULL;
- char *directory = NULL;
- const char *referer = NULL;
- char *my_base;
-
- if (!strcasecmp(value, "map") || !strcasecmp(value, "menu")) {
- return ap_construct_url(r->pool, r->uri, r);
- }
-
- if (!strcasecmp(value, "nocontent") || !strcasecmp(value, "error")) {
- return apr_pstrdup(r->pool, value); /* these are handled elsewhere,
- so just copy them */
- }
-
- if (!strcasecmp(value, "referer")) {
- referer = apr_table_get(r->headers_in, "Referer");
- if (referer && *referer) {
- return apr_pstrdup(r->pool, referer);
- }
- else {
- /* XXX: This used to do *value = '\0'; ... which is totally bogus
- * because it hammers the passed in value, which can be a string
- * constant, or part of a config, or whatever. Total garbage.
- * This works around that without changing the rest of this
- * code much
- */
- value = ""; /* if 'referer' but no referring page,
- null the value */
- }
- }
-
- string_pos_const = value;
- while (apr_isalpha(*string_pos_const)) {
- string_pos_const++; /* go along the URL from the map
- until a non-letter */
- }
- if (*string_pos_const == ':') {
- /* if letters and then a colon (like http:) */
- /* it's an absolute URL, so use it! */
- return apr_pstrdup(r->pool, value);
- }
-
- if (!base || !*base) {
- if (value && *value) {
- return apr_pstrdup(r->pool, value); /* no base: use what is given */
- }
- /* no base, no value: pick a simple default */
- return ap_construct_url(r->pool, "/", r);
- }
-
- /* must be a relative URL to be combined with base */
- if (ap_strchr_c(base, '/') == NULL && (!strncmp(value, "../", 3)
- || !strcmp(value, ".."))) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "invalid base directive in map file: %s", r->uri);
- return NULL;
- }
- my_base = apr_pstrdup(r->pool, base);
- string_pos = my_base;
- while (*string_pos) {
- if (*string_pos == '/' && *(string_pos + 1) == '/') {
- string_pos += 2; /* if there are two slashes, jump over them */
- continue;
- }
- if (*string_pos == '/') { /* the first single slash */
- if (value[0] == '/') {
- *string_pos = '\0';
- } /* if the URL from the map starts from root,
- end the base URL string at the first single
- slash */
- else {
- directory = string_pos; /* save the start of
- the directory portion */
-
- string_pos = strrchr(string_pos, '/'); /* now reuse
- string_pos */
- string_pos++; /* step over that last slash */
- *string_pos = '\0';
- } /* but if the map url is relative, leave the
- slash on the base (if there is one) */
- break;
- }
- string_pos++; /* until we get to the end of my_base without
- finding a slash by itself */
- }
-
- while (!strncmp(value, "../", 3) || !strcmp(value, "..")) {
-
- if (directory && (slen = strlen(directory))) {
-
- /* for each '..', knock a directory off the end
- by ending the string right at the last slash.
- But only consider the directory portion: don't eat
- into the server name. And only try if a directory
- portion was found */
-
- clen = slen - 1;
-
- while ((slen - clen) == 1) {
-
- if ((string_pos = strrchr(directory, '/'))) {
- *string_pos = '\0';
- }
- clen = strlen(directory);
- if (clen == 0) {
- break;
- }
- }
-
- value += 2; /* jump over the '..' that we found in the
- value */
- }
- else if (directory) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "invalid directory name in map file: %s", r->uri);
- return NULL;
- }
-
- if (!strncmp(value, "/../", 4) || !strcmp(value, "/..")) {
- value++; /* step over the '/' if there are more '..'
- to do. This way, we leave the starting
- '/' on value after the last '..', but get
- rid of it otherwise */
- }
-
- } /* by this point, value does not start
- with '..' */
-
- if (value && *value) {
- return apr_pstrcat(r->pool, my_base, value, NULL);
- }
- return my_base;
-}
-
-static int imap_reply(request_rec *r, char *redirect)
-{
- if (!strcasecmp(redirect, "error")) {
- /* they actually requested an error! */
- return HTTP_INTERNAL_SERVER_ERROR;
- }
- if (!strcasecmp(redirect, "nocontent")) {
- /* tell the client to keep the page it has */
- return HTTP_NO_CONTENT;
- }
- if (redirect && *redirect) {
- /* must be a URL, so redirect to it */
- apr_table_setn(r->headers_out, "Location", redirect);
- return HTTP_MOVED_TEMPORARILY;
- }
- return HTTP_INTERNAL_SERVER_ERROR;
-}
-
-static void menu_header(request_rec *r, char *menu)
-{
- r->content_type = "text/html";
-
- ap_rvputs(r, DOCTYPE_HTML_3_2, "<html><head>\n<title>Menu for ", r->uri,
- "</title>\n</head><body>\n", NULL);
-
- if (!strcasecmp(menu, "formatted")) {
- ap_rvputs(r, "<h1>Menu for ", r->uri, "</h1>\n<hr>\n\n", NULL);
- }
-
- return;
-}
-
-static void menu_blank(request_rec *r, char *menu)
-{
- if (!strcasecmp(menu, "formatted")) {
- ap_rputs("\n", r);
- }
- if (!strcasecmp(menu, "semiformatted")) {
- ap_rputs("<br>\n", r);
- }
- if (!strcasecmp(menu, "unformatted")) {
- ap_rputs("\n", r);
- }
- return;
-}
-
-static void menu_comment(request_rec *r, char *menu, char *comment)
-{
- if (!strcasecmp(menu, "formatted")) {
- ap_rputs("\n", r); /* print just a newline if 'formatted' */
- }
- if (!strcasecmp(menu, "semiformatted") && *comment) {
- ap_rvputs(r, comment, "\n", NULL);
- }
- if (!strcasecmp(menu, "unformatted") && *comment) {
- ap_rvputs(r, comment, "\n", NULL);
- }
- return; /* comments are ignored in the
- 'formatted' form */
-}
-
-static void menu_default(request_rec *r, char *menu, char *href, char *text)
-{
- if (!strcasecmp(href, "error") || !strcasecmp(href, "nocontent")) {
- return; /* don't print such lines, these aren't
- really href's */
- }
- if (!strcasecmp(menu, "formatted")) {
- ap_rvputs(r, "<pre>(Default) <a href=\"", href, "\">", text,
- "</a></pre>\n", NULL);
- }
- if (!strcasecmp(menu, "semiformatted")) {
- ap_rvputs(r, "<pre>(Default) <a href=\"", href, "\">", text,
- "</a></pre>\n", NULL);
- }
- if (!strcasecmp(menu, "unformatted")) {
- ap_rvputs(r, "<a href=\"", href, "\">", text, "</a>", NULL);
- }
- return;
-}
-
-static void menu_directive(request_rec *r, char *menu, char *href, char *text)
-{
- if (!strcasecmp(href, "error") || !strcasecmp(href, "nocontent")) {
- return; /* don't print such lines, as this isn't
- really an href */
- }
- if (!strcasecmp(menu, "formatted")) {
- ap_rvputs(r, "<pre> <a href=\"", href, "\">", text,
- "</a></pre>\n", NULL);
- }
- if (!strcasecmp(menu, "semiformatted")) {
- ap_rvputs(r, "<pre> <a href=\"", href, "\">", text,
- "</a></pre>\n", NULL);
- }
- if (!strcasecmp(menu, "unformatted")) {
- ap_rvputs(r, "<a href=\"", href, "\">", text, "</a>", NULL);
- }
- return;
-}
-
-static void menu_footer(request_rec *r)
-{
- ap_rputs("\n\n</body>\n</html>\n", r); /* finish the menu */
-}
-
-static int imap_handler(request_rec *r)
-{
- char input[MAX_STRING_LEN];
- char *directive;
- char *value;
- char *href_text;
- char *base;
- char *redirect;
- char *mapdflt;
- char *closest = NULL;
- double closest_yet = -1;
- apr_status_t status;
-
- double testpoint[2];
- double pointarray[MAXVERTS + 1][2];
- int vertex;
-
- char *string_pos;
- int showmenu = 0;
-
- imap_conf_rec *icr;
-
- char *imap_menu;
- char *imap_default;
- char *imap_base;
-
- ap_configfile_t *imap;
-
- if (r->method_number != M_GET || (strcmp(r->handler,IMAP_MAGIC_TYPE)
- && strcmp(r->handler, "imap-file")))
- return DECLINED;
-
- icr = ap_get_module_config(r->per_dir_config, &imap_module);
-
- imap_menu = icr->imap_menu ? icr->imap_menu : IMAP_MENU_DEFAULT;
- imap_default = icr->imap_default
- ? icr->imap_default : IMAP_DEFAULT_DEFAULT;
- imap_base = icr->imap_base ? icr->imap_base : IMAP_BASE_DEFAULT;
-
- status = ap_pcfg_openfile(&imap, r->pool, r->filename);
-
- if (status != APR_SUCCESS) {
- return HTTP_NOT_FOUND;
- }
-
- base = imap_url(r, NULL, imap_base); /* set base according
- to default */
- if (!base) {
- return HTTP_INTERNAL_SERVER_ERROR;
- }
- mapdflt = imap_url(r, NULL, imap_default); /* and default to
- global default */
- if (!mapdflt) {
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- testpoint[X] = get_x_coord(r->args);
- testpoint[Y] = get_y_coord(r->args);
-
- if ((testpoint[X] == -1 || testpoint[Y] == -1) ||
- (testpoint[X] == 0 && testpoint[Y] == 0)) {
- /* if either is -1 or if both are zero (new Lynx) */
- /* we don't have valid coordinates */
- testpoint[X] = -1;
- testpoint[Y] = -1;
- if (strncasecmp(imap_menu, "none", 2)) {
- showmenu = 1; /* show the menu _unless_ ImapMenu is
- 'none' or 'no' */
- }
- }
-
- if (showmenu) { /* send start of imagemap menu if
- we're going to */
- menu_header(r, imap_menu);
- }
-
- while (!ap_cfg_getline(input, sizeof(input), imap)) {
- if (!input[0]) {
- if (showmenu) {
- menu_blank(r, imap_menu);
- }
- continue;
- }
-
- if (input[0] == '#') {
- if (showmenu) {
- menu_comment(r, imap_menu, input + 1);
- }
- continue;
- } /* blank lines and comments are ignored
- if we aren't printing a menu */
-
- /* find the first two space delimited fields, recall that
- * ap_cfg_getline has removed leading/trailing whitespace.
- *
- * note that we're tokenizing as we go... if we were to use the
- * ap_getword() class of functions we would end up allocating extra
- * memory for every line of the map file
- */
- string_pos = input;
- if (!*string_pos) { /* need at least two fields */
- goto need_2_fields;
- }
-
- directive = string_pos;
- while (*string_pos && !apr_isspace(*string_pos)) { /* past directive */
- ++string_pos;
- }
- if (!*string_pos) { /* need at least two fields */
- goto need_2_fields;
- }
- *string_pos++ = '\0';
-
- if (!*string_pos) { /* need at least two fields */
- goto need_2_fields;
- }
- while(*string_pos && apr_isspace(*string_pos)) { /* past whitespace */
- ++string_pos;
- }
-
- value = string_pos;
- while (*string_pos && !apr_isspace(*string_pos)) { /* past value */
- ++string_pos;
- }
- if (apr_isspace(*string_pos)) {
- *string_pos++ = '\0';
- }
- else {
- /* end of input, don't advance past it */
- *string_pos = '\0';
- }
-
- if (!strncasecmp(directive, "base", 4)) { /* base, base_uri */
- base = imap_url(r, NULL, value);
- if (!base) {
- goto menu_bail;
- }
- continue; /* base is never printed to a menu */
- }
-
- read_quoted(&string_pos, &href_text);
-
- if (!strcasecmp(directive, "default")) { /* default */
- mapdflt = imap_url(r, NULL, value);
- if (!mapdflt) {
- goto menu_bail;
- }
- if (showmenu) { /* print the default if there's a menu */
- redirect = imap_url(r, base, mapdflt);
- if (!redirect) {
- goto menu_bail;
- }
- menu_default(r, imap_menu, redirect,
- href_text ? href_text : mapdflt);
- }
- continue;
- }
-
- vertex = 0;
- while (vertex < MAXVERTS &&
- sscanf(string_pos, "%lf%*[, ]%lf",
- &pointarray[vertex][X], &pointarray[vertex][Y]) == 2) {
- /* Now skip what we just read... we can't use ANSIism %n */
- while (apr_isspace(*string_pos)) { /* past whitespace */
- string_pos++;
- }
- while (apr_isdigit(*string_pos)) { /* and the 1st number */
- string_pos++;
- }
- string_pos++; /* skip the ',' */
- while (apr_isspace(*string_pos)) { /* past any more whitespace */
- string_pos++;
- }
- while (apr_isdigit(*string_pos)) { /* 2nd number */
- string_pos++;
- }
- vertex++;
- } /* so long as there are more vertices to
- read, and we have room, read them in.
- We start where we left off of the last
- sscanf, not at the beginning. */
-
- pointarray[vertex][X] = -1; /* signals the end of vertices */
-
- if (showmenu) {
- if (!href_text) {
- read_quoted(&string_pos, &href_text); /* href text could
- be here instead */
- }
- redirect = imap_url(r, base, value);
- if (!redirect) {
- goto menu_bail;
- }
- menu_directive(r, imap_menu, redirect,
- href_text ? href_text : value);
- continue;
- }
- /* note that we don't make it past here if we are making a menu */
-
- if (testpoint[X] == -1 || pointarray[0][X] == -1) {
- continue; /* don't try the following tests if testpoints
- are invalid, or if there are no
- coordinates */
- }
-
- if (!strcasecmp(directive, "poly")) { /* poly */
-
- if (pointinpoly(testpoint, pointarray)) {
- ap_cfg_closefile(imap);
- redirect = imap_url(r, base, value);
- if (!redirect) {
- return HTTP_INTERNAL_SERVER_ERROR;
- }
- return (imap_reply(r, redirect));
- }
- continue;
- }
-
- if (!strcasecmp(directive, "circle")) { /* circle */
-
- if (pointincircle(testpoint, pointarray)) {
- ap_cfg_closefile(imap);
- redirect = imap_url(r, base, value);
- if (!redirect) {
- return HTTP_INTERNAL_SERVER_ERROR;
- }
- return (imap_reply(r, redirect));
- }
- continue;
- }
-
- if (!strcasecmp(directive, "rect")) { /* rect */
-
- if (pointinrect(testpoint, pointarray)) {
- ap_cfg_closefile(imap);
- redirect = imap_url(r, base, value);
- if (!redirect) {
- return HTTP_INTERNAL_SERVER_ERROR;
- }
- return (imap_reply(r, redirect));
- }
- continue;
- }
-
- if (!strcasecmp(directive, "point")) { /* point */
-
- if (is_closer(testpoint, pointarray, &closest_yet)) {
- closest = apr_pstrdup(r->pool, value);
- }
-
- continue;
- } /* move on to next line whether it's
- closest or not */
-
- } /* nothing matched, so we get another line! */
-
- ap_cfg_closefile(imap); /* we are done with the map file; close it */
-
- if (showmenu) {
- menu_footer(r); /* finish the menu and we are done */
- return OK;
- }
-
- if (closest) { /* if a 'point' directive has been seen */
- redirect = imap_url(r, base, closest);
- if (!redirect) {
- return HTTP_INTERNAL_SERVER_ERROR;
- }
- return (imap_reply(r, redirect));
- }
-
- if (mapdflt) { /* a default should be defined, even if
- only 'nocontent' */
- redirect = imap_url(r, base, mapdflt);
- if (!redirect) {
- return HTTP_INTERNAL_SERVER_ERROR;
- }
- return (imap_reply(r, redirect));
- }
-
- return HTTP_INTERNAL_SERVER_ERROR; /* If we make it this far,
- we failed. They lose! */
-
-need_2_fields:
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "map file %s, line %d syntax error: requires at "
- "least two fields", r->uri, imap->line_number);
- /* fall through */
-menu_bail:
- ap_cfg_closefile(imap);
- if (showmenu) {
- /* There's not much else we can do ... we've already sent the headers
- * to the client.
- */
- ap_rputs("\n\n[an internal server error occured]\n", r);
- menu_footer(r);
- return OK;
- }
- return HTTP_INTERNAL_SERVER_ERROR;
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_handler(imap_handler,NULL,NULL,APR_HOOK_MIDDLE);
-}
-
-module AP_MODULE_DECLARE_DATA imap_module =
-{
- STANDARD20_MODULE_STUFF,
- create_imap_dir_config, /* dir config creater */
- merge_imap_dir_configs, /* dir merger --- default is to override */
- NULL, /* server config */
- NULL, /* merge server config */
- imap_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
diff --git a/modules/mappers/mod_imap.exp b/modules/mappers/mod_imap.exp
deleted file mode 100644
index 1e0e0b83d0..0000000000
--- a/modules/mappers/mod_imap.exp
+++ /dev/null
@@ -1 +0,0 @@
-imap_module
diff --git a/modules/mappers/mod_negotiation.c b/modules/mappers/mod_negotiation.c
deleted file mode 100644
index 679460c088..0000000000
--- a/modules/mappers/mod_negotiation.c
+++ /dev/null
@@ -1,2756 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * mod_negotiation.c: keeps track of MIME types the client is willing to
- * accept, and contains code to handle type arbitration.
- *
- * rst
- */
-
-#include "apr.h"
-#include "apr_strings.h"
-#include "apr_file_io.h"
-#include "apr_lib.h"
-
-#define APR_WANT_STDIO /* for EOF */
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#include "ap_config.h"
-#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 MAP_FILE_MAGIC_TYPE "application/x-type-map"
-
-/* Commands --- configuring document caching on a per (virtual?)
- * server basis...
- */
-
-typedef struct {
- apr_array_header_t *language_priority;
-} neg_dir_config;
-
-module AP_MODULE_DECLARE_DATA negotiation_module;
-
-static void *create_neg_dir_config(apr_pool_t *p, char *dummy)
-{
- neg_dir_config *new = (neg_dir_config *) apr_palloc(p, sizeof(neg_dir_config));
-
- new->language_priority = apr_array_make(p, 4, sizeof(char *));
- return new;
-}
-
-static void *merge_neg_dir_configs(apr_pool_t *p, void *basev, void *addv)
-{
- neg_dir_config *base = (neg_dir_config *) basev;
- neg_dir_config *add = (neg_dir_config *) addv;
- neg_dir_config *new = (neg_dir_config *) apr_palloc(p, sizeof(neg_dir_config));
-
- /* give priority to the config in the subdirectory */
- new->language_priority = apr_array_append(p, add->language_priority,
- base->language_priority);
- return new;
-}
-
-static const char *set_language_priority(cmd_parms *cmd, void *n,
- const char *lang)
-{
- apr_array_header_t *arr = ((neg_dir_config *) n)->language_priority;
- const char **langp = (const char **) apr_array_push(arr);
-
- *langp = lang;
- return NULL;
-}
-
-static const char *cache_negotiated_docs(cmd_parms *cmd, void *dummy,
- int arg)
-{
- ap_set_module_config(cmd->server->module_config, &negotiation_module,
- (arg ? "Cache" : NULL));
- return NULL;
-}
-
-static int do_cache_negotiated_docs(server_rec *s)
-{
- return (ap_get_module_config(s->module_config, &negotiation_module) != NULL);
-}
-
-static const command_rec negotiation_cmds[] =
-{
- AP_INIT_FLAG("CacheNegotiatedDocs", cache_negotiated_docs, NULL, RSRC_CONF,
- "Either 'on' or 'off' (default)"),
- AP_INIT_ITERATE("LanguagePriority", set_language_priority, NULL, OR_FILEINFO,
- "space-delimited list of MIME language abbreviations"),
- {NULL}
-};
-
-/*
- * Record of available info on a media type specified by the client
- * (we also use 'em for encodings and languages)
- */
-
-typedef struct accept_rec {
- char *name; /* MUST be lowercase */
- float quality;
- float level;
- char *charset; /* for content-type only */
-} accept_rec;
-
-/*
- * Record of available info on a particular variant
- *
- * Note that a few of these fields are updated by the actual negotiation
- * code. These are:
- *
- * level_matched --- initialized to zero. Set to the value of level
- * if the client actually accepts this media type at that
- * level (and *not* if it got in on a wildcard). See level_cmp
- * below.
- * mime_stars -- initialized to zero. Set to the number of stars
- * present in the best matching Accept header element.
- * 1 for star/star, 2 for type/star and 3 for
- * type/subtype.
- *
- * definite -- initialized to 1. Set to 0 if there is a match which
- * makes the variant non-definite according to the rules
- * in rfc2296.
- */
-
-typedef struct var_rec {
- request_rec *sub_req; /* May be NULL (is, for map files) */
- char *mime_type; /* MUST be lowercase */
- char *file_name;
- const char *content_encoding;
- apr_array_header_t *content_languages; /* list of languages for this variant */
- char *content_charset;
- char *description;
-
- /* The next five items give the quality values for the dimensions
- * of negotiation for this variant. They are obtained from the
- * appropriate header lines, except for source_quality, which
- * is obtained from the variant itself (the 'qs' parameter value
- * from the variant's mime-type). Apart from source_quality,
- * these values are set when we find the quality for each variant
- * (see best_match()). source_quality is set from the 'qs' parameter
- * of the variant description or mime type: see set_mime_fields().
- */
- float lang_quality; /* quality of this variant's language */
- float encoding_quality; /* ditto encoding */
- float charset_quality; /* ditto charset */
- float mime_type_quality; /* ditto media type */
- float source_quality; /* source quality for this variant */
-
- /* Now some special values */
- float level; /* Auxiliary to content-type... */
- long bytes; /* content length, if known */
- int lang_index; /* pre HTTP/1.1 language priority stuff */
- int is_pseudo_html; /* text/html, *or* the INCLUDES_MAGIC_TYPEs */
-
- /* Above are all written-once properties of the variant. The
- * three fields below are changed during negotiation:
- */
-
- float level_matched;
- int mime_stars;
- int definite;
-} var_rec;
-
-/* Something to carry around the state of negotiation (and to keep
- * all of this thread-safe)...
- */
-
-typedef struct {
- apr_pool_t *pool;
- request_rec *r;
- char *dir_name;
- int accept_q; /* 1 if an Accept item has a q= param */
- float default_lang_quality; /* fiddle lang q for variants with no lang */
-
- /* the array pointers below are NULL if the corresponding accept
- * headers are not present
- */
- apr_array_header_t *accepts; /* accept_recs */
- apr_array_header_t *accept_encodings; /* accept_recs */
- apr_array_header_t *accept_charsets; /* accept_recs */
- apr_array_header_t *accept_langs; /* accept_recs */
-
- apr_array_header_t *avail_vars; /* available variants */
-
- int count_multiviews_variants; /* number of variants found on disk */
-
- int is_transparent; /* 1 if this resource is trans. negotiable */
-
- int dont_fiddle_headers; /* 1 if we may not fiddle with accept hdrs */
- int ua_supports_trans; /* 1 if ua supports trans negotiation */
- int send_alternates; /* 1 if we want to send an Alternates header */
- int may_choose; /* 1 if we may choose a variant for the client */
- int use_rvsa; /* 1 if we must use RVSA/1.0 negotiation algo */
-} negotiation_state;
-
-/* A few functions to manipulate var_recs.
- * Cleaning out the fields...
- */
-
-static void clean_var_rec(var_rec *mime_info)
-{
- mime_info->sub_req = NULL;
- mime_info->mime_type = "";
- mime_info->file_name = "";
- mime_info->content_encoding = NULL;
- mime_info->content_languages = NULL;
- mime_info->content_charset = "";
- mime_info->description = "";
-
- mime_info->is_pseudo_html = 0;
- mime_info->level = 0.0f;
- mime_info->level_matched = 0.0f;
- mime_info->bytes = 0;
- mime_info->lang_index = -1;
- mime_info->mime_stars = 0;
- mime_info->definite = 1;
-
- mime_info->charset_quality = 1.0f;
- mime_info->encoding_quality = 1.0f;
- mime_info->lang_quality = 1.0f;
- mime_info->mime_type_quality = 1.0f;
- mime_info->source_quality = 0.0f;
-}
-
-/* Initializing the relevant fields of a variant record from the
- * accept_info read out of its content-type, one way or another.
- */
-
-static void set_mime_fields(var_rec *var, accept_rec *mime_info)
-{
- var->mime_type = mime_info->name;
- var->source_quality = mime_info->quality;
- var->level = mime_info->level;
- var->content_charset = mime_info->charset;
-
- var->is_pseudo_html = (!strcmp(var->mime_type, "text/html")
- || !strcmp(var->mime_type, INCLUDES_MAGIC_TYPE)
- || !strcmp(var->mime_type, INCLUDES_MAGIC_TYPE3));
-}
-
-/* Create a variant list validator in r using info from vlistr. */
-
-static void set_vlist_validator(request_rec *r, request_rec *vlistr)
-{
- /* Calculating the variant list validator is similar to
- * calculating an etag for the source of the variant list
- * information, so we use ap_make_etag(). Note that this
- * validator can be 'weak' in extreme case.
- */
- ap_update_mtime(vlistr, vlistr->finfo.mtime);
- r->vlist_validator = ap_make_etag(vlistr, 0);
-
- /* ap_set_etag will later take r->vlist_validator into account
- * when creating the etag header
- */
-}
-
-
-/*****************************************************************
- *
- * Parsing (lists of) media types and their parameters, as seen in
- * HTTPD header lines and elsewhere.
- */
-
-/*
- * Get a single mime type entry --- one media type and parameters;
- * enter the values we recognize into the argument accept_rec
- */
-
-static const char *get_entry(apr_pool_t *p, accept_rec *result,
- const char *accept_line)
-{
- result->quality = 1.0f;
- result->level = 0.0f;
- result->charset = "";
-
- /*
- * Note that this handles what I gather is the "old format",
- *
- * Accept: text/html text/plain moo/zot
- *
- * without any compatibility kludges --- if the token after the
- * MIME type begins with a semicolon, we know we're looking at parms,
- * otherwise, we know we aren't. (So why all the pissing and moaning
- * in the CERN server code? I must be missing something).
- */
-
- result->name = ap_get_token(p, &accept_line, 0);
- ap_str_tolower(result->name); /* You want case insensitive,
- * you'll *get* case insensitive.
- */
-
- /* KLUDGE!!! Default HTML to level 2.0 unless the browser
- * *explicitly* says something else.
- */
-
- if (!strcmp(result->name, "text/html") && (result->level == 0.0)) {
- result->level = 2.0f;
- }
- else if (!strcmp(result->name, INCLUDES_MAGIC_TYPE)) {
- result->level = 2.0f;
- }
- else if (!strcmp(result->name, INCLUDES_MAGIC_TYPE3)) {
- result->level = 3.0f;
- }
-
- while (*accept_line == ';') {
- /* Parameters ... */
-
- char *parm;
- char *cp;
- char *end;
-
- ++accept_line;
- parm = ap_get_token(p, &accept_line, 1);
-
- /* Look for 'var = value' --- and make sure the var is in lcase. */
-
- for (cp = parm; (*cp && !apr_isspace(*cp) && *cp != '='); ++cp) {
- *cp = apr_tolower(*cp);
- }
-
- if (!*cp) {
- continue; /* No '='; just ignore it. */
- }
-
- *cp++ = '\0'; /* Delimit var */
- while (*cp && (apr_isspace(*cp) || *cp == '=')) {
- ++cp;
- }
-
- if (*cp == '"') {
- ++cp;
- for (end = cp;
- (*end && *end != '\n' && *end != '\r' && *end != '\"');
- end++);
- }
- else {
- for (end = cp; (*end && !apr_isspace(*end)); end++);
- }
- if (*end) {
- *end = '\0'; /* strip ending quote or return */
- }
- ap_str_tolower(cp);
-
- if (parm[0] == 'q'
- && (parm[1] == '\0' || (parm[1] == 's' && parm[2] == '\0'))) {
- result->quality = (float)atof(cp);
- }
- else if (parm[0] == 'l' && !strcmp(&parm[1], "evel")) {
- result->level = (float)atof(cp);
- }
- else if (!strcmp(parm, "charset")) {
- result->charset = cp;
- }
- }
-
- if (*accept_line == ',') {
- ++accept_line;
- }
-
- return accept_line;
-}
-
-/*****************************************************************
- *
- * Dealing with header lines ...
- *
- * Accept, Accept-Charset, Accept-Language and Accept-Encoding
- * are handled by do_header_line() - they all have the same
- * basic structure of a list of items of the format
- * name; q=N; charset=TEXT
- *
- * where charset is only valid in Accept.
- */
-
-static apr_array_header_t *do_header_line(apr_pool_t *p, const char *accept_line)
-{
- apr_array_header_t *accept_recs;
-
- if (!accept_line) {
- return NULL;
- }
-
- accept_recs = apr_array_make(p, 40, sizeof(accept_rec));
-
- while (*accept_line) {
- accept_rec *new = (accept_rec *) apr_array_push(accept_recs);
- accept_line = get_entry(p, new, accept_line);
- }
-
- return accept_recs;
-}
-
-/* Given the text of the Content-Languages: line from the var map file,
- * return an array containing the languages of this variant
- */
-
-static apr_array_header_t *do_languages_line(apr_pool_t *p, const char **lang_line)
-{
- apr_array_header_t *lang_recs = apr_array_make(p, 2, sizeof(char *));
-
- if (!lang_line) {
- return lang_recs;
- }
-
- while (**lang_line) {
- char **new = (char **) apr_array_push(lang_recs);
- *new = ap_get_token(p, lang_line, 0);
- ap_str_tolower(*new);
- if (**lang_line == ',' || **lang_line == ';') {
- ++(*lang_line);
- }
- }
-
- return lang_recs;
-}
-
-/*****************************************************************
- *
- * Handling header lines from clients...
- */
-
-static negotiation_state *parse_accept_headers(request_rec *r)
-{
- negotiation_state *new =
- (negotiation_state *) apr_pcalloc(r->pool, sizeof(negotiation_state));
- accept_rec *elts;
- apr_table_t *hdrs = r->headers_in;
- int i;
-
- new->pool = r->pool;
- new->r = r;
- new->dir_name = ap_make_dirstr_parent(r->pool, r->filename);
-
- new->accepts = do_header_line(r->pool, apr_table_get(hdrs, "Accept"));
-
- /* calculate new->accept_q value */
- if (new->accepts) {
- elts = (accept_rec *) new->accepts->elts;
-
- for (i = 0; i < new->accepts->nelts; ++i) {
- if (elts[i].quality < 1.0) {
- new->accept_q = 1;
- }
- }
- }
-
- new->accept_encodings =
- do_header_line(r->pool, apr_table_get(hdrs, "Accept-Encoding"));
- new->accept_langs =
- do_header_line(r->pool, apr_table_get(hdrs, "Accept-Language"));
- new->accept_charsets =
- do_header_line(r->pool, apr_table_get(hdrs, "Accept-Charset"));
-
- new->avail_vars = apr_array_make(r->pool, 40, sizeof(var_rec));
-
- return new;
-}
-
-
-static void parse_negotiate_header(request_rec *r, negotiation_state *neg)
-{
- const char *negotiate = apr_table_get(r->headers_in, "Negotiate");
- char *tok;
-
- /* First, default to no TCN, no Alternates, and the original Apache
- * negotiation algorithm with fiddles for broken browser configs.
- *
- * To save network bandwidth, we do not configure to send an
- * Alternates header to the user agent by default. User
- * agents that want an Alternates header for agent-driven
- * negotiation will have to request it by sending an
- * appropriate Negotiate header.
- */
- neg->ua_supports_trans = 0;
- neg->send_alternates = 0;
- neg->may_choose = 1;
- neg->use_rvsa = 0;
- neg->dont_fiddle_headers = 0;
-
- if (!negotiate)
- return;
-
- if (strcmp(negotiate, "trans") == 0) {
- /* Lynx 2.7 and 2.8 send 'negotiate: trans' even though they
- * do not support transparent content negotiation, so for Lynx we
- * ignore the negotiate header when its contents are exactly "trans".
- * If future versions of Lynx ever need to say 'negotiate: trans',
- * they can send the equivalent 'negotiate: trans, trans' instead
- * to avoid triggering the workaround below.
- */
- const char *ua = apr_table_get(r->headers_in, "User-Agent");
-
- if (ua && (strncmp(ua, "Lynx", 4) == 0))
- return;
- }
-
- neg->may_choose = 0; /* An empty Negotiate would require 300 response */
-
- while ((tok = ap_get_list_item(neg->pool, &negotiate)) != NULL) {
-
- if (strcmp(tok, "trans") == 0 ||
- strcmp(tok, "vlist") == 0 ||
- strcmp(tok, "guess-small") == 0 ||
- apr_isdigit(tok[0]) ||
- strcmp(tok, "*") == 0) {
-
- /* The user agent supports transparent negotiation */
- neg->ua_supports_trans = 1;
-
- /* Send-alternates could be configurable, but note
- * that it must be 1 if we have 'vlist' in the
- * negotiate header.
- */
- neg->send_alternates = 1;
-
- if (strcmp(tok, "1.0") == 0) {
- /* we may use the RVSA/1.0 algorithm, configure for it */
- neg->may_choose = 1;
- neg->use_rvsa = 1;
- neg->dont_fiddle_headers = 1;
- }
- else if (tok[0] == '*') {
- /* we may use any variant selection algorithm, configure
- * to use the Apache algorithm
- */
- neg->may_choose = 1;
-
- /* We disable header fiddles on the assumption that a
- * client sending Negotiate knows how to send correct
- * headers which don't need fiddling.
- */
- neg->dont_fiddle_headers = 1;
- }
- }
- }
-
-#ifdef NEG_DEBUG
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "dont_fiddle_headers=%d use_rvsa=%d ua_supports_trans=%d "
- "send_alternates=%d, may_choose=%d",
- neg->dont_fiddle_headers, neg->use_rvsa,
- neg->ua_supports_trans, neg->send_alternates, neg->may_choose);
-#endif
-
-}
-
-/* Sometimes clients will give us no Accept info at all; this routine sets
- * up the standard default for that case, and also arranges for us to be
- * willing to run a CGI script if we find one. (In fact, we set up to
- * dramatically prefer CGI scripts in cases where that's appropriate,
- * e.g., POST or when URI includes query args or extra path info).
- */
-static void maybe_add_default_accepts(negotiation_state *neg,
- int prefer_scripts)
-{
- accept_rec *new_accept;
-
- if (!neg->accepts) {
- neg->accepts = apr_array_make(neg->pool, 4, sizeof(accept_rec));
-
- new_accept = (accept_rec *) apr_array_push(neg->accepts);
-
- new_accept->name = "*/*";
- new_accept->quality = 1.0f;
- new_accept->level = 0.0f;
- }
-
- new_accept = (accept_rec *) apr_array_push(neg->accepts);
-
- new_accept->name = CGI_MAGIC_TYPE;
- if (neg->use_rvsa) {
- new_accept->quality = 0;
- }
- else {
- new_accept->quality = prefer_scripts ? 2.0f : 0.001f;
- }
- new_accept->level = 0.0f;
-}
-
-/*****************************************************************
- *
- * Parsing type-map files, in Roy's meta/http format augmented with
- * #-comments.
- */
-
-/* Reading RFC822-style header lines, ignoring #-comments and
- * handling continuations.
- */
-
-enum header_state {
- header_eof, header_seen, header_sep
-};
-
-static enum header_state get_header_line(char *buffer, int len, apr_file_t *map)
-{
- char *buf_end = buffer + len;
- char *cp;
- char c;
-
- /* Get a noncommented line */
-
- do {
- if (apr_file_gets(buffer, MAX_STRING_LEN, map) != APR_SUCCESS) {
- return header_eof;
- }
- } while (buffer[0] == '#');
-
- /* If blank, just return it --- this ends information on this variant */
-
- for (cp = buffer; (*cp && apr_isspace(*cp)); ++cp) {
- continue;
- }
-
- if (*cp == '\0') {
- return header_sep;
- }
-
- /* If non-blank, go looking for header lines, but note that we still
- * have to treat comments specially...
- */
-
- cp += strlen(cp);
-
- while (apr_file_getc(&c, map) != APR_EOF) {
- if (c == '#') {
- /* Comment line */
- while (apr_file_getc(&c, map) != EOF && c != '\n') {
- continue;
- }
- }
- else if (apr_isspace(c)) {
- /* Leading whitespace. POSSIBLE continuation line
- * Also, possibly blank --- if so, we ungetc() the final newline
- * so that we will pick up the blank line the next time 'round.
- */
-
- while (c != '\n' && apr_isspace(c)) {
- if(apr_file_getc(&c, map) != APR_SUCCESS)
- break;
- }
-
- apr_file_ungetc(c, map);
-
- if (c == '\n') {
- return header_seen; /* Blank line */
- }
-
- /* Continuation */
-
- while (cp < buf_end - 2 && (apr_file_getc(&c, map)) != EOF && c != '\n') {
- *cp++ = c;
- }
-
- *cp++ = '\n';
- *cp = '\0';
- }
- else {
-
- /* Line beginning with something other than whitespace */
-
- apr_file_ungetc(c, map);
- return header_seen;
- }
- }
-
- return header_seen;
-}
-
-/* Stripping out RFC822 comments */
-
-static void strip_paren_comments(char *hdr)
-{
- /* Hmmm... is this correct? In Roy's latest draft, (comments) can nest! */
- /* Nope, it isn't correct. Fails to handle backslash escape as well. */
-
- while (*hdr) {
- if (*hdr == '"') {
- hdr = strchr(hdr, '"');
- if (hdr == NULL) {
- return;
- }
- ++hdr;
- }
- else if (*hdr == '(') {
- while (*hdr && *hdr != ')') {
- *hdr++ = ' ';
- }
-
- if (*hdr) {
- *hdr++ = ' ';
- }
- }
- else {
- ++hdr;
- }
- }
-}
-
-/* Getting to a header body from the header */
-
-static char *lcase_header_name_return_body(char *header, request_rec *r)
-{
- char *cp = header;
-
- for ( ; *cp && *cp != ':' ; ++cp) {
- *cp = apr_tolower(*cp);
- }
-
- if (!*cp) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Syntax error in type map --- no ':': %s", r->filename);
- return NULL;
- }
-
- do {
- ++cp;
- } while (*cp && apr_isspace(*cp));
-
- if (!*cp) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Syntax error in type map --- no header body: %s",
- r->filename);
- return NULL;
- }
-
- return cp;
-}
-
-static int read_type_map(negotiation_state *neg, request_rec *rr)
-{
- request_rec *r = neg->r;
- apr_file_t *map = NULL;
- apr_status_t status;
- 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;
-
- if ((status = apr_file_open(&map, rr->filename, APR_READ,
- APR_OS_DEFAULT, neg->pool)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
- "cannot access type map file: %s", rr->filename);
- return HTTP_FORBIDDEN;
- }
-
- clean_var_rec(&mime_info);
- has_content = 0;
-
- do {
- hstate = get_header_line(buffer, MAX_STRING_LEN, map);
-
- if (hstate == header_seen) {
- char *body1 = lcase_header_name_return_body(buffer, neg->r);
- const char *body;
-
- if (body1 == NULL) {
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- strip_paren_comments(body1);
- body = body1;
-
- if (!strncmp(buffer, "uri:", 4)) {
- mime_info.file_name = ap_get_token(neg->pool, &body, 0);
- }
- else if (!strncmp(buffer, "content-type:", 13)) {
- struct accept_rec accept_info;
-
- get_entry(neg->pool, &accept_info, body);
- set_mime_fields(&mime_info, &accept_info);
- has_content = 1;
- }
- else if (!strncmp(buffer, "content-length:", 15)) {
- mime_info.bytes = atol(body);
- has_content = 1;
- }
- else if (!strncmp(buffer, "content-language:", 17)) {
- mime_info.content_languages = do_languages_line(neg->pool,
- &body);
- has_content = 1;
- }
- else if (!strncmp(buffer, "content-encoding:", 17)) {
- mime_info.content_encoding = ap_get_token(neg->pool, &body, 0);
- has_content = 1;
- }
- else if (!strncmp(buffer, "description:", 12)) {
- char *desc = apr_pstrdup(neg->pool, body);
- char *cp;
-
- for (cp = desc; *cp; ++cp) {
- if (*cp=='\n') *cp=' ';
- }
- if (cp>desc) *(cp-1)=0;
- mime_info.description = desc;
- }
- }
- else {
- if (*mime_info.file_name && has_content) {
- void *new_var = apr_array_push(neg->avail_vars);
-
- memcpy(new_var, (void *) &mime_info, sizeof(var_rec));
- }
-
- clean_var_rec(&mime_info);
- has_content = 0;
- }
- } while (hstate != header_eof);
-
- apr_file_close(map);
-
- set_vlist_validator(r, rr);
-
- return OK;
-}
-
-
-/* Sort function used by read_types_multi. */
-static int variantsortf(var_rec *a, var_rec *b) {
-
- /* First key is the source quality, sort in descending order. */
-
- /* XXX: note that we currently implement no method of setting the
- * source quality for multiviews variants, so we are always comparing
- * 1.0 to 1.0 for now
- */
- if (a->source_quality < b->source_quality)
- return 1;
- if (a->source_quality > b->source_quality)
- return -1;
-
- /* Second key is the variant name */
- return strcmp(a->file_name, b->file_name);
-}
-
-/*****************************************************************
- *
- * Same as read_type_map, except we use a filtered directory listing
- * as the map...
- */
-
-static int read_types_multi(negotiation_state *neg)
-{
- request_rec *r = neg->r;
-
- char *filp;
- int prefix_len;
- apr_dir_t *dirp;
- apr_finfo_t dirent;
- apr_status_t status;
- struct var_rec mime_info;
- struct accept_rec accept_info;
- void *new_var;
-
- clean_var_rec(&mime_info);
-
- if (!(filp = strrchr(r->filename, '/'))) {
- return DECLINED; /* Weird... */
- }
-
- if (strncmp(r->filename, "proxy:", 6) == 0) {
- return DECLINED;
- }
-
- ++filp;
- prefix_len = strlen(filp);
-
- if ((status = apr_dir_open(&dirp, neg->dir_name, neg->pool)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
- "cannot read directory for multi: %s", neg->dir_name);
- return HTTP_FORBIDDEN;
- }
-
- while (apr_dir_read(&dirent, APR_FINFO_DIRENT, dirp) == APR_SUCCESS) {
- request_rec *sub_req;
-
- /* Do we have a match? */
- if (strncmp(dirent.name, filp, prefix_len)) {
- continue;
- }
- if (dirent.name[prefix_len] != '.') {
- continue;
- }
-
- /* Yep. See if it's something which we have access to, and
- * which has a known type and encoding (as opposed to something
- * which we'll be slapping default_type on later).
- */
-
- sub_req = ap_sub_req_lookup_file(dirent.name, r, NULL);
-
- /* If it has a handler, we'll pretend it's a CGI script,
- * since that's a good indication of the sort of thing it
- * might be doing.
- */
- if (sub_req->handler && !sub_req->content_type) {
- sub_req->content_type = CGI_MAGIC_TYPE;
- }
-
- if (sub_req->status != HTTP_OK || !sub_req->content_type) {
- ap_destroy_sub_req(sub_req);
- continue;
- }
-
- /* If it's a map file, we use that instead of the map
- * we're building...
- */
-
- if (((sub_req->content_type) &&
- !strcmp(sub_req->content_type, MAP_FILE_MAGIC_TYPE)) ||
- ((sub_req->handler) &&
- !strcmp(sub_req->handler, "type-map"))) {
-
- apr_dir_close(dirp);
- neg->avail_vars->nelts = 0;
- if (sub_req->status != HTTP_OK) {
- return sub_req->status;
- }
- return read_type_map(neg, sub_req);
- }
-
- /* Have reasonable variant --- gather notes. */
-
- mime_info.sub_req = sub_req;
- mime_info.file_name = apr_pstrdup(neg->pool, dirent.name);
- if (sub_req->content_encoding) {
- mime_info.content_encoding = sub_req->content_encoding;
- }
- if (sub_req->content_languages) {
- mime_info.content_languages = sub_req->content_languages;
- }
-
- get_entry(neg->pool, &accept_info, sub_req->content_type);
- set_mime_fields(&mime_info, &accept_info);
-
- new_var = apr_array_push(neg->avail_vars);
- memcpy(new_var, (void *) &mime_info, sizeof(var_rec));
-
- neg->count_multiviews_variants++;
-
- clean_var_rec(&mime_info);
- }
-
- apr_dir_close(dirp);
-
- set_vlist_validator(r, r);
-
- /* Sort the variants into a canonical order. The negotiation
- * result sometimes depends on the order of the variants. By
- * sorting the variants into a canonical order, rather than using
- * the order in which readdir() happens to return them, we ensure
- * that the negotiation result will be consistent over filesystem
- * backup/restores and over all mirror sites.
- */
-
- qsort((void *) neg->avail_vars->elts, neg->avail_vars->nelts,
- sizeof(var_rec), (int (*)(const void *, const void *)) variantsortf);
-
- return OK;
-}
-
-
-/*****************************************************************
- * And now for the code you've been waiting for... actually
- * finding a match to the client's requirements.
- */
-
-/* Matching MIME types ... the star/star and foo/star commenting conventions
- * are implemented here. (You know what I mean by star/star, but just
- * try mentioning those three characters in a C comment). Using strcmp()
- * is legit, because everything has already been smashed to lowercase.
- *
- * Note also that if we get an exact match on the media type, we update
- * level_matched for use in level_cmp below...
- *
- * We also give a value for mime_stars, which is used later. It should
- * be 1 for star/star, 2 for type/star and 3 for type/subtype.
- */
-
-static int mime_match(accept_rec *accept_r, var_rec *avail)
-{
- char *accept_type = accept_r->name;
- char *avail_type = avail->mime_type;
- int len = strlen(accept_type);
-
- if (accept_type[0] == '*') { /* Anything matches star/star */
- if (avail->mime_stars < 1) {
- avail->mime_stars = 1;
- }
- return 1;
- }
- else if ((accept_type[len - 1] == '*') &&
- !strncmp(accept_type, avail_type, len - 2)) {
- if (avail->mime_stars < 2) {
- avail->mime_stars = 2;
- }
- return 1;
- }
- else if (!strcmp(accept_type, avail_type)
- || (!strcmp(accept_type, "text/html")
- && (!strcmp(avail_type, INCLUDES_MAGIC_TYPE)
- || !strcmp(avail_type, INCLUDES_MAGIC_TYPE3)))) {
- if (accept_r->level >= avail->level) {
- avail->level_matched = avail->level;
- avail->mime_stars = 3;
- return 1;
- }
- }
-
- return OK;
-}
-
-/* This code implements a piece of the tie-breaking algorithm between
- * variants of equal quality. This piece is the treatment of variants
- * of the same base media type, but different levels. What we want to
- * return is the variant at the highest level that the client explicitly
- * claimed to accept.
- *
- * If all the variants available are at a higher level than that, or if
- * the client didn't say anything specific about this media type at all
- * and these variants just got in on a wildcard, we prefer the lowest
- * level, on grounds that that's the one that the client is least likely
- * to choke on.
- *
- * (This is all motivated by treatment of levels in HTML --- we only
- * want to give level 3 to browsers that explicitly ask for it; browsers
- * that don't, including HTTP/0.9 browsers that only get the implicit
- * "Accept: * / *" [space added to avoid confusing cpp --- no, that
- * syntax doesn't really work] should get HTML2 if available).
- *
- * (Note that this code only comes into play when we are choosing among
- * variants of equal quality, where the draft standard gives us a fair
- * bit of leeway about what to do. It ain't specified by the standard;
- * rather, it is a choice made by this server about what to do in cases
- * where the standard does not specify a unique course of action).
- */
-
-static int level_cmp(var_rec *var1, var_rec *var2)
-{
- /* Levels are only comparable between matching media types */
-
- if (var1->is_pseudo_html && !var2->is_pseudo_html) {
- return 0;
- }
-
- if (!var1->is_pseudo_html && strcmp(var1->mime_type, var2->mime_type)) {
- return 0;
- }
- /* The result of the above if statements is that, if we get to
- * here, both variants have the same mime_type or both are
- * pseudo-html.
- */
-
- /* Take highest level that matched, if either did match. */
-
- if (var1->level_matched > var2->level_matched) {
- return 1;
- }
- if (var1->level_matched < var2->level_matched) {
- return -1;
- }
-
- /* Neither matched. Take lowest level, if there's a difference. */
-
- if (var1->level < var2->level) {
- return 1;
- }
- if (var1->level > var2->level) {
- return -1;
- }
-
- /* Tied */
-
- return 0;
-}
-
-/* Finding languages. The main entry point is set_language_quality()
- * which is called for each variant. It sets two elements in the
- * variant record:
- * language_quality - the 'q' value of the 'best' matching language
- * from Accept-Language: header (HTTP/1.1)
- * lang_index - Pre HTTP/1.1 language priority, using
- * position of language on the Accept-Language:
- * header, if present, else LanguagePriority
- * directive order.
- *
- * When we do the variant checking for best variant, we use language
- * quality first, and if a tie, language_index next (this only applies
- * when _not_ using the RVSA/1.0 algorithm). If using the RVSA/1.0
- * algorithm, lang_index is never used.
- *
- * set_language_quality() calls find_lang_index() and find_default_index()
- * to set lang_index.
- */
-
-static int find_lang_index(apr_array_header_t *accept_langs, char *lang)
-{
- accept_rec *accs;
- int i;
-
- if (!lang || !accept_langs) {
- return -1;
- }
-
- accs = (accept_rec *) accept_langs->elts;
-
- for (i = 0; i < accept_langs->nelts; ++i) {
- if (!strncmp(lang, accs[i].name, strlen(accs[i].name))) {
- return i;
- }
- }
-
- return -1;
-}
-
-/* This function returns the priority of a given language
- * according to LanguagePriority. It is used in case of a tie
- * between several languages.
- */
-
-static int find_default_index(neg_dir_config *conf, char *lang)
-{
- apr_array_header_t *arr;
- int nelts;
- char **elts;
- int i;
-
- if (!lang) {
- return -1;
- }
-
- arr = conf->language_priority;
- nelts = arr->nelts;
- elts = (char **) arr->elts;
-
- for (i = 0; i < nelts; ++i) {
- if (!strcasecmp(elts[i], lang)) {
- return i;
- }
- }
-
- return -1;
-}
-
-/* set_default_lang_quality() sets the quality we apply to variants
- * which have no language assigned to them. If none of the variants
- * have a language, we are not negotiating on language, so all are
- * acceptable, and we set the default q value to 1.0. However if
- * some of the variants have languages, we set this default to 0.001.
- * The value of this default will be applied to all variants with
- * no explicit language -- which will have the effect of making them
- * acceptable, but only if no variants with an explicit language
- * are acceptable. The default q value set here is assigned to variants
- * with no language type in set_language_quality().
- *
- * Note that if using the RVSA/1.0 algorithm, we don't use this
- * fiddle.
- */
-
-static void set_default_lang_quality(negotiation_state *neg)
-{
- var_rec *avail_recs = (var_rec *) neg->avail_vars->elts;
- int j;
-
- if (!neg->dont_fiddle_headers) {
- for (j = 0; j < neg->avail_vars->nelts; ++j) {
- var_rec *variant = &avail_recs[j];
- if (variant->content_languages &&
- variant->content_languages->nelts) {
- neg->default_lang_quality = 0.001f;
- return;
- }
- }
- }
-
- neg->default_lang_quality = 1.0f;
-}
-
-/* Set the language_quality value in the variant record. Also
- * assigns lang_index for back-compat.
- *
- * To find the language_quality value, we look for the 'q' value
- * of the 'best' matching language on the Accept-Language
- * header. The 'best' match is the language on Accept-Language
- * header which matches the language of this variant either fully,
- * or as far as the prefix marker (-). If two or more languages
- * match, use the longest string from the Accept-Language header
- * (see HTTP/1.1 [14.4])
- *
- * When a variant has multiple languages, we find the 'best'
- * match for each variant language tag as above, then select the
- * one with the highest q value. Because both the accept-header
- * and variant can have multiple languages, we now have a hairy
- * loop-within-a-loop here.
- *
- * If the variant has no language and we have no Accept-Language
- * items, leave the quality at 1.0 and return.
- *
- * If the variant has no language, we use the default as set by
- * set_default_lang_quality() (1.0 if we are not negotiating on
- * language, 0.001 if we are).
- *
- * Following the setting of the language quality, we drop through to
- * set the old 'lang_index'. This is set based on either the order
- * of the languages on the Accept-Language header, or the
- * order on the LanguagePriority directive. This is only used
- * in the negotiation if the language qualities tie.
- */
-
-static void set_language_quality(negotiation_state *neg, var_rec *variant)
-{
- char *firstlang;
- int idx;
-
- if (!variant->content_languages || !variant->content_languages->nelts) {
- /* This variant has no content-language, so use the default
- * quality factor for variants with no content-language
- * (previously set by set_default_lang_quality()).
- * Leave the factor alone (it remains at 1.0) when we may not fiddle
- * with the headers.
- */
- if (!neg->dont_fiddle_headers) {
- variant->lang_quality = neg->default_lang_quality;
- }
- if (!neg->accept_langs) {
- return; /* no accept-language header */
- }
-
- }
- else {
- /* Variant has one (or more) languages. Look for the best
- * match. We do this by going through each language on the
- * variant description looking for a match on the
- * Accept-Language header. The best match is the longest
- * matching language on the header. The final result is the
- * best q value from all the languages on the variant
- * description.
- */
-
- if (!neg->accept_langs) {
- /* no accept-language header makes the variant indefinite */
- variant->definite = 0;
- }
- else { /* There is an accept-language with 0 or more items */
- accept_rec *accs = (accept_rec *) neg->accept_langs->elts;
- accept_rec *best = NULL, *star = NULL;
- accept_rec *bestthistag;
- char *lang, *p;
- float fiddle_q = 0.0f;
- int any_match_on_star = 0;
- int i, j;
- size_t alen, longest_lang_range_len;
-
- for (j = 0; j < variant->content_languages->nelts; ++j) {
- p = NULL;
- bestthistag = NULL;
- longest_lang_range_len = 0;
- alen = 0;
-
- /* lang is the variant's language-tag, which is the one
- * we are allowed to use the prefix of in HTTP/1.1
- */
- lang = ((char **) (variant->content_languages->elts))[j];
-
- /* now find the best (i.e. longest) matching
- * Accept-Language header language. We put the best match
- * for this tag in bestthistag. We cannot update the
- * overall best (based on q value) because the best match
- * for this tag is the longest language item on the accept
- * header, not necessarily the highest q.
- */
- for (i = 0; i < neg->accept_langs->nelts; ++i) {
- if (!strcmp(accs[i].name, "*")) {
- if (!star) {
- star = &accs[i];
- }
- continue;
- }
- /* Find language. We match if either the variant
- * language tag exactly matches the language range
- * from the accept header, or a prefix of the variant
- * language tag up to a '-' character matches the
- * whole of the language range in the Accept-Language
- * header. Note that HTTP/1.x allows any number of
- * '-' characters in a tag or range, currently only
- * tags with zero or one '-' characters are defined
- * for general use (see rfc1766).
- *
- * We only use language range in the Accept-Language
- * header the best match for the variant language tag
- * if it is longer than the previous best match.
- */
-
- alen = strlen(accs[i].name);
-
- if ((strlen(lang) >= alen) &&
- !strncmp(lang, accs[i].name, alen) &&
- ((lang[alen] == 0) || (lang[alen] == '-')) ) {
-
- if (alen > longest_lang_range_len) {
- longest_lang_range_len = alen;
- bestthistag = &accs[i];
- }
- }
-
- if (!bestthistag && !neg->dont_fiddle_headers) {
- /* The next bit is a fiddle. Some browsers might
- * be configured to send more specific language
- * ranges than desirable. For example, an
- * Accept-Language of en-US should never match
- * variants with languages en or en-GB. But US
- * English speakers might pick en-US as their
- * language choice. So this fiddle checks if the
- * language range has a prefix, and if so, it
- * matches variants which match that prefix with a
- * priority of 0.001. So a request for en-US would
- * match variants of types en and en-GB, but at
- * much lower priority than matches of en-US
- * directly, or of any other language listed on
- * the Accept-Language header. Note that this
- * fiddle does not handle multi-level prefixes.
- */
- if ((p = strchr(accs[i].name, '-'))) {
- int plen = p - accs[i].name;
-
- if (!strncmp(lang, accs[i].name, plen)) {
- fiddle_q = 0.001f;
- }
- }
- }
- }
- /* Finished looking at Accept-Language headers, the best
- * (longest) match is in bestthistag, or NULL if no match
- */
- if (!best ||
- (bestthistag && bestthistag->quality > best->quality)) {
- best = bestthistag;
- }
-
- /* See if the tag matches on a * in the Accept-Language
- * header. If so, record this fact for later use
- */
- if (!bestthistag && star) {
- any_match_on_star = 1;
- }
- }
-
- /* If one of the language tags of the variant matched on *, we
- * need to see if its q is better than that of any non-* match
- * on any other tag of the variant. If so the * match takes
- * precedence and the overall match is not definite.
- */
- if ( any_match_on_star &&
- ((best && star->quality > best->quality) ||
- (!best)) ) {
- best = star;
- variant->definite = 0;
- }
-
- variant->lang_quality = best ? best->quality : fiddle_q;
- }
- }
-
- /* Now set the old lang_index field. Since this is old
- * stuff anyway, don't bother with handling multiple languages
- * per variant, just use the first one assigned to it
- */
- idx = 0;
- if (variant->content_languages && variant->content_languages->nelts) {
- firstlang = ((char **) variant->content_languages->elts)[0];
- }
- else {
- firstlang = "";
- }
- if (!neg->accept_langs) { /* Client doesn't care */
- idx = find_default_index((neg_dir_config *) ap_get_module_config(
- neg->r->per_dir_config, &negotiation_module),
- firstlang);
- }
- else { /* Client has Accept-Language */
- idx = find_lang_index(neg->accept_langs, firstlang);
- }
- variant->lang_index = idx;
-
- return;
-}
-
-/* Determining the content length --- if the map didn't tell us,
- * we have to do a stat() and remember for next time.
- *
- * Grump. For Apache, even the first stat here may well be
- * redundant (for multiviews) with a stat() done by the sub_req
- * machinery. At some point, that ought to be fixed.
- */
-
-static long find_content_length(negotiation_state *neg, var_rec *variant)
-{
- apr_finfo_t statb;
-
- if (variant->bytes == 0) {
- char *fullname = ap_make_full_path(neg->pool, neg->dir_name,
- variant->file_name);
-
- if (apr_stat(&statb, fullname,
- APR_FINFO_SIZE, neg->pool) == APR_SUCCESS) {
- variant->bytes = statb.size;
- }
- }
-
- return variant->bytes;
-}
-
-/* For a given variant, find the best matching Accept: header
- * and assign the Accept: header's quality value to the
- * mime_type_quality field of the variant, for later use in
- * determining the best matching variant.
- */
-
-static void set_accept_quality(negotiation_state *neg, var_rec *variant)
-{
- int i;
- accept_rec *accept_recs;
- float q = 0.0f;
- int q_definite = 1;
-
- /* if no Accept: header, leave quality alone (will
- * remain at the default value of 1)
- *
- * XXX: This if is currently never true because of the effect of
- * maybe_add_default_accepts().
- */
- if (!neg->accepts) {
- if (variant->mime_type && *variant->mime_type)
- variant->definite = 0;
- return;
- }
-
- accept_recs = (accept_rec *) neg->accepts->elts;
-
- /*
- * Go through each of the ranges on the Accept: header,
- * looking for the 'best' match with this variant's
- * content-type. We use the best match's quality
- * value (from the Accept: header) for this variant's
- * mime_type_quality field.
- *
- * The best match is determined like this:
- * type/type is better than type/ * is better than * / *
- * if match is type/type, use the level mime param if available
- */
- for (i = 0; i < neg->accepts->nelts; ++i) {
-
- accept_rec *type = &accept_recs[i];
- int prev_mime_stars;
-
- prev_mime_stars = variant->mime_stars;
-
- if (!mime_match(type, variant)) {
- continue; /* didn't match the content type at all */
- }
- else {
- /* did match - see if there were less or more stars than
- * in previous match
- */
- if (prev_mime_stars == variant->mime_stars) {
- continue; /* more stars => not as good a match */
- }
- }
-
- /* If we are allowed to mess with the q-values
- * and have no explicit q= parameters in the accept header,
- * make wildcards very low, so we have a low chance
- * of ending up with them if there's something better.
- */
-
- if (!neg->dont_fiddle_headers && !neg->accept_q &&
- variant->mime_stars == 1) {
- q = 0.01f;
- }
- else if (!neg->dont_fiddle_headers && !neg->accept_q &&
- variant->mime_stars == 2) {
- q = 0.02f;
- }
- else {
- q = type->quality;
- }
-
- q_definite = (variant->mime_stars == 3);
- }
- variant->mime_type_quality = q;
- variant->definite = variant->definite && q_definite;
-
-}
-
-/* For a given variant, find the 'q' value of the charset given
- * on the Accept-Charset line. If no charsets are listed,
- * assume value of '1'.
- */
-static void set_charset_quality(negotiation_state *neg, var_rec *variant)
-{
- int i;
- accept_rec *accept_recs;
- char *charset = variant->content_charset;
- accept_rec *star = NULL;
-
- /* if no Accept-Charset: header, leave quality alone (will
- * remain at the default value of 1)
- */
- if (!neg->accept_charsets) {
- if (charset && *charset)
- variant->definite = 0;
- return;
- }
-
- accept_recs = (accept_rec *) neg->accept_charsets->elts;
-
- if (charset == NULL || !*charset) {
- /* Charset of variant not known */
-
- /* if not a text / * type, leave quality alone */
- if (!(!strncmp(variant->mime_type, "text/", 5)
- || !strcmp(variant->mime_type, INCLUDES_MAGIC_TYPE)
- || !strcmp(variant->mime_type, INCLUDES_MAGIC_TYPE3)
- ))
- return;
-
- /* Don't go guessing if we are in strict header mode,
- * e.g. when running the rvsa, as any guess won't be reflected
- * in the variant list or content-location headers.
- */
- if (neg->dont_fiddle_headers)
- return;
-
- charset = "iso-8859-1"; /* The default charset for HTTP text types */
- }
-
- /*
- * Go through each of the items on the Accept-Charset header,
- * looking for a match with this variant's charset. If none
- * match, charset is unacceptable, so set quality to 0.
- */
- for (i = 0; i < neg->accept_charsets->nelts; ++i) {
-
- accept_rec *type = &accept_recs[i];
-
- if (!strcmp(type->name, charset)) {
- variant->charset_quality = type->quality;
- return;
- }
- else if (strcmp(type->name, "*") == 0) {
- star = type;
- }
- }
- /* No explicit match */
- if (star) {
- variant->charset_quality = star->quality;
- variant->definite = 0;
- return;
- }
- /* If this variant is in charset iso-8859-1, the default is 1.0 */
- if (strcmp(charset, "iso-8859-1") == 0) {
- variant->charset_quality = 1.0f;
- }
- else {
- variant->charset_quality = 0.0f;
- }
-}
-
-
-/* is_identity_encoding is included for back-compat, but does anyone
- * use 7bit, 8bin or binary in their var files??
- */
-
-static int is_identity_encoding(const char *enc)
-{
- return (!enc || !enc[0] || !strcmp(enc, "7bit") || !strcmp(enc, "8bit")
- || !strcmp(enc, "binary"));
-}
-
-/*
- * set_encoding_quality determines whether the encoding for a particular
- * variant is acceptable for the user-agent.
- *
- * The rules for encoding are that if the user-agent does not supply
- * any Accept-Encoding header, then all encodings are allowed but a
- * variant with no encoding should be preferred.
- * If there is an empty Accept-Encoding header, then no encodings are
- * acceptable. If there is a non-empty Accept-Encoding header, then
- * any of the listed encodings are acceptable, as well as no encoding
- * unless the "identity" encoding is specifically excluded.
- */
-static void set_encoding_quality(negotiation_state *neg, var_rec *variant)
-{
- accept_rec *accept_recs;
- const char *enc = variant->content_encoding;
- accept_rec *star = NULL;
- float value_if_not_found = 0.0f;
- int i;
-
- if (!neg->accept_encodings) {
- /* We had no Accept-Encoding header, assume that all
- * encodings are acceptable with a low quality,
- * but we prefer no encoding if available.
- */
- if (!enc || is_identity_encoding(enc))
- variant->encoding_quality = 1.0f;
- else
- variant->encoding_quality = 0.5f;
-
- return;
- }
-
- if (!enc || is_identity_encoding(enc)) {
- enc = "identity";
- value_if_not_found = 0.0001f;
- }
-
- accept_recs = (accept_rec *) neg->accept_encodings->elts;
-
- /* Go through each of the encodings on the Accept-Encoding: header,
- * looking for a match with our encoding. x- prefixes are ignored.
- */
- if (enc[0] == 'x' && enc[1] == '-') {
- enc += 2;
- }
- for (i = 0; i < neg->accept_encodings->nelts; ++i) {
-
- char *name = accept_recs[i].name;
-
- if (name[0] == 'x' && name[1] == '-') {
- name += 2;
- }
-
- if (!strcmp(name, enc)) {
- variant->encoding_quality = accept_recs[i].quality;
- return;
- }
-
- if (strcmp(name, "*") == 0) {
- star = &accept_recs[i];
- }
-
- }
- /* No explicit match */
- if (star) {
- variant->encoding_quality = star->quality;
- return;
- }
-
- /* Encoding not found on Accept-Encoding: header, so it is
- * _not_ acceptable unless it is the identity (no encoding)
- */
- variant->encoding_quality = value_if_not_found;
-}
-
-/*************************************************************
- * Possible results of the variant selection algorithm
- */
-enum algorithm_results {
- alg_choice = 1, /* choose variant */
- alg_list /* list variants */
-};
-
-/* Below is the 'best_match' function. It returns an int, which has
- * one of the two values alg_choice or alg_list, which give the result
- * of the variant selection algorithm. alg_list means that no best
- * variant was found by the algorithm, alg_choice means that a best
- * variant was found and should be returned. The list/choice
- * terminology comes from TCN (rfc2295), but is used in a more generic
- * way here. The best variant is returned in *pbest. best_match has
- * two possible algorithms for determining the best variant: the
- * RVSA/1.0 algorithm (from RFC2296), and the standard Apache
- * algorithm. These are split out into separate functions
- * (is_variant_better_rvsa() and is_variant_better()). Selection of
- * one is through the neg->use_rvsa flag.
- *
- * The call to best_match also creates full information, including
- * language, charset, etc quality for _every_ variant. This is needed
- * for generating a correct Vary header, and can be used for the
- * Alternates header, the human-readable list responses and 406 errors.
- */
-
-/* Firstly, the RVSA/1.0 (HTTP Remote Variant Selection Algorithm
- * v1.0) from rfc2296. This is the algorithm that goes together with
- * transparent content negotiation (TCN).
- */
-static int is_variant_better_rvsa(negotiation_state *neg, var_rec *variant,
- var_rec *best, float *p_bestq)
-{
- float bestq = *p_bestq, q;
-
- /* TCN does not cover negotiation on content-encoding. For now,
- * we ignore the encoding unless it was explicitly excluded.
- */
- if (variant->encoding_quality == 0.0f)
- return 0;
-
- q = variant->mime_type_quality *
- variant->source_quality *
- variant->charset_quality *
- variant->lang_quality;
-
- /* RFC 2296 calls for the result to be rounded to 5 decimal places,
- * but we don't do that because it serves no useful purpose other
- * than to ensure that a remote algorithm operates on the same
- * precision as ours. That is silly, since what we obviously want
- * is for the algorithm to operate on the best available precision
- * regardless of who runs it. Since the above calculation may
- * result in significant variance at 1e-12, rounding would be bogus.
- */
-
-#ifdef NEG_DEBUG
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "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",
- (variant->file_name ? variant->file_name : ""),
- (variant->mime_type ? variant->mime_type : ""),
- (variant->content_languages
- ? apr_array_pstrcat(neg->pool, variant->content_languages, ',')
- : ""),
- variant->source_quality,
- variant->mime_type_quality,
- variant->lang_quality,
- variant->charset_quality,
- variant->encoding_quality,
- q,
- variant->definite);
-#endif
-
- if (q <= 0.0f) {
- return 0;
- }
- if (q > bestq) {
- *p_bestq = q;
- return 1;
- }
- if (q == bestq) {
- /* If the best variant's encoding is of lesser quality than
- * this variant, then we prefer this variant
- */
- if (variant->encoding_quality > best->encoding_quality) {
- *p_bestq = q;
- return 1;
- }
- }
- return 0;
-}
-
-/* Negotiation algorithm as used by previous versions of Apache
- * (just about).
- */
-
-static int is_variant_better(negotiation_state *neg, var_rec *variant,
- var_rec *best, float *p_bestq)
-{
- float bestq = *p_bestq, q;
- int levcmp;
-
- /* For non-transparent negotiation, server can choose how
- * to handle the negotiation. We'll use the following in
- * order: content-type, language, content-type level, charset,
- * content encoding, content length.
- *
- * For each check, we have three possible outcomes:
- * This variant is worse than current best: return 0
- * This variant is better than the current best:
- * assign this variant's q to *p_bestq, and return 1
- * This variant is just as desirable as the current best:
- * drop through to the next test.
- *
- * This code is written in this long-winded way to allow future
- * customisation, either by the addition of additional
- * checks, or to allow the order of the checks to be determined
- * by configuration options (e.g. we might prefer to check
- * language quality _before_ content type).
- */
-
- /* First though, eliminate this variant if it is not
- * acceptable by type, charset, encoding or language.
- */
-
-#ifdef NEG_DEBUG
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Variant: file=%s type=%s lang=%s sourceq=%1.3f "
- "mimeq=%1.3f langq=%1.3f langidx=%d charq=%1.3f encq=%1.3f ",
- (variant->file_name ? variant->file_name : ""),
- (variant->mime_type ? variant->mime_type : ""),
- (variant->content_languages
- ? apr_array_pstrcat(neg->pool, variant->content_languages, ',')
- : ""),
- variant->source_quality,
- variant->mime_type_quality,
- variant->lang_quality,
- variant->lang_index,
- variant->charset_quality,
- variant->encoding_quality);
-#endif
-
- if (variant->encoding_quality == 0.0f ||
- variant->lang_quality == 0.0f ||
- variant->source_quality == 0.0f ||
- variant->charset_quality == 0.0f ||
- variant->mime_type_quality == 0.0f) {
- return 0; /* don't consider unacceptables */
- }
-
- q = variant->mime_type_quality * variant->source_quality;
- if (q == 0.0 || q < bestq) {
- return 0;
- }
- if (q > bestq || !best) {
- *p_bestq = q;
- return 1;
- }
-
- /* language */
- if (variant->lang_quality < best->lang_quality) {
- return 0;
- }
- if (variant->lang_quality > best->lang_quality) {
- *p_bestq = q;
- return 1;
- }
-
- /* if language qualities were equal, try the LanguagePriority stuff */
- if (best->lang_index != -1 &&
- (variant->lang_index == -1 || variant->lang_index > best->lang_index)) {
- return 0;
- }
- if (variant->lang_index != -1 &&
- (best->lang_index == -1 || variant->lang_index < best->lang_index)) {
- *p_bestq = q;
- return 1;
- }
-
- /* content-type level (sometimes used with text/html, though we
- * support it on other types too)
- */
- levcmp = level_cmp(variant, best);
- if (levcmp == -1) {
- return 0;
- }
- if (levcmp == 1) {
- *p_bestq = q;
- return 1;
- }
-
- /* charset */
- if (variant->charset_quality < best->charset_quality) {
- return 0;
- }
- /* If the best variant's charset is ISO-8859-1 and this variant has
- * the same charset quality, then we prefer this variant
- */
-
- if (variant->charset_quality > best->charset_quality ||
- ((variant->content_charset != NULL &&
- *variant->content_charset != '\0' &&
- strcmp(variant->content_charset, "iso-8859-1") != 0) &&
- (best->content_charset == NULL ||
- *best->content_charset == '\0' ||
- strcmp(best->content_charset, "iso-8859-1") == 0))) {
- *p_bestq = q;
- return 1;
- }
-
- /* Prefer the highest value for encoding_quality.
- */
- if (variant->encoding_quality < best->encoding_quality) {
- return 0;
- }
- if (variant->encoding_quality > best->encoding_quality) {
- *p_bestq = q;
- return 1;
- }
-
- /* content length if all else equal */
- if (find_content_length(neg, variant) >= find_content_length(neg, best)) {
- return 0;
- }
-
- /* ok, to get here means every thing turned out equal, except
- * we have a shorter content length, so use this variant
- */
- *p_bestq = q;
- return 1;
-}
-
-static int best_match(negotiation_state *neg, var_rec **pbest)
-{
- int j;
- var_rec *best = NULL;
- float bestq = 0.0f;
- enum algorithm_results algorithm_result;
-
- var_rec *avail_recs = (var_rec *) neg->avail_vars->elts;
-
- set_default_lang_quality(neg);
-
- /*
- * Find the 'best' variant
- */
-
- for (j = 0; j < neg->avail_vars->nelts; ++j) {
- var_rec *variant = &avail_recs[j];
-
- /* Find all the relevant 'quality' values from the
- * Accept... headers, and store in the variant. This also
- * prepares for sending an Alternates header etc so we need to
- * do it even if we do not actually plan to find a best
- * variant.
- */
- set_accept_quality(neg, variant);
- set_language_quality(neg, variant);
- set_encoding_quality(neg, variant);
- set_charset_quality(neg, variant);
-
- /* Only do variant selection if we may actually choose a
- * variant for the client
- */
- if (neg->may_choose) {
-
- /* Now find out if this variant is better than the current
- * best, either using the RVSA/1.0 algorithm, or Apache's
- * internal server-driven algorithm. Presumably other
- * server-driven algorithms are possible, and could be
- * implemented here.
- */
-
- if (neg->use_rvsa) {
- if (is_variant_better_rvsa(neg, variant, best, &bestq)) {
- best = variant;
- }
- }
- else {
- if (is_variant_better(neg, variant, best, &bestq)) {
- best = variant;
- }
- }
- }
- }
-
- /* We now either have a best variant, or no best variant */
-
- if (neg->use_rvsa) {
- /* calculate result for RVSA/1.0 algorithm:
- * only a choice response if the best variant has q>0
- * and is definite
- */
- algorithm_result = (best && best->definite) && (bestq > 0) ?
- alg_choice : alg_list;
- }
- else {
- /* calculate result for Apache negotiation algorithm */
- algorithm_result = bestq > 0 ? alg_choice : alg_list;
- }
-
- /* Returning a choice response with a non-neighboring variant is a
- * protocol security error in TCN (see rfc2295). We do *not*
- * verify here that the variant and URI are neighbors, even though
- * we may return alg_choice. We depend on the environment (the
- * caller) to only declare the resource transparently negotiable if
- * all variants are neighbors.
- */
- *pbest = best;
- return algorithm_result;
-}
-
-/* Sets response headers for a negotiated response.
- * neg->is_transparent determines whether a transparently negotiated
- * response or a plain `server driven negotiation' response is
- * created. Applicable headers are Alternates, Vary, and TCN.
- *
- * The Vary header we create is sometimes longer than is required for
- * the correct caching of negotiated results by HTTP/1.1 caches. For
- * example if we have 3 variants x.html, x.ps.en and x.ps.nl, and if
- * the Accept: header assigns a 0 quality to .ps, then the results of
- * the two server-side negotiation algorithms we currently implement
- * will never depend on Accept-Language so we could return `Vary:
- * negotiate, accept' instead of the longer 'Vary: negotiate, accept,
- * accept-language' which the code below will return. A routine for
- * computing the exact minimal Vary header would be a huge pain to code
- * and maintain though, especially because we need to take all possible
- * twiddles in the server-side negotiation algorithms into account.
- */
-static void set_neg_headers(request_rec *r, negotiation_state *neg,
- int alg_result)
-{
- apr_table_t *hdrs;
- var_rec *avail_recs = (var_rec *) neg->avail_vars->elts;
- const char *sample_type = NULL;
- const char *sample_language = NULL;
- const char *sample_encoding = NULL;
- const char *sample_charset = NULL;
- char *lang;
- char *qstr;
- char *lenstr;
- long len;
- apr_array_header_t *arr;
- int max_vlist_array = (neg->avail_vars->nelts * 21);
- int first_variant = 1;
- int vary_by_type = 0;
- int vary_by_language = 0;
- int vary_by_charset = 0;
- int vary_by_encoding = 0;
- int j;
-
- /* In order to avoid O(n^2) memory copies in building Alternates,
- * we preallocate a apr_table_t 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 = apr_array_make(r->pool, max_vlist_array, sizeof(char *));
- else
- arr = NULL;
-
- /* Put headers into err_headers_out, since send_http_header()
- * outputs both headers_out and err_headers_out.
- */
- hdrs = r->err_headers_out;
-
- for (j = 0; j < neg->avail_vars->nelts; ++j) {
- var_rec *variant = &avail_recs[j];
-
- if (variant->content_languages && variant->content_languages->nelts) {
- lang = apr_array_pstrcat(r->pool, variant->content_languages, ',');
- }
- else {
- lang = NULL;
- }
-
- /* Calculate Vary by looking for any difference between variants */
-
- if (first_variant) {
- sample_type = variant->mime_type;
- sample_charset = variant->content_charset;
- sample_language = lang;
- sample_encoding = variant->content_encoding;
- }
- else {
- if (!vary_by_type &&
- strcmp(sample_type ? sample_type : "",
- variant->mime_type ? variant->mime_type : "")) {
- vary_by_type = 1;
- }
- if (!vary_by_charset &&
- strcmp(sample_charset ? sample_charset : "",
- variant->content_charset ?
- variant->content_charset : "")) {
- vary_by_charset = 1;
- }
- if (!vary_by_language &&
- strcmp(sample_language ? sample_language : "",
- lang ? lang : "")) {
- vary_by_language = 1;
- }
- if (!vary_by_encoding &&
- strcmp(sample_encoding ? sample_encoding : "",
- variant->content_encoding ?
- variant->content_encoding : "")) {
- vary_by_encoding = 1;
- }
- }
- first_variant = 0;
-
- if (!neg->send_alternates)
- continue;
-
- /* Generate the string components for this Alternates entry */
-
- *((const char **) apr_array_push(arr)) = "{\"";
- *((const char **) apr_array_push(arr)) = variant->file_name;
- *((const char **) apr_array_push(arr)) = "\" ";
-
- qstr = (char *) apr_palloc(r->pool, 6);
- apr_snprintf(qstr, 6, "%1.3f", variant->source_quality);
-
- /* Strip trailing zeros (saves those valuable network bytes) */
- if (qstr[4] == '0') {
- qstr[4] = '\0';
- if (qstr[3] == '0') {
- qstr[3] = '\0';
- if (qstr[2] == '0') {
- qstr[1] = '\0';
- }
- }
- }
- *((const char **) apr_array_push(arr)) = qstr;
-
- if (variant->mime_type && *variant->mime_type) {
- *((const char **) apr_array_push(arr)) = " {type ";
- *((const char **) apr_array_push(arr)) = variant->mime_type;
- *((const char **) apr_array_push(arr)) = "}";
- }
- if (variant->content_charset && *variant->content_charset) {
- *((const char **) apr_array_push(arr)) = " {charset ";
- *((const char **) apr_array_push(arr)) = variant->content_charset;
- *((const char **) apr_array_push(arr)) = "}";
- }
- if (lang) {
- *((const char **) apr_array_push(arr)) = " {language ";
- *((const char **) apr_array_push(arr)) = lang;
- *((const char **) apr_array_push(arr)) = "}";
- }
- if (variant->content_encoding && *variant->content_encoding) {
- /* Strictly speaking, this is non-standard, but so is TCN */
-
- *((const char **) apr_array_push(arr)) = " {encoding ";
- *((const char **) apr_array_push(arr)) = variant->content_encoding;
- *((const char **) apr_array_push(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 *) apr_palloc(r->pool, 22);
- apr_snprintf(lenstr, 22, "%ld", len);
- *((const char **) apr_array_push(arr)) = " {length ";
- *((const char **) apr_array_push(arr)) = lenstr;
- *((const char **) apr_array_push(arr)) = "}";
- }
-
- *((const char **) apr_array_push(arr)) = "}";
- *((const char **) apr_array_push(arr)) = ", "; /* trimmed below */
- }
-
- if (neg->send_alternates && neg->avail_vars->nelts) {
- arr->nelts--; /* remove last comma */
- apr_table_mergen(hdrs, "Alternates",
- apr_array_pstrcat(r->pool, arr, '\0'));
- }
-
- if (neg->is_transparent || vary_by_type || vary_by_language ||
- vary_by_language || vary_by_charset || vary_by_encoding) {
-
- apr_table_mergen(hdrs, "Vary", 2 + apr_pstrcat(r->pool,
- neg->is_transparent ? ", negotiate" : "",
- vary_by_type ? ", accept" : "",
- vary_by_language ? ", accept-language" : "",
- vary_by_charset ? ", accept-charset" : "",
- vary_by_encoding ? ", accept-encoding" : "", NULL));
- }
-
- if (neg->is_transparent) { /* Create TCN response header */
- apr_table_setn(hdrs, "TCN",
- alg_result == alg_list ? "list" : "choice");
- }
-}
-
-/**********************************************************************
- *
- * Return an HTML list of variants. This is output as part of the
- * choice response or 406 status body.
- */
-
-static char *make_variant_list(request_rec *r, negotiation_state *neg)
-{
- apr_array_header_t *arr;
- int i;
- int max_vlist_array = (neg->avail_vars->nelts * 15) + 2;
-
- /* In order to avoid O(n^2) memory copies in building the list,
- * we preallocate a apr_table_t with the maximum substrings possible,
- * fill it with the variant list, and then concatenate the entire array.
- */
- arr = apr_array_make(r->pool, max_vlist_array, sizeof(char *));
-
- *((const char **) apr_array_push(arr)) = "Available variants:\n<ul>\n";
-
- for (i = 0; i < neg->avail_vars->nelts; ++i) {
- var_rec *variant = &((var_rec *) neg->avail_vars->elts)[i];
- char *filename = variant->file_name ? variant->file_name : "";
- apr_array_header_t *languages = variant->content_languages;
- char *description = variant->description ? variant->description : "";
-
- /* The format isn't very neat, and it would be nice to make
- * the tags human readable (eg replace 'language en' with 'English').
- * Note that if you change the number of substrings pushed, you also
- * need to change the calculation of max_vlist_array above.
- */
- *((const char **) apr_array_push(arr)) = "<li><a href=\"";
- *((const char **) apr_array_push(arr)) = filename;
- *((const char **) apr_array_push(arr)) = "\">";
- *((const char **) apr_array_push(arr)) = filename;
- *((const char **) apr_array_push(arr)) = "</a> ";
- *((const char **) apr_array_push(arr)) = description;
-
- if (variant->mime_type && *variant->mime_type) {
- *((const char **) apr_array_push(arr)) = ", type ";
- *((const char **) apr_array_push(arr)) = variant->mime_type;
- }
- if (languages && languages->nelts) {
- *((const char **) apr_array_push(arr)) = ", language ";
- *((const char **) apr_array_push(arr)) = apr_array_pstrcat(r->pool,
- languages, ',');
- }
- if (variant->content_charset && *variant->content_charset) {
- *((const char **) apr_array_push(arr)) = ", charset ";
- *((const char **) apr_array_push(arr)) = variant->content_charset;
- }
- if (variant->content_encoding) {
- *((const char **) apr_array_push(arr)) = ", encoding ";
- *((const char **) apr_array_push(arr)) = variant->content_encoding;
- }
- *((const char **) apr_array_push(arr)) = "\n";
- }
- *((const char **) apr_array_push(arr)) = "</ul>\n";
-
- return apr_array_pstrcat(r->pool, arr, '\0');
-}
-
-static void store_variant_list(request_rec *r, negotiation_state *neg)
-{
- if (r->main == NULL) {
- apr_table_setn(r->notes, "variant-list", make_variant_list(r, neg));
- }
- else {
- apr_table_setn(r->main->notes, "variant-list",
- make_variant_list(r->main, neg));
- }
-}
-
-/* Called if we got a "Choice" response from the variant selection algorithm.
- * It checks the result of the chosen variant to see if it
- * is itself negotiated (if so, return error HTTP_VARIANT_ALSO_VARIES).
- * Otherwise, add the appropriate headers to the current response.
- */
-
-static int setup_choice_response(request_rec *r, negotiation_state *neg,
- var_rec *variant)
-{
- request_rec *sub_req;
- const char *sub_vary;
-
- if (!variant->sub_req) {
- int status;
-
- sub_req = ap_sub_req_lookup_file(variant->file_name, r, NULL);
- status = sub_req->status;
-
- if (status != HTTP_OK &&
- !apr_table_get(sub_req->err_headers_out, "TCN")) {
- ap_destroy_sub_req(sub_req);
- return status;
- }
- variant->sub_req = sub_req;
- }
- else {
- sub_req = variant->sub_req;
- }
-
- /* The variant selection algorithm told us to return a "Choice"
- * response. This is the normal variant response, with
- * some extra headers. First, ensure that the chosen
- * variant did or will not itself engage in transparent negotiation.
- * If not, set the appropriate headers, and fall through to
- * the normal variant handling
- */
-
- /* This catches the error that a transparent type map selects a
- * transparent multiviews resource as the best variant.
- *
- * XXX: We do not signal an error if a transparent type map
- * selects a _non_transparent multiviews resource as the best
- * variant, because we can generate a legal negotiation response
- * in this case. In this case, the vlist_validator of the
- * nontransparent subrequest will be lost however. This could
- * lead to cases in which a change in the set of variants or the
- * negotiation algorithm of the nontransparent resource is never
- * propagated up to a HTTP/1.1 cache which interprets Vary. To be
- * completely on the safe side we should return HTTP_VARIANT_ALSO_VARIES
- * for this type of recursive negotiation too.
- */
- if (neg->is_transparent &&
- apr_table_get(sub_req->err_headers_out, "TCN")) {
- return HTTP_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 HTTP_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 = apr_table_get(sub_req->err_headers_out, "Vary")) != NULL) {
- apr_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.
- */
- apr_table_setn(r->err_headers_out, "Vary", sub_vary);
- apr_table_unset(sub_req->err_headers_out, "Vary");
- }
-
- apr_table_setn(r->err_headers_out, "Content-Location",
- apr_pstrdup(r->pool, variant->file_name));
-
- set_neg_headers(r, neg, alg_choice); /* add Alternates and Vary */
-
- /* Still to do by caller: add Expires */
-
- return 0;
-}
-
-/****************************************************************
- *
- * Executive...
- */
-
-static int do_negotiation(request_rec *r, negotiation_state *neg,
- var_rec **bestp, int prefer_scripts)
-{
- var_rec *avail_recs = (var_rec *) neg->avail_vars->elts;
- int alg_result; /* result of variant selection algorithm */
- int res;
- int j;
-
- /* Decide if resource is transparently negotiable */
-
- /* GET or HEAD? (HEAD has same method number as GET) */
- if (r->method_number == M_GET) {
-
- /* maybe this should be configurable, see also the comment
- * about recursive type maps in setup_choice_response()
- */
- neg->is_transparent = 1;
-
- /* We can't be transparent if we are a map file in the middle
- * of the request URI.
- */
- if (r->path_info && *r->path_info)
- neg->is_transparent = 0;
-
- for (j = 0; j < neg->avail_vars->nelts; ++j) {
- var_rec *variant = &avail_recs[j];
-
- /* We can't be transparent, because of internal
- * assumptions in best_match(), if there is a
- * non-neighboring variant. We can have a non-neighboring
- * variant when processing a type map.
- */
- if (strchr(variant->file_name, '/'))
- neg->is_transparent = 0;
- }
- }
-
- if (neg->is_transparent) {
- parse_negotiate_header(r, neg);
- }
- else { /* configure negotiation on non-transparent resource */
- neg->may_choose = 1;
- }
-
- maybe_add_default_accepts(neg, prefer_scripts);
-
- alg_result = best_match(neg, bestp);
-
- /* alg_result is one of
- * alg_choice: a best variant is chosen
- * alg_list: no best variant is chosen
- */
-
- if (alg_result == alg_list) {
- /* send a list response or HTTP_NOT_ACCEPTABLE error response */
-
- neg->send_alternates = 1; /* always include Alternates header */
- set_neg_headers(r, neg, alg_result);
- store_variant_list(r, neg);
-
- if (neg->is_transparent && neg->ua_supports_trans) {
- /* XXX todo: expires? cachability? */
-
- /* Some HTTP/1.0 clients are known to choke when they get
- * a 300 (multiple choices) response without a Location
- * header. However the 300 code response we are are about
- * to generate will only reach 1.0 clients which support
- * transparent negotiation, and they should be OK. The
- * response should never reach older 1.0 clients, even if
- * we have CacheNegotiatedDocs enabled, because no 1.0
- * proxy cache (we know of) will cache and return 300
- * responses (they certainly won't if they conform to the
- * HTTP/1.0 specification).
- */
- return HTTP_MULTIPLE_CHOICES;
- }
-
- if (!*bestp) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "no acceptable variant: %s", r->filename);
- return HTTP_NOT_ACCEPTABLE;
- }
- }
-
- /* Variant selection chose a variant */
-
- /* XXX todo: merge the two cases in the if statement below */
- if (neg->is_transparent) {
-
- if ((res = setup_choice_response(r, neg, *bestp)) != 0) {
- return res; /* return if error */
- }
- }
- else {
- set_neg_headers(r, neg, alg_result);
- }
-
- /* Make sure caching works - Vary should handle HTTP/1.1, but for
- * HTTP/1.0, we can't allow caching at all.
- */
-
- /* XXX: Note that we only set r->no_cache to 1, which causes
- * Expires: <now> to be added, when responding to a HTTP/1.0
- * client. If we return the response to a 1.1 client, we do not
- * add Expires <now>, because doing so would degrade 1.1 cache
- * performance by preventing re-use of the response without prior
- * revalidation. On the other hand, if the 1.1 client is a proxy
- * which was itself contacted by a 1.0 client, or a proxy cache
- * which can be contacted later by 1.0 clients, then we currently
- * rely on this 1.1 proxy to add the Expires: <now> when it
- * forwards the response.
- *
- * XXX: TODO: Find out if the 1.1 spec requires proxies and
- * tunnels to add Expires: <now> when forwarding the response to
- * 1.0 clients. I (kh) recall it is rather vague on this point.
- * Testing actual 1.1 proxy implementations would also be nice. If
- * Expires: <now> is not added by proxies then we need to always
- * include Expires: <now> ourselves to ensure correct caching, but
- * this would degrade HTTP/1.1 cache efficiency unless we also add
- * Cache-Control: max-age=N, which we currently don't.
- *
- * Roy: No, we are not going to screw over HTTP future just to
- * ensure that people who can't be bothered to upgrade their
- * clients will always receive perfect server-side negotiation.
- * Hell, those clients are sending bogus accept headers anyway.
- *
- * Manual setting of cache-control/expires always overrides this
- * automated kluge, on purpose.
- */
-
- if ((!do_cache_negotiated_docs(r->server)
- && (r->proto_num < HTTP_VERSION(1,1)))
- && neg->count_multiviews_variants != 1) {
- r->no_cache = 1;
- }
-
- return OK;
-}
-
-static int handle_map_file(request_rec *r)
-{
- negotiation_state *neg;
- var_rec *best;
- int res;
- char *udir;
-
- if(strcmp(r->handler,MAP_FILE_MAGIC_TYPE) && strcmp(r->handler,"type-map"))
- return DECLINED;
-
- neg = parse_accept_headers(r);
- if ((res = read_type_map(neg, r))) {
- return res;
- }
-
- res = do_negotiation(r, neg, &best, 0);
- if (res != 0) return res;
-
- if (r->path_info && *r->path_info) {
- r->uri[ap_find_path_info(r->uri, r->path_info)] = '\0';
- }
- udir = ap_make_dirstr_parent(r->pool, r->uri);
- udir = ap_escape_uri(r->pool, udir);
- ap_internal_redirect(apr_pstrcat(r->pool, udir, best->file_name,
- r->path_info, NULL), r);
- return OK;
-}
-
-static int handle_multi(request_rec *r)
-{
- negotiation_state *neg;
- var_rec *best, *avail_recs;
- request_rec *sub_req;
- int res;
- int j;
-
- if (r->finfo.filetype != 0 || !(ap_allow_options(r) & OPT_MULTI)) {
- return DECLINED;
- }
-
- neg = parse_accept_headers(r);
-
- if ((res = read_types_multi(neg))) {
- return_from_multi:
- /* free all allocated memory from subrequests */
- avail_recs = (var_rec *) neg->avail_vars->elts;
- for (j = 0; j < neg->avail_vars->nelts; ++j) {
- var_rec *variant = &avail_recs[j];
- if (variant->sub_req) {
- ap_destroy_sub_req(variant->sub_req);
- }
- }
- return res;
- }
- if (neg->avail_vars->nelts == 0) {
- return DECLINED;
- }
-
- res = do_negotiation(r, neg, &best,
- (r->method_number != M_GET) || r->args ||
- (r->path_info && *r->path_info));
- if (res != 0)
- goto return_from_multi;
-
- if (!(sub_req = best->sub_req)) {
- /* We got this out of a map file, so we don't actually have
- * a sub_req structure yet. Get one now.
- */
-
- sub_req = ap_sub_req_lookup_file(best->file_name, r, NULL);
- if (sub_req->status != HTTP_OK) {
- res = sub_req->status;
- ap_destroy_sub_req(sub_req);
- goto return_from_multi;
- }
- }
-
- /* BLECH --- don't multi-resolve non-ordinary files */
-
- if (sub_req->finfo.filetype != APR_REG) {
- res = HTTP_NOT_FOUND;
- goto return_from_multi;
- }
-
- /* Otherwise, use it. */
-
- /* now do a "fast redirect" ... promote the sub_req into the main req */
- /* We need to tell POOL_DEBUG that we're guaranteeing that sub_req->pool
- * will exist as long as r->pool. Otherwise we run into troubles because
- * some values in this request will be allocated in r->pool, and others in
- * sub_req->pool.
- */
- apr_pool_join(r->pool, sub_req->pool);
- r->mtime = 0; /* reset etag info for subrequest */
- r->filename = sub_req->filename;
- r->handler = sub_req->handler;
- r->content_type = sub_req->content_type;
- r->content_encoding = sub_req->content_encoding;
- r->content_languages = sub_req->content_languages;
- r->content_language = sub_req->content_language;
- r->finfo = sub_req->finfo;
- r->per_dir_config = sub_req->per_dir_config;
- /* copy output headers from subrequest, but leave negotiation headers */
- r->notes = apr_table_overlay(r->pool, sub_req->notes, r->notes);
- r->headers_out = apr_table_overlay(r->pool, sub_req->headers_out,
- r->headers_out);
- r->err_headers_out = apr_table_overlay(r->pool, sub_req->err_headers_out,
- r->err_headers_out);
- r->subprocess_env = apr_table_overlay(r->pool, sub_req->subprocess_env,
- r->subprocess_env);
- avail_recs = (var_rec *) neg->avail_vars->elts;
- for (j = 0; j < neg->avail_vars->nelts; ++j) {
- var_rec *variant = &avail_recs[j];
- if (variant != best && variant->sub_req) {
- ap_destroy_sub_req(variant->sub_req);
- }
- }
- return OK;
-}
-
-/**********************************************************************
- * There is a problem with content-encoding, as some clients send and
- * expect an x- token (e.g. x-gzip) while others expect the plain token
- * (i.e. gzip). To try and deal with this as best as possible we do
- * the following: if the client sent an Accept-Encoding header and it
- * contains a plain token corresponding to the content encoding of the
- * response, then set content encoding using the plain token. Else if
- * the A-E header contains the x- token use the x- token in the C-E
- * header. Else don't do anything.
- *
- * Note that if no A-E header was sent, or it does not contain a token
- * compatible with the final content encoding, then the token in the
- * C-E header will be whatever was specified in the AddEncoding
- * directive.
- */
-static int fix_encoding(request_rec *r)
-{
- const char *enc = r->content_encoding;
- char *x_enc = NULL;
- apr_array_header_t *accept_encodings;
- accept_rec *accept_recs;
- int i;
-
- if (!enc || !*enc) {
- return DECLINED;
- }
-
- if (enc[0] == 'x' && enc[1] == '-') {
- enc += 2;
- }
-
- if ((accept_encodings = do_header_line(r->pool,
- apr_table_get(r->headers_in, "Accept-Encoding"))) == NULL) {
- return DECLINED;
- }
-
- accept_recs = (accept_rec *) accept_encodings->elts;
-
- for (i = 0; i < accept_encodings->nelts; ++i) {
- char *name = accept_recs[i].name;
-
- if (!strcmp(name, enc)) {
- r->content_encoding = name;
- return OK;
- }
-
- if (name[0] == 'x' && name[1] == '-' && !strcmp(name+2, enc)) {
- x_enc = name;
- }
- }
-
- if (x_enc) {
- r->content_encoding = x_enc;
- return OK;
- }
-
- return DECLINED;
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_fixups(fix_encoding,NULL,NULL,APR_HOOK_MIDDLE);
- ap_hook_type_checker(handle_multi,NULL,NULL,APR_HOOK_FIRST);
- ap_hook_handler(handle_map_file,NULL,NULL,APR_HOOK_MIDDLE);
-}
-
-module AP_MODULE_DECLARE_DATA negotiation_module =
-{
- STANDARD20_MODULE_STUFF,
- create_neg_dir_config, /* dir config creator */
- merge_neg_dir_configs, /* dir merger --- default is to override */
- NULL, /* server config */
- NULL, /* merge server config */
- negotiation_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
diff --git a/modules/mappers/mod_negotiation.exp b/modules/mappers/mod_negotiation.exp
deleted file mode 100644
index a7c18da1de..0000000000
--- a/modules/mappers/mod_negotiation.exp
+++ /dev/null
@@ -1 +0,0 @@
-negotiation_module
diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c
deleted file mode 100644
index a5c4563bff..0000000000
--- a/modules/mappers/mod_rewrite.c
+++ /dev/null
@@ -1,4132 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/* _ _ _
-** _ __ ___ ___ __| | _ __ _____ ___ __(_) |_ ___
-** | '_ ` _ \ / _ \ / _` | | '__/ _ \ \ /\ / / '__| | __/ _ \
-** | | | | | | (_) | (_| | | | | __/\ V V /| | | | || __/
-** |_| |_| |_|\___/ \__,_|___|_| \___| \_/\_/ |_| |_|\__\___|
-** |_____|
-**
-** URL Rewriting Module
-**
-** This module uses a rule-based rewriting engine (based on a
-** regular-expression parser) to rewrite requested URLs on the fly.
-**
-** It supports an unlimited number of additional rule conditions (which can
-** operate on a lot of variables, even on HTTP headers) for granular
-** matching and even external database lookups (either via plain text
-** tables, DBM hash files or even external processes) for advanced URL
-** substitution.
-**
-** It operates on the full URLs (including the PATH_INFO part) both in
-** per-server context (httpd.conf) and per-dir context (.htaccess) and even
-** can generate QUERY_STRING parts on result. The rewriting result finally
-** can lead to internal subprocessing, external request redirection or even
-** to internal proxy throughput.
-**
-** This module was originally written in April 1996 and
-** gifted exclusively to the The Apache Software Foundation in July 1997 by
-**
-** Ralf S. Engelschall
-** rse@engelschall.com
-** www.engelschall.com
-*/
-
-#include "apr.h"
-#include "apr_strings.h"
-#include "apr_user.h"
-#include "apr_lib.h"
-#include "apr_signal.h"
-
-#define APR_WANT_STRFUNC
-#define APR_WANT_IOVEC
-#include "apr_want.h"
-
-#if APR_HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if APR_HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_request.h"
-#include "http_core.h"
-#include "http_log.h"
-#include "http_protocol.h"
-#include "mod_rewrite.h"
-
-#if !defined(OS2) && !defined(WIN32) && !defined(BEOS)
-#include "unixd.h"
-#endif
-
-/*
-** +-------------------------------------------------------+
-** | |
-** | static module configuration
-** | |
-** +-------------------------------------------------------+
-*/
-
-
-/*
-** Our interface to the Apache server kernel:
-**
-** o Runtime logic of a request is as following:
-** while(request or subrequest)
-** foreach(stage #0...#9)
-** foreach(module) (**)
-** try to run hook
-**
-** o the order of modules at (**) is the inverted order as
-** given in the "Configuration" file, i.e. the last module
-** specified is the first one called for each hook!
-** The core module is always the last!
-**
-** o there are two different types of result checking and
-** continue processing:
-** for hook #0,#1,#4,#5,#6,#8:
-** hook run loop stops on first modules which gives
-** back a result != DECLINED, i.e. it usually returns OK
-** which says "OK, module has handled this _stage_" and for #1
-** this have not to mean "Ok, the filename is now valid".
-** for hook #2,#3,#7,#9:
-** all hooks are run, independend of result
-**
-** o at the last stage, the core module always
-** - says "HTTP_BAD_REQUEST" if r->filename does not begin with "/"
-** - prefix URL with document_root or replaced server_root
-** with document_root and sets r->filename
-** - always return a "OK" independed if the file really exists
-** or not!
-*/
-
- /* The section for the Configure script:
- * XXX: this needs updating for apache-2.0 configuration method
- * MODULE-DEFINITION-START
- * Name: rewrite_module
- * ConfigStart
- . ./build/find-dbm-lib
- if [ "x$found_dbm" = "x1" ]; then
- echo " enabling DBM support for mod_rewrite"
- else
- echo " disabling DBM support for mod_rewrite"
- echo " (perhaps you need to add -ldbm, -lndbm or -lgdbm to EXTRA_LIBS)"
- CFLAGS="$CFLAGS -DNO_DBM_REWRITEMAP"
- fi
- * ConfigEnd
- * MODULE-DEFINITION-END
- */
-
- /* the module (predeclaration) */
-module AP_MODULE_DECLARE_DATA rewrite_module;
-
- /* the cache */
-static cache *cachep;
-
- /* whether proxy module is available or not */
-static int proxy_available;
-
-static const char *lockname;
-static apr_lock_t *rewrite_mapr_lock_acquire = NULL;
-static apr_lock_t *rewrite_log_lock = NULL;
-
-/*
-** +-------------------------------------------------------+
-** | |
-** | configuration directive handling
-** | |
-** +-------------------------------------------------------+
-*/
-
-/*
-**
-** per-server configuration structure handling
-**
-*/
-
-static void *config_server_create(apr_pool_t *p, server_rec *s)
-{
- rewrite_server_conf *a;
-
- a = (rewrite_server_conf *)apr_pcalloc(p, sizeof(rewrite_server_conf));
-
- a->state = ENGINE_DISABLED;
- a->options = OPTION_NONE;
- a->rewritelogfile = NULL;
- a->rewritelogfp = NULL;
- a->rewriteloglevel = 0;
- a->rewritemaps = apr_array_make(p, 2, sizeof(rewritemap_entry));
- a->rewriteconds = apr_array_make(p, 2, sizeof(rewritecond_entry));
- a->rewriterules = apr_array_make(p, 2, sizeof(rewriterule_entry));
- a->server = s;
-
- return (void *)a;
-}
-
-static void *config_server_merge(apr_pool_t *p, void *basev, void *overridesv)
-{
- rewrite_server_conf *a, *base, *overrides;
-
- a = (rewrite_server_conf *)apr_pcalloc(p, sizeof(rewrite_server_conf));
- base = (rewrite_server_conf *)basev;
- overrides = (rewrite_server_conf *)overridesv;
-
- a->state = overrides->state;
- a->options = overrides->options;
- a->server = overrides->server;
-
- if (a->options & OPTION_INHERIT) {
- /*
- * local directives override
- * and anything else is inherited
- */
- a->rewriteloglevel = overrides->rewriteloglevel != 0
- ? overrides->rewriteloglevel
- : base->rewriteloglevel;
- a->rewritelogfile = overrides->rewritelogfile != NULL
- ? overrides->rewritelogfile
- : base->rewritelogfile;
- a->rewritelogfp = overrides->rewritelogfp != NULL
- ? overrides->rewritelogfp
- : base->rewritelogfp;
- a->rewritemaps = apr_array_append(p, overrides->rewritemaps,
- base->rewritemaps);
- a->rewriteconds = apr_array_append(p, overrides->rewriteconds,
- base->rewriteconds);
- a->rewriterules = apr_array_append(p, overrides->rewriterules,
- base->rewriterules);
- }
- else {
- /*
- * local directives override
- * and anything else gets defaults
- */
- a->rewriteloglevel = overrides->rewriteloglevel;
- a->rewritelogfile = overrides->rewritelogfile;
- a->rewritelogfp = overrides->rewritelogfp;
- a->rewritemaps = overrides->rewritemaps;
- a->rewriteconds = overrides->rewriteconds;
- a->rewriterules = overrides->rewriterules;
- }
-
- return (void *)a;
-}
-
-
-/*
-**
-** per-directory configuration structure handling
-**
-*/
-
-static void *config_perdir_create(apr_pool_t *p, char *path)
-{
- rewrite_perdir_conf *a;
-
- a = (rewrite_perdir_conf *)apr_pcalloc(p, sizeof(rewrite_perdir_conf));
-
- a->state = ENGINE_DISABLED;
- a->options = OPTION_NONE;
- a->baseurl = NULL;
- a->rewriteconds = apr_array_make(p, 2, sizeof(rewritecond_entry));
- a->rewriterules = apr_array_make(p, 2, sizeof(rewriterule_entry));
-
- if (path == NULL) {
- a->directory = NULL;
- }
- else {
- /* make sure it has a trailing slash */
- if (path[strlen(path)-1] == '/') {
- a->directory = apr_pstrdup(p, path);
- }
- else {
- a->directory = apr_pstrcat(p, path, "/", NULL);
- }
- }
-
- return (void *)a;
-}
-
-static void *config_perdir_merge(apr_pool_t *p, void *basev, void *overridesv)
-{
- rewrite_perdir_conf *a, *base, *overrides;
-
- a = (rewrite_perdir_conf *)apr_pcalloc(p,
- sizeof(rewrite_perdir_conf));
- base = (rewrite_perdir_conf *)basev;
- overrides = (rewrite_perdir_conf *)overridesv;
-
- a->state = overrides->state;
- a->options = overrides->options;
- a->directory = overrides->directory;
- a->baseurl = overrides->baseurl;
-
- if (a->options & OPTION_INHERIT) {
- a->rewriteconds = apr_array_append(p, overrides->rewriteconds,
- base->rewriteconds);
- a->rewriterules = apr_array_append(p, overrides->rewriterules,
- base->rewriterules);
- }
- else {
- a->rewriteconds = overrides->rewriteconds;
- a->rewriterules = overrides->rewriterules;
- }
-
- return (void *)a;
-}
-
-
-/*
-**
-** the configuration commands
-**
-*/
-
-static const char *cmd_rewriteengine(cmd_parms *cmd,
- void *in_dconf, int flag)
-{
- rewrite_perdir_conf *dconf = in_dconf;
- rewrite_server_conf *sconf;
-
- sconf = ap_get_module_config(cmd->server->module_config, &rewrite_module);
-
- if (cmd->path == NULL) { /* is server command */
- sconf->state = (flag ? ENGINE_ENABLED : ENGINE_DISABLED);
- }
- else /* is per-directory command */ {
- dconf->state = (flag ? ENGINE_ENABLED : ENGINE_DISABLED);
- }
-
- return NULL;
-}
-
-static const char *cmd_rewriteoptions(cmd_parms *cmd,
- void *in_dconf, const char *option)
-{
- rewrite_perdir_conf *dconf = in_dconf;
- rewrite_server_conf *sconf;
- const char *err;
-
- sconf = ap_get_module_config(cmd->server->module_config, &rewrite_module);
-
- if (cmd->path == NULL) { /* is server command */
- err = cmd_rewriteoptions_setoption(cmd->pool,
- &(sconf->options), option);
- }
- else { /* is per-directory command */
- err = cmd_rewriteoptions_setoption(cmd->pool,
- &(dconf->options), option);
- }
-
- return err;
-}
-
-static const char *cmd_rewriteoptions_setoption(apr_pool_t *p, int *options,
- const char *name)
-{
- if (strcasecmp(name, "inherit") == 0) {
- *options |= OPTION_INHERIT;
- }
- else {
- return apr_pstrcat(p, "RewriteOptions: unknown option '",
- name, "'", NULL);
- }
- return NULL;
-}
-
-static const char *cmd_rewritelog(cmd_parms *cmd, void *dconf, const char *a1)
-{
- rewrite_server_conf *sconf;
-
- sconf = ap_get_module_config(cmd->server->module_config, &rewrite_module);
-
- sconf->rewritelogfile = a1;
-
- return NULL;
-}
-
-static const char *cmd_rewriteloglevel(cmd_parms *cmd, void *dconf, const char *a1)
-{
- rewrite_server_conf *sconf;
-
- sconf = ap_get_module_config(cmd->server->module_config, &rewrite_module);
-
- sconf->rewriteloglevel = atoi(a1);
-
- return NULL;
-}
-
-static const char *cmd_rewritemap(cmd_parms *cmd, void *dconf, const char *a1,
- const char *a2)
-{
- rewrite_server_conf *sconf;
- rewritemap_entry *newmap;
- apr_finfo_t st;
-
- sconf = ap_get_module_config(cmd->server->module_config, &rewrite_module);
-
- newmap = apr_array_push(sconf->rewritemaps);
-
- newmap->name = a1;
- newmap->func = NULL;
- if (strncmp(a2, "txt:", 4) == 0) {
- newmap->type = MAPTYPE_TXT;
- newmap->datafile = a2+4;
- newmap->checkfile = a2+4;
- }
- else if (strncmp(a2, "rnd:", 4) == 0) {
- newmap->type = MAPTYPE_RND;
- newmap->datafile = a2+4;
- newmap->checkfile = a2+4;
- }
- else if (strncmp(a2, "dbm:", 4) == 0) {
-#ifndef NO_DBM_REWRITEMAP
- newmap->type = MAPTYPE_DBM;
- newmap->datafile = a2+4;
- newmap->checkfile = apr_pstrcat(cmd->pool, a2+4, NDBM_FILE_SUFFIX, NULL);
-#else
- return apr_pstrdup(cmd->pool, "RewriteMap: cannot use NDBM mapfile, "
- "because no NDBM support is compiled in");
-#endif
- }
- else if (strncmp(a2, "prg:", 4) == 0) {
- newmap->type = MAPTYPE_PRG;
- newmap->datafile = a2+4;
- newmap->checkfile = a2+4;
- }
- else if (strncmp(a2, "int:", 4) == 0) {
- newmap->type = MAPTYPE_INT;
- newmap->datafile = NULL;
- newmap->checkfile = NULL;
- if (strcmp(a2+4, "tolower") == 0) {
- newmap->func = rewrite_mapfunc_tolower;
- }
- else if (strcmp(a2+4, "toupper") == 0) {
- newmap->func = rewrite_mapfunc_toupper;
- }
- else if (strcmp(a2+4, "escape") == 0) {
- newmap->func = rewrite_mapfunc_escape;
- }
- else if (strcmp(a2+4, "unescape") == 0) {
- newmap->func = rewrite_mapfunc_unescape;
- }
- else if (sconf->state == ENGINE_ENABLED) {
- return apr_pstrcat(cmd->pool, "RewriteMap: internal map not found:",
- a2+4, NULL);
- }
- }
- else {
- newmap->type = MAPTYPE_TXT;
- newmap->datafile = a2;
- newmap->checkfile = a2;
- }
- newmap->fpin = NULL;
- newmap->fpout = NULL;
-
- if (newmap->checkfile && (sconf->state == ENGINE_ENABLED)
- && (apr_stat(&st, newmap->checkfile, APR_FINFO_MIN,
- cmd->pool) != APR_SUCCESS)) {
- return apr_pstrcat(cmd->pool,
- "RewriteMap: map file or program not found:",
- newmap->checkfile, NULL);
- }
-
- return NULL;
-}
-
-static const char *cmd_rewritelock(cmd_parms *cmd, void *dconf, const char *a1)
-{
- const char *error;
-
- if ((error = ap_check_cmd_context(cmd, GLOBAL_ONLY)) != NULL)
- return error;
-
- lockname = a1;
-
- return NULL;
-}
-
-static const char *cmd_rewritebase(cmd_parms *cmd, void *in_dconf,
- const char *a1)
-{
- rewrite_perdir_conf *dconf = in_dconf;
-
- if (cmd->path == NULL || dconf == NULL) {
- return "RewriteBase: only valid in per-directory config files";
- }
- if (a1[0] == '\0') {
- return "RewriteBase: empty URL not allowed";
- }
- if (a1[0] != '/') {
- return "RewriteBase: argument is not a valid URL";
- }
-
- dconf->baseurl = a1;
-
- return NULL;
-}
-
-static const char *cmd_rewritecond(cmd_parms *cmd, void *in_dconf,
- const char *in_str)
-{
- rewrite_perdir_conf *dconf = in_dconf;
- char *str = apr_pstrdup(cmd->pool, in_str);
- rewrite_server_conf *sconf;
- rewritecond_entry *newcond;
- regex_t *regexp;
- char *a1;
- char *a2;
- char *a3;
- char *cp;
- const char *err;
- int rc;
-
- sconf = ap_get_module_config(cmd->server->module_config, &rewrite_module);
-
- /* make a new entry in the internal temporary rewrite rule list */
- if (cmd->path == NULL) { /* is server command */
- newcond = apr_array_push(sconf->rewriteconds);
- }
- else { /* is per-directory command */
- newcond = apr_array_push(dconf->rewriteconds);
- }
-
- /* parse the argument line ourself */
- if (parseargline(str, &a1, &a2, &a3)) {
- return apr_pstrcat(cmd->pool, "RewriteCond: bad argument line '", str,
- "'", NULL);
- }
-
- /* arg1: the input string */
- newcond->input = apr_pstrdup(cmd->pool, a1);
-
- /* arg3: optional flags field
- (this have to be first parsed, because we need to
- know if the regex should be compiled with ICASE!) */
- newcond->flags = CONDFLAG_NONE;
- if (a3 != NULL) {
- if ((err = cmd_rewritecond_parseflagfield(cmd->pool, newcond,
- a3)) != NULL) {
- return err;
- }
- }
-
- /* arg2: the pattern
- try to compile the regexp to test if is ok */
- cp = a2;
- if (cp[0] == '!') {
- newcond->flags |= CONDFLAG_NOTMATCH;
- cp++;
- }
-
- /* now be careful: Under the POSIX regex library
- we can compile the pattern for case insensitive matching,
- under the old V8 library we have to do it self via a hack */
- if (newcond->flags & CONDFLAG_NOCASE) {
- rc = ((regexp = ap_pregcomp(cmd->pool, cp, REG_EXTENDED|REG_ICASE))
- == NULL);
- }
- else {
- rc = ((regexp = ap_pregcomp(cmd->pool, cp, REG_EXTENDED)) == NULL);
- }
- if (rc) {
- return apr_pstrcat(cmd->pool,
- "RewriteCond: cannot compile regular expression '",
- a2, "'", NULL);
- }
-
- newcond->pattern = apr_pstrdup(cmd->pool, cp);
- newcond->regexp = regexp;
-
- return NULL;
-}
-
-static const char *cmd_rewritecond_parseflagfield(apr_pool_t *p,
- rewritecond_entry *cfg,
- char *str)
-{
- char *cp;
- char *cp1;
- char *cp2;
- char *cp3;
- char *key;
- char *val;
- const char *err;
-
- if (str[0] != '[' || str[strlen(str)-1] != ']') {
- return "RewriteCond: bad flag delimiters";
- }
-
- cp = str+1;
- str[strlen(str)-1] = ','; /* for simpler parsing */
- for ( ; *cp != '\0'; ) {
- /* skip whitespaces */
- for ( ; (*cp == ' ' || *cp == '\t') && *cp != '\0'; cp++)
- ;
- if (*cp == '\0') {
- break;
- }
- cp1 = cp;
- if ((cp2 = strchr(cp, ',')) != NULL) {
- cp = cp2+1;
- for ( ; (*(cp2-1) == ' ' || *(cp2-1) == '\t'); cp2--)
- ;
- *cp2 = '\0';
- if ((cp3 = strchr(cp1, '=')) != NULL) {
- *cp3 = '\0';
- key = cp1;
- val = cp3+1;
- }
- else {
- key = cp1;
- val = "";
- }
- if ((err = cmd_rewritecond_setflag(p, cfg, key, val)) != NULL) {
- return err;
- }
- }
- else {
- break;
- }
- }
-
- return NULL;
-}
-
-static const char *cmd_rewritecond_setflag(apr_pool_t *p, rewritecond_entry *cfg,
- char *key, char *val)
-{
- if ( strcasecmp(key, "nocase") == 0
- || strcasecmp(key, "NC") == 0 ) {
- cfg->flags |= CONDFLAG_NOCASE;
- }
- else if ( strcasecmp(key, "ornext") == 0
- || strcasecmp(key, "OR") == 0 ) {
- cfg->flags |= CONDFLAG_ORNEXT;
- }
- else {
- return apr_pstrcat(p, "RewriteCond: unknown flag '", key, "'", NULL);
- }
- return NULL;
-}
-
-static const char *cmd_rewriterule(cmd_parms *cmd, void *in_dconf,
- const char *in_str)
-{
- rewrite_perdir_conf *dconf = in_dconf;
- char *str = apr_pstrdup(cmd->pool, in_str);
- rewrite_server_conf *sconf;
- rewriterule_entry *newrule;
- regex_t *regexp;
- char *a1;
- char *a2;
- char *a3;
- char *cp;
- const char *err;
- int mode;
-
- sconf = ap_get_module_config(cmd->server->module_config, &rewrite_module);
-
- /* make a new entry in the internal rewrite rule list */
- if (cmd->path == NULL) { /* is server command */
- newrule = apr_array_push(sconf->rewriterules);
- }
- else { /* is per-directory command */
- newrule = apr_array_push(dconf->rewriterules);
- }
-
- /* parse the argument line ourself */
- if (parseargline(str, &a1, &a2, &a3)) {
- return apr_pstrcat(cmd->pool, "RewriteRule: bad argument line '", str,
- "'", NULL);
- }
-
- /* arg3: optional flags field */
- newrule->forced_mimetype = NULL;
- newrule->forced_responsecode = HTTP_MOVED_TEMPORARILY;
- newrule->flags = RULEFLAG_NONE;
- newrule->env[0] = NULL;
- newrule->skip = 0;
- if (a3 != NULL) {
- if ((err = cmd_rewriterule_parseflagfield(cmd->pool, newrule,
- a3)) != NULL) {
- return err;
- }
- }
-
- /* arg1: the pattern
- * try to compile the regexp to test if is ok
- */
- cp = a1;
- if (cp[0] == '!') {
- newrule->flags |= RULEFLAG_NOTMATCH;
- cp++;
- }
- mode = REG_EXTENDED;
- if (newrule->flags & RULEFLAG_NOCASE) {
- mode |= REG_ICASE;
- }
- if ((regexp = ap_pregcomp(cmd->pool, cp, mode)) == NULL) {
- return apr_pstrcat(cmd->pool,
- "RewriteRule: cannot compile regular expression '",
- a1, "'", NULL);
- }
- newrule->pattern = apr_pstrdup(cmd->pool, cp);
- newrule->regexp = regexp;
-
- /* arg2: the output string
- * replace the $<N> by \<n> which is needed by the currently
- * used Regular Expression library
- *
- * TODO: Is this still required for PCRE? If not, does it *work* with PCRE?
- */
- newrule->output = apr_pstrdup(cmd->pool, a2);
-
- /* now, if the server or per-dir config holds an
- * array of RewriteCond entries, we take it for us
- * and clear the array
- */
- if (cmd->path == NULL) { /* is server command */
- newrule->rewriteconds = sconf->rewriteconds;
- sconf->rewriteconds = apr_array_make(cmd->pool, 2,
- sizeof(rewritecond_entry));
- }
- else { /* is per-directory command */
- newrule->rewriteconds = dconf->rewriteconds;
- dconf->rewriteconds = apr_array_make(cmd->pool, 2,
- sizeof(rewritecond_entry));
- }
-
- return NULL;
-}
-
-static const char *cmd_rewriterule_parseflagfield(apr_pool_t *p,
- rewriterule_entry *cfg,
- char *str)
-{
- char *cp;
- char *cp1;
- char *cp2;
- char *cp3;
- char *key;
- char *val;
- const char *err;
-
- if (str[0] != '[' || str[strlen(str)-1] != ']') {
- return "RewriteRule: bad flag delimiters";
- }
-
- cp = str+1;
- str[strlen(str)-1] = ','; /* for simpler parsing */
- for ( ; *cp != '\0'; ) {
- /* skip whitespaces */
- for ( ; (*cp == ' ' || *cp == '\t') && *cp != '\0'; cp++)
- ;
- if (*cp == '\0') {
- break;
- }
- cp1 = cp;
- if ((cp2 = strchr(cp, ',')) != NULL) {
- cp = cp2+1;
- for ( ; (*(cp2-1) == ' ' || *(cp2-1) == '\t'); cp2--)
- ;
- *cp2 = '\0';
- if ((cp3 = strchr(cp1, '=')) != NULL) {
- *cp3 = '\0';
- key = cp1;
- val = cp3+1;
- }
- else {
- key = cp1;
- val = "";
- }
- if ((err = cmd_rewriterule_setflag(p, cfg, key, val)) != NULL) {
- return err;
- }
- }
- else {
- break;
- }
- }
-
- return NULL;
-}
-
-static const char *cmd_rewriterule_setflag(apr_pool_t *p, rewriterule_entry *cfg,
- char *key, char *val)
-{
- int status = 0;
- int i;
-
- if ( strcasecmp(key, "redirect") == 0
- || strcasecmp(key, "R") == 0 ) {
- cfg->flags |= RULEFLAG_FORCEREDIRECT;
- if (strlen(val) > 0) {
- if (strcasecmp(val, "permanent") == 0) {
- status = HTTP_MOVED_PERMANENTLY;
- }
- else if (strcasecmp(val, "temp") == 0) {
- status = HTTP_MOVED_TEMPORARILY;
- }
- else if (strcasecmp(val, "seeother") == 0) {
- status = HTTP_SEE_OTHER;
- }
- else if (apr_isdigit(*val)) {
- status = atoi(val);
- }
- if (!ap_is_HTTP_REDIRECT(status)) {
- return "RewriteRule: invalid HTTP response code "
- "for flag 'R'";
- }
- cfg->forced_responsecode = status;
- }
- }
- else if ( strcasecmp(key, "last") == 0
- || strcasecmp(key, "L") == 0 ) {
- cfg->flags |= RULEFLAG_LASTRULE;
- }
- else if ( strcasecmp(key, "next") == 0
- || strcasecmp(key, "N") == 0 ) {
- cfg->flags |= RULEFLAG_NEWROUND;
- }
- else if ( strcasecmp(key, "chain") == 0
- || strcasecmp(key, "C") == 0 ) {
- cfg->flags |= RULEFLAG_CHAIN;
- }
- else if ( strcasecmp(key, "type") == 0
- || strcasecmp(key, "T") == 0 ) {
- cfg->forced_mimetype = apr_pstrdup(p, val);
- ap_str_tolower(cfg->forced_mimetype);
- }
- else if ( strcasecmp(key, "env") == 0
- || strcasecmp(key, "E") == 0 ) {
- for (i = 0; (cfg->env[i] != NULL) && (i < MAX_ENV_FLAGS); i++)
- ;
- if (i < MAX_ENV_FLAGS) {
- cfg->env[i] = apr_pstrdup(p, val);
- cfg->env[i+1] = NULL;
- }
- else {
- return "RewriteRule: too many environment flags 'E'";
- }
- }
- else if ( strcasecmp(key, "nosubreq") == 0
- || strcasecmp(key, "NS") == 0 ) {
- cfg->flags |= RULEFLAG_IGNOREONSUBREQ;
- }
- else if ( strcasecmp(key, "proxy") == 0
- || strcasecmp(key, "P") == 0 ) {
- cfg->flags |= RULEFLAG_PROXY;
- }
- else if ( strcasecmp(key, "passthrough") == 0
- || strcasecmp(key, "PT") == 0 ) {
- cfg->flags |= RULEFLAG_PASSTHROUGH;
- }
- else if ( strcasecmp(key, "skip") == 0
- || strcasecmp(key, "S") == 0 ) {
- cfg->skip = atoi(val);
- }
- else if ( strcasecmp(key, "forbidden") == 0
- || strcasecmp(key, "F") == 0 ) {
- cfg->flags |= RULEFLAG_FORBIDDEN;
- }
- else if ( strcasecmp(key, "gone") == 0
- || strcasecmp(key, "G") == 0 ) {
- cfg->flags |= RULEFLAG_GONE;
- }
- else if ( strcasecmp(key, "qsappend") == 0
- || strcasecmp(key, "QSA") == 0 ) {
- cfg->flags |= RULEFLAG_QSAPPEND;
- }
- else if ( strcasecmp(key, "nocase") == 0
- || strcasecmp(key, "NC") == 0 ) {
- cfg->flags |= RULEFLAG_NOCASE;
- }
- else {
- return apr_pstrcat(p, "RewriteRule: unknown flag '", key, "'", NULL);
- }
- return NULL;
-}
-
-
-/*
-**
-** Global Module Initialization
-** [called from read_config() after all
-** config commands were already called]
-**
-*/
-
-static void init_module(apr_pool_t *p,
- apr_pool_t *plog,
- apr_pool_t *ptemp,
- server_rec *s)
-{
- apr_status_t rv;
- void *data;
- int first_time = 0;
- const char *userdata_key = "rewrite_init_module";
-
- apr_pool_userdata_get(&data, userdata_key, s->process->pool);
- if (!data) {
- first_time = 1;
- apr_pool_userdata_set((const void *)1, userdata_key,
- apr_pool_cleanup_null, s->process->pool);
- }
-
- /* check if proxy module is available */
- proxy_available = (ap_find_linked_module("mod_proxy.c") != NULL);
-
- /* create the rewriting lockfiles in the parent */
- if ((rv = apr_lock_create (&rewrite_log_lock, APR_MUTEX, APR_LOCKALL,
- NULL, p)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
- "mod_rewrite: could not create rewrite_log_lock");
- exit(1);
- }
-
- rewritelock_create(s, p);
- apr_pool_cleanup_register(p, (void *)s, rewritelock_remove, apr_pool_cleanup_null);
-
- /* step through the servers and
- * - open each rewriting logfile
- * - open the RewriteMap prg:xxx programs
- */
- for (; s; s = s->next) {
- open_rewritelog(s, p);
- if (!first_time)
- run_rewritemap_programs(s, p);
- }
-}
-
-
-/*
-**
-** Per-Child Module Initialization
-** [called after a child process is spawned]
-**
-*/
-
-static void init_child(apr_pool_t *p, server_rec *s)
-{
- apr_status_t rv;
-
- if (lockname != NULL && *(lockname) != '\0')
- {
- rv = apr_lock_child_init (&rewrite_mapr_lock_acquire, lockname, p);
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
- "mod_rewrite: could not init rewrite_mapr_lock_acquire "
- "in child");
- }
- }
-
- /* create the lookup cache */
- cachep = init_cache(p);
-}
-
-
-/*
-** +-------------------------------------------------------+
-** | |
-** | runtime hooks
-** | |
-** +-------------------------------------------------------+
-*/
-
-/*
-**
-** URI-to-filename hook
-**
-** [used for the rewriting engine triggered by
-** the per-server 'RewriteRule' directives]
-**
-*/
-
-static int hook_uri2file(request_rec *r)
-{
- rewrite_server_conf *conf;
- const char *var;
- const char *thisserver;
- char *thisport;
- const char *thisurl;
- char buf[512];
- char docroot[512];
- char *cp, *cp2;
- const char *ccp;
- apr_finfo_t finfo;
- unsigned int port;
- int n;
- int l;
-
- /*
- * retrieve the config structures
- */
- conf = ap_get_module_config(r->server->module_config, &rewrite_module);
-
- /*
- * only do something under runtime if the engine is really enabled,
- * else return immediately!
- */
- if (conf->state == ENGINE_DISABLED) {
- return DECLINED;
- }
-
- /*
- * check for the ugly API case of a virtual host section where no
- * mod_rewrite directives exists. In this situation we became no chance
- * by the API to setup our default per-server config so we have to
- * on-the-fly assume we have the default config. But because the default
- * config has a disabled rewriting engine we are lucky because can
- * just stop operating now.
- */
- if (conf->server != r->server) {
- return DECLINED;
- }
-
- /*
- * add the SCRIPT_URL variable to the env. this is a bit complicated
- * due to the fact that apache uses subrequests and internal redirects
- */
-
- if (r->main == NULL) {
- var = apr_pstrcat(r->pool, "REDIRECT_", ENVVAR_SCRIPT_URL, NULL);
- var = apr_table_get(r->subprocess_env, var);
- if (var == NULL) {
- apr_table_setn(r->subprocess_env, ENVVAR_SCRIPT_URL, r->uri);
- }
- else {
- apr_table_setn(r->subprocess_env, ENVVAR_SCRIPT_URL, var);
- }
- }
- else {
- var = apr_table_get(r->main->subprocess_env, ENVVAR_SCRIPT_URL);
- apr_table_setn(r->subprocess_env, ENVVAR_SCRIPT_URL, var);
- }
-
- /*
- * create the SCRIPT_URI variable for the env
- */
-
- /* add the canonical URI of this URL */
- thisserver = ap_get_server_name(r);
- port = ap_get_server_port(r);
- if (ap_is_default_port(port, r)) {
- thisport = "";
- }
- else {
- apr_snprintf(buf, sizeof(buf), ":%u", port);
- thisport = buf;
- }
- thisurl = apr_table_get(r->subprocess_env, ENVVAR_SCRIPT_URL);
-
- /* set the variable */
- var = apr_pstrcat(r->pool, ap_http_method(r), "://", thisserver, thisport,
- thisurl, NULL);
- apr_table_setn(r->subprocess_env, ENVVAR_SCRIPT_URI, var);
-
- /* if filename was not initially set,
- * we start with the requested URI
- */
- if (r->filename == NULL) {
- r->filename = apr_pstrdup(r->pool, r->uri);
- rewritelog(r, 2, "init rewrite engine with requested uri %s",
- r->filename);
- }
-
- /*
- * now apply the rules ...
- */
- if (apply_rewrite_list(r, conf->rewriterules, NULL)) {
-
- if (strlen(r->filename) > 6 &&
- strncmp(r->filename, "proxy:", 6) == 0) {
- /* it should be go on as an internal proxy request */
-
- /* check if the proxy module is enabled, so
- * we can actually use it!
- */
- if (!proxy_available) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "attempt to make remote request from mod_rewrite "
- "without proxy enabled: %s", r->filename);
- return HTTP_FORBIDDEN;
- }
-
- /* make sure the QUERY_STRING and
- * PATH_INFO parts get incorporated
- */
- if (r->path_info != NULL) {
- r->filename = apr_pstrcat(r->pool, r->filename,
- r->path_info, NULL);
- }
- if (r->args != NULL &&
- r->uri == r->unparsed_uri) {
- /* see proxy_http:proxy_http_canon() */
- r->filename = apr_pstrcat(r->pool, r->filename,
- "?", r->args, NULL);
- }
-
- /* now make sure the request gets handled by the proxy handler */
- r->proxyreq = PROXYREQ_REVERSE;
- r->handler = "proxy-server";
-
- rewritelog(r, 1, "go-ahead with proxy request %s [OK]",
- r->filename);
- return OK;
- }
- else if (is_absolute_uri(r->filename)) {
- /* it was finally rewritten to a remote URL */
-
- /* skip 'scheme:' */
- for (cp = r->filename; *cp != ':' && *cp != '\0'; cp++)
- ;
- /* skip '://' */
- cp += 3;
- /* skip host part */
- for ( ; *cp != '/' && *cp != '\0'; cp++)
- ;
- if (*cp != '\0') {
- rewritelog(r, 1, "escaping %s for redirect", r->filename);
- cp2 = ap_escape_uri(r->pool, cp);
- *cp = '\0';
- r->filename = apr_pstrcat(r->pool, r->filename, cp2, NULL);
- }
-
- /* append the QUERY_STRING part */
- if (r->args != NULL) {
- r->filename = apr_pstrcat(r->pool, r->filename, "?",
- ap_escape_uri(r->pool, r->args), NULL);
- }
-
- /* determine HTTP redirect response code */
- if (ap_is_HTTP_REDIRECT(r->status)) {
- n = r->status;
- r->status = HTTP_OK; /* make Apache kernel happy */
- }
- else {
- n = HTTP_MOVED_TEMPORARILY;
- }
-
- /* now do the redirection */
- apr_table_setn(r->headers_out, "Location", r->filename);
- rewritelog(r, 1, "redirect to %s [REDIRECT/%d]", r->filename, n);
- return n;
- }
- else if (strlen(r->filename) > 10 &&
- strncmp(r->filename, "forbidden:", 10) == 0) {
- /* This URLs is forced to be forbidden for the requester */
- return HTTP_FORBIDDEN;
- }
- else if (strlen(r->filename) > 5 &&
- strncmp(r->filename, "gone:", 5) == 0) {
- /* This URLs is forced to be gone */
- return HTTP_GONE;
- }
- else if (strlen(r->filename) > 12 &&
- strncmp(r->filename, "passthrough:", 12) == 0) {
- /*
- * Hack because of underpowered API: passing the current
- * rewritten filename through to other URL-to-filename handlers
- * just as it were the requested URL. This is to enable
- * post-processing by mod_alias, etc. which always act on
- * r->uri! The difference here is: We do not try to
- * add the document root
- */
- r->uri = apr_pstrdup(r->pool, r->filename+12);
- return DECLINED;
- }
- else {
- /* it was finally rewritten to a local path */
-
- /* expand "/~user" prefix */
-#if APR_HAS_USER
- r->filename = expand_tildepaths(r, r->filename);
-#endif
- rewritelog(r, 2, "local path result: %s", r->filename);
-
- /* the filename has to start with a slash! */
- if (r->filename[0] != '/') {
- return HTTP_BAD_REQUEST;
- }
-
- /* if there is no valid prefix, we have
- * to emulate the translator from the core and
- * prefix the filename with document_root
- *
- * NOTICE:
- * We cannot leave out the prefix_stat because
- * - when we always prefix with document_root
- * then no absolute path can be created, e.g. via
- * emulating a ScriptAlias directive, etc.
- * - when we always NOT prefix with document_root
- * then the files under document_root have to
- * be references directly and document_root
- * gets never used and will be a dummy parameter -
- * this is also bad
- *
- * BUT:
- * Under real Unix systems this is no problem,
- * because we only do stat() on the first directory
- * and this gets cached by the kernel for along time!
- */
- n = prefix_stat(r->filename, &finfo);
- if (n == 0) {
- if ((ccp = ap_document_root(r)) != NULL) {
- l = apr_cpystrn(docroot, ccp, sizeof(docroot)) - docroot;
-
- /* always NOT have a trailing slash */
- if (docroot[l-1] == '/') {
- docroot[l-1] = '\0';
- }
- if (r->server->path
- && !strncmp(r->filename, r->server->path,
- r->server->pathlen)) {
- r->filename = apr_pstrcat(r->pool, docroot,
- (r->filename +
- r->server->pathlen), NULL);
- }
- else {
- r->filename = apr_pstrcat(r->pool, docroot,
- r->filename, NULL);
- }
- rewritelog(r, 2, "prefixed with document_root to %s",
- r->filename);
- }
- }
-
- rewritelog(r, 1, "go-ahead with %s [OK]", r->filename);
- return OK;
- }
- }
- else {
- rewritelog(r, 1, "pass through %s", r->filename);
- return DECLINED;
- }
-}
-
-
-/*
-**
-** MIME-type hook
-**
-** [used to support the forced-MIME-type feature]
-**
-*/
-
-static int hook_mimetype(request_rec *r)
-{
- const char *t;
-
- /* now check if we have to force a MIME-type */
- t = apr_table_get(r->notes, REWRITE_FORCED_MIMETYPE_NOTEVAR);
- if (t == NULL) {
- return DECLINED;
- }
- else {
- rewritelog(r, 1, "force filename %s to have MIME-type '%s'",
- r->filename, t);
- r->content_type = t;
- return OK;
- }
-}
-
-
-/*
-**
-** Fixup hook
-**
-** [used for the rewriting engine triggered by
-** the per-directory 'RewriteRule' directives]
-**
-*/
-
-static int hook_fixup(request_rec *r)
-{
- rewrite_perdir_conf *dconf;
- char *cp;
- char *cp2;
- const char *ccp;
- char *prefix;
- int l;
- int n;
- char *ofilename;
-
- dconf = (rewrite_perdir_conf *)ap_get_module_config(r->per_dir_config,
- &rewrite_module);
-
- /* if there is no per-dir config we return immediately */
- if (dconf == NULL) {
- return DECLINED;
- }
-
- /* we shouldn't do anything in subrequests */
- if (r->main != NULL) {
- return DECLINED;
- }
-
- /* if there are no real (i.e. no RewriteRule directives!)
- per-dir config of us, we return also immediately */
- if (dconf->directory == NULL) {
- return DECLINED;
- }
-
- /*
- * only do something under runtime if the engine is really enabled,
- * for this directory, else return immediately!
- */
- if (!(ap_allow_options(r) & (OPT_SYM_LINKS | OPT_SYM_OWNER))) {
- /* FollowSymLinks is mandatory! */
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Options FollowSymLinks or SymLinksIfOwnerMatch is off "
- "which implies that RewriteRule directive is forbidden: "
- "%s", r->filename);
- return HTTP_FORBIDDEN;
- }
- else {
- /* FollowSymLinks is given, but the user can
- * still turn off the rewriting engine
- */
- if (dconf->state == ENGINE_DISABLED) {
- return DECLINED;
- }
- }
-
- /*
- * remember the current filename before rewriting for later check
- * to prevent deadlooping because of internal redirects
- * on final URL/filename which can be equal to the inital one.
- */
- ofilename = r->filename;
-
- /*
- * now apply the rules ...
- */
- if (apply_rewrite_list(r, dconf->rewriterules, dconf->directory)) {
-
- if (strlen(r->filename) > 6 &&
- strncmp(r->filename, "proxy:", 6) == 0) {
- /* it should go on as an internal proxy request */
-
- /* make sure the QUERY_STRING and
- * PATH_INFO parts get incorporated
- * (r->path_info was already appended by the
- * rewriting engine because of the per-dir context!)
- */
- if (r->args != NULL) {
- r->filename = apr_pstrcat(r->pool, r->filename,
- "?", r->args, NULL);
- }
-
- /* now make sure the request gets handled by the proxy handler */
- r->proxyreq = PROXYREQ_REVERSE;
- r->handler = "proxy-server";
-
- rewritelog(r, 1, "[per-dir %s] go-ahead with proxy request "
- "%s [OK]", dconf->directory, r->filename);
- return OK;
- }
- else if (is_absolute_uri(r->filename)) {
- /* it was finally rewritten to a remote URL */
-
- /* because we are in a per-dir context
- * first try to replace the directory with its base-URL
- * if there is a base-URL available
- */
- if (dconf->baseurl != NULL) {
- /* skip 'scheme:' */
- for (cp = r->filename; *cp != ':' && *cp != '\0'; cp++)
- ;
- /* skip '://' */
- cp += 3;
- if ((cp = strchr(cp, '/')) != NULL) {
- rewritelog(r, 2,
- "[per-dir %s] trying to replace "
- "prefix %s with %s",
- dconf->directory, dconf->directory,
- dconf->baseurl);
- cp2 = subst_prefix_path(r, cp, dconf->directory,
- dconf->baseurl);
- if (strcmp(cp2, cp) != 0) {
- *cp = '\0';
- r->filename = apr_pstrcat(r->pool, r->filename,
- cp2, NULL);
- }
- }
- }
-
- /* now prepare the redirect... */
-
- /* skip 'scheme:' */
- for (cp = r->filename; *cp != ':' && *cp != '\0'; cp++)
- ;
- /* skip '://' */
- cp += 3;
- /* skip host part */
- for ( ; *cp != '/' && *cp != '\0'; cp++)
- ;
- if (*cp != '\0') {
- rewritelog(r, 1, "[per-dir %s] escaping %s for redirect",
- dconf->directory, r->filename);
- cp2 = ap_escape_uri(r->pool, cp);
- *cp = '\0';
- r->filename = apr_pstrcat(r->pool, r->filename, cp2, NULL);
- }
-
- /* append the QUERY_STRING part */
- if (r->args != NULL) {
- r->filename = apr_pstrcat(r->pool, r->filename, "?",
- ap_escape_uri(r->pool, r->args), NULL);
- }
-
- /* determine HTTP redirect response code */
- if (ap_is_HTTP_REDIRECT(r->status)) {
- n = r->status;
- r->status = HTTP_OK; /* make Apache kernel happy */
- }
- else {
- n = HTTP_MOVED_TEMPORARILY;
- }
-
- /* now do the redirection */
- apr_table_setn(r->headers_out, "Location", r->filename);
- rewritelog(r, 1, "[per-dir %s] redirect to %s [REDIRECT/%d]",
- dconf->directory, r->filename, n);
- return n;
- }
- else if (strlen(r->filename) > 10 &&
- strncmp(r->filename, "forbidden:", 10) == 0) {
- /* This URL is forced to be forbidden for the requester */
- return HTTP_FORBIDDEN;
- }
- else if (strlen(r->filename) > 5 &&
- strncmp(r->filename, "gone:", 5) == 0) {
- /* This URL is forced to be gone */
- return HTTP_GONE;
- }
- else {
- /* it was finally rewritten to a local path */
-
- /* if someone used the PASSTHROUGH flag in per-dir
- * context we just ignore it. It is only useful
- * in per-server context
- */
- if (strlen(r->filename) > 12 &&
- strncmp(r->filename, "passthrough:", 12) == 0) {
- r->filename = apr_pstrdup(r->pool, r->filename+12);
- }
-
- /* the filename has to start with a slash! */
- if (r->filename[0] != '/') {
- return HTTP_BAD_REQUEST;
- }
-
- /* Check for deadlooping:
- * At this point we KNOW that at least one rewriting
- * rule was applied, but when the resulting URL is
- * the same as the initial URL, we are not allowed to
- * use the following internal redirection stuff because
- * this would lead to a deadloop.
- */
- if (strcmp(r->filename, ofilename) == 0) {
- rewritelog(r, 1, "[per-dir %s] initial URL equal rewritten "
- "URL: %s [IGNORING REWRITE]",
- dconf->directory, r->filename);
- return OK;
- }
-
- /* if there is a valid base-URL then substitute
- * the per-dir prefix with this base-URL if the
- * current filename still is inside this per-dir
- * context. If not then treat the result as a
- * plain URL
- */
- if (dconf->baseurl != NULL) {
- rewritelog(r, 2,
- "[per-dir %s] trying to replace prefix %s with %s",
- dconf->directory, dconf->directory, dconf->baseurl);
- r->filename = subst_prefix_path(r, r->filename,
- dconf->directory,
- dconf->baseurl);
- }
- else {
- /* if no explicit base-URL exists we assume
- * that the directory prefix is also a valid URL
- * for this webserver and only try to remove the
- * document_root if it is prefix
- */
- if ((ccp = ap_document_root(r)) != NULL) {
- prefix = apr_pstrdup(r->pool, ccp);
- /* always NOT have a trailing slash */
- l = strlen(prefix);
- if (prefix[l-1] == '/') {
- prefix[l-1] = '\0';
- l--;
- }
- if (strncmp(r->filename, prefix, l) == 0) {
- rewritelog(r, 2,
- "[per-dir %s] strip document_root "
- "prefix: %s -> %s",
- dconf->directory, r->filename,
- r->filename+l);
- r->filename = apr_pstrdup(r->pool, r->filename+l);
- }
- }
- }
-
- /* now initiate the internal redirect */
- rewritelog(r, 1, "[per-dir %s] internal redirect with %s "
- "[INTERNAL REDIRECT]", dconf->directory, r->filename);
- r->filename = apr_pstrcat(r->pool, "redirect:", r->filename, NULL);
- r->handler = "redirect-handler";
- return OK;
- }
- }
- else {
- rewritelog(r, 1, "[per-dir %s] pass through %s",
- dconf->directory, r->filename);
- return DECLINED;
- }
-}
-
-
-/*
-**
-** Content-Handlers
-**
-** [used for redirect support]
-**
-*/
-
-static int handler_redirect(request_rec *r)
-{
- if (strcmp(r->handler, "redirect-handler")) {
- return DECLINED;
- }
-
- /* just make sure that we are really meant! */
- if (strncmp(r->filename, "redirect:", 9) != 0) {
- return DECLINED;
- }
-
- /* now do the internal redirect */
- ap_internal_redirect(apr_pstrcat(r->pool, r->filename+9,
- r->args ? "?" : NULL, r->args, NULL), r);
-
- /* and return gracefully */
- return OK;
-}
-
-
-/*
-** +-------------------------------------------------------+
-** | |
-** | the rewriting engine
-** | |
-** +-------------------------------------------------------+
-*/
-
-/*
- * Apply a complete rule set,
- * i.e. a list of rewrite rules
- */
-static int apply_rewrite_list(request_rec *r, apr_array_header_t *rewriterules,
- char *perdir)
-{
- rewriterule_entry *entries;
- rewriterule_entry *p;
- int i;
- int changed;
- int rc;
- int s;
-
- /*
- * Iterate over all existing rules
- */
- entries = (rewriterule_entry *)rewriterules->elts;
- changed = 0;
- loop:
- for (i = 0; i < rewriterules->nelts; i++) {
- p = &entries[i];
-
- /*
- * Ignore this rule on subrequests if we are explicitly
- * asked to do so or this is a proxy-throughput or a
- * forced redirect rule.
- */
- if (r->main != NULL &&
- (p->flags & RULEFLAG_IGNOREONSUBREQ ||
- p->flags & RULEFLAG_PROXY ||
- p->flags & RULEFLAG_FORCEREDIRECT )) {
- continue;
- }
-
- /*
- * Apply the current rule.
- */
- rc = apply_rewrite_rule(r, p, perdir);
- if (rc) {
- /*
- * Indicate a change if this was not a match-only rule.
- */
- if (rc != 2) {
- changed = 1;
- }
-
- /*
- * Pass-Through Feature (`RewriteRule .. .. [PT]'):
- * Because the Apache 1.x API is very limited we
- * need this hack to pass the rewritten URL to other
- * modules like mod_alias, mod_userdir, etc.
- */
- if (p->flags & RULEFLAG_PASSTHROUGH) {
- rewritelog(r, 2, "forcing '%s' to get passed through "
- "to next API URI-to-filename handler", r->filename);
- r->filename = apr_pstrcat(r->pool, "passthrough:",
- r->filename, NULL);
- changed = 1;
- break;
- }
-
- /*
- * Rule has the "forbidden" flag set which means that
- * we stop processing and indicate this to the caller.
- */
- if (p->flags & RULEFLAG_FORBIDDEN) {
- rewritelog(r, 2, "forcing '%s' to be forbidden", r->filename);
- r->filename = apr_pstrcat(r->pool, "forbidden:",
- r->filename, NULL);
- changed = 1;
- break;
- }
-
- /*
- * Rule has the "gone" flag set which means that
- * we stop processing and indicate this to the caller.
- */
- if (p->flags & RULEFLAG_GONE) {
- rewritelog(r, 2, "forcing '%s' to be gone", r->filename);
- r->filename = apr_pstrcat(r->pool, "gone:", r->filename, NULL);
- changed = 1;
- break;
- }
-
- /*
- * Stop processing also on proxy pass-through and
- * last-rule and new-round flags.
- */
- if (p->flags & RULEFLAG_PROXY) {
- break;
- }
- if (p->flags & RULEFLAG_LASTRULE) {
- break;
- }
-
- /*
- * On "new-round" flag we just start from the top of
- * the rewriting ruleset again.
- */
- if (p->flags & RULEFLAG_NEWROUND) {
- goto loop;
- }
-
- /*
- * If we are forced to skip N next rules, do it now.
- */
- if (p->skip > 0) {
- s = p->skip;
- while ( i < rewriterules->nelts
- && s > 0) {
- i++;
- p = &entries[i];
- s--;
- }
- }
- }
- else {
- /*
- * If current rule is chained with next rule(s),
- * skip all this next rule(s)
- */
- while ( i < rewriterules->nelts
- && p->flags & RULEFLAG_CHAIN) {
- i++;
- p = &entries[i];
- }
- }
- }
- return changed;
-}
-
-/*
- * Apply a single(!) rewrite rule
- */
-static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,
- char *perdir)
-{
- char *uri;
- char *output;
- const char *vary;
- char newuri[MAX_STRING_LEN];
- regex_t *regexp;
- regmatch_t regmatch[MAX_NMATCH];
- backrefinfo *briRR = NULL;
- backrefinfo *briRC = NULL;
- int prefixstrip;
- int failed;
- apr_array_header_t *rewriteconds;
- rewritecond_entry *conds;
- rewritecond_entry *c;
- int i;
- int rc;
-
- /*
- * Initialisation
- */
- uri = r->filename;
- regexp = p->regexp;
- output = p->output;
-
- /*
- * Add (perhaps splitted away) PATH_INFO postfix to URL to
- * make sure we really match against the complete URL.
- */
- if (perdir != NULL && r->path_info != NULL && r->path_info[0] != '\0') {
- rewritelog(r, 3, "[per-dir %s] add path info postfix: %s -> %s%s",
- perdir, uri, uri, r->path_info);
- uri = apr_pstrcat(r->pool, uri, r->path_info, NULL);
- }
-
- /*
- * On per-directory context (.htaccess) strip the location
- * prefix from the URL to make sure patterns apply only to
- * the local part. Additionally indicate this special
- * threatment in the logfile.
- */
- prefixstrip = 0;
- if (perdir != NULL) {
- if ( strlen(uri) >= strlen(perdir)
- && strncmp(uri, perdir, strlen(perdir)) == 0) {
- rewritelog(r, 3, "[per-dir %s] strip per-dir prefix: %s -> %s",
- perdir, uri, uri+strlen(perdir));
- uri = uri+strlen(perdir);
- prefixstrip = 1;
- }
- }
-
- /*
- * Try to match the URI against the RewriteRule pattern
- * and exit immeddiately if it didn't apply.
- */
- if (perdir == NULL) {
- rewritelog(r, 3, "applying pattern '%s' to uri '%s'",
- p->pattern, uri);
- }
- else {
- rewritelog(r, 3, "[per-dir %s] applying pattern '%s' to uri '%s'",
- perdir, p->pattern, uri);
- }
- rc = (ap_regexec(regexp, uri, regexp->re_nsub+1, regmatch, 0) == 0);
- if (! (( rc && !(p->flags & RULEFLAG_NOTMATCH)) ||
- (!rc && (p->flags & RULEFLAG_NOTMATCH)) ) ) {
- return 0;
- }
-
- /*
- * Else create the RewriteRule `regsubinfo' structure which
- * holds the substitution information.
- */
- briRR = (backrefinfo *)apr_palloc(r->pool, sizeof(backrefinfo));
- if (!rc && (p->flags & RULEFLAG_NOTMATCH)) {
- /* empty info on negative patterns */
- briRR->source = "";
- briRR->nsub = 0;
- }
- else {
- briRR->source = apr_pstrdup(r->pool, uri);
- briRR->nsub = regexp->re_nsub;
- memcpy((void *)(briRR->regmatch), (void *)(regmatch),
- sizeof(regmatch));
- }
-
- /*
- * Initiallally create the RewriteCond backrefinfo with
- * empty backrefinfo, i.e. not subst parts
- * (this one is adjusted inside apply_rewrite_cond() later!!)
- */
- briRC = (backrefinfo *)apr_pcalloc(r->pool, sizeof(backrefinfo));
- briRC->source = "";
- briRC->nsub = 0;
-
- /*
- * Ok, we already know the pattern has matched, but we now
- * additionally have to check for all existing preconditions
- * (RewriteCond) which have to be also true. We do this at
- * this very late stage to avoid unnessesary checks which
- * would slow down the rewriting engine!!
- */
- rewriteconds = p->rewriteconds;
- conds = (rewritecond_entry *)rewriteconds->elts;
- failed = 0;
- for (i = 0; i < rewriteconds->nelts; i++) {
- c = &conds[i];
- rc = apply_rewrite_cond(r, c, perdir, briRR, briRC);
- if (c->flags & CONDFLAG_ORNEXT) {
- /*
- * The "OR" case
- */
- if (rc == 0) {
- /* One condition is false, but another can be
- * still true, so we have to continue...
- */
- apr_table_unset(r->notes, VARY_KEY_THIS);
- continue;
- }
- else {
- /* One true condition is enough in "or" case, so
- * skip the other conditions which are "ornext"
- * chained
- */
- while ( i < rewriteconds->nelts
- && c->flags & CONDFLAG_ORNEXT) {
- i++;
- c = &conds[i];
- }
- continue;
- }
- }
- else {
- /*
- * The "AND" case, i.e. no "or" flag,
- * so a single failure means total failure.
- */
- if (rc == 0) {
- failed = 1;
- break;
- }
- }
- vary = apr_table_get(r->notes, VARY_KEY_THIS);
- if (vary != NULL) {
- apr_table_merge(r->notes, VARY_KEY, vary);
- apr_table_unset(r->notes, VARY_KEY_THIS);
- }
- }
- /* if any condition fails the complete rule fails */
- if (failed) {
- apr_table_unset(r->notes, VARY_KEY);
- apr_table_unset(r->notes, VARY_KEY_THIS);
- return 0;
- }
-
- /*
- * Regardless of what we do next, we've found a match. Check to see
- * if any of the request header fields were involved, and add them
- * to the Vary field of the response.
- */
- if ((vary = apr_table_get(r->notes, VARY_KEY)) != NULL) {
- apr_table_merge(r->headers_out, "Vary", vary);
- apr_table_unset(r->notes, VARY_KEY);
- }
-
- /*
- * If this is a pure matching rule (`RewriteRule <pat> -')
- * we stop processing and return immediately. The only thing
- * we have not to forget are the environment variables
- * (`RewriteRule <pat> - [E=...]')
- */
- if (strcmp(output, "-") == 0) {
- do_expand_env(r, p->env, briRR, briRC);
- if (p->forced_mimetype != NULL) {
- if (perdir == NULL) {
- /* In the per-server context we can force the MIME-type
- * the correct way by notifying our MIME-type hook handler
- * to do the job when the MIME-type API stage is reached.
- */
- rewritelog(r, 2, "remember %s to have MIME-type '%s'",
- r->filename, p->forced_mimetype);
- apr_table_setn(r->notes, REWRITE_FORCED_MIMETYPE_NOTEVAR,
- p->forced_mimetype);
- }
- else {
- /* In per-directory context we operate in the Fixup API hook
- * which is after the MIME-type hook, so our MIME-type handler
- * has no chance to set r->content_type. And because we are
- * in the situation where no substitution takes place no
- * sub-request will happen (which could solve the
- * restriction). As a workaround we do it ourself now
- * immediately although this is not strictly API-conforming.
- * But it's the only chance we have...
- */
- rewritelog(r, 1, "[per-dir %s] force %s to have MIME-type "
- "'%s'", perdir, r->filename, p->forced_mimetype);
- r->content_type = p->forced_mimetype;
- }
- }
- return 2;
- }
-
- /*
- * Ok, now we finally know all patterns have matched and
- * that there is something to replace, so we create the
- * substitution URL string in `newuri'.
- */
- do_expand(r, output, newuri, sizeof(newuri), briRR, briRC);
- if (perdir == NULL) {
- rewritelog(r, 2, "rewrite %s -> %s", uri, newuri);
- }
- else {
- rewritelog(r, 2, "[per-dir %s] rewrite %s -> %s", perdir, uri, newuri);
- }
-
- /*
- * Additionally do expansion for the environment variable
- * strings (`RewriteRule .. .. [E=<string>]').
- */
- do_expand_env(r, p->env, briRR, briRC);
-
- /*
- * Now replace API's knowledge of the current URI:
- * Replace r->filename with the new URI string and split out
- * an on-the-fly generated QUERY_STRING part into r->args
- */
- r->filename = apr_pstrdup(r->pool, newuri);
- splitout_queryargs(r, p->flags & RULEFLAG_QSAPPEND);
-
- /*
- * Again add the previously stripped per-directory location
- * prefix if the new URI is not a new one for this
- * location, i.e. if it's not starting with either a slash
- * or a fully qualified URL scheme.
- */
- if (prefixstrip && r->filename[0] != '/'
- && !is_absolute_uri(r->filename)) {
- rewritelog(r, 3, "[per-dir %s] add per-dir prefix: %s -> %s%s",
- perdir, r->filename, perdir, r->filename);
- r->filename = apr_pstrcat(r->pool, perdir, r->filename, NULL);
- }
-
- /*
- * If this rule is forced for proxy throughput
- * (`RewriteRule ... ... [P]') then emulate mod_proxy's
- * URL-to-filename handler to be sure mod_proxy is triggered
- * for this URL later in the Apache API. But make sure it is
- * a fully-qualified URL. (If not it is qualified with
- * ourself).
- */
- if (p->flags & RULEFLAG_PROXY) {
- fully_qualify_uri(r);
- if (perdir == NULL) {
- rewritelog(r, 2, "forcing proxy-throughput with %s", r->filename);
- }
- else {
- rewritelog(r, 2, "[per-dir %s] forcing proxy-throughput with %s",
- perdir, r->filename);
- }
- r->filename = apr_pstrcat(r->pool, "proxy:", r->filename, NULL);
- return 1;
- }
-
- /*
- * If this rule is explicitly forced for HTTP redirection
- * (`RewriteRule .. .. [R]') then force an external HTTP
- * redirect. But make sure it is a fully-qualified URL. (If
- * not it is qualified with ourself).
- */
- if (p->flags & RULEFLAG_FORCEREDIRECT) {
- fully_qualify_uri(r);
- if (perdir == NULL) {
- rewritelog(r, 2,
- "explicitly forcing redirect with %s", r->filename);
- }
- else {
- rewritelog(r, 2,
- "[per-dir %s] explicitly forcing redirect with %s",
- perdir, r->filename);
- }
- r->status = p->forced_responsecode;
- return 1;
- }
-
- /*
- * Special Rewriting Feature: Self-Reduction
- * We reduce the URL by stripping a possible
- * http[s]://<ourhost>[:<port>] prefix, i.e. a prefix which
- * corresponds to ourself. This is to simplify rewrite maps
- * and to avoid recursion, etc. When this prefix is not a
- * coincidence then the user has to use [R] explicitly (see
- * above).
- */
- reduce_uri(r);
-
- /*
- * If this rule is still implicitly forced for HTTP
- * redirection (`RewriteRule .. <scheme>://...') then
- * directly force an external HTTP redirect.
- */
- if (is_absolute_uri(r->filename)) {
- if (perdir == NULL) {
- rewritelog(r, 2,
- "implicitly forcing redirect (rc=%d) with %s",
- p->forced_responsecode, r->filename);
- }
- else {
- rewritelog(r, 2, "[per-dir %s] implicitly forcing redirect "
- "(rc=%d) with %s", perdir, p->forced_responsecode,
- r->filename);
- }
- r->status = p->forced_responsecode;
- return 1;
- }
-
- /*
- * Now we are sure it is not a fully qualified URL. But
- * there is still one special case left: A local rewrite in
- * per-directory context, i.e. a substitution URL which does
- * not start with a slash. Here we add again the initially
- * stripped per-directory prefix.
- */
- if (prefixstrip && r->filename[0] != '/') {
- rewritelog(r, 3, "[per-dir %s] add per-dir prefix: %s -> %s%s",
- perdir, r->filename, perdir, r->filename);
- r->filename = apr_pstrcat(r->pool, perdir, r->filename, NULL);
- }
-
- /*
- * Finally we had to remember if a MIME-type should be
- * forced for this URL (`RewriteRule .. .. [T=<type>]')
- * Later in the API processing phase this is forced by our
- * MIME API-hook function. This time its no problem even for
- * the per-directory context (where the MIME-type hook was
- * already processed) because a sub-request happens ;-)
- */
- if (p->forced_mimetype != NULL) {
- apr_table_setn(r->notes, REWRITE_FORCED_MIMETYPE_NOTEVAR,
- p->forced_mimetype);
- if (perdir == NULL) {
- rewritelog(r, 2, "remember %s to have MIME-type '%s'",
- r->filename, p->forced_mimetype);
- }
- else {
- rewritelog(r, 2,
- "[per-dir %s] remember %s to have MIME-type '%s'",
- perdir, r->filename, p->forced_mimetype);
- }
- }
-
- /*
- * Puuhhhhhhhh... WHAT COMPLICATED STUFF ;_)
- * But now we're done for this particular rule.
- */
- return 1;
-}
-
-static int apply_rewrite_cond(request_rec *r, rewritecond_entry *p,
- char *perdir, backrefinfo *briRR,
- backrefinfo *briRC)
-{
- char input[MAX_STRING_LEN];
- apr_finfo_t sb;
- request_rec *rsub;
- regmatch_t regmatch[MAX_NMATCH];
- int rc;
-
- /*
- * Construct the string we match against
- */
-
- do_expand(r, p->input, input, sizeof(input), briRR, briRC);
-
- /*
- * Apply the patterns
- */
-
- rc = 0;
- if (strcmp(p->pattern, "-f") == 0) {
- if (apr_stat(&sb, input, APR_FINFO_MIN, r->pool) == APR_SUCCESS) {
- if (sb.filetype == APR_REG) {
- rc = 1;
- }
- }
- }
- else if (strcmp(p->pattern, "-s") == 0) {
- if (apr_stat(&sb, input, APR_FINFO_MIN, r->pool) == APR_SUCCESS) {
- if ((sb.filetype == APR_REG) && sb.size > 0) {
- rc = 1;
- }
- }
- }
- else if (strcmp(p->pattern, "-l") == 0) {
-#if !defined(OS2)
- if (apr_lstat(&sb, input, APR_FINFO_MIN, r->pool) == APR_SUCCESS) {
- if (sb.filetype == APR_LNK) {
- rc = 1;
- }
- }
-#endif
- }
- else if (strcmp(p->pattern, "-d") == 0) {
- if (apr_stat(&sb, input, APR_FINFO_MIN, r->pool) == APR_SUCCESS) {
- if (sb.filetype == APR_DIR) {
- rc = 1;
- }
- }
- }
- else if (strcmp(p->pattern, "-U") == 0) {
- /* avoid infinite subrequest recursion */
- if (strlen(input) > 0 && subreq_ok(r)) {
-
- /* run a URI-based subrequest */
- rsub = ap_sub_req_lookup_uri(input, r, NULL);
-
- /* URI exists for any result up to 3xx, redirects allowed */
- if (rsub->status < 400)
- rc = 1;
-
- /* log it */
- rewritelog(r, 5, "RewriteCond URI (-U) check: "
- "path=%s -> status=%d", input, rsub->status);
-
- /* cleanup by destroying the subrequest */
- ap_destroy_sub_req(rsub);
- }
- }
- else if (strcmp(p->pattern, "-F") == 0) {
- /* avoid infinite subrequest recursion */
- if (strlen(input) > 0 && subreq_ok(r)) {
-
- /* process a file-based subrequest:
- * this differs from -U in that no path translation is done.
- */
- rsub = ap_sub_req_lookup_file(input, r, NULL);
-
- /* file exists for any result up to 2xx, no redirects */
- if (rsub->status < 300 &&
- /* double-check that file exists since default result is 200 */
- apr_stat(&sb, rsub->filename, APR_FINFO_MIN,
- r->pool) == APR_SUCCESS) {
- rc = 1;
- }
-
- /* log it */
- rewritelog(r, 5, "RewriteCond file (-F) check: path=%s "
- "-> file=%s status=%d", input, rsub->filename,
- rsub->status);
-
- /* cleanup by destroying the subrequest */
- ap_destroy_sub_req(rsub);
- }
- }
- else if (strlen(p->pattern) > 1 && *(p->pattern) == '>') {
- rc = (compare_lexicography(input, p->pattern+1) == 1 ? 1 : 0);
- }
- else if (strlen(p->pattern) > 1 && *(p->pattern) == '<') {
- rc = (compare_lexicography(input, p->pattern+1) == -1 ? 1 : 0);
- }
- else if (strlen(p->pattern) > 1 && *(p->pattern) == '=') {
- if (strcmp(p->pattern+1, "\"\"") == 0) {
- rc = (*input == '\0');
- }
- else {
- rc = (strcmp(input, p->pattern+1) == 0 ? 1 : 0);
- }
- }
- else {
- /* it is really a regexp pattern, so apply it */
- rc = (ap_regexec(p->regexp, input,
- p->regexp->re_nsub+1, regmatch,0) == 0);
-
- /* if it isn't a negated pattern and really matched
- we update the passed-through regex subst info structure */
- if (rc && !(p->flags & CONDFLAG_NOTMATCH)) {
- briRC->source = apr_pstrdup(r->pool, input);
- briRC->nsub = p->regexp->re_nsub;
- memcpy((void *)(briRC->regmatch), (void *)(regmatch),
- sizeof(regmatch));
- }
- }
-
- /* if this is a non-matching regexp, just negate the result */
- if (p->flags & CONDFLAG_NOTMATCH) {
- rc = !rc;
- }
-
- rewritelog(r, 4, "RewriteCond: input='%s' pattern='%s%s' => %s",
- input, (p->flags & CONDFLAG_NOTMATCH ? "!" : ""),
- p->pattern, rc ? "matched" : "not-matched");
-
- /* end just return the result */
- return rc;
-}
-
-
-/*
-** +-------------------------------------------------------+
-** | |
-** | URL transformation functions
-** | |
-** +-------------------------------------------------------+
-*/
-
-
-/*
-**
-** perform all the expansions on the input string
-** leaving the result in the supplied buffer
-**
-*/
-
-static void do_expand(request_rec *r, char *input, char *buffer, int nbuf,
- backrefinfo *briRR, backrefinfo *briRC)
-{
- char *inp, *outp;
- size_t span, space;
-
- /*
- * for security reasons this expansion must be perfomed in a
- * single pass, otherwise an attacker can arrange for the result
- * of an earlier expansion to include expansion specifiers that
- * are interpreted by a later expansion, producing results that
- * were not intended by the administrator.
- */
-
- inp = input;
- outp = buffer;
- space = nbuf - 1; /* room for '\0' */
-
- for (;;) {
- span = strcspn(inp, "$%");
- if (span > space) {
- span = space;
- }
- memcpy(outp, inp, span);
- inp += span;
- outp += span;
- space -= span;
- if (space == 0 || *inp == '\0') {
- break;
- }
- /* now we have a '$' or a '%' */
- if (inp[1] == '{') {
- char *endp;
- endp = find_closing_bracket(inp+2, '{', '}');
- if (endp == NULL) {
- goto skip;
- }
- /*
- * These lookups may be recursive in a very convoluted
- * fashion -- see the LA-U and LA-F variable expansion
- * prefixes -- so we copy lookup keys to a separate buffer
- * rather than adding zero bytes in order to use them in
- * place.
- */
- if (inp[0] == '$') {
- /* ${...} map lookup expansion */
- /*
- * To make rewrite maps useful the lookup key and
- * default values must be expanded, so we make
- * recursive calls to do the work. For security
- * reasons we must never expand a string that includes
- * verbatim data from the network. The recursion here
- * isn't a problem because the result of expansion is
- * only passed to lookup_map() so it cannot be
- * re-expanded, only re-looked-up. Another way of
- * looking at it is that the recursion is entirely
- * driven by the syntax of the nested curly brackets.
- */
- char *map, *key, *dflt, *result;
- char xkey[MAX_STRING_LEN];
- char xdflt[MAX_STRING_LEN];
- key = find_char_in_brackets(inp+2, ':', '{', '}');
- if (key == NULL)
- goto skip;
- map = apr_pstrndup(r->pool, inp+2, key-inp-2);
- dflt = find_char_in_brackets(key+1, '|', '{', '}');
- if (dflt == NULL) {
- key = apr_pstrndup(r->pool, key+1, endp-key-1);
- dflt = "";
- } else {
- key = apr_pstrndup(r->pool, key+1, dflt-key-1);
- dflt = apr_pstrndup(r->pool, dflt+1, endp-dflt-1);
- }
- do_expand(r, key, xkey, sizeof(xkey), briRR, briRC);
- result = lookup_map(r, map, xkey);
- if (result) {
- span = apr_cpystrn(outp, result, space) - outp;
- } else {
- do_expand(r, dflt, xdflt, sizeof(xdflt), briRR, briRC);
- span = apr_cpystrn(outp, xdflt, space) - outp;
- }
- }
- else if (inp[0] == '%') {
- /* %{...} variable lookup expansion */
- char *var;
- var = apr_pstrndup(r->pool, inp+2, endp-inp-2);
- span = apr_cpystrn(outp, lookup_variable(r, var), space) - outp;
- }
- else {
- span = 0;
- }
- inp = endp+1;
- outp += span;
- space -= span;
- continue;
- }
- else if (apr_isdigit(inp[1])) {
- int n = inp[1] - '0';
- backrefinfo *bri = NULL;
- if (inp[0] == '$') {
- /* $N RewriteRule regexp backref expansion */
- bri = briRR;
- }
- else if (inp[0] == '%') {
- /* %N RewriteCond regexp backref expansion */
- bri = briRC;
- }
- /* see ap_pregsub() in src/main/util.c */
- if (bri && n <= bri->nsub &&
- bri->regmatch[n].rm_eo > bri->regmatch[n].rm_so) {
- span = bri->regmatch[n].rm_eo - bri->regmatch[n].rm_so;
- if (span > space) {
- span = space;
- }
- memcpy(outp, bri->source + bri->regmatch[n].rm_so, span);
- outp += span;
- space -= span;
- }
- inp += 2;
- continue;
- }
- skip:
- *outp++ = *inp++;
- space--;
- }
- *outp++ = '\0';
-}
-
-
-/*
-**
-** perform all the expansions on the environment variables
-**
-*/
-
-static void do_expand_env(request_rec *r, char *env[],
- backrefinfo *briRR, backrefinfo *briRC)
-{
- int i;
- char buf[MAX_STRING_LEN];
-
- for (i = 0; env[i] != NULL; i++) {
- do_expand(r, env[i], buf, sizeof(buf), briRR, briRC);
- add_env_variable(r, buf);
- }
-}
-
-
-/*
-**
-** split out a QUERY_STRING part from
-** the current URI string
-**
-*/
-
-static void splitout_queryargs(request_rec *r, int qsappend)
-{
- char *q;
- char *olduri;
-
- q = strchr(r->filename, '?');
- if (q != NULL) {
- olduri = apr_pstrdup(r->pool, r->filename);
- *q++ = '\0';
- if (qsappend) {
- r->args = apr_pstrcat(r->pool, q, "&", r->args, NULL);
- }
- else {
- r->args = apr_pstrdup(r->pool, q);
- }
- if (strlen(r->args) == 0) {
- r->args = NULL;
- rewritelog(r, 3, "split uri=%s -> uri=%s, args=<none>", olduri,
- r->filename);
- }
- else {
- if (r->args[strlen(r->args)-1] == '&') {
- r->args[strlen(r->args)-1] = '\0';
- }
- rewritelog(r, 3, "split uri=%s -> uri=%s, args=%s", olduri,
- r->filename, r->args);
- }
- }
- return;
-}
-
-
-/*
-**
-** strip 'http[s]://ourhost/' from URI
-**
-*/
-
-static void reduce_uri(request_rec *r)
-{
- char *cp;
- unsigned short port;
- char *portp;
- char *hostp;
- char *url;
- char c;
- char host[LONG_STRING_LEN];
- char buf[MAX_STRING_LEN];
- char *olduri;
- int l;
-
- cp = (char *)ap_http_method(r);
- l = strlen(cp);
- if ( strlen(r->filename) > l+3
- && strncasecmp(r->filename, cp, l) == 0
- && r->filename[l] == ':'
- && r->filename[l+1] == '/'
- && r->filename[l+2] == '/' ) {
- /* there was really a rewrite to a remote path */
-
- olduri = apr_pstrdup(r->pool, r->filename); /* save for logging */
-
- /* cut the hostname and port out of the URI */
- apr_cpystrn(buf, r->filename+(l+3), sizeof(buf));
- hostp = buf;
- for (cp = hostp; *cp != '\0' && *cp != '/' && *cp != ':'; cp++)
- ;
- if (*cp == ':') {
- /* set host */
- *cp++ = '\0';
- apr_cpystrn(host, hostp, sizeof(host));
- /* set port */
- portp = cp;
- for (; *cp != '\0' && *cp != '/'; cp++)
- ;
- c = *cp;
- *cp = '\0';
- port = atoi(portp);
- *cp = c;
- /* set remaining url */
- url = cp;
- }
- else if (*cp == '/') {
- /* set host */
- *cp = '\0';
- apr_cpystrn(host, hostp, sizeof(host));
- *cp = '/';
- /* set port */
- port = ap_default_port(r);
- /* set remaining url */
- url = cp;
- }
- else {
- /* set host */
- apr_cpystrn(host, hostp, sizeof(host));
- /* set port */
- port = ap_default_port(r);
- /* set remaining url */
- url = "/";
- }
-
- /* now check whether we could reduce it to a local path... */
- if (ap_matches_request_vhost(r, host, port)) {
- /* this is our host, so only the URL remains */
- r->filename = apr_pstrdup(r->pool, url);
- rewritelog(r, 3, "reduce %s -> %s", olduri, r->filename);
- }
- }
- return;
-}
-
-
-/*
-**
-** add 'http[s]://ourhost[:ourport]/' to URI
-** if URI is still not fully qualified
-**
-*/
-
-static void fully_qualify_uri(request_rec *r)
-{
- char buf[32];
- const char *thisserver;
- char *thisport;
- int port;
-
- if (!is_absolute_uri(r->filename)) {
-
- thisserver = ap_get_server_name(r);
- port = ap_get_server_port(r);
- if (ap_is_default_port(port,r)) {
- thisport = "";
- }
- else {
- apr_snprintf(buf, sizeof(buf), ":%u", port);
- thisport = buf;
- }
-
- if (r->filename[0] == '/') {
- r->filename = apr_psprintf(r->pool, "%s://%s%s%s",
- ap_http_method(r), thisserver,
- thisport, r->filename);
- }
- else {
- r->filename = apr_psprintf(r->pool, "%s://%s%s/%s",
- ap_http_method(r), thisserver,
- thisport, r->filename);
- }
- }
- return;
-}
-
-
-/*
-**
-** return non-zero if the URI is absolute (includes a scheme etc.)
-**
-*/
-
-static int is_absolute_uri(char *uri)
-{
- int i = strlen(uri);
- if ( (i > 7 && strncasecmp(uri, "http://", 7) == 0)
- || (i > 8 && strncasecmp(uri, "https://", 8) == 0)
- || (i > 9 && strncasecmp(uri, "gopher://", 9) == 0)
- || (i > 6 && strncasecmp(uri, "ftp://", 6) == 0)
- || (i > 5 && strncasecmp(uri, "ldap:", 5) == 0)
- || (i > 5 && strncasecmp(uri, "news:", 5) == 0)
- || (i > 7 && strncasecmp(uri, "mailto:", 7) == 0) ) {
- return 1;
- }
- else {
- return 0;
- }
-}
-
-
-/*
-**
-** Expand tilde-paths (/~user) through Unix /etc/passwd
-** database information (or other OS-specific database)
-**
-*/
-#if APR_HAS_USER
-static char *expand_tildepaths(request_rec *r, char *uri)
-{
- char user[LONG_STRING_LEN];
- char *newuri;
- int i, j;
- char *homedir;
-
- newuri = uri;
- if (uri != NULL && strlen(uri) > 2 && uri[0] == '/' && uri[1] == '~') {
- /* cut out the username */
- for (j = 0, i = 2; j < sizeof(user)-1
- && uri[i] != '\0'
- && uri[i] != '/' ; ) {
- user[j++] = uri[i++];
- }
- user[j] = '\0';
-
- /* lookup username in systems passwd file */
- if (apr_get_home_directory(&homedir, user, r->pool) == APR_SUCCESS) {
- /* ok, user was found, so expand the ~user string */
- if (uri[i] != '\0') {
- /* ~user/anything... has to be expanded */
- if (homedir[strlen(homedir)-1] == '/') {
- homedir[strlen(homedir)-1] = '\0';
- }
- newuri = apr_pstrcat(r->pool, homedir, uri+i, NULL);
- }
- else {
- /* only ~user has to be expanded */
- newuri = homedir;
- }
- }
- }
- return newuri;
-}
-#endif /* if APR_HAS_USER */
-
-
-
-/*
-** +-------------------------------------------------------+
-** | |
-** | DBM hashfile support
-** | |
-** +-------------------------------------------------------+
-*/
-
-
-static char *lookup_map(request_rec *r, char *name, char *key)
-{
- rewrite_server_conf *conf;
- apr_array_header_t *rewritemaps;
- rewritemap_entry *entries;
- rewritemap_entry *s;
- char *value;
- apr_finfo_t st;
- apr_status_t rv;
- int i;
-
- /* get map configuration */
- conf = ap_get_module_config(r->server->module_config, &rewrite_module);
- rewritemaps = conf->rewritemaps;
-
- entries = (rewritemap_entry *)rewritemaps->elts;
- for (i = 0; i < rewritemaps->nelts; i++) {
- s = &entries[i];
- if (strcmp(s->name, name) == 0) {
- if (s->type == MAPTYPE_TXT) {
- if ((rv = apr_stat(&st, s->checkfile,
- APR_FINFO_MIN, r->pool)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "mod_rewrite: can't access text RewriteMap "
- "file %s", s->checkfile);
- rewritelog(r, 1, "can't open RewriteMap file, "
- "see error log");
- return NULL;
- }
- value = get_cache_string(cachep, s->name, CACHEMODE_TS,
- st.mtime, key);
- if (value == NULL) {
- rewritelog(r, 6, "cache lookup FAILED, forcing new "
- "map lookup");
- if ((value =
- lookup_map_txtfile(r, s->datafile, key)) != NULL) {
- rewritelog(r, 5, "map lookup OK: map=%s key=%s[txt] "
- "-> val=%s", s->name, key, value);
- set_cache_string(cachep, s->name, CACHEMODE_TS,
- st.mtime, key, value);
- return value;
- }
- else {
- rewritelog(r, 5, "map lookup FAILED: map=%s[txt] "
- "key=%s", s->name, key);
- set_cache_string(cachep, s->name, CACHEMODE_TS,
- st.mtime, key, "");
- return NULL;
- }
- }
- else {
- rewritelog(r, 5, "cache lookup OK: map=%s[txt] key=%s "
- "-> val=%s", s->name, key, value);
- return value[0] != '\0' ? value : NULL;
- }
- }
- else if (s->type == MAPTYPE_DBM) {
-#ifndef NO_DBM_REWRITEMAP
- if ((rv = apr_stat(&st, s->checkfile,
- APR_FINFO_MIN, r->pool)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "mod_rewrite: can't access DBM RewriteMap "
- "file %s", s->checkfile);
- rewritelog(r, 1, "can't open DBM RewriteMap file, "
- "see error log");
- return NULL;
- }
- value = get_cache_string(cachep, s->name, CACHEMODE_TS,
- st.mtime, key);
- if (value == NULL) {
- rewritelog(r, 6,
- "cache lookup FAILED, forcing new map lookup");
- if ((value =
- lookup_map_dbmfile(r, s->datafile, key)) != NULL) {
- rewritelog(r, 5, "map lookup OK: map=%s[dbm] key=%s "
- "-> val=%s", s->name, key, value);
- set_cache_string(cachep, s->name, CACHEMODE_TS,
- st.mtime, key, value);
- return value;
- }
- else {
- rewritelog(r, 5, "map lookup FAILED: map=%s[dbm] "
- "key=%s", s->name, key);
- set_cache_string(cachep, s->name, CACHEMODE_TS,
- st.mtime, key, "");
- return NULL;
- }
- }
- else {
- rewritelog(r, 5, "cache lookup OK: map=%s[dbm] key=%s "
- "-> val=%s", s->name, key, value);
- return value[0] != '\0' ? value : NULL;
- }
-#else
- return NULL;
-#endif
- }
- else if (s->type == MAPTYPE_PRG) {
- if ((value =
- lookup_map_program(r, s->fpin, s->fpout, key)) != NULL) {
- rewritelog(r, 5, "map lookup OK: map=%s key=%s -> val=%s",
- s->name, key, value);
- return value;
- }
- else {
- rewritelog(r, 5, "map lookup FAILED: map=%s key=%s",
- s->name, key);
- }
- }
- else if (s->type == MAPTYPE_INT) {
- if ((value = lookup_map_internal(r, s->func, key)) != NULL) {
- rewritelog(r, 5, "map lookup OK: map=%s key=%s -> val=%s",
- s->name, key, value);
- return value;
- }
- else {
- rewritelog(r, 5, "map lookup FAILED: map=%s key=%s",
- s->name, key);
- }
- }
- else if (s->type == MAPTYPE_RND) {
- if ((rv = apr_stat(&st, s->checkfile,
- APR_FINFO_MIN, r->pool)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "mod_rewrite: can't access text RewriteMap "
- "file %s", s->checkfile);
- rewritelog(r, 1, "can't open RewriteMap file, "
- "see error log");
- return NULL;
- }
- value = get_cache_string(cachep, s->name, CACHEMODE_TS,
- st.mtime, key);
- if (value == NULL) {
- rewritelog(r, 6, "cache lookup FAILED, forcing new "
- "map lookup");
- if ((value =
- lookup_map_txtfile(r, s->datafile, key)) != NULL) {
- rewritelog(r, 5, "map lookup OK: map=%s key=%s[txt] "
- "-> val=%s", s->name, key, value);
- set_cache_string(cachep, s->name, CACHEMODE_TS,
- st.mtime, key, value);
- }
- else {
- rewritelog(r, 5, "map lookup FAILED: map=%s[txt] "
- "key=%s", s->name, key);
- set_cache_string(cachep, s->name, CACHEMODE_TS,
- st.mtime, key, "");
- return NULL;
- }
- }
- else {
- rewritelog(r, 5, "cache lookup OK: map=%s[txt] key=%s "
- "-> val=%s", s->name, key, value);
- }
- if (value[0] != '\0') {
- value = select_random_value_part(r, value);
- rewritelog(r, 5, "randomly choosen the subvalue `%s'", value);
- }
- else {
- value = NULL;
- }
- return value;
- }
- }
- }
- return NULL;
-}
-
-static char *lookup_map_txtfile(request_rec *r, const char *file, char *key)
-{
- apr_file_t *fp = NULL;
- apr_status_t rc;
- char line[1024];
- char *value = NULL;
- char *cpT;
- size_t skip;
- char *curkey;
- char *curval;
-
- rc = apr_file_open(&fp, file, APR_READ, APR_OS_DEFAULT, r->pool);
- if (rc != APR_SUCCESS) {
- return NULL;
- }
-
- while (apr_file_gets(line, sizeof(line), fp) == APR_SUCCESS) {
- if (line[0] == '#')
- continue; /* ignore comments */
- cpT = line;
- curkey = cpT;
- skip = strcspn(cpT," \t\r\n");
- if (skip == 0)
- continue; /* ignore lines that start with a space, tab, CR, or LF */
- cpT += skip;
- *cpT = '\0';
- if (strcmp(curkey, key) != 0)
- continue; /* key does not match... */
-
- /* found a matching key; now extract and return the value */
- ++cpT;
- skip = strspn(cpT, " \t\r\n");
- cpT += skip;
- curval = cpT;
- skip = strcspn(cpT, " \t\r\n");
- if (skip == 0)
- continue; /* no value... */
- cpT += skip;
- *cpT = '\0';
- value = apr_pstrdup(r->pool, curval);
- break;
- }
- apr_file_close(fp);
- return value;
-}
-
-#ifndef NO_DBM_REWRITEMAP
-static char *lookup_map_dbmfile(request_rec *r, const char *file, char *key)
-{
- DBM *dbmfp = NULL;
- datum dbmkey;
- datum dbmval;
- char *value = NULL;
- char buf[MAX_STRING_LEN];
-
- dbmkey.dptr = key;
- dbmkey.dsize = strlen(key);
- if ((dbmfp = dbm_open(file, O_RDONLY, 0666)) != NULL) {
- dbmval = dbm_fetch(dbmfp, dbmkey);
- if (dbmval.dptr != NULL) {
- memcpy(buf, dbmval.dptr,
- dbmval.dsize < sizeof(buf)-1 ?
- dbmval.dsize : sizeof(buf)-1 );
- buf[dbmval.dsize] = '\0';
- value = apr_pstrdup(r->pool, buf);
- }
- dbm_close(dbmfp);
- }
- return value;
-}
-#endif
-
-static char *lookup_map_program(request_rec *r, apr_file_t *fpin,
- apr_file_t *fpout, char *key)
-{
- char buf[LONG_STRING_LEN];
- char c;
- int i;
- apr_size_t nbytes;
-
-#ifndef NO_WRITEV
- struct iovec iova[2];
- apr_size_t niov;
-#endif
-
- /* when `RewriteEngine off' was used in the per-server
- * context then the rewritemap-programs were not spawned.
- * In this case using such a map (usually in per-dir context)
- * is useless because it is not available.
- */
- if (fpin == NULL || fpout == NULL) {
- return NULL;
- }
-
- /* take the lock */
-
- if (rewrite_mapr_lock_acquire) {
- apr_lock_acquire(rewrite_mapr_lock_acquire);
- }
-
- /* write out the request key */
-#ifdef NO_WRITEV
- nbytes = strlen(key);
- apr_file_write(fpin, key, &nbytes);
- nbytes = 1;
- apr_file_write(fpin, "\n", &nbytes);
-#else
- iova[0].iov_base = key;
- iova[0].iov_len = strlen(key);
- iova[1].iov_base = "\n";
- iova[1].iov_len = 1;
-
- niov = 2;
- apr_file_writev(fpin, iova, niov, &nbytes);
-#endif
-
- /* read in the response value */
- i = 0;
- nbytes = 1;
- apr_file_read(fpout, &c, &nbytes);
- while (nbytes == 1 && (i < LONG_STRING_LEN-1)) {
- if (c == '\n') {
- break;
- }
- buf[i++] = c;
-
- apr_file_read(fpout, &c, &nbytes);
- }
- buf[i] = '\0';
-
- /* give the lock back */
- if (rewrite_mapr_lock_acquire) {
- apr_lock_release(rewrite_mapr_lock_acquire);
- }
-
- if (strcasecmp(buf, "NULL") == 0) {
- return NULL;
- }
- else {
- return apr_pstrdup(r->pool, buf);
- }
-}
-
-static char *lookup_map_internal(request_rec *r,
- char *(*func)(request_rec *, char *),
- char *key)
-{
- /* currently we just let the function convert
- the key to a corresponding value */
- return func(r, key);
-}
-
-static char *rewrite_mapfunc_toupper(request_rec *r, char *key)
-{
- char *value, *cp;
-
- for (cp = value = apr_pstrdup(r->pool, key); cp != NULL && *cp != '\0';
- cp++) {
- *cp = apr_toupper(*cp);
- }
- return value;
-}
-
-static char *rewrite_mapfunc_tolower(request_rec *r, char *key)
-{
- char *value, *cp;
-
- for (cp = value = apr_pstrdup(r->pool, key); cp != NULL && *cp != '\0';
- cp++) {
- *cp = apr_tolower(*cp);
- }
- return value;
-}
-
-static char *rewrite_mapfunc_escape(request_rec *r, char *key)
-{
- char *value;
-
- value = ap_escape_uri(r->pool, key);
- return value;
-}
-
-static char *rewrite_mapfunc_unescape(request_rec *r, char *key)
-{
- char *value;
-
- value = apr_pstrdup(r->pool, key);
- ap_unescape_url(value);
- return value;
-}
-
-static int rewrite_rand_init_done = 0;
-
-static void rewrite_rand_init(void)
-{
- if (!rewrite_rand_init_done) {
- srand((unsigned)(getpid()));
- rewrite_rand_init_done = 1;
- }
- return;
-}
-
-static int rewrite_rand(int l, int h)
-{
- rewrite_rand_init();
-
- /* Get [0,1) and then scale to the appropriate range. Note that using
- * a floating point value ensures that we use all bits of the rand()
- * result. Doing an integer modulus would only use the lower-order bits
- * which may not be as uniformly random.
- */
- return ((double)(rand() % RAND_MAX) / RAND_MAX) * (h - l + 1) + l;
-}
-
-static char *select_random_value_part(request_rec *r, char *value)
-{
- char *buf;
- int n, i, k;
-
- /* count number of distinct values */
- for (n = 1, i = 0; value[i] != '\0'; i++) {
- if (value[i] == '|') {
- n++;
- }
- }
-
- /* when only one value we have no option to choose */
- if (n == 1) {
- return value;
- }
-
- /* else randomly select one */
- k = rewrite_rand(1, n);
-
- /* and grep it out */
- for (n = 1, i = 0; value[i] != '\0'; i++) {
- if (n == k) {
- break;
- }
- if (value[i] == '|') {
- n++;
- }
- }
- buf = apr_pstrdup(r->pool, &value[i]);
- for (i = 0; buf[i] != '\0' && buf[i] != '|'; i++)
- ;
- buf[i] = '\0';
- return buf;
-}
-
-
-/*
-** +-------------------------------------------------------+
-** | |
-** | rewriting logfile support
-** | |
-** +-------------------------------------------------------+
-*/
-
-
-static void open_rewritelog(server_rec *s, apr_pool_t *p)
-{
- rewrite_server_conf *conf;
- const char *fname;
- apr_status_t rc;
- piped_log *pl;
- int rewritelog_flags = ( APR_WRITE | APR_APPEND | APR_CREATE );
- apr_fileperms_t rewritelog_mode = ( APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD );
-
- conf = ap_get_module_config(s->module_config, &rewrite_module);
-
- if (conf->rewritelogfile == NULL) {
- return;
- }
- if (*(conf->rewritelogfile) == '\0') {
- return;
- }
- if (conf->rewritelogfp != NULL) {
- return; /* virtual log shared w/ main server */
- }
-
- fname = ap_server_root_relative(p, conf->rewritelogfile);
-
- if (*conf->rewritelogfile == '|') {
- if ((pl = ap_open_piped_log(p, conf->rewritelogfile+1)) == NULL) {
- ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, s,
- "mod_rewrite: could not open reliable pipe "
- "to RewriteLog filter %s", conf->rewritelogfile+1);
- exit(1);
- }
- conf->rewritelogfp = ap_piped_log_write_fd(pl);
- }
- else if (*conf->rewritelogfile != '\0') {
- rc = apr_file_open(&conf->rewritelogfp, fname, rewritelog_flags, rewritelog_mode, p);
- if (rc != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rc, s,
- "mod_rewrite: could not open RewriteLog "
- "file %s", fname);
- exit(1);
- }
- }
- return;
-}
-
-static void rewritelog(request_rec *r, int level, const char *text, ...)
-{
- rewrite_server_conf *conf;
- conn_rec *conn;
- char *str1;
- char str2[512];
- char str3[1024];
- char type[20];
- char redir[20];
- va_list ap;
- int i;
- apr_size_t nbytes;
- request_rec *req;
- char *ruser;
- const char *rhost;
-
- va_start(ap, text);
- conf = ap_get_module_config(r->server->module_config, &rewrite_module);
- conn = r->connection;
-
- if (conf->rewritelogfp == NULL) {
- return;
- }
- if (conf->rewritelogfile == NULL) {
- return;
- }
- if (*(conf->rewritelogfile) == '\0') {
- return;
- }
-
- if (level > conf->rewriteloglevel) {
- return;
- }
-
- if (r->user == NULL) {
- ruser = "-";
- }
- else if (strlen(r->user) != 0) {
- ruser = r->user;
- }
- else {
- ruser = "\"\"";
- }
-
- rhost = ap_get_remote_host(conn, r->server->module_config,
- REMOTE_NOLOOKUP, NULL);
- if (rhost == NULL) {
- rhost = "UNKNOWN-HOST";
- }
-
- str1 = apr_pstrcat(r->pool, rhost, " ",
- (conn->remote_logname != NULL ?
- conn->remote_logname : "-"), " ",
- ruser, NULL);
- apr_vsnprintf(str2, sizeof(str2), text, ap);
-
- if (r->main == NULL) {
- strcpy(type, "initial");
- }
- else {
- strcpy(type, "subreq");
- }
-
- for (i = 0, req = r; req->prev != NULL; req = req->prev) {
- i++;
- }
- if (i == 0) {
- redir[0] = '\0';
- }
- else {
- apr_snprintf(redir, sizeof(redir), "/redir#%d", i);
- }
-
- apr_snprintf(str3, sizeof(str3),
- "%s %s [%s/sid#%lx][rid#%lx/%s%s] (%d) %s\n", str1,
- current_logtime(r), ap_get_server_name(r),
- (unsigned long)(r->server), (unsigned long)r,
- type, redir, level, str2);
-
- apr_lock_acquire(rewrite_log_lock);
- nbytes = strlen(str3);
- apr_file_write(conf->rewritelogfp, str3, &nbytes);
- apr_lock_release(rewrite_log_lock);
-
- va_end(ap);
- return;
-}
-
-static char *current_logtime(request_rec *r)
-{
- apr_exploded_time_t t;
- char tstr[80];
- apr_size_t len;
-
- apr_explode_localtime(&t, apr_time_now());
-
- apr_strftime(tstr, &len, 80, "[%d/%b/%Y:%H:%M:%S ", &t);
- apr_snprintf(tstr + strlen(tstr), 80-strlen(tstr), "%c%.2d%.2d]",
- t.tm_gmtoff < 0 ? '-' : '+',
- t.tm_gmtoff / (60*60), t.tm_gmtoff % (60*60));
- return apr_pstrdup(r->pool, tstr);
-}
-
-
-
-
-/*
-** +-------------------------------------------------------+
-** | |
-** | rewriting lockfile support
-** | |
-** +-------------------------------------------------------+
-*/
-
-#define REWRITELOCK_MODE ( APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD )
-
-static void rewritelock_create(server_rec *s, apr_pool_t *p)
-{
- apr_status_t rc;
-
- /* only operate if a lockfile is used */
- if (lockname == NULL || *(lockname) == '\0') {
- return;
- }
-
- /* fixup the path, especially for rewritelock_remove() */
- lockname = ap_server_root_relative(p, lockname);
-
- /* create the lockfile */
- rc = apr_lock_create (&rewrite_mapr_lock_acquire, APR_MUTEX, APR_LOCKALL, lockname, p);
- if (rc != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rc, s,
- "mod_rewrite: Parent could not create RewriteLock "
- "file %s", lockname);
- exit(1);
- }
-
- return;
-}
-
-static apr_status_t rewritelock_remove(void *data)
-{
- /* only operate if a lockfile is used */
- if (lockname == NULL || *(lockname) == '\0') {
- return APR_SUCCESS;
- }
-
- /* destroy the rewritelock */
- apr_lock_destroy (rewrite_mapr_lock_acquire);
- rewrite_mapr_lock_acquire = NULL;
- lockname = NULL;
- return(0);
-}
-
-
-/*
-** +-------------------------------------------------------+
-** | |
-** | program map support
-** | |
-** +-------------------------------------------------------+
-*/
-
-static void run_rewritemap_programs(server_rec *s, apr_pool_t *p)
-{
- rewrite_server_conf *conf;
- apr_file_t *fpin = NULL;
- apr_file_t *fpout = NULL;
- apr_file_t *fperr = NULL;
- apr_array_header_t *rewritemaps;
- rewritemap_entry *entries;
- rewritemap_entry *map;
- int i;
- apr_status_t rc;
-
- conf = ap_get_module_config(s->module_config, &rewrite_module);
-
- /* If the engine isn't turned on,
- * don't even try to do anything.
- */
- if (conf->state == ENGINE_DISABLED) {
- return;
- }
-
- rewritemaps = conf->rewritemaps;
- entries = (rewritemap_entry *)rewritemaps->elts;
- for (i = 0; i < rewritemaps->nelts; i++) {
- map = &entries[i];
- if (map->type != MAPTYPE_PRG) {
- continue;
- }
- if (map->datafile == NULL
- || *(map->datafile) == '\0'
- || map->fpin != NULL
- || map->fpout != NULL ) {
- continue;
- }
- fpin = NULL;
- fpout = NULL;
- rc = rewritemap_program_child(p, map->datafile,
- &fpout, &fpin, &fperr);
- if (rc != APR_SUCCESS || fpin == NULL || fpout == NULL) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rc, s,
- "mod_rewrite: could not fork child for "
- "RewriteMap process");
- exit(1);
- }
- map->fpin = fpin;
- map->fpout = fpout;
- map->fperr = fperr;
- }
- return;
-}
-
-/* child process code */
-static apr_status_t rewritemap_program_child(apr_pool_t *p, const char *progname,
- apr_file_t **fpout, apr_file_t **fpin,
- apr_file_t **fperr)
-{
- apr_status_t rc;
- apr_procattr_t *procattr;
- apr_proc_t *procnew;
-
-#ifdef SIGHUP
- apr_signal(SIGHUP, SIG_IGN);
-#endif
-
-
- if (((rc = apr_procattr_create(&procattr, p)) != APR_SUCCESS) ||
- ((rc = apr_procattr_io_set(procattr, APR_FULL_BLOCK,
- APR_FULL_NONBLOCK,
- APR_FULL_NONBLOCK)) != APR_SUCCESS) ||
- ((rc = apr_procattr_dir_set(procattr,
- ap_make_dirstr_parent(p, progname)))
- != APR_SUCCESS) ||
- ((rc = apr_procattr_cmdtype_set(procattr, APR_PROGRAM)) != APR_SUCCESS)) {
- /* Something bad happened, give up and go away. */
- }
- else {
- procnew = apr_pcalloc(p, sizeof(*procnew));
- rc = apr_proc_create(procnew, progname, NULL, NULL, procattr, p);
-
- if (rc == APR_SUCCESS) {
- apr_pool_note_subprocess(p, procnew, kill_after_timeout);
-
- if (fpin) {
- (*fpin) = procnew->in;
- }
-
- if (fpout) {
- (*fpout) = procnew->out;
- }
-
- if (fperr) {
- (*fperr) = procnew->err;
- }
- }
- }
-
- return (rc);
-}
-
-
-
-
-/*
-** +-------------------------------------------------------+
-** | |
-** | environment variable support
-** | |
-** +-------------------------------------------------------+
-*/
-
-
-static char *lookup_variable(request_rec *r, char *var)
-{
- const char *result;
- char resultbuf[LONG_STRING_LEN];
- apr_exploded_time_t tm;
- request_rec *rsub;
-
- result = NULL;
-
- /* HTTP headers */
- if (strcasecmp(var, "HTTP_USER_AGENT") == 0) {
- result = lookup_header(r, "User-Agent");
- }
- else if (strcasecmp(var, "HTTP_REFERER") == 0) {
- result = lookup_header(r, "Referer");
- }
- else if (strcasecmp(var, "HTTP_COOKIE") == 0) {
- result = lookup_header(r, "Cookie");
- }
- else if (strcasecmp(var, "HTTP_FORWARDED") == 0) {
- result = lookup_header(r, "Forwarded");
- }
- else if (strcasecmp(var, "HTTP_HOST") == 0) {
- result = lookup_header(r, "Host");
- }
- else if (strcasecmp(var, "HTTP_PROXY_CONNECTION") == 0) {
- result = lookup_header(r, "Proxy-Connection");
- }
- else if (strcasecmp(var, "HTTP_ACCEPT") == 0) {
- result = lookup_header(r, "Accept");
- }
- /* all other headers from which we are still not know about */
- else if (strlen(var) > 5 && strncasecmp(var, "HTTP:", 5) == 0) {
- result = lookup_header(r, var+5);
- }
-
- /* connection stuff */
- else if (strcasecmp(var, "REMOTE_ADDR") == 0) {
- result = r->connection->remote_ip;
- }
- else if (strcasecmp(var, "REMOTE_HOST") == 0) {
- result = (char *)ap_get_remote_host(r->connection,
- r->per_dir_config, REMOTE_NAME, NULL);
- }
- else if (strcasecmp(var, "REMOTE_USER") == 0) {
- result = r->user;
- }
- else if (strcasecmp(var, "REMOTE_IDENT") == 0) {
- result = (char *)ap_get_remote_logname(r);
- }
-
- /* request stuff */
- else if (strcasecmp(var, "THE_REQUEST") == 0) { /* non-standard */
- result = r->the_request;
- }
- else if (strcasecmp(var, "REQUEST_METHOD") == 0) {
- result = r->method;
- }
- else if (strcasecmp(var, "REQUEST_URI") == 0) { /* non-standard */
- result = r->uri;
- }
- else if (strcasecmp(var, "SCRIPT_FILENAME") == 0 ||
- strcasecmp(var, "REQUEST_FILENAME") == 0 ) {
- result = r->filename;
- }
- else if (strcasecmp(var, "PATH_INFO") == 0) {
- result = r->path_info;
- }
- else if (strcasecmp(var, "QUERY_STRING") == 0) {
- result = r->args;
- }
- else if (strcasecmp(var, "AUTH_TYPE") == 0) {
- result = r->ap_auth_type;
- }
- else if (strcasecmp(var, "IS_SUBREQ") == 0) { /* non-standard */
- result = (r->main != NULL ? "true" : "false");
- }
-
- /* internal server stuff */
- else if (strcasecmp(var, "DOCUMENT_ROOT") == 0) {
- result = ap_document_root(r);
- }
- else if (strcasecmp(var, "SERVER_ADMIN") == 0) {
- result = r->server->server_admin;
- }
- else if (strcasecmp(var, "SERVER_NAME") == 0) {
- result = ap_get_server_name(r);
- }
- else if (strcasecmp(var, "SERVER_ADDR") == 0) { /* non-standard */
- result = r->connection->local_ip;
- }
- else if (strcasecmp(var, "SERVER_PORT") == 0) {
- apr_snprintf(resultbuf, sizeof(resultbuf), "%u", ap_get_server_port(r));
- result = resultbuf;
- }
- else if (strcasecmp(var, "SERVER_PROTOCOL") == 0) {
- result = r->protocol;
- }
- else if (strcasecmp(var, "SERVER_SOFTWARE") == 0) {
- result = ap_get_server_version();
- }
- else if (strcasecmp(var, "API_VERSION") == 0) { /* non-standard */
- apr_snprintf(resultbuf, sizeof(resultbuf), "%d:%d",
- MODULE_MAGIC_NUMBER_MAJOR, MODULE_MAGIC_NUMBER_MINOR);
- result = resultbuf;
- }
-
-/* XXX: wow this has gotta be slow if you actually use it for a lot, recalculates exploded time for each variable */
- /* underlaying Unix system stuff */
- else if (strcasecmp(var, "TIME_YEAR") == 0) {
- apr_explode_localtime(&tm, apr_time_now());
- apr_snprintf(resultbuf, sizeof(resultbuf), "%04d", tm.tm_year + 1900);
- result = resultbuf;
- }
-#define MKTIMESTR(format, tmfield) \
- apr_explode_localtime(&tm, apr_time_now()); \
- apr_snprintf(resultbuf, sizeof(resultbuf), format, tm.tmfield); \
- result = resultbuf;
- else if (strcasecmp(var, "TIME_MON") == 0) {
- MKTIMESTR("%02d", tm_mon+1)
- }
- else if (strcasecmp(var, "TIME_DAY") == 0) {
- MKTIMESTR("%02d", tm_mday)
- }
- else if (strcasecmp(var, "TIME_HOUR") == 0) {
- MKTIMESTR("%02d", tm_hour)
- }
- else if (strcasecmp(var, "TIME_MIN") == 0) {
- MKTIMESTR("%02d", tm_min)
- }
- else if (strcasecmp(var, "TIME_SEC") == 0) {
- MKTIMESTR("%02d", tm_sec)
- }
- else if (strcasecmp(var, "TIME_WDAY") == 0) {
- MKTIMESTR("%d", tm_wday)
- }
- else if (strcasecmp(var, "TIME") == 0) {
- apr_explode_localtime(&tm, apr_time_now());
- apr_snprintf(resultbuf, sizeof(resultbuf),
- "%04d%02d%02d%02d%02d%02d", tm.tm_year + 1900,
- tm.tm_mon+1, tm.tm_mday,
- tm.tm_hour, tm.tm_min, tm.tm_sec);
- result = resultbuf;
- rewritelog(r, 1, "RESULT='%s'", result);
- }
-
- /* all other env-variables from the parent Apache process */
- else if (strlen(var) > 4 && strncasecmp(var, "ENV:", 4) == 0) {
- /* first try the internal Apache notes structure */
- result = apr_table_get(r->notes, var+4);
- /* second try the internal Apache env structure */
- if (result == NULL) {
- result = apr_table_get(r->subprocess_env, var+4);
- }
- /* third try the external OS env */
- if (result == NULL) {
- result = getenv(var+4);
- }
- }
-
-#define LOOKAHEAD(subrecfunc) \
- if ( \
- /* filename is safe to use */ \
- r->filename != NULL \
- /* - and we're either not in a subrequest */ \
- && ( r->main == NULL \
- /* - or in a subrequest where paths are non-NULL... */ \
- || ( r->main->uri != NULL && r->uri != NULL \
- /* ...and sub and main paths differ */ \
- && strcmp(r->main->uri, r->uri) != 0))) { \
- /* process a file-based subrequest */ \
- rsub = subrecfunc(r->filename, r, NULL); \
- /* now recursively lookup the variable in the sub_req */ \
- result = lookup_variable(rsub, var+5); \
- /* copy it up to our scope before we destroy sub_req's apr_pool_t */ \
- result = apr_pstrdup(r->pool, result); \
- /* cleanup by destroying the subrequest */ \
- ap_destroy_sub_req(rsub); \
- /* log it */ \
- rewritelog(r, 5, "lookahead: path=%s var=%s -> val=%s", \
- r->filename, var+5, result); \
- /* return ourself to prevent re-pstrdup */ \
- return (char *)result; \
- }
-
- /* look-ahead for parameter through URI-based sub-request */
- else if (strlen(var) > 5 && strncasecmp(var, "LA-U:", 5) == 0) {
- LOOKAHEAD(ap_sub_req_lookup_uri)
- }
- /* look-ahead for parameter through file-based sub-request */
- else if (strlen(var) > 5 && strncasecmp(var, "LA-F:", 5) == 0) {
- LOOKAHEAD(ap_sub_req_lookup_file)
- }
-
- /* file stuff */
- else if (strcasecmp(var, "SCRIPT_USER") == 0) {
- result = "<unknown>";
- if (r->finfo.valid & APR_FINFO_USER) {
- apr_get_username((char **)&result, r->finfo.user, r->pool);
- }
- }
- else if (strcasecmp(var, "SCRIPT_GROUP") == 0) {
- result = "<unknown>";
- if (r->finfo.valid & APR_FINFO_GROUP) {
- apr_get_groupname((char **)&result, r->finfo.group, r->pool);
- }
- }
-
- if (result == NULL) {
- return apr_pstrdup(r->pool, "");
- }
- else {
- return apr_pstrdup(r->pool, result);
- }
-}
-
-static char *lookup_header(request_rec *r, const char *name)
-{
- apr_array_header_t *hdrs_arr;
- apr_table_entry_t *hdrs;
- int i;
-
- hdrs_arr = apr_table_elts(r->headers_in);
- hdrs = (apr_table_entry_t *)hdrs_arr->elts;
- for (i = 0; i < hdrs_arr->nelts; ++i) {
- if (hdrs[i].key == NULL) {
- continue;
- }
- if (strcasecmp(hdrs[i].key, name) == 0) {
- apr_table_merge(r->notes, VARY_KEY_THIS, name);
- return hdrs[i].val;
- }
- }
- return NULL;
-}
-
-
-
-
-/*
-** +-------------------------------------------------------+
-** | |
-** | caching support
-** | |
-** +-------------------------------------------------------+
-*/
-
-
-static cache *init_cache(apr_pool_t *p)
-{
- cache *c;
-
- c = (cache *)apr_palloc(p, sizeof(cache));
- if (apr_pool_create(&c->pool, p) != APR_SUCCESS)
- return NULL;
- c->lists = apr_array_make(c->pool, 2, sizeof(cachelist));
- return c;
-}
-
-static void set_cache_string(cache *c, const char *res, int mode, apr_time_t t,
- char *key, char *value)
-{
- cacheentry ce;
-
- ce.time = t;
- ce.key = key;
- ce.value = value;
- store_cache_string(c, res, &ce);
- return;
-}
-
-static char *get_cache_string(cache *c, const char *res, int mode,
- apr_time_t t, char *key)
-{
- cacheentry *ce;
-
- ce = retrieve_cache_string(c, res, key);
- if (ce == NULL) {
- return NULL;
- }
- if (mode & CACHEMODE_TS) {
- if (t != ce->time) {
- return NULL;
- }
- }
- else if (mode & CACHEMODE_TTL) {
- if (t > ce->time) {
- return NULL;
- }
- }
- return apr_pstrdup(c->pool, ce->value);
-}
-
-static int cache_tlb_hash(char *key)
-{
- unsigned long n;
- char *p;
-
- n = 0;
- for (p = key; *p != '\0'; p++) {
- n = ((n << 5) + n) ^ (unsigned long)(*p++);
- }
-
- return n % CACHE_TLB_ROWS;
-}
-
-static cacheentry *cache_tlb_lookup(cachetlbentry *tlb, cacheentry *elt,
- char *key)
-{
- int ix = cache_tlb_hash(key);
- int i;
- int j;
-
- for (i=0; i < CACHE_TLB_COLS; ++i) {
- j = tlb[ix].t[i];
- if (j < 0)
- return NULL;
- if (strcmp(elt[j].key, key) == 0)
- return &elt[j];
- }
- return NULL;
-}
-
-static void cache_tlb_replace(cachetlbentry *tlb, cacheentry *elt,
- cacheentry *e)
-{
- int ix = cache_tlb_hash(e->key);
- int i;
-
- tlb = &tlb[ix];
-
- for (i=1; i < CACHE_TLB_COLS; ++i)
- tlb->t[i] = tlb->t[i-1];
-
- tlb->t[0] = e - elt;
-}
-
-static void store_cache_string(cache *c, const char *res, cacheentry *ce)
-{
- int i;
- int j;
- cachelist *l;
- cacheentry *e;
- cachetlbentry *t;
- int found_list;
-
- found_list = 0;
- /* first try to edit an existing entry */
- for (i = 0; i < c->lists->nelts; i++) {
- l = &(((cachelist *)c->lists->elts)[i]);
- if (strcmp(l->resource, res) == 0) {
- found_list = 1;
-
- e = cache_tlb_lookup((cachetlbentry *)l->tlb->elts,
- (cacheentry *)l->entries->elts, ce->key);
- if (e != NULL) {
- e->time = ce->time;
- e->value = apr_pstrdup(c->pool, ce->value);
- return;
- }
-
- for (j = 0; j < l->entries->nelts; j++) {
- e = &(((cacheentry *)l->entries->elts)[j]);
- if (strcmp(e->key, ce->key) == 0) {
- e->time = ce->time;
- e->value = apr_pstrdup(c->pool, ce->value);
- cache_tlb_replace((cachetlbentry *)l->tlb->elts,
- (cacheentry *)l->entries->elts, e);
- return;
- }
- }
- }
- }
-
- /* create a needed new list */
- if (!found_list) {
- l = apr_array_push(c->lists);
- l->resource = apr_pstrdup(c->pool, res);
- l->entries = apr_array_make(c->pool, 2, sizeof(cacheentry));
- l->tlb = apr_array_make(c->pool, CACHE_TLB_ROWS,
- sizeof(cachetlbentry));
- for (i=0; i<CACHE_TLB_ROWS; ++i) {
- t = &((cachetlbentry *)l->tlb->elts)[i];
- for (j=0; j<CACHE_TLB_COLS; ++j)
- t->t[j] = -1;
- }
- }
-
- /* create the new entry */
- for (i = 0; i < c->lists->nelts; i++) {
- l = &(((cachelist *)c->lists->elts)[i]);
- if (strcmp(l->resource, res) == 0) {
- e = apr_array_push(l->entries);
- e->time = ce->time;
- e->key = apr_pstrdup(c->pool, ce->key);
- e->value = apr_pstrdup(c->pool, ce->value);
- cache_tlb_replace((cachetlbentry *)l->tlb->elts,
- (cacheentry *)l->entries->elts, e);
- return;
- }
- }
-
- /* not reached, but when it is no problem... */
- return;
-}
-
-static cacheentry *retrieve_cache_string(cache *c, const char *res, char *key)
-{
- int i;
- int j;
- cachelist *l;
- cacheentry *e;
-
- for (i = 0; i < c->lists->nelts; i++) {
- l = &(((cachelist *)c->lists->elts)[i]);
- if (strcmp(l->resource, res) == 0) {
-
- e = cache_tlb_lookup((cachetlbentry *)l->tlb->elts,
- (cacheentry *)l->entries->elts, key);
- if (e != NULL)
- return e;
-
- for (j = 0; j < l->entries->nelts; j++) {
- e = &(((cacheentry *)l->entries->elts)[j]);
- if (strcmp(e->key, key) == 0) {
- return e;
- }
- }
- }
- }
- return NULL;
-}
-
-
-
-
-/*
-** +-------------------------------------------------------+
-** | |
-** | misc functions
-** | |
-** +-------------------------------------------------------+
-*/
-
-static char *subst_prefix_path(request_rec *r, char *input, char *match,
- const char *subst)
-{
- char matchbuf[LONG_STRING_LEN];
- char substbuf[LONG_STRING_LEN];
- char *output;
- int l;
-
- output = input;
-
- /* first create a match string which always has a trailing slash */
- l = apr_cpystrn(matchbuf, match, sizeof(matchbuf)) - matchbuf;
- if (matchbuf[l-1] != '/') {
- matchbuf[l] = '/';
- matchbuf[l+1] = '\0';
- l++;
- }
- /* now compare the prefix */
- if (strncmp(input, matchbuf, l) == 0) {
- rewritelog(r, 5, "strip matching prefix: %s -> %s", output, output+l);
- output = apr_pstrdup(r->pool, output+l);
-
- /* and now add the base-URL as replacement prefix */
- l = apr_cpystrn(substbuf, subst, sizeof(substbuf)) - substbuf;
- if (substbuf[l-1] != '/') {
- substbuf[l] = '/';
- substbuf[l+1] = '\0';
- l++;
- }
- if (output[0] == '/') {
- rewritelog(r, 4, "add subst prefix: %s -> %s%s",
- output, substbuf, output+1);
- output = apr_pstrcat(r->pool, substbuf, output+1, NULL);
- }
- else {
- rewritelog(r, 4, "add subst prefix: %s -> %s%s",
- output, substbuf, output);
- output = apr_pstrcat(r->pool, substbuf, output, NULL);
- }
- }
- return output;
-}
-
-
-/*
-**
-** own command line parser which don't have the '\\' problem
-**
-*/
-
-static int parseargline(char *str, char **a1, char **a2, char **a3)
-{
- char *cp;
- int isquoted;
-
-#define SKIP_WHITESPACE(cp) \
- for ( ; *cp == ' ' || *cp == '\t'; ) { \
- cp++; \
- };
-
-#define CHECK_QUOTATION(cp,isquoted) \
- isquoted = 0; \
- if (*cp == '"') { \
- isquoted = 1; \
- cp++; \
- }
-
-#define DETERMINE_NEXTSTRING(cp,isquoted) \
- for ( ; *cp != '\0'; cp++) { \
- if ( (isquoted && (*cp == ' ' || *cp == '\t')) \
- || (*cp == '\\' && (*(cp+1) == ' ' || *(cp+1) == '\t'))) { \
- cp++; \
- continue; \
- } \
- if ( (!isquoted && (*cp == ' ' || *cp == '\t')) \
- || (isquoted && *cp == '"') ) { \
- break; \
- } \
- }
-
- cp = str;
- SKIP_WHITESPACE(cp);
-
- /* determine first argument */
- CHECK_QUOTATION(cp, isquoted);
- *a1 = cp;
- DETERMINE_NEXTSTRING(cp, isquoted);
- if (*cp == '\0') {
- return 1;
- }
- *cp++ = '\0';
-
- SKIP_WHITESPACE(cp);
-
- /* determine second argument */
- CHECK_QUOTATION(cp, isquoted);
- *a2 = cp;
- DETERMINE_NEXTSTRING(cp, isquoted);
- if (*cp == '\0') {
- *cp++ = '\0';
- *a3 = NULL;
- return 0;
- }
- *cp++ = '\0';
-
- SKIP_WHITESPACE(cp);
-
- /* again check if there are only two arguments */
- if (*cp == '\0') {
- *cp++ = '\0';
- *a3 = NULL;
- return 0;
- }
-
- /* determine second argument */
- CHECK_QUOTATION(cp, isquoted);
- *a3 = cp;
- DETERMINE_NEXTSTRING(cp, isquoted);
- *cp++ = '\0';
-
- return 0;
-}
-
-
-static void add_env_variable(request_rec *r, char *s)
-{
- char var[MAX_STRING_LEN];
- char val[MAX_STRING_LEN];
- char *cp;
- int n;
-
- if ((cp = strchr(s, ':')) != NULL) {
- n = ((cp-s) > MAX_STRING_LEN-1 ? MAX_STRING_LEN-1 : (cp-s));
- memcpy(var, s, n);
- var[n] = '\0';
- apr_cpystrn(val, cp+1, sizeof(val));
- apr_table_set(r->subprocess_env, var, val);
- rewritelog(r, 5, "setting env variable '%s' to '%s'", var, val);
- }
-}
-
-
-/*
-**
-** check that a subrequest won't cause infinite recursion
-**
-*/
-
-static int subreq_ok(request_rec *r)
-{
- /*
- * either not in a subrequest, or in a subrequest
- * and URIs aren't NULL and sub/main URIs differ
- */
- return (r->main == NULL ||
- (r->main->uri != NULL && r->uri != NULL &&
- strcmp(r->main->uri, r->uri) != 0));
-}
-
-
-/*
-**
-** stat() for only the prefix of a path
-**
-*/
-
-static int prefix_stat(const char *path, apr_finfo_t *sb)
-{
- char curpath[LONG_STRING_LEN];
- char *cp;
-
- apr_cpystrn(curpath, path, sizeof(curpath));
- if (curpath[0] != '/') {
- return 0;
- }
- if ((cp = strchr(curpath+1, '/')) != NULL) {
- *cp = '\0';
- }
- if (apr_stat(sb, curpath, APR_FINFO_MIN, NULL) == APR_SUCCESS) {
- return 1;
- }
- else {
- return 0;
- }
-}
-
-
-/*
-**
-** Lexicographic Compare
-**
-*/
-
-static int compare_lexicography(char *cpNum1, char *cpNum2)
-{
- int i;
- int n1, n2;
-
- n1 = strlen(cpNum1);
- n2 = strlen(cpNum2);
- if (n1 > n2) {
- return 1;
- }
- if (n1 < n2) {
- return -1;
- }
- for (i = 0; i < n1; i++) {
- if (cpNum1[i] > cpNum2[i]) {
- return 1;
- }
- if (cpNum1[i] < cpNum2[i]) {
- return -1;
- }
- }
- return 0;
-}
-
-/*
-**
-** Bracketed expression handling
-** s points after the opening bracket
-**
-*/
-
-static char *find_closing_bracket(char *s, int left, int right)
-{
- int depth;
-
- for (depth = 1; *s; ++s) {
- if (*s == right && --depth == 0) {
- return s;
- }
- else if (*s == left) {
- ++depth;
- }
- }
- return NULL;
-}
-
-static char *find_char_in_brackets(char *s, int c, int left, int right)
-{
- int depth;
-
- for (depth = 1; *s; ++s) {
- if (*s == c && depth == 1) {
- return s;
- }
- else if (*s == right && --depth == 0) {
- return NULL;
- }
- else if (*s == left) {
- ++depth;
- }
- }
- return NULL;
-}
-
-/*
-**
-** Module paraphernalia
-**
-*/
-
-#ifdef NETWARE
-int main(int argc, char *argv[])
-{
- ExitThread(TSR_THREAD, 0);
-}
-#endif
-
- /* the apr_table_t of commands we provide */
-static const command_rec command_table[] = {
- AP_INIT_FLAG( "RewriteEngine", cmd_rewriteengine, NULL, OR_FILEINFO,
- "On or Off to enable or disable (default) the whole "
- "rewriting engine"),
- AP_INIT_ITERATE( "RewriteOptions", cmd_rewriteoptions, NULL, OR_FILEINFO,
- "List of option strings to set"),
- AP_INIT_TAKE1( "RewriteBase", cmd_rewritebase, NULL, OR_FILEINFO,
- "the base URL of the per-directory context"),
- AP_INIT_RAW_ARGS("RewriteCond", cmd_rewritecond, NULL, OR_FILEINFO,
- "an input string and a to be applied regexp-pattern"),
- AP_INIT_RAW_ARGS("RewriteRule", cmd_rewriterule, NULL, OR_FILEINFO,
- "an URL-applied regexp-pattern and a substitution URL"),
- AP_INIT_TAKE2( "RewriteMap", cmd_rewritemap, NULL, RSRC_CONF,
- "a mapname and a filename"),
- AP_INIT_TAKE1( "RewriteLock", cmd_rewritelock, NULL, RSRC_CONF,
- "the filename of a lockfile used for inter-process "
- "synchronization"),
- AP_INIT_TAKE1( "RewriteLog", cmd_rewritelog, NULL, RSRC_CONF,
- "the filename of the rewriting logfile"),
- AP_INIT_TAKE1( "RewriteLogLevel", cmd_rewriteloglevel, NULL, RSRC_CONF,
- "the level of the rewriting logfile verbosity "
- "(0=none, 1=std, .., 9=max)"),
- { NULL }
-};
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_handler(handler_redirect, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_post_config(init_module,NULL,NULL,APR_HOOK_MIDDLE);
- ap_hook_child_init(init_child,NULL,NULL,APR_HOOK_MIDDLE);
-
- ap_hook_fixups(hook_fixup,NULL,NULL,APR_HOOK_FIRST);
- ap_hook_translate_name(hook_uri2file,NULL,NULL,APR_HOOK_FIRST);
- ap_hook_type_checker(hook_mimetype,NULL,NULL,APR_HOOK_MIDDLE);
-}
-
- /* the main config structure */
-module AP_MODULE_DECLARE_DATA rewrite_module = {
- STANDARD20_MODULE_STUFF,
- config_perdir_create, /* create per-dir config structures */
- config_perdir_merge, /* merge per-dir config structures */
- config_server_create, /* create per-server config structures */
- config_server_merge, /* merge per-server config structures */
- command_table, /* apr_table_t of config file commands */
- register_hooks /* register hooks */
-};
-
-/*EOF*/
diff --git a/modules/mappers/mod_rewrite.dsp b/modules/mappers/mod_rewrite.dsp
deleted file mode 100644
index b88f0b0fce..0000000000
--- a/modules/mappers/mod_rewrite.dsp
+++ /dev/null
@@ -1,95 +0,0 @@
-# Microsoft Developer Studio Project File - Name="mod_rewrite" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=mod_rewrite - Win32 Release
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "mod_rewrite.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_rewrite.mak" CFG="mod_rewrite - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_rewrite - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_rewrite - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "mod_rewrite - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\os\win32" /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "NO_DBM_REWRITEMAP" /Fd"Release\mod_rewrite" /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "NDEBUG"
-# ADD RSC /l 0x809 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_rewrite.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_rewrite
-# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_rewrite.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_rewrite
-
-!ELSEIF "$(CFG)" == "mod_rewrite - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\..\include" /I "..\..\os\win32" /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "NO_DBM_REWRITEMAP" /Fd"Debug\mod_rewrite" /FD /c
-# ADD BASE MTL /nologo /D "_DEBUG" /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "_DEBUG"
-# ADD RSC /l 0x809 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /out:"Debug/mod_rewrite.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_rewrite
-# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /out:"Debug/mod_rewrite.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_rewrite
-
-!ENDIF
-
-# Begin Target
-
-# Name "mod_rewrite - Win32 Release"
-# Name "mod_rewrite - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\mod_rewrite.c
-# End Source File
-# End Target
-# End Project
diff --git a/modules/mappers/mod_rewrite.exp b/modules/mappers/mod_rewrite.exp
deleted file mode 100644
index 8f2165bfe0..0000000000
--- a/modules/mappers/mod_rewrite.exp
+++ /dev/null
@@ -1 +0,0 @@
-rewrite_module
diff --git a/modules/mappers/mod_rewrite.h b/modules/mappers/mod_rewrite.h
deleted file mode 100644
index f139877978..0000000000
--- a/modules/mappers/mod_rewrite.h
+++ /dev/null
@@ -1,473 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#ifndef MOD_REWRITE_H
-#define MOD_REWRITE_H 1
-
-/*
-** _ _ _
-** _ __ ___ ___ __| | _ __ _____ ___ __(_) |_ ___
-** | '_ ` _ \ / _ \ / _` | | '__/ _ \ \ /\ / / '__| | __/ _ \
-** | | | | | | (_) | (_| | | | | __/\ V V /| | | | || __/
-** |_| |_| |_|\___/ \__,_|___|_| \___| \_/\_/ |_| |_|\__\___|
-** |_____|
-**
-** URL Rewriting Module
-**
-** This module uses a rule-based rewriting engine (based on a
-** regular-expression parser) to rewrite requested URLs on the fly.
-**
-** It supports an unlimited number of additional rule conditions (which can
-** operate on a lot of variables, even on HTTP headers) for granular
-** matching and even external database lookups (either via plain text
-** tables, DBM hash files or even external processes) for advanced URL
-** substitution.
-**
-** It operates on the full URLs (including the PATH_INFO part) both in
-** per-server context (httpd.conf) and per-dir context (.htaccess) and even
-** can generate QUERY_STRING parts on result. The rewriting result finally
-** can lead to internal subprocessing, external request redirection or even
-** to internal proxy throughput.
-**
-** This module was originally written in April 1996 and
-** gifted exclusively to the The Apache Software Foundation in July 1997 by
-**
-** Ralf S. Engelschall
-** rse@engelschall.com
-** www.engelschall.com
-*/
-
-#include "apr.h"
-
-#define APR_WANT_STRFUNC
-#define APR_WANT_MEMFUNC
-#include "apr_want.h"
-
- /* Include from the underlaying Unix system ... */
-#if APR_HAVE_STDARG_H
-#include <stdarg.h>
-#endif
-#if APR_HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#if APR_HAVE_CTYPE_H
-#include <ctype.h>
-#endif
-#if APR_HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ap_config.h"
-
- /* Include from the Apache server ... */
-#define CORE_PRIVATE
-#include "httpd.h"
-#include "http_config.h"
-#include "http_request.h"
-#include "http_core.h"
-#include "http_log.h"
-#include "http_vhost.h"
-
- /*
- * The key in the r->notes apr_table_t wherein we store our accumulated
- * Vary values, and the one used for per-condition checks in a chain.
- */
-#define VARY_KEY "rewrite-Vary"
-#define VARY_KEY_THIS "rewrite-Vary-this"
-
- /* The NDBM support:
- * We support only NDBM files.
- * But we have to stat the file for the mtime,
- * so we also need to know the file extension
- */
-#ifndef NO_DBM_REWRITEMAP
-#if defined(__GLIBC__) && defined(__GLIBC_MINOR__) \
- && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
-#include <db1/ndbm.h>
-#else
-#include <ndbm.h>
-#endif
-#if defined(DBM_SUFFIX)
-#define NDBM_FILE_SUFFIX DBM_SUFFIX
-#elif defined(__FreeBSD__) || (defined(DB_LOCK) && defined(DB_SHMEM))
-#define NDBM_FILE_SUFFIX ".db"
-#else
-#define NDBM_FILE_SUFFIX ".pag"
-#endif
-#endif
-
-
-/*
-**
-** Some defines
-**
-*/
-
-#define ENVVAR_SCRIPT_URL "SCRIPT_URL"
-#define ENVVAR_SCRIPT_URI "SCRIPT_URI"
-
-#ifndef SUPPORT_DBM_REWRITEMAP
-#define SUPPORT_DBM_REWRITEMAP 0
-#endif
-
-#define REWRITE_FORCED_MIMETYPE_NOTEVAR "rewrite-forced-mimetype"
-
-#define CONDFLAG_NONE 1<<0
-#define CONDFLAG_NOCASE 1<<1
-#define CONDFLAG_NOTMATCH 1<<2
-#define CONDFLAG_ORNEXT 1<<3
-
-#define RULEFLAG_NONE 1<<0
-#define RULEFLAG_FORCEREDIRECT 1<<1
-#define RULEFLAG_LASTRULE 1<<2
-#define RULEFLAG_NEWROUND 1<<3
-#define RULEFLAG_CHAIN 1<<4
-#define RULEFLAG_IGNOREONSUBREQ 1<<5
-#define RULEFLAG_NOTMATCH 1<<6
-#define RULEFLAG_PROXY 1<<7
-#define RULEFLAG_PASSTHROUGH 1<<8
-#define RULEFLAG_FORBIDDEN 1<<9
-#define RULEFLAG_GONE 1<<10
-#define RULEFLAG_QSAPPEND 1<<11
-#define RULEFLAG_NOCASE 1<<12
-
-#define MAPTYPE_TXT 1<<0
-#define MAPTYPE_DBM 1<<1
-#define MAPTYPE_PRG 1<<2
-#define MAPTYPE_INT 1<<3
-#define MAPTYPE_RND 1<<4
-
-#define ENGINE_DISABLED 1<<0
-#define ENGINE_ENABLED 1<<1
-
-#define OPTION_NONE 1<<0
-#define OPTION_INHERIT 1<<1
-
-#define CACHEMODE_TS 1<<0
-#define CACHEMODE_TTL 1<<1
-
-#define CACHE_TLB_ROWS 1024
-#define CACHE_TLB_COLS 4
-
-#ifndef FALSE
-#define FALSE 0
-#define TRUE !FALSE
-#endif
-
-#ifndef NO
-#define NO FALSE
-#define YES TRUE
-#endif
-
-#ifndef RAND_MAX
-#define RAND_MAX 32767
-#endif
-
-#ifndef LONG_STRING_LEN
-#define LONG_STRING_LEN 2048
-#endif
-
-#define MAX_ENV_FLAGS 15
-
-#define MAX_NMATCH 10
-
-/*
-**
-** our private data structures we handle with
-**
-*/
-
- /* the list structures for holding the mapfile information
- * and the rewrite rules
- */
-typedef struct {
- const char *name; /* the name of the map */
- const char *datafile; /* filename for map data files */
- const char *checkfile; /* filename to check for map existence */
- int type; /* the type of the map */
- apr_file_t *fpin; /* in file pointer for program maps */
- apr_file_t *fpout; /* out file pointer for program maps */
- apr_file_t *fperr; /* err file pointer for program maps */
- char *(*func)(request_rec *, /* function pointer for internal maps */
- char *);
-} rewritemap_entry;
-
-typedef struct {
- char *input; /* Input string of RewriteCond */
- char *pattern; /* the RegExp pattern string */
- regex_t *regexp;
- int flags; /* Flags which control the match */
-} rewritecond_entry;
-
-typedef struct {
- apr_array_header_t *rewriteconds; /* the corresponding RewriteCond entries */
- char *pattern; /* the RegExp pattern string */
- regex_t *regexp; /* the RegExp pattern compilation */
- char *output; /* the Substitution string */
- int flags; /* Flags which control the substitution */
- char *forced_mimetype; /* forced MIME type of substitution */
- int forced_responsecode; /* forced HTTP redirect response status */
- char *env[MAX_ENV_FLAGS+1]; /* added environment variables */
- int skip; /* number of next rules to skip */
-} rewriterule_entry;
-
-
- /* the per-server or per-virtual-server configuration
- * statically generated once on startup for every server
- */
-typedef struct {
- int state; /* the RewriteEngine state */
- int options; /* the RewriteOption state */
- const char *rewritelogfile; /* the RewriteLog filename */
- apr_file_t *rewritelogfp; /* the RewriteLog open filepointer */
- int rewriteloglevel; /* the RewriteLog level of verbosity */
- apr_array_header_t *rewritemaps; /* the RewriteMap entries */
- apr_array_header_t *rewriteconds; /* the RewriteCond entries (temporary) */
- apr_array_header_t *rewriterules; /* the RewriteRule entries */
- server_rec *server; /* the corresponding server indicator */
-} rewrite_server_conf;
-
-
- /* the per-directory configuration
- * generated on-the-fly by Apache server for current request
- */
-typedef struct {
- int state; /* the RewriteEngine state */
- int options; /* the RewriteOption state */
- apr_array_header_t *rewriteconds; /* the RewriteCond entries (temporary) */
- apr_array_header_t *rewriterules; /* the RewriteRule entries */
- char *directory; /* the directory where it applies */
- const char *baseurl; /* the base-URL where it applies */
-} rewrite_perdir_conf;
-
-
- /* the cache structures,
- * a 4-way hash apr_table_t with LRU functionality
- */
-typedef struct cacheentry {
- apr_time_t time;
- char *key;
- char *value;
-} cacheentry;
-
-typedef struct tlbentry {
- int t[CACHE_TLB_COLS];
-} cachetlbentry;
-
-typedef struct cachelist {
- char *resource;
- apr_array_header_t *entries;
- apr_array_header_t *tlb;
-} cachelist;
-
-typedef struct cache {
- apr_pool_t *pool;
- apr_array_header_t *lists;
-} cache;
-
-
- /* the regex structure for the
- * substitution of backreferences
- */
-typedef struct backrefinfo {
- char *source;
- int nsub;
- regmatch_t regmatch[10];
-} backrefinfo;
-
-
-/*
-**
-** forward declarations
-**
-*/
-
- /* config structure handling */
-static void *config_server_create(apr_pool_t *p, server_rec *s);
-static void *config_server_merge (apr_pool_t *p, void *basev, void *overridesv);
-static void *config_perdir_create(apr_pool_t *p, char *path);
-static void *config_perdir_merge (apr_pool_t *p, void *basev, void *overridesv);
-
- /* config directive handling */
-static const char *cmd_rewriteengine(cmd_parms *cmd,
- void *dconf, int flag);
-static const char *cmd_rewriteoptions(cmd_parms *cmd,
- void *dconf,
- const char *option);
-static const char *cmd_rewriteoptions_setoption(apr_pool_t *p, int *options,
- const char *name);
-static const char *cmd_rewritelog (cmd_parms *cmd, void *dconf, const char *a1);
-static const char *cmd_rewriteloglevel(cmd_parms *cmd, void *dconf, const char *a1);
-static const char *cmd_rewritemap (cmd_parms *cmd, void *dconf,
- const char *a1, const char *a2);
-static const char *cmd_rewritelock(cmd_parms *cmd, void *dconf, const char *a1);
-static const char *cmd_rewritebase(cmd_parms *cmd, void *dconf,
- const char *a1);
-static const char *cmd_rewritecond(cmd_parms *cmd, void *dconf,
- const char *str);
-static const char *cmd_rewritecond_parseflagfield(apr_pool_t *p,
- rewritecond_entry *new,
- char *str);
-static const char *cmd_rewritecond_setflag(apr_pool_t *p, rewritecond_entry *cfg,
- char *key, char *val);
-static const char *cmd_rewriterule(cmd_parms *cmd, void *dconf,
- const char *str);
-static const char *cmd_rewriterule_parseflagfield(apr_pool_t *p,
- rewriterule_entry *new,
- char *str);
-static const char *cmd_rewriterule_setflag(apr_pool_t *p, rewriterule_entry *cfg,
- char *key, char *val);
-
- /* initialisation */
-static void init_module(apr_pool_t *p,
- apr_pool_t *plog,
- apr_pool_t *ptemp,
- server_rec *s);
-static void init_child(apr_pool_t *p, server_rec *s);
-
- /* runtime hooks */
-static int hook_uri2file (request_rec *r);
-static int hook_mimetype (request_rec *r);
-static int hook_fixup (request_rec *r);
-static int handler_redirect(request_rec *r);
-
- /* rewriting engine */
-static int apply_rewrite_list(request_rec *r, apr_array_header_t *rewriterules,
- char *perdir);
-static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,
- char *perdir);
-static int apply_rewrite_cond(request_rec *r, rewritecond_entry *p,
- char *perdir, backrefinfo *briRR,
- backrefinfo *briRC);
-
-static void do_expand(request_rec *r, char *input, char *buffer, int nbuf,
- backrefinfo *briRR, backrefinfo *briRC);
-static void do_expand_env(request_rec *r, char *env[],
- backrefinfo *briRR, backrefinfo *briRC);
-
- /* URI transformation function */
-static void splitout_queryargs(request_rec *r, int qsappend);
-static void fully_qualify_uri(request_rec *r);
-static void reduce_uri(request_rec *r);
-static int is_absolute_uri(char *uri);
-static char *expand_tildepaths(request_rec *r, char *uri);
-
- /* rewrite map support functions */
-static char *lookup_map(request_rec *r, char *name, char *key);
-static char *lookup_map_txtfile(request_rec *r, const char *file, char *key);
-#ifndef NO_DBM_REWRITEMAP
-static char *lookup_map_dbmfile(request_rec *r, const char *file, char *key);
-#endif
-static char *lookup_map_program(request_rec *r, apr_file_t *fpin,
- apr_file_t *fpout, char *key);
-static char *lookup_map_internal(request_rec *r,
- char *(*func)(request_rec *r, char *key),
- char *key);
-static char *rewrite_mapfunc_toupper(request_rec *r, char *key);
-static char *rewrite_mapfunc_tolower(request_rec *r, char *key);
-static char *rewrite_mapfunc_escape(request_rec *r, char *key);
-static char *rewrite_mapfunc_unescape(request_rec *r, char *key);
-static char *select_random_value_part(request_rec *r, char *value);
-static void rewrite_rand_init(void);
-static int rewrite_rand(int l, int h);
-
- /* rewriting logfile support */
-static void open_rewritelog(server_rec *s, apr_pool_t *p);
-static void rewritelog(request_rec *r, int level, const char *text, ...)
- __attribute__((format(printf,3,4)));
-static char *current_logtime(request_rec *r);
-
- /* rewriting lockfile support */
-static void rewritelock_create(server_rec *s, apr_pool_t *p);
-static apr_status_t rewritelock_remove(void *data);
-
- /* program map support */
-static void run_rewritemap_programs(server_rec *s, apr_pool_t *p);
-static apr_status_t rewritemap_program_child(apr_pool_t *p, const char *progname,
- apr_file_t **fpout, apr_file_t **fpin,
- apr_file_t **fperr);
-
- /* env variable support */
-static char *lookup_variable(request_rec *r, char *var);
-static char *lookup_header(request_rec *r, const char *name);
-
- /* caching functions */
-static cache *init_cache(apr_pool_t *p);
-static char *get_cache_string(cache *c, const char *res, int mode, apr_time_t mtime,
- char *key);
-static void set_cache_string(cache *c, const char *res, int mode, apr_time_t mtime,
- char *key, char *value);
-static cacheentry *retrieve_cache_string(cache *c, const char *res, char *key);
-static void store_cache_string(cache *c, const char *res, cacheentry *ce);
-
- /* misc functions */
-static char *subst_prefix_path(request_rec *r, char *input, char *match,
- const char *subst);
-static int parseargline(char *str, char **a1, char **a2, char **a3);
-static int prefix_stat(const char *path, apr_finfo_t *sb);
-static void add_env_variable(request_rec *r, char *s);
-static int subreq_ok(request_rec *r);
-
- /* Lexicographic Comparison */
-static int compare_lexicography(char *cpNum1, char *cpNum2);
-
- /* Bracketed expression handling */
-static char *find_closing_bracket(char *s, int left, int right);
-static char *find_char_in_brackets(char *s, int c, int left, int right);
-
-#endif /* MOD_REWRITE_H */
diff --git a/modules/mappers/mod_rewrite.mak b/modules/mappers/mod_rewrite.mak
deleted file mode 100644
index 135063b48d..0000000000
--- a/modules/mappers/mod_rewrite.mak
+++ /dev/null
@@ -1,335 +0,0 @@
-# Microsoft Developer Studio Generated NMAKE File, Based on mod_rewrite.dsp
-!IF "$(CFG)" == ""
-CFG=mod_rewrite - Win32 Release
-!MESSAGE No configuration specified. Defaulting to mod_rewrite - Win32 Release.
-!ENDIF
-
-!IF "$(CFG)" != "mod_rewrite - Win32 Release" && "$(CFG)" !=\
- "mod_rewrite - Win32 Debug"
-!MESSAGE Invalid configuration "$(CFG)" specified.
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_rewrite.mak" CFG="mod_rewrite - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_rewrite - Win32 Release" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_rewrite - Win32 Debug" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-!ERROR An invalid configuration is specified.
-!ENDIF
-
-!IF "$(OS)" == "Windows_NT"
-NULL=
-!ELSE
-NULL=nul
-!ENDIF
-
-!IF "$(CFG)" == "mod_rewrite - Win32 Release"
-
-OUTDIR=.\Release
-INTDIR=.\Release
-# Begin Custom Macros
-OutDir=.\Release
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_rewrite.so"
-
-!ELSE
-
-ALL : "libhttpd - Win32 Release" "libapr - Win32 Release"\
- "$(OUTDIR)\mod_rewrite.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libapr - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\mod_rewrite.idb"
- -@erase "$(INTDIR)\mod_rewrite.obj"
- -@erase "$(OUTDIR)\mod_rewrite.exp"
- -@erase "$(OUTDIR)\mod_rewrite.lib"
- -@erase "$(OUTDIR)\mod_rewrite.map"
- -@erase "$(OUTDIR)\mod_rewrite.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\os\win32" /I\
- "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D\
- "WIN32" /D "_WINDOWS" /D "NO_DBM_REWRITEMAP" /Fo"$(INTDIR)\\"\
- /Fd"$(INTDIR)\mod_rewrite" /FD /c
-CPP_OBJS=.\Release/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_rewrite.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no\
- /pdb:"$(OUTDIR)\mod_rewrite.pdb" /map:"$(INTDIR)\mod_rewrite.map" /machine:I386\
- /out:"$(OUTDIR)\mod_rewrite.so" /implib:"$(OUTDIR)\mod_rewrite.lib"\
- /base:@..\..\os\win32\BaseAddr.ref,mod_rewrite
-LINK32_OBJS= \
- "$(INTDIR)\mod_rewrite.obj" \
- "..\..\Release\libhttpd.lib" \
- "..\..\srclib\apr\Release\libapr.lib"
-
-"$(OUTDIR)\mod_rewrite.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ELSEIF "$(CFG)" == "mod_rewrite - Win32 Debug"
-
-OUTDIR=.\Debug
-INTDIR=.\Debug
-# Begin Custom Macros
-OutDir=.\Debug
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_rewrite.so"
-
-!ELSE
-
-ALL : "libhttpd - Win32 Debug" "libapr - Win32 Debug"\
- "$(OUTDIR)\mod_rewrite.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libapr - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\mod_rewrite.idb"
- -@erase "$(INTDIR)\mod_rewrite.obj"
- -@erase "$(OUTDIR)\mod_rewrite.exp"
- -@erase "$(OUTDIR)\mod_rewrite.lib"
- -@erase "$(OUTDIR)\mod_rewrite.map"
- -@erase "$(OUTDIR)\mod_rewrite.pdb"
- -@erase "$(OUTDIR)\mod_rewrite.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /I\
- "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D\
- "WIN32" /D "_WINDOWS" /D "NO_DBM_REWRITEMAP" /Fo"$(INTDIR)\\"\
- /Fd"$(INTDIR)\mod_rewrite" /FD /c
-CPP_OBJS=.\Debug/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_rewrite.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no\
- /pdb:"$(OUTDIR)\mod_rewrite.pdb" /map:"$(INTDIR)\mod_rewrite.map" /debug\
- /machine:I386 /out:"$(OUTDIR)\mod_rewrite.so"\
- /implib:"$(OUTDIR)\mod_rewrite.lib"\
- /base:@..\..\os\win32\BaseAddr.ref,mod_rewrite
-LINK32_OBJS= \
- "$(INTDIR)\mod_rewrite.obj" \
- "..\..\Debug\libhttpd.lib" \
- "..\..\srclib\apr\Debug\libapr.lib"
-
-"$(OUTDIR)\mod_rewrite.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ENDIF
-
-
-!IF "$(CFG)" == "mod_rewrite - Win32 Release" || "$(CFG)" ==\
- "mod_rewrite - Win32 Debug"
-
-!IF "$(CFG)" == "mod_rewrite - Win32 Release"
-
-"libapr - Win32 Release" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F .\libapr.mak CFG="libapr - Win32 Release"
- cd "..\..\modules\mappers"
-
-"libapr - Win32 ReleaseCLEAN" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libapr.mak CFG="libapr - Win32 Release"\
- RECURSE=1
- cd "..\..\modules\mappers"
-
-!ELSEIF "$(CFG)" == "mod_rewrite - Win32 Debug"
-
-"libapr - Win32 Debug" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F .\libapr.mak CFG="libapr - Win32 Debug"
- cd "..\..\modules\mappers"
-
-"libapr - Win32 DebugCLEAN" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libapr.mak CFG="libapr - Win32 Debug"\
- RECURSE=1
- cd "..\..\modules\mappers"
-
-!ENDIF
-
-!IF "$(CFG)" == "mod_rewrite - Win32 Release"
-
-"libhttpd - Win32 Release" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) /F .\libhttpd.mak CFG="libhttpd - Win32 Release"
- cd ".\modules\mappers"
-
-"libhttpd - Win32 ReleaseCLEAN" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libhttpd.mak CFG="libhttpd - Win32 Release"\
- RECURSE=1
- cd ".\modules\mappers"
-
-!ELSEIF "$(CFG)" == "mod_rewrite - Win32 Debug"
-
-"libhttpd - Win32 Debug" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) /F .\libhttpd.mak CFG="libhttpd - Win32 Debug"
- cd ".\modules\mappers"
-
-"libhttpd - Win32 DebugCLEAN" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libhttpd.mak CFG="libhttpd - Win32 Debug"\
- RECURSE=1
- cd ".\modules\mappers"
-
-!ENDIF
-
-SOURCE=.\mod_rewrite.c
-DEP_CPP_MOD_R=\
- "..\..\include\ap_config.h"\
- "..\..\include\ap_mmn.h"\
- "..\..\include\ap_release.h"\
- "..\..\include\http_config.h"\
- "..\..\include\http_core.h"\
- "..\..\include\http_log.h"\
- "..\..\include\http_protocol.h"\
- "..\..\include\http_request.h"\
- "..\..\include\http_vhost.h"\
- "..\..\include\httpd.h"\
- "..\..\include\pcreposix.h"\
- "..\..\include\util_cfgtree.h"\
- "..\..\include\util_filter.h"\
- "..\..\include\util_uri.h"\
- "..\..\os\win32\os.h"\
- "..\..\srclib\apr-util\include\apr_buckets.h"\
- "..\..\srclib\apr-util\include\apr_hooks.h"\
- "..\..\srclib\apr-util\include\apr_ring.h"\
- "..\..\srclib\apr-util\include\apu.h"\
- "..\..\srclib\apr\include\apr.h"\
- "..\..\srclib\apr\include\apr_dso.h"\
- "..\..\srclib\apr\include\apr_errno.h"\
- "..\..\srclib\apr\include\apr_file_info.h"\
- "..\..\srclib\apr\include\apr_file_io.h"\
- "..\..\srclib\apr\include\apr_general.h"\
- "..\..\srclib\apr\include\apr_lib.h"\
- "..\..\srclib\apr\include\apr_lock.h"\
- "..\..\srclib\apr\include\apr_mmap.h"\
- "..\..\srclib\apr\include\apr_network_io.h"\
- "..\..\srclib\apr\include\apr_pools.h"\
- "..\..\srclib\apr\include\apr_portable.h"\
- "..\..\srclib\apr\include\apr_signal.h"\
- "..\..\srclib\apr\include\apr_strings.h"\
- "..\..\srclib\apr\include\apr_tables.h"\
- "..\..\srclib\apr\include\apr_thread_proc.h"\
- "..\..\srclib\apr\include\apr_time.h"\
- "..\..\srclib\apr\include\apr_user.h"\
- "..\..\srclib\apr\include\apr_want.h"\
- ".\mod_rewrite.h"\
-
-NODEP_CPP_MOD_R=\
- "..\..\include\ap_config_auto.h"\
- ".\unixd.h"\
-
-
-"$(INTDIR)\mod_rewrite.obj" : $(SOURCE) $(DEP_CPP_MOD_R) "$(INTDIR)"
-
-
-
-!ENDIF
-
diff --git a/modules/mappers/mod_so.c b/modules/mappers/mod_so.c
deleted file mode 100644
index ba9466f622..0000000000
--- a/modules/mappers/mod_so.c
+++ /dev/null
@@ -1,353 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * This module is used to load Apache modules at runtime. This means that the
- * server functionality can be extended without recompiling and even without
- * taking the server down at all. Only a HUP or WINCH signal needs to be send
- * to the server to reload the dynamically loaded modules.
- *
- * To use, you'll first need to build your module as a shared library, then
- * update your configuration (httpd.conf) to get the Apache core to load the
- * module at start-up.
- *
- * The easiest way to build a module as a shared library is to use the
- * `SharedModule' command in the Configuration file, instead of `AddModule'.
- * You should also change the file extension from `.o' to `.so'. So, for
- * example, to build the status module as a shared library edit Configuration
- * and change
- * AddModule modules/standard/mod_status.o
- * to
- * SharedModule modules/standard/mod_status.so
- *
- * Run Configure and make. Now Apache's httpd binary will _not_ include
- * mod_status. Instead a shared object called mod_status.so will be build, in
- * the modules/standard directory. You can build most of the modules as shared
- * libraries like this.
- *
- * To use the shared module, move the .so file(s) into an appropriate
- * directory. You might like to create a directory called "modules" under you
- * server root for this (e.g. /usr/local/httpd/modules).
- *
- * Then edit your conf/httpd.conf file, and add LoadModule lines. For
- * example
- * LoadModule status_module modules/mod_status.so
- *
- * The first argument is the module's structure name (look at the end of the
- * module source to find this). The second option is the path to the module
- * file, relative to the server root. Put these directives right at the top
- * of your httpd.conf file.
- *
- * Now you can start Apache. A message will be logged at "debug" level to your
- * error_log to confirm that the module(s) are loaded (use "LogLevel debug"
- * directive to get these log messages).
- *
- * If you edit the LoadModule directives while the server is live you can get
- * Apache to re-load the modules by sending it a HUP or WINCH signal as normal.
- * You can use this to dynamically change the capability of your server
- * without bringing it down.
- *
- * Because currently there is only limited builtin support in the Configure
- * script for creating the shared library files (`.so'), please consult your
- * vendors cc(1), ld(1) and dlopen(3) manpages to find out the appropriate
- * compiler and linker flags and insert them manually into the Configuration
- * file under CFLAGS_SHLIB, LDFLAGS_SHLIB and LDFLAGS_SHLIB_EXPORT.
- *
- * If you still have problems figuring out the flags both try the paper
- * http://developer.netscape.com/library/documentation/enterprise
- * /unix/svrplug.htm#1013807
- * or install a Perl 5 interpreter on your platform and then run the command
- *
- * $ perl -V:usedl -V:ccdlflags -V:cccdlflags -V:lddlflags
- *
- * This gives you what type of dynamic loading Perl 5 uses on your platform
- * and which compiler and linker flags Perl 5 uses to create the shared object
- * files.
- *
- * Another location where you can find useful hints is the `ltconfig' script
- * of the GNU libtool 1.2 package. Search for your platform name inside the
- * various "case" constructs.
- *
- */
-
-#include "apr.h"
-#include "apr_dso.h"
-#include "apr_strings.h"
-#include "apr_errno.h"
-
-#define CORE_PRIVATE
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_log.h"
-#include "ap_config.h"
-
-module AP_MODULE_DECLARE_DATA so_module;
-
-
-/*
- * Server configuration to keep track of actually
- * loaded modules and the corresponding module name.
- */
-
-typedef struct moduleinfo {
- const char *name;
- module *modp;
-} moduleinfo;
-
-typedef struct so_server_conf {
- apr_array_header_t *loaded_modules;
-} so_server_conf;
-
-static void *so_sconf_create(apr_pool_t *p, server_rec *s)
-{
- so_server_conf *soc;
-
- soc = (so_server_conf *)apr_pcalloc(p, sizeof(so_server_conf));
- soc->loaded_modules = apr_array_make(p, DYNAMIC_MODULE_LIMIT,
- sizeof(moduleinfo));
-
- return (void *)soc;
-}
-
-#ifndef NO_DLOPEN
-
-/*
- * This is the cleanup for a loaded shared object. It unloads the module.
- * This is called as a cleanup function from the core.
- */
-
-static apr_status_t unload_module(void *data)
-{
- moduleinfo *modi = (moduleinfo*)data;
-
- /* only unload if module information is still existing */
- if (modi->modp == NULL)
- return APR_SUCCESS;
-
- /* remove the module pointer from the core structure */
- ap_remove_loaded_module(modi->modp);
-
- /* destroy the module information */
- modi->modp = NULL;
- modi->name = NULL;
- return APR_SUCCESS;
-}
-
-/*
- * This is called for the directive LoadModule and actually loads
- * a shared object file into the address space of the server process.
- */
-
-static const char *load_module(cmd_parms *cmd, void *dummy,
- const char *modname, const char *filename)
-{
- apr_dso_handle_t *modhandle;
- apr_dso_handle_sym_t modsym;
- module *modp;
- const char *szModuleFile=ap_server_root_relative(cmd->pool, filename);
- so_server_conf *sconf;
- moduleinfo *modi;
- moduleinfo *modie;
- int i;
-
- /* we need to setup this value for dummy to make sure that we don't try
- * to add a non-existant tree into the build when we return to
- * execute_now.
- */
- *(ap_directive_t **)dummy = NULL;
-
- /*
- * check for already existing module
- * If it already exists, we have nothing to do
- */
- sconf = (so_server_conf *)ap_get_module_config(cmd->server->module_config,
- &so_module);
- modie = (moduleinfo *)sconf->loaded_modules->elts;
- for (i = 0; i < sconf->loaded_modules->nelts; i++) {
- modi = &modie[i];
- if (modi->name != NULL && strcmp(modi->name, modname) == 0)
- return NULL;
- }
- modi = apr_array_push(sconf->loaded_modules);
- modi->name = modname;
-
- /*
- * Load the file into the Apache address space
- */
- if (apr_dso_load(&modhandle, szModuleFile, cmd->pool) != APR_SUCCESS) {
- char my_error[256];
-
- return apr_pstrcat(cmd->pool, "Cannot load ", szModuleFile,
- " into server: ",
- apr_dso_error(modhandle, my_error, sizeof(my_error)),
- NULL);
- }
- ap_log_perror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, cmd->pool,
- "loaded module %s", modname);
-
- /*
- * Retrieve the pointer to the module structure through the module name:
- * First with the hidden variant (prefix `AP_') and then with the plain
- * symbol name.
- */
- if (apr_dso_sym(&modsym, modhandle, modname) != APR_SUCCESS) {
- char my_error[256];
-
- return apr_pstrcat(cmd->pool, "Can't locate API module structure `",
- modname, "' in file ", szModuleFile, ": ",
- apr_dso_error(modhandle, my_error, sizeof(my_error)),
- NULL);
- }
- modp = (module*) modsym;
- modp->dynamic_load_handle = (apr_dso_handle_t *)modhandle;
- modi->modp = modp;
-
- /*
- * Make sure the found module structure is really a module structure
- *
- */
- if (modp->magic != MODULE_MAGIC_COOKIE) {
- return apr_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, cmd->pool);
-
- /*
- * Register a cleanup in the config apr_pool_t (normally pconf). When
- * we do a restart (or shutdown) this cleanup will cause the
- * shared object to be unloaded.
- */
- apr_pool_cleanup_register(cmd->pool, modi, unload_module, apr_pool_cleanup_null);
-
- /*
- * Finally we need to run the configuration process for the module
- */
- ap_single_module_configure(cmd->pool, cmd->server, modp);
-
- return NULL;
-}
-
-/*
- * This implements the LoadFile directive and loads an arbitrary
- * shared object file into the adress space of the server process.
- */
-
-static const char *load_file(cmd_parms *cmd, void *dummy, const char *filename)
-{
- apr_dso_handle_t *handle;
- const char *file;
-
- file = ap_server_root_relative(cmd->pool, filename);
-
- if (apr_dso_load(&handle, file, cmd->pool) != APR_SUCCESS) {
- char my_error[256];
-
- return apr_pstrcat(cmd->pool, "Cannot load ", filename,
- " into server: ",
- apr_dso_error(handle, my_error, sizeof(my_error)),
- NULL);
- }
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
- "loaded file %s", filename);
-
- return NULL;
-}
-
-#else /* not NO_DLOPEN */
-
-static const char *load_file(cmd_parms *cmd, void *dummy, const char *filename)
-{
- ap_log_perror(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, cmd->pool,
- "WARNING: LoadFile not supported on this platform");
- return NULL;
-}
-
-static const char *load_module(cmd_parms *cmd, void *dummy,
- const char *modname, const char *filename)
-{
- ap_log_perror(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, cmd->pool,
- "WARNING: LoadModule not supported on this platform");
- return NULL;
-}
-
-#endif /* NO_DLOPEN */
-
-static const command_rec so_cmds[] = {
- AP_INIT_TAKE2("LoadModule", load_module, NULL, RSRC_CONF | EXEC_ON_READ,
- "a module name and the name of a shared object file to load it from"),
- AP_INIT_ITERATE("LoadFile", load_file, NULL, RSRC_CONF,
- "shared object file or library to load into the server at runtime"),
- { NULL }
-};
-
-module AP_MODULE_DECLARE_DATA so_module = {
- STANDARD20_MODULE_STUFF,
- NULL, /* create per-dir config */
- NULL, /* merge per-dir config */
- so_sconf_create, /* server config */
- NULL, /* merge server config */
- so_cmds, /* command apr_table_t */
- NULL /* register hooks */
-};
diff --git a/modules/mappers/mod_speling.c b/modules/mappers/mod_speling.c
deleted file mode 100644
index d89a86923d..0000000000
--- a/modules/mappers/mod_speling.c
+++ /dev/null
@@ -1,569 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "apr.h"
-#include "apr_file_io.h"
-#include "apr_strings.h"
-#include "apr_lib.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#define WANT_BASENAME_MATCH
-
-#include "httpd.h"
-#include "http_core.h"
-#include "http_config.h"
-#include "http_request.h"
-#include "http_log.h"
-
-/* mod_speling.c - by Alexei Kosut <akosut@organic.com> June, 1996
- *
- * This module is transparent, and simple. It attempts to correct
- * misspellings of URLs that users might have entered, namely by checking
- * capitalizations. If it finds a match, it sends a redirect.
- *
- * 08-Aug-1997 <Martin.Kraemer@Mch.SNI.De>
- * o Upgraded module interface to apache_1.3a2-dev API (more NULL's in
- * speling_module).
- * o Integrated tcsh's "spelling correction" routine which allows one
- * misspelling (character insertion/omission/typo/transposition).
- * Rewrote it to ignore case as well. This ought to catch the majority
- * of misspelled requests.
- * o Commented out the second pass where files' suffixes are stripped.
- * Given the better hit rate of the first pass, this rather ugly
- * (request index.html, receive index.db ?!?!) solution can be
- * omitted.
- * o wrote a "kind of" html page for mod_speling
- *
- * Activate it with "CheckSpelling On"
- */
-
-AP_MODULE_DECLARE_DATA module speling_module;
-
-typedef struct {
- int enabled;
-} spconfig;
-
-/*
- * Create a configuration specific to this module for a server or directory
- * location, and fill it with the default settings.
- *
- * The API says that in the absence of a merge function, the record for the
- * closest ancestor is used exclusively. That's what we want, so we don't
- * bother to have such a function.
- */
-
-static void *mkconfig(apr_pool_t *p)
-{
- spconfig *cfg = apr_pcalloc(p, sizeof(spconfig));
-
- cfg->enabled = 0;
- return cfg;
-}
-
-/*
- * Respond to a callback to create configuration record for a server or
- * vhost environment.
- */
-static void *create_mconfig_for_server(apr_pool_t *p, server_rec *s)
-{
- return mkconfig(p);
-}
-
-/*
- * Respond to a callback to create a config record for a specific directory.
- */
-static void *create_mconfig_for_directory(apr_pool_t *p, char *dir)
-{
- return mkconfig(p);
-}
-
-/*
- * Handler for the CheckSpelling directive, which is FLAG.
- */
-static const char *set_speling(cmd_parms *cmd, void *mconfig, int arg)
-{
- spconfig *cfg = (spconfig *) mconfig;
-
- cfg->enabled = arg;
- return NULL;
-}
-
-/*
- * Define the directives specific to this module. This structure is referenced
- * later by the 'module' structure.
- */
-static const command_rec speling_cmds[] =
-{
- AP_INIT_FLAG("CheckSpelling", set_speling, NULL, OR_OPTIONS,
- "whether or not to fix miscapitalized/misspelled requests"),
- { NULL }
-};
-
-typedef enum {
- SP_IDENTICAL = 0,
- SP_MISCAPITALIZED = 1,
- SP_TRANSPOSITION = 2,
- SP_MISSINGCHAR = 3,
- SP_EXTRACHAR = 4,
- SP_SIMPLETYPO = 5,
- SP_VERYDIFFERENT = 6
-} sp_reason;
-
-static const char *sp_reason_str[] =
-{
- "identical",
- "miscapitalized",
- "transposed characters",
- "character missing",
- "extra character",
- "mistyped character",
- "common basename",
-};
-
-typedef struct {
- const char *name;
- sp_reason quality;
-} misspelled_file;
-
-/*
- * spdist() is taken from Kernighan & Pike,
- * _The_UNIX_Programming_Environment_
- * and adapted somewhat to correspond better to psychological reality.
- * (Note the changes to the return values)
- *
- * According to Pollock and Zamora, CACM April 1984 (V. 27, No. 4),
- * page 363, the correct order for this is:
- * OMISSION = TRANSPOSITION > INSERTION > SUBSTITUTION
- * thus, it was exactly backwards in the old version. -- PWP
- *
- * This routine was taken out of tcsh's spelling correction code
- * (tcsh-6.07.04) and re-converted to apache data types ("char" type
- * instead of tcsh's NLS'ed "Char"). Plus it now ignores the case
- * during comparisons, so is a "approximate strcasecmp()".
- * NOTE that is still allows only _one_ real "typo",
- * it does NOT try to correct multiple errors.
- */
-
-static sp_reason spdist(const char *s, const char *t)
-{
- for (; apr_tolower(*s) == apr_tolower(*t); t++, s++) {
- if (*t == '\0') {
- return SP_MISCAPITALIZED; /* exact match (sans case) */
- }
- }
- if (*s) {
- if (*t) {
- if (s[1] && t[1] && apr_tolower(*s) == apr_tolower(t[1])
- && apr_tolower(*t) == apr_tolower(s[1])
- && strcasecmp(s + 2, t + 2) == 0) {
- return SP_TRANSPOSITION; /* transposition */
- }
- if (strcasecmp(s + 1, t + 1) == 0) {
- return SP_SIMPLETYPO; /* 1 char mismatch */
- }
- }
- if (strcasecmp(s + 1, t) == 0) {
- return SP_EXTRACHAR; /* extra character */
- }
- }
- if (*t && strcasecmp(s, t + 1) == 0) {
- return SP_MISSINGCHAR; /* missing character */
- }
- return SP_VERYDIFFERENT; /* distance too large to fix. */
-}
-
-static int sort_by_quality(const void *left, const void *rite)
-{
- return (int) (((misspelled_file *) left)->quality)
- - (int) (((misspelled_file *) rite)->quality);
-}
-
-static int check_speling(request_rec *r)
-{
- spconfig *cfg;
- char *good, *bad, *postgood, *url;
- apr_finfo_t dirent;
- int filoc, dotloc, urlen, pglen;
- apr_array_header_t *candidates = NULL;
- apr_dir_t *dir;
-
- cfg = ap_get_module_config(r->per_dir_config, &speling_module);
- if (!cfg->enabled) {
- return DECLINED;
- }
-
- /* We only want to worry about GETs */
- if (r->method_number != M_GET) {
- return DECLINED;
- }
-
- /* We've already got a file of some kind or another */
- if (r->proxyreq || (r->finfo.filetype != 0)) {
- return DECLINED;
- }
-
- /* This is a sub request - don't mess with it */
- if (r->main) {
- return DECLINED;
- }
-
- /*
- * The request should end up looking like this:
- * r->uri: /correct-url/mispelling/more
- * r->filename: /correct-file/mispelling r->path_info: /more
- *
- * So we do this in steps. First break r->filename into two pieces
- */
-
- filoc = ap_rind(r->filename, '/');
- /*
- * Don't do anything if the request doesn't contain a slash, or
- * requests "/"
- */
- if (filoc == -1 || strcmp(r->uri, "/") == 0) {
- return DECLINED;
- }
-
- /* good = /correct-file */
- good = apr_pstrndup(r->pool, r->filename, filoc);
- /* bad = mispelling */
- bad = apr_pstrdup(r->pool, r->filename + filoc + 1);
- /* postgood = mispelling/more */
- postgood = apr_pstrcat(r->pool, bad, r->path_info, NULL);
-
- urlen = strlen(r->uri);
- pglen = strlen(postgood);
-
- /* Check to see if the URL pieces add up */
- if (strcmp(postgood, r->uri + (urlen - pglen))) {
- return DECLINED;
- }
-
- /* url = /correct-url */
- url = apr_pstrndup(r->pool, r->uri, (urlen - pglen));
-
- /* Now open the directory and do ourselves a check... */
- if (apr_dir_open(&dir, good, r->pool) != APR_SUCCESS) {
- /* Oops, not a directory... */
- return DECLINED;
- }
-
- candidates = apr_array_make(r->pool, 2, sizeof(misspelled_file));
-
- dotloc = ap_ind(bad, '.');
- if (dotloc == -1) {
- dotloc = strlen(bad);
- }
-
- while (apr_dir_read(&dirent, APR_FINFO_DIRENT, dir) == APR_SUCCESS) {
- sp_reason q;
-
- /*
- * If we end up with a "fixed" URL which is identical to the
- * requested one, we must have found a broken symlink or some such.
- * Do _not_ try to redirect this, it causes a loop!
- */
- if (strcmp(bad, dirent.name) == 0) {
- apr_dir_close(dir);
- return OK;
- }
-
- /*
- * miscapitalization errors are checked first (like, e.g., lower case
- * file, upper case request)
- */
- else if (strcasecmp(bad, dirent.name) == 0) {
- misspelled_file *sp_new;
-
- sp_new = (misspelled_file *) apr_array_push(candidates);
- sp_new->name = apr_pstrdup(r->pool, dirent.name);
- sp_new->quality = SP_MISCAPITALIZED;
- }
-
- /*
- * simple typing errors are checked next (like, e.g.,
- * missing/extra/transposed char)
- */
- else if ((q = spdist(bad, dirent.name)) != SP_VERYDIFFERENT) {
- misspelled_file *sp_new;
-
- sp_new = (misspelled_file *) apr_array_push(candidates);
- sp_new->name = apr_pstrdup(r->pool, dirent.name);
- sp_new->quality = q;
- }
-
- /*
- * The spdist() should have found the majority of the misspelled
- * requests. It is of questionable use to continue looking for
- * files with the same base name, but potentially of totally wrong
- * type (index.html <-> index.db).
- * I would propose to not set the WANT_BASENAME_MATCH define.
- * 08-Aug-1997 <Martin.Kraemer@Mch.SNI.De>
- *
- * However, Alexei replied giving some reasons to add it anyway:
- * > Oh, by the way, I remembered why having the
- * > extension-stripping-and-matching stuff is a good idea:
- * >
- * > If you're using MultiViews, and have a file named foobar.html,
- * > which you refer to as "foobar", and someone tried to access
- * > "Foobar", mod_speling won't find it, because it won't find
- * > anything matching that spelling. With the extension-munging,
- * > it would locate "foobar.html". Not perfect, but I ran into
- * > that problem when I first wrote the module.
- */
- else {
-#ifdef WANT_BASENAME_MATCH
- /*
- * Okay... we didn't find anything. Now we take out the hard-core
- * power tools. There are several cases here. Someone might have
- * entered a wrong extension (.htm instead of .html or vice
- * versa) or the document could be negotiated. At any rate, now
- * we just compare stuff before the first dot. If it matches, we
- * figure we got us a match. This can result in wrong things if
- * there are files of different content types but the same prefix
- * (e.g. foo.gif and foo.html) This code will pick the first one
- * it finds. Better than a Not Found, though.
- */
- int entloc = ap_ind(dirent.name, '.');
- if (entloc == -1) {
- entloc = strlen(dirent.name);
- }
-
- if ((dotloc == entloc)
- && !strncasecmp(bad, dirent.name, dotloc)) {
- misspelled_file *sp_new;
-
- sp_new = (misspelled_file *) apr_array_push(candidates);
- sp_new->name = apr_pstrdup(r->pool, dirent.name);
- sp_new->quality = SP_VERYDIFFERENT;
- }
-#endif
- }
- }
- apr_dir_close(dir);
-
- if (candidates->nelts != 0) {
- /* Wow... we found us a mispelling. Construct a fixed url */
- char *nuri;
- const char *ref;
- misspelled_file *variant = (misspelled_file *) candidates->elts;
- int i;
-
- ref = apr_table_get(r->headers_in, "Referer");
-
- qsort((void *) candidates->elts, candidates->nelts,
- sizeof(misspelled_file), sort_by_quality);
-
- /*
- * Conditions for immediate redirection:
- * a) the first candidate was not found by stripping the suffix
- * AND b) there exists only one candidate OR the best match is not
- * ambiguous
- * then return a redirection right away.
- */
- if (variant[0].quality != SP_VERYDIFFERENT
- && (candidates->nelts == 1
- || variant[0].quality != variant[1].quality)) {
-
- nuri = ap_escape_uri(r->pool, apr_pstrcat(r->pool, url,
- variant[0].name,
- r->path_info, NULL));
- if (r->parsed_uri.query)
- nuri = apr_pstrcat(r->pool, nuri, "?", r->parsed_uri.query, NULL);
-
- apr_table_setn(r->headers_out, "Location",
- ap_construct_url(r->pool, nuri, r));
-
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_INFO, APR_SUCCESS,
- r,
- ref ? "Fixed spelling: %s to %s from %s"
- : "Fixed spelling: %s to %s",
- r->uri, nuri, ref);
-
- return HTTP_MOVED_PERMANENTLY;
- }
- /*
- * Otherwise, a "[300] Multiple Choices" list with the variants is
- * returned.
- */
- else {
- apr_pool_t *p;
- apr_table_t *notes;
- apr_pool_t *sub_pool;
- apr_array_header_t *t;
- apr_array_header_t *v;
-
-
- if (r->main == NULL) {
- p = r->pool;
- notes = r->notes;
- }
- else {
- p = r->main->pool;
- notes = r->main->notes;
- }
-
- if (apr_pool_create(&sub_pool, p) != APR_SUCCESS)
- return DECLINED;
-
- t = apr_array_make(sub_pool, candidates->nelts * 8 + 8,
- sizeof(char *));
- v = apr_array_make(sub_pool, candidates->nelts * 5,
- sizeof(char *));
-
- /* Generate the response text. */
-
- *(const char **)apr_array_push(t) =
- "The document name you requested (<code>";
- *(const char **)apr_array_push(t) = ap_escape_html(sub_pool, r->uri);
- *(const char **)apr_array_push(t) =
- "</code>) could not be found on this server.\n"
- "However, we found documents with names similar "
- "to the one you requested.<p>"
- "Available documents:\n<ul>\n";
-
- for (i = 0; i < candidates->nelts; ++i) {
- char *vuri;
- const char *reason;
-
- reason = sp_reason_str[(int) (variant[i].quality)];
- /* The format isn't very neat... */
- vuri = apr_pstrcat(sub_pool, url, variant[i].name, r->path_info,
- (r->parsed_uri.query != NULL) ? "?" : "",
- (r->parsed_uri.query != NULL)
- ? r->parsed_uri.query : "",
- NULL);
- *(const char **)apr_array_push(v) = "\"";
- *(const char **)apr_array_push(v) = ap_escape_uri(sub_pool, vuri);
- *(const char **)apr_array_push(v) = "\";\"";
- *(const char **)apr_array_push(v) = reason;
- *(const char **)apr_array_push(v) = "\"";
-
- *(const char **)apr_array_push(t) = "<li><a href=\"";
- *(const char **)apr_array_push(t) = ap_escape_uri(sub_pool, vuri);
- *(const char **)apr_array_push(t) = "\">";
- *(const char **)apr_array_push(t) = ap_escape_html(sub_pool, vuri);
- *(const char **)apr_array_push(t) = "</a> (";
- *(const char **)apr_array_push(t) = reason;
- *(const char **)apr_array_push(t) = ")\n";
-
- /*
- * when we have printed the "close matches" and there are
- * more "distant matches" (matched by stripping the suffix),
- * then we insert an additional separator text to suggest
- * that the user LOOK CLOSELY whether these are really the
- * files she wanted.
- */
- if (i > 0 && i < candidates->nelts - 1
- && variant[i].quality != SP_VERYDIFFERENT
- && variant[i + 1].quality == SP_VERYDIFFERENT) {
- *(const char **)apr_array_push(t) =
- "</ul>\nFurthermore, the following related "
- "documents were found:\n<ul>\n";
- }
- }
- *(const char **)apr_array_push(t) = "</ul>\n";
-
- /* If we know there was a referring page, add a note: */
- if (ref != NULL) {
- *(const char **)apr_array_push(t) =
- "Please consider informing the owner of the "
- "<a href=\"";
- *(const char **)apr_array_push(t) = ap_escape_uri(sub_pool, ref);
- *(const char **)apr_array_push(t) = "\">referring page</a> "
- "about the broken link.\n";
- }
-
-
- /* Pass our apr_table_t to http_protocol.c (see mod_negotiation): */
- apr_table_setn(notes, "variant-list", apr_array_pstrcat(p, t, 0));
-
- apr_table_mergen(r->subprocess_env, "VARIANTS",
- apr_array_pstrcat(p, v, ','));
-
- apr_pool_destroy(sub_pool);
-
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_INFO, 0, r,
- ref ? "Spelling fix: %s: %d candidates from %s"
- : "Spelling fix: %s: %d candidates",
- r->uri, candidates->nelts, ref);
-
- return HTTP_MULTIPLE_CHOICES;
- }
- }
-
- return OK;
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_fixups(check_speling,NULL,NULL,APR_HOOK_LAST);
-}
-
-module AP_MODULE_DECLARE_DATA speling_module =
-{
- STANDARD20_MODULE_STUFF,
- create_mconfig_for_directory, /* create per-dir config */
- NULL, /* merge per-dir config */
- create_mconfig_for_server, /* server config */
- NULL, /* merge server config */
- speling_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
diff --git a/modules/mappers/mod_speling.dsp b/modules/mappers/mod_speling.dsp
deleted file mode 100644
index 15c098ca02..0000000000
--- a/modules/mappers/mod_speling.dsp
+++ /dev/null
@@ -1,95 +0,0 @@
-# Microsoft Developer Studio Project File - Name="mod_speling" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=mod_speling - Win32 Release
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "mod_speling.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_speling.mak" CFG="mod_speling - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_speling - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_speling - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "mod_speling - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\os\win32" /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_speling" /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "NDEBUG"
-# ADD RSC /l 0x809 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_speling.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_speling
-# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_speling.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_speling
-
-!ELSEIF "$(CFG)" == "mod_speling - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\..\include" /I "..\..\os\win32" /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_speling" /FD /c
-# ADD BASE MTL /nologo /D "_DEBUG" /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "_DEBUG"
-# ADD RSC /l 0x809 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /out:"Debug/mod_speling.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_speling
-# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /out:"Debug/mod_speling.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_speling
-
-!ENDIF
-
-# Begin Target
-
-# Name "mod_speling - Win32 Release"
-# Name "mod_speling - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\mod_speling.c
-# End Source File
-# End Target
-# End Project
diff --git a/modules/mappers/mod_speling.exp b/modules/mappers/mod_speling.exp
deleted file mode 100644
index a6ee8b5034..0000000000
--- a/modules/mappers/mod_speling.exp
+++ /dev/null
@@ -1 +0,0 @@
-speling_module
diff --git a/modules/mappers/mod_speling.mak b/modules/mappers/mod_speling.mak
deleted file mode 100644
index bc9460d0c3..0000000000
--- a/modules/mappers/mod_speling.mak
+++ /dev/null
@@ -1,325 +0,0 @@
-# Microsoft Developer Studio Generated NMAKE File, Based on mod_speling.dsp
-!IF "$(CFG)" == ""
-CFG=mod_speling - Win32 Release
-!MESSAGE No configuration specified. Defaulting to mod_speling - Win32 Release.
-!ENDIF
-
-!IF "$(CFG)" != "mod_speling - Win32 Release" && "$(CFG)" !=\
- "mod_speling - Win32 Debug"
-!MESSAGE Invalid configuration "$(CFG)" specified.
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_speling.mak" CFG="mod_speling - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_speling - Win32 Release" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_speling - Win32 Debug" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-!ERROR An invalid configuration is specified.
-!ENDIF
-
-!IF "$(OS)" == "Windows_NT"
-NULL=
-!ELSE
-NULL=nul
-!ENDIF
-
-!IF "$(CFG)" == "mod_speling - Win32 Release"
-
-OUTDIR=.\Release
-INTDIR=.\Release
-# Begin Custom Macros
-OutDir=.\Release
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_speling.so"
-
-!ELSE
-
-ALL : "libhttpd - Win32 Release" "libapr - Win32 Release"\
- "$(OUTDIR)\mod_speling.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libapr - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\mod_speling.idb"
- -@erase "$(INTDIR)\mod_speling.obj"
- -@erase "$(OUTDIR)\mod_speling.exp"
- -@erase "$(OUTDIR)\mod_speling.lib"
- -@erase "$(OUTDIR)\mod_speling.map"
- -@erase "$(OUTDIR)\mod_speling.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\os\win32" /I\
- "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D\
- "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_speling" /FD /c
-CPP_OBJS=.\Release/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_speling.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no\
- /pdb:"$(OUTDIR)\mod_speling.pdb" /map:"$(INTDIR)\mod_speling.map" /machine:I386\
- /out:"$(OUTDIR)\mod_speling.so" /implib:"$(OUTDIR)\mod_speling.lib"\
- /base:@..\..\os\win32\BaseAddr.ref,mod_speling
-LINK32_OBJS= \
- "$(INTDIR)\mod_speling.obj" \
- "..\..\Release\libhttpd.lib" \
- "..\..\srclib\apr\Release\libapr.lib"
-
-"$(OUTDIR)\mod_speling.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ELSEIF "$(CFG)" == "mod_speling - Win32 Debug"
-
-OUTDIR=.\Debug
-INTDIR=.\Debug
-# Begin Custom Macros
-OutDir=.\Debug
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_speling.so"
-
-!ELSE
-
-ALL : "libhttpd - Win32 Debug" "libapr - Win32 Debug"\
- "$(OUTDIR)\mod_speling.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libapr - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\mod_speling.idb"
- -@erase "$(INTDIR)\mod_speling.obj"
- -@erase "$(OUTDIR)\mod_speling.exp"
- -@erase "$(OUTDIR)\mod_speling.lib"
- -@erase "$(OUTDIR)\mod_speling.map"
- -@erase "$(OUTDIR)\mod_speling.pdb"
- -@erase "$(OUTDIR)\mod_speling.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /I\
- "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D\
- "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_speling" /FD /c
-CPP_OBJS=.\Debug/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_speling.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no\
- /pdb:"$(OUTDIR)\mod_speling.pdb" /map:"$(INTDIR)\mod_speling.map" /debug\
- /machine:I386 /out:"$(OUTDIR)\mod_speling.so"\
- /implib:"$(OUTDIR)\mod_speling.lib"\
- /base:@..\..\os\win32\BaseAddr.ref,mod_speling
-LINK32_OBJS= \
- "$(INTDIR)\mod_speling.obj" \
- "..\..\Debug\libhttpd.lib" \
- "..\..\srclib\apr\Debug\libapr.lib"
-
-"$(OUTDIR)\mod_speling.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ENDIF
-
-
-!IF "$(CFG)" == "mod_speling - Win32 Release" || "$(CFG)" ==\
- "mod_speling - Win32 Debug"
-
-!IF "$(CFG)" == "mod_speling - Win32 Release"
-
-"libapr - Win32 Release" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F .\libapr.mak CFG="libapr - Win32 Release"
- cd "..\..\modules\mappers"
-
-"libapr - Win32 ReleaseCLEAN" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libapr.mak CFG="libapr - Win32 Release"\
- RECURSE=1
- cd "..\..\modules\mappers"
-
-!ELSEIF "$(CFG)" == "mod_speling - Win32 Debug"
-
-"libapr - Win32 Debug" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F .\libapr.mak CFG="libapr - Win32 Debug"
- cd "..\..\modules\mappers"
-
-"libapr - Win32 DebugCLEAN" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libapr.mak CFG="libapr - Win32 Debug"\
- RECURSE=1
- cd "..\..\modules\mappers"
-
-!ENDIF
-
-!IF "$(CFG)" == "mod_speling - Win32 Release"
-
-"libhttpd - Win32 Release" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) /F .\libhttpd.mak CFG="libhttpd - Win32 Release"
- cd ".\modules\mappers"
-
-"libhttpd - Win32 ReleaseCLEAN" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libhttpd.mak CFG="libhttpd - Win32 Release"\
- RECURSE=1
- cd ".\modules\mappers"
-
-!ELSEIF "$(CFG)" == "mod_speling - Win32 Debug"
-
-"libhttpd - Win32 Debug" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) /F .\libhttpd.mak CFG="libhttpd - Win32 Debug"
- cd ".\modules\mappers"
-
-"libhttpd - Win32 DebugCLEAN" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libhttpd.mak CFG="libhttpd - Win32 Debug"\
- RECURSE=1
- cd ".\modules\mappers"
-
-!ENDIF
-
-SOURCE=.\mod_speling.c
-DEP_CPP_MOD_S=\
- "..\..\include\ap_config.h"\
- "..\..\include\ap_mmn.h"\
- "..\..\include\ap_release.h"\
- "..\..\include\http_config.h"\
- "..\..\include\http_core.h"\
- "..\..\include\http_log.h"\
- "..\..\include\http_request.h"\
- "..\..\include\httpd.h"\
- "..\..\include\pcreposix.h"\
- "..\..\include\util_cfgtree.h"\
- "..\..\include\util_filter.h"\
- "..\..\include\util_uri.h"\
- "..\..\os\win32\os.h"\
- "..\..\srclib\apr-util\include\apr_buckets.h"\
- "..\..\srclib\apr-util\include\apr_hooks.h"\
- "..\..\srclib\apr-util\include\apr_ring.h"\
- "..\..\srclib\apr-util\include\apu.h"\
- "..\..\srclib\apr\include\apr.h"\
- "..\..\srclib\apr\include\apr_errno.h"\
- "..\..\srclib\apr\include\apr_file_info.h"\
- "..\..\srclib\apr\include\apr_file_io.h"\
- "..\..\srclib\apr\include\apr_general.h"\
- "..\..\srclib\apr\include\apr_lib.h"\
- "..\..\srclib\apr\include\apr_mmap.h"\
- "..\..\srclib\apr\include\apr_network_io.h"\
- "..\..\srclib\apr\include\apr_pools.h"\
- "..\..\srclib\apr\include\apr_strings.h"\
- "..\..\srclib\apr\include\apr_tables.h"\
- "..\..\srclib\apr\include\apr_thread_proc.h"\
- "..\..\srclib\apr\include\apr_time.h"\
- "..\..\srclib\apr\include\apr_user.h"\
- "..\..\srclib\apr\include\apr_want.h"\
-
-NODEP_CPP_MOD_S=\
- "..\..\include\ap_config_auto.h"\
-
-
-"$(INTDIR)\mod_speling.obj" : $(SOURCE) $(DEP_CPP_MOD_S) "$(INTDIR)"
-
-
-
-!ENDIF
-
diff --git a/modules/mappers/mod_userdir.c b/modules/mappers/mod_userdir.c
deleted file mode 100644
index baf8a51b12..0000000000
--- a/modules/mappers/mod_userdir.c
+++ /dev/null
@@ -1,399 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * mod_userdir... implement the UserDir command. Broken away from the
- * Alias stuff for a couple of good and not-so-good reasons:
- *
- * 1) It shows a real minimal working example of how to do something like
- * this.
- * 2) I know people who are actually interested in changing this *particular*
- * aspect of server functionality without changing the rest of it. That's
- * what this whole modular arrangement is supposed to be good at...
- *
- * Modified by Alexei Kosut to support the following constructs
- * (server running at www.foo.com, request for /~bar/one/two.html)
- *
- * UserDir public_html -> ~bar/public_html/one/two.html
- * UserDir /usr/web -> /usr/web/bar/one/two.html
- * UserDir /home/ * /www -> /home/bar/www/one/two.html
- * NOTE: theses ^ ^ space only added allow it to work in a comment, ignore
- * UserDir http://x/users -> (302) http://x/users/bar/one/two.html
- * UserDir http://x/ * /y -> (302) http://x/bar/y/one/two.html
- * NOTE: here also ^ ^
- *
- * In addition, you can use multiple entries, to specify alternate
- * user directories (a la Directory Index). For example:
- *
- * UserDir public_html /usr/web http://www.xyz.com/users
- *
- * Modified by Ken Coar to provide for the following:
- *
- * UserDir disable[d] username ...
- * UserDir enable[d] username ...
- *
- * If "disabled" has no other arguments, *all* ~<username> references are
- * disabled, except those explicitly turned on with the "enabled" keyword.
- */
-
-#include "apr_strings.h"
-#include "apr_user.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#if APR_HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_request.h"
-
-#if !defined(WIN32) && !defined(OS2) && !defined(BEOS)
-#define HAVE_UNIX_SUEXEC
-#endif
-
-#ifdef HAVE_UNIX_SUEXEC
-#include "unixd.h" /* Contains the suexec_identity hook used on Unix */
-#endif
-
-
-/* The default directory in user's home dir */
-#ifndef DEFAULT_USER_DIR
-#define DEFAULT_USER_DIR "public_html"
-#endif
-
-module userdir_module;
-
-typedef struct {
- int globally_disabled;
- char *userdir;
- apr_table_t *enabled_users;
- apr_table_t *disabled_users;
-} userdir_config;
-
-/*
- * Server config for this module: global disablement flag, a list of usernames
- * ineligible for UserDir access, a list of those immune to global (but not
- * explicit) disablement, and the replacement string for all others.
- */
-
-static void *create_userdir_config(apr_pool_t *p, server_rec *s)
-{
- userdir_config *newcfg = apr_pcalloc(p, sizeof(*newcfg));
-
- newcfg->globally_disabled = 0;
- newcfg->userdir = DEFAULT_USER_DIR;
- newcfg->enabled_users = apr_table_make(p, 4);
- newcfg->disabled_users = apr_table_make(p, 4);
-
- return newcfg;
-}
-
-#define O_DEFAULT 0
-#define O_ENABLE 1
-#define O_DISABLE 2
-
-static const char *set_user_dir(cmd_parms *cmd, void *dummy, const char *arg)
-{
- userdir_config *s_cfg = ap_get_module_config(cmd->server->module_config,
- &userdir_module);
- char *username;
- const char *usernames = arg;
- char *kw = ap_getword_conf(cmd->pool, &usernames);
- apr_table_t *usertable;
-
- /*
- * Let's do the comparisons once.
- */
- if ((!strcasecmp(kw, "disable")) || (!strcasecmp(kw, "disabled"))) {
- /*
- * If there are no usernames specified, this is a global disable - we
- * need do no more at this point than record the fact.
- */
- if (strlen(usernames) == 0) {
- s_cfg->globally_disabled = 1;
- return NULL;
- }
- usertable = s_cfg->disabled_users;
- }
- else if ((!strcasecmp(kw, "enable")) || (!strcasecmp(kw, "enabled"))) {
- /*
- * The "disable" keyword can stand alone or take a list of names, but
- * the "enable" keyword requires the list. Whinge if it doesn't have
- * it.
- */
- if (strlen(usernames) == 0) {
- return "UserDir \"enable\" keyword requires a list of usernames";
- }
- usertable = s_cfg->enabled_users;
- }
- else {
- /*
- * If the first (only?) value isn't one of our keywords, just copy
- * the string to the userdir string.
- */
- s_cfg->userdir = apr_pstrdup(cmd->pool, arg);
- return NULL;
- }
- /*
- * Now we just take each word in turn from the command line and add it to
- * the appropriate table.
- */
- while (*usernames) {
- username = ap_getword_conf(cmd->pool, &usernames);
- apr_table_setn(usertable, username, kw);
- }
- return NULL;
-}
-
-static const command_rec userdir_cmds[] = {
- AP_INIT_RAW_ARGS("UserDir", set_user_dir, NULL, RSRC_CONF,
- "the public subdirectory in users' home directories, or "
- "'disabled', or 'disabled username username...', or "
- "'enabled username username...'"),
- {NULL}
-};
-
-static int translate_userdir(request_rec *r)
-{
- ap_conf_vector_t *server_conf = r->server->module_config;
- const userdir_config *s_cfg = ap_get_module_config(server_conf,
- &userdir_module);
- char *name = r->uri;
- const char *userdirs = s_cfg->userdir;
- const char *w, *dname;
- char *redirect;
- char *x = NULL;
- apr_finfo_t statbuf;
-
- /*
- * If the URI doesn't match our basic pattern, we've nothing to do with
- * it.
- */
- if (s_cfg->userdir == NULL || name[0] != '/' || name[1] != '~') {
- return DECLINED;
- }
-
- dname = name + 2;
- w = ap_getword(r->pool, &dname, '/');
-
- /*
- * The 'dname' funny business involves backing it up to capture the '/'
- * delimiting the "/~user" part from the rest of the URL, in case there
- * was one (the case where there wasn't being just "GET /~user HTTP/1.0",
- * for which we don't want to tack on a '/' onto the filename).
- */
-
- if (dname[-1] == '/') {
- --dname;
- }
-
- /*
- * If there's no username, it's not for us. Ignore . and .. as well.
- */
- if (w[0] == '\0' || (w[1] == '.' && (w[2] == '\0' || (w[2] == '.' && w[3] == '\0')))) {
- return DECLINED;
- }
- /*
- * Nor if there's an username but it's in the disabled list.
- */
- if (apr_table_get(s_cfg->disabled_users, w) != NULL) {
- return DECLINED;
- }
- /*
- * If there's a global interdiction on UserDirs, check to see if this
- * name is one of the Blessed.
- */
- if (s_cfg->globally_disabled
- && apr_table_get(s_cfg->enabled_users, w) == NULL) {
- return DECLINED;
- }
-
- /*
- * Special cases all checked, onward to normal substitution processing.
- */
-
- while (*userdirs) {
- const char *userdir = ap_getword_conf(r->pool, &userdirs);
- char *filename = NULL;
- apr_status_t rv;
-
- if (ap_strchr_c(userdir, '*'))
- x = ap_getword(r->pool, &userdir, '*');
-
- if (userdir[0] == '\0' || ap_os_is_path_absolute(userdir)) {
- if (x) {
-#ifdef HAVE_DRIVE_LETTERS
- /*
- * Crummy hack. Need to figure out whether we have been
- * redirected to a URL or to a file on some drive. Since I
- * know of no protocols that are a single letter, ignore
- * a : as the first or second character, and assume a file
- * was specified
- *
- * XXX: Still no good for NETWARE, since : is embedded (sys:/home)
- */
- if (strchr(x + 2, ':'))
-#else
- if (strchr(x, ':'))
-#endif /* HAVE_DRIVE_LETTERS */
- {
- redirect = apr_pstrcat(r->pool, x, w, userdir, dname, NULL);
- apr_table_setn(r->headers_out, "Location", redirect);
- return HTTP_MOVED_TEMPORARILY;
- }
- else
- filename = apr_pstrcat(r->pool, x, w, userdir, NULL);
- }
- else
- filename = apr_pstrcat(r->pool, userdir, "/", w, NULL);
- }
- else if (ap_strchr_c(userdir, ':')) {
- redirect = apr_pstrcat(r->pool, userdir, "/", w, dname, NULL);
- apr_table_setn(r->headers_out, "Location", redirect);
- return HTTP_MOVED_TEMPORARILY;
- }
- else {
-#if APR_HAS_USER
- char *homedir;
-
- if (apr_get_home_directory(&homedir, w, r->pool) == APR_SUCCESS) {
- filename = apr_pstrcat(r->pool, homedir, "/", userdir, NULL);
- }
- else {
- return DECLINED;
- }
-#else
- return DECLINED;
-#endif
- }
-
- /*
- * Now see if it exists, or we're at the last entry. If we are at the
- * last entry, then use the filename generated (if there is one)
- * anyway, in the hope that some handler might handle it. This can be
- * used, for example, to run a CGI script for the user.
- */
- if (filename && (!*userdirs
- || ((rv = apr_stat(&statbuf, filename, APR_FINFO_MIN,
- r->pool)) == APR_SUCCESS
- || rv == APR_INCOMPLETE))) {
- r->filename = apr_pstrcat(r->pool, filename, dname, NULL);
- /* XXX: Does this walk us around FollowSymLink rules?
- * When statbuf contains info on r->filename we can save a syscall
- * by copying it to r->finfo
- */
- if (*userdirs && dname[0] == 0)
- r->finfo = statbuf;
-
- /* For use in the get_suexec_identity phase */
- apr_table_setn(r->notes, "mod_userdir_user", w);
-
- return OK;
- }
- }
-
- return DECLINED;
-}
-
-#ifdef HAVE_UNIX_SUEXEC
-static ap_unix_identity_t *get_suexec_id_doer(const request_rec *r)
-{
- ap_unix_identity_t *ugid = NULL;
-#if APR_HAS_USER
- const char *username = apr_table_get(r->notes, "mod_userdir_user");
-
- if (username == NULL) {
- return NULL;
- }
-
- if ((ugid = apr_palloc(r->pool, sizeof(ap_unix_identity_t *))) == NULL) {
- return NULL;
- }
-
- if (apr_get_userid(&ugid->uid, &ugid->gid, username, r->pool) != APR_SUCCESS) {
- return NULL;
- }
-
-#endif
- return ugid;
-}
-#endif /* HAVE_UNIX_SUEXEC */
-
-static void register_hooks(apr_pool_t *p)
-{
- static const char * const aszSucc[]={ "mod_alias.c",NULL };
-
- ap_hook_translate_name(translate_userdir,NULL,aszSucc,APR_HOOK_MIDDLE);
-#ifdef HAVE_UNIX_SUEXEC
- ap_hook_get_suexec_identity(get_suexec_id_doer,NULL,NULL,APR_HOOK_MIDDLE);
-#endif
-}
-
-module userdir_module = {
- STANDARD20_MODULE_STUFF,
- NULL, /* dir config creater */
- NULL, /* dir merger --- default is to override */
- create_userdir_config, /* server config */
- NULL, /* merge server config */
- userdir_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
diff --git a/modules/mappers/mod_userdir.exp b/modules/mappers/mod_userdir.exp
deleted file mode 100644
index 6b8b81d5c3..0000000000
--- a/modules/mappers/mod_userdir.exp
+++ /dev/null
@@ -1 +0,0 @@
-userdir_module
diff --git a/modules/mappers/mod_vhost_alias.c b/modules/mappers/mod_vhost_alias.c
deleted file mode 100644
index 09994fb7a4..0000000000
--- a/modules/mappers/mod_vhost_alias.c
+++ /dev/null
@@ -1,490 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * mod_vhost_alias.c: support for dynamically configured mass virtual hosting
- *
- * Copyright (c) 1998-1999 Demon Internet Ltd.
- *
- * This software was submitted by Demon Internet to the Apache Software Foundation
- * in May 1999. Future revisions and derivatives of this source code
- * must acknowledge Demon Internet as the original contributor of
- * this module. All other licensing and usage conditions are those
- * of the Apache Software Foundation.
- *
- * Originally written by Tony Finch <fanf@demon.net> <dot@dotat.at>.
- *
- * Implementation ideas were taken from mod_alias.c. The overall
- * concept is derived from the OVERRIDE_DOC_ROOT/OVERRIDE_CGIDIR
- * patch to Apache 1.3b3 and a similar feature in Demon's thttpd,
- * both written by James Grinter <jrg@blodwen.demon.co.uk>.
- */
-
-#include "apr.h"
-#include "apr_strings.h"
-#include "apr_hooks.h"
-#include "apr_lib.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#include "httpd.h"
-#include "http_config.h"
-#include "http_core.h"
-#include "http_request.h" /* for ap_hook_translate_name */
-
-
-module AP_MODULE_DECLARE_DATA vhost_alias_module;
-
-
-/*
- * basic configuration things
- * we abbreviate "mod_vhost_alias" to "mva" for shorter names
- */
-
-typedef enum {
- VHOST_ALIAS_UNSET, VHOST_ALIAS_NONE, VHOST_ALIAS_NAME, VHOST_ALIAS_IP
-} mva_mode_e;
-
-/*
- * Per-server module config record.
- */
-typedef struct mva_sconf_t {
- const char *doc_root;
- const char *cgi_root;
- mva_mode_e doc_root_mode;
- mva_mode_e cgi_root_mode;
-} mva_sconf_t;
-
-static void *mva_create_server_config(apr_pool_t *p, server_rec *s)
-{
- mva_sconf_t *conf;
-
- conf = (mva_sconf_t *) apr_pcalloc(p, sizeof(mva_sconf_t));
- conf->doc_root = NULL;
- conf->cgi_root = NULL;
- conf->doc_root_mode = VHOST_ALIAS_UNSET;
- conf->cgi_root_mode = VHOST_ALIAS_UNSET;
- return conf;
-}
-
-static void *mva_merge_server_config(apr_pool_t *p, void *parentv, void *childv)
-{
- mva_sconf_t *parent = (mva_sconf_t *) parentv;
- mva_sconf_t *child = (mva_sconf_t *) childv;
- mva_sconf_t *conf;
-
- conf = (mva_sconf_t *) apr_pcalloc(p, sizeof(*conf));
- if (child->doc_root_mode == VHOST_ALIAS_UNSET) {
- conf->doc_root_mode = parent->doc_root_mode;
- conf->doc_root = parent->doc_root;
- }
- else {
- conf->doc_root_mode = child->doc_root_mode;
- conf->doc_root = child->doc_root;
- }
- if (child->cgi_root_mode == VHOST_ALIAS_UNSET) {
- conf->cgi_root_mode = parent->cgi_root_mode;
- conf->cgi_root = parent->cgi_root;
- }
- else {
- conf->cgi_root_mode = child->cgi_root_mode;
- conf->cgi_root = child->cgi_root;
- }
- return conf;
-}
-
-
-/*
- * These are just here to tell us what vhost_alias_set should do.
- * We don't put anything into them; we just use the cell addresses.
- */
-static int vhost_alias_set_doc_root_ip,
- vhost_alias_set_cgi_root_ip,
- vhost_alias_set_doc_root_name,
- vhost_alias_set_cgi_root_name;
-
-static const char *vhost_alias_set(cmd_parms *cmd, void *dummy, const char *map)
-{
- mva_sconf_t *conf;
- mva_mode_e mode, *pmode;
- const char **pmap;
- const char *p;
-
- conf = (mva_sconf_t *) ap_get_module_config(cmd->server->module_config,
- &vhost_alias_module);
- /* there ought to be a better way of doing this */
- if (&vhost_alias_set_doc_root_ip == cmd->info) {
- mode = VHOST_ALIAS_IP;
- pmap = &conf->doc_root;
- pmode = &conf->doc_root_mode;
- }
- else if (&vhost_alias_set_cgi_root_ip == cmd->info) {
- mode = VHOST_ALIAS_IP;
- pmap = &conf->cgi_root;
- pmode = &conf->cgi_root_mode;
- }
- else if (&vhost_alias_set_doc_root_name == cmd->info) {
- mode = VHOST_ALIAS_NAME;
- pmap = &conf->doc_root;
- pmode = &conf->doc_root_mode;
- }
- else if (&vhost_alias_set_cgi_root_name == cmd->info) {
- mode = VHOST_ALIAS_NAME;
- pmap = &conf->cgi_root;
- pmode = &conf->cgi_root_mode;
- }
- else {
- return "INTERNAL ERROR: unknown command info";
- }
-
- if (*map != '/') {
- if (strcasecmp(map, "none")) {
- return "format string must start with '/' or be 'none'";
- }
- *pmap = NULL;
- *pmode = VHOST_ALIAS_NONE;
- return NULL;
- }
-
- /* sanity check */
- p = map;
- while (*p != '\0') {
- if (*p++ != '%') {
- continue;
- }
- /* we just found a '%' */
- if (*p == 'p' || *p == '%') {
- ++p;
- continue;
- }
- /* optional dash */
- if (*p == '-') {
- ++p;
- }
- /* digit N */
- if (apr_isdigit(*p)) {
- ++p;
- }
- else {
- return "syntax error in format string";
- }
- /* optional plus */
- if (*p == '+') {
- ++p;
- }
- /* do we end here? */
- if (*p != '.') {
- continue;
- }
- ++p;
- /* optional dash */
- if (*p == '-') {
- ++p;
- }
- /* digit M */
- if (apr_isdigit(*p)) {
- ++p;
- }
- else {
- return "syntax error in format string";
- }
- /* optional plus */
- if (*p == '+') {
- ++p;
- }
- }
- *pmap = map;
- *pmode = mode;
- return NULL;
-}
-
-static const command_rec mva_commands[] =
-{
- AP_INIT_TAKE1("VirtualScriptAlias", vhost_alias_set,
- &vhost_alias_set_cgi_root_name, RSRC_CONF,
- "how to create a ScriptAlias based on the host"),
- AP_INIT_TAKE1("VirtualDocumentRoot", vhost_alias_set,
- &vhost_alias_set_doc_root_name, RSRC_CONF,
- "how to create the DocumentRoot based on the host"),
- AP_INIT_TAKE1("VirtualScriptAliasIP", vhost_alias_set,
- &vhost_alias_set_cgi_root_ip, RSRC_CONF,
- "how to create a ScriptAlias based on the host"),
- AP_INIT_TAKE1("VirtualDocumentRootIP", vhost_alias_set,
- &vhost_alias_set_doc_root_ip, RSRC_CONF,
- "how to create the DocumentRoot based on the host"),
- { NULL }
-};
-
-
-/*
- * This really wants to be a nested function
- * but C is too feeble to support them.
- */
-static APR_INLINE void vhost_alias_checkspace(request_rec *r, char *buf,
- char **pdest, int size)
-{
- /* XXX: what if size > HUGE_STRING_LEN? */
- if (*pdest + size > buf + HUGE_STRING_LEN) {
- **pdest = '\0';
- if (r->filename) {
- r->filename = apr_pstrcat(r->pool, r->filename, buf, NULL);
- }
- else {
- r->filename = apr_pstrdup(r->pool, buf);
- }
- *pdest = buf;
- }
-}
-
-static void vhost_alias_interpolate(request_rec *r, const char *name,
- const char *map, const char *uri)
-{
- /* 0..9 9..0 */
- enum { MAXDOTS = 19 };
- const char *dots[MAXDOTS+1];
- int ndots;
-
- char buf[HUGE_STRING_LEN];
- char *dest, last;
-
- int N, M, Np, Mp, Nd, Md;
- const char *start, *end;
-
- const char *p;
-
- ndots = 0;
- dots[ndots++] = name-1; /* slightly naughty */
- for (p = name; *p; ++p){
- if (*p == '.' && ndots < MAXDOTS) {
- dots[ndots++] = p;
- }
- }
- dots[ndots] = p;
-
- r->filename = NULL;
-
- dest = buf;
- last = '\0';
- while (*map) {
- if (*map != '%') {
- /* normal characters */
- vhost_alias_checkspace(r, buf, &dest, 1);
- last = *dest++ = *map++;
- continue;
- }
- /* we are in a format specifier */
- ++map;
- /* can't be a slash */
- last = '\0';
- /* %% -> % */
- if (*map == '%') {
- ++map;
- vhost_alias_checkspace(r, buf, &dest, 1);
- *dest++ = '%';
- continue;
- }
- /* port number */
- if (*map == 'p') {
- ++map;
- /* no. of decimal digits in a short plus one */
- vhost_alias_checkspace(r, buf, &dest, 7);
- dest += apr_snprintf(dest, 7, "%d", ap_get_server_port(r));
- continue;
- }
- /* deal with %-N+.-M+ -- syntax is already checked */
- N = M = 0; /* value */
- Np = Mp = 0; /* is there a plus? */
- Nd = Md = 0; /* is there a dash? */
- if (*map == '-') ++map, Nd = 1;
- N = *map++ - '0';
- if (*map == '+') ++map, Np = 1;
- if (*map == '.') {
- ++map;
- if (*map == '-') {
- ++map, Md = 1;
- }
- M = *map++ - '0';
- if (*map == '+') {
- ++map, Mp = 1;
- }
- }
- /* note that N and M are one-based indices, not zero-based */
- start = dots[0]+1; /* ptr to the first character */
- end = dots[ndots]; /* ptr to the character after the last one */
- if (N != 0) {
- if (N > ndots) {
- start = "_";
- end = start+1;
- }
- else if (!Nd) {
- start = dots[N-1]+1;
- if (!Np) {
- end = dots[N];
- }
- }
- else {
- if (!Np) {
- start = dots[ndots-N]+1;
- }
- end = dots[ndots-N+1];
- }
- }
- if (M != 0) {
- if (M > end - start) {
- start = "_";
- end = start+1;
- }
- else if (!Md) {
- start = start+M-1;
- if (!Mp) {
- end = start+1;
- }
- }
- else {
- if (!Mp) {
- start = end-M;
- }
- end = end-M+1;
- }
- }
- vhost_alias_checkspace(r, buf, &dest, end - start);
- for (p = start; p < end; ++p) {
- *dest++ = apr_tolower(*p);
- }
- }
- *dest = '\0';
- /* no double slashes */
- if (last == '/') {
- ++uri;
- }
- if (r->filename) {
- r->filename = apr_pstrcat(r->pool, r->filename, buf, uri, NULL);
- }
- else {
- r->filename = apr_pstrcat(r->pool, buf, uri, NULL);
- }
-}
-
-static int mva_translate(request_rec *r)
-{
- mva_sconf_t *conf;
- const char *name, *map, *uri;
- mva_mode_e mode;
- const char *cgi;
-
- conf = (mva_sconf_t *) ap_get_module_config(r->server->module_config,
- &vhost_alias_module);
- cgi = NULL;
- if (conf->cgi_root) {
- cgi = strstr(r->uri, "cgi-bin/");
- if (cgi && cgi - r->uri != strspn(r->uri, "/")) {
- cgi = NULL;
- }
- }
- if (cgi) {
- mode = conf->cgi_root_mode;
- map = conf->cgi_root;
- uri = cgi + strlen("cgi-bin");
- }
- else if (r->uri[0] == '/') {
- mode = conf->doc_root_mode;
- map = conf->doc_root;
- uri = r->uri;
- }
- else {
- return DECLINED;
- }
-
- if (mode == VHOST_ALIAS_NAME) {
- name = ap_get_server_name(r);
- }
- else if (mode == VHOST_ALIAS_IP) {
- name = r->connection->local_ip;
- }
- else {
- return DECLINED;
- }
-
- vhost_alias_interpolate(r, name, map, uri);
-
- if (cgi) {
- /* see is_scriptaliased() in mod_cgi */
- r->handler = "cgi-script";
- apr_table_setn(r->notes, "alias-forced-type", r->handler);
- }
-
- return OK;
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_translate_name(mva_translate, NULL, NULL, APR_HOOK_MIDDLE);
-}
-
-module AP_MODULE_DECLARE_DATA vhost_alias_module =
-{
- STANDARD20_MODULE_STUFF,
- NULL, /* dir config creater */
- NULL, /* dir merger --- default is to override */
- mva_create_server_config, /* server config */
- mva_merge_server_config, /* merge server configs */
- mva_commands, /* command apr_table_t */
- register_hooks /* register hooks */
-};
-
diff --git a/modules/metadata/.cvsignore b/modules/metadata/.cvsignore
deleted file mode 100644
index 65f0cc30cf..0000000000
--- a/modules/metadata/.cvsignore
+++ /dev/null
@@ -1,10 +0,0 @@
-.deps
-.libs
-*.la
-modules.mk
-Makefile
-*.lo
-*.slo
-*.so
-Debug
-Release
diff --git a/modules/metadata/.indent.pro b/modules/metadata/.indent.pro
deleted file mode 100644
index a9fbe9f9a1..0000000000
--- a/modules/metadata/.indent.pro
+++ /dev/null
@@ -1,54 +0,0 @@
--i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1
--TBUFF
--TFILE
--TTRANS
--TUINT4
--T_trans
--Tallow_options_t
--Tapache_sfio
--Tarray_header
--Tbool_int
--Tbuf_area
--Tbuff_struct
--Tbuffy
--Tcmd_how
--Tcmd_parms
--Tcommand_rec
--Tcommand_struct
--Tconn_rec
--Tcore_dir_config
--Tcore_server_config
--Tdir_maker_func
--Tevent
--Tglobals_s
--Thandler_func
--Thandler_rec
--Tjoblist_s
--Tlisten_rec
--Tmerger_func
--Tmode_t
--Tmodule
--Tmodule_struct
--Tmutex
--Tn_long
--Tother_child_rec
--Toverrides_t
--Tparent_score
--Tpid_t
--Tpiped_log
--Tpool
--Trequest_rec
--Trequire_line
--Trlim_t
--Tscoreboard
--Tsemaphore
--Tserver_addr_rec
--Tserver_rec
--Tserver_rec_chain
--Tshort_score
--Ttable
--Ttable_entry
--Tthread
--Tu_wide_int
--Tvtime_t
--Twide_int
diff --git a/modules/metadata/Makefile.in b/modules/metadata/Makefile.in
deleted file mode 100644
index 167b343d0d..0000000000
--- a/modules/metadata/Makefile.in
+++ /dev/null
@@ -1,3 +0,0 @@
-
-include $(top_srcdir)/build/special.mk
-
diff --git a/modules/metadata/config.m4 b/modules/metadata/config.m4
deleted file mode 100644
index d1bfb56d5b..0000000000
--- a/modules/metadata/config.m4
+++ /dev/null
@@ -1,23 +0,0 @@
-dnl modules enabled in this directory by default
-
-dnl APACHE_MODULE(name, helptext[, objects[, structname[, default[, config]]]])
-
-APACHE_MODPATH_INIT(metadata)
-
-APACHE_MODULE(env, clearing/setting of ENV vars, , , yes)
-APACHE_MODULE(mime_magic, automagically determining MIME type)
-APACHE_MODULE(cern_meta, CERN-type meta files)
-APACHE_MODULE(expires, Expires header control, , , most)
-APACHE_MODULE(headers, HTTP header control, , , most)
-
-APACHE_MODULE(usertrack, user-session tracking, , , , [
- AC_CHECK_HEADERS(sys/times.h)
- AC_CHECK_FUNCS(times)
-])
-
-APACHE_MODULE(unique_id, per-request unique ids)
-APACHE_MODULE(setenvif, basing ENV vars on headers, , , yes)
-
-APR_ADDTO(LTFLAGS,-export-dynamic)
-
-APACHE_MODPATH_FINISH
diff --git a/modules/metadata/mod_cern_meta.c b/modules/metadata/mod_cern_meta.c
deleted file mode 100644
index 44a1ebae3e..0000000000
--- a/modules/metadata/mod_cern_meta.c
+++ /dev/null
@@ -1,406 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * mod_cern_meta.c
- * version 0.1.0
- * status beta
- *
- * Andrew Wilson <Andrew.Wilson@cm.cf.ac.uk> 25.Jan.96
- *
- * *** IMPORTANT ***
- * This version of mod_cern_meta.c controls Meta File behaviour on a
- * per-directory basis. Previous versions of the module defined behaviour
- * on a per-server basis. The upshot is that you'll need to revisit your
- * configuration files in order to make use of the new module.
- * ***
- *
- * Emulate the CERN HTTPD Meta file semantics. Meta files are HTTP
- * headers that can be output in addition to the normal range of
- * headers for each file accessed. They appear rather like the Apache
- * .asis files, and are able to provide a crude way of influencing
- * the Expires: header, as well as providing other curiosities.
- * There are many ways to manage meta information, this one was
- * chosen because there is already a large number of CERN users
- * who can exploit this module. It should be noted that there are probably
- * more sensitive ways of managing the Expires: header specifically.
- *
- * The module obeys the following directives, which can appear
- * in the server's .conf files and in .htaccess files.
- *
- * MetaFiles <on|off>
- *
- * turns on|off meta file processing for any directory.
- * Default value is off
- *
- * # turn on MetaFiles in this directory
- * MetaFiles on
- *
- * MetaDir <directory name>
- *
- * specifies the name of the directory in which Apache can find
- * meta information files. The directory is usually a 'hidden'
- * subdirectory of the directory that contains the file being
- * accessed. eg:
- *
- * # .meta files are in the *same* directory as the
- * # file being accessed
- * MetaDir .
- *
- * the default is to look in a '.web' subdirectory. This is the
- * same as for CERN 3.+ webservers and behaviour is the same as
- * for the directive:
- *
- * MetaDir .web
- *
- * MetaSuffix <meta file suffix>
- *
- * specifies the file name suffix for the file containing the
- * meta information. eg:
- *
- * # our meta files are suffixed with '.cern_meta'
- * MetaSuffix .cern_meta
- *
- * the default is to look for files with the suffix '.meta'. This
- * behaviour is the same as for the directive:
- *
- * MetaSuffix .meta
- *
- * When accessing the file
- *
- * DOCUMENT_ROOT/somedir/index.html
- *
- * this module will look for the file
- *
- * DOCUMENT_ROOT/somedir/.web/index.html.meta
- *
- * and will use its contents to generate additional MIME header
- * information.
- *
- * For more information on the CERN Meta file semantics see:
- *
- * http://www.w3.org/hypertext/WWW/Daemon/User/Config/General.html#MetaDir
- *
- * Change-log:
- * 29.Jan.96 pfopen/pfclose instead of fopen/fclose
- * DECLINE when real file not found, we may be checking each
- * of the index.html/index.shtml/index.htm variants and don't
- * need to report missing ones as spurious errors.
- * 31.Jan.96 log_error reports about a malformed .meta file, rather
- * than a script error.
- * 20.Jun.96 MetaFiles <on|off> default off, added, so that module
- * can be configured per-directory. Prior to this the module
- * was running for each request anywhere on the server, naughty..
- * 29.Jun.96 All directives made per-directory.
- */
-
-#include "apr.h"
-#include "apr_strings.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#if APR_HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "util_script.h"
-#include "http_log.h"
-#include "http_request.h"
-#include "apr_lib.h"
-
-#define DIR_CMD_PERMS OR_INDEXES
-
-#define DEFAULT_METADIR ".web"
-#define DEFAULT_METASUFFIX ".meta"
-#define DEFAULT_METAFILES 0
-
-module AP_MODULE_DECLARE_DATA cern_meta_module;
-
-typedef struct {
- const char *metadir;
- const char *metasuffix;
- int metafiles;
-} cern_meta_dir_config;
-
-static void *create_cern_meta_dir_config(apr_pool_t *p, char *dummy)
-{
- cern_meta_dir_config *new =
- (cern_meta_dir_config *) apr_palloc(p, sizeof(cern_meta_dir_config));
-
- new->metadir = NULL;
- new->metasuffix = NULL;
- new->metafiles = DEFAULT_METAFILES;
-
- return new;
-}
-
-static void *merge_cern_meta_dir_configs(apr_pool_t *p, void *basev, void *addv)
-{
- cern_meta_dir_config *base = (cern_meta_dir_config *) basev;
- cern_meta_dir_config *add = (cern_meta_dir_config *) addv;
- cern_meta_dir_config *new =
- (cern_meta_dir_config *) apr_palloc(p, sizeof(cern_meta_dir_config));
-
- new->metadir = add->metadir ? add->metadir : base->metadir;
- new->metasuffix = add->metasuffix ? add->metasuffix : base->metasuffix;
- new->metafiles = add->metafiles;
-
- return new;
-}
-
-static const char *set_metadir(cmd_parms *parms, void *in_dconf, const char *arg)
-{
- cern_meta_dir_config *dconf = in_dconf;
-
- dconf->metadir = arg;
- return NULL;
-}
-
-static const char *set_metasuffix(cmd_parms *parms, void *in_dconf, const char *arg)
-{
- cern_meta_dir_config *dconf = in_dconf;
-
- dconf->metasuffix = arg;
- return NULL;
-}
-
-static const char *set_metafiles(cmd_parms *parms, void *in_dconf, int arg)
-{
- cern_meta_dir_config *dconf = in_dconf;
-
- dconf->metafiles = arg;
- return NULL;
-}
-
-
-static const command_rec cern_meta_cmds[] =
-{
- AP_INIT_FLAG("MetaFiles", set_metafiles, NULL, DIR_CMD_PERMS,
- "Limited to 'on' or 'off'"),
- AP_INIT_TAKE1("MetaDir", set_metadir, NULL, DIR_CMD_PERMS,
- "the name of the directory containing meta files"),
- AP_INIT_TAKE1("MetaSuffix", set_metasuffix, NULL, DIR_CMD_PERMS,
- "the filename suffix for meta files"),
- {NULL}
-};
-
-/* XXX: this is very similar to ap_scan_script_header_err_core...
- * are the differences deliberate, or just a result of bit rot?
- */
-static int scan_meta_file(request_rec *r, apr_file_t *f)
-{
- char w[MAX_STRING_LEN];
- char *l;
- int p;
- apr_table_t *tmp_headers;
-
- tmp_headers = apr_table_make(r->pool, 5);
- while (apr_file_gets(w, MAX_STRING_LEN - 1, f) == APR_SUCCESS) {
-
- /* Delete terminal (CR?)LF */
-
- p = strlen(w);
- if (p > 0 && w[p - 1] == '\n') {
- if (p > 1 && w[p - 2] == '\015')
- w[p - 2] = '\0';
- else
- w[p - 1] = '\0';
- }
-
- if (w[0] == '\0') {
- return OK;
- }
-
- /* if we see a bogus header don't ignore it. Shout and scream */
-
- if (!(l = strchr(w, ':'))) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "malformed header in meta file: %s", r->filename);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- *l++ = '\0';
- while (*l && apr_isspace(*l))
- ++l;
-
- if (!strcasecmp(w, "Content-type")) {
- char *tmp;
- /* Nuke trailing whitespace */
-
- char *endp = l + strlen(l) - 1;
- while (endp > l && apr_isspace(*endp))
- *endp-- = '\0';
-
- tmp = apr_pstrdup(r->pool, l);
- ap_content_type_tolower(tmp);
- r->content_type = tmp;
- }
- else if (!strcasecmp(w, "Status")) {
- sscanf(l, "%d", &r->status);
- r->status_line = apr_pstrdup(r->pool, l);
- }
- else {
- apr_table_set(tmp_headers, w, l);
- }
- }
- apr_table_overlap(r->headers_out, tmp_headers, APR_OVERLAP_TABLES_SET);
- return OK;
-}
-
-static int add_cern_meta_data(request_rec *r)
-{
- char *metafilename;
- char *last_slash;
- char *real_file;
- char *scrap_book;
- apr_file_t *f = NULL;
- apr_status_t retcode;
- cern_meta_dir_config *dconf;
- int rv;
- request_rec *rr;
-
- dconf = ap_get_module_config(r->per_dir_config, &cern_meta_module);
-
- if (!dconf->metafiles) {
- return DECLINED;
- };
-
- /* if ./.web/$1.meta exists then output 'asis' */
-
- if (r->finfo.filetype == 0) {
- return DECLINED;
- };
-
- /* is this a directory? */
- if (r->finfo.filetype == APR_DIR || r->uri[strlen(r->uri) - 1] == '/') {
- return DECLINED;
- };
-
- /* what directory is this file in? */
- scrap_book = apr_pstrdup(r->pool, r->filename);
- /* skip leading slash, recovered in later processing */
- scrap_book++;
- last_slash = strrchr(scrap_book, '/');
- if (last_slash != NULL) {
- /* skip over last slash */
- real_file = last_slash;
- real_file++;
- *last_slash = '\0';
- }
- else {
- /* no last slash, buh?! */
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "internal error in mod_cern_meta: %s", r->filename);
- /* should really barf, but hey, let's be friends... */
- return DECLINED;
- };
-
- metafilename = apr_pstrcat(r->pool, "/", scrap_book, "/",
- dconf->metadir ? dconf->metadir : DEFAULT_METADIR,
- "/", real_file,
- dconf->metasuffix ? dconf->metasuffix : DEFAULT_METASUFFIX,
- NULL);
-
- /* XXX: it sucks to require this subrequest to complete, because this
- * means people must leave their meta files accessible to the world.
- * A better solution might be a "safe open" feature of pfopen to avoid
- * pipes, symlinks, and crap like that.
- */
- rr = ap_sub_req_lookup_file(metafilename, r, NULL);
- if (rr->status != HTTP_OK) {
- ap_destroy_sub_req(rr);
- return DECLINED;
- }
- ap_destroy_sub_req(rr);
-
- retcode = apr_file_open(&f, metafilename, APR_READ | APR_CREATE, APR_OS_DEFAULT, r->pool);
- if (retcode != APR_SUCCESS) {
- if (APR_STATUS_IS_ENOENT(retcode)) {
- return DECLINED;
- }
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- "meta file permissions deny server access: %s", metafilename);
- return HTTP_FORBIDDEN;
- };
-
- /* read the headers in */
- rv = scan_meta_file(r, f);
- apr_file_close(f);
-
- return rv;
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_fixups(add_cern_meta_data,NULL,NULL,APR_HOOK_MIDDLE);
-}
-
-module AP_MODULE_DECLARE_DATA cern_meta_module =
-{
- STANDARD20_MODULE_STUFF,
- create_cern_meta_dir_config,/* dir config creater */
- merge_cern_meta_dir_configs,/* dir merger --- default is to override */
- NULL, /* server config */
- NULL, /* merge server configs */
- cern_meta_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
diff --git a/modules/metadata/mod_cern_meta.dsp b/modules/metadata/mod_cern_meta.dsp
deleted file mode 100644
index 789970ced3..0000000000
--- a/modules/metadata/mod_cern_meta.dsp
+++ /dev/null
@@ -1,95 +0,0 @@
-# Microsoft Developer Studio Project File - Name="mod_cern_meta" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=mod_cern_meta - Win32 Release
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "mod_cern_meta.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_cern_meta.mak" CFG="mod_cern_meta - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_cern_meta - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_cern_meta - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "mod_cern_meta - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\os\win32" /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_cern_meta" /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "NDEBUG"
-# ADD RSC /l 0x809 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_cern_meta.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_cern_meta
-# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_cern_meta.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_cern_meta
-
-!ELSEIF "$(CFG)" == "mod_cern_meta - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\..\include" /I "..\..\os\win32" /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_cern_meta" /FD /c
-# ADD BASE MTL /nologo /D "_DEBUG" /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "_DEBUG"
-# ADD RSC /l 0x809 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /out:"Debug/mod_cern_meta.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_cern_meta
-# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /out:"Debug/mod_cern_meta.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_cern_meta
-
-!ENDIF
-
-# Begin Target
-
-# Name "mod_cern_meta - Win32 Release"
-# Name "mod_cern_meta - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\mod_cern_meta.c
-# End Source File
-# End Target
-# End Project
diff --git a/modules/metadata/mod_cern_meta.exp b/modules/metadata/mod_cern_meta.exp
deleted file mode 100644
index d36e2be6a8..0000000000
--- a/modules/metadata/mod_cern_meta.exp
+++ /dev/null
@@ -1 +0,0 @@
-cern_meta_module
diff --git a/modules/metadata/mod_cern_meta.mak b/modules/metadata/mod_cern_meta.mak
deleted file mode 100644
index c21fe9c48c..0000000000
--- a/modules/metadata/mod_cern_meta.mak
+++ /dev/null
@@ -1,327 +0,0 @@
-# Microsoft Developer Studio Generated NMAKE File, Based on mod_cern_meta.dsp
-!IF "$(CFG)" == ""
-CFG=mod_cern_meta - Win32 Release
-!MESSAGE No configuration specified. Defaulting to mod_cern_meta - Win32\
- Release.
-!ENDIF
-
-!IF "$(CFG)" != "mod_cern_meta - Win32 Release" && "$(CFG)" !=\
- "mod_cern_meta - Win32 Debug"
-!MESSAGE Invalid configuration "$(CFG)" specified.
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_cern_meta.mak" CFG="mod_cern_meta - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_cern_meta - Win32 Release" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_cern_meta - Win32 Debug" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-!ERROR An invalid configuration is specified.
-!ENDIF
-
-!IF "$(OS)" == "Windows_NT"
-NULL=
-!ELSE
-NULL=nul
-!ENDIF
-
-!IF "$(CFG)" == "mod_cern_meta - Win32 Release"
-
-OUTDIR=.\Release
-INTDIR=.\Release
-# Begin Custom Macros
-OutDir=.\Release
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_cern_meta.so"
-
-!ELSE
-
-ALL : "libhttpd - Win32 Release" "libapr - Win32 Release"\
- "$(OUTDIR)\mod_cern_meta.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libapr - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\mod_cern_meta.idb"
- -@erase "$(INTDIR)\mod_cern_meta.obj"
- -@erase "$(OUTDIR)\mod_cern_meta.exp"
- -@erase "$(OUTDIR)\mod_cern_meta.lib"
- -@erase "$(OUTDIR)\mod_cern_meta.map"
- -@erase "$(OUTDIR)\mod_cern_meta.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\os\win32" /I\
- "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D\
- "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_cern_meta" /FD /c
-CPP_OBJS=.\Release/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_cern_meta.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no\
- /pdb:"$(OUTDIR)\mod_cern_meta.pdb" /map:"$(INTDIR)\mod_cern_meta.map"\
- /machine:I386 /out:"$(OUTDIR)\mod_cern_meta.so"\
- /implib:"$(OUTDIR)\mod_cern_meta.lib"\
- /base:@..\..\os\win32\BaseAddr.ref,mod_cern_meta
-LINK32_OBJS= \
- "$(INTDIR)\mod_cern_meta.obj" \
- "..\..\Release\libhttpd.lib" \
- "..\..\srclib\apr\Release\libapr.lib"
-
-"$(OUTDIR)\mod_cern_meta.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ELSEIF "$(CFG)" == "mod_cern_meta - Win32 Debug"
-
-OUTDIR=.\Debug
-INTDIR=.\Debug
-# Begin Custom Macros
-OutDir=.\Debug
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_cern_meta.so"
-
-!ELSE
-
-ALL : "libhttpd - Win32 Debug" "libapr - Win32 Debug"\
- "$(OUTDIR)\mod_cern_meta.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libapr - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\mod_cern_meta.idb"
- -@erase "$(INTDIR)\mod_cern_meta.obj"
- -@erase "$(OUTDIR)\mod_cern_meta.exp"
- -@erase "$(OUTDIR)\mod_cern_meta.lib"
- -@erase "$(OUTDIR)\mod_cern_meta.map"
- -@erase "$(OUTDIR)\mod_cern_meta.pdb"
- -@erase "$(OUTDIR)\mod_cern_meta.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /I\
- "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D\
- "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_cern_meta" /FD /c
-CPP_OBJS=.\Debug/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_cern_meta.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no\
- /pdb:"$(OUTDIR)\mod_cern_meta.pdb" /map:"$(INTDIR)\mod_cern_meta.map" /debug\
- /machine:I386 /out:"$(OUTDIR)\mod_cern_meta.so"\
- /implib:"$(OUTDIR)\mod_cern_meta.lib"\
- /base:@..\..\os\win32\BaseAddr.ref,mod_cern_meta
-LINK32_OBJS= \
- "$(INTDIR)\mod_cern_meta.obj" \
- "..\..\Debug\libhttpd.lib" \
- "..\..\srclib\apr\Debug\libapr.lib"
-
-"$(OUTDIR)\mod_cern_meta.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ENDIF
-
-
-!IF "$(CFG)" == "mod_cern_meta - Win32 Release" || "$(CFG)" ==\
- "mod_cern_meta - Win32 Debug"
-
-!IF "$(CFG)" == "mod_cern_meta - Win32 Release"
-
-"libapr - Win32 Release" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F .\libapr.mak CFG="libapr - Win32 Release"
- cd "..\..\modules\metadata"
-
-"libapr - Win32 ReleaseCLEAN" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libapr.mak CFG="libapr - Win32 Release"\
- RECURSE=1
- cd "..\..\modules\metadata"
-
-!ELSEIF "$(CFG)" == "mod_cern_meta - Win32 Debug"
-
-"libapr - Win32 Debug" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F .\libapr.mak CFG="libapr - Win32 Debug"
- cd "..\..\modules\metadata"
-
-"libapr - Win32 DebugCLEAN" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libapr.mak CFG="libapr - Win32 Debug"\
- RECURSE=1
- cd "..\..\modules\metadata"
-
-!ENDIF
-
-!IF "$(CFG)" == "mod_cern_meta - Win32 Release"
-
-"libhttpd - Win32 Release" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) /F .\libhttpd.mak CFG="libhttpd - Win32 Release"
- cd ".\modules\metadata"
-
-"libhttpd - Win32 ReleaseCLEAN" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libhttpd.mak CFG="libhttpd - Win32 Release"\
- RECURSE=1
- cd ".\modules\metadata"
-
-!ELSEIF "$(CFG)" == "mod_cern_meta - Win32 Debug"
-
-"libhttpd - Win32 Debug" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) /F .\libhttpd.mak CFG="libhttpd - Win32 Debug"
- cd ".\modules\metadata"
-
-"libhttpd - Win32 DebugCLEAN" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libhttpd.mak CFG="libhttpd - Win32 Debug"\
- RECURSE=1
- cd ".\modules\metadata"
-
-!ENDIF
-
-SOURCE=.\mod_cern_meta.c
-DEP_CPP_MOD_C=\
- "..\..\include\ap_config.h"\
- "..\..\include\ap_mmn.h"\
- "..\..\include\ap_release.h"\
- "..\..\include\http_config.h"\
- "..\..\include\http_log.h"\
- "..\..\include\http_request.h"\
- "..\..\include\httpd.h"\
- "..\..\include\pcreposix.h"\
- "..\..\include\util_cfgtree.h"\
- "..\..\include\util_filter.h"\
- "..\..\include\util_script.h"\
- "..\..\include\util_uri.h"\
- "..\..\os\win32\os.h"\
- "..\..\srclib\apr-util\include\apr_buckets.h"\
- "..\..\srclib\apr-util\include\apr_hooks.h"\
- "..\..\srclib\apr-util\include\apr_ring.h"\
- "..\..\srclib\apr-util\include\apu.h"\
- "..\..\srclib\apr\include\apr.h"\
- "..\..\srclib\apr\include\apr_errno.h"\
- "..\..\srclib\apr\include\apr_file_info.h"\
- "..\..\srclib\apr\include\apr_file_io.h"\
- "..\..\srclib\apr\include\apr_general.h"\
- "..\..\srclib\apr\include\apr_lib.h"\
- "..\..\srclib\apr\include\apr_mmap.h"\
- "..\..\srclib\apr\include\apr_network_io.h"\
- "..\..\srclib\apr\include\apr_pools.h"\
- "..\..\srclib\apr\include\apr_strings.h"\
- "..\..\srclib\apr\include\apr_tables.h"\
- "..\..\srclib\apr\include\apr_thread_proc.h"\
- "..\..\srclib\apr\include\apr_time.h"\
- "..\..\srclib\apr\include\apr_user.h"\
- "..\..\srclib\apr\include\apr_want.h"\
-
-NODEP_CPP_MOD_C=\
- "..\..\include\ap_config_auto.h"\
-
-
-"$(INTDIR)\mod_cern_meta.obj" : $(SOURCE) $(DEP_CPP_MOD_C) "$(INTDIR)"
-
-
-
-!ENDIF
-
diff --git a/modules/metadata/mod_env.c b/modules/metadata/mod_env.c
deleted file mode 100644
index ebe112b859..0000000000
--- a/modules/metadata/mod_env.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * mod_env.c
- * version 0.0.5
- * status beta
- * Pass environment variables to CGI/SSI scripts.
- *
- * Andrew Wilson <Andrew.Wilson@cm.cf.ac.uk> 06.Dec.95
- *
- * Change log:
- * 08.Dec.95 Now allows PassEnv directive to appear more than once in
- * conf files.
- * 10.Dec.95 optimisation. getenv() only called at startup and used
- * to build a fast-to-access table. apr_table_t used to build
- * per-server environment for each request.
- * robustness. better able to handle errors in configuration
- * files:
- * 1) PassEnv directive present, but no environment variable listed
- * 2) PassEnv FOO present, but $FOO not present in environment
- * 3) no PassEnv directive present
- * 23.Dec.95 Now allows SetEnv directive with same semantics as 'sh' setenv:
- * SetEnv Var sets Var to the empty string
- * SetEnv Var Val sets Var to the value Val
- * Values containing whitespace should be quoted, eg:
- * SetEnv Var "this is some text"
- * Environment variables take their value from the last instance
- * of PassEnv / SetEnv to be reached in the configuration file.
- * For example, the sequence:
- * PassEnv FOO
- * SetEnv FOO override
- * Causes FOO to take the value 'override'.
- * 23.Feb.96 Added UnsetEnv directive to allow environment variables
- * to be removed.
- * Virtual hosts now 'inherit' parent server environment which
- * they're able to overwrite with their own directives or
- * selectively ignore with UnsetEnv.
- * *** IMPORTANT - the way that virtual hosts inherit their ***
- * *** environment variables from the default server's ***
- * *** configuration has changed. You should test your ***
- * *** configuration carefully before accepting this ***
- * *** version of the module in a live webserver which used ***
- * *** older versions of the module. ***
- */
-
-#include "apr.h"
-#include "apr_strings.h"
-
-#if APR_HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_request.h"
-
-
-typedef struct {
- apr_table_t *vars;
- const char *unsetenv;
- int vars_present;
-} env_dir_config_rec;
-
-module AP_MODULE_DECLARE_DATA env_module;
-
-static void *create_env_dir_config(apr_pool_t *p, char *dummy)
-{
- env_dir_config_rec *conf = apr_palloc(p, sizeof(*conf));
-
- conf->vars = apr_table_make(p, 50);
- conf->unsetenv = "";
- conf->vars_present = 0;
-
- return conf;
-}
-
-static void *merge_env_dir_configs(apr_pool_t *p, void *basev, void *addv)
-{
- env_dir_config_rec *base = basev;
- env_dir_config_rec *add = addv;
- env_dir_config_rec *newconf = apr_palloc(p, sizeof(*newconf));
-
- apr_table_t *new_table;
- apr_table_entry_t *elts;
- apr_array_header_t *arr;
-
- int i;
- const char *uenv, *unset;
-
- /*
- * new_table = copy_table( p, base->vars );
- * foreach $element ( @add->vars ) {
- * table_set( new_table, $element.key, $element.val );
- * };
- * foreach $unsetenv ( @UNSETENV ) {
- * table_unset( new_table, $unsetenv );
- * }
- */
-
- new_table = apr_table_copy(p, base->vars);
-
- arr = apr_table_elts(add->vars);
- elts = (apr_table_entry_t *)arr->elts;
-
- for (i = 0; i < arr->nelts; ++i) {
- apr_table_setn(new_table, elts[i].key, elts[i].val);
- }
-
- unset = add->unsetenv;
- uenv = ap_getword_conf(p, &unset);
- while (uenv[0] != '\0') {
- apr_table_unset(new_table, uenv);
- uenv = ap_getword_conf(p, &unset);
- }
-
- newconf->vars = new_table;
-
- newconf->vars_present = base->vars_present || add->vars_present;
-
- return newconf;
-}
-
-static const char *add_env_module_vars_passed(cmd_parms *cmd, void *sconf_,
- const char *arg)
-{
- env_dir_config_rec *sconf = sconf_;
- apr_table_t *vars = sconf->vars;
- char *env_var;
- char *name_ptr;
-
- while (*arg) {
- name_ptr = ap_getword_conf(cmd->pool, &arg);
- env_var = getenv(name_ptr);
- if (env_var != NULL) {
- sconf->vars_present = 1;
- apr_table_setn(vars, name_ptr, apr_pstrdup(cmd->pool, env_var));
- }
- }
- return NULL;
-}
-
-static const char *add_env_module_vars_set(cmd_parms *cmd, void *sconf_,
- const char *arg)
-{
- env_dir_config_rec *sconf = sconf_;
- apr_table_t *vars = sconf->vars;
- char *name, *value;
-
- name = ap_getword_conf(cmd->pool, &arg);
- value = ap_getword_conf(cmd->pool, &arg);
-
- /* name is mandatory, value is optional. no value means
- * set the variable to an empty string
- */
-
-
- if ((*name == '\0') || (*arg != '\0')) {
- return "SetEnv takes one or two arguments. An environment variable name and an optional value to pass to CGI.";
- }
-
- sconf->vars_present = 1;
- apr_table_setn(vars, name, value);
-
- return NULL;
-}
-
-static const char *add_env_module_vars_unset(cmd_parms *cmd, void *sconf_,
- const char *arg)
-{
- env_dir_config_rec *sconf = sconf_;
-
- sconf->unsetenv = sconf->unsetenv
- ? apr_pstrcat(cmd->pool, sconf->unsetenv, " ", arg, NULL)
- : arg;
-
- return NULL;
-}
-
-static const command_rec env_module_cmds[] =
-{
-AP_INIT_RAW_ARGS("PassEnv", add_env_module_vars_passed, NULL,
- OR_FILEINFO, "a list of environment variables to pass to CGI."),
-AP_INIT_RAW_ARGS("SetEnv", add_env_module_vars_set, NULL,
- OR_FILEINFO, "an environment variable name and a value to pass to CGI."),
-AP_INIT_RAW_ARGS("UnsetEnv", add_env_module_vars_unset, NULL,
- OR_FILEINFO, "a list of variables to remove from the CGI environment."),
- {NULL},
-};
-
-static int fixup_env_module(request_rec *r)
-{
- apr_table_t *e = r->subprocess_env;
- env_dir_config_rec *sconf = ap_get_module_config(r->per_dir_config,
- &env_module);
- apr_table_t *vars = sconf->vars;
-
- if (!sconf->vars_present)
- return DECLINED;
-
- r->subprocess_env = apr_table_overlay(r->pool, e, vars);
-
- return OK;
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_fixups(fixup_env_module, NULL, NULL, APR_HOOK_MIDDLE);
-}
-
-module AP_MODULE_DECLARE_DATA env_module =
-{
- STANDARD20_MODULE_STUFF,
- create_env_dir_config, /* dir config creater */
- merge_env_dir_configs, /* dir merger --- default is to override */
- NULL, /* server config */
- NULL, /* merge server configs */
- env_module_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
diff --git a/modules/metadata/mod_env.exp b/modules/metadata/mod_env.exp
deleted file mode 100644
index b487bf09c8..0000000000
--- a/modules/metadata/mod_env.exp
+++ /dev/null
@@ -1 +0,0 @@
-env_module
diff --git a/modules/metadata/mod_expires.c b/modules/metadata/mod_expires.c
deleted file mode 100644
index 068c03cf2e..0000000000
--- a/modules/metadata/mod_expires.c
+++ /dev/null
@@ -1,520 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * mod_expires.c
- * version 0.0.11
- * status beta
- *
- * Andrew Wilson <Andrew.Wilson@cm.cf.ac.uk> 26.Jan.96
- *
- * This module allows you to control the form of the Expires: header
- * that Apache issues for each access. Directives can appear in
- * configuration files or in .htaccess files so expiry semantics can
- * be defined on a per-directory basis.
- *
- * DIRECTIVE SYNTAX
- *
- * Valid directives are:
- *
- * ExpiresActive on | off
- * ExpiresDefault <code><seconds>
- * ExpiresByType type/encoding <code><seconds>
- *
- * Valid values for <code> are:
- *
- * 'M' expires header shows file modification date + <seconds>
- * 'A' expires header shows access time + <seconds>
- *
- * [I'm not sure which of these is best under different
- * circumstances, I guess it's for other people to explore.
- * The effects may be indistinguishable for a number of cases]
- *
- * <seconds> should be an integer value [acceptable to atoi()]
- *
- * There is NO space between the <code> and <seconds>.
- *
- * For example, a directory which contains information which changes
- * frequently might contain:
- *
- * # reports generated by cron every hour. don't let caches
- * # hold onto stale information
- * ExpiresDefault M3600
- *
- * Another example, our html pages can change all the time, the gifs
- * tend not to change often:
- *
- * # pages are hot (1 week), images are cold (1 month)
- * ExpiresByType text/html A604800
- * ExpiresByType image/gif A2592000
- *
- * Expires can be turned on for all URLs on the server by placing the
- * following directive in a conf file:
- *
- * ExpiresActive on
- *
- * ExpiresActive can also appear in .htaccess files, enabling the
- * behaviour to be turned on or off for each chosen directory.
- *
- * # turn off Expires behaviour in this directory
- * # and subdirectories
- * ExpiresActive off
- *
- * Directives defined for a directory are valid in subdirectories
- * unless explicitly overridden by new directives in the subdirectory
- * .htaccess files.
- *
- * ALTERNATIVE DIRECTIVE SYNTAX
- *
- * Directives can also be defined in a more readable syntax of the form:
- *
- * ExpiresDefault "<base> [plus] {<num> <type>}*"
- * ExpiresByType type/encoding "<base> [plus] {<num> <type>}*"
- *
- * where <base> is one of:
- * access
- * now equivalent to 'access'
- * modification
- *
- * where the 'plus' keyword is optional
- *
- * where <num> should be an integer value [acceptable to atoi()]
- *
- * where <type> is one of:
- * years
- * months
- * weeks
- * days
- * hours
- * minutes
- * seconds
- *
- * For example, any of the following directives can be used to make
- * documents expire 1 month after being accessed, by default:
- *
- * ExpiresDefault "access plus 1 month"
- * ExpiresDefault "access plus 4 weeks"
- * ExpiresDefault "access plus 30 days"
- *
- * The expiry time can be fine-tuned by adding several '<num> <type>'
- * clauses:
- *
- * ExpiresByType text/html "access plus 1 month 15 days 2 hours"
- * ExpiresByType image/gif "modification plus 5 hours 3 minutes"
- *
- * ---
- *
- * Change-log:
- * 29.Jan.96 Hardened the add_* functions. Server will now bail out
- * if bad directives are given in the conf files.
- * 02.Feb.96 Returns DECLINED if not 'ExpiresActive on', giving other
- * expires-aware modules a chance to play with the same
- * directives. [Michael Rutman]
- * 03.Feb.96 Call tzset() before localtime(). Trying to get the module
- * to work properly in non GMT timezones.
- * 12.Feb.96 Modified directive syntax to allow more readable commands:
- * ExpiresDefault "now plus 10 days 20 seconds"
- * ExpiresDefault "access plus 30 days"
- * ExpiresDefault "modification plus 1 year 10 months 30 days"
- * 13.Feb.96 Fix call to table_get() with NULL 2nd parameter [Rob Hartill]
- * 19.Feb.96 Call gm_timestr_822() to get time formatted correctly, can't
- * rely on presence of HTTP_TIME_FORMAT in Apache 1.1+.
- * 21.Feb.96 This version (0.0.9) reverses assumptions made in 0.0.8
- * about star/star handlers. Reverting to 0.0.7 behaviour.
- * 08.Jun.96 allows ExpiresDefault to be used with responses that use
- * the DefaultType by not DECLINING, but instead skipping
- * the table_get check and then looking for an ExpiresDefault.
- * [Rob Hartill]
- * 04.Nov.96 'const' definitions added.
- *
- * TODO
- * add support for Cache-Control: max-age=20 from the HTTP/1.1
- * proposal (in this case, a ttl of 20 seconds) [ask roy]
- * add per-file expiry and explicit expiry times - duplicates some
- * of the mod_cern_meta.c functionality. eg:
- * ExpiresExplicit index.html "modification plus 30 days"
- *
- * BUGS
- * Hi, welcome to the internet.
- */
-
-#include "apr.h"
-#include "apr_strings.h"
-#include "apr_lib.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_log.h"
-#include "http_request.h"
-
-typedef struct {
- int active;
- char *expiresdefault;
- apr_table_t *expiresbytype;
-} expires_dir_config;
-
-/* from mod_dir, why is this alias used?
- */
-#define DIR_CMD_PERMS OR_INDEXES
-
-#define ACTIVE_ON 1
-#define ACTIVE_OFF 0
-#define ACTIVE_DONTCARE 2
-
-module AP_MODULE_DECLARE_DATA expires_module;
-
-static void *create_dir_expires_config(apr_pool_t *p, char *dummy)
-{
- expires_dir_config *new =
- (expires_dir_config *) apr_pcalloc(p, sizeof(expires_dir_config));
- new->active = ACTIVE_DONTCARE;
- new->expiresdefault = "";
- new->expiresbytype = apr_table_make(p, 4);
- return (void *) new;
-}
-
-static const char *set_expiresactive(cmd_parms *cmd, void *in_dir_config, int arg)
-{
- expires_dir_config *dir_config = in_dir_config;
-
- /* if we're here at all it's because someone explicitly
- * set the active flag
- */
- dir_config->active = ACTIVE_ON;
- if (arg == 0) {
- dir_config->active = ACTIVE_OFF;
- };
- return NULL;
-}
-
-/* check_code() parse 'code' and return NULL or an error response
- * string. If we return NULL then real_code contains code converted
- * to the cnnnn format.
- */
-static char *check_code(apr_pool_t *p, const char *code, char **real_code)
-{
- char *word;
- char base = 'X';
- int modifier = 0;
- int num = 0;
- int factor = 0;
-
- /* 0.0.4 compatibility?
- */
- if ((code[0] == 'A') || (code[0] == 'M')) {
- *real_code = (char *)code;
- return NULL;
- };
-
- /* <base> [plus] {<num> <type>}*
- */
-
- /* <base>
- */
- word = ap_getword_conf(p, &code);
- if (!strncasecmp(word, "now", 1) ||
- !strncasecmp(word, "access", 1)) {
- base = 'A';
- }
- else if (!strncasecmp(word, "modification", 1)) {
- base = 'M';
- }
- else {
- return apr_pstrcat(p, "bad expires code, unrecognised <base> '",
- word, "'", NULL);
- };
-
- /* [plus]
- */
- word = ap_getword_conf(p, &code);
- if (!strncasecmp(word, "plus", 1)) {
- word = ap_getword_conf(p, &code);
- };
-
- /* {<num> <type>}*
- */
- while (word[0]) {
- /* <num>
- */
- if (apr_isdigit(word[0])) {
- num = atoi(word);
- }
- else {
- return apr_pstrcat(p, "bad expires code, numeric value expected <num> '",
- word, "'", NULL);
- };
-
- /* <type>
- */
- word = ap_getword_conf(p, &code);
- if (word[0]) {
- /* do nothing */
- }
- else {
- return apr_pstrcat(p, "bad expires code, missing <type>", NULL);
- };
-
- factor = 0;
- if (!strncasecmp(word, "years", 1)) {
- factor = 60 * 60 * 24 * 365;
- }
- else if (!strncasecmp(word, "months", 2)) {
- factor = 60 * 60 * 24 * 30;
- }
- else if (!strncasecmp(word, "weeks", 1)) {
- factor = 60 * 60 * 24 * 7;
- }
- else if (!strncasecmp(word, "days", 1)) {
- factor = 60 * 60 * 24;
- }
- else if (!strncasecmp(word, "hours", 1)) {
- factor = 60 * 60;
- }
- else if (!strncasecmp(word, "minutes", 2)) {
- factor = 60;
- }
- else if (!strncasecmp(word, "seconds", 1)) {
- factor = 1;
- }
- else {
- return apr_pstrcat(p, "bad expires code, unrecognised <type>",
- "'", word, "'", NULL);
- };
-
- modifier = modifier + factor * num;
-
- /* next <num>
- */
- word = ap_getword_conf(p, &code);
- };
-
- *real_code = apr_psprintf(p, "%c%d", base, modifier);
-
- return NULL;
-}
-
-static const char *set_expiresbytype(cmd_parms *cmd, void *in_dir_config,
- const char *mime, const char *code)
-{
- expires_dir_config *dir_config = in_dir_config;
- char *response, *real_code;
-
- if ((response = check_code(cmd->pool, code, &real_code)) == NULL) {
- apr_table_setn(dir_config->expiresbytype, mime, real_code);
- return NULL;
- };
- return apr_pstrcat(cmd->pool,
- "'ExpiresByType ", mime, " ", code, "': ", response, NULL);
-}
-
-static const char *set_expiresdefault(cmd_parms *cmd, void *in_dir_config,
- const char *code)
-{
- expires_dir_config * dir_config = in_dir_config;
- char *response, *real_code;
-
- if ((response = check_code(cmd->pool, code, &real_code)) == NULL) {
- dir_config->expiresdefault = real_code;
- return NULL;
- };
- return apr_pstrcat(cmd->pool,
- "'ExpiresDefault ", code, "': ", response, NULL);
-}
-
-static const command_rec expires_cmds[] =
-{
- AP_INIT_FLAG("ExpiresActive", set_expiresactive, NULL, DIR_CMD_PERMS,
- "Limited to 'on' or 'off'"),
- AP_INIT_TAKE2("ExpiresBytype", set_expiresbytype, NULL, DIR_CMD_PERMS,
- "a MIME type followed by an expiry date code"),
- AP_INIT_TAKE1("ExpiresDefault", set_expiresdefault, NULL, DIR_CMD_PERMS,
- "an expiry date code"),
- {NULL}
-};
-
-static void *merge_expires_dir_configs(apr_pool_t *p, void *basev, void *addv)
-{
- expires_dir_config *new = (expires_dir_config *) apr_pcalloc(p, sizeof(expires_dir_config));
- expires_dir_config *base = (expires_dir_config *) basev;
- expires_dir_config *add = (expires_dir_config *) addv;
-
- if (add->active == ACTIVE_DONTCARE) {
- new->active = base->active;
- }
- else {
- new->active = add->active;
- };
-
- if (add->expiresdefault != '\0') {
- new->expiresdefault = add->expiresdefault;
- };
-
- new->expiresbytype = apr_table_overlay(p, add->expiresbytype,
- base->expiresbytype);
- return new;
-}
-
-static int add_expires(request_rec *r)
-{
- expires_dir_config *conf;
- char *code;
- apr_time_t base;
- apr_time_t additional;
- apr_time_t expires;
- char *timestr;
-
- if (ap_is_HTTP_ERROR(r->status)) /* Don't add Expires headers to errors */
- return DECLINED;
-
- if (r->main != NULL) /* Say no to subrequests */
- return DECLINED;
-
- conf = (expires_dir_config *) ap_get_module_config(r->per_dir_config, &expires_module);
- if (conf == NULL) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "internal error: %s", r->filename);
- return HTTP_INTERNAL_SERVER_ERROR;
- };
-
- if (conf->active != ACTIVE_ON)
- return DECLINED;
-
- /* we perhaps could use the default_type(r) in its place but that
- * may be 2nd guesing the desired configuration... calling table_get
- * with a NULL key will SEGV us
- *
- * I still don't know *why* r->content_type would ever be NULL, this
- * is possibly a result of fixups being called in many different
- * places. Fixups is probably the wrong place to be doing all this
- * work... Bah.
- *
- * Changed as of 08.Jun.96 don't DECLINE, look for an ExpiresDefault.
- */
- if (r->content_type == NULL)
- code = NULL;
- else
- code = (char *) apr_table_get(conf->expiresbytype,
- ap_field_noparam(r->pool, r->content_type));
-
- if (code == NULL) {
- /* no expires defined for that type, is there a default? */
- code = conf->expiresdefault;
-
- if (code[0] == '\0')
- return OK;
- };
-
- /* we have our code */
-
- switch (code[0]) {
- case 'M':
- if (r->finfo.filetype == 0) {
- /* file doesn't exist on disk, so we can't do anything based on
- * modification time. Note that this does _not_ log an error.
- */
- return DECLINED;
- }
- base = r->finfo.mtime;
- additional = atoi(&code[1]);
- break;
- case 'A':
- /* there's been some discussion and it's possible that
- * 'access time' will be stored in request structure
- */
- base = r->request_time;
- additional = atoi(&code[1]);
- break;
- default:
- /* expecting the add_* routines to be case-hardened this
- * is just a reminder that module is beta
- */
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "internal error: bad expires code: %s", r->filename);
- return HTTP_INTERNAL_SERVER_ERROR;
- };
-
- expires = base + additional;
- apr_table_mergen(r->headers_out, "Cache-Control",
- apr_psprintf(r->pool, "max-age=%qd",
- (expires - r->request_time)
- / APR_USEC_PER_SEC));
- timestr = apr_palloc(r->pool, APR_RFC822_DATE_LEN);
- apr_rfc822_date(timestr, expires);
- apr_table_setn(r->headers_out, "Expires", timestr);
- return OK;
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_fixups(add_expires,NULL,NULL,APR_HOOK_MIDDLE);
-}
-
-module AP_MODULE_DECLARE_DATA expires_module =
-{
- STANDARD20_MODULE_STUFF,
- create_dir_expires_config, /* dir config creater */
- merge_expires_dir_configs, /* dir merger --- default is to override */
- NULL, /* server config */
- NULL, /* merge server configs */
- expires_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
diff --git a/modules/metadata/mod_expires.dsp b/modules/metadata/mod_expires.dsp
deleted file mode 100644
index a0fac42270..0000000000
--- a/modules/metadata/mod_expires.dsp
+++ /dev/null
@@ -1,95 +0,0 @@
-# Microsoft Developer Studio Project File - Name="mod_expires" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=mod_expires - Win32 Release
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "mod_expires.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_expires.mak" CFG="mod_expires - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_expires - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_expires - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "mod_expires - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\os\win32" /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_expires" /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "NDEBUG"
-# ADD RSC /l 0x809 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_expires.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_expires
-# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_expires.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_expires
-
-!ELSEIF "$(CFG)" == "mod_expires - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\..\include" /I "..\..\os\win32" /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_expires" /FD /c
-# ADD BASE MTL /nologo /D "_DEBUG" /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "_DEBUG"
-# ADD RSC /l 0x809 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /out:"Debug/mod_expires.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_expires
-# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /out:"Debug/mod_expires.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_expires
-
-!ENDIF
-
-# Begin Target
-
-# Name "mod_expires - Win32 Release"
-# Name "mod_expires - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\mod_expires.c
-# End Source File
-# End Target
-# End Project
diff --git a/modules/metadata/mod_expires.exp b/modules/metadata/mod_expires.exp
deleted file mode 100644
index 863a96878e..0000000000
--- a/modules/metadata/mod_expires.exp
+++ /dev/null
@@ -1 +0,0 @@
-expires_module
diff --git a/modules/metadata/mod_expires.mak b/modules/metadata/mod_expires.mak
deleted file mode 100644
index 2dcc652d05..0000000000
--- a/modules/metadata/mod_expires.mak
+++ /dev/null
@@ -1,324 +0,0 @@
-# Microsoft Developer Studio Generated NMAKE File, Based on mod_expires.dsp
-!IF "$(CFG)" == ""
-CFG=mod_expires - Win32 Release
-!MESSAGE No configuration specified. Defaulting to mod_expires - Win32 Release.
-!ENDIF
-
-!IF "$(CFG)" != "mod_expires - Win32 Release" && "$(CFG)" !=\
- "mod_expires - Win32 Debug"
-!MESSAGE Invalid configuration "$(CFG)" specified.
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_expires.mak" CFG="mod_expires - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_expires - Win32 Release" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_expires - Win32 Debug" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-!ERROR An invalid configuration is specified.
-!ENDIF
-
-!IF "$(OS)" == "Windows_NT"
-NULL=
-!ELSE
-NULL=nul
-!ENDIF
-
-!IF "$(CFG)" == "mod_expires - Win32 Release"
-
-OUTDIR=.\Release
-INTDIR=.\Release
-# Begin Custom Macros
-OutDir=.\Release
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_expires.so"
-
-!ELSE
-
-ALL : "libhttpd - Win32 Release" "libapr - Win32 Release"\
- "$(OUTDIR)\mod_expires.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libapr - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\mod_expires.idb"
- -@erase "$(INTDIR)\mod_expires.obj"
- -@erase "$(OUTDIR)\mod_expires.exp"
- -@erase "$(OUTDIR)\mod_expires.lib"
- -@erase "$(OUTDIR)\mod_expires.map"
- -@erase "$(OUTDIR)\mod_expires.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\os\win32" /I\
- "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D\
- "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_expires" /FD /c
-CPP_OBJS=.\Release/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_expires.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no\
- /pdb:"$(OUTDIR)\mod_expires.pdb" /map:"$(INTDIR)\mod_expires.map" /machine:I386\
- /out:"$(OUTDIR)\mod_expires.so" /implib:"$(OUTDIR)\mod_expires.lib"\
- /base:@..\..\os\win32\BaseAddr.ref,mod_expires
-LINK32_OBJS= \
- "$(INTDIR)\mod_expires.obj" \
- "..\..\Release\libhttpd.lib" \
- "..\..\srclib\apr\Release\libapr.lib"
-
-"$(OUTDIR)\mod_expires.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ELSEIF "$(CFG)" == "mod_expires - Win32 Debug"
-
-OUTDIR=.\Debug
-INTDIR=.\Debug
-# Begin Custom Macros
-OutDir=.\Debug
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_expires.so"
-
-!ELSE
-
-ALL : "libhttpd - Win32 Debug" "libapr - Win32 Debug"\
- "$(OUTDIR)\mod_expires.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libapr - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\mod_expires.idb"
- -@erase "$(INTDIR)\mod_expires.obj"
- -@erase "$(OUTDIR)\mod_expires.exp"
- -@erase "$(OUTDIR)\mod_expires.lib"
- -@erase "$(OUTDIR)\mod_expires.map"
- -@erase "$(OUTDIR)\mod_expires.pdb"
- -@erase "$(OUTDIR)\mod_expires.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /I\
- "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D\
- "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_expires" /FD /c
-CPP_OBJS=.\Debug/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_expires.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no\
- /pdb:"$(OUTDIR)\mod_expires.pdb" /map:"$(INTDIR)\mod_expires.map" /debug\
- /machine:I386 /out:"$(OUTDIR)\mod_expires.so"\
- /implib:"$(OUTDIR)\mod_expires.lib"\
- /base:@..\..\os\win32\BaseAddr.ref,mod_expires
-LINK32_OBJS= \
- "$(INTDIR)\mod_expires.obj" \
- "..\..\Debug\libhttpd.lib" \
- "..\..\srclib\apr\Debug\libapr.lib"
-
-"$(OUTDIR)\mod_expires.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ENDIF
-
-
-!IF "$(CFG)" == "mod_expires - Win32 Release" || "$(CFG)" ==\
- "mod_expires - Win32 Debug"
-
-!IF "$(CFG)" == "mod_expires - Win32 Release"
-
-"libapr - Win32 Release" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F .\libapr.mak CFG="libapr - Win32 Release"
- cd "..\..\modules\metadata"
-
-"libapr - Win32 ReleaseCLEAN" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libapr.mak CFG="libapr - Win32 Release"\
- RECURSE=1
- cd "..\..\modules\metadata"
-
-!ELSEIF "$(CFG)" == "mod_expires - Win32 Debug"
-
-"libapr - Win32 Debug" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F .\libapr.mak CFG="libapr - Win32 Debug"
- cd "..\..\modules\metadata"
-
-"libapr - Win32 DebugCLEAN" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libapr.mak CFG="libapr - Win32 Debug"\
- RECURSE=1
- cd "..\..\modules\metadata"
-
-!ENDIF
-
-!IF "$(CFG)" == "mod_expires - Win32 Release"
-
-"libhttpd - Win32 Release" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) /F .\libhttpd.mak CFG="libhttpd - Win32 Release"
- cd ".\modules\metadata"
-
-"libhttpd - Win32 ReleaseCLEAN" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libhttpd.mak CFG="libhttpd - Win32 Release"\
- RECURSE=1
- cd ".\modules\metadata"
-
-!ELSEIF "$(CFG)" == "mod_expires - Win32 Debug"
-
-"libhttpd - Win32 Debug" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) /F .\libhttpd.mak CFG="libhttpd - Win32 Debug"
- cd ".\modules\metadata"
-
-"libhttpd - Win32 DebugCLEAN" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libhttpd.mak CFG="libhttpd - Win32 Debug"\
- RECURSE=1
- cd ".\modules\metadata"
-
-!ENDIF
-
-SOURCE=.\mod_expires.c
-DEP_CPP_MOD_E=\
- "..\..\include\ap_config.h"\
- "..\..\include\ap_mmn.h"\
- "..\..\include\ap_release.h"\
- "..\..\include\http_config.h"\
- "..\..\include\http_log.h"\
- "..\..\include\http_request.h"\
- "..\..\include\httpd.h"\
- "..\..\include\pcreposix.h"\
- "..\..\include\util_cfgtree.h"\
- "..\..\include\util_filter.h"\
- "..\..\include\util_uri.h"\
- "..\..\os\win32\os.h"\
- "..\..\srclib\apr-util\include\apr_buckets.h"\
- "..\..\srclib\apr-util\include\apr_hooks.h"\
- "..\..\srclib\apr-util\include\apr_ring.h"\
- "..\..\srclib\apr-util\include\apu.h"\
- "..\..\srclib\apr\include\apr.h"\
- "..\..\srclib\apr\include\apr_errno.h"\
- "..\..\srclib\apr\include\apr_file_info.h"\
- "..\..\srclib\apr\include\apr_file_io.h"\
- "..\..\srclib\apr\include\apr_general.h"\
- "..\..\srclib\apr\include\apr_lib.h"\
- "..\..\srclib\apr\include\apr_mmap.h"\
- "..\..\srclib\apr\include\apr_network_io.h"\
- "..\..\srclib\apr\include\apr_pools.h"\
- "..\..\srclib\apr\include\apr_strings.h"\
- "..\..\srclib\apr\include\apr_tables.h"\
- "..\..\srclib\apr\include\apr_thread_proc.h"\
- "..\..\srclib\apr\include\apr_time.h"\
- "..\..\srclib\apr\include\apr_user.h"\
- "..\..\srclib\apr\include\apr_want.h"\
-
-NODEP_CPP_MOD_E=\
- "..\..\include\ap_config_auto.h"\
-
-
-"$(INTDIR)\mod_expires.obj" : $(SOURCE) $(DEP_CPP_MOD_E) "$(INTDIR)"
-
-
-
-!ENDIF
-
diff --git a/modules/metadata/mod_headers.c b/modules/metadata/mod_headers.c
deleted file mode 100644
index 20edf23ae1..0000000000
--- a/modules/metadata/mod_headers.c
+++ /dev/null
@@ -1,269 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * mod_headers.c: Add/append/remove HTTP response headers
- * Written by Paul Sutton, paul@ukweb.com, 1 Oct 1996
- *
- * New directive, Header, can be used to add/replace/remove HTTP headers.
- * Valid in both per-server and per-dir configurations.
- *
- * Syntax is:
- *
- * Header action header value
- *
- * Where action is one of:
- * set - set this header, replacing any old value
- * add - add this header, possible resulting in two or more
- * headers with the same name
- * append - append this text onto any existing header of this same
- * unset - remove this header
- *
- * Where action is unset, the third argument (value) should not be given.
- * The header name can include the colon, or not.
- *
- * The Header directive can only be used where allowed by the FileInfo
- * override.
- *
- * When the request is processed, the header directives are processed in
- * this order: firstly, the main server, then the virtual server handling
- * this request (if any), then any <Directory> sections (working downwards
- * from the root dir), then an <Location> sections (working down from
- * shortest URL component), the any <File> sections. This order is
- * important if any 'set' or 'unset' actions are used. For example,
- * the following two directives have different effect if applied in
- * the reverse order:
- *
- * Header append Author "John P. Doe"
- * Header unset Author
- *
- * Examples:
- *
- * To set the "Author" header, use
- * Header add Author "John P. Doe"
- *
- * To remove a header:
- * Header unset Author
- *
- */
-
-#include "apr.h"
-#include "apr_strings.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#include "httpd.h"
-#include "http_config.h"
-#include "http_request.h"
-
-
-typedef enum {
- hdr_add = 'a', /* add header (could mean multiple hdrs) */
- hdr_set = 's', /* set (replace old value) */
- hdr_append = 'm', /* append (merge into any old value) */
- hdr_unset = 'u' /* unset header */
-} hdr_actions;
-
-typedef struct {
- hdr_actions action;
- char *header;
- const char *value;
-} header_entry;
-
-/*
- * headers_conf is our per-module configuration. This is used as both
- * a per-dir and per-server config
- */
-typedef struct {
- apr_array_header_t *headers;
-} headers_conf;
-
-module AP_MODULE_DECLARE_DATA headers_module;
-
-static void *create_headers_config(apr_pool_t *p, server_rec *s)
-{
- headers_conf *conf = apr_pcalloc(p, sizeof(*conf));
-
- conf->headers = apr_array_make(p, 2, sizeof(header_entry));
-
- return conf;
-}
-
-static void *create_headers_dir_config(apr_pool_t *p, char *d)
-{
- return create_headers_config(p, NULL);
-}
-
-static void *merge_headers_config(apr_pool_t *p, void *basev, void *overridesv)
-{
- headers_conf *newconf = apr_pcalloc(p, sizeof(*newconf));
- headers_conf *base = basev;
- headers_conf *overrides = overridesv;
-
- newconf->headers = apr_array_append(p, base->headers, overrides->headers);
-
- return newconf;
-}
-
-
-static const char *header_cmd(cmd_parms *cmd, void *indirconf,
- const char *action, const char *inhdr,
- const char *value)
-{
- headers_conf *dirconf = indirconf;
- char *hdr = apr_pstrdup(cmd->pool, inhdr);
- header_entry *new;
- server_rec *s = cmd->server;
- headers_conf *serverconf = ap_get_module_config(s->module_config,
- &headers_module);
- char *colon;
-
- if (cmd->path) {
- new = (header_entry *) apr_array_push(dirconf->headers);
- }
- else {
- new = (header_entry *) apr_array_push(serverconf->headers);
- }
-
- if (!strcasecmp(action, "set"))
- new->action = hdr_set;
- else if (!strcasecmp(action, "add"))
- new->action = hdr_add;
- else if (!strcasecmp(action, "append"))
- new->action = hdr_append;
- else if (!strcasecmp(action, "unset"))
- new->action = hdr_unset;
- else
- return "first argument must be add, set, append or unset.";
-
- if (new->action == hdr_unset) {
- if (value)
- return "Header unset takes two arguments";
- }
- else if (!value)
- return "Header requires three arguments";
-
- if ((colon = strchr(hdr, ':')))
- *colon = '\0';
-
- new->header = hdr;
- new->value = value;
-
- return NULL;
-}
-
-static const command_rec headers_cmds[] =
-{
- AP_INIT_TAKE23("Header", header_cmd, NULL, OR_FILEINFO,
- "an action, header and value"),
- {NULL}
-};
-
-static void do_headers_fixup(request_rec *r, apr_array_header_t *headers)
-{
- int i;
-
- for (i = 0; i < headers->nelts; ++i) {
- header_entry *hdr = &((header_entry *) (headers->elts))[i];
- switch (hdr->action) {
- case hdr_add:
- apr_table_addn(r->headers_out, hdr->header, hdr->value);
- break;
- case hdr_append:
- apr_table_mergen(r->headers_out, hdr->header, hdr->value);
- break;
- case hdr_set:
- apr_table_setn(r->headers_out, hdr->header, hdr->value);
- break;
- case hdr_unset:
- apr_table_unset(r->headers_out, hdr->header);
- break;
- }
- }
-
-}
-
-static int fixup_headers(request_rec *r)
-{
- headers_conf *serverconf = ap_get_module_config(r->server->module_config,
- &headers_module);
- headers_conf *dirconf = ap_get_module_config(r->per_dir_config,
- &headers_module);
-
- do_headers_fixup(r, serverconf->headers);
- do_headers_fixup(r, dirconf->headers);
-
- return DECLINED;
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_fixups(fixup_headers, NULL, NULL, APR_HOOK_MIDDLE);
-}
-
-module AP_MODULE_DECLARE_DATA headers_module =
-{
- STANDARD20_MODULE_STUFF,
- create_headers_dir_config, /* dir config creater */
- merge_headers_config, /* dir merger --- default is to override */
- create_headers_config, /* server config */
- merge_headers_config, /* merge server configs */
- headers_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
diff --git a/modules/metadata/mod_headers.dsp b/modules/metadata/mod_headers.dsp
deleted file mode 100644
index 0575868143..0000000000
--- a/modules/metadata/mod_headers.dsp
+++ /dev/null
@@ -1,95 +0,0 @@
-# Microsoft Developer Studio Project File - Name="mod_headers" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=mod_headers - Win32 Release
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "mod_headers.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_headers.mak" CFG="mod_headers - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_headers - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_headers - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "mod_headers - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\os\win32" /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_headers" /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "NDEBUG"
-# ADD RSC /l 0x809 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_headers.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_headers
-# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_headers.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_headers
-
-!ELSEIF "$(CFG)" == "mod_headers - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\..\include" /I "..\..\os\win32" /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_headers" /FD /c
-# ADD BASE MTL /nologo /D "_DEBUG" /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "_DEBUG"
-# ADD RSC /l 0x809 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /out:"Debug/mod_headers.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_headers
-# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /out:"Debug/mod_headers.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_headers
-
-!ENDIF
-
-# Begin Target
-
-# Name "mod_headers - Win32 Release"
-# Name "mod_headers - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\mod_headers.c
-# End Source File
-# End Target
-# End Project
diff --git a/modules/metadata/mod_headers.exp b/modules/metadata/mod_headers.exp
deleted file mode 100644
index 3f3063808a..0000000000
--- a/modules/metadata/mod_headers.exp
+++ /dev/null
@@ -1 +0,0 @@
-headers_module
diff --git a/modules/metadata/mod_headers.mak b/modules/metadata/mod_headers.mak
deleted file mode 100644
index 8544faa05c..0000000000
--- a/modules/metadata/mod_headers.mak
+++ /dev/null
@@ -1,321 +0,0 @@
-# Microsoft Developer Studio Generated NMAKE File, Based on mod_headers.dsp
-!IF "$(CFG)" == ""
-CFG=mod_headers - Win32 Release
-!MESSAGE No configuration specified. Defaulting to mod_headers - Win32 Release.
-!ENDIF
-
-!IF "$(CFG)" != "mod_headers - Win32 Release" && "$(CFG)" !=\
- "mod_headers - Win32 Debug"
-!MESSAGE Invalid configuration "$(CFG)" specified.
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_headers.mak" CFG="mod_headers - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_headers - Win32 Release" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_headers - Win32 Debug" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-!ERROR An invalid configuration is specified.
-!ENDIF
-
-!IF "$(OS)" == "Windows_NT"
-NULL=
-!ELSE
-NULL=nul
-!ENDIF
-
-!IF "$(CFG)" == "mod_headers - Win32 Release"
-
-OUTDIR=.\Release
-INTDIR=.\Release
-# Begin Custom Macros
-OutDir=.\Release
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_headers.so"
-
-!ELSE
-
-ALL : "libhttpd - Win32 Release" "libapr - Win32 Release"\
- "$(OUTDIR)\mod_headers.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libapr - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\mod_headers.idb"
- -@erase "$(INTDIR)\mod_headers.obj"
- -@erase "$(OUTDIR)\mod_headers.exp"
- -@erase "$(OUTDIR)\mod_headers.lib"
- -@erase "$(OUTDIR)\mod_headers.map"
- -@erase "$(OUTDIR)\mod_headers.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\os\win32" /I\
- "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D\
- "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_headers" /FD /c
-CPP_OBJS=.\Release/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_headers.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no\
- /pdb:"$(OUTDIR)\mod_headers.pdb" /map:"$(INTDIR)\mod_headers.map" /machine:I386\
- /out:"$(OUTDIR)\mod_headers.so" /implib:"$(OUTDIR)\mod_headers.lib"\
- /base:@..\..\os\win32\BaseAddr.ref,mod_headers
-LINK32_OBJS= \
- "$(INTDIR)\mod_headers.obj" \
- "..\..\Release\libhttpd.lib" \
- "..\..\srclib\apr\Release\libapr.lib"
-
-"$(OUTDIR)\mod_headers.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ELSEIF "$(CFG)" == "mod_headers - Win32 Debug"
-
-OUTDIR=.\Debug
-INTDIR=.\Debug
-# Begin Custom Macros
-OutDir=.\Debug
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_headers.so"
-
-!ELSE
-
-ALL : "libhttpd - Win32 Debug" "libapr - Win32 Debug"\
- "$(OUTDIR)\mod_headers.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libapr - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\mod_headers.idb"
- -@erase "$(INTDIR)\mod_headers.obj"
- -@erase "$(OUTDIR)\mod_headers.exp"
- -@erase "$(OUTDIR)\mod_headers.lib"
- -@erase "$(OUTDIR)\mod_headers.map"
- -@erase "$(OUTDIR)\mod_headers.pdb"
- -@erase "$(OUTDIR)\mod_headers.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /I\
- "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D\
- "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_headers" /FD /c
-CPP_OBJS=.\Debug/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_headers.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no\
- /pdb:"$(OUTDIR)\mod_headers.pdb" /map:"$(INTDIR)\mod_headers.map" /debug\
- /machine:I386 /out:"$(OUTDIR)\mod_headers.so"\
- /implib:"$(OUTDIR)\mod_headers.lib"\
- /base:@..\..\os\win32\BaseAddr.ref,mod_headers
-LINK32_OBJS= \
- "$(INTDIR)\mod_headers.obj" \
- "..\..\Debug\libhttpd.lib" \
- "..\..\srclib\apr\Debug\libapr.lib"
-
-"$(OUTDIR)\mod_headers.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ENDIF
-
-
-!IF "$(CFG)" == "mod_headers - Win32 Release" || "$(CFG)" ==\
- "mod_headers - Win32 Debug"
-
-!IF "$(CFG)" == "mod_headers - Win32 Release"
-
-"libapr - Win32 Release" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F .\libapr.mak CFG="libapr - Win32 Release"
- cd "..\..\modules\metadata"
-
-"libapr - Win32 ReleaseCLEAN" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libapr.mak CFG="libapr - Win32 Release"\
- RECURSE=1
- cd "..\..\modules\metadata"
-
-!ELSEIF "$(CFG)" == "mod_headers - Win32 Debug"
-
-"libapr - Win32 Debug" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F .\libapr.mak CFG="libapr - Win32 Debug"
- cd "..\..\modules\metadata"
-
-"libapr - Win32 DebugCLEAN" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libapr.mak CFG="libapr - Win32 Debug"\
- RECURSE=1
- cd "..\..\modules\metadata"
-
-!ENDIF
-
-!IF "$(CFG)" == "mod_headers - Win32 Release"
-
-"libhttpd - Win32 Release" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) /F .\libhttpd.mak CFG="libhttpd - Win32 Release"
- cd ".\modules\metadata"
-
-"libhttpd - Win32 ReleaseCLEAN" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libhttpd.mak CFG="libhttpd - Win32 Release"\
- RECURSE=1
- cd ".\modules\metadata"
-
-!ELSEIF "$(CFG)" == "mod_headers - Win32 Debug"
-
-"libhttpd - Win32 Debug" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) /F .\libhttpd.mak CFG="libhttpd - Win32 Debug"
- cd ".\modules\metadata"
-
-"libhttpd - Win32 DebugCLEAN" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libhttpd.mak CFG="libhttpd - Win32 Debug"\
- RECURSE=1
- cd ".\modules\metadata"
-
-!ENDIF
-
-SOURCE=.\mod_headers.c
-DEP_CPP_MOD_H=\
- "..\..\include\ap_config.h"\
- "..\..\include\ap_mmn.h"\
- "..\..\include\ap_release.h"\
- "..\..\include\http_config.h"\
- "..\..\include\http_request.h"\
- "..\..\include\httpd.h"\
- "..\..\include\pcreposix.h"\
- "..\..\include\util_cfgtree.h"\
- "..\..\include\util_filter.h"\
- "..\..\include\util_uri.h"\
- "..\..\os\win32\os.h"\
- "..\..\srclib\apr-util\include\apr_buckets.h"\
- "..\..\srclib\apr-util\include\apr_hooks.h"\
- "..\..\srclib\apr-util\include\apr_ring.h"\
- "..\..\srclib\apr-util\include\apu.h"\
- "..\..\srclib\apr\include\apr.h"\
- "..\..\srclib\apr\include\apr_errno.h"\
- "..\..\srclib\apr\include\apr_file_info.h"\
- "..\..\srclib\apr\include\apr_file_io.h"\
- "..\..\srclib\apr\include\apr_general.h"\
- "..\..\srclib\apr\include\apr_mmap.h"\
- "..\..\srclib\apr\include\apr_network_io.h"\
- "..\..\srclib\apr\include\apr_pools.h"\
- "..\..\srclib\apr\include\apr_strings.h"\
- "..\..\srclib\apr\include\apr_tables.h"\
- "..\..\srclib\apr\include\apr_time.h"\
- "..\..\srclib\apr\include\apr_user.h"\
- "..\..\srclib\apr\include\apr_want.h"\
-
-NODEP_CPP_MOD_H=\
- "..\..\include\ap_config_auto.h"\
-
-
-"$(INTDIR)\mod_headers.obj" : $(SOURCE) $(DEP_CPP_MOD_H) "$(INTDIR)"
-
-
-
-!ENDIF
-
diff --git a/modules/metadata/mod_mime_magic.c b/modules/metadata/mod_mime_magic.c
deleted file mode 100644
index 36aa086918..0000000000
--- a/modules/metadata/mod_mime_magic.c
+++ /dev/null
@@ -1,2501 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * mod_mime_magic: MIME type lookup via file magic numbers
- * Copyright (c) 1996-1997 Cisco Systems, Inc.
- *
- * This software was submitted by Cisco Systems to the Apache Software Foundation in July
- * 1997. Future revisions and derivatives of this source code must
- * acknowledge Cisco Systems as the original contributor of this module.
- * All other licensing and usage conditions are those of the Apache Software Foundation.
- *
- * Some of this code is derived from the free version of the file command
- * originally posted to comp.sources.unix. Copyright info for that program
- * is included below as required.
- * ---------------------------------------------------------------------------
- * - Copyright (c) Ian F. Darwin, 1987. Written by Ian F. Darwin.
- *
- * This software is not subject to any license of the American Telephone and
- * Telegraph Company or of the Regents of the University of California.
- *
- * Permission is granted to anyone to use this software for any purpose on any
- * computer system, and to alter it and redistribute it freely, subject to
- * the following restrictions:
- *
- * 1. The author is not responsible for the consequences of use of this
- * software, no matter how awful, even if they arise from flaws in it.
- *
- * 2. The origin of this software must not be misrepresented, either by
- * explicit claim or by omission. Since few users ever read sources, credits
- * must appear in the documentation.
- *
- * 3. Altered versions must be plainly marked as such, and must not be
- * misrepresented as being the original software. Since few users ever read
- * sources, credits must appear in the documentation.
- *
- * 4. This notice may not be removed or altered.
- * -------------------------------------------------------------------------
- *
- * For compliance with Mr Darwin's terms: this has been very significantly
- * modified from the free "file" command.
- * - all-in-one file for compilation convenience when moving from one
- * version of Apache to the next.
- * - Memory allocation is done through the Apache API's apr_pool_t structure.
- * - All functions have had necessary Apache API request or server
- * structures passed to them where necessary to call other Apache API
- * routines. (i.e. usually for logging, files, or memory allocation in
- * itself or a called function.)
- * - struct magic has been converted from an array to a single-ended linked
- * list because it only grows one record at a time, it's only accessed
- * sequentially, and the Apache API has no equivalent of realloc().
- * - Functions have been changed to get their parameters from the server
- * configuration instead of globals. (It should be reentrant now but has
- * not been tested in a threaded environment.)
- * - Places where it used to print results to stdout now saves them in a
- * list where they're used to set the MIME type in the Apache request
- * record.
- * - Command-line flags have been removed since they will never be used here.
- *
- * Ian Kluft <ikluft@cisco.com>
- * Engineering Information Framework
- * Central Engineering
- * Cisco Systems, Inc.
- * San Jose, CA, USA
- *
- * Initial installation July/August 1996
- * Misc bug fixes May 1997
- * Submission to Apache Software Foundation July 1997
- *
- */
-
-#include "apr.h"
-#include "apr_strings.h"
-#include "apr_lib.h"
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#if APR_HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_request.h"
-#include "http_core.h"
-#include "http_log.h"
-#include "http_protocol.h"
-#include "util_script.h"
-
-/* ### this isn't set by configure? does anybody set this? */
-#ifdef HAVE_UTIME_H
-#include <utime.h>
-#endif
-
-/*
- * data structures and related constants
- */
-
-#define MODNAME "mod_mime_magic"
-#define MIME_MAGIC_DEBUG 0
-
-#define MIME_BINARY_UNKNOWN "application/octet-stream"
-#define MIME_TEXT_UNKNOWN "text/plain"
-
-#define MAXMIMESTRING 256
-
-/* HOWMANY must be at least 4096 to make gzip -dcq work */
-#define HOWMANY 4096
-/* SMALL_HOWMANY limits how much work we do to figure out text files */
-#define SMALL_HOWMANY 1024
-#define MAXDESC 50 /* max leng of text description */
-#define MAXstring 64 /* max leng of "string" types */
-
-struct magic {
- struct magic *next; /* link to next entry */
- int lineno; /* line number from magic file */
-
- short flag;
-#define INDIR 1 /* if '>(...)' appears, */
-#define UNSIGNED 2 /* comparison is unsigned */
- short cont_level; /* level of ">" */
- struct {
- char type; /* byte short long */
- long offset; /* offset from indirection */
- } in;
- long offset; /* offset to magic number */
- unsigned char reln; /* relation (0=eq, '>'=gt, etc) */
- char type; /* int, short, long or string. */
- char vallen; /* length of string value, if any */
-#define BYTE 1
-#define SHORT 2
-#define LONG 4
-#define STRING 5
-#define DATE 6
-#define BESHORT 7
-#define BELONG 8
-#define BEDATE 9
-#define LESHORT 10
-#define LELONG 11
-#define LEDATE 12
- union VALUETYPE {
- unsigned char b;
- unsigned short h;
- unsigned long l;
- char s[MAXstring];
- unsigned char hs[2]; /* 2 bytes of a fixed-endian "short" */
- unsigned char hl[4]; /* 2 bytes of a fixed-endian "long" */
- } value; /* either number or string */
- unsigned long mask; /* mask before comparison with value */
- char nospflag; /* supress space character */
-
- /* NOTE: this string is suspected of overrunning - find it! */
- char desc[MAXDESC]; /* description */
-};
-
-/*
- * data structures for tar file recognition
- * --------------------------------------------------------------------------
- * Header file for public domain tar (tape archive) program.
- *
- * @(#)tar.h 1.20 86/10/29 Public Domain. Created 25 August 1985 by John
- * Gilmore, ihnp4!hoptoad!gnu.
- *
- * Header block on tape.
- *
- * I'm going to use traditional DP naming conventions here. A "block" is a big
- * chunk of stuff that we do I/O on. A "record" is a piece of info that we
- * care about. Typically many "record"s fit into a "block".
- */
-#define RECORDSIZE 512
-#define NAMSIZ 100
-#define TUNMLEN 32
-#define TGNMLEN 32
-
-union record {
- char charptr[RECORDSIZE];
- struct header {
- char name[NAMSIZ];
- char mode[8];
- char uid[8];
- char gid[8];
- char size[12];
- char mtime[12];
- char chksum[8];
- char linkflag;
- char linkname[NAMSIZ];
- char magic[8];
- char uname[TUNMLEN];
- char gname[TGNMLEN];
- char devmajor[8];
- char devminor[8];
- } header;
-};
-
-/* The magic field is filled with this if uname and gname are valid. */
-#define TMAGIC "ustar " /* 7 chars and a null */
-
-/*
- * file-function prototypes
- */
-static int ascmagic(request_rec *, unsigned char *, apr_size_t);
-static int is_tar(unsigned char *, apr_size_t);
-static int softmagic(request_rec *, unsigned char *, apr_size_t);
-static void tryit(request_rec *, unsigned char *, apr_size_t, int);
-static int zmagic(request_rec *, unsigned char *, apr_size_t);
-
-static int getvalue(server_rec *, struct magic *, char **);
-static int hextoint(int);
-static char *getstr(server_rec *, char *, char *, int, int *);
-static int parse(server_rec *, apr_pool_t *p, char *, int);
-
-static int match(request_rec *, unsigned char *, apr_size_t);
-static int mget(request_rec *, union VALUETYPE *, unsigned char *,
- struct magic *, apr_size_t);
-static int mcheck(request_rec *, union VALUETYPE *, struct magic *);
-static void mprint(request_rec *, union VALUETYPE *, struct magic *);
-
-static int uncompress(request_rec *, int,
- unsigned char **, apr_size_t);
-static long from_oct(int, char *);
-static int fsmagic(request_rec *r, const char *fn);
-
-/*
- * includes for ASCII substring recognition formerly "names.h" in file
- * command
- *
- * Original notes: names and types used by ascmagic in file(1). These tokens are
- * here because they can appear anywhere in the first HOWMANY bytes, while
- * tokens in /etc/magic must appear at fixed offsets into the file. Don't
- * make HOWMANY too high unless you have a very fast CPU.
- */
-
-/* these types are used to index the apr_table_t 'types': keep em in sync! */
-/* HTML inserted in first because this is a web server module now */
-#define L_HTML 0 /* HTML */
-#define L_C 1 /* first and foremost on UNIX */
-#define L_FORT 2 /* the oldest one */
-#define L_MAKE 3 /* Makefiles */
-#define L_PLI 4 /* PL/1 */
-#define L_MACH 5 /* some kinda assembler */
-#define L_ENG 6 /* English */
-#define L_PAS 7 /* Pascal */
-#define L_MAIL 8 /* Electronic mail */
-#define L_NEWS 9 /* Usenet Netnews */
-
-static char *types[] =
-{
- "text/html", /* HTML */
- "text/plain", /* "c program text", */
- "text/plain", /* "fortran program text", */
- "text/plain", /* "make commands text", */
- "text/plain", /* "pl/1 program text", */
- "text/plain", /* "assembler program text", */
- "text/plain", /* "English text", */
- "text/plain", /* "pascal program text", */
- "message/rfc822", /* "mail text", */
- "message/news", /* "news text", */
- "application/binary", /* "can't happen error on names.h/types", */
- 0
-};
-
-static struct names {
- char *name;
- short type;
-} names[] = {
-
- /* These must be sorted by eye for optimal hit rate */
- /* Add to this list only after substantial meditation */
- {
- "<html>", L_HTML
- },
- {
- "<HTML>", L_HTML
- },
- {
- "<head>", L_HTML
- },
- {
- "<HEAD>", L_HTML
- },
- {
- "<title>", L_HTML
- },
- {
- "<TITLE>", L_HTML
- },
- {
- "<h1>", L_HTML
- },
- {
- "<H1>", L_HTML
- },
- {
- "<!--", L_HTML
- },
- {
- "<!DOCTYPE HTML", L_HTML
- },
- {
- "/*", L_C
- }, /* must precede "The", "the", etc. */
- {
- "#include", L_C
- },
- {
- "char", L_C
- },
- {
- "The", L_ENG
- },
- {
- "the", L_ENG
- },
- {
- "double", L_C
- },
- {
- "extern", L_C
- },
- {
- "float", L_C
- },
- {
- "real", L_C
- },
- {
- "struct", L_C
- },
- {
- "union", L_C
- },
- {
- "CFLAGS", L_MAKE
- },
- {
- "LDFLAGS", L_MAKE
- },
- {
- "all:", L_MAKE
- },
- {
- ".PRECIOUS", L_MAKE
- },
- /*
- * Too many files of text have these words in them. Find another way to
- * recognize Fortrash.
- */
-#ifdef NOTDEF
- {
- "subroutine", L_FORT
- },
- {
- "function", L_FORT
- },
- {
- "block", L_FORT
- },
- {
- "common", L_FORT
- },
- {
- "dimension", L_FORT
- },
- {
- "integer", L_FORT
- },
- {
- "data", L_FORT
- },
-#endif /* NOTDEF */
- {
- ".ascii", L_MACH
- },
- {
- ".asciiz", L_MACH
- },
- {
- ".byte", L_MACH
- },
- {
- ".even", L_MACH
- },
- {
- ".globl", L_MACH
- },
- {
- "clr", L_MACH
- },
- {
- "(input,", L_PAS
- },
- {
- "dcl", L_PLI
- },
- {
- "Received:", L_MAIL
- },
- {
- ">From", L_MAIL
- },
- {
- "Return-Path:", L_MAIL
- },
- {
- "Cc:", L_MAIL
- },
- {
- "Newsgroups:", L_NEWS
- },
- {
- "Path:", L_NEWS
- },
- {
- "Organization:", L_NEWS
- },
- {
- NULL, 0
- }
-};
-
-#define NNAMES ((sizeof(names)/sizeof(struct names)) - 1)
-
-/*
- * Result String List (RSL)
- *
- * The file(1) command prints its output. Instead, we store the various
- * "printed" strings in a list (allocating memory as we go) and concatenate
- * them at the end when we finally know how much space they'll need.
- */
-
-typedef struct magic_rsl_s {
- char *str; /* string, possibly a fragment */
- struct magic_rsl_s *next; /* pointer to next fragment */
-} magic_rsl;
-
-/*
- * Apache module configuration structures
- */
-
-/* per-server info */
-typedef struct {
- const char *magicfile; /* where magic be found */
- struct magic *magic; /* head of magic config list */
- struct magic *last;
-} magic_server_config_rec;
-
-/* per-request info */
-typedef struct {
- magic_rsl *head; /* result string list */
- magic_rsl *tail;
- unsigned suf_recursion; /* recursion depth in suffix check */
-} magic_req_rec;
-
-/*
- * configuration functions - called by Apache API routines
- */
-
-module mime_magic_module;
-
-static void *create_magic_server_config(apr_pool_t *p, server_rec *d)
-{
- /* allocate the config - use pcalloc because it needs to be zeroed */
- return apr_pcalloc(p, sizeof(magic_server_config_rec));
-}
-
-static void *merge_magic_server_config(apr_pool_t *p, void *basev, void *addv)
-{
- magic_server_config_rec *base = (magic_server_config_rec *) basev;
- magic_server_config_rec *add = (magic_server_config_rec *) addv;
- magic_server_config_rec *new = (magic_server_config_rec *)
- apr_palloc(p, sizeof(magic_server_config_rec));
-
- new->magicfile = add->magicfile ? add->magicfile : base->magicfile;
- new->magic = NULL;
- new->last = NULL;
- return new;
-}
-
-static const char *set_magicfile(cmd_parms *cmd, void *dummy, const char *arg)
-{
- magic_server_config_rec *conf = (magic_server_config_rec *)
- ap_get_module_config(cmd->server->module_config,
- &mime_magic_module);
-
- if (!conf) {
- return MODNAME ": server structure not allocated";
- }
- conf->magicfile = arg;
- return NULL;
-}
-
-/*
- * configuration file commands - exported to Apache API
- */
-
-static const command_rec mime_magic_cmds[] =
-{
- AP_INIT_TAKE1("MimeMagicFile", set_magicfile, NULL, RSRC_CONF,
- "Path to MIME Magic file (in file(1) format)"),
- {NULL}
-};
-
-/*
- * RSL (result string list) processing routines
- *
- * These collect strings that would have been printed in fragments by file(1)
- * into a list of magic_rsl structures with the strings. When complete,
- * they're concatenated together to become the MIME content and encoding
- * types.
- *
- * return value conventions for these functions: functions which return int:
- * failure = -1, other = result functions which return pointers: failure = 0,
- * other = result
- */
-
-/* allocate a per-request structure and put it in the request record */
-static magic_req_rec *magic_set_config(request_rec *r)
-{
- magic_req_rec *req_dat = (magic_req_rec *) apr_palloc(r->pool,
- sizeof(magic_req_rec));
-
- req_dat->head = req_dat->tail = (magic_rsl *) NULL;
- ap_set_module_config(r->request_config, &mime_magic_module, req_dat);
- return req_dat;
-}
-
-/* add a string to the result string list for this request */
-/* it is the responsibility of the caller to allocate "str" */
-static int magic_rsl_add(request_rec *r, char *str)
-{
- magic_req_rec *req_dat = (magic_req_rec *)
- ap_get_module_config(r->request_config, &mime_magic_module);
- magic_rsl *rsl;
-
- /* make sure we have a list to put it in */
- if (!req_dat) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, APR_EINVAL, r,
- MODNAME ": request config should not be NULL");
- if (!(req_dat = magic_set_config(r))) {
- /* failure */
- return -1;
- }
- }
-
- /* allocate the list entry */
- rsl = (magic_rsl *) apr_palloc(r->pool, sizeof(magic_rsl));
-
- /* fill it */
- rsl->str = str;
- rsl->next = (magic_rsl *) NULL;
-
- /* append to the list */
- if (req_dat->head && req_dat->tail) {
- req_dat->tail->next = rsl;
- req_dat->tail = rsl;
- }
- else {
- req_dat->head = req_dat->tail = rsl;
- }
-
- /* success */
- return 0;
-}
-
-/* RSL hook for puts-type functions */
-static int magic_rsl_puts(request_rec *r, char *str)
-{
- return magic_rsl_add(r, str);
-}
-
-/* RSL hook for printf-type functions */
-static int magic_rsl_printf(request_rec *r, char *str,...)
-{
- va_list ap;
-
- char buf[MAXMIMESTRING];
-
- /* assemble the string into the buffer */
- va_start(ap, str);
- apr_vsnprintf(buf, sizeof(buf), str, ap);
- va_end(ap);
-
- /* add the buffer to the list */
- return magic_rsl_add(r, strdup(buf));
-}
-
-/* RSL hook for putchar-type functions */
-static int magic_rsl_putchar(request_rec *r, char c)
-{
- char str[2];
-
- /* high overhead for 1 char - just hope they don't do this much */
- str[0] = c;
- str[1] = '\0';
- return magic_rsl_add(r, str);
-}
-
-/* allocate and copy a contiguous string from a result string list */
-static char *rsl_strdup(request_rec *r, int start_frag, int start_pos, int len)
-{
- char *result; /* return value */
- int cur_frag, /* current fragment number/counter */
- cur_pos, /* current position within fragment */
- res_pos; /* position in result string */
- magic_rsl *frag; /* list-traversal pointer */
- magic_req_rec *req_dat = (magic_req_rec *)
- ap_get_module_config(r->request_config, &mime_magic_module);
-
- /* allocate the result string */
- result = (char *) apr_palloc(r->pool, len + 1);
-
- /* loop through and collect the string */
- res_pos = 0;
- for (frag = req_dat->head, cur_frag = 0;
- frag->next;
- frag = frag->next, cur_frag++) {
- /* loop to the first fragment */
- if (cur_frag < start_frag)
- continue;
-
- /* loop through and collect chars */
- for (cur_pos = (cur_frag == start_frag) ? start_pos : 0;
- frag->str[cur_pos];
- cur_pos++) {
- if (cur_frag >= start_frag
- && cur_pos >= start_pos
- && res_pos <= len) {
- result[res_pos++] = frag->str[cur_pos];
- if (res_pos > len) {
- break;
- }
- }
- }
- }
-
- /* clean up and return */
- result[res_pos] = 0;
-#if MIME_MAGIC_DEBUG
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, r,
- MODNAME ": rsl_strdup() %d chars: %s", res_pos - 1, result);
-#endif
- return result;
-}
-
-/* states for the state-machine algorithm in magic_rsl_to_request() */
-typedef enum {
- rsl_leading_space, rsl_type, rsl_subtype, rsl_separator, rsl_encoding
-} rsl_states;
-
-/* process the RSL and set the MIME info in the request record */
-static int magic_rsl_to_request(request_rec *r)
-{
- int cur_frag, /* current fragment number/counter */
- cur_pos, /* current position within fragment */
- type_frag, /* content type starting point: fragment */
- type_pos, /* content type starting point: position */
- type_len, /* content type length */
- encoding_frag, /* content encoding starting point: fragment */
- encoding_pos, /* content encoding starting point: position */
- encoding_len; /* content encoding length */
-
- magic_rsl *frag; /* list-traversal pointer */
- rsl_states state;
-
- magic_req_rec *req_dat = (magic_req_rec *)
- ap_get_module_config(r->request_config, &mime_magic_module);
-
- /* check if we have a result */
- if (!req_dat || !req_dat->head) {
- /* empty - no match, we defer to other Apache modules */
- return DECLINED;
- }
-
- /* start searching for the type and encoding */
- state = rsl_leading_space;
- type_frag = type_pos = type_len = 0;
- encoding_frag = encoding_pos = encoding_len = 0;
- for (frag = req_dat->head, cur_frag = 0;
- frag && frag->next;
- frag = frag->next, cur_frag++) {
- /* loop through the characters in the fragment */
- for (cur_pos = 0; frag->str[cur_pos]; cur_pos++) {
- if (apr_isspace(frag->str[cur_pos])) {
- /* process whitespace actions for each state */
- if (state == rsl_leading_space) {
- /* eat whitespace in this state */
- continue;
- }
- else if (state == rsl_type) {
- /* whitespace: type has no slash! */
- return DECLINED;
- }
- else if (state == rsl_subtype) {
- /* whitespace: end of MIME type */
- state++;
- continue;
- }
- else if (state == rsl_separator) {
- /* eat whitespace in this state */
- continue;
- }
- else if (state == rsl_encoding) {
- /* whitespace: end of MIME encoding */
- /* we're done */
- frag = req_dat->tail;
- break;
- }
- else {
- /* should not be possible */
- /* abandon malfunctioning module */
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, 0, r,
- MODNAME ": bad state %d (ws)", state);
- return DECLINED;
- }
- /* NOTREACHED */
- }
- else if (state == rsl_type &&
- frag->str[cur_pos] == '/') {
- /* copy the char and go to rsl_subtype state */
- type_len++;
- state++;
- }
- else {
- /* process non-space actions for each state */
- if (state == rsl_leading_space) {
- /* non-space: begin MIME type */
- state++;
- type_frag = cur_frag;
- type_pos = cur_pos;
- type_len = 1;
- continue;
- }
- else if (state == rsl_type ||
- state == rsl_subtype) {
- /* non-space: adds to type */
- type_len++;
- continue;
- }
- else if (state == rsl_separator) {
- /* non-space: begin MIME encoding */
- state++;
- encoding_frag = cur_frag;
- encoding_pos = cur_pos;
- encoding_len = 1;
- continue;
- }
- else if (state == rsl_encoding) {
- /* non-space: adds to encoding */
- encoding_len++;
- continue;
- }
- else {
- /* should not be possible */
- /* abandon malfunctioning module */
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, 0, r,
- MODNAME ": bad state %d (ns)", state);
- return DECLINED;
- }
- /* NOTREACHED */
- }
- /* NOTREACHED */
- }
- }
-
- /* if we ended prior to state rsl_subtype, we had incomplete info */
- if (state != rsl_subtype && state != rsl_separator &&
- state != rsl_encoding) {
- /* defer to other modules */
- return DECLINED;
- }
-
- /* save the info in the request record */
- if (state == rsl_subtype || state == rsl_encoding ||
- state == rsl_encoding) {
- char *tmp;
- tmp = rsl_strdup(r, type_frag, type_pos, type_len);
- /* XXX: this could be done at config time I'm sure... but I'm
- * confused by all this magic_rsl stuff. -djg */
- ap_content_type_tolower(tmp);
- r->content_type = tmp;
- }
- if (state == rsl_encoding) {
- char *tmp;
- tmp = rsl_strdup(r, encoding_frag,
- encoding_pos, encoding_len);
- /* XXX: this could be done at config time I'm sure... but I'm
- * confused by all this magic_rsl stuff. -djg */
- ap_str_tolower(tmp);
- r->content_encoding = tmp;
- }
-
- /* detect memory allocation errors */
- if (!r->content_type ||
- (state == rsl_encoding && !r->content_encoding)) {
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- /* success! */
- return OK;
-}
-
-/*
- * magic_process - process input file r Apache API request record
- * (formerly called "process" in file command, prefix added for clarity) Opens
- * the file and reads a fixed-size buffer to begin processing the contents.
- */
-static int magic_process(request_rec *r)
-{
- apr_file_t *fd = NULL;
- unsigned char buf[HOWMANY + 1]; /* one extra for terminating '\0' */
- apr_size_t nbytes = 0; /* number of bytes read from a datafile */
- int result;
-
- /*
- * first try judging the file based on its filesystem status
- */
- switch ((result = fsmagic(r, r->filename))) {
- case DONE:
- magic_rsl_putchar(r, '\n');
- return OK;
- case OK:
- break;
- default:
- /* fatal error, bail out */
- return result;
- }
-
- if (apr_file_open(&fd, r->filename, APR_READ, APR_OS_DEFAULT, r->pool) != APR_SUCCESS) {
- /* We can't open it, but we were able to stat it. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
- MODNAME ": can't read `%s'", r->filename);
- /* let some other handler decide what the problem is */
- return DECLINED;
- }
-
- /*
- * try looking at the first HOWMANY bytes
- */
- nbytes = sizeof(buf) - 1;
- if ((result = apr_file_read(fd, (char *) buf, &nbytes)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, result, r,
- MODNAME ": read failed: %s", r->filename);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (nbytes == 0)
- magic_rsl_puts(r, MIME_TEXT_UNKNOWN);
- else {
- buf[nbytes++] = '\0'; /* null-terminate it */
- tryit(r, buf, nbytes, 1);
- }
-
- (void) apr_file_close(fd);
- (void) magic_rsl_putchar(r, '\n');
-
- return OK;
-}
-
-
-static void tryit(request_rec *r, unsigned char *buf, apr_size_t nb, int checkzmagic)
-{
- /*
- * Try compression stuff
- */
- if (checkzmagic == 1) {
- if (zmagic(r, buf, nb) == 1)
- return;
- }
-
- /*
- * try tests in /etc/magic (or surrogate magic file)
- */
- if (softmagic(r, buf, nb) == 1)
- return;
-
- /*
- * try known keywords, check for ascii-ness too.
- */
- if (ascmagic(r, buf, nb) == 1)
- return;
-
- /*
- * abandon hope, all ye who remain here
- */
- magic_rsl_puts(r, MIME_BINARY_UNKNOWN);
-}
-
-#define EATAB {while (apr_isspace((unsigned char) *l)) ++l;}
-
-/*
- * apprentice - load configuration from the magic file r
- * API request record
- */
-static int apprentice(server_rec *s, apr_pool_t *p)
-{
- apr_file_t *f = NULL;
- apr_status_t result;
- char line[BUFSIZ + 1];
- int errs = 0;
- int lineno;
-#if MIME_MAGIC_DEBUG
- int rule = 0;
- struct magic *m, *prevm;
-#endif
- magic_server_config_rec *conf = (magic_server_config_rec *)
- ap_get_module_config(s->module_config, &mime_magic_module);
-
- const char *fname = ap_server_root_relative(p, conf->magicfile);
- result = apr_file_open(&f, fname, APR_READ | APR_BUFFERED, APR_OS_DEFAULT, p);
- if (result != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, result, s,
- MODNAME ": can't read magic file %s", fname);
- return -1;
- }
-
- /* set up the magic list (empty) */
- conf->magic = conf->last = NULL;
-
- /* parse it */
- for (lineno = 1; apr_file_gets(line, BUFSIZ, f) == APR_SUCCESS; lineno++) {
- int ws_offset;
-
- /* delete newline */
- if (line[0]) {
- line[strlen(line) - 1] = '\0';
- }
-
- /* skip leading whitespace */
- ws_offset = 0;
- while (line[ws_offset] && apr_isspace(line[ws_offset])) {
- ws_offset++;
- }
-
- /* skip blank lines */
- if (line[ws_offset] == 0) {
- continue;
- }
-
- /* comment, do not parse */
- if (line[ws_offset] == '#')
- continue;
-
-#if MIME_MAGIC_DEBUG
- /* if we get here, we're going to use it so count it */
- rule++;
-#endif
-
- /* parse it */
- if (parse(s, p, line + ws_offset, lineno) != 0)
- ++errs;
- }
-
- (void) apr_file_close(f);
-
-#if MIME_MAGIC_DEBUG
- ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, s,
- MODNAME ": apprentice conf=%x file=%s m=%s m->next=%s last=%s",
- conf,
- conf->magicfile ? conf->magicfile : "NULL",
- conf->magic ? "set" : "NULL",
- (conf->magic && conf->magic->next) ? "set" : "NULL",
- conf->last ? "set" : "NULL");
- ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, s,
- MODNAME ": apprentice read %d lines, %d rules, %d errors",
- lineno, rule, errs);
-#endif
-
-#if MIME_MAGIC_DEBUG
- prevm = 0;
- ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, s,
- MODNAME ": apprentice test");
- for (m = conf->magic; m; m = m->next) {
- if (apr_isprint((((unsigned long) m) >> 24) & 255) &&
- apr_isprint((((unsigned long) m) >> 16) & 255) &&
- apr_isprint((((unsigned long) m) >> 8) & 255) &&
- apr_isprint(((unsigned long) m) & 255)) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, s,
- MODNAME ": apprentice: POINTER CLOBBERED! "
- "m=\"%c%c%c%c\" line=%d",
- (((unsigned long) m) >> 24) & 255,
- (((unsigned long) m) >> 16) & 255,
- (((unsigned long) m) >> 8) & 255,
- ((unsigned long) m) & 255,
- prevm ? prevm->lineno : -1);
- break;
- }
- prevm = m;
- }
-#endif
-
- return (errs ? -1 : 0);
-}
-
-/*
- * extend the sign bit if the comparison is to be signed
- */
-static unsigned long signextend(server_rec *s, struct magic *m, unsigned long v)
-{
- if (!(m->flag & UNSIGNED))
- switch (m->type) {
- /*
- * Do not remove the casts below. They are vital. When later
- * compared with the data, the sign extension must have happened.
- */
- case BYTE:
- v = (char) v;
- break;
- case SHORT:
- case BESHORT:
- case LESHORT:
- v = (short) v;
- break;
- case DATE:
- case BEDATE:
- case LEDATE:
- case LONG:
- case BELONG:
- case LELONG:
- v = (long) v;
- break;
- case STRING:
- break;
- default:
- ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, 0, s,
- MODNAME ": can't happen: m->type=%d", m->type);
- return -1;
- }
- return v;
-}
-
-/*
- * parse one line from magic file, put into magic[index++] if valid
- */
-static int parse(server_rec *serv, apr_pool_t *p, char *l, int lineno)
-{
- struct magic *m;
- char *t, *s;
- magic_server_config_rec *conf = (magic_server_config_rec *)
- ap_get_module_config(serv->module_config, &mime_magic_module);
-
- /* allocate magic structure entry */
- m = (struct magic *) apr_pcalloc(p, sizeof(struct magic));
-
- /* append to linked list */
- m->next = NULL;
- if (!conf->magic || !conf->last) {
- conf->magic = conf->last = m;
- }
- else {
- conf->last->next = m;
- conf->last = m;
- }
-
- /* set values in magic structure */
- m->flag = 0;
- m->cont_level = 0;
- m->lineno = lineno;
-
- while (*l == '>') {
- ++l; /* step over */
- m->cont_level++;
- }
-
- if (m->cont_level != 0 && *l == '(') {
- ++l; /* step over */
- m->flag |= INDIR;
- }
-
- /* get offset, then skip over it */
- m->offset = (int) strtol(l, &t, 0);
- if (l == t) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, 0, serv,
- MODNAME ": offset %s invalid", l);
- }
- l = t;
-
- if (m->flag & INDIR) {
- m->in.type = LONG;
- m->in.offset = 0;
- /*
- * read [.lbs][+-]nnnnn)
- */
- if (*l == '.') {
- switch (*++l) {
- case 'l':
- m->in.type = LONG;
- break;
- case 's':
- m->in.type = SHORT;
- break;
- case 'b':
- m->in.type = BYTE;
- break;
- default:
- ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, 0, serv,
- MODNAME ": indirect offset type %c invalid", *l);
- break;
- }
- l++;
- }
- s = l;
- if (*l == '+' || *l == '-')
- l++;
- if (apr_isdigit((unsigned char) *l)) {
- m->in.offset = strtol(l, &t, 0);
- if (*s == '-')
- m->in.offset = -m->in.offset;
- }
- else
- t = l;
- if (*t++ != ')') {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, 0, serv,
- MODNAME ": missing ')' in indirect offset");
- }
- l = t;
- }
-
-
- while (apr_isdigit((unsigned char) *l))
- ++l;
- EATAB;
-
-#define NBYTE 4
-#define NSHORT 5
-#define NLONG 4
-#define NSTRING 6
-#define NDATE 4
-#define NBESHORT 7
-#define NBELONG 6
-#define NBEDATE 6
-#define NLESHORT 7
-#define NLELONG 6
-#define NLEDATE 6
-
- if (*l == 'u') {
- ++l;
- m->flag |= UNSIGNED;
- }
-
- /* get type, skip it */
- if (strncmp(l, "byte", NBYTE) == 0) {
- m->type = BYTE;
- l += NBYTE;
- }
- else if (strncmp(l, "short", NSHORT) == 0) {
- m->type = SHORT;
- l += NSHORT;
- }
- else if (strncmp(l, "long", NLONG) == 0) {
- m->type = LONG;
- l += NLONG;
- }
- else if (strncmp(l, "string", NSTRING) == 0) {
- m->type = STRING;
- l += NSTRING;
- }
- else if (strncmp(l, "date", NDATE) == 0) {
- m->type = DATE;
- l += NDATE;
- }
- else if (strncmp(l, "beshort", NBESHORT) == 0) {
- m->type = BESHORT;
- l += NBESHORT;
- }
- else if (strncmp(l, "belong", NBELONG) == 0) {
- m->type = BELONG;
- l += NBELONG;
- }
- else if (strncmp(l, "bedate", NBEDATE) == 0) {
- m->type = BEDATE;
- l += NBEDATE;
- }
- else if (strncmp(l, "leshort", NLESHORT) == 0) {
- m->type = LESHORT;
- l += NLESHORT;
- }
- else if (strncmp(l, "lelong", NLELONG) == 0) {
- m->type = LELONG;
- l += NLELONG;
- }
- else if (strncmp(l, "ledate", NLEDATE) == 0) {
- m->type = LEDATE;
- l += NLEDATE;
- }
- else {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, 0, serv,
- MODNAME ": type %s invalid", l);
- return -1;
- }
- /* New-style anding: "0 byte&0x80 =0x80 dynamically linked" */
- if (*l == '&') {
- ++l;
- m->mask = signextend(serv, m, strtol(l, &l, 0));
- }
- else
- m->mask = ~0L;
- EATAB;
-
- switch (*l) {
- case '>':
- case '<':
- /* Old-style anding: "0 byte &0x80 dynamically linked" */
- case '&':
- case '^':
- case '=':
- m->reln = *l;
- ++l;
- break;
- case '!':
- if (m->type != STRING) {
- m->reln = *l;
- ++l;
- break;
- }
- /* FALL THROUGH */
- default:
- if (*l == 'x' && apr_isspace((unsigned char) l[1])) {
- m->reln = *l;
- ++l;
- goto GetDesc; /* Bill The Cat */
- }
- m->reln = '=';
- break;
- }
- EATAB;
-
- if (getvalue(serv, m, &l))
- return -1;
- /*
- * now get last part - the description
- */
- GetDesc:
- EATAB;
- if (l[0] == '\b') {
- ++l;
- m->nospflag = 1;
- }
- else if ((l[0] == '\\') && (l[1] == 'b')) {
- ++l;
- ++l;
- m->nospflag = 1;
- }
- else
- m->nospflag = 0;
- strncpy(m->desc, l, sizeof(m->desc) - 1);
- m->desc[sizeof(m->desc) - 1] = '\0';
-
-#if MIME_MAGIC_DEBUG
- ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, serv,
- MODNAME ": parse line=%d m=%x next=%x cont=%d desc=%s",
- lineno, m, m->next, m->cont_level, m->desc);
-#endif /* MIME_MAGIC_DEBUG */
-
- return 0;
-}
-
-/*
- * Read a numeric value from a pointer, into the value union of a magic
- * pointer, according to the magic type. Update the string pointer to point
- * just after the number read. Return 0 for success, non-zero for failure.
- */
-static int getvalue(server_rec *s, struct magic *m, char **p)
-{
- int slen;
-
- if (m->type == STRING) {
- *p = getstr(s, *p, m->value.s, sizeof(m->value.s), &slen);
- m->vallen = slen;
- }
- else if (m->reln != 'x')
- m->value.l = signextend(s, m, strtol(*p, p, 0));
- return 0;
-}
-
-/*
- * Convert a string containing C character escapes. Stop at an unescaped
- * space or tab. Copy the converted version to "p", returning its length in
- * *slen. Return updated scan pointer as function result.
- */
-static char *getstr(server_rec *serv, register char *s, register char *p,
- int plen, int *slen)
-{
- char *origs = s, *origp = p;
- char *pmax = p + plen - 1;
- register int c;
- register int val;
-
- while ((c = *s++) != '\0') {
- if (apr_isspace((unsigned char) c))
- break;
- if (p >= pmax) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, 0, serv,
- MODNAME ": string too long: %s", origs);
- break;
- }
- if (c == '\\') {
- switch (c = *s++) {
-
- case '\0':
- goto out;
-
- default:
- *p++ = (char) c;
- break;
-
- case 'n':
- *p++ = '\n';
- break;
-
- case 'r':
- *p++ = '\r';
- break;
-
- case 'b':
- *p++ = '\b';
- break;
-
- case 't':
- *p++ = '\t';
- break;
-
- case 'f':
- *p++ = '\f';
- break;
-
- case 'v':
- *p++ = '\v';
- break;
-
- /* \ and up to 3 octal digits */
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- val = c - '0';
- c = *s++; /* try for 2 */
- if (c >= '0' && c <= '7') {
- val = (val << 3) | (c - '0');
- c = *s++; /* try for 3 */
- if (c >= '0' && c <= '7')
- val = (val << 3) | (c - '0');
- else
- --s;
- }
- else
- --s;
- *p++ = (char) val;
- break;
-
- /* \x and up to 3 hex digits */
- case 'x':
- val = 'x'; /* Default if no digits */
- c = hextoint(*s++); /* Get next char */
- if (c >= 0) {
- val = c;
- c = hextoint(*s++);
- if (c >= 0) {
- val = (val << 4) + c;
- c = hextoint(*s++);
- if (c >= 0) {
- val = (val << 4) + c;
- }
- else
- --s;
- }
- else
- --s;
- }
- else
- --s;
- *p++ = (char) val;
- break;
- }
- }
- else
- *p++ = (char) c;
- }
- out:
- *p = '\0';
- *slen = p - origp;
- return s;
-}
-
-
-/* Single hex char to int; -1 if not a hex char. */
-static int hextoint(int c)
-{
- if (apr_isdigit((unsigned char) c))
- return c - '0';
- if ((c >= 'a') && (c <= 'f'))
- return c + 10 - 'a';
- if ((c >= 'A') && (c <= 'F'))
- return c + 10 - 'A';
- return -1;
-}
-
-
-/*
- * return DONE to indicate it's been handled
- * return OK to indicate it's a regular file still needing handling
- * other returns indicate a failure of some sort
- */
-static int fsmagic(request_rec *r, const char *fn)
-{
- switch (r->finfo.filetype) {
- case APR_DIR:
- magic_rsl_puts(r, DIR_MAGIC_TYPE);
- return DONE;
- case APR_CHR:
- /*
- * (void) magic_rsl_printf(r,"character special (%d/%d)",
- * major(sb->st_rdev), minor(sb->st_rdev));
- */
- (void) magic_rsl_puts(r, MIME_BINARY_UNKNOWN);
- return DONE;
- case APR_BLK:
- /*
- * (void) magic_rsl_printf(r,"block special (%d/%d)",
- * major(sb->st_rdev), minor(sb->st_rdev));
- */
- (void) magic_rsl_puts(r, MIME_BINARY_UNKNOWN);
- return DONE;
- /* TODO add code to handle V7 MUX and Blit MUX files */
- case APR_PIPE:
- /*
- * magic_rsl_puts(r,"fifo (named pipe)");
- */
- (void) magic_rsl_puts(r, MIME_BINARY_UNKNOWN);
- return DONE;
- case APR_LNK:
- /* We used stat(), the only possible reason for this is that the
- * symlink is broken.
- */
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, 0, r,
- MODNAME ": broken symlink (%s)", fn);
- return HTTP_INTERNAL_SERVER_ERROR;
- case APR_SOCK:
- magic_rsl_puts(r, MIME_BINARY_UNKNOWN);
- return DONE;
- case APR_REG:
- break;
- default:
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, 0, r,
- MODNAME ": invalid file type %d.", r->finfo.filetype);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- /*
- * regular file, check next possibility
- */
- if (r->finfo.size == 0) {
- magic_rsl_puts(r, MIME_TEXT_UNKNOWN);
- return DONE;
- }
- return OK;
-}
-
-/*
- * softmagic - lookup one file in database (already read from /etc/magic by
- * apprentice.c). Passed the name and FILE * of one file to be typed.
- */
- /* ARGSUSED1 *//* nbytes passed for regularity, maybe need later */
-static int softmagic(request_rec *r, unsigned char *buf, apr_size_t nbytes)
-{
- if (match(r, buf, nbytes))
- return 1;
-
- return 0;
-}
-
-/*
- * Go through the whole list, stopping if you find a match. Process all the
- * continuations of that match before returning.
- *
- * We support multi-level continuations:
- *
- * At any time when processing a successful top-level match, there is a current
- * continuation level; it represents the level of the last successfully
- * matched continuation.
- *
- * Continuations above that level are skipped as, if we see one, it means that
- * the continuation that controls them - i.e, the lower-level continuation
- * preceding them - failed to match.
- *
- * Continuations below that level are processed as, if we see one, it means
- * we've finished processing or skipping higher-level continuations under the
- * control of a successful or unsuccessful lower-level continuation, and are
- * now seeing the next lower-level continuation and should process it. The
- * current continuation level reverts to the level of the one we're seeing.
- *
- * Continuations at the current level are processed as, if we see one, there's
- * no lower-level continuation that may have failed.
- *
- * If a continuation matches, we bump the current continuation level so that
- * higher-level continuations are processed.
- */
-static int match(request_rec *r, unsigned char *s, apr_size_t nbytes)
-{
-#if MIME_MAGIC_DEBUG
- int rule_counter = 0;
-#endif
- int cont_level = 0;
- int need_separator = 0;
- union VALUETYPE p;
- magic_server_config_rec *conf = (magic_server_config_rec *)
- ap_get_module_config(r->server->module_config, &mime_magic_module);
- struct magic *m;
-
-#if MIME_MAGIC_DEBUG
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, r,
- MODNAME ": match conf=%x file=%s m=%s m->next=%s last=%s",
- conf,
- conf->magicfile ? conf->magicfile : "NULL",
- conf->magic ? "set" : "NULL",
- (conf->magic && conf->magic->next) ? "set" : "NULL",
- conf->last ? "set" : "NULL");
-#endif
-
-#if MIME_MAGIC_DEBUG
- for (m = conf->magic; m; m = m->next) {
- if (apr_isprint((((unsigned long) m) >> 24) & 255) &&
- apr_isprint((((unsigned long) m) >> 16) & 255) &&
- apr_isprint((((unsigned long) m) >> 8) & 255) &&
- apr_isprint(((unsigned long) m) & 255)) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, r,
- MODNAME ": match: POINTER CLOBBERED! "
- "m=\"%c%c%c%c\"",
- (((unsigned long) m) >> 24) & 255,
- (((unsigned long) m) >> 16) & 255,
- (((unsigned long) m) >> 8) & 255,
- ((unsigned long) m) & 255);
- break;
- }
- }
-#endif
-
- for (m = conf->magic; m; m = m->next) {
-#if MIME_MAGIC_DEBUG
- rule_counter++;
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, r,
- MODNAME ": line=%d desc=%s", m->lineno, m->desc);
-#endif
-
- /* check if main entry matches */
- if (!mget(r, &p, s, m, nbytes) ||
- !mcheck(r, &p, m)) {
- struct magic *m_cont;
-
- /*
- * main entry didn't match, flush its continuations
- */
- if (!m->next || (m->next->cont_level == 0)) {
- continue;
- }
-
- m_cont = m->next;
- while (m_cont && (m_cont->cont_level != 0)) {
-#if MIME_MAGIC_DEBUG
- rule_counter++;
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, r,
- MODNAME ": line=%d mc=%x mc->next=%x cont=%d desc=%s",
- m_cont->lineno, m_cont,
- m_cont->next, m_cont->cont_level,
- m_cont->desc);
-#endif
- /*
- * this trick allows us to keep *m in sync when the continue
- * advances the pointer
- */
- m = m_cont;
- m_cont = m_cont->next;
- }
- continue;
- }
-
- /* if we get here, the main entry rule was a match */
- /* this will be the last run through the loop */
-#if MIME_MAGIC_DEBUG
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, r,
- MODNAME ": rule matched, line=%d type=%d %s",
- m->lineno, m->type,
- (m->type == STRING) ? m->value.s : "");
-#endif
-
- /* print the match */
- mprint(r, &p, m);
-
- /*
- * If we printed something, we'll need to print a blank before we
- * print something else.
- */
- if (m->desc[0])
- need_separator = 1;
- /* and any continuations that match */
- cont_level++;
- /*
- * while (m && m->next && m->next->cont_level != 0 && ( m = m->next
- * ))
- */
- m = m->next;
- while (m && (m->cont_level != 0)) {
-#if MIME_MAGIC_DEBUG
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, r,
- MODNAME ": match line=%d cont=%d type=%d %s",
- m->lineno, m->cont_level, m->type,
- (m->type == STRING) ? m->value.s : "");
-#endif
- if (cont_level >= m->cont_level) {
- if (cont_level > m->cont_level) {
- /*
- * We're at the end of the level "cont_level"
- * continuations.
- */
- cont_level = m->cont_level;
- }
- if (mget(r, &p, s, m, nbytes) &&
- mcheck(r, &p, m)) {
- /*
- * This continuation matched. Print its message, with a
- * blank before it if the previous item printed and this
- * item isn't empty.
- */
- /* space if previous printed */
- if (need_separator
- && (m->nospflag == 0)
- && (m->desc[0] != '\0')
- ) {
- (void) magic_rsl_putchar(r, ' ');
- need_separator = 0;
- }
- mprint(r, &p, m);
- if (m->desc[0])
- need_separator = 1;
-
- /*
- * If we see any continuations at a higher level, process
- * them.
- */
- cont_level++;
- }
- }
-
- /* move to next continuation record */
- m = m->next;
- }
-#if MIME_MAGIC_DEBUG
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, r,
- MODNAME ": matched after %d rules", rule_counter);
-#endif
- return 1; /* all through */
- }
-#if MIME_MAGIC_DEBUG
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, r,
- MODNAME ": failed after %d rules", rule_counter);
-#endif
- return 0; /* no match at all */
-}
-
-static void mprint(request_rec *r, union VALUETYPE *p, struct magic *m)
-{
- char *pp, *rt;
- unsigned long v;
-
- switch (m->type) {
- case BYTE:
- v = p->b;
- break;
-
- case SHORT:
- case BESHORT:
- case LESHORT:
- v = p->h;
- break;
-
- case LONG:
- case BELONG:
- case LELONG:
- v = p->l;
- break;
-
- case STRING:
- if (m->reln == '=') {
- (void) magic_rsl_printf(r, m->desc, m->value.s);
- }
- else {
- (void) magic_rsl_printf(r, m->desc, p->s);
- }
- return;
-
- case DATE:
- case BEDATE:
- case LEDATE:
- /* XXX: not multithread safe */
- pp = ctime((time_t *) & p->l);
- if ((rt = strchr(pp, '\n')) != NULL)
- *rt = '\0';
- (void) magic_rsl_printf(r, m->desc, pp);
- return;
- default:
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, 0, r,
- MODNAME ": invalid m->type (%d) in mprint().",
- m->type);
- return;
- }
-
- v = signextend(r->server, m, v) & m->mask;
- (void) magic_rsl_printf(r, m->desc, (unsigned long) v);
-}
-
-/*
- * Convert the byte order of the data we are looking at
- */
-static int mconvert(request_rec *r, union VALUETYPE *p, struct magic *m)
-{
- char *rt;
-
- switch (m->type) {
- case BYTE:
- case SHORT:
- case LONG:
- case DATE:
- return 1;
- case STRING:
- /* Null terminate and eat the return */
- p->s[sizeof(p->s) - 1] = '\0';
- if ((rt = strchr(p->s, '\n')) != NULL)
- *rt = '\0';
- return 1;
- case BESHORT:
- p->h = (short) ((p->hs[0] << 8) | (p->hs[1]));
- return 1;
- case BELONG:
- case BEDATE:
- p->l = (long)
- ((p->hl[0] << 24) | (p->hl[1] << 16) | (p->hl[2] << 8) | (p->hl[3]));
- return 1;
- case LESHORT:
- p->h = (short) ((p->hs[1] << 8) | (p->hs[0]));
- return 1;
- case LELONG:
- case LEDATE:
- p->l = (long)
- ((p->hl[3] << 24) | (p->hl[2] << 16) | (p->hl[1] << 8) | (p->hl[0]));
- return 1;
- default:
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, 0, r,
- MODNAME ": invalid type %d in mconvert().", m->type);
- return 0;
- }
-}
-
-
-static int mget(request_rec *r, union VALUETYPE *p, unsigned char *s,
- struct magic *m, apr_size_t nbytes)
-{
- long offset = m->offset;
-
- if (offset + sizeof(union VALUETYPE) > nbytes)
- return 0;
-
- memcpy(p, s + offset, sizeof(union VALUETYPE));
-
- if (!mconvert(r, p, m))
- return 0;
-
- if (m->flag & INDIR) {
-
- switch (m->in.type) {
- case BYTE:
- offset = p->b + m->in.offset;
- break;
- case SHORT:
- offset = p->h + m->in.offset;
- break;
- case LONG:
- offset = p->l + m->in.offset;
- break;
- }
-
- if (offset + sizeof(union VALUETYPE) > nbytes)
- return 0;
-
- memcpy(p, s + offset, sizeof(union VALUETYPE));
-
- if (!mconvert(r, p, m))
- return 0;
- }
- return 1;
-}
-
-static int mcheck(request_rec *r, union VALUETYPE *p, struct magic *m)
-{
- register unsigned long l = m->value.l;
- register unsigned long v;
- int matched;
-
- if ((m->value.s[0] == 'x') && (m->value.s[1] == '\0')) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, 0, r,
- MODNAME ": BOINK");
- return 1;
- }
-
- switch (m->type) {
- case BYTE:
- v = p->b;
- break;
-
- case SHORT:
- case BESHORT:
- case LESHORT:
- v = p->h;
- break;
-
- case LONG:
- case BELONG:
- case LELONG:
- case DATE:
- case BEDATE:
- case LEDATE:
- v = p->l;
- break;
-
- case STRING:
- l = 0;
- /*
- * What we want here is: v = strncmp(m->value.s, p->s, m->vallen);
- * but ignoring any nulls. bcmp doesn't give -/+/0 and isn't
- * universally available anyway.
- */
- v = 0;
- {
- register unsigned char *a = (unsigned char *) m->value.s;
- register unsigned char *b = (unsigned char *) p->s;
- register int len = m->vallen;
-
- while (--len >= 0)
- if ((v = *b++ - *a++) != 0)
- break;
- }
- break;
- default:
- /* bogosity, pretend that it just wasn't a match */
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, 0, r,
- MODNAME ": invalid type %d in mcheck().", m->type);
- return 0;
- }
-
- v = signextend(r->server, m, v) & m->mask;
-
- switch (m->reln) {
- case 'x':
-#if MIME_MAGIC_DEBUG
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, r,
- "%lu == *any* = 1", v);
-#endif
- matched = 1;
- break;
-
- case '!':
- matched = v != l;
-#if MIME_MAGIC_DEBUG
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, r,
- "%lu != %lu = %d", v, l, matched);
-#endif
- break;
-
- case '=':
- matched = v == l;
-#if MIME_MAGIC_DEBUG
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, r,
- "%lu == %lu = %d", v, l, matched);
-#endif
- break;
-
- case '>':
- if (m->flag & UNSIGNED) {
- matched = v > l;
-#if MIME_MAGIC_DEBUG
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, r,
- "%lu > %lu = %d", v, l, matched);
-#endif
- }
- else {
- matched = (long) v > (long) l;
-#if MIME_MAGIC_DEBUG
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, r,
- "%ld > %ld = %d", v, l, matched);
-#endif
- }
- break;
-
- case '<':
- if (m->flag & UNSIGNED) {
- matched = v < l;
-#if MIME_MAGIC_DEBUG
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, r,
- "%lu < %lu = %d", v, l, matched);
-#endif
- }
- else {
- matched = (long) v < (long) l;
-#if MIME_MAGIC_DEBUG
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, r,
- "%ld < %ld = %d", v, l, matched);
-#endif
- }
- break;
-
- case '&':
- matched = (v & l) == l;
-#if MIME_MAGIC_DEBUG
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, r,
- "((%lx & %lx) == %lx) = %d", v, l, l, matched);
-#endif
- break;
-
- case '^':
- matched = (v & l) != l;
-#if MIME_MAGIC_DEBUG
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, r,
- "((%lx & %lx) != %lx) = %d", v, l, l, matched);
-#endif
- break;
-
- default:
- /* bogosity, pretend it didn't match */
- matched = 0;
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_ERR, 0, r,
- MODNAME ": mcheck: can't happen: invalid relation %d.",
- m->reln);
- break;
- }
-
- return matched;
-}
-
-/* an optimization over plain strcmp() */
-#define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
-
-static int ascmagic(request_rec *r, unsigned char *buf, apr_size_t nbytes)
-{
- int has_escapes = 0;
- unsigned char *s;
- char nbuf[HOWMANY + 1]; /* one extra for terminating '\0' */
- char *token;
- register struct names *p;
- int small_nbytes;
-
- /* these are easy, do them first */
-
- /*
- * for troff, look for . + letter + letter or .\"; this must be done to
- * disambiguate tar archives' ./file and other trash from real troff
- * input.
- */
- if (*buf == '.') {
- unsigned char *tp = buf + 1;
-
- while (apr_isspace(*tp))
- ++tp; /* skip leading whitespace */
- if ((apr_isalnum(*tp) || *tp == '\\') &&
- (apr_isalnum(*(tp + 1)) || *tp == '"')) {
- magic_rsl_puts(r, "application/x-troff");
- return 1;
- }
- }
- if ((*buf == 'c' || *buf == 'C') && apr_isspace(*(buf + 1))) {
- /* Fortran */
- magic_rsl_puts(r, "text/plain");
- return 1;
- }
-
- /* look for tokens from names.h - this is expensive!, so we'll limit
- * ourselves to only SMALL_HOWMANY bytes */
- small_nbytes = (nbytes > SMALL_HOWMANY) ? SMALL_HOWMANY : nbytes;
- /* make a copy of the buffer here because strtok() will destroy it */
- s = (unsigned char *) memcpy(nbuf, buf, small_nbytes);
- s[small_nbytes] = '\0';
- has_escapes = (memchr(s, '\033', small_nbytes) != NULL);
- /* XXX: not multithread safe */
- while ((token = strtok((char *) s, " \t\n\r\f")) != NULL) {
- s = NULL; /* make strtok() keep on tokin' */
- for (p = names; p < names + NNAMES; p++) {
- if (STREQ(p->name, token)) {
- magic_rsl_puts(r, types[p->type]);
- if (has_escapes)
- magic_rsl_puts(r, " (with escape sequences)");
- return 1;
- }
- }
- }
-
- switch (is_tar(buf, nbytes)) {
- case 1:
- /* V7 tar archive */
- magic_rsl_puts(r, "application/x-tar");
- return 1;
- case 2:
- /* POSIX tar archive */
- magic_rsl_puts(r, "application/x-tar");
- return 1;
- }
-
- /* all else fails, but it is ascii... */
- if (has_escapes) {
- /* text with escape sequences */
- /* we leave this open for further differentiation later */
- magic_rsl_puts(r, "text/plain");
- }
- else {
- /* plain text */
- magic_rsl_puts(r, "text/plain");
- }
- return 1;
-}
-
-
-/*
- * compress routines: zmagic() - returns 0 if not recognized, uncompresses
- * and prints information if recognized uncompress(s, method, old, n, newch)
- * - uncompress old into new, using method, return sizeof new
- */
-
-static struct {
- char *magic;
- int maglen;
- char *argv[3];
- int silent;
- char *encoding; /* MUST be lowercase */
-} compr[] = {
-
- /* we use gzip here rather than uncompress because we have to pass
- * it a full filename -- and uncompress only considers filenames
- * ending with .Z
- */
- {
- "\037\235", 2, {
- "gzip", "-dcq", NULL
- }, 0, "x-compress"
- },
- {
- "\037\213", 2, {
- "gzip", "-dcq", NULL
- }, 1, "x-gzip"
- },
- /*
- * XXX pcat does not work, cause I don't know how to make it read stdin,
- * so we use gzip
- */
- {
- "\037\036", 2, {
- "gzip", "-dcq", NULL
- }, 0, "x-gzip"
- },
-};
-
-static int ncompr = sizeof(compr) / sizeof(compr[0]);
-
-static int zmagic(request_rec *r, unsigned char *buf, apr_size_t nbytes)
-{
- unsigned char *newbuf;
- int newsize;
- int i;
-
- for (i = 0; i < ncompr; i++) {
- if (nbytes < compr[i].maglen)
- continue;
- if (memcmp(buf, compr[i].magic, compr[i].maglen) == 0)
- break;
- }
-
- if (i == ncompr)
- return 0;
-
- if ((newsize = uncompress(r, i, &newbuf, nbytes)) > 0) {
- tryit(r, newbuf, newsize, 0);
-
- /* set encoding type in the request record */
- r->content_encoding = compr[i].encoding;
- }
- return 1;
-}
-
-
-struct uncompress_parms {
- request_rec *r;
- int method;
-};
-
-static int create_uncompress_child(struct uncompress_parms *parm, apr_pool_t *cntxt,
- apr_file_t **pipe_in)
-{
- int rc = 1;
- const char *new_argv[4];
- const char *const *env;
- request_rec *r = parm->r;
- apr_pool_t *child_context = cntxt;
- apr_procattr_t *procattr;
- apr_proc_t *procnew;
-
- /* XXX missing 1.3 logic:
- *
- * what happens when !compr[parm->method].silent?
- * Should we create the err pipe, read it, and copy to the log?
- */
-
- env = (const char *const *)ap_create_environment(child_context, r->subprocess_env);
-
- if ((apr_procattr_create(&procattr, child_context) != APR_SUCCESS) ||
- (apr_procattr_io_set(procattr, APR_FULL_BLOCK,
- APR_FULL_BLOCK, APR_NO_PIPE) != APR_SUCCESS) ||
- (apr_procattr_dir_set(procattr, r->filename) != APR_SUCCESS) ||
- (apr_procattr_cmdtype_set(procattr, APR_PROGRAM) != APR_SUCCESS)) {
- /* Something bad happened, tell the world. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_ENOPROC, r,
- "couldn't setup child process: %s", r->filename);
- }
- else {
- new_argv[0] = compr[parm->method].argv[0];
- new_argv[1] = compr[parm->method].argv[1];
- new_argv[2] = r->filename;
- new_argv[3] = NULL;
-
- procnew = apr_pcalloc(child_context, sizeof(*procnew));
- rc = apr_proc_create(procnew, compr[parm->method].argv[0],
- new_argv, env, procattr, child_context);
-
- if (rc != APR_SUCCESS) {
- /* Bad things happened. Everyone should have cleaned up. */
- ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_ENOPROC, r,
- MODNAME ": could not execute `%s'.",
- compr[parm->method].argv[0]);
- }
- else {
- apr_pool_note_subprocess(child_context, procnew, kill_after_timeout);
- *pipe_in = procnew->out;
- }
- }
-
- return (rc);
-}
-
-static int uncompress(request_rec *r, int method,
- unsigned char **newch, apr_size_t n)
-{
- struct uncompress_parms parm;
- apr_file_t *pipe_out = NULL;
- apr_pool_t *sub_context;
- apr_status_t rv;
-
- parm.r = r;
- parm.method = method;
-
- /* We make a sub_pool so that we can collect our child early, otherwise
- * there are cases (i.e. generating directory indicies with mod_autoindex)
- * where we would end up with LOTS of zombies.
- */
- if (apr_pool_create(&sub_context, r->pool) != APR_SUCCESS)
- return -1;
-
- if ((rv = create_uncompress_child(&parm, sub_context, &pipe_out)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- MODNAME ": couldn't spawn uncompress process: %s", r->uri);
- return -1;
- }
-
- *newch = (unsigned char *) apr_palloc(r->pool, n);
- rv = apr_file_read(pipe_out, *newch, &n);
- if (n == 0) {
- apr_pool_destroy(sub_context);
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- MODNAME ": read failed %s", r->filename);
- return -1;
- }
- apr_pool_destroy(sub_context);
- return n;
-}
-
-/*
- * is_tar() -- figure out whether file is a tar archive.
- *
- * Stolen (by author of file utility) from the public domain tar program: Public
- * Domain version written 26 Aug 1985 John Gilmore (ihnp4!hoptoad!gnu).
- *
- * @(#)list.c 1.18 9/23/86 Public Domain - gnu $Id: mod_mime_magic.c,v 1.7
- * 1997/06/24 00:41:02 ikluft Exp ikluft $
- *
- * Comments changed and some code/comments reformatted for file command by Ian
- * Darwin.
- */
-
-#define isodigit(c) ( ((c) >= '0') && ((c) <= '7') )
-
-/*
- * Return 0 if the checksum is bad (i.e., probably not a tar archive), 1 for
- * old UNIX tar file, 2 for Unix Std (POSIX) tar file.
- */
-
-static int is_tar(unsigned char *buf, apr_size_t nbytes)
-{
- register union record *header = (union record *) buf;
- register int i;
- register long sum, recsum;
- register char *p;
-
- if (nbytes < sizeof(union record))
- return 0;
-
- recsum = from_oct(8, header->header.chksum);
-
- sum = 0;
- p = header->charptr;
- for (i = sizeof(union record); --i >= 0;) {
- /*
- * We can't use unsigned char here because of old compilers, e.g. V7.
- */
- sum += 0xFF & *p++;
- }
-
- /* Adjust checksum to count the "chksum" field as blanks. */
- for (i = sizeof(header->header.chksum); --i >= 0;)
- sum -= 0xFF & header->header.chksum[i];
- sum += ' ' * sizeof header->header.chksum;
-
- if (sum != recsum)
- return 0; /* Not a tar archive */
-
- if (0 == strcmp(header->header.magic, TMAGIC))
- return 2; /* Unix Standard tar archive */
-
- return 1; /* Old fashioned tar archive */
-}
-
-
-/*
- * Quick and dirty octal conversion.
- *
- * Result is -1 if the field is invalid (all blank, or nonoctal).
- */
-static long from_oct(int digs, char *where)
-{
- register long value;
-
- while (apr_isspace(*where)) { /* Skip spaces */
- where++;
- if (--digs <= 0)
- return -1; /* All blank field */
- }
- value = 0;
- while (digs > 0 && isodigit(*where)) { /* Scan til nonoctal */
- value = (value << 3) | (*where++ - '0');
- --digs;
- }
-
- if (digs > 0 && *where && !apr_isspace(*where))
- return -1; /* Ended on non-space/nul */
-
- return value;
-}
-
-/*
- * Check for file-revision suffix
- *
- * This is for an obscure document control system used on an intranet.
- * The web representation of each file's revision has an @1, @2, etc
- * appended with the revision number. This needs to be stripped off to
- * find the file suffix, which can be recognized by sending the name back
- * through a sub-request. The base file name (without the @num suffix)
- * must exist because its type will be used as the result.
- */
-static int revision_suffix(request_rec *r)
-{
- int suffix_pos, result;
- char *sub_filename;
- request_rec *sub;
-
-#if MIME_MAGIC_DEBUG
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, r,
- MODNAME ": revision_suffix checking %s", r->filename);
-#endif /* MIME_MAGIC_DEBUG */
-
- /* check for recognized revision suffix */
- suffix_pos = strlen(r->filename) - 1;
- if (!apr_isdigit(r->filename[suffix_pos])) {
- return 0;
- }
- while (suffix_pos >= 0 && apr_isdigit(r->filename[suffix_pos]))
- suffix_pos--;
- if (suffix_pos < 0 || r->filename[suffix_pos] != '@') {
- return 0;
- }
-
- /* perform sub-request for the file name without the suffix */
- result = 0;
- sub_filename = apr_pstrndup(r->pool, r->filename, suffix_pos);
-#if MIME_MAGIC_DEBUG
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, r,
- MODNAME ": subrequest lookup for %s", sub_filename);
-#endif /* MIME_MAGIC_DEBUG */
- sub = ap_sub_req_lookup_file(sub_filename, r, NULL);
-
- /* extract content type/encoding/language from sub-request */
- if (sub->content_type) {
- r->content_type = apr_pstrdup(r->pool, sub->content_type);
-#if MIME_MAGIC_DEBUG
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, r,
- MODNAME ": subrequest %s got %s",
- sub_filename, r->content_type);
-#endif /* MIME_MAGIC_DEBUG */
- if (sub->content_encoding)
- r->content_encoding =
- apr_pstrdup(r->pool, sub->content_encoding);
- if (sub->content_language)
- r->content_language =
- apr_pstrdup(r->pool, sub->content_language);
- result = 1;
- }
-
- /* clean up */
- ap_destroy_sub_req(sub);
-
- return result;
-}
-
-/*
- * initialize the module
- */
-static void magic_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *main_server)
-{
- int result;
- magic_server_config_rec *conf;
- magic_server_config_rec *main_conf;
- server_rec *s;
-#if MIME_MAGIC_DEBUG
- struct magic *m, *prevm;
-#endif /* MIME_MAGIC_DEBUG */
-
- main_conf = ap_get_module_config(main_server->module_config, &mime_magic_module);
- for (s = main_server; s; s = s->next) {
- conf = ap_get_module_config(s->module_config, &mime_magic_module);
- if (conf->magicfile == NULL && s != main_server) {
- /* inherits from the parent */
- *conf = *main_conf;
- }
- else if (conf->magicfile) {
- result = apprentice(s, p);
- if (result == -1)
- return;
-#if MIME_MAGIC_DEBUG
- prevm = 0;
- ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, s,
- MODNAME ": magic_init 1 test");
- for (m = conf->magic; m; m = m->next) {
- if (apr_isprint((((unsigned long) m) >> 24) & 255) &&
- apr_isprint((((unsigned long) m) >> 16) & 255) &&
- apr_isprint((((unsigned long) m) >> 8) & 255) &&
- apr_isprint(((unsigned long) m) & 255)) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO | APLOG_DEBUG, 0, s,
- MODNAME ": magic_init 1: POINTER CLOBBERED! "
- "m=\"%c%c%c%c\" line=%d",
- (((unsigned long) m) >> 24) & 255,
- (((unsigned long) m) >> 16) & 255,
- (((unsigned long) m) >> 8) & 255,
- ((unsigned long) m) & 255,
- prevm ? prevm->lineno : -1);
- break;
- }
- prevm = m;
- }
-#endif
- }
- }
-}
-
-/*
- * Find the Content-Type from any resource this module has available
- */
-
-static int magic_find_ct(request_rec *r)
-{
- int result;
- magic_server_config_rec *conf;
-
- /* the file has to exist */
- if (r->finfo.filetype == 0 || !r->filename) {
- return DECLINED;
- }
-
- /* was someone else already here? */
- if (r->content_type) {
- return DECLINED;
- }
-
- conf = ap_get_module_config(r->server->module_config, &mime_magic_module);
- if (!conf || !conf->magic) {
- return DECLINED;
- }
-
- /* initialize per-request info */
- if (!magic_set_config(r)) {
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- /* try excluding file-revision suffixes */
- if (revision_suffix(r) != 1) {
- /* process it based on the file contents */
- if ((result = magic_process(r)) != OK) {
- return result;
- }
- }
-
- /* if we have any results, put them in the request structure */
- return magic_rsl_to_request(r);
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- static const char * const aszPre[]={ "mod_mime.c", NULL };
-
- /* mod_mime_magic should be run after mod_mime, if at all. */
-
- ap_hook_type_checker(magic_find_ct, aszPre, NULL, APR_HOOK_MIDDLE);
- ap_hook_post_config(magic_init, NULL, NULL, APR_HOOK_FIRST);
-}
-
-/*
- * Apache API module interface
- */
-
-module mime_magic_module =
-{
- STANDARD20_MODULE_STUFF,
- NULL, /* dir config creator */
- NULL, /* dir merger --- default is to override */
- create_magic_server_config, /* server config */
- merge_magic_server_config, /* merge server config */
- mime_magic_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
-
-
diff --git a/modules/metadata/mod_mime_magic.exp b/modules/metadata/mod_mime_magic.exp
deleted file mode 100644
index 42068a4342..0000000000
--- a/modules/metadata/mod_mime_magic.exp
+++ /dev/null
@@ -1 +0,0 @@
-mime_magic_module
diff --git a/modules/metadata/mod_setenvif.c b/modules/metadata/mod_setenvif.c
deleted file mode 100644
index 386f3c8d74..0000000000
--- a/modules/metadata/mod_setenvif.c
+++ /dev/null
@@ -1,471 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * mod_setenvif.c
- * Set environment variables based on matching request headers or
- * attributes against regex strings
- *
- * Paul Sutton <paul@ukweb.com> 27 Oct 1996
- * Based on mod_browser by Alexei Kosut <akosut@organic.com>
- */
-
-/*
- * Used to set environment variables based on the incoming request headers,
- * or some selected other attributes of the request (e.g., the remote host
- * name).
- *
- * Usage:
- *
- * SetEnvIf name regex var ...
- *
- * where name is either a HTTP request header name, or one of the
- * special values (see below). The 'value' of the header (or the
- * value of the special value from below) are compared against the
- * regex argument. If this is a simple string, a simple sub-string
- * match is performed. Otherwise, a request expression match is
- * done. If the value matches the string or regular expression, the
- * environment variables listed as var ... are set. Each var can
- * be in one of three formats: var, which sets the named variable
- * (the value value "1"); var=value, which sets the variable to
- * the given value; or !var, which unsets the variable is it has
- * been previously set.
- *
- * Normally the strings are compared with regard to case. To ignore
- * case, use the directive SetEnvIfNoCase instead.
- *
- * Special values for 'name' are:
- *
- * remote_host Remote host name (if available)
- * remote_addr Remote IP address
- * remote_user Remote authenticated user (if any)
- * request_method Request method (GET, POST, etc)
- * request_uri Requested URI
- *
- * Examples:
- *
- * To set the enviroment variable LOCALHOST if the client is the local
- * machine:
- *
- * SetEnvIf remote_addr 127.0.0.1 LOCALHOST
- *
- * To set LOCAL if the client is the local host, or within our company's
- * domain (192.168.10):
- *
- * SetEnvIf remote_addr 192.168.10. LOCAL
- * SetEnvIf remote_addr 127.0.0.1 LOCALHOST
- *
- * This could be written as:
- *
- * SetEnvIf remote_addr (127.0.0.1|192.168.10.) LOCAL
- */
-
-#include "apr.h"
-#include "apr_strings.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_core.h"
-#include "http_log.h"
-#include "http_protocol.h"
-
-
-enum special {
- SPECIAL_NOT,
- SPECIAL_REMOTE_ADDR,
- SPECIAL_REMOTE_HOST,
- SPECIAL_REMOTE_USER,
- SPECIAL_REQUEST_URI,
- SPECIAL_REQUEST_METHOD,
- SPECIAL_REQUEST_PROTOCOL
-};
-typedef struct {
- char *name; /* header name */
- char *regex; /* regex to match against */
- regex_t *preg; /* compiled regex */
- apr_table_t *features; /* env vars to set (or unset) */
- enum special special_type; /* is it a "special" header ? */
- int icase; /* ignoring case? */
-} sei_entry;
-
-typedef struct {
- apr_array_header_t *conditionals;
-} sei_cfg_rec;
-
-module AP_MODULE_DECLARE_DATA setenvif_module;
-
-/*
- * These routines, the create- and merge-config functions, are called
- * for both the server-wide and the per-directory contexts. This is
- * because the different definitions are used at different times; the
- * server-wide ones are used in the post-read-request phase, and the
- * per-directory ones are used during the header-parse phase (after
- * the URI has been mapped to a file and we have anything from the
- * .htaccess file and <Directory> and <Files> containers).
- */
-static void *create_setenvif_config(apr_pool_t *p)
-{
- sei_cfg_rec *new = (sei_cfg_rec *) apr_palloc(p, sizeof(sei_cfg_rec));
-
- new->conditionals = apr_array_make(p, 20, sizeof(sei_entry));
- return (void *) new;
-}
-
-static void *create_setenvif_config_svr(apr_pool_t *p, server_rec *dummy)
-{
- return create_setenvif_config(p);
-}
-
-static void *create_setenvif_config_dir(apr_pool_t *p, char *dummy)
-{
- return create_setenvif_config(p);
-}
-
-static void *merge_setenvif_config(apr_pool_t *p, void *basev, void *overridesv)
-{
- sei_cfg_rec *a = apr_pcalloc(p, sizeof(sei_cfg_rec));
- sei_cfg_rec *base = basev, *overrides = overridesv;
-
- a->conditionals = apr_array_append(p, base->conditionals,
- overrides->conditionals);
- return a;
-}
-
-/*
- * any non-NULL magic constant will do... used to indicate if REG_ICASE should
- * be used
- */
-#define ICASE_MAGIC ((void *)(&setenvif_module))
-#define SEI_MAGIC_HEIRLOOM "setenvif-phase-flag"
-
-static const char *add_setenvif_core(cmd_parms *cmd, void *mconfig,
- char *fname, const char *args)
-{
- char *regex;
- const char *feature;
- sei_cfg_rec *sconf;
- sei_entry *new;
- sei_entry *entries;
- char *var;
- int i;
- int beenhere = 0;
- int icase;
-
- /*
- * Determine from our context into which record to put the entry.
- * cmd->path == NULL means we're in server-wide context; otherwise,
- * we're dealing with a per-directory setting.
- */
- sconf = (cmd->path != NULL)
- ? (sei_cfg_rec *) mconfig
- : (sei_cfg_rec *) ap_get_module_config(cmd->server->module_config,
- &setenvif_module);
- entries = (sei_entry *) sconf->conditionals->elts;
- /* get regex */
- regex = ap_getword_conf(cmd->pool, &args);
- if (!*regex) {
- return apr_pstrcat(cmd->pool, "Missing regular expression for ",
- cmd->cmd->name, NULL);
- }
-
- /*
- * If we've already got a sei_entry with the same name we want to
- * just copy the name pointer... so that later on we can compare
- * two header names just by comparing the pointers.
- */
-
- for (i = 0; i < sconf->conditionals->nelts; ++i) {
- new = &entries[i];
- if (!strcasecmp(new->name, fname)) {
- fname = new->name;
- break;
- }
- }
-
- /* if the last entry has an identical headername and regex then
- * merge with it
- */
- i = sconf->conditionals->nelts - 1;
- icase = cmd->info == ICASE_MAGIC;
- if (i < 0
- || entries[i].name != fname
- || entries[i].icase != icase
- || strcmp(entries[i].regex, regex)) {
-
- /* no match, create a new entry */
-
- new = apr_array_push(sconf->conditionals);
- new->name = fname;
- new->regex = regex;
- new->icase = icase;
- new->preg = ap_pregcomp(cmd->pool, regex,
- (REG_EXTENDED | REG_NOSUB
- | (icase ? REG_ICASE : 0)));
- if (new->preg == NULL) {
- return apr_pstrcat(cmd->pool, cmd->cmd->name,
- " regex could not be compiled.", NULL);
- }
- new->features = apr_table_make(cmd->pool, 2);
-
- if (!strcasecmp(fname, "remote_addr")) {
- new->special_type = SPECIAL_REMOTE_ADDR;
- }
- else if (!strcasecmp(fname, "remote_host")) {
- new->special_type = SPECIAL_REMOTE_HOST;
- }
- else if (!strcasecmp(fname, "remote_user")) {
- new->special_type = SPECIAL_REMOTE_USER;
- }
- else if (!strcasecmp(fname, "request_uri")) {
- new->special_type = SPECIAL_REQUEST_URI;
- }
- else if (!strcasecmp(fname, "request_method")) {
- new->special_type = SPECIAL_REQUEST_METHOD;
- }
- else if (!strcasecmp(fname, "request_protocol")) {
- new->special_type = SPECIAL_REQUEST_PROTOCOL;
- }
- else {
- new->special_type = SPECIAL_NOT;
- }
- }
- else {
- new = &entries[i];
- }
-
- for ( ; ; ) {
- feature = ap_getword_conf(cmd->pool, &args);
- if (!*feature) {
- break;
- }
- beenhere++;
-
- var = ap_getword(cmd->pool, &feature, '=');
- if (*feature) {
- apr_table_setn(new->features, var, feature);
- }
- else if (*var == '!') {
- apr_table_setn(new->features, var + 1, "!");
- }
- else {
- apr_table_setn(new->features, var, "1");
- }
- }
-
- if (!beenhere) {
- return apr_pstrcat(cmd->pool, "Missing envariable expression for ",
- cmd->cmd->name, NULL);
- }
-
- return NULL;
-}
-
-static const char *add_setenvif(cmd_parms *cmd, void *mconfig,
- const char *args)
-{
- char *fname;
-
- /* get header name */
- fname = ap_getword_conf(cmd->pool, &args);
- if (!*fname) {
- return apr_pstrcat(cmd->pool, "Missing header-field name for ",
- cmd->cmd->name, NULL);
- }
- return add_setenvif_core(cmd, mconfig, fname, args);
-}
-
-/*
- * This routine handles the BrowserMatch* directives. It simply turns around
- * and feeds them, with the appropriate embellishments, to the general-purpose
- * command handler.
- */
-static const char *add_browser(cmd_parms *cmd, void *mconfig, const char *args)
-{
- return add_setenvif_core(cmd, mconfig, "User-Agent", args);
-}
-
-static const command_rec setenvif_module_cmds[] =
-{
- AP_INIT_RAW_ARGS("SetEnvIf", add_setenvif, NULL,
- OR_FILEINFO, "A header-name, regex and a list of variables."),
- AP_INIT_RAW_ARGS("SetEnvIfNoCase", add_setenvif, ICASE_MAGIC,
- OR_FILEINFO, "a header-name, regex and a list of variables."),
- AP_INIT_RAW_ARGS("BrowserMatch", add_browser, NULL,
- OR_FILEINFO, "A browser regex and a list of variables."),
- AP_INIT_RAW_ARGS("BrowserMatchNoCase", add_browser, ICASE_MAGIC,
- OR_FILEINFO, "A browser regex and a list of variables."),
- { NULL },
-};
-
-/*
- * This routine gets called at two different points in request processing:
- * once before the URI has been translated (during the post-read-request
- * phase) and once after (during the header-parse phase). We use different
- * config records for the two different calls to reduce overhead (by not
- * re-doing the server-wide settings during directory processing), and
- * signal which call it is by having the earlier one pass a flag to the
- * later one.
- */
-static int match_headers(request_rec *r)
-{
- sei_cfg_rec *sconf;
- sei_entry *entries;
- apr_table_entry_t *elts;
- const char *val;
- int i, j;
- char *last_name;
-
- if (apr_table_get(r->notes, SEI_MAGIC_HEIRLOOM) == NULL) {
- apr_table_set(r->notes, SEI_MAGIC_HEIRLOOM, "post-read done");
- sconf = (sei_cfg_rec *) ap_get_module_config(r->server->module_config,
- &setenvif_module);
- }
- else {
- sconf = (sei_cfg_rec *) ap_get_module_config(r->per_dir_config,
- &setenvif_module);
- }
- entries = (sei_entry *) sconf->conditionals->elts;
- last_name = NULL;
- val = NULL;
- for (i = 0; i < sconf->conditionals->nelts; ++i) {
- sei_entry *b = &entries[i];
-
- /* Optimize the case where a bunch of directives in a row use the
- * same header. Remember we don't need to strcmp the two header
- * names because we made sure the pointers were equal during
- * configuration.
- */
- if (b->name != last_name) {
- last_name = b->name;
- switch (b->special_type) {
- case SPECIAL_REMOTE_ADDR:
- val = r->connection->remote_ip;
- break;
- case SPECIAL_REMOTE_HOST:
- val = ap_get_remote_host(r->connection, r->per_dir_config,
- REMOTE_NAME, NULL);
- break;
- case SPECIAL_REMOTE_USER:
- val = r->user;
- break;
- case SPECIAL_REQUEST_URI:
- val = r->uri;
- break;
- case SPECIAL_REQUEST_METHOD:
- val = r->method;
- break;
- case SPECIAL_REQUEST_PROTOCOL:
- val = r->protocol;
- break;
- case SPECIAL_NOT:
- val = apr_table_get(r->headers_in, b->name);
- if (val == NULL) {
- val = apr_table_get(r->subprocess_env, b->name);
- }
- break;
- }
- }
-
- /*
- * A NULL value indicates that the header field or special entity
- * wasn't present or is undefined. Represent that as an empty string
- * so that REs like "^$" will work and allow envariable setting
- * based on missing or empty field.
- */
- if (val == NULL) {
- val = "";
- }
-
- if (!ap_regexec(b->preg, val, 0, NULL, 0)) {
- apr_array_header_t *arr = apr_table_elts(b->features);
- elts = (apr_table_entry_t *) arr->elts;
-
- for (j = 0; j < arr->nelts; ++j) {
- if (!strcmp(elts[j].val, "!")) {
- apr_table_unset(r->subprocess_env, elts[j].key);
- }
- else {
- apr_table_setn(r->subprocess_env, elts[j].key, elts[j].val);
- }
- }
- }
- }
-
- return DECLINED;
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_header_parser(match_headers, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_post_read_request(match_headers, NULL, NULL, APR_HOOK_MIDDLE);
-}
-
-module AP_MODULE_DECLARE_DATA setenvif_module =
-{
- STANDARD20_MODULE_STUFF,
- create_setenvif_config_dir, /* dir config creater */
- merge_setenvif_config, /* dir merger --- default is to override */
- create_setenvif_config_svr, /* server config */
- merge_setenvif_config, /* merge server configs */
- setenvif_module_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
diff --git a/modules/metadata/mod_setenvif.exp b/modules/metadata/mod_setenvif.exp
deleted file mode 100644
index 4f3800e3a8..0000000000
--- a/modules/metadata/mod_setenvif.exp
+++ /dev/null
@@ -1 +0,0 @@
-setenvif_module
diff --git a/modules/metadata/mod_unique_id.c b/modules/metadata/mod_unique_id.c
deleted file mode 100644
index 69a54174b4..0000000000
--- a/modules/metadata/mod_unique_id.c
+++ /dev/null
@@ -1,402 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * mod_unique_id.c: generate a unique identifier for each request
- *
- * Original author: Dean Gaudet <dgaudet@arctic.org>
- * UUencoding modified by: Alvaro Martinez Echevarria <alvaro@lander.es>
- */
-
-#include "apr_general.h" /* for XtOffsetOf */
-
-#include "httpd.h"
-#include "http_config.h"
-#include "http_log.h"
-#include "http_protocol.h" /* for ap_hook_post_read_request */
-
-#if APR_HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#if APR_HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#if APR_HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-typedef struct {
- unsigned int stamp;
- unsigned int in_addr;
- unsigned int pid;
- unsigned short counter;
- unsigned int thread_index;
-} unique_id_rec;
-
-/* We are using thread_index (the index into the scoreboard), because we
- * cannont garauntee the thread_id will be an integer.
- *
- * This code looks like it won't give a unique ID with the new thread logic.
- * It will. The reason is, we don't increment the counter in a thread_safe
- * manner. Because the thread_index is also in the unique ID now, this does
- * not matter. In order for the id to not be unique, the same thread would
- * have to get the same counter twice in the same second.
- */
-
-/* Comments:
- *
- * We want an identifier which is unique across all hits, everywhere.
- * "everywhere" includes multiple httpd instances on the same machine, or on
- * multiple machines. Essentially "everywhere" should include all possible
- * httpds across all servers at a particular "site". We make some assumptions
- * that if the site has a cluster of machines then their time is relatively
- * synchronized. We also assume that the first address returned by a
- * gethostbyname (gethostname()) is unique across all the machines at the
- * "site".
- *
- * We also further assume that pids fit in 32-bits. If something uses more
- * than 32-bits, the fix is trivial, but it requires the unrolled uuencoding
- * loop to be extended. * A similar fix is needed to support multithreaded
- * servers, using a pid/tid combo.
- *
- * Together, the in_addr and pid are assumed to absolutely uniquely identify
- * this one child from all other currently running children on all servers
- * (including this physical server if it is running multiple httpds) from each
- * other.
- *
- * The stamp and counter are used to distinguish all hits for a particular
- * (in_addr,pid) pair. The stamp is updated using r->request_time,
- * saving cpu cycles. The counter is never reset, and is used to permit up to
- * 64k requests in a single second by a single child.
- *
- * The 112-bits of unique_id_rec are encoded using the alphabet
- * [A-Za-z0-9@-], resulting in 19 bytes of printable characters. That is then
- * stuffed into the environment variable UNIQUE_ID so that it is available to
- * other modules. The alphabet choice differs from normal base64 encoding
- * [A-Za-z0-9+/] because + and / are special characters in URLs and we want to
- * make it easy to use UNIQUE_ID in URLs.
- *
- * Note that UNIQUE_ID should be considered an opaque token by other
- * applications. No attempt should be made to dissect its internal components.
- * It is an abstraction that may change in the future as the needs of this
- * module change.
- *
- * It is highly desirable that identifiers exist for "eternity". But future
- * needs (such as much faster webservers, moving to 64-bit pids, or moving to a
- * multithreaded server) may dictate a need to change the contents of
- * unique_id_rec. Such a future implementation should ensure that the first
- * field is still a time_t stamp. By doing that, it is possible for a site to
- * have a "flag second" in which they stop all of their old-format servers,
- * wait one entire second, and then start all of their new-servers. This
- * procedure will ensure that the new space of identifiers is completely unique
- * from the old space. (Since the first four unencoded bytes always differ.)
- */
-/*
- * Sun Jun 7 05:43:49 CEST 1998 -- Alvaro
- * More comments:
- * 1) The UUencoding prodecure is now done in a general way, avoiding the problems
- * with sizes and paddings that can arise depending on the architecture. Now the
- * offsets and sizes of the elements of the unique_id_rec structure are calculated
- * in unique_id_global_init; and then used to duplicate the structure without the
- * paddings that might exist. The multithreaded server fix should be now very easy:
- * just add a new "tid" field to the unique_id_rec structure, and increase by one
- * UNIQUE_ID_REC_MAX.
- * 2) unique_id_rec.stamp has been changed from "time_t" to "unsigned int", because
- * its size is 64bits on some platforms (linux/alpha), and this caused problems with
- * htonl/ntohl. Well, this shouldn't be a problem till year 2106.
- */
-
-static unsigned global_in_addr;
-
-static unique_id_rec cur_unique_id;
-
-/*
- * Number of elements in the structure unique_id_rec.
- */
-#define UNIQUE_ID_REC_MAX 5
-
-static unsigned short unique_id_rec_offset[UNIQUE_ID_REC_MAX],
- unique_id_rec_size[UNIQUE_ID_REC_MAX],
- unique_id_rec_total_size,
- unique_id_rec_size_uu;
-
-static void unique_id_global_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *main_server)
-{
-#ifndef MAXHOSTNAMELEN
-#define MAXHOSTNAMELEN 256
-#endif
- char str[MAXHOSTNAMELEN + 1];
- struct hostent *hent;
- apr_short_interval_time_t pause;
-
- /*
- * Calculate the sizes and offsets in cur_unique_id.
- */
- unique_id_rec_offset[0] = XtOffsetOf(unique_id_rec, stamp);
- unique_id_rec_size[0] = sizeof(cur_unique_id.stamp);
- unique_id_rec_offset[1] = XtOffsetOf(unique_id_rec, in_addr);
- unique_id_rec_size[1] = sizeof(cur_unique_id.in_addr);
- unique_id_rec_offset[2] = XtOffsetOf(unique_id_rec, pid);
- unique_id_rec_size[2] = sizeof(cur_unique_id.pid);
- unique_id_rec_offset[3] = XtOffsetOf(unique_id_rec, counter);
- unique_id_rec_size[3] = sizeof(cur_unique_id.counter);
- unique_id_rec_offset[4] = XtOffsetOf(unique_id_rec, thread_index);
- unique_id_rec_size[4] = sizeof(cur_unique_id.thread_index);
- unique_id_rec_total_size = unique_id_rec_size[0] + unique_id_rec_size[1] +
- unique_id_rec_size[2] + unique_id_rec_size[3] +
- unique_id_rec_size[4];
-
- /*
- * Calculate the size of the structure when encoded.
- */
- unique_id_rec_size_uu = (unique_id_rec_total_size*8+5)/6;
-
- /*
- * Now get the global in_addr. Note that it is not sufficient to use one
- * of the addresses from the main_server, since those aren't as likely to
- * be unique as the physical address of the machine
- */
- if (gethostname(str, sizeof(str) - 1) != 0) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, errno, main_server,
- "gethostname: mod_unique_id requires the hostname of the server");
- exit(1);
- }
- str[sizeof(str) - 1] = '\0';
-
- if ((hent = gethostbyname(str)) == NULL) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ALERT, h_errno, main_server,
- "mod_unique_id: unable to gethostbyname(\"%s\")", str);
- exit(1);
- }
-
- global_in_addr = ((struct in_addr *) hent->h_addr_list[0])->s_addr;
-
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, main_server,
- "mod_unique_id: using ip addr %s",
- inet_ntoa(*(struct in_addr *) hent->h_addr_list[0]));
-
- /*
- * If the server is pummelled with restart requests we could possibly end
- * up in a situation where we're starting again during the same second
- * that has been used in previous identifiers. Avoid that situation.
- *
- * In truth, for this to actually happen not only would it have to restart
- * in the same second, but it would have to somehow get the same pids as
- * one of the other servers that was running in that second. Which would
- * mean a 64k wraparound on pids ... not very likely at all.
- *
- * But protecting against it is relatively cheap. We just sleep into the
- * next second.
- */
- pause = (apr_short_interval_time_t)(1000000 - (apr_time_now() % APR_USEC_PER_SEC));
- apr_sleep(pause);
-}
-
-static void unique_id_child_init(apr_pool_t *p, server_rec *s)
-{
- pid_t pid;
- apr_time_t tv;
-
- /*
- * Note that we use the pid because it's possible that on the same
- * physical machine there are multiple servers (i.e. using Listen). But
- * it's guaranteed that none of them will share the same pids between
- * children.
- *
- * XXX: for multithread this needs to use a pid/tid combo and probably
- * needs to be expanded to 32 bits
- */
- pid = getpid();
- cur_unique_id.pid = pid;
-
- /*
- * Test our assumption that the pid is 32-bits. It's possible that
- * 64-bit machines will declare pid_t to be 64 bits but only use 32
- * of them. It would have been really nice to test this during
- * global_init ... but oh well.
- */
- if (cur_unique_id.pid != pid) {
- ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, 0, s,
- "oh no! pids are greater than 32-bits! I'm broken!");
- }
-
- cur_unique_id.in_addr = global_in_addr;
-
- /*
- * If we use 0 as the initial counter we have a little less protection
- * against restart problems, and a little less protection against a clock
- * going backwards in time.
- */
- tv = apr_time_now();
- /* Some systems have very low variance on the low end of their system
- * counter, defend against that.
- */
- cur_unique_id.counter = tv % APR_USEC_PER_SEC / 10;
-
- /*
- * We must always use network ordering for these bytes, so that
- * identifiers are comparable between machines of different byte
- * orderings. Note in_addr is already in network order.
- */
- cur_unique_id.pid = htonl(cur_unique_id.pid);
- cur_unique_id.counter = htons(cur_unique_id.counter);
-}
-
-/* NOTE: This is *NOT* the same encoding used by base64encode ... the last two
- * characters should be + and /. But those two characters have very special
- * meanings in URLs, and we want to make it easy to use identifiers in
- * URLs. So we replace them with @ and -.
- */
-static const char uuencoder[64] = {
- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
- 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
- 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
- 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '@', '-',
-};
-
-static int gen_unique_id(request_rec *r)
-{
- char *str;
- /*
- * Buffer padded with two final bytes, used to copy the unique_id_red
- * structure without the internal paddings that it could have.
- */
- unique_id_rec new_unique_id;
- struct {
- unique_id_rec foo;
- unsigned char pad[2];
- } paddedbuf;
- unsigned char *x,*y;
- unsigned short counter;
- const char *e;
- int i,j,k;
-
- /* copy the unique_id if this is an internal redirect (we're never
- * actually called for sub requests, so we don't need to test for
- * them) */
- if (r->prev && (e = apr_table_get(r->subprocess_env, "REDIRECT_UNIQUE_ID"))) {
- apr_table_setn(r->subprocess_env, "UNIQUE_ID", e);
- return DECLINED;
- }
-
- new_unique_id.in_addr = cur_unique_id.in_addr;
- new_unique_id.pid = cur_unique_id.pid;
- new_unique_id.counter = cur_unique_id.counter;
-
- new_unique_id.stamp = htonl((unsigned int)r->request_time);
- new_unique_id.thread_index = htonl((unsigned int)r->connection->id);
-
- /* we'll use a temporal buffer to avoid uuencoding the possible internal
- * paddings of the original structure */
- x = (unsigned char *) &paddedbuf;
- y = (unsigned char *) &new_unique_id;
- k = 0;
- for (i = 0; i < UNIQUE_ID_REC_MAX; i++) {
- y = ((unsigned char *) &new_unique_id) + unique_id_rec_offset[i];
- for (j = 0; j < unique_id_rec_size[i]; j++, k++) {
- x[k] = y[j];
- }
- }
- /*
- * We reset two more bytes just in case padding is needed for the uuencoding.
- */
- x[k++] = '\0';
- x[k++] = '\0';
-
- /* alloc str and do the uuencoding */
- str = (char *)apr_palloc(r->pool, unique_id_rec_size_uu + 1);
- k = 0;
- for (i = 0; i < unique_id_rec_total_size; i += 3) {
- y = x + i;
- str[k++] = uuencoder[y[0] >> 2];
- str[k++] = uuencoder[((y[0] & 0x03) << 4) | ((y[1] & 0xf0) >> 4)];
- if (k == unique_id_rec_size_uu) break;
- str[k++] = uuencoder[((y[1] & 0x0f) << 2) | ((y[2] & 0xc0) >> 6)];
- if (k == unique_id_rec_size_uu) break;
- str[k++] = uuencoder[y[2] & 0x3f];
- }
- str[k++] = '\0';
-
- /* set the environment variable */
- apr_table_setn(r->subprocess_env, "UNIQUE_ID", str);
-
- /* and increment the identifier for the next call */
-
- counter = ntohs(new_unique_id.counter) + 1;
- cur_unique_id.counter = htons(counter);
-
- return DECLINED;
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_post_config(unique_id_global_init, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_child_init(unique_id_child_init, NULL, NULL, APR_HOOK_MIDDLE);
- ap_hook_post_read_request(gen_unique_id, NULL, NULL, APR_HOOK_MIDDLE);
-}
-
-module AP_MODULE_DECLARE_DATA unique_id_module = {
- STANDARD20_MODULE_STUFF,
- NULL, /* dir config creater */
- NULL, /* dir merger --- default is to override */
- NULL, /* server config */
- NULL, /* merge server configs */
- NULL, /* command apr_table_t */
- register_hooks /* register hooks */
-};
diff --git a/modules/metadata/mod_unique_id.exp b/modules/metadata/mod_unique_id.exp
deleted file mode 100644
index 93000f1ee6..0000000000
--- a/modules/metadata/mod_unique_id.exp
+++ /dev/null
@@ -1 +0,0 @@
-unique_id_module
diff --git a/modules/metadata/mod_usertrack.c b/modules/metadata/mod_usertrack.c
deleted file mode 100644
index dfe39f0875..0000000000
--- a/modules/metadata/mod_usertrack.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/* User Tracking Module (Was mod_cookies.c)
- *
- * This Apache module is designed to track users paths through a site.
- * It uses the client-side state ("Cookie") protocol developed by Netscape.
- * It is known to work on Netscape browsers, Microsoft Internet
- * Explorer and others currently being developed.
- *
- * Each time a page is requested we look to see if the browser is sending
- * us a Cookie: header that we previously generated.
- *
- * If we don't find one then the user hasn't been to this site since
- * starting their browser or their browser doesn't support cookies. So
- * we generate a unique Cookie for the transaction and send it back to
- * the browser (via a "Set-Cookie" header)
- * Future requests from the same browser should keep the same Cookie line.
- *
- * By matching up all the requests with the same cookie you can
- * work out exactly what path a user took through your site. To log
- * the cookie use the " %{Cookie}n " directive in a custom access log;
- *
- * Example 1 : If you currently use the standard Log file format (CLF)
- * and use the command "TransferLog somefilename", add the line
- * LogFormat "%h %l %u %t \"%r\" %s %b %{Cookie}n"
- * to your config file.
- *
- * Example 2 : If you used to use the old "CookieLog" directive, you
- * can emulate it by adding the following command to your config file
- * CustomLog filename "%{Cookie}n \"%r\" %t"
- *
- * Notes:
- * 1. This code now logs the initial transaction (the one that created
- * the cookie to start with).
- * 2. This module has been designed to not interfere with other Cookies
- * your site may be using; just avoid sending out cookies with
- * the name "Apache=" or things will get confused.
- * 3. If you want you can modify the Set-Cookie line so that the Cookie
- * never expires. You would then get the same Cookie each time the
- * user revisits your site.
- *
- * Mark Cox, mark@ukweb.com, 6 July 95
- *
- * This file replaces mod_cookies.c
- */
-
-#include "apr.h"
-#include "apr_lib.h"
-#include "apr_strings.h"
-
-#define APR_WANT_STRFUNC
-#include "apr_want.h"
-
-#include "httpd.h"
-#include "http_config.h"
-#include "http_core.h"
-#include "http_request.h"
-
-
-module AP_MODULE_DECLARE_DATA usertrack_module;
-
-typedef struct {
- int always;
- int expires;
-} cookie_log_state;
-
-typedef struct {
- int enabled;
- char *cookie_name;
-} cookie_dir_rec;
-
-/* Make Cookie: Now we have to generate something that is going to be
- * pretty unique. We can base it on the pid, time, hostip */
-
-#define COOKIE_NAME "Apache"
-
-static void make_cookie(request_rec *r)
-{
- cookie_log_state *cls = ap_get_module_config(r->server->module_config,
- &usertrack_module);
- /* 1024 == hardcoded constant */
- char cookiebuf[1024];
- char *new_cookie;
- const char *rname = ap_get_remote_host(r->connection, r->per_dir_config,
- REMOTE_NAME, NULL);
- cookie_dir_rec *dcfg;
-
- dcfg = ap_get_module_config(r->per_dir_config, &usertrack_module);
-
- /* XXX: hmm, this should really tie in with mod_unique_id */
- apr_snprintf(cookiebuf, sizeof(cookiebuf), "%s.%qd", rname, apr_time_now());
-
- if (cls->expires) {
- apr_exploded_time_t tms;
-
- apr_explode_gmt(&tms, r->request_time + cls->expires * APR_USEC_PER_SEC);
-
- /* Cookie with date; as strftime '%a, %d-%h-%y %H:%M:%S GMT' */
- new_cookie = apr_psprintf(r->pool,
- "%s=%s; path=/; expires=%s, %.2d-%s-%.2d %.2d:%.2d:%.2d GMT",
- dcfg->cookie_name, cookiebuf, apr_day_snames[tms.tm_wday],
- tms.tm_mday, apr_month_snames[tms.tm_mon],
- tms.tm_year % 100,
- tms.tm_hour, tms.tm_min, tms.tm_sec);
- }
- else {
- new_cookie = apr_psprintf(r->pool, "%s=%s; path=/",
- dcfg->cookie_name, cookiebuf);
- }
-
- apr_table_setn(r->headers_out, "Set-Cookie", new_cookie);
- apr_table_setn(r->notes, "cookie", apr_pstrdup(r->pool, cookiebuf)); /* log first time */
- return;
-}
-
-static int spot_cookie(request_rec *r)
-{
- cookie_dir_rec *dcfg = ap_get_module_config(r->per_dir_config,
- &usertrack_module);
- const char *cookie;
- const char *value;
-
- if (!dcfg->enabled) {
- return DECLINED;
- }
-
- if ((cookie = apr_table_get(r->headers_in, "Cookie")))
- if ((value = ap_strstr_c(cookie, dcfg->cookie_name))) {
- char *cookiebuf, *cookieend;
-
- value += strlen(dcfg->cookie_name) + 1; /* Skip over the '=' */
- cookiebuf = apr_pstrdup(r->pool, value);
- cookieend = strchr(cookiebuf, ';');
- if (cookieend)
- *cookieend = '\0'; /* Ignore anything after a ; */
-
- /* Set the cookie in a note, for logging */
- apr_table_setn(r->notes, "cookie", cookiebuf);
-
- return DECLINED; /* There's already a cookie, no new one */
- }
- make_cookie(r);
- return OK; /* We set our cookie */
-}
-
-static void *make_cookie_log_state(apr_pool_t *p, server_rec *s)
-{
- cookie_log_state *cls =
- (cookie_log_state *) apr_palloc(p, sizeof(cookie_log_state));
-
- cls->expires = 0;
-
- return (void *) cls;
-}
-
-static void *make_cookie_dir(apr_pool_t *p, char *d)
-{
- cookie_dir_rec *dcfg;
-
- dcfg = (cookie_dir_rec *) apr_pcalloc(p, sizeof(cookie_dir_rec));
- dcfg->cookie_name = COOKIE_NAME;
- dcfg->enabled = 0;
- return dcfg;
-}
-
-static const char *set_cookie_enable(cmd_parms *cmd, void *mconfig, int arg)
-{
- cookie_dir_rec *dcfg = mconfig;
-
- dcfg->enabled = arg;
- return NULL;
-}
-
-static const char *set_cookie_exp(cmd_parms *parms, void *dummy, const char *arg)
-{
- cookie_log_state *cls = ap_get_module_config(parms->server->module_config,
- &usertrack_module);
- time_t factor, modifier = 0;
- time_t num = 0;
- char *word;
-
- /* The simple case first - all numbers (we assume) */
- if (apr_isdigit(arg[0]) && apr_isdigit(arg[strlen(arg) - 1])) {
- cls->expires = atol(arg);
- return NULL;
- }
-
- /*
- * The harder case - stolen from mod_expires
- *
- * CookieExpires "[plus] {<num> <type>}*"
- */
-
- word = ap_getword_conf(parms->pool, &arg);
- if (!strncasecmp(word, "plus", 1)) {
- word = ap_getword_conf(parms->pool, &arg);
- };
-
- /* {<num> <type>}* */
- while (word[0]) {
- /* <num> */
- if (apr_isdigit(word[0]))
- num = atoi(word);
- else
- return "bad expires code, numeric value expected.";
-
- /* <type> */
- word = ap_getword_conf(parms->pool, &arg);
- if (!word[0])
- return "bad expires code, missing <type>";
-
- factor = 0;
- if (!strncasecmp(word, "years", 1))
- factor = 60 * 60 * 24 * 365;
- else if (!strncasecmp(word, "months", 2))
- factor = 60 * 60 * 24 * 30;
- else if (!strncasecmp(word, "weeks", 1))
- factor = 60 * 60 * 24 * 7;
- else if (!strncasecmp(word, "days", 1))
- factor = 60 * 60 * 24;
- else if (!strncasecmp(word, "hours", 1))
- factor = 60 * 60;
- else if (!strncasecmp(word, "minutes", 2))
- factor = 60;
- else if (!strncasecmp(word, "seconds", 1))
- factor = 1;
- else
- return "bad expires code, unrecognized type";
-
- modifier = modifier + factor * num;
-
- /* next <num> */
- word = ap_getword_conf(parms->pool, &arg);
- }
-
- cls->expires = modifier;
-
- return NULL;
-}
-
-static const char *set_cookie_name(cmd_parms *cmd, void *mconfig, const char *name)
-{
- cookie_dir_rec *dcfg = (cookie_dir_rec *) mconfig;
-
- dcfg->cookie_name = apr_pstrdup(cmd->pool, name);
- return NULL;
-}
-
-static const command_rec cookie_log_cmds[] = {
- AP_INIT_TAKE1("CookieExpires", set_cookie_exp, NULL, RSRC_CONF,
- "an expiry date code"),
- AP_INIT_FLAG("CookieTracking", set_cookie_enable, NULL, OR_FILEINFO,
- "whether or not to enable cookies"),
- AP_INIT_TAKE1("CookieName", set_cookie_name, NULL, OR_FILEINFO,
- "name of the tracking cookie"),
- {NULL}
-};
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_fixups(spot_cookie,NULL,NULL,APR_HOOK_MIDDLE);
-}
-
-module AP_MODULE_DECLARE_DATA usertrack_module = {
- STANDARD20_MODULE_STUFF,
- make_cookie_dir, /* dir config creater */
- NULL, /* dir merger --- default is to override */
- make_cookie_log_state, /* server config */
- NULL, /* merge server configs */
- cookie_log_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
diff --git a/modules/metadata/mod_usertrack.dsp b/modules/metadata/mod_usertrack.dsp
deleted file mode 100644
index 47a70f1645..0000000000
--- a/modules/metadata/mod_usertrack.dsp
+++ /dev/null
@@ -1,95 +0,0 @@
-# Microsoft Developer Studio Project File - Name="mod_usertrack" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=mod_usertrack - Win32 Release
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "mod_usertrack.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_usertrack.mak" CFG="mod_usertrack - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_usertrack - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_usertrack - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "mod_usertrack - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\os\win32" /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_usertrack" /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "NDEBUG"
-# ADD RSC /l 0x809 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_usertrack.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_usertrack
-# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_usertrack.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_usertrack
-
-!ELSEIF "$(CFG)" == "mod_usertrack - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\..\include" /I "..\..\os\win32" /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_usertrack" /FD /c
-# ADD BASE MTL /nologo /D "_DEBUG" /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "_DEBUG"
-# ADD RSC /l 0x809 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /out:"Debug/mod_usertrack.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_usertrack
-# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /out:"Debug/mod_usertrack.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_usertrack
-
-!ENDIF
-
-# Begin Target
-
-# Name "mod_usertrack - Win32 Release"
-# Name "mod_usertrack - Win32 Debug"
-# Begin Source File
-
-SOURCE=.\mod_usertrack.c
-# End Source File
-# End Target
-# End Project
diff --git a/modules/metadata/mod_usertrack.exp b/modules/metadata/mod_usertrack.exp
deleted file mode 100644
index 234a5f759d..0000000000
--- a/modules/metadata/mod_usertrack.exp
+++ /dev/null
@@ -1 +0,0 @@
-usertrack_module
diff --git a/modules/metadata/mod_usertrack.mak b/modules/metadata/mod_usertrack.mak
deleted file mode 100644
index 342ea22ce1..0000000000
--- a/modules/metadata/mod_usertrack.mak
+++ /dev/null
@@ -1,325 +0,0 @@
-# Microsoft Developer Studio Generated NMAKE File, Based on mod_usertrack.dsp
-!IF "$(CFG)" == ""
-CFG=mod_usertrack - Win32 Release
-!MESSAGE No configuration specified. Defaulting to mod_usertrack - Win32\
- Release.
-!ENDIF
-
-!IF "$(CFG)" != "mod_usertrack - Win32 Release" && "$(CFG)" !=\
- "mod_usertrack - Win32 Debug"
-!MESSAGE Invalid configuration "$(CFG)" specified.
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_usertrack.mak" CFG="mod_usertrack - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_usertrack - Win32 Release" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_usertrack - Win32 Debug" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-!ERROR An invalid configuration is specified.
-!ENDIF
-
-!IF "$(OS)" == "Windows_NT"
-NULL=
-!ELSE
-NULL=nul
-!ENDIF
-
-!IF "$(CFG)" == "mod_usertrack - Win32 Release"
-
-OUTDIR=.\Release
-INTDIR=.\Release
-# Begin Custom Macros
-OutDir=.\Release
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_usertrack.so"
-
-!ELSE
-
-ALL : "libhttpd - Win32 Release" "libapr - Win32 Release"\
- "$(OUTDIR)\mod_usertrack.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libapr - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\mod_usertrack.idb"
- -@erase "$(INTDIR)\mod_usertrack.obj"
- -@erase "$(OUTDIR)\mod_usertrack.exp"
- -@erase "$(OUTDIR)\mod_usertrack.lib"
- -@erase "$(OUTDIR)\mod_usertrack.map"
- -@erase "$(OUTDIR)\mod_usertrack.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MD /W3 /O2 /I "..\..\include" /I "..\..\os\win32" /I\
- "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D\
- "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_usertrack" /FD /c
-CPP_OBJS=.\Release/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_usertrack.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no\
- /pdb:"$(OUTDIR)\mod_usertrack.pdb" /map:"$(INTDIR)\mod_usertrack.map"\
- /machine:I386 /out:"$(OUTDIR)\mod_usertrack.so"\
- /implib:"$(OUTDIR)\mod_usertrack.lib"\
- /base:@..\..\os\win32\BaseAddr.ref,mod_usertrack
-LINK32_OBJS= \
- "$(INTDIR)\mod_usertrack.obj" \
- "..\..\Release\libhttpd.lib" \
- "..\..\srclib\apr\Release\libapr.lib"
-
-"$(OUTDIR)\mod_usertrack.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ELSEIF "$(CFG)" == "mod_usertrack - Win32 Debug"
-
-OUTDIR=.\Debug
-INTDIR=.\Debug
-# Begin Custom Macros
-OutDir=.\Debug
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_usertrack.so"
-
-!ELSE
-
-ALL : "libhttpd - Win32 Debug" "libapr - Win32 Debug"\
- "$(OUTDIR)\mod_usertrack.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libapr - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\mod_usertrack.idb"
- -@erase "$(INTDIR)\mod_usertrack.obj"
- -@erase "$(OUTDIR)\mod_usertrack.exp"
- -@erase "$(OUTDIR)\mod_usertrack.lib"
- -@erase "$(OUTDIR)\mod_usertrack.map"
- -@erase "$(OUTDIR)\mod_usertrack.pdb"
- -@erase "$(OUTDIR)\mod_usertrack.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\include" /I "..\..\os\win32" /I\
- "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D\
- "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_usertrack" /FD /c
-CPP_OBJS=.\Debug/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_usertrack.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib /nologo /subsystem:windows /dll /incremental:no\
- /pdb:"$(OUTDIR)\mod_usertrack.pdb" /map:"$(INTDIR)\mod_usertrack.map" /debug\
- /machine:I386 /out:"$(OUTDIR)\mod_usertrack.so"\
- /implib:"$(OUTDIR)\mod_usertrack.lib"\
- /base:@..\..\os\win32\BaseAddr.ref,mod_usertrack
-LINK32_OBJS= \
- "$(INTDIR)\mod_usertrack.obj" \
- "..\..\Debug\libhttpd.lib" \
- "..\..\srclib\apr\Debug\libapr.lib"
-
-"$(OUTDIR)\mod_usertrack.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ENDIF
-
-
-!IF "$(CFG)" == "mod_usertrack - Win32 Release" || "$(CFG)" ==\
- "mod_usertrack - Win32 Debug"
-
-!IF "$(CFG)" == "mod_usertrack - Win32 Release"
-
-"libapr - Win32 Release" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F .\libapr.mak CFG="libapr - Win32 Release"
- cd "..\..\modules\metadata"
-
-"libapr - Win32 ReleaseCLEAN" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libapr.mak CFG="libapr - Win32 Release"\
- RECURSE=1
- cd "..\..\modules\metadata"
-
-!ELSEIF "$(CFG)" == "mod_usertrack - Win32 Debug"
-
-"libapr - Win32 Debug" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F .\libapr.mak CFG="libapr - Win32 Debug"
- cd "..\..\modules\metadata"
-
-"libapr - Win32 DebugCLEAN" :
- cd "..\..\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libapr.mak CFG="libapr - Win32 Debug"\
- RECURSE=1
- cd "..\..\modules\metadata"
-
-!ENDIF
-
-!IF "$(CFG)" == "mod_usertrack - Win32 Release"
-
-"libhttpd - Win32 Release" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) /F .\libhttpd.mak CFG="libhttpd - Win32 Release"
- cd ".\modules\metadata"
-
-"libhttpd - Win32 ReleaseCLEAN" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libhttpd.mak CFG="libhttpd - Win32 Release"\
- RECURSE=1
- cd ".\modules\metadata"
-
-!ELSEIF "$(CFG)" == "mod_usertrack - Win32 Debug"
-
-"libhttpd - Win32 Debug" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) /F .\libhttpd.mak CFG="libhttpd - Win32 Debug"
- cd ".\modules\metadata"
-
-"libhttpd - Win32 DebugCLEAN" :
- cd "..\.."
- $(MAKE) /$(MAKEFLAGS) CLEAN /F .\libhttpd.mak CFG="libhttpd - Win32 Debug"\
- RECURSE=1
- cd ".\modules\metadata"
-
-!ENDIF
-
-SOURCE=.\mod_usertrack.c
-DEP_CPP_MOD_U=\
- "..\..\include\ap_config.h"\
- "..\..\include\ap_mmn.h"\
- "..\..\include\ap_release.h"\
- "..\..\include\http_config.h"\
- "..\..\include\http_core.h"\
- "..\..\include\http_request.h"\
- "..\..\include\httpd.h"\
- "..\..\include\pcreposix.h"\
- "..\..\include\util_cfgtree.h"\
- "..\..\include\util_filter.h"\
- "..\..\include\util_uri.h"\
- "..\..\os\win32\os.h"\
- "..\..\srclib\apr-util\include\apr_buckets.h"\
- "..\..\srclib\apr-util\include\apr_hooks.h"\
- "..\..\srclib\apr-util\include\apr_ring.h"\
- "..\..\srclib\apr-util\include\apu.h"\
- "..\..\srclib\apr\include\apr.h"\
- "..\..\srclib\apr\include\apr_errno.h"\
- "..\..\srclib\apr\include\apr_file_info.h"\
- "..\..\srclib\apr\include\apr_file_io.h"\
- "..\..\srclib\apr\include\apr_general.h"\
- "..\..\srclib\apr\include\apr_lib.h"\
- "..\..\srclib\apr\include\apr_mmap.h"\
- "..\..\srclib\apr\include\apr_network_io.h"\
- "..\..\srclib\apr\include\apr_pools.h"\
- "..\..\srclib\apr\include\apr_strings.h"\
- "..\..\srclib\apr\include\apr_tables.h"\
- "..\..\srclib\apr\include\apr_time.h"\
- "..\..\srclib\apr\include\apr_user.h"\
- "..\..\srclib\apr\include\apr_want.h"\
-
-NODEP_CPP_MOD_U=\
- "..\..\include\ap_config_auto.h"\
-
-
-"$(INTDIR)\mod_usertrack.obj" : $(SOURCE) $(DEP_CPP_MOD_U) "$(INTDIR)"
-
-
-
-!ENDIF
-
diff --git a/modules/proxy/.cvsignore b/modules/proxy/.cvsignore
deleted file mode 100644
index efec0263f6..0000000000
--- a/modules/proxy/.cvsignore
+++ /dev/null
@@ -1,10 +0,0 @@
-Debug
-Release
-Makefile
-*.lo
-*.slo
-*.la
-*.so
-modules.mk
-.deps
-.libs
diff --git a/modules/proxy/.indent.pro b/modules/proxy/.indent.pro
deleted file mode 100644
index 20c2d83371..0000000000
--- a/modules/proxy/.indent.pro
+++ /dev/null
@@ -1,55 +0,0 @@
--i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1
--TBUFF
--TFILE
--TTRANS
--TUINT4
--T_trans
--Tallow_options_t
--Tapache_sfio
--Tarray_header
--Tbool_int
--Tbuf_area
--Tbuff_struct
--Tbuffy
--Tcmd_how
--Tcmd_parms
--Tcommand_rec
--Tcommand_struct
--Tconn_rec
--Tcore_dir_config
--Tcore_server_config
--Tdir_maker_func
--Tevent
--Tglobals_s
--Thandler_func
--Thandler_rec
--Tjoblist_s
--Tlisten_rec
--Tmerger_func
--Tmode_t
--Tmodule
--Tmodule_struct
--Tmutex
--Tn_long
--Tother_child_rec
--Toverrides_t
--Tparent_score
--Tpid_t
--Tpiped_log
--Tpool
--Trequest_rec
--Trequire_line
--Trlim_t
--Tscoreboard
--Tsemaphore
--Tserver_addr_rec
--Tserver_rec
--Tserver_rec_chain
--Tshort_score
--Ttable
--Ttable_entry
--Tthread
--Tu_wide_int
--Tvtime_t
--Twide_int
--Tproxy_server_conf
diff --git a/modules/proxy/Makefile.in b/modules/proxy/Makefile.in
deleted file mode 100644
index 7c5c149d85..0000000000
--- a/modules/proxy/Makefile.in
+++ /dev/null
@@ -1,3 +0,0 @@
-# a modules Makefile has no explicit targets -- they will be defined by
-# whatever modules are enabled. just grab special.mk to deal with this.
-include $(top_srcdir)/build/special.mk
diff --git a/modules/proxy/config.m4 b/modules/proxy/config.m4
deleted file mode 100644
index 325fca910f..0000000000
--- a/modules/proxy/config.m4
+++ /dev/null
@@ -1,24 +0,0 @@
-dnl modules enabled in this directory by default
-
-APACHE_MODPATH_INIT(proxy)
-
-if test "$enable_proxy" = "shared"; then
- proxy_mods_enable=shared
-elif test "$enable_proxy" = "yes"; then
- proxy_mods_enable=yes
-else
- proxy_mods_enable=no
-fi
-
-proxy_objs="mod_proxy.lo proxy_util.lo"
-APACHE_MODULE(proxy, Apache proxy module, $proxy_objs, , $proxy_mods_enable)
-
-proxy_connect_objs="proxy_connect.lo proxy_util.lo"
-APACHE_MODULE(proxy_connect, Apache proxy CONNECT module, $proxy_connect_objs, , $proxy_mods_enable)
-proxy_ftp_objs="proxy_ftp.lo proxy_util.lo"
-APACHE_MODULE(proxy_ftp, Apache proxy FTP module, $proxy_ftp_objs, , $proxy_mods_enable)
-proxy_http_objs="proxy_http.lo proxy_util.lo"
-APACHE_MODULE(proxy_http, Apache proxy HTTP module, $proxy_http_objs, , $proxy_mods_enable)
-
-
-APACHE_MODPATH_FINISH
diff --git a/modules/proxy/libproxy.exp b/modules/proxy/libproxy.exp
deleted file mode 100644
index a20f2378f5..0000000000
--- a/modules/proxy/libproxy.exp
+++ /dev/null
@@ -1 +0,0 @@
-proxy_module
diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c
deleted file mode 100644
index 0d6b28977f..0000000000
--- a/modules/proxy/mod_proxy.c
+++ /dev/null
@@ -1,768 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#define CORE_PRIVATE
-
-#include "mod_proxy.h"
-
-extern module AP_MODULE_DECLARE_DATA proxy_module;
-
-
-/*
- * A Web proxy module. Stages:
- *
- * translate_name: set filename to proxy:<URL>
- * type_checker: set type to PROXY_MAGIC_TYPE if filename begins proxy:
- * fix_ups: convert the URL stored in the filename to the
- * canonical form.
- * handler: handle proxy requests
- */
-
-/* -------------------------------------------------------------- */
-/* Translate the URL into a 'filename' */
-
-static int alias_match(const char *uri, const char *alias_fakename)
-{
- const char *end_fakename = alias_fakename + strlen(alias_fakename);
- const char *aliasp = alias_fakename, *urip = uri;
-
- while (aliasp < end_fakename) {
- if (*aliasp == '/') {
- /* any number of '/' in the alias matches any number in
- * the supplied URI, but there must be at least one...
- */
- if (*urip != '/')
- return 0;
-
- while (*aliasp == '/')
- ++aliasp;
- while (*urip == '/')
- ++urip;
- }
- else {
- /* Other characters are compared literally */
- if (*urip++ != *aliasp++)
- return 0;
- }
- }
-
- /* Check last alias path component matched all the way */
-
- if (aliasp[-1] != '/' && *urip != '\0' && *urip != '/')
- return 0;
-
- /* Return number of characters from URI which matched (may be
- * greater than length of alias, since we may have matched
- * doubled slashes)
- */
-
- return urip - uri;
-}
-
-/* Detect if an absoluteURI should be proxied or not. Note that we
- * have to do this during this phase because later phases are
- * "short-circuiting"... i.e. translate_names will end when the first
- * module returns OK. So for example, if the request is something like:
- *
- * GET http://othervhost/cgi-bin/printenv HTTP/1.0
- *
- * mod_alias will notice the /cgi-bin part and ScriptAlias it and
- * short-circuit the proxy... just because of the ordering in the
- * configuration file.
- */
-static int proxy_detect(request_rec *r)
-{
- void *sconf = r->server->module_config;
- proxy_server_conf *conf;
-
- conf = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
-
- if (conf->req && r->parsed_uri.scheme) {
- /* but it might be something vhosted */
- if (!(r->parsed_uri.hostname
- && !strcasecmp(r->parsed_uri.scheme, ap_http_method(r))
- && ap_matches_request_vhost(r, r->parsed_uri.hostname,
- r->parsed_uri.port_str ? r->parsed_uri.port : ap_default_port(r)))) {
- r->proxyreq = PROXYREQ_PROXY;
- r->uri = r->unparsed_uri;
- r->filename = apr_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 = PROXYREQ_PROXY;
- r->uri = r->unparsed_uri;
- r->filename = apr_pstrcat(r->pool, "proxy:", r->uri, NULL);
- r->handler = "proxy-server";
- }
- return DECLINED;
-}
-
-static int proxy_trans(request_rec *r)
-{
- void *sconf = r->server->module_config;
- proxy_server_conf *conf =
- (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
- int i, len;
- struct proxy_alias *ent = (struct proxy_alias *) conf->aliases->elts;
-
- if (r->proxyreq) {
- /* someone has already set up the proxy, it was possibly ourselves
- * in proxy_detect
- */
- return OK;
- }
-
- /* XXX: since r->uri has been manipulated already we're not really
- * compliant with RFC1945 at this point. But this probably isn't
- * an issue because this is a hybrid proxy/origin server.
- */
-
- for (i = 0; i < conf->aliases->nelts; i++) {
- len = alias_match(r->uri, ent[i].fake);
-
- if (len > 0) {
- r->filename = apr_pstrcat(r->pool, "proxy:", ent[i].real,
- r->uri + len, NULL);
- r->handler = "proxy-server";
- r->proxyreq = PROXYREQ_REVERSE;
- return OK;
- }
- }
- return DECLINED;
-}
-
-/* -------------------------------------------------------------- */
-/* Fixup the filename */
-
-/*
- * Canonicalise the URL
- */
-static int proxy_fixup(request_rec *r)
-{
- char *url, *p;
- int access_status;
-
- if (!r->proxyreq || strncmp(r->filename, "proxy:", 6) != 0)
- return DECLINED;
-
- url = &r->filename[6];
-
- /* canonicalise each specific scheme */
- if ((access_status = proxy_run_canon_handler(r, url))) {
- return access_status;
- }
-
- p = strchr(url, ':');
- if (p == NULL || p == url)
- return HTTP_BAD_REQUEST;
-
- return OK; /* otherwise; we've done the best we can */
-}
-
-/* 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 = apr_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 = apr_pstrcat(r->pool, r->parsed_uri.hostname,
- domain, NULL);
- nuri = ap_unparse_uri_components(r->pool,
- &r->parsed_uri,
- UNP_REVEALPASSWORD);
-
- apr_table_set(r->headers_out, "Location", nuri);
- ap_log_rerror(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, 0, r,
- "Domain missing: %s sent to %s%s%s", r->uri,
- ap_unparse_uri_components(r->pool, &r->parsed_uri,
- UNP_OMITUSERINFO),
- ref ? " from " : "", ref ? ref : "");
-
- return HTTP_MOVED_PERMANENTLY;
-}
-
-/* -------------------------------------------------------------- */
-/* Invoke handler */
-
-static int proxy_handler(request_rec *r)
-{
- char *url, *scheme, *p;
- const char *p2;
- void *sconf = r->server->module_config;
- proxy_server_conf *conf = (proxy_server_conf *)
- ap_get_module_config(sconf, &proxy_module);
- apr_array_header_t *proxies = conf->proxies;
- struct proxy_remote *ents = (struct proxy_remote *) proxies->elts;
- int i, rc, access_status;
- int direct_connect = 0;
- const char *str;
- long maxfwd;
-
- /* is this for us? */
- if (!r->proxyreq || strncmp(r->filename, "proxy:", 6) != 0)
- return DECLINED;
-
- /* handle max-forwards / OPTIONS / TRACE */
- if ((str = apr_table_get(r->headers_in, "Max-Forwards"))) {
- maxfwd = strtol(str, NULL, 10);
- if (maxfwd < 1) {
- switch (r->method_number) {
- case M_TRACE: {
- int access_status;
- r->proxyreq = PROXYREQ_NONE;
- if ((access_status = ap_send_http_trace(r)))
- ap_die(access_status, r);
- else
- ap_finalize_request_protocol(r);
- return OK;
- }
- case M_OPTIONS: {
- int access_status;
- r->proxyreq = PROXYREQ_NONE;
- if ((access_status = ap_send_http_options(r)))
- ap_die(access_status, r);
- else
- ap_finalize_request_protocol(r);
- return OK;
- }
- default: {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- "Max-Forwards has reached zero - proxy loop?");
- }
- }
- }
- maxfwd = (maxfwd > 0) ? maxfwd - 1 : 0;
- }
- else {
- /* set configured max-forwards */
- maxfwd = conf->maxfwd;
- }
- apr_table_setn(r->headers_in, "Max-Forwards",
- apr_psprintf(r->pool, "%ld", (maxfwd > 0) ? maxfwd : 0));
-
- if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)))
- return rc;
-
- url = r->filename + 6;
- p = strchr(url, ':');
- if (p == NULL)
- return HTTP_BAD_REQUEST;
-
- /* 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 = apr_pstrdup(r->pool, url);
- *p = ':';
-
- /* Check URI's destination host against NoProxy hosts */
- /* Bypass ProxyRemote server lookup if configured as NoProxy */
- /* we only know how to handle communication to a proxy via http */
- /*if (strcasecmp(scheme, "http") == 0) */
- {
- int ii;
- struct dirconn_entry *list = (struct dirconn_entry *) conf->dirconn->elts;
-
- for (direct_connect = ii = 0; ii < conf->dirconn->nelts && !direct_connect; ii++) {
- direct_connect = list[ii].matcher(&list[ii], r);
- }
-#if DEBUGGING
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, r,
- (direct_connect) ? "NoProxy for %s" : "UseProxy for %s",
- r->uri);
-#endif
- }
-
- /* firstly, try a proxy, unless a NoProxy directive is active */
- if (!direct_connect) {
- for (i = 0; i < proxies->nelts; i++) {
- p2 = ap_strchr_c(ents[i].scheme, ':'); /* is it a partial URL? */
- if (strcmp(ents[i].scheme, "*") == 0 ||
- (p2 == NULL && strcasecmp(scheme, ents[i].scheme) == 0) ||
- (p2 != NULL &&
- strncasecmp(url, ents[i].scheme, strlen(ents[i].scheme)) == 0)) {
-
- /* handle the scheme */
- ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server,
- "Trying to run scheme_handler against proxy");
- access_status = proxy_run_scheme_handler(r, conf, url, ents[i].hostname, ents[i].port);
-
- /* an error or success */
- if (access_status != DECLINED && access_status != HTTP_BAD_GATEWAY) {
- return access_status;
- }
- /* 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 */
- ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server,
- "Trying to run scheme_handler");
- access_status = proxy_run_scheme_handler(r, conf, url, NULL, 0);
- if (DECLINED == access_status) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server,
- "Neither CONNECT, HTTP or FTP for %s",
- r->uri);
- return HTTP_FORBIDDEN;
- }
- return access_status;
-}
-
-/* -------------------------------------------------------------- */
-/* Setup configurable data */
-
-static void * create_proxy_config(apr_pool_t *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->allowed_connect_ports = ap_make_array(p, 10, sizeof(int));
- ps->domain = NULL;
- ps->viaopt = via_off; /* initially backward compatible with 1.3.1 */
- ps->viaopt_set = 0; /* 0 means default */
- ps->req = 0;
- ps->req_set = 0;
- ps->recv_buffer_size = 0; /* this default was left unset for some reason */
- ps->recv_buffer_size_set = 0;
- ps->maxfwd = DEFAULT_MAX_FORWARDS;
- ps->maxfwd_set = 0;
-
- return ps;
-}
-
-static void * merge_proxy_config(apr_pool_t *p, void *basev, void *overridesv)
-{
- proxy_server_conf *ps = ap_pcalloc(p, sizeof(proxy_server_conf));
- proxy_server_conf *base = (proxy_server_conf *) basev;
- proxy_server_conf *overrides = (proxy_server_conf *) overridesv;
-
- ps->proxies = ap_append_arrays(p, base->proxies, overrides->proxies);
- ps->aliases = ap_append_arrays(p, base->aliases, overrides->aliases);
- ps->raliases = ap_append_arrays(p, base->raliases, overrides->raliases);
- ps->noproxies = ap_append_arrays(p, base->noproxies, overrides->noproxies);
- ps->dirconn = ap_append_arrays(p, base->dirconn, overrides->dirconn);
- ps->allowed_connect_ports = ap_append_arrays(p, base->allowed_connect_ports, overrides->allowed_connect_ports);
-
- ps->domain = (overrides->domain == NULL) ? base->domain : overrides->domain;
- ps->viaopt = (overrides->viaopt_set == 0) ? base->viaopt : overrides->viaopt;
- ps->req = (overrides->req_set == 0) ? base->req : overrides->req;
- ps->recv_buffer_size = (overrides->recv_buffer_size_set == 0) ? base->recv_buffer_size : overrides->recv_buffer_size;
- ps->maxfwd = (overrides->maxfwd_set == 0) ? base->maxfwd : overrides->maxfwd;
-
- return ps;
-}
-
-static const char *
- add_proxy(cmd_parms *cmd, void *dummy, const char *f1, const char *r1)
-{
- server_rec *s = cmd->server;
- proxy_server_conf *conf =
- (proxy_server_conf *) ap_get_module_config(s->module_config, &proxy_module);
- struct proxy_remote *new;
- char *p, *q;
- char *r, *f, *scheme;
- int port;
-
- r = apr_pstrdup(cmd->pool, r1);
- scheme = apr_pstrdup(cmd->pool, r1);
- f = apr_pstrdup(cmd->pool, f1);
- p = strchr(r, ':');
- if (p == NULL || p[1] != '/' || p[2] != '/' || p[3] == '\0') {
- return "ProxyRemote: Bad syntax for a remote proxy server";
- }
- else {
- scheme[p-r] = 0;
- }
- q = strchr(p + 3, ':');
- if (q != NULL) {
- if (sscanf(q + 1, "%u", &port) != 1 || port > 65535)
- return "ProxyRemote: Bad syntax for a remote proxy server (bad port number)";
- *q = '\0';
- }
- else
- port = -1;
- *p = '\0';
- if (strchr(f, ':') == NULL)
- ap_str_tolower(f); /* lowercase scheme */
- ap_str_tolower(p + 3); /* lowercase hostname */
-
- if (port == -1) {
- port = ap_default_port_for_scheme(scheme);
- }
-
- new = apr_array_push(conf->proxies);
- new->scheme = f;
- new->protocol = r;
- new->hostname = p + 3;
- new->port = port;
- return NULL;
-}
-
-static const char *
- add_pass(cmd_parms *cmd, void *dummy, const char *f, const char *r)
-{
- server_rec *s = cmd->server;
- proxy_server_conf *conf =
- (proxy_server_conf *) ap_get_module_config(s->module_config, &proxy_module);
- struct proxy_alias *new;
-
- new = apr_array_push(conf->aliases);
- new->fake = f;
- new->real = r;
- return NULL;
-}
-
-static const char *
- add_pass_reverse(cmd_parms *cmd, void *dummy, const char *f, const char *r)
-{
- server_rec *s = cmd->server;
- proxy_server_conf *conf;
- struct proxy_alias *new;
-
- conf = (proxy_server_conf *)ap_get_module_config(s->module_config,
- &proxy_module);
- new = apr_array_push(conf->raliases);
- new->fake = f;
- new->real = r;
- return NULL;
-}
-
-static const char *
- set_proxy_exclude(cmd_parms *parms, void *dummy, const char *arg)
-{
- server_rec *s = parms->server;
- proxy_server_conf *conf =
- ap_get_module_config(s->module_config, &proxy_module);
- struct noproxy_entry *new;
- struct noproxy_entry *list = (struct noproxy_entry *) conf->noproxies->elts;
- struct apr_sockaddr_t *addr;
- int found = 0;
- int i;
-
- /* Don't duplicate entries */
- for (i = 0; i < conf->noproxies->nelts; i++) {
- if (apr_strnatcasecmp(arg, list[i].name) == 0) { /* ignore case for host names */
- found = 1;
- }
- }
-
- if (!found) {
- new = apr_array_push(conf->noproxies);
- new->name = arg;
- if (APR_SUCCESS == apr_sockaddr_info_get(&addr, new->name, APR_UNSPEC, 0, 0, parms->pool)) {
- new->addr = addr;
- }
- else {
- new->addr = NULL;
- }
- }
- return NULL;
-}
-
-/*
- * Set the ports CONNECT can use
- */
-static const char *
- set_allowed_ports(cmd_parms *parms, void *dummy, const char *arg)
-{
- server_rec *s = parms->server;
- proxy_server_conf *conf =
- ap_get_module_config(s->module_config, &proxy_module);
- int *New;
-
- if (!apr_isdigit(arg[0]))
- return "AllowCONNECT: port number must be numeric";
-
- New = apr_array_push(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, const 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 = apr_array_push(conf->dirconn);
- New->name = apr_pstrdup(parms->pool, arg);
- New->hostentry = NULL;
-
- if (ap_proxy_is_ipaddr(New, parms->pool)) {
-#if DEBUGGING
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Parsed addr %s", inet_ntoa(New->addr));
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Parsed mask %s", inet_ntoa(New->mask));
-#endif
- }
- else if (ap_proxy_is_domainname(New, parms->pool)) {
- ap_str_tolower(New->name);
-#if DEBUGGING
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Parsed domain %s", New->name);
-#endif
- }
- else if (ap_proxy_is_hostname(New, parms->pool)) {
- ap_str_tolower(New->name);
-#if DEBUGGING
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Parsed host %s", New->name);
-#endif
- }
- else {
- ap_proxy_is_word(New, parms->pool);
-#if DEBUGGING
- fprintf(stderr, "Parsed word %s\n", New->name);
-#endif
- }
- }
- return NULL;
-}
-
-static const char *
- set_proxy_domain(cmd_parms *parms, void *dummy, const char *arg)
-{
- proxy_server_conf *psf =
- ap_get_module_config(parms->server->module_config, &proxy_module);
-
- if (arg[0] != '.')
- return "ProxyDomain: domain name must start with a dot.";
-
- psf->domain = arg;
- return NULL;
-}
-
-static const char *
- set_proxy_req(cmd_parms *parms, void *dummy, int flag)
-{
- proxy_server_conf *psf =
- ap_get_module_config(parms->server->module_config, &proxy_module);
-
- psf->req = flag;
- psf->req_set = 1;
- return NULL;
-}
-
-static const char *
- set_recv_buffer_size(cmd_parms *parms, void *dummy, const char *arg)
-{
- proxy_server_conf *psf =
- ap_get_module_config(parms->server->module_config, &proxy_module);
- int s = atoi(arg);
- if (s < 512 && s != 0) {
- return "ProxyReceiveBufferSize must be >= 512 bytes, or 0 for system default.";
- }
-
- psf->recv_buffer_size = s;
- psf->recv_buffer_size_set = 1;
- return NULL;
-}
-
-static const char *
- set_max_forwards(cmd_parms *parms, void *dummy, const char *arg)
-{
- proxy_server_conf *psf =
- ap_get_module_config(parms->server->module_config, &proxy_module);
- long s = atol(arg);
- if (s < 0) {
- return "ProxyMaxForwards must be greater or equal to zero..";
- }
-
- psf->maxfwd = s;
- psf->maxfwd_set = 1;
- return NULL;
-}
-
-static const char*
- set_via_opt(cmd_parms *parms, void *dummy, const char *arg)
-{
- proxy_server_conf *psf =
- ap_get_module_config(parms->server->module_config, &proxy_module);
-
- if (strcasecmp(arg, "Off") == 0)
- psf->viaopt = via_off;
- else if (strcasecmp(arg, "On") == 0)
- psf->viaopt = via_on;
- else if (strcasecmp(arg, "Block") == 0)
- psf->viaopt = via_block;
- else if (strcasecmp(arg, "Full") == 0)
- psf->viaopt = via_full;
- else {
- return "ProxyVia must be one of: "
- "off | on | full | block";
- }
-
- psf->viaopt_set = 1;
- return NULL;
-}
-
-static const command_rec proxy_cmds[] =
-{
- AP_INIT_FLAG("ProxyRequests", set_proxy_req, NULL, RSRC_CONF,
- "on if the true proxy requests should be accepted"),
- AP_INIT_TAKE2("ProxyRemote", add_proxy, NULL, RSRC_CONF,
- "a scheme, partial URL or '*' and a proxy server"),
- AP_INIT_TAKE2("ProxyPass", add_pass, NULL, RSRC_CONF,
- "a virtual path and a URL"),
- AP_INIT_TAKE2("ProxyPassReverse", add_pass_reverse, NULL, RSRC_CONF,
- "a virtual path and a URL for reverse proxy behaviour"),
- AP_INIT_ITERATE("ProxyBlock", set_proxy_exclude, NULL, RSRC_CONF,
- "A list of names, hosts or domains to which the proxy will not connect"),
- AP_INIT_TAKE1("ProxyReceiveBufferSize", set_recv_buffer_size, NULL, RSRC_CONF,
- "Receive buffer size for outgoing HTTP and FTP connections in bytes"),
- AP_INIT_TAKE1("ProxyMaxForwards", set_max_forwards, NULL, RSRC_CONF,
- "The maximum number of proxies a request may be forwarded through."),
- AP_INIT_ITERATE("NoProxy", set_proxy_dirconn, NULL, RSRC_CONF,
- "A list of domains, hosts, or subnets to which the proxy will connect directly"),
- AP_INIT_TAKE1("ProxyDomain", set_proxy_domain, NULL, RSRC_CONF,
- "The default intranet domain name (in absence of a domain in the URL)"),
- AP_INIT_ITERATE("AllowCONNECT", set_allowed_ports, NULL, RSRC_CONF,
- "A list of ports which CONNECT may connect to"),
- AP_INIT_TAKE1("ProxyVia", set_via_opt, NULL, RSRC_CONF,
- "Configure Via: proxy header header to one of: on | off | block | full"),
- {NULL}
-};
-
-static void register_hooks(apr_pool_t *p)
-{
- /* handler */
- ap_hook_handler(proxy_handler, NULL, NULL, APR_HOOK_FIRST);
- /* filename-to-URI translation */
- ap_hook_translate_name(proxy_trans, NULL, NULL, APR_HOOK_FIRST);
- /* fixups */
- ap_hook_fixups(proxy_fixup, NULL, NULL, APR_HOOK_FIRST);
- /* post read_request handling */
- ap_hook_post_read_request(proxy_detect, NULL, NULL, APR_HOOK_FIRST);
-}
-
-module AP_MODULE_DECLARE_DATA proxy_module =
-{
- STANDARD20_MODULE_STUFF,
- NULL, /* create per-directory config structure */
- NULL, /* merge per-directory config structures */
- create_proxy_config, /* create per-server config structure */
- merge_proxy_config, /* merge per-server config structures */
- proxy_cmds, /* command table */
- register_hooks
-};
-
-APR_HOOK_STRUCT(
- APR_HOOK_LINK(scheme_handler)
- APR_HOOK_LINK(canon_handler)
-)
-
-APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(proxy, PROXY, int, scheme_handler,
- (request_rec *r, proxy_server_conf *conf,
- char *url, const char *proxyhost,
- apr_port_t proxyport),(r,conf,url,
- proxyhost,proxyport),DECLINED)
-APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(proxy, PROXY, int, canon_handler,
- (request_rec *r, char *url),(r,
- url),DECLINED)
diff --git a/modules/proxy/mod_proxy.dsp b/modules/proxy/mod_proxy.dsp
deleted file mode 100644
index d57baaa0e5..0000000000
--- a/modules/proxy/mod_proxy.dsp
+++ /dev/null
@@ -1,123 +0,0 @@
-# Microsoft Developer Studio Project File - Name="mod_proxy" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
-
-CFG=mod_proxy - Win32 Release
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "mod_proxy.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_proxy.mak" CFG="mod_proxy - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_proxy - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_proxy - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "mod_proxy - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MD /W3 /O2 /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /I "..\..\include" /I "..\..\os\win32" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Release\mod_proxy" /FD /c
-# ADD BASE MTL /nologo /D "NDEBUG" /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "NDEBUG"
-# ADD RSC /l 0x809 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_proxy.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_proxy
-# ADD LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /map /out:"Release/mod_proxy.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_proxy
-
-!ELSEIF "$(CFG)" == "mod_proxy - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "Debug"
-# PROP BASE Intermediate_Dir "Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "Debug"
-# PROP Intermediate_Dir "Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /MDd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
-# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\..\srclib\apr\include" /I "../../srclib/apr-util/include" /I "..\..\include" /I "..\..\os\win32" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fd"Debug\mod_proxy" /FD /c
-# ADD BASE MTL /nologo /D "_DEBUG" /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x809 /d "_DEBUG"
-# ADD RSC /l 0x809 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /out:"Debug/mod_proxy.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_proxy
-# ADD LINK32 kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /out:"Debug/mod_proxy.so" /machine:I386 /base:@..\..\os\win32\BaseAddr.ref,mod_proxy
-
-!ENDIF
-
-# Begin Target
-
-# Name "mod_proxy - Win32 Release"
-# Name "mod_proxy - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
-# Begin Source File
-
-SOURCE=.\mod_proxy.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\proxy_connect.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\proxy_ftp.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\proxy_http.c
-# End Source File
-# Begin Source File
-
-SOURCE=.\proxy_util.c
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
-# Begin Source File
-
-SOURCE=.\mod_proxy.h
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h
deleted file mode 100644
index c614605a36..0000000000
--- a/modules/proxy/mod_proxy.h
+++ /dev/null
@@ -1,259 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#ifndef MOD_PROXY_H
-#define MOD_PROXY_H
-
-/*
- * Main include file for the Apache proxy
- */
-
-/*
-
- Also note numerous FIXMEs and CHECKMEs which should be eliminated.
-
- This code is once again experimental!
-
- Things to do:
-
- 1. Make it completely work (for FTP too)
-
- 2. HTTP/1.1
-
- Chuck Murcko <chuck@topsail.org> 02-06-01
-
- */
-
-#define CORE_PRIVATE
-
-#include "apr_hooks.h"
-#include "apr.h"
-#include "apr_compat.h"
-#include "apr_lib.h"
-#include "apr_strings.h"
-#include "apr_buckets.h"
-#include "apr_md5.h"
-#include "apr_pools.h"
-#include "apr_strings.h"
-
-#include "httpd.h"
-#include "http_config.h"
-#include "ap_config.h"
-#include "http_core.h"
-#include "http_protocol.h"
-#include "http_request.h"
-#include "http_vhost.h"
-#include "http_main.h"
-#include "http_log.h"
-#include "http_connection.h"
-#include "util_filter.h"
-#include "util_date.h"
-#include "util_uri.h"
-#include "mod_core.h"
-
-
-#if APR_HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#if APR_HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#if APR_HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#if APR_HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-
-/* for proxy_canonenc() */
-enum enctype {
- enc_path, enc_search, enc_user, enc_fpath, enc_parm
-};
-
-#if APR_CHARSET_EBCDIC
-#define CRLF "\r\n"
-#else /*APR_CHARSET_EBCDIC*/
-#define CRLF "\015\012"
-#endif /*APR_CHARSET_EBCDIC*/
-
-/* default Max-Forwards header setting */
-#define DEFAULT_MAX_FORWARDS 10
-
-/* static information about a remote proxy */
-struct proxy_remote {
- const char *scheme; /* the schemes handled by this proxy, or '*' */
- const char *protocol; /* the scheme used to talk to this proxy */
- const char *hostname; /* the hostname of this proxy */
- int port; /* the port for this proxy */
-};
-
-struct proxy_alias {
- const char *real;
- const 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 {
- const char *name;
- struct apr_sockaddr_t *addr;
-};
-
-typedef struct {
- apr_array_header_t *proxies;
- apr_array_header_t *aliases;
- apr_array_header_t *raliases;
- apr_array_header_t *noproxies;
- apr_array_header_t *dirconn;
- apr_array_header_t *allowed_connect_ports;
- const char *domain; /* domain name to use in absence of a domain name in the request */
- int req; /* true if proxy requests are enabled */
- char req_set;
- enum {
- via_off,
- via_on,
- via_block,
- via_full
- } viaopt; /* how to deal with proxy Via: headers */
- char viaopt_set;
- size_t recv_buffer_size;
- char recv_buffer_size_set;
- long maxfwd;
- char maxfwd_set;
-} proxy_server_conf;
-
-struct per_thread_data {
- struct hostent hpbuf;
- u_long ipaddr;
- char *charpbuf[2];
-};
-
-typedef struct {
- conn_rec *connection;
- char *hostname;
- apr_port_t port;
-} proxy_conn_rec;
-
-typedef struct {
- float cache_completion; /* completion percentage */
- int content_length; /* length of the content */
-} proxy_completion;
-
-
-/* hooks */
-
-/* Create a set of PROXY_DECLARE(type), PROXY_DECLARE_NONSTD(type) and
- * PROXY_DECLARE_DATA with appropriate export and import tags for the platform
- */
-#if !defined(WIN32)
-#define PROXY_DECLARE(type) type
-#define PROXY_DECLARE_NONSTD(type) type
-#define PROXY_DECLARE_DATA
-#elif defined(PROXY_DECLARE_STATIC)
-#define PROXY_DECLARE(type) type __stdcall
-#define PROXY_DECLARE_NONSTD(type) type
-#define PROXY_DECLARE_DATA
-#elif defined(PROXY_DECLARE_EXPORT)
-#define PROXY_DECLARE(type) __declspec(dllexport) type __stdcall
-#define PROXY_DECLARE_NONSTD(type) __declspec(dllexport) type
-#define PROXY_DECLARE_DATA __declspec(dllexport)
-#else
-#define PROXY_DECLARE(type) __declspec(dllimport) type __stdcall
-#define PROXY_DECLARE_NONSTD(type) __declspec(dllimport) type
-#define PROXY_DECLARE_DATA __declspec(dllimport)
-#endif
-
-APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, scheme_handler, (request_rec *r,
- proxy_server_conf *conf, char *url,
- const char *proxyhost, apr_port_t proxyport))
-APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, canon_handler, (request_rec *r,
- char *url))
-
-/* proxy_util.c */
-
-request_rec *make_fake_req(conn_rec *c, request_rec *r);
-int ap_proxy_hex2c(const char *x);
-void ap_proxy_c2hex(int ch, char *x);
-char *ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t,
- int isenc);
-char *ap_proxy_canon_netloc(apr_pool_t *p, char **const urlp, char **userp,
- char **passwordp, char **hostp, apr_port_t *port);
-const char *ap_proxy_date_canon(apr_pool_t *p, const char *x);
-apr_table_t *ap_proxy_read_headers(request_rec *r, request_rec *rp, char *buffer, int size, conn_rec *c);
-int ap_proxy_liststr(const char *list, const char *val);
-char *ap_proxy_removestr(apr_pool_t *pool, const char *list, const char *val);
-int ap_proxy_hex2sec(const char *x);
-void ap_proxy_sec2hex(int t, char *y);
-const char *ap_proxy_host2addr(const char *host, struct hostent *reqhp);
-int ap_proxyerror(request_rec *r, int statuscode, const char *message);
-int ap_proxy_is_ipaddr(struct dirconn_entry *This, apr_pool_t *p);
-int ap_proxy_is_domainname(struct dirconn_entry *This, apr_pool_t *p);
-int ap_proxy_is_hostname(struct dirconn_entry *This, apr_pool_t *p);
-int ap_proxy_is_word(struct dirconn_entry *This, apr_pool_t *p);
-int ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf, apr_sockaddr_t *uri_addr);
-int ap_proxy_pre_http_connection(conn_rec *c, request_rec *r);
-apr_status_t ap_proxy_string_read(conn_rec *c, apr_bucket_brigade *bb, char *buff, size_t bufflen, int *eos);
-void ap_proxy_reset_output_filters(conn_rec *c);
-
-
-#endif /*MOD_PROXY_H*/
diff --git a/modules/proxy/mod_proxy.mak b/modules/proxy/mod_proxy.mak
deleted file mode 100644
index 3d13f3d1ac..0000000000
--- a/modules/proxy/mod_proxy.mak
+++ /dev/null
@@ -1,573 +0,0 @@
-# Microsoft Developer Studio Generated NMAKE File, Based on mod_proxy.dsp
-!IF "$(CFG)" == ""
-CFG=mod_proxy - Win32 Release
-!MESSAGE No configuration specified. Defaulting to mod_proxy - Win32 Release.
-!ENDIF
-
-!IF "$(CFG)" != "mod_proxy - Win32 Release" && "$(CFG)" !=\
- "mod_proxy - Win32 Debug"
-!MESSAGE Invalid configuration "$(CFG)" specified.
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "mod_proxy.mak" CFG="mod_proxy - Win32 Release"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "mod_proxy - Win32 Release" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE "mod_proxy - Win32 Debug" (based on\
- "Win32 (x86) Dynamic-Link Library")
-!MESSAGE
-!ERROR An invalid configuration is specified.
-!ENDIF
-
-!IF "$(OS)" == "Windows_NT"
-NULL=
-!ELSE
-NULL=nul
-!ENDIF
-
-!IF "$(CFG)" == "mod_proxy - Win32 Release"
-
-OUTDIR=.\Release
-INTDIR=.\Release
-# Begin Custom Macros
-OutDir=.\Release
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_proxy.so"
-
-!ELSE
-
-ALL : "libaprutil - Win32 Release" "libhttpd - Win32 Release"\
- "libapr - Win32 Release" "$(OUTDIR)\mod_proxy.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libapr - Win32 ReleaseCLEAN" "libhttpd - Win32 ReleaseCLEAN"\
- "libaprutil - Win32 ReleaseCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\mod_proxy.idb"
- -@erase "$(INTDIR)\mod_proxy.obj"
- -@erase "$(INTDIR)\proxy_connect.obj"
- -@erase "$(INTDIR)\proxy_ftp.obj"
- -@erase "$(INTDIR)\proxy_http.obj"
- -@erase "$(INTDIR)\proxy_util.obj"
- -@erase "$(OUTDIR)\mod_proxy.exp"
- -@erase "$(OUTDIR)\mod_proxy.lib"
- -@erase "$(OUTDIR)\mod_proxy.map"
- -@erase "$(OUTDIR)\mod_proxy.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MD /W3 /O2 /I "..\..\srclib\apr\include" /I\
- "../../srclib/apr-util/include" /I "..\..\include" /I "..\..\os\win32" /D\
- "NDEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_proxy" /FD\
- /c
-CPP_OBJS=.\Release/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_proxy.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows\
- /dll /incremental:no /pdb:"$(OUTDIR)\mod_proxy.pdb"\
- /map:"$(INTDIR)\mod_proxy.map" /machine:I386 /out:"$(OUTDIR)\mod_proxy.so"\
- /implib:"$(OUTDIR)\mod_proxy.lib" /base:@..\..\os\win32\BaseAddr.ref,mod_proxy
-LINK32_OBJS= \
- "$(INTDIR)\mod_proxy.obj" \
- "$(INTDIR)\proxy_connect.obj" \
- "$(INTDIR)\proxy_ftp.obj" \
- "$(INTDIR)\proxy_http.obj" \
- "$(INTDIR)\proxy_util.obj" \
- "..\..\Release\libhttpd.lib" \
- "..\..\srclib\apr-util\Release\libaprutil.lib" \
- "..\..\srclib\apr\Release\libapr.lib"
-
-"$(OUTDIR)\mod_proxy.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ELSEIF "$(CFG)" == "mod_proxy - Win32 Debug"
-
-OUTDIR=.\Debug
-INTDIR=.\Debug
-# Begin Custom Macros
-OutDir=.\Debug
-# End Custom Macros
-
-!IF "$(RECURSE)" == "0"
-
-ALL : "$(OUTDIR)\mod_proxy.so"
-
-!ELSE
-
-ALL : "libaprutil - Win32 Debug" "libhttpd - Win32 Debug"\
- "libapr - Win32 Debug" "$(OUTDIR)\mod_proxy.so"
-
-!ENDIF
-
-!IF "$(RECURSE)" == "1"
-CLEAN :"libapr - Win32 DebugCLEAN" "libhttpd - Win32 DebugCLEAN"\
- "libaprutil - Win32 DebugCLEAN"
-!ELSE
-CLEAN :
-!ENDIF
- -@erase "$(INTDIR)\mod_proxy.idb"
- -@erase "$(INTDIR)\mod_proxy.obj"
- -@erase "$(INTDIR)\proxy_connect.obj"
- -@erase "$(INTDIR)\proxy_ftp.obj"
- -@erase "$(INTDIR)\proxy_http.obj"
- -@erase "$(INTDIR)\proxy_util.obj"
- -@erase "$(OUTDIR)\mod_proxy.exp"
- -@erase "$(OUTDIR)\mod_proxy.lib"
- -@erase "$(OUTDIR)\mod_proxy.map"
- -@erase "$(OUTDIR)\mod_proxy.pdb"
- -@erase "$(OUTDIR)\mod_proxy.so"
-
-"$(OUTDIR)" :
- if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
-
-CPP=cl.exe
-CPP_PROJ=/nologo /MDd /W3 /GX /Zi /Od /I "..\..\srclib\apr\include" /I\
- "../../srclib/apr-util/include" /I "..\..\include" /I "..\..\os\win32" /D\
- "_DEBUG" /D "WIN32" /D "_WINDOWS" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\mod_proxy" /FD\
- /c
-CPP_OBJS=.\Debug/
-CPP_SBRS=.
-
-.c{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_OBJS)}.obj::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.c{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cpp{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-.cxx{$(CPP_SBRS)}.sbr::
- $(CPP) @<<
- $(CPP_PROJ) $<
-<<
-
-MTL=midl.exe
-MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
-RSC=rc.exe
-BSC32=bscmake.exe
-BSC32_FLAGS=/nologo /o"$(OUTDIR)\mod_proxy.bsc"
-BSC32_SBRS= \
-
-LINK32=link.exe
-LINK32_FLAGS=kernel32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows\
- /dll /incremental:no /pdb:"$(OUTDIR)\mod_proxy.pdb"\
- /map:"$(INTDIR)\mod_proxy.map" /debug /machine:I386\
- /out:"$(OUTDIR)\mod_proxy.so" /implib:"$(OUTDIR)\mod_proxy.lib"\
- /base:@..\..\os\win32\BaseAddr.ref,mod_proxy
-LINK32_OBJS= \
- "$(INTDIR)\mod_proxy.obj" \
- "$(INTDIR)\proxy_connect.obj" \
- "$(INTDIR)\proxy_ftp.obj" \
- "$(INTDIR)\proxy_http.obj" \
- "$(INTDIR)\proxy_util.obj" \
- "..\..\Debug\libhttpd.lib" \
- "..\..\srclib\apr-util\Debug\libaprutil.lib" \
- "..\..\srclib\apr\Debug\libapr.lib"
-
-"$(OUTDIR)\mod_proxy.so" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
- $(LINK32) @<<
- $(LINK32_FLAGS) $(LINK32_OBJS)
-<<
-
-!ENDIF
-
-
-!IF "$(CFG)" == "mod_proxy - Win32 Release" || "$(CFG)" ==\
- "mod_proxy - Win32 Debug"
-SOURCE=.\mod_proxy.c
-DEP_CPP_MOD_P=\
- "..\..\include\ap_config.h"\
- "..\..\include\ap_mmn.h"\
- "..\..\include\http_config.h"\
- "..\..\include\http_log.h"\
- "..\..\include\http_protocol.h"\
- "..\..\include\http_request.h"\
- "..\..\include\http_vhost.h"\
- "..\..\include\httpd.h"\
- "..\..\include\pcreposix.h"\
- "..\..\include\util_cfgtree.h"\
- "..\..\include\util_date.h"\
- "..\..\include\util_filter.h"\
- "..\..\include\util_uri.h"\
- "..\..\os\win32\os.h"\
- "..\..\srclib\apr-util\include\ap_buckets.h"\
- "..\..\srclib\apr-util\include\ap_hooks.h"\
- "..\..\srclib\apr-util\include\ap_ring.h"\
- "..\..\srclib\apr\include\apr.h"\
- "..\..\srclib\apr\include\apr_compat.h"\
- "..\..\srclib\apr\include\apr_dso.h"\
- "..\..\srclib\apr\include\apr_errno.h"\
- "..\..\srclib\apr\include\apr_file_io.h"\
- "..\..\srclib\apr\include\apr_general.h"\
- "..\..\srclib\apr\include\apr_lib.h"\
- "..\..\srclib\apr\include\apr_lock.h"\
- "..\..\srclib\apr\include\apr_mmap.h"\
- "..\..\srclib\apr\include\apr_network_io.h"\
- "..\..\srclib\apr\include\apr_pools.h"\
- "..\..\srclib\apr\include\apr_portable.h"\
- "..\..\srclib\apr\include\apr_strings.h"\
- "..\..\srclib\apr\include\apr_tables.h"\
- "..\..\srclib\apr\include\apr_thread_proc.h"\
- "..\..\srclib\apr\include\apr_time.h"\
- "..\..\srclib\apr\network_io\os2\os2nerrno.h"\
- ".\mod_proxy.h"\
-
-NODEP_CPP_MOD_P=\
- "..\..\include\ap_config_auto.h"\
- "..\..\include\ap_config_path.h"\
- ".\ap_cache.h"\
- ".\buff.h"\
-
-
-"$(INTDIR)\mod_proxy.obj" : $(SOURCE) $(DEP_CPP_MOD_P) "$(INTDIR)"
-
-
-SOURCE=.\proxy_connect.c
-DEP_CPP_PROXY=\
- "..\..\include\ap_config.h"\
- "..\..\include\ap_mmn.h"\
- "..\..\include\http_config.h"\
- "..\..\include\http_log.h"\
- "..\..\include\http_main.h"\
- "..\..\include\http_protocol.h"\
- "..\..\include\httpd.h"\
- "..\..\include\pcreposix.h"\
- "..\..\include\util_cfgtree.h"\
- "..\..\include\util_filter.h"\
- "..\..\include\util_uri.h"\
- "..\..\os\win32\os.h"\
- "..\..\srclib\apr-util\include\ap_buckets.h"\
- "..\..\srclib\apr-util\include\ap_hooks.h"\
- "..\..\srclib\apr-util\include\ap_ring.h"\
- "..\..\srclib\apr\include\apr.h"\
- "..\..\srclib\apr\include\apr_compat.h"\
- "..\..\srclib\apr\include\apr_dso.h"\
- "..\..\srclib\apr\include\apr_errno.h"\
- "..\..\srclib\apr\include\apr_file_io.h"\
- "..\..\srclib\apr\include\apr_general.h"\
- "..\..\srclib\apr\include\apr_lib.h"\
- "..\..\srclib\apr\include\apr_lock.h"\
- "..\..\srclib\apr\include\apr_mmap.h"\
- "..\..\srclib\apr\include\apr_network_io.h"\
- "..\..\srclib\apr\include\apr_pools.h"\
- "..\..\srclib\apr\include\apr_portable.h"\
- "..\..\srclib\apr\include\apr_strings.h"\
- "..\..\srclib\apr\include\apr_tables.h"\
- "..\..\srclib\apr\include\apr_thread_proc.h"\
- "..\..\srclib\apr\include\apr_time.h"\
- "..\..\srclib\apr\network_io\os2\os2nerrno.h"\
- ".\mod_proxy.h"\
-
-NODEP_CPP_PROXY=\
- "..\..\include\ap_config_auto.h"\
- "..\..\include\ap_config_path.h"\
- ".\ap_cache.h"\
- ".\buff.h"\
-
-
-"$(INTDIR)\proxy_connect.obj" : $(SOURCE) $(DEP_CPP_PROXY) "$(INTDIR)"
-
-
-SOURCE=.\proxy_ftp.c
-DEP_CPP_PROXY_=\
- "..\..\include\ap_config.h"\
- "..\..\include\ap_mmn.h"\
- "..\..\include\http_config.h"\
- "..\..\include\http_core.h"\
- "..\..\include\http_log.h"\
- "..\..\include\http_main.h"\
- "..\..\include\http_protocol.h"\
- "..\..\include\httpd.h"\
- "..\..\include\pcreposix.h"\
- "..\..\include\util_cfgtree.h"\
- "..\..\include\util_filter.h"\
- "..\..\include\util_uri.h"\
- "..\..\os\win32\os.h"\
- "..\..\srclib\apr-util\include\ap_buckets.h"\
- "..\..\srclib\apr-util\include\ap_hooks.h"\
- "..\..\srclib\apr-util\include\ap_ring.h"\
- "..\..\srclib\apr\include\apr.h"\
- "..\..\srclib\apr\include\apr_compat.h"\
- "..\..\srclib\apr\include\apr_dso.h"\
- "..\..\srclib\apr\include\apr_errno.h"\
- "..\..\srclib\apr\include\apr_file_io.h"\
- "..\..\srclib\apr\include\apr_general.h"\
- "..\..\srclib\apr\include\apr_lib.h"\
- "..\..\srclib\apr\include\apr_lock.h"\
- "..\..\srclib\apr\include\apr_mmap.h"\
- "..\..\srclib\apr\include\apr_network_io.h"\
- "..\..\srclib\apr\include\apr_pools.h"\
- "..\..\srclib\apr\include\apr_portable.h"\
- "..\..\srclib\apr\include\apr_strings.h"\
- "..\..\srclib\apr\include\apr_tables.h"\
- "..\..\srclib\apr\include\apr_thread_proc.h"\
- "..\..\srclib\apr\include\apr_time.h"\
- "..\..\srclib\apr\network_io\os2\os2nerrno.h"\
- ".\mod_proxy.h"\
-
-NODEP_CPP_PROXY_=\
- "..\..\include\ap_config_auto.h"\
- "..\..\include\ap_config_path.h"\
- ".\ap_cache.h"\
- ".\buff.h"\
-
-
-"$(INTDIR)\proxy_ftp.obj" : $(SOURCE) $(DEP_CPP_PROXY_) "$(INTDIR)"
-
-
-SOURCE=.\proxy_http.c
-DEP_CPP_PROXY_H=\
- "..\..\include\ap_config.h"\
- "..\..\include\ap_mmn.h"\
- "..\..\include\http_config.h"\
- "..\..\include\http_connection.h"\
- "..\..\include\http_core.h"\
- "..\..\include\http_log.h"\
- "..\..\include\http_main.h"\
- "..\..\include\http_protocol.h"\
- "..\..\include\httpd.h"\
- "..\..\include\pcreposix.h"\
- "..\..\include\util_cfgtree.h"\
- "..\..\include\util_date.h"\
- "..\..\include\util_filter.h"\
- "..\..\include\util_uri.h"\
- "..\..\os\win32\os.h"\
- "..\..\srclib\apr-util\include\ap_buckets.h"\
- "..\..\srclib\apr-util\include\ap_hooks.h"\
- "..\..\srclib\apr-util\include\ap_ring.h"\
- "..\..\srclib\apr\include\apr.h"\
- "..\..\srclib\apr\include\apr_compat.h"\
- "..\..\srclib\apr\include\apr_dso.h"\
- "..\..\srclib\apr\include\apr_errno.h"\
- "..\..\srclib\apr\include\apr_file_io.h"\
- "..\..\srclib\apr\include\apr_general.h"\
- "..\..\srclib\apr\include\apr_lib.h"\
- "..\..\srclib\apr\include\apr_lock.h"\
- "..\..\srclib\apr\include\apr_mmap.h"\
- "..\..\srclib\apr\include\apr_network_io.h"\
- "..\..\srclib\apr\include\apr_pools.h"\
- "..\..\srclib\apr\include\apr_portable.h"\
- "..\..\srclib\apr\include\apr_strings.h"\
- "..\..\srclib\apr\include\apr_tables.h"\
- "..\..\srclib\apr\include\apr_thread_proc.h"\
- "..\..\srclib\apr\include\apr_time.h"\
- "..\..\srclib\apr\network_io\os2\os2nerrno.h"\
- ".\mod_proxy.h"\
-
-NODEP_CPP_PROXY_H=\
- "..\..\include\ap_config_auto.h"\
- "..\..\include\ap_config_path.h"\
- ".\ap_cache.h"\
- ".\buff.h"\
-
-
-"$(INTDIR)\proxy_http.obj" : $(SOURCE) $(DEP_CPP_PROXY_H) "$(INTDIR)"
-
-
-SOURCE=.\proxy_util.c
-DEP_CPP_PROXY_U=\
- "..\..\include\ap_config.h"\
- "..\..\include\ap_mmn.h"\
- "..\..\include\http_config.h"\
- "..\..\include\http_core.h"\
- "..\..\include\http_log.h"\
- "..\..\include\http_main.h"\
- "..\..\include\http_protocol.h"\
- "..\..\include\httpd.h"\
- "..\..\include\pcreposix.h"\
- "..\..\include\util_cfgtree.h"\
- "..\..\include\util_date.h"\
- "..\..\include\util_filter.h"\
- "..\..\include\util_uri.h"\
- "..\..\os\win32\os.h"\
- "..\..\srclib\apr-util\include\ap_buckets.h"\
- "..\..\srclib\apr-util\include\ap_hooks.h"\
- "..\..\srclib\apr-util\include\ap_ring.h"\
- "..\..\srclib\apr\include\apr.h"\
- "..\..\srclib\apr\include\apr_compat.h"\
- "..\..\srclib\apr\include\apr_dso.h"\
- "..\..\srclib\apr\include\apr_errno.h"\
- "..\..\srclib\apr\include\apr_file_io.h"\
- "..\..\srclib\apr\include\apr_general.h"\
- "..\..\srclib\apr\include\apr_lib.h"\
- "..\..\srclib\apr\include\apr_lock.h"\
- "..\..\srclib\apr\include\apr_md5.h"\
- "..\..\srclib\apr\include\apr_mmap.h"\
- "..\..\srclib\apr\include\apr_network_io.h"\
- "..\..\srclib\apr\include\apr_pools.h"\
- "..\..\srclib\apr\include\apr_portable.h"\
- "..\..\srclib\apr\include\apr_strings.h"\
- "..\..\srclib\apr\include\apr_tables.h"\
- "..\..\srclib\apr\include\apr_thread_proc.h"\
- "..\..\srclib\apr\include\apr_time.h"\
- "..\..\srclib\apr\include\apr_xlate.h"\
- "..\..\srclib\apr\network_io\os2\os2nerrno.h"\
- ".\mod_proxy.h"\
-
-NODEP_CPP_PROXY_U=\
- "..\..\include\ap_config_auto.h"\
- "..\..\include\ap_config_path.h"\
- ".\ap_cache.h"\
- ".\buff.h"\
-
-
-"$(INTDIR)\proxy_util.obj" : $(SOURCE) $(DEP_CPP_PROXY_U) "$(INTDIR)"
-
-
-!IF "$(CFG)" == "mod_proxy - Win32 Release"
-
-"libapr - Win32 Release" :
- cd "\test\httpd-2.0\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Release"
- cd "..\..\modules\proxy"
-
-"libapr - Win32 ReleaseCLEAN" :
- cd "\test\httpd-2.0\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F ".\libapr.mak" CFG="libapr - Win32 Release"\
- RECURSE=1
- cd "..\..\modules\proxy"
-
-!ELSEIF "$(CFG)" == "mod_proxy - Win32 Debug"
-
-"libapr - Win32 Debug" :
- cd "\test\httpd-2.0\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) /F ".\libapr.mak" CFG="libapr - Win32 Debug"
- cd "..\..\modules\proxy"
-
-"libapr - Win32 DebugCLEAN" :
- cd "\test\httpd-2.0\srclib\apr"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F ".\libapr.mak" CFG="libapr - Win32 Debug"\
- RECURSE=1
- cd "..\..\modules\proxy"
-
-!ENDIF
-
-!IF "$(CFG)" == "mod_proxy - Win32 Release"
-
-"libhttpd - Win32 Release" :
- cd "\test\httpd-2.0"
- $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Release"
- cd ".\modules\proxy"
-
-"libhttpd - Win32 ReleaseCLEAN" :
- cd "\test\httpd-2.0"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F ".\libhttpd.mak"\
- CFG="libhttpd - Win32 Release" RECURSE=1
- cd ".\modules\proxy"
-
-!ELSEIF "$(CFG)" == "mod_proxy - Win32 Debug"
-
-"libhttpd - Win32 Debug" :
- cd "\test\httpd-2.0"
- $(MAKE) /$(MAKEFLAGS) /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug"
- cd ".\modules\proxy"
-
-"libhttpd - Win32 DebugCLEAN" :
- cd "\test\httpd-2.0"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F ".\libhttpd.mak" CFG="libhttpd - Win32 Debug"\
- RECURSE=1
- cd ".\modules\proxy"
-
-!ENDIF
-
-!IF "$(CFG)" == "mod_proxy - Win32 Release"
-
-"libaprutil - Win32 Release" :
- cd "\test\httpd-2.0\srclib\apr-util"
- $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Release"\
-
- cd "..\..\modules\proxy"
-
-"libaprutil - Win32 ReleaseCLEAN" :
- cd "\test\httpd-2.0\srclib\apr-util"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F ".\libaprutil.mak"\
- CFG="libaprutil - Win32 Release" RECURSE=1
- cd "..\..\modules\proxy"
-
-!ELSEIF "$(CFG)" == "mod_proxy - Win32 Debug"
-
-"libaprutil - Win32 Debug" :
- cd "\test\httpd-2.0\srclib\apr-util"
- $(MAKE) /$(MAKEFLAGS) /F ".\libaprutil.mak" CFG="libaprutil - Win32 Debug"
- cd "..\..\modules\proxy"
-
-"libaprutil - Win32 DebugCLEAN" :
- cd "\test\httpd-2.0\srclib\apr-util"
- $(MAKE) /$(MAKEFLAGS) CLEAN /F ".\libaprutil.mak"\
- CFG="libaprutil - Win32 Debug" RECURSE=1
- cd "..\..\modules\proxy"
-
-!ENDIF
-
-
-!ENDIF
-
diff --git a/modules/proxy/proxy_connect.c b/modules/proxy/proxy_connect.c
deleted file mode 100644
index c83e2accf6..0000000000
--- a/modules/proxy/proxy_connect.c
+++ /dev/null
@@ -1,427 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/* CONNECT method for Apache proxy */
-
-#define CORE_PRIVATE
-
-#include "mod_proxy.h"
-
-module AP_MODULE_DECLARE_DATA proxy_connect_module;
-
-PROXY_DECLARE (int) ap_proxy_connect_canon(request_rec *r, char *url);
-PROXY_DECLARE (int) ap_proxy_connect_handler(request_rec *r, proxy_server_conf *conf,
- char *url, const char *proxyname,
- apr_port_t proxyport);
-
-/*
- * This handles Netscape CONNECT method secure proxy requests.
- * A connection is opened to the specified host and data is
- * passed through between the WWW site and the browser.
- *
- * This code is based on the INTERNET-DRAFT document
- * "Tunneling SSL Through a WWW Proxy" currently at
- * http://www.mcom.com/newsref/std/tunneling_ssl.html.
- *
- * If proxyhost and proxyport are set, we send a CONNECT to
- * the specified proxy..
- *
- * FIXME: this doesn't log the number of bytes sent, but
- * that may be okay, since the data is supposed to
- * be transparent. In fact, this doesn't log at all
- * yet. 8^)
- * FIXME: doesn't check any headers initally sent from the
- * client.
- * FIXME: should allow authentication, but hopefully the
- * generic proxy authentication is good enough.
- * FIXME: no check for r->assbackwards, whatever that is.
- */
-
-static int
-allowed_port(proxy_server_conf *conf, int port)
-{
- int i;
- int *list = (int *) conf->allowed_connect_ports->elts;
-
- for(i = 0; i < conf->allowed_connect_ports->nelts; i++) {
- if(port == list[i])
- return 1;
- }
- return 0;
-}
-
-/* canonicalise CONNECT URLs. */
-PROXY_DECLARE (int) ap_proxy_connect_canon(request_rec *r, char *url)
-{
-
- if (r->method_number != M_CONNECT) {
- return DECLINED;
- }
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: CONNECT: canonicalising URL %s", url);
-
- return OK;
-}
-
-/* CONNECT handler */
-PROXY_DECLARE (int) ap_proxy_connect_handler(request_rec *r, proxy_server_conf *conf,
- char *url, const char *proxyname,
- apr_port_t proxyport)
-{
- apr_pool_t *p = r->pool;
- apr_socket_t *sock;
- apr_status_t err, rv;
- apr_size_t i, o, nbytes;
- char buffer[HUGE_STRING_LEN];
-
- apr_pollfd_t *pollfd;
- apr_int32_t pollcnt;
- apr_int16_t pollevent;
- apr_sockaddr_t *uri_addr, *connect_addr;
-
- uri_components uri;
- const char *connectname;
- int connectport = 0;
-
- /* is this for us? */
- if (r->method_number != M_CONNECT) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: CONNECT: rejecting URL %s", url);
- return DECLINED;
- }
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: CONNECT: serving URL %s", url);
-
-
- /*
- * Step One: Determine Who To Connect To
- *
- * Break up the URL to determine the host to connect to
- */
-
- /* we break the URL into host, port, uri */
- if (HTTP_OK != ap_parse_hostinfo_components(p, url, &uri)) {
- return ap_proxyerror(r, HTTP_BAD_REQUEST,
- apr_pstrcat(p, "URI cannot be parsed: ", url, NULL));
- }
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: CONNECT: connecting %s to %s:%d", url, uri.hostname, uri.port);
-
- /* do a DNS lookup for the destination host */
- err = apr_sockaddr_info_get(&uri_addr, uri.hostname, APR_UNSPEC, uri.port, 0, p);
-
- /* are we connecting directly, or via a proxy? */
- if (proxyname) {
- connectname = proxyname;
- connectport = proxyport;
- err = apr_sockaddr_info_get(&connect_addr, proxyname, APR_UNSPEC, proxyport, 0, p);
- }
- else {
- connectname = uri.hostname;
- connectport = uri.port;
- connect_addr = uri_addr;
- }
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
- "proxy: CONNECT: connecting to remote proxy %s on port %d", connectname, connectport);
-
- /* check if ProxyBlock directive on this host */
- if (OK != ap_proxy_checkproxyblock(r, conf, uri_addr)) {
- return ap_proxyerror(r, HTTP_FORBIDDEN,
- "Connect to remote machine blocked");
- }
-
- /* Check if it is an allowed port */
- if (conf->allowed_connect_ports->nelts == 0) {
- /* Default setting if not overridden by AllowCONNECT */
- switch (uri.port) {
- case DEFAULT_HTTPS_PORT:
- case DEFAULT_SNEWS_PORT:
- break;
- default:
- return HTTP_FORBIDDEN;
- }
- } else if(!allowed_port(conf, uri.port))
- return HTTP_FORBIDDEN;
-
-
- /*
- * Step Two: Make the Connection
- *
- * We have determined who to connect to. Now make the connection.
- */
-
- /* get all the possible IP addresses for the destname and loop through them
- * until we get a successful connection
- */
- if (APR_SUCCESS != err) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_pstrcat(p,
- "DNS lookup failure for: ",
- connectname, NULL));
- }
-
- /* create a new socket */
- if ((rv = apr_socket_create(&sock, APR_INET, SOCK_STREAM, r->pool)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "proxy: error creating socket");
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- /*
- * At this point we have a list of one or more IP addresses of
- * the machine to connect to. If configured, reorder this
- * list so that the "best candidate" is first try. "best
- * candidate" could mean the least loaded server, the fastest
- * responding server, whatever.
- *
- * For now we do nothing, ie we get DNS round robin.
- * XXX FIXME
- */
-
-
- /* try each IP address until we connect successfully */
- {
- int failed = 1;
- while (connect_addr) {
-
- /* make the connection out of the socket */
- rv = apr_connect(sock, connect_addr);
-
- /* if an error occurred, loop round and try again */
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
- "proxy: CONNECT: attempt to connect to %pI (%s) failed", connect_addr, connectname);
- connect_addr = connect_addr->next;
- continue;
- }
-
- /* if we get here, all is well */
- failed = 0;
- break;
- }
-
- /* handle a permanent error from the above loop */
- if (failed) {
- apr_socket_close(sock);
- if (proxyname) {
- return DECLINED;
- }
- else {
- return HTTP_BAD_GATEWAY;
- }
- }
- }
-
-
- /*
- * Step Three: Send the Request
- *
- * Send the HTTP/1.1 CONNECT request to the remote server
- */
-
- /* we are acting as a tunnel - the output filter stack should
- * be completely empty, because when we are done here we are done completely.
- * We add the NULL filter to the stack to do this...
- */
- r->output_filters = NULL;
- r->connection->output_filters = NULL;
-
-
- /* If we are connecting through a remote proxy, we need to pass
- * the CONNECT request on to it.
- */
- if (proxyport) {
- /* FIXME: Error checking ignored.
- */
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: CONNECT: sending the CONNECT request to the remote proxy");
- nbytes = apr_snprintf(buffer, sizeof(buffer),
- "CONNECT %s HTTP/1.0" CRLF, r->uri);
- apr_send(sock, buffer, &nbytes);
- nbytes = apr_snprintf(buffer, sizeof(buffer),
- "Proxy-agent: %s" CRLF CRLF, ap_get_server_version());
- apr_send(sock, buffer, &nbytes);
- }
- else {
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: CONNECT: Returning 200 OK Status");
- nbytes = apr_snprintf(buffer, sizeof(buffer),
- "HTTP/1.0 200 Connection Established" CRLF);
- apr_send(r->connection->client_socket, buffer, &nbytes);
- nbytes = apr_snprintf(buffer, sizeof(buffer),
- "Proxy-agent: %s" CRLF CRLF, ap_get_server_version());
- apr_send(r->connection->client_socket, buffer, &nbytes);
- }
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: CONNECT: setting up poll()");
-
- /*
- * Step Four: Handle Data Transfer
- *
- * Handle two way transfer of data over the socket (this is a tunnel).
- */
-
-/* r->sent_bodyct = 1;*/
-
- if((rv = apr_poll_setup(&pollfd, 2, r->pool)) != APR_SUCCESS)
- {
- apr_socket_close(sock);
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "proxy: CONNECT: error apr_poll_setup()");
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- /* Add client side to the poll */
- apr_poll_socket_add(pollfd, r->connection->client_socket, APR_POLLIN);
-
- /* Add the server side to the poll */
- apr_poll_socket_add(pollfd, sock, APR_POLLIN);
-
- while (1) { /* Infinite loop until error (one side closes the connection) */
-/* ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server, "proxy: CONNECT: going to sleep (poll)");*/
- if ((rv = apr_poll(pollfd, &pollcnt, -1)) != APR_SUCCESS)
- {
- apr_socket_close(sock);
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "proxy: CONNECT: error apr_poll()");
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-/* ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: CONNECT: woke from select(), i=%d", pollcnt);*/
-
- if (pollcnt) {
- apr_poll_revents_get(&pollevent, sock, pollfd);
- if (pollevent & APR_POLLIN) {
-/* ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: CONNECT: sock was set");*/
- nbytes = sizeof(buffer);
- if (apr_recv(sock, buffer, &nbytes) == APR_SUCCESS) {
- o = 0;
- i = nbytes;
- while(i > 0)
- {
- nbytes = i;
- if (apr_send(r->connection->client_socket, buffer + o, &nbytes) != APR_SUCCESS)
- break;
- o += nbytes;
- i -= nbytes;
- }
- }
- else
- break;
- }
- else if ((pollevent & APR_POLLERR) || (pollevent & APR_POLLHUP))
- break;
-
-
- apr_poll_revents_get(&pollevent, r->connection->client_socket, pollfd);
- if (pollevent & APR_POLLIN) {
-/* ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: CONNECT: client was set");*/
- nbytes = sizeof(buffer);
- if (apr_recv(r->connection->client_socket, buffer, &nbytes) == APR_SUCCESS) {
- o = 0;
- i = nbytes;
- while(i > 0)
- {
- nbytes = i;
- if (apr_send(sock, buffer + o, &nbytes) != APR_SUCCESS)
- break;
- o += nbytes;
- i -= nbytes;
- }
- }
- else
- break;
- }
- else if ((pollevent & APR_POLLERR) || (pollevent & APR_POLLHUP))
- break;
- }
- else
- break;
- }
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: CONNECT: finished with poll() - cleaning up");
-
- /*
- * Step Five: Clean Up
- *
- * Close the socket and clean up
- */
-
- apr_socket_close(sock);
-
- return OK;
-}
-
-static void ap_proxy_connect_register_hook(apr_pool_t *p)
-{
- proxy_hook_scheme_handler(ap_proxy_connect_handler, NULL, NULL, APR_HOOK_MIDDLE);
- proxy_hook_canon_handler(ap_proxy_connect_canon, NULL, NULL, APR_HOOK_MIDDLE);
-}
-
-module AP_MODULE_DECLARE_DATA proxy_connect_module = {
- STANDARD20_MODULE_STUFF,
- NULL, /* create per-directory config structure */
- NULL, /* merge per-directory config structures */
- NULL, /* create per-server config structure */
- NULL, /* merge per-server config structures */
- NULL, /* command apr_table_t */
- ap_proxy_connect_register_hook /* register hooks */
-};
diff --git a/modules/proxy/proxy_ftp.c b/modules/proxy/proxy_ftp.c
deleted file mode 100644
index a6661db7a9..0000000000
--- a/modules/proxy/proxy_ftp.c
+++ /dev/null
@@ -1,1666 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/* FTP routines for Apache proxy */
-
-#include "mod_proxy.h"
-
-#define AUTODETECT_PWD
-
-module AP_MODULE_DECLARE_DATA proxy_ftp_module;
-
-PROXY_DECLARE (int) ap_proxy_ftp_canon(request_rec *r, char *url);
-PROXY_DECLARE (int) ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf,
- char *url, const char *proxyhost,
- apr_port_t proxyport);
-apr_status_t ap_proxy_send_dir_filter(ap_filter_t *f,
- apr_bucket_brigade *bb);
-
-
-/*
- * Decodes a '%' escaped string, and returns the number of characters
- */
-static int decodeenc(char *x)
-{
- int i, j, ch;
-
- if (x[0] == '\0')
- return 0; /* special case for no characters */
- for (i = 0, j = 0; x[i] != '\0'; i++, j++) {
- /* decode it if not already done */
- ch = x[i];
- if (ch == '%' && ap_isxdigit(x[i + 1]) && ap_isxdigit(x[i + 2])) {
- ch = ap_proxy_hex2c(&x[i + 1]);
- i += 2;
- }
- x[j] = ch;
- }
- x[j] = '\0';
- return j;
-}
-
-/*
- * checks an encoded ftp string for bad characters, namely, CR, LF or
- * non-ascii character
- */
-static int ftp_check_string(const char *x)
-{
- int i, ch = 0;
-
- for (i = 0; x[i] != '\0'; i++) {
- ch = x[i];
- if (ch == '%' && ap_isxdigit(x[i + 1]) && ap_isxdigit(x[i + 2])) {
- ch = ap_proxy_hex2c(&x[i + 1]);
- i += 2;
- }
-#if !APR_CHARSET_EBCDIC
- if (ch == '\015' || ch == '\012' || (ch & 0x80))
-#else /*APR_CHARSET_EBCDIC*/
- if (ch == '\r' || ch == '\n' || (os_toascii[ch] & 0x80))
-#endif /*APR_CHARSET_EBCDIC*/
- return 0;
- }
- return 1;
-}
-
-/*
- * Canonicalise ftp URLs.
- */
-PROXY_DECLARE (int) ap_proxy_ftp_canon(request_rec *r, char *url)
-{
- char *user, *password, *host, *path, *parms, *strp, sport[7];
- apr_pool_t *p = r->pool;
- const char *err;
- apr_port_t port, def_port;
-
- /* */
- if (strncasecmp(url, "ftp:", 4) == 0) {
- url += 4;
- }
- else {
- return DECLINED;
- }
- def_port = ap_default_port_for_scheme("ftp");
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: canonicalising URL %s", url);
-
- port = def_port;
- err = ap_proxy_canon_netloc(p, &url, &user, &password, &host, &port);
- if (err)
- return HTTP_BAD_REQUEST;
- if (user != NULL && !ftp_check_string(user))
- return HTTP_BAD_REQUEST;
- if (password != NULL && !ftp_check_string(password))
- return HTTP_BAD_REQUEST;
-
- /* now parse path/parameters args, according to rfc1738 */
- /* N.B. if this isn't a true proxy request, then the URL path
- * (but not query args) has already been decoded.
- * This gives rise to the problem of a ; being decoded into the
- * path.
- */
- strp = strchr(url, ';');
- if (strp != NULL) {
- *(strp++) = '\0';
- parms = ap_proxy_canonenc(p, strp, strlen(strp), enc_parm,
- r->proxyreq);
- if (parms == NULL)
- return HTTP_BAD_REQUEST;
- }
- else
- parms = "";
-
- path = ap_proxy_canonenc(p, url, strlen(url), enc_path, r->proxyreq);
- if (path == NULL)
- return HTTP_BAD_REQUEST;
- if (!ftp_check_string(path))
- return HTTP_BAD_REQUEST;
-
- if (r->proxyreq && 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 = apr_pstrcat(p, parms, "?", strp, NULL);
- }
- else {
- strp = ap_proxy_canonenc(p, r->args, strlen(r->args), enc_fpath, 1);
- if (strp == NULL)
- return HTTP_BAD_REQUEST;
- path = apr_pstrcat(p, path, "?", strp, NULL);
- }
- r->args = NULL;
- }
-
-/* now, rebuild URL */
-
- if (port != def_port)
- apr_snprintf(sport, sizeof(sport), ":%d", port);
- else
- sport[0] = '\0';
-
- r->filename = apr_pstrcat(p, "proxy:ftp://", (user != NULL) ? user : "",
- (password != NULL) ? ":" : "",
- (password != NULL) ? password : "",
- (user != NULL) ? "@" : "", host, sport, "/", path,
- (parms[0] != '\0') ? ";" : "", parms, NULL);
-
- return OK;
-}
-
-/* we chop lines longer than 80 characters */
-#define MAX_LINE_LEN 80
-
-/*
- * Reads response lines, returns both the ftp status code and
- * remembers the response message in the supplied buffer
- */
-static int ftp_getrc_msg(conn_rec *c, apr_bucket_brigade *bb, char *msgbuf, int msglen)
-{
- int status;
- char response[MAX_LINE_LEN];
- char buff[5];
- char *mb = msgbuf,
- *me = &msgbuf[msglen];
- apr_status_t rv;
- int eos;
-
- if (APR_SUCCESS != (rv = ap_proxy_string_read(c, bb, response, sizeof(response), &eos))) {
- return -1;
- }
- if (!apr_isdigit(response[0]) || !apr_isdigit(response[1]) ||
- !apr_isdigit(response[2]) || (response[3] != ' ' && response[3] != '-'))
- status = 0;
- else
- status = 100 * response[0] + 10 * response[1] + response[2] - 111 * '0';
-
- mb = apr_cpystrn(mb, response+4, me - mb);
-
- if (response[3] == '-') {
- memcpy(buff, response, 3);
- buff[3] = ' ';
- do {
- if (APR_SUCCESS != (rv = ap_proxy_string_read(c, bb, response, sizeof(response), &eos))) {
- return -1;
- }
- mb = apr_cpystrn(mb, response + (' ' == response[0] ? 1 : 4), me - mb);
- } while (memcmp(response, buff, 4) != 0);
- }
-
- return status;
-}
-
-/* this is a filter that turns a raw ASCII directory listing into pretty HTML */
-
-/* ideally, mod_proxy should simply send the raw directory list up the filter
- * stack to mod_autoindex, which in theory should turn the raw ascii into
- * pretty html along with all the bells and whistles it provides...
- *
- * all in good time...! :)
- */
-
-typedef struct {
- apr_bucket_brigade *in;
- char buffer[MAX_STRING_LEN];
- enum {HEADER, BODY, FOOTER} state;
-} proxy_dir_ctx_t;
-
-apr_status_t ap_proxy_send_dir_filter(ap_filter_t *f, apr_bucket_brigade *in)
-{
- request_rec *r = f->r;
- apr_pool_t *p = r->pool;
- apr_bucket *e;
- apr_bucket_brigade *out = apr_brigade_create(p);
- apr_status_t rv;
-
- register int n;
- char *dir, *path, *reldir, *site, *str;
-
- const char *pwd = apr_table_get(r->notes, "Directory-PWD");
- const char *readme = apr_table_get(r->notes, "Directory-README");
-
- proxy_dir_ctx_t *ctx = f->ctx;
- if (!ctx) {
- f->ctx = ctx = apr_pcalloc(p, sizeof(*ctx));
- ctx->in = apr_brigade_create(p);
- ctx->buffer[0] = 0;
- ctx->state = HEADER;
- }
-
- /* combine the stored and the new */
- APR_BRIGADE_CONCAT(ctx->in, in);
-
- if (HEADER == ctx->state) {
-
- /* Save "scheme://site" prefix without password */
- site = ap_unparse_uri_components(p, &f->r->parsed_uri, UNP_OMITPASSWORD|UNP_OMITPATHINFO);
- /* ... and path without query args */
- path = ap_unparse_uri_components(p, &f->r->parsed_uri, UNP_OMITSITEPART|UNP_OMITQUERY);
- (void)decodeenc(path);
-
- /* Copy path, strip (all except the last) trailing slashes */
- path = dir = apr_pstrcat(p, path, "/", NULL);
- while ((n = strlen(path)) > 1 && path[n-1] == '/' && path[n-2] == '/')
- path[n-1] = '\0';
-
- /* print "ftp://host/" */
- str = apr_psprintf(p, DOCTYPE_HTML_3_2
- "\n\n<HTML>\n<HEAD>\n<TITLE>%s%s</TITLE>\n"
- "<BASE HREF=\"%s%s\">\n</HEAD>\n\n"
- "<BODY>\n\n<H2>Directory of "
- "<A HREF=\"/\">%s</A>/",
- site, path, site, path, site);
-
- e = apr_bucket_pool_create(str, strlen(str), p);
- APR_BRIGADE_INSERT_TAIL(out, e);
-
- while ((dir = strchr(dir+1, '/')) != NULL)
- {
- *dir = '\0';
- if ((reldir = strrchr(path+1, '/'))==NULL)
- reldir = path+1;
- else
- ++reldir;
- /* print "path/" component */
- str = apr_psprintf(p, "<A HREF=\"/%s/\">%s</A>/", path+1, reldir);
- e = apr_bucket_pool_create(str, strlen(str), p);
- APR_BRIGADE_INSERT_TAIL(out, e);
- *dir = '/';
- }
- /* If the caller has determined the current directory, and it differs */
- /* from what the client requested, then show the real name */
- if (pwd == NULL || strncmp (pwd, path, strlen(pwd)) == 0) {
- str = apr_psprintf(p, "</H2>\n\n<HR></HR>\n\n<PRE>");
- } else {
- str = apr_psprintf(p, "</H2>\n\n(%s)\n\n<HR></HR>\n\n<PRE>", pwd);
- }
- e = apr_bucket_pool_create(str, strlen(str), p);
- APR_BRIGADE_INSERT_TAIL(out, e);
-
- /* print README */
- if (readme) {
- str = apr_psprintf(p, "%s\n</PRE>\n\n<HR></HR>\n\n<PRE>\n",
- readme);
-
- e = apr_bucket_pool_create(str, strlen(str), p);
- APR_BRIGADE_INSERT_TAIL(out, e);
- }
-
- /* make sure page intro gets sent out */
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(out, e);
- if (APR_SUCCESS != (rv = ap_pass_brigade(f->next, out))) {
- return rv;
- }
- apr_brigade_cleanup(out);
-
- ctx->state = BODY;
- }
-
- /* loop through each line of directory */
- while (BODY == ctx->state) {
- char *filename;
- int found = 0;
- int eos = 0;
-
- /* get a complete line */
- /* if the buffer overruns - throw data away */
- while (!found && !APR_BRIGADE_EMPTY(ctx->in)) {
- char *pos, *response;
- apr_size_t len, max;
- e = APR_BRIGADE_FIRST(ctx->in);
- if (APR_BUCKET_IS_EOS(e)) {
- eos = 1;
- break;
- }
- if (APR_SUCCESS != (rv = apr_bucket_read(e, (const char **)&response, &len, APR_BLOCK_READ))) {
- return rv;
- }
- pos = memchr(response, APR_ASCII_LF, len);
- if (pos != NULL) {
- if ((pos - response + 1) != len) {
- len = pos - response + 1;
- apr_bucket_split(e, pos - response + 1);
-
- }
- found = 1;
- }
- max = sizeof(ctx->buffer)-strlen(ctx->buffer)-1;
- if (len > max) {
- len = max;
- }
-/* strncat works here, but apr_cpystrn does not - the last char gets chopped, dunno why */
-/* apr_cpystrn(ctx->buffer+strlen(ctx->buffer), response, len);*/
- strncat(ctx->buffer, response, len);
- APR_BUCKET_REMOVE(e);
- apr_bucket_destroy(e);
- }
-
- /* EOS? jump to footer */
- if (eos) {
- ctx->state = FOOTER;
- break;
- }
-
- /* not complete? leave and try get some more */
- if (!found) {
- return APR_SUCCESS;
- }
-
- /* a symlink? */
- if (ctx->buffer[0] == 'l' && (filename=strstr(ctx->buffer, " -> ")) != 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';
- str = apr_psprintf(p, "%s <A HREF=\"%s\">%s %s</A>\n", ctx->buffer, filename, filename, link_ptr);
- }
-
- /* a directory/file? */
- else if (ctx->buffer[0] == 'd' || ctx->buffer[0] == '-' || ctx->buffer[0] == 'l' || apr_isdigit(ctx->buffer[0])) {
- int searchidx = 0;
- char *searchptr = NULL;
- int firstfile = 1;
- if (apr_isdigit(ctx->buffer[0])) { /* handle DOS dir */
- searchptr = strchr(ctx->buffer, '<');
- if (searchptr != NULL)
- *searchptr = '[';
- searchptr = strchr(ctx->buffer, '>');
- if (searchptr != NULL)
- *searchptr = ']';
- }
-
- filename = strrchr(ctx->buffer, ' ');
- *(filename++) = 0;
- filename[strlen(filename) - 1] = 0;
-
- /* handle filenames with spaces in 'em */
- if (!strcmp(filename, ".") || !strcmp(filename, "..") || firstfile) {
- firstfile = 0;
- searchidx = filename - ctx->buffer;
- }
- else if (searchidx != 0 && ctx->buffer[searchidx] != 0) {
- *(--filename) = ' ';
- ctx->buffer[searchidx - 1] = 0;
- filename = &ctx->buffer[searchidx];
- }
-
- /* Special handling for '.' and '..' */
- if (!strcmp(filename, ".") || !strcmp(filename, "..") || ctx->buffer[0] == 'd') {
- str = apr_psprintf(p, "%s <A HREF=\"%s/\">%s</A>\n",
- ctx->buffer, filename, filename);
- }
- else {
- str = apr_psprintf(p, "%s <A HREF=\"%s\">%s</A>\n",
- ctx->buffer, filename, filename);
- }
- }
- else {
- str = apr_pstrdup(p, ctx->buffer);
- }
-
- /* erase buffer for next time around */
- ctx->buffer[0] = 0;
-
- e = apr_bucket_pool_create(str, strlen(str), p);
- APR_BRIGADE_INSERT_TAIL(out, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(out, e);
- if (APR_SUCCESS != (rv = ap_pass_brigade(f->next, out))) {
- return rv;
- }
- apr_brigade_cleanup(out);
-
- }
-
- if (FOOTER == ctx->state) {
- str = apr_psprintf(p, "</PRE>\n\n<HR></HR>\n\n%s\n\n</BODY>\n</HTML>\n", ap_psignature("", r));
- e = apr_bucket_pool_create(str, strlen(str), p);
- APR_BRIGADE_INSERT_TAIL(out, e);
-
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(out, e);
-
- e = apr_bucket_eos_create();
- APR_BRIGADE_INSERT_TAIL(out, e);
-
- if (APR_SUCCESS != (rv = ap_pass_brigade(f->next, out))) {
- return rv;
- }
- apr_brigade_destroy(out);
- }
-
- return APR_SUCCESS;
-}
-
-/* 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 = PROXYREQ_NONE;
- /* 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, 0, r,
- "proxy: missing or failed auth to %s",
- ap_unparse_uri_components(r->pool,
- &r->parsed_uri, UNP_OMITPATHINFO));
-
- apr_table_setn(r->err_headers_out, "WWW-Authenticate",
- apr_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
- * Filters by [Graham Leggett <minfrin@sharp.fm>]
- */
-PROXY_DECLARE (int) ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf,
- char *url, const char *proxyhost,
- apr_port_t proxyport)
-{
- apr_pool_t *p = r->pool;
- conn_rec *c = r->connection;
- proxy_conn_rec *backend;
- apr_socket_t *sock, *local_sock, *remote_sock;
- apr_sockaddr_t *connect_addr;
- apr_status_t rv;
- conn_rec *origin, *remote;
- int err;
- apr_bucket *e;
- apr_bucket_brigade *bb = apr_brigade_create(p);
- apr_bucket_brigade *cbb = apr_brigade_create(p);
- char *buf, *connectname;
- apr_port_t connectport;
- char buffer[MAX_STRING_LEN];
- char *path, *strp, *parms;
- char *user = NULL;
-/* char *account = NULL; how to supply an account in a URL? */
- const char *password = NULL;
- int i, j, len, rc;
- int one = 1;
- char *size = NULL;
- apr_size_t readbytes = -1;
-
- /* stuff for PASV mode */
- int connect = 0, use_port = 0;
- char dates[AP_RFC822_DATE_LEN];
-
- /* is this for us? */
- if (proxyhost) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: rejecting URL %s - proxyhost %s specified:", url, proxyhost);
- return DECLINED; /* proxy connections are via HTTP */
- }
- if (strncasecmp(url, "ftp:", 4)) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: rejecting URL %s - not ftp:", url);
- return DECLINED; /* only interested in FTP */
- }
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: serving URL %s", url);
-
- /* create space for state information */
- backend = (proxy_conn_rec *) ap_get_module_config(c->conn_config, &proxy_ftp_module);
- if (!backend) {
- backend = ap_pcalloc(c->pool, sizeof(proxy_conn_rec));
- backend->connection = NULL;
- backend->hostname = NULL;
- backend->port = 0;
- ap_set_module_config(c->conn_config, &proxy_ftp_module, backend);
- }
-
-
- /*
- * I: Who Do I Connect To?
- * -----------------------
- *
- * Break up the URL to determine the host to connect to
- */
-
- /* we only support GET and HEAD */
- if (r->method_number != M_GET)
- return HTTP_NOT_IMPLEMENTED;
-
-
- /* We break the URL into host, port, path-search */
- connectname = r->parsed_uri.hostname;
- connectport = (r->parsed_uri.port != 0)
- ? r->parsed_uri.port
- : ap_default_port_for_request(r);
- path = apr_pstrdup(p, r->parsed_uri.path);
- path = (path != NULL && path[0] != '\0') ? &path[1] : "";
-
- parms = strchr(path, ';');
- if (parms != NULL)
- *(parms++) = '\0';
-
- /* 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 = apr_table_get(r->headers_in, "Authorization")) != NULL
- && strcasecmp(ap_getword(r->pool, &password, ' '), "Basic") == 0
- && (password = ap_pbase64decode(r->pool, password))[0] != ':') {
- /* Note that this allocation has to be made from r->connection->pool
- * because it has the lifetime of the connection. The other allocations
- * are temporary and can be tossed away any time.
- */
- user = ap_getword_nulls (r->connection->pool, &password, ':');
- r->ap_auth_type = "Basic";
- r->user = r->parsed_uri.user = user;
- }
- else if ((user = r->parsed_uri.user) != NULL) {
- user = apr_pstrdup(p, user);
- decodeenc(user);
- if ((password = r->parsed_uri.password) != NULL) {
- char *tmp = apr_pstrdup(p, password);
- decodeenc(tmp);
- password = tmp;
- }
- }
- else {
- user = "anonymous";
- password = "apache-proxy@";
- }
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: connecting %s to %s:%d", url, connectname, connectport);
-
- /* do a DNS lookup for the destination host */
- err = apr_sockaddr_info_get(&connect_addr, connectname, APR_UNSPEC, connectport, 0, p);
-
- /* check if ProxyBlock directive on this host */
- if (OK != ap_proxy_checkproxyblock(r, conf, connect_addr)) {
- return ap_proxyerror(r, HTTP_FORBIDDEN,
- "Connect to remote machine blocked");
- }
-
-
- /*
- * II: Make the Connection
- * -----------------------
- *
- * We have determined who to connect to. Now make the connection.
- */
-
- /* get all the possible IP addresses for the destname and loop through them
- * until we get a successful connection
- */
- if (APR_SUCCESS != err) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_pstrcat(p,
- "DNS lookup failure for: ",
- connectname, NULL));
- }
-
-
- if ((rv = apr_socket_create(&sock, APR_INET, SOCK_STREAM, r->pool)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "proxy: FTP: error creating socket");
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
-#if !defined(TPF) && !defined(BEOS)
- if (conf->recv_buffer_size > 0
- && (rv = apr_setsocketopt(sock, APR_SO_RCVBUF,
- conf->recv_buffer_size))) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
- }
-#endif
-
- if (APR_SUCCESS != (rv = apr_setsocketopt(sock, APR_SO_REUSEADDR, one))) {
-#ifndef _OSD_POSIX /* BS2000 has this option "always on" */
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "proxy: FTP: error setting reuseaddr option: setsockopt(SO_REUSEADDR)");
- return HTTP_INTERNAL_SERVER_ERROR;
-#endif /*_OSD_POSIX*/
- }
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: socket has been created");
-
-
- /*
- * At this point we have a list of one or more IP addresses of
- * the machine to connect to. If configured, reorder this
- * list so that the "best candidate" is first try. "best
- * candidate" could mean the least loaded server, the fastest
- * responding server, whatever.
- *
- * For now we do nothing, ie we get DNS round robin.
- * XXX FIXME
- */
-
-
- /* try each IP address until we connect successfully */
- {
- int failed = 1;
- while (connect_addr) {
-
- /* make the connection out of the socket */
- rv = apr_connect(sock, connect_addr);
-
- /* if an error occurred, loop round and try again */
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
- "proxy: FTP: attempt to connect to %pI (%s) failed", connect_addr, connectname);
- connect_addr = connect_addr->next;
- continue;
- }
-
- /* if we get here, all is well */
- failed = 0;
- break;
- }
-
- /* handle a permanent error from the above loop */
- if (failed) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_psprintf(r->pool,
- "Could not connect to remote machine: %s port %d",
- connectname, connectport));
- }
- }
-
- /* the socket is now open, create a new connection */
- origin = ap_new_connection(p, r->server, sock, r->connection->id);
- if (!origin) {
- /* the peer reset the connection already; ap_new_connection()
- * closed the socket */
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: an error occurred creating a new connection to %pI (%s)", connect_addr, connectname);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- /* if a keepalive connection is floating around, close it first! */
- /* we might support ftp keepalives later, but not now... */
- if (backend->connection) {
- apr_socket_close(backend->connection->client_socket);
- backend->connection = NULL;
- }
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: control connection complete");
-
-
- /*
- * III: Send Control Request
- * -------------------------
- *
- * Log into the ftp server, send the username & password, change to the correct
- * directory...
- */
-
- /* set up the connection filters */
- ap_proxy_pre_http_connection(origin, NULL);
-
- /* possible results: */
- /* 120 Service ready in nnn minutes. */
- /* 220 Service ready for new user. */
- /* 421 Service not available, closing control connection. */
- i = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", i, buffer);
- if (i == -1) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, "Error reading from remote server");
- }
- if (i == 120) {
- /* RFC2616 states:
- * 14.37 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 )
- */
- for (i=0 ; buffer[i] && !isdigit(buffer[i]); i++);
- if (buffer[i]) {
- ap_table_add(r->headers_out, "Retry-After", apr_psprintf(p, "%lu", 60*atol(buffer+i)));
- }
- return ap_proxyerror(r, HTTP_SERVICE_UNAVAILABLE, buffer);
- }
- if (i != 220) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, buffer);
- }
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: connected.");
-
- buf = apr_pstrcat(p, "USER ", user, CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: 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_msg(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", i, buffer);
- if (i == -1) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, "Error reading from remote server");
- }
- if (i == 530) {
- return ftp_unauthorized (r, 1); /* log it: user name guessing attempt? */
- }
- if (i != 230 && i != 331) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, buffer);
- }
-
- if (i == 331) { /* send password */
- if (password == NULL) {
- return ftp_unauthorized (r, 0);
- }
- buf = apr_pstrcat(p, "PASS ", password, CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: 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_msg(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", i, buffer);
- if (i == -1) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- "Error reading from remote server");
- }
- if (i == 332) {
- return ap_proxyerror(r, HTTP_UNAUTHORIZED,
- apr_pstrcat(p, "Need account for login: ", buffer, NULL));
- }
- /* @@@ questionable -- we might as well return a 403 Forbidden here */
- if (i == 530) {
- return ftp_unauthorized (r, 1); /* log it: passwd guessing attempt? */
- }
- if (i != 230 && i != 202) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, buffer);
- }
- }
- apr_table_set(r->notes, "Directory-README", buffer);
-
- /* set the directory (walk directory component by component):
- * this is what we must do if we don't know the OS type of the remote
- * machine
- */
- for (;;) {
- strp = strchr(path, '/');
- if (strp == NULL)
- break;
- *strp = '\0';
-
- len = decodeenc(path);
- buf = apr_pstrcat(p, "CWD ", path, CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: CWD %s", path);
- *strp = '/';
- /* responses: 250, 421, 500, 501, 502, 530, 550 */
- /* 250 Requested file action okay, completed. */
- /* 421 Service not available, closing control connection. */
- /* 500 Syntax error, command unrecognized. */
- /* 501 Syntax error in parameters or arguments. */
- /* 502 Command not implemented. */
- /* 530 Not logged in. */
- /* 550 Requested action not taken. */
- i = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", i, buffer);
- if (i == -1) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- "Error reading from remote server");
- }
- if (i == 550) {
- return ap_proxyerror(r, HTTP_NOT_FOUND, buffer);
- }
- if (i != 250) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, buffer);
- }
-
- path = strp + 1;
- }
-
- if (parms != NULL && strncasecmp(parms, "type=a", 6) == 0) {
- parms = "A";
- }
- else {
- parms = "I";
- }
-
- /* changed to make binary transfers the default */
- /* set type to binary */
- buf = apr_pstrcat(p, "TYPE ", parms, CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: 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_msg(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", i, buffer);
- if (i == -1) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- "Error reading from remote server");
- }
- if (i != 200 && i != 504) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, buffer);
- }
- /* Allow not implemented */
- if (i == 504) {
- parms[0] = '\0';
- }
-
-
- /*
- * IV: Make Data Connection?
- * -------------------------
- *
- * Try EPSV, if that fails...
- * try PASV, if that fails...
- * try PORT.
- */
-/* this temporarily switches off EPSV/PASV */
-/*goto bypass;*/
-
- /* set up data connection - EPSV */
- {
- apr_sockaddr_t *remote_addr;
- char *remote_ip;
- apr_port_t remote_port;
-
- /* The EPSV command replaces PASV where both IPV4 and IPV6 is supported. Only
- * the port is returned, the IP address is always the same as that on the
- * control connection. Example:
- * Entering Extended Passive Mode (|||6446|)
- */
- buf = apr_pstrcat(p, "EPSV", CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: EPSV");
- /* possible results: 227, 421, 500, 501, 502, 530 */
- /* 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2). */
- /* 421 Service not available, closing control connection. */
- /* 500 Syntax error, command unrecognized. */
- /* 501 Syntax error in parameters or arguments. */
- /* 502 Command not implemented. */
- /* 530 Not logged in. */
- i = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", i, buffer);
- if (i == -1) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- "Error reading from remote server");
- }
- if (i != 229 && i != 500 && i != 501 && i != 502) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, buffer);
- }
- else if (i == 229) {
- char *pstr;
-
- pstr = apr_pstrdup(p, buffer);
- pstr = strtok(pstr, " "); /* separate result code */
- if (pstr != NULL) {
- if (*(pstr + strlen(pstr) + 1) == '=') {
- pstr += strlen(pstr) + 2;
- }
- else {
- pstr = strtok(NULL, "("); /* separate address & port params */
- if (pstr != NULL)
- pstr = strtok(NULL, ")");
- }
- }
-
- if (pstr) {
- apr_sockaddr_t *epsv_addr;
- remote_port = atoi(pstr+3);
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: EPSV contacting remote host on port %d",
- remote_port);
-
- if ((rv = apr_socket_create(&remote_sock, APR_INET, SOCK_STREAM, r->pool)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "proxy: FTP: error creating EPSV socket");
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
-#if !defined (TPF) && !defined(BEOS)
- if (conf->recv_buffer_size > 0 && (rv = apr_setsocketopt(remote_sock, APR_SO_RCVBUF,
- conf->recv_buffer_size))) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "proxy: FTP: setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
- }
-#endif
-
- /* make the connection */
- apr_socket_addr_get(&remote_addr, APR_REMOTE, sock);
- apr_sockaddr_ip_get(&remote_ip, remote_addr);
- apr_sockaddr_info_get(&epsv_addr, remote_ip, APR_INET, remote_port, 0, p);
- rv = apr_connect(remote_sock, epsv_addr);
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
- "proxy: FTP: EPSV attempt to connect to %pI failed - Firewall/NAT?", epsv_addr);
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_psprintf(r->pool,
- "EPSV attempt to connect to %pI failed - firewall/NAT?", epsv_addr));
- }
- else {
- connect = 1;
- }
- }
- else {
- /* and try the regular way */
- apr_socket_close(remote_sock);
- }
- }
- }
-
- /* set up data connection - PASV */
- if (!connect) {
- buf = apr_pstrcat(p, "PASV", CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: PASV");
- /* possible results: 227, 421, 500, 501, 502, 530 */
- /* 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2). */
- /* 421 Service not available, closing control connection. */
- /* 500 Syntax error, command unrecognized. */
- /* 501 Syntax error in parameters or arguments. */
- /* 502 Command not implemented. */
- /* 530 Not logged in. */
- i = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", i, buffer);
- if (i == -1) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- "Error reading from remote server");
- }
- if (i != 227 && i != 502) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, buffer);
- }
- else if (i == 227) {
- unsigned int h0, h1, h2, h3, p0, p1;
- char *pstr;
-
-/* FIXME: Check PASV against RFC1123 */
-
- pstr = apr_pstrdup(p, buffer);
- pstr = strtok(pstr, " "); /* separate result code */
- if (pstr != NULL) {
- if (*(pstr + strlen(pstr) + 1) == '=') {
- pstr += strlen(pstr) + 2;
- }
- else {
- pstr = strtok(NULL, "("); /* separate address & port params */
- if (pstr != NULL)
- pstr = strtok(NULL, ")");
- }
- }
-
-/* FIXME: Only supports IPV4 - fix in RFC2428 */
-
- if (pstr != NULL && (sscanf(pstr,
- "%d,%d,%d,%d,%d,%d", &h3, &h2, &h1, &h0, &p1, &p0) == 6)) {
-
- apr_sockaddr_t *pasv_addr;
- int pasvport = (p1 << 8) + p0;
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: PASV contacting host %d.%d.%d.%d:%d",
- h3, h2, h1, h0, pasvport);
-
- if ((rv = apr_socket_create(&remote_sock, APR_INET, SOCK_STREAM, r->pool)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "proxy: error creating PASV socket");
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
-#if !defined (TPF) && !defined(BEOS)
- if (conf->recv_buffer_size > 0 && (rv = apr_setsocketopt(remote_sock, APR_SO_RCVBUF,
- conf->recv_buffer_size))) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "proxy: FTP: setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
- }
-#endif
-
- /* make the connection */
- apr_sockaddr_info_get(&pasv_addr, apr_psprintf(p, "%d.%d.%d.%d", h3, h2, h1, h0), APR_INET, pasvport, 0, p);
- rv = apr_connect(remote_sock, pasv_addr);
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
- "proxy: FTP: PASV attempt to connect to %pI failed - Firewall/NAT?", pasv_addr);
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_psprintf(r->pool,
- "PASV attempt to connect to %pI failed - firewall/NAT?", pasv_addr));
- }
- else {
- connect = 1;
- }
- }
- else {
- /* and try the regular way */
- apr_socket_close(remote_sock);
- }
- }
- }
-/*bypass:*/
-
- /* set up data connection - PORT */
- if (!connect) {
- apr_sockaddr_t *local_addr;
- char *local_ip;
- apr_port_t local_port;
- unsigned int h0, h1, h2, h3, p0, p1;
-
- if ((rv = apr_socket_create(&local_sock, APR_INET, SOCK_STREAM, r->pool)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "proxy: FTP: error creating local socket");
- return HTTP_INTERNAL_SERVER_ERROR;
- }
- apr_socket_addr_get(&local_addr, APR_LOCAL, sock);
- apr_sockaddr_port_get(&local_port, local_addr);
- apr_sockaddr_ip_get(&local_ip, local_addr);
-
- if ((rv = apr_setsocketopt(local_sock, APR_SO_REUSEADDR, one)) != APR_SUCCESS) {
-#ifndef _OSD_POSIX /* BS2000 has this option "always on" */
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "proxy: FTP: error setting reuseaddr option");
- return HTTP_INTERNAL_SERVER_ERROR;
-#endif /*_OSD_POSIX*/
- }
-
- apr_sockaddr_info_get(&local_addr, local_ip, APR_UNSPEC, local_port, 0, r->pool);
-
- if ((rv = apr_bind(local_sock, local_addr)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "proxy: FTP: error binding to ftp data socket %pI", local_addr);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- /* only need a short queue */
- if ((rv = apr_listen(local_sock, 2)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "proxy: FTP: error listening to ftp data socket %pI", local_addr);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
-/* FIXME: Sent PORT here */
-
- if (local_ip && (sscanf(local_ip,
- "%d.%d.%d.%d", &h3, &h2, &h1, &h0) == 4)) {
- p1 = (local_port >> 8);
- p0 = (local_port & 0xFF);
-
- buf = apr_psprintf(p, "PORT %d,%d,%d,%d,%d,%d" CRLF, h3, h2, h1, h0, p1, p0);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: PORT %d,%d,%d,%d,%d,%d", h3, h2, h1, h0, p1, p0);
- /* possible results: 200, 421, 500, 501, 502, 530 */
- /* 200 Command okay. */
- /* 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. */
- rc = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", rc, buffer);
- if (rc == -1) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- "Error reading from remote server");
- }
- if (rc != 200) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, buffer);
- }
-
- /* signal that we must use the EPRT/PORT loop */
- use_port = 1;
- }
- else {
-/* IPV6 FIXME:
- * The EPRT command replaces PORT where both IPV4 and IPV6 is supported. The first
- * number (1,2) indicates the protocol type. Examples:
- * EPRT |1|132.235.1.2|6275|
- * EPRT |2|1080::8:800:200C:417A|5282|
- */
- return ap_proxyerror(r, HTTP_NOT_IMPLEMENTED, "Connect to IPV6 ftp server using EPRT not supported. Enable EPSV.");
- }
- }
-
-
- /*
- * V: Set The Headers
- * -------------------
- *
- * Get the size of the request, set up the environment for HTTP.
- */
-
- /* 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 {
- buf = apr_pstrcat(p, "SIZE ", path, CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: SIZE %s", path);
- i = ftp_getrc_msg(origin, cbb, buffer, sizeof buffer);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: returned status %d with response %s", i, buffer);
- if (i != 500) { /* Size command not recognized */
- if (i == 550) { /* Not a regular file */
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: SIZE shows this is a directory");
- parms = "d";
- buf = apr_pstrcat(p, "CWD ", path, CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: CWD %s", path);
- i = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
- /* 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. */
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", i, buffer);
- if (i == -1) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- "Error reading from remote server");
- }
- if (i == 550) {
- return ap_proxyerror(r, HTTP_NOT_FOUND, buffer);
- }
- if (i != 250) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, buffer);
- }
- path = "";
- len = 0;
- }
- else if (i == 213) { /* Size command ok */
- for (j = 0; j < sizeof(buffer) && apr_isdigit(buffer[j]); j++);
- buffer[j] = '\0';
- if (buffer[0] != '\0')
- size = apr_pstrdup(p, buffer);
- }
- }
- }
-
-
-
-#ifdef AUTODETECT_PWD
- buf = apr_pstrcat(p, "PWD", CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: 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(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", i, buffer);
- if (i == -1 || i == 421) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- "Error reading from remote server");
- }
- if (i == 550) {
- return ap_proxyerror(r, HTTP_NOT_FOUND, buffer);
- }
- if (i == 257) {
- const char *dirp = buffer;
- apr_table_set(r->notes, "Directory-PWD", ap_getword_conf(r->pool, &dirp));
- }
-#endif /*AUTODETECT_PWD*/
-
- if (parms[0] == 'd') {
- if (len != 0)
- buf = apr_pstrcat(p, "LIST ", path, CRLF, NULL);
- else
- buf = apr_pstrcat(p, "LIST -lag", CRLF, NULL);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: LIST %s", (len == 0 ? "-lag" : path));
- }
- else {
-/* FIXME: Handle range requests - send REST */
- buf = apr_pstrcat(p, "RETR ", path, CRLF, NULL);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: RETR %s", path);
- }
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- /* 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_msg(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", rc, buffer);
- if (rc == -1) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- "Error reading from remote server");
- }
- if (rc == 550) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: RETR failed, trying LIST instead");
- parms = "d";
- buf = apr_pstrcat(p, "CWD ", path, CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: 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_msg(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", rc, buffer);
- if (rc == -1) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- "Error reading from remote server");
- }
- if (rc == 550) {
- return ap_proxyerror(r, HTTP_NOT_FOUND, buffer);
- }
- if (rc != 250) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, buffer);
- }
-
-#ifdef AUTODETECT_PWD
- buf = apr_pstrcat(p, "PWD ", CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: 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(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", i, buffer);
- if (i == -1 || i == 421) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- "Error reading from remote server");
- }
- if (i == 550) {
- return ap_proxyerror(r, HTTP_NOT_FOUND, buffer);
- }
- if (i == 257) {
- const char *dirp = buffer;
- apr_table_set(r->notes, "Directory-PWD", ap_getword_conf(r->pool, &dirp));
- }
-#endif /*AUTODETECT_PWD*/
-
- buf = apr_pstrcat(p, "LIST -lag", CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: LIST -lag");
- rc = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", rc, buffer);
- if (rc == -1)
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- "Error reading from remote server");
- }
- if (rc != 125 && rc != 150 && rc != 226 && rc != 250) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, buffer);
- }
-
- r->status = HTTP_OK;
- r->status_line = "200 OK";
-
- apr_rfc822_date(dates, r->request_time);
- apr_table_setn(r->headers_out, "Date", dates);
- apr_table_setn(r->headers_out, "Server", ap_get_server_version());
-
- /* set content-type */
- if (parms[0] == 'd') {
- r->content_type = "text/html";
- }
- else {
- if (r->content_type) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: Content-Type set to %s", r->content_type);
- }
- else {
- r->content_type = ap_default_type(r);
- }
- if (parms[0] != 'a' && size != NULL) {
- /* We "trust" the ftp server to really serve (size) bytes... */
- apr_table_setn(r->headers_out, "Content-Length", size);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: Content-Length set to %s", size);
- }
- }
- apr_table_setn(r->headers_out, "Content-Type", r->content_type);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: Content-Type set to %s", r->content_type);
-
- /* set content-encoding */
- if (r->content_encoding != NULL && r->content_encoding[0] != '\0') {
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: Content-Encoding set to %s", r->content_encoding);
- apr_table_setn(r->headers_out, "Content-Encoding", r->content_encoding);
- }
-
- /* wait for connection */
- if (use_port) {
- for(;;)
- {
-/* FIXME: this does not return, despite the incoming connection being accepted */
- switch(rv = apr_accept(&remote_sock, local_sock, r->pool))
- {
- case APR_EINTR:
- continue;
- case APR_SUCCESS:
- break;
- default:
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "proxy: FTP: failed to accept data connection");
- return HTTP_BAD_GATEWAY;
- }
- }
- }
-
- /* the transfer socket is now open, create a new connection */
- remote = ap_new_connection(p, r->server, remote_sock, r->connection->id);
- if (!remote) {
- /* the peer reset the connection already; ap_new_connection()
- * closed the socket */
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: an error occurred creating the transfer connection");
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
- /* set up the connection filters */
- ap_proxy_pre_http_connection(remote, NULL);
-
-
- /*
- * VI: Receive the Response
- * ------------------------
- *
- * Get response from the remote ftp socket, and pass it up the
- * filter chain.
- */
-
- /* send response */
- r->sent_bodyct = 1;
-
- if (parms[0] == 'd') {
- /* insert directory filter */
- ap_add_output_filter("PROXY_SEND_DIR", NULL, r, r->connection);
- }
-
- /* send body */
- if (!r->header_only) {
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: start body send");
-
- /* read the body, pass it to the output filters */
- while (ap_get_brigade(remote->input_filters, bb, AP_MODE_BLOCKING, &readbytes) == APR_SUCCESS) {
- if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(r->output_filters, bb);
- break;
- }
- ap_pass_brigade(r->output_filters, bb);
- apr_brigade_cleanup(bb);
- }
- apr_brigade_cleanup(bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: end body send");
-
- }
- else {
-
- /* abort the transfer */
- buf = apr_pstrcat(p, "ABOR", CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: 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_msg(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", i, buffer);
- }
-
-
- /*
- * VII: Clean Up
- * -------------
- *
- * If there are no KeepAlives, or if the connection has been signalled
- * to close, close the socket and clean up
- */
-
- /* finish */
- buf = apr_pstrcat(p, "QUIT", CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: QUIT");
- /* responses: 221, 500 */
- /* 221 Service closing control connection. */
- /* 500 Syntax error, command unrecognized. */
- i = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer));
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: FTP: %d %s", i, buffer);
-
- apr_brigade_destroy(bb);
- return OK;
-}
-
-static void ap_proxy_ftp_register_hook(apr_pool_t *p)
-{
- /* hooks */
- proxy_hook_scheme_handler(ap_proxy_ftp_handler, NULL, NULL, APR_HOOK_MIDDLE);
- proxy_hook_canon_handler(ap_proxy_ftp_canon, NULL, NULL, APR_HOOK_MIDDLE);
- /* filters */
- ap_register_output_filter("PROXY_SEND_DIR", ap_proxy_send_dir_filter, AP_FTYPE_CONTENT);
-}
-
-module AP_MODULE_DECLARE_DATA proxy_ftp_module = {
- STANDARD20_MODULE_STUFF,
- NULL, /* create per-directory config structure */
- NULL, /* merge per-directory config structures */
- NULL, /* create per-server config structure */
- NULL, /* merge per-server config structures */
- NULL, /* command apr_table_t */
- ap_proxy_ftp_register_hook /* register hooks */
-};
diff --git a/modules/proxy/proxy_http.c b/modules/proxy/proxy_http.c
deleted file mode 100644
index f6d3213a28..0000000000
--- a/modules/proxy/proxy_http.c
+++ /dev/null
@@ -1,835 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/* HTTP routines for Apache proxy */
-
-#include "mod_proxy.h"
-
-module AP_MODULE_DECLARE_DATA proxy_http_module;
-
-PROXY_DECLARE (int) ap_proxy_http_canon(request_rec *r, char *url);
-PROXY_DECLARE (int) ap_proxy_http_handler(request_rec *r, proxy_server_conf *conf,
- char *url, const char *proxyname,
- apr_port_t proxyport);
-
-
-/*
- * Canonicalise http-like URLs.
- * scheme is the scheme for the URL
- * url is the URL starting with the first '/'
- * def_port is the default port for this scheme.
- */
-PROXY_DECLARE (int) ap_proxy_http_canon(request_rec *r, char *url)
-{
- char *host, *path, *search, sport[7];
- const char *err;
- const char *scheme;
- apr_port_t port, def_port;
-
- /* ap_default_port_for_scheme() */
- if (strncasecmp(url, "http:", 5) == 0) {
- url += 5;
- scheme = "http";
- }
- else if (strncasecmp(url, "https:", 6) == 0) {
- url += 6;
- scheme = "https:";
- }
- else {
- return DECLINED;
- }
- def_port = ap_default_port_for_scheme(scheme);
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: HTTP: canonicalising URL %s", url);
-
- /* do syntatic check.
- * We break the URL into host, port, path, search
- */
- port = def_port;
- err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port);
- if (err)
- return HTTP_BAD_REQUEST;
-
- /* now parse path/search args, according to rfc1738 */
- /* N.B. if this isn't a true proxy request, then the URL _path_
- * has already been decoded. True proxy requests have r->uri
- * == r->unparsed_uri, and no others have that property.
- */
- if (r->uri == r->unparsed_uri) {
- search = strchr(url, '?');
- if (search != NULL)
- *(search++) = '\0';
- }
- else
- search = r->args;
-
- /* process path */
- path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, r->proxyreq);
- if (path == NULL)
- return HTTP_BAD_REQUEST;
-
- if (port != def_port)
- apr_snprintf(sport, sizeof(sport), ":%d", port);
- else
- sport[0] = '\0';
-
- r->filename = apr_pstrcat(r->pool, "proxy:", scheme, "://", host, sport, "/",
- path, (search) ? "?" : "", (search) ? search : "", NULL);
- return OK;
-}
-
-static const char *ap_proxy_location_reverse_map(request_rec *r, proxy_server_conf *conf, const char *url)
-{
- struct proxy_alias *ent;
- int i, l1, l2;
- char *u;
-
- /* XXX FIXME: Make sure this handled the ambiguous case of the :80
- * after the hostname */
-
- 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 = apr_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 ap_proxy_clear_connection(apr_pool_t *p, apr_table_t *headers)
-{
- const char *name;
- char *next = apr_pstrdup(p, apr_table_get(headers, "Connection"));
-
- apr_table_unset(headers, "Proxy-Connection");
- if (!next)
- return;
-
- while (*next) {
- name = next;
- while (*next && !apr_isspace(*next) && (*next != ','))
- ++next;
- while (*next && (apr_isspace(*next) || (*next == ','))) {
- *next = '\0';
- ++next;
- }
- apr_table_unset(headers, name);
- }
- apr_table_unset(headers, "Connection");
-}
-
-/*
- * This handles http:// URLs, and other URLs using a remote proxy over http
- * If proxyhost is NULL, then contact the server directly, otherwise
- * go via the proxy.
- * Note that if a proxy is used, then URLs other than http: can be accessed,
- * also, if we have trouble which is clearly specific to the proxy, then
- * we return DECLINED so that we can try another proxy. (Or the direct
- * route.)
- */
-PROXY_DECLARE (int) ap_proxy_http_handler(request_rec *r, proxy_server_conf *conf,
- char *url, const char *proxyname,
- apr_port_t proxyport)
-{
- request_rec *rp;
- const char *connectname;
- int connectport = 0;
- apr_sockaddr_t *uri_addr;
- apr_sockaddr_t *connect_addr;
- char server_portstr[32];
- apr_socket_t *sock;
- int i, len, backasswards, eos, close=0, failed=0, new=0;
- apr_status_t err, rv;
- apr_array_header_t *headers_in_array;
- apr_table_entry_t *headers_in;
- char buffer[HUGE_STRING_LEN];
- char *buf;
- conn_rec *origin;
- uri_components uri;
- proxy_conn_rec *backend;
-
- /* Note: Memory pool allocation.
- * A downstream keepalive connection is always connected to the existence
- * (or not) of an upstream keepalive connection. If this is not done then
- * load balancing against multiple backend servers breaks (one backend
- * server ends up taking 100% of the load), and the risk is run of
- * downstream keepalive connections being kept open unnecessarily. This
- * keeps webservers busy and ties up resources.
- *
- * As a result, we allocate all sockets out of the upstream connection
- * pool, and when we want to reuse a socket, we check first whether the
- * connection ID of the current upstream connection is the same as that
- * of the connection when the socket was opened.
- */
- apr_pool_t *p = r->connection->pool;
- conn_rec *c = r->connection;
- apr_bucket *e;
- apr_bucket_brigade *bb = apr_brigade_create(p);
-
- /* is it for us? */
- if (strncasecmp(url, "http:", 5)) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: HTTP: rejecting URL %s", url);
- return DECLINED; /* only interested in HTTP */
- }
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: HTTP: serving URL %s", url);
-
- /* create space for state information */
- backend = (proxy_conn_rec *) ap_get_module_config(c->conn_config, &proxy_http_module);
- if (!backend) {
- backend = ap_pcalloc(c->pool, sizeof(proxy_conn_rec));
- backend->connection = NULL;
- backend->hostname = NULL;
- backend->port = 0;
- ap_set_module_config(c->conn_config, &proxy_http_module, backend);
- }
-
- /*
- * Step One: Determine Who To Connect To
- *
- * Break up the URL to determine the host to connect to
- */
-
- /* we break the URL into host, port, uri */
- if (HTTP_OK != ap_parse_uri_components(p, url, &uri)) {
- return ap_proxyerror(r, HTTP_BAD_REQUEST,
- apr_pstrcat(p,"URI cannot be parsed: ", url, NULL));
- }
- if (!uri.port) {
- uri.port = ap_default_port_for_scheme(uri.scheme);
- }
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: HTTP connecting %s to %s:%d", url, uri.hostname, uri.port);
-
- /* do a DNS lookup for the destination host */
- /* see memory note above */
- err = apr_sockaddr_info_get(&uri_addr, apr_pstrdup(c->pool, uri.hostname), APR_UNSPEC, uri.port, 0, c->pool);
-
- /* allocate these out of the connection pool - the check on r->connection->id makes
- * sure that this string does not get accessed past the connection lifetime */
- /* are we connecting directly, or via a proxy? */
- if (proxyname) {
- connectname = apr_pstrdup(c->pool,proxyname);
- connectport = proxyport;
- /* see memory note above */
- err = apr_sockaddr_info_get(&connect_addr, connectname, APR_UNSPEC, connectport, 0, c->pool);
- }
- else {
- connectname = apr_pstrdup(c->pool, uri.hostname);
- connectport = uri.port;
- connect_addr = uri_addr;
- url = apr_pstrcat(p, uri.path, uri.query ? "?" : "",
- uri.query ? uri.query : "", uri.fragment ? "#" : "",
- uri.fragment ? uri.fragment : "", NULL);
- }
-
-
- /* Get the server port for the Via headers */
- {
- i = ap_get_server_port(r);
- if (ap_is_default_port(i,r)) {
- strcpy(server_portstr,"");
- } else {
- apr_snprintf(server_portstr, sizeof server_portstr, ":%d", i);
- }
- }
-
- /* check if ProxyBlock directive on this host */
- if (OK != ap_proxy_checkproxyblock(r, conf, uri_addr)) {
- return ap_proxyerror(r, HTTP_FORBIDDEN,
- "Connect to remote machine blocked");
- }
-
-
- /*
- * Step Two: Make the Connection
- *
- * We have determined who to connect to. Now make the connection, supporting
- * a KeepAlive connection.
- */
-
- /* get all the possible IP addresses for the destname and loop through them
- * until we get a successful connection
- */
- if (APR_SUCCESS != err) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY, apr_pstrcat(p,
- "DNS lookup failure for: ",
- connectname, NULL));
- }
-
- /* if a keepalive socket is already open, check whether it must stay
- * open, or whether it should be closed and a new socket created.
- */
- /* see memory note above */
- if (backend->connection) {
- if ((backend->connection->id == c->id) &&
- (backend->port == connectport) &&
- (backend->hostname) &&
- (!apr_strnatcasecmp(backend->hostname,connectname))) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: keepalive address match (keep original socket)");
- }
- else {
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: keepalive address mismatch / connection has"
- " changed (close old socket (%s/%s, %d/%d))",
- connectname, backend->hostname,
- connectport, backend->port);
- apr_socket_close(backend->connection->client_socket);
- backend->connection = NULL;
- }
- }
-
- /* get a socket - either a keepalive one, or a new one */
- new = 1;
- if ((backend->connection) && (backend->connection->id == c->id)) {
-
- /* use previous keepalive socket */
- origin = backend->connection;
- sock = origin->client_socket;
- new = 0;
-
- /* reset the connection filters */
- ap_proxy_reset_output_filters(origin);
-
- /* XXX FIXME: If the socket has since closed, change new to 1 so
- * a new socket is opened */
- }
- if (new) {
-
- /* create a new socket */
- backend->connection = NULL;
-
- /* see memory note above */
- if ((rv = apr_socket_create(&sock, APR_INET, SOCK_STREAM, c->pool)) != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
- "proxy: error creating socket");
- return HTTP_INTERNAL_SERVER_ERROR;
- }
-
-#if !defined(TPF) && !defined(BEOS)
- if (conf->recv_buffer_size > 0 && (rv = apr_setsocketopt(sock, APR_SO_RCVBUF,
- conf->recv_buffer_size))) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default");
- }
-#endif
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: socket has been created");
-
- /*
- * At this point we have a list of one or more IP addresses of
- * the machine to connect to. If configured, reorder this
- * list so that the "best candidate" is first try. "best
- * candidate" could mean the least loaded server, the fastest
- * responding server, whatever.
- *
- * For now we do nothing, ie we get DNS round robin.
- * XXX FIXME
- */
-
-
- /* try each IP address until we connect successfully */
- failed = 1;
- while (connect_addr) {
-
- /* make the connection out of the socket */
- rv = apr_connect(sock, connect_addr);
-
- /* if an error occurred, loop round and try again */
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
- "proxy: attempt to connect to %pI (%s) failed",
- connect_addr, connectname);
- connect_addr = connect_addr->next;
- continue;
- }
-
- /* if we get here, all is well */
- failed = 0;
- break;
- }
-
- /* handle a permanent error from the above loop */
- if (failed) {
- apr_socket_close(sock);
- if (proxyname) {
- return DECLINED;
- }
- else {
- return HTTP_BAD_GATEWAY;
- }
- }
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: socket is connected");
-
- /* the socket is now open, create a new backend server connection */
- origin = ap_new_connection(c->pool, r->server, sock, r->connection->id);
- if (!origin) {
- /* the peer reset the connection already; ap_new_connection()
- * closed the socket */
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: an error occurred creating a new connection to %pI (%s)", connect_addr, connectname);
- apr_socket_close(sock);
- return HTTP_INTERNAL_SERVER_ERROR;
- }
- backend->connection = origin;
- backend->hostname = apr_pstrdup(c->pool, connectname);
- backend->port = connectport;
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: connection complete");
-
- /* set up the connection filters */
- ap_proxy_pre_http_connection(origin, NULL);
-
- }
-
-
- /*
- * Step Three: Send the Request
- *
- * Send the HTTP/1.1 request to the remote server
- */
-
-
- /* strip connection listed hop-by-hop headers from the request */
- /* even though in theory a connection: close coming from the client
- * should not affect the connection to the server, it's unlikely
- * that subsequent client requests will hit this thread/process, so
- * we cancel server keepalive if the client does.
- */
- close += ap_proxy_liststr(apr_table_get(r->headers_in, "Connection"), "close");
- ap_proxy_clear_connection(p, r->headers_in);
- if (close) {
- apr_table_mergen(r->headers_in, "Connection", "close");
- origin->keepalive = 0;
- }
-
- buf = apr_pstrcat(p, r->method, " ", url, " HTTP/1.1" CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- if (uri.port_str && uri.port != DEFAULT_HTTP_PORT) {
- buf = apr_pstrcat(p, "Host: ", uri.hostname, ":", uri.port_str, CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- }
- else {
- buf = apr_pstrcat(p, "Host: ", uri.hostname, CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- }
-
- /* handle Via */
- if (conf->viaopt == via_block) {
- /* Block all outgoing Via: headers */
- apr_table_unset(r->headers_in, "Via");
- } else if (conf->viaopt != via_off) {
- /* Create a "Via:" request header entry and merge it */
- /* Generate outgoing Via: header with/without server comment: */
- apr_table_mergen(r->headers_in, "Via",
- (conf->viaopt == via_full)
- ? apr_psprintf(p, "%d.%d %s%s (%s)",
- HTTP_VERSION_MAJOR(r->proto_num),
- HTTP_VERSION_MINOR(r->proto_num),
- ap_get_server_name(r), server_portstr,
- AP_SERVER_BASEVERSION)
- : apr_psprintf(p, "%d.%d %s%s",
- HTTP_VERSION_MAJOR(r->proto_num),
- HTTP_VERSION_MINOR(r->proto_num),
- ap_get_server_name(r), server_portstr)
- );
- }
-
- /* X-Forwarded-*: handling
- *
- * XXX Privacy Note:
- * -----------------
- *
- * These request headers are only really useful when the mod_proxy
- * is used in a reverse proxy configuration, so that useful info
- * about the client can be passed through the reverse proxy and on
- * to the backend server, which may require the information to
- * function properly.
- *
- * In a forward proxy situation, these options are a potential
- * privacy violation, as information about clients behind the proxy
- * are revealed to arbitrary servers out there on the internet.
- *
- * The HTTP/1.1 Via: header is designed for passing client
- * information through proxies to a server, and should be used in
- * a forward proxy configuation instead of X-Forwarded-*. See the
- * ProxyVia option for details.
- */
-
- if (PROXYREQ_REVERSE == r->proxyreq) {
- const char *buf;
-
- /* Add X-Forwarded-For: so that the upstream has a chance to
- * determine, where the original request came from.
- */
- apr_table_mergen(r->headers_in, "X-Forwarded-For", r->connection->remote_ip);
-
- /* Add X-Forwarded-Host: so that upstream knows what the
- * original request hostname was.
- */
- if ((buf = apr_table_get(r->headers_in, "Host"))) {
- apr_table_mergen(r->headers_in, "X-Forwarded-Host", buf);
- }
-
- /* Add X-Forwarded-Server: so that upstream knows what the
- * name of this proxy server is (if there are more than one)
- * XXX: This duplicates Via: - do we strictly need it?
- */
- apr_table_mergen(r->headers_in, "X-Forwarded-Server",
- r->server->server_hostname);
- }
-
- /* send request headers */
- headers_in_array = apr_table_elts(r->headers_in);
- headers_in = (apr_table_entry_t *) headers_in_array->elts;
- for (i = 0; i < headers_in_array->nelts; i++) {
- if (headers_in[i].key == NULL || headers_in[i].val == NULL
-
- /* Clear out hop-by-hop request headers not to send
- * RFC2616 13.5.1 says we should strip these headers
- */
- || !apr_strnatcasecmp(headers_in[i].key, "Host") /* Already sent */
- || !apr_strnatcasecmp(headers_in[i].key, "Keep-Alive")
- || !apr_strnatcasecmp(headers_in[i].key, "TE")
- || !apr_strnatcasecmp(headers_in[i].key, "Trailer")
- || !apr_strnatcasecmp(headers_in[i].key, "Transfer-Encoding")
- || !apr_strnatcasecmp(headers_in[i].key, "Upgrade")
-
- /* XXX: @@@ FIXME: "Proxy-Authorization" should *only* be
- * suppressed if THIS server requested the authentication,
- * not when a frontend proxy requested it!
- *
- * The solution to this problem is probably to strip out
- * the Proxy-Authorisation header in the authorisation
- * code itself, not here. This saves us having to signal
- * somehow whether this request was authenticated or not.
- */
- || !apr_strnatcasecmp(headers_in[i].key, "Proxy-Authorization")
- || !apr_strnatcasecmp(headers_in[i].key, "Proxy-Authenticate"))
- continue;
-
- buf = apr_pstrcat(p, headers_in[i].key, ": ", headers_in[i].val, CRLF, NULL);
- e = apr_bucket_pool_create(buf, strlen(buf), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
-
- }
-
- /* add empty line at the end of the headers */
- e = apr_bucket_pool_create(CRLF, strlen(CRLF), p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
-
- ap_pass_brigade(origin->output_filters, bb);
-
- /* send the request data, if any. */
- if (ap_should_client_block(r)) {
- while ((i = ap_get_client_block(r, buffer, sizeof buffer)) > 0) {
- e = apr_bucket_pool_create(buffer, i, p);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(origin->output_filters, bb);
- apr_brigade_cleanup(bb);
- }
- }
-
-
- /*
- * Step Four: Receive the Response
- *
- * Get response from the remote server, and pass it up the
- * filter chain
- */
-
- rp = make_fake_req(origin, r);
-
- apr_brigade_cleanup(bb);
-
- if (APR_SUCCESS != (rv = ap_proxy_string_read(origin, bb, buffer, sizeof(buffer), &eos))) {
- apr_socket_close(sock);
- backend->connection = NULL;
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "proxy: error reading status line from remote server %s",
- connectname);
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- "Error reading from remote server");
- }
- len = strlen(buffer);
-
- /* Is it an HTTP/1 response? This is buggy if we ever see an HTTP/1.10 */
- if (ap_checkmask(buffer, "HTTP/#.# ###*")) {
- int major, minor;
-
- if (2 != sscanf(buffer, "HTTP/%u.%u", &major, &minor)) {
- major = 1;
- minor = 1;
- }
-
- /* If not an HTTP/1 message or if the status line was > 8192 bytes */
- else if ((buffer[5] != '1') || (len >= sizeof(buffer)-1)) {
- apr_socket_close(sock);
- backend->connection = NULL;
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- apr_pstrcat(p, "Corrupt status line returned by remote server: ", buffer, NULL));
- }
- backasswards = 0;
- buffer[--len] = '\0';
-
- buffer[12] = '\0';
- r->status = atoi(&buffer[9]);
-
- buffer[12] = ' ';
- r->status_line = apr_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. */
-
- r->headers_out = ap_proxy_read_headers(r, rp, buffer, sizeof(buffer), origin);
- if (r->headers_out == NULL) {
- ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server,
- "proxy: bad HTTP/%d.%d header returned by %s (%s)",
- major, minor, r->uri, r->method);
- close += 1;
- }
- else
- {
- /* strip connection listed hop-by-hop headers from response */
- const char *buf;
- close += ap_proxy_liststr(apr_table_get(r->headers_out, "Connection"), "close");
- ap_proxy_clear_connection(p, r->headers_out);
- if ((buf = apr_table_get(r->headers_out, "Content-Type"))) {
- r->content_type = apr_pstrdup(p, buf);
- }
- }
-
- /* handle Via header in response */
- if (conf->viaopt != via_off && conf->viaopt != via_block) {
- /* create a "Via:" response header entry and merge it */
- ap_table_mergen(r->headers_out, "Via",
- (conf->viaopt == via_full)
- ? apr_psprintf(p, "%d.%d %s%s (%s)",
- HTTP_VERSION_MAJOR(r->proto_num),
- HTTP_VERSION_MINOR(r->proto_num),
- ap_get_server_name(r), server_portstr,
- AP_SERVER_BASEVERSION)
- : apr_psprintf(p, "%d.%d %s%s",
- HTTP_VERSION_MAJOR(r->proto_num),
- HTTP_VERSION_MINOR(r->proto_num),
- ap_get_server_name(r), server_portstr)
- );
- }
-
- /* cancel keepalive if HTTP/1.0 or less */
- if ((major < 1) || (minor < 1)) {
- close += 1;
- origin->keepalive = 0;
- }
- }
- else {
- /* an http/0.9 response */
- backasswards = 1;
- r->status = 200;
- r->status_line = "200 OK";
- close += 1;
- }
-
- /* we must accept 3 kinds of date, but generate only 1 kind of date */
- {
- const char *buf;
- if ((buf = apr_table_get(r->headers_out, "Date")) != NULL) {
- apr_table_set(r->headers_out, "Date", ap_proxy_date_canon(p, buf));
- }
- if ((buf = apr_table_get(r->headers_out, "Expires")) != NULL) {
- apr_table_set(r->headers_out, "Expires", ap_proxy_date_canon(p, buf));
- }
- if ((buf = apr_table_get(r->headers_out, "Last-Modified")) != NULL) {
- apr_table_set(r->headers_out, "Last-Modified", ap_proxy_date_canon(p, buf));
- }
- }
-
- /* munge the Location and URI response headers according to ProxyPassReverse */
- {
- const char *buf;
- if ((buf = apr_table_get(r->headers_out, "Location")) != NULL) {
- apr_table_set(r->headers_out, "Location", ap_proxy_location_reverse_map(r, conf, buf));
- }
- if ((buf = apr_table_get(r->headers_out, "Content-Location")) != NULL) {
- apr_table_set(r->headers_out, "Content-Location", ap_proxy_location_reverse_map(r, conf, buf));
- }
- if ((buf = apr_table_get(r->headers_out, "URI")) != NULL) {
- apr_table_set(r->headers_out, "URI", ap_proxy_location_reverse_map(r, conf, buf));
- }
- }
-
- r->sent_bodyct = 1;
- /* Is it an HTTP/0.9 response? If so, send the extra data */
- if (backasswards) {
- apr_ssize_t cntr = len;
- e = apr_bucket_heap_create(buffer, cntr, 0, NULL);
- APR_BRIGADE_INSERT_TAIL(bb, e);
- }
-
- /* send body - but only if a body is expected */
- if ((!r->header_only) && /* not HEAD request */
- (r->status > 199) && /* not any 1xx response */
- (r->status != HTTP_NO_CONTENT) && /* not 204 */
- (r->status != HTTP_RESET_CONTENT) && /* not 205 */
- (r->status != HTTP_NOT_MODIFIED)) { /* not 304 */
-
- const char *buf;
- apr_size_t readbytes;
-
- /* if chunked - insert DECHUNK filter */
- if (ap_proxy_liststr((buf = apr_table_get(r->headers_out, "Transfer-Encoding")), "chunked")) {
- rp->read_chunked = 1;
- apr_table_unset(r->headers_out, "Transfer-Encoding");
- if ((buf = ap_proxy_removestr(r->pool, buf, "chunked"))) {
- apr_table_set(r->headers_out, "Transfer-Encoding", buf);
- }
- ap_add_input_filter("DECHUNK", NULL, rp, origin);
- readbytes = -1;
- }
-
- /* if content length - set the length to read */
- else if ((buf = apr_table_get(r->headers_out, "Content-Length"))) {
- readbytes = atol(buf);
- }
-
- /* no chunked / no length therefore read till EOF and cancel keepalive */
- else {
- close += 1;
- }
-
- /* if keepalive cancelled, read to EOF */
- if (close) {
- readbytes = -1;
- }
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: start body send");
-
- /* read the body, pass it to the output filters */
- while (ap_get_brigade(rp->input_filters, bb, AP_MODE_BLOCKING, &readbytes) == APR_SUCCESS) {
- if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) {
- e = apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(bb, e);
- ap_pass_brigade(r->output_filters, bb);
- break;
- }
- ap_pass_brigade(r->output_filters, bb);
- apr_brigade_cleanup(bb);
- }
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: end body send");
- }
- else {
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: header only");
- }
-
-
- /*
- * Step Five: Clean Up
- *
- * If there are no KeepAlives, or if the connection has been signalled
- * to close, close the socket and clean up
- */
-
- /* if the connection is < HTTP/1.1, or Connection: close,
- * we close the socket, otherwise we leave it open for KeepAlive support
- */
- if (close || (r->proto_num < HTTP_VERSION(1,1))) {
- apr_socket_close(sock);
- backend->connection = NULL;
- }
-
- return OK;
-}
-
-static void ap_proxy_http_register_hook(apr_pool_t *p)
-{
- proxy_hook_scheme_handler(ap_proxy_http_handler, NULL, NULL, APR_HOOK_FIRST);
- proxy_hook_canon_handler(ap_proxy_http_canon, NULL, NULL, APR_HOOK_FIRST);
-}
-
-module AP_MODULE_DECLARE_DATA proxy_http_module = {
- STANDARD20_MODULE_STUFF,
- NULL, /* create per-directory config structure */
- NULL, /* merge per-directory config structures */
- NULL, /* create per-server config structure */
- NULL, /* merge per-server config structures */
- NULL, /* command apr_table_t */
- ap_proxy_http_register_hook /* register hooks */
-};
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
deleted file mode 100644
index b51feb1a11..0000000000
--- a/modules/proxy/proxy_util.c
+++ /dev/null
@@ -1,1187 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/* Utility routines for Apache proxy */
-#include "mod_proxy.h"
-
-
-static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r);
-static int proxy_match_domainname(struct dirconn_entry *This, request_rec *r);
-static int proxy_match_hostname(struct dirconn_entry *This, request_rec *r);
-static int proxy_match_word(struct dirconn_entry *This, request_rec *r);
-static struct per_thread_data *get_per_thread_data(void);
-
-/* already called in the knowledge that the characters are hex digits */
-int ap_proxy_hex2c(const char *x)
-{
- int i, ch;
-
-#if !APR_CHARSET_EBCDIC
- ch = x[0];
- if (apr_isdigit(ch))
- i = ch - '0';
- else if (apr_isupper(ch))
- i = ch - ('A' - 10);
- else
- i = ch - ('a' - 10);
- i <<= 4;
-
- ch = x[1];
- if (apr_isdigit(ch))
- i += ch - '0';
- else if (apr_isupper(ch))
- i += ch - ('A' - 10);
- else
- i += ch - ('a' - 10);
- return i;
-#else /*APR_CHARSET_EBCDIC*/
- return (1 == sscanf(x, "%2x", &i)) ? os_toebcdic[i&0xFF] : 0;
-#endif /*APR_CHARSET_EBCDIC*/
-}
-
-void ap_proxy_c2hex(int ch, char *x)
-{
-#if !APR_CHARSET_EBCDIC
- int i;
-
- x[0] = '%';
- i = (ch & 0xF0) >> 4;
- if (i >= 10)
- x[1] = ('A' - 10) + i;
- else
- x[1] = '0' + i;
-
- i = ch & 0x0F;
- if (i >= 10)
- x[2] = ('A' - 10) + i;
- else
- x[2] = '0' + i;
-#else /*APR_CHARSET_EBCDIC*/
- static const char ntoa[] = { "0123456789ABCDEF" };
- ch &= 0xFF;
- x[0] = '%';
- x[1] = ntoa[(os_toascii[ch]>>4)&0x0F];
- x[2] = ntoa[os_toascii[ch]&0x0F];
- x[3] = '\0';
-#endif /*APR_CHARSET_EBCDIC*/
-}
-
-/*
- * canonicalise a URL-encoded string
- */
-
-/*
- * Convert a URL-encoded string to canonical form.
- * It decodes characters which need not be encoded,
- * and encodes those which must be encoded, and does not touch
- * those which must not be touched.
- */
-char *ap_proxy_canonenc(apr_pool_t *p, const char *x, int len, enum enctype t,
- int isenc)
-{
- int i, j, ch;
- char *y;
- char *allowed; /* characters which should not be encoded */
- char *reserved; /* characters which much not be en/de-coded */
-
-/* N.B. in addition to :@&=, this allows ';' in an http path
- * and '?' in an ftp path -- this may be revised
- *
- * Also, it makes a '+' character in a search string reserved, as
- * it may be form-encoded. (Although RFC 1738 doesn't allow this -
- * it only permits ; / ? : @ = & as reserved chars.)
- */
- if (t == enc_path)
- allowed = "$-_.+!*'(),;:@&=";
- else if (t == enc_search)
- allowed = "$-_.!*'(),;:@&=";
- else if (t == enc_user)
- allowed = "$-_.+!*'(),;@&=";
- else if (t == enc_fpath)
- allowed = "$-_.+!*'(),?:@&=";
- else /* if (t == enc_parm) */
- allowed = "$-_.+!*'(),?/:@&=";
-
- if (t == enc_path)
- reserved = "/";
- else if (t == enc_search)
- reserved = "+";
- else
- reserved = "";
-
- y = apr_palloc(p, 3 * len + 1);
-
- for (i = 0, j = 0; i < len; i++, j++) {
-/* always handle '/' first */
- ch = x[i];
- if (strchr(reserved, ch)) {
- y[j] = ch;
- continue;
- }
-/* decode it if not already done */
- if (isenc && ch == '%') {
- if (!ap_isxdigit(x[i + 1]) || !ap_isxdigit(x[i + 2]))
- return NULL;
- ch = ap_proxy_hex2c(&x[i + 1]);
- i += 2;
- if (ch != 0 && strchr(reserved, ch)) { /* keep it encoded */
- ap_proxy_c2hex(ch, &y[j]);
- j += 2;
- continue;
- }
- }
-/* recode it, if necessary */
- if (!apr_isalnum(ch) && !strchr(allowed, ch)) {
- ap_proxy_c2hex(ch, &y[j]);
- j += 2;
- }
- else
- y[j] = ch;
- }
- y[j] = '\0';
- return y;
-}
-
-/*
- * Parses network-location.
- * urlp on input the URL; on output the path, after the leading /
- * user NULL if no user/password permitted
- * password holder for password
- * host holder for host
- * port port number; only set if one is supplied.
- *
- * Returns an error string.
- */
-char *
- ap_proxy_canon_netloc(apr_pool_t *p, char **const urlp, char **userp,
- char **passwordp, char **hostp, apr_port_t *port)
-{
- apr_port_t i;
- char *strp, *host, *url = *urlp;
- char *user = NULL, *password = NULL;
-
- if (url[0] != '/' || url[1] != '/')
- return "Malformed URL";
- host = url + 2;
- url = strchr(host, '/');
- if (url == NULL)
- url = "";
- else
- *(url++) = '\0'; /* skip seperating '/' */
-
- /* find _last_ '@' since it might occur in user/password part */
- strp = strrchr(host, '@');
-
- if (strp != NULL) {
- *strp = '\0';
- user = host;
- host = strp + 1;
-
-/* find password */
- strp = strchr(user, ':');
- if (strp != NULL) {
- *strp = '\0';
- password = ap_proxy_canonenc(p, strp + 1, strlen(strp + 1), enc_user, 1);
- if (password == NULL)
- return "Bad %-escape in URL (password)";
- }
-
- user = ap_proxy_canonenc(p, user, strlen(user), enc_user, 1);
- if (user == NULL)
- return "Bad %-escape in URL (username)";
- }
- if (userp != NULL) {
- *userp = user;
- }
- if (passwordp != NULL) {
- *passwordp = password;
- }
-
- strp = strrchr(host, ':');
- if (strp != NULL) {
- *(strp++) = '\0';
-
- for (i = 0; strp[i] != '\0'; i++)
- if (!apr_isdigit(strp[i]))
- break;
-
- /* if (i == 0) the no port was given; keep default */
- if (strp[i] != '\0') {
- return "Bad port number in URL";
- } else if (i > 0) {
- *port = atoi(strp);
- if (*port > 65535)
- return "Port number in URL > 65535";
- }
- }
- ap_str_tolower(host); /* DNS names are case-insensitive */
- if (*host == '\0')
- return "Missing host in URL";
-/* check hostname syntax */
- for (i = 0; host[i] != '\0'; i++)
- if (!apr_isdigit(host[i]) && host[i] != '.')
- break;
- /* must be an IP address */
-#if defined(WIN32) || defined(NETWARE) || defined(TPF) || defined(BEOS)
- if (host[i] == '\0' && (inet_addr(host) == -1))
-#else
- if (host[i] == '\0' && (ap_inet_addr(host) == -1 || inet_network(host) == -1))
-#endif
- {
- return "Bad IP address in URL";
- }
-
-/* if (strchr(host,'.') == NULL && domain != NULL)
- host = pstrcat(p, host, domain, NULL);
- */
- *urlp = url;
- *hostp = host;
-
- return NULL;
-}
-
-static const char * const lwday[7] =
-{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
-
-/*
- * If the date is a valid RFC 850 date or asctime() date, then it
- * is converted to the RFC 1123 format, otherwise it is not modified.
- * This routine is not very fast at doing conversions, as it uses
- * sscanf and sprintf. However, if the date is already correctly
- * formatted, then it exits very quickly.
- */
-const char *
- ap_proxy_date_canon(apr_pool_t *p, const char *x1)
-{
- char *x = apr_pstrdup(p, x1);
- int wk, mday, year, hour, min, sec, mon;
- char *q, month[4], zone[4], week[4];
-
- q = strchr(x, ',');
- /* check for RFC 850 date */
- if (q != NULL && q - x > 3 && q[1] == ' ') {
- *q = '\0';
- for (wk = 0; wk < 7; wk++)
- if (strcmp(x, lwday[wk]) == 0)
- break;
- *q = ',';
- if (wk == 7)
- return x; /* not a valid date */
- if (q[4] != '-' || q[8] != '-' || q[11] != ' ' || q[14] != ':' ||
- q[17] != ':' || strcmp(&q[20], " GMT") != 0)
- return x;
- if (sscanf(q + 2, "%u-%3s-%u %u:%u:%u %3s", &mday, month, &year,
- &hour, &min, &sec, zone) != 7)
- return x;
- if (year < 70)
- year += 2000;
- else
- year += 1900;
- }
- else {
-/* check for acstime() date */
- if (x[3] != ' ' || x[7] != ' ' || x[10] != ' ' || x[13] != ':' ||
- x[16] != ':' || x[19] != ' ' || x[24] != '\0')
- return x;
- if (sscanf(x, "%3s %3s %u %u:%u:%u %u", week, month, &mday, &hour,
- &min, &sec, &year) != 7)
- return x;
- for (wk = 0; wk < 7; wk++)
- if (strcmp(week, ap_day_snames[wk]) == 0)
- break;
- if (wk == 7)
- return x;
- }
-
-/* check date */
- for (mon = 0; mon < 12; mon++)
- if (strcmp(month, ap_month_snames[mon]) == 0)
- break;
- if (mon == 12)
- return x;
-
- q = apr_palloc(p, 30);
- apr_snprintf(q, 30, "%s, %.2d %s %d %.2d:%.2d:%.2d GMT", ap_day_snames[wk],
- mday, ap_month_snames[mon], year, hour, min, sec);
- return q;
-}
-
-request_rec *make_fake_req(conn_rec *c, request_rec *r)
-{
- request_rec *rp = apr_pcalloc(c->pool, sizeof(*r));
- core_request_config *req_cfg;
-
- rp->pool = c->pool;
- rp->status = HTTP_OK;
-
- rp->headers_in = apr_table_make(c->pool, 50);
- rp->subprocess_env = apr_table_make(c->pool, 50);
- rp->headers_out = apr_table_make(c->pool, 12);
- rp->err_headers_out = apr_table_make(c->pool, 5);
- rp->notes = apr_table_make(c->pool, 5);
-
- rp->server = r->server;
- rp->request_time = r->request_time;
- rp->connection = c;
- rp->output_filters = c->output_filters;
- rp->input_filters = c->input_filters;
-
- rp->request_config = ap_create_request_config(c->pool);
- req_cfg = apr_pcalloc(rp->pool, sizeof(core_request_config));
- req_cfg->bb = apr_brigade_create(c->pool);
- ap_set_module_config(rp->request_config, &core_module, req_cfg);
-
- return rp;
-}
-
-/*
- * Reads headers from a buffer and returns an array of headers.
- * Returns NULL on file error
- * This routine tries to deal with too long lines and continuation lines.
- * @@@: XXX: FIXME: currently the headers are passed thru un-merged.
- * Is that okay, or should they be collapsed where possible?
- */
-apr_table_t *ap_proxy_read_headers(request_rec *r, request_rec *rr, char *buffer, int size, conn_rec *c)
-{
- apr_table_t *headers_out;
- int len;
- char *value, *end;
- char field[MAX_STRING_LEN];
-
- headers_out = ap_make_table(r->pool, 20);
-
- /*
- * Read header lines until we get the empty separator line, a read error,
- * the connection closes (EOF), or we timeout.
- */
- while ((len = ap_getline(buffer, size, rr, 1)) > 0) {
-
- if (!(value = strchr(buffer, ':'))) { /* Find the colon separator */
-
- /* Buggy MS IIS servers sometimes return invalid headers
- * (an extra "HTTP/1.0 200, OK" line sprinkled in between
- * the usual MIME headers). Try to deal with it in a sensible
- * way, but log the fact.
- * XXX: The mask check is buggy if we ever see an HTTP/1.10 */
-
- if (!ap_checkmask(buffer, "HTTP/#.# ###*")) {
- /* Nope, it wasn't even an extra HTTP header. Give up. */
- return NULL;
- }
-
- ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server,
- "proxy: Ignoring duplicate HTTP header "
- "returned by %s (%s)", r->uri, r->method);
- continue;
- }
-
- *value = '\0';
- ++value;
- /* XXX: RFC2068 defines only SP and HT as whitespace, this test is
- * wrong... and so are many others probably.
- */
- while (apr_isspace(*value))
- ++value; /* Skip to start of value */
-
- /* should strip trailing whitespace as well */
- for (end = &value[strlen(value)-1]; end > value && apr_isspace(*end); --end)
- *end = '\0';
-
- apr_table_add(headers_out, buffer, value);
-
- /* the header was too long; at the least we should skip extra data */
- if (len >= size - 1) {
- while ((len = ap_getline(field, MAX_STRING_LEN, rr, 1))
- >= MAX_STRING_LEN - 1) {
- /* soak up the extra data */
- }
- if (len == 0) /* time to exit the larger loop as well */
- break;
- }
- }
- return headers_out;
-}
-
-
-/*
- * list is a comma-separated list of case-insensitive tokens, with
- * optional whitespace around the tokens.
- * The return returns 1 if the token val is found in the list, or 0
- * otherwise.
- */
-int ap_proxy_liststr(const char *list, const char *val)
-{
- int len, i;
- const char *p;
-
- len = strlen(val);
-
- while (list != NULL) {
- p = ap_strchr_c(list, ',');
- if (p != NULL) {
- i = p - list;
- do
- p++;
- while (apr_isspace(*p));
- }
- else
- i = strlen(list);
-
- while (i > 0 && apr_isspace(list[i - 1]))
- i--;
- if (i == len && strncasecmp(list, val, len) == 0)
- return 1;
- list = p;
- }
- return 0;
-}
-
-/*
- * list is a comma-separated list of case-insensitive tokens, with
- * optional whitespace around the tokens.
- * The return returns 1 if the token val is found in the list, or 0
- * otherwise.
- */
-char *ap_proxy_removestr(apr_pool_t *pool, const char *list, const char *val)
-{
- int len, i;
- const char *p;
- char *new = NULL;
-
- len = strlen(val);
-
- while (list != NULL) {
- p = ap_strchr_c(list, ',');
- if (p != NULL) {
- i = p - list;
- do
- p++;
- while (apr_isspace(*p));
- }
- else
- i = strlen(list);
-
- while (i > 0 && apr_isspace(list[i - 1]))
- i--;
- if (i == len && strncasecmp(list, val, len) == 0) {
- /* do nothing */
- }
- else {
- if (new)
- new = apr_pstrcat(pool, new, ",", apr_pstrndup(pool, list, i), NULL);
- else
- new = apr_pstrndup(pool, list, i);
- }
- list = p;
- }
- return new;
-}
-
-/*
- * Converts 8 hex digits to a time integer
- */
-int ap_proxy_hex2sec(const char *x)
-{
- int i, ch;
- unsigned int j;
-
- for (i = 0, j = 0; i < 8; i++) {
- ch = x[i];
- j <<= 4;
- if (apr_isdigit(ch))
- j |= ch - '0';
- else if (apr_isupper(ch))
- j |= ch - ('A' - 10);
- else
- j |= ch - ('a' - 10);
- }
- if (j == 0xffffffff)
- return -1; /* so that it works with 8-byte ints */
- else
- return j;
-}
-
-/*
- * Converts a time integer to 8 hex digits
- */
-void ap_proxy_sec2hex(int t, char *y)
-{
- int i, ch;
- unsigned int j = t;
-
- for (i = 7; i >= 0; i--) {
- ch = j & 0xF;
- j >>= 4;
- if (ch >= 10)
- y[i] = ch + ('A' - 10);
- else
- y[i] = ch + '0';
- }
- y[8] = '\0';
-}
-
-int ap_proxyerror(request_rec *r, int statuscode, const char *message)
-{
- apr_table_setn(r->notes, "error-notes",
- apr_pstrcat(r->pool,
- "The proxy server could not handle the request "
- "<EM><A HREF=\"", ap_escape_uri(r->pool, r->uri),
- "\">", ap_escape_html(r->pool, r->method),
- "&nbsp;",
- ap_escape_html(r->pool, r->uri), "</A></EM>.<P>\n"
- "Reason: <STRONG>",
- ap_escape_html(r->pool, message),
- "</STRONG>", NULL));
-
- /* Allow "error-notes" string to be printed by ap_send_error_response() */
- apr_table_setn(r->notes, "verbose-error-to", apr_pstrdup(r->pool, "*"));
-
- r->status_line = apr_psprintf(r->pool, "%3.3u Proxy Error", statuscode);
- return statuscode;
-}
-
-/*
- * This routine returns its own error message
- */
-const char *ap_proxy_host2addr(const char *host, struct hostent *reqhp)
-{
- int i;
- struct hostent *hp;
- struct per_thread_data *ptd = get_per_thread_data();
-
- for (i = 0; host[i] != '\0'; i++)
- if (!apr_isdigit(host[i]) && host[i] != '.')
- break;
-
- if (host[i] != '\0') {
- hp = gethostbyname(host);
- if (hp == NULL)
- return "Host not found";
- }
- else {
- ptd->ipaddr = ap_inet_addr(host);
- hp = gethostbyaddr((char *) &ptd->ipaddr, sizeof(ptd->ipaddr), AF_INET);
- if (hp == NULL) {
- memset(&ptd->hpbuf, 0, sizeof(ptd->hpbuf));
- ptd->hpbuf.h_name = 0;
- ptd->hpbuf.h_addrtype = AF_INET;
- ptd->hpbuf.h_length = sizeof(ptd->ipaddr);
- ptd->hpbuf.h_addr_list = ptd->charpbuf;
- ptd->hpbuf.h_addr_list[0] = (char *) &ptd->ipaddr;
- ptd->hpbuf.h_addr_list[1] = 0;
- hp = &ptd->hpbuf;
- }
- }
- *reqhp = *hp;
- return NULL;
-}
-
-static const char *
- proxy_get_host_of_request(request_rec *r)
-{
- char *url, *user = NULL, *password = NULL, *err, *host;
- apr_port_t port = -1;
-
- if (r->hostname != NULL)
- return r->hostname;
-
- /* Set url to the first char after "scheme://" */
- if ((url = strchr(r->uri, ':')) == NULL
- || url[1] != '/' || url[2] != '/')
- return NULL;
-
- url = apr_pstrdup(r->pool, &url[1]); /* make it point to "//", which is what proxy_canon_netloc expects */
-
- err = ap_proxy_canon_netloc(r->pool, &url, &user, &password, &host, &port);
-
- if (err != NULL)
- ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,
- "%s", err);
-
- r->hostname = host;
-
- return host; /* ought to return the port, too */
-}
-
-/* Return TRUE if addr represents an IP address (or an IP network address) */
-int ap_proxy_is_ipaddr(struct dirconn_entry *This, apr_pool_t *p)
-{
- const char *addr = This->name;
- long ip_addr[4];
- int i, quads;
- long bits;
-
- /* if the address is given with an explicit netmask, use that */
- /* Due to a deficiency in ap_inet_addr(), it is impossible to parse */
- /* "partial" addresses (with less than 4 quads) correctly, i.e. */
- /* 192.168.123 is parsed as 192.168.0.123, which is not what I want. */
- /* I therefore have to parse the IP address manually: */
- /*if (proxy_readmask(This->name, &This->addr.s_addr, &This->mask.s_addr) == 0) */
- /* addr and mask were set by proxy_readmask() */
- /*return 1; */
-
- /* Parse IP addr manually, optionally allowing */
- /* abbreviated net addresses like 192.168. */
-
- /* Iterate over up to 4 (dotted) quads. */
- for (quads = 0; quads < 4 && *addr != '\0'; ++quads) {
- char *tmp;
-
- if (*addr == '/' && quads > 0) /* netmask starts here. */
- break;
-
- if (!apr_isdigit(*addr))
- return 0; /* no digit at start of quad */
-
- ip_addr[quads] = strtol(addr, &tmp, 0);
-
- if (tmp == addr) /* expected a digit, found something else */
- return 0;
-
- if (ip_addr[quads] < 0 || ip_addr[quads] > 255) {
- /* invalid octet */
- return 0;
- }
-
- addr = tmp;
-
- if (*addr == '.' && quads != 3)
- ++addr; /* after the 4th quad, a dot would be illegal */
- }
-
- for (This->addr.s_addr = 0, i = 0; i < quads; ++i)
- This->addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i));
-
- if (addr[0] == '/' && apr_isdigit(addr[1])) { /* net mask follows: */
- char *tmp;
-
- ++addr;
-
- bits = strtol(addr, &tmp, 0);
-
- if (tmp == addr) /* expected a digit, found something else */
- return 0;
-
- addr = tmp;
-
- if (bits < 0 || bits > 32) /* netmask must be between 0 and 32 */
- return 0;
-
- }
- else {
- /* Determine (i.e., "guess") netmask by counting the */
- /* number of trailing .0's; reduce #quads appropriately */
- /* (so that 192.168.0.0 is equivalent to 192.168.) */
- while (quads > 0 && ip_addr[quads - 1] == 0)
- --quads;
-
- /* "IP Address should be given in dotted-quad form, optionally followed by a netmask (e.g., 192.168.111.0/24)"; */
- if (quads < 1)
- return 0;
-
- /* every zero-byte counts as 8 zero-bits */
- bits = 8 * quads;
-
- if (bits != 32) /* no warning for fully qualified IP address */
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Warning: NetMask not supplied with IP-Addr; guessing: %s/%ld\n",
- inet_ntoa(This->addr), bits);
- }
-
- This->mask.s_addr = htonl(APR_INADDR_NONE << (32 - bits));
-
- if (*addr == '\0' && (This->addr.s_addr & ~This->mask.s_addr) != 0) {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "Warning: NetMask and IP-Addr disagree in %s/%ld\n",
- inet_ntoa(This->addr), bits);
- This->addr.s_addr &= This->mask.s_addr;
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- " Set to %s/%ld\n",
- inet_ntoa(This->addr), bits);
- }
-
- if (*addr == '\0') {
- This->matcher = proxy_match_ipaddr;
- return 1;
- }
- else
- return (*addr == '\0'); /* okay iff we've parsed the whole string */
-}
-
-/* Return TRUE if addr represents an IP address (or an IP network address) */
-static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r)
-{
- int i;
- int ip_addr[4];
- struct in_addr addr;
- struct in_addr *ip_list;
- char **ip_listptr;
- const char *found;
- const char *host = proxy_get_host_of_request(r);
-
- if (host == NULL) /* oops! */
- return 0;
-
- memset(&addr, '\0', sizeof addr);
- memset(ip_addr, '\0', sizeof ip_addr);
-
- if (4 == sscanf(host, "%d.%d.%d.%d", &ip_addr[0], &ip_addr[1], &ip_addr[2], &ip_addr[3])) {
- for (addr.s_addr = 0, i = 0; i < 4; ++i)
- addr.s_addr |= htonl(ip_addr[i] << (24 - 8 * i));
-
- if (This->addr.s_addr == (addr.s_addr & This->mask.s_addr)) {
-#if DEBUGGING
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "1)IP-Match: %s[%s] <-> ", host, inet_ntoa(addr));
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "%s/", inet_ntoa(This->addr));
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "%s", inet_ntoa(This->mask));
-#endif
- return 1;
- }
-#if DEBUGGING
- else {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "1)IP-NoMatch: %s[%s] <-> ", host, inet_ntoa(addr));
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "%s/", inet_ntoa(This->addr));
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "%s", inet_ntoa(This->mask));
- }
-#endif
- }
- else {
- struct hostent the_host;
-
- memset(&the_host, '\0', sizeof the_host);
- found = ap_proxy_host2addr(host, &the_host);
-
- if (found != NULL) {
-#if DEBUGGING
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "2)IP-NoMatch: hostname=%s msg=%s", host, found);
-#endif
- return 0;
- }
-
- if (the_host.h_name != NULL)
- found = the_host.h_name;
- else
- found = host;
-
- /* Try to deal with multiple IP addr's for a host */
- for (ip_listptr = the_host.h_addr_list; *ip_listptr; ++ip_listptr) {
- ip_list = (struct in_addr *) *ip_listptr;
- if (This->addr.s_addr == (ip_list->s_addr & This->mask.s_addr)) {
-#if DEBUGGING
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "3)IP-Match: %s[%s] <-> ", found, inet_ntoa(*ip_list));
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "%s/", inet_ntoa(This->addr));
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "%s", inet_ntoa(This->mask));
-#endif
- return 1;
- }
-#if DEBUGGING
- else {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "3)IP-NoMatch: %s[%s] <-> ", found, inet_ntoa(*ip_list));
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "%s/", inet_ntoa(This->addr));
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "%s", inet_ntoa(This->mask));
- }
-#endif
- }
- }
-
- return 0;
-}
-
-/* Return TRUE if addr represents a domain name */
-int ap_proxy_is_domainname(struct dirconn_entry *This, apr_pool_t *p)
-{
- char *addr = This->name;
- int i;
-
- /* Domain name must start with a '.' */
- if (addr[0] != '.')
- return 0;
-
- /* rfc1035 says DNS names must consist of "[-a-zA-Z0-9]" and '.' */
- for (i = 0; apr_isalnum(addr[i]) || addr[i] == '-' || addr[i] == '.'; ++i)
- continue;
-
-#if 0
- if (addr[i] == ':') {
- ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
- "@@@@ handle optional port in proxy_is_domainname()");
- /* @@@@ handle optional port */
- }
-#endif
-
- if (addr[i] != '\0')
- return 0;
-
- /* Strip trailing dots */
- for (i = strlen(addr) - 1; i > 0 && addr[i] == '.'; --i)
- addr[i] = '\0';
-
- This->matcher = proxy_match_domainname;
- return 1;
-}
-
-/* Return TRUE if host "host" is in domain "domain" */
-static int proxy_match_domainname(struct dirconn_entry *This, request_rec *r)
-{
- const char *host = proxy_get_host_of_request(r);
- int d_len = strlen(This->name), h_len;
-
- if (host == NULL) /* some error was logged already */
- return 0;
-
- h_len = strlen(host);
-
- /* @@@ do this within the setup? */
- /* Ignore trailing dots in domain comparison: */
- while (d_len > 0 && This->name[d_len - 1] == '.')
- --d_len;
- while (h_len > 0 && host[h_len - 1] == '.')
- --h_len;
- return h_len > d_len
- && strncasecmp(&host[h_len - d_len], This->name, d_len) == 0;
-}
-
-/* Create a copy of a "struct hostent" record; it was presumably returned
- * from a call to gethostbyname() and lives in static storage.
- * By creating a copy we can tuck it away for later use.
- */
-static struct hostent * pduphostent(apr_pool_t *p, const struct hostent *hp)
-{
- struct hostent *newent;
- char **ptrs;
- char **aliases;
- struct in_addr *addrs;
- int i = 0, j = 0;
-
- if (hp == NULL)
- return NULL;
-
- /* Count number of alias entries */
- if (hp->h_aliases != NULL)
- for (; hp->h_aliases[j] != NULL; ++j)
- continue;
-
- /* Count number of in_addr entries */
- if (hp->h_addr_list != NULL)
- for (; hp->h_addr_list[i] != NULL; ++i)
- continue;
-
- /* Allocate hostent structure, alias ptrs, addr ptrs, addrs */
- newent = (struct hostent *) apr_palloc(p, sizeof(*hp));
- aliases = (char **) apr_palloc(p, (j+1) * sizeof(char*));
- ptrs = (char **) apr_palloc(p, (i+1) * sizeof(char*));
- addrs = (struct in_addr *) apr_palloc(p, (i+1) * sizeof(struct in_addr));
-
- *newent = *hp;
- newent->h_name = apr_pstrdup(p, hp->h_name);
- newent->h_aliases = aliases;
- newent->h_addr_list = (char**) ptrs;
-
- /* Copy Alias Names: */
- for (j = 0; hp->h_aliases[j] != NULL; ++j) {
- aliases[j] = apr_pstrdup(p, hp->h_aliases[j]);
- }
- aliases[j] = NULL;
-
- /* Copy address entries */
- for (i = 0; hp->h_addr_list[i] != NULL; ++i) {
- ptrs[i] = (char*) &addrs[i];
- addrs[i] = *(struct in_addr *) hp->h_addr_list[i];
- }
- ptrs[i] = NULL;
-
- return newent;
-}
-
-/* Return TRUE if addr represents a host name */
-int ap_proxy_is_hostname(struct dirconn_entry *This, apr_pool_t *p)
-{
- struct hostent host;
- char *addr = This->name;
- int i;
-
- /* Host names must not start with a '.' */
- if (addr[0] == '.')
- return 0;
-
- /* rfc1035 says DNS names must consist of "[-a-zA-Z0-9]" and '.' */
- for (i = 0; apr_isalnum(addr[i]) || addr[i] == '-' || addr[i] == '.'; ++i);
-
- if (addr[i] != '\0' || ap_proxy_host2addr(addr, &host) != NULL)
- return 0;
-
- This->hostentry = pduphostent (p, &host);
-
- /* Strip trailing dots */
- for (i = strlen(addr) - 1; i > 0 && addr[i] == '.'; --i)
- addr[i] = '\0';
-
- This->matcher = proxy_match_hostname;
- return 1;
-}
-
-/* Return TRUE if host "host" is equal to host2 "host2" */
-static int proxy_match_hostname(struct dirconn_entry *This, request_rec *r)
-{
- char *host = This->name;
- const char *host2 = proxy_get_host_of_request(r);
- int h2_len;
- int h1_len;
-
- if (host == NULL || host2 == NULL)
- return 0; /* oops! */
-
- h2_len = strlen(host2);
- h1_len = strlen(host);
-
-#if 0
- unsigned long *ip_list;
-
- /* Try to deal with multiple IP addr's for a host */
- for (ip_list = *This->hostentry->h_addr_list; *ip_list != 0UL; ++ip_list)
- if (*ip_list == ? ? ? ? ? ? ? ? ? ? ? ? ?)
- return 1;
-#endif
-
- /* Ignore trailing dots in host2 comparison: */
- while (h2_len > 0 && host2[h2_len - 1] == '.')
- --h2_len;
- while (h1_len > 0 && host[h1_len - 1] == '.')
- --h1_len;
- return h1_len == h2_len
- && strncasecmp(host, host2, h1_len) == 0;
-}
-
-/* Return TRUE if addr is to be matched as a word */
-int ap_proxy_is_word(struct dirconn_entry *This, apr_pool_t *p)
-{
- This->matcher = proxy_match_word;
- return 1;
-}
-
-/* Return TRUE if string "str2" occurs literally in "str1" */
-static int proxy_match_word(struct dirconn_entry *This, request_rec *r)
-{
- const char *host = proxy_get_host_of_request(r);
- return host != NULL && ap_strstr_c(host, This->name) != NULL;
-}
-
-/* checks whether a host in uri_addr matches proxyblock */
-int ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf,
- apr_sockaddr_t *uri_addr)
-{
- int j;
- /* XXX FIXME: conf->noproxies->elts is part of an opaque structure */
- for (j = 0; j < conf->noproxies->nelts; j++) {
- struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts;
- struct apr_sockaddr_t *conf_addr = npent[j].addr;
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: checking remote machine [%s] against [%s]", uri_addr->hostname, npent[j].name);
- if ((npent[j].name && ap_strstr_c(uri_addr->hostname, npent[j].name))
- || npent[j].name[0] == '*') {
- ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server,
- "proxy: connect to remote machine %s blocked: name %s matched", uri_addr->hostname, npent[j].name);
- return HTTP_FORBIDDEN;
- }
- while (conf_addr) {
- while (uri_addr) {
- char *conf_ip;
- char *uri_ip;
- apr_sockaddr_ip_get(&conf_ip, conf_addr);
- apr_sockaddr_ip_get(&uri_ip, uri_addr);
- ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
- "proxy: ProxyBlock comparing %s and %s", conf_ip, uri_ip);
- if (!apr_strnatcasecmp(conf_ip, uri_ip)) {
- ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r->server,
- "proxy: connect to remote machine %s blocked: IP %s matched", uri_addr->hostname, conf_ip);
- return HTTP_FORBIDDEN;
- }
- uri_addr = uri_addr->next;
- }
- conf_addr = conf_addr->next;
- }
- }
- return OK;
-}
-
-/* set up the minimal filter set */
-int ap_proxy_pre_http_connection(conn_rec *c, request_rec *r)
-{
- ap_add_input_filter("HTTP_IN", NULL, r, c);
- ap_add_input_filter("CORE_IN", NULL, r, c);
- ap_add_output_filter("CORE", NULL, r, c);
- return OK;
-}
-
-/* converts a series of buckets into a string */
-apr_status_t ap_proxy_string_read(conn_rec *c, apr_bucket_brigade *bb,
- char *buff, size_t bufflen, int *eos)
-{
- apr_bucket *e;
- apr_status_t rv;
- apr_size_t readbytes = 0; /* line-at-a-time */
- char *pos = buff;
- char *response;
- int found = 0;
- apr_size_t len;
-
- /* start with an empty string */
- buff[0] = 0;
- *eos = 0;
-
- /* loop through each brigade */
- while (!found) {
-
- /* get brigade from network one line at a time */
- if (APR_SUCCESS != (rv = ap_get_brigade(c->input_filters, bb, AP_MODE_BLOCKING, &readbytes))) {
- return rv;
- }
-
- /* loop through each bucket */
- while (!found && !APR_BRIGADE_EMPTY(bb)) {
- e = APR_BRIGADE_FIRST(bb);
- if (APR_BUCKET_IS_EOS(e)) {
- *eos = 1;
- }
- if (APR_SUCCESS != apr_bucket_read(e, (const char **)&response, &len, APR_BLOCK_READ)) {
- return rv;
- }
- /* is string LF terminated? */
- if (memchr(response, APR_ASCII_LF, len)) {
- found = 1;
- }
- /* concat strings until buff is full - then throw the data away */
- if (len > ((bufflen-1)-(pos-buff))) {
- len = (bufflen-1)-(pos-buff);
- }
- if (len > 0) {
- pos = apr_cpystrn(pos, response, len);
- }
- APR_BUCKET_REMOVE(e);
- apr_bucket_destroy(e);
- }
- }
-
- return APR_SUCCESS;
-
-}
-
-/* remove other filters (like DECHUNK) from filter stack */
-void ap_proxy_reset_output_filters(conn_rec *c)
-{
- ap_filter_t *f = c->output_filters;
-
- while (f) {
- if (!strcasecmp(f->frec->name, "CORE") ||
- !strcasecmp(f->frec->name, "CONTENT_LENGTH") ||
- !strcasecmp(f->frec->name, "HTTP_HEADER")) {
- f = f->next;
- continue;
- }
- else {
- ap_remove_output_filter(f);
- f = f->next;
- }
- }
-}
-
-#if defined WIN32
-
-static DWORD tls_index;
-
-BOOL WINAPI DllMain (HINSTANCE dllhandle, DWORD reason, LPVOID reserved)
-{
- LPVOID memptr;
-
- switch (reason) {
- case DLL_PROCESS_ATTACH:
- tls_index = TlsAlloc();
- case DLL_THREAD_ATTACH: /* intentional no break */
- TlsSetValue (tls_index, malloc (sizeof (struct per_thread_data)));
- break;
- case DLL_THREAD_DETACH:
- memptr = TlsGetValue (tls_index);
- if (memptr) {
- free (memptr);
- TlsSetValue (tls_index, 0);
- }
- break;
- }
-
- return TRUE;
-}
-
-#endif
-
-static struct per_thread_data *get_per_thread_data(void)
-{
- return NULL;
-}
diff --git a/modules/ssl/.cvsignore b/modules/ssl/.cvsignore
deleted file mode 100644
index 65f0cc30cf..0000000000
--- a/modules/ssl/.cvsignore
+++ /dev/null
@@ -1,10 +0,0 @@
-.deps
-.libs
-*.la
-modules.mk
-Makefile
-*.lo
-*.slo
-*.so
-Debug
-Release
diff --git a/modules/ssl/README b/modules/ssl/README
deleted file mode 100644
index ca9e225bf8..0000000000
--- a/modules/ssl/README
+++ /dev/null
@@ -1,163 +0,0 @@
- _ _
- _ __ ___ ___ __| | ___ ___| |
- | '_ ` _ \ / _ \ / _` | / __/ __| |
- | | | | | | (_) | (_| | \__ \__ \ | ``mod_ssl combines the flexibility of
- |_| |_| |_|\___/ \__,_|___|___/___/_| Apache with the security of OpenSSL.''
- |_____|
- mod_ssl ``Ralf Engelschall has released an
- Apache Interface to OpenSSL excellent module that integrates
- http://www.modssl.org/ Apache and SSLeay.''
- Version 2.8 -- Tim J. Hudson
-
- SYNOPSIS
-
- This Apache module provides strong cryptography for the Apache 1.3 webserver
- via the Secure Sockets Layer (SSL v2/v3) and Transport Layer Security (TLS
- v1) protocols by the help of the SSL/TLS implementation library OpenSSL which
- is based on SSLeay from Eric A. Young and Tim J. Hudson. The mod_ssl package
- was created in April 1998 by Ralf S. Engelschall and was originally derived
- from software developed by Ben Laurie for use in the Apache-SSL HTTP server
- project.
-
- SOURCES
-
- Here is a short overview of the source files:
-
- Makefile.libdir ......... dummy for Apache config mechanism
- Makefile.tmpl ........... Makefile template for Unix platform
- Makefile.win32 .......... Makefile template for Win32 platform
- libssl.module ........... stub called from the Apache config mechanism
- libssl.version .......... file containing the mod_ssl version information
- mod_ssl.c ............... main source file containing API structures
- mod_ssl.h ............... common header file of mod_ssl
- ssl_engine_compat.c ..... backward compatibility support
- ssl_engine_config.c ..... module configuration handling
- ssl_engine_dh.c ......... DSA/DH support
- ssl_engine_ds.c ......... data structures
- ssl_engine_ext.c ........ Extensions to other Apache parts
- ssl_engine_init.c ....... module initialization
- ssl_engine_io.c ......... I/O support
- ssl_engine_kernel.c ..... SSL engine kernel
- ssl_engine_log.c ........ logfile support
- ssl_engine_mutex.c ...... mutual exclusion support
- ssl_engine_pphrase.c .... pass-phrase handling
- ssl_engine_rand.c ....... PRNG support
- ssl_engine_vars.c ....... Variable Expansion support
- ssl_expr.c .............. expression handling main source
- ssl_expr.h .............. expression handling common header
- ssl_expr_scan.c ......... expression scanner automaton (pre-generated)
- ssl_expr_scan.l ......... expression scanner source
- ssl_expr_parse.c ........ expression parser automaton (pre-generated)
- ssl_expr_parse.h ........ expression parser header (pre-generated)
- ssl_expr_parse.y ........ expression parser source
- ssl_expr_eval.c ......... expression machine evaluation
- ssl_scache.c ............ session cache abstraction layer
- ssl_scache_dbm.c ........ session cache via DBM file
- ssl_scache_shmcb.c ...... session cache via shared memory cyclic buffer
- ssl_scache_shmht.c ...... session cache via shared memory hash table
- ssl_util.c .............. utility functions
- ssl_util_ssl.c .......... the OpenSSL companion source
- ssl_util_ssl.h .......... the OpenSSL companion header
- ssl_util_sdbm.c ......... the SDBM library source
- ssl_util_sdbm.h ......... the SDBM library header
- ssl_util_table.c ........ the hash table library source
- ssl_util_table.h ........ the hash table library header
-
- The source files are written in clean ANSI C and pass the ``gcc -O -g
- -ggdb3 -Wall -Wshadow -Wpointer-arith -Wcast-align -Wmissing-prototypes
- -Wmissing-declarations -Wnested-externs -Winline'' compiler test
- (assuming `gcc' is GCC 2.95.2 or newer) without any complains. When
- you make changes or additions make sure the source still passes this
- compiler test.
-
- FUNCTIONS
-
- Inside the source code you will be confronted with the following types of
- functions which can be identified by their prefixes:
-
- ap_xxxx() ............... Apache API function
- ssl_xxxx() .............. mod_ssl function
- SSL_xxxx() .............. OpenSSL function (SSL library)
- OpenSSL_xxxx() .......... OpenSSL function (SSL library)
- X509_xxxx() ............. OpenSSL function (Crypto library)
- PEM_xxxx() .............. OpenSSL function (Crypto library)
- EVP_xxxx() .............. OpenSSL function (Crypto library)
- RSA_xxxx() .............. OpenSSL function (Crypto library)
-
- DATA STRUCTURES
-
- Inside the source code you will be confronted with the following
- data structures:
-
- ap_ctx .................. Apache EAPI Context
- server_rec .............. Apache (Virtual) Server
- conn_rec ................ Apache Connection
- BUFF .................... Apache Connection Buffer
- request_rec ............. Apache Request
- SSLModConfig ............ mod_ssl (Global) Module Configuration
- SSLSrvConfig ............ mod_ssl (Virtual) Server Configuration
- SSLDirConfig ............ mod_ssl Directory Configuration
- SSL_CTX ................. OpenSSL Context
- SSL_METHOD .............. OpenSSL Protocol Method
- SSL_CIPHER .............. OpenSSL Cipher
- SSL_SESSION ............. OpenSSL Session
- SSL ..................... OpenSSL Connection
- BIO ..................... OpenSSL Connection Buffer
-
- For an overview how these are related and chained together have a look at the
- page in README.dsov.{fig,ps}. It contains overview diagrams for those data
- structures. It's designed for DIN A4 paper size, but you can easily generate
- a smaller version inside XFig by specifing a magnification on the Export
- panel.
-
- EXPERIMENTAL CODE
-
- Experimental code is always encapsulated as following:
-
- | #ifdef SSL_EXPERIMENTAL_xxxx
- | ...
- | #endif
-
- This way it is only compiled in when this define is enabled with
- the APACI --enable-rule=SSL_EXPERIMENTAL option and as long as the
- C pre-processor variable SSL_EXPERIMENTAL_xxxx_IGNORE is _NOT_
- defined (via CFLAGS). Or in other words: SSL_EXPERIMENTAL enables all
- SSL_EXPERIMENTAL_xxxx variables, except if SSL_EXPERIMENTAL_xxxx_IGNORE
- is already defined. Currently the following features are experimental:
-
- o SSL_EXPERIMENTAL_PERDIRCA
- The ability to use SSLCACertificateFile and SSLCACertificatePath
- in a per-directory context (.htaccess). This is provided by some nasty
- reconfiguration hacks until OpenSSL has better support for this. It
- should work on non-multithreaded platforms (all but Win32).
-
- o SSL_EXPERIMENTAL_PROXY
- The ability to use various additional SSLProxyXXX directives in
- oder to control extended client functionality in the HTTPS proxy
- code.
-
- o SSL_EXPERIMENTAL_ENGINE
- The ability to support the new forthcoming OpenSSL ENGINE stuff.
- Until this development branch of OpenSSL is merged into the main
- stream, you have to use openssl-engine-0.9.x.tar.gz for this.
- mod_ssl automatically recognizes this OpenSSL variant and then can
- activate external crypto devices through SSLCryptoDevice directive.
-
- VENDOR EXTENSIONS
-
- Inside the mod_ssl sources you can enable various EAPI vendor hooks
- (`ap::mod_ssl::vendor::xxxx') by using the APACI --enable-rule=SSL_VENDOR
- option. These hooks can be used to change or extend mod_ssl by a vendor
- without patching the source code. Grep for `ap::mod_ssl::vendor::'.
- Additionally vendors can add their own source code to files named
- ssl_vendor.c, ssl_vendor_XXX.c, etc. The libssl.module script automatically
- picks these up under configuration time and mod_ssl under run-time calls the
- functions `void ssl_vendor_register(void)' and `void
- ssl_vendor_unregister(void)' inside these objects to bootstrap them.
-
- An ssl_vendor.c should at least contain the following contents:
-
- | #include "mod_ssl.h"
- | void ssl_vendor_register(void) { return; }
- | void ssl_vendor_unregister(void) { return; }
-
diff --git a/modules/ssl/README.dsov.fig b/modules/ssl/README.dsov.fig
deleted file mode 100644
index d8d03db247..0000000000
--- a/modules/ssl/README.dsov.fig
+++ /dev/null
@@ -1,346 +0,0 @@
-#FIG 3.2
-Landscape
-Center
-Metric
-Letter
-100.00
-Single
--2
-1200 2
-0 32 #616561
-0 33 #b6b2b6
-0 34 #f7f3f7
-0 35 #cfcfcf
-0 36 #ffffff
-6 6345 2835 7155 3150
-6 6345 2970 7110 3150
-4 0 0 200 0 20 8 0.0000 4 120 585 6345 3105 "ssl_module")\001
--6
-4 0 0 200 0 20 8 0.0000 4 120 660 6345 2970 ap_ctx_get(...,\001
--6
-6 10800 2610 12240 3060
-4 0 0 200 0 20 8 0.0000 4 120 1170 10800 2745 ap_get_module_config(...\001
-4 0 0 200 0 20 8 0.0000 4 120 795 10800 2880 ->per_dir_config,\001
-4 0 0 200 0 20 8 0.0000 4 120 585 10800 3015 &ssl_module)\001
--6
-6 7920 4770 9135 4995
-2 4 0 1 35 35 200 0 20 0.000 0 0 4 0 0 5
- 9135 4995 7920 4995 7920 4770 9135 4770 9135 4995
-4 0 0 100 0 18 12 0.0000 4 180 1065 8010 4950 request_rec\001
--6
-2 1 0 1 0 34 200 0 20 0.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 6975 3330 7425 2520
-2 1 0 1 0 34 200 0 20 0.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 7200 4230 9450 2520
-2 1 0 1 0 34 200 0 20 0.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 7875 4905 7200 5220
-2 1 0 1 0 34 200 0 20 0.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 6750 5130 6750 4545
-2 1 0 1 0 34 200 0 20 0.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 6705 5445 7155 6120
-2 1 0 1 0 34 200 0 20 0.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 7875 4815 7200 4590
-2 1 0 1 0 34 200 0 20 0.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 9585 2565 11475 4230
-2 1 0 1 0 34 200 0 20 0.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 10170 5130 11835 4545
-2 1 0 1 0 34 200 0 20 0.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 7920 6075 9855 5400
-2 1 0 1 0 34 200 0 20 0.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 9990 5445 10935 5625
-2 1 0 1 0 34 200 0 20 0.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 10215 5310 10935 5310
-2 1 0 1 0 34 200 0 20 0.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 11925 4590 11925 5085
-2 1 0 1 0 34 200 0 20 0.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 9810 5490 9810 6840
-2 1 0 1 0 34 200 0 20 0.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 9945 5445 10935 6030
-2 1 0 1 0 34 200 0 20 0.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 8865 4725 10800 2565
-2 1 0 3 0 34 200 0 20 0.000 0 0 -1 0 0 2
- 675 6075 5850 6075
-2 1 2 1 0 34 200 0 20 1.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 675 6525 675 6075
-2 1 2 1 0 34 200 0 20 1.000 0 0 -1 1 0 2
- 1 0 1.00 60.00 120.00
- 5850 6075 5850 6525
-2 1 0 3 0 34 200 0 20 0.000 0 0 -1 0 0 2
- 900 5625 5625 5625
-2 1 0 3 0 34 200 0 20 0.000 0 0 -1 0 0 2
- 1125 5175 5400 5175
-2 1 0 3 0 34 200 0 20 0.000 0 0 -1 0 0 2
- 1350 4725 5175 4725
-2 1 0 3 0 34 200 0 20 0.000 0 0 -1 0 0 2
- 1575 4275 4950 4275
-2 1 0 3 0 34 200 0 20 0.000 0 0 -1 0 0 2
- 1800 3825 4725 3825
-2 1 0 3 0 34 200 0 20 0.000 0 0 -1 0 0 2
- 2025 3375 4500 3375
-2 1 0 3 0 34 200 0 20 0.000 0 0 -1 0 0 2
- 2250 2925 4275 2925
-2 1 0 3 0 34 200 0 20 0.000 0 0 -1 0 0 2
- 2475 2475 4050 2475
-2 1 0 3 0 34 200 0 20 0.000 0 0 -1 0 0 2
- 2700 2025 3825 2025
-2 1 0 3 0 34 200 0 20 0.000 0 0 -1 0 0 2
- 2925 1575 3600 1575
-2 1 2 1 0 34 200 0 20 1.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 900 6075 900 5625
-2 1 2 1 0 34 200 0 20 1.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 1125 6525 1125 5175
-2 1 2 1 0 34 200 0 20 1.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 1350 5175 1350 4725
-2 1 2 1 0 34 200 0 20 1.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 1575 4725 1575 4275
-2 1 2 1 0 34 200 0 20 1.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 1800 6525 1800 3825
-2 1 2 1 0 34 200 0 20 1.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 2025 3825 2025 3375
-2 1 2 1 0 34 200 0 20 1.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 2250 3375 2250 2925
-2 1 2 1 0 34 200 0 20 1.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 2475 2925 2475 2475
-2 1 2 1 0 34 200 0 20 1.000 0 0 -1 1 0 2
- 1 0 1.00 60.00 120.00
- 5625 5625 5625 6075
-2 1 2 1 0 34 200 0 20 1.000 0 0 -1 1 0 2
- 1 0 1.00 60.00 120.00
- 5400 5175 5400 6525
-2 1 2 1 0 34 200 0 20 1.000 0 0 -1 1 0 2
- 1 0 1.00 60.00 120.00
- 5175 4725 5175 5175
-2 1 2 1 0 34 200 0 20 1.000 0 0 -1 1 0 2
- 1 0 1.00 60.00 120.00
- 4950 4275 4950 4725
-2 1 2 1 0 34 200 0 20 1.000 0 0 -1 1 0 2
- 1 0 1.00 60.00 120.00
- 4725 3825 4725 6525
-2 1 2 1 0 34 200 0 20 1.000 0 0 -1 1 0 2
- 1 0 1.00 60.00 120.00
- 4500 3375 4500 3825
-2 1 2 1 0 34 200 0 20 1.000 0 0 -1 1 0 2
- 1 0 1.00 60.00 120.00
- 4275 2925 4275 3375
-2 1 2 1 0 34 200 0 20 1.000 0 0 -1 1 0 2
- 1 0 1.00 60.00 120.00
- 4050 2475 4050 2925
-2 1 2 1 0 34 200 0 20 1.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 2700 6525 2700 2025
-2 1 2 1 0 34 200 0 20 1.000 0 0 -1 1 0 2
- 1 0 1.00 60.00 120.00
- 3825 2025 3825 6525
-2 1 2 1 0 34 200 0 20 1.000 0 0 -1 1 0 2
- 1 0 1.00 60.00 120.00
- 3600 1575 3600 2025
-2 1 2 1 0 34 200 0 20 1.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 2925 2025 2925 1575
-2 1 0 4 0 0 200 0 20 0.000 0 0 -1 1 0 2
- 1 1 4.00 60.00 120.00
- 540 6525 6300 6525
-2 3 0 1 7 7 800 0 20 0.000 0 0 -1 0 0 9
- 675 6525 5850 6525 5850 6075 5625 6075 5625 5625 900 5625
- 900 6075 675 6075 675 6525
-2 3 0 1 34 34 700 0 20 0.000 0 0 -1 0 0 13
- 1125 6525 5355 6525 5400 5175 5175 5175 5175 4725 4950 4725
- 4950 4275 1575 4275 1575 4725 1350 4725 1350 5175 1125 5175
- 1125 6525
-2 3 0 1 35 35 500 0 20 0.000 0 0 -1 0 0 17
- 1800 6525 4725 6525 4725 3825 4500 3825 4500 3375 4275 3375
- 4275 2925 4050 2925 4050 2475 2475 2475 2475 2925 2250 2925
- 2250 3375 2025 3375 2025 3825 1800 3825 1800 6525
-2 3 0 1 33 33 400 0 20 0.000 0 0 -1 0 0 9
- 2700 6525 3825 6525 3825 2025 3600 2025 3600 1575 2925 1575
- 2925 2025 2700 2025 2700 6525
-2 1 0 1 0 34 200 0 20 0.000 0 0 -1 1 1 2
- 2 0 1.00 60.00 120.00
- 2 0 1.00 60.00 120.00
- 2700 6750 3825 6750
-2 1 0 1 0 34 200 0 20 0.000 0 0 -1 1 1 2
- 2 0 1.00 60.00 120.00
- 2 0 1.00 60.00 120.00
- 1125 7200 5400 7200
-2 1 0 1 0 34 200 0 20 0.000 0 0 -1 1 1 2
- 2 0 1.00 60.00 120.00
- 2 0 1.00 60.00 120.00
- 1800 6975 4725 6975
-2 1 0 1 0 34 200 0 20 0.000 0 0 -1 1 1 2
- 2 0 1.00 60.00 120.00
- 2 0 1.00 60.00 120.00
- 675 7425 5850 7425
-2 1 2 1 0 34 200 0 20 3.000 0 1 -1 0 0 2
- 675 6570 675 7650
-2 1 2 1 0 34 200 0 20 3.000 0 1 -1 0 0 2
- 1125 6570 1125 7650
-2 1 2 1 0 34 200 0 20 3.000 0 1 -1 0 0 2
- 1800 6570 1800 7650
-2 1 2 1 0 34 200 0 20 3.000 0 1 -1 0 0 2
- 2700 6570 2700 7650
-2 1 2 1 0 34 200 0 20 3.000 0 1 -1 0 0 2
- 3825 6570 3825 7650
-2 1 2 1 0 34 200 0 20 3.000 0 1 -1 0 0 2
- 4725 6570 4725 7650
-2 1 2 1 0 34 200 0 20 3.000 0 1 -1 0 0 2
- 5400 6570 5400 7650
-2 1 2 1 0 34 200 0 20 3.000 0 1 -1 0 0 2
- 5850 6570 5850 7650
-2 4 0 2 0 7 100 0 -1 0.000 0 0 20 0 0 5
- 12600 8550 450 8550 450 225 12600 225 12600 8550
-2 4 0 1 0 34 200 0 20 0.000 0 0 20 0 0 5
- 12600 1350 450 1350 450 225 12600 225 12600 1350
-2 4 0 1 35 35 200 0 20 0.000 0 0 4 0 0 5
- 10170 2475 8775 2475 8775 2250 10170 2250 10170 2475
-2 4 0 1 35 35 200 0 20 0.000 0 0 4 0 0 5
- 11925 2475 10575 2475 10575 2250 11925 2250 11925 2475
-2 4 0 1 35 35 200 0 20 0.000 0 0 4 0 0 5
- 12375 4500 11430 4500 11430 4275 12375 4275 12375 4500
-2 4 0 1 35 35 200 0 20 0.000 0 0 4 0 0 5
- 12375 5400 10980 5400 10980 5175 12375 5175 12375 5400
-2 4 0 1 35 35 200 0 20 0.000 0 0 4 0 0 5
- 10170 5400 9675 5400 9675 5175 10170 5175 10170 5400
-2 4 0 1 35 35 200 0 20 0.000 0 0 4 0 0 5
- 7875 6300 7200 6300 7200 6075 7875 6075 7875 6300
-2 4 0 1 35 35 200 0 20 0.000 0 0 4 0 0 5
- 8190 2475 6750 2475 6750 2250 8190 2250 8190 2475
-2 4 0 1 35 35 200 0 20 0.000 0 0 4 0 0 5
- 7605 3600 6300 3600 6300 3375 7605 3375 7605 3600
-2 4 0 1 35 35 200 0 20 0.000 0 0 4 0 0 5
- 7335 4500 6300 4500 6300 4275 7335 4275 7335 4500
-2 4 0 1 35 35 200 0 20 0.000 0 0 4 0 0 5
- 7200 5400 6300 5400 6300 5175 7200 5175 7200 5400
-2 1 0 6 7 7 600 0 -1 0.000 0 0 -1 0 0 2
- 9450 4500 6075 1935
-2 1 0 6 7 7 600 0 -1 0.000 0 0 4 0 0 2
- 9450 4500 12465 2205
-2 1 0 6 7 7 600 0 -1 0.000 0 0 4 0 0 2
- 9450 4500 9450 7785
-2 1 0 1 0 34 200 0 20 0.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 9630 5310 7245 5310
-2 1 0 1 0 34 200 0 20 0.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 11385 4365 7380 4365
-2 4 0 1 35 35 200 0 20 0.000 0 0 4 0 0 5
- 12240 5805 10980 5805 10980 5580 12240 5580 12240 5805
-2 4 0 1 35 35 200 0 20 0.000 0 0 4 0 0 5
- 12375 6210 10980 6210 10980 5985 12375 5985 12375 6210
-2 1 0 1 0 34 200 0 20 0.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 11205 6885 9900 5445
-2 4 0 1 35 35 200 0 20 0.000 0 0 4 0 0 5
- 12285 7155 10530 7155 10530 6930 12285 6930 12285 7155
-2 4 0 1 35 35 200 0 20 0.000 0 0 4 0 0 5
- 10170 7155 9630 7155 9630 6930 10170 6930 10170 7155
-2 1 0 6 7 7 600 0 -1 0.000 0 0 4 0 0 2
- 12510 6435 9450 6435
-2 1 0 1 0 34 300 0 20 0.000 0 0 7 1 0 4
- 1 1 1.00 60.00 120.00
- 12375 4455 12510 4635 12510 6210 11970 6885
-2 1 2 1 0 34 200 0 20 1.000 0 0 -1 1 0 2
- 1 1 1.00 60.00 120.00
- 9850 5143 9175 4918
-3 1 0 1 34 34 800 0 20 0.000 0 0 0 41
- 7380 1710 6390 2115 5535 2115 6075 3015 5670 3465 6165 3915
- 5715 4410 6030 5040 6030 5310 6480 5715 6390 6255 6975 6300
- 7065 6975 7965 6750 8100 7560 8955 7290 9360 7740 9720 7560
- 10755 8145 12060 8280 12375 7650 12420 7200 12510 7065 12330 6660
- 12510 6390 12420 5940 12375 5400 12510 5220 12510 4725 12600 4275
- 12375 3645 12105 3240 12150 2745 12375 2700 12330 1980 11790 1575
- 11250 1935 10125 1485 8955 2070 7785 1620 7695 1575
- 1.000 1.000 1.000 1.000 1.000 1.000 1.000 1.000
- 1.000 1.000 1.000 1.000 1.000 1.000 1.000 1.000
- 1.000 1.000 1.000 1.000 1.000 1.000 1.000 1.000
- 1.000 1.000 1.000 1.000 1.000 1.000 1.000 1.000
- 1.000 1.000 1.000 1.000 1.000 1.000 1.000 1.000
- 1.000
-4 0 0 100 0 0 12 0.0000 4 180 1440 10575 675 Ralf S. Engelschall\001
-4 0 0 100 0 18 20 0.0000 4 270 3840 4275 675 Apache+mod_ssl+OpenSSL\001
-4 0 0 100 0 0 10 0.0000 4 135 1320 10575 855 rse@engelschall.com\001
-4 0 0 100 0 0 10 0.0000 4 135 1410 10575 1035 www.engelschall.com\001
-4 0 0 100 0 0 12 0.0000 4 135 870 900 675 Version 1.3\001
-4 0 0 100 0 0 12 0.0000 4 180 1035 900 855 12-Apr-1999\001
-4 0 0 200 0 20 8 0.0000 4 60 390 6210 4680 ->server\001
-4 0 0 200 0 20 8 0.0000 4 120 855 8280 6120 ap_ctx_get(...,"ssl")\001
-4 0 0 200 0 20 8 0.0000 4 120 1170 7740 2700 ap_get_module_config(...\001
-4 0 0 200 0 20 8 0.0000 4 120 810 7740 2835 ->module_config,\001
-4 0 0 200 0 20 8 0.0000 4 120 585 7740 2970 &ssl_module)\001
-4 0 0 100 0 18 20 0.0000 4 270 1200 9000 8100 Chaining\001
-4 0 0 100 0 18 20 0.0000 4 210 1095 2745 8100 Lifetime\001
-4 0 0 100 0 18 12 0.0000 4 180 1215 810 6255 ap_global_ctx\001
-4 0 0 100 0 18 12 0.0000 4 180 1305 990 5805 SSLModConfig\001
-4 0 0 100 0 18 12 0.0000 4 180 840 4050 4455 SSL_CTX\001
-4 0 0 100 0 18 12 0.0000 4 150 975 4455 5355 server_rec\001
-4 0 0 100 0 18 12 0.0000 4 180 1260 3870 4905 SSLSrvConfig\001
-4 0 0 100 0 18 12 0.0000 4 135 480 1845 4005 BUFF\001
-4 0 0 100 0 18 12 0.0000 4 150 810 2070 3555 conn_rec\001
-4 0 0 100 0 18 12 0.0000 4 135 345 2295 3105 BIO\001
-4 0 0 100 0 18 12 0.0000 4 135 375 2565 2655 SSL\001
-4 0 0 100 0 18 12 0.0000 4 180 1185 3645 1620 SSLDirConfig\001
-4 0 0 100 0 18 12 0.0000 4 180 1065 3915 2070 request_rec\001
-4 0 0 200 0 0 8 0.0000 4 120 1440 900 7560 Startup, Runtime, Shutdown\001
-4 0 0 200 0 0 8 0.0000 4 105 975 1350 7335 Configuration Time\001
-4 0 0 200 0 0 8 0.0000 4 90 1050 2025 7110 Connection Duration\001
-4 0 0 200 0 0 8 0.0000 4 120 885 2835 6885 Request Duration\001
-4 0 0 200 0 18 20 0.0000 4 195 90 6345 6795 t\001
-4 0 0 200 0 20 8 0.0000 4 90 345 7110 5985 ->client\001
-4 0 0 100 0 18 12 0.0000 4 180 1305 6795 2430 SSLModConfig\001
-4 0 0 100 0 18 12 0.0000 4 180 1260 8865 2430 SSLSrvConfig\001
-4 0 0 100 0 18 12 0.0000 4 180 1215 6345 3555 ap_global_ctx\001
-4 0 0 100 0 18 12 0.0000 4 150 975 6345 4455 server_rec\001
-4 0 0 100 0 18 12 0.0000 4 150 810 6345 5355 conn_rec\001
-4 0 0 100 0 18 12 0.0000 4 135 375 9720 5355 SSL\001
-4 0 0 100 0 18 12 0.0000 4 180 1185 10665 2430 SSLDirConfig\001
-4 0 0 100 0 18 12 0.0000 4 135 480 7290 6255 BUFF\001
-4 0 0 100 0 18 12 0.0000 4 180 1305 11025 5355 SSL_METHOD\001
-4 0 0 100 0 18 12 0.0000 4 180 840 11475 4455 SSL_CTX\001
-4 0 0 100 0 18 24 0.0000 4 285 4365 3915 1080 Data Structure Overview\001
-4 0 0 200 0 20 8 0.0000 4 90 615 7065 5085 ->connection\001
-4 0 0 200 0 20 8 0.0000 4 60 390 7065 4770 ->server\001
-4 0 0 200 0 20 8 0.0000 4 120 960 8010 5445 SSL_get_app_data()\001
-4 0 0 200 0 20 8 0.0000 4 120 510 10530 4050 ->pSSLCtx\001
-4 0 0 200 0 20 8 0.0000 4 120 1215 7875 4275 SSL_CTX_get_app_data()\001
-4 0 0 200 0 20 8 0.0000 4 120 1155 10305 5535 SSL_get_current_cipher()\001
-4 0 0 100 0 18 12 0.0000 4 180 1170 11025 5760 SSL_CIPHER\001
-4 0 0 100 0 18 12 0.0000 4 180 1350 10980 6165 SSL_SESSION\001
-4 0 0 200 0 20 8 0.0000 4 120 840 10440 5940 SSL_get_session()\001
-4 0 0 100 0 18 12 0.0000 4 180 1665 10575 7110 X509_STORE_CTX\001
-4 0 0 100 0 18 12 0.0000 4 135 345 9720 7110 BIO\001
-4 0 0 200 0 20 8 0.0000 4 120 840 9540 7335 SSL_get_{r,w}bio()\001
-4 0 0 100 0 18 20 0.0000 4 270 1170 8730 3465 mod_ssl\001
-4 0 0 100 0 18 20 0.0000 4 270 1050 8145 6750 Apache\001
-4 0 0 200 0 20 8 0.0000 4 120 945 10125 4680 SSL_get_SSL_CTX()\001
-4 0 0 200 0 20 8 0.0000 4 120 1170 10350 5175 SSL_get_SSL_METHOD()\001
-4 0 0 200 0 20 8 0.0000 4 90 465 11745 4770 ->method\001
-4 0 0 200 0 20 8 0.0000 4 120 1665 9945 6480 X509_STORE_CTX_get_app_data()\001
-4 0 0 200 0 20 8 0.0000 4 120 1215 10980 6705 SSL_CTX_get_cert_store()\001
-4 0 0 200 0 20 8 0.0000 4 120 1020 8280 5130 SSL_get_app_data2()\001
-4 0 0 100 0 18 20 0.0000 4 270 1290 10710 7605 OpenSSL\001
-4 0 0 100 0 18 12 0.0000 4 180 720 10710 7785 [Crypto]\001
-4 0 0 100 0 18 20 0.0000 4 270 1290 10935 3645 OpenSSL\001
-4 0 0 100 0 18 12 0.0000 4 180 495 10935 3825 [SSL]\001
diff --git a/modules/ssl/README.dsov.ps b/modules/ssl/README.dsov.ps
deleted file mode 100644
index def19dbecf..0000000000
--- a/modules/ssl/README.dsov.ps
+++ /dev/null
@@ -1,1138 +0,0 @@
-%!PS-Adobe-2.0
-%%Title: README.dsov.ps
-%%Creator: fig2dev Version 3.2 Patchlevel 1
-%%CreationDate: Mon Apr 12 17:09:11 1999
-%%For: rse@en1.engelschall.com (Ralf S. Engelschall)
-%%Orientation: Landscape
-%%BoundingBox: 59 37 553 755
-%%Pages: 1
-%%BeginSetup
-%%IncludeFeature: *PageSize Letter
-%%EndSetup
-%%Magnification: 0.9340
-%%EndComments
-/$F2psDict 200 dict def
-$F2psDict begin
-$F2psDict /mtrx matrix put
-/col-1 {0 setgray} bind def
-/col0 {0.000 0.000 0.000 srgb} bind def
-/col1 {0.000 0.000 1.000 srgb} bind def
-/col2 {0.000 1.000 0.000 srgb} bind def
-/col3 {0.000 1.000 1.000 srgb} bind def
-/col4 {1.000 0.000 0.000 srgb} bind def
-/col5 {1.000 0.000 1.000 srgb} bind def
-/col6 {1.000 1.000 0.000 srgb} bind def
-/col7 {1.000 1.000 1.000 srgb} bind def
-/col8 {0.000 0.000 0.560 srgb} bind def
-/col9 {0.000 0.000 0.690 srgb} bind def
-/col10 {0.000 0.000 0.820 srgb} bind def
-/col11 {0.530 0.810 1.000 srgb} bind def
-/col12 {0.000 0.560 0.000 srgb} bind def
-/col13 {0.000 0.690 0.000 srgb} bind def
-/col14 {0.000 0.820 0.000 srgb} bind def
-/col15 {0.000 0.560 0.560 srgb} bind def
-/col16 {0.000 0.690 0.690 srgb} bind def
-/col17 {0.000 0.820 0.820 srgb} bind def
-/col18 {0.560 0.000 0.000 srgb} bind def
-/col19 {0.690 0.000 0.000 srgb} bind def
-/col20 {0.820 0.000 0.000 srgb} bind def
-/col21 {0.560 0.000 0.560 srgb} bind def
-/col22 {0.690 0.000 0.690 srgb} bind def
-/col23 {0.820 0.000 0.820 srgb} bind def
-/col24 {0.500 0.190 0.000 srgb} bind def
-/col25 {0.630 0.250 0.000 srgb} bind def
-/col26 {0.750 0.380 0.000 srgb} bind def
-/col27 {1.000 0.500 0.500 srgb} bind def
-/col28 {1.000 0.630 0.630 srgb} bind def
-/col29 {1.000 0.750 0.750 srgb} bind def
-/col30 {1.000 0.880 0.880 srgb} bind def
-/col31 {1.000 0.840 0.000 srgb} bind def
-/col32 {0.380 0.396 0.380 srgb} bind def
-/col33 {0.714 0.698 0.714 srgb} bind def
-/col34 {0.969 0.953 0.969 srgb} bind def
-/col35 {0.812 0.812 0.812 srgb} bind def
-/col36 {1.000 1.000 1.000 srgb} bind def
-
-end
-save
-48.0 12.0 translate
- 90 rotate
-1 -1 scale
-
-/cp {closepath} bind def
-/ef {eofill} bind def
-/gr {grestore} bind def
-/gs {gsave} bind def
-/sa {save} bind def
-/rs {restore} bind def
-/l {lineto} bind def
-/m {moveto} bind def
-/rm {rmoveto} bind def
-/n {newpath} bind def
-/s {stroke} bind def
-/sh {show} bind def
-/slc {setlinecap} bind def
-/slj {setlinejoin} bind def
-/slw {setlinewidth} bind def
-/srgb {setrgbcolor} bind def
-/rot {rotate} bind def
-/sc {scale} bind def
-/sd {setdash} bind def
-/ff {findfont} bind def
-/sf {setfont} bind def
-/scf {scalefont} bind def
-/sw {stringwidth} bind def
-/tr {translate} bind def
-/tnt {dup dup currentrgbcolor
- 4 -2 roll dup 1 exch sub 3 -1 roll mul add
- 4 -2 roll dup 1 exch sub 3 -1 roll mul add
- 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
- bind def
-/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
- 4 -2 roll mul srgb} bind def
-/reencdict 12 dict def /ReEncode { reencdict begin
-/newcodesandnames exch def /newfontname exch def /basefontname exch def
-/basefontdict basefontname findfont def /newfont basefontdict maxlength dict def
-basefontdict { exch dup /FID ne { dup /Encoding eq
-{ exch dup length array copy newfont 3 1 roll put }
-{ exch newfont 3 1 roll put } ifelse } { pop pop } ifelse } forall
-newfont /FontName newfontname put newcodesandnames aload pop
-128 1 255 { newfont /Encoding get exch /.notdef put } for
-newcodesandnames length 2 idiv { newfont /Encoding get 3 1 roll put } repeat
-newfontname newfont definefont pop end } def
-/isovec [
-8#200 /grave 8#201 /acute 8#202 /circumflex 8#203 /tilde
-8#204 /macron 8#205 /breve 8#206 /dotaccent 8#207 /dieresis
-8#210 /ring 8#211 /cedilla 8#212 /hungarumlaut 8#213 /ogonek 8#214 /caron
-8#220 /dotlessi 8#230 /oe 8#231 /OE
-8#240 /space 8#241 /exclamdown 8#242 /cent 8#243 /sterling
-8#244 /currency 8#245 /yen 8#246 /brokenbar 8#247 /section 8#250 /dieresis
-8#251 /copyright 8#252 /ordfeminine 8#253 /guillemotleft 8#254 /logicalnot
-8#255 /endash 8#256 /registered 8#257 /macron 8#260 /degree 8#261 /plusminus
-8#262 /twosuperior 8#263 /threesuperior 8#264 /acute 8#265 /mu 8#266 /paragraph
-8#267 /periodcentered 8#270 /cedilla 8#271 /onesuperior 8#272 /ordmasculine
-8#273 /guillemotright 8#274 /onequarter 8#275 /onehalf
-8#276 /threequarters 8#277 /questiondown 8#300 /Agrave 8#301 /Aacute
-8#302 /Acircumflex 8#303 /Atilde 8#304 /Adieresis 8#305 /Aring
-8#306 /AE 8#307 /Ccedilla 8#310 /Egrave 8#311 /Eacute
-8#312 /Ecircumflex 8#313 /Edieresis 8#314 /Igrave 8#315 /Iacute
-8#316 /Icircumflex 8#317 /Idieresis 8#320 /Eth 8#321 /Ntilde 8#322 /Ograve
-8#323 /Oacute 8#324 /Ocircumflex 8#325 /Otilde 8#326 /Odieresis 8#327 /multiply
-8#330 /Oslash 8#331 /Ugrave 8#332 /Uacute 8#333 /Ucircumflex
-8#334 /Udieresis 8#335 /Yacute 8#336 /Thorn 8#337 /germandbls 8#340 /agrave
-8#341 /aacute 8#342 /acircumflex 8#343 /atilde 8#344 /adieresis 8#345 /aring
-8#346 /ae 8#347 /ccedilla 8#350 /egrave 8#351 /eacute
-8#352 /ecircumflex 8#353 /edieresis 8#354 /igrave 8#355 /iacute
-8#356 /icircumflex 8#357 /idieresis 8#360 /eth 8#361 /ntilde 8#362 /ograve
-8#363 /oacute 8#364 /ocircumflex 8#365 /otilde 8#366 /odieresis 8#367 /divide
-8#370 /oslash 8#371 /ugrave 8#372 /uacute 8#373 /ucircumflex
-8#374 /udieresis 8#375 /yacute 8#376 /thorn 8#377 /ydieresis] def
-/Times-Roman /Times-Roman-iso isovec ReEncode
-/Helvetica-Bold /Helvetica-Bold-iso isovec ReEncode
-/Helvetica-Narrow /Helvetica-Narrow-iso isovec ReEncode
-/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
-/$F2psEnd {$F2psEnteredState restore end} def
-%%EndProlog
-
-$F2psBegin
-10 setmiterlimit
-n -1000 9572 m -1000 -1000 l 13622 -1000 l 13622 9572 l cp clip
- 0.05883 0.05883 sc
-%%Page: 1 1
-% Polyline
-7.500 slw
-n 6413 2048 m 6380 2054 l 6348 2061 l 6315 2067 l 6283 2073 l 6250 2079 l
- 6217 2084 l 6185 2090 l 6152 2095 l 6120 2101 l 6088 2107 l
- 6057 2113 l 6027 2120 l 5998 2126 l 5970 2134 l 5943 2141 l
- 5918 2149 l 5894 2158 l 5873 2167 l 5853 2177 l 5835 2187 l
- 5819 2198 l 5805 2210 l 5793 2222 l 5782 2235 l 5774 2250 l
- 5768 2265 l 5763 2281 l 5760 2299 l 5759 2318 l 5759 2339 l
- 5761 2360 l 5764 2383 l 5768 2408 l 5774 2433 l 5780 2460 l
- 5788 2488 l 5797 2516 l 5806 2546 l 5815 2575 l 5825 2606 l
- 5836 2636 l 5846 2666 l 5856 2696 l 5866 2726 l 5875 2755 l
- 5884 2784 l 5892 2812 l 5899 2839 l 5905 2866 l 5910 2891 l
- 5915 2916 l 5918 2940 l 5919 2968 l 5920 2995 l 5919 3022 l
- 5916 3048 l 5912 3075 l 5908 3101 l 5902 3127 l 5895 3153 l
- 5887 3179 l 5880 3205 l 5871 3230 l 5863 3254 l 5855 3278 l
- 5848 3302 l 5841 3324 l 5834 3346 l 5829 3367 l 5824 3388 l
- 5821 3408 l 5819 3427 l 5819 3446 l 5820 3465 l 5823 3484 l
- 5827 3503 l 5833 3522 l 5840 3542 l 5848 3562 l 5858 3582 l
- 5868 3603 l 5880 3625 l 5891 3647 l 5904 3669 l 5916 3691 l
- 5929 3713 l 5941 3736 l 5953 3758 l 5964 3779 l 5974 3801 l
- 5983 3822 l 5991 3843 l 5997 3863 l 6002 3883 l 6006 3903 l
- 6008 3923 l 6008 3942 l 6006 3962 l 6003 3983 l 5998 4004 l
- 5992 4025 l 5985 4048 l 5977 4070 l 5968 4094 l 5958 4118 l
- 5947 4142 l 5936 4167 l 5925 4192 l 5913 4216 l 5902 4241 l
- 5892 4266 l 5882 4291 l 5872 4315 l 5864 4339 l 5857 4362 l
- 5851 4386 l 5846 4409 l 5843 4433 l 5840 4456 l 5840 4480 l
- 5840 4505 l 5842 4530 l 5845 4556 l 5849 4582 l 5854 4609 l
- 5860 4636 l 5867 4664 l 5875 4692 l 5883 4720 l 5892 4747 l
- 5901 4774 l 5910 4801 l 5920 4827 l 5929 4852 l 5938 4875 l
- 5947 4898 l 5955 4920 l 5963 4941 l 5971 4961 l 5978 4980 l
- 5985 5002 l 5992 5024 l 5999 5046 l 6005 5067 l 6010 5088 l
- 6016 5109 l 6022 5129 l 6027 5150 l 6033 5170 l 6039 5190 l
- 6045 5209 l 6052 5228 l 6059 5246 l 6067 5264 l 6075 5281 l
- 6084 5298 l 6094 5315 l 6105 5333 l 6115 5347 l 6125 5361 l
- 6137 5376 l 6149 5392 l 6162 5408 l 6176 5425 l 6191 5443 l
- 6206 5461 l 6221 5480 l 6237 5499 l 6253 5519 l 6269 5539 l
- 6284 5559 l 6299 5579 l 6313 5599 l 6327 5619 l 6340 5639 l
- 6352 5659 l 6363 5679 l 6373 5698 l 6382 5718 l 6390 5738 l
- 6398 5759 l 6404 5782 l 6410 5805 l 6415 5828 l 6420 5852 l
- 6424 5877 l 6428 5902 l 6431 5927 l 6435 5952 l 6438 5977 l
- 6442 6001 l 6446 6025 l 6450 6048 l 6455 6069 l 6461 6090 l
- 6467 6109 l 6474 6127 l 6483 6143 l 6492 6159 l 6503 6173 l
- 6515 6185 l 6528 6197 l 6543 6209 l 6560 6220 l 6578 6230 l
- 6598 6240 l 6619 6250 l 6641 6260 l 6663 6270 l 6687 6281 l
- 6710 6291 l 6733 6302 l 6757 6312 l 6779 6324 l 6801 6335 l
- 6821 6348 l 6841 6361 l 6859 6374 l 6876 6389 l 6893 6405 l
- 6906 6421 l 6919 6437 l 6932 6455 l 6944 6475 l 6955 6495 l
- 6967 6516 l 6979 6538 l 6991 6561 l 7003 6584 l 7015 6608 l
- 7027 6631 l 7040 6654 l 7053 6677 l 7067 6699 l 7081 6720 l
- 7096 6739 l 7111 6758 l 7127 6774 l 7144 6789 l 7161 6803 l
- 7180 6815 l 7200 6825 l 7220 6833 l 7240 6840 l 7263 6845 l
- 7286 6850 l 7311 6854 l 7338 6857 l 7365 6859 l 7394 6861 l
- 7424 6862 l 7454 6864 l 7485 6865 l 7516 6866 l 7547 6867 l
- 7578 6868 l 7609 6870 l 7639 6872 l 7668 6875 l 7696 6879 l
- 7723 6883 l 7748 6889 l 7773 6895 l 7795 6903 l 7817 6912 l
- 7838 6923 l 7857 6934 l 7875 6948 l 7892 6963 l 7909 6980 l
- 7926 6998 l 7941 7017 l 7957 7038 l 7972 7060 l 7987 7083 l
- 8002 7106 l 8017 7130 l 8031 7154 l 8046 7178 l 8061 7202 l
- 8075 7225 l 8090 7247 l 8105 7269 l 8120 7289 l 8135 7308 l
- 8151 7326 l 8167 7342 l 8184 7356 l 8202 7369 l 8220 7380 l
- 8239 7390 l 8260 7397 l 8282 7404 l 8305 7409 l 8330 7413 l
- 8356 7416 l 8383 7418 l 8412 7420 l 8441 7420 l 8471 7419 l
- 8502 7418 l 8534 7417 l 8565 7415 l 8597 7413 l 8629 7411 l
- 8660 7409 l 8690 7407 l 8720 7405 l 8749 7404 l 8777 7404 l
- 8804 7404 l 8830 7405 l 8856 7407 l 8880 7410 l 8906 7414 l
- 8931 7420 l 8956 7427 l 8981 7435 l 9005 7444 l 9029 7455 l
- 9053 7466 l 9077 7478 l 9100 7491 l 9123 7504 l 9146 7517 l
- 9168 7531 l 9190 7544 l 9210 7557 l 9230 7570 l 9250 7582 l
- 9268 7593 l 9286 7604 l 9304 7613 l 9320 7621 l 9336 7629 l
- 9353 7635 l 9370 7641 l 9388 7645 l 9406 7648 l 9425 7650 l
- 9444 7652 l 9464 7653 l 9485 7653 l 9508 7653 l 9531 7653 l
- 9555 7653 l 9579 7653 l 9605 7654 l 9631 7655 l 9658 7656 l
- 9685 7659 l 9713 7662 l 9742 7666 l 9771 7672 l 9801 7679 l
- 9833 7688 l 9853 7694 l 9874 7700 l 9895 7708 l 9918 7716 l
- 9941 7725 l 9966 7734 l 9991 7745 l 10017 7755 l 10045 7767 l
- 10073 7779 l 10102 7791 l 10132 7804 l 10163 7818 l 10194 7831 l
- 10227 7845 l 10259 7860 l 10293 7874 l 10326 7889 l 10360 7903 l
- 10394 7918 l 10429 7932 l 10463 7947 l 10497 7961 l 10531 7974 l
- 10565 7988 l 10599 8001 l 10633 8013 l 10667 8025 l 10700 8037 l
- 10733 8049 l 10767 8059 l 10800 8070 l 10834 8080 l 10868 8090 l
- 10902 8099 l 10937 8108 l 10973 8117 l 11009 8125 l 11045 8133 l
- 11083 8141 l 11120 8148 l 11158 8155 l 11197 8161 l 11236 8167 l
- 11275 8172 l 11313 8177 l 11352 8181 l 11391 8184 l 11429 8187 l
- 11467 8190 l 11504 8191 l 11540 8192 l 11576 8192 l 11610 8192 l
- 11644 8191 l 11676 8189 l 11707 8187 l 11738 8184 l 11767 8180 l
- 11794 8176 l 11821 8171 l 11847 8165 l 11871 8159 l 11895 8153 l
- 11923 8143 l 11950 8133 l 11976 8122 l 12001 8109 l 12025 8096 l
- 12048 8081 l 12071 8065 l 12092 8048 l 12113 8031 l 12133 8012 l
- 12153 7992 l 12171 7972 l 12188 7951 l 12205 7930 l 12220 7909 l
- 12235 7887 l 12248 7865 l 12260 7843 l 12272 7822 l 12282 7800 l
- 12292 7779 l 12301 7759 l 12309 7739 l 12316 7719 l 12323 7699 l
- 12330 7680 l 12338 7655 l 12345 7631 l 12352 7607 l 12359 7582 l
- 12365 7558 l 12371 7533 l 12377 7508 l 12382 7484 l 12388 7460 l
- 12392 7436 l 12397 7414 l 12401 7391 l 12405 7370 l 12409 7350 l
- 12412 7331 l 12415 7313 l 12418 7297 l 12421 7281 l 12424 7266 l
- 12428 7253 l 12432 7234 l 12437 7216 l 12442 7199 l 12446 7183 l
- 12451 7166 l 12456 7150 l 12460 7134 l 12463 7117 l 12466 7101 l
- 12468 7086 l 12469 7070 l 12469 7054 l 12467 7037 l 12465 7020 l
- 12462 7006 l 12459 6991 l 12455 6975 l 12450 6958 l 12445 6940 l
- 12440 6921 l 12434 6901 l 12428 6880 l 12422 6859 l 12416 6838 l
- 12411 6817 l 12406 6796 l 12401 6776 l 12397 6756 l 12394 6736 l
- 12392 6718 l 12390 6700 l 12390 6683 l 12390 6665 l 12392 6649 l
- 12394 6631 l 12397 6614 l 12401 6597 l 12406 6579 l 12411 6561 l
- 12416 6542 l 12422 6524 l 12428 6505 l 12434 6487 l 12440 6468 l
- 12445 6450 l 12450 6432 l 12455 6414 l 12459 6396 l 12462 6378 l
- 12465 6360 l 12467 6343 l 12468 6326 l 12469 6308 l 12469 6289 l
- 12468 6269 l 12468 6249 l 12466 6227 l 12464 6205 l 12462 6182 l
- 12460 6159 l 12457 6135 l 12454 6111 l 12451 6087 l 12447 6063 l
- 12444 6040 l 12441 6016 l 12437 5993 l 12434 5970 l 12431 5948 l
- 12428 5925 l 12424 5902 l 12421 5879 l 12419 5855 l 12416 5831 l
- 12413 5806 l 12411 5781 l 12408 5755 l 12406 5729 l 12404 5702 l
- 12403 5676 l 12401 5651 l 12400 5625 l 12400 5601 l 12399 5578 l
- 12399 5555 l 12400 5534 l 12401 5514 l 12402 5495 l 12403 5477 l
- 12405 5460 l 12408 5440 l 12411 5421 l 12416 5402 l 12420 5384 l
- 12426 5365 l 12431 5347 l 12437 5329 l 12444 5311 l 12450 5293 l
- 12456 5275 l 12462 5258 l 12468 5240 l 12474 5222 l 12479 5205 l
- 12483 5186 l 12488 5168 l 12490 5152 l 12493 5135 l 12496 5117 l
- 12498 5099 l 12500 5079 l 12502 5058 l 12504 5036 l 12506 5014 l
- 12507 4990 l 12509 4966 l 12510 4942 l 12512 4918 l 12513 4893 l
- 12515 4869 l 12516 4845 l 12518 4822 l 12520 4799 l 12521 4776 l
- 12523 4754 l 12525 4733 l 12527 4713 l 12529 4693 l 12531 4673 l
- 12534 4653 l 12536 4632 l 12539 4610 l 12541 4588 l 12543 4566 l
- 12546 4543 l 12548 4520 l 12550 4497 l 12552 4473 l 12553 4450 l
- 12554 4426 l 12555 4403 l 12555 4380 l 12555 4357 l 12555 4334 l
- 12554 4312 l 12552 4290 l 12550 4267 l 12548 4245 l 12545 4224 l
- 12541 4203 l 12537 4181 l 12533 4159 l 12528 4136 l 12523 4112 l
- 12517 4088 l 12510 4064 l 12503 4038 l 12496 4013 l 12488 3987 l
- 12479 3961 l 12471 3935 l 12462 3909 l 12452 3884 l 12443 3859 l
- 12434 3835 l 12424 3811 l 12415 3788 l 12405 3766 l 12396 3744 l
- 12386 3723 l 12377 3702 l 12368 3683 l 12357 3661 l 12347 3640 l
- 12336 3619 l 12325 3598 l 12314 3576 l 12303 3555 l 12291 3533 l
- 12280 3511 l 12269 3489 l 12257 3467 l 12246 3446 l 12235 3424 l
- 12225 3402 l 12215 3381 l 12206 3360 l 12197 3340 l 12189 3320 l
- 12181 3301 l 12174 3281 l 12168 3262 l 12162 3244 l 12158 3225 l
- 12153 3204 l 12149 3183 l 12145 3162 l 12142 3139 l 12140 3117 l
- 12138 3094 l 12137 3071 l 12137 3047 l 12138 3024 l 12139 3001 l
- 12141 2978 l 12143 2956 l 12146 2935 l 12150 2915 l 12154 2896 l
- 12158 2879 l 12163 2862 l 12168 2847 l 12174 2833 l 12180 2820 l
- 12188 2805 l 12197 2792 l 12206 2779 l 12216 2766 l 12227 2754 l
- 12238 2742 l 12249 2730 l 12260 2717 l 12272 2704 l 12282 2691 l
- 12292 2676 l 12302 2661 l 12310 2645 l 12318 2627 l 12324 2608 l
- 12330 2588 l 12334 2571 l 12336 2553 l 12339 2534 l 12341 2513 l
- 12342 2491 l 12343 2467 l 12343 2442 l 12342 2416 l 12340 2389 l
- 12338 2360 l 12335 2332 l 12331 2303 l 12326 2273 l 12320 2244 l
- 12314 2215 l 12307 2187 l 12299 2159 l 12290 2132 l 12280 2106 l
- 12270 2081 l 12259 2056 l 12248 2033 l 12236 2011 l 12224 1990 l
- 12210 1970 l 12196 1949 l 12181 1929 l 12164 1910 l 12147 1890 l
- 12129 1871 l 12110 1853 l 12090 1835 l 12070 1818 l 12049 1802 l
- 12027 1787 l 12005 1773 l 11983 1761 l 11961 1749 l 11939 1739 l
- 11917 1730 l 11895 1722 l 11874 1716 l 11852 1710 l 11831 1707 l
- 11811 1704 l 11790 1703 l 11769 1702 l 11748 1703 l 11727 1705 l
- 11706 1708 l 11683 1711 l 11660 1716 l 11636 1721 l 11612 1727 l
- 11587 1733 l 11560 1740 l 11534 1747 l 11506 1754 l 11479 1761 l
- 11450 1768 l 11422 1774 l 11393 1780 l 11364 1786 l 11334 1791 l
- 11305 1795 l 11275 1798 l 11245 1800 l 11215 1801 l 11184 1801 l
- 11153 1800 l 11128 1798 l 11104 1796 l 11078 1793 l 11052 1790 l
- 11025 1785 l 10997 1781 l 10968 1776 l 10939 1770 l 10908 1764 l
- 10877 1758 l 10844 1751 l 10811 1744 l 10778 1737 l 10743 1730 l
- 10708 1722 l 10673 1715 l 10637 1708 l 10601 1701 l 10565 1695 l
- 10530 1688 l 10494 1682 l 10458 1677 l 10422 1672 l 10387 1668 l
- 10352 1664 l 10318 1661 l 10284 1658 l 10250 1657 l 10216 1656 l
- 10183 1655 l 10150 1656 l 10118 1658 l 10087 1660 l 10055 1663 l
- 10024 1666 l 9992 1671 l 9960 1676 l 9927 1682 l 9894 1688 l
- 9861 1695 l 9827 1703 l 9792 1711 l 9757 1720 l 9721 1729 l
- 9685 1738 l 9649 1748 l 9613 1757 l 9576 1767 l 9539 1778 l
- 9502 1788 l 9465 1798 l 9429 1807 l 9392 1817 l 9356 1826 l
- 9320 1835 l 9285 1844 l 9250 1852 l 9216 1860 l 9182 1867 l
- 9148 1873 l 9115 1879 l 9082 1884 l 9050 1889 l 9018 1892 l
- 8987 1895 l 8955 1898 l 8919 1899 l 8883 1900 l 8847 1899 l
- 8811 1898 l 8774 1896 l 8737 1893 l 8699 1889 l 8661 1884 l
- 8623 1878 l 8585 1872 l 8546 1865 l 8508 1857 l 8470 1849 l
- 8432 1840 l 8395 1830 l 8358 1821 l 8322 1811 l 8287 1801 l
- 8254 1790 l 8221 1780 l 8189 1770 l 8159 1760 l 8130 1750 l
- 8102 1740 l 8076 1730 l 8051 1721 l 8028 1712 l 8006 1703 l
- 7985 1695 l 7965 1688 l 7931 1674 l 7899 1662 l 7871 1650 l
- 7844 1640 l 7820 1631 l 7798 1623 l 7778 1617 l 7760 1611 l
- 7743 1607 l 7728 1603 l 7715 1601 l 7702 1600 l 7691 1600 l
- 7680 1601 l 7669 1603 l 7658 1605 l 7648 1607 l 7638 1610 l
- 7627 1613 l 7615 1617 l 7601 1621 l 7587 1626 l 7571 1632 l
- 7554 1638 l 7536 1645 l 7517 1653 l 7496 1661 l 7474 1670 l
- 7452 1679 l 7428 1689 l 7403 1699 l 7378 1709 l 7352 1720 l
- 7325 1731 l 7297 1743 l 7268 1755 l 7247 1763 l 7226 1772 l
- 7204 1781 l 7182 1790 l 7158 1800 l 7133 1810 l 7108 1820 l
- 7081 1831 l 7053 1842 l 7025 1853 l 6996 1864 l 6966 1875 l
- 6935 1886 l 6904 1898 l 6873 1909 l 6841 1921 l 6809 1932 l
- 6776 1943 l 6744 1954 l 6712 1964 l 6680 1974 l 6649 1984 l
- 6618 1994 l 6587 2003 l 6557 2011 l 6527 2019 l 6498 2027 l
- 6469 2034 l 6441 2041 l cp gs col34 1.00 shd ef gr gs col34 s gr
-% Polyline
-n 675 6525 m 5850 6525 l 5850 6075 l 5625 6075 l 5625 5625 l 900 5625 l
- 900 6075 l 675 6075 l cp gs col7 1.00 shd ef gr gs col7 s gr
-% Polyline
-n 1125 6525 m 5355 6525 l 5400 5175 l 5175 5175 l 5175 4725 l 4950 4725 l
- 4950 4275 l 1575 4275 l 1575 4725 l 1350 4725 l 1350 5175 l
- 1125 5175 l cp gs col34 1.00 shd ef gr gs col34 s gr
-% Polyline
-75.000 slw
-n 9450 4500 m 12465 2205 l gs col7 s gr
-% Polyline
-n 9450 4500 m 9450 7785 l gs col7 s gr
-% Polyline
-n 9450 4500 m 6075 1935 l gs col7 s gr
-% Polyline
-n 12510 6435 m 9450 6435 l gs col7 s gr
-% Polyline
-7.500 slw
-n 1800 6525 m 4725 6525 l 4725 3825 l 4500 3825 l 4500 3375 l 4275 3375 l
- 4275 2925 l 4050 2925 l 4050 2475 l 2475 2475 l 2475 2925 l
- 2250 2925 l 2250 3375 l 2025 3375 l 2025 3825 l 1800 3825 l
- cp gs col35 1.00 shd ef gr gs col35 s gr
-% Polyline
-n 2700 6525 m 3825 6525 l 3825 2025 l 3600 2025 l 3600 1575 l 2925 1575 l
- 2925 2025 l 2700 2025 l cp gs col33 1.00 shd ef gr gs col33 s gr
-% Polyline
-gs clippath
-12068 6810 m 11970 6885 l 12022 6773 l 11937 6878 l 11984 6915 l cp
-clip
-n 12375 4455 m 12510 4635 l 12510 6210 l 11970 6885 l gs col34 1.00 shd ef gr gs col0 s gr gr
-
-% arrowhead
-n 12068 6810 m 11970 6885 l 12022 6773 l 12045 6791 l 12068 6810 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
-gs clippath
-7113 6004 m 7155 6120 l 7063 6037 l 7138 6149 l 7188 6116 l cp
-clip
-n 6705 5445 m 7155 6120 l gs col34 1.00 shd ef gr gs col0 s gr gr
-
-% arrowhead
-n 7113 6004 m 7155 6120 l 7063 6037 l 7088 6020 l 7113 6004 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
-gs clippath
-7304 4656 m 7200 4590 l 7323 4599 l 7195 4557 l 7176 4614 l cp
-clip
-n 7875 4815 m 7200 4590 l gs col34 1.00 shd ef gr gs col0 s gr gr
-
-% arrowhead
-n 7304 4656 m 7200 4590 l 7323 4599 l 7314 4628 l 7304 4656 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
-gs clippath
-11405 4128 m 11475 4230 l 11365 4173 l 11466 4262 l 11506 4217 l cp
-clip
-n 9585 2565 m 11475 4230 l gs col34 1.00 shd ef gr gs col0 s gr gr
-
-% arrowhead
-n 11405 4128 m 11475 4230 l 11365 4173 l 11385 4151 l 11405 4128 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
-gs clippath
-11712 4556 m 11835 4545 l 11732 4613 l 11859 4568 l 11839 4512 l cp
-clip
-n 10170 5130 m 11835 4545 l gs col34 1.00 shd ef gr gs col0 s gr gr
-
-% arrowhead
-n 11712 4556 m 11835 4545 l 11732 4613 l 11722 4585 l 11712 4556 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
-gs clippath
-9732 5411 m 9855 5400 l 9752 5468 l 9879 5423 l 9859 5367 l cp
-clip
-n 7920 6075 m 9855 5400 l gs col34 1.00 shd ef gr gs col0 s gr gr
-
-% arrowhead
-n 9732 5411 m 9855 5400 l 9752 5468 l 9742 5440 l 9732 5411 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
-gs clippath
-10823 5573 m 10935 5625 l 10812 5632 l 10944 5657 l 10955 5598 l cp
-clip
-n 9990 5445 m 10935 5625 l gs col34 1.00 shd ef gr gs col0 s gr gr
-
-% arrowhead
-n 10823 5573 m 10935 5625 l 10812 5632 l 10817 5603 l 10823 5573 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
-gs clippath
-10815 5280 m 10935 5310 l 10815 5340 l 10950 5340 l 10950 5280 l cp
-clip
-n 10215 5310 m 10935 5310 l gs col34 1.00 shd ef gr gs col0 s gr gr
-
-% arrowhead
-n 10815 5280 m 10935 5310 l 10815 5340 l 10815 5310 l 10815 5280 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
-gs clippath
-11955 4965 m 11925 5085 l 11895 4965 l 11895 5100 l 11955 5100 l cp
-clip
-n 11925 4590 m 11925 5085 l gs col34 1.00 shd ef gr gs col0 s gr gr
-
-% arrowhead
-n 11955 4965 m 11925 5085 l 11895 4965 l 11925 4965 l 11955 4965 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
-gs clippath
-9840 6720 m 9810 6840 l 9780 6720 l 9780 6855 l 9840 6855 l cp
-clip
-n 9810 5490 m 9810 6840 l gs col34 1.00 shd ef gr gs col0 s gr gr
-
-% arrowhead
-n 9840 6720 m 9810 6840 l 9780 6720 l 9810 6720 l 9840 6720 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
-gs clippath
-10847 5943 m 10935 6030 l 10816 5995 l 10933 6063 l 10963 6012 l cp
-clip
-n 9945 5445 m 10935 6030 l gs col34 1.00 shd ef gr gs col0 s gr gr
-
-% arrowhead
-n 10847 5943 m 10935 6030 l 10816 5995 l 10832 5969 l 10847 5943 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
-gs clippath
-10698 2634 m 10800 2565 l 10742 2674 l 10832 2574 l 10788 2534 l cp
-clip
-n 8865 4725 m 10800 2565 l gs col34 1.00 shd ef gr gs col0 s gr gr
-
-% arrowhead
-n 10698 2634 m 10800 2565 l 10742 2674 l 10720 2654 l 10698 2634 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
-30.000 slw
-n 675 6075 m 5850 6075 l gs col34 1.00 shd ef gr gs col0 s gr
-% Polyline
-7.500 slw
- [15 15] 15 sd
-gs clippath
-645 6195 m 675 6075 l 705 6195 l 705 6060 l 645 6060 l cp
-clip
-n 675 6525 m 675 6075 l gs col34 1.00 shd ef gr gs col0 s gr gr
- [] 0 sd
-% arrowhead
-n 645 6195 m 675 6075 l 705 6195 l 675 6195 l 645 6195 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
- [15 15] 15 sd
-gs clippath
-5880 6405 m 5850 6525 l 5820 6405 l 5820 6540 l 5880 6540 l cp
-clip
-n 5850 6075 m 5850 6525 l gs col34 1.00 shd ef gr gs col0 s gr gr
- [] 0 sd
-% arrowhead
-n 5880 6405 m 5850 6525 l 5820 6405 l 5850 6405 l 5880 6405 l cp gs col7 1.00 shd ef gr col0 s
-% Polyline
-30.000 slw
-n 900 5625 m 5625 5625 l gs col34 1.00 shd ef gr gs col0 s gr
-% Polyline
-n 1125 5175 m 5400 5175 l gs col34 1.00 shd ef gr gs col0 s gr
-% Polyline
-n 1350 4725 m 5175 4725 l gs col34 1.00 shd ef gr gs col0 s gr
-% Polyline
-n 1575 4275 m 4950 4275 l gs col34 1.00 shd ef gr gs col0 s gr
-% Polyline
-n 1800 3825 m 4725 3825 l gs col34 1.00 shd ef gr gs col0 s gr
-% Polyline
-n 2025 3375 m 4500 3375 l gs col34 1.00 shd ef gr gs col0 s gr
-% Polyline
-n 2250 2925 m 4275 2925 l gs col34 1.00 shd ef gr gs col0 s gr
-% Polyline
-n 2475 2475 m 4050 2475 l gs col34 1.00 shd ef gr gs col0 s gr
-% Polyline
-n 2700 2025 m 3825 2025 l gs col34 1.00 shd ef gr gs col0 s gr
-% Polyline
-n 2925 1575 m 3600 1575 l gs col34 1.00 shd ef gr gs col0 s gr
-% Polyline
-7.500 slw
- [15 15] 15 sd
-gs clippath
-870 5745 m 900 5625 l 930 5745 l 930 5610 l 870 5610 l cp
-clip
-n 900 6075 m 900 5625 l gs col34 1.00 shd ef gr gs col0 s gr gr
- [] 0 sd
-% arrowhead
-n 870 5745 m 900 5625 l 930 5745 l 900 5745 l 870 5745 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
- [15 15] 15 sd
-gs clippath
-1095 5295 m 1125 5175 l 1155 5295 l 1155 5160 l 1095 5160 l cp
-clip
-n 1125 6525 m 1125 5175 l gs col34 1.00 shd ef gr gs col0 s gr gr
- [] 0 sd
-% arrowhead
-n 1095 5295 m 1125 5175 l 1155 5295 l 1125 5295 l 1095 5295 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
- [15 15] 15 sd
-gs clippath
-1320 4845 m 1350 4725 l 1380 4845 l 1380 4710 l 1320 4710 l cp
-clip
-n 1350 5175 m 1350 4725 l gs col34 1.00 shd ef gr gs col0 s gr gr
- [] 0 sd
-% arrowhead
-n 1320 4845 m 1350 4725 l 1380 4845 l 1350 4845 l 1320 4845 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
- [15 15] 15 sd
-gs clippath
-1545 4395 m 1575 4275 l 1605 4395 l 1605 4260 l 1545 4260 l cp
-clip
-n 1575 4725 m 1575 4275 l gs col34 1.00 shd ef gr gs col0 s gr gr
- [] 0 sd
-% arrowhead
-n 1545 4395 m 1575 4275 l 1605 4395 l 1575 4395 l 1545 4395 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
- [15 15] 15 sd
-gs clippath
-1770 3945 m 1800 3825 l 1830 3945 l 1830 3810 l 1770 3810 l cp
-clip
-n 1800 6525 m 1800 3825 l gs col34 1.00 shd ef gr gs col0 s gr gr
- [] 0 sd
-% arrowhead
-n 1770 3945 m 1800 3825 l 1830 3945 l 1800 3945 l 1770 3945 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
- [15 15] 15 sd
-gs clippath
-1995 3495 m 2025 3375 l 2055 3495 l 2055 3360 l 1995 3360 l cp
-clip
-n 2025 3825 m 2025 3375 l gs col34 1.00 shd ef gr gs col0 s gr gr
- [] 0 sd
-% arrowhead
-n 1995 3495 m 2025 3375 l 2055 3495 l 2025 3495 l 1995 3495 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
- [15 15] 15 sd
-gs clippath
-2220 3045 m 2250 2925 l 2280 3045 l 2280 2910 l 2220 2910 l cp
-clip
-n 2250 3375 m 2250 2925 l gs col34 1.00 shd ef gr gs col0 s gr gr
- [] 0 sd
-% arrowhead
-n 2220 3045 m 2250 2925 l 2280 3045 l 2250 3045 l 2220 3045 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
- [15 15] 15 sd
-gs clippath
-2445 2595 m 2475 2475 l 2505 2595 l 2505 2460 l 2445 2460 l cp
-clip
-n 2475 2925 m 2475 2475 l gs col34 1.00 shd ef gr gs col0 s gr gr
- [] 0 sd
-% arrowhead
-n 2445 2595 m 2475 2475 l 2505 2595 l 2475 2595 l 2445 2595 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
- [15 15] 15 sd
-gs clippath
-5655 5955 m 5625 6075 l 5595 5955 l 5595 6090 l 5655 6090 l cp
-clip
-n 5625 5625 m 5625 6075 l gs col34 1.00 shd ef gr gs col0 s gr gr
- [] 0 sd
-% arrowhead
-n 5655 5955 m 5625 6075 l 5595 5955 l 5625 5955 l 5655 5955 l cp gs col7 1.00 shd ef gr col0 s
-% Polyline
- [15 15] 15 sd
-gs clippath
-5430 6405 m 5400 6525 l 5370 6405 l 5370 6540 l 5430 6540 l cp
-clip
-n 5400 5175 m 5400 6525 l gs col34 1.00 shd ef gr gs col0 s gr gr
- [] 0 sd
-% arrowhead
-n 5430 6405 m 5400 6525 l 5370 6405 l 5400 6405 l 5430 6405 l cp gs col7 1.00 shd ef gr col0 s
-% Polyline
- [15 15] 15 sd
-gs clippath
-5205 5055 m 5175 5175 l 5145 5055 l 5145 5190 l 5205 5190 l cp
-clip
-n 5175 4725 m 5175 5175 l gs col34 1.00 shd ef gr gs col0 s gr gr
- [] 0 sd
-% arrowhead
-n 5205 5055 m 5175 5175 l 5145 5055 l 5175 5055 l 5205 5055 l cp gs col7 1.00 shd ef gr col0 s
-% Polyline
- [15 15] 15 sd
-gs clippath
-4980 4605 m 4950 4725 l 4920 4605 l 4920 4740 l 4980 4740 l cp
-clip
-n 4950 4275 m 4950 4725 l gs col34 1.00 shd ef gr gs col0 s gr gr
- [] 0 sd
-% arrowhead
-n 4980 4605 m 4950 4725 l 4920 4605 l 4950 4605 l 4980 4605 l cp gs col7 1.00 shd ef gr col0 s
-% Polyline
- [15 15] 15 sd
-gs clippath
-4755 6405 m 4725 6525 l 4695 6405 l 4695 6540 l 4755 6540 l cp
-clip
-n 4725 3825 m 4725 6525 l gs col34 1.00 shd ef gr gs col0 s gr gr
- [] 0 sd
-% arrowhead
-n 4755 6405 m 4725 6525 l 4695 6405 l 4725 6405 l 4755 6405 l cp gs col7 1.00 shd ef gr col0 s
-% Polyline
- [15 15] 15 sd
-gs clippath
-4530 3705 m 4500 3825 l 4470 3705 l 4470 3840 l 4530 3840 l cp
-clip
-n 4500 3375 m 4500 3825 l gs col34 1.00 shd ef gr gs col0 s gr gr
- [] 0 sd
-% arrowhead
-n 4530 3705 m 4500 3825 l 4470 3705 l 4500 3705 l 4530 3705 l cp gs col7 1.00 shd ef gr col0 s
-% Polyline
- [15 15] 15 sd
-gs clippath
-4305 3255 m 4275 3375 l 4245 3255 l 4245 3390 l 4305 3390 l cp
-clip
-n 4275 2925 m 4275 3375 l gs col34 1.00 shd ef gr gs col0 s gr gr
- [] 0 sd
-% arrowhead
-n 4305 3255 m 4275 3375 l 4245 3255 l 4275 3255 l 4305 3255 l cp gs col7 1.00 shd ef gr col0 s
-% Polyline
- [15 15] 15 sd
-gs clippath
-4080 2805 m 4050 2925 l 4020 2805 l 4020 2940 l 4080 2940 l cp
-clip
-n 4050 2475 m 4050 2925 l gs col34 1.00 shd ef gr gs col0 s gr gr
- [] 0 sd
-% arrowhead
-n 4080 2805 m 4050 2925 l 4020 2805 l 4050 2805 l 4080 2805 l cp gs col7 1.00 shd ef gr col0 s
-% Polyline
- [15 15] 15 sd
-gs clippath
-2670 2145 m 2700 2025 l 2730 2145 l 2730 2010 l 2670 2010 l cp
-clip
-n 2700 6525 m 2700 2025 l gs col34 1.00 shd ef gr gs col0 s gr gr
- [] 0 sd
-% arrowhead
-n 2670 2145 m 2700 2025 l 2730 2145 l 2700 2145 l 2670 2145 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
- [15 15] 15 sd
-gs clippath
-3855 6405 m 3825 6525 l 3795 6405 l 3795 6540 l 3855 6540 l cp
-clip
-n 3825 2025 m 3825 6525 l gs col34 1.00 shd ef gr gs col0 s gr gr
- [] 0 sd
-% arrowhead
-n 3855 6405 m 3825 6525 l 3795 6405 l 3825 6405 l 3855 6405 l cp gs col7 1.00 shd ef gr col0 s
-% Polyline
- [15 15] 15 sd
-gs clippath
-3630 1905 m 3600 2025 l 3570 1905 l 3570 2040 l 3630 2040 l cp
-clip
-n 3600 1575 m 3600 2025 l gs col34 1.00 shd ef gr gs col0 s gr gr
- [] 0 sd
-% arrowhead
-n 3630 1905 m 3600 2025 l 3570 1905 l 3600 1905 l 3630 1905 l cp gs col7 1.00 shd ef gr col0 s
-% Polyline
- [15 15] 15 sd
-gs clippath
-2895 1695 m 2925 1575 l 2955 1695 l 2955 1560 l 2895 1560 l cp
-clip
-n 2925 2025 m 2925 1575 l gs col34 1.00 shd ef gr gs col0 s gr gr
- [] 0 sd
-% arrowhead
-n 2895 1695 m 2925 1575 l 2955 1695 l 2925 1695 l 2895 1695 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
-45.000 slw
-gs clippath
-6087 6495 m 6207 6525 l 6087 6555 l 6360 6555 l 6360 6495 l cp
-clip
-n 540 6525 m 6300 6525 l gs 0.00 setgray ef gr gs col0 s gr gr
-
-% arrowhead
-n 6087 6495 m 6207 6525 l 6087 6555 l 6087 6525 l 6087 6495 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
-7.500 slw
-gs clippath
-3681 6720 m 3825 6750 l 3681 6780 l 3840 6780 l 3840 6720 l cp
-2844 6780 m 2700 6750 l 2844 6720 l 2685 6720 l 2685 6780 l cp
-clip
-n 2700 6750 m 3825 6750 l gs col34 1.00 shd ef gr gs col0 s gr gr
-
-% arrowhead
-n 2844 6780 m 2700 6750 l 2844 6720 l 2820 6750 l 2844 6780 l cp gs col7 1.00 shd ef gr col0 s
-% arrowhead
-n 3681 6720 m 3825 6750 l 3681 6780 l 3705 6750 l 3681 6720 l cp gs col7 1.00 shd ef gr col0 s
-% Polyline
-gs clippath
-5256 7170 m 5400 7200 l 5256 7230 l 5415 7230 l 5415 7170 l cp
-1269 7230 m 1125 7200 l 1269 7170 l 1110 7170 l 1110 7230 l cp
-clip
-n 1125 7200 m 5400 7200 l gs col34 1.00 shd ef gr gs col0 s gr gr
-
-% arrowhead
-n 1269 7230 m 1125 7200 l 1269 7170 l 1245 7200 l 1269 7230 l cp gs col7 1.00 shd ef gr col0 s
-% arrowhead
-n 5256 7170 m 5400 7200 l 5256 7230 l 5280 7200 l 5256 7170 l cp gs col7 1.00 shd ef gr col0 s
-% Polyline
-gs clippath
-4581 6945 m 4725 6975 l 4581 7005 l 4740 7005 l 4740 6945 l cp
-1944 7005 m 1800 6975 l 1944 6945 l 1785 6945 l 1785 7005 l cp
-clip
-n 1800 6975 m 4725 6975 l gs col34 1.00 shd ef gr gs col0 s gr gr
-
-% arrowhead
-n 1944 7005 m 1800 6975 l 1944 6945 l 1920 6975 l 1944 7005 l cp gs col7 1.00 shd ef gr col0 s
-% arrowhead
-n 4581 6945 m 4725 6975 l 4581 7005 l 4605 6975 l 4581 6945 l cp gs col7 1.00 shd ef gr col0 s
-% Polyline
-gs clippath
-5706 7395 m 5850 7425 l 5706 7455 l 5865 7455 l 5865 7395 l cp
-819 7455 m 675 7425 l 819 7395 l 660 7395 l 660 7455 l cp
-clip
-n 675 7425 m 5850 7425 l gs col34 1.00 shd ef gr gs col0 s gr gr
-
-% arrowhead
-n 819 7455 m 675 7425 l 819 7395 l 795 7425 l 819 7455 l cp gs col7 1.00 shd ef gr col0 s
-% arrowhead
-n 5706 7395 m 5850 7425 l 5706 7455 l 5730 7425 l 5706 7395 l cp gs col7 1.00 shd ef gr col0 s
-% Polyline
-1 slc
- [15 45] 45 sd
-n 675 6570 m 675 7650 l gs col34 1.00 shd ef gr gs col0 s gr [] 0 sd
-% Polyline
- [15 45] 45 sd
-n 1125 6570 m 1125 7650 l gs col34 1.00 shd ef gr gs col0 s gr [] 0 sd
-% Polyline
- [15 45] 45 sd
-n 1800 6570 m 1800 7650 l gs col34 1.00 shd ef gr gs col0 s gr [] 0 sd
-% Polyline
- [15 45] 45 sd
-n 2700 6570 m 2700 7650 l gs col34 1.00 shd ef gr gs col0 s gr [] 0 sd
-% Polyline
- [15 45] 45 sd
-n 3825 6570 m 3825 7650 l gs col34 1.00 shd ef gr gs col0 s gr [] 0 sd
-% Polyline
- [15 45] 45 sd
-n 4725 6570 m 4725 7650 l gs col34 1.00 shd ef gr gs col0 s gr [] 0 sd
-% Polyline
- [15 45] 45 sd
-n 5400 6570 m 5400 7650 l gs col34 1.00 shd ef gr gs col0 s gr [] 0 sd
-% Polyline
- [15 45] 45 sd
-n 5850 6570 m 5850 7650 l gs col34 1.00 shd ef gr gs col0 s gr [] 0 sd
-% Polyline
-0 slc
-n 750 225 m 450 225 450 1050 300 arcto 4 {pop} repeat
- 450 1350 12300 1350 300 arcto 4 {pop} repeat
- 12600 1350 12600 525 300 arcto 4 {pop} repeat
- 12600 225 750 225 300 arcto 4 {pop} repeat
- cp gs col34 1.00 shd ef gr gs col0 s gr
-% Polyline
-n 8835 2250 m 8775 2250 8775 2415 60 arcto 4 {pop} repeat
- 8775 2475 10110 2475 60 arcto 4 {pop} repeat
- 10170 2475 10170 2310 60 arcto 4 {pop} repeat
- 10170 2250 8835 2250 60 arcto 4 {pop} repeat
- cp gs col35 1.00 shd ef gr gs col35 s gr
-% Polyline
-n 10635 2250 m 10575 2250 10575 2415 60 arcto 4 {pop} repeat
- 10575 2475 11865 2475 60 arcto 4 {pop} repeat
- 11925 2475 11925 2310 60 arcto 4 {pop} repeat
- 11925 2250 10635 2250 60 arcto 4 {pop} repeat
- cp gs col35 1.00 shd ef gr gs col35 s gr
-% Polyline
-n 11490 4275 m 11430 4275 11430 4440 60 arcto 4 {pop} repeat
- 11430 4500 12315 4500 60 arcto 4 {pop} repeat
- 12375 4500 12375 4335 60 arcto 4 {pop} repeat
- 12375 4275 11490 4275 60 arcto 4 {pop} repeat
- cp gs col35 1.00 shd ef gr gs col35 s gr
-% Polyline
-n 11040 5175 m 10980 5175 10980 5340 60 arcto 4 {pop} repeat
- 10980 5400 12315 5400 60 arcto 4 {pop} repeat
- 12375 5400 12375 5235 60 arcto 4 {pop} repeat
- 12375 5175 11040 5175 60 arcto 4 {pop} repeat
- cp gs col35 1.00 shd ef gr gs col35 s gr
-% Polyline
-n 9735 5175 m 9675 5175 9675 5340 60 arcto 4 {pop} repeat
- 9675 5400 10110 5400 60 arcto 4 {pop} repeat
- 10170 5400 10170 5235 60 arcto 4 {pop} repeat
- 10170 5175 9735 5175 60 arcto 4 {pop} repeat
- cp gs col35 1.00 shd ef gr gs col35 s gr
-% Polyline
-n 7260 6075 m 7200 6075 7200 6240 60 arcto 4 {pop} repeat
- 7200 6300 7815 6300 60 arcto 4 {pop} repeat
- 7875 6300 7875 6135 60 arcto 4 {pop} repeat
- 7875 6075 7260 6075 60 arcto 4 {pop} repeat
- cp gs col35 1.00 shd ef gr gs col35 s gr
-% Polyline
-n 6810 2250 m 6750 2250 6750 2415 60 arcto 4 {pop} repeat
- 6750 2475 8130 2475 60 arcto 4 {pop} repeat
- 8190 2475 8190 2310 60 arcto 4 {pop} repeat
- 8190 2250 6810 2250 60 arcto 4 {pop} repeat
- cp gs col35 1.00 shd ef gr gs col35 s gr
-% Polyline
-n 6360 3375 m 6300 3375 6300 3540 60 arcto 4 {pop} repeat
- 6300 3600 7545 3600 60 arcto 4 {pop} repeat
- 7605 3600 7605 3435 60 arcto 4 {pop} repeat
- 7605 3375 6360 3375 60 arcto 4 {pop} repeat
- cp gs col35 1.00 shd ef gr gs col35 s gr
-% Polyline
-n 6360 4275 m 6300 4275 6300 4440 60 arcto 4 {pop} repeat
- 6300 4500 7275 4500 60 arcto 4 {pop} repeat
- 7335 4500 7335 4335 60 arcto 4 {pop} repeat
- 7335 4275 6360 4275 60 arcto 4 {pop} repeat
- cp gs col35 1.00 shd ef gr gs col35 s gr
-% Polyline
-n 6360 5175 m 6300 5175 6300 5340 60 arcto 4 {pop} repeat
- 6300 5400 7140 5400 60 arcto 4 {pop} repeat
- 7200 5400 7200 5235 60 arcto 4 {pop} repeat
- 7200 5175 6360 5175 60 arcto 4 {pop} repeat
- cp gs col35 1.00 shd ef gr gs col35 s gr
-% Polyline
-gs clippath
-7365 5340 m 7245 5310 l 7365 5280 l 7230 5280 l 7230 5340 l cp
-clip
-n 9630 5310 m 7245 5310 l gs col34 1.00 shd ef gr gs col0 s gr gr
-
-% arrowhead
-n 7365 5340 m 7245 5310 l 7365 5280 l 7365 5310 l 7365 5340 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
-gs clippath
-7500 4395 m 7380 4365 l 7500 4335 l 7365 4335 l 7365 4395 l cp
-clip
-n 11385 4365 m 7380 4365 l gs col34 1.00 shd ef gr gs col0 s gr gr
-
-% arrowhead
-n 7500 4395 m 7380 4365 l 7500 4335 l 7500 4365 l 7500 4395 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
-n 11040 5580 m 10980 5580 10980 5745 60 arcto 4 {pop} repeat
- 10980 5805 12180 5805 60 arcto 4 {pop} repeat
- 12240 5805 12240 5640 60 arcto 4 {pop} repeat
- 12240 5580 11040 5580 60 arcto 4 {pop} repeat
- cp gs col35 1.00 shd ef gr gs col35 s gr
-% Polyline
-n 11040 5985 m 10980 5985 10980 6150 60 arcto 4 {pop} repeat
- 10980 6210 12315 6210 60 arcto 4 {pop} repeat
- 12375 6210 12375 6045 60 arcto 4 {pop} repeat
- 12375 5985 11040 5985 60 arcto 4 {pop} repeat
- cp gs col35 1.00 shd ef gr gs col35 s gr
-% Polyline
-gs clippath
-9958 5554 m 9900 5445 l 10003 5514 l 9912 5414 l 9868 5454 l cp
-clip
-n 11205 6885 m 9900 5445 l gs col34 1.00 shd ef gr gs col0 s gr gr
-
-% arrowhead
-n 9958 5554 m 9900 5445 l 10003 5514 l 9981 5534 l 9958 5554 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
-n 10590 6930 m 10530 6930 10530 7095 60 arcto 4 {pop} repeat
- 10530 7155 12225 7155 60 arcto 4 {pop} repeat
- 12285 7155 12285 6990 60 arcto 4 {pop} repeat
- 12285 6930 10590 6930 60 arcto 4 {pop} repeat
- cp gs col35 1.00 shd ef gr gs col35 s gr
-% Polyline
-n 9690 6930 m 9630 6930 9630 7095 60 arcto 4 {pop} repeat
- 9630 7155 10110 7155 60 arcto 4 {pop} repeat
- 10170 7155 10170 6990 60 arcto 4 {pop} repeat
- 10170 6930 9690 6930 60 arcto 4 {pop} repeat
- cp gs col35 1.00 shd ef gr gs col35 s gr
-/Times-Roman-iso ff 120.00 scf sf
-900 7560 m
-gs 1 -1 sc (Startup, Runtime, Shutdown) col0 sh gr
-/Helvetica-Narrow-iso ff 120.00 scf sf
-6345 2970 m
-gs 1 -1 sc (ap_ctx_get\(...,) col0 sh gr
-/Helvetica-Narrow-iso ff 120.00 scf sf
-10800 2745 m
-gs 1 -1 sc (ap_get_module_config\(...) col0 sh gr
-/Helvetica-Narrow-iso ff 120.00 scf sf
-10800 2880 m
-gs 1 -1 sc (->per_dir_config,) col0 sh gr
-/Helvetica-Narrow-iso ff 120.00 scf sf
-10800 3015 m
-gs 1 -1 sc (&ssl_module\)) col0 sh gr
-% Polyline
-n 7980 4770 m 7920 4770 7920 4935 60 arcto 4 {pop} repeat
- 7920 4995 9075 4995 60 arcto 4 {pop} repeat
- 9135 4995 9135 4830 60 arcto 4 {pop} repeat
- 9135 4770 7980 4770 60 arcto 4 {pop} repeat
- cp gs col35 1.00 shd ef gr gs col35 s gr
-% Polyline
-gs clippath
-7340 2610 m 7425 2520 l 7393 2639 l 7459 2521 l 7406 2492 l cp
-clip
-n 6975 3330 m 7425 2520 l gs col34 1.00 shd ef gr gs col0 s gr gr
-
-% arrowhead
-n 7340 2610 m 7425 2520 l 7393 2639 l 7367 2625 l 7340 2610 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
-gs clippath
-9336 2569 m 9450 2520 l 9373 2616 l 9480 2535 l 9444 2487 l cp
-clip
-n 7200 4230 m 9450 2520 l gs col34 1.00 shd ef gr gs col0 s gr gr
-
-% arrowhead
-n 9336 2569 m 9450 2520 l 9373 2616 l 9354 2593 l 9336 2569 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
-gs clippath
-7321 5196 m 7200 5220 l 7296 5142 l 7174 5199 l 7199 5254 l cp
-clip
-n 7875 4905 m 7200 5220 l gs col34 1.00 shd ef gr gs col0 s gr gr
-
-% arrowhead
-n 7321 5196 m 7200 5220 l 7296 5142 l 7309 5169 l 7321 5196 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
-gs clippath
-6720 4665 m 6750 4545 l 6780 4665 l 6780 4530 l 6720 4530 l cp
-clip
-n 6750 5130 m 6750 4545 l gs col34 1.00 shd ef gr gs col0 s gr gr
-
-% arrowhead
-n 6720 4665 m 6750 4545 l 6780 4665 l 6750 4665 l 6720 4665 l cp gs 0.00 setgray ef gr col0 s
-% Polyline
- [15 15] 15 sd
-gs clippath
-9279 4984 m 9175 4918 l 9298 4927 l 9170 4885 l 9151 4942 l cp
-clip
-n 9850 5143 m 9175 4918 l gs col34 1.00 shd ef gr gs col0 s gr gr
- [] 0 sd
-% arrowhead
-n 9279 4984 m 9175 4918 l 9298 4927 l 9289 4956 l 9279 4984 l cp gs 0.00 setgray ef gr col0 s
-/Helvetica-Narrow-iso ff 120.00 scf sf
-6210 4680 m
-gs 1 -1 sc (->server) col0 sh gr
-/Helvetica-Narrow-iso ff 120.00 scf sf
-8280 6120 m
-gs 1 -1 sc (ap_ctx_get\(...,"ssl"\)) col0 sh gr
-/Helvetica-Narrow-iso ff 120.00 scf sf
-7740 2700 m
-gs 1 -1 sc (ap_get_module_config\(...) col0 sh gr
-/Helvetica-Narrow-iso ff 120.00 scf sf
-7740 2835 m
-gs 1 -1 sc (->module_config,) col0 sh gr
-/Helvetica-Narrow-iso ff 120.00 scf sf
-7740 2970 m
-gs 1 -1 sc (&ssl_module\)) col0 sh gr
-/Helvetica-Narrow-iso ff 120.00 scf sf
-6345 3105 m
-gs 1 -1 sc ("ssl_module"\)) col0 sh gr
-/Times-Roman-iso ff 120.00 scf sf
-1350 7335 m
-gs 1 -1 sc (Configuration Time) col0 sh gr
-/Times-Roman-iso ff 120.00 scf sf
-2025 7110 m
-gs 1 -1 sc (Connection Duration) col0 sh gr
-/Times-Roman-iso ff 120.00 scf sf
-2835 6885 m
-gs 1 -1 sc (Request Duration) col0 sh gr
-/Helvetica-Bold-iso ff 300.00 scf sf
-6345 6795 m
-gs 1 -1 sc (t) col0 sh gr
-/Helvetica-Narrow-iso ff 120.00 scf sf
-7110 5985 m
-gs 1 -1 sc (->client) col0 sh gr
-/Helvetica-Narrow-iso ff 120.00 scf sf
-7065 5085 m
-gs 1 -1 sc (->connection) col0 sh gr
-/Helvetica-Narrow-iso ff 120.00 scf sf
-7065 4770 m
-gs 1 -1 sc (->server) col0 sh gr
-/Helvetica-Narrow-iso ff 120.00 scf sf
-8010 5445 m
-gs 1 -1 sc (SSL_get_app_data\(\)) col0 sh gr
-/Helvetica-Narrow-iso ff 120.00 scf sf
-10530 4050 m
-gs 1 -1 sc (->pSSLCtx) col0 sh gr
-/Helvetica-Narrow-iso ff 120.00 scf sf
-7875 4275 m
-gs 1 -1 sc (SSL_CTX_get_app_data\(\)) col0 sh gr
-/Helvetica-Narrow-iso ff 120.00 scf sf
-10305 5535 m
-gs 1 -1 sc (SSL_get_current_cipher\(\)) col0 sh gr
-/Helvetica-Narrow-iso ff 120.00 scf sf
-10440 5940 m
-gs 1 -1 sc (SSL_get_session\(\)) col0 sh gr
-/Helvetica-Narrow-iso ff 120.00 scf sf
-9540 7335 m
-gs 1 -1 sc (SSL_get_{r,w}bio\(\)) col0 sh gr
-/Helvetica-Narrow-iso ff 120.00 scf sf
-10125 4680 m
-gs 1 -1 sc (SSL_get_SSL_CTX\(\)) col0 sh gr
-/Helvetica-Narrow-iso ff 120.00 scf sf
-10350 5175 m
-gs 1 -1 sc (SSL_get_SSL_METHOD\(\)) col0 sh gr
-/Helvetica-Narrow-iso ff 120.00 scf sf
-11745 4770 m
-gs 1 -1 sc (->method) col0 sh gr
-/Helvetica-Narrow-iso ff 120.00 scf sf
-9945 6480 m
-gs 1 -1 sc (X509_STORE_CTX_get_app_data\(\)) col0 sh gr
-/Helvetica-Narrow-iso ff 120.00 scf sf
-10980 6705 m
-gs 1 -1 sc (SSL_CTX_get_cert_store\(\)) col0 sh gr
-/Helvetica-Narrow-iso ff 120.00 scf sf
-8280 5130 m
-gs 1 -1 sc (SSL_get_app_data2\(\)) col0 sh gr
-/Helvetica-Bold-iso ff 180.00 scf sf
-3645 1620 m
-gs 1 -1 sc (SSLDirConfig) col0 sh gr
-/Helvetica-Bold-iso ff 300.00 scf sf
-10935 3645 m
-gs 1 -1 sc (OpenSSL) col0 sh gr
-/Helvetica-Bold-iso ff 180.00 scf sf
-10935 3825 m
-gs 1 -1 sc ([SSL]) col0 sh gr
-/Helvetica-Bold-iso ff 180.00 scf sf
-11025 5760 m
-gs 1 -1 sc (SSL_CIPHER) col0 sh gr
-/Helvetica-Bold-iso ff 180.00 scf sf
-10980 6165 m
-gs 1 -1 sc (SSL_SESSION) col0 sh gr
-/Helvetica-Bold-iso ff 300.00 scf sf
-10710 7605 m
-gs 1 -1 sc (OpenSSL) col0 sh gr
-/Helvetica-Bold-iso ff 180.00 scf sf
-10575 7110 m
-gs 1 -1 sc (X509_STORE_CTX) col0 sh gr
-/Helvetica-Bold-iso ff 180.00 scf sf
-6795 2430 m
-gs 1 -1 sc (SSLModConfig) col0 sh gr
-/Helvetica-Bold-iso ff 180.00 scf sf
-8865 2430 m
-gs 1 -1 sc (SSLSrvConfig) col0 sh gr
-/Helvetica-Bold-iso ff 180.00 scf sf
-6345 3555 m
-gs 1 -1 sc (ap_global_ctx) col0 sh gr
-/Helvetica-Bold-iso ff 180.00 scf sf
-6345 4455 m
-gs 1 -1 sc (server_rec) col0 sh gr
-/Helvetica-Bold-iso ff 180.00 scf sf
-6345 5355 m
-gs 1 -1 sc (conn_rec) col0 sh gr
-/Helvetica-Bold-iso ff 180.00 scf sf
-9720 5355 m
-gs 1 -1 sc (SSL) col0 sh gr
-/Helvetica-Bold-iso ff 180.00 scf sf
-10665 2430 m
-gs 1 -1 sc (SSLDirConfig) col0 sh gr
-/Helvetica-Bold-iso ff 180.00 scf sf
-7290 6255 m
-gs 1 -1 sc (BUFF) col0 sh gr
-/Helvetica-Bold-iso ff 180.00 scf sf
-11025 5355 m
-gs 1 -1 sc (SSL_METHOD) col0 sh gr
-% Polyline
-15.000 slw
-n 750 225 m 450 225 450 8250 300 arcto 4 {pop} repeat
- 450 8550 12300 8550 300 arcto 4 {pop} repeat
- 12600 8550 12600 525 300 arcto 4 {pop} repeat
- 12600 225 750 225 300 arcto 4 {pop} repeat
- cp gs col0 s gr
-/Helvetica-Bold-iso ff 180.00 scf sf
-11475 4455 m
-gs 1 -1 sc (SSL_CTX) col0 sh gr
-/Helvetica-Bold-iso ff 180.00 scf sf
-8010 4950 m
-gs 1 -1 sc (request_rec) col0 sh gr
-/Times-Roman-iso ff 180.00 scf sf
-10575 675 m
-gs 1 -1 sc (Ralf S. Engelschall) col0 sh gr
-/Helvetica-Bold-iso ff 300.00 scf sf
-4275 675 m
-gs 1 -1 sc (Apache+mod_ssl+OpenSSL) col0 sh gr
-/Times-Roman-iso ff 150.00 scf sf
-10575 855 m
-gs 1 -1 sc (rse@engelschall.com) col0 sh gr
-/Times-Roman-iso ff 150.00 scf sf
-10575 1035 m
-gs 1 -1 sc (www.engelschall.com) col0 sh gr
-/Times-Roman-iso ff 180.00 scf sf
-900 675 m
-gs 1 -1 sc (Version 1.3) col0 sh gr
-/Times-Roman-iso ff 180.00 scf sf
-900 855 m
-gs 1 -1 sc (12-Apr-1999) col0 sh gr
-/Helvetica-Bold-iso ff 360.00 scf sf
-3915 1080 m
-gs 1 -1 sc (Data Structure Overview) col0 sh gr
-/Helvetica-Bold-iso ff 180.00 scf sf
-9720 7110 m
-gs 1 -1 sc (BIO) col0 sh gr
-/Helvetica-Bold-iso ff 180.00 scf sf
-10710 7785 m
-gs 1 -1 sc ([Crypto]) col0 sh gr
-/Helvetica-Bold-iso ff 300.00 scf sf
-8730 3465 m
-gs 1 -1 sc (mod_ssl) col0 sh gr
-/Helvetica-Bold-iso ff 300.00 scf sf
-8145 6750 m
-gs 1 -1 sc (Apache) col0 sh gr
-/Helvetica-Bold-iso ff 300.00 scf sf
-9000 8100 m
-gs 1 -1 sc (Chaining) col0 sh gr
-/Helvetica-Bold-iso ff 300.00 scf sf
-2745 8100 m
-gs 1 -1 sc (Lifetime) col0 sh gr
-/Helvetica-Bold-iso ff 180.00 scf sf
-810 6255 m
-gs 1 -1 sc (ap_global_ctx) col0 sh gr
-/Helvetica-Bold-iso ff 180.00 scf sf
-990 5805 m
-gs 1 -1 sc (SSLModConfig) col0 sh gr
-/Helvetica-Bold-iso ff 180.00 scf sf
-4050 4455 m
-gs 1 -1 sc (SSL_CTX) col0 sh gr
-/Helvetica-Bold-iso ff 180.00 scf sf
-4455 5355 m
-gs 1 -1 sc (server_rec) col0 sh gr
-/Helvetica-Bold-iso ff 180.00 scf sf
-3870 4905 m
-gs 1 -1 sc (SSLSrvConfig) col0 sh gr
-/Helvetica-Bold-iso ff 180.00 scf sf
-1845 4005 m
-gs 1 -1 sc (BUFF) col0 sh gr
-/Helvetica-Bold-iso ff 180.00 scf sf
-2070 3555 m
-gs 1 -1 sc (conn_rec) col0 sh gr
-/Helvetica-Bold-iso ff 180.00 scf sf
-2295 3105 m
-gs 1 -1 sc (BIO) col0 sh gr
-/Helvetica-Bold-iso ff 180.00 scf sf
-2565 2655 m
-gs 1 -1 sc (SSL) col0 sh gr
-/Helvetica-Bold-iso ff 180.00 scf sf
-3915 2070 m
-gs 1 -1 sc (request_rec) col0 sh gr
-$F2psEnd
-rs
-showpage
diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c
deleted file mode 100644
index 2d1b5e1b0a..0000000000
--- a/modules/ssl/mod_ssl.c
+++ /dev/null
@@ -1,248 +0,0 @@
-/* _ _
-** _ __ ___ ___ __| | ___ ___| | mod_ssl
-** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
-** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
-** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
-** |_____|
-** mod_ssl.c
-** Apache API interface structures
-*/
-
-/* ====================================================================
- * Copyright (c) 1998-2001 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * 4. The names "mod_ssl" must not be used to endorse or promote
- * products derived from this software without prior written
- * permission. For written permission, please contact
- * rse@engelschall.com.
- *
- * 5. Products derived from this software may not be called "mod_ssl"
- * nor may "mod_ssl" appear in their names without prior
- * written permission of Ralf S. Engelschall.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
- /* ``I'll be surprised if
- others think that what you
- are doing is honourable.''
- -- Ben Laurie, Apache-SSL author */
-#include "mod_ssl.h"
-
-/* _________________________________________________________________
-**
-** Apache API glue structures
-** _________________________________________________________________
-*/
-
-/*
- * identify the module to SCCS `what' and RCS `ident' commands
- */
-static char const sccsid[] = "@(#) mod_ssl/" MOD_SSL_VERSION " >";
-static char const rcsid[] = "$Id: mod_ssl.c,v 1.1 2001/05/04 21:54:42 rse Exp $";
-
-/*
- * the table of configuration directives we provide
- */
-static command_rec ssl_config_cmds[] = {
- /*
- * Global (main-server) context configuration directives
- */
- AP_SRV_CMD(Mutex, TAKE1,
- "SSL lock for handling internal mutual exclusions "
- "(`none', `file:/path/to/file')")
- AP_SRV_CMD(PassPhraseDialog, TAKE1,
- "SSL dialog mechanism for the pass phrase query "
- "(`builtin', `exec:/path/to/program')")
- AP_SRV_CMD(SessionCache, TAKE1,
- "SSL Session Cache storage "
- "(`none', `dbm:/path/to/file')")
-#ifdef SSL_EXPERIMENTAL_ENGINE
- AP_SRV_CMD(CryptoDevice, TAKE1,
- "SSL external Crypto Device usage "
- "(`builtin', `...')")
-#endif
- AP_SRV_CMD(RandomSeed, TAKE23,
- "SSL Pseudo Random Number Generator (PRNG) seeding source "
- "(`startup|connect builtin|file:/path|exec:/path [bytes]')")
-
- /*
- * Per-server context configuration directives
- */
- AP_SRV_CMD(Engine, FLAG,
- "SSL switch for the protocol engine "
- "(`on', `off')")
- AP_ALL_CMD(CipherSuite, TAKE1,
- "Colon-delimited list of permitted SSL Ciphers "
- "(`XXX:...:XXX' - see manual)")
- AP_SRV_CMD(CertificateFile, TAKE1,
- "SSL Server Certificate file "
- "(`/path/to/file' - PEM or DER encoded)")
- AP_SRV_CMD(CertificateKeyFile, TAKE1,
- "SSL Server Private Key file "
- "(`/path/to/file' - PEM or DER encoded)")
- AP_SRV_CMD(CertificateChainFile, TAKE1,
- "SSL Server CA Certificate Chain file "
- "(`/path/to/file' - PEM encoded)")
-#ifdef SSL_EXPERIMENTAL_PERDIRCA
- AP_ALL_CMD(CACertificatePath, TAKE1,
- "SSL CA Certificate path "
- "(`/path/to/dir' - contains PEM encoded files)")
- AP_ALL_CMD(CACertificateFile, TAKE1,
- "SSL CA Certificate file "
- "(`/path/to/file' - PEM encoded)")
-#else
- AP_SRV_CMD(CACertificatePath, TAKE1,
- "SSL CA Certificate path "
- "(`/path/to/dir' - contains PEM encoded files)")
- AP_SRV_CMD(CACertificateFile, TAKE1,
- "SSL CA Certificate file "
- "(`/path/to/file' - PEM encoded)")
-#endif
- AP_SRV_CMD(CARevocationPath, TAKE1,
- "SSL CA Certificate Revocation List (CRL) path "
- "(`/path/to/dir' - contains PEM encoded files)")
- AP_SRV_CMD(CARevocationFile, TAKE1,
- "SSL CA Certificate Revocation List (CRL) file "
- "(`/path/to/file' - PEM encoded)")
- AP_ALL_CMD(VerifyClient, TAKE1,
- "SSL Client verify type "
- "(`none', `optional', `require', `optional_no_ca')")
- AP_ALL_CMD(VerifyDepth, TAKE1,
- "SSL Client verify depth "
- "(`N' - number of intermediate certificates)")
- AP_SRV_CMD(SessionCacheTimeout, TAKE1,
- "SSL Session Cache object lifetime "
- "(`N' - number of seconds)")
- AP_SRV_CMD(Log, TAKE1,
- "SSL logfile for SSL-related messages "
- "(`/path/to/file', `|/path/to/program')")
- AP_SRV_CMD(LogLevel, TAKE1,
- "SSL logfile verbosity level "
- "(`none', `error', `warn', `info', `debug')")
- AP_SRV_CMD(Protocol, RAW_ARGS,
- "Enable or disable various SSL protocols"
- "(`[+-][SSLv2|SSLv3|TLSv1] ...' - see manual)")
-
-#ifdef SSL_EXPERIMENTAL_PROXY
- /*
- * Proxy configuration for remote SSL connections
- */
- AP_SRV_CMD(ProxyProtocol, RAW_ARGS,
- "SSL Proxy: enable or disable SSL protocol flavors "
- "(`[+-][SSLv2|SSLv3|TLSv1] ...' - see manual)")
- AP_SRV_CMD(ProxyCipherSuite, TAKE1,
- "SSL Proxy: colon-delimited list of permitted SSL ciphers "
- "(`XXX:...:XXX' - see manual)")
- AP_SRV_CMD(ProxyVerify, FLAG,
- "SSL Proxy: whether to verify the remote certificate "
- "(`on' or `off')")
- AP_SRV_CMD(ProxyVerifyDepth, TAKE1,
- "SSL Proxy: maximum certificate verification depth "
- "(`N' - number of intermediate certificates)")
- AP_SRV_CMD(ProxyCACertificateFile, TAKE1,
- "SSL Proxy: file containing server certificates "
- "(`/path/to/file' - PEM encoded certificates)")
- AP_SRV_CMD(ProxyCACertificatePath, TAKE1,
- "SSL Proxy: directory containing server certificates "
- "(`/path/to/dir' - contains PEM encoded certificates)")
- AP_SRV_CMD(ProxyMachineCertificateFile, TAKE1,
- "SSL Proxy: file containing client certificates "
- "(`/path/to/file' - PEM encoded certificates)")
- AP_SRV_CMD(ProxyMachineCertificatePath, TAKE1,
- "SSL Proxy: directory containing client certificates "
- "(`/path/to/dir' - contains PEM encoded certificates)")
-#endif
-
- /*
- * Per-directory context configuration directives
- */
- AP_DIR_CMD(Options, OPTIONS, RAW_ARGS,
- "Set one of more options to configure the SSL engine"
- "(`[+-]option[=value] ...' - see manual)")
- AP_DIR_CMD(RequireSSL, AUTHCFG, NO_ARGS,
- "Require the SSL protocol for the per-directory context "
- "(no arguments)")
- AP_DIR_CMD(Require, AUTHCFG, RAW_ARGS,
- "Require a boolean expresion to evaluate to true for granting access"
- "(arbitrary complex boolean expression - see manual)")
-
- AP_END_CMD
-};
-
-static const handler_rec ssl_config_handler[] = {
- { "mod_ssl:content-handler", ssl_hook_Handler },
- { NULL, NULL }
-};
-
-/*
- * the main Apache API config structure
- */
-module MODULE_VAR_EXPORT ssl_module = {
- STANDARD_MODULE_STUFF,
-
- /* Standard API (always present) */
-
- ssl_init_Module, /* module initializer */
- ssl_config_perdir_create, /* create per-dir config structures */
- ssl_config_perdir_merge, /* merge per-dir config structures */
- ssl_config_server_create, /* create per-server config structures */
- ssl_config_server_merge, /* merge per-server config structures */
- ssl_config_cmds, /* table of config file commands */
- ssl_config_handler, /* [#8] MIME-typed-dispatched handlers */
- ssl_hook_Translate, /* [#1] URI to filename translation */
- ssl_hook_Auth, /* [#4] validate user id from request */
- ssl_hook_UserCheck, /* [#5] check if the user is ok _here_ */
- ssl_hook_Access, /* [#3] check access by host address */
- NULL, /* [#6] determine MIME type */
- ssl_hook_Fixup, /* [#7] pre-run fixups */
- NULL, /* [#9] log a transaction */
- NULL, /* [#2] header parser */
- ssl_init_Child, /* child_init */
- NULL, /* child_exit */
- ssl_hook_ReadReq, /* [#0] post read-request */
-
- /* Extended API (forced to be enabled with mod_ssl) */
-
- ssl_hook_AddModule, /* after modules was added to core */
- ssl_hook_RemoveModule, /* before module is removed from core */
- ssl_hook_RewriteCommand, /* configuration command rewriting */
- ssl_hook_NewConnection, /* socket connection open */
- ssl_hook_CloseConnection /* socket connection close */
-};
-
diff --git a/modules/ssl/mod_ssl.h b/modules/ssl/mod_ssl.h
deleted file mode 100644
index 8731ef9de4..0000000000
--- a/modules/ssl/mod_ssl.h
+++ /dev/null
@@ -1,854 +0,0 @@
-/* _ _
-** _ __ ___ ___ __| | ___ ___| | mod_ssl
-** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
-** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
-** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
-** |_____|
-** mod_ssl.h
-** Global header
-*/
-
-/* ====================================================================
- * Copyright (c) 1998-2001 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * 4. The names "mod_ssl" must not be used to endorse or promote
- * products derived from this software without prior written
- * permission. For written permission, please contact
- * rse@engelschall.com.
- *
- * 5. Products derived from this software may not be called "mod_ssl"
- * nor may "mod_ssl" appear in their names without prior
- * written permission of Ralf S. Engelschall.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
- /* ``The Apache Group: a collection
- of talented individuals who are
- trying to perfect the art of
- never finishing something.''
- -- Rob Hartill */
-#ifndef MOD_SSL_H
-#define MOD_SSL_H 1
-
-/*
- * Check whether Extended API (EAPI) is enabled
- */
-#ifndef EAPI
-#error "mod_ssl requires Extended API (EAPI)"
-#endif
-
-/*
- * Optionally enable the experimental stuff, but allow the user to
- * override the decision which experimental parts are included by using
- * CFLAGS="-DSSL_EXPERIMENTAL_xxxx_IGNORE".
- */
-#ifdef SSL_EXPERIMENTAL
-#ifndef SSL_EXPERIMENTAL_PERDIRCA_IGNORE
-#define SSL_EXPERIMENTAL_PERDIRCA
-#endif
-#ifndef SSL_EXPERIMENTAL_PROXY_IGNORE
-#define SSL_EXPERIMENTAL_PROXY
-#endif
-#ifdef SSL_ENGINE
-#ifndef SSL_EXPERIMENTAL_ENGINE_IGNORE
-#define SSL_EXPERIMENTAL_ENGINE
-#endif
-#endif
-#endif /* SSL_EXPERIMENTAL */
-
-/*
- * Power up our brain...
- */
-
-/* OS headers */
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <time.h>
-#ifndef WIN32
-#include <sys/time.h>
-#endif
-#ifdef WIN32
-#include <wincrypt.h>
-#include <winsock2.h>
-#endif
-
-/* OpenSSL headers */
-#include <openssl/ssl.h>
-#include <openssl/err.h>
-#include <openssl/x509.h>
-#include <openssl/x509v3.h>
-#include <openssl/pem.h>
-#include <openssl/crypto.h>
-#include <openssl/evp.h>
-#include <openssl/rand.h>
-#ifdef SSL_EXPERIMENTAL_ENGINE
-#include <openssl/engine.h>
-#endif
-
-/* Apache headers */
-#define CORE_PRIVATE
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_conf_globals.h"
-#include "http_protocol.h"
-#include "http_request.h"
-#include "http_main.h"
-#include "http_core.h"
-#include "http_log.h"
-#include "scoreboard.h"
-#include "util_md5.h"
-#include "fnmatch.h"
-#undef CORE_PRIVATE
-
-/* mod_ssl headers */
-#include "ssl_expr.h"
-#include "ssl_util_ssl.h"
-#include "ssl_util_table.h"
-
-/*
- * Provide reasonable default for some defines
- */
-#ifndef FALSE
-#define FALSE (0)
-#endif
-#ifndef TRUE
-#define TRUE (!FALSE)
-#endif
-#ifndef PFALSE
-#define PFALSE ((void *)FALSE)
-#endif
-#ifndef PTRUE
-#define PTRUE ((void *)TRUE)
-#endif
-#ifndef UNSET
-#define UNSET (-1)
-#endif
-#ifndef NUL
-#define NUL '\0'
-#endif
-#ifndef RAND_MAX
-#include <limits.h>
-#define RAND_MAX INT_MAX
-#endif
-
-/*
- * Provide reasonable defines for some types
- */
-#ifndef BOOL
-#define BOOL unsigned int
-#endif
-#ifndef UCHAR
-#define UCHAR unsigned char
-#endif
-
-/*
- * Provide useful shorthands
- */
-#define strEQ(s1,s2) (strcmp(s1,s2) == 0)
-#define strNE(s1,s2) (strcmp(s1,s2) != 0)
-#define strEQn(s1,s2,n) (strncmp(s1,s2,n) == 0)
-#define strNEn(s1,s2,n) (strncmp(s1,s2,n) != 0)
-
-#define strcEQ(s1,s2) (strcasecmp(s1,s2) == 0)
-#define strcNE(s1,s2) (strcasecmp(s1,s2) != 0)
-#define strcEQn(s1,s2,n) (strncasecmp(s1,s2,n) == 0)
-#define strcNEn(s1,s2,n) (strncasecmp(s1,s2,n) != 0)
-
-#define strIsEmpty(s) (s == NULL || s[0] == NUL)
-
-#define cfgMerge(el,unset) new->el = add->el == unset ? base->el : add->el
-#define cfgMergeArray(el) new->el = ap_append_arrays(p, add->el, base->el)
-#define cfgMergeTable(el) new->el = ap_overlay_tables(p, add->el, base->el)
-#define cfgMergeCtx(el) new->el = ap_ctx_overlay(p, add->el, base->el)
-#define cfgMergeString(el) cfgMerge(el, NULL)
-#define cfgMergeBool(el) cfgMerge(el, UNSET)
-#define cfgMergeInt(el) cfgMerge(el, UNSET)
-
-#define myModConfig() (SSLModConfigRec *)ap_ctx_get(ap_global_ctx, "ssl_module")
-#define mySrvConfig(srv) (SSLSrvConfigRec *)ap_get_module_config(srv->module_config, &ssl_module)
-#define myDirConfig(req) (SSLDirConfigRec *)ap_get_module_config(req->per_dir_config, &ssl_module)
-
-#define myCtxVarSet(mc,num,val) mc->rCtx.pV##num = val
-#define myCtxVarGet(mc,num,type) (type)(mc->rCtx.pV##num)
-
-#define AP_ALL_CMD(name, args, desc) \
- { "SSL"#name, ssl_cmd_SSL##name, NULL, RSRC_CONF|OR_AUTHCFG, args, desc },
-#define AP_SRV_CMD(name, args, desc) \
- { "SSL"#name, ssl_cmd_SSL##name, NULL, RSRC_CONF, args, desc },
-#define AP_DIR_CMD(name, type, args, desc) \
- { "SSL"#name, ssl_cmd_SSL##name, NULL, OR_##type, args, desc },
-#define AP_END_CMD \
- { NULL }
-
-/*
- * SSL Logging
- */
-#define SSL_LOG_NONE (1<<0)
-#define SSL_LOG_ERROR (1<<1)
-#define SSL_LOG_WARN (1<<2)
-#define SSL_LOG_INFO (1<<3)
-#define SSL_LOG_TRACE (1<<4)
-#define SSL_LOG_DEBUG (1<<5)
-#define SSL_LOG_MASK (SSL_LOG_ERROR|SSL_LOG_WARN|SSL_LOG_INFO|SSL_LOG_TRACE|SSL_LOG_DEBUG)
-
-#define SSL_ADD_NONE (1<<8)
-#define SSL_ADD_ERRNO (1<<9)
-#define SSL_ADD_SSLERR (1<<10)
-#define SSL_NO_TIMESTAMP (1<<11)
-#define SSL_NO_LEVELID (1<<12)
-#define SSL_NO_NEWLINE (1<<13)
-
-/*
- * Defaults for the configuration
- */
-#ifndef SSL_SESSION_CACHE_TIMEOUT
-#define SSL_SESSION_CACHE_TIMEOUT 300
-#endif
-
-/*
- * Support for file locking: Try to determine whether we should use fcntl() or
- * flock(). Would be better ap_config.h could provide this... :-(
- */
-#if defined(USE_FCNTL_SERIALIZED_ACCEPT)
-#define SSL_USE_FCNTL 1
-#include <fcntl.h>
-#endif
-#if defined(USE_FLOCK_SERIALIZED_ACCEPT)
-#define SSL_USE_FLOCK 1
-#include <sys/file.h>
-#endif
-#if !defined(SSL_USE_FCNTL) && !defined(SSL_USE_FLOCK)
-#define SSL_USE_FLOCK 1
-#if !defined(MPE) && !defined(WIN32)
-#include <sys/file.h>
-#endif
-#ifndef LOCK_UN
-#undef SSL_USE_FLOCK
-#define SSL_USE_FCNTL 1
-#include <fcntl.h>
-#endif
-#endif
-#ifdef AIX
-#undef SSL_USE_FLOCK
-#define SSL_USE_FCNTL 1
-#include <fcntl.h>
-#endif
-
-/*
- * Support for Mutex
- */
-#ifndef WIN32
-#define SSL_MUTEX_LOCK_MODE ( S_IRUSR|S_IWUSR )
-#else
-#define SSL_MUTEX_LOCK_MODE (_S_IREAD|_S_IWRITE )
-#endif
-#if defined(USE_SYSVSEM_SERIALIZED_ACCEPT) ||\
- (defined(__FreeBSD__) && defined(__FreeBSD_version) &&\
- __FreeBSD_version >= 300000) ||\
- (defined(LINUX) && defined(__GLIBC__) && defined(__GLIBC_MINOR__) &&\
- LINUX >= 2 && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1) ||\
- defined(SOLARIS2) || defined(__hpux) ||\
- (defined (__digital__) && defined (__unix__))
-#define SSL_CAN_USE_SEM
-#define SSL_HAVE_IPCSEM
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/sem.h>
-/*
- * Some platforms have a `union semun' pre-defined but Single Unix
- * Specification (SUSv2) says in semctl(2): `If required, it is of
- * type union semun, which the application program must explicitly
- * declare'. So we define it always ourself to avoid problems (but under
- * a different name to avoid a namespace clash).
- */
-union ssl_ipc_semun {
- long val;
- struct semid_ds *buf;
- unsigned short int *array;
-};
-#endif
-#ifdef WIN32
-#define SSL_CAN_USE_SEM
-#define SSL_HAVE_W32SEM
-#include "multithread.h"
-#include <process.h>
-#endif
-
-/*
- * Support for MM library
- */
-#ifndef WIN32
-#define SSL_MM_FILE_MODE ( S_IRUSR|S_IWUSR )
-#else
-#define SSL_MM_FILE_MODE ( _S_IREAD|_S_IWRITE )
-#endif
-
-/*
- * Support for DBM library
- */
-#ifndef WIN32
-#define SSL_DBM_FILE_MODE ( S_IRUSR|S_IWUSR )
-#else
-#define SSL_USE_SDBM
-#define SSL_DBM_FILE_MODE ( _S_IREAD|_S_IWRITE )
-#endif
-
-#ifdef SSL_USE_SDBM
-#include "ssl_util_sdbm.h"
-#define ssl_dbm_open sdbm_open
-#define ssl_dbm_close sdbm_close
-#define ssl_dbm_store sdbm_store
-#define ssl_dbm_fetch sdbm_fetch
-#define ssl_dbm_delete sdbm_delete
-#define ssl_dbm_firstkey sdbm_firstkey
-#define ssl_dbm_nextkey sdbm_nextkey
-#define SSL_DBM_FILE_SUFFIX_DIR ".dir"
-#define SSL_DBM_FILE_SUFFIX_PAG ".pag"
-#else /* !SSL_USE_SDBM */
-#if defined(__GLIBC__) && defined(__GLIBC_MINOR__) \
- && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
-#include <db1/ndbm.h>
-#else
-#include <ndbm.h>
-#endif
-#define ssl_dbm_open dbm_open
-#define ssl_dbm_close dbm_close
-#define ssl_dbm_store dbm_store
-#define ssl_dbm_fetch dbm_fetch
-#define ssl_dbm_delete dbm_delete
-#define ssl_dbm_firstkey dbm_firstkey
-#define ssl_dbm_nextkey dbm_nextkey
-#if !defined(SSL_DBM_FILE_SUFFIX_DIR) && !defined(SSL_DBM_FILE_SUFFIX_PAG)
-#if defined(DBM_SUFFIX)
-#define SSL_DBM_FILE_SUFFIX_DIR DBM_SUFFIX
-#define SSL_DBM_FILE_SUFFIX_PAG DBM_SUFFIX
-#elif defined(__FreeBSD__) || (defined(DB_LOCK) && defined(DB_SHMEM))
-#define SSL_DBM_FILE_SUFFIX_DIR ".db"
-#define SSL_DBM_FILE_SUFFIX_PAG ".db"
-#else
-#define SSL_DBM_FILE_SUFFIX_DIR ".dir"
-#define SSL_DBM_FILE_SUFFIX_PAG ".pag"
-#endif
-#endif
-#endif /* !SSL_USE_SDBM */
-
-/*
- * Check for OpenSSL version
- */
-#if SSL_LIBRARY_VERSION < 0x00903100
-#error "mod_ssl requires OpenSSL 0.9.3 or higher"
-#endif
-
-/*
- * The own data structures
- */
-typedef struct {
- pool *pPool;
- pool *pSubPool;
- array_header *aData;
-} ssl_ds_array;
-
-typedef struct {
- pool *pPool;
- pool *pSubPool;
- array_header *aKey;
- array_header *aData;
-} ssl_ds_table;
-
-/*
- * Define the certificate algorithm types
- */
-
-typedef int ssl_algo_t;
-
-#define SSL_ALGO_UNKNOWN (0)
-#define SSL_ALGO_RSA (1<<0)
-#define SSL_ALGO_DSA (1<<1)
-#define SSL_ALGO_ALL (SSL_ALGO_RSA|SSL_ALGO_DSA)
-
-#define SSL_AIDX_RSA (0)
-#define SSL_AIDX_DSA (1)
-#define SSL_AIDX_MAX (2)
-
-/*
- * Define IDs for the temporary RSA keys and DH params
- */
-
-#define SSL_TKP_GEN (0)
-#define SSL_TKP_ALLOC (1)
-#define SSL_TKP_FREE (2)
-
-#define SSL_TKPIDX_RSA512 (0)
-#define SSL_TKPIDX_RSA1024 (1)
-#define SSL_TKPIDX_DH512 (2)
-#define SSL_TKPIDX_DH1024 (3)
-#define SSL_TKPIDX_MAX (4)
-
-/*
- * Define the SSL options
- */
-#define SSL_OPT_NONE (0)
-#define SSL_OPT_RELSET (1<<0)
-#define SSL_OPT_STDENVVARS (1<<1)
-#define SSL_OPT_COMPATENVVARS (1<<2)
-#define SSL_OPT_EXPORTCERTDATA (1<<3)
-#define SSL_OPT_FAKEBASICAUTH (1<<4)
-#define SSL_OPT_STRICTREQUIRE (1<<5)
-#define SSL_OPT_OPTRENEGOTIATE (1<<6)
-#define SSL_OPT_ALL (SSL_OPT_STDENVVARS|SSL_OPT_COMPATENVVAR|SSL_OPT_EXPORTCERTDATA|SSL_OPT_FAKEBASICAUTH|SSL_OPT_STRICTREQUIRE|SSL_OPT_OPTRENEGOTIATE)
-typedef int ssl_opt_t;
-
-/*
- * Define the SSL Protocol options
- */
-#define SSL_PROTOCOL_NONE (0)
-#define SSL_PROTOCOL_SSLV2 (1<<0)
-#define SSL_PROTOCOL_SSLV3 (1<<1)
-#define SSL_PROTOCOL_TLSV1 (1<<2)
-#define SSL_PROTOCOL_ALL (SSL_PROTOCOL_SSLV2|SSL_PROTOCOL_SSLV3|SSL_PROTOCOL_TLSV1)
-typedef int ssl_proto_t;
-
-/*
- * Define the SSL verify levels
- */
-typedef enum {
- SSL_CVERIFY_UNSET = UNSET,
- SSL_CVERIFY_NONE = 0,
- SSL_CVERIFY_OPTIONAL = 1,
- SSL_CVERIFY_REQUIRE = 2,
- SSL_CVERIFY_OPTIONAL_NO_CA = 3
-} ssl_verify_t;
-
-/*
- * Define the SSL pass phrase dialog types
- */
-typedef enum {
- SSL_PPTYPE_UNSET = UNSET,
- SSL_PPTYPE_BUILTIN = 0,
- SSL_PPTYPE_FILTER = 1
-} ssl_pphrase_t;
-
-/*
- * Define the Path Checking modes
- */
-#define SSL_PCM_EXISTS 1
-#define SSL_PCM_ISREG 2
-#define SSL_PCM_ISDIR 4
-#define SSL_PCM_ISNONZERO 8
-typedef unsigned int ssl_pathcheck_t;
-
-/*
- * Define the SSL session cache modes and structures
- */
-typedef enum {
- SSL_SCMODE_UNSET = UNSET,
- SSL_SCMODE_NONE = 0,
- SSL_SCMODE_DBM = 1,
- SSL_SCMODE_SHMHT = 2,
- SSL_SCMODE_SHMCB = 3
-} ssl_scmode_t;
-
-/*
- * Define the SSL mutex modes
- */
-typedef enum {
- SSL_MUTEXMODE_UNSET = UNSET,
- SSL_MUTEXMODE_NONE = 0,
- SSL_MUTEXMODE_FILE = 1,
- SSL_MUTEXMODE_SEM = 2
-} ssl_mutexmode_t;
-
-/*
- * Define the SSL requirement structure
- */
-typedef struct {
- char *cpExpr;
- ssl_expr *mpExpr;
-} ssl_require_t;
-
-/*
- * Define the SSL random number generator seeding source
- */
-typedef enum {
- SSL_RSCTX_STARTUP = 1,
- SSL_RSCTX_CONNECT = 2
-} ssl_rsctx_t;
-typedef enum {
- SSL_RSSRC_BUILTIN = 1,
- SSL_RSSRC_FILE = 2,
- SSL_RSSRC_EXEC = 3
-#if SSL_LIBRARY_VERSION >= 0x00905100
- ,SSL_RSSRC_EGD = 4
-#endif
-} ssl_rssrc_t;
-typedef struct {
- ssl_rsctx_t nCtx;
- ssl_rssrc_t nSrc;
- char *cpPath;
- int nBytes;
-} ssl_randseed_t;
-
-/*
- * Define the structure of an ASN.1 anything
- */
-typedef struct {
- long int nData;
- unsigned char *cpData;
-} ssl_asn1_t;
-
-/*
- * Define the mod_ssl per-module configuration structure
- * (i.e. the global configuration for each httpd process)
- */
-
-typedef struct {
- pool *pPool;
- BOOL bFixed;
- int nInitCount;
- int nSessionCacheMode;
- char *szSessionCacheDataFile;
- int nSessionCacheDataSize;
- AP_MM *pSessionCacheDataMM;
- table_t *tSessionCacheDataTable;
- ssl_mutexmode_t nMutexMode;
- char *szMutexFile;
- int nMutexFD;
- int nMutexSEMID;
- array_header *aRandSeed;
- ssl_ds_table *tTmpKeys;
- void *pTmpKeys[SSL_TKPIDX_MAX];
- ssl_ds_table *tPublicCert;
- ssl_ds_table *tPrivateKey;
-#ifdef SSL_EXPERIMENTAL_ENGINE
- char *szCryptoDevice;
-#endif
- struct {
- void *pV1, *pV2, *pV3, *pV4, *pV5, *pV6, *pV7, *pV8, *pV9, *pV10;
- } rCtx;
-#ifdef SSL_VENDOR
- ap_ctx *ctx;
-#endif
-} SSLModConfigRec;
-
-/*
- * Define the mod_ssl per-server configuration structure
- * (i.e. the configuration for the main server
- * and all <VirtualHost> contexts)
- */
-typedef struct {
- BOOL bEnabled;
- char *szPublicCertFile[SSL_AIDX_MAX];
- char *szPrivateKeyFile[SSL_AIDX_MAX];
- char *szCertificateChain;
- char *szCACertificatePath;
- char *szCACertificateFile;
- char *szLogFile;
- char *szCipherSuite;
- FILE *fileLogFile;
- int nLogLevel;
- int nVerifyDepth;
- ssl_verify_t nVerifyClient;
- X509 *pPublicCert[SSL_AIDX_MAX];
- EVP_PKEY *pPrivateKey[SSL_AIDX_MAX];
- SSL_CTX *pSSLCtx;
- int nSessionCacheTimeout;
- int nPassPhraseDialogType;
- char *szPassPhraseDialogPath;
- ssl_proto_t nProtocol;
- char *szCARevocationPath;
- char *szCARevocationFile;
- X509_STORE *pRevocationStore;
-#ifdef SSL_EXPERIMENTAL_PROXY
- /* Configuration details for proxy operation */
- ssl_proto_t nProxyProtocol;
- int bProxyVerify;
- int nProxyVerifyDepth;
- char *szProxyCACertificatePath;
- char *szProxyCACertificateFile;
- char *szProxyClientCertificateFile;
- char *szProxyClientCertificatePath;
- char *szProxyCipherSuite;
- SSL_CTX *pSSLProxyCtx;
- STACK_OF(X509_INFO) *skProxyClientCerts;
-#endif
-#ifdef SSL_VENDOR
- ap_ctx *ctx;
-#endif
-} SSLSrvConfigRec;
-
-/*
- * Define the mod_ssl per-directory configuration structure
- * (i.e. the local configuration for all <Directory>
- * and .htaccess contexts)
- */
-typedef struct {
- BOOL bSSLRequired;
- array_header *aRequirement;
- ssl_opt_t nOptions;
- ssl_opt_t nOptionsAdd;
- ssl_opt_t nOptionsDel;
- char *szCipherSuite;
- ssl_verify_t nVerifyClient;
- int nVerifyDepth;
-#ifdef SSL_EXPERIMENTAL_PERDIRCA
- char *szCACertificatePath;
- char *szCACertificateFile;
-#endif
-#ifdef SSL_VENDOR
- ap_ctx *ctx;
-#endif
-} SSLDirConfigRec;
-
-/*
- * function prototypes
- */
-
-/* API glue structures */
-extern module MODULE_VAR_EXPORT ssl_module;
-
-/* configuration handling */
-void ssl_config_global_create(void);
-void ssl_config_global_fix(void);
-BOOL ssl_config_global_isfixed(void);
-void *ssl_config_server_create(pool *, server_rec *);
-void *ssl_config_server_merge(pool *, void *, void *);
-void *ssl_config_perdir_create(pool *, char *);
-void *ssl_config_perdir_merge(pool *, void *, void *);
-const char *ssl_cmd_SSLMutex(cmd_parms *, char *, char *);
-const char *ssl_cmd_SSLPassPhraseDialog(cmd_parms *, char *, char *);
-const char *ssl_cmd_SSLCryptoDevice(cmd_parms *, char *, char *);
-const char *ssl_cmd_SSLRandomSeed(cmd_parms *, char *, char *, char *, char *);
-const char *ssl_cmd_SSLEngine(cmd_parms *, char *, int);
-const char *ssl_cmd_SSLCipherSuite(cmd_parms *, SSLDirConfigRec *, char *);
-const char *ssl_cmd_SSLCertificateFile(cmd_parms *, char *, char *);
-const char *ssl_cmd_SSLCertificateKeyFile(cmd_parms *, char *, char *);
-const char *ssl_cmd_SSLCertificateChainFile(cmd_parms *, char *, char *);
-const char *ssl_cmd_SSLCACertificatePath(cmd_parms *, SSLDirConfigRec *, char *);
-const char *ssl_cmd_SSLCACertificateFile(cmd_parms *, SSLDirConfigRec *, char *);
-const char *ssl_cmd_SSLCARevocationPath(cmd_parms *, SSLDirConfigRec *, char *);
-const char *ssl_cmd_SSLCARevocationFile(cmd_parms *, SSLDirConfigRec *, char *);
-const char *ssl_cmd_SSLVerifyClient(cmd_parms *, SSLDirConfigRec *, char *);
-const char *ssl_cmd_SSLVerifyDepth(cmd_parms *, SSLDirConfigRec *, char *);
-const char *ssl_cmd_SSLSessionCache(cmd_parms *, char *, char *);
-const char *ssl_cmd_SSLSessionCacheTimeout(cmd_parms *, char *, char *);
-const char *ssl_cmd_SSLLog(cmd_parms *, char *, char *);
-const char *ssl_cmd_SSLLogLevel(cmd_parms *, char *, char *);
-const char *ssl_cmd_SSLProtocol(cmd_parms *, char *, const char *);
-const char *ssl_cmd_SSLOptions(cmd_parms *, SSLDirConfigRec *, const char *);
-const char *ssl_cmd_SSLRequireSSL(cmd_parms *, SSLDirConfigRec *, char *);
-const char *ssl_cmd_SSLRequire(cmd_parms *, SSLDirConfigRec *, char *);
-#ifdef SSL_EXPERIMENTAL_PROXY
-const char *ssl_cmd_SSLProxyProtocol(cmd_parms *, char *, const char *);
-const char *ssl_cmd_SSLProxyCipherSuite(cmd_parms *, char *, char *);
-const char *ssl_cmd_SSLProxyVerify(cmd_parms *, char *, int);
-const char *ssl_cmd_SSLProxyVerifyDepth(cmd_parms *, char *, char *);
-const char *ssl_cmd_SSLProxyCACertificatePath(cmd_parms *, char *, char *);
-const char *ssl_cmd_SSLProxyCACertificateFile(cmd_parms *, char *, char *);
-const char *ssl_cmd_SSLProxyMachineCertificatePath(cmd_parms *, char *, char *);
-const char *ssl_cmd_SSLProxyMachineCertificateFile(cmd_parms *, char *, char *);
-#endif
-
-/* module initialization */
-void ssl_init_Module(server_rec *, pool *);
-void ssl_init_SSLLibrary(void);
-void ssl_init_Engine(server_rec *, pool *);
-void ssl_init_TmpKeysHandle(int, server_rec *, pool *);
-void ssl_init_ConfigureServer(server_rec *, pool *, SSLSrvConfigRec *);
-void ssl_init_CheckServers(server_rec *, pool *);
-STACK_OF(X509_NAME)
- *ssl_init_FindCAList(server_rec *, pool *, char *, char *);
-void ssl_init_Child(server_rec *, pool *);
-void ssl_init_ChildKill(void *);
-void ssl_init_ModuleKill(void *);
-
-/* Apache API hooks */
-void ssl_hook_AddModule(module *);
-void ssl_hook_RemoveModule(module *);
-char *ssl_hook_RewriteCommand(cmd_parms *, void *, const char *);
-void ssl_hook_NewConnection(conn_rec *);
-void ssl_hook_TimeoutConnection(int);
-void ssl_hook_CloseConnection(conn_rec *);
-int ssl_hook_Translate(request_rec *);
-int ssl_hook_Auth(request_rec *);
-int ssl_hook_UserCheck(request_rec *);
-int ssl_hook_Access(request_rec *);
-int ssl_hook_Fixup(request_rec *);
-int ssl_hook_ReadReq(request_rec *);
-int ssl_hook_Handler(request_rec *);
-
-/* OpenSSL callbacks */
-RSA *ssl_callback_TmpRSA(SSL *, int, int);
-DH *ssl_callback_TmpDH(SSL *, int, int);
-int ssl_callback_SSLVerify(int, X509_STORE_CTX *);
-int ssl_callback_SSLVerify_CRL(int, X509_STORE_CTX *, server_rec *);
-int ssl_callback_NewSessionCacheEntry(SSL *, SSL_SESSION *);
-SSL_SESSION *ssl_callback_GetSessionCacheEntry(SSL *, unsigned char *, int, int *);
-void ssl_callback_DelSessionCacheEntry(SSL_CTX *, SSL_SESSION *);
-void ssl_callback_LogTracingState(SSL *, int, int);
-
-/* Session Cache Support */
-void ssl_scache_init(server_rec *, pool *);
-void ssl_scache_kill(server_rec *);
-BOOL ssl_scache_store(server_rec *, UCHAR *, int, time_t, SSL_SESSION *);
-SSL_SESSION *ssl_scache_retrieve(server_rec *, UCHAR *, int);
-void ssl_scache_remove(server_rec *, UCHAR *, int);
-void ssl_scache_expire(server_rec *);
-void ssl_scache_status(server_rec *, pool *, void (*)(char *, void *), void *);
-char *ssl_scache_id2sz(UCHAR *, int);
-void ssl_scache_dbm_init(server_rec *, pool *);
-void ssl_scache_dbm_kill(server_rec *);
-BOOL ssl_scache_dbm_store(server_rec *, UCHAR *, int, time_t, SSL_SESSION *);
-SSL_SESSION *ssl_scache_dbm_retrieve(server_rec *, UCHAR *, int);
-void ssl_scache_dbm_remove(server_rec *, UCHAR *, int);
-void ssl_scache_dbm_expire(server_rec *);
-void ssl_scache_dbm_status(server_rec *, pool *, void (*)(char *, void *), void *);
-void ssl_scache_shmht_init(server_rec *, pool *);
-void ssl_scache_shmht_kill(server_rec *);
-BOOL ssl_scache_shmht_store(server_rec *, UCHAR *, int, time_t, SSL_SESSION *);
-SSL_SESSION *ssl_scache_shmht_retrieve(server_rec *, UCHAR *, int);
-void ssl_scache_shmht_remove(server_rec *, UCHAR *, int);
-void ssl_scache_shmht_expire(server_rec *);
-void ssl_scache_shmht_status(server_rec *, pool *, void (*)(char *, void *), void *);
-void ssl_scache_shmcb_init(server_rec *, pool *);
-void ssl_scache_shmcb_kill(server_rec *);
-BOOL ssl_scache_shmcb_store(server_rec *, UCHAR *, int, time_t, SSL_SESSION *);
-SSL_SESSION *ssl_scache_shmcb_retrieve(server_rec *, UCHAR *, int);
-void ssl_scache_shmcb_remove(server_rec *, UCHAR *, int);
-void ssl_scache_shmcb_expire(server_rec *);
-void ssl_scache_shmcb_status(server_rec *, pool *, void (*)(char *, void *), void *);
-
-/* Pass Phrase Support */
-void ssl_pphrase_Handle(server_rec *, pool *);
-int ssl_pphrase_Handle_CB(char *, int, int);
-
-/* Diffie-Hellman Parameter Support */
-DH *ssl_dh_GetTmpParam(int);
-DH *ssl_dh_GetParamFromFile(char *);
-
-/* Data Structures */
-ssl_ds_array *ssl_ds_array_make(pool *, int);
-BOOL ssl_ds_array_isempty(ssl_ds_array *);
-void *ssl_ds_array_push(ssl_ds_array *);
-void *ssl_ds_array_get(ssl_ds_array *, int);
-void ssl_ds_array_wipeout(ssl_ds_array *);
-void ssl_ds_array_kill(ssl_ds_array *);
-ssl_ds_table *ssl_ds_table_make(pool *, int);
-BOOL ssl_ds_table_isempty(ssl_ds_table *);
-void *ssl_ds_table_push(ssl_ds_table *, char *);
-void *ssl_ds_table_get(ssl_ds_table *, char *);
-void ssl_ds_table_wipeout(ssl_ds_table *);
-void ssl_ds_table_kill(ssl_ds_table *);
-
-/* Mutex Support */
-void ssl_mutex_init(server_rec *, pool *);
-void ssl_mutex_reinit(server_rec *, pool *);
-void ssl_mutex_on(server_rec *);
-void ssl_mutex_off(server_rec *);
-void ssl_mutex_kill(server_rec *s);
-void ssl_mutex_file_create(server_rec *, pool *);
-void ssl_mutex_file_open(server_rec *, pool *);
-void ssl_mutex_file_remove(void *);
-BOOL ssl_mutex_file_acquire(void);
-BOOL ssl_mutex_file_release(void);
-void ssl_mutex_sem_create(server_rec *, pool *);
-void ssl_mutex_sem_open(server_rec *, pool *);
-void ssl_mutex_sem_remove(void *);
-BOOL ssl_mutex_sem_acquire(void);
-BOOL ssl_mutex_sem_release(void);
-
-/* Logfile Support */
-void ssl_log_open(server_rec *, server_rec *, pool *);
-BOOL ssl_log_applies(server_rec *, int);
-void ssl_log(server_rec *, int, const char *, ...);
-void ssl_die(void);
-
-/* Variables */
-void ssl_var_register(void);
-void ssl_var_unregister(void);
-char *ssl_var_lookup(pool *, server_rec *, conn_rec *, request_rec *, char *);
-
-/* I/O */
-void ssl_io_register(void);
-void ssl_io_unregister(void);
-long ssl_io_data_cb(BIO *, int, const char *, int, long, long);
-#ifndef SSL_CONSERVATIVE
-void ssl_io_suck(request_rec *, SSL *);
-#endif
-
-/* PRNG */
-int ssl_rand_seed(server_rec *, pool *, ssl_rsctx_t, char *);
-
-/* Extensions */
-void ssl_ext_register(void);
-void ssl_ext_unregister(void);
-
-/* Compatibility */
-#ifdef SSL_COMPAT
-char *ssl_compat_directive(server_rec *, pool *, const char *);
-void ssl_compat_variables(request_rec *);
-#endif
-
-/* Utility Functions */
-char *ssl_util_server_root_relative(pool *, char *, char *);
-char *ssl_util_vhostid(pool *, server_rec *);
-void ssl_util_strupper(char *);
-void ssl_util_uuencode(char *, const char *, BOOL);
-void ssl_util_uuencode_binary(unsigned char *, const unsigned char *, int, BOOL);
-FILE *ssl_util_ppopen(server_rec *, pool *, char *);
-int ssl_util_ppopen_child(void *, child_info *);
-void ssl_util_ppclose(server_rec *, pool *, FILE *);
-char *ssl_util_readfilter(server_rec *, pool *, char *);
-BOOL ssl_util_path_check(ssl_pathcheck_t, char *);
-ssl_algo_t ssl_util_algotypeof(X509 *, EVP_PKEY *);
-char *ssl_util_algotypestr(ssl_algo_t);
-char *ssl_util_ptxtsub(pool *, const char *, const char *, char *);
-void ssl_util_thread_setup(void);
-
-/* Vendor extension support */
-#if defined(SSL_VENDOR) && defined(SSL_VENDOR_OBJS)
-void ssl_vendor_register(void);
-void ssl_vendor_unregister(void);
-#endif
-
-#endif /* MOD_SSL_H */
diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c
deleted file mode 100644
index c47340b223..0000000000
--- a/modules/ssl/ssl_engine_config.c
+++ /dev/null
@@ -1,1093 +0,0 @@
-/* _ _
-** _ __ ___ ___ __| | ___ ___| | mod_ssl
-** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
-** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
-** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
-** |_____|
-** ssl_engine_config.c
-** Apache Configuration Directives
-*/
-
-/* ====================================================================
- * Copyright (c) 1998-2001 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * 4. The names "mod_ssl" must not be used to endorse or promote
- * products derived from this software without prior written
- * permission. For written permission, please contact
- * rse@engelschall.com.
- *
- * 5. Products derived from this software may not be called "mod_ssl"
- * nor may "mod_ssl" appear in their names without prior
- * written permission of Ralf S. Engelschall.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
-
- /* ``Damned if you do,
- damned if you don't.''
- -- Unknown */
-#include "mod_ssl.h"
-
-
-/* _________________________________________________________________
-**
-** Support for Global Configuration
-** _________________________________________________________________
-*/
-
-void ssl_hook_AddModule(module *m)
-{
- if (m == &ssl_module) {
- /*
- * Announce us for the configuration files
- */
- ap_add_config_define("MOD_SSL");
-
- /*
- * Link ourself into the Apache kernel
- */
- ssl_var_register();
- ssl_ext_register();
- ssl_io_register();
-#if defined(SSL_VENDOR) && defined(SSL_VENDOR_OBJS)
- ssl_vendor_register();
-#endif
- }
- return;
-}
-
-void ssl_hook_RemoveModule(module *m)
-{
- if (m == &ssl_module) {
- /*
- * Unlink ourself from the Apache kernel
- */
- ssl_var_unregister();
- ssl_ext_unregister();
- ssl_io_unregister();
-#if defined(SSL_VENDOR) && defined(SSL_VENDOR_OBJS)
- ssl_vendor_unregister();
-#endif
- }
- return;
-}
-
-void ssl_config_global_create(void)
-{
- pool *pPool;
- SSLModConfigRec *mc;
-
- mc = ap_ctx_get(ap_global_ctx, "ssl_module");
- if (mc == NULL) {
- /*
- * allocate an own subpool which survives server restarts
- */
- pPool = ap_make_sub_pool(NULL);
- mc = (SSLModConfigRec *)ap_palloc(pPool, sizeof(SSLModConfigRec));
- mc->pPool = pPool;
- mc->bFixed = FALSE;
-
- /*
- * initialize per-module configuration
- */
- mc->nInitCount = 0;
- mc->nSessionCacheMode = SSL_SCMODE_UNSET;
- mc->szSessionCacheDataFile = NULL;
- mc->nSessionCacheDataSize = 0;
- mc->pSessionCacheDataMM = NULL;
- mc->tSessionCacheDataTable = NULL;
- mc->nMutexMode = SSL_MUTEXMODE_UNSET;
- mc->szMutexFile = NULL;
- mc->nMutexFD = -1;
- mc->nMutexSEMID = -1;
- mc->aRandSeed = ap_make_array(pPool, 4, sizeof(ssl_randseed_t));
- mc->tPrivateKey = ssl_ds_table_make(pPool, sizeof(ssl_asn1_t));
- mc->tPublicCert = ssl_ds_table_make(pPool, sizeof(ssl_asn1_t));
- mc->tTmpKeys = ssl_ds_table_make(pPool, sizeof(ssl_asn1_t));
-#ifdef SSL_EXPERIMENTAL_ENGINE
- mc->szCryptoDevice = NULL;
-#endif
-
- (void)memset(mc->pTmpKeys, 0, SSL_TKPIDX_MAX*sizeof(void *));
-
-#ifdef SSL_VENDOR
- mc->ctx = ap_ctx_new(pPool);
- ap_hook_use("ap::mod_ssl::vendor::config_global_create",
- AP_HOOK_SIG2(void,ptr), AP_HOOK_MODE_ALL, mc);
-#endif
-
- /*
- * And push it into Apache's global context
- */
- ap_ctx_set(ap_global_ctx, "ssl_module", mc);
- }
- return;
-}
-
-void ssl_config_global_fix(void)
-{
- SSLModConfigRec *mc = myModConfig();
- mc->bFixed = TRUE;
- return;
-}
-
-BOOL ssl_config_global_isfixed(void)
-{
- SSLModConfigRec *mc = myModConfig();
- return (mc->bFixed);
-}
-
-
-/* _________________________________________________________________
-**
-** Configuration handling
-** _________________________________________________________________
-*/
-
-/*
- * Create per-server SSL configuration
- */
-void *ssl_config_server_create(pool *p, server_rec *s)
-{
- SSLSrvConfigRec *sc;
-
- ssl_config_global_create();
-
- sc = ap_palloc(p, sizeof(SSLSrvConfigRec));
- sc->bEnabled = UNSET;
- sc->szCACertificatePath = NULL;
- sc->szCACertificateFile = NULL;
- sc->szCertificateChain = NULL;
- sc->szLogFile = NULL;
- sc->szCipherSuite = NULL;
- sc->nLogLevel = SSL_LOG_NONE;
- sc->nVerifyDepth = UNSET;
- sc->nVerifyClient = SSL_CVERIFY_UNSET;
- sc->nSessionCacheTimeout = UNSET;
- sc->nPassPhraseDialogType = SSL_PPTYPE_UNSET;
- sc->szPassPhraseDialogPath = NULL;
- sc->nProtocol = SSL_PROTOCOL_ALL;
- sc->fileLogFile = NULL;
- sc->pSSLCtx = NULL;
- sc->szCARevocationPath = NULL;
- sc->szCARevocationFile = NULL;
- sc->pRevocationStore = NULL;
-
-#ifdef SSL_EXPERIMENTAL_PROXY
- sc->nProxyVerifyDepth = UNSET;
- sc->szProxyCACertificatePath = NULL;
- sc->szProxyCACertificateFile = NULL;
- sc->szProxyClientCertificateFile = NULL;
- sc->szProxyClientCertificatePath = NULL;
- sc->szProxyCipherSuite = NULL;
- sc->nProxyProtocol = SSL_PROTOCOL_ALL & ~SSL_PROTOCOL_TLSV1;
- sc->bProxyVerify = UNSET;
- sc->pSSLProxyCtx = NULL;
-#endif
-
- (void)memset(sc->szPublicCertFile, 0, SSL_AIDX_MAX*sizeof(char *));
- (void)memset(sc->szPrivateKeyFile, 0, SSL_AIDX_MAX*sizeof(char *));
- (void)memset(sc->pPublicCert, 0, SSL_AIDX_MAX*sizeof(X509 *));
- (void)memset(sc->pPrivateKey, 0, SSL_AIDX_MAX*sizeof(EVP_PKEY *));
-
-#ifdef SSL_VENDOR
- sc->ctx = ap_ctx_new(p);
- ap_hook_use("ap::mod_ssl::vendor::config_server_create",
- AP_HOOK_SIG4(void,ptr,ptr,ptr), AP_HOOK_MODE_ALL,
- p, s, sc);
-#endif
-
- return sc;
-}
-
-/*
- * Merge per-server SSL configurations
- */
-void *ssl_config_server_merge(pool *p, void *basev, void *addv)
-{
- SSLSrvConfigRec *base = (SSLSrvConfigRec *)basev;
- SSLSrvConfigRec *add = (SSLSrvConfigRec *)addv;
- SSLSrvConfigRec *new = (SSLSrvConfigRec *)ap_palloc(p, sizeof(SSLSrvConfigRec));
- int i;
-
- cfgMergeBool(bEnabled);
- cfgMergeString(szCACertificatePath);
- cfgMergeString(szCACertificateFile);
- cfgMergeString(szCertificateChain);
- cfgMergeString(szLogFile);
- cfgMergeString(szCipherSuite);
- cfgMerge(nLogLevel, SSL_LOG_NONE);
- cfgMergeInt(nVerifyDepth);
- cfgMerge(nVerifyClient, SSL_CVERIFY_UNSET);
- cfgMergeInt(nSessionCacheTimeout);
- cfgMerge(nPassPhraseDialogType, SSL_PPTYPE_UNSET);
- cfgMergeString(szPassPhraseDialogPath);
- cfgMerge(nProtocol, SSL_PROTOCOL_ALL);
- cfgMerge(fileLogFile, NULL);
- cfgMerge(pSSLCtx, NULL);
- cfgMerge(szCARevocationPath, NULL);
- cfgMerge(szCARevocationFile, NULL);
- cfgMerge(pRevocationStore, NULL);
-
- for (i = 0; i < SSL_AIDX_MAX; i++) {
- cfgMergeString(szPublicCertFile[i]);
- cfgMergeString(szPrivateKeyFile[i]);
- cfgMerge(pPublicCert[i], NULL);
- cfgMerge(pPrivateKey[i], NULL);
- }
-
-#ifdef SSL_VENDOR
- cfgMergeCtx(ctx);
- ap_hook_use("ap::mod_ssl::vendor::config_server_merge",
- AP_HOOK_SIG5(void,ptr,ptr,ptr,ptr), AP_HOOK_MODE_ALL,
- p, base, add, new);
-#endif
-
-#ifdef SSL_EXPERIMENTAL_PROXY
- cfgMergeInt(nProxyVerifyDepth);
- cfgMergeString(szProxyCACertificatePath);
- cfgMergeString(szProxyCACertificateFile);
- cfgMergeString(szProxyClientCertificateFile);
- cfgMergeString(szProxyClientCertificatePath);
- cfgMergeString(szProxyCipherSuite);
- cfgMerge(nProxyProtocol, (SSL_PROTOCOL_ALL & ~SSL_PROTOCOL_TLSV1));
- cfgMergeBool(bProxyVerify);
- cfgMerge(pSSLProxyCtx, NULL);
-#endif
-
- return new;
-}
-
-/*
- * Create per-directory SSL configuration
- */
-void *ssl_config_perdir_create(pool *p, char *dir)
-{
- SSLDirConfigRec *dc = ap_palloc(p, sizeof(SSLDirConfigRec));
-
- dc->bSSLRequired = FALSE;
- dc->aRequirement = ap_make_array(p, 4, sizeof(ssl_require_t));
- dc->nOptions = SSL_OPT_NONE|SSL_OPT_RELSET;
- dc->nOptionsAdd = SSL_OPT_NONE;
- dc->nOptionsDel = SSL_OPT_NONE;
-
- dc->szCipherSuite = NULL;
- dc->nVerifyClient = SSL_CVERIFY_UNSET;
- dc->nVerifyDepth = UNSET;
-#ifdef SSL_EXPERIMENTAL_PERDIRCA
- dc->szCACertificatePath = NULL;
- dc->szCACertificateFile = NULL;
-#endif
-
-#ifdef SSL_VENDOR
- dc->ctx = ap_ctx_new(p);
- ap_hook_use("ap::mod_ssl::vendor::config_perdir_create",
- AP_HOOK_SIG4(void,ptr,ptr,ptr), AP_HOOK_MODE_ALL,
- p, dir, dc);
-#endif
-
- return dc;
-}
-
-/*
- * Merge per-directory SSL configurations
- */
-void *ssl_config_perdir_merge(pool *p, void *basev, void *addv)
-{
- SSLDirConfigRec *base = (SSLDirConfigRec *)basev;
- SSLDirConfigRec *add = (SSLDirConfigRec *)addv;
- SSLDirConfigRec *new = (SSLDirConfigRec *)ap_palloc(p,
- sizeof(SSLDirConfigRec));
-
- cfgMerge(bSSLRequired, FALSE);
- cfgMergeArray(aRequirement);
-
- if (add->nOptions & SSL_OPT_RELSET) {
- new->nOptionsAdd = (base->nOptionsAdd & ~(add->nOptionsDel)) | add->nOptionsAdd;
- new->nOptionsDel = (base->nOptionsDel & ~(add->nOptionsAdd)) | add->nOptionsDel;
- new->nOptions = (base->nOptions & ~(new->nOptionsDel)) | new->nOptionsAdd;
- }
- else {
- new->nOptions = add->nOptions;
- new->nOptionsAdd = add->nOptionsAdd;
- new->nOptionsDel = add->nOptionsDel;
- }
-
- cfgMergeString(szCipherSuite);
- cfgMerge(nVerifyClient, SSL_CVERIFY_UNSET);
- cfgMergeInt(nVerifyDepth);
-#ifdef SSL_EXPERIMENTAL_PERDIRCA
- cfgMergeString(szCACertificatePath);
- cfgMergeString(szCACertificateFile);
-#endif
-
-#ifdef SSL_VENDOR
- cfgMergeCtx(ctx);
- ap_hook_use("ap::mod_ssl::vendor::config_perdir_merge",
- AP_HOOK_SIG5(void,ptr,ptr,ptr,ptr), AP_HOOK_MODE_ALL,
- p, base, add, new);
-#endif
-
- return new;
-}
-
-/*
- * Directive Rewriting
- */
-
-char *ssl_hook_RewriteCommand(cmd_parms *cmd, void *config, const char *cmd_line)
-{
-#ifdef SSL_COMPAT
- return ssl_compat_directive(cmd->server, cmd->pool, cmd_line);
-#else
- return NULL;
-#endif
-}
-
-/*
- * Configuration functions for particular directives
- */
-
-const char *ssl_cmd_SSLMutex(
- cmd_parms *cmd, char *struct_ptr, char *arg)
-{
- const char *err;
- SSLModConfigRec *mc = myModConfig();
-
- if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY)) != NULL)
- return err;
- if (ssl_config_global_isfixed())
- return NULL;
- if (strcEQ(arg, "none")) {
- mc->nMutexMode = SSL_MUTEXMODE_NONE;
- }
- else if (strlen(arg) > 5 && strcEQn(arg, "file:", 5)) {
-#ifndef WIN32
- mc->nMutexMode = SSL_MUTEXMODE_FILE;
- mc->szMutexFile = ap_psprintf(mc->pPool, "%s.%lu",
- ssl_util_server_root_relative(cmd->pool, "mutex", arg+5),
- (unsigned long)getpid());
-#else
- return "SSLMutex: Lockfiles not available on this platform";
-#endif
- }
- else if (strcEQ(arg, "sem")) {
-#ifdef SSL_CAN_USE_SEM
- mc->nMutexMode = SSL_MUTEXMODE_SEM;
-#else
- return "SSLMutex: Semaphores not available on this platform";
-#endif
- }
- else
- return "SSLMutex: Invalid argument";
- return NULL;
-}
-
-const char *ssl_cmd_SSLPassPhraseDialog(
- cmd_parms *cmd, char *struct_ptr, char *arg)
-{
- SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
- const char *err;
-
- if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY)) != NULL)
- return err;
- if (strcEQ(arg, "builtin")) {
- sc->nPassPhraseDialogType = SSL_PPTYPE_BUILTIN;
- sc->szPassPhraseDialogPath = NULL;
- }
- else if (strlen(arg) > 5 && strEQn(arg, "exec:", 5)) {
- sc->nPassPhraseDialogType = SSL_PPTYPE_FILTER;
- sc->szPassPhraseDialogPath = ssl_util_server_root_relative(cmd->pool, "dialog", arg+5);
- if (!ssl_util_path_check(SSL_PCM_EXISTS, sc->szPassPhraseDialogPath))
- return ap_pstrcat(cmd->pool, "SSLPassPhraseDialog: file '",
- sc->szPassPhraseDialogPath, "' not exists", NULL);
- }
- else
- return "SSLPassPhraseDialog: Invalid argument";
- return NULL;
-}
-
-#ifdef SSL_EXPERIMENTAL_ENGINE
-const char *ssl_cmd_SSLCryptoDevice(
- cmd_parms *cmd, char *struct_ptr, char *arg)
-{
- SSLModConfigRec *mc = myModConfig();
- const char *err;
- ENGINE *e;
-#if SSL_LIBRARY_VERSION >= 0x00907000
- static int loaded_engines = FALSE;
-
- /* early loading to make sure the engines are already
- available for ENGINE_by_id() above... */
- if (!loaded_engines) {
- ENGINE_load_builtin_engines();
- loaded_engines = TRUE;
- }
-#endif
- if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY)) != NULL)
- return err;
- if (strcEQ(arg, "builtin")) {
- mc->szCryptoDevice = NULL;
- }
- else if ((e = ENGINE_by_id(arg)) != NULL) {
- mc->szCryptoDevice = arg;
- ENGINE_free(e);
- }
- else
- return "SSLCryptoDevice: Invalid argument";
- return NULL;
-}
-#endif
-
-const char *ssl_cmd_SSLRandomSeed(
- cmd_parms *cmd, char *struct_ptr, char *arg1, char *arg2, char *arg3)
-{
- SSLModConfigRec *mc = myModConfig();
- const char *err;
- ssl_randseed_t *pRS;
-
- if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY)) != NULL)
- return err;
- if (ssl_config_global_isfixed())
- return NULL;
- pRS = ap_push_array(mc->aRandSeed);
- if (strcEQ(arg1, "startup"))
- pRS->nCtx = SSL_RSCTX_STARTUP;
- else if (strcEQ(arg1, "connect"))
- pRS->nCtx = SSL_RSCTX_CONNECT;
- else
- return ap_pstrcat(cmd->pool, "SSLRandomSeed: "
- "invalid context: `", arg1, "'");
- if (strlen(arg2) > 5 && strEQn(arg2, "file:", 5)) {
- pRS->nSrc = SSL_RSSRC_FILE;
- pRS->cpPath = ap_pstrdup(mc->pPool, ssl_util_server_root_relative(cmd->pool, "random", arg2+5));
- }
- else if (strlen(arg2) > 5 && strEQn(arg2, "exec:", 5)) {
- pRS->nSrc = SSL_RSSRC_EXEC;
- pRS->cpPath = ap_pstrdup(mc->pPool, ssl_util_server_root_relative(cmd->pool, "random", arg2+5));
- }
-#if SSL_LIBRARY_VERSION >= 0x00905100
- else if (strlen(arg2) > 4 && strEQn(arg2, "egd:", 4)) {
- pRS->nSrc = SSL_RSSRC_EGD;
- pRS->cpPath = ap_pstrdup(mc->pPool, ssl_util_server_root_relative(cmd->pool, "random", arg2+4));
- }
-#endif
- else if (strcEQ(arg2, "builtin")) {
- pRS->nSrc = SSL_RSSRC_BUILTIN;
- pRS->cpPath = NULL;
- }
- else {
- pRS->nSrc = SSL_RSSRC_FILE;
- pRS->cpPath = ap_pstrdup(mc->pPool, ssl_util_server_root_relative(cmd->pool, "random", arg2));
- }
- if (pRS->nSrc != SSL_RSSRC_BUILTIN)
- if (!ssl_util_path_check(SSL_PCM_EXISTS, pRS->cpPath))
- return ap_pstrcat(cmd->pool, "SSLRandomSeed: source path '",
- pRS->cpPath, "' not exists", NULL);
- if (arg3 == NULL)
- pRS->nBytes = 0; /* read whole file */
- else {
- if (pRS->nSrc == SSL_RSSRC_BUILTIN)
- return "SSLRandomSeed: byte specification not "
- "allowed for builtin seed source";
- pRS->nBytes = atoi(arg3);
- if (pRS->nBytes < 0)
- return "SSLRandomSeed: invalid number of bytes specified";
- }
- return NULL;
-}
-
-const char *ssl_cmd_SSLEngine(
- cmd_parms *cmd, char *struct_ptr, int flag)
-{
- SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
-
- sc->bEnabled = (flag ? TRUE : FALSE);
- return NULL;
-}
-
-const char *ssl_cmd_SSLCipherSuite(
- cmd_parms *cmd, SSLDirConfigRec *dc, char *arg)
-{
- SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
-
- if (cmd->path == NULL || dc == NULL)
- sc->szCipherSuite = arg;
- else
- dc->szCipherSuite = arg;
- return NULL;
-}
-
-const char *ssl_cmd_SSLCertificateFile(
- cmd_parms *cmd, char *struct_ptr, char *arg)
-{
- SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
- char *cpPath;
- int i;
-
- cpPath = ssl_util_server_root_relative(cmd->pool, "certkey", arg);
- if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISREG|SSL_PCM_ISNONZERO, cpPath))
- return ap_pstrcat(cmd->pool, "SSLCertificateFile: file '",
- cpPath, "' not exists or empty", NULL);
- for (i = 0; i < SSL_AIDX_MAX && sc->szPublicCertFile[i] != NULL; i++)
- ;
- if (i == SSL_AIDX_MAX)
- return ap_psprintf(cmd->pool, "SSLCertificateFile: only up to %d "
- "different certificates per virtual host allowed",
- SSL_AIDX_MAX);
- sc->szPublicCertFile[i] = cpPath;
- return NULL;
-}
-
-const char *ssl_cmd_SSLCertificateKeyFile(
- cmd_parms *cmd, char *struct_ptr, char *arg)
-{
- SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
- char *cpPath;
- int i;
-
- cpPath = ssl_util_server_root_relative(cmd->pool, "certkey", arg);
- if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISREG|SSL_PCM_ISNONZERO, cpPath))
- return ap_pstrcat(cmd->pool, "SSLCertificateKeyFile: file '",
- cpPath, "' not exists or empty", NULL);
- for (i = 0; i < SSL_AIDX_MAX && sc->szPrivateKeyFile[i] != NULL; i++)
- ;
- if (i == SSL_AIDX_MAX)
- return ap_psprintf(cmd->pool, "SSLCertificateKeyFile: only up to %d "
- "different private keys per virtual host allowed",
- SSL_AIDX_MAX);
- sc->szPrivateKeyFile[i] = cpPath;
- return NULL;
-}
-
-const char *ssl_cmd_SSLCertificateChainFile(
- cmd_parms *cmd, char *struct_ptr, char *arg)
-{
- SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
- char *cpPath;
-
- cpPath = ssl_util_server_root_relative(cmd->pool, "certkey", arg);
- if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISREG|SSL_PCM_ISNONZERO, cpPath))
- return ap_pstrcat(cmd->pool, "SSLCertificateChainFile: file '",
- cpPath, "' not exists or empty", NULL);
- sc->szCertificateChain = cpPath;
- return NULL;
-}
-
-const char *ssl_cmd_SSLCACertificatePath(
- cmd_parms *cmd, SSLDirConfigRec *dc, char *arg)
-{
- SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
- char *cpPath;
-
- cpPath = ssl_util_server_root_relative(cmd->pool, "certkey", arg);
- if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISDIR, cpPath))
- return ap_pstrcat(cmd->pool, "SSLCACertificatePath: directory '",
- cpPath, "' not exists", NULL);
-#ifdef SSL_EXPERIMENTAL_PERDIRCA
- if (cmd->path == NULL || dc == NULL)
- sc->szCACertificatePath = cpPath;
- else
- dc->szCACertificatePath = cpPath;
-#else
- sc->szCACertificatePath = cpPath;
-#endif
- return NULL;
-}
-
-const char *ssl_cmd_SSLCACertificateFile(
- cmd_parms *cmd, SSLDirConfigRec *dc, char *arg)
-{
- SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
- char *cpPath;
-
- cpPath = ssl_util_server_root_relative(cmd->pool, "certkey", arg);
- if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISREG|SSL_PCM_ISNONZERO, cpPath))
- return ap_pstrcat(cmd->pool, "SSLCACertificateFile: file '",
- cpPath, "' not exists or empty", NULL);
-#ifdef SSL_EXPERIMENTAL_PERDIRCA
- if (cmd->path == NULL || dc == NULL)
- sc->szCACertificateFile = cpPath;
- else
- dc->szCACertificateFile = cpPath;
-#else
- sc->szCACertificateFile = cpPath;
-#endif
- return NULL;
-}
-
-const char *ssl_cmd_SSLCARevocationPath(
- cmd_parms *cmd, SSLDirConfigRec *dc, char *arg)
-{
- SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
- char *cpPath;
-
- cpPath = ssl_util_server_root_relative(cmd->pool, "certkey", arg);
- if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISDIR, cpPath))
- return ap_pstrcat(cmd->pool, "SSLCARecocationPath: directory '",
- cpPath, "' not exists", NULL);
- sc->szCARevocationPath = cpPath;
- return NULL;
-}
-
-const char *ssl_cmd_SSLCARevocationFile(
- cmd_parms *cmd, SSLDirConfigRec *dc, char *arg)
-{
- SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
- char *cpPath;
-
- cpPath = ssl_util_server_root_relative(cmd->pool, "certkey", arg);
- if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISREG|SSL_PCM_ISNONZERO, cpPath))
- return ap_pstrcat(cmd->pool, "SSLCARevocationFile: file '",
- cpPath, "' not exists or empty", NULL);
- sc->szCARevocationFile = cpPath;
- return NULL;
-}
-
-const char *ssl_cmd_SSLVerifyClient(
- cmd_parms *cmd, SSLDirConfigRec *dc, char *level)
-{
- SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
- ssl_verify_t id;
-
- if (strEQ(level, "0") || strcEQ(level, "none"))
- id = SSL_CVERIFY_NONE;
- else if (strEQ(level, "1") || strcEQ(level, "optional"))
- id = SSL_CVERIFY_OPTIONAL;
- else if (strEQ(level, "2") || strcEQ(level, "require"))
- id = SSL_CVERIFY_REQUIRE;
- else if (strEQ(level, "3") || strcEQ(level, "optional_no_ca"))
- id = SSL_CVERIFY_OPTIONAL_NO_CA;
- else
- return "SSLVerifyClient: Invalid argument";
- if (cmd->path == NULL || dc == NULL)
- sc->nVerifyClient = id;
- else
- dc->nVerifyClient = id;
- return NULL;
-}
-
-const char *ssl_cmd_SSLVerifyDepth(
- cmd_parms *cmd, SSLDirConfigRec *dc, char *arg)
-{
- SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
- int d;
-
- d = atoi(arg);
- if (d < 0)
- return "SSLVerifyDepth: Invalid argument";
- if (cmd->path == NULL || dc == NULL)
- sc->nVerifyDepth = d;
- else
- dc->nVerifyDepth = d;
- return NULL;
-}
-
-const char *ssl_cmd_SSLSessionCache(
- cmd_parms *cmd, char *struct_ptr, char *arg)
-{
- const char *err;
- SSLModConfigRec *mc = myModConfig();
- char *cp, *cp2;
- int maxsize;
-
- if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY)) != NULL)
- return err;
- if (ssl_config_global_isfixed())
- return NULL;
- if (strcEQ(arg, "none")) {
- mc->nSessionCacheMode = SSL_SCMODE_NONE;
- mc->szSessionCacheDataFile = NULL;
- }
- else if (strlen(arg) > 4 && strcEQn(arg, "dbm:", 4)) {
- mc->nSessionCacheMode = SSL_SCMODE_DBM;
- mc->szSessionCacheDataFile = ap_pstrdup(mc->pPool,
- ssl_util_server_root_relative(cmd->pool, "scache", arg+4));
- }
- else if ( (strlen(arg) > 4 && strcEQn(arg, "shm:", 4))
- || (strlen(arg) > 6 && strcEQn(arg, "shmht:", 6))) {
- if (!ap_mm_useable())
- return "SSLSessionCache: shared memory cache not useable on this platform";
- mc->nSessionCacheMode = SSL_SCMODE_SHMHT;
- cp = strchr(arg, ':');
- mc->szSessionCacheDataFile = ap_pstrdup(mc->pPool,
- ssl_util_server_root_relative(cmd->pool, "scache", cp+1));
- mc->tSessionCacheDataTable = NULL;
- mc->nSessionCacheDataSize = 1024*512; /* 512KB */
- if ((cp = strchr(mc->szSessionCacheDataFile, '(')) != NULL) {
- *cp++ = NUL;
- if ((cp2 = strchr(cp, ')')) == NULL)
- return "SSLSessionCache: Invalid argument: no closing parenthesis";
- *cp2 = NUL;
- mc->nSessionCacheDataSize = atoi(cp);
- if (mc->nSessionCacheDataSize <= 8192)
- return "SSLSessionCache: Invalid argument: size has to be >= 8192 bytes";
- maxsize = ap_mm_core_maxsegsize();
- if (mc->nSessionCacheDataSize >= maxsize)
- return ap_psprintf(cmd->pool, "SSLSessionCache: Invalid argument: "
- "size has to be < %d bytes on this platform", maxsize);
- }
- }
- else if (strlen(arg) > 6 && strcEQn(arg, "shmcb:", 6)) {
- if (!ap_mm_useable())
- return "SSLSessionCache: shared memory cache not useable on this platform";
- mc->nSessionCacheMode = SSL_SCMODE_SHMCB;
- mc->szSessionCacheDataFile = ap_pstrdup(mc->pPool,
- ap_server_root_relative(cmd->pool, arg+6));
- mc->tSessionCacheDataTable = NULL;
- mc->nSessionCacheDataSize = 1024*512; /* 512KB */
- if ((cp = strchr(mc->szSessionCacheDataFile, '(')) != NULL) {
- *cp++ = NUL;
- if ((cp2 = strchr(cp, ')')) == NULL)
- return "SSLSessionCache: Invalid argument: no closing parenthesis";
- *cp2 = NUL;
- mc->nSessionCacheDataSize = atoi(cp);
- if (mc->nSessionCacheDataSize <= 8192)
- return "SSLSessionCache: Invalid argument: size has to be >= 8192 bytes";
- maxsize = ap_mm_core_maxsegsize();
- if (mc->nSessionCacheDataSize >= maxsize)
- return ap_psprintf(cmd->pool, "SSLSessionCache: Invalid argument: "
- "size has to be < %d bytes on this platform", maxsize);
- }
- }
- else
-#ifdef SSL_VENDOR
- if (!ap_hook_use("ap::mod_ssl::vendor::cmd_sslsessioncache",
- AP_HOOK_SIG4(void,ptr,ptr,ptr), AP_HOOK_MODE_ALL,
- cmd, arg, mc))
-#endif
- return "SSLSessionCache: Invalid argument";
- return NULL;
-}
-
-const char *ssl_cmd_SSLSessionCacheTimeout(
- cmd_parms *cmd, char *struct_ptr, char *arg)
-{
- SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
-
- sc->nSessionCacheTimeout = atoi(arg);
- if (sc->nSessionCacheTimeout < 0)
- return "SSLSessionCacheTimeout: Invalid argument";
- return NULL;
-}
-
-const char *ssl_cmd_SSLLog(
- cmd_parms *cmd, char *struct_ptr, char *arg)
-{
- SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
- const char *err;
-
- if ((err = ap_check_cmd_context(cmd, NOT_IN_LIMIT|NOT_IN_DIRECTORY
- |NOT_IN_LOCATION|NOT_IN_FILES )) != NULL)
- return err;
- sc->szLogFile = arg;
- return NULL;
-}
-
-const char *ssl_cmd_SSLLogLevel(
- cmd_parms *cmd, char *struct_ptr, char *level)
-{
- SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
- const char *err;
-
- if ((err = ap_check_cmd_context(cmd, NOT_IN_LIMIT|NOT_IN_DIRECTORY
- |NOT_IN_LOCATION|NOT_IN_FILES )) != NULL)
- return err;
- if (strcEQ(level, "none"))
- sc->nLogLevel = SSL_LOG_NONE;
- else if (strcEQ(level, "error"))
- sc->nLogLevel = SSL_LOG_ERROR;
- else if (strcEQ(level, "warn"))
- sc->nLogLevel = SSL_LOG_WARN;
- else if (strcEQ(level, "info"))
- sc->nLogLevel = SSL_LOG_INFO;
- else if (strcEQ(level, "trace"))
- sc->nLogLevel = SSL_LOG_TRACE;
- else if (strcEQ(level, "debug"))
- sc->nLogLevel = SSL_LOG_DEBUG;
- else
- return "SSLLogLevel: Invalid argument";
- return NULL;
-}
-
-const char *ssl_cmd_SSLOptions(
- cmd_parms *cmd, SSLDirConfigRec *dc, const char *cpLine)
-{
- ssl_opt_t opt;
- int first;
- char action;
- char *w;
-
- first = TRUE;
- while (cpLine[0] != NUL) {
- w = ap_getword_conf(cmd->pool, &cpLine);
- action = NUL;
-
- if (*w == '+' || *w == '-') {
- action = *(w++);
- }
- else if (first) {
- dc->nOptions = SSL_OPT_NONE;
- first = FALSE;
- }
-
- if (strcEQ(w, "StdEnvVars"))
- opt = SSL_OPT_STDENVVARS;
- else if (strcEQ(w, "CompatEnvVars"))
- opt = SSL_OPT_COMPATENVVARS;
- else if (strcEQ(w, "ExportCertData"))
- opt = SSL_OPT_EXPORTCERTDATA;
- else if (strcEQ(w, "FakeBasicAuth"))
- opt = SSL_OPT_FAKEBASICAUTH;
- else if (strcEQ(w, "StrictRequire"))
- opt = SSL_OPT_STRICTREQUIRE;
- else if (strcEQ(w, "OptRenegotiate"))
- opt = SSL_OPT_OPTRENEGOTIATE;
- else
- return ap_pstrcat(cmd->pool, "SSLOptions: Illegal option '", w, "'", NULL);
-
- if (action == '-') {
- dc->nOptionsAdd &= ~opt;
- dc->nOptionsDel |= opt;
- dc->nOptions &= ~opt;
- }
- else if (action == '+') {
- dc->nOptionsAdd |= opt;
- dc->nOptionsDel &= ~opt;
- dc->nOptions |= opt;
- }
- else {
- dc->nOptions = opt;
- dc->nOptionsAdd = opt;
- dc->nOptionsDel = SSL_OPT_NONE;
- }
- }
- return NULL;
-}
-
-const char *ssl_cmd_SSLRequireSSL(
- cmd_parms *cmd, SSLDirConfigRec *dc, char *cipher)
-{
- dc->bSSLRequired = TRUE;
- return NULL;
-}
-
-const char *ssl_cmd_SSLRequire(
- cmd_parms *cmd, SSLDirConfigRec *dc, char *cpExpr)
-{
- ssl_expr *mpExpr;
- ssl_require_t *pReqRec;
-
- if ((mpExpr = ssl_expr_comp(cmd->pool, cpExpr)) == NULL)
- return ap_pstrcat(cmd->pool, "SSLRequire: ", ssl_expr_get_error(), NULL);
- pReqRec = ap_push_array(dc->aRequirement);
- pReqRec->cpExpr = ap_pstrdup(cmd->pool, cpExpr);
- pReqRec->mpExpr = mpExpr;
- return NULL;
-}
-
-const char *ssl_cmd_SSLProtocol(
- cmd_parms *cmd, char *struct_ptr, const char *opt)
-{
- SSLSrvConfigRec *sc;
- ssl_proto_t options, thisopt;
- char action;
- char *w;
-
- sc = mySrvConfig(cmd->server);
- options = SSL_PROTOCOL_NONE;
- while (opt[0] != NUL) {
- w = ap_getword_conf(cmd->pool, &opt);
-
- action = NUL;
- if (*w == '+' || *w == '-')
- action = *(w++);
-
- if (strcEQ(w, "SSLv2"))
- thisopt = SSL_PROTOCOL_SSLV2;
- else if (strcEQ(w, "SSLv3"))
- thisopt = SSL_PROTOCOL_SSLV3;
- else if (strcEQ(w, "TLSv1"))
- thisopt = SSL_PROTOCOL_TLSV1;
- else if (strcEQ(w, "all"))
- thisopt = SSL_PROTOCOL_ALL;
- else
- return ap_pstrcat(cmd->pool, "SSLProtocol: Illegal protocol '", w, "'", NULL);
-
- if (action == '-')
- options &= ~thisopt;
- else if (action == '+')
- options |= thisopt;
- else
- options = thisopt;
- }
- sc->nProtocol = options;
- return NULL;
-}
-
-#ifdef SSL_EXPERIMENTAL_PROXY
-
-const char *ssl_cmd_SSLProxyProtocol(
- cmd_parms *cmd, char *struct_ptr, const char *opt)
-{
- SSLSrvConfigRec *sc;
- ssl_proto_t options, thisopt;
- char action;
- char *w;
-
- sc = mySrvConfig(cmd->server);
- options = SSL_PROTOCOL_NONE;
- while (opt[0] != NUL) {
- w = ap_getword_conf(cmd->pool, &opt);
-
- action = NUL;
- if (*w == '+' || *w == '-')
- action = *(w++);
-
- if (strcEQ(w, "SSLv2"))
- thisopt = SSL_PROTOCOL_SSLV2;
- else if (strcEQ(w, "SSLv3"))
- thisopt = SSL_PROTOCOL_SSLV3;
- else if (strcEQ(w, "TLSv1"))
- thisopt = SSL_PROTOCOL_TLSV1;
- else if (strcEQ(w, "all"))
- thisopt = SSL_PROTOCOL_ALL;
- else
- return ap_pstrcat(cmd->pool, "SSLProxyProtocol: "
- "Illegal protocol '", w, "'", NULL);
- if (action == '-')
- options &= ~thisopt;
- else if (action == '+')
- options |= thisopt;
- else
- options = thisopt;
- }
- sc->nProxyProtocol = options;
- return NULL;
-}
-
-const char *ssl_cmd_SSLProxyCipherSuite(
- cmd_parms *cmd, char *struct_ptr, char *arg)
-{
- SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
-
- sc->szProxyCipherSuite = arg;
- return NULL;
-}
-
-const char *ssl_cmd_SSLProxyVerify(
- cmd_parms *cmd, char *struct_ptr, int flag)
-{
- SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
-
- sc->bProxyVerify = (flag ? TRUE : FALSE);
- return NULL;
-}
-
-const char *ssl_cmd_SSLProxyVerifyDepth(
- cmd_parms *cmd, char *struct_ptr, char *arg)
-{
- SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
- int d;
-
- d = atoi(arg);
- if (d < 0)
- return "SSLProxyVerifyDepth: Invalid argument";
- sc->nProxyVerifyDepth = d;
- return NULL;
-}
-
-const char *ssl_cmd_SSLProxyCACertificateFile(
- cmd_parms *cmd, char *struct_ptr, char *arg)
-{
- SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
- char *cpPath;
-
- cpPath = ssl_util_server_root_relative(cmd->pool, "certkey", arg);
- if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISREG|SSL_PCM_ISNONZERO, cpPath))
- return ap_pstrcat(cmd->pool, "SSLProxyCACertificateFile: file '",
- cpPath, "' not exists or empty", NULL);
- sc->szProxyCACertificateFile = cpPath;
- return NULL;
-}
-
-const char *ssl_cmd_SSLProxyCACertificatePath(
- cmd_parms *cmd, char *struct_ptr, char *arg)
-{
- SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
- char *cpPath;
-
- cpPath = ssl_util_server_root_relative(cmd->pool, "certkey", arg);
- if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISDIR, cpPath))
- return ap_pstrcat(cmd->pool, "SSLProxyCACertificatePath: directory '",
- cpPath, "' does not exists", NULL);
- sc->szProxyCACertificatePath = cpPath;
- return NULL;
-}
-
-const char *ssl_cmd_SSLProxyMachineCertificateFile(
- cmd_parms *cmd, char *struct_ptr, char *arg)
-{
- SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
- char *cpPath;
-
- cpPath = ssl_util_server_root_relative(cmd->pool, "certkey", arg);
- if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISREG|SSL_PCM_ISNONZERO, cpPath))
- return ap_pstrcat(cmd->pool, "SSLProxyMachineCertFile: file '",
- cpPath, "' not exists or empty", NULL);
- sc->szProxyClientCertificateFile = cpPath;
- return NULL;
-}
-
-const char *ssl_cmd_SSLProxyMachineCertificatePath(
- cmd_parms *cmd, char *struct_ptr, char *arg)
-{
- SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
- char *cpPath;
-
- cpPath = ssl_util_server_root_relative(cmd->pool, "certkey", arg);
- if (!ssl_util_path_check(SSL_PCM_EXISTS|SSL_PCM_ISDIR, cpPath))
- return ap_pstrcat(cmd->pool, "SSLProxyMachineCertPath: directory '",
- cpPath, "' does not exists", NULL);
- sc->szProxyClientCertificatePath = cpPath;
- return NULL;
-}
-
-#endif /* SSL_EXPERIMENTAL_PROXY */
-
diff --git a/modules/ssl/ssl_engine_dh.c b/modules/ssl/ssl_engine_dh.c
deleted file mode 100644
index 84f49e6657..0000000000
--- a/modules/ssl/ssl_engine_dh.c
+++ /dev/null
@@ -1,255 +0,0 @@
-#if 0
-=pod
-#endif
-/* _ _
-** _ __ ___ ___ __| | ___ ___| | mod_ssl
-** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
-** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
-** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
-** |_____|
-** ssl_engine_dh.c
-** Diffie-Hellman Built-in Temporary Parameters
-*/
-
-/* ====================================================================
- * Copyright (c) 1998-2001 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * 4. The names "mod_ssl" must not be used to endorse or promote
- * products derived from this software without prior written
- * permission. For written permission, please contact
- * rse@engelschall.com.
- *
- * 5. Products derived from this software may not be called "mod_ssl"
- * nor may "mod_ssl" appear in their names without prior
- * written permission of Ralf S. Engelschall.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
-
-#include "mod_ssl.h"
-
-/* ----BEGIN GENERATED SECTION-------- */
-
-/*
-** Diffie-Hellman-Parameters: (512 bit)
-** prime:
-** 00:d4:bc:d5:24:06:f6:9b:35:99:4b:88:de:5d:b8:
-** 96:82:c8:15:7f:62:d8:f3:36:33:ee:57:72:f1:1f:
-** 05:ab:22:d6:b5:14:5b:9f:24:1e:5a:cc:31:ff:09:
-** 0a:4b:c7:11:48:97:6f:76:79:50:94:e7:1e:79:03:
-** 52:9f:5a:82:4b
-** generator: 2 (0x2)
-** Diffie-Hellman-Parameters: (1024 bit)
-** prime:
-** 00:e6:96:9d:3d:49:5b:e3:2c:7c:f1:80:c3:bd:d4:
-** 79:8e:91:b7:81:82:51:bb:05:5e:2a:20:64:90:4a:
-** 79:a7:70:fa:15:a2:59:cb:d5:23:a6:a6:ef:09:c4:
-** 30:48:d5:a2:2f:97:1f:3c:20:12:9b:48:00:0e:6e:
-** dd:06:1c:bc:05:3e:37:1d:79:4e:53:27:df:61:1e:
-** bb:be:1b:ac:9b:5c:60:44:cf:02:3d:76:e0:5e:ea:
-** 9b:ad:99:1b:13:a6:3c:97:4e:9e:f1:83:9e:b5:db:
-** 12:51:36:f7:26:2e:56:a8:87:15:38:df:d8:23:c6:
-** 50:50:85:e2:1f:0d:d5:c8:6b
-** generator: 2 (0x2)
-*/
-
-static unsigned char dh512_p[] =
-{
- 0xD4, 0xBC, 0xD5, 0x24, 0x06, 0xF6, 0x9B, 0x35, 0x99, 0x4B, 0x88, 0xDE,
- 0x5D, 0xB8, 0x96, 0x82, 0xC8, 0x15, 0x7F, 0x62, 0xD8, 0xF3, 0x36, 0x33,
- 0xEE, 0x57, 0x72, 0xF1, 0x1F, 0x05, 0xAB, 0x22, 0xD6, 0xB5, 0x14, 0x5B,
- 0x9F, 0x24, 0x1E, 0x5A, 0xCC, 0x31, 0xFF, 0x09, 0x0A, 0x4B, 0xC7, 0x11,
- 0x48, 0x97, 0x6F, 0x76, 0x79, 0x50, 0x94, 0xE7, 0x1E, 0x79, 0x03, 0x52,
- 0x9F, 0x5A, 0x82, 0x4B,
-};
-static unsigned char dh512_g[] =
-{
- 0x02,
-};
-
-static DH *get_dh512()
-{
- DH *dh;
-
- if ((dh = DH_new()) == NULL)
- return (NULL);
- dh->p = BN_bin2bn(dh512_p, sizeof(dh512_p), NULL);
- dh->g = BN_bin2bn(dh512_g, sizeof(dh512_g), NULL);
- if ((dh->p == NULL) || (dh->g == NULL))
- return (NULL);
- return (dh);
-}
-static unsigned char dh1024_p[] =
-{
- 0xE6, 0x96, 0x9D, 0x3D, 0x49, 0x5B, 0xE3, 0x2C, 0x7C, 0xF1, 0x80, 0xC3,
- 0xBD, 0xD4, 0x79, 0x8E, 0x91, 0xB7, 0x81, 0x82, 0x51, 0xBB, 0x05, 0x5E,
- 0x2A, 0x20, 0x64, 0x90, 0x4A, 0x79, 0xA7, 0x70, 0xFA, 0x15, 0xA2, 0x59,
- 0xCB, 0xD5, 0x23, 0xA6, 0xA6, 0xEF, 0x09, 0xC4, 0x30, 0x48, 0xD5, 0xA2,
- 0x2F, 0x97, 0x1F, 0x3C, 0x20, 0x12, 0x9B, 0x48, 0x00, 0x0E, 0x6E, 0xDD,
- 0x06, 0x1C, 0xBC, 0x05, 0x3E, 0x37, 0x1D, 0x79, 0x4E, 0x53, 0x27, 0xDF,
- 0x61, 0x1E, 0xBB, 0xBE, 0x1B, 0xAC, 0x9B, 0x5C, 0x60, 0x44, 0xCF, 0x02,
- 0x3D, 0x76, 0xE0, 0x5E, 0xEA, 0x9B, 0xAD, 0x99, 0x1B, 0x13, 0xA6, 0x3C,
- 0x97, 0x4E, 0x9E, 0xF1, 0x83, 0x9E, 0xB5, 0xDB, 0x12, 0x51, 0x36, 0xF7,
- 0x26, 0x2E, 0x56, 0xA8, 0x87, 0x15, 0x38, 0xDF, 0xD8, 0x23, 0xC6, 0x50,
- 0x50, 0x85, 0xE2, 0x1F, 0x0D, 0xD5, 0xC8, 0x6B,
-};
-static unsigned char dh1024_g[] =
-{
- 0x02,
-};
-
-static DH *get_dh1024()
-{
- DH *dh;
-
- if ((dh = DH_new()) == NULL)
- return (NULL);
- dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
- dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
- if ((dh->p == NULL) || (dh->g == NULL))
- return (NULL);
- return (dh);
-}
-/* ----END GENERATED SECTION---------- */
-
-DH *ssl_dh_GetTmpParam(int nKeyLen)
-{
- DH *dh;
-
- if (nKeyLen == 512)
- dh = get_dh512();
- else if (nKeyLen == 1024)
- dh = get_dh1024();
- else
- dh = get_dh1024();
- return dh;
-}
-
-DH *ssl_dh_GetParamFromFile(char *file)
-{
- DH *dh = NULL;
- BIO *bio;
-
- if ((bio = BIO_new_file(file, "r")) == NULL)
- return NULL;
-#if SSL_LIBRARY_VERSION < 0x00904000
- dh = PEM_read_bio_DHparams(bio, NULL, NULL);
-#else
- dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
-#endif
- BIO_free(bio);
- return (dh);
-}
-
-/*
-=cut
-##
-## Embedded Perl script for generating the temporary DH parameters
-##
-
-require 5.003;
-use strict;
-
-# configuration
-my $file = $0;
-my $begin = '----BEGIN GENERATED SECTION--------';
-my $end = '----END GENERATED SECTION----------';
-
-# read ourself and keep a backup
-open(FP, "<$file") || die;
-my $source = '';
-$source .= $_ while (<FP>);
-close(FP);
-open(FP, ">$file.bak") || die;
-print FP $source;
-close(FP);
-
-# generate the DH parameters
-print "1. Generate 512 and 1024 bit Diffie-Hellman parameters (p, g)\n";
-my $rand = '';
-foreach $file (qw(/var/log/messages /var/adm/messages
- /kernel /vmunix /vmlinuz /etc/hosts /etc/resolv.conf)) {
- if (-f $file) {
- $rand = $file if ($rand eq '');
- $rand .= ":$file" if ($rand ne '');
- }
-}
-$rand = "-rand $rand" if ($rand ne '');
-system("openssl gendh $rand -out dh512.pem 512");
-system("openssl gendh $rand -out dh1024.pem 1024");
-
-# generate DH param info
-my $dhinfo = '';
-open(FP, "openssl dh -noout -text -in dh512.pem |") || die;
-$dhinfo .= $_ while (<FP>);
-close(FP);
-open(FP, "openssl dh -noout -text -in dh1024.pem |") || die;
-$dhinfo .= $_ while (<FP>);
-close(FP);
-$dhinfo =~ s|^|** |mg;
-$dhinfo = "\n\/\*\n$dhinfo\*\/\n\n";
-
-# generate C source from DH params
-my $dhsource = '';
-open(FP, "openssl dh -noout -C -in dh512.pem | indent | expand -8 |") || die;
-$dhsource .= $_ while (<FP>);
-close(FP);
-open(FP, "openssl dh -noout -C -in dh1024.pem | indent | expand -8 |") || die;
-$dhsource .= $_ while (<FP>);
-close(FP);
-$dhsource =~ s|(DH\s+\*get_dh)|static $1|sg;
-
-# generate output
-my $o = $dhinfo . $dhsource;
-
-# insert the generated code at the target location
-$source =~ s|(\/\* $begin.+?\n).*\n(.*?\/\* $end)|$1$o$2|s;
-
-# and update the source on disk
-print "Updating file `$file'\n";
-open(FP, ">$file") || die;
-print FP $source;
-close(FP);
-
-# cleanup
-unlink("dh512.pem");
-unlink("dh1024.pem");
-
-=pod
-*/
diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
deleted file mode 100644
index 6a27c4af4d..0000000000
--- a/modules/ssl/ssl_engine_init.c
+++ /dev/null
@@ -1,1090 +0,0 @@
-/* _ _
-** _ __ ___ ___ __| | ___ ___| | mod_ssl
-** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
-** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
-** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
-** |_____|
-** ssl_engine_init.c
-** Initialization of Servers
-*/
-
-/* ====================================================================
- * Copyright (c) 1998-2001 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * 4. The names "mod_ssl" must not be used to endorse or promote
- * products derived from this software without prior written
- * permission. For written permission, please contact
- * rse@engelschall.com.
- *
- * 5. Products derived from this software may not be called "mod_ssl"
- * nor may "mod_ssl" appear in their names without prior
- * written permission of Ralf S. Engelschall.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
-
-/* ====================================================================
- * Copyright (c) 1995-1999 Ben Laurie. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by Ben Laurie
- * for use in the Apache-SSL HTTP server project."
- *
- * 4. The name "Apache-SSL Server" must not be used to
- * endorse or promote products derived from this software without
- * prior written permission.
- *
- * 5. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by Ben Laurie
- * for use in the Apache-SSL HTTP server project."
- *
- * THIS SOFTWARE IS PROVIDED BY BEN LAURIE ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BEN LAURIE OR
- * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
- /* ``Recursive, adj.;
- see Recursive.''
- -- Unknown */
-#include "mod_ssl.h"
-
-
-/* _________________________________________________________________
-**
-** Module Initialization
-** _________________________________________________________________
-*/
-
-/*
- * Per-module initialization
- */
-void ssl_init_Module(server_rec *s, pool *p)
-{
- SSLModConfigRec *mc = myModConfig();
- SSLSrvConfigRec *sc;
- server_rec *s2;
- char *cp;
-
- mc->nInitCount++;
-
- /*
- * Let us cleanup on restarts and exists
- */
- ap_register_cleanup(p, s, ssl_init_ModuleKill, ssl_init_ChildKill);
-
- /*
- * Any init round fixes the global config
- */
- ssl_config_global_create(); /* just to avoid problems */
- ssl_config_global_fix();
-
- /*
- * try to fix the configuration and open the dedicated SSL
- * logfile as early as possible
- */
- for (s2 = s; s2 != NULL; s2 = s2->next) {
- sc = mySrvConfig(s2);
-
- /* Fix up stuff that may not have been set */
- if (sc->bEnabled == UNSET)
- sc->bEnabled = FALSE;
- if (sc->nVerifyClient == SSL_CVERIFY_UNSET)
- sc->nVerifyClient = SSL_CVERIFY_NONE;
- if (sc->nVerifyDepth == UNSET)
- sc->nVerifyDepth = 1;
-#ifdef SSL_EXPERIMENTAL_PROXY
- if (sc->nProxyVerifyDepth == UNSET)
- sc->nProxyVerifyDepth = 1;
-#endif
- if (sc->nSessionCacheTimeout == UNSET)
- sc->nSessionCacheTimeout = SSL_SESSION_CACHE_TIMEOUT;
- if (sc->nPassPhraseDialogType == SSL_PPTYPE_UNSET)
- sc->nPassPhraseDialogType = SSL_PPTYPE_BUILTIN;
-
- /* Open the dedicated SSL logfile */
- ssl_log_open(s, s2, p);
- }
-
- /*
- * Identification
- */
- if (mc->nInitCount == 1) {
- ssl_log(s, SSL_LOG_INFO, "Server: %s, Interface: %s, Library: %s",
- SERVER_BASEVERSION,
- ssl_var_lookup(p, NULL, NULL, NULL, "SSL_VERSION_INTERFACE"),
- ssl_var_lookup(p, NULL, NULL, NULL, "SSL_VERSION_LIBRARY"));
-#ifdef WIN32
- ssl_log(s, SSL_LOG_WARN, "You are using mod_ssl under Win32. "
- "This combination is *NOT* officially supported. "
- "Use it at your own risk!");
-#endif
- }
-
- /*
- * Initialization round information
- */
- if (mc->nInitCount == 1)
- ssl_log(s, SSL_LOG_INFO, "Init: 1st startup round (still not detached)");
- else if (mc->nInitCount == 2)
- ssl_log(s, SSL_LOG_INFO, "Init: 2nd startup round (already detached)");
- else
- ssl_log(s, SSL_LOG_INFO, "Init: %d%s restart round (already detached)",
- mc->nInitCount-2, (mc->nInitCount-2) == 1 ? "st" : "nd");
-
-#ifdef SSL_VENDOR
- ap_hook_use("ap::mod_ssl::vendor::init_module",
- AP_HOOK_SIG3(void,ptr,ptr), AP_HOOK_ALL, s, p);
-#endif
-
- /*
- * The initialization phase inside the Apache API is totally bogus.
- * We actually have three non-trivial problems:
- *
- * 1. Under Unix the API does a 2-round initialization of modules while
- * under Win32 it doesn't. This means we have to make sure that at
- * least the pass phrase dialog doesn't occur twice. We overcome this
- * problem by using a counter (mc->nInitCount) which has to
- * survive the init rounds.
- *
- * 2. Between the first and the second round Apache detaches from
- * the terminal under Unix. This means that our pass phrase dialog
- * _has_ to be done in the first round and _cannot_ be done in the
- * second round.
- *
- * 3. When Dynamic Shared Object (DSO) mechanism is used under Unix the
- * module segment (code & data) gets unloaded and re-loaded between
- * the first and the second round. This means no global data survives
- * between first and the second init round. We overcome this by using
- * an entry ("ssl_module") inside the ap_global_ctx.
- *
- * The situation as a table:
- *
- * Unix/static Unix/DSO Win32 Action Required
- * (-DSHARED_MODULE) (-DWIN32)
- * ----------- ----------------- --------- -----------------------------------
- * - load module - -
- * init init init SSL library init, Pass Phrase Dialog
- * detach detach - -
- * - reload module - -
- * init init - SSL library init, mod_ssl init
- *
- * Ok, now try to solve this totally ugly situation...
- */
-
-#ifdef SHARED_MODULE
- ssl_log(s, SSL_LOG_INFO, "Init: %snitializing %s library",
- mc->nInitCount == 1 ? "I" : "Rei", SSL_LIBRARY_NAME);
- ssl_init_SSLLibrary();
-#else
- if (mc->nInitCount <= 2) {
- ssl_log(s, SSL_LOG_INFO, "Init: %snitializing %s library",
- mc->nInitCount == 1 ? "I" : "Rei", SSL_LIBRARY_NAME);
- ssl_init_SSLLibrary();
- }
-#endif
- if (mc->nInitCount == 1) {
- ssl_pphrase_Handle(s, p);
- ssl_init_TmpKeysHandle(SSL_TKP_GEN, s, p);
-#ifndef WIN32
- return;
-#endif
- }
-
- /*
- * SSL external crypto device ("engine") support
- */
-#ifdef SSL_EXPERIMENTAL_ENGINE
- ssl_init_Engine(s, p);
-#endif
-
- /*
- * Warn the user that he should use the session cache.
- * But we can operate without it, of course.
- */
- if (mc->nSessionCacheMode == SSL_SCMODE_UNSET) {
- ssl_log(s, SSL_LOG_WARN,
- "Init: Session Cache is not configured [hint: SSLSessionCache]");
- mc->nSessionCacheMode = SSL_SCMODE_NONE;
- }
-
- /*
- * initialize the mutex handling and session caching
- */
- ssl_mutex_init(s, p);
- ssl_scache_init(s, p);
-
- /*
- * Seed the Pseudo Random Number Generator (PRNG)
- */
- ssl_rand_seed(s, p, SSL_RSCTX_STARTUP, "Init: ");
-
- /*
- * allocate the temporary RSA keys and DH params
- */
- ssl_init_TmpKeysHandle(SSL_TKP_ALLOC, s, p);
-
- /*
- * initialize servers
- */
- ssl_log(s, SSL_LOG_INFO, "Init: Initializing (virtual) servers for SSL");
- for (s2 = s; s2 != NULL; s2 = s2->next) {
- sc = mySrvConfig(s2);
- /*
- * Either now skip this server when SSL is disabled for
- * it or give out some information about what we're
- * configuring.
- */
- if (!sc->bEnabled)
- continue;
- ssl_log(s2, SSL_LOG_INFO,
- "Init: Configuring server %s for SSL protocol",
- ssl_util_vhostid(p, s2));
-
- /*
- * Read the server certificate and key
- */
- ssl_init_ConfigureServer(s2, p, sc);
- }
-
- /*
- * Configuration consistency checks
- */
- ssl_init_CheckServers(s, p);
-
- /*
- * Announce mod_ssl and SSL library in HTTP Server field
- * as ``mod_ssl/X.X.X OpenSSL/X.X.X''
- */
- if ((cp = ssl_var_lookup(p, NULL, NULL, NULL, "SSL_VERSION_PRODUCT")) != NULL && cp[0] != NUL)
- ap_add_version_component(cp);
- ap_add_version_component(ssl_var_lookup(p, NULL, NULL, NULL, "SSL_VERSION_INTERFACE"));
- ap_add_version_component(ssl_var_lookup(p, NULL, NULL, NULL, "SSL_VERSION_LIBRARY"));
-
- return;
-}
-
-/*
- * Initialize SSL library (also already needed for the pass phrase dialog)
- */
-void ssl_init_SSLLibrary(void)
-{
-#ifdef WIN32
- CRYPTO_malloc_init();
-#endif
- SSL_load_error_strings();
- SSL_library_init();
- ssl_util_thread_setup();
- X509V3_add_standard_extensions();
- return;
-}
-
-/*
- * Support for external a Crypto Device ("engine"), usually
- * a hardware accellerator card for crypto operations.
- */
-#ifdef SSL_EXPERIMENTAL_ENGINE
-void ssl_init_Engine(server_rec *s, pool *p)
-{
- SSLModConfigRec *mc = myModConfig();
- ENGINE *e;
-
- if (mc->szCryptoDevice != NULL) {
- if ((e = ENGINE_by_id(mc->szCryptoDevice)) == NULL) {
- ssl_log(s, SSL_LOG_ERROR, "Init: Failed to load Crypto Device API `%s'",
- mc->szCryptoDevice);
- ssl_die();
- }
- if (strEQ(mc->szCryptoDevice, "chil"))
- ENGINE_ctrl(e, ENGINE_CTRL_CHIL_SET_FORKCHECK, 1, 0, 0);
- if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
- ssl_log(s, SSL_LOG_ERROR, "Init: Failed to enable Crypto Device API `%s'",
- mc->szCryptoDevice);
- ssl_die();
- }
- ENGINE_free(e);
- }
- return;
-}
-#endif
-
-/*
- * Handle the Temporary RSA Keys and DH Params
- */
-void ssl_init_TmpKeysHandle(int action, server_rec *s, pool *p)
-{
- SSLModConfigRec *mc = myModConfig();
- ssl_asn1_t *asn1;
- unsigned char *ucp;
- RSA *rsa;
- DH *dh;
-
- /* Generate Keys and Params */
- if (action == SSL_TKP_GEN) {
-
- /* seed PRNG */
- ssl_rand_seed(s, p, SSL_RSCTX_STARTUP, "Init: ");
-
- /* generate 512 bit RSA key */
- ssl_log(s, SSL_LOG_INFO, "Init: Generating temporary RSA private keys (512/1024 bits)");
- if ((rsa = RSA_generate_key(512, RSA_F4, NULL, NULL)) == NULL) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "Init: Failed to generate temporary 512 bit RSA private key");
- ssl_die();
- }
- asn1 = (ssl_asn1_t *)ssl_ds_table_push(mc->tTmpKeys, "RSA:512");
- asn1->nData = i2d_RSAPrivateKey(rsa, NULL);
- asn1->cpData = ap_palloc(mc->pPool, asn1->nData);
- ucp = asn1->cpData; i2d_RSAPrivateKey(rsa, &ucp); /* 2nd arg increments */
- RSA_free(rsa);
-
- /* generate 1024 bit RSA key */
- if ((rsa = RSA_generate_key(1024, RSA_F4, NULL, NULL)) == NULL) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "Init: Failed to generate temporary 1024 bit RSA private key");
- ssl_die();
- }
- asn1 = (ssl_asn1_t *)ssl_ds_table_push(mc->tTmpKeys, "RSA:1024");
- asn1->nData = i2d_RSAPrivateKey(rsa, NULL);
- asn1->cpData = ap_palloc(mc->pPool, asn1->nData);
- ucp = asn1->cpData; i2d_RSAPrivateKey(rsa, &ucp); /* 2nd arg increments */
- RSA_free(rsa);
-
- ssl_log(s, SSL_LOG_INFO, "Init: Configuring temporary DH parameters (512/1024 bits)");
-
- /* import 512 bit DH param */
- if ((dh = ssl_dh_GetTmpParam(512)) == NULL) {
- ssl_log(s, SSL_LOG_ERROR, "Init: Failed to import temporary 512 bit DH parameters");
- ssl_die();
- }
- asn1 = (ssl_asn1_t *)ssl_ds_table_push(mc->tTmpKeys, "DH:512");
- asn1->nData = i2d_DHparams(dh, NULL);
- asn1->cpData = ap_palloc(mc->pPool, asn1->nData);
- ucp = asn1->cpData; i2d_DHparams(dh, &ucp); /* 2nd arg increments */
- /* no need to free dh, it's static */
-
- /* import 1024 bit DH param */
- if ((dh = ssl_dh_GetTmpParam(1024)) == NULL) {
- ssl_log(s, SSL_LOG_ERROR, "Init: Failed to import temporary 1024 bit DH parameters");
- ssl_die();
- }
- asn1 = (ssl_asn1_t *)ssl_ds_table_push(mc->tTmpKeys, "DH:1024");
- asn1->nData = i2d_DHparams(dh, NULL);
- asn1->cpData = ap_palloc(mc->pPool, asn1->nData);
- ucp = asn1->cpData; i2d_DHparams(dh, &ucp); /* 2nd arg increments */
- /* no need to free dh, it's static */
- }
-
- /* Allocate Keys and Params */
- else if (action == SSL_TKP_ALLOC) {
-
- ssl_log(s, SSL_LOG_INFO, "Init: Configuring temporary RSA private keys (512/1024 bits)");
-
- /* allocate 512 bit RSA key */
- if ((asn1 = (ssl_asn1_t *)ssl_ds_table_get(mc->tTmpKeys, "RSA:512")) != NULL) {
- ucp = asn1->cpData;
- if ((mc->pTmpKeys[SSL_TKPIDX_RSA512] =
-#if SSL_LIBRARY_VERSION >= 0x00907000
- (void *)d2i_RSAPrivateKey(NULL, (const unsigned char **)&ucp, asn1->nData)) == NULL) {
-#else
- (void *)d2i_RSAPrivateKey(NULL, &ucp, asn1->nData)) == NULL) {
-#endif
- ssl_log(s, SSL_LOG_ERROR, "Init: Failed to load temporary 512 bit RSA private key");
- ssl_die();
- }
- }
-
- /* allocate 1024 bit RSA key */
- if ((asn1 = (ssl_asn1_t *)ssl_ds_table_get(mc->tTmpKeys, "RSA:1024")) != NULL) {
- ucp = asn1->cpData;
- if ((mc->pTmpKeys[SSL_TKPIDX_RSA1024] =
-#if SSL_LIBRARY_VERSION >= 0x00907000
- (void *)d2i_RSAPrivateKey(NULL, (const unsigned char **)&ucp, asn1->nData)) == NULL) {
-#else
- (void *)d2i_RSAPrivateKey(NULL, &ucp, asn1->nData)) == NULL) {
-#endif
- ssl_log(s, SSL_LOG_ERROR, "Init: Failed to load temporary 1024 bit RSA private key");
- ssl_die();
- }
- }
-
- ssl_log(s, SSL_LOG_INFO, "Init: Configuring temporary DH parameters (512/1024 bits)");
-
- /* allocate 512 bit DH param */
- if ((asn1 = (ssl_asn1_t *)ssl_ds_table_get(mc->tTmpKeys, "DH:512")) != NULL) {
- ucp = asn1->cpData;
- if ((mc->pTmpKeys[SSL_TKPIDX_DH512] =
-#if SSL_LIBRARY_VERSION >= 0x00907000
- (void *)d2i_DHparams(NULL, (const unsigned char **)&ucp, asn1->nData)) == NULL) {
-#else
- (void *)d2i_DHparams(NULL, &ucp, asn1->nData)) == NULL) {
-#endif
- ssl_log(s, SSL_LOG_ERROR, "Init: Failed to load temporary 512 bit DH parameters");
- ssl_die();
- }
- }
-
- /* allocate 1024 bit DH param */
- if ((asn1 = (ssl_asn1_t *)ssl_ds_table_get(mc->tTmpKeys, "DH:1024")) != NULL) {
- ucp = asn1->cpData;
- if ((mc->pTmpKeys[SSL_TKPIDX_DH1024] =
-#if SSL_LIBRARY_VERSION >= 0x00907000
- (void *)d2i_DHparams(NULL, (const unsigned char **)&ucp, asn1->nData)) == NULL) {
-#else
- (void *)d2i_DHparams(NULL, &ucp, asn1->nData)) == NULL) {
-#endif
- ssl_log(s, SSL_LOG_ERROR, "Init: Failed to load temporary 1024 bit DH parameters");
- ssl_die();
- }
- }
- }
-
- /* Free Keys and Params */
- else if (action == SSL_TKP_FREE) {
- if (mc->pTmpKeys[SSL_TKPIDX_RSA512] != NULL) {
- RSA_free((RSA *)mc->pTmpKeys[SSL_TKPIDX_RSA512]);
- mc->pTmpKeys[SSL_TKPIDX_RSA512] = NULL;
- }
- if (mc->pTmpKeys[SSL_TKPIDX_RSA1024] != NULL) {
- RSA_free((RSA *)mc->pTmpKeys[SSL_TKPIDX_RSA1024]);
- mc->pTmpKeys[SSL_TKPIDX_RSA1024] = NULL;
- }
- if (mc->pTmpKeys[SSL_TKPIDX_DH512] != NULL) {
- DH_free((DH *)mc->pTmpKeys[SSL_TKPIDX_DH512]);
- mc->pTmpKeys[SSL_TKPIDX_DH512] = NULL;
- }
- if (mc->pTmpKeys[SSL_TKPIDX_DH1024] != NULL) {
- DH_free((DH *)mc->pTmpKeys[SSL_TKPIDX_DH1024]);
- mc->pTmpKeys[SSL_TKPIDX_DH1024] = NULL;
- }
- }
- return;
-}
-
-/*
- * Configure a particular server
- */
-void ssl_init_ConfigureServer(server_rec *s, pool *p, SSLSrvConfigRec *sc)
-{
- SSLModConfigRec *mc = myModConfig();
- int nVerify;
- char *cpVHostID;
- EVP_PKEY *pKey;
- SSL_CTX *ctx;
- STACK_OF(X509_NAME) *skCAList;
- ssl_asn1_t *asn1;
- unsigned char *ucp;
- char *cp;
- BOOL ok;
- BOOL bSkipFirst;
- int isca, pathlen;
- int i, n;
-
- /*
- * Create the server host:port string because we need it a lot
- */
- cpVHostID = ssl_util_vhostid(p, s);
-
- /*
- * Now check for important parameters and the
- * possibility that the user forgot to set them.
- */
- if (sc->szPublicCertFile[0] == NULL) {
- ssl_log(s, SSL_LOG_ERROR,
- "Init: (%s) No SSL Certificate set [hint: SSLCertificateFile]",
- cpVHostID);
- ssl_die();
- }
-
- /*
- * Check for problematic re-initializations
- */
- if (sc->pPublicCert[SSL_AIDX_RSA] != NULL ||
- sc->pPublicCert[SSL_AIDX_DSA] != NULL ) {
- ssl_log(s, SSL_LOG_ERROR,
- "Init: (%s) Illegal attempt to re-initialise SSL for server "
- "(theoretically shouldn't happen!)", cpVHostID);
- ssl_die();
- }
-
- /*
- * Create the new per-server SSL context
- */
- if (sc->nProtocol == SSL_PROTOCOL_NONE) {
- ssl_log(s, SSL_LOG_ERROR,
- "Init: (%s) No SSL protocols available [hint: SSLProtocol]",
- cpVHostID);
- ssl_die();
- }
- cp = ap_pstrcat(p, (sc->nProtocol & SSL_PROTOCOL_SSLV2 ? "SSLv2, " : ""),
- (sc->nProtocol & SSL_PROTOCOL_SSLV3 ? "SSLv3, " : ""),
- (sc->nProtocol & SSL_PROTOCOL_TLSV1 ? "TLSv1, " : ""), NULL);
- cp[strlen(cp)-2] = NUL;
- ssl_log(s, SSL_LOG_TRACE,
- "Init: (%s) Creating new SSL context (protocols: %s)", cpVHostID, cp);
- if (sc->nProtocol == SSL_PROTOCOL_SSLV2)
- ctx = SSL_CTX_new(SSLv2_server_method()); /* only SSLv2 is left */
- else
- ctx = SSL_CTX_new(SSLv23_server_method()); /* be more flexible */
- SSL_CTX_set_options(ctx, SSL_OP_ALL);
- if (!(sc->nProtocol & SSL_PROTOCOL_SSLV2))
- SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
- if (!(sc->nProtocol & SSL_PROTOCOL_SSLV3))
- SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3);
- if (!(sc->nProtocol & SSL_PROTOCOL_TLSV1))
- SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1);
- SSL_CTX_set_app_data(ctx, s);
- sc->pSSLCtx = ctx;
-
- /*
- * Configure additional context ingredients
- */
- SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE);
- if (mc->nSessionCacheMode == SSL_SCMODE_NONE)
- SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
- else
- SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER);
-
- /*
- * Configure callbacks for SSL context
- */
- nVerify = SSL_VERIFY_NONE;
- if (sc->nVerifyClient == SSL_CVERIFY_REQUIRE)
- nVerify |= SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
- if ( (sc->nVerifyClient == SSL_CVERIFY_OPTIONAL)
- || (sc->nVerifyClient == SSL_CVERIFY_OPTIONAL_NO_CA) )
- nVerify |= SSL_VERIFY_PEER;
- SSL_CTX_set_verify(ctx, nVerify, ssl_callback_SSLVerify);
- SSL_CTX_sess_set_new_cb(ctx, ssl_callback_NewSessionCacheEntry);
- SSL_CTX_sess_set_get_cb(ctx, ssl_callback_GetSessionCacheEntry);
- SSL_CTX_sess_set_remove_cb(ctx, ssl_callback_DelSessionCacheEntry);
- SSL_CTX_set_tmp_rsa_callback(ctx, ssl_callback_TmpRSA);
- SSL_CTX_set_tmp_dh_callback(ctx, ssl_callback_TmpDH);
- SSL_CTX_set_info_callback(ctx, ssl_callback_LogTracingState);
-
- /*
- * Configure SSL Cipher Suite
- */
- if (sc->szCipherSuite != NULL) {
- ssl_log(s, SSL_LOG_TRACE,
- "Init: (%s) Configuring permitted SSL ciphers [%s]",
- cpVHostID, sc->szCipherSuite);
- if (!SSL_CTX_set_cipher_list(ctx, sc->szCipherSuite)) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "Init: (%s) Unable to configure permitted SSL ciphers",
- cpVHostID);
- ssl_die();
- }
- }
-
- /*
- * Configure Client Authentication details
- */
- if (sc->szCACertificateFile != NULL || sc->szCACertificatePath != NULL) {
- ssl_log(s, SSL_LOG_TRACE,
- "Init: (%s) Configuring client authentication", cpVHostID);
- if (!SSL_CTX_load_verify_locations(ctx,
- sc->szCACertificateFile,
- sc->szCACertificatePath)) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "Init: (%s) Unable to configure verify locations "
- "for client authentication", cpVHostID);
- ssl_die();
- }
- if ((skCAList = ssl_init_FindCAList(s, p, sc->szCACertificateFile,
- sc->szCACertificatePath)) == NULL) {
- ssl_log(s, SSL_LOG_ERROR,
- "Init: (%s) Unable to determine list of available "
- "CA certificates for client authentication", cpVHostID);
- ssl_die();
- }
- SSL_CTX_set_client_CA_list(sc->pSSLCtx, skCAList);
- }
-
- /*
- * Configure Certificate Revocation List (CRL) Details
- */
- if (sc->szCARevocationFile != NULL || sc->szCARevocationPath != NULL) {
- ssl_log(s, SSL_LOG_TRACE,
- "Init: (%s) Configuring certificate revocation facility", cpVHostID);
- if ((sc->pRevocationStore =
- SSL_X509_STORE_create(sc->szCARevocationFile,
- sc->szCARevocationPath)) == NULL) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "Init: (%s) Unable to configure X.509 CRL storage "
- "for certificate revocation", cpVHostID);
- ssl_die();
- }
- }
-
- /*
- * Give a warning when no CAs were configured but client authentication
- * should take place. This cannot work.
- */
- if (sc->nVerifyClient == SSL_CVERIFY_REQUIRE) {
- skCAList = SSL_CTX_get_client_CA_list(ctx);
- if (sk_X509_NAME_num(skCAList) == 0)
- ssl_log(s, SSL_LOG_WARN,
- "Init: Ops, you want to request client authentication, "
- "but no CAs are known for verification!? "
- "[Hint: SSLCACertificate*]");
- }
-
- /*
- * Configure server certificate(s)
- */
- ok = FALSE;
- cp = ap_psprintf(p, "%s:RSA", cpVHostID);
- if ((asn1 = (ssl_asn1_t *)ssl_ds_table_get(mc->tPublicCert, cp)) != NULL) {
- ssl_log(s, SSL_LOG_TRACE,
- "Init: (%s) Configuring RSA server certificate", cpVHostID);
- ucp = asn1->cpData;
- if ((sc->pPublicCert[SSL_AIDX_RSA] = d2i_X509(NULL, &ucp, asn1->nData)) == NULL) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "Init: (%s) Unable to import RSA server certificate",
- cpVHostID);
- ssl_die();
- }
- if (SSL_CTX_use_certificate(ctx, sc->pPublicCert[SSL_AIDX_RSA]) <= 0) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "Init: (%s) Unable to configure RSA server certificate",
- cpVHostID);
- ssl_die();
- }
- ok = TRUE;
- }
- cp = ap_psprintf(p, "%s:DSA", cpVHostID);
- if ((asn1 = (ssl_asn1_t *)ssl_ds_table_get(mc->tPublicCert, cp)) != NULL) {
- ssl_log(s, SSL_LOG_TRACE,
- "Init: (%s) Configuring DSA server certificate", cpVHostID);
- ucp = asn1->cpData;
- if ((sc->pPublicCert[SSL_AIDX_DSA] = d2i_X509(NULL, &ucp, asn1->nData)) == NULL) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "Init: (%s) Unable to import DSA server certificate",
- cpVHostID);
- ssl_die();
- }
- if (SSL_CTX_use_certificate(ctx, sc->pPublicCert[SSL_AIDX_DSA]) <= 0) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "Init: (%s) Unable to configure DSA server certificate",
- cpVHostID);
- ssl_die();
- }
- ok = TRUE;
- }
- if (!ok) {
- ssl_log(s, SSL_LOG_ERROR,
- "Init: (%s) Ops, no RSA or DSA server certificate found?!", cpVHostID);
- ssl_log(s, SSL_LOG_ERROR,
- "Init: (%s) You have to perform a *full* server restart when you added or removed a certificate and/or key file", cpVHostID);
- ssl_die();
- }
-
- /*
- * Some information about the certificate(s)
- */
- for (i = 0; i < SSL_AIDX_MAX; i++) {
- if (sc->pPublicCert[i] != NULL) {
- if (SSL_X509_isSGC(sc->pPublicCert[i])) {
- ssl_log(s, SSL_LOG_INFO,
- "Init: (%s) %s server certificate enables "
- "Server Gated Cryptography (SGC)",
- cpVHostID, (i == SSL_AIDX_RSA ? "RSA" : "DSA"));
- }
- if (SSL_X509_getBC(sc->pPublicCert[i], &isca, &pathlen)) {
- if (isca)
- ssl_log(s, SSL_LOG_WARN,
- "Init: (%s) %s server certificate is a CA certificate "
- "(BasicConstraints: CA == TRUE !?)",
- cpVHostID, (i == SSL_AIDX_RSA ? "RSA" : "DSA"));
- if (pathlen > 0)
- ssl_log(s, SSL_LOG_WARN,
- "Init: (%s) %s server certificate is not a leaf certificate "
- "(BasicConstraints: pathlen == %d > 0 !?)",
- cpVHostID, (i == SSL_AIDX_RSA ? "RSA" : "DSA"), pathlen);
- }
- if (SSL_X509_getCN(p, sc->pPublicCert[i], &cp)) {
- if (ap_is_fnmatch(cp) &&
- !ap_fnmatch(cp, s->server_hostname, FNM_PERIOD|FNM_CASE_BLIND)) {
- ssl_log(s, SSL_LOG_WARN,
- "Init: (%s) %s server certificate wildcard CommonName (CN) `%s' "
- "does NOT match server name!?", cpVHostID,
- (i == SSL_AIDX_RSA ? "RSA" : "DSA"), cp);
- }
- else if (strNE(s->server_hostname, cp)) {
- ssl_log(s, SSL_LOG_WARN,
- "Init: (%s) %s server certificate CommonName (CN) `%s' "
- "does NOT match server name!?", cpVHostID,
- (i == SSL_AIDX_RSA ? "RSA" : "DSA"), cp);
- }
- }
- }
- }
-
- /*
- * Configure server private key(s)
- */
- ok = FALSE;
- cp = ap_psprintf(p, "%s:RSA", cpVHostID);
- if ((asn1 = (ssl_asn1_t *)ssl_ds_table_get(mc->tPrivateKey, cp)) != NULL) {
- ssl_log(s, SSL_LOG_TRACE,
- "Init: (%s) Configuring RSA server private key", cpVHostID);
- ucp = asn1->cpData;
- if ((sc->pPrivateKey[SSL_AIDX_RSA] =
- d2i_PrivateKey(EVP_PKEY_RSA, NULL, &ucp, asn1->nData)) == NULL) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "Init: (%s) Unable to import RSA server private key",
- cpVHostID);
- ssl_die();
- }
- if (SSL_CTX_use_PrivateKey(ctx, sc->pPrivateKey[SSL_AIDX_RSA]) <= 0) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "Init: (%s) Unable to configure RSA server private key",
- cpVHostID);
- ssl_die();
- }
- ok = TRUE;
- }
- cp = ap_psprintf(p, "%s:DSA", cpVHostID);
- if ((asn1 = (ssl_asn1_t *)ssl_ds_table_get(mc->tPrivateKey, cp)) != NULL) {
- ssl_log(s, SSL_LOG_TRACE,
- "Init: (%s) Configuring DSA server private key", cpVHostID);
- ucp = asn1->cpData;
- if ((sc->pPrivateKey[SSL_AIDX_DSA] =
- d2i_PrivateKey(EVP_PKEY_DSA, NULL, &ucp, asn1->nData)) == NULL) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "Init: (%s) Unable to import DSA server private key",
- cpVHostID);
- ssl_die();
- }
- if (SSL_CTX_use_PrivateKey(ctx, sc->pPrivateKey[SSL_AIDX_DSA]) <= 0) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "Init: (%s) Unable to configure DSA server private key",
- cpVHostID);
- ssl_die();
- }
- ok = TRUE;
- }
- if (!ok) {
- ssl_log(s, SSL_LOG_ERROR,
- "Init: (%s) Ops, no RSA or DSA server private key found?!", cpVHostID);
- ssl_die();
- }
-
- /*
- * Optionally copy DSA parameters for certificate from private key
- * (see http://www.psy.uq.edu.au/~ftp/Crypto/ssleay/TODO.html)
- */
- if ( sc->pPublicCert[SSL_AIDX_DSA] != NULL
- && sc->pPrivateKey[SSL_AIDX_DSA] != NULL) {
- pKey = X509_get_pubkey(sc->pPublicCert[SSL_AIDX_DSA]);
- if ( pKey != NULL
- && EVP_PKEY_type(pKey->type) == EVP_PKEY_DSA
- && EVP_PKEY_missing_parameters(pKey))
- EVP_PKEY_copy_parameters(pKey, sc->pPrivateKey[SSL_AIDX_DSA]);
- }
-
- /*
- * Optionally configure extra server certificate chain certificates.
- * This is usually done by OpenSSL automatically when one of the
- * server cert issuers are found under SSLCACertificatePath or in
- * SSLCACertificateFile. But because these are intended for client
- * authentication it can conflict. For instance when you use a
- * Global ID server certificate you've to send out the intermediate
- * CA certificate, too. When you would just configure this with
- * SSLCACertificateFile and also use client authentication mod_ssl
- * would accept all clients also issued by this CA. Obviously this
- * isn't what we want in this situation. So this feature here exists
- * to allow one to explicity configure CA certificates which are
- * used only for the server certificate chain.
- */
- if (sc->szCertificateChain != NULL) {
- bSkipFirst = FALSE;
- for (i = 0; i < SSL_AIDX_MAX && sc->szPublicCertFile[i] != NULL; i++) {
- if (strEQ(sc->szPublicCertFile[i], sc->szCertificateChain)) {
- bSkipFirst = TRUE;
- break;
- }
- }
- if ((n = SSL_CTX_use_certificate_chain(ctx, sc->szCertificateChain,
- bSkipFirst, NULL)) < 0) {
- ssl_log(s, SSL_LOG_ERROR,
- "Init: (%s) Failed to configure CA certificate chain!", cpVHostID);
- ssl_die();
- }
- ssl_log(s, SSL_LOG_TRACE, "Init: (%s) Configuring "
- "server certificate chain (%d CA certificate%s)", cpVHostID,
- n, n == 1 ? "" : "s");
- }
-
-#ifdef SSL_VENDOR
- ap_hook_use("ap::mod_ssl::vendor::configure_server",
- AP_HOOK_SIG4(void,ptr,ptr,ptr), AP_HOOK_ALL,
- s, p, sc);
-#endif
-
- return;
-}
-
-void ssl_init_CheckServers(server_rec *sm, pool *p)
-{
- server_rec *s;
- server_rec **ps;
- SSLSrvConfigRec *sc;
- ssl_ds_table *t;
- pool *sp;
- char *key;
- BOOL bConflict;
-
- /*
- * Give out warnings when a server has HTTPS configured
- * for the HTTP port or vice versa
- */
- for (s = sm; s != NULL; s = s->next) {
- sc = mySrvConfig(s);
- if (sc->bEnabled && s->port == DEFAULT_HTTP_PORT)
- ssl_log(sm, SSL_LOG_WARN,
- "Init: (%s) You configured HTTPS(%d) on the standard HTTP(%d) port!",
- ssl_util_vhostid(p, s), DEFAULT_HTTPS_PORT, DEFAULT_HTTP_PORT);
- if (!sc->bEnabled && s->port == DEFAULT_HTTPS_PORT)
- ssl_log(sm, SSL_LOG_WARN,
- "Init: (%s) You configured HTTP(%d) on the standard HTTPS(%d) port!",
- ssl_util_vhostid(p, s), DEFAULT_HTTP_PORT, DEFAULT_HTTPS_PORT);
- }
-
- /*
- * Give out warnings when more than one SSL-aware virtual server uses the
- * same IP:port. This doesn't work because mod_ssl then will always use
- * just the certificate/keys of one virtual host (which one cannot be said
- * easily - but that doesn't matter here).
- */
- sp = ap_make_sub_pool(p);
- t = ssl_ds_table_make(sp, sizeof(server_rec *));
- bConflict = FALSE;
- for (s = sm; s != NULL; s = s->next) {
- sc = mySrvConfig(s);
- if (!sc->bEnabled)
- continue;
- key = ap_psprintf(sp, "%pA:%u", &s->addrs->host_addr, s->addrs->host_port);
- ps = ssl_ds_table_get(t, key);
- if (ps != NULL) {
- ssl_log(sm, SSL_LOG_WARN,
- "Init: SSL server IP/port conflict: %s (%s:%d) vs. %s (%s:%d)",
- ssl_util_vhostid(p, s),
- (s->defn_name != NULL ? s->defn_name : "unknown"),
- s->defn_line_number,
- ssl_util_vhostid(p, *ps),
- ((*ps)->defn_name != NULL ? (*ps)->defn_name : "unknown"),
- (*ps)->defn_line_number);
- bConflict = TRUE;
- continue;
- }
- ps = ssl_ds_table_push(t, key);
- *ps = s;
- }
- ssl_ds_table_kill(t);
- ap_destroy_pool(sp);
- if (bConflict)
- ssl_log(sm, SSL_LOG_WARN,
- "Init: You should not use name-based virtual hosts in conjunction with SSL!!");
-
- return;
-}
-
-static int ssl_init_FindCAList_X509NameCmp(X509_NAME **a, X509_NAME **b)
-{
- return(X509_NAME_cmp(*a, *b));
-}
-
-STACK_OF(X509_NAME) *ssl_init_FindCAList(server_rec *s, pool *pp, char *cpCAfile, char *cpCApath)
-{
- STACK_OF(X509_NAME) *skCAList;
- STACK_OF(X509_NAME) *sk;
- DIR *dir;
- struct DIR_TYPE *direntry;
- char *cp;
- pool *p;
- int n;
-
- /*
- * Use a subpool so we don't bloat up the server pool which
- * is remains in memory for the complete operation time of
- * the server.
- */
- p = ap_make_sub_pool(pp);
-
- /*
- * Start with a empty stack/list where new
- * entries get added in sorted order.
- */
- skCAList = sk_X509_NAME_new(ssl_init_FindCAList_X509NameCmp);
-
- /*
- * Process CA certificate bundle file
- */
- if (cpCAfile != NULL) {
- sk = SSL_load_client_CA_file(cpCAfile);
- for(n = 0; sk != NULL && n < sk_X509_NAME_num(sk); n++) {
- ssl_log(s, SSL_LOG_TRACE,
- "CA certificate: %s",
- X509_NAME_oneline(sk_X509_NAME_value(sk, n), NULL, 0));
- if (sk_X509_NAME_find(skCAList, sk_X509_NAME_value(sk, n)) < 0)
- sk_X509_NAME_push(skCAList, sk_X509_NAME_value(sk, n));
- }
- }
-
- /*
- * Process CA certificate path files
- */
- if (cpCApath != NULL) {
- dir = ap_popendir(p, cpCApath);
- while ((direntry = readdir(dir)) != NULL) {
- cp = ap_pstrcat(p, cpCApath, "/", direntry->d_name, NULL);
- sk = SSL_load_client_CA_file(cp);
- for(n = 0; sk != NULL && n < sk_X509_NAME_num(sk); n++) {
- ssl_log(s, SSL_LOG_TRACE,
- "CA certificate: %s",
- X509_NAME_oneline(sk_X509_NAME_value(sk, n), NULL, 0));
- if (sk_X509_NAME_find(skCAList, sk_X509_NAME_value(sk, n)) < 0)
- sk_X509_NAME_push(skCAList, sk_X509_NAME_value(sk, n));
- }
- }
- ap_pclosedir(p, dir);
- }
-
- /*
- * Cleanup
- */
- sk_X509_NAME_set_cmp_func(skCAList, NULL);
- ap_destroy_pool(p);
-
- return skCAList;
-}
-
-void ssl_init_Child(server_rec *s, pool *p)
-{
- /* open the mutex lockfile */
- ssl_mutex_reinit(s, p);
- return;
-}
-
-void ssl_init_ChildKill(void *data)
-{
- /* currently nothing to do */
- return;
-}
-
-void ssl_init_ModuleKill(void *data)
-{
- SSLSrvConfigRec *sc;
- server_rec *s = (server_rec *)data;
-
- /*
- * Drop the session cache and mutex
- */
- ssl_scache_kill(s);
- ssl_mutex_kill(s);
-
- /*
- * Destroy the temporary keys and params
- */
- ssl_init_TmpKeysHandle(SSL_TKP_FREE, s, NULL);
-
- /*
- * Free the non-pool allocated structures
- * in the per-server configurations
- */
- for (; s != NULL; s = s->next) {
- sc = mySrvConfig(s);
- if (sc->pPublicCert[SSL_AIDX_RSA] != NULL) {
- X509_free(sc->pPublicCert[SSL_AIDX_RSA]);
- sc->pPublicCert[SSL_AIDX_RSA] = NULL;
- }
- if (sc->pPublicCert[SSL_AIDX_DSA] != NULL) {
- X509_free(sc->pPublicCert[SSL_AIDX_DSA]);
- sc->pPublicCert[SSL_AIDX_DSA] = NULL;
- }
- if (sc->pPrivateKey[SSL_AIDX_RSA] != NULL) {
- EVP_PKEY_free(sc->pPrivateKey[SSL_AIDX_RSA]);
- sc->pPrivateKey[SSL_AIDX_RSA] = NULL;
- }
- if (sc->pPrivateKey[SSL_AIDX_DSA] != NULL) {
- EVP_PKEY_free(sc->pPrivateKey[SSL_AIDX_DSA]);
- sc->pPrivateKey[SSL_AIDX_DSA] = NULL;
- }
- if (sc->pSSLCtx != NULL) {
- SSL_CTX_free(sc->pSSLCtx);
- sc->pSSLCtx = NULL;
- }
- }
-
- /*
- * Try to kill the internals of the SSL library.
- */
-#ifdef SHARED_MODULE
- ERR_free_strings();
- ERR_remove_state(0);
- EVP_cleanup();
-#endif
-
- return;
-}
-
diff --git a/modules/ssl/ssl_engine_io.c b/modules/ssl/ssl_engine_io.c
deleted file mode 100644
index 4ba1574ca8..0000000000
--- a/modules/ssl/ssl_engine_io.c
+++ /dev/null
@@ -1,728 +0,0 @@
-/* _ _
-** _ __ ___ ___ __| | ___ ___| | mod_ssl
-** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
-** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
-** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
-** |_____|
-** ssl_engine_io.c
-** I/O Functions
-*/
-
-/* ====================================================================
- * Copyright (c) 1998-2001 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * 4. The names "mod_ssl" must not be used to endorse or promote
- * products derived from this software without prior written
- * permission. For written permission, please contact
- * rse@engelschall.com.
- *
- * 5. Products derived from this software may not be called "mod_ssl"
- * nor may "mod_ssl" appear in their names without prior
- * written permission of Ralf S. Engelschall.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
- /* ``MY HACK: This universe.
- Just one little problem:
- core keeps dumping.''
- -- Unknown */
-#include "mod_ssl.h"
-
-/* _________________________________________________________________
-**
-** I/O Request Body Sucking and Re-Injection
-** _________________________________________________________________
-*/
-
-#ifndef SSL_CONSERVATIVE
-
-/*
- * Background:
- *
- * 1. When the client sends a HTTP/HTTPS request, Apache's core code
- * reads only the request line ("METHOD /path HTTP/x.y") and the
- * attached MIME headers ("Foo: bar") up to the terminating line ("CR
- * LF"). An attached request body (for instance the data of a POST
- * method) is _NOT_ read. Instead it is read by mod_cgi's content
- * handler and directly passed to the CGI script.
- *
- * 2. mod_ssl supports per-directory re-configuration of SSL parameters.
- * This is implemented by performing an SSL renegotiation of the
- * re-configured parameters after the request is read, but before the
- * response is sent. In more detail: the renegotiation happens after the
- * request line and MIME headers were read, but _before_ the attached
- * request body is read. The reason simply is that in the HTTP protocol
- * usually there is no acknowledgment step between the headers and the
- * body (there is the 100-continue feature and the chunking facility
- * only), so Apache has no API hook for this step.
- *
- * 3. the problem now occurs when the client sends a POST request for
- * URL /foo via HTTPS the server and the server has SSL parameters
- * re-configured on a per-URL basis for /foo. Then mod_ssl has to
- * perform an SSL renegotiation after the request was read and before
- * the response is sent. But the problem is the pending POST body data
- * in the receive buffer of SSL (which Apache still has not read - it's
- * pending until mod_cgi sucks it in). When mod_ssl now tries to perform
- * the renegotiation the pending data leads to an I/O error.
- *
- * Solution Idea:
- *
- * There are only two solutions: Either to simply state that POST
- * requests to URLs with SSL re-configurations are not allowed, or to
- * renegotiate really after the _complete_ request (i.e. including
- * the POST body) was read. Obviously the latter would be preferred,
- * but it cannot be done easily inside Apache, because as already
- * mentioned, there is no API step between the body reading and the body
- * processing. And even when we mod_ssl would hook directly into the
- * loop of mod_cgi, we wouldn't solve the problem for other handlers, of
- * course. So the only general solution is to suck in the pending data
- * of the request body from the OpenSSL BIO into the Apache BUFF. Then
- * the renegotiation can be done and after this step Apache can proceed
- * processing the request as before.
- *
- * Solution Implementation:
- *
- * We cannot simply suck in the data via an SSL_read-based loop because of
- * HTTP chunking. Instead we _have_ to use the Apache API for this step which
- * is aware of HTTP chunking. So the trick is to suck in the pending request
- * data via the Apache API (which uses Apache's BUFF code and in the
- * background mod_ssl's I/O glue code) and re-inject it later into the Apache
- * BUFF code again. This way the data flows twice through the Apache BUFF, of
- * course. But this way the solution doesn't depend on any Apache specifics
- * and is fully transparent to Apache modules.
- */
-
-struct ssl_io_suck_st {
- BOOL active;
- char *bufptr;
- int buflen;
- char *pendptr;
- int pendlen;
-};
-
-/* prepare request_rec structure for input sucking */
-static void ssl_io_suck_start(request_rec *r)
-{
- struct ssl_io_suck_st *ss;
-
- ss = ap_ctx_get(r->ctx, "ssl::io::suck");
- if (ss == NULL) {
- ss = ap_palloc(r->pool, sizeof(struct ssl_io_suck_st));
- ap_ctx_set(r->ctx, "ssl::io::suck", ss);
- ss->buflen = 8192;
- ss->bufptr = ap_palloc(r->pool, ss->buflen);
- }
- ss->pendptr = ss->bufptr;
- ss->pendlen = 0;
- ss->active = FALSE;
- return;
-}
-
-/* record a sucked input chunk */
-static void ssl_io_suck_record(request_rec *r, char *buf, int len)
-{
- struct ssl_io_suck_st *ss;
-
- if ((ss = ap_ctx_get(r->ctx, "ssl::io::suck")) == NULL)
- return;
- if (((ss->bufptr + ss->buflen) - (ss->pendptr + ss->pendlen)) < len) {
- /* "expand" buffer: actually we cannot really expand the buffer
- here, because Apache's pool system doesn't support expanding chunks
- of memory. Instead we have to either reuse processed data or
- allocate a new chunk of memory in advance if we really need more
- memory. */
- int newlen;
- char *newptr;
-
- if (( (ss->pendptr - ss->bufptr)
- + ((ss->bufptr + ss->buflen) - (ss->pendptr + ss->pendlen)) ) >= len) {
- /* make memory available by reusing already processed data */
- memmove(ss->bufptr, ss->pendptr, ss->pendlen);
- ss->pendptr = ss->bufptr;
- }
- else {
- /* too bad, we have to allocate a new larger buffer */
- newlen = (ss->buflen * 2) + len;
- newptr = ap_palloc(r->pool, newlen);
- ss->bufptr = newptr;
- ss->buflen = newlen;
- memcpy(ss->bufptr, ss->pendptr, ss->pendlen);
- ss->pendptr = ss->bufptr;
- }
- }
- memcpy(ss->pendptr+ss->pendlen, buf, len);
- ss->pendlen += len;
- return;
-}
-
-/* finish request_rec after input sucking */
-static void ssl_io_suck_end(request_rec *r)
-{
- struct ssl_io_suck_st *ss;
-
- if ((ss = ap_ctx_get(r->ctx, "ssl::io::suck")) == NULL)
- return;
- ss->active = TRUE;
- r->read_body = REQUEST_NO_BODY;
- r->read_length = 0;
- r->read_chunked = 0;
- r->remaining = 0;
- ap_bsetflag(r->connection->client, B_CHUNK, 0);
- return;
-}
-
-void ssl_io_suck(request_rec *r, SSL *ssl)
-{
- int rc;
- int len;
- char *buf;
- int buflen;
- char c;
- int sucked;
-
- if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK)) == OK) {
- if (ap_should_client_block(r)) {
-
- /* read client request block through Apache API */
- buflen = HUGE_STRING_LEN;
- buf = ap_palloc(r->pool, buflen);
- ap_hard_timeout("SSL I/O request body pre-sucking", r);
- sucked = 0;
- ssl_io_suck_start(r);
- while ((len = ap_get_client_block(r, buf, buflen)) > 0) {
- ssl_io_suck_record(r, buf, len);
- sucked += len;
- }
- ssl_io_suck_end(r);
- ap_kill_timeout(r);
-
- /* suck trailing data (usually CR LF) which
- is still in the Apache BUFF layer */
- while (ap_bpeekc(r->connection->client) != EOF) {
- c = ap_bgetc(r->connection->client);
- ssl_io_suck_record(r, &c, 1);
- sucked++;
- }
-
- ssl_log(r->server, SSL_LOG_TRACE,
- "I/O: sucked %d bytes of input data from SSL/TLS I/O layer "
- "for delayed injection into Apache I/O layer", sucked);
- }
- }
- return;
-}
-
-/* the SSL_read replacement routine which knows about the suck buffer */
-static int ssl_io_suck_read(SSL *ssl, char *buf, int len)
-{
- ap_ctx *actx;
- struct ssl_io_suck_st *ss;
- request_rec *r = NULL;
- int rv;
-
- actx = (ap_ctx *)SSL_get_app_data2(ssl);
- if (actx != NULL)
- r = (request_rec *)ap_ctx_get(actx, "ssl::request_rec");
-
- rv = -1;
- if (r != NULL) {
- ss = ap_ctx_get(r->ctx, "ssl::io::suck");
- if (ss != NULL) {
- if (ss->active && ss->pendlen > 0) {
- /* ok, there is pre-sucked data */
- len = (ss->pendlen > len ? len : ss->pendlen);
- memcpy(buf, ss->pendptr, len);
- ss->pendptr += len;
- ss->pendlen -= len;
- ssl_log(r->server, SSL_LOG_TRACE,
- "I/O: injecting %d bytes of pre-sucked data "
- "into Apache I/O layer", len);
- rv = len;
- }
- }
- }
- if (rv == -1)
- rv = SSL_read(ssl, buf, len);
- return rv;
-}
-
-/* override SSL_read in the following code... */
-#define SSL_read ssl_io_suck_read
-
-#endif /* !SSL_CONSERVATIVE */
-
-/* _________________________________________________________________
-**
-** I/O Hooks
-** _________________________________________________________________
-*/
-
-#ifndef NO_WRITEV
-#include <sys/types.h>
-#include <sys/uio.h>
-#endif
-
-static int ssl_io_hook_read(BUFF *fb, char *buf, int len);
-static int ssl_io_hook_write(BUFF *fb, char *buf, int len);
-#ifndef NO_WRITEV
-static int ssl_io_hook_writev(BUFF *fb, const struct iovec *iov, int iovcnt);
-#endif
-#ifdef WIN32
-static int ssl_io_hook_recvwithtimeout(BUFF *fb, char *buf, int len);
-static int ssl_io_hook_sendwithtimeout(BUFF *fb, const char *buf, int len);
-#endif /* WIN32 */
-
-void ssl_io_register(void)
-{
- ap_hook_register("ap::buff::read", ssl_io_hook_read, AP_HOOK_NOCTX);
- ap_hook_register("ap::buff::write", ssl_io_hook_write, AP_HOOK_NOCTX);
-#ifndef NO_WRITEV
- ap_hook_register("ap::buff::writev", ssl_io_hook_writev, AP_HOOK_NOCTX);
-#endif
-#ifdef WIN32
- ap_hook_register("ap::buff::recvwithtimeout",
- ssl_io_hook_recvwithtimeout, AP_HOOK_NOCTX);
- ap_hook_register("ap::buff::sendwithtimeout",
- ssl_io_hook_sendwithtimeout, AP_HOOK_NOCTX);
-#endif
- return;
-}
-
-void ssl_io_unregister(void)
-{
- ap_hook_unregister("ap::buff::read", ssl_io_hook_read);
- ap_hook_unregister("ap::buff::write", ssl_io_hook_write);
-#ifndef NO_WRITEV
- ap_hook_unregister("ap::buff::writev", ssl_io_hook_writev);
-#endif
-#ifdef WIN32
- ap_hook_unregister("ap::buff::recvwithtimeout", ssl_io_hook_recvwithtimeout);
- ap_hook_unregister("ap::buff::sendwithtimeout", ssl_io_hook_sendwithtimeout);
-#endif
- return;
-}
-
-static int ssl_io_hook_read(BUFF *fb, char *buf, int len)
-{
- SSL *ssl;
- conn_rec *c;
- int rc;
-
- if ((ssl = ap_ctx_get(fb->ctx, "ssl")) != NULL) {
- rc = SSL_read(ssl, buf, len);
- /*
- * Simulate an EINTR in case OpenSSL wants to read more.
- * (This is usually the case when the client forces an SSL
- * renegotation which is handled implicitly by OpenSSL.)
- */
- if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_WANT_READ)
- errno = EINTR;
- /*
- * Log SSL errors
- */
- if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_SSL) {
- c = (conn_rec *)SSL_get_app_data(ssl);
- ssl_log(c->server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "SSL error on reading data");
- }
- /*
- * read(2) returns only the generic error number -1
- */
- if (rc < 0)
- rc = -1;
- }
- else
- rc = read(fb->fd_in, buf, len);
- return rc;
-}
-
-static int ssl_io_hook_write(BUFF *fb, char *buf, int len)
-{
- SSL *ssl;
- conn_rec *c;
- int rc;
-
- if ((ssl = ap_ctx_get(fb->ctx, "ssl")) != NULL) {
- rc = SSL_write(ssl, buf, len);
- /*
- * Simulate an EINTR in case OpenSSL wants to write more.
- */
- if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_WANT_WRITE)
- errno = EINTR;
- /*
- * Log SSL errors
- */
- if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_SSL) {
- c = (conn_rec *)SSL_get_app_data(ssl);
- ssl_log(c->server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "SSL error on writing data");
- }
- /*
- * write(2) returns only the generic error number -1
- */
- if (rc < 0)
- rc = -1;
- }
- else
- rc = write(fb->fd, buf, len);
- return rc;
-}
-
-#ifndef NO_WRITEV
-/* the prototype for our own SSL_writev() */
-static int SSL_writev(SSL *, const struct iovec *, int);
-
-static int ssl_io_hook_writev(BUFF *fb, const struct iovec *iov, int iovcnt)
-{
- SSL *ssl;
- conn_rec *c;
- int rc;
-
- if ((ssl = ap_ctx_get(fb->ctx, "ssl")) != NULL) {
- rc = SSL_writev(ssl, iov, iovcnt);
- /*
- * Simulate an EINTR in case OpenSSL wants to write more.
- */
- if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_WANT_WRITE)
- errno = EINTR;
- /*
- * Log SSL errors
- */
- if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_SSL) {
- c = (conn_rec *)SSL_get_app_data(ssl);
- ssl_log(c->server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "SSL error on writing data");
- }
- /*
- * writev(2) returns only the generic error number -1
- */
- if (rc < 0)
- rc = -1;
- }
- else
- rc = writev(fb->fd, iov, iovcnt);
- return rc;
-}
-#endif
-
-#ifdef WIN32
-
-/* these two functions are exported from buff.c under WIN32 */
-API_EXPORT(int) sendwithtimeout(int sock, const char *buf, int len, int flags);
-API_EXPORT(int) recvwithtimeout(int sock, char *buf, int len, int flags);
-
-/* and the prototypes for our SSL_xxx variants */
-static int SSL_sendwithtimeout(BUFF *fb, const char *buf, int len);
-static int SSL_recvwithtimeout(BUFF *fb, char *buf, int len);
-
-static int ssl_io_hook_recvwithtimeout(BUFF *fb, char *buf, int len)
-{
- SSL *ssl;
- int rc;
-
- if ((ssl = ap_ctx_get(fb->ctx, "ssl")) != NULL)
- rc = SSL_recvwithtimeout(fb, buf, len);
- else
- rc = recvwithtimeout(fb->fd, buf, len, 0);
- return rc;
-}
-
-static int ssl_io_hook_sendwithtimeout(BUFF *fb, const char *buf, int len)
-{
- SSL *ssl;
- int rc;
-
- if ((ssl = ap_ctx_get(fb->ctx, "ssl")) != NULL)
- rc = SSL_sendwithtimeout(fb, buf, len);
- else
- rc = sendwithtimeout(fb->fd, buf, len, 0);
- return rc;
-}
-
-#endif /* WIN32 */
-
-/* _________________________________________________________________
-**
-** Special Functions for OpenSSL
-** _________________________________________________________________
-*/
-
-#ifdef WIN32
-
-static int SSL_sendwithtimeout(BUFF *fb, const char *buf, int len)
-{
- int iostate = 1;
- fd_set fdset;
- struct timeval tv;
- int err = WSAEWOULDBLOCK;
- int rv;
- int retry;
- int sock = fb->fd;
- SSL *ssl;
-
- ssl = ap_ctx_get(fb->ctx, "ssl");
-
- if (!(tv.tv_sec = ap_check_alarm()))
- return (SSL_write(ssl, (char*)buf, len));
-
- rv = ioctlsocket(sock, FIONBIO, &iostate);
- iostate = 0;
- if (rv) {
- err = WSAGetLastError();
- ap_assert(0);
- }
- rv = SSL_write(ssl, (char*)buf, len);
- if (rv <= 0) {
- if (BIO_sock_should_retry(rv)) {
- do {
- retry = 0;
- FD_ZERO(&fdset);
- FD_SET((unsigned int)sock, &fdset);
- tv.tv_usec = 0;
- rv = select(FD_SETSIZE, NULL, &fdset, NULL, &tv);
- if (rv == SOCKET_ERROR)
- err = WSAGetLastError();
- else if (rv == 0) {
- ioctlsocket(sock, FIONBIO, &iostate);
- if(ap_check_alarm() < 0) {
- WSASetLastError(EINTR); /* Simulate an alarm() */
- return (SOCKET_ERROR);
- }
- }
- else {
- rv = SSL_write(ssl, (char*)buf, len);
- if (BIO_sock_should_retry(rv)) {
- ap_log_error(APLOG_MARK,APLOG_DEBUG, NULL,
- "select claimed we could write, "
- "but in fact we couldn't. "
- "This is a bug in Windows.");
- retry = 1;
- Sleep(100);
- }
- }
- } while(retry);
- }
- }
- ioctlsocket(sock, FIONBIO, &iostate);
- if (rv == SOCKET_ERROR)
- WSASetLastError(err);
- return (rv);
-}
-
-static int SSL_recvwithtimeout(BUFF *fb, char *buf, int len)
-{
- int iostate = 1;
- fd_set fdset;
- struct timeval tv;
- int err = WSAEWOULDBLOCK;
- int rv;
- int sock = fb->fd_in;
- SSL *ssl;
- int retry;
-
- ssl = ap_ctx_get(fb->ctx, "ssl");
-
- if (!(tv.tv_sec = ap_check_alarm()))
- return (SSL_read(ssl, buf, len));
-
- rv = ioctlsocket(sock, FIONBIO, &iostate);
- iostate = 0;
- ap_assert(!rv);
- rv = SSL_read(ssl, buf, len);
- if (rv <= 0) {
- if (BIO_sock_should_retry(rv)) {
- do {
- retry = 0;
- FD_ZERO(&fdset);
- FD_SET((unsigned int)sock, &fdset);
- tv.tv_usec = 0;
- rv = select(FD_SETSIZE, &fdset, NULL, NULL, &tv);
- if (rv == SOCKET_ERROR)
- err = WSAGetLastError();
- else if (rv == 0) {
- ioctlsocket(sock, FIONBIO, &iostate);
- ap_check_alarm();
- WSASetLastError(WSAEWOULDBLOCK);
- return (SOCKET_ERROR);
- }
- else {
- rv = SSL_read(ssl, buf, len);
- if (rv == SOCKET_ERROR) {
- if (BIO_sock_should_retry(rv)) {
- ap_log_error(APLOG_MARK,APLOG_DEBUG, NULL,
- "select claimed we could read, "
- "but in fact we couldn't. "
- "This is a bug in Windows.");
- retry = 1;
- Sleep(100);
- }
- else {
- err = WSAGetLastError();
- }
- }
- }
- } while(retry);
- }
- }
- ioctlsocket(sock, FIONBIO, &iostate);
- if (rv == SOCKET_ERROR)
- WSASetLastError(err);
- return (rv);
-}
-
-#endif /*WIN32*/
-
-/*
- * There is no SSL_writev() provided by OpenSSL. The reason is mainly because
- * OpenSSL has to fragment the data itself again for the SSL record layer, so a
- * writev() like interface makes not much sense. What we do is to emulate it
- * to at least being able to use the write() like interface. But keep in mind
- * that the network I/O performance is not write() like, of course.
- */
-#ifndef NO_WRITEV
-static int SSL_writev(SSL *ssl, const struct iovec *iov, int iovcnt)
-{
- int i;
- int n;
- int rc;
-
- rc = 0;
- for (i = 0; i < iovcnt; i++) {
- if ((n = SSL_write(ssl, iov[i].iov_base, iov[i].iov_len)) == -1) {
- rc = -1;
- break;
- }
- rc += n;
- }
- return rc;
-}
-#endif
-
-/* _________________________________________________________________
-**
-** I/O Data Debugging
-** _________________________________________________________________
-*/
-
-#define DUMP_WIDTH 16
-
-static void ssl_io_data_dump(server_rec *srvr, const char *s, long len)
-{
- char buf[256];
- char tmp[64];
- int i, j, rows, trunc;
- unsigned char ch;
-
- trunc = 0;
- for(; (len > 0) && ((s[len-1] == ' ') || (s[len-1] == '\0')); len--)
- trunc++;
- rows = (len / DUMP_WIDTH);
- if ((rows * DUMP_WIDTH) < len)
- rows++;
- ssl_log(srvr, SSL_LOG_DEBUG|SSL_NO_TIMESTAMP|SSL_NO_LEVELID,
- "+-------------------------------------------------------------------------+");
- for(i = 0 ; i< rows; i++) {
- ap_snprintf(tmp, sizeof(tmp), "| %04x: ", i * DUMP_WIDTH);
- ap_cpystrn(buf, tmp, sizeof(buf));
- for (j = 0; j < DUMP_WIDTH; j++) {
- if (((i * DUMP_WIDTH) + j) >= len)
- ap_cpystrn(buf+strlen(buf), " ", sizeof(buf)-strlen(buf));
- else {
- ch = ((unsigned char)*((char *)(s) + i * DUMP_WIDTH + j)) & 0xff;
- ap_snprintf(tmp, sizeof(tmp), "%02x%c", ch , j==7 ? '-' : ' ');
- ap_cpystrn(buf+strlen(buf), tmp, sizeof(buf)-strlen(buf));
- }
- }
- ap_cpystrn(buf+strlen(buf), " ", sizeof(buf)-strlen(buf));
- for (j = 0; j < DUMP_WIDTH; j++) {
- if (((i * DUMP_WIDTH) + j) >= len)
- ap_cpystrn(buf+strlen(buf), " ", sizeof(buf)-strlen(buf));
- else {
- ch = ((unsigned char)*((char *)(s) + i * DUMP_WIDTH + j)) & 0xff;
- ap_snprintf(tmp, sizeof(tmp), "%c", ((ch >= ' ') && (ch <= '~')) ? ch : '.');
- ap_cpystrn(buf+strlen(buf), tmp, sizeof(buf)-strlen(buf));
- }
- }
- ap_cpystrn(buf+strlen(buf), " |", sizeof(buf)-strlen(buf));
- ssl_log(srvr, SSL_LOG_DEBUG|SSL_NO_TIMESTAMP|SSL_NO_LEVELID, "%s", buf);
- }
- if (trunc > 0)
- ssl_log(srvr, SSL_LOG_DEBUG|SSL_NO_TIMESTAMP|SSL_NO_LEVELID,
- "| %04x - <SPACES/NULS>", len + trunc);
- ssl_log(srvr, SSL_LOG_DEBUG|SSL_NO_TIMESTAMP|SSL_NO_LEVELID,
- "+-------------------------------------------------------------------------+");
- return;
-}
-
-long ssl_io_data_cb(BIO *bio, int cmd, const char *argp, int argi, long argl, long rc)
-{
- SSL *ssl;
- conn_rec *c;
- server_rec *s;
-
- if ((ssl = (SSL *)BIO_get_callback_arg(bio)) == NULL)
- return rc;
- if ((c = (conn_rec *)SSL_get_app_data(ssl)) == NULL)
- return rc;
- s = c->server;
-
- if ( cmd == (BIO_CB_WRITE|BIO_CB_RETURN)
- || cmd == (BIO_CB_READ |BIO_CB_RETURN) ) {
- if (rc >= 0) {
- ssl_log(s, SSL_LOG_DEBUG,
- "%s: %s %ld/%d bytes %s BIO#%08X [mem: %08lX] %s",
- SSL_LIBRARY_NAME,
- (cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "write" : "read"),
- rc, argi, (cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "to" : "from"),
- bio, argp,
- (argp != NULL ? "(BIO dump follows)" : "(Ops, no memory buffer?)"));
- if (argp != NULL)
- ssl_io_data_dump(s, argp, rc);
- }
- else {
- ssl_log(s, SSL_LOG_DEBUG,
- "%s: I/O error, %d bytes expected to %s on BIO#%08X [mem: %08lX]",
- SSL_LIBRARY_NAME, argi,
- (cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "write" : "read"),
- bio, argp);
- }
- }
- return rc;
-}
-
diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
deleted file mode 100644
index ca1b3f0a55..0000000000
--- a/modules/ssl/ssl_engine_kernel.c
+++ /dev/null
@@ -1,1905 +0,0 @@
-/* _ _
-** _ __ ___ ___ __| | ___ ___| | mod_ssl
-** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
-** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
-** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
-** |_____|
-** ssl_engine_kernel.c
-** The SSL engine kernel
-*/
-
-/* ====================================================================
- * Copyright (c) 1998-2001 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * 4. The names "mod_ssl" must not be used to endorse or promote
- * products derived from this software without prior written
- * permission. For written permission, please contact
- * rse@engelschall.com.
- *
- * 5. Products derived from this software may not be called "mod_ssl"
- * nor may "mod_ssl" appear in their names without prior
- * written permission of Ralf S. Engelschall.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
-
-/* ====================================================================
- * Copyright (c) 1995-1999 Ben Laurie. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by Ben Laurie
- * for use in the Apache-SSL HTTP server project."
- *
- * 4. The name "Apache-SSL Server" must not be used to
- * endorse or promote products derived from this software without
- * prior written permission.
- *
- * 5. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by Ben Laurie
- * for use in the Apache-SSL HTTP server project."
- *
- * THIS SOFTWARE IS PROVIDED BY BEN LAURIE ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BEN LAURIE OR
- * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
- /* ``It took me fifteen years to discover
- I had no talent for programming, but
- I couldn't give it up because by that
- time I was too famous.''
- -- Unknown */
-#include "mod_ssl.h"
-
-
-/* _________________________________________________________________
-**
-** SSL Engine Kernel
-** _________________________________________________________________
-*/
-
-/*
- * Connect Handler:
- * Connect SSL to the accepted socket
- *
- * Usually we would need an Apache API hook which is triggered right after
- * the socket is accepted for handling a new request. But Apache 1.3 doesn't
- * provide such a hook, so we have to patch http_main.c and call this
- * function directly.
- */
-void ssl_hook_NewConnection(conn_rec *conn)
-{
- server_rec *srvr;
- BUFF *fb;
- SSLSrvConfigRec *sc;
- ap_ctx *apctx;
- SSL *ssl;
- char *cp;
- char *cpVHostID;
- char *cpVHostMD5;
- X509 *xs;
- int rc;
-
- /*
- * Get context
- */
- srvr = conn->server;
- fb = conn->client;
- sc = mySrvConfig(srvr);
-
- /*
- * Create SSL context
- */
- ap_ctx_set(fb->ctx, "ssl", NULL);
-
- /*
- * Immediately stop processing if SSL
- * is disabled for this connection
- */
- if (sc == NULL || !sc->bEnabled)
- return;
-
- /*
- * Remember the connection information for
- * later access inside callback functions
- */
- cpVHostID = ssl_util_vhostid(conn->pool, srvr);
- ssl_log(srvr, SSL_LOG_INFO, "Connection to child %d established "
- "(server %s, client %s)", conn->child_num, cpVHostID,
- conn->remote_ip != NULL ? conn->remote_ip : "unknown");
-
- /*
- * Seed the Pseudo Random Number Generator (PRNG)
- */
- ssl_rand_seed(srvr, conn->pool, SSL_RSCTX_CONNECT, "");
-
- /*
- * Create a new SSL connection with the configured server SSL context and
- * attach this to the socket. Additionally we register this attachment
- * so we can detach later.
- */
- if ((ssl = SSL_new(sc->pSSLCtx)) == NULL) {
- ssl_log(conn->server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "Unable to create a new SSL connection from the SSL context");
- ap_ctx_set(fb->ctx, "ssl", NULL);
- ap_bsetflag(fb, B_EOF|B_EOUT, 1);
- conn->aborted = 1;
- return;
- }
- SSL_clear(ssl);
- cpVHostMD5 = ap_md5(conn->pool, (unsigned char *)cpVHostID);
- if (!SSL_set_session_id_context(ssl, (unsigned char *)cpVHostMD5, strlen(cpVHostMD5))) {
- ssl_log(conn->server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "Unable to set session id context to `%s'", cpVHostMD5);
- ap_ctx_set(fb->ctx, "ssl", NULL);
- ap_bsetflag(fb, B_EOF|B_EOUT, 1);
- conn->aborted = 1;
- return;
- }
- SSL_set_app_data(ssl, conn);
- apctx = ap_ctx_new(conn->pool);
- ap_ctx_set(apctx, "ssl::request_rec", NULL);
- ap_ctx_set(apctx, "ssl::verify::depth", AP_CTX_NUM2PTR(0));
- SSL_set_app_data2(ssl, apctx);
- SSL_set_fd(ssl, fb->fd);
- ap_ctx_set(fb->ctx, "ssl", ssl);
-
- /*
- * Configure callbacks for SSL connection
- */
- SSL_set_tmp_rsa_callback(ssl, ssl_callback_TmpRSA);
- SSL_set_tmp_dh_callback(ssl, ssl_callback_TmpDH);
- if (sc->nLogLevel >= SSL_LOG_DEBUG) {
- BIO_set_callback(SSL_get_rbio(ssl), ssl_io_data_cb);
- BIO_set_callback_arg(SSL_get_rbio(ssl), ssl);
- }
-
- /*
- * Predefine some client verification results
- */
- ap_ctx_set(fb->ctx, "ssl::client::dn", NULL);
- ap_ctx_set(fb->ctx, "ssl::verify::error", NULL);
- ap_ctx_set(fb->ctx, "ssl::verify::info", NULL);
- SSL_set_verify_result(ssl, X509_V_OK);
-
- /*
- * We have to manage a I/O timeout ourself, because Apache
- * does it the first time when reading the request, but we're
- * working some time before this happens.
- */
- ap_ctx_set(ap_global_ctx, "ssl::handshake::timeout", (void *)FALSE);
- ap_set_callback_and_alarm(ssl_hook_TimeoutConnection, srvr->timeout);
-
- /*
- * Now enter the SSL Handshake Phase
- */
- while (!SSL_is_init_finished(ssl)) {
-
- if ((rc = SSL_accept(ssl)) <= 0) {
-
- if (SSL_get_error(ssl, rc) == SSL_ERROR_ZERO_RETURN) {
- /*
- * The case where the connection was closed before any data
- * was transferred. That's not a real error and can occur
- * sporadically with some clients.
- */
- ssl_log(srvr, SSL_LOG_INFO,
- "SSL handshake stopped: connection was closed");
- SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
- SSL_smart_shutdown(ssl);
- SSL_free(ssl);
- ap_ctx_set(fb->ctx, "ssl", NULL);
- ap_bsetflag(fb, B_EOF|B_EOUT, 1);
- conn->aborted = 1;
- return;
- }
- else if (ERR_GET_REASON(ERR_peek_error()) == SSL_R_HTTP_REQUEST) {
- /*
- * The case where OpenSSL has recognized a HTTP request:
- * This means the client speaks plain HTTP on our HTTPS
- * port. Hmmmm... At least for this error we can be more friendly
- * and try to provide him with a HTML error page. We have only one
- * problem: OpenSSL has already read some bytes from the HTTP
- * request. So we have to skip the request line manually and
- * instead provide a faked one in order to continue the internal
- * Apache processing.
- *
- */
- char ca[2];
- int rv;
-
- /* log the situation */
- ssl_log(srvr, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "SSL handshake failed: HTTP spoken on HTTPS port; "
- "trying to send HTML error page");
-
- /* first: skip the remaining bytes of the request line */
- do {
- do {
- rv = read(fb->fd, ca, 1);
- } while (rv == -1 && errno == EINTR);
- } while (rv > 0 && ca[0] != '\012' /*LF*/);
-
- /* second: fake the request line */
- fb->inbase = ap_palloc(fb->pool, fb->bufsiz);
- ap_cpystrn((char *)fb->inbase, "GET /mod_ssl:error:HTTP-request HTTP/1.0\r\n",
- fb->bufsiz);
- fb->inptr = fb->inbase;
- fb->incnt = strlen((char *)fb->inptr);
-
- /* third: kick away the SSL stuff */
- SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
- SSL_smart_shutdown(ssl);
- SSL_free(ssl);
- ap_ctx_set(fb->ctx, "ssl", NULL);
-
- /* finally: let Apache go on with processing */
- return;
- }
- else if (ap_ctx_get(ap_global_ctx, "ssl::handshake::timeout") == (void *)TRUE) {
- ssl_log(srvr, SSL_LOG_ERROR,
- "SSL handshake timed out (client %s, server %s)",
- conn->remote_ip != NULL ? conn->remote_ip : "unknown", cpVHostID);
- SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
- SSL_smart_shutdown(ssl);
- SSL_free(ssl);
- ap_ctx_set(fb->ctx, "ssl", NULL);
- ap_bsetflag(fb, B_EOF|B_EOUT, 1);
- conn->aborted = 1;
- return;
- }
- else if (SSL_get_error(ssl, rc) == SSL_ERROR_SYSCALL) {
- if (errno == EINTR)
- continue;
- if (errno > 0)
- ssl_log(srvr, SSL_LOG_ERROR|SSL_ADD_SSLERR|SSL_ADD_ERRNO,
- "SSL handshake interrupted by system "
- "[Hint: Stop button pressed in browser?!]");
- else
- ssl_log(srvr, SSL_LOG_INFO|SSL_ADD_SSLERR|SSL_ADD_ERRNO,
- "Spurious SSL handshake interrupt"
- "[Hint: Usually just one of those OpenSSL confusions!?]");
- SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
- SSL_smart_shutdown(ssl);
- SSL_free(ssl);
- ap_ctx_set(fb->ctx, "ssl", NULL);
- ap_bsetflag(fb, B_EOF|B_EOUT, 1);
- conn->aborted = 1;
- return;
- }
- else {
- /*
- * Ok, anything else is a fatal error
- */
- ssl_log(srvr, SSL_LOG_ERROR|SSL_ADD_SSLERR|SSL_ADD_ERRNO,
- "SSL handshake failed (server %s, client %s)", cpVHostID,
- conn->remote_ip != NULL ? conn->remote_ip : "unknown");
-
- /*
- * try to gracefully shutdown the connection:
- * - send an own shutdown message (be gracefully)
- * - don't wait for peer's shutdown message (deadloop)
- * - kick away the SSL stuff immediately
- * - block the socket, so Apache cannot operate any more
- */
- SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
- SSL_smart_shutdown(ssl);
- SSL_free(ssl);
- ap_ctx_set(fb->ctx, "ssl", NULL);
- ap_bsetflag(fb, B_EOF|B_EOUT, 1);
- conn->aborted = 1;
- return;
- }
- }
-
- /*
- * Check for failed client authentication
- */
- if ( SSL_get_verify_result(ssl) != X509_V_OK
- || ap_ctx_get(fb->ctx, "ssl::verify::error") != NULL) {
- cp = (char *)ap_ctx_get(fb->ctx, "ssl::verify::error");
- ssl_log(srvr, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "SSL client authentication failed: %s",
- cp != NULL ? cp : "unknown reason");
- SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
- SSL_smart_shutdown(ssl);
- SSL_free(ssl);
- ap_ctx_set(fb->ctx, "ssl", NULL);
- ap_bsetflag(fb, B_EOF|B_EOUT, 1);
- conn->aborted = 1;
- return;
- }
-
- /*
- * Remember the peer certificate's DN
- */
- if ((xs = SSL_get_peer_certificate(ssl)) != NULL) {
- cp = X509_NAME_oneline(X509_get_subject_name(xs), NULL, 0);
- ap_ctx_set(fb->ctx, "ssl::client::dn", ap_pstrdup(conn->pool, cp));
- free(cp);
- }
-
- /*
- * Make really sure that when a peer certificate
- * is required we really got one... (be paranoid)
- */
- if ( sc->nVerifyClient == SSL_CVERIFY_REQUIRE
- && ap_ctx_get(fb->ctx, "ssl::client::dn") == NULL) {
- ssl_log(srvr, SSL_LOG_ERROR,
- "No acceptable peer certificate available");
- SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
- SSL_smart_shutdown(ssl);
- SSL_free(ssl);
- ap_ctx_set(fb->ctx, "ssl", NULL);
- ap_bsetflag(fb, B_EOF|B_EOUT, 1);
- conn->aborted = 1;
- return;
- }
- }
-
- /*
- * Remove the timeout handling
- */
- ap_set_callback_and_alarm(NULL, 0);
- ap_ctx_set(ap_global_ctx, "ssl::handshake::timeout", (void *)FALSE);
-
- /*
- * Improve I/O throughput by using
- * OpenSSL's read-ahead functionality
- * (don't used under Win32, because
- * there we use select())
- */
-#ifndef WIN32
- SSL_set_read_ahead(ssl, TRUE);
-#endif
-
-#ifdef SSL_VENDOR
- /* Allow vendors to do more things on connection time... */
- ap_hook_use("ap::mod_ssl::vendor::new_connection",
- AP_HOOK_SIG2(void,ptr), AP_HOOK_ALL, conn);
-#endif
-
- return;
-}
-
-/*
- * Signal handler function for the SSL handshake phase
- */
-void ssl_hook_TimeoutConnection(int sig)
-{
- /* we just set a flag for the handshake processing loop */
- ap_ctx_set(ap_global_ctx, "ssl::handshake::timeout", (void *)TRUE);
- return;
-}
-
-/*
- * Close the SSL part of the socket connection
- * (called immediately _before_ the socket is closed)
- */
-void ssl_hook_CloseConnection(conn_rec *conn)
-{
- SSL *ssl;
- char *cpType;
-
- ssl = ap_ctx_get(conn->client->ctx, "ssl");
- if (ssl == NULL)
- return;
-
- /*
- * First make sure that no more data is pending in Apache's BUFF,
- * because when it's (implicitly) flushed later by the ap_bclose()
- * calls of Apache it would lead to an I/O error in the browser due
- * to the fact that the SSL layer was already removed by us.
- */
- ap_bflush(conn->client);
-
- /*
- * Now close the SSL layer of the connection. We've to take
- * the TLSv1 standard into account here:
- *
- * | 7.2.1. Closure alerts
- * |
- * | The client and the server must share knowledge that the connection is
- * | ending in order to avoid a truncation attack. Either party may
- * | initiate the exchange of closing messages.
- * |
- * | close_notify
- * | This message notifies the recipient that the sender will not send
- * | any more messages on this connection. The session becomes
- * | unresumable if any connection is terminated without proper
- * | close_notify messages with level equal to warning.
- * |
- * | Either party may initiate a close by sending a close_notify alert.
- * | Any data received after a closure alert is ignored.
- * |
- * | Each party is required to send a close_notify alert before closing
- * | the write side of the connection. It is required that the other party
- * | respond with a close_notify alert of its own and close down the
- * | connection immediately, discarding any pending writes. It is not
- * | required for the initiator of the close to wait for the responding
- * | close_notify alert before closing the read side of the connection.
- *
- * This means we've to send a close notify message, but haven't to wait
- * for the close notify of the client. Actually we cannot wait for the
- * close notify of the client because some clients (including Netscape
- * 4.x) don't send one, so we would hang.
- */
-
- /*
- * exchange close notify messages, but allow the user
- * to force the type of handshake via SetEnvIf directive
- */
- if (ap_ctx_get(conn->client->ctx, "ssl::flag::unclean-shutdown") == PTRUE) {
- /* perform no close notify handshake at all
- (violates the SSL/TLS standard!) */
- SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
- cpType = "unclean";
- }
- else if (ap_ctx_get(conn->client->ctx, "ssl::flag::accurate-shutdown") == PTRUE) {
- /* send close notify and wait for clients close notify
- (standard compliant, but usually causes connection hangs) */
- SSL_set_shutdown(ssl, 0);
- cpType = "accurate";
- }
- else {
- /* send close notify, but don't wait for clients close notify
- (standard compliant and safe, so it's the DEFAULT!) */
- SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
- cpType = "standard";
- }
- SSL_smart_shutdown(ssl);
-
- /* deallocate the SSL connection */
- SSL_free(ssl);
- ap_ctx_set(conn->client->ctx, "ssl", NULL);
-
- /* and finally log the fact that we've closed the connection */
- ssl_log(conn->server, SSL_LOG_INFO,
- "Connection to child %d closed with %s shutdown (server %s, client %s)",
- conn->child_num, cpType, ssl_util_vhostid(conn->pool, conn->server),
- conn->remote_ip != NULL ? conn->remote_ip : "unknown");
- return;
-}
-
-/*
- * Post Read Request Handler
- */
-int ssl_hook_ReadReq(request_rec *r)
-{
- SSL *ssl;
- ap_ctx *apctx;
-
- /*
- * Get the SSL connection structure and perform the
- * delayed interlinking from SSL back to request_rec
- */
- ssl = ap_ctx_get(r->connection->client->ctx, "ssl");
- if (ssl != NULL) {
- apctx = SSL_get_app_data2(ssl);
- ap_ctx_set(apctx, "ssl::request_rec", r);
- }
-
- /*
- * Force the mod_ssl content handler when URL indicates this
- */
- if (strEQn(r->uri, "/mod_ssl:", 9))
- r->handler = "mod_ssl:content-handler";
- if (ssl != NULL) {
- ap_ctx_set(r->ctx, "ap::http::method", "https");
- ap_ctx_set(r->ctx, "ap::default::port", "443");
- }
- else {
- ap_ctx_set(r->ctx, "ap::http::method", NULL);
- ap_ctx_set(r->ctx, "ap::default::port", NULL);
- }
- return DECLINED;
-}
-
-/*
- * URL Translation Handler
- */
-int ssl_hook_Translate(request_rec *r)
-{
- if (ap_ctx_get(r->connection->client->ctx, "ssl") == NULL)
- return DECLINED;
-
- /*
- * Log information about incoming HTTPS requests
- */
- if (ap_is_initial_req(r))
- ssl_log(r->server, SSL_LOG_INFO,
- "%s HTTPS request received for child %d (server %s)",
- r->connection->keepalives <= 0 ?
- "Initial (No.1)" :
- ap_psprintf(r->pool, "Subsequent (No.%d)",
- r->connection->keepalives+1),
- r->connection->child_num,
- ssl_util_vhostid(r->pool, r->server));
-
- /*
- * Move SetEnvIf information from request_rec to conn_rec/BUFF
- * to allow the close connection handler to use them.
- */
- if (ap_table_get(r->subprocess_env, "ssl-unclean-shutdown") != NULL)
- ap_ctx_set(r->connection->client->ctx, "ssl::flag::unclean-shutdown", PTRUE);
- else
- ap_ctx_set(r->connection->client->ctx, "ssl::flag::unclean-shutdown", PFALSE);
- if (ap_table_get(r->subprocess_env, "ssl-accurate-shutdown") != NULL)
- ap_ctx_set(r->connection->client->ctx, "ssl::flag::accurate-shutdown", PTRUE);
- else
- ap_ctx_set(r->connection->client->ctx, "ssl::flag::accurate-shutdown", PFALSE);
-
- return DECLINED;
-}
-
-/*
- * Content Handler
- */
-int ssl_hook_Handler(request_rec *r)
-{
- int port;
- char *thisport;
- char *thisurl;
-
- if (strNEn(r->uri, "/mod_ssl:", 9))
- return DECLINED;
-
- if (strEQ(r->uri, "/mod_ssl:error:HTTP-request")) {
- thisport = "";
- port = ap_get_server_port(r);
- if (!ap_is_default_port(port, r))
- thisport = ap_psprintf(r->pool, ":%u", port);
- thisurl = ap_psprintf(r->pool, "https://%s%s/",
- ap_get_server_name(r), thisport);
-
- ap_table_setn(r->notes, "error-notes", ap_psprintf(r->pool,
- "Reason: You're speaking plain HTTP to an SSL-enabled server port.<BR>\n"
- "Instead use the HTTPS scheme to access this URL, please.<BR>\n"
- "<BLOCKQUOTE>Hint: <A HREF=\"%s\"><B>%s</B></A></BLOCKQUOTE>",
- thisurl, thisurl));
- }
-
- return HTTP_BAD_REQUEST;
-}
-
-/*
- * Access Handler
- */
-int ssl_hook_Access(request_rec *r)
-{
- SSLDirConfigRec *dc;
- SSLSrvConfigRec *sc;
- SSL *ssl;
- SSL_CTX *ctx = NULL;
- array_header *apRequirement;
- ssl_require_t *pRequirements;
- ssl_require_t *pRequirement;
- char *cp;
- int ok;
- int i;
- BOOL renegotiate;
- BOOL renegotiate_quick;
-#ifdef SSL_EXPERIMENTAL_PERDIRCA
- BOOL reconfigured_locations;
- STACK_OF(X509_NAME) *skCAList;
- char *cpCAPath;
- char *cpCAFile;
-#endif
- X509 *cert;
- STACK_OF(X509) *certstack;
- X509_STORE *certstore;
- X509_STORE_CTX certstorectx;
- int depth;
- STACK_OF(SSL_CIPHER) *skCipherOld;
- STACK_OF(SSL_CIPHER) *skCipher;
- SSL_CIPHER *pCipher;
- ap_ctx *apctx;
- int nVerifyOld;
- int nVerify;
- int n;
- void *vp;
- int rc;
-
- dc = myDirConfig(r);
- sc = mySrvConfig(r->server);
- ssl = ap_ctx_get(r->connection->client->ctx, "ssl");
- if (ssl != NULL)
- ctx = SSL_get_SSL_CTX(ssl);
-
- /*
- * Support for SSLRequireSSL directive
- */
- if (dc->bSSLRequired && ssl == NULL) {
- ap_log_reason("SSL connection required", r->filename, r);
- /* remember forbidden access for strict require option */
- ap_table_setn(r->notes, "ssl-access-forbidden", (void *)1);
- return FORBIDDEN;
- }
-
- /*
- * Check to see if SSL protocol is on
- */
- if (!sc->bEnabled)
- return DECLINED;
- if (ssl == NULL)
- return DECLINED;
-
- /*
- * Support for per-directory reconfigured SSL connection parameters.
- *
- * This is implemented by forcing an SSL renegotiation with the
- * reconfigured parameter suite. But Apache's internal API processing
- * makes our life very hard here, because when internal sub-requests occur
- * we nevertheless should avoid multiple unnecessary SSL handshakes (they
- * require extra network I/O and especially time to perform).
- *
- * But the optimization for filtering out the unnecessary handshakes isn't
- * obvious and trivial. Especially because while Apache is in its
- * sub-request processing the client could force additional handshakes,
- * too. And these take place perhaps without our notice. So the only
- * possibility is to explicitly _ask_ OpenSSL whether the renegotiation
- * has to be performed or not. It has to performed when some parameters
- * which were previously known (by us) are not those we've now
- * reconfigured (as known by OpenSSL) or (in optimized way) at least when
- * the reconfigured parameter suite is stronger (more restrictions) than
- * the currently active one.
- */
- renegotiate = FALSE;
- renegotiate_quick = FALSE;
-#ifdef SSL_EXPERIMENTAL_PERDIRCA
- reconfigured_locations = FALSE;
-#endif
-
- /*
- * Override of SSLCipherSuite
- *
- * We provide two options here:
- *
- * o The paranoid and default approach where we force a renegotiation when
- * the cipher suite changed in _any_ way (which is straight-forward but
- * often forces renegotiations too often and is perhaps not what the
- * user actually wanted).
- *
- * o The optimized and still secure way where we force a renegotiation
- * only if the currently active cipher is no longer contained in the
- * reconfigured/new cipher suite. Any other changes are not important
- * because it's the servers choice to select a cipher from the ones the
- * client supports. So as long as the current cipher is still in the new
- * cipher suite we're happy. Because we can assume we would have
- * selected it again even when other (better) ciphers exists now in the
- * new cipher suite. This approach is fine because the user explicitly
- * has to enable this via ``SSLOptions +OptRenegotiate''. So we do no
- * implicit optimizations.
- */
- if (dc->szCipherSuite != NULL) {
- /* remember old state */
- pCipher = NULL;
- skCipherOld = NULL;
- if (dc->nOptions & SSL_OPT_OPTRENEGOTIATE)
- pCipher = SSL_get_current_cipher(ssl);
- else {
- skCipherOld = SSL_get_ciphers(ssl);
- if (skCipherOld != NULL)
- skCipherOld = sk_SSL_CIPHER_dup(skCipherOld);
- }
- /* configure new state */
- if (!SSL_set_cipher_list(ssl, dc->szCipherSuite)) {
- ssl_log(r->server, SSL_LOG_WARN|SSL_ADD_SSLERR,
- "Unable to reconfigure (per-directory) permitted SSL ciphers");
- if (skCipherOld != NULL)
- sk_SSL_CIPHER_free(skCipherOld);
- return FORBIDDEN;
- }
- /* determine whether a renegotiation has to be forced */
- skCipher = SSL_get_ciphers(ssl);
- if (dc->nOptions & SSL_OPT_OPTRENEGOTIATE) {
- /* optimized way */
- if ((pCipher == NULL && skCipher != NULL) ||
- (pCipher != NULL && skCipher == NULL) )
- renegotiate = TRUE;
- else if (pCipher != NULL && skCipher != NULL
- && sk_SSL_CIPHER_find(skCipher, pCipher) < 0) {
- renegotiate = TRUE;
- }
- }
- else {
- /* paranoid way */
- if ((skCipherOld == NULL && skCipher != NULL) ||
- (skCipherOld != NULL && skCipher == NULL) )
- renegotiate = TRUE;
- else if (skCipherOld != NULL && skCipher != NULL) {
- for (n = 0; !renegotiate && n < sk_SSL_CIPHER_num(skCipher); n++) {
- if (sk_SSL_CIPHER_find(skCipherOld, sk_SSL_CIPHER_value(skCipher, n)) < 0)
- renegotiate = TRUE;
- }
- for (n = 0; !renegotiate && n < sk_SSL_CIPHER_num(skCipherOld); n++) {
- if (sk_SSL_CIPHER_find(skCipher, sk_SSL_CIPHER_value(skCipherOld, n)) < 0)
- renegotiate = TRUE;
- }
- }
- }
- /* cleanup */
- if (skCipherOld != NULL)
- sk_SSL_CIPHER_free(skCipherOld);
- /* tracing */
- if (renegotiate)
- ssl_log(r->server, SSL_LOG_TRACE,
- "Reconfigured cipher suite will force renegotiation");
- }
-
- /*
- * override of SSLVerifyDepth
- *
- * The depth checks are handled by us manually inside the verify callback
- * function and not by OpenSSL internally (and our function is aware of
- * both the per-server and per-directory contexts). So we cannot ask
- * OpenSSL about the currently verify depth. Instead we remember it in our
- * ap_ctx attached to the SSL* of OpenSSL. We've to force the
- * renegotiation if the reconfigured/new verify depth is less than the
- * currently active/remembered verify depth (because this means more
- * restriction on the certificate chain).
- */
- if (dc->nVerifyDepth != UNSET) {
- apctx = SSL_get_app_data2(ssl);
- if ((vp = ap_ctx_get(apctx, "ssl::verify::depth")) != NULL)
- n = (int)AP_CTX_PTR2NUM(vp);
- else
- n = sc->nVerifyDepth;
- ap_ctx_set(apctx, "ssl::verify::depth",
- AP_CTX_NUM2PTR(dc->nVerifyDepth));
- /* determine whether a renegotiation has to be forced */
- if (dc->nVerifyDepth < n) {
- renegotiate = TRUE;
- ssl_log(r->server, SSL_LOG_TRACE,
- "Reduced client verification depth will force renegotiation");
- }
- }
-
- /*
- * override of SSLVerifyClient
- *
- * We force a renegotiation if the reconfigured/new verify type is
- * stronger than the currently active verify type.
- *
- * The order is: none << optional_no_ca << optional << require
- *
- * Additionally the following optimization is possible here: When the
- * currently active verify type is "none" but a client certificate is
- * already known/present, it's enough to manually force a client
- * verification but at least skip the I/O-intensive renegotation
- * handshake.
- */
- if (dc->nVerifyClient != SSL_CVERIFY_UNSET) {
- /* remember old state */
- nVerifyOld = SSL_get_verify_mode(ssl);
- /* configure new state */
- nVerify = SSL_VERIFY_NONE;
- if (dc->nVerifyClient == SSL_CVERIFY_REQUIRE)
- nVerify |= SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
- if ( (dc->nVerifyClient == SSL_CVERIFY_OPTIONAL)
- || (dc->nVerifyClient == SSL_CVERIFY_OPTIONAL_NO_CA) )
- nVerify |= SSL_VERIFY_PEER;
- SSL_set_verify(ssl, nVerify, ssl_callback_SSLVerify);
- SSL_set_verify_result(ssl, X509_V_OK);
- /* determine whether we've to force a renegotiation */
- if (nVerify != nVerifyOld) {
- if ( ( (nVerifyOld == SSL_VERIFY_NONE)
- && (nVerify != SSL_VERIFY_NONE))
- || ( !(nVerifyOld & SSL_VERIFY_PEER)
- && (nVerify & SSL_VERIFY_PEER))
- || ( !(nVerifyOld & (SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT))
- && (nVerify & (SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT)))) {
- renegotiate = TRUE;
- /* optimization */
- if ( dc->nOptions & SSL_OPT_OPTRENEGOTIATE
- && nVerifyOld == SSL_VERIFY_NONE
- && SSL_get_peer_certificate(ssl) != NULL)
- renegotiate_quick = TRUE;
- ssl_log(r->server, SSL_LOG_TRACE,
- "Changed client verification type will force %srenegotiation",
- renegotiate_quick ? "quick " : "");
- }
- }
- }
-
- /*
- * override SSLCACertificateFile & SSLCACertificatePath
- * This is tagged experimental because it has to use an ugly kludge: We
- * have to change the locations inside the SSL_CTX* (per-server global)
- * instead inside SSL* (per-connection local) and reconfigure it to the
- * old values later. That's problematic at least for the threaded process
- * model of Apache under Win32 or when an error occurs. But unless
- * OpenSSL provides a SSL_load_verify_locations() function we've no other
- * chance to provide this functionality...
- */
-#ifdef SSL_EXPERIMENTAL_PERDIRCA
- if ( ( dc->szCACertificateFile != NULL
- && ( sc->szCACertificateFile == NULL
- || ( sc->szCACertificateFile != NULL
- && strNE(dc->szCACertificateFile, sc->szCACertificateFile))))
- || ( dc->szCACertificatePath != NULL
- && ( sc->szCACertificatePath == NULL
- || ( sc->szCACertificatePath != NULL
- && strNE(dc->szCACertificatePath, sc->szCACertificatePath)))) ) {
- cpCAFile = dc->szCACertificateFile != NULL ?
- dc->szCACertificateFile : sc->szCACertificateFile;
- cpCAPath = dc->szCACertificatePath != NULL ?
- dc->szCACertificatePath : sc->szCACertificatePath;
- /*
- FIXME: This should be...
- if (!SSL_load_verify_locations(ssl, cpCAFile, cpCAPath)) {
- ...but OpenSSL still doesn't provide this!
- */
- if (!SSL_CTX_load_verify_locations(ctx, cpCAFile, cpCAPath)) {
- ssl_log(r->server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "Unable to reconfigure verify locations "
- "for client authentication");
- return FORBIDDEN;
- }
- if ((skCAList = ssl_init_FindCAList(r->server, r->pool,
- cpCAFile, cpCAPath)) == NULL) {
- ssl_log(r->server, SSL_LOG_ERROR,
- "Unable to determine list of available "
- "CA certificates for client authentication");
- return FORBIDDEN;
- }
- SSL_set_client_CA_list(ssl, skCAList);
- renegotiate = TRUE;
- reconfigured_locations = TRUE;
- ssl_log(r->server, SSL_LOG_TRACE,
- "Changed client verification locations will force renegotiation");
- }
-#endif /* SSL_EXPERIMENTAL_PERDIRCA */
-
-#ifdef SSL_CONSERVATIVE
- /*
- * SSL renegotiations in conjunction with HTTP
- * requests using the POST method are not supported.
- */
- if (renegotiate && r->method_number == M_POST) {
- ssl_log(r->server, SSL_LOG_ERROR,
- "SSL Re-negotiation in conjunction with POST method not supported!");
- ssl_log(r->server, SSL_LOG_INFO,
- "You have to compile without -DSSL_CONSERVATIVE to enabled support for this.");
- return METHOD_NOT_ALLOWED;
- }
-#endif /* SSL_CONSERVATIVE */
-
- /*
- * now do the renegotiation if anything was actually reconfigured
- */
- if (renegotiate) {
- /*
- * Now we force the SSL renegotation by sending the Hello Request
- * message to the client. Here we have to do a workaround: Actually
- * OpenSSL returns immediately after sending the Hello Request (the
- * intent AFAIK is because the SSL/TLS protocol says it's not a must
- * that the client replies to a Hello Request). But because we insist
- * on a reply (anything else is an error for us) we have to go to the
- * ACCEPT state manually. Using SSL_set_accept_state() doesn't work
- * here because it resets too much of the connection. So we set the
- * state explicitly and continue the handshake manually.
- */
- ssl_log(r->server, SSL_LOG_INFO, "Requesting connection re-negotiation");
- if (renegotiate_quick) {
- /* perform just a manual re-verification of the peer */
- ssl_log(r->server, SSL_LOG_TRACE,
- "Performing quick renegotiation: just re-verifying the peer");
- certstore = SSL_CTX_get_cert_store(ctx);
- if (certstore == NULL) {
- ssl_log(r->server, SSL_LOG_ERROR, "Cannot find certificate storage");
- return FORBIDDEN;
- }
- certstack = SSL_get_peer_cert_chain(ssl);
- if (certstack == NULL || sk_X509_num(certstack) == 0) {
- ssl_log(r->server, SSL_LOG_ERROR, "Cannot find peer certificate chain");
- return FORBIDDEN;
- }
- cert = sk_X509_value(certstack, 0);
- X509_STORE_CTX_init(&certstorectx, certstore, cert, certstack);
- depth = SSL_get_verify_depth(ssl);
- if (depth >= 0)
- X509_STORE_CTX_set_depth(&certstorectx, depth);
- X509_STORE_CTX_set_ex_data(&certstorectx,
- SSL_get_ex_data_X509_STORE_CTX_idx(), (char *)ssl);
- if (!X509_verify_cert(&certstorectx))
- ssl_log(r->server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "Re-negotiation verification step failed");
- SSL_set_verify_result(ssl, certstorectx.error);
- X509_STORE_CTX_cleanup(&certstorectx);
- }
- else {
- /* do a full renegotiation */
- ssl_log(r->server, SSL_LOG_TRACE,
- "Performing full renegotiation: complete handshake protocol");
- if (r->main != NULL)
- SSL_set_session_id_context(ssl, (unsigned char *)&(r->main), sizeof(r->main));
- else
- SSL_set_session_id_context(ssl, (unsigned char *)&r, sizeof(r));
-#ifndef SSL_CONSERVATIVE
- ssl_io_suck(r, ssl);
-#endif
- SSL_renegotiate(ssl);
- SSL_do_handshake(ssl);
- if (SSL_get_state(ssl) != SSL_ST_OK) {
- ssl_log(r->server, SSL_LOG_ERROR, "Re-negotiation request failed");
- return FORBIDDEN;
- }
- ssl_log(r->server, SSL_LOG_INFO, "Awaiting re-negotiation handshake");
- SSL_set_state(ssl, SSL_ST_ACCEPT);
- SSL_do_handshake(ssl);
- if (SSL_get_state(ssl) != SSL_ST_OK) {
- ssl_log(r->server, SSL_LOG_ERROR,
- "Re-negotiation handshake failed: Not accepted by client!?");
- return FORBIDDEN;
- }
- }
-
- /*
- * Remember the peer certificate's DN
- */
- if ((cert = SSL_get_peer_certificate(ssl)) != NULL) {
- cp = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
- ap_ctx_set(r->connection->client->ctx, "ssl::client::dn",
- ap_pstrdup(r->connection->pool, cp));
- free(cp);
- }
-
- /*
- * Finally check for acceptable renegotiation results
- */
- if (dc->nVerifyClient != SSL_CVERIFY_NONE) {
- if ( dc->nVerifyClient == SSL_CVERIFY_REQUIRE
- && SSL_get_verify_result(ssl) != X509_V_OK ) {
- ssl_log(r->server, SSL_LOG_ERROR,
- "Re-negotiation handshake failed: Client verification failed");
- return FORBIDDEN;
- }
- if ( dc->nVerifyClient == SSL_CVERIFY_REQUIRE
- && SSL_get_peer_certificate(ssl) == NULL ) {
- ssl_log(r->server, SSL_LOG_ERROR,
- "Re-negotiation handshake failed: Client certificate missing");
- return FORBIDDEN;
- }
- }
- }
-
- /*
- * Under old OpenSSL we had to change the X509_STORE inside the
- * SSL_CTX instead inside the SSL structure, so we have to reconfigure it
- * to the old values. This should be changed with forthcoming OpenSSL
- * versions when better functionality is avaiable.
- */
-#ifdef SSL_EXPERIMENTAL_PERDIRCA
- if (renegotiate && reconfigured_locations) {
- if (!SSL_CTX_load_verify_locations(ctx,
- sc->szCACertificateFile, sc->szCACertificatePath)) {
- ssl_log(r->server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "Unable to reconfigure verify locations "
- "to per-server configuration parameters");
- return FORBIDDEN;
- }
- }
-#endif /* SSL_EXPERIMENTAL_PERDIRCA */
-
- /*
- * Check SSLRequire boolean expressions
- */
- apRequirement = dc->aRequirement;
- pRequirements = (ssl_require_t *)apRequirement->elts;
- for (i = 0; i < apRequirement->nelts; i++) {
- pRequirement = &pRequirements[i];
- ok = ssl_expr_exec(r, pRequirement->mpExpr);
- if (ok < 0) {
- cp = ap_psprintf(r->pool, "Failed to execute SSL requirement expression: %s",
- ssl_expr_get_error());
- ap_log_reason(cp, r->filename, r);
- /* remember forbidden access for strict require option */
- ap_table_setn(r->notes, "ssl-access-forbidden", (void *)1);
- return FORBIDDEN;
- }
- if (ok != 1) {
- ssl_log(r->server, SSL_LOG_INFO,
- "Access to %s denied for %s (requirement expression not fulfilled)",
- r->filename, r->connection->remote_ip);
- ssl_log(r->server, SSL_LOG_INFO,
- "Failed expression: %s", pRequirement->cpExpr);
- ap_log_reason("SSL requirement expression not fulfilled "
- "(see SSL logfile for more details)", r->filename, r);
- /* remember forbidden access for strict require option */
- ap_table_setn(r->notes, "ssl-access-forbidden", (void *)1);
- return FORBIDDEN;
- }
- }
-
- /*
- * Else access is granted from our point of view (except vendor
- * handlers override). But we have to return DECLINED here instead
- * of OK, because mod_auth and other modules still might want to
- * deny access.
- */
- rc = DECLINED;
-#ifdef SSL_VENDOR
- ap_hook_use("ap::mod_ssl::vendor::access_handler",
- AP_HOOK_SIG2(int,ptr), AP_HOOK_DECLINE(DECLINED),
- &rc, r);
-#endif
- return rc;
-}
-
-/*
- * Auth Handler:
- * Fake a Basic authentication from the X509 client certificate.
- *
- * This must be run fairly early on to prevent a real authentication from
- * occuring, in particular it must be run before anything else that
- * authenticates a user. This means that the Module statement for this
- * module should be LAST in the Configuration file.
- */
-int ssl_hook_Auth(request_rec *r)
-{
- SSLSrvConfigRec *sc = mySrvConfig(r->server);
- SSLDirConfigRec *dc = myDirConfig(r);
- char b1[MAX_STRING_LEN], b2[MAX_STRING_LEN];
- char *clientdn;
- const char *cpAL;
- const char *cpUN;
- const char *cpPW;
-
- /*
- * Additionally forbid access (again)
- * when strict require option is used.
- */
- if ( (dc->nOptions & SSL_OPT_STRICTREQUIRE)
- && (ap_table_get(r->notes, "ssl-access-forbidden") != NULL))
- return FORBIDDEN;
-
- /*
- * Make sure the user is not able to fake the client certificate
- * based authentication by just entering an X.509 Subject DN
- * ("/XX=YYY/XX=YYY/..") as the username and "password" as the
- * password.
- */
- if ((cpAL = ap_table_get(r->headers_in, "Authorization")) != NULL) {
- if (strcEQ(ap_getword(r->pool, &cpAL, ' '), "Basic")) {
- while (*cpAL == ' ' || *cpAL == '\t')
- cpAL++;
- cpAL = ap_pbase64decode(r->pool, cpAL);
- cpUN = ap_getword_nulls(r->pool, &cpAL, ':');
- cpPW = cpAL;
- if (cpUN[0] == '/' && strEQ(cpPW, "password"))
- return FORBIDDEN;
- }
- }
-
- /*
- * We decline operation in various situations...
- */
- if (!sc->bEnabled)
- return DECLINED;
- if (ap_ctx_get(r->connection->client->ctx, "ssl") == NULL)
- return DECLINED;
- if (!(dc->nOptions & SSL_OPT_FAKEBASICAUTH))
- return DECLINED;
- if (r->connection->user)
- return DECLINED;
- if ((clientdn = (char *)ap_ctx_get(r->connection->client->ctx, "ssl::client::dn")) == NULL)
- return DECLINED;
-
- /*
- * Fake a password - which one would be immaterial, as, it seems, an empty
- * password in the users file would match ALL incoming passwords, if only
- * we were using the standard crypt library routine. Unfortunately, OpenSSL
- * "fixes" a "bug" in crypt and thus prevents blank passwords from
- * working. (IMHO what they really fix is a bug in the users of the code
- * - failing to program correctly for shadow passwords). We need,
- * therefore, to provide a password. This password can be matched by
- * adding the string "xxj31ZMTZzkVA" as the password in the user file.
- * This is just the crypted variant of the word "password" ;-)
- */
- ap_snprintf(b1, sizeof(b1), "%s:password", clientdn);
- ssl_util_uuencode(b2, b1, FALSE);
- ap_snprintf(b1, sizeof(b1), "Basic %s", b2);
- ap_table_set(r->headers_in, "Authorization", b1);
- ssl_log(r->server, SSL_LOG_INFO,
- "Faking HTTP Basic Auth header: \"Authorization: %s\"", b1);
-
- return DECLINED;
-}
-
-int ssl_hook_UserCheck(request_rec *r)
-{
- SSLDirConfigRec *dc = myDirConfig(r);
-
- /*
- * Additionally forbid access (again)
- * when strict require option is used.
- */
- if ( (dc->nOptions & SSL_OPT_STRICTREQUIRE)
- && (ap_table_get(r->notes, "ssl-access-forbidden") != NULL))
- return FORBIDDEN;
-
- return DECLINED;
-}
-
-/*
- * Fixup Handler
- */
-
-static const char *ssl_hook_Fixup_vars[] = {
- "SSL_VERSION_INTERFACE",
- "SSL_VERSION_LIBRARY",
- "SSL_PROTOCOL",
- "SSL_CIPHER",
- "SSL_CIPHER_EXPORT",
- "SSL_CIPHER_USEKEYSIZE",
- "SSL_CIPHER_ALGKEYSIZE",
- "SSL_CLIENT_VERIFY",
- "SSL_CLIENT_M_VERSION",
- "SSL_CLIENT_M_SERIAL",
- "SSL_CLIENT_V_START",
- "SSL_CLIENT_V_END",
- "SSL_CLIENT_S_DN",
- "SSL_CLIENT_S_DN_C",
- "SSL_CLIENT_S_DN_ST",
- "SSL_CLIENT_S_DN_L",
- "SSL_CLIENT_S_DN_O",
- "SSL_CLIENT_S_DN_OU",
- "SSL_CLIENT_S_DN_CN",
- "SSL_CLIENT_S_DN_T",
- "SSL_CLIENT_S_DN_I",
- "SSL_CLIENT_S_DN_G",
- "SSL_CLIENT_S_DN_S",
- "SSL_CLIENT_S_DN_D",
- "SSL_CLIENT_S_DN_UID",
- "SSL_CLIENT_S_DN_Email",
- "SSL_CLIENT_I_DN",
- "SSL_CLIENT_I_DN_C",
- "SSL_CLIENT_I_DN_ST",
- "SSL_CLIENT_I_DN_L",
- "SSL_CLIENT_I_DN_O",
- "SSL_CLIENT_I_DN_OU",
- "SSL_CLIENT_I_DN_CN",
- "SSL_CLIENT_I_DN_T",
- "SSL_CLIENT_I_DN_I",
- "SSL_CLIENT_I_DN_G",
- "SSL_CLIENT_I_DN_S",
- "SSL_CLIENT_I_DN_D",
- "SSL_CLIENT_I_DN_UID",
- "SSL_CLIENT_I_DN_Email",
- "SSL_CLIENT_A_KEY",
- "SSL_CLIENT_A_SIG",
- "SSL_SERVER_M_VERSION",
- "SSL_SERVER_M_SERIAL",
- "SSL_SERVER_V_START",
- "SSL_SERVER_V_END",
- "SSL_SERVER_S_DN",
- "SSL_SERVER_S_DN_C",
- "SSL_SERVER_S_DN_ST",
- "SSL_SERVER_S_DN_L",
- "SSL_SERVER_S_DN_O",
- "SSL_SERVER_S_DN_OU",
- "SSL_SERVER_S_DN_CN",
- "SSL_SERVER_S_DN_T",
- "SSL_SERVER_S_DN_I",
- "SSL_SERVER_S_DN_G",
- "SSL_SERVER_S_DN_S",
- "SSL_SERVER_S_DN_D",
- "SSL_SERVER_S_DN_UID",
- "SSL_SERVER_S_DN_Email",
- "SSL_SERVER_I_DN",
- "SSL_SERVER_I_DN_C",
- "SSL_SERVER_I_DN_ST",
- "SSL_SERVER_I_DN_L",
- "SSL_SERVER_I_DN_O",
- "SSL_SERVER_I_DN_OU",
- "SSL_SERVER_I_DN_CN",
- "SSL_SERVER_I_DN_T",
- "SSL_SERVER_I_DN_I",
- "SSL_SERVER_I_DN_G",
- "SSL_SERVER_I_DN_S",
- "SSL_SERVER_I_DN_D",
- "SSL_SERVER_I_DN_UID",
- "SSL_SERVER_I_DN_Email",
- "SSL_SERVER_A_KEY",
- "SSL_SERVER_A_SIG",
- "SSL_SESSION_ID",
- NULL
-};
-
-int ssl_hook_Fixup(request_rec *r)
-{
- SSLSrvConfigRec *sc = mySrvConfig(r->server);
- SSLDirConfigRec *dc = myDirConfig(r);
- table *e = r->subprocess_env;
- char *var;
- char *val;
- STACK_OF(X509) *sk;
- SSL *ssl;
- int i;
-
- /*
- * Check to see if SSL is on
- */
- if (!sc->bEnabled)
- return DECLINED;
- if ((ssl = ap_ctx_get(r->connection->client->ctx, "ssl")) == NULL)
- return DECLINED;
-
- /*
- * Annotate the SSI/CGI environment with standard SSL information
- */
- /* the always present HTTPS (=HTTP over SSL) flag! */
- ap_table_set(e, "HTTPS", "on");
- /* standard SSL environment variables */
- if (dc->nOptions & SSL_OPT_STDENVVARS) {
- for (i = 0; ssl_hook_Fixup_vars[i] != NULL; i++) {
- var = (char *)ssl_hook_Fixup_vars[i];
- val = ssl_var_lookup(r->pool, r->server, r->connection, r, var);
- if (!strIsEmpty(val))
- ap_table_set(e, var, val);
- }
- }
-
- /*
- * On-demand bloat up the SSI/CGI environment with certificate data
- */
- if (dc->nOptions & SSL_OPT_EXPORTCERTDATA) {
- val = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_SERVER_CERT");
- ap_table_set(e, "SSL_SERVER_CERT", val);
- val = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_CLIENT_CERT");
- ap_table_set(e, "SSL_CLIENT_CERT", val);
- if ((sk = SSL_get_peer_cert_chain(ssl)) != NULL) {
- for (i = 0; i < sk_X509_num(sk); i++) {
- var = ap_psprintf(r->pool, "SSL_CLIENT_CERT_CHAIN_%d", i);
- val = ssl_var_lookup(r->pool, r->server, r->connection, r, var);
- if (val != NULL)
- ap_table_set(e, var, val);
- }
- }
- }
-
- /*
- * On-demand bloat up the SSI/CGI environment with compat variables
- */
-#ifdef SSL_COMPAT
- if (dc->nOptions & SSL_OPT_COMPATENVVARS)
- ssl_compat_variables(r);
-#endif
-
- return DECLINED;
-}
-
-/* _________________________________________________________________
-**
-** OpenSSL Callback Functions
-** _________________________________________________________________
-*/
-
-/*
- * Handle out temporary RSA private keys on demand
- *
- * The background of this as the TLSv1 standard explains it:
- *
- * | D.1. Temporary RSA keys
- * |
- * | US Export restrictions limit RSA keys used for encryption to 512
- * | bits, but do not place any limit on lengths of RSA keys used for
- * | signing operations. Certificates often need to be larger than 512
- * | bits, since 512-bit RSA keys are not secure enough for high-value
- * | transactions or for applications requiring long-term security. Some
- * | certificates are also designated signing-only, in which case they
- * | cannot be used for key exchange.
- * |
- * | When the public key in the certificate cannot be used for encryption,
- * | the server signs a temporary RSA key, which is then exchanged. In
- * | exportable applications, the temporary RSA key should be the maximum
- * | allowable length (i.e., 512 bits). Because 512-bit RSA keys are
- * | relatively insecure, they should be changed often. For typical
- * | electronic commerce applications, it is suggested that keys be
- * | changed daily or every 500 transactions, and more often if possible.
- * | Note that while it is acceptable to use the same temporary key for
- * | multiple transactions, it must be signed each time it is used.
- * |
- * | RSA key generation is a time-consuming process. In many cases, a
- * | low-priority process can be assigned the task of key generation.
- * | Whenever a new key is completed, the existing temporary key can be
- * | replaced with the new one.
- *
- * So we generated 512 and 1024 bit temporary keys on startup
- * which we now just handle out on demand....
- */
-RSA *ssl_callback_TmpRSA(SSL *pSSL, int nExport, int nKeyLen)
-{
- SSLModConfigRec *mc = myModConfig();
- RSA *rsa;
-
- rsa = NULL;
- if (nExport) {
- /* It's because an export cipher is used */
- if (nKeyLen == 512)
- rsa = (RSA *)mc->pTmpKeys[SSL_TKPIDX_RSA512];
- else if (nKeyLen == 1024)
- rsa = (RSA *)mc->pTmpKeys[SSL_TKPIDX_RSA1024];
- else
- /* it's too expensive to generate on-the-fly, so keep 1024bit */
- rsa = (RSA *)mc->pTmpKeys[SSL_TKPIDX_RSA1024];
- }
- else {
- /* It's because a sign-only certificate situation exists */
- rsa = (RSA *)mc->pTmpKeys[SSL_TKPIDX_RSA1024];
- }
- return rsa;
-}
-
-/*
- * Handle out the already generated DH parameters...
- */
-DH *ssl_callback_TmpDH(SSL *pSSL, int nExport, int nKeyLen)
-{
- SSLModConfigRec *mc = myModConfig();
- DH *dh;
-
- dh = NULL;
- if (nExport) {
- /* It's because an export cipher is used */
- if (nKeyLen == 512)
- dh = (DH *)mc->pTmpKeys[SSL_TKPIDX_DH512];
- else if (nKeyLen == 1024)
- dh = (DH *)mc->pTmpKeys[SSL_TKPIDX_DH1024];
- else
- /* it's too expensive to generate on-the-fly, so keep 1024bit */
- dh = (DH *)mc->pTmpKeys[SSL_TKPIDX_DH1024];
- }
- else {
- /* It's because a sign-only certificate situation exists */
- dh = (DH *)mc->pTmpKeys[SSL_TKPIDX_DH1024];
- }
- return dh;
-}
-
-/*
- * This OpenSSL callback function is called when OpenSSL
- * does client authentication and verifies the certificate chain.
- */
-int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx)
-{
- SSL *ssl;
- conn_rec *conn;
- server_rec *s;
- request_rec *r;
- SSLSrvConfigRec *sc;
- SSLDirConfigRec *dc;
- ap_ctx *actx;
- X509 *xs;
- int errnum;
- int errdepth;
- char *cp;
- char *cp2;
- int depth;
- int verify;
-
- /*
- * Get Apache context back through OpenSSL context
- */
- ssl = (SSL *)X509_STORE_CTX_get_app_data(ctx);
- conn = (conn_rec *)SSL_get_app_data(ssl);
- actx = (ap_ctx *)SSL_get_app_data2(ssl);
- r = (request_rec *)ap_ctx_get(actx, "ssl::request_rec");
- s = conn->server;
- sc = mySrvConfig(s);
- dc = (r != NULL ? myDirConfig(r) : NULL);
-
- /*
- * Get verify ingredients
- */
- xs = X509_STORE_CTX_get_current_cert(ctx);
- errnum = X509_STORE_CTX_get_error(ctx);
- errdepth = X509_STORE_CTX_get_error_depth(ctx);
-
- /*
- * Log verification information
- */
- cp = X509_NAME_oneline(X509_get_subject_name(xs), NULL, 0);
- cp2 = X509_NAME_oneline(X509_get_issuer_name(xs), NULL, 0);
- ssl_log(s, SSL_LOG_TRACE,
- "Certificate Verification: depth: %d, subject: %s, issuer: %s",
- errdepth, cp != NULL ? cp : "-unknown-",
- cp2 != NULL ? cp2 : "-unknown");
- if (cp)
- free(cp);
- if (cp2)
- free(cp2);
-
- /*
- * Check for optionally acceptable non-verifiable issuer situation
- */
- if (dc != NULL && dc->nVerifyClient != SSL_CVERIFY_UNSET)
- verify = dc->nVerifyClient;
- else
- verify = sc->nVerifyClient;
- if ( ( errnum == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
- || errnum == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
- || errnum == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
-#if SSL_LIBRARY_VERSION >= 0x00905000
- || errnum == X509_V_ERR_CERT_UNTRUSTED
-#endif
- || errnum == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE )
- && verify == SSL_CVERIFY_OPTIONAL_NO_CA ) {
- ssl_log(s, SSL_LOG_TRACE,
- "Certificate Verification: Verifiable Issuer is configured as "
- "optional, therefore we're accepting the certificate");
- ap_ctx_set(conn->client->ctx, "ssl::verify::info", "GENEROUS");
- ok = TRUE;
- }
-
- /*
- * Additionally perform CRL-based revocation checks
- */
- if (ok) {
- ok = ssl_callback_SSLVerify_CRL(ok, ctx, s);
- if (!ok)
- errnum = X509_STORE_CTX_get_error(ctx);
- }
-
- /*
- * If we already know it's not ok, log the real reason
- */
- if (!ok) {
- ssl_log(s, SSL_LOG_ERROR, "Certificate Verification: Error (%d): %s",
- errnum, X509_verify_cert_error_string(errnum));
- ap_ctx_set(conn->client->ctx, "ssl::client::dn", NULL);
- ap_ctx_set(conn->client->ctx, "ssl::verify::error",
- (void *)X509_verify_cert_error_string(errnum));
- }
-
- /*
- * Finally check the depth of the certificate verification
- */
- if (dc != NULL && dc->nVerifyDepth != UNSET)
- depth = dc->nVerifyDepth;
- else
- depth = sc->nVerifyDepth;
- if (errdepth > depth) {
- ssl_log(s, SSL_LOG_ERROR,
- "Certificate Verification: Certificate Chain too long "
- "(chain has %d certificates, but maximum allowed are only %d)",
- errdepth, depth);
- ap_ctx_set(conn->client->ctx, "ssl::verify::error",
- (void *)X509_verify_cert_error_string(X509_V_ERR_CERT_CHAIN_TOO_LONG));
- ok = FALSE;
- }
-
- /*
- * And finally signal OpenSSL the (perhaps changed) state
- */
- return (ok);
-}
-
-int ssl_callback_SSLVerify_CRL(
- int ok, X509_STORE_CTX *ctx, server_rec *s)
-{
- SSLSrvConfigRec *sc;
- X509_OBJECT obj;
- X509_NAME *subject;
- X509_NAME *issuer;
- X509 *xs;
- X509_CRL *crl;
- X509_REVOKED *revoked;
- long serial;
- BIO *bio;
- int i, n, rc;
- char *cp;
- char *cp2;
-
- /*
- * Unless a revocation store for CRLs was created we
- * cannot do any CRL-based verification, of course.
- */
- sc = mySrvConfig(s);
- if (sc->pRevocationStore == NULL)
- return ok;
-
- /*
- * Determine certificate ingredients in advance
- */
- xs = X509_STORE_CTX_get_current_cert(ctx);
- subject = X509_get_subject_name(xs);
- issuer = X509_get_issuer_name(xs);
-
- /*
- * OpenSSL provides the general mechanism to deal with CRLs but does not
- * use them automatically when verifying certificates, so we do it
- * explicitly here. We will check the CRL for the currently checked
- * certificate, if there is such a CRL in the store.
- *
- * We come through this procedure for each certificate in the certificate
- * chain, starting with the root-CA's certificate. At each step we've to
- * both verify the signature on the CRL (to make sure it's a valid CRL)
- * and it's revocation list (to make sure the current certificate isn't
- * revoked). But because to check the signature on the CRL we need the
- * public key of the issuing CA certificate (which was already processed
- * one round before), we've a little problem. But we can both solve it and
- * at the same time optimize the processing by using the following
- * verification scheme (idea and code snippets borrowed from the GLOBUS
- * project):
- *
- * 1. We'll check the signature of a CRL in each step when we find a CRL
- * through the _subject_ name of the current certificate. This CRL
- * itself will be needed the first time in the next round, of course.
- * But we do the signature processing one round before this where the
- * public key of the CA is available.
- *
- * 2. We'll check the revocation list of a CRL in each step when
- * we find a CRL through the _issuer_ name of the current certificate.
- * This CRLs signature was then already verified one round before.
- *
- * This verification scheme allows a CA to revoke its own certificate as
- * well, of course.
- */
-
- /*
- * Try to retrieve a CRL corresponding to the _subject_ of
- * the current certificate in order to verify it's integrity.
- */
- memset((char *)&obj, 0, sizeof(obj));
- rc = SSL_X509_STORE_lookup(sc->pRevocationStore, X509_LU_CRL, subject, &obj);
- crl = obj.data.crl;
- if (rc > 0 && crl != NULL) {
- /*
- * Log information about CRL
- * (A little bit complicated because of ASN.1 and BIOs...)
- */
- if (ssl_log_applies(s, SSL_LOG_TRACE)) {
- bio = BIO_new(BIO_s_mem());
- BIO_printf(bio, "lastUpdate: ");
- ASN1_UTCTIME_print(bio, X509_CRL_get_lastUpdate(crl));
- BIO_printf(bio, ", nextUpdate: ");
- ASN1_UTCTIME_print(bio, X509_CRL_get_nextUpdate(crl));
- n = BIO_pending(bio);
- cp = malloc(n+1);
- n = BIO_read(bio, cp, n);
- cp[n] = NUL;
- BIO_free(bio);
- cp2 = X509_NAME_oneline(subject, NULL, 0);
- ssl_log(s, SSL_LOG_TRACE, "CA CRL: Issuer: %s, %s", cp2, cp);
- free(cp2);
- free(cp);
- }
-
- /*
- * Verify the signature on this CRL
- */
- if (X509_CRL_verify(crl, X509_get_pubkey(xs)) <= 0) {
- ssl_log(s, SSL_LOG_WARN, "Invalid signature on CRL");
- X509_STORE_CTX_set_error(ctx, X509_V_ERR_CRL_SIGNATURE_FAILURE);
- X509_OBJECT_free_contents(&obj);
- return FALSE;
- }
-
- /*
- * Check date of CRL to make sure it's not expired
- */
- i = X509_cmp_current_time(X509_CRL_get_nextUpdate(crl));
- if (i == 0) {
- ssl_log(s, SSL_LOG_WARN, "Found CRL has invalid nextUpdate field");
- X509_STORE_CTX_set_error(ctx, X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD);
- X509_OBJECT_free_contents(&obj);
- return FALSE;
- }
- if (i < 0) {
- ssl_log(s, SSL_LOG_WARN,
- "Found CRL is expired - "
- "revoking all certificates until you get updated CRL");
- X509_STORE_CTX_set_error(ctx, X509_V_ERR_CRL_HAS_EXPIRED);
- X509_OBJECT_free_contents(&obj);
- return FALSE;
- }
- X509_OBJECT_free_contents(&obj);
- }
-
- /*
- * Try to retrieve a CRL corresponding to the _issuer_ of
- * the current certificate in order to check for revocation.
- */
- memset((char *)&obj, 0, sizeof(obj));
- rc = SSL_X509_STORE_lookup(sc->pRevocationStore, X509_LU_CRL, issuer, &obj);
- crl = obj.data.crl;
- if (rc > 0 && crl != NULL) {
- /*
- * Check if the current certificate is revoked by this CRL
- */
-#if SSL_LIBRARY_VERSION < 0x00904000
- n = sk_num(X509_CRL_get_REVOKED(crl));
-#else
- n = sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl));
-#endif
- for (i = 0; i < n; i++) {
-#if SSL_LIBRARY_VERSION < 0x00904000
- revoked = (X509_REVOKED *)sk_value(X509_CRL_get_REVOKED(crl), i);
-#else
- revoked = sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i);
-#endif
- if (ASN1_INTEGER_cmp(revoked->serialNumber, X509_get_serialNumber(xs)) == 0) {
-
- serial = ASN1_INTEGER_get(revoked->serialNumber);
- cp = X509_NAME_oneline(issuer, NULL, 0);
- ssl_log(s, SSL_LOG_INFO,
- "Certificate with serial %ld (0x%lX) "
- "revoked per CRL from issuer %s",
- serial, serial, cp);
- free(cp);
-
- X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REVOKED);
- X509_OBJECT_free_contents(&obj);
- return FALSE;
- }
- }
- X509_OBJECT_free_contents(&obj);
- }
- return ok;
-}
-
-/*
- * This callback function is executed by OpenSSL whenever a new SSL_SESSION is
- * added to the internal OpenSSL session cache. We use this hook to spread the
- * SSL_SESSION also to the inter-process disk-cache to make share it with our
- * other Apache pre-forked server processes.
- */
-int ssl_callback_NewSessionCacheEntry(SSL *ssl, SSL_SESSION *pNew)
-{
- conn_rec *conn;
- server_rec *s;
- SSLSrvConfigRec *sc;
- long t;
- BOOL rc;
-
- /*
- * Get Apache context back through OpenSSL context
- */
- conn = (conn_rec *)SSL_get_app_data(ssl);
- s = conn->server;
- sc = mySrvConfig(s);
-
- /*
- * Set the timeout also for the internal OpenSSL cache, because this way
- * our inter-process cache is consulted only when it's really necessary.
- */
- t = sc->nSessionCacheTimeout;
- SSL_set_timeout(pNew, t);
-
- /*
- * Store the SSL_SESSION in the inter-process cache with the
- * same expire time, so it expires automatically there, too.
- */
- t = (SSL_get_time(pNew) + sc->nSessionCacheTimeout);
- rc = ssl_scache_store(s, pNew->session_id, pNew->session_id_length, t, pNew);
-
- /*
- * Log this cache operation
- */
- ssl_log(s, SSL_LOG_TRACE, "Inter-Process Session Cache: "
- "request=SET status=%s id=%s timeout=%ds (session caching)",
- rc == TRUE ? "OK" : "BAD",
- SSL_SESSION_id2sz(pNew->session_id, pNew->session_id_length),
- t-time(NULL));
-
- /*
- * return 0 which means to OpenSSL that the pNew is still
- * valid and was not freed by us with SSL_SESSION_free().
- */
- return 0;
-}
-
-/*
- * This callback function is executed by OpenSSL whenever a
- * SSL_SESSION is looked up in the internal OpenSSL cache and it
- * was not found. We use this to lookup the SSL_SESSION in the
- * inter-process disk-cache where it was perhaps stored by one
- * of our other Apache pre-forked server processes.
- */
-SSL_SESSION *ssl_callback_GetSessionCacheEntry(
- SSL *ssl, unsigned char *id, int idlen, int *pCopy)
-{
- conn_rec *conn;
- server_rec *s;
- SSL_SESSION *pSession;
-
- /*
- * Get Apache context back through OpenSSL context
- */
- conn = (conn_rec *)SSL_get_app_data(ssl);
- s = conn->server;
-
- /*
- * Try to retrieve the SSL_SESSION from the inter-process cache
- */
- pSession = ssl_scache_retrieve(s, id, idlen);
-
- /*
- * Log this cache operation
- */
- if (pSession != NULL)
- ssl_log(s, SSL_LOG_TRACE, "Inter-Process Session Cache: "
- "request=GET status=FOUND id=%s (session reuse)",
- SSL_SESSION_id2sz(id, idlen));
- else
- ssl_log(s, SSL_LOG_TRACE, "Inter-Process Session Cache: "
- "request=GET status=MISSED id=%s (session renewal)",
- SSL_SESSION_id2sz(id, idlen));
-
- /*
- * Return NULL or the retrieved SSL_SESSION. But indicate (by
- * setting pCopy to 0) that the reference count on the
- * SSL_SESSION should not be incremented by the SSL library,
- * because we will no longer hold a reference to it ourself.
- */
- *pCopy = 0;
- return pSession;
-}
-
-/*
- * This callback function is executed by OpenSSL whenever a
- * SSL_SESSION is removed from the the internal OpenSSL cache.
- * We use this to remove the SSL_SESSION in the inter-process
- * disk-cache, too.
- */
-void ssl_callback_DelSessionCacheEntry(
- SSL_CTX *ctx, SSL_SESSION *pSession)
-{
- server_rec *s;
-
- /*
- * Get Apache context back through OpenSSL context
- */
- s = (server_rec *)SSL_CTX_get_app_data(ctx);
- if (s == NULL) /* on server shutdown Apache is already gone */
- return;
-
- /*
- * Remove the SSL_SESSION from the inter-process cache
- */
- ssl_scache_remove(s, pSession->session_id, pSession->session_id_length);
-
- /*
- * Log this cache operation
- */
- ssl_log(s, SSL_LOG_TRACE, "Inter-Process Session Cache: "
- "request=REM status=OK id=%s (session dead)",
- SSL_SESSION_id2sz(pSession->session_id,
- pSession->session_id_length));
-
- return;
-}
-
-/*
- * This callback function is executed while OpenSSL processes the
- * SSL handshake and does SSL record layer stuff. We use it to
- * trace OpenSSL's processing in out SSL logfile.
- */
-void ssl_callback_LogTracingState(SSL *ssl, int where, int rc)
-{
- conn_rec *c;
- server_rec *s;
- SSLSrvConfigRec *sc;
- char *str;
-
- /*
- * find corresponding server
- */
- if ((c = (conn_rec *)SSL_get_app_data(ssl)) == NULL)
- return;
- s = c->server;
- if ((sc = mySrvConfig(s)) == NULL)
- return;
-
- /*
- * create the various trace messages
- */
- if (sc->nLogLevel >= SSL_LOG_TRACE) {
- if (where & SSL_CB_HANDSHAKE_START)
- ssl_log(s, SSL_LOG_TRACE, "%s: Handshake: start", SSL_LIBRARY_NAME);
- else if (where & SSL_CB_HANDSHAKE_DONE)
- ssl_log(s, SSL_LOG_TRACE, "%s: Handshake: done", SSL_LIBRARY_NAME);
- else if (where & SSL_CB_LOOP)
- ssl_log(s, SSL_LOG_TRACE, "%s: Loop: %s",
- SSL_LIBRARY_NAME, SSL_state_string_long(ssl));
- else if (where & SSL_CB_READ)
- ssl_log(s, SSL_LOG_TRACE, "%s: Read: %s",
- SSL_LIBRARY_NAME, SSL_state_string_long(ssl));
- else if (where & SSL_CB_WRITE)
- ssl_log(s, SSL_LOG_TRACE, "%s: Write: %s",
- SSL_LIBRARY_NAME, SSL_state_string_long(ssl));
- else if (where & SSL_CB_ALERT) {
- str = (where & SSL_CB_READ) ? "read" : "write";
- ssl_log(s, SSL_LOG_TRACE, "%s: Alert: %s:%s:%s\n",
- SSL_LIBRARY_NAME, str,
- SSL_alert_type_string_long(rc),
- SSL_alert_desc_string_long(rc));
- }
- else if (where & SSL_CB_EXIT) {
- if (rc == 0)
- ssl_log(s, SSL_LOG_TRACE, "%s: Exit: failed in %s",
- SSL_LIBRARY_NAME, SSL_state_string_long(ssl));
- else if (rc < 0)
- ssl_log(s, SSL_LOG_TRACE, "%s: Exit: error in %s",
- SSL_LIBRARY_NAME, SSL_state_string_long(ssl));
- }
- }
-
- /*
- * Because SSL renegotations can happen at any time (not only after
- * SSL_accept()), the best way to log the current connection details is
- * right after a finished handshake.
- */
- if (where & SSL_CB_HANDSHAKE_DONE) {
- ssl_log(s, SSL_LOG_INFO,
- "Connection: Client IP: %s, Protocol: %s, Cipher: %s (%s/%s bits)",
- ssl_var_lookup(NULL, s, c, NULL, "REMOTE_ADDR"),
- ssl_var_lookup(NULL, s, c, NULL, "SSL_PROTOCOL"),
- ssl_var_lookup(NULL, s, c, NULL, "SSL_CIPHER"),
- ssl_var_lookup(NULL, s, c, NULL, "SSL_CIPHER_USEKEYSIZE"),
- ssl_var_lookup(NULL, s, c, NULL, "SSL_CIPHER_ALGKEYSIZE"));
- }
-
- return;
-}
-
diff --git a/modules/ssl/ssl_engine_log.c b/modules/ssl/ssl_engine_log.c
deleted file mode 100644
index 0e1c53a852..0000000000
--- a/modules/ssl/ssl_engine_log.c
+++ /dev/null
@@ -1,326 +0,0 @@
-/* _ _
-** _ __ ___ ___ __| | ___ ___| | mod_ssl
-** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
-** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
-** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
-** |_____|
-** ssl_engine_log.c
-** Logging Facility
-*/
-
-/* ====================================================================
- * Copyright (c) 1998-2001 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * 4. The names "mod_ssl" must not be used to endorse or promote
- * products derived from this software without prior written
- * permission. For written permission, please contact
- * rse@engelschall.com.
- *
- * 5. Products derived from this software may not be called "mod_ssl"
- * nor may "mod_ssl" appear in their names without prior
- * written permission of Ralf S. Engelschall.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
- /* ``The difference between a computer
- industry job and open-source software
- hacking is about 30 hours a week.''
- -- Ralf S. Engelschall */
-#include "mod_ssl.h"
-
-
-/* _________________________________________________________________
-**
-** Logfile Support
-** _________________________________________________________________
-*/
-
-/*
- * Open the SSL logfile
- */
-void ssl_log_open(server_rec *s_main, server_rec *s, pool *p)
-{
- char *szLogFile;
- SSLSrvConfigRec *sc_main = mySrvConfig(s_main);
- SSLSrvConfigRec *sc = mySrvConfig(s);
- piped_log *pl;
-
- /*
- * Short-circuit for inherited logfiles in order to save
- * filedescriptors in mass-vhost situation. Be careful, this works
- * fine because the close happens implicitly by the pool facility.
- */
- if ( s != s_main
- && sc_main->fileLogFile != NULL
- && ( (sc->szLogFile == NULL)
- || ( sc->szLogFile != NULL
- && sc_main->szLogFile != NULL
- && strEQ(sc->szLogFile, sc_main->szLogFile)))) {
- sc->fileLogFile = sc_main->fileLogFile;
- }
- else if (sc->szLogFile != NULL) {
- if (strEQ(sc->szLogFile, "/dev/null"))
- return;
- else if (sc->szLogFile[0] == '|') {
- szLogFile = ssl_util_server_root_relative(p, "log", sc->szLogFile+1);
- if ((pl = ap_open_piped_log(p, szLogFile)) == NULL) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
- "Cannot open reliable pipe to SSL logfile filter %s", szLogFile);
- ssl_die();
- }
- sc->fileLogFile = ap_pfdopen(p, ap_piped_log_write_fd(pl), "a");
- setbuf(sc->fileLogFile, NULL);
- }
- else {
- szLogFile = ssl_util_server_root_relative(p, "log", sc->szLogFile);
- if ((sc->fileLogFile = ap_pfopen(p, szLogFile, "a")) == NULL) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
- "Cannot open SSL logfile %s", szLogFile);
- ssl_die();
- }
- setbuf(sc->fileLogFile, NULL);
- }
- }
- return;
-}
-
-static struct {
- int nLevel;
- char *szLevel;
-} ssl_log_level2string[] = {
- { SSL_LOG_ERROR, "error" },
- { SSL_LOG_WARN, "warn" },
- { SSL_LOG_INFO, "info" },
- { SSL_LOG_TRACE, "trace" },
- { SSL_LOG_DEBUG, "debug" },
- { 0, NULL }
-};
-
-static struct {
- char *cpPattern;
- char *cpAnnotation;
-} ssl_log_annotate[] = {
- { "*envelope*bad*decrypt*", "wrong pass phrase!?" },
- { "*CLIENT_HELLO*unknown*protocol*", "speaking not SSL to HTTPS port!?" },
- { "*CLIENT_HELLO*http*request*", "speaking HTTP to HTTPS port!?" },
- { "*SSL3_READ_BYTES:sslv3*alert*bad*certificate*", "Subject CN in certificate not server name or identical to CA!?" },
- { "*self signed certificate in certificate chain*", "Client certificate signed by CA not known to server?" },
- { "*peer did not return a certificate*", "No CAs known to server for verification?" },
- { "*no shared cipher*", "Too restrictive SSLCipherSuite or using DSA server certificate?" },
- { "*no start line*", "Bad file contents or format - or even just a forgotten SSLCertificateKeyFile?" },
- { "*bad password read*", "You entered an incorrect pass phrase!?" },
- { "*bad mac decode*", "Browser still remembered details of a re-created server certificate?" },
- { NULL, NULL }
-};
-
-static char *ssl_log_annotation(char *error)
-{
- char *errstr;
- int i;
-
- errstr = NULL;
- for (i = 0; ssl_log_annotate[i].cpPattern != NULL; i++) {
- if (ap_strcmp_match(error, ssl_log_annotate[i].cpPattern) == 0) {
- errstr = ssl_log_annotate[i].cpAnnotation;
- break;
- }
- }
- return errstr;
-}
-
-BOOL ssl_log_applies(server_rec *s, int level)
-{
- SSLSrvConfigRec *sc;
-
- sc = mySrvConfig(s);
- if ( sc->fileLogFile == NULL
- && !(level & SSL_LOG_ERROR))
- return FALSE;
- if ( level > sc->nLogLevel
- && !(level & SSL_LOG_ERROR))
- return FALSE;
- return TRUE;
-}
-
-void ssl_log(server_rec *s, int level, const char *msg, ...)
-{
- char tstr[80];
- char lstr[20];
- char vstr[1024];
- char str[1024];
- char nstr[2];
- int timz;
- struct tm *t;
- va_list ap;
- int add;
- int i;
- char *astr;
- int safe_errno;
- unsigned long e;
- SSLSrvConfigRec *sc;
- char *cpE;
- char *cpA;
-
- /* initialization */
- va_start(ap, msg);
- safe_errno = errno;
- sc = mySrvConfig(s);
-
- /* strip out additional flags */
- add = (level & ~SSL_LOG_MASK);
- level = (level & SSL_LOG_MASK);
-
- /* reduce flags when not reasonable in context */
- if (add & SSL_ADD_ERRNO && errno == 0)
- add &= ~SSL_ADD_ERRNO;
- if (add & SSL_ADD_SSLERR && ERR_peek_error() == 0)
- add &= ~SSL_ADD_SSLERR;
-
- /* we log only levels below, except for errors */
- if ( sc->fileLogFile == NULL
- && !(level & SSL_LOG_ERROR))
- return;
- if ( level > sc->nLogLevel
- && !(level & SSL_LOG_ERROR))
- return;
-
- /* determine the time entry string */
- if (add & SSL_NO_TIMESTAMP)
- tstr[0] = NUL;
- else {
- t = ap_get_gmtoff(&timz);
- strftime(tstr, 80, "[%d/%b/%Y %H:%M:%S", t);
- i = strlen(tstr);
- ap_snprintf(tstr+i, 80-i, " %05d] ", (unsigned int)getpid());
- }
-
- /* determine whether newline should be written */
- if (add & SSL_NO_NEWLINE)
- nstr[0] = NUL;
- else {
- nstr[0] = '\n';
- nstr[1] = NUL;
- }
-
- /* determine level name */
- lstr[0] = NUL;
- if (!(add & SSL_NO_LEVELID)) {
- for (i = 0; ssl_log_level2string[i].nLevel != 0; i++) {
- if (ssl_log_level2string[i].nLevel == level) {
- ap_snprintf(lstr, sizeof(lstr), "[%s]", ssl_log_level2string[i].szLevel);
- break;
- }
- }
- for (i = strlen(lstr); i <= 7; i++)
- lstr[i] = ' ';
- lstr[i] = NUL;
- }
-
- /* create custom message */
- ap_vsnprintf(vstr, sizeof(vstr), msg, ap);
-
- /* write out SSLog message */
- if ((add & SSL_ADD_ERRNO) && (add & SSL_ADD_SSLERR))
- astr = " (System and " SSL_LIBRARY_NAME " library errors follow)";
- else if (add & SSL_ADD_ERRNO)
- astr = " (System error follows)";
- else if (add & SSL_ADD_SSLERR)
- astr = " (" SSL_LIBRARY_NAME " library error follows)";
- else
- astr = "";
- if (level <= sc->nLogLevel && sc->fileLogFile != NULL) {
- ap_snprintf(str, sizeof(str), "%s%s%s%s%s", tstr, lstr, vstr, astr, nstr);
- fprintf(sc->fileLogFile, "%s", str);
- }
- if (level & SSL_LOG_ERROR)
- ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, s,
- "mod_ssl: %s%s", vstr, astr);
-
- /* write out additional attachment messages */
- if (add & SSL_ADD_ERRNO) {
- if (level <= sc->nLogLevel && sc->fileLogFile != NULL) {
- ap_snprintf(str, sizeof(str), "%s%sSystem: %s (errno: %d)%s",
- tstr, lstr, strerror(safe_errno), safe_errno, nstr);
- fprintf(sc->fileLogFile, "%s", str);
- }
- if (level & SSL_LOG_ERROR)
- ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, s,
- "System: %s (errno: %d)",
- strerror(safe_errno), safe_errno);
- }
- if (add & SSL_ADD_SSLERR) {
- while ((e = ERR_get_error())) {
- cpE = ERR_error_string(e, NULL);
- cpA = ssl_log_annotation(cpE);
- if (level <= sc->nLogLevel && sc->fileLogFile != NULL) {
- ap_snprintf(str, sizeof(str), "%s%s%s: %s%s%s%s%s",
- tstr, lstr, SSL_LIBRARY_NAME, cpE,
- cpA != NULL ? " [Hint: " : "",
- cpA != NULL ? cpA : "", cpA != NULL ? "]" : "",
- nstr);
- fprintf(sc->fileLogFile, "%s", str);
- }
- if (level & SSL_LOG_ERROR)
- ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, s,
- "%s: %s%s%s%s", SSL_LIBRARY_NAME, cpE,
- cpA != NULL ? " [Hint: " : "",
- cpA != NULL ? cpA : "", cpA != NULL ? "]" : "");
- }
- }
- /* make sure the next log starts from a clean base */
- /* ERR_clear_error(); */
-
- /* cleanup and return */
- if (sc->fileLogFile != NULL)
- fflush(sc->fileLogFile);
- errno = safe_errno;
- va_end(ap);
- return;
-}
-
-void ssl_die(void)
-{
- /*
- * This is used for fatal errors and here
- * it is common module practice to really
- * exit from the complete program.
- */
- exit(1);
-}
-
diff --git a/modules/ssl/ssl_engine_mutex.c b/modules/ssl/ssl_engine_mutex.c
deleted file mode 100644
index 146f9ce4d9..0000000000
--- a/modules/ssl/ssl_engine_mutex.c
+++ /dev/null
@@ -1,397 +0,0 @@
-/* _ _
-** _ __ ___ ___ __| | ___ ___| | mod_ssl
-** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
-** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
-** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
-** |_____|
-** ssl_engine_mutex.c
-** Semaphore for Mutual Exclusion
-*/
-
-/* ====================================================================
- * Copyright (c) 1998-2001 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * 4. The names "mod_ssl" must not be used to endorse or promote
- * products derived from this software without prior written
- * permission. For written permission, please contact
- * rse@engelschall.com.
- *
- * 5. Products derived from this software may not be called "mod_ssl"
- * nor may "mod_ssl" appear in their names without prior
- * written permission of Ralf S. Engelschall.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
- /* ``Real programmers confuse
- Christmas and Halloween
- because DEC 25 = OCT 31.''
- -- Unknown */
-#include "mod_ssl.h"
-
-
-/* _________________________________________________________________
-**
-** Mutex Support (Common)
-** _________________________________________________________________
-*/
-
-void ssl_mutex_init(server_rec *s, pool *p)
-{
- SSLModConfigRec *mc = myModConfig();
-
- if (mc->nMutexMode == SSL_MUTEXMODE_FILE)
- ssl_mutex_file_create(s, p);
- else if (mc->nMutexMode == SSL_MUTEXMODE_SEM)
- ssl_mutex_sem_create(s, p);
- return;
-}
-
-void ssl_mutex_reinit(server_rec *s, pool *p)
-{
- SSLModConfigRec *mc = myModConfig();
-
- if (mc->nMutexMode == SSL_MUTEXMODE_FILE)
- ssl_mutex_file_open(s, p);
- else if (mc->nMutexMode == SSL_MUTEXMODE_SEM)
- ssl_mutex_sem_open(s, p);
- return;
-}
-
-void ssl_mutex_on(server_rec *s)
-{
- SSLModConfigRec *mc = myModConfig();
- BOOL ok = TRUE;
-
- if (mc->nMutexMode == SSL_MUTEXMODE_FILE)
- ok = ssl_mutex_file_acquire();
- else if (mc->nMutexMode == SSL_MUTEXMODE_SEM)
- ok = ssl_mutex_sem_acquire();
- if (!ok)
- ssl_log(s, SSL_LOG_WARN, "Failed to acquire global mutex lock");
- return;
-}
-
-void ssl_mutex_off(server_rec *s)
-{
- SSLModConfigRec *mc = myModConfig();
- BOOL ok = TRUE;
-
- if (mc->nMutexMode == SSL_MUTEXMODE_FILE)
- ok = ssl_mutex_file_release();
- else if (mc->nMutexMode == SSL_MUTEXMODE_SEM)
- ok = ssl_mutex_sem_release();
- if (!ok)
- ssl_log(s, SSL_LOG_WARN, "Failed to release global mutex lock");
- return;
-}
-
-void ssl_mutex_kill(server_rec *s)
-{
- SSLModConfigRec *mc = myModConfig();
-
- if (mc->nMutexMode == SSL_MUTEXMODE_FILE)
- ssl_mutex_file_remove(s);
- else if (mc->nMutexMode == SSL_MUTEXMODE_SEM)
- ssl_mutex_sem_remove(s);
- return;
-}
-
-
-/* _________________________________________________________________
-**
-** Mutex Support (Lockfile)
-** _________________________________________________________________
-*/
-
-void ssl_mutex_file_create(server_rec *s, pool *p)
-{
-#ifndef WIN32
- SSLModConfigRec *mc = myModConfig();
-
- /* create the lockfile */
- unlink(mc->szMutexFile);
- if ((mc->nMutexFD = ap_popenf(p, mc->szMutexFile,
- O_WRONLY|O_CREAT, SSL_MUTEX_LOCK_MODE)) < 0) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
- "Parent process could not create SSLMutex lockfile %s",
- mc->szMutexFile);
- ssl_die();
- }
- ap_pclosef(p, mc->nMutexFD);
-
- /* make sure the childs have access to this file */
-#ifndef OS2
- if (geteuid() == 0 /* is superuser */)
- chown(mc->szMutexFile, ap_user_id, -1 /* no gid change */);
-#endif
-
- /* open the lockfile for real */
- if ((mc->nMutexFD = ap_popenf(p, mc->szMutexFile,
- O_WRONLY, SSL_MUTEX_LOCK_MODE)) < 0) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
- "Parent could not open SSLMutex lockfile %s",
- mc->szMutexFile);
- ssl_die();
- }
-#endif
- return;
-}
-
-void ssl_mutex_file_open(server_rec *s, pool *p)
-{
-#ifndef WIN32
- SSLModConfigRec *mc = myModConfig();
-
- /* open the lockfile (once per child) to get a unique fd */
- if ((mc->nMutexFD = ap_popenf(p, mc->szMutexFile,
- O_WRONLY, SSL_MUTEX_LOCK_MODE)) < 0) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
- "Child could not open SSLMutex lockfile %s",
- mc->szMutexFile);
- ssl_die();
- }
-#endif
- return;
-}
-
-void ssl_mutex_file_remove(void *data)
-{
-#ifndef WIN32
- SSLModConfigRec *mc = myModConfig();
-
- /* remove the mutex lockfile */
- unlink(mc->szMutexFile);
-#endif
- return;
-}
-
-#ifndef WIN32
-#ifdef SSL_USE_FCNTL
-static struct flock lock_it;
-static struct flock unlock_it;
-#endif
-#endif
-
-BOOL ssl_mutex_file_acquire(void)
-{
- int rc = -1;
-#ifndef WIN32
- SSLModConfigRec *mc = myModConfig();
-
-#ifdef SSL_USE_FCNTL
- lock_it.l_whence = SEEK_SET; /* from current point */
- lock_it.l_start = 0; /* -"- */
- lock_it.l_len = 0; /* until end of file */
- lock_it.l_type = F_WRLCK; /* set exclusive/write lock */
- lock_it.l_pid = 0; /* pid not actually interesting */
-
- while ( ((rc = fcntl(mc->nMutexFD, F_SETLKW, &lock_it)) < 0)
- && (errno == EINTR) )
- ;
-#endif
-#ifdef SSL_USE_FLOCK
- while ( ((rc = flock(mc->nMutexFD, LOCK_EX)) < 0)
- && (errno == EINTR) )
- ;
-#endif
-#endif
-
- if (rc < 0)
- return FALSE;
- else
- return TRUE;
-}
-
-BOOL ssl_mutex_file_release(void)
-{
- int rc = -1;
-#ifndef WIN32
- SSLModConfigRec *mc = myModConfig();
-
-#ifdef SSL_USE_FCNTL
- unlock_it.l_whence = SEEK_SET; /* from current point */
- unlock_it.l_start = 0; /* -"- */
- unlock_it.l_len = 0; /* until end of file */
- unlock_it.l_type = F_UNLCK; /* unlock */
- unlock_it.l_pid = 0; /* pid not actually interesting */
-
- while ( (rc = fcntl(mc->nMutexFD, F_SETLKW, &unlock_it)) < 0
- && (errno == EINTR) )
- ;
-#endif
-#ifdef SSL_USE_FLOCK
- while ( (rc = flock(mc->nMutexFD, LOCK_UN)) < 0
- && (errno == EINTR) )
- ;
-#endif
-#endif
-
- if (rc < 0)
- return FALSE;
- else
- return TRUE;
-}
-
-/* _________________________________________________________________
-**
-** Mutex Support (Process Semaphore)
-** _________________________________________________________________
-*/
-
-void ssl_mutex_sem_create(server_rec *s, pool *p)
-{
-#ifdef SSL_CAN_USE_SEM
- int semid;
- SSLModConfigRec *mc = myModConfig();
-#ifdef SSL_HAVE_IPCSEM
- union ssl_ipc_semun semctlarg;
- struct semid_ds semctlbuf;
-#endif
-
-#ifdef SSL_HAVE_IPCSEM
- semid = semget(IPC_PRIVATE, 1, IPC_CREAT|IPC_EXCL|S_IRUSR|S_IWUSR);
- if (semid == -1 && errno == EEXIST)
- semid = semget(IPC_PRIVATE, 1, IPC_EXCL|S_IRUSR|S_IWUSR);
- if (semid == -1) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
- "Parent process could not create private SSLMutex semaphore");
- ssl_die();
- }
- semctlarg.val = 0;
- if (semctl(semid, 0, SETVAL, semctlarg) < 0) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
- "Parent process could not initialize SSLMutex semaphore value");
- ssl_die();
- }
- semctlbuf.sem_perm.uid = ap_user_id;
- semctlbuf.sem_perm.gid = ap_group_id;
- semctlbuf.sem_perm.mode = 0660;
- semctlarg.buf = &semctlbuf;
- if (semctl(semid, 0, IPC_SET, semctlarg) < 0) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
- "Parent process could not set permissions for SSLMutex semaphore");
- ssl_die();
- }
-#endif
-#ifdef SSL_HAVE_W32SEM
- semid = (int)ap_create_mutex("mod_ssl_mutex");
-#endif
- mc->nMutexSEMID = semid;
-#endif
- return;
-}
-
-void ssl_mutex_sem_open(server_rec *s, pool *p)
-{
-#ifdef SSL_CAN_USE_SEM
-#ifdef SSL_HAVE_W32SEM
- SSLModConfigRec *mc = myModConfig();
-
- mc->nMutexSEMID = (int)ap_open_mutex("mod_ssl_mutex");
-#endif
-#endif
- return;
-}
-
-void ssl_mutex_sem_remove(void *data)
-{
-#ifdef SSL_CAN_USE_SEM
- SSLModConfigRec *mc = myModConfig();
-
-#ifdef SSL_HAVE_IPCSEM
- semctl(mc->nMutexSEMID, 0, IPC_RMID, 0);
-#endif
-#ifdef SSL_HAVE_W32SEM
- ap_destroy_mutex((mutex *)mc->nMutexSEMID);
-#endif
-#endif
- return;
-}
-
-BOOL ssl_mutex_sem_acquire(void)
-{
- int rc = 0;
-#ifdef SSL_CAN_USE_SEM
- SSLModConfigRec *mc = myModConfig();
-
-#ifdef SSL_HAVE_IPCSEM
- struct sembuf sb[] = {
- { 0, 0, 0 }, /* wait for semaphore */
- { 0, 1, SEM_UNDO } /* increment semaphore */
- };
-
- while ( (rc = semop(mc->nMutexSEMID, sb, 2)) < 0
- && (errno == EINTR) )
- ;
-#endif
-#ifdef SSL_HAVE_W32SEM
- rc = ap_acquire_mutex((mutex *)mc->nMutexSEMID);
-#endif
-#endif
- if (rc != 0)
- return FALSE;
- else
- return TRUE;
-}
-
-BOOL ssl_mutex_sem_release(void)
-{
- int rc = 0;
-#ifdef SSL_CAN_USE_SEM
- SSLModConfigRec *mc = myModConfig();
-
-#ifdef SSL_HAVE_IPCSEM
- struct sembuf sb[] = {
- { 0, -1, SEM_UNDO } /* decrements semaphore */
- };
-
- while ( (rc = semop(mc->nMutexSEMID, sb, 1)) < 0
- && (errno == EINTR) )
- ;
-#endif
-#ifdef SSL_HAVE_W32SEM
- rc = ap_release_mutex((mutex *)mc->nMutexSEMID);
-#endif
-#endif
- if (rc != 0)
- return FALSE;
- else
- return TRUE;
-}
-
diff --git a/modules/ssl/ssl_engine_pphrase.c b/modules/ssl/ssl_engine_pphrase.c
deleted file mode 100644
index 2cef4e309e..0000000000
--- a/modules/ssl/ssl_engine_pphrase.c
+++ /dev/null
@@ -1,545 +0,0 @@
-/* _ _
-** _ __ ___ ___ __| | ___ ___| | mod_ssl
-** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
-** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
-** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
-** |_____|
-** ssl_engine_pphrase.c
-** Pass Phrase Dialog
-*/
-
-/* ====================================================================
- * Copyright (c) 1998-2001 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * 4. The names "mod_ssl" must not be used to endorse or promote
- * products derived from this software without prior written
- * permission. For written permission, please contact
- * rse@engelschall.com.
- *
- * 5. Products derived from this software may not be called "mod_ssl"
- * nor may "mod_ssl" appear in their names without prior
- * written permission of Ralf S. Engelschall.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
- /* ``Treat your password like your
- toothbrush. Don't let anybody
- else use it, and get a new one
- every six months.''
- -- Clifford Stoll */
-#include "mod_ssl.h"
-
-
-/* _________________________________________________________________
-**
-** Pass Phrase and Private Key Handling
-** _________________________________________________________________
-*/
-
-#define STDERR_FILENO_STORE 50
-#define BUILTIN_DIALOG_BACKOFF 2
-#define BUILTIN_DIALOG_RETRIES 5
-
-void ssl_pphrase_Handle(server_rec *s, pool *p)
-{
- SSLModConfigRec *mc = myModConfig();
- SSLSrvConfigRec *sc;
- server_rec *pServ;
- char *cpVHostID;
- char szPath[MAX_STRING_LEN];
- EVP_PKEY *pPrivateKey;
- ssl_asn1_t *asn1;
- unsigned char *ucp;
- X509 *pX509Cert;
- FILE *fp;
- BOOL bReadable;
- ssl_ds_array *aPassPhrase;
- int nPassPhrase;
- int nPassPhraseCur;
- char *cpPassPhraseCur;
- int nPassPhraseRetry;
- int nPassPhraseDialog;
- int nPassPhraseDialogCur;
- BOOL bPassPhraseDialogOnce;
- char **cpp;
- int i, j;
- ssl_algo_t algoCert, algoKey, at;
- char *an;
- char *cp;
-
- /*
- * Start with a fresh pass phrase array
- */
- aPassPhrase = ssl_ds_array_make(p, sizeof(char *));
- nPassPhrase = 0;
- nPassPhraseDialog = 0;
-
- /*
- * Walk through all configured servers
- */
- for (pServ = s; pServ != NULL; pServ = pServ->next) {
- sc = mySrvConfig(pServ);
-
- if (!sc->bEnabled)
- continue;
-
- cpVHostID = ssl_util_vhostid(p, pServ);
- ssl_log(pServ, SSL_LOG_INFO,
- "Init: Loading certificate & private key of SSL-aware server %s",
- cpVHostID);
-
- /*
- * Read in server certificate(s): This is the easy part
- * because this file isn't encrypted in any way.
- */
- if (sc->szPublicCertFile[0] == NULL) {
- ssl_log(pServ, SSL_LOG_ERROR,
- "Init: Server %s should be SSL-aware but has no certificate configured "
- "[Hint: SSLCertificateFile]", cpVHostID);
- ssl_die();
- }
- algoCert = SSL_ALGO_UNKNOWN;
- algoKey = SSL_ALGO_UNKNOWN;
- for (i = 0, j = 0; i < SSL_AIDX_MAX && sc->szPublicCertFile[i] != NULL; i++) {
-
- ap_cpystrn(szPath, sc->szPublicCertFile[i], sizeof(szPath));
- if ((fp = ap_pfopen(p, szPath, "r")) == NULL) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
- "Init: Can't open server certificate file %s", szPath);
- ssl_die();
- }
- if ((pX509Cert = SSL_read_X509(fp, NULL, NULL)) == NULL) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "Init: Unable to read server certificate from file %s", szPath);
- ssl_die();
- }
- ap_pfclose(p, fp);
-
- /*
- * check algorithm type of certificate and make
- * sure only one certificate per type is used.
- */
- at = ssl_util_algotypeof(pX509Cert, NULL);
- an = ssl_util_algotypestr(at);
- if (algoCert & at) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "Init: Multiple %s server certificates not allowed", an);
- ssl_die();
- }
- algoCert |= at;
-
- /*
- * Insert the certificate into global module configuration to let it
- * survive the processing between the 1st Apache API init round (where
- * we operate here) and the 2nd Apache init round (where the
- * certificate is actually used to configure mod_ssl's per-server
- * configuration structures).
- */
- cp = ap_psprintf(mc->pPool, "%s:%s", cpVHostID, an);
- asn1 = (ssl_asn1_t *)ssl_ds_table_push(mc->tPublicCert, cp);
- asn1->nData = i2d_X509(pX509Cert, NULL);
- asn1->cpData = ap_palloc(mc->pPool, asn1->nData);
- ucp = asn1->cpData; i2d_X509(pX509Cert, &ucp); /* 2nd arg increments */
-
- /*
- * Free the X509 structure
- */
- X509_free(pX509Cert);
-
- /*
- * Read in the private key: This is the non-trivial part, because the
- * key is typically encrypted, so a pass phrase dialog has to be used
- * to request it from the user (or it has to be alternatively gathered
- * from a dialog program). The important point here is that ISPs
- * usually have hundrets of virtual servers configured and a lot of
- * them use SSL, so really we have to minimize the pass phrase
- * dialogs.
- *
- * The idea is this: When N virtual hosts are configured and all of
- * them use encrypted private keys with different pass phrases, we
- * have no chance and have to pop up N pass phrase dialogs. But
- * usually the admin is clever enough and uses the same pass phrase
- * for more private key files (typically he even uses one single pass
- * phrase for all). When this is the case we can minimize the dialogs
- * by trying to re-use already known/entered pass phrases.
- */
- if (sc->szPrivateKeyFile[j] != NULL)
- ap_cpystrn(szPath, sc->szPrivateKeyFile[j++], sizeof(szPath));
-
- /*
- * Try to read the private key file with the help of
- * the callback function which serves the pass
- * phrases to OpenSSL
- */
- myCtxVarSet(mc, 1, pServ);
- myCtxVarSet(mc, 2, p);
- myCtxVarSet(mc, 3, aPassPhrase);
- myCtxVarSet(mc, 4, &nPassPhraseCur);
- myCtxVarSet(mc, 5, &cpPassPhraseCur);
- myCtxVarSet(mc, 6, cpVHostID);
- myCtxVarSet(mc, 7, an);
- myCtxVarSet(mc, 8, &nPassPhraseDialog);
- myCtxVarSet(mc, 9, &nPassPhraseDialogCur);
- myCtxVarSet(mc, 10, &bPassPhraseDialogOnce);
-
- nPassPhraseCur = 0;
- nPassPhraseRetry = 0;
- nPassPhraseDialogCur = 0;
- bPassPhraseDialogOnce = TRUE;
-
- pPrivateKey = NULL;
-
- for (;;) {
- /*
- * Try to read the private key file with the help of
- * the callback function which serves the pass
- * phrases to OpenSSL
- */
- if ((fp = ap_pfopen(p, szPath, "r")) == NULL) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
- "Init: Can't open server private key file %s", szPath);
- ssl_die();
- }
- cpPassPhraseCur = NULL;
- bReadable = ((pPrivateKey = SSL_read_PrivateKey(fp, NULL,
- ssl_pphrase_Handle_CB)) != NULL ? TRUE : FALSE);
- ap_pfclose(p, fp);
-
- /*
- * when the private key file now was readable,
- * it's fine and we go out of the loop
- */
- if (bReadable)
- break;
-
- /*
- * when we have more remembered pass phrases
- * try to reuse these first.
- */
- if (nPassPhraseCur < nPassPhrase) {
- nPassPhraseCur++;
- continue;
- }
-
- /*
- * else it's not readable and we have no more
- * remembered pass phrases. Then this has to mean
- * that the callback function popped up the dialog
- * but a wrong pass phrase was entered. We give the
- * user (but not the dialog program) a few more
- * chances...
- */
- if ( sc->nPassPhraseDialogType == SSL_PPTYPE_BUILTIN
- && cpPassPhraseCur != NULL
- && nPassPhraseRetry < BUILTIN_DIALOG_RETRIES ) {
- fprintf(stdout, "Apache:mod_ssl:Error: Pass phrase incorrect "
- "(%d more retr%s permitted).\n",
- (BUILTIN_DIALOG_RETRIES-nPassPhraseRetry),
- (BUILTIN_DIALOG_RETRIES-nPassPhraseRetry) == 1 ? "y" : "ies");
- nPassPhraseRetry++;
- if (nPassPhraseRetry > BUILTIN_DIALOG_BACKOFF)
- sleep((nPassPhraseRetry-BUILTIN_DIALOG_BACKOFF)*5);
- continue;
- }
-
- /*
- * Ok, anything else now means a fatal error.
- */
- if (cpPassPhraseCur == NULL)
- ssl_log(pServ, SSL_LOG_ERROR|SSL_ADD_SSLERR, "Init: Private key not found");
- if (sc->nPassPhraseDialogType == SSL_PPTYPE_BUILTIN) {
- fprintf(stdout, "Apache:mod_ssl:Error: Private key not found.\n");
- fprintf(stdout, "**Stopped\n");
- }
- else {
- ssl_log(pServ, SSL_LOG_ERROR|SSL_ADD_SSLERR, "Init: Pass phrase incorrect");
- if (sc->nPassPhraseDialogType == SSL_PPTYPE_BUILTIN) {
- fprintf(stdout, "Apache:mod_ssl:Error: Pass phrase incorrect.\n");
- fprintf(stdout, "**Stopped\n");
- }
- }
- ssl_die();
- }
-
- if (pPrivateKey == NULL) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "Init: Unable to read server private key from file %s", szPath);
- ssl_die();
- }
-
- /*
- * check algorithm type of private key and make
- * sure only one private key per type is used.
- */
- at = ssl_util_algotypeof(NULL, pPrivateKey);
- an = ssl_util_algotypestr(at);
- if (algoKey & at) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
- "Init: Multiple %s server private keys not allowed", an);
- ssl_die();
- }
- algoKey |= at;
-
- /*
- * Log the type of reading
- */
- if (nPassPhraseDialogCur == 0)
- ssl_log(pServ, SSL_LOG_TRACE,
- "Init: (%s) unencrypted %s private key - pass phrase not required",
- cpVHostID, an);
- else {
- if (cpPassPhraseCur != NULL)
- ssl_log(pServ, SSL_LOG_TRACE,
- "Init: (%s) encrypted %s private key - pass phrase requested",
- cpVHostID, an);
- else
- ssl_log(pServ, SSL_LOG_TRACE,
- "Init: (%s) encrypted %s private key - pass phrase reused",
- cpVHostID, an);
- }
-
- /*
- * Ok, when we have one more pass phrase store it
- */
- if (cpPassPhraseCur != NULL) {
- cpp = (char **)ssl_ds_array_push(aPassPhrase);
- *cpp = cpPassPhraseCur;
- nPassPhrase++;
- }
-
- /*
- * Insert private key into the global module configuration
- * (we convert it to a stand-alone DER byte sequence
- * because the SSL library uses static variables inside a
- * RSA structure which do not survive DSO reloads!)
- */
- cp = ap_psprintf(mc->pPool, "%s:%s", cpVHostID, an);
- asn1 = (ssl_asn1_t *)ssl_ds_table_push(mc->tPrivateKey, cp);
- asn1->nData = i2d_PrivateKey(pPrivateKey, NULL);
- asn1->cpData = ap_palloc(mc->pPool, asn1->nData);
- ucp = asn1->cpData; i2d_PrivateKey(pPrivateKey, &ucp); /* 2nd arg increments */
-
- /*
- * Free the private key structure
- */
- EVP_PKEY_free(pPrivateKey);
- }
- }
-
- /*
- * Let the user know when we're successful.
- */
- if (nPassPhraseDialog > 0) {
- sc = mySrvConfig(s);
- if (sc->nPassPhraseDialogType == SSL_PPTYPE_BUILTIN) {
- fprintf(stdout, "\n");
- fprintf(stdout, "Ok: Pass Phrase Dialog successful.\n");
- }
- }
-
- /*
- * Wipe out the used memory from the
- * pass phrase array and then deallocate it
- */
- if (!ssl_ds_array_isempty(aPassPhrase)) {
- ssl_ds_array_wipeout(aPassPhrase);
- ssl_ds_array_kill(aPassPhrase);
- ssl_log(s, SSL_LOG_INFO, "Init: Wiped out the queried pass phrases from memory");
- }
-
- return;
-}
-
-int ssl_pphrase_Handle_CB(char *buf, int bufsize, int verify)
-{
- SSLModConfigRec *mc = myModConfig();
- server_rec *s;
- pool *p;
- ssl_ds_array *aPassPhrase;
- SSLSrvConfigRec *sc;
- int *pnPassPhraseCur;
- char **cppPassPhraseCur;
- char *cpVHostID;
- char *cpAlgoType;
- int *pnPassPhraseDialog;
- int *pnPassPhraseDialogCur;
- BOOL *pbPassPhraseDialogOnce;
- int stderr_store;
- char **cpp;
- int len = -1;
-
- /*
- * Reconnect to the context of ssl_phrase_Handle()
- */
- s = myCtxVarGet(mc, 1, server_rec *);
- p = myCtxVarGet(mc, 2, pool *);
- aPassPhrase = myCtxVarGet(mc, 3, ssl_ds_array *);
- pnPassPhraseCur = myCtxVarGet(mc, 4, int *);
- cppPassPhraseCur = myCtxVarGet(mc, 5, char **);
- cpVHostID = myCtxVarGet(mc, 6, char *);
- cpAlgoType = myCtxVarGet(mc, 7, char *);
- pnPassPhraseDialog = myCtxVarGet(mc, 8, int *);
- pnPassPhraseDialogCur = myCtxVarGet(mc, 9, int *);
- pbPassPhraseDialogOnce = myCtxVarGet(mc, 10, BOOL *);
- sc = mySrvConfig(s);
-
- (*pnPassPhraseDialog)++;
- (*pnPassPhraseDialogCur)++;
-
- /*
- * When remembered pass phrases are available use them...
- */
- if ((cpp = (char **)ssl_ds_array_get(aPassPhrase, *pnPassPhraseCur)) != NULL) {
- ap_cpystrn(buf, *cpp, bufsize);
- len = strlen(buf);
- return len;
- }
-
- /*
- * Builtin dialog
- */
- if (sc->nPassPhraseDialogType == SSL_PPTYPE_BUILTIN) {
- char *prompt;
- int i;
-#ifdef WIN32
- FILE *con;
-#endif
-
- ssl_log(s, SSL_LOG_INFO,
- "Init: Requesting pass phrase via builtin terminal dialog");
-
- /*
- * Reconnect STDERR to terminal (here STDOUT) because
- * at our init stage Apache already connected STDERR
- * to the general error logfile.
- */
-#ifdef WIN32
- stderr_store = STDERR_FILENO_STORE;
-#else
- if ((stderr_store = open("/dev/null", O_WRONLY)) == -1)
- stderr_store = STDERR_FILENO_STORE;
-#endif
- dup2(STDERR_FILENO, stderr_store);
-#ifdef WIN32
- if ((con = fopen("con", "w")) != NULL)
- dup2(fileno(con), STDERR_FILENO);
- else
- dup2(STDOUT_FILENO, STDERR_FILENO);
-#else
- dup2(STDOUT_FILENO, STDERR_FILENO);
-#endif
-
- /*
- * The first time display a header to inform the user about what
- * program he actually speaks to, which module is responsible for
- * this terminal dialog and why to the hell he has to enter
- * something...
- */
- if (*pnPassPhraseDialog == 1) {
- fprintf(stderr, "%s mod_ssl/%s (Pass Phrase Dialog)\n",
- SERVER_BASEVERSION, MOD_SSL_VERSION);
- fprintf(stderr, "Some of your private key files are encrypted for security reasons.\n");
- fprintf(stderr, "In order to read them you have to provide us with the pass phrases.\n");
- }
- if (*pbPassPhraseDialogOnce) {
- *pbPassPhraseDialogOnce = FALSE;
- fprintf(stderr, "\n");
- fprintf(stderr, "Server %s (%s)\n", cpVHostID, cpAlgoType);
- }
-
- /*
- * Emulate the OpenSSL internal pass phrase dialog
- * (see crypto/pem/pem_lib.c:def_callback() for details)
- */
- prompt = "Enter pass phrase:";
- for (;;) {
- if ((i = EVP_read_pw_string(buf, bufsize, prompt, FALSE)) != 0) {
- PEMerr(PEM_F_DEF_CALLBACK,PEM_R_PROBLEMS_GETTING_PASSWORD);
- memset(buf, 0, (unsigned int)bufsize);
- return (-1);
- }
- len = strlen(buf);
- if (len < 1)
- fprintf(stderr, "Apache:mod_ssl:Error: Pass phrase empty (needs to be at least 1 character).\n");
- else
- break;
- }
-
- /*
- * Restore STDERR to Apache error logfile
- */
- dup2(stderr_store, STDERR_FILENO);
- close(stderr_store);
-#ifdef WIN32
- if (con != NULL)
- fclose(con);
-#endif
- }
-
- /*
- * Filter program
- */
- else if (sc->nPassPhraseDialogType == SSL_PPTYPE_FILTER) {
- char *cmd;
- char *result;
-
- ssl_log(s, SSL_LOG_INFO,
- "Init: Requesting pass phrase from dialog filter program (%s)",
- sc->szPassPhraseDialogPath);
-
- if (strchr(sc->szPassPhraseDialogPath, ' ') != NULL)
- cmd = ap_psprintf(p, "\"%s\" %s %s", sc->szPassPhraseDialogPath, cpVHostID, cpAlgoType);
- else
- cmd = ap_psprintf(p, "%s %s %s", sc->szPassPhraseDialogPath, cpVHostID, cpAlgoType);
- result = ssl_util_readfilter(s, p, cmd);
- ap_cpystrn(buf, result, bufsize);
- len = strlen(buf);
- }
-
- /*
- * Ok, we now have the pass phrase, so give it back
- */
- *cppPassPhraseCur = ap_pstrdup(p, buf);
-
- /*
- * And return it's length to OpenSSL...
- */
- return (len);
-}
-
diff --git a/modules/ssl/ssl_engine_rand.c b/modules/ssl/ssl_engine_rand.c
deleted file mode 100644
index afb49b4f5c..0000000000
--- a/modules/ssl/ssl_engine_rand.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/* _ _
-** _ __ ___ ___ __| | ___ ___| | mod_ssl
-** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
-** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
-** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
-** |_____|
-** ssl_engine_rand.c
-** Random Number Generator Seeding
-*/
-
-/* ====================================================================
- * Copyright (c) 1998-2001 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * 4. The names "mod_ssl" must not be used to endorse or promote
- * products derived from this software without prior written
- * permission. For written permission, please contact
- * rse@engelschall.com.
- *
- * 5. Products derived from this software may not be called "mod_ssl"
- * nor may "mod_ssl" appear in their names without prior
- * written permission of Ralf S. Engelschall.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
- /* ``The generation of random
- numbers is too important
- to be left to chance.'' */
-
-#include "mod_ssl.h"
-
-
-/* _________________________________________________________________
-**
-** Support for better seeding of SSL library's RNG
-** _________________________________________________________________
-*/
-
-static int ssl_rand_choosenum(int, int);
-static int ssl_rand_feedfp(pool *, FILE *, int);
-
-int ssl_rand_seed(server_rec *s, pool *p, ssl_rsctx_t nCtx, char *prefix)
-{
- SSLModConfigRec *mc;
- array_header *apRandSeed;
- ssl_randseed_t *pRandSeeds;
- ssl_randseed_t *pRandSeed;
- unsigned char stackdata[256];
- int nReq, nDone;
- FILE *fp;
- int i, n, l;
- time_t t;
- pid_t pid;
-
- mc = myModConfig();
- nReq = 0;
- nDone = 0;
- apRandSeed = mc->aRandSeed;
- pRandSeeds = (ssl_randseed_t *)apRandSeed->elts;
- for (i = 0; i < apRandSeed->nelts; i++) {
- pRandSeed = &pRandSeeds[i];
- if (pRandSeed->nCtx == nCtx) {
- nReq += pRandSeed->nBytes;
- if (pRandSeed->nSrc == SSL_RSSRC_FILE) {
- /*
- * seed in contents of an external file
- */
- if ((fp = ap_pfopen(p, pRandSeed->cpPath, "r")) == NULL)
- continue;
- nDone += ssl_rand_feedfp(p, fp, pRandSeed->nBytes);
- ap_pfclose(p, fp);
- }
- else if (pRandSeed->nSrc == SSL_RSSRC_EXEC) {
- /*
- * seed in contents generated by an external program
- */
- if ((fp = ssl_util_ppopen(s, p, ap_psprintf(p, "%s %d",
- pRandSeed->cpPath, pRandSeed->nBytes))) == NULL)
- continue;
- nDone += ssl_rand_feedfp(p, fp, pRandSeed->nBytes);
- ssl_util_ppclose(s, p, fp);
- }
-#if SSL_LIBRARY_VERSION >= 0x00905100
- else if (pRandSeed->nSrc == SSL_RSSRC_EGD) {
- /*
- * seed in contents provided by the external
- * Entropy Gathering Daemon (EGD)
- */
- if ((n = RAND_egd(pRandSeed->cpPath)) == -1)
- continue;
- nDone += n;
- }
-#endif
- else if (pRandSeed->nSrc == SSL_RSSRC_BUILTIN) {
- /*
- * seed in the current time (usually just 4 bytes)
- */
- t = time(NULL);
- l = sizeof(time_t);
- RAND_seed((unsigned char *)&t, l);
- nDone += l;
-
- /*
- * seed in the current process id (usually just 4 bytes)
- */
- pid = getpid();
- l = sizeof(pid_t);
- RAND_seed((unsigned char *)&pid, l);
- nDone += l;
-
- /*
- * seed in some current state of the run-time stack (128 bytes)
- */
- n = ssl_rand_choosenum(0, sizeof(stackdata)-128-1);
- RAND_seed(stackdata+n, 128);
- nDone += 128;
-
- /*
- * seed in an 1KB extract of the current scoreboard
- */
- if (ap_scoreboard_image != NULL) {
- n = ssl_rand_choosenum(0, SCOREBOARD_SIZE-1024-1);
- RAND_seed((unsigned char *)ap_scoreboard_image+n, 1024);
- nDone += 1024;
- }
- }
- }
- }
- ssl_log(s, SSL_LOG_INFO, "%sSeeding PRNG with %d bytes of entropy", prefix, nDone);
-
-#if SSL_LIBRARY_VERSION >= 0x00905100
- if (RAND_status() == 0)
- ssl_log(s, SSL_LOG_WARN, "%sPRNG still contains not sufficient entropy!", prefix);
-#endif
- return nDone;
-}
-
-#define BUFSIZE 8192
-
-static int ssl_rand_feedfp(pool *p, FILE *fp, int nReq)
-{
- int nDone;
- unsigned char caBuf[BUFSIZE];
- int nBuf;
- int nRead;
- int nTodo;
-
- nDone = 0;
- nRead = BUFSIZE;
- nTodo = nReq;
- while (1) {
- if (nReq > 0)
- nRead = (nTodo < BUFSIZE ? nTodo : BUFSIZE);
- if ((nBuf = (int)fread(caBuf, 1, nRead, fp)) <= 0)
- break;
- RAND_seed(caBuf, nBuf);
- nDone += nBuf;
- if (nReq > 0) {
- nTodo -= nBuf;
- if (nTodo <= 0)
- break;
- }
- }
- return nDone;
-}
-
-static int ssl_rand_choosenum(int l, int h)
-{
- int i;
- char buf[50];
-
- srand((unsigned int)time(NULL));
- ap_snprintf(buf, sizeof(buf), "%.0f",
- (((double)(rand()%RAND_MAX)/RAND_MAX)*(h-l)));
- i = atoi(buf)+1;
- if (i < l) i = l;
- if (i > h) i = h;
- return i;
-}
-
diff --git a/modules/ssl/ssl_engine_vars.c b/modules/ssl/ssl_engine_vars.c
deleted file mode 100644
index c0755a5ec8..0000000000
--- a/modules/ssl/ssl_engine_vars.c
+++ /dev/null
@@ -1,615 +0,0 @@
-/* _ _
-** _ __ ___ ___ __| | ___ ___| | mod_ssl
-** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
-** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
-** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
-** |_____|
-** ssl_engine_vars.c
-** Variable Lookup Facility
-*/
-
-/* ====================================================================
- * Copyright (c) 1998-2001 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * 4. The names "mod_ssl" must not be used to endorse or promote
- * products derived from this software without prior written
- * permission. For written permission, please contact
- * rse@engelschall.com.
- *
- * 5. Products derived from this software may not be called "mod_ssl"
- * nor may "mod_ssl" appear in their names without prior
- * written permission of Ralf S. Engelschall.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
- /* ``Those of you who think they
- know everything are very annoying
- to those of us who do.''
- -- Unknown */
-#include "mod_ssl.h"
-
-
-/* _________________________________________________________________
-**
-** Variable Lookup
-** _________________________________________________________________
-*/
-
-static char *ssl_var_lookup_header(pool *p, request_rec *r, const char *name);
-static char *ssl_var_lookup_ssl(pool *p, conn_rec *c, char *var);
-static char *ssl_var_lookup_ssl_cert(pool *p, X509 *xs, char *var);
-static char *ssl_var_lookup_ssl_cert_dn(pool *p, X509_NAME *xsname, char *var);
-static char *ssl_var_lookup_ssl_cert_valid(pool *p, ASN1_UTCTIME *tm);
-static char *ssl_var_lookup_ssl_cert_serial(pool *p, X509 *xs);
-static char *ssl_var_lookup_ssl_cert_chain(pool *p, STACK_OF(X509) *sk, char *var);
-static char *ssl_var_lookup_ssl_cert_PEM(pool *p, X509 *xs);
-static char *ssl_var_lookup_ssl_cert_verify(pool *p, conn_rec *c);
-static char *ssl_var_lookup_ssl_cipher(pool *p, conn_rec *c, char *var);
-static void ssl_var_lookup_ssl_cipher_bits(SSL *ssl, int *usekeysize, int *algkeysize);
-static char *ssl_var_lookup_ssl_version(pool *p, char *var);
-
-void ssl_var_register(void)
-{
- ap_hook_configure("ap::mod_ssl::var_lookup",
- AP_HOOK_SIG6(ptr,ptr,ptr,ptr,ptr,ptr), AP_HOOK_DECLINE(NULL));
- ap_hook_register("ap::mod_ssl::var_lookup",
- ssl_var_lookup, AP_HOOK_NOCTX);
- return;
-}
-
-void ssl_var_unregister(void)
-{
- ap_hook_unregister("ap::mod_ssl::var_lookup", ssl_var_lookup);
- return;
-}
-
-char *ssl_var_lookup(pool *p, server_rec *s, conn_rec *c, request_rec *r, char *var)
-{
- SSLModConfigRec *mc = myModConfig();
- char *result;
- BOOL resdup;
- time_t tc;
- struct tm *tm;
-
- result = NULL;
- resdup = TRUE;
-
- /*
- * When no pool is given try to find one
- */
- if (p == NULL) {
- if (r != NULL)
- p = r->pool;
- else if (c != NULL)
- p = c->pool;
- else
- p = mc->pPool;
- }
-
- /*
- * Request dependent stuff
- */
- if (r != NULL) {
- if (strcEQ(var, "HTTP_USER_AGENT"))
- result = ssl_var_lookup_header(p, r, "User-Agent");
- else if (strcEQ(var, "HTTP_REFERER"))
- result = ssl_var_lookup_header(p, r, "Referer");
- else if (strcEQ(var, "HTTP_COOKIE"))
- result = ssl_var_lookup_header(p, r, "Cookie");
- else if (strcEQ(var, "HTTP_FORWARDED"))
- result = ssl_var_lookup_header(p, r, "Forwarded");
- else if (strcEQ(var, "HTTP_HOST"))
- result = ssl_var_lookup_header(p, r, "Host");
- else if (strcEQ(var, "HTTP_PROXY_CONNECTION"))
- result = ssl_var_lookup_header(p, r, "Proxy-Connection");
- else if (strcEQ(var, "HTTP_ACCEPT"))
- result = ssl_var_lookup_header(p, r, "Accept");
- else if (strlen(var) > 5 && strcEQn(var, "HTTP:", 5))
- /* all other headers from which we are still not know about */
- result = ssl_var_lookup_header(p, r, var+5);
- else if (strcEQ(var, "THE_REQUEST"))
- result = r->the_request;
- else if (strcEQ(var, "REQUEST_METHOD"))
- result = (char *)(r->method);
- else if (strcEQ(var, "REQUEST_SCHEME"))
- result = ap_http_method(r);
- else if (strcEQ(var, "REQUEST_URI"))
- result = r->uri;
- else if (strcEQ(var, "SCRIPT_FILENAME") ||
- strcEQ(var, "REQUEST_FILENAME"))
- result = r->filename;
- else if (strcEQ(var, "PATH_INFO"))
- result = r->path_info;
- else if (strcEQ(var, "QUERY_STRING"))
- result = r->args;
- else if (strcEQ(var, "REMOTE_HOST"))
- result = (char *)ap_get_remote_host(r->connection,
- r->per_dir_config, REMOTE_NAME);
- else if (strcEQ(var, "REMOTE_IDENT"))
- result = (char *)ap_get_remote_logname(r);
- else if (strcEQ(var, "IS_SUBREQ"))
- result = (r->main != NULL ? "true" : "false");
- else if (strcEQ(var, "DOCUMENT_ROOT"))
- result = (char *)ap_document_root(r);
- else if (strcEQ(var, "SERVER_ADMIN"))
- result = r->server->server_admin;
- else if (strcEQ(var, "SERVER_NAME"))
- result = (char *)ap_get_server_name(r);
- else if (strcEQ(var, "SERVER_PORT"))
- result = ap_psprintf(p, "%u", ap_get_server_port(r));
- else if (strcEQ(var, "SERVER_PROTOCOL"))
- result = r->protocol;
- }
-
- /*
- * Connection stuff
- */
- if (result == NULL && c != NULL) {
- if (strcEQ(var, "REMOTE_ADDR"))
- result = c->remote_ip;
- else if (strcEQ(var, "REMOTE_USER"))
- result = c->user;
- else if (strcEQ(var, "AUTH_TYPE"))
- result = c->ap_auth_type;
- else if (strlen(var) > 4 && strcEQn(var, "SSL_", 4))
- result = ssl_var_lookup_ssl(p, c, var+4);
- else if (strcEQ(var, "HTTPS")) {
- if (ap_ctx_get(c->client->ctx, "ssl") != NULL)
- result = "on";
- else
- result = "off";
- }
- }
-
- /*
- * Totally independent stuff
- */
- if (result == NULL) {
- if (strlen(var) > 12 && strcEQn(var, "SSL_VERSION_", 12))
- result = ssl_var_lookup_ssl_version(p, var+12);
- else if (strcEQ(var, "SERVER_SOFTWARE"))
- result = (char *)ap_get_server_version();
- else if (strcEQ(var, "API_VERSION")) {
- result = ap_psprintf(p, "%d", MODULE_MAGIC_NUMBER);
- resdup = FALSE;
- }
- else if (strcEQ(var, "TIME_YEAR")) {
- tc = time(NULL);
- tm = localtime(&tc);
- result = ap_psprintf(p, "%02d%02d",
- (tm->tm_year / 100) + 19, tm->tm_year % 100);
- resdup = FALSE;
- }
-#define MKTIMESTR(format, tmfield) \
- tc = time(NULL); \
- tm = localtime(&tc); \
- result = ap_psprintf(p, format, tm->tmfield); \
- resdup = FALSE;
- else if (strcEQ(var, "TIME_MON")) {
- MKTIMESTR("%02d", tm_mon+1)
- }
- else if (strcEQ(var, "TIME_DAY")) {
- MKTIMESTR("%02d", tm_mday)
- }
- else if (strcEQ(var, "TIME_HOUR")) {
- MKTIMESTR("%02d", tm_hour)
- }
- else if (strcEQ(var, "TIME_MIN")) {
- MKTIMESTR("%02d", tm_min)
- }
- else if (strcEQ(var, "TIME_SEC")) {
- MKTIMESTR("%02d", tm_sec)
- }
- else if (strcEQ(var, "TIME_WDAY")) {
- MKTIMESTR("%d", tm_wday)
- }
- else if (strcEQ(var, "TIME")) {
- tc = time(NULL);
- tm = localtime(&tc);
- result = ap_psprintf(p,
- "%02d%02d%02d%02d%02d%02d%02d", (tm->tm_year / 100) + 19,
- (tm->tm_year % 100), tm->tm_mon+1, tm->tm_mday,
- tm->tm_hour, tm->tm_min, tm->tm_sec);
- resdup = FALSE;
- }
- /* all other env-variables from the parent Apache process */
- else if (strlen(var) > 4 && strcEQn(var, "ENV:", 4)) {
- result = (char *)ap_table_get(r->notes, var+4);
- if (result == NULL)
- result = (char *)ap_table_get(r->subprocess_env, var+4);
- if (result == NULL)
- result = getenv(var+4);
- }
- }
-
- if (result != NULL && resdup)
- result = ap_pstrdup(p, result);
- if (result == NULL)
- result = "";
- return result;
-}
-
-static char *ssl_var_lookup_header(pool *p, request_rec *r, const char *name)
-{
- array_header *hdrs_arr;
- table_entry *hdrs;
- int i;
-
- hdrs_arr = ap_table_elts(r->headers_in);
- hdrs = (table_entry *)hdrs_arr->elts;
- for (i = 0; i < hdrs_arr->nelts; ++i) {
- if (hdrs[i].key == NULL)
- continue;
- if (strcEQ(hdrs[i].key, name))
- return ap_pstrdup(p, hdrs[i].val);
- }
- return NULL;
-}
-
-static char *ssl_var_lookup_ssl(pool *p, conn_rec *c, char *var)
-{
- char *result;
- X509 *xs;
- STACK_OF(X509) *sk;
- SSL *ssl;
-
- result = NULL;
-
- ssl = ap_ctx_get(c->client->ctx, "ssl");
- if (strlen(var) > 8 && strcEQn(var, "VERSION_", 8)) {
- result = ssl_var_lookup_ssl_version(p, var+8);
- }
- else if (ssl != NULL && strcEQ(var, "PROTOCOL")) {
- result = (char *)SSL_get_version(ssl);
- }
- else if (ssl != NULL && strcEQ(var, "SESSION_ID")) {
- SSL_SESSION *pSession = SSL_get_session(ssl);
- result = ap_pstrdup(p, SSL_SESSION_id2sz(pSession->session_id,
- pSession->session_id_length));
- }
- else if (ssl != NULL && strlen(var) >= 6 && strcEQn(var, "CIPHER", 6)) {
- result = ssl_var_lookup_ssl_cipher(p, c, var+6);
- }
- else if (ssl != NULL && strlen(var) > 18 && strcEQn(var, "CLIENT_CERT_CHAIN_", 18)) {
- sk = SSL_get_peer_cert_chain(ssl);
- result = ssl_var_lookup_ssl_cert_chain(p, sk, var+17);
- }
- else if (ssl != NULL && strcEQ(var, "CLIENT_VERIFY")) {
- result = ssl_var_lookup_ssl_cert_verify(p, c);
- }
- else if (ssl != NULL && strlen(var) > 7 && strcEQn(var, "CLIENT_", 7)) {
- if ((xs = SSL_get_peer_certificate(ssl)) != NULL)
- result = ssl_var_lookup_ssl_cert(p, xs, var+7);
- }
- else if (ssl != NULL && strlen(var) > 7 && strcEQn(var, "SERVER_", 7)) {
- if ((xs = SSL_get_certificate(ssl)) != NULL)
- result = ssl_var_lookup_ssl_cert(p, xs, var+7);
- }
- return result;
-}
-
-static char *ssl_var_lookup_ssl_cert(pool *p, X509 *xs, char *var)
-{
- char *result;
- BOOL resdup;
- X509_NAME *xsname;
- int nid;
- char *cp;
-
- result = NULL;
- resdup = TRUE;
-
- if (strcEQ(var, "M_VERSION")) {
- result = ap_psprintf(p, "%lu", X509_get_version(xs)+1);
- resdup = FALSE;
- }
- else if (strcEQ(var, "M_SERIAL")) {
- result = ssl_var_lookup_ssl_cert_serial(p, xs);
- }
- else if (strcEQ(var, "V_START")) {
- result = ssl_var_lookup_ssl_cert_valid(p, X509_get_notBefore(xs));
- }
- else if (strcEQ(var, "V_END")) {
- result = ssl_var_lookup_ssl_cert_valid(p, X509_get_notAfter(xs));
- }
- else if (strcEQ(var, "S_DN")) {
- xsname = X509_get_subject_name(xs);
- cp = X509_NAME_oneline(xsname, NULL, 0);
- result = ap_pstrdup(p, cp);
- free(cp);
- resdup = FALSE;
- }
- else if (strlen(var) > 5 && strcEQn(var, "S_DN_", 5)) {
- xsname = X509_get_subject_name(xs);
- result = ssl_var_lookup_ssl_cert_dn(p, xsname, var+5);
- resdup = FALSE;
- }
- else if (strcEQ(var, "I_DN")) {
- xsname = X509_get_issuer_name(xs);
- cp = X509_NAME_oneline(xsname, NULL, 0);
- result = ap_pstrdup(p, cp);
- free(cp);
- resdup = FALSE;
- }
- else if (strlen(var) > 5 && strcEQn(var, "I_DN_", 5)) {
- xsname = X509_get_issuer_name(xs);
- result = ssl_var_lookup_ssl_cert_dn(p, xsname, var+5);
- resdup = FALSE;
- }
- else if (strcEQ(var, "A_SIG")) {
- nid = OBJ_obj2nid(xs->cert_info->signature->algorithm);
- result = ap_pstrdup(p, (nid == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(nid));
- resdup = FALSE;
- }
- else if (strcEQ(var, "A_KEY")) {
- nid = OBJ_obj2nid(xs->cert_info->key->algor->algorithm);
- result = ap_pstrdup(p, (nid == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(nid));
- resdup = FALSE;
- }
- else if (strcEQ(var, "CERT")) {
- result = ssl_var_lookup_ssl_cert_PEM(p, xs);
- }
-
- if (result != NULL && resdup)
- result = ap_pstrdup(p, result);
- return result;
-}
-
-static const struct {
- char *name;
- int nid;
-} ssl_var_lookup_ssl_cert_dn_rec[] = {
- { "C", NID_countryName },
- { "ST", NID_stateOrProvinceName }, /* officially (RFC2156) */
- { "SP", NID_stateOrProvinceName }, /* compatibility (SSLeay) */
- { "L", NID_localityName },
- { "O", NID_organizationName },
- { "OU", NID_organizationalUnitName },
- { "CN", NID_commonName },
- { "T", NID_title },
- { "I", NID_initials },
- { "G", NID_givenName },
- { "S", NID_surname },
- { "D", NID_description },
- { "UID", NID_uniqueIdentifier },
- { "Email", NID_pkcs9_emailAddress },
- { NULL, 0 }
-};
-
-static char *ssl_var_lookup_ssl_cert_dn(pool *p, X509_NAME *xsname, char *var)
-{
- char *result;
- X509_NAME_ENTRY *xsne;
- int i, j, n;
-
- result = NULL;
-
- for (i = 0; ssl_var_lookup_ssl_cert_dn_rec[i].name != NULL; i++) {
- if (strEQ(var, ssl_var_lookup_ssl_cert_dn_rec[i].name)) {
- for (j = 0; j < sk_X509_NAME_ENTRY_num(xsname->entries); j++) {
- xsne = sk_X509_NAME_ENTRY_value(xsname->entries, j);
- n = OBJ_obj2nid(xsne->object);
- if (n == ssl_var_lookup_ssl_cert_dn_rec[i].nid) {
- result = ap_palloc(p, xsne->value->length+1);
- ap_cpystrn(result, (char *)xsne->value->data, xsne->value->length+1);
-#ifdef CHARSET_EBCDIC
- ascii2ebcdic(result, result, xsne->value->length);
-#endif /* CHARSET_EBCDIC */
- result[xsne->value->length] = NUL;
- break;
- }
- }
- break;
- }
- }
- return result;
-}
-
-static char *ssl_var_lookup_ssl_cert_valid(pool *p, ASN1_UTCTIME *tm)
-{
- char *result;
- BIO* bio;
- int n;
-
- if ((bio = BIO_new(BIO_s_mem())) == NULL)
- return NULL;
- ASN1_UTCTIME_print(bio, tm);
- n = BIO_pending(bio);
- result = ap_pcalloc(p, n+1);
- n = BIO_read(bio, result, n);
- result[n] = NUL;
- BIO_free(bio);
- return result;
-}
-
-static char *ssl_var_lookup_ssl_cert_serial(pool *p, X509 *xs)
-{
- char *result;
- BIO *bio;
- int n;
-
- if ((bio = BIO_new(BIO_s_mem())) == NULL)
- return NULL;
- i2a_ASN1_INTEGER(bio, X509_get_serialNumber(xs));
- n = BIO_pending(bio);
- result = ap_pcalloc(p, n+1);
- n = BIO_read(bio, result, n);
- result[n] = NUL;
- BIO_free(bio);
- return result;
-}
-
-static char *ssl_var_lookup_ssl_cert_chain(pool *p, STACK_OF(X509) *sk, char *var)
-{
- char *result;
- X509 *xs;
- int n;
-
- result = NULL;
-
- if (strspn(var, "0123456789") == strlen(var)) {
- n = atoi(var);
- if (n < sk_X509_num(sk)) {
- xs = sk_X509_value(sk, n);
- result = ssl_var_lookup_ssl_cert_PEM(p, xs);
- }
- }
-
- return result;
-}
-
-static char *ssl_var_lookup_ssl_cert_PEM(pool *p, X509 *xs)
-{
- char *result;
- BIO *bio;
- int n;
-
- if ((bio = BIO_new(BIO_s_mem())) == NULL)
- return NULL;
- PEM_write_bio_X509(bio, xs);
- n = BIO_pending(bio);
- result = ap_pcalloc(p, n+1);
- n = BIO_read(bio, result, n);
- result[n] = NUL;
- BIO_free(bio);
- return result;
-}
-
-static char *ssl_var_lookup_ssl_cert_verify(pool *p, conn_rec *c)
-{
- char *result;
- long vrc;
- char *verr;
- char *vinfo;
- SSL *ssl;
- X509 *xs;
-
- result = NULL;
- ssl = ap_ctx_get(c->client->ctx, "ssl");
- verr = ap_ctx_get(c->client->ctx, "ssl::verify::error");
- vinfo = ap_ctx_get(c->client->ctx, "ssl::verify::info");
- vrc = SSL_get_verify_result(ssl);
- xs = SSL_get_peer_certificate(ssl);
-
- if (vrc == X509_V_OK && verr == NULL && vinfo == NULL && xs == NULL)
- /* no client verification done at all */
- result = "NONE";
- else if (vrc == X509_V_OK && verr == NULL && vinfo == NULL && xs != NULL)
- /* client verification done successful */
- result = "SUCCESS";
- else if (vrc == X509_V_OK && vinfo != NULL && strEQ(vinfo, "GENEROUS"))
- /* client verification done in generous way */
- result = "GENEROUS";
- else
- /* client verification failed */
- result = ap_psprintf(p, "FAILED:%s", verr);
- return result;
-}
-
-static char *ssl_var_lookup_ssl_cipher(pool *p, conn_rec *c, char *var)
-{
- char *result;
- BOOL resdup;
- int usekeysize, algkeysize;
- SSL *ssl;
-
- result = NULL;
- resdup = TRUE;
-
- ssl = ap_ctx_get(c->client->ctx, "ssl");
- ssl_var_lookup_ssl_cipher_bits(ssl, &usekeysize, &algkeysize);
-
- if (strEQ(var, ""))
- result = (ssl != NULL ? (char *)SSL_get_cipher_name(ssl) : NULL);
- else if (strcEQ(var, "_EXPORT"))
- result = (usekeysize < 56 ? "true" : "false");
- else if (strcEQ(var, "_USEKEYSIZE")) {
- result = ap_psprintf(p, "%d", usekeysize);
- resdup = FALSE;
- }
- else if (strcEQ(var, "_ALGKEYSIZE")) {
- result = ap_psprintf(p, "%d", algkeysize);
- resdup = FALSE;
- }
-
- if (result != NULL && resdup)
- result = ap_pstrdup(p, result);
- return result;
-}
-
-static void ssl_var_lookup_ssl_cipher_bits(SSL *ssl, int *usekeysize, int *algkeysize)
-{
- SSL_CIPHER *cipher;
-
- *usekeysize = 0;
- *algkeysize = 0;
- if (ssl != NULL)
- if ((cipher = SSL_get_current_cipher(ssl)) != NULL)
- *usekeysize = SSL_CIPHER_get_bits(cipher, algkeysize);
- return;
-}
-
-static char *ssl_var_lookup_ssl_version(pool *p, char *var)
-{
- char *result;
- char *cp, *cp2;
-
- result = NULL;
-
- if (strEQ(var, "PRODUCT")) {
-#if defined(SSL_PRODUCT_NAME) && defined(SSL_PRODUCT_VERSION)
- result = ap_psprintf(p, "%s/%s", SSL_PRODUCT_NAME, SSL_PRODUCT_VERSION);
-#else
- result = NULL;
-#endif
- }
- else if (strEQ(var, "INTERFACE")) {
- result = ap_psprintf(p, "mod_ssl/%s", MOD_SSL_VERSION);
- }
- else if (strEQ(var, "LIBRARY")) {
- result = ap_pstrdup(p, SSL_LIBRARY_TEXT);
- if ((cp = strchr(result, ' ')) != NULL) {
- *cp = '/';
- if ((cp2 = strchr(cp, ' ')) != NULL)
- *cp2 = NUL;
- }
- }
- return result;
-}
-
diff --git a/modules/ssl/ssl_expr.c b/modules/ssl/ssl_expr.c
deleted file mode 100644
index 49ab873ded..0000000000
--- a/modules/ssl/ssl_expr.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/* _ _
-** _ __ ___ ___ __| | ___ ___| | mod_ssl
-** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
-** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
-** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
-** |_____|
-** ssl_expr.c
-** Expression Handling
-*/
-
-/* ====================================================================
- * Copyright (c) 1998-2001 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * 4. The names "mod_ssl" must not be used to endorse or promote
- * products derived from this software without prior written
- * permission. For written permission, please contact
- * rse@engelschall.com.
- *
- * 5. Products derived from this software may not be called "mod_ssl"
- * nor may "mod_ssl" appear in their names without prior
- * written permission of Ralf S. Engelschall.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
- /* ``It is hard to fly with
- the eagles when you work
- with the turkeys.''
- -- Unknown */
-#include "mod_ssl.h"
-
-
-/* _________________________________________________________________
-**
-** Expression Handling
-** _________________________________________________________________
-*/
-
-ssl_expr_info_type ssl_expr_info;
-char *ssl_expr_error;
-
-ssl_expr *ssl_expr_comp(pool *p, char *expr)
-{
- ssl_expr_info.pool = p;
- ssl_expr_info.inputbuf = expr;
- ssl_expr_info.inputlen = strlen(expr);
- ssl_expr_info.inputptr = ssl_expr_info.inputbuf;
- ssl_expr_info.expr = FALSE;
-
- ssl_expr_error = NULL;
- if (ssl_expr_yyparse())
- return NULL;
- return ssl_expr_info.expr;
-}
-
-char *ssl_expr_get_error(void)
-{
- if (ssl_expr_error == NULL)
- return "";
- return ssl_expr_error;
-}
-
-ssl_expr *ssl_expr_make(ssl_expr_node_op op, void *a1, void *a2)
-{
- ssl_expr *node;
-
- node = (ssl_expr *)ap_palloc(ssl_expr_info.pool, sizeof(ssl_expr));
- node->node_op = op;
- node->node_arg1 = (char *)a1;
- node->node_arg2 = (char *)a2;
- return node;
-}
-
-int ssl_expr_exec(request_rec *r, ssl_expr *expr)
-{
- BOOL rc;
-
- rc = ssl_expr_eval(r, expr);
- if (ssl_expr_error != NULL)
- return (-1);
- else
- return (rc ? 1 : 0);
-}
-
diff --git a/modules/ssl/ssl_expr.h b/modules/ssl/ssl_expr.h
deleted file mode 100644
index 419bb02192..0000000000
--- a/modules/ssl/ssl_expr.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/* _ _
-** _ __ ___ ___ __| | ___ ___| | mod_ssl
-** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
-** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
-** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
-** |_____|
-** ssl_expr.h
-** Expression Handling (Header)
-*/
-
-/* ====================================================================
- * Copyright (c) 1998-2001 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * 4. The names "mod_ssl" must not be used to endorse or promote
- * products derived from this software without prior written
- * permission. For written permission, please contact
- * rse@engelschall.com.
- *
- * 5. Products derived from this software may not be called "mod_ssl"
- * nor may "mod_ssl" appear in their names without prior
- * written permission of Ralf S. Engelschall.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
-
- /* ``May all your PUSHes be POPed.'' */
-
-#ifndef SSL_EXPR_H
-#define SSL_EXPR_H
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef TRUE
-#define TRUE !FALSE
-#endif
-
-#ifndef YY_NULL
-#define YY_NULL 0
-#endif
-
-#ifndef MIN
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#endif
-
-#ifndef BOOL
-#define BOOL unsigned int
-#endif
-
-#ifndef NULL
-#define NULL (void *)0
-#endif
-
-#ifndef NUL
-#define NUL '\0'
-#endif
-
-#ifndef YYDEBUG
-#define YYDEBUG 0
-#endif
-
-typedef enum {
- op_NOP, op_ListElement,
- op_True, op_False, op_Not, op_Or, op_And, op_Comp,
- op_EQ, op_NE, op_LT, op_LE, op_GT, op_GE, op_IN, op_REG, op_NRE,
- op_Digit, op_String, op_Regex, op_Var, op_Func
-} ssl_expr_node_op;
-
-typedef struct {
- ssl_expr_node_op node_op;
- void *node_arg1;
- void *node_arg2;
-} ssl_expr_node;
-
-typedef ssl_expr_node ssl_expr;
-
-typedef struct {
- pool *pool;
- char *inputbuf;
- int inputlen;
- char *inputptr;
- ssl_expr *expr;
-} ssl_expr_info_type;
-
-extern ssl_expr_info_type ssl_expr_info;
-extern char *ssl_expr_error;
-
-#define yylval ssl_expr_yylval
-#define yyerror ssl_expr_yyerror
-#define yyinput ssl_expr_yyinput
-
-extern int ssl_expr_yyparse(void);
-extern int ssl_expr_yyerror(char *);
-extern int ssl_expr_yylex(void);
-
-extern ssl_expr *ssl_expr_comp(pool *, char *);
-extern int ssl_expr_exec(request_rec *, ssl_expr *);
-extern char *ssl_expr_get_error(void);
-extern ssl_expr *ssl_expr_make(ssl_expr_node_op, void *, void *);
-extern BOOL ssl_expr_eval(request_rec *, ssl_expr *);
-
-#endif /* SSL_EXPR_H */
diff --git a/modules/ssl/ssl_expr_eval.c b/modules/ssl/ssl_expr_eval.c
deleted file mode 100644
index d8c5ea5f9e..0000000000
--- a/modules/ssl/ssl_expr_eval.c
+++ /dev/null
@@ -1,282 +0,0 @@
-/* _ _
-** _ __ ___ ___ __| | ___ ___| | mod_ssl
-** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
-** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
-** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
-** |_____|
-** ssl_expr_eval.c
-** Expression Evaluation
-*/
-
-/* ====================================================================
- * Copyright (c) 1998-2001 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * 4. The names "mod_ssl" must not be used to endorse or promote
- * products derived from this software without prior written
- * permission. For written permission, please contact
- * rse@engelschall.com.
- *
- * 5. Products derived from this software may not be called "mod_ssl"
- * nor may "mod_ssl" appear in their names without prior
- * written permission of Ralf S. Engelschall.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
- /* ``Make love,
- not software!''
- -- Unknown */
-#include "mod_ssl.h"
-
-
-/* _________________________________________________________________
-**
-** Expression Evaluation
-** _________________________________________________________________
-*/
-
-static BOOL ssl_expr_eval_comp(request_rec *, ssl_expr *);
-static char *ssl_expr_eval_word(request_rec *, ssl_expr *);
-static char *ssl_expr_eval_func_file(request_rec *, char *);
-static int ssl_expr_eval_strcmplex(char *, char *);
-
-BOOL ssl_expr_eval(request_rec *r, ssl_expr *node)
-{
- switch (node->node_op) {
- case op_True: {
- return TRUE;
- }
- case op_False: {
- return FALSE;
- }
- case op_Not: {
- ssl_expr *e = (ssl_expr *)node->node_arg1;
- return (!ssl_expr_eval(r, e));
- }
- case op_Or: {
- ssl_expr *e1 = (ssl_expr *)node->node_arg1;
- ssl_expr *e2 = (ssl_expr *)node->node_arg2;
- return (ssl_expr_eval(r, e1) || ssl_expr_eval(r, e2));
- }
- case op_And: {
- ssl_expr *e1 = (ssl_expr *)node->node_arg1;
- ssl_expr *e2 = (ssl_expr *)node->node_arg2;
- return (ssl_expr_eval(r, e1) && ssl_expr_eval(r, e2));
- }
- case op_Comp: {
- ssl_expr *e = (ssl_expr *)node->node_arg1;
- return ssl_expr_eval_comp(r, e);
- }
- default: {
- ssl_expr_error = "Internal evaluation error: Unknown expression node";
- return FALSE;
- }
- }
-}
-
-static BOOL ssl_expr_eval_comp(request_rec *r, ssl_expr *node)
-{
- switch (node->node_op) {
- case op_EQ: {
- ssl_expr *e1 = (ssl_expr *)node->node_arg1;
- ssl_expr *e2 = (ssl_expr *)node->node_arg2;
- return (strcmp(ssl_expr_eval_word(r, e1), ssl_expr_eval_word(r, e2)) == 0);
- }
- case op_NE: {
- ssl_expr *e1 = (ssl_expr *)node->node_arg1;
- ssl_expr *e2 = (ssl_expr *)node->node_arg2;
- return (strcmp(ssl_expr_eval_word(r, e1), ssl_expr_eval_word(r, e2)) != 0);
- }
- case op_LT: {
- ssl_expr *e1 = (ssl_expr *)node->node_arg1;
- ssl_expr *e2 = (ssl_expr *)node->node_arg2;
- return (ssl_expr_eval_strcmplex(ssl_expr_eval_word(r, e1), ssl_expr_eval_word(r, e2)) < 0);
- }
- case op_LE: {
- ssl_expr *e1 = (ssl_expr *)node->node_arg1;
- ssl_expr *e2 = (ssl_expr *)node->node_arg2;
- return (ssl_expr_eval_strcmplex(ssl_expr_eval_word(r, e1), ssl_expr_eval_word(r, e2)) <= 0);
- }
- case op_GT: {
- ssl_expr *e1 = (ssl_expr *)node->node_arg1;
- ssl_expr *e2 = (ssl_expr *)node->node_arg2;
- return (ssl_expr_eval_strcmplex(ssl_expr_eval_word(r, e1), ssl_expr_eval_word(r, e2)) > 0);
- }
- case op_GE: {
- ssl_expr *e1 = (ssl_expr *)node->node_arg1;
- ssl_expr *e2 = (ssl_expr *)node->node_arg2;
- return (ssl_expr_eval_strcmplex(ssl_expr_eval_word(r, e1), ssl_expr_eval_word(r, e2)) >= 0);
- }
- case op_IN: {
- ssl_expr *e1 = (ssl_expr *)node->node_arg1;
- ssl_expr *e2 = (ssl_expr *)node->node_arg2;
- ssl_expr *e3;
- char *w1 = ssl_expr_eval_word(r, e1);
- BOOL found = FALSE;
- do {
- e3 = (ssl_expr *)e2->node_arg1;
- e2 = (ssl_expr *)e2->node_arg2;
- if (strcmp(w1, ssl_expr_eval_word(r, e3)) == 0) {
- found = TRUE;
- break;
- }
- } while (e2 != NULL);
- return found;
- }
- case op_REG: {
- ssl_expr *e1;
- ssl_expr *e2;
- char *word;
- regex_t *regex;
-
- e1 = (ssl_expr *)node->node_arg1;
- e2 = (ssl_expr *)node->node_arg2;
- word = ssl_expr_eval_word(r, e1);
- regex = (regex_t *)(e2->node_arg1);
- return (regexec(regex, word, 0, NULL, 0) == 0);
- }
- case op_NRE: {
- ssl_expr *e1;
- ssl_expr *e2;
- char *word;
- regex_t *regex;
-
- e1 = (ssl_expr *)node->node_arg1;
- e2 = (ssl_expr *)node->node_arg2;
- word = ssl_expr_eval_word(r, e1);
- regex = (regex_t *)(e2->node_arg1);
- return !(regexec(regex, word, 0, NULL, 0) == 0);
- }
- default: {
- ssl_expr_error = "Internal evaluation error: Unknown expression node";
- return FALSE;
- }
- }
-}
-
-static char *ssl_expr_eval_word(request_rec *r, ssl_expr *node)
-{
- switch (node->node_op) {
- case op_Digit: {
- char *string = (char *)node->node_arg1;
- return string;
- }
- case op_String: {
- char *string = (char *)node->node_arg1;
- return string;
- }
- case op_Var: {
- char *var = (char *)node->node_arg1;
- char *val = ssl_var_lookup(r->pool, r->server, r->connection, r, var);
- return (val == NULL ? "" : val);
- }
- case op_Func: {
- char *name = (char *)node->node_arg1;
- ssl_expr *args = (ssl_expr *)node->node_arg2;
- if (strEQ(name, "file"))
- return ssl_expr_eval_func_file(r, (char *)(args->node_arg1));
- else {
- ssl_expr_error = "Internal evaluation error: Unknown function name";
- return "";
- }
- }
- default: {
- ssl_expr_error = "Internal evaluation error: Unknown expression node";
- return FALSE;
- }
- }
-}
-
-static char *ssl_expr_eval_func_file(request_rec *r, char *filename)
-{
- FILE *fp;
- char *buf;
- int len;
-
- if ((fp = ap_pfopen(r->pool, filename, "r")) == NULL) {
- ssl_expr_error = "Cannot open file";
- return "";
- }
- fseek(fp, 0, SEEK_END);
- len = ftell(fp);
- if (len == 0) {
- buf = (char *)ap_palloc(r->pool, sizeof(char) * 1);
- *buf = NUL;
- }
- else {
- if ((buf = (char *)ap_palloc(r->pool, sizeof(char) * len+1)) == NULL) {
- ssl_expr_error = "Cannot allocate memory";
- ap_pfclose(r->pool, fp);
- return "";
- }
- fseek(fp, 0, SEEK_SET);
- if (fread(buf, len, 1, fp) == 0) {
- ssl_expr_error = "Cannot read from file";
- fclose(fp);
- return ("");
- }
- buf[len] = NUL;
- }
- ap_pfclose(r->pool, fp);
- return buf;
-}
-
-/* a variant of strcmp(3) which works correctly also for number strings */
-static int ssl_expr_eval_strcmplex(char *cpNum1, char *cpNum2)
-{
- int i, n1, n2;
-
- if (cpNum1 == NULL)
- return -1;
- if (cpNum2 == NULL)
- return +1;
- n1 = strlen(cpNum1);
- n2 = strlen(cpNum2);
- if (n1 > n2)
- return 1;
- if (n1 < n2)
- return -1;
- for (i = 0; i < n1; i++) {
- if (cpNum1[i] > cpNum2[i])
- return 1;
- if (cpNum1[i] < cpNum2[i])
- return -1;
- }
- return 0;
-}
-
diff --git a/modules/ssl/ssl_expr_parse.c b/modules/ssl/ssl_expr_parse.c
deleted file mode 100644
index 8e35553a4e..0000000000
--- a/modules/ssl/ssl_expr_parse.c
+++ /dev/null
@@ -1,605 +0,0 @@
-#ifndef lint
-static char const
-ssl_expr_yyrcsid[] = "$FreeBSD: src/usr.bin/yacc/skeleton.c,v 1.28 2000/01/17 02:04:06 bde Exp $";
-#endif
-#include <stdlib.h>
-#define YYBYACC 1
-#define YYMAJOR 1
-#define YYMINOR 9
-#define YYLEX ssl_expr_yylex()
-#define YYEMPTY -1
-#define ssl_expr_yyclearin (ssl_expr_yychar=(YYEMPTY))
-#define ssl_expr_yyerrok (ssl_expr_yyerrflag=0)
-#define YYRECOVERING() (ssl_expr_yyerrflag!=0)
-static int ssl_expr_yygrowstack();
-#define YYPREFIX "ssl_expr_yy"
-#line 72 "ssl_expr_parse.y"
-#include "mod_ssl.h"
-#line 75 "ssl_expr_parse.y"
-typedef union {
- char *cpVal;
- ssl_expr *exVal;
-} YYSTYPE;
-#line 24 "y.tab.c"
-#define YYERRCODE 256
-#define T_TRUE 257
-#define T_FALSE 258
-#define T_DIGIT 259
-#define T_ID 260
-#define T_STRING 261
-#define T_REGEX 262
-#define T_REGEX_I 263
-#define T_FUNC_FILE 264
-#define T_OP_EQ 265
-#define T_OP_NE 266
-#define T_OP_LT 267
-#define T_OP_LE 268
-#define T_OP_GT 269
-#define T_OP_GE 270
-#define T_OP_REG 271
-#define T_OP_NRE 272
-#define T_OP_IN 273
-#define T_OP_OR 274
-#define T_OP_AND 275
-#define T_OP_NOT 276
-const short ssl_expr_yylhs[] = { -1,
- 0, 1, 1, 1, 1, 1, 1, 1, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 5, 5, 6,
- 6, 6, 6, 4, 4, 3,
-};
-const short ssl_expr_yylen[] = { 2,
- 1, 1, 1, 2, 3, 3, 1, 3, 3, 3,
- 3, 3, 3, 3, 5, 3, 3, 1, 3, 1,
- 1, 4, 1, 1, 1, 4,
-};
-const short ssl_expr_yydefred[] = { 0,
- 2, 3, 20, 21, 0, 0, 0, 0, 0, 0,
- 7, 23, 0, 0, 4, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 8,
- 0, 0, 6, 9, 10, 11, 12, 13, 14, 24,
- 25, 16, 17, 0, 26, 22, 0, 18, 15, 0,
- 19,
-};
-const short ssl_expr_yydgoto[] = { 9,
- 10, 11, 12, 42, 47, 13,
-};
-const short ssl_expr_yysindex[] = { -37,
- 0, 0, 0, 0, -35, -37, -37, -99, 0, -247,
- 0, 0, -250, -229, 0, -39, -227, -37, -37, -33,
- -33, -33, -33, -33, -33, -233, -233, -89, -6, 0,
- -87, -239, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, -33, 0, 0, -38, 0, 0, -33,
- 0,
-};
-const short ssl_expr_yyrindex[] = { 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 39,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0,
-};
-const short ssl_expr_yygindex[] = { 0,
- 7, 0, 0, 13, 0, -13,
-};
-#define YYTABLESIZE 275
-const short ssl_expr_yytable[] = { 8,
- 5, 30, 7, 8, 14, 50, 34, 35, 36, 37,
- 38, 39, 15, 16, 20, 21, 22, 23, 24, 25,
- 26, 27, 28, 17, 32, 33, 18, 19, 40, 41,
- 48, 29, 31, 44, 45, 19, 51, 46, 1, 43,
- 0, 5, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 49, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
- 2, 3, 0, 4, 0, 3, 5, 4, 0, 0,
- 5, 0, 0, 0, 18, 19, 0, 0, 6, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 5,
-};
-const short ssl_expr_yycheck[] = { 37,
- 0, 41, 40, 37, 40, 44, 20, 21, 22, 23,
- 24, 25, 6, 7, 265, 266, 267, 268, 269, 270,
- 271, 272, 273, 123, 18, 19, 274, 275, 262, 263,
- 44, 261, 260, 123, 41, 275, 50, 125, 0, 27,
- -1, 41, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 125, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 257,
- 258, 259, -1, 261, -1, 259, 264, 261, -1, -1,
- 264, -1, -1, -1, 274, 275, -1, -1, 276, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 274,
-};
-#define YYFINAL 9
-#ifndef YYDEBUG
-#define YYDEBUG 0
-#endif
-#define YYMAXTOKEN 276
-#if YYDEBUG
-const char * const ssl_expr_yyname[] = {
-"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,"'%'",0,0,"'('","')'",0,0,"','",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"'{'",0,"'}'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"T_TRUE",
-"T_FALSE","T_DIGIT","T_ID","T_STRING","T_REGEX","T_REGEX_I","T_FUNC_FILE",
-"T_OP_EQ","T_OP_NE","T_OP_LT","T_OP_LE","T_OP_GT","T_OP_GE","T_OP_REG",
-"T_OP_NRE","T_OP_IN","T_OP_OR","T_OP_AND","T_OP_NOT",
-};
-const char * const ssl_expr_yyrule[] = {
-"$accept : root",
-"root : expr",
-"expr : T_TRUE",
-"expr : T_FALSE",
-"expr : T_OP_NOT expr",
-"expr : expr T_OP_OR expr",
-"expr : expr T_OP_AND expr",
-"expr : comparison",
-"expr : '(' expr ')'",
-"comparison : word T_OP_EQ word",
-"comparison : word T_OP_NE word",
-"comparison : word T_OP_LT word",
-"comparison : word T_OP_LE word",
-"comparison : word T_OP_GT word",
-"comparison : word T_OP_GE word",
-"comparison : word T_OP_IN '{' words '}'",
-"comparison : word T_OP_REG regex",
-"comparison : word T_OP_NRE regex",
-"words : word",
-"words : words ',' word",
-"word : T_DIGIT",
-"word : T_STRING",
-"word : '%' '{' T_ID '}'",
-"word : funccall",
-"regex : T_REGEX",
-"regex : T_REGEX_I",
-"funccall : T_FUNC_FILE '(' T_STRING ')'",
-};
-#endif
-#if YYDEBUG
-#include <stdio.h>
-#endif
-#ifdef YYSTACKSIZE
-#undef YYMAXDEPTH
-#define YYMAXDEPTH YYSTACKSIZE
-#else
-#ifdef YYMAXDEPTH
-#define YYSTACKSIZE YYMAXDEPTH
-#else
-#define YYSTACKSIZE 10000
-#define YYMAXDEPTH 10000
-#endif
-#endif
-#define YYINITSTACKSIZE 200
-int ssl_expr_yydebug;
-int ssl_expr_yynerrs;
-int ssl_expr_yyerrflag;
-int ssl_expr_yychar;
-short *ssl_expr_yyssp;
-YYSTYPE *ssl_expr_yyvsp;
-YYSTYPE ssl_expr_yyval;
-YYSTYPE ssl_expr_yylval;
-short *ssl_expr_yyss;
-short *ssl_expr_yysslim;
-YYSTYPE *ssl_expr_yyvs;
-int ssl_expr_yystacksize;
-#line 180 "ssl_expr_parse.y"
-
-int ssl_expr_yyerror(char *s)
-{
- ssl_expr_error = s;
- return 2;
-}
-
-#line 230 "y.tab.c"
-/* allocate initial stack or double stack size, up to YYMAXDEPTH */
-static int ssl_expr_yygrowstack()
-{
- int newsize, i;
- short *newss;
- YYSTYPE *newvs;
-
- if ((newsize = ssl_expr_yystacksize) == 0)
- newsize = YYINITSTACKSIZE;
- else if (newsize >= YYMAXDEPTH)
- return -1;
- else if ((newsize *= 2) > YYMAXDEPTH)
- newsize = YYMAXDEPTH;
- i = ssl_expr_yyssp - ssl_expr_yyss;
- newss = ssl_expr_yyss ? (short *)realloc(ssl_expr_yyss, newsize * sizeof *newss) :
- (short *)malloc(newsize * sizeof *newss);
- if (newss == NULL)
- return -1;
- ssl_expr_yyss = newss;
- ssl_expr_yyssp = newss + i;
- newvs = ssl_expr_yyvs ? (YYSTYPE *)realloc(ssl_expr_yyvs, newsize * sizeof *newvs) :
- (YYSTYPE *)malloc(newsize * sizeof *newvs);
- if (newvs == NULL)
- return -1;
- ssl_expr_yyvs = newvs;
- ssl_expr_yyvsp = newvs + i;
- ssl_expr_yystacksize = newsize;
- ssl_expr_yysslim = ssl_expr_yyss + newsize - 1;
- return 0;
-}
-
-#define YYABORT goto ssl_expr_yyabort
-#define YYREJECT goto ssl_expr_yyabort
-#define YYACCEPT goto ssl_expr_yyaccept
-#define YYERROR goto ssl_expr_yyerrlab
-
-#ifndef YYPARSE_PARAM
-#if defined(__cplusplus) || __STDC__
-#define YYPARSE_PARAM_ARG void
-#define YYPARSE_PARAM_DECL
-#else /* ! ANSI-C/C++ */
-#define YYPARSE_PARAM_ARG
-#define YYPARSE_PARAM_DECL
-#endif /* ANSI-C/C++ */
-#else /* YYPARSE_PARAM */
-#ifndef YYPARSE_PARAM_TYPE
-#define YYPARSE_PARAM_TYPE void *
-#endif
-#if defined(__cplusplus) || __STDC__
-#define YYPARSE_PARAM_ARG YYPARSE_PARAM_TYPE YYPARSE_PARAM
-#define YYPARSE_PARAM_DECL
-#else /* ! ANSI-C/C++ */
-#define YYPARSE_PARAM_ARG YYPARSE_PARAM
-#define YYPARSE_PARAM_DECL YYPARSE_PARAM_TYPE YYPARSE_PARAM;
-#endif /* ANSI-C/C++ */
-#endif /* ! YYPARSE_PARAM */
-
-int
-ssl_expr_yyparse (YYPARSE_PARAM_ARG)
- YYPARSE_PARAM_DECL
-{
- register int ssl_expr_yym, ssl_expr_yyn, ssl_expr_yystate;
-#if YYDEBUG
- register const char *ssl_expr_yys;
-
- if ((ssl_expr_yys = getenv("YYDEBUG")))
- {
- ssl_expr_yyn = *ssl_expr_yys;
- if (ssl_expr_yyn >= '0' && ssl_expr_yyn <= '9')
- ssl_expr_yydebug = ssl_expr_yyn - '0';
- }
-#endif
-
- ssl_expr_yynerrs = 0;
- ssl_expr_yyerrflag = 0;
- ssl_expr_yychar = (-1);
-
- if (ssl_expr_yyss == NULL && ssl_expr_yygrowstack()) goto ssl_expr_yyoverflow;
- ssl_expr_yyssp = ssl_expr_yyss;
- ssl_expr_yyvsp = ssl_expr_yyvs;
- *ssl_expr_yyssp = ssl_expr_yystate = 0;
-
-ssl_expr_yyloop:
- if ((ssl_expr_yyn = ssl_expr_yydefred[ssl_expr_yystate])) goto ssl_expr_yyreduce;
- if (ssl_expr_yychar < 0)
- {
- if ((ssl_expr_yychar = ssl_expr_yylex()) < 0) ssl_expr_yychar = 0;
-#if YYDEBUG
- if (ssl_expr_yydebug)
- {
- ssl_expr_yys = 0;
- if (ssl_expr_yychar <= YYMAXTOKEN) ssl_expr_yys = ssl_expr_yyname[ssl_expr_yychar];
- if (!ssl_expr_yys) ssl_expr_yys = "illegal-symbol";
- printf("%sdebug: state %d, reading %d (%s)\n",
- YYPREFIX, ssl_expr_yystate, ssl_expr_yychar, ssl_expr_yys);
- }
-#endif
- }
- if ((ssl_expr_yyn = ssl_expr_yysindex[ssl_expr_yystate]) && (ssl_expr_yyn += ssl_expr_yychar) >= 0 &&
- ssl_expr_yyn <= YYTABLESIZE && ssl_expr_yycheck[ssl_expr_yyn] == ssl_expr_yychar)
- {
-#if YYDEBUG
- if (ssl_expr_yydebug)
- printf("%sdebug: state %d, shifting to state %d\n",
- YYPREFIX, ssl_expr_yystate, ssl_expr_yytable[ssl_expr_yyn]);
-#endif
- if (ssl_expr_yyssp >= ssl_expr_yysslim && ssl_expr_yygrowstack())
- {
- goto ssl_expr_yyoverflow;
- }
- *++ssl_expr_yyssp = ssl_expr_yystate = ssl_expr_yytable[ssl_expr_yyn];
- *++ssl_expr_yyvsp = ssl_expr_yylval;
- ssl_expr_yychar = (-1);
- if (ssl_expr_yyerrflag > 0) --ssl_expr_yyerrflag;
- goto ssl_expr_yyloop;
- }
- if ((ssl_expr_yyn = ssl_expr_yyrindex[ssl_expr_yystate]) && (ssl_expr_yyn += ssl_expr_yychar) >= 0 &&
- ssl_expr_yyn <= YYTABLESIZE && ssl_expr_yycheck[ssl_expr_yyn] == ssl_expr_yychar)
- {
- ssl_expr_yyn = ssl_expr_yytable[ssl_expr_yyn];
- goto ssl_expr_yyreduce;
- }
- if (ssl_expr_yyerrflag) goto ssl_expr_yyinrecovery;
-#if defined(lint) || defined(__GNUC__)
- goto ssl_expr_yynewerror;
-#endif
-ssl_expr_yynewerror:
- ssl_expr_yyerror("syntax error");
-#if defined(lint) || defined(__GNUC__)
- goto ssl_expr_yyerrlab;
-#endif
-ssl_expr_yyerrlab:
- ++ssl_expr_yynerrs;
-ssl_expr_yyinrecovery:
- if (ssl_expr_yyerrflag < 3)
- {
- ssl_expr_yyerrflag = 3;
- for (;;)
- {
- if ((ssl_expr_yyn = ssl_expr_yysindex[*ssl_expr_yyssp]) && (ssl_expr_yyn += YYERRCODE) >= 0 &&
- ssl_expr_yyn <= YYTABLESIZE && ssl_expr_yycheck[ssl_expr_yyn] == YYERRCODE)
- {
-#if YYDEBUG
- if (ssl_expr_yydebug)
- printf("%sdebug: state %d, error recovery shifting\
- to state %d\n", YYPREFIX, *ssl_expr_yyssp, ssl_expr_yytable[ssl_expr_yyn]);
-#endif
- if (ssl_expr_yyssp >= ssl_expr_yysslim && ssl_expr_yygrowstack())
- {
- goto ssl_expr_yyoverflow;
- }
- *++ssl_expr_yyssp = ssl_expr_yystate = ssl_expr_yytable[ssl_expr_yyn];
- *++ssl_expr_yyvsp = ssl_expr_yylval;
- goto ssl_expr_yyloop;
- }
- else
- {
-#if YYDEBUG
- if (ssl_expr_yydebug)
- printf("%sdebug: error recovery discarding state %d\n",
- YYPREFIX, *ssl_expr_yyssp);
-#endif
- if (ssl_expr_yyssp <= ssl_expr_yyss) goto ssl_expr_yyabort;
- --ssl_expr_yyssp;
- --ssl_expr_yyvsp;
- }
- }
- }
- else
- {
- if (ssl_expr_yychar == 0) goto ssl_expr_yyabort;
-#if YYDEBUG
- if (ssl_expr_yydebug)
- {
- ssl_expr_yys = 0;
- if (ssl_expr_yychar <= YYMAXTOKEN) ssl_expr_yys = ssl_expr_yyname[ssl_expr_yychar];
- if (!ssl_expr_yys) ssl_expr_yys = "illegal-symbol";
- printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
- YYPREFIX, ssl_expr_yystate, ssl_expr_yychar, ssl_expr_yys);
- }
-#endif
- ssl_expr_yychar = (-1);
- goto ssl_expr_yyloop;
- }
-ssl_expr_yyreduce:
-#if YYDEBUG
- if (ssl_expr_yydebug)
- printf("%sdebug: state %d, reducing by rule %d (%s)\n",
- YYPREFIX, ssl_expr_yystate, ssl_expr_yyn, ssl_expr_yyrule[ssl_expr_yyn]);
-#endif
- ssl_expr_yym = ssl_expr_yylen[ssl_expr_yyn];
- ssl_expr_yyval = ssl_expr_yyvsp[1-ssl_expr_yym];
- switch (ssl_expr_yyn)
- {
-case 1:
-#line 118 "ssl_expr_parse.y"
-{ ssl_expr_info.expr = ssl_expr_yyvsp[0].exVal; }
-break;
-case 2:
-#line 121 "ssl_expr_parse.y"
-{ ssl_expr_yyval.exVal = ssl_expr_make(op_True, NULL, NULL); }
-break;
-case 3:
-#line 122 "ssl_expr_parse.y"
-{ ssl_expr_yyval.exVal = ssl_expr_make(op_False, NULL, NULL); }
-break;
-case 4:
-#line 123 "ssl_expr_parse.y"
-{ ssl_expr_yyval.exVal = ssl_expr_make(op_Not, ssl_expr_yyvsp[0].exVal, NULL); }
-break;
-case 5:
-#line 124 "ssl_expr_parse.y"
-{ ssl_expr_yyval.exVal = ssl_expr_make(op_Or, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); }
-break;
-case 6:
-#line 125 "ssl_expr_parse.y"
-{ ssl_expr_yyval.exVal = ssl_expr_make(op_And, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); }
-break;
-case 7:
-#line 126 "ssl_expr_parse.y"
-{ ssl_expr_yyval.exVal = ssl_expr_make(op_Comp, ssl_expr_yyvsp[0].exVal, NULL); }
-break;
-case 8:
-#line 127 "ssl_expr_parse.y"
-{ ssl_expr_yyval.exVal = ssl_expr_yyvsp[-1].exVal; }
-break;
-case 9:
-#line 130 "ssl_expr_parse.y"
-{ ssl_expr_yyval.exVal = ssl_expr_make(op_EQ, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); }
-break;
-case 10:
-#line 131 "ssl_expr_parse.y"
-{ ssl_expr_yyval.exVal = ssl_expr_make(op_NE, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); }
-break;
-case 11:
-#line 132 "ssl_expr_parse.y"
-{ ssl_expr_yyval.exVal = ssl_expr_make(op_LT, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); }
-break;
-case 12:
-#line 133 "ssl_expr_parse.y"
-{ ssl_expr_yyval.exVal = ssl_expr_make(op_LE, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); }
-break;
-case 13:
-#line 134 "ssl_expr_parse.y"
-{ ssl_expr_yyval.exVal = ssl_expr_make(op_GT, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); }
-break;
-case 14:
-#line 135 "ssl_expr_parse.y"
-{ ssl_expr_yyval.exVal = ssl_expr_make(op_GE, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); }
-break;
-case 15:
-#line 136 "ssl_expr_parse.y"
-{ ssl_expr_yyval.exVal = ssl_expr_make(op_IN, ssl_expr_yyvsp[-4].exVal, ssl_expr_yyvsp[-1].exVal); }
-break;
-case 16:
-#line 137 "ssl_expr_parse.y"
-{ ssl_expr_yyval.exVal = ssl_expr_make(op_REG, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); }
-break;
-case 17:
-#line 138 "ssl_expr_parse.y"
-{ ssl_expr_yyval.exVal = ssl_expr_make(op_NRE, ssl_expr_yyvsp[-2].exVal, ssl_expr_yyvsp[0].exVal); }
-break;
-case 18:
-#line 141 "ssl_expr_parse.y"
-{ ssl_expr_yyval.exVal = ssl_expr_make(op_ListElement, ssl_expr_yyvsp[0].exVal, NULL); }
-break;
-case 19:
-#line 142 "ssl_expr_parse.y"
-{ ssl_expr_yyval.exVal = ssl_expr_make(op_ListElement, ssl_expr_yyvsp[0].exVal, ssl_expr_yyvsp[-2].exVal); }
-break;
-case 20:
-#line 145 "ssl_expr_parse.y"
-{ ssl_expr_yyval.exVal = ssl_expr_make(op_Digit, ssl_expr_yyvsp[0].cpVal, NULL); }
-break;
-case 21:
-#line 146 "ssl_expr_parse.y"
-{ ssl_expr_yyval.exVal = ssl_expr_make(op_String, ssl_expr_yyvsp[0].cpVal, NULL); }
-break;
-case 22:
-#line 147 "ssl_expr_parse.y"
-{ ssl_expr_yyval.exVal = ssl_expr_make(op_Var, ssl_expr_yyvsp[-1].cpVal, NULL); }
-break;
-case 23:
-#line 148 "ssl_expr_parse.y"
-{ ssl_expr_yyval.exVal = ssl_expr_yyvsp[0].exVal; }
-break;
-case 24:
-#line 151 "ssl_expr_parse.y"
-{
- regex_t *regex;
- if ((regex = ap_pregcomp(ssl_expr_info.pool, ssl_expr_yyvsp[0].cpVal,
- REG_EXTENDED|REG_NOSUB)) == NULL) {
- ssl_expr_error = "Failed to compile regular expression";
- YYERROR;
- regex = NULL;
- }
- ssl_expr_yyval.exVal = ssl_expr_make(op_Regex, regex, NULL);
- }
-break;
-case 25:
-#line 161 "ssl_expr_parse.y"
-{
- regex_t *regex;
- if ((regex = ap_pregcomp(ssl_expr_info.pool, ssl_expr_yyvsp[0].cpVal,
- REG_EXTENDED|REG_NOSUB|REG_ICASE)) == NULL) {
- ssl_expr_error = "Failed to compile regular expression";
- YYERROR;
- regex = NULL;
- }
- ssl_expr_yyval.exVal = ssl_expr_make(op_Regex, regex, NULL);
- }
-break;
-case 26:
-#line 173 "ssl_expr_parse.y"
-{
- ssl_expr *args = ssl_expr_make(op_ListElement, ssl_expr_yyvsp[-1].cpVal, NULL);
- ssl_expr_yyval.exVal = ssl_expr_make(op_Func, "file", args);
- }
-break;
-#line 550 "y.tab.c"
- }
- ssl_expr_yyssp -= ssl_expr_yym;
- ssl_expr_yystate = *ssl_expr_yyssp;
- ssl_expr_yyvsp -= ssl_expr_yym;
- ssl_expr_yym = ssl_expr_yylhs[ssl_expr_yyn];
- if (ssl_expr_yystate == 0 && ssl_expr_yym == 0)
- {
-#if YYDEBUG
- if (ssl_expr_yydebug)
- printf("%sdebug: after reduction, shifting from state 0 to\
- state %d\n", YYPREFIX, YYFINAL);
-#endif
- ssl_expr_yystate = YYFINAL;
- *++ssl_expr_yyssp = YYFINAL;
- *++ssl_expr_yyvsp = ssl_expr_yyval;
- if (ssl_expr_yychar < 0)
- {
- if ((ssl_expr_yychar = ssl_expr_yylex()) < 0) ssl_expr_yychar = 0;
-#if YYDEBUG
- if (ssl_expr_yydebug)
- {
- ssl_expr_yys = 0;
- if (ssl_expr_yychar <= YYMAXTOKEN) ssl_expr_yys = ssl_expr_yyname[ssl_expr_yychar];
- if (!ssl_expr_yys) ssl_expr_yys = "illegal-symbol";
- printf("%sdebug: state %d, reading %d (%s)\n",
- YYPREFIX, YYFINAL, ssl_expr_yychar, ssl_expr_yys);
- }
-#endif
- }
- if (ssl_expr_yychar == 0) goto ssl_expr_yyaccept;
- goto ssl_expr_yyloop;
- }
- if ((ssl_expr_yyn = ssl_expr_yygindex[ssl_expr_yym]) && (ssl_expr_yyn += ssl_expr_yystate) >= 0 &&
- ssl_expr_yyn <= YYTABLESIZE && ssl_expr_yycheck[ssl_expr_yyn] == ssl_expr_yystate)
- ssl_expr_yystate = ssl_expr_yytable[ssl_expr_yyn];
- else
- ssl_expr_yystate = ssl_expr_yydgoto[ssl_expr_yym];
-#if YYDEBUG
- if (ssl_expr_yydebug)
- printf("%sdebug: after reduction, shifting from state %d \
-to state %d\n", YYPREFIX, *ssl_expr_yyssp, ssl_expr_yystate);
-#endif
- if (ssl_expr_yyssp >= ssl_expr_yysslim && ssl_expr_yygrowstack())
- {
- goto ssl_expr_yyoverflow;
- }
- *++ssl_expr_yyssp = ssl_expr_yystate;
- *++ssl_expr_yyvsp = ssl_expr_yyval;
- goto ssl_expr_yyloop;
-ssl_expr_yyoverflow:
- ssl_expr_yyerror("yacc stack overflow");
-ssl_expr_yyabort:
- return (1);
-ssl_expr_yyaccept:
- return (0);
-}
diff --git a/modules/ssl/ssl_expr_parse.h b/modules/ssl/ssl_expr_parse.h
deleted file mode 100644
index 618cacbe3b..0000000000
--- a/modules/ssl/ssl_expr_parse.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef YYERRCODE
-#define YYERRCODE 256
-#endif
-
-#define T_TRUE 257
-#define T_FALSE 258
-#define T_DIGIT 259
-#define T_ID 260
-#define T_STRING 261
-#define T_REGEX 262
-#define T_REGEX_I 263
-#define T_FUNC_FILE 264
-#define T_OP_EQ 265
-#define T_OP_NE 266
-#define T_OP_LT 267
-#define T_OP_LE 268
-#define T_OP_GT 269
-#define T_OP_GE 270
-#define T_OP_REG 271
-#define T_OP_NRE 272
-#define T_OP_IN 273
-#define T_OP_OR 274
-#define T_OP_AND 275
-#define T_OP_NOT 276
-typedef union {
- char *cpVal;
- ssl_expr *exVal;
-} YYSTYPE;
-extern YYSTYPE ssl_expr_yylval;
diff --git a/modules/ssl/ssl_expr_parse.y b/modules/ssl/ssl_expr_parse.y
deleted file mode 100644
index 1e3ad6e513..0000000000
--- a/modules/ssl/ssl_expr_parse.y
+++ /dev/null
@@ -1,186 +0,0 @@
-/* _ _
-** _ __ ___ ___ __| | ___ ___| |
-** | '_ ` _ \ / _ \ / _` | / __/ __| |
-** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to OpenSSL
-** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.modssl.org/
-** |_____|
-** ssl_expr_parse.y
-** Expression LR(1) Parser
-*/
-
-/* ====================================================================
- * Copyright (c) 1998-2001 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * 4. The names "mod_ssl" must not be used to endorse or promote
- * products derived from this software without prior written
- * permission. For written permission, please contact
- * rse@engelschall.com.
- *
- * 5. Products derived from this software may not be called "mod_ssl"
- * nor may "mod_ssl" appear in their names without prior
- * written permission of Ralf S. Engelschall.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
-
- /* ``What you see is all you get.''
- -- Brian Kernighan */
-
-/* _________________________________________________________________
-**
-** Expression Parser
-** _________________________________________________________________
-*/
-
-%{
-#include "mod_ssl.h"
-%}
-
-%union {
- char *cpVal;
- ssl_expr *exVal;
-}
-
-%token T_TRUE
-%token T_FALSE
-
-%token <cpVal> T_DIGIT
-%token <cpVal> T_ID
-%token <cpVal> T_STRING
-%token <cpVal> T_REGEX
-%token <cpVal> T_REGEX_I
-
-%token T_FUNC_FILE
-
-%token T_OP_EQ
-%token T_OP_NE
-%token T_OP_LT
-%token T_OP_LE
-%token T_OP_GT
-%token T_OP_GE
-%token T_OP_REG
-%token T_OP_NRE
-%token T_OP_IN
-
-%token T_OP_OR
-%token T_OP_AND
-%token T_OP_NOT
-
-%left T_OP_OR
-%left T_OP_AND
-%left T_OP_NOT
-
-%type <exVal> expr
-%type <exVal> comparison
-%type <exVal> funccall
-%type <exVal> regex
-%type <exVal> words
-%type <exVal> word
-
-%%
-
-root : expr { ssl_expr_info.expr = $1; }
- ;
-
-expr : T_TRUE { $$ = ssl_expr_make(op_True, NULL, NULL); }
- | T_FALSE { $$ = ssl_expr_make(op_False, NULL, NULL); }
- | T_OP_NOT expr { $$ = ssl_expr_make(op_Not, $2, NULL); }
- | expr T_OP_OR expr { $$ = ssl_expr_make(op_Or, $1, $3); }
- | expr T_OP_AND expr { $$ = ssl_expr_make(op_And, $1, $3); }
- | comparison { $$ = ssl_expr_make(op_Comp, $1, NULL); }
- | '(' expr ')' { $$ = $2; }
- ;
-
-comparison: word T_OP_EQ word { $$ = ssl_expr_make(op_EQ, $1, $3); }
- | word T_OP_NE word { $$ = ssl_expr_make(op_NE, $1, $3); }
- | word T_OP_LT word { $$ = ssl_expr_make(op_LT, $1, $3); }
- | word T_OP_LE word { $$ = ssl_expr_make(op_LE, $1, $3); }
- | word T_OP_GT word { $$ = ssl_expr_make(op_GT, $1, $3); }
- | word T_OP_GE word { $$ = ssl_expr_make(op_GE, $1, $3); }
- | word T_OP_IN '{' words '}' { $$ = ssl_expr_make(op_IN, $1, $4); }
- | word T_OP_REG regex { $$ = ssl_expr_make(op_REG, $1, $3); }
- | word T_OP_NRE regex { $$ = ssl_expr_make(op_NRE, $1, $3); }
- ;
-
-words : word { $$ = ssl_expr_make(op_ListElement, $1, NULL); }
- | words ',' word { $$ = ssl_expr_make(op_ListElement, $3, $1); }
- ;
-
-word : T_DIGIT { $$ = ssl_expr_make(op_Digit, $1, NULL); }
- | T_STRING { $$ = ssl_expr_make(op_String, $1, NULL); }
- | '%' '{' T_ID '}' { $$ = ssl_expr_make(op_Var, $3, NULL); }
- | funccall { $$ = $1; }
- ;
-
-regex : T_REGEX {
- regex_t *regex;
- if ((regex = ap_pregcomp(ssl_expr_info.pool, $1,
- REG_EXTENDED|REG_NOSUB)) == NULL) {
- ssl_expr_error = "Failed to compile regular expression";
- YYERROR;
- regex = NULL;
- }
- $$ = ssl_expr_make(op_Regex, regex, NULL);
- }
- | T_REGEX_I {
- regex_t *regex;
- if ((regex = ap_pregcomp(ssl_expr_info.pool, $1,
- REG_EXTENDED|REG_NOSUB|REG_ICASE)) == NULL) {
- ssl_expr_error = "Failed to compile regular expression";
- YYERROR;
- regex = NULL;
- }
- $$ = ssl_expr_make(op_Regex, regex, NULL);
- }
- ;
-
-funccall : T_FUNC_FILE '(' T_STRING ')' {
- ssl_expr *args = ssl_expr_make(op_ListElement, $3, NULL);
- $$ = ssl_expr_make(op_Func, "file", args);
- }
- ;
-
-%%
-
-int yyerror(char *s)
-{
- ssl_expr_error = s;
- return 2;
-}
-
diff --git a/modules/ssl/ssl_expr_scan.c b/modules/ssl/ssl_expr_scan.c
deleted file mode 100644
index f3e9f9d1f5..0000000000
--- a/modules/ssl/ssl_expr_scan.c
+++ /dev/null
@@ -1,2002 +0,0 @@
-#define yy_create_buffer ssl_expr_yy_create_buffer
-#define yy_delete_buffer ssl_expr_yy_delete_buffer
-#define yy_scan_buffer ssl_expr_yy_scan_buffer
-#define yy_scan_string ssl_expr_yy_scan_string
-#define yy_scan_bytes ssl_expr_yy_scan_bytes
-#define yy_flex_debug ssl_expr_yy_flex_debug
-#define yy_init_buffer ssl_expr_yy_init_buffer
-#define yy_flush_buffer ssl_expr_yy_flush_buffer
-#define yy_load_buffer_state ssl_expr_yy_load_buffer_state
-#define yy_switch_to_buffer ssl_expr_yy_switch_to_buffer
-#define yyin ssl_expr_yyin
-#define yyleng ssl_expr_yyleng
-#define yylex ssl_expr_yylex
-#define yyout ssl_expr_yyout
-#define yyrestart ssl_expr_yyrestart
-#define yytext ssl_expr_yytext
-
-/* A lexical scanner generated by flex */
-
-/* Scanner skeleton version:
- */
-
-#define FLEX_SCANNER
-#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-
-#include <stdio.h>
-
-
-/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
-#ifdef c_plusplus
-#ifndef __cplusplus
-#define __cplusplus
-#endif
-#endif
-
-
-#ifdef __cplusplus
-
-#include <stdlib.h>
-#include <unistd.h>
-
-/* Use prototypes in function declarations. */
-#define YY_USE_PROTOS
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else /* ! __cplusplus */
-
-#if __STDC__
-
-#define YY_USE_PROTOS
-#define YY_USE_CONST
-
-#endif /* __STDC__ */
-#endif /* ! __cplusplus */
-
-#ifdef __TURBOC__
- #pragma warn -rch
- #pragma warn -use
-#include <io.h>
-#include <stdlib.h>
-#define YY_USE_CONST
-#define YY_USE_PROTOS
-#endif
-
-#ifdef YY_USE_CONST
-#define yyconst const
-#else
-#define yyconst
-#endif
-
-
-#ifdef YY_USE_PROTOS
-#define YY_PROTO(proto) proto
-#else
-#define YY_PROTO(proto) ()
-#endif
-
-/* Returned upon end-of-file. */
-#define YY_NULL 0
-
-/* Promotes a possibly negative, possibly signed char to an unsigned
- * integer for use as an array index. If the signed char is negative,
- * we want to instead treat it as an 8-bit unsigned char, hence the
- * double cast.
- */
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
-
-/* Enter a start condition. This macro really ought to take a parameter,
- * but we do it the disgusting crufty way forced on us by the ()-less
- * definition of BEGIN.
- */
-#define BEGIN yy_start = 1 + 2 *
-
-/* Translate the current start state into a value that can be later handed
- * to BEGIN to return to the state. The YYSTATE alias is for lex
- * compatibility.
- */
-#define YY_START ((yy_start - 1) / 2)
-#define YYSTATE YY_START
-
-/* Action number for EOF rule of a given start state. */
-#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
-/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE yyrestart( yyin )
-
-#define YY_END_OF_BUFFER_CHAR 0
-
-/* Size of default input buffer. */
-#define YY_BUF_SIZE 16384
-
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-
-extern int yyleng;
-extern FILE *yyin, *yyout;
-
-#define EOB_ACT_CONTINUE_SCAN 0
-#define EOB_ACT_END_OF_FILE 1
-#define EOB_ACT_LAST_MATCH 2
-
-/* The funky do-while in the following #define is used to turn the definition
- * int a single C statement (which needs a semi-colon terminator). This
- * avoids problems with code like:
- *
- * if ( condition_holds )
- * yyless( 5 );
- * else
- * do_something_else();
- *
- * Prior to using the do-while the compiler would get upset at the
- * "else" because it interpreted the "if" statement as being all
- * done when it reached the ';' after the yyless() call.
- */
-
-/* Return all but the first 'n' matched characters back to the input stream. */
-
-#define yyless(n) \
- do \
- { \
- /* Undo effects of setting up yytext. */ \
- *yy_cp = yy_hold_char; \
- YY_RESTORE_YY_MORE_OFFSET \
- yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
- YY_DO_BEFORE_ACTION; /* set up yytext again */ \
- } \
- while ( 0 )
-
-#define unput(c) yyunput( c, yytext_ptr )
-
-/* The following is because we cannot portably get our hands on size_t
- * (without autoconf's help, which isn't available because we want
- * flex-generated scanners to compile on their own).
- */
-typedef unsigned int yy_size_t;
-
-
-struct yy_buffer_state
- {
- FILE *yy_input_file;
-
- char *yy_ch_buf; /* input buffer */
- char *yy_buf_pos; /* current position in input buffer */
-
- /* Size of input buffer in bytes, not including room for EOB
- * characters.
- */
- yy_size_t yy_buf_size;
-
- /* Number of characters read into yy_ch_buf, not including EOB
- * characters.
- */
- int yy_n_chars;
-
- /* Whether we "own" the buffer - i.e., we know we created it,
- * and can realloc() it to grow it, and should free() it to
- * delete it.
- */
- int yy_is_our_buffer;
-
- /* Whether this is an "interactive" input source; if so, and
- * if we're using stdio for input, then we want to use getc()
- * instead of fread(), to make sure we stop fetching input after
- * each newline.
- */
- int yy_is_interactive;
-
- /* Whether we're considered to be at the beginning of a line.
- * If so, '^' rules will be active on the next match, otherwise
- * not.
- */
- int yy_at_bol;
-
- /* Whether to try to fill the input buffer when we reach the
- * end of it.
- */
- int yy_fill_buffer;
-
- int yy_buffer_status;
-#define YY_BUFFER_NEW 0
-#define YY_BUFFER_NORMAL 1
- /* When an EOF's been seen but there's still some text to process
- * then we mark the buffer as YY_EOF_PENDING, to indicate that we
- * shouldn't try reading from the input source any more. We might
- * still have a bunch of tokens to match, though, because of
- * possible backing-up.
- *
- * When we actually see the EOF, we change the status to "new"
- * (via yyrestart()), so that the user can continue scanning by
- * just pointing yyin at a new input file.
- */
-#define YY_BUFFER_EOF_PENDING 2
- };
-
-static YY_BUFFER_STATE yy_current_buffer = 0;
-
-/* We provide macros for accessing buffer states in case in the
- * future we want to put the buffer states in a more general
- * "scanner state".
- */
-#define YY_CURRENT_BUFFER yy_current_buffer
-
-
-/* yy_hold_char holds the character lost when yytext is formed. */
-static char yy_hold_char;
-
-static int yy_n_chars; /* number of characters read into yy_ch_buf */
-
-
-int yyleng;
-
-/* Points to current character in buffer. */
-static char *yy_c_buf_p = (char *) 0;
-static int yy_init = 1; /* whether we need to initialize */
-static int yy_start = 0; /* start state number */
-
-/* Flag which is used to allow yywrap()'s to do buffer switches
- * instead of setting up a fresh yyin. A bit of a hack ...
- */
-static int yy_did_buffer_switch_on_eof;
-
-void yyrestart YY_PROTO(( FILE *input_file ));
-
-void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
-void yy_load_buffer_state YY_PROTO(( void ));
-YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
-void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
-void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
-void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
-#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
-
-YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
-YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
-YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
-
-static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
-static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
-static void yy_flex_free YY_PROTO(( void * ));
-
-#define yy_new_buffer yy_create_buffer
-
-#define yy_set_interactive(is_interactive) \
- { \
- if ( ! yy_current_buffer ) \
- yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
- yy_current_buffer->yy_is_interactive = is_interactive; \
- }
-
-#define yy_set_bol(at_bol) \
- { \
- if ( ! yy_current_buffer ) \
- yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
- yy_current_buffer->yy_at_bol = at_bol; \
- }
-
-#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
-
-
-#define yywrap() 1
-#define YY_SKIP_YYWRAP
-typedef unsigned char YY_CHAR;
-FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
-typedef int yy_state_type;
-extern char *yytext;
-#define yytext_ptr yytext
-
-static yy_state_type yy_get_previous_state YY_PROTO(( void ));
-static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
-static int yy_get_next_buffer YY_PROTO(( void ));
-static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
-
-/* Done after the current pattern has been matched and before the
- * corresponding action - sets up yytext.
- */
-#define YY_DO_BEFORE_ACTION \
- yytext_ptr = yy_bp; \
- yyleng = (int) (yy_cp - yy_bp); \
- yy_hold_char = *yy_cp; \
- *yy_cp = '\0'; \
- yy_c_buf_p = yy_cp;
-
-#define YY_NUM_RULES 46
-#define YY_END_OF_BUFFER 47
-static yyconst short int yy_accept[86] =
- { 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 47, 45,
- 1, 38, 2, 45, 43, 24, 45, 28, 44, 44,
- 44, 44, 44, 44, 44, 44, 44, 44, 44, 45,
- 13, 4, 3, 14, 16, 18, 17, 1, 22, 32,
- 34, 43, 26, 20, 31, 30, 44, 44, 19, 44,
- 44, 29, 27, 39, 25, 23, 15, 15, 21, 44,
- 35, 44, 36, 13, 12, 5, 6, 10, 11, 7,
- 8, 9, 33, 44, 44, 37, 44, 5, 6, 44,
- 40, 41, 5, 42, 0
- } ;
-
-static yyconst int yy_ec[256] =
- { 0,
- 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 2, 4, 5, 1, 1, 1, 6, 1, 1,
- 1, 1, 1, 1, 7, 1, 1, 8, 8, 8,
- 8, 8, 8, 8, 8, 9, 9, 7, 1, 10,
- 11, 12, 1, 1, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 1, 14, 1, 1, 7, 1, 15, 16, 13, 17,
-
- 18, 19, 20, 13, 21, 13, 13, 22, 23, 24,
- 25, 13, 26, 27, 28, 29, 30, 13, 13, 13,
- 13, 13, 1, 31, 1, 32, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1
- } ;
-
-static yyconst int yy_meta[33] =
- { 0,
- 1, 1, 2, 1, 3, 1, 4, 4, 4, 1,
- 1, 1, 4, 3, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 1, 1
- } ;
-
-static yyconst short int yy_base[93] =
- { 0,
- 0, 0, 30, 31, 0, 0, 82, 81, 101, 142,
- 35, 28, 142, 94, 32, 88, 31, 87, 0, 69,
- 66, 28, 28, 67, 29, 63, 30, 63, 62, 57,
- 0, 142, 142, 88, 142, 142, 142, 48, 142, 142,
- 142, 44, 142, 142, 142, 142, 0, 70, 0, 64,
- 63, 0, 0, 0, 0, 0, 142, 0, 0, 55,
- 0, 46, 142, 0, 142, 53, 62, 142, 142, 142,
- 142, 142, 0, 44, 48, 0, 41, 70, 72, 38,
- 0, 0, 74, 0, 142, 117, 121, 125, 50, 129,
- 133, 137
-
- } ;
-
-static yyconst short int yy_def[93] =
- { 0,
- 85, 1, 86, 86, 87, 87, 88, 88, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 89, 89,
- 89, 89, 89, 89, 89, 90, 89, 89, 89, 85,
- 91, 85, 85, 92, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 89, 89, 89, 89,
- 89, 89, 89, 89, 89, 89, 85, 89, 89, 89,
- 89, 89, 85, 91, 85, 85, 85, 85, 85, 85,
- 85, 85, 89, 89, 89, 89, 89, 85, 85, 89,
- 89, 89, 85, 89, 0, 85, 85, 85, 85, 85,
- 85, 85
-
- } ;
-
-static yyconst short int yy_nxt[175] =
- { 0,
- 10, 11, 11, 12, 13, 14, 10, 15, 15, 16,
- 17, 18, 19, 10, 20, 19, 19, 21, 22, 23,
- 24, 25, 26, 27, 28, 19, 19, 19, 29, 19,
- 30, 10, 32, 32, 33, 33, 38, 38, 39, 42,
- 42, 44, 50, 34, 34, 52, 55, 59, 51, 38,
- 38, 42, 42, 47, 60, 84, 53, 56, 82, 40,
- 78, 79, 45, 57, 57, 81, 57, 57, 57, 79,
- 79, 80, 57, 57, 57, 77, 57, 83, 79, 79,
- 79, 79, 79, 76, 75, 74, 73, 63, 62, 61,
- 54, 49, 48, 57, 57, 66, 67, 46, 43, 41,
-
- 85, 37, 37, 68, 85, 85, 69, 85, 85, 85,
- 85, 70, 85, 85, 71, 85, 72, 31, 31, 31,
- 31, 35, 35, 35, 35, 36, 36, 36, 36, 58,
- 85, 58, 58, 64, 85, 85, 64, 65, 65, 65,
- 65, 9, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85
- } ;
-
-static yyconst short int yy_chk[175] =
- { 0,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 3, 4, 3, 4, 11, 11, 12, 15,
- 15, 17, 22, 3, 4, 23, 25, 27, 22, 38,
- 38, 42, 42, 89, 27, 80, 23, 25, 77, 12,
- 66, 66, 17, 26, 26, 75, 26, 26, 26, 67,
- 67, 74, 26, 26, 26, 62, 26, 78, 78, 79,
- 79, 83, 83, 60, 51, 50, 48, 30, 29, 28,
- 24, 21, 20, 26, 26, 34, 34, 18, 16, 14,
-
- 9, 8, 7, 34, 0, 0, 34, 0, 0, 0,
- 0, 34, 0, 0, 34, 0, 34, 86, 86, 86,
- 86, 87, 87, 87, 87, 88, 88, 88, 88, 90,
- 0, 90, 90, 91, 0, 0, 91, 92, 92, 92,
- 92, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85
- } ;
-
-static yy_state_type yy_last_accepting_state;
-static char *yy_last_accepting_cpos;
-
-/* The intent behind this definition is that it'll catch
- * any uses of REJECT which flex missed.
- */
-#define REJECT reject_used_but_not_detected
-#define yymore() yymore_used_but_not_detected
-#define YY_MORE_ADJ 0
-#define YY_RESTORE_YY_MORE_OFFSET
-char *yytext;
-#line 1 "ssl_expr_scan.l"
-#define INITIAL 0
-/* _ _
-** _ __ ___ ___ __| | ___ ___| |
-** | '_ ` _ \ / _ \ / _` | / __/ __| |
-** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to OpenSSL
-** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.modssl.org/
-** |_____|
-** ssl_expr_scan.l
-** Expression Scanner
-*/
-/* ====================================================================
- * Copyright (c) 1998-2001 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * 4. The names "mod_ssl" must not be used to endorse or promote
- * products derived from this software without prior written
- * permission. For written permission, please contact
- * rse@engelschall.com.
- *
- * 5. Products derived from this software may not be called "mod_ssl"
- * nor may "mod_ssl" appear in their names without prior
- * written permission of Ralf S. Engelschall.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
-/* ``Killing for peace is
-like fucking for virginity.''
--- Unknown */
-/* _________________________________________________________________
-**
-** Expression Scanner
-** _________________________________________________________________
-*/
-#line 73 "ssl_expr_scan.l"
-#include "mod_ssl.h"
-
-#include "ssl_expr_parse.h"
-
-#define YY_NO_UNPUT 1
-int yyinput(char *buf, int max_size);
-
-#undef YY_INPUT
-#define YY_INPUT(buf,result,max_size) \
- (result = yyinput(buf, max_size))
-
-#define MAX_STR_LEN 2048
-/* %option stack */
-#define YY_NEVER_INTERACTIVE 1
-#define str 1
-
-#define regex 2
-#define regex_flags 3
-
-#line 537 "lex.ssl_expr_yy.c"
-
-/* Macros after this point can all be overridden by user definitions in
- * section 1.
- */
-
-#ifndef YY_SKIP_YYWRAP
-#ifdef __cplusplus
-extern "C" int yywrap YY_PROTO(( void ));
-#else
-extern int yywrap YY_PROTO(( void ));
-#endif
-#endif
-
-#ifndef YY_NO_UNPUT
-static void yyunput YY_PROTO(( int c, char *buf_ptr ));
-#endif
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen YY_PROTO(( yyconst char * ));
-#endif
-
-#ifndef YY_NO_INPUT
-#ifdef __cplusplus
-static int yyinput YY_PROTO(( void ));
-#else
-static int input YY_PROTO(( void ));
-#endif
-#endif
-
-#if YY_STACK_USED
-static int yy_start_stack_ptr = 0;
-static int yy_start_stack_depth = 0;
-static int *yy_start_stack = 0;
-#ifndef YY_NO_PUSH_STATE
-static void yy_push_state YY_PROTO(( int new_state ));
-#endif
-#ifndef YY_NO_POP_STATE
-static void yy_pop_state YY_PROTO(( void ));
-#endif
-#ifndef YY_NO_TOP_STATE
-static int yy_top_state YY_PROTO(( void ));
-#endif
-
-#else
-#define YY_NO_PUSH_STATE 1
-#define YY_NO_POP_STATE 1
-#define YY_NO_TOP_STATE 1
-#endif
-
-#ifdef YY_MALLOC_DECL
-YY_MALLOC_DECL
-#else
-#if __STDC__
-#ifndef __cplusplus
-#include <stdlib.h>
-#endif
-#else
-/* Just try to get by without declaring the routines. This will fail
- * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
- * or sizeof(void*) != sizeof(int).
- */
-#endif
-#endif
-
-/* Amount of stuff to slurp up with each read. */
-#ifndef YY_READ_BUF_SIZE
-#define YY_READ_BUF_SIZE 8192
-#endif
-
-/* Copy whatever the last rule matched to the standard output. */
-
-#ifndef ECHO
-/* This used to be an fputs(), but since the string might contain NUL's,
- * we now use fwrite().
- */
-#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
-#endif
-
-/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
- * is returned in "result".
- */
-#ifndef YY_INPUT
-#define YY_INPUT(buf,result,max_size) \
- if ( yy_current_buffer->yy_is_interactive ) \
- { \
- int c = '*', n; \
- for ( n = 0; n < max_size && \
- (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
- buf[n] = (char) c; \
- if ( c == '\n' ) \
- buf[n++] = (char) c; \
- if ( c == EOF && ferror( yyin ) ) \
- YY_FATAL_ERROR( "input in flex scanner failed" ); \
- result = n; \
- } \
- else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \
- && ferror( yyin ) ) \
- YY_FATAL_ERROR( "input in flex scanner failed" );
-#endif
-
-/* No semi-colon after return; correct usage is to write "yyterminate();" -
- * we don't want an extra ';' after the "return" because that will cause
- * some compilers to complain about unreachable statements.
- */
-#ifndef yyterminate
-#define yyterminate() return YY_NULL
-#endif
-
-/* Number of entries by which start-condition stack grows. */
-#ifndef YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#endif
-
-/* Report a fatal error. */
-#ifndef YY_FATAL_ERROR
-#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
-#endif
-
-/* Default declaration of generated scanner - a define so the user can
- * easily add parameters.
- */
-#ifndef YY_DECL
-#define YY_DECL int yylex YY_PROTO(( void ))
-#endif
-
-/* Code executed at the beginning of each rule, after yytext and yyleng
- * have been set up.
- */
-#ifndef YY_USER_ACTION
-#define YY_USER_ACTION
-#endif
-
-/* Code executed at the end of each rule. */
-#ifndef YY_BREAK
-#define YY_BREAK break;
-#endif
-
-#define YY_RULE_SETUP \
- YY_USER_ACTION
-
-YY_DECL
- {
- register yy_state_type yy_current_state;
- register char *yy_cp, *yy_bp;
- register int yy_act;
-
-#line 94 "ssl_expr_scan.l"
-
-
- char caStr[MAX_STR_LEN];
- char *cpStr = NULL;
- char caRegex[MAX_STR_LEN];
- char *cpRegex = NULL;
- char cRegexDel = NUL;
-
- /*
- * Whitespaces
- */
-#line 700 "lex.ssl_expr_yy.c"
-
- if ( yy_init )
- {
- yy_init = 0;
-
-#ifdef YY_USER_INIT
- YY_USER_INIT;
-#endif
-
- if ( ! yy_start )
- yy_start = 1; /* first start state */
-
- if ( ! yyin )
- yyin = stdin;
-
- if ( ! yyout )
- yyout = stdout;
-
- if ( ! yy_current_buffer )
- yy_current_buffer =
- yy_create_buffer( yyin, YY_BUF_SIZE );
-
- yy_load_buffer_state();
- }
-
- while ( 1 ) /* loops until end-of-file is reached */
- {
- yy_cp = yy_c_buf_p;
-
- /* Support of yytext. */
- *yy_cp = yy_hold_char;
-
- /* yy_bp points to the position in yy_ch_buf of the start of
- * the current run.
- */
- yy_bp = yy_cp;
-
- yy_current_state = yy_start;
-yy_match:
- do
- {
- register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
- if ( yy_accept[yy_current_state] )
- {
- yy_last_accepting_state = yy_current_state;
- yy_last_accepting_cpos = yy_cp;
- }
- while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
- {
- yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 86 )
- yy_c = yy_meta[(unsigned int) yy_c];
- }
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- ++yy_cp;
- }
- while ( yy_current_state != 85 );
- yy_cp = yy_last_accepting_cpos;
- yy_current_state = yy_last_accepting_state;
-
-yy_find_action:
- yy_act = yy_accept[yy_current_state];
-
- YY_DO_BEFORE_ACTION;
-
-
-do_action: /* This label is used only to access EOF actions. */
-
-
- switch ( yy_act )
- { /* beginning of action switch */
- case 0: /* must back up */
- /* undo the effects of YY_DO_BEFORE_ACTION */
- *yy_cp = yy_hold_char;
- yy_cp = yy_last_accepting_cpos;
- yy_current_state = yy_last_accepting_state;
- goto yy_find_action;
-
-case 1:
-YY_RULE_SETUP
-#line 105 "ssl_expr_scan.l"
-{
- /* NOP */
-}
- YY_BREAK
-/*
- * C-style strings ("...")
- */
-case 2:
-YY_RULE_SETUP
-#line 112 "ssl_expr_scan.l"
-{
- cpStr = caStr;
- BEGIN(str);
-}
- YY_BREAK
-case 3:
-YY_RULE_SETUP
-#line 116 "ssl_expr_scan.l"
-{
- BEGIN(INITIAL);
- *cpStr = NUL;
- yylval.cpVal = ap_pstrdup(ssl_expr_info.pool, caStr);
- return T_STRING;
-}
- YY_BREAK
-case 4:
-YY_RULE_SETUP
-#line 122 "ssl_expr_scan.l"
-{
- yyerror("Unterminated string");
-}
- YY_BREAK
-case 5:
-YY_RULE_SETUP
-#line 125 "ssl_expr_scan.l"
-{
- int result;
-
- (void)sscanf(yytext+1, "%o", &result);
- if (result > 0xff)
- yyerror("Escape sequence out of bound");
- else
- *cpStr++ = result;
-}
- YY_BREAK
-case 6:
-YY_RULE_SETUP
-#line 134 "ssl_expr_scan.l"
-{
- yyerror("Bad escape sequence");
-}
- YY_BREAK
-case 7:
-YY_RULE_SETUP
-#line 137 "ssl_expr_scan.l"
-{ *cpStr++ = '\n'; }
- YY_BREAK
-case 8:
-YY_RULE_SETUP
-#line 138 "ssl_expr_scan.l"
-{ *cpStr++ = '\r'; }
- YY_BREAK
-case 9:
-YY_RULE_SETUP
-#line 139 "ssl_expr_scan.l"
-{ *cpStr++ = '\t'; }
- YY_BREAK
-case 10:
-YY_RULE_SETUP
-#line 140 "ssl_expr_scan.l"
-{ *cpStr++ = '\b'; }
- YY_BREAK
-case 11:
-YY_RULE_SETUP
-#line 141 "ssl_expr_scan.l"
-{ *cpStr++ = '\f'; }
- YY_BREAK
-case 12:
-YY_RULE_SETUP
-#line 142 "ssl_expr_scan.l"
-{
- *cpStr++ = yytext[1];
-}
- YY_BREAK
-case 13:
-YY_RULE_SETUP
-#line 145 "ssl_expr_scan.l"
-{
- char *cp = yytext;
- while (*cp != NUL)
- *cpStr++ = *cp++;
-}
- YY_BREAK
-case 14:
-YY_RULE_SETUP
-#line 150 "ssl_expr_scan.l"
-{
- *cpStr++ = yytext[1];
-}
- YY_BREAK
-/*
- * Regular Expression
- */
-case 15:
-YY_RULE_SETUP
-#line 157 "ssl_expr_scan.l"
-{
- cRegexDel = yytext[1];
- cpRegex = caRegex;
- BEGIN(regex);
-}
- YY_BREAK
-case 16:
-YY_RULE_SETUP
-#line 162 "ssl_expr_scan.l"
-{
- if (yytext[0] == cRegexDel) {
- *cpRegex = NUL;
- BEGIN(regex_flags);
- }
- else {
- *cpRegex++ = yytext[0];
- }
-}
- YY_BREAK
-case 17:
-YY_RULE_SETUP
-#line 171 "ssl_expr_scan.l"
-{
- yylval.cpVal = ap_pstrdup(ssl_expr_info.pool, caRegex);
- BEGIN(INITIAL);
- return T_REGEX_I;
-}
- YY_BREAK
-case 18:
-YY_RULE_SETUP
-#line 176 "ssl_expr_scan.l"
-{
- yylval.cpVal = ap_pstrdup(ssl_expr_info.pool, caRegex);
- yyless(0);
- BEGIN(INITIAL);
- return T_REGEX;
-}
- YY_BREAK
-case YY_STATE_EOF(regex_flags):
-#line 182 "ssl_expr_scan.l"
-{
- yylval.cpVal = ap_pstrdup(ssl_expr_info.pool, caRegex);
- BEGIN(INITIAL);
- return T_REGEX;
-}
- YY_BREAK
-/*
- * Operators
- */
-case 19:
-YY_RULE_SETUP
-#line 191 "ssl_expr_scan.l"
-{ return T_OP_EQ; }
- YY_BREAK
-case 20:
-YY_RULE_SETUP
-#line 192 "ssl_expr_scan.l"
-{ return T_OP_EQ; }
- YY_BREAK
-case 21:
-YY_RULE_SETUP
-#line 193 "ssl_expr_scan.l"
-{ return T_OP_NE; }
- YY_BREAK
-case 22:
-YY_RULE_SETUP
-#line 194 "ssl_expr_scan.l"
-{ return T_OP_NE; }
- YY_BREAK
-case 23:
-YY_RULE_SETUP
-#line 195 "ssl_expr_scan.l"
-{ return T_OP_LT; }
- YY_BREAK
-case 24:
-YY_RULE_SETUP
-#line 196 "ssl_expr_scan.l"
-{ return T_OP_LT; }
- YY_BREAK
-case 25:
-YY_RULE_SETUP
-#line 197 "ssl_expr_scan.l"
-{ return T_OP_LE; }
- YY_BREAK
-case 26:
-YY_RULE_SETUP
-#line 198 "ssl_expr_scan.l"
-{ return T_OP_LE; }
- YY_BREAK
-case 27:
-YY_RULE_SETUP
-#line 199 "ssl_expr_scan.l"
-{ return T_OP_GT; }
- YY_BREAK
-case 28:
-YY_RULE_SETUP
-#line 200 "ssl_expr_scan.l"
-{ return T_OP_GT; }
- YY_BREAK
-case 29:
-YY_RULE_SETUP
-#line 201 "ssl_expr_scan.l"
-{ return T_OP_GE; }
- YY_BREAK
-case 30:
-YY_RULE_SETUP
-#line 202 "ssl_expr_scan.l"
-{ return T_OP_GE; }
- YY_BREAK
-case 31:
-YY_RULE_SETUP
-#line 203 "ssl_expr_scan.l"
-{ return T_OP_REG; }
- YY_BREAK
-case 32:
-YY_RULE_SETUP
-#line 204 "ssl_expr_scan.l"
-{ return T_OP_NRE; }
- YY_BREAK
-case 33:
-YY_RULE_SETUP
-#line 205 "ssl_expr_scan.l"
-{ return T_OP_AND; }
- YY_BREAK
-case 34:
-YY_RULE_SETUP
-#line 206 "ssl_expr_scan.l"
-{ return T_OP_AND; }
- YY_BREAK
-case 35:
-YY_RULE_SETUP
-#line 207 "ssl_expr_scan.l"
-{ return T_OP_OR; }
- YY_BREAK
-case 36:
-YY_RULE_SETUP
-#line 208 "ssl_expr_scan.l"
-{ return T_OP_OR; }
- YY_BREAK
-case 37:
-YY_RULE_SETUP
-#line 209 "ssl_expr_scan.l"
-{ return T_OP_NOT; }
- YY_BREAK
-case 38:
-YY_RULE_SETUP
-#line 210 "ssl_expr_scan.l"
-{ return T_OP_NOT; }
- YY_BREAK
-case 39:
-YY_RULE_SETUP
-#line 211 "ssl_expr_scan.l"
-{ return T_OP_IN; }
- YY_BREAK
-/*
- * Functions
- */
-case 40:
-YY_RULE_SETUP
-#line 216 "ssl_expr_scan.l"
-{ return T_FUNC_FILE; }
- YY_BREAK
-/*
- * Specials
- */
-case 41:
-YY_RULE_SETUP
-#line 221 "ssl_expr_scan.l"
-{ return T_TRUE; }
- YY_BREAK
-case 42:
-YY_RULE_SETUP
-#line 222 "ssl_expr_scan.l"
-{ return T_FALSE; }
- YY_BREAK
-/*
- * Digits
- */
-case 43:
-YY_RULE_SETUP
-#line 227 "ssl_expr_scan.l"
-{
- yylval.cpVal = ap_pstrdup(ssl_expr_info.pool, yytext);
- return T_DIGIT;
-}
- YY_BREAK
-/*
- * Identifiers
- */
-case 44:
-YY_RULE_SETUP
-#line 235 "ssl_expr_scan.l"
-{
- yylval.cpVal = ap_pstrdup(ssl_expr_info.pool, yytext);
- return T_ID;
-}
- YY_BREAK
-/*
- * Anything else is returned as is...
- */
-case 45:
-YY_RULE_SETUP
-#line 243 "ssl_expr_scan.l"
-{
- return yytext[0];
-}
- YY_BREAK
-case 46:
-YY_RULE_SETUP
-#line 247 "ssl_expr_scan.l"
-YY_FATAL_ERROR( "flex scanner jammed" );
- YY_BREAK
-#line 1100 "lex.ssl_expr_yy.c"
-case YY_STATE_EOF(INITIAL):
-case YY_STATE_EOF(str):
-case YY_STATE_EOF(regex):
- yyterminate();
-
- case YY_END_OF_BUFFER:
- {
- /* Amount of text matched not including the EOB char. */
- int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;
-
- /* Undo the effects of YY_DO_BEFORE_ACTION. */
- *yy_cp = yy_hold_char;
- YY_RESTORE_YY_MORE_OFFSET
-
- if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
- {
- /* We're scanning a new file or input source. It's
- * possible that this happened because the user
- * just pointed yyin at a new source and called
- * yylex(). If so, then we have to assure
- * consistency between yy_current_buffer and our
- * globals. Here is the right place to do so, because
- * this is the first action (other than possibly a
- * back-up) that will match for the new input source.
- */
- yy_n_chars = yy_current_buffer->yy_n_chars;
- yy_current_buffer->yy_input_file = yyin;
- yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
- }
-
- /* Note that here we test for yy_c_buf_p "<=" to the position
- * of the first EOB in the buffer, since yy_c_buf_p will
- * already have been incremented past the NUL character
- * (since all states make transitions on EOB to the
- * end-of-buffer state). Contrast this with the test
- * in input().
- */
- if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
- { /* This was really a NUL. */
- yy_state_type yy_next_state;
-
- yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
-
- yy_current_state = yy_get_previous_state();
-
- /* Okay, we're now positioned to make the NUL
- * transition. We couldn't have
- * yy_get_previous_state() go ahead and do it
- * for us because it doesn't know how to deal
- * with the possibility of jamming (and we don't
- * want to build jamming into it because then it
- * will run more slowly).
- */
-
- yy_next_state = yy_try_NUL_trans( yy_current_state );
-
- yy_bp = yytext_ptr + YY_MORE_ADJ;
-
- if ( yy_next_state )
- {
- /* Consume the NUL. */
- yy_cp = ++yy_c_buf_p;
- yy_current_state = yy_next_state;
- goto yy_match;
- }
-
- else
- {
- yy_cp = yy_last_accepting_cpos;
- yy_current_state = yy_last_accepting_state;
- goto yy_find_action;
- }
- }
-
- else switch ( yy_get_next_buffer() )
- {
- case EOB_ACT_END_OF_FILE:
- {
- yy_did_buffer_switch_on_eof = 0;
-
- if ( yywrap() )
- {
- /* Note: because we've taken care in
- * yy_get_next_buffer() to have set up
- * yytext, we can now set up
- * yy_c_buf_p so that if some total
- * hoser (like flex itself) wants to
- * call the scanner after we return the
- * YY_NULL, it'll still work - another
- * YY_NULL will get returned.
- */
- yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
-
- yy_act = YY_STATE_EOF(YY_START);
- goto do_action;
- }
-
- else
- {
- if ( ! yy_did_buffer_switch_on_eof )
- YY_NEW_FILE;
- }
- break;
- }
-
- case EOB_ACT_CONTINUE_SCAN:
- yy_c_buf_p =
- yytext_ptr + yy_amount_of_matched_text;
-
- yy_current_state = yy_get_previous_state();
-
- yy_cp = yy_c_buf_p;
- yy_bp = yytext_ptr + YY_MORE_ADJ;
- goto yy_match;
-
- case EOB_ACT_LAST_MATCH:
- yy_c_buf_p =
- &yy_current_buffer->yy_ch_buf[yy_n_chars];
-
- yy_current_state = yy_get_previous_state();
-
- yy_cp = yy_c_buf_p;
- yy_bp = yytext_ptr + YY_MORE_ADJ;
- goto yy_find_action;
- }
- break;
- }
-
- default:
- YY_FATAL_ERROR(
- "fatal flex scanner internal error--no action found" );
- } /* end of action switch */
- } /* end of scanning one token */
- } /* end of yylex */
-
-
-/* yy_get_next_buffer - try to read in a new buffer
- *
- * Returns a code representing an action:
- * EOB_ACT_LAST_MATCH -
- * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
- * EOB_ACT_END_OF_FILE - end of file
- */
-
-static int yy_get_next_buffer()
- {
- register char *dest = yy_current_buffer->yy_ch_buf;
- register char *source = yytext_ptr;
- register int number_to_move, i;
- int ret_val;
-
- if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
- YY_FATAL_ERROR(
- "fatal flex scanner internal error--end of buffer missed" );
-
- if ( yy_current_buffer->yy_fill_buffer == 0 )
- { /* Don't try to fill the buffer, so this is an EOF. */
- if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
- {
- /* We matched a single character, the EOB, so
- * treat this as a final EOF.
- */
- return EOB_ACT_END_OF_FILE;
- }
-
- else
- {
- /* We matched some text prior to the EOB, first
- * process it.
- */
- return EOB_ACT_LAST_MATCH;
- }
- }
-
- /* Try to read more data. */
-
- /* First move last chars to start of buffer. */
- number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1;
-
- for ( i = 0; i < number_to_move; ++i )
- *(dest++) = *(source++);
-
- if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING )
- /* don't do the read, it's not guaranteed to return an EOF,
- * just force an EOF
- */
- yy_current_buffer->yy_n_chars = yy_n_chars = 0;
-
- else
- {
- int num_to_read =
- yy_current_buffer->yy_buf_size - number_to_move - 1;
-
- while ( num_to_read <= 0 )
- { /* Not enough room in the buffer - grow it. */
-#ifdef YY_USES_REJECT
- YY_FATAL_ERROR(
-"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
-#else
-
- /* just a shorter name for the current buffer */
- YY_BUFFER_STATE b = yy_current_buffer;
-
- int yy_c_buf_p_offset =
- (int) (yy_c_buf_p - b->yy_ch_buf);
-
- if ( b->yy_is_our_buffer )
- {
- int new_size = b->yy_buf_size * 2;
-
- if ( new_size <= 0 )
- b->yy_buf_size += b->yy_buf_size / 8;
- else
- b->yy_buf_size *= 2;
-
- b->yy_ch_buf = (char *)
- /* Include room in for 2 EOB chars. */
- yy_flex_realloc( (void *) b->yy_ch_buf,
- b->yy_buf_size + 2 );
- }
- else
- /* Can't grow it, we don't own it. */
- b->yy_ch_buf = 0;
-
- if ( ! b->yy_ch_buf )
- YY_FATAL_ERROR(
- "fatal error - scanner input buffer overflow" );
-
- yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
-
- num_to_read = yy_current_buffer->yy_buf_size -
- number_to_move - 1;
-#endif
- }
-
- if ( num_to_read > YY_READ_BUF_SIZE )
- num_to_read = YY_READ_BUF_SIZE;
-
- /* Read in more data. */
- YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
- yy_n_chars, num_to_read );
-
- yy_current_buffer->yy_n_chars = yy_n_chars;
- }
-
- if ( yy_n_chars == 0 )
- {
- if ( number_to_move == YY_MORE_ADJ )
- {
- ret_val = EOB_ACT_END_OF_FILE;
- yyrestart( yyin );
- }
-
- else
- {
- ret_val = EOB_ACT_LAST_MATCH;
- yy_current_buffer->yy_buffer_status =
- YY_BUFFER_EOF_PENDING;
- }
- }
-
- else
- ret_val = EOB_ACT_CONTINUE_SCAN;
-
- yy_n_chars += number_to_move;
- yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
- yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
-
- yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
-
- return ret_val;
- }
-
-
-/* yy_get_previous_state - get the state just before the EOB char was reached */
-
-static yy_state_type yy_get_previous_state()
- {
- register yy_state_type yy_current_state;
- register char *yy_cp;
-
- yy_current_state = yy_start;
-
- for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
- {
- register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
- if ( yy_accept[yy_current_state] )
- {
- yy_last_accepting_state = yy_current_state;
- yy_last_accepting_cpos = yy_cp;
- }
- while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
- {
- yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 86 )
- yy_c = yy_meta[(unsigned int) yy_c];
- }
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- }
-
- return yy_current_state;
- }
-
-
-/* yy_try_NUL_trans - try to make a transition on the NUL character
- *
- * synopsis
- * next_state = yy_try_NUL_trans( current_state );
- */
-
-#ifdef YY_USE_PROTOS
-static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
-#else
-static yy_state_type yy_try_NUL_trans( yy_current_state )
-yy_state_type yy_current_state;
-#endif
- {
- register int yy_is_jam;
- register char *yy_cp = yy_c_buf_p;
-
- register YY_CHAR yy_c = 1;
- if ( yy_accept[yy_current_state] )
- {
- yy_last_accepting_state = yy_current_state;
- yy_last_accepting_cpos = yy_cp;
- }
- while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
- {
- yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 86 )
- yy_c = yy_meta[(unsigned int) yy_c];
- }
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- yy_is_jam = (yy_current_state == 85);
-
- return yy_is_jam ? 0 : yy_current_state;
- }
-
-
-#ifndef YY_NO_UNPUT
-#ifdef YY_USE_PROTOS
-static void yyunput( int c, register char *yy_bp )
-#else
-static void yyunput( c, yy_bp )
-int c;
-register char *yy_bp;
-#endif
- {
- register char *yy_cp = yy_c_buf_p;
-
- /* undo effects of setting up yytext */
- *yy_cp = yy_hold_char;
-
- if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
- { /* need to shift things up to make room */
- /* +2 for EOB chars. */
- register int number_to_move = yy_n_chars + 2;
- register char *dest = &yy_current_buffer->yy_ch_buf[
- yy_current_buffer->yy_buf_size + 2];
- register char *source =
- &yy_current_buffer->yy_ch_buf[number_to_move];
-
- while ( source > yy_current_buffer->yy_ch_buf )
- *--dest = *--source;
-
- yy_cp += (int) (dest - source);
- yy_bp += (int) (dest - source);
- yy_current_buffer->yy_n_chars =
- yy_n_chars = yy_current_buffer->yy_buf_size;
-
- if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
- YY_FATAL_ERROR( "flex scanner push-back overflow" );
- }
-
- *--yy_cp = (char) c;
-
-
- yytext_ptr = yy_bp;
- yy_hold_char = *yy_cp;
- yy_c_buf_p = yy_cp;
- }
-#endif /* ifndef YY_NO_UNPUT */
-
-
-#ifdef __cplusplus
-static int yyinput()
-#else
-static int input()
-#endif
- {
- int c;
-
- *yy_c_buf_p = yy_hold_char;
-
- if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
- {
- /* yy_c_buf_p now points to the character we want to return.
- * If this occurs *before* the EOB characters, then it's a
- * valid NUL; if not, then we've hit the end of the buffer.
- */
- if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
- /* This was really a NUL. */
- *yy_c_buf_p = '\0';
-
- else
- { /* need more input */
- int offset = yy_c_buf_p - yytext_ptr;
- ++yy_c_buf_p;
-
- switch ( yy_get_next_buffer() )
- {
- case EOB_ACT_LAST_MATCH:
- /* This happens because yy_g_n_b()
- * sees that we've accumulated a
- * token and flags that we need to
- * try matching the token before
- * proceeding. But for input(),
- * there's no matching to consider.
- * So convert the EOB_ACT_LAST_MATCH
- * to EOB_ACT_END_OF_FILE.
- */
-
- /* Reset buffer status. */
- yyrestart( yyin );
-
- /* fall through */
-
- case EOB_ACT_END_OF_FILE:
- {
- if ( yywrap() )
- return EOF;
-
- if ( ! yy_did_buffer_switch_on_eof )
- YY_NEW_FILE;
-#ifdef __cplusplus
- return yyinput();
-#else
- return input();
-#endif
- }
-
- case EOB_ACT_CONTINUE_SCAN:
- yy_c_buf_p = yytext_ptr + offset;
- break;
- }
- }
- }
-
- c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */
- *yy_c_buf_p = '\0'; /* preserve yytext */
- yy_hold_char = *++yy_c_buf_p;
-
-
- return c;
- }
-
-
-#ifdef YY_USE_PROTOS
-void yyrestart( FILE *input_file )
-#else
-void yyrestart( input_file )
-FILE *input_file;
-#endif
- {
- if ( ! yy_current_buffer )
- yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
-
- yy_init_buffer( yy_current_buffer, input_file );
- yy_load_buffer_state();
- }
-
-
-#ifdef YY_USE_PROTOS
-void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
-#else
-void yy_switch_to_buffer( new_buffer )
-YY_BUFFER_STATE new_buffer;
-#endif
- {
- if ( yy_current_buffer == new_buffer )
- return;
-
- if ( yy_current_buffer )
- {
- /* Flush out information for old buffer. */
- *yy_c_buf_p = yy_hold_char;
- yy_current_buffer->yy_buf_pos = yy_c_buf_p;
- yy_current_buffer->yy_n_chars = yy_n_chars;
- }
-
- yy_current_buffer = new_buffer;
- yy_load_buffer_state();
-
- /* We don't actually know whether we did this switch during
- * EOF (yywrap()) processing, but the only time this flag
- * is looked at is after yywrap() is called, so it's safe
- * to go ahead and always set it.
- */
- yy_did_buffer_switch_on_eof = 1;
- }
-
-
-#ifdef YY_USE_PROTOS
-void yy_load_buffer_state( void )
-#else
-void yy_load_buffer_state()
-#endif
- {
- yy_n_chars = yy_current_buffer->yy_n_chars;
- yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
- yyin = yy_current_buffer->yy_input_file;
- yy_hold_char = *yy_c_buf_p;
- }
-
-
-#ifdef YY_USE_PROTOS
-YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
-#else
-YY_BUFFER_STATE yy_create_buffer( file, size )
-FILE *file;
-int size;
-#endif
- {
- YY_BUFFER_STATE b;
-
- b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
- if ( ! b )
- YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
-
- b->yy_buf_size = size;
-
- /* yy_ch_buf has to be 2 characters longer than the size given because
- * we need to put in 2 end-of-buffer characters.
- */
- b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
- if ( ! b->yy_ch_buf )
- YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
-
- b->yy_is_our_buffer = 1;
-
- yy_init_buffer( b, file );
-
- return b;
- }
-
-
-#ifdef YY_USE_PROTOS
-void yy_delete_buffer( YY_BUFFER_STATE b )
-#else
-void yy_delete_buffer( b )
-YY_BUFFER_STATE b;
-#endif
- {
- if ( ! b )
- return;
-
- if ( b == yy_current_buffer )
- yy_current_buffer = (YY_BUFFER_STATE) 0;
-
- if ( b->yy_is_our_buffer )
- yy_flex_free( (void *) b->yy_ch_buf );
-
- yy_flex_free( (void *) b );
- }
-
-
-#ifndef YY_ALWAYS_INTERACTIVE
-#ifndef YY_NEVER_INTERACTIVE
-extern int isatty YY_PROTO(( int ));
-#endif
-#endif
-
-#ifdef YY_USE_PROTOS
-void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
-#else
-void yy_init_buffer( b, file )
-YY_BUFFER_STATE b;
-FILE *file;
-#endif
-
-
- {
- yy_flush_buffer( b );
-
- b->yy_input_file = file;
- b->yy_fill_buffer = 1;
-
-#if YY_ALWAYS_INTERACTIVE
- b->yy_is_interactive = 1;
-#else
-#if YY_NEVER_INTERACTIVE
- b->yy_is_interactive = 0;
-#else
- b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
-#endif
-#endif
- }
-
-
-#ifdef YY_USE_PROTOS
-void yy_flush_buffer( YY_BUFFER_STATE b )
-#else
-void yy_flush_buffer( b )
-YY_BUFFER_STATE b;
-#endif
-
- {
- if ( ! b )
- return;
-
- b->yy_n_chars = 0;
-
- /* We always need two end-of-buffer characters. The first causes
- * a transition to the end-of-buffer state. The second causes
- * a jam in that state.
- */
- b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
- b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
-
- b->yy_buf_pos = &b->yy_ch_buf[0];
-
- b->yy_at_bol = 1;
- b->yy_buffer_status = YY_BUFFER_NEW;
-
- if ( b == yy_current_buffer )
- yy_load_buffer_state();
- }
-
-
-#ifndef YY_NO_SCAN_BUFFER
-#ifdef YY_USE_PROTOS
-YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
-#else
-YY_BUFFER_STATE yy_scan_buffer( base, size )
-char *base;
-yy_size_t size;
-#endif
- {
- YY_BUFFER_STATE b;
-
- if ( size < 2 ||
- base[size-2] != YY_END_OF_BUFFER_CHAR ||
- base[size-1] != YY_END_OF_BUFFER_CHAR )
- /* They forgot to leave room for the EOB's. */
- return 0;
-
- b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
- if ( ! b )
- YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
-
- b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
- b->yy_buf_pos = b->yy_ch_buf = base;
- b->yy_is_our_buffer = 0;
- b->yy_input_file = 0;
- b->yy_n_chars = b->yy_buf_size;
- b->yy_is_interactive = 0;
- b->yy_at_bol = 1;
- b->yy_fill_buffer = 0;
- b->yy_buffer_status = YY_BUFFER_NEW;
-
- yy_switch_to_buffer( b );
-
- return b;
- }
-#endif
-
-
-#ifndef YY_NO_SCAN_STRING
-#ifdef YY_USE_PROTOS
-YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str )
-#else
-YY_BUFFER_STATE yy_scan_string( yy_str )
-yyconst char *yy_str;
-#endif
- {
- int len;
- for ( len = 0; yy_str[len]; ++len )
- ;
-
- return yy_scan_bytes( yy_str, len );
- }
-#endif
-
-
-#ifndef YY_NO_SCAN_BYTES
-#ifdef YY_USE_PROTOS
-YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
-#else
-YY_BUFFER_STATE yy_scan_bytes( bytes, len )
-yyconst char *bytes;
-int len;
-#endif
- {
- YY_BUFFER_STATE b;
- char *buf;
- yy_size_t n;
- int i;
-
- /* Get memory for full buffer, including space for trailing EOB's. */
- n = len + 2;
- buf = (char *) yy_flex_alloc( n );
- if ( ! buf )
- YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
-
- for ( i = 0; i < len; ++i )
- buf[i] = bytes[i];
-
- buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
-
- b = yy_scan_buffer( buf, n );
- if ( ! b )
- YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
-
- /* It's okay to grow etc. this buffer, and we should throw it
- * away when we're done.
- */
- b->yy_is_our_buffer = 1;
-
- return b;
- }
-#endif
-
-
-#ifndef YY_NO_PUSH_STATE
-#ifdef YY_USE_PROTOS
-static void yy_push_state( int new_state )
-#else
-static void yy_push_state( new_state )
-int new_state;
-#endif
- {
- if ( yy_start_stack_ptr >= yy_start_stack_depth )
- {
- yy_size_t new_size;
-
- yy_start_stack_depth += YY_START_STACK_INCR;
- new_size = yy_start_stack_depth * sizeof( int );
-
- if ( ! yy_start_stack )
- yy_start_stack = (int *) yy_flex_alloc( new_size );
-
- else
- yy_start_stack = (int *) yy_flex_realloc(
- (void *) yy_start_stack, new_size );
-
- if ( ! yy_start_stack )
- YY_FATAL_ERROR(
- "out of memory expanding start-condition stack" );
- }
-
- yy_start_stack[yy_start_stack_ptr++] = YY_START;
-
- BEGIN(new_state);
- }
-#endif
-
-
-#ifndef YY_NO_POP_STATE
-static void yy_pop_state()
- {
- if ( --yy_start_stack_ptr < 0 )
- YY_FATAL_ERROR( "start-condition stack underflow" );
-
- BEGIN(yy_start_stack[yy_start_stack_ptr]);
- }
-#endif
-
-
-#ifndef YY_NO_TOP_STATE
-static int yy_top_state()
- {
- return yy_start_stack[yy_start_stack_ptr - 1];
- }
-#endif
-
-#ifndef YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#endif
-
-#ifdef YY_USE_PROTOS
-static void yy_fatal_error( yyconst char msg[] )
-#else
-static void yy_fatal_error( msg )
-char msg[];
-#endif
- {
- (void) fprintf( stderr, "%s\n", msg );
- exit( YY_EXIT_FAILURE );
- }
-
-
-
-/* Redefine yyless() so it works in section 3 code. */
-
-#undef yyless
-#define yyless(n) \
- do \
- { \
- /* Undo effects of setting up yytext. */ \
- yytext[yyleng] = yy_hold_char; \
- yy_c_buf_p = yytext + n; \
- yy_hold_char = *yy_c_buf_p; \
- *yy_c_buf_p = '\0'; \
- yyleng = n; \
- } \
- while ( 0 )
-
-
-/* Internal utility routines. */
-
-#ifndef yytext_ptr
-#ifdef YY_USE_PROTOS
-static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
-#else
-static void yy_flex_strncpy( s1, s2, n )
-char *s1;
-yyconst char *s2;
-int n;
-#endif
- {
- register int i;
- for ( i = 0; i < n; ++i )
- s1[i] = s2[i];
- }
-#endif
-
-#ifdef YY_NEED_STRLEN
-#ifdef YY_USE_PROTOS
-static int yy_flex_strlen( yyconst char *s )
-#else
-static int yy_flex_strlen( s )
-yyconst char *s;
-#endif
- {
- register int n;
- for ( n = 0; s[n]; ++n )
- ;
-
- return n;
- }
-#endif
-
-
-#ifdef YY_USE_PROTOS
-static void *yy_flex_alloc( yy_size_t size )
-#else
-static void *yy_flex_alloc( size )
-yy_size_t size;
-#endif
- {
- return (void *) malloc( size );
- }
-
-#ifdef YY_USE_PROTOS
-static void *yy_flex_realloc( void *ptr, yy_size_t size )
-#else
-static void *yy_flex_realloc( ptr, size )
-void *ptr;
-yy_size_t size;
-#endif
- {
- /* The cast to (char *) in the following accommodates both
- * implementations that use char* generic pointers, and those
- * that use void* generic pointers. It works with the latter
- * because both ANSI C and C++ allow castless assignment from
- * any pointer type to void*, and deal with argument conversions
- * as though doing an assignment.
- */
- return (void *) realloc( (char *) ptr, size );
- }
-
-#ifdef YY_USE_PROTOS
-static void yy_flex_free( void *ptr )
-#else
-static void yy_flex_free( ptr )
-void *ptr;
-#endif
- {
- free( ptr );
- }
-
-#if YY_MAIN
-int main()
- {
- yylex();
- return 0;
- }
-#endif
-#line 247 "ssl_expr_scan.l"
-
-
-int yyinput(char *buf, int max_size)
-{
- int n;
-
- if ((n = MIN(max_size, ssl_expr_info.inputbuf
- + ssl_expr_info.inputlen
- - ssl_expr_info.inputptr)) <= 0)
- return YY_NULL;
- memcpy(buf, ssl_expr_info.inputptr, n);
- ssl_expr_info.inputptr += n;
- return n;
-}
-
diff --git a/modules/ssl/ssl_expr_scan.l b/modules/ssl/ssl_expr_scan.l
deleted file mode 100644
index a0db7cccde..0000000000
--- a/modules/ssl/ssl_expr_scan.l
+++ /dev/null
@@ -1,261 +0,0 @@
-/* _ _
-** _ __ ___ ___ __| | ___ ___| |
-** | '_ ` _ \ / _ \ / _` | / __/ __| |
-** | | | | | | (_) | (_| | \__ \__ \ | mod_ssl - Apache Interface to OpenSSL
-** |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.modssl.org/
-** |_____|
-** ssl_expr_scan.l
-** Expression Scanner
-*/
-
-/* ====================================================================
- * Copyright (c) 1998-2001 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * 4. The names "mod_ssl" must not be used to endorse or promote
- * products derived from this software without prior written
- * permission. For written permission, please contact
- * rse@engelschall.com.
- *
- * 5. Products derived from this software may not be called "mod_ssl"
- * nor may "mod_ssl" appear in their names without prior
- * written permission of Ralf S. Engelschall.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
-
- /* ``Killing for peace is
- like fucking for virginity.''
- -- Unknown */
-
-/* _________________________________________________________________
-**
-** Expression Scanner
-** _________________________________________________________________
-*/
-
-%{
-#include "mod_ssl.h"
-
-#include "ssl_expr_parse.h"
-
-#define YY_NO_UNPUT 1
-int yyinput(char *buf, int max_size);
-
-#undef YY_INPUT
-#define YY_INPUT(buf,result,max_size) \
- (result = yyinput(buf, max_size))
-
-#define MAX_STR_LEN 2048
-%}
-
-%pointer
-/* %option stack */
-%option never-interactive
-%option noyywrap
-%x str
-%x regex regex_flags
-
-%%
-
- char caStr[MAX_STR_LEN];
- char *cpStr = NULL;
- char caRegex[MAX_STR_LEN];
- char *cpRegex = NULL;
- char cRegexDel = NUL;
-
- /*
- * Whitespaces
- */
-[ \t\n]+ {
- /* NOP */
-}
-
- /*
- * C-style strings ("...")
- */
-\" {
- cpStr = caStr;
- BEGIN(str);
-}
-<str>\" {
- BEGIN(INITIAL);
- *cpStr = NUL;
- yylval.cpVal = ap_pstrdup(ssl_expr_info.pool, caStr);
- return T_STRING;
-}
-<str>\n {
- yyerror("Unterminated string");
-}
-<str>\\[0-7]{1,3} {
- int result;
-
- (void)sscanf(yytext+1, "%o", &result);
- if (result > 0xff)
- yyerror("Escape sequence out of bound");
- else
- *cpStr++ = result;
-}
-<str>\\[0-9]+ {
- yyerror("Bad escape sequence");
-}
-<str>\\n { *cpStr++ = '\n'; }
-<str>\\r { *cpStr++ = '\r'; }
-<str>\\t { *cpStr++ = '\t'; }
-<str>\\b { *cpStr++ = '\b'; }
-<str>\\f { *cpStr++ = '\f'; }
-<str>\\(.|\n) {
- *cpStr++ = yytext[1];
-}
-<str>[^\\\n\"]+ {
- char *cp = yytext;
- while (*cp != NUL)
- *cpStr++ = *cp++;
-}
-<str>. {
- *cpStr++ = yytext[1];
-}
-
- /*
- * Regular Expression
- */
-"m". {
- cRegexDel = yytext[1];
- cpRegex = caRegex;
- BEGIN(regex);
-}
-<regex>.|\n {
- if (yytext[0] == cRegexDel) {
- *cpRegex = NUL;
- BEGIN(regex_flags);
- }
- else {
- *cpRegex++ = yytext[0];
- }
-}
-<regex_flags>i {
- yylval.cpVal = ap_pstrdup(ssl_expr_info.pool, caRegex);
- BEGIN(INITIAL);
- return T_REGEX_I;
-}
-<regex_flags>.|\n {
- yylval.cpVal = ap_pstrdup(ssl_expr_info.pool, caRegex);
- yyless(0);
- BEGIN(INITIAL);
- return T_REGEX;
-}
-<regex_flags><<EOF>> {
- yylval.cpVal = ap_pstrdup(ssl_expr_info.pool, caRegex);
- BEGIN(INITIAL);
- return T_REGEX;
-}
-
- /*
- * Operators
- */
-"eq" { return T_OP_EQ; }
-"==" { return T_OP_EQ; }
-"ne" { return T_OP_NE; }
-"!=" { return T_OP_NE; }
-"lt" { return T_OP_LT; }
-"<" { return T_OP_LT; }
-"le" { return T_OP_LE; }
-"<=" { return T_OP_LE; }
-"gt" { return T_OP_GT; }
-">" { return T_OP_GT; }
-"ge" { return T_OP_GE; }
-">=" { return T_OP_GE; }
-"=~" { return T_OP_REG; }
-"!~" { return T_OP_NRE; }
-"and" { return T_OP_AND; }
-"&&" { return T_OP_AND; }
-"or" { return T_OP_OR; }
-"||" { return T_OP_OR; }
-"not" { return T_OP_NOT; }
-"!" { return T_OP_NOT; }
-"in" { return T_OP_IN; }
-
- /*
- * Functions
- */
-"file" { return T_FUNC_FILE; }
-
- /*
- * Specials
- */
-"true" { return T_TRUE; }
-"false" { return T_FALSE; }
-
- /*
- * Digits
- */
-[0-9]+ {
- yylval.cpVal = ap_pstrdup(ssl_expr_info.pool, yytext);
- return T_DIGIT;
-}
-
- /*
- * Identifiers
- */
-[a-zA-Z][a-zA-Z0-9_:-]* {
- yylval.cpVal = ap_pstrdup(ssl_expr_info.pool, yytext);
- return T_ID;
-}
-
- /*
- * Anything else is returned as is...
- */
-.|\n {
- return yytext[0];
-}
-
-%%
-
-int yyinput(char *buf, int max_size)
-{
- int n;
-
- if ((n = MIN(max_size, ssl_expr_info.inputbuf
- + ssl_expr_info.inputlen
- - ssl_expr_info.inputptr)) <= 0)
- return YY_NULL;
- memcpy(buf, ssl_expr_info.inputptr, n);
- ssl_expr_info.inputptr += n;
- return n;
-}
-
diff --git a/modules/ssl/ssl_scache.c b/modules/ssl/ssl_scache.c
deleted file mode 100644
index 139c7865fe..0000000000
--- a/modules/ssl/ssl_scache.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/* _ _
-** _ __ ___ ___ __| | ___ ___| | mod_ssl
-** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
-** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
-** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
-** |_____|
-** ssl_scache.c
-** Session Cache Abstraction
-*/
-
-/* ====================================================================
- * Copyright (c) 1998-2001 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * 4. The names "mod_ssl" must not be used to endorse or promote
- * products derived from this software without prior written
- * permission. For written permission, please contact
- * rse@engelschall.com.
- *
- * 5. Products derived from this software may not be called "mod_ssl"
- * nor may "mod_ssl" appear in their names without prior
- * written permission of Ralf S. Engelschall.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
- /* ``Open-Source Software: generous
- programmers from around the world all
- join forces to help you shoot
- yourself in the foot for free.''
- -- Unknown */
-#include "mod_ssl.h"
-
-/* _________________________________________________________________
-**
-** Session Cache: Common Abstraction Layer
-** _________________________________________________________________
-*/
-
-void ssl_scache_init(server_rec *s, pool *p)
-{
- SSLModConfigRec *mc = myModConfig();
-
- if (mc->nSessionCacheMode == SSL_SCMODE_DBM)
- ssl_scache_dbm_init(s, p);
- else if (mc->nSessionCacheMode == SSL_SCMODE_SHMHT)
- ssl_scache_shmht_init(s, p);
- else if (mc->nSessionCacheMode == SSL_SCMODE_SHMCB)
- ssl_scache_shmcb_init(s, p);
-#ifdef SSL_VENDOR
- else
- ap_hook_use("ap::mod_ssl::vendor::scache_init",
- AP_HOOK_SIG3(void,ptr,ptr), AP_HOOK_ALL, s, p);
-#endif
- return;
-}
-
-void ssl_scache_kill(server_rec *s)
-{
- SSLModConfigRec *mc = myModConfig();
-
- if (mc->nSessionCacheMode == SSL_SCMODE_DBM)
- ssl_scache_dbm_kill(s);
- else if (mc->nSessionCacheMode == SSL_SCMODE_SHMHT)
- ssl_scache_shmht_kill(s);
- else if (mc->nSessionCacheMode == SSL_SCMODE_SHMCB)
- ssl_scache_shmcb_kill(s);
-#ifdef SSL_VENDOR
- else
- ap_hook_use("ap::mod_ssl::vendor::scache_kill",
- AP_HOOK_SIG2(void,ptr), AP_HOOK_ALL, s);
-#endif
- return;
-}
-
-BOOL ssl_scache_store(server_rec *s, UCHAR *id, int idlen, time_t expiry, SSL_SESSION *sess)
-{
- SSLModConfigRec *mc = myModConfig();
- BOOL rv = FALSE;
-
- if (mc->nSessionCacheMode == SSL_SCMODE_DBM)
- rv = ssl_scache_dbm_store(s, id, idlen, expiry, sess);
- else if (mc->nSessionCacheMode == SSL_SCMODE_SHMHT)
- rv = ssl_scache_shmht_store(s, id, idlen, expiry, sess);
- else if (mc->nSessionCacheMode == SSL_SCMODE_SHMCB)
- rv = ssl_scache_shmcb_store(s, id, idlen, expiry, sess);
-#ifdef SSL_VENDOR
- else
- ap_hook_use("ap::mod_ssl::vendor::scache_store",
- AP_HOOK_SIG6(int,ptr,ptr,int,int,ptr), AP_HOOK_ALL,
- (int *)&rv, s, id, idlen, (int)expiry, sess);
-#endif
- return rv;
-}
-
-SSL_SESSION *ssl_scache_retrieve(server_rec *s, UCHAR *id, int idlen)
-{
- SSLModConfigRec *mc = myModConfig();
- SSL_SESSION *sess = NULL;
-
- if (mc->nSessionCacheMode == SSL_SCMODE_DBM)
- sess = ssl_scache_dbm_retrieve(s, id, idlen);
- else if (mc->nSessionCacheMode == SSL_SCMODE_SHMHT)
- sess = ssl_scache_shmht_retrieve(s, id, idlen);
- else if (mc->nSessionCacheMode == SSL_SCMODE_SHMCB)
- sess = ssl_scache_shmcb_retrieve(s, id, idlen);
-#ifdef SSL_VENDOR
- else
- ap_hook_use("ap::mod_ssl::vendor::scache_retrieve",
- AP_HOOK_SIG4(ptr,ptr,ptr,int), AP_HOOK_ALL,
- &sess, s, id, idlen);
-#endif
- return sess;
-}
-
-void ssl_scache_remove(server_rec *s, UCHAR *id, int idlen)
-{
- SSLModConfigRec *mc = myModConfig();
-
- if (mc->nSessionCacheMode == SSL_SCMODE_DBM)
- ssl_scache_dbm_remove(s, id, idlen);
- else if (mc->nSessionCacheMode == SSL_SCMODE_SHMHT)
- ssl_scache_shmht_remove(s, id, idlen);
- else if (mc->nSessionCacheMode == SSL_SCMODE_SHMCB)
- ssl_scache_shmcb_remove(s, id, idlen);
-#ifdef SSL_VENDOR
- else
- ap_hook_use("ap::mod_ssl::vendor::scache_remove",
- AP_HOOK_SIG4(void,ptr,ptr,int), AP_HOOK_ALL, s, id, idlen);
-#endif
- return;
-}
-
-void ssl_scache_status(server_rec *s, pool *p, void (*func)(char *, void *), void *arg)
-{
- SSLModConfigRec *mc = myModConfig();
-
- if (mc->nSessionCacheMode == SSL_SCMODE_DBM)
- ssl_scache_dbm_status(s, p, func, arg);
- else if (mc->nSessionCacheMode == SSL_SCMODE_SHMHT)
- ssl_scache_shmht_status(s, p, func, arg);
- else if (mc->nSessionCacheMode == SSL_SCMODE_SHMCB)
- ssl_scache_shmcb_status(s, p, func, arg);
-#ifdef SSL_VENDOR
- else
- ap_hook_use("ap::mod_ssl::vendor::scache_status",
- AP_HOOK_SIG5(void,ptr,ptr,ptr,ptr), AP_HOOK_ALL,
- s, p, func, arg);
-#endif
- return;
-}
-
-void ssl_scache_expire(server_rec *s)
-{
- SSLModConfigRec *mc = myModConfig();
-
- if (mc->nSessionCacheMode == SSL_SCMODE_DBM)
- ssl_scache_dbm_expire(s);
- else if (mc->nSessionCacheMode == SSL_SCMODE_SHMHT)
- ssl_scache_shmht_expire(s);
- else if (mc->nSessionCacheMode == SSL_SCMODE_SHMCB)
- ssl_scache_shmcb_expire(s);
-#ifdef SSL_VENDOR
- else
- ap_hook_use("ap::mod_ssl::vendor::scache_expire",
- AP_HOOK_SIG2(void,ptr), AP_HOOK_ALL, s);
-#endif
- return;
-}
-
diff --git a/modules/ssl/ssl_scache_dbm.c b/modules/ssl/ssl_scache_dbm.c
deleted file mode 100644
index 323c612991..0000000000
--- a/modules/ssl/ssl_scache_dbm.c
+++ /dev/null
@@ -1,440 +0,0 @@
-/* _ _
-** _ __ ___ ___ __| | ___ ___| | mod_ssl
-** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
-** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
-** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
-** |_____|
-** ssl_scache_dbm.c
-** Session Cache via DBM
-*/
-
-/* ====================================================================
- * Copyright (c) 1998-2001 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * 4. The names "mod_ssl" must not be used to endorse or promote
- * products derived from this software without prior written
- * permission. For written permission, please contact
- * rse@engelschall.com.
- *
- * 5. Products derived from this software may not be called "mod_ssl"
- * nor may "mod_ssl" appear in their names without prior
- * written permission of Ralf S. Engelschall.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
-
-#include "mod_ssl.h"
-
-void ssl_scache_dbm_init(server_rec *s, pool *p)
-{
- SSLModConfigRec *mc = myModConfig();
- DBM *dbm;
-
- /* for the DBM we need the data file */
- if (mc->szSessionCacheDataFile == NULL) {
- ssl_log(s, SSL_LOG_ERROR, "SSLSessionCache required");
- ssl_die();
- }
-
- /* open it once to create it and to make sure it _can_ be created */
- ssl_mutex_on(s);
- if ((dbm = ssl_dbm_open(mc->szSessionCacheDataFile,
- O_RDWR|O_CREAT, SSL_DBM_FILE_MODE)) == NULL) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
- "Cannot create SSLSessionCache DBM file `%s'",
- mc->szSessionCacheDataFile);
- ssl_mutex_off(s);
- return;
- }
- ssl_dbm_close(dbm);
-
-#if !defined(OS2) && !defined(WIN32)
- /*
- * We have to make sure the Apache child processes have access to
- * the DBM file. But because there are brain-dead platforms where we
- * cannot exactly determine the suffixes we try all possibilities.
- */
- if (geteuid() == 0 /* is superuser */) {
- chown(mc->szSessionCacheDataFile, ap_user_id, -1 /* no gid change */);
- if (chown(ap_pstrcat(p, mc->szSessionCacheDataFile, SSL_DBM_FILE_SUFFIX_DIR, NULL),
- ap_user_id, -1) == -1) {
- if (chown(ap_pstrcat(p, mc->szSessionCacheDataFile, ".db", NULL),
- ap_user_id, -1) == -1)
- chown(ap_pstrcat(p, mc->szSessionCacheDataFile, ".dir", NULL),
- ap_user_id, -1);
- }
- if (chown(ap_pstrcat(p, mc->szSessionCacheDataFile, SSL_DBM_FILE_SUFFIX_PAG, NULL),
- ap_user_id, -1) == -1) {
- if (chown(ap_pstrcat(p, mc->szSessionCacheDataFile, ".db", NULL),
- ap_user_id, -1) == -1)
- chown(ap_pstrcat(p, mc->szSessionCacheDataFile, ".pag", NULL),
- ap_user_id, -1);
- }
- }
-#endif
- ssl_mutex_off(s);
- ssl_scache_dbm_expire(s);
- return;
-}
-
-void ssl_scache_dbm_kill(server_rec *s)
-{
- SSLModConfigRec *mc = myModConfig();
- pool *p;
-
- if ((p = ap_make_sub_pool(NULL)) != NULL) {
- /* the correct way */
- unlink(ap_pstrcat(p, mc->szSessionCacheDataFile, SSL_DBM_FILE_SUFFIX_DIR, NULL));
- unlink(ap_pstrcat(p, mc->szSessionCacheDataFile, SSL_DBM_FILE_SUFFIX_PAG, NULL));
- /* the additional ways to be sure */
- unlink(ap_pstrcat(p, mc->szSessionCacheDataFile, ".dir", NULL));
- unlink(ap_pstrcat(p, mc->szSessionCacheDataFile, ".pag", NULL));
- unlink(ap_pstrcat(p, mc->szSessionCacheDataFile, ".db", NULL));
- unlink(mc->szSessionCacheDataFile);
- ap_destroy_pool(p);
- }
- return;
-}
-
-BOOL ssl_scache_dbm_store(server_rec *s, UCHAR *id, int idlen, time_t expiry, SSL_SESSION *sess)
-{
- SSLModConfigRec *mc = myModConfig();
- DBM *dbm;
- datum dbmkey;
- datum dbmval;
- UCHAR ucaData[SSL_SESSION_MAX_DER];
- int nData;
- UCHAR *ucp;
-
- /* streamline session data */
- ucp = ucaData;
- nData = i2d_SSL_SESSION(sess, &ucp);
-
- /* be careful: do not try to store too much bytes in a DBM file! */
-#ifdef SSL_USE_SDBM
- if ((idlen + nData) >= PAIRMAX)
- return FALSE;
-#else
- if ((idlen + nData) >= 950 /* at least less than approx. 1KB */)
- return FALSE;
-#endif
-
- /* create DBM key */
- dbmkey.dptr = (char *)id;
- dbmkey.dsize = idlen;
-
- /* create DBM value */
- dbmval.dsize = sizeof(time_t) + nData;
- dbmval.dptr = (char *)malloc(dbmval.dsize);
- if (dbmval.dptr == NULL)
- return FALSE;
- memcpy((char *)dbmval.dptr, &expiry, sizeof(time_t));
- memcpy((char *)dbmval.dptr+sizeof(time_t), ucaData, nData);
-
- /* and store it to the DBM file */
- ssl_mutex_on(s);
- if ((dbm = ssl_dbm_open(mc->szSessionCacheDataFile,
- O_RDWR, SSL_DBM_FILE_MODE)) == NULL) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
- "Cannot open SSLSessionCache DBM file `%s' for writing (store)",
- mc->szSessionCacheDataFile);
- ssl_mutex_off(s);
- free(dbmval.dptr);
- return FALSE;
- }
- if (ssl_dbm_store(dbm, dbmkey, dbmval, DBM_INSERT) < 0) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
- "Cannot store SSL session to DBM file `%s'",
- mc->szSessionCacheDataFile);
- ssl_dbm_close(dbm);
- ssl_mutex_off(s);
- free(dbmval.dptr);
- return FALSE;
- }
- ssl_dbm_close(dbm);
- ssl_mutex_off(s);
-
- /* free temporary buffers */
- free(dbmval.dptr);
-
- /* allow the regular expiring to occur */
- ssl_scache_dbm_expire(s);
-
- return TRUE;
-}
-
-SSL_SESSION *ssl_scache_dbm_retrieve(server_rec *s, UCHAR *id, int idlen)
-{
- SSLModConfigRec *mc = myModConfig();
- DBM *dbm;
- datum dbmkey;
- datum dbmval;
- SSL_SESSION *sess = NULL;
- UCHAR *ucpData;
- int nData;
- time_t expiry;
- time_t now;
-
- /* allow the regular expiring to occur */
- ssl_scache_dbm_expire(s);
-
- /* create DBM key and values */
- dbmkey.dptr = (char *)id;
- dbmkey.dsize = idlen;
-
- /* and fetch it from the DBM file */
- ssl_mutex_on(s);
- if ((dbm = ssl_dbm_open(mc->szSessionCacheDataFile,
- O_RDONLY, SSL_DBM_FILE_MODE)) == NULL) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
- "Cannot open SSLSessionCache DBM file `%s' for reading (fetch)",
- mc->szSessionCacheDataFile);
- ssl_mutex_off(s);
- return NULL;
- }
- dbmval = ssl_dbm_fetch(dbm, dbmkey);
- ssl_dbm_close(dbm);
- ssl_mutex_off(s);
-
- /* immediately return if not found */
- if (dbmval.dptr == NULL || dbmval.dsize <= sizeof(time_t))
- return NULL;
-
- /* parse resulting data */
- nData = dbmval.dsize-sizeof(time_t);
- ucpData = (UCHAR *)malloc(nData);
- if (ucpData == NULL)
- return NULL;
- memcpy(ucpData, (char *)dbmval.dptr+sizeof(time_t), nData);
- memcpy(&expiry, dbmval.dptr, sizeof(time_t));
-
- /* make sure the stuff is still not expired */
- now = time(NULL);
- if (expiry <= now) {
- ssl_scache_dbm_remove(s, id, idlen);
- return NULL;
- }
-
- /* unstreamed SSL_SESSION */
- sess = d2i_SSL_SESSION(NULL, &ucpData, nData);
-
- return sess;
-}
-
-void ssl_scache_dbm_remove(server_rec *s, UCHAR *id, int idlen)
-{
- SSLModConfigRec *mc = myModConfig();
- DBM *dbm;
- datum dbmkey;
-
- /* create DBM key and values */
- dbmkey.dptr = (char *)id;
- dbmkey.dsize = idlen;
-
- /* and delete it from the DBM file */
- ssl_mutex_on(s);
- if ((dbm = ssl_dbm_open(mc->szSessionCacheDataFile,
- O_RDWR, SSL_DBM_FILE_MODE)) == NULL) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
- "Cannot open SSLSessionCache DBM file `%s' for writing (delete)",
- mc->szSessionCacheDataFile);
- ssl_mutex_off(s);
- return;
- }
- ssl_dbm_delete(dbm, dbmkey);
- ssl_dbm_close(dbm);
- ssl_mutex_off(s);
-
- return;
-}
-
-void ssl_scache_dbm_expire(server_rec *s)
-{
- SSLModConfigRec *mc = myModConfig();
- SSLSrvConfigRec *sc = mySrvConfig(s);
- static time_t tLast = 0;
- DBM *dbm;
- datum dbmkey;
- datum dbmval;
- pool *p;
- time_t tExpiresAt;
- int nElements = 0;
- int nDeleted = 0;
- int bDelete;
- datum *keylist;
- int keyidx;
- int i;
- time_t tNow;
-
- /*
- * make sure the expiration for still not-accessed session
- * cache entries is done only from time to time
- */
- tNow = time(NULL);
- if (tNow < tLast+sc->nSessionCacheTimeout)
- return;
- tLast = tNow;
-
- /*
- * Here we have to be very carefully: Not all DBM libraries are
- * smart enough to allow one to iterate over the elements and at the
- * same time delete expired ones. Some of them get totally crazy
- * while others have no problems. So we have to do it the slower but
- * more safe way: we first iterate over all elements and remember
- * those which have to be expired. Then in a second pass we delete
- * all those expired elements. Additionally we reopen the DBM file
- * to be really safe in state.
- */
-
-#define KEYMAX 1024
-
- ssl_mutex_on(s);
- for (;;) {
- /* allocate the key array in a memory sub pool */
- if ((p = ap_make_sub_pool(NULL)) == NULL)
- break;
- if ((keylist = ap_palloc(p, sizeof(dbmkey)*KEYMAX)) == NULL) {
- ap_destroy_pool(p);
- break;
- }
-
- /* pass 1: scan DBM database */
- keyidx = 0;
- if ((dbm = ssl_dbm_open(mc->szSessionCacheDataFile,
- O_RDWR, SSL_DBM_FILE_MODE)) == NULL) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
- "Cannot open SSLSessionCache DBM file `%s' for scanning",
- mc->szSessionCacheDataFile);
- ap_destroy_pool(p);
- break;
- }
- dbmkey = ssl_dbm_firstkey(dbm);
- while (dbmkey.dptr != NULL) {
- nElements++;
- bDelete = FALSE;
- dbmval = ssl_dbm_fetch(dbm, dbmkey);
- if (dbmval.dsize <= sizeof(time_t) || dbmval.dptr == NULL)
- bDelete = TRUE;
- else {
- memcpy(&tExpiresAt, dbmval.dptr, sizeof(time_t));
- if (tExpiresAt <= tNow)
- bDelete = TRUE;
- }
- if (bDelete) {
- if ((keylist[keyidx].dptr = ap_palloc(p, dbmkey.dsize)) != NULL) {
- memcpy(keylist[keyidx].dptr, dbmkey.dptr, dbmkey.dsize);
- keylist[keyidx].dsize = dbmkey.dsize;
- keyidx++;
- if (keyidx == KEYMAX)
- break;
- }
- }
- dbmkey = ssl_dbm_nextkey(dbm);
- }
- ssl_dbm_close(dbm);
-
- /* pass 2: delete expired elements */
- if ((dbm = ssl_dbm_open(mc->szSessionCacheDataFile,
- O_RDWR, SSL_DBM_FILE_MODE)) == NULL) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
- "Cannot re-open SSLSessionCache DBM file `%s' for expiring",
- mc->szSessionCacheDataFile);
- ap_destroy_pool(p);
- break;
- }
- for (i = 0; i < keyidx; i++) {
- ssl_dbm_delete(dbm, keylist[i]);
- nDeleted++;
- }
- ssl_dbm_close(dbm);
-
- /* destroy temporary pool */
- ap_destroy_pool(p);
-
- if (keyidx < KEYMAX)
- break;
- }
- ssl_mutex_off(s);
-
- ssl_log(s, SSL_LOG_TRACE, "Inter-Process Session Cache (DBM) Expiry: "
- "old: %d, new: %d, removed: %d", nElements, nElements-nDeleted, nDeleted);
- return;
-}
-
-void ssl_scache_dbm_status(server_rec *s, pool *p, void (*func)(char *, void *), void *arg)
-{
- SSLModConfigRec *mc = myModConfig();
- DBM *dbm;
- datum dbmkey;
- datum dbmval;
- int nElem;
- int nSize;
- int nAverage;
-
- nElem = 0;
- nSize = 0;
- ssl_mutex_on(s);
- if ((dbm = ssl_dbm_open(mc->szSessionCacheDataFile,
- O_RDONLY, SSL_DBM_FILE_MODE)) == NULL) {
- ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO,
- "Cannot open SSLSessionCache DBM file `%s' for status retrival",
- mc->szSessionCacheDataFile);
- ssl_mutex_off(s);
- return;
- }
- dbmkey = ssl_dbm_firstkey(dbm);
- for ( ; dbmkey.dptr != NULL; dbmkey = ssl_dbm_nextkey(dbm)) {
- dbmval = ssl_dbm_fetch(dbm, dbmkey);
- if (dbmval.dptr == NULL)
- continue;
- nElem += 1;
- nSize += dbmval.dsize;
- }
- ssl_dbm_close(dbm);
- ssl_mutex_off(s);
- if (nSize > 0 && nElem > 0)
- nAverage = nSize / nElem;
- else
- nAverage = 0;
- func(ap_psprintf(p, "cache type: <b>DBM</b>, maximum size: <b>unlimited</b><br>"), arg);
- func(ap_psprintf(p, "current sessions: <b>%d</b>, current size: <b>%d</b> bytes<br>", nElem, nSize), arg);
- func(ap_psprintf(p, "average session size: <b>%d</b> bytes<br>", nAverage), arg);
- return;
-}
-
diff --git a/modules/ssl/ssl_scache_shmcb.c b/modules/ssl/ssl_scache_shmcb.c
deleted file mode 100644
index e588f0a5d1..0000000000
--- a/modules/ssl/ssl_scache_shmcb.c
+++ /dev/null
@@ -1,1343 +0,0 @@
-/* _ _
-** _ __ ___ ___ __| | ___ ___| | mod_ssl
-** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
-** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
-** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
-** |_____|
-** ssl_scache_shmcb.c
-** Session Cache via Shared Memory (Cyclic Buffer Variant)
-*/
-
-/* ====================================================================
- * Copyright (c) 2000-2001 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * 4. The names "mod_ssl" must not be used to endorse or promote
- * products derived from this software without prior written
- * permission. For written permission, please contact
- * rse@engelschall.com.
- *
- * 5. Products derived from this software may not be called "mod_ssl"
- * nor may "mod_ssl" appear in their names without prior
- * written permission of Ralf S. Engelschall.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
-
-#include "mod_ssl.h"
-
-/*
- * This shared memory based SSL session cache implementation was
- * originally written by Geoff Thorpe <geoff@eu.c2.net> for C2Net Europe
- * and as a contribution to Ralf Engelschall's mod_ssl project.
- */
-
-/*
- * The shared-memory segment header can be cast to and from the
- * SHMCBHeader type, all other structures need to be initialised by
- * utility functions.
- *
- * The "header" looks like this;
- *
- * data applying to the overall structure:
- * - division_offset (unsigned int):
- * how far into the shared memory segment the first division is.
- * - division_size (unsigned int):
- * how many bytes each division occupies.
- * (NB: This includes the queue and the cache)
- * - division_mask (unsigned char):
- * the "mask" in the next line. Add one to this,
- * and that's the number of divisions.
- *
- * data applying to within each division:
- * - queue_size (unsigned int):
- * how big each "queue" is. NB: The queue is the first block in each
- * division and is followed immediately by the cache itself so so
- * there's no cache_offset value.
- *
- * data applying to within each queue:
- * - index_num (unsigned char):
- * how many indexes in each cache's queue
- * - index_offset (unsigned char):
- * how far into the queue the first index is.
- * - index_size:
- * how big each index is.
- *
- * data applying to within each cache:
- * - cache_data_offset (unsigned int):
- * how far into the cache the session-data array is stored.
- * - cache_data_size (unsigned int):
- * how big each cache's data block is.
- *
- * statistics data (this will eventually be per-division but right now
- * there's only one mutex):
- * - stores (unsigned long):
- * how many stores have been performed in the cache.
- * - expiries (unsigned long):
- * how many session have been expired from the cache.
- * - scrolled (unsigned long):
- * how many sessions have been scrolled out of full cache during a
- * "store" operation. This is different to the "removes" stats as
- * they are requested by mod_ssl/Apache, these are done because of
- * cache logistics. (NB: Also, this value should be deducible from
- * the others if my code has no bugs, but I count it anyway - plus
- * it helps debugging :-).
- * - retrieves_hit (unsigned long):
- * how many session-retrieves have succeeded.
- * - retrieves_miss (unsigned long):
- * how many session-retrieves have failed.
- * - removes_hit (unsigned long):
- * - removes_miss (unsigned long):
- *
- * Following immediately after the header is an array of "divisions".
- * Each division is simply a "queue" immediately followed by its
- * corresponding "cache". Each division handles some pre-defined band
- * of sessions by using the "division_mask" in the header. Eg. if
- * division_mask=0x1f then there are 32 divisions, the first of which
- * will store sessions whose least-significant 5 bits are 0, the second
- * stores session whose LS 5 bits equal 1, etc. A queue is an indexing
- * structure referring to its corresponding cache.
- *
- * A "queue" looks like this;
- *
- * - first_pos (unsigned int):
- * the location within the array of indexes where the virtual
- * "left-hand-edge" of the cyclic buffer is.
- * - pos_count (unsigned int):
- * the number of indexes occupied from first_pos onwards.
- *
- * ...followed by an array of indexes, each of which can be
- * memcpy'd to and from an SHMCBIndex, and look like this;
- *
- * - expires (time_t):
- * the time() value at which this session expires.
- * - offset (unsigned int):
- * the offset within the cache data block where the corresponding
- * session is stored.
- * - s_id2 (unsigned char):
- * the second byte of the session_id, stored as an optimisation to
- * reduce the number of d2i_SSL_SESSION calls that are made when doing
- * a lookup.
- * - removed (unsigned char):
- * a byte used to indicate whether a session has been "passively"
- * removed. Ie. it is still in the cache but is to be disregarded by
- * any "retrieve" operation.
- *
- * A "cache" looks like this;
- *
- * - first_pos (unsigned int):
- * the location within the data block where the virtual
- * "left-hand-edge" of the cyclic buffer is.
- * - pos_count (unsigned int):
- * the number of bytes used in the data block from first_pos onwards.
- *
- * ...followed by the data block in which actual DER-encoded SSL
- * sessions are stored.
- */
-
-/*
- * Header - can be memcpy'd to and from the front of the shared
- * memory segment. NB: The first copy (commented out) has the
- * elements in a meaningful order, but due to data-alignment
- * braindeadness, the second (uncommented) copy has the types grouped
- * so as to decrease "struct-bloat". sigh.
- */
-typedef struct {
-#if 0
- unsigned char division_mask;
- unsigned int division_offset;
- unsigned int division_size;
- unsigned int queue_size;
- unsigned char index_num;
- unsigned char index_offset;
- unsigned char index_size;
- unsigned int cache_data_offset;
- unsigned int cache_data_size;
- unsigned long num_stores;
- unsigned long num_expiries;
- unsigned long num_scrolled;
- unsigned long num_retrieves_hit;
- unsigned long num_retrieves_miss;
- unsigned long num_removes_hit;
- unsigned long num_removes_miss;
-#else
- unsigned long num_stores;
- unsigned long num_expiries;
- unsigned long num_scrolled;
- unsigned long num_retrieves_hit;
- unsigned long num_retrieves_miss;
- unsigned long num_removes_hit;
- unsigned long num_removes_miss;
- unsigned int division_offset;
- unsigned int division_size;
- unsigned int queue_size;
- unsigned int cache_data_offset;
- unsigned int cache_data_size;
- unsigned char division_mask;
- unsigned char index_num;
- unsigned char index_offset;
- unsigned char index_size;
-#endif
-} SHMCBHeader;
-
-/*
- * Index - can be memcpy'd to and from an index inside each
- * queue's index array.
- */
-typedef struct {
- time_t expires;
- unsigned int offset;
- unsigned char s_id2;
- unsigned char removed;
-} SHMCBIndex;
-
-/*
- * Queue - must be populated by a call to shmcb_get_division
- * and the structure's pointers are used for updating (ie.
- * the structure doesn't need any "set" to update values).
- */
-typedef struct {
- SHMCBHeader *header;
- unsigned int *first_pos;
- unsigned int *pos_count;
- SHMCBIndex *indexes;
-} SHMCBQueue;
-
-/*
- * Cache - same comment as for Queue. 'Queue's are in a 1-1
- * correspondance with 'Cache's and are usually carried round
- * in a pair, they are only seperated for clarity.
- */
-typedef struct {
- SHMCBHeader *header;
- unsigned int *first_pos;
- unsigned int *pos_count;
- unsigned char *data;
-} SHMCBCache;
-
-/*
- * Forward function prototypes.
- */
-
-/* Functions for working around data-alignment-picky systems (sparcs,
- Irix, etc). These use "memcpy" as a way of foxing these systems into
- treating the composite types as byte-arrays rather than higher-level
- primitives that it prefers to have 4-(or 8-)byte aligned. I don't
- envisage this being a performance issue as a couple of 2 or 4 byte
- memcpys can hardly make a dent on the massive memmove operations this
- cache technique avoids, nor the overheads of ASN en/decoding. */
-static unsigned int shmcb_get_safe_uint(unsigned int *);
-static void shmcb_set_safe_uint(unsigned int *, unsigned int);
-#if 0 /* Unused so far */
-static unsigned long shmcb_get_safe_ulong(unsigned long *);
-static void shmcb_set_safe_ulong(unsigned long *, unsigned long);
-#endif
-static time_t shmcb_get_safe_time(time_t *);
-static void shmcb_set_safe_time(time_t *, time_t);
-
-/* Underlying functions for session-caching */
-static BOOL shmcb_init_memory(server_rec *, void *, unsigned int);
-static BOOL shmcb_store_session(server_rec *, void *, UCHAR *, int, SSL_SESSION *, time_t);
-static SSL_SESSION *shmcb_retrieve_session(server_rec *, void *, UCHAR *, int);
-static BOOL shmcb_remove_session(server_rec *, void *, UCHAR *, int);
-
-/* Utility functions for manipulating the structures */
-static void shmcb_get_header(void *, SHMCBHeader **);
-static BOOL shmcb_get_division(SHMCBHeader *, SHMCBQueue *, SHMCBCache *, unsigned int);
-static SHMCBIndex *shmcb_get_index(const SHMCBQueue *, unsigned int);
-static unsigned int shmcb_expire_division(server_rec *, SHMCBQueue *, SHMCBCache *);
-static BOOL shmcb_insert_encoded_session(server_rec *, SHMCBQueue *, SHMCBCache *, unsigned char *, unsigned int, unsigned char *, time_t);
-static SSL_SESSION *shmcb_lookup_session_id(server_rec *, SHMCBQueue *, SHMCBCache *, UCHAR *, int);
-static BOOL shmcb_remove_session_id(server_rec *, SHMCBQueue *, SHMCBCache *, UCHAR *, int);
-
-/*
- * Data-alignment functions (a.k.a. avoidance tactics)
- *
- * NB: On HPUX (and possibly others) there is a *very* mischievous little
- * "optimisation" in the compilers where it will convert the following;
- * memcpy(dest_ptr, &source, sizeof(unsigned int));
- * (where dest_ptr is of type (unsigned int *) and source is (unsigned int))
- * into;
- * *dest_ptr = source; (or *dest_ptr = *(&source), not sure).
- * Either way, it completely destroys the whole point of these _safe_
- * functions, because the assignment operation will fall victim to the
- * architecture's byte-alignment dictations, whereas the memcpy (as a
- * byte-by-byte copy) should not. sigh. So, if you're wondering about the
- * apparently unnecessary conversions to (unsigned char *) in these
- * functions, you now have an explanation. Don't just revert them back and
- * say "ooh look, it still works" - if you try it on HPUX (well, 32-bit
- * HPUX 11.00 at least) you may find it fails with a SIGBUS. :-(
- */
-
-static unsigned int shmcb_get_safe_uint(unsigned int *ptr)
-{
- unsigned char *from;
- unsigned int ret;
-
- from = (unsigned char *)ptr;
- memcpy(&ret, from, sizeof(unsigned int));
- return ret;
-}
-
-static void shmcb_set_safe_uint(unsigned int *ptr, unsigned int val)
-{
- unsigned char *to, *from;
-
- to = (unsigned char *)ptr;
- from = (unsigned char *)(&val);
- memcpy(to, from, sizeof(unsigned int));
-}
-
-#if 0 /* Unused so far */
-static unsigned long shmcb_get_safe_ulong(unsigned long *ptr)
-{
- unsigned char *from;
- unsigned long ret;
-
- from = (unsigned char *)ptr;
- memcpy(&ret, from, sizeof(unsigned long));
- return ret;
-}
-
-static void shmcb_set_safe_ulong(unsigned long *ptr, unsigned long val)
-{
- unsigned char *to, *from;
-
- to = (unsigned char *)ptr;
- from = (unsigned char *)(&val);
- memcpy(to, from, sizeof(unsigned long));
-}
-#endif
-
-static time_t shmcb_get_safe_time(time_t * ptr)
-{
- unsigned char *from;
- time_t ret;
-
- from = (unsigned char *)ptr;
- memcpy(&ret, from, sizeof(time_t));
- return ret;
-}
-
-static void shmcb_set_safe_time(time_t * ptr, time_t val)
-{
- unsigned char *to, *from;
-
- to = (unsigned char *)ptr;
- from = (unsigned char *)(&val);
- memcpy(to, from, sizeof(time_t));
-}
-
-/*
-**
-** High-Level "handlers" as per ssl_scache.c
-**
-*/
-
-static void *shmcb_malloc(size_t size)
-{
- SSLModConfigRec *mc = myModConfig();
- return ap_mm_malloc(mc->pSessionCacheDataMM, size);
-}
-
-void ssl_scache_shmcb_init(server_rec *s, pool *p)
-{
- SSLModConfigRec *mc = myModConfig();
- AP_MM *mm;
- void *shm_segment = NULL;
- int avail, avail_orig;
-
- /*
- * Create shared memory segment
- */
- if (mc->szSessionCacheDataFile == NULL) {
- ssl_log(s, SSL_LOG_ERROR, "SSLSessionCache required");
- ssl_die();
- }
- if ((mm = ap_mm_create(mc->nSessionCacheDataSize,
- mc->szSessionCacheDataFile)) == NULL) {
- ssl_log(s, SSL_LOG_ERROR,
- "Cannot allocate shared memory: %s", ap_mm_error());
- ssl_die();
- }
- mc->pSessionCacheDataMM = mm;
-
- /*
- * Make sure the child processes have access to the underlying files
- */
- ap_mm_permission(mm, SSL_MM_FILE_MODE, ap_user_id, -1);
-
- /*
- * Create cache inside the shared memory segment
- */
- avail = avail_orig = ap_mm_available(mm);
- ssl_log(s, SSL_LOG_TRACE, "Shared-memory segment has %u available",
- avail);
-
- /*
- * For some reason to do with MM's internal management, I can't
- * allocate the full amount. Implement a reasonable form of trial
- * and error and output trace information.
- */
- while ((shm_segment == NULL) && ((avail_orig - avail) * 100 < avail_orig)) {
- shm_segment = shmcb_malloc(avail);
- if (shm_segment == NULL) {
- ssl_log(s, SSL_LOG_TRACE,
- "shmcb_malloc attempt for %u bytes failed", avail);
- avail -= 2;
- }
- }
- if (shm_segment == NULL) {
- ssl_log(s, SSL_LOG_ERROR,
- "Cannot allocate memory for the 'shmcb' session cache\n");
- ssl_die();
- }
- ssl_log(s, SSL_LOG_TRACE, "shmcb_init allocated %u bytes of shared "
- "memory", avail);
- if (!shmcb_init_memory(s, shm_segment, avail)) {
- ssl_log(s, SSL_LOG_ERROR,
- "Failure initialising 'shmcb' shared memory");
- ssl_die();
- }
- ssl_log(s, SSL_LOG_INFO, "Shared memory session cache initialised");
-
- /*
- * Success ... we hack the memory block into place by cheating for
- * now and stealing a member variable the original shared memory
- * cache was using. :-)
- */
- mc->tSessionCacheDataTable = (table_t *) shm_segment;
- return;
-}
-
-void ssl_scache_shmcb_kill(server_rec *s)
-{
- SSLModConfigRec *mc = myModConfig();
-
- if (mc->pSessionCacheDataMM != NULL) {
- ap_mm_destroy(mc->pSessionCacheDataMM);
- mc->pSessionCacheDataMM = NULL;
- }
- return;
-}
-
-BOOL ssl_scache_shmcb_store(server_rec *s, UCHAR * id, int idlen,
- time_t timeout, SSL_SESSION * pSession)
-{
- SSLModConfigRec *mc = myModConfig();
- void *shm_segment;
- BOOL to_return = FALSE;
-
- /* We've kludged our pointer into the other cache's member variable. */
- shm_segment = (void *) mc->tSessionCacheDataTable;
- ssl_mutex_on(s);
- if (!shmcb_store_session(s, shm_segment, id, idlen, pSession, timeout))
- /* in this cache engine, "stores" should never fail. */
- ssl_log(s, SSL_LOG_ERROR, "'shmcb' code was unable to store a "
- "session in the cache.");
- else {
- ssl_log(s, SSL_LOG_TRACE, "shmcb_store successful");
- to_return = TRUE;
- }
- ssl_mutex_off(s);
- return to_return;
-}
-
-SSL_SESSION *ssl_scache_shmcb_retrieve(server_rec *s, UCHAR * id, int idlen)
-{
- SSLModConfigRec *mc = myModConfig();
- void *shm_segment;
- SSL_SESSION *pSession;
-
- /* We've kludged our pointer into the other cache's member variable. */
- shm_segment = (void *) mc->tSessionCacheDataTable;
- ssl_mutex_on(s);
- pSession = shmcb_retrieve_session(s, shm_segment, id, idlen);
- ssl_mutex_off(s);
- if (pSession)
- ssl_log(s, SSL_LOG_TRACE, "shmcb_retrieve had a hit");
- else {
- ssl_log(s, SSL_LOG_TRACE, "shmcb_retrieve had a miss");
- ssl_log(s, SSL_LOG_INFO, "Client requested a 'session-resume' but "
- "we have no such session.");
- }
- return pSession;
-}
-
-void ssl_scache_shmcb_remove(server_rec *s, UCHAR * id, int idlen)
-{
- SSLModConfigRec *mc = myModConfig();
- void *shm_segment;
-
- /* We've kludged our pointer into the other cache's member variable. */
- shm_segment = (void *) mc->tSessionCacheDataTable;
- shmcb_remove_session(s, shm_segment, id, idlen);
-}
-
-void ssl_scache_shmcb_expire(server_rec *s)
-{
- /* NOP */
- return;
-}
-
-void ssl_scache_shmcb_status(server_rec *s, pool *p,
- void (*func) (char *, void *), void *arg)
-{
- SSLModConfigRec *mc = myModConfig();
- SHMCBHeader *header;
- SHMCBQueue queue;
- SHMCBCache cache;
- SHMCBIndex *idx;
- void *shm_segment;
- unsigned int loop, total, cache_total, non_empty_divisions;
- int index_pct, cache_pct;
- double expiry_total;
- time_t average_expiry, now, max_expiry, min_expiry, idxexpiry;
-
- ssl_log(s, SSL_LOG_TRACE, "inside ssl_scache_shmcb_status");
-
- /* We've kludged our pointer into the other cache's member variable. */
- shm_segment = (void *) mc->tSessionCacheDataTable;
-
- /* Get the header structure. */
- shmcb_get_header(shm_segment, &header);
- total = cache_total = non_empty_divisions = 0;
- average_expiry = max_expiry = min_expiry = 0;
- expiry_total = 0;
-
- /* It may seem strange to grab "now" at this point, but in theory
- * we should never have a negative threshold but grabbing "now" after
- * the loop (which performs expiries) could allow that chance. */
- now = time(NULL);
- for (loop = 0; loop <= header->division_mask; loop++) {
- if (shmcb_get_division(header, &queue, &cache, loop)) {
- shmcb_expire_division(s, &queue, &cache);
- total += shmcb_get_safe_uint(queue.pos_count);
- cache_total += shmcb_get_safe_uint(cache.pos_count);
- if (shmcb_get_safe_uint(queue.pos_count) > 0) {
- idx = shmcb_get_index(&queue,
- shmcb_get_safe_uint(queue.first_pos));
- non_empty_divisions++;
- idxexpiry = shmcb_get_safe_time(&(idx->expires));
- expiry_total += (double) idxexpiry;
- max_expiry = (idxexpiry > max_expiry ? idxexpiry :
- max_expiry);
- if (min_expiry == 0)
- min_expiry = idxexpiry;
- else
- min_expiry = (idxexpiry < min_expiry ? idxexpiry :
- min_expiry);
- }
- }
- }
- index_pct = (100 * total) / (header->index_num * (header->division_mask + 1));
- cache_pct = (100 * cache_total) / (header->cache_data_size * (header->division_mask + 1));
- func(ap_psprintf(p, "cache type: <b>SHMCB</b>, shared memory: <b>%d</b> "
- "bytes, current sessions: <b>%d</b><br>",
- mc->nSessionCacheDataSize, total), arg);
- func(ap_psprintf(p, "sub-caches: <b>%d</b>, indexes per sub-cache: "
- "<b>%d</b><br>", (int) header->division_mask + 1,
- (int) header->index_num), arg);
- if (non_empty_divisions != 0) {
- average_expiry = (time_t)(expiry_total / (double)non_empty_divisions);
- func(ap_psprintf(p, "time left on oldest entries' SSL sessions: "), arg);
- if (now < average_expiry)
- func(ap_psprintf(p, "avg: <b>%d</b> seconds, (range: %d...%d)<br>",
- (int)(average_expiry - now), (int) (min_expiry - now),
- (int)(max_expiry - now)), arg);
- else
- func(ap_psprintf(p, "expiry threshold: <b>Calculation Error!</b>"
- "<br>"), arg);
-
- }
- func(ap_psprintf(p, "index usage: <b>%d%%</b>, cache usage: <b>%d%%</b>"
- "<br>", index_pct, cache_pct), arg);
- func(ap_psprintf(p, "total sessions stored since starting: <b>%lu</b><br>",
- header->num_stores), arg);
- func(ap_psprintf(p, "total sessions expired since starting: <b>%lu</b><br>",
- header->num_expiries), arg);
- func(ap_psprintf(p, "total (pre-expiry) sessions scrolled out of the "
- "cache: <b>%lu</b><br>", header->num_scrolled), arg);
- func(ap_psprintf(p, "total retrieves since starting: <b>%lu</b> hit, "
- "<b>%lu</b> miss<br>", header->num_retrieves_hit,
- header->num_retrieves_miss), arg);
- func(ap_psprintf(p, "total removes since starting: <b>%lu</b> hit, "
- "<b>%lu</b> miss<br>", header->num_removes_hit,
- header->num_removes_miss), arg);
- ssl_log(s, SSL_LOG_TRACE, "leaving shmcb_status");
- return;
-}
-
-/*
-**
-** Memory manipulation and low-level cache operations
-**
-*/
-
-static BOOL shmcb_init_memory(
- server_rec *s, void *shm_mem,
- unsigned int shm_mem_size)
-{
- SHMCBHeader *header;
- SHMCBQueue queue;
- SHMCBCache cache;
- unsigned int temp, loop, granularity;
-
- ssl_log(s, SSL_LOG_TRACE, "entered shmcb_init_memory()");
-
- /* Calculate some sizes... */
- temp = sizeof(SHMCBHeader);
-
- /* If the segment is ridiculously too small, bail out */
- if (shm_mem_size < (2*temp)) {
- ssl_log(s, SSL_LOG_ERROR, "shared memory segment too small");
- return FALSE;
- }
-
- /* Make temp the amount of memory without the header */
- temp = shm_mem_size - temp;
-
- /* Work on the basis that you need 10 bytes index for each session
- * (approx 150 bytes), which is to divide temp by 160 - and then
- * make sure we err on having too index space to burn even when
- * the cache is full, which is a lot less stupid than having
- * having not enough index space to utilise the whole cache!. */
- temp /= 120;
- ssl_log(s, SSL_LOG_TRACE, "for %u bytes, recommending %u indexes",
- shm_mem_size, temp);
-
- /* We should divide these indexes evenly amongst the queues. Try
- * to get it so that there are roughly half the number of divisions
- * as there are indexes in each division. */
- granularity = 256;
- while ((temp / granularity) < (2 * granularity))
- granularity /= 2;
-
- /* So we have 'granularity' divisions, set 'temp' equal to the
- * number of indexes in each division. */
- temp /= granularity;
-
- /* Too small? Bail ... */
- if (temp < 5) {
- ssl_log(s, SSL_LOG_ERROR, "shared memory segment too small");
- return FALSE;
- }
-
- /* OK, we're sorted - from here on in, the return should be TRUE */
- header = (SHMCBHeader *)shm_mem;
- header->division_mask = (unsigned char)(granularity - 1);
- header->division_offset = sizeof(SHMCBHeader);
- header->index_num = temp;
- header->index_offset = (2 * sizeof(unsigned int));
- header->index_size = sizeof(SHMCBIndex);
- header->queue_size = header->index_offset +
- (header->index_num * header->index_size);
-
- /* Now calculate the space for each division */
- temp = shm_mem_size - header->division_offset;
- header->division_size = temp / granularity;
-
- /* Calculate the space left in each division for the cache */
- temp -= header->queue_size;
- header->cache_data_offset = (2 * sizeof(unsigned int));
- header->cache_data_size = header->division_size -
- header->queue_size - header->cache_data_offset;
-
- /* Output trace info */
- ssl_log(s, SSL_LOG_TRACE, "shmcb_init_memory choices follow");
- ssl_log(s, SSL_LOG_TRACE, "division_mask = 0x%02X", header->division_mask);
- ssl_log(s, SSL_LOG_TRACE, "division_offset = %u", header->division_offset);
- ssl_log(s, SSL_LOG_TRACE, "division_size = %u", header->division_size);
- ssl_log(s, SSL_LOG_TRACE, "queue_size = %u", header->queue_size);
- ssl_log(s, SSL_LOG_TRACE, "index_num = %u", header->index_num);
- ssl_log(s, SSL_LOG_TRACE, "index_offset = %u", header->index_offset);
- ssl_log(s, SSL_LOG_TRACE, "index_size = %u", header->index_size);
- ssl_log(s, SSL_LOG_TRACE, "cache_data_offset = %u", header->cache_data_offset);
- ssl_log(s, SSL_LOG_TRACE, "cache_data_size = %u", header->cache_data_size);
-
- /* The header is done, make the caches empty */
- for (loop = 0; loop < granularity; loop++) {
- if (!shmcb_get_division(header, &queue, &cache, loop))
- ssl_log(s, SSL_LOG_ERROR, "shmcb_init_memory, " "internal error");
- shmcb_set_safe_uint(cache.first_pos, 0);
- shmcb_set_safe_uint(cache.pos_count, 0);
- shmcb_set_safe_uint(queue.first_pos, 0);
- shmcb_set_safe_uint(queue.pos_count, 0);
- }
-
- ssl_log(s, SSL_LOG_TRACE, "leaving shmcb_init_memory()");
- return TRUE;
-}
-
-static BOOL shmcb_store_session(
- server_rec *s, void *shm_segment, UCHAR * id,
- int idlen, SSL_SESSION * pSession,
- time_t timeout)
-{
- SHMCBHeader *header;
- SHMCBQueue queue;
- SHMCBCache cache;
- unsigned char masked_index;
- unsigned char encoded[SSL_SESSION_MAX_DER];
- unsigned char *ptr_encoded;
- unsigned int len_encoded;
- time_t expiry_time;
-
- ssl_log(s, SSL_LOG_TRACE, "inside shmcb_store_session");
-
- /* Get the header structure, which division this session will fall into etc. */
- shmcb_get_header(shm_segment, &header);
- masked_index = pSession->session_id[0] & header->division_mask;
- ssl_log(s, SSL_LOG_TRACE, "session_id[0]=%u, masked index=%u",
- pSession->session_id[0], masked_index);
- if (!shmcb_get_division(header, &queue, &cache, (unsigned int)masked_index)) {
- ssl_log(s, SSL_LOG_ERROR, "shmcb_store_session, " "internal error");
- return FALSE;
- }
-
- /* Serialise the session, work out how much we're dealing
- * with. NB: This check could be removed if we're not paranoid
- * or we find some assurance that it will never be necessary. */
- len_encoded = i2d_SSL_SESSION(pSession, NULL);
- if (len_encoded > SSL_SESSION_MAX_DER) {
- ssl_log(s, SSL_LOG_ERROR, "session is too big (%u bytes)",
- len_encoded);
- return FALSE;
- }
- ptr_encoded = encoded;
- len_encoded = i2d_SSL_SESSION(pSession, &ptr_encoded);
- expiry_time = timeout;
- if (!shmcb_insert_encoded_session(s, &queue, &cache, encoded,
- len_encoded, pSession->session_id,
- expiry_time)) {
- ssl_log(s, SSL_LOG_ERROR, "can't store a session!");
- return FALSE;
- }
- ssl_log(s, SSL_LOG_TRACE, "leaving shmcb_store successfully");
- header->num_stores++;
- return TRUE;
-}
-
-static SSL_SESSION *shmcb_retrieve_session(
- server_rec *s, void *shm_segment,
- UCHAR * id, int idlen)
-{
- SHMCBHeader *header;
- SHMCBQueue queue;
- SHMCBCache cache;
- unsigned char masked_index;
- SSL_SESSION *pSession;
-
- ssl_log(s, SSL_LOG_TRACE, "inside shmcb_retrieve_session");
- if (idlen < 2) {
- ssl_log(s, SSL_LOG_ERROR, "unusably short session_id provided "
- "(%u bytes)", idlen);
- return FALSE;
- }
-
- /* Get the header structure, which division this session lookup
- * will come from etc. */
- shmcb_get_header(shm_segment, &header);
- masked_index = id[0] & header->division_mask;
- ssl_log(s, SSL_LOG_TRACE, "id[0]=%u, masked index=%u", id[0],
- masked_index);
- if (!shmcb_get_division(header, &queue, &cache, (unsigned int) masked_index)) {
- ssl_log(s, SSL_LOG_ERROR, "shmcb_retrieve_session, " "internal error");
- header->num_retrieves_miss++;
- return FALSE;
- }
-
- /* Get the session corresponding to the session_id or NULL if it
- * doesn't exist (or is flagged as "removed"). */
- pSession = shmcb_lookup_session_id(s, &queue, &cache, id, idlen);
- if (pSession)
- header->num_retrieves_hit++;
- else
- header->num_retrieves_miss++;
- ssl_log(s, SSL_LOG_TRACE, "leaving shmcb_retrieve_session");
- return pSession;
-}
-
-static BOOL shmcb_remove_session(
- server_rec *s, void *shm_segment,
- UCHAR * id, int idlen)
-{
- SHMCBHeader *header;
- SHMCBQueue queue;
- SHMCBCache cache;
- unsigned char masked_index;
- BOOL res;
-
- ssl_log(s, SSL_LOG_TRACE, "inside shmcb_remove_session");
- if (id == NULL) {
- ssl_log(s, SSL_LOG_ERROR, "remove called with NULL session_id!");
- return FALSE;
- }
-
- /* Get the header structure, which division this session remove
- * will happen in etc. */
- shmcb_get_header(shm_segment, &header);
- masked_index = id[0] & header->division_mask;
- ssl_log(s, SSL_LOG_TRACE, "id[0]=%u, masked index=%u",
- id[0], masked_index);
- if (!shmcb_get_division(header, &queue, &cache, (unsigned int)masked_index)) {
- ssl_log(s, SSL_LOG_ERROR, "shmcb_remove_session, internal error");
- header->num_removes_miss++;
- return FALSE;
- }
- res = shmcb_remove_session_id(s, &queue, &cache, id, idlen);
- if (res)
- header->num_removes_hit++;
- else
- header->num_removes_miss++;
- ssl_log(s, SSL_LOG_TRACE, "leaving shmcb_remove_session");
- return res;
-}
-
-
-/*
-**
-** Weirdo cyclic buffer functions
-**
-*/
-
-/* This gets used in the cyclic "index array" (in the 'Queue's) and
- * in the cyclic 'Cache's too ... you provide the "width" of the
- * cyclic store, the starting position and how far to move (with
- * wrapping if necessary). Basically it's addition modulo buf_size. */
-static unsigned int shmcb_cyclic_increment(
- unsigned int buf_size,
- unsigned int start_pos,
- unsigned int to_add)
-{
- start_pos += to_add;
- while (start_pos >= buf_size)
- start_pos -= buf_size;
- return start_pos;
-}
-
-/* Given two positions in a cyclic buffer, calculate the "distance".
- * This is to cover the case ("non-trivial") where the 'next' offset
- * is to the left of the 'start' offset. NB: This calculates the
- * space inclusive of one end-point but not the other. There is an
- * ambiguous case (which is why we use the <start_pos,offset>
- * coordinate system rather than <start_pos,end_pos> one) when 'start'
- * is the same as 'next'. It could indicate the buffer is full or it
- * can indicate the buffer is empty ... I choose the latter as it's
- * easier and usually necessary to check if the buffer is full anyway
- * before doing incremental logic (which is this useful for), but we
- * definitely need the empty case handled - in fact it's our starting
- * state!! */
-static unsigned int shmcb_cyclic_space(
- unsigned int buf_size,
- unsigned int start_offset,
- unsigned int next_offset)
-{
- /* Is it the trivial case? */
- if (start_offset <= next_offset)
- return (next_offset - start_offset); /* yes */
- else
- return ((buf_size - start_offset) + next_offset); /* no */
-}
-
-/* A "normal-to-cyclic" memcpy ... this takes a linear block of
- * memory and copies it onto a cyclic buffer. The purpose and
- * function of this is pretty obvious, you need to cover the case
- * that the destination (cyclic) buffer has to wrap round. */
-static void shmcb_cyclic_ntoc_memcpy(
- unsigned int buf_size,
- unsigned char *data,
- unsigned int dest_offset,
- unsigned char *src, unsigned int src_len)
-{
- /* Can it be copied all in one go? */
- if (dest_offset + src_len < buf_size)
- /* yes */
- memcpy(data + dest_offset, src, src_len);
- else {
- /* no */
- memcpy(data + dest_offset, src, buf_size - dest_offset);
- memcpy(data, src + buf_size - dest_offset,
- src_len + dest_offset - buf_size);
- }
- return;
-}
-
-/* A "cyclic-to-normal" memcpy ... given the last function, this
- * one's purpose is clear, it copies out of a cyclic buffer handling
- * wrapping. */
-static void shmcb_cyclic_cton_memcpy(
- unsigned int buf_size,
- unsigned char *dest,
- unsigned char *data,
- unsigned int src_offset,
- unsigned int src_len)
-{
- /* Can it be copied all in one go? */
- if (src_offset + src_len < buf_size)
- /* yes */
- memcpy(dest, data + src_offset, src_len);
- else {
- /* no */
- memcpy(dest, data + src_offset, buf_size - src_offset);
- memcpy(dest + buf_size - src_offset, data,
- src_len + src_offset - buf_size);
- }
- return;
-}
-
-/* Here's the cool hack that makes it all work ... by simply
- * making the first collection of bytes *be* our header structure
- * (casting it into the C structure), we have the perfect way to
- * maintain state in a shared-memory session cache from one call
- * (and process) to the next, use the shared memory itself! The
- * original mod_ssl shared-memory session cache uses variables
- * inside the context, but we simply use that for storing the
- * pointer to the shared memory itself. And don't forget, after
- * Apache's initialisation, this "header" is constant/read-only
- * so we can read it outside any locking.
- * <grin> - sometimes I just *love* coding y'know?! */
-static void shmcb_get_header(void *shm_mem, SHMCBHeader **header)
-{
- *header = (SHMCBHeader *)shm_mem;
- return;
-}
-
-/* This is what populates our "interesting" structures. Given a
- * pointer to the header, and an index into the appropriate
- * division (this must have already been masked using the
- * division_mask by the caller!), we can populate the provided
- * SHMCBQueue and SHMCBCache structures with values and
- * pointers to the underlying shared memory. Upon returning
- * (if not FALSE), the caller can meddle with the pointer
- * values and they will map into the shared-memory directly,
- * as such there's no need to "free" or "set" the Queue or
- * Cache values, they were themselves references to the *real*
- * data. */
-static BOOL shmcb_get_division(
- SHMCBHeader *header, SHMCBQueue *queue,
- SHMCBCache *cache, unsigned int idx)
-{
- unsigned char *pQueue;
- unsigned char *pCache;
-
- /* bounds check */
- if (idx > (unsigned int) header->division_mask)
- return FALSE;
-
- /* Locate the blocks of memory storing the corresponding data */
- pQueue = ((unsigned char *) header) + header->division_offset +
- (idx * header->division_size);
- pCache = pQueue + header->queue_size;
-
- /* Populate the structures with appropriate pointers */
- queue->first_pos = (unsigned int *) pQueue;
-
- /* Our structures stay packed, no matter what the system's
- * data-alignment regime is. */
- queue->pos_count = (unsigned int *) (pQueue + sizeof(unsigned int));
- queue->indexes = (SHMCBIndex *) (pQueue + (2 * sizeof(unsigned int)));
- cache->first_pos = (unsigned int *) pCache;
- cache->pos_count = (unsigned int *) (pCache + sizeof(unsigned int));
- cache->data = (unsigned char *) (pCache + (2 * sizeof(unsigned int)));
- queue->header = cache->header = header;
-
- return TRUE;
-}
-
-/* This returns a pointer to the piece of shared memory containing
- * a specified 'Index'. SHMCBIndex, like SHMCBHeader, is a fixed
- * width non-referencing structure of primitive types that can be
- * cast onto the corresponding block of shared memory. Thus, by
- * returning a cast pointer to that section of shared memory, the
- * caller can read and write values to and from the "structure" and
- * they are actually reading and writing the underlying shared
- * memory. */
-static SHMCBIndex *shmcb_get_index(
- const SHMCBQueue *queue, unsigned int idx)
-{
- /* bounds check */
- if (idx > (unsigned int) queue->header->index_num)
- return NULL;
-
- /* Return a pointer to the index. NB: I am being horribly pendantic
- * here so as to avoid any potential data-alignment assumptions being
- * placed on the pointer arithmetic by the compiler (sigh). */
- return (SHMCBIndex *)(((unsigned char *) queue->indexes) +
- (idx * sizeof(SHMCBIndex)));
-}
-
-/* This functions rolls expired cache (and index) entries off the front
- * of the cyclic buffers in a division. The function returns the number
- * of expired sessions. */
-static unsigned int shmcb_expire_division(
- server_rec *s, SHMCBQueue *queue, SHMCBCache *cache)
-{
- SHMCBIndex *idx;
- time_t now;
- unsigned int loop, index_num, pos_count, new_pos;
- SHMCBHeader *header;
-
- ssl_log(s, SSL_LOG_TRACE, "entering shmcb_expire_division");
-
- /* We must calculate num and space ourselves based on expiry times. */
- now = time(NULL);
- loop = 0;
- new_pos = shmcb_get_safe_uint(queue->first_pos);
-
- /* Cache useful values */
- header = queue->header;
- index_num = header->index_num;
- pos_count = shmcb_get_safe_uint(queue->pos_count);
- while (loop < pos_count) {
- idx = shmcb_get_index(queue, new_pos);
- if (shmcb_get_safe_time(&(idx->expires)) > now)
- /* it hasn't expired yet, we're done iterating */
- break;
- /* This one should be expired too. Shift to the next entry. */
- loop++;
- new_pos = shmcb_cyclic_increment(index_num, new_pos, 1);
- }
-
- /* Find the new_offset and make the expiries happen. */
- if (loop > 0) {
- ssl_log(s, SSL_LOG_TRACE, "will be expiring %u sessions", loop);
- /* We calculate the new_offset by "peeking" (or in the
- * case it's the last entry, "sneaking" ;-). */
- if (loop == pos_count) {
- /* We are expiring everything! This is easy to do... */
- shmcb_set_safe_uint(queue->pos_count, 0);
- shmcb_set_safe_uint(cache->pos_count, 0);
- }
- else {
- /* The Queue is easy to adjust */
- shmcb_set_safe_uint(queue->pos_count,
- shmcb_get_safe_uint(queue->pos_count) - loop);
- shmcb_set_safe_uint(queue->first_pos, new_pos);
- /* peek to the start of the next session */
- idx = shmcb_get_index(queue, new_pos);
- /* We can use shmcb_cyclic_space because we've guaranteed
- * we don't fit the ambiguous full/empty case. */
- shmcb_set_safe_uint(cache->pos_count,
- shmcb_get_safe_uint(cache->pos_count) -
- shmcb_cyclic_space(header->cache_data_size,
- shmcb_get_safe_uint(cache->first_pos),
- shmcb_get_safe_uint(&(idx->offset))));
- shmcb_set_safe_uint(cache->first_pos, shmcb_get_safe_uint(&(idx->offset)));
- }
- ssl_log(s, SSL_LOG_TRACE, "we now have %u sessions",
- shmcb_get_safe_uint(queue->pos_count));
- }
- header->num_expiries += loop;
- return loop;
-}
-
-/* Inserts a new encoded session into a queue/cache pair - expiring
- * (early or otherwise) any leading sessions as necessary to ensure
- * there is room. An error return (FALSE) should only happen in the
- * event of surreal values being passed on, or ridiculously small
- * cache sizes. NB: For tracing purposes, this function is also given
- * the server_rec to allow "ssl_log()". */
-static BOOL shmcb_insert_encoded_session(
- server_rec *s, SHMCBQueue * queue,
- SHMCBCache * cache,
- unsigned char *encoded,
- unsigned int encoded_len,
- unsigned char *session_id,
- time_t expiry_time)
-{
- SHMCBHeader *header;
- SHMCBIndex *idx = NULL;
- unsigned int gap, new_pos, loop, new_offset;
- int need;
-
- ssl_log(s, SSL_LOG_TRACE, "entering shmcb_insert_encoded_session, "
- "*queue->pos_count = %u", shmcb_get_safe_uint(queue->pos_count));
-
- /* If there's entries to expire, ditch them first thing. */
- shmcb_expire_division(s, queue, cache);
- header = cache->header;
- gap = header->cache_data_size - shmcb_get_safe_uint(cache->pos_count);
- if (gap < encoded_len) {
- new_pos = shmcb_get_safe_uint(queue->first_pos);
- loop = 0;
- need = (int) encoded_len - (int) gap;
- while ((need > 0) && (loop + 1 < shmcb_get_safe_uint(queue->pos_count))) {
- new_pos = shmcb_cyclic_increment(header->index_num, new_pos, 1);
- loop += 1;
- idx = shmcb_get_index(queue, new_pos);
- need = (int) encoded_len - (int) gap -
- shmcb_cyclic_space(header->cache_data_size,
- shmcb_get_safe_uint(cache->first_pos),
- shmcb_get_safe_uint(&(idx->offset)));
- }
- if (loop > 0) {
- ssl_log(s, SSL_LOG_TRACE, "about to scroll %u sessions from %u",
- loop, shmcb_get_safe_uint(queue->pos_count));
- /* We are removing "loop" items from the cache. */
- shmcb_set_safe_uint(cache->pos_count,
- shmcb_get_safe_uint(cache->pos_count) -
- shmcb_cyclic_space(header->cache_data_size,
- shmcb_get_safe_uint(cache->first_pos),
- shmcb_get_safe_uint(&(idx->offset))));
- shmcb_set_safe_uint(cache->first_pos, shmcb_get_safe_uint(&(idx->offset)));
- shmcb_set_safe_uint(queue->pos_count, shmcb_get_safe_uint(queue->pos_count) - loop);
- shmcb_set_safe_uint(queue->first_pos, new_pos);
- ssl_log(s, SSL_LOG_TRACE, "now only have %u sessions",
- shmcb_get_safe_uint(queue->pos_count));
- /* Update the stats!!! */
- header->num_scrolled += loop;
- }
- }
-
- /* probably unecessary checks, but I'll leave them until this code
- * is verified. */
- if (shmcb_get_safe_uint(cache->pos_count) + encoded_len >
- header->cache_data_size) {
- ssl_log(s, SSL_LOG_ERROR, "shmcb_insert_encoded_session, "
- "internal error");
- return FALSE;
- }
- if (shmcb_get_safe_uint(queue->pos_count) == header->index_num) {
- ssl_log(s, SSL_LOG_ERROR, "shmcb_insert_encoded_session, "
- "internal error");
- return FALSE;
- }
- ssl_log(s, SSL_LOG_TRACE, "we have %u bytes and %u indexes free - "
- "enough", header->cache_data_size -
- shmcb_get_safe_uint(cache->pos_count), header->index_num -
- shmcb_get_safe_uint(queue->pos_count));
-
-
- /* HERE WE ASSUME THAT THE NEW SESSION SHOULD GO ON THE END! I'M NOT
- * CHECKING WHETHER IT SHOULD BE GENUINELY "INSERTED" SOMEWHERE.
- *
- * We either fix that, or find out at a "higher" (read "mod_ssl")
- * level whether it is possible to have distinct session caches for
- * any attempted tomfoolery to do with different session timeouts.
- * Knowing in advance that we can have a cache-wide constant timeout
- * would make this stuff *MUCH* more efficient. Mind you, it's very
- * efficient right now because I'm ignoring this problem!!!
- */
-
- /* Increment to the first unused byte */
- new_offset = shmcb_cyclic_increment(header->cache_data_size,
- shmcb_get_safe_uint(cache->first_pos),
- shmcb_get_safe_uint(cache->pos_count));
- /* Copy the DER-encoded session into place */
- shmcb_cyclic_ntoc_memcpy(header->cache_data_size, cache->data,
- new_offset, encoded, encoded_len);
- /* Get the new index that this session is stored in. */
- new_pos = shmcb_cyclic_increment(header->index_num,
- shmcb_get_safe_uint(queue->first_pos),
- shmcb_get_safe_uint(queue->pos_count));
- ssl_log(s, SSL_LOG_TRACE, "storing in index %u, at offset %u", new_pos,
- new_offset);
- idx = shmcb_get_index(queue, new_pos);
- if (idx == NULL) {
- ssl_log(s, SSL_LOG_ERROR, "shmcb_insert_encoded_session, "
- "internal error");
- return FALSE;
- }
- memset(idx, 0, sizeof(SHMCBIndex));
- shmcb_set_safe_time(&(idx->expires), expiry_time);
- shmcb_set_safe_uint(&(idx->offset), new_offset);
-
- /* idx->removed = (unsigned char)0; */ /* Not needed given the memset above. */
- idx->s_id2 = session_id[1];
- ssl_log(s, SSL_LOG_TRACE, "session_id[0]=%u, idx->s_id2=%u",
- session_id[0], session_id[1]);
-
- /* All that remains is to adjust the cache's and queue's "pos_count"s. */
- shmcb_set_safe_uint(cache->pos_count,
- shmcb_get_safe_uint(cache->pos_count) + encoded_len);
- shmcb_set_safe_uint(queue->pos_count,
- shmcb_get_safe_uint(queue->pos_count) + 1);
-
- /* And just for good debugging measure ... */
- ssl_log(s, SSL_LOG_TRACE, "leaving now with %u bytes in the cache and "
- "%u indexes", shmcb_get_safe_uint(cache->pos_count),
- shmcb_get_safe_uint(queue->pos_count));
- ssl_log(s, SSL_LOG_TRACE, "leaving shmcb_insert_encoded_session");
- return TRUE;
-}
-
-/* Performs a lookup into a queue/cache pair for a
- * session_id. If found, the session is deserialised
- * and returned, otherwise NULL. */
-static SSL_SESSION *shmcb_lookup_session_id(
- server_rec *s, SHMCBQueue *queue,
- SHMCBCache *cache, UCHAR *id,
- int idlen)
-{
- unsigned char tempasn[SSL_SESSION_MAX_DER];
- SHMCBIndex *idx;
- SHMCBHeader *header;
- SSL_SESSION *pSession = NULL;
- unsigned int curr_pos, loop, count;
- unsigned char *ptr;
- time_t now;
-
- ssl_log(s, SSL_LOG_TRACE, "entering shmcb_lookup_session_id");
-
- /* If there are entries to expire, ditch them first thing. */
- shmcb_expire_division(s, queue, cache);
- now = time(NULL);
- curr_pos = shmcb_get_safe_uint(queue->first_pos);
- count = shmcb_get_safe_uint(queue->pos_count);
- header = queue->header;
- for (loop = 0; loop < count; loop++) {
- ssl_log(s, SSL_LOG_TRACE, "loop=%u, count=%u, curr_pos=%u",
- loop, count, curr_pos);
- idx = shmcb_get_index(queue, curr_pos);
- ssl_log(s, SSL_LOG_TRACE, "idx->s_id2=%u, id[1]=%u, offset=%u",
- idx->s_id2, id[1], shmcb_get_safe_uint(&(idx->offset)));
- /* Only look into the session further if;
- * (a) the second byte of the session_id matches,
- * (b) the "removed" flag isn't set,
- * (c) the session hasn't expired yet.
- * We do (c) like this so that it saves us having to
- * do natural expiries ... naturally expired sessions
- * scroll off the front anyway when the cache is full and
- * "rotating", the only real issue that remains is the
- * removal or disabling of forcibly killed sessions. */
- if ((idx->s_id2 == id[1]) && !idx->removed &&
- (shmcb_get_safe_time(&(idx->expires)) > now)) {
- ssl_log(s, SSL_LOG_TRACE, "at index %u, found possible "
- "session match", curr_pos);
- shmcb_cyclic_cton_memcpy(header->cache_data_size,
- tempasn, cache->data,
- shmcb_get_safe_uint(&(idx->offset)),
- SSL_SESSION_MAX_DER);
- ptr = tempasn;
- pSession = d2i_SSL_SESSION(NULL, &ptr, SSL_SESSION_MAX_DER);
- if (pSession == NULL) {
- ssl_log(s, SSL_LOG_ERROR, "scach2_lookup_"
- "session_id, internal error");
- return NULL;
- }
- if ((pSession->session_id_length == idlen) &&
- (memcmp(pSession->session_id, id, idlen) == 0)) {
- ssl_log(s, SSL_LOG_TRACE, "a match!");
- return pSession;
- }
- ssl_log(s, SSL_LOG_TRACE, "not a match");
- SSL_SESSION_free(pSession);
- pSession = NULL;
- }
- curr_pos = shmcb_cyclic_increment(header->index_num, curr_pos, 1);
- }
- ssl_log(s, SSL_LOG_TRACE, "no matching sessions were found");
- return NULL;
-}
-
-static BOOL shmcb_remove_session_id(
- server_rec *s, SHMCBQueue *queue,
- SHMCBCache *cache, UCHAR *id, int idlen)
-{
- unsigned char tempasn[SSL_SESSION_MAX_DER];
- SSL_SESSION *pSession = NULL;
- SHMCBIndex *idx;
- SHMCBHeader *header;
- unsigned int curr_pos, loop, count;
- unsigned char *ptr;
- BOOL to_return = FALSE;
-
- ssl_log(s, SSL_LOG_TRACE, "entering shmcb_remove_session_id");
-
- /* If there's entries to expire, ditch them first thing. */
- /* shmcb_expire_division(s, queue, cache); */
-
- /* Regarding the above ... hmmm ... I know my expiry code is slightly
- * "faster" than all this remove stuff ... but if the higher level
- * code calls a "remove" operation (and this *only* seems to happen
- * when it has spotted an expired session before we had a chance to)
- * then it should get credit for a remove (stats-wise). Also, in the
- * off-chance that the server *requests* a renegotiate and wants to
- * wipe the session clean we should give that priority over our own
- * routine expiry handling. So I've moved the expiry check to *after*
- * this general remove stuff. */
- curr_pos = shmcb_get_safe_uint(queue->first_pos);
- count = shmcb_get_safe_uint(queue->pos_count);
- header = cache->header;
- for (loop = 0; loop < count; loop++) {
- ssl_log(s, SSL_LOG_TRACE, "loop=%u, count=%u, curr_pos=%u",
- loop, count, curr_pos);
- idx = shmcb_get_index(queue, curr_pos);
- ssl_log(s, SSL_LOG_TRACE, "idx->s_id2=%u, id[1]=%u", idx->s_id2,
- id[1]);
- /* Only look into the session further if the second byte of the
- * session_id matches. */
- if (idx->s_id2 == id[1]) {
- ssl_log(s, SSL_LOG_TRACE, "at index %u, found possible "
- "session match", curr_pos);
- shmcb_cyclic_cton_memcpy(header->cache_data_size,
- tempasn, cache->data,
- shmcb_get_safe_uint(&(idx->offset)),
- SSL_SESSION_MAX_DER);
- ptr = tempasn;
- pSession = d2i_SSL_SESSION(NULL, &ptr, SSL_SESSION_MAX_DER);
- if (pSession == NULL) {
- ssl_log(s, SSL_LOG_ERROR, "shmcb_remove_session_id, "
- "internal error");
- goto end;
- }
- if ((pSession->session_id_length == idlen)
- && (memcmp(id, pSession->session_id, idlen) == 0)) {
- ssl_log(s, SSL_LOG_TRACE, "a match!");
- /* Scrub out this session "quietly" */
- idx->removed = (unsigned char) 1;
- SSL_SESSION_free(pSession);
- to_return = TRUE;
- goto end;
- }
- ssl_log(s, SSL_LOG_TRACE, "not a match");
- SSL_SESSION_free(pSession);
- pSession = NULL;
- }
- curr_pos = shmcb_cyclic_increment(header->index_num, curr_pos, 1);
- }
- ssl_log(s, SSL_LOG_TRACE, "no matching sessions were found");
-
- /* If there's entries to expire, ditch them now. */
- shmcb_expire_division(s, queue, cache);
-end:
- ssl_log(s, SSL_LOG_TRACE, "leaving shmcb_remove_session_id");
- return to_return;
-}
-
diff --git a/modules/ssl/ssl_util.c b/modules/ssl/ssl_util.c
deleted file mode 100644
index af4a9672f2..0000000000
--- a/modules/ssl/ssl_util.c
+++ /dev/null
@@ -1,437 +0,0 @@
-/* _ _
-** _ __ ___ ___ __| | ___ ___| | mod_ssl
-** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
-** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
-** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
-** |_____|
-** ssl_util.c
-** Utility Functions
-*/
-
-/* ====================================================================
- * Copyright (c) 1998-2001 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * 4. The names "mod_ssl" must not be used to endorse or promote
- * products derived from this software without prior written
- * permission. For written permission, please contact
- * rse@engelschall.com.
- *
- * 5. Products derived from this software may not be called "mod_ssl"
- * nor may "mod_ssl" appear in their names without prior
- * written permission of Ralf S. Engelschall.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
-
-/* ====================================================================
- * Copyright (c) 1995-1999 Ben Laurie. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by Ben Laurie
- * for use in the Apache-SSL HTTP server project."
- *
- * 4. The name "Apache-SSL Server" must not be used to
- * endorse or promote products derived from this software without
- * prior written permission.
- *
- * 5. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by Ben Laurie
- * for use in the Apache-SSL HTTP server project."
- *
- * THIS SOFTWARE IS PROVIDED BY BEN LAURIE ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BEN LAURIE OR
- * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
- /* ``Every day of my life
- I am forced to add another
- name to the list of people
- who piss me off!''
- -- Calvin */
-#include "mod_ssl.h"
-
-
-/* _________________________________________________________________
-**
-** Utility Functions
-** _________________________________________________________________
-*/
-
-char *ssl_util_server_root_relative(pool *p, char *what, char *arg)
-{
- char *rv = NULL;
-
-#ifdef SSL_VENDOR
- ap_hook_use("ap::mod_ssl::vendor::ssl_server_root_relative",
- AP_HOOK_SIG4(ptr,ptr,ptr,ptr), AP_HOOK_ALL, &rv, p, what, arg);
- if (rv != NULL)
- return rv;
-#endif
- rv = ap_server_root_relative(p, arg);
- return rv;
-}
-
-char *ssl_util_vhostid(pool *p, server_rec *s)
-{
- char *id;
- SSLSrvConfigRec *sc;
- char *host;
- unsigned int port;
-
- host = s->server_hostname;
- if (s->port != 0)
- port = s->port;
- else {
- sc = mySrvConfig(s);
- if (sc->bEnabled)
- port = DEFAULT_HTTPS_PORT;
- else
- port = DEFAULT_HTTP_PORT;
- }
- id = ap_psprintf(p, "%s:%u", host, port);
- return id;
-}
-
-void ssl_util_strupper(char *s)
-{
- for (; *s; ++s)
- *s = toupper(*s);
- return;
-}
-
-static const char ssl_util_uuencode_six2pr[64+1] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-void ssl_util_uuencode(char *szTo, const char *szFrom, BOOL bPad)
-{
- ssl_util_uuencode_binary((unsigned char *)szTo,
- (const unsigned char *)szFrom,
- strlen(szFrom), bPad);
-}
-
-void ssl_util_uuencode_binary(
- unsigned char *szTo, const unsigned char *szFrom, int nLength, BOOL bPad)
-{
- const unsigned char *s;
- int nPad = 0;
-
- for (s = szFrom; nLength > 0; s += 3) {
- *szTo++ = ssl_util_uuencode_six2pr[s[0] >> 2];
- *szTo++ = ssl_util_uuencode_six2pr[(s[0] << 4 | s[1] >> 4) & 0x3f];
- if (--nLength == 0) {
- nPad = 2;
- break;
- }
- *szTo++ = ssl_util_uuencode_six2pr[(s[1] << 2 | s[2] >> 6) & 0x3f];
- if (--nLength == 0) {
- nPad = 1;
- break;
- }
- *szTo++ = ssl_util_uuencode_six2pr[s[2] & 0x3f];
- --nLength;
- }
- while(bPad && nPad--)
- *szTo++ = NUL;
- *szTo = NUL;
- return;
-}
-
-FILE *ssl_util_ppopen(server_rec *s, pool *p, char *cmd)
-{
- FILE *fpout;
- int rc;
-
- fpout = NULL;
- rc = ap_spawn_child(p, ssl_util_ppopen_child,
- (void *)cmd, kill_after_timeout,
- NULL, &fpout, NULL);
- if (rc == 0 || fpout == NULL) {
- ap_log_error(APLOG_MARK, APLOG_ERR, s,
- "ssl_util_ppopen: could not run: %s", cmd);
- return NULL;
- }
- return (fpout);
-}
-
-int ssl_util_ppopen_child(void *cmd, child_info *pinfo)
-{
- int child_pid = 1;
-
- /*
- * Prepare for exec
- */
- ap_cleanup_for_exec();
-#ifdef SIGHUP
- signal(SIGHUP, SIG_IGN);
-#endif
-
- /*
- * Exec() the child program
- */
-#if defined(WIN32)
- /* MS Windows */
- {
- char pCommand[MAX_STRING_LEN];
- STARTUPINFO si;
- PROCESS_INFORMATION pi;
-
- ap_snprintf(pCommand, sizeof(pCommand), "%s /C %s", SHELL_PATH, cmd);
-
- memset(&si, 0, sizeof(si));
- memset(&pi, 0, sizeof(pi));
-
- si.cb = sizeof(si);
- si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
- si.wShowWindow = SW_HIDE;
- si.hStdInput = pinfo->hPipeInputRead;
- si.hStdOutput = pinfo->hPipeOutputWrite;
- si.hStdError = pinfo->hPipeErrorWrite;
-
- if (CreateProcess(NULL, pCommand, NULL, NULL, TRUE, 0,
- environ, NULL, &si, &pi)) {
- CloseHandle(pi.hProcess);
- CloseHandle(pi.hThread);
- child_pid = pi.dwProcessId;
- }
- }
-#elif defined(OS2)
- /* IBM OS/2 */
- spawnl(P_NOWAIT, SHELL_PATH, SHELL_PATH, "/c", (char *)cmd, NULL);
-#else
- /* Standard Unix */
- execl(SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL);
-#endif
- return (child_pid);
-}
-
-void ssl_util_ppclose(server_rec *s, pool *p, FILE *fp)
-{
- ap_pfclose(p, fp);
- return;
-}
-
-/*
- * Run a filter program and read the first line of its stdout output
- */
-char *ssl_util_readfilter(server_rec *s, pool *p, char *cmd)
-{
- static char buf[MAX_STRING_LEN];
- FILE *fp;
- char c;
- int k;
-
- if ((fp = ssl_util_ppopen(s, p, cmd)) == NULL)
- return NULL;
- for (k = 0; read(fileno(fp), &c, 1) == 1
- && (k < MAX_STRING_LEN-1) ; ) {
- if (c == '\n' || c == '\r')
- break;
- buf[k++] = c;
- }
- buf[k] = NUL;
- ssl_util_ppclose(s, p, fp);
-
- return buf;
-}
-
-BOOL ssl_util_path_check(ssl_pathcheck_t pcm, char *path)
-{
- struct stat sb;
-
- if (path == NULL)
- return FALSE;
- if (pcm & SSL_PCM_EXISTS && stat(path, &sb) != 0)
- return FALSE;
- if (pcm & SSL_PCM_ISREG && !S_ISREG(sb.st_mode))
- return FALSE;
- if (pcm & SSL_PCM_ISDIR && !S_ISDIR(sb.st_mode))
- return FALSE;
- if (pcm & SSL_PCM_ISNONZERO && sb.st_mode <= 0)
- return FALSE;
- return TRUE;
-}
-
-ssl_algo_t ssl_util_algotypeof(X509 *pCert, EVP_PKEY *pKey)
-{
- ssl_algo_t t;
-
- t = SSL_ALGO_UNKNOWN;
- if (pCert != NULL)
- pKey = X509_get_pubkey(pCert);
- if (pKey != NULL) {
- switch (EVP_PKEY_type(pKey->type)) {
- case EVP_PKEY_RSA:
- t = SSL_ALGO_RSA;
- break;
- case EVP_PKEY_DSA:
- t = SSL_ALGO_DSA;
- break;
- default:
- break;
- }
- }
- return t;
-}
-
-char *ssl_util_algotypestr(ssl_algo_t t)
-{
- char *cp;
-
- cp = "UNKNOWN";
- switch (t) {
- case SSL_ALGO_RSA:
- cp = "RSA";
- break;
- case SSL_ALGO_DSA:
- cp = "DSA";
- break;
- default:
- break;
- }
- return cp;
-}
-
-char *ssl_util_ptxtsub(
- pool *p, const char *cpLine, const char *cpMatch, char *cpSubst)
-{
-#define MAX_PTXTSUB 100
- char *cppMatch[MAX_PTXTSUB];
- char *cpResult;
- int nResult;
- int nLine;
- int nSubst;
- int nMatch;
- char *cpI;
- char *cpO;
- char *cp;
- int i;
-
- /*
- * Pass 1: find substitution locations and calculate sizes
- */
- nLine = strlen(cpLine);
- nMatch = strlen(cpMatch);
- nSubst = strlen(cpSubst);
- for (cpI = (char *)cpLine, i = 0, nResult = 0;
- cpI < cpLine+nLine && i < MAX_PTXTSUB; ) {
- if ((cp = strstr(cpI, cpMatch)) != NULL) {
- cppMatch[i++] = cp;
- nResult += ((cp-cpI)+nSubst);
- cpI = (cp+nMatch);
- }
- else {
- nResult += strlen(cpI);
- break;
- }
- }
- cppMatch[i] = NULL;
- if (i == 0)
- return NULL;
-
- /*
- * Pass 2: allocate memory and assemble result
- */
- cpResult = ap_pcalloc(p, nResult+1);
- for (cpI = (char *)cpLine, cpO = cpResult, i = 0; cppMatch[i] != NULL; i++) {
- ap_cpystrn(cpO, cpI, cppMatch[i]-cpI+1);
- cpO += (cppMatch[i]-cpI);
- ap_cpystrn(cpO, cpSubst, nSubst+1);
- cpO += nSubst;
- cpI = (cppMatch[i]+nMatch);
- }
- ap_cpystrn(cpO, cpI, cpResult+nResult-cpO+1);
-
- return cpResult;
-}
-
-/* _________________________________________________________________
-**
-** Special Functions for Win32/OpenSSL
-** _________________________________________________________________
-*/
-
-#ifdef WIN32
-static HANDLE lock_cs[CRYPTO_NUM_LOCKS];
-
-static void win32_locking_callback(int mode, int type, char* file, int line)
-{
- if (mode & CRYPTO_LOCK)
- WaitForSingleObject(lock_cs[type], INFINITE);
- else
- ReleaseMutex(lock_cs[type]);
- return;
-}
-#endif /* WIN32 */
-
-void ssl_util_thread_setup(void)
-{
-#ifdef WIN32
- int i;
-
- for (i = 0; i < CRYPTO_NUM_LOCKS; i++)
- lock_cs[i] = CreateMutex(NULL, FALSE, NULL);
- CRYPTO_set_locking_callback((void(*)(int, int, const char *, int))
- win32_locking_callback);
-#endif /* WIN32 */
- return;
-}
-
diff --git a/modules/ssl/ssl_util_ssl.c b/modules/ssl/ssl_util_ssl.c
deleted file mode 100644
index 19f6bd3629..0000000000
--- a/modules/ssl/ssl_util_ssl.c
+++ /dev/null
@@ -1,544 +0,0 @@
-/* _ _
-** _ __ ___ ___ __| | ___ ___| | mod_ssl
-** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
-** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
-** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
-** |_____|
-** ssl_util_ssl.c
-** Additional Utility Functions for OpenSSL
-*/
-
-/* ====================================================================
- * Copyright (c) 1998-2001 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * 4. The names "mod_ssl" must not be used to endorse or promote
- * products derived from this software without prior written
- * permission. For written permission, please contact
- * rse@engelschall.com.
- *
- * 5. Products derived from this software may not be called "mod_ssl"
- * nor may "mod_ssl" appear in their names without prior
- * written permission of Ralf S. Engelschall.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
-
-#include "mod_ssl.h"
-
-
-/* _________________________________________________________________
-**
-** Additional High-Level Functions for OpenSSL
-** _________________________________________________________________
-*/
-
-int SSL_get_app_data2_idx(void)
-{
- static int app_data2_idx = -1;
-
- if (app_data2_idx < 0) {
- app_data2_idx = SSL_get_ex_new_index(0,
- "Second Application Data for SSL", NULL, NULL, NULL);
- app_data2_idx = SSL_get_ex_new_index(0,
- "Second Application Data for SSL", NULL, NULL, NULL);
- }
- return(app_data2_idx);
-}
-
-void *SSL_get_app_data2(SSL *ssl)
-{
- return (void *)SSL_get_ex_data(ssl, SSL_get_app_data2_idx());
-}
-
-void SSL_set_app_data2(SSL *ssl, void *arg)
-{
- SSL_set_ex_data(ssl, SSL_get_app_data2_idx(), (char *)arg);
- return;
-}
-
-/* _________________________________________________________________
-**
-** High-Level Certificate / Private Key Loading
-** _________________________________________________________________
-*/
-
-X509 *SSL_read_X509(FILE *fp, X509 **x509, int (*cb)())
-{
- X509 *rc;
- BIO *bioS;
- BIO *bioF;
-
- /* 1. try PEM (= DER+Base64+headers) */
-#if SSL_LIBRARY_VERSION < 0x00904000
- rc = PEM_read_X509(fp, x509, cb);
-#else
- rc = PEM_read_X509(fp, x509, cb, NULL);
-#endif
- if (rc == NULL) {
- /* 2. try DER+Base64 */
- fseek(fp, 0L, SEEK_SET);
- if ((bioS = BIO_new(BIO_s_fd())) == NULL)
- return NULL;
- BIO_set_fd(bioS, fileno(fp), BIO_NOCLOSE);
- if ((bioF = BIO_new(BIO_f_base64())) == NULL) {
- BIO_free(bioS);
- return NULL;
- }
- bioS = BIO_push(bioF, bioS);
- rc = d2i_X509_bio(bioS, NULL);
- BIO_free_all(bioS);
- if (rc == NULL) {
- /* 3. try plain DER */
- fseek(fp, 0L, SEEK_SET);
- if ((bioS = BIO_new(BIO_s_fd())) == NULL)
- return NULL;
- BIO_set_fd(bioS, fileno(fp), BIO_NOCLOSE);
- rc = d2i_X509_bio(bioS, NULL);
- BIO_free(bioS);
- }
- }
- if (rc != NULL && x509 != NULL) {
- if (*x509 != NULL)
- X509_free(*x509);
- *x509 = rc;
- }
- return rc;
-}
-
-#if SSL_LIBRARY_VERSION <= 0x00904100
-static EVP_PKEY *d2i_PrivateKey_bio(BIO *bio, EVP_PKEY **key)
-{
- return ((EVP_PKEY *)ASN1_d2i_bio(
- (char *(*)())EVP_PKEY_new,
- (char *(*)())d2i_PrivateKey,
- (bio), (unsigned char **)(key)));
-}
-#endif
-
-EVP_PKEY *SSL_read_PrivateKey(FILE *fp, EVP_PKEY **key, int (*cb)())
-{
- EVP_PKEY *rc;
- BIO *bioS;
- BIO *bioF;
-
- /* 1. try PEM (= DER+Base64+headers) */
-#if SSL_LIBRARY_VERSION < 0x00904000
- rc = PEM_read_PrivateKey(fp, key, cb);
-#else
- rc = PEM_read_PrivateKey(fp, key, cb, NULL);
-#endif
- if (rc == NULL) {
- /* 2. try DER+Base64 */
- fseek(fp, 0L, SEEK_SET);
- if ((bioS = BIO_new(BIO_s_fd())) == NULL)
- return NULL;
- BIO_set_fd(bioS, fileno(fp), BIO_NOCLOSE);
- if ((bioF = BIO_new(BIO_f_base64())) == NULL) {
- BIO_free(bioS);
- return NULL;
- }
- bioS = BIO_push(bioF, bioS);
- rc = d2i_PrivateKey_bio(bioS, NULL);
- BIO_free_all(bioS);
- if (rc == NULL) {
- /* 3. try plain DER */
- fseek(fp, 0L, SEEK_SET);
- if ((bioS = BIO_new(BIO_s_fd())) == NULL)
- return NULL;
- BIO_set_fd(bioS, fileno(fp), BIO_NOCLOSE);
- rc = d2i_PrivateKey_bio(bioS, NULL);
- BIO_free(bioS);
- }
- }
- if (rc != NULL && key != NULL) {
- if (*key != NULL)
- EVP_PKEY_free(*key);
- *key = rc;
- }
- return rc;
-}
-
-/* _________________________________________________________________
-**
-** Smart shutdown
-** _________________________________________________________________
-*/
-
-int SSL_smart_shutdown(SSL *ssl)
-{
- int i;
- int rc;
-
- /*
- * Repeat the calls, because SSL_shutdown internally dispatches through a
- * little state machine. Usually only one or two interation should be
- * needed, so we restrict the total number of restrictions in order to
- * avoid process hangs in case the client played bad with the socket
- * connection and OpenSSL cannot recognize it.
- */
- rc = 0;
- for (i = 0; i < 4 /* max 2x pending + 2x data = 4 */; i++) {
- if ((rc = SSL_shutdown(ssl)))
- break;
- }
- return rc;
-}
-
-/* _________________________________________________________________
-**
-** Certificate Revocation List (CRL) Storage
-** _________________________________________________________________
-*/
-
-X509_STORE *SSL_X509_STORE_create(char *cpFile, char *cpPath)
-{
- X509_STORE *pStore;
- X509_LOOKUP *pLookup;
-
- if (cpFile == NULL && cpPath == NULL)
- return NULL;
- if ((pStore = X509_STORE_new()) == NULL)
- return NULL;
- if (cpFile != NULL) {
- if ((pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_file())) == NULL) {
- X509_STORE_free(pStore);
- return NULL;
- }
- X509_LOOKUP_load_file(pLookup, cpFile, X509_FILETYPE_PEM);
- }
- if (cpPath != NULL) {
- if ((pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_hash_dir())) == NULL) {
- X509_STORE_free(pStore);
- return NULL;
- }
- X509_LOOKUP_add_dir(pLookup, cpPath, X509_FILETYPE_PEM);
- }
- return pStore;
-}
-
-int SSL_X509_STORE_lookup(X509_STORE *pStore, int nType,
- X509_NAME *pName, X509_OBJECT *pObj)
-{
- X509_STORE_CTX pStoreCtx;
- int rc;
-
- X509_STORE_CTX_init(&pStoreCtx, pStore, NULL, NULL);
- rc = X509_STORE_get_by_subject(&pStoreCtx, nType, pName, pObj);
- X509_STORE_CTX_cleanup(&pStoreCtx);
- return rc;
-}
-
-/* _________________________________________________________________
-**
-** Cipher Suite Spec String Creation
-** _________________________________________________________________
-*/
-
-char *SSL_make_ciphersuite(pool *p, SSL *ssl)
-{
- STACK_OF(SSL_CIPHER) *sk;
- SSL_CIPHER *c;
- int i;
- int l;
- char *cpCipherSuite;
- char *cp;
-
- if (ssl == NULL)
- return "";
- if ((sk = SSL_get_ciphers(ssl)) == NULL)
- return "";
- l = 0;
- for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
- c = sk_SSL_CIPHER_value(sk, i);
- l += strlen(c->name)+2+1;
- }
- if (l == 0)
- return "";
- cpCipherSuite = (char *)ap_palloc(p, l+1);
- cp = cpCipherSuite;
- for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
- c = sk_SSL_CIPHER_value(sk, i);
- l = strlen(c->name);
- memcpy(cp, c->name, l);
- cp += l;
- *cp++ = '/';
- *cp++ = (c->valid == 1 ? '1' : '0');
- *cp++ = ':';
- }
- *(cp-1) = NUL;
- return cpCipherSuite;
-}
-
-/* _________________________________________________________________
-**
-** Certificate Checks
-** _________________________________________________________________
-*/
-
-/* check whether cert contains extended key usage with a SGC tag */
-BOOL SSL_X509_isSGC(X509 *cert)
-{
- X509_EXTENSION *ext;
- int ext_nid;
- STACK *sk;
- BOOL is_sgc;
- int idx;
- int i;
-
- is_sgc = FALSE;
- idx = X509_get_ext_by_NID(cert, NID_ext_key_usage, -1);
- if (idx >= 0) {
- ext = X509_get_ext(cert, idx);
- if ((sk = (STACK *)X509V3_EXT_d2i(ext)) != NULL) {
- for (i = 0; i < sk_num(sk); i++) {
- ext_nid = OBJ_obj2nid((ASN1_OBJECT *)sk_value(sk, i));
- if (ext_nid == NID_ms_sgc || ext_nid == NID_ns_sgc) {
- is_sgc = TRUE;
- break;
- }
- }
- }
- }
- return is_sgc;
-}
-
-/* retrieve basic constraints ingredients */
-BOOL SSL_X509_getBC(X509 *cert, int *ca, int *pathlen)
-{
- X509_EXTENSION *ext;
- BASIC_CONSTRAINTS *bc;
- int idx;
- BIGNUM *bn = NULL;
- char *cp;
-
- if ((idx = X509_get_ext_by_NID(cert, NID_basic_constraints, -1)) < 0)
- return FALSE;
- ext = X509_get_ext(cert, idx);
- if (ext == NULL)
- return FALSE;
- if ((bc = (BASIC_CONSTRAINTS *)X509V3_EXT_d2i(ext)) == NULL)
- return FALSE;
- *ca = bc->ca;
- *pathlen = -1 /* unlimited */;
- if (bc->pathlen != NULL) {
- if ((bn = ASN1_INTEGER_to_BN(bc->pathlen, NULL)) == NULL)
- return FALSE;
- if ((cp = BN_bn2dec(bn)) == NULL)
- return FALSE;
- *pathlen = atoi(cp);
- free(cp);
- BN_free(bn);
- }
- BASIC_CONSTRAINTS_free(bc);
- return TRUE;
-}
-
-/* retrieve subject CommonName of certificate */
-BOOL SSL_X509_getCN(pool *p, X509 *xs, char **cppCN)
-{
- X509_NAME *xsn;
- X509_NAME_ENTRY *xsne;
- int i, nid;
-
- xsn = X509_get_subject_name(xs);
- for (i = 0; i < sk_X509_NAME_ENTRY_num(xsn->entries); i++) {
- xsne = sk_X509_NAME_ENTRY_value(xsn->entries, i);
- nid = OBJ_obj2nid(xsne->object);
- if (nid == NID_commonName) {
- *cppCN = ap_palloc(p, xsne->value->length+1);
- ap_cpystrn(*cppCN, (char *)xsne->value->data, xsne->value->length+1);
- (*cppCN)[xsne->value->length] = NUL;
-#ifdef CHARSET_EBCDIC
- ascii2ebcdic(*cppCN, *cppCN, strlen(*cppCN));
-#endif
- return TRUE;
- }
- }
- return FALSE;
-}
-
-/* _________________________________________________________________
-**
-** Low-Level CA Certificate Loading
-** _________________________________________________________________
-*/
-
-#ifdef SSL_EXPERIMENTAL_PROXY
-
-BOOL SSL_load_CrtAndKeyInfo_file(pool *p, STACK_OF(X509_INFO) *sk, char *filename)
-{
- BIO *in;
-
- if ((in = BIO_new(BIO_s_file())) == NULL)
- return FALSE;
- if (BIO_read_filename(in, filename) <= 0) {
- BIO_free(in);
- return FALSE;
- }
- ERR_clear_error();
-#if SSL_LIBRARY_VERSION < 0x00904000
- PEM_X509_INFO_read_bio(in, sk, NULL);
-#else
- PEM_X509_INFO_read_bio(in, sk, NULL, NULL);
-#endif
- BIO_free(in);
- return TRUE;
-}
-
-BOOL SSL_load_CrtAndKeyInfo_path(pool *p, STACK_OF(X509_INFO) *sk, char *pathname)
-{
- struct stat st;
- DIR *dir;
- pool *sp;
- struct dirent *nextent;
- char *fullname;
- BOOL ok;
-
- sp = ap_make_sub_pool(p);
- if ((dir = ap_popendir(sp, pathname)) == NULL) {
- ap_destroy_pool(sp);
- return FALSE;
- }
- ok = FALSE;
- while ((nextent = readdir(dir)) != NULL) {
- fullname = ap_pstrcat(sp, pathname, "/", nextent->d_name, NULL);
- if (stat(fullname, &st) != 0)
- continue;
- if (!S_ISREG(st.st_mode))
- continue;
- if (SSL_load_CrtAndKeyInfo_file(sp, sk, fullname))
- ok = TRUE;
- }
- ap_pclosedir(p, dir);
- ap_destroy_pool(sp);
- return ok;
-}
-
-#endif /* SSL_EXPERIMENTAL_PROXY */
-
-/* _________________________________________________________________
-**
-** Extra Server Certificate Chain Support
-** _________________________________________________________________
-*/
-
-/*
- * Read a file that optionally contains the server certificate in PEM
- * format, possibly followed by a sequence of CA certificates that
- * should be sent to the peer in the SSL Certificate message.
- */
-int SSL_CTX_use_certificate_chain(
- SSL_CTX *ctx, char *file, int skipfirst, int (*cb)())
-{
- BIO *bio;
- X509 *x509;
- unsigned long err;
- int n;
-
- if ((bio = BIO_new(BIO_s_file_internal())) == NULL)
- return -1;
- if (BIO_read_filename(bio, file) <= 0) {
- BIO_free(bio);
- return -1;
- }
- /* optionally skip a leading server certificate */
- if (skipfirst) {
-#if SSL_LIBRARY_VERSION < 0x00904000
- if ((x509 = PEM_read_bio_X509(bio, NULL, cb)) == NULL) {
-#else
- if ((x509 = PEM_read_bio_X509(bio, NULL, cb, NULL)) == NULL) {
-#endif
- BIO_free(bio);
- return -1;
- }
- X509_free(x509);
- }
- /* free a perhaps already configured extra chain */
- if (ctx->extra_certs != NULL) {
- sk_X509_pop_free(ctx->extra_certs, X509_free);
- ctx->extra_certs = NULL;
- }
- /* create new extra chain by loading the certs */
- n = 0;
-#if SSL_LIBRARY_VERSION < 0x00904000
- while ((x509 = PEM_read_bio_X509(bio, NULL, cb)) != NULL) {
-#else
- while ((x509 = PEM_read_bio_X509(bio, NULL, cb, NULL)) != NULL) {
-#endif
- if (!SSL_CTX_add_extra_chain_cert(ctx, x509)) {
- X509_free(x509);
- BIO_free(bio);
- return -1;
- }
- n++;
- }
- /* Make sure that only the error is just an EOF */
- if ((err = ERR_peek_error()) > 0) {
- if (!( ERR_GET_LIB(err) == ERR_LIB_PEM
- && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) {
- BIO_free(bio);
- return -1;
- }
- while (ERR_get_error() > 0) ;
- }
- BIO_free(bio);
- return n;
-}
-
-/* _________________________________________________________________
-**
-** Session Stuff
-** _________________________________________________________________
-*/
-
-char *SSL_SESSION_id2sz(unsigned char *id, int idlen)
-{
- static char str[(SSL_MAX_SSL_SESSION_ID_LENGTH+1)*2];
- char *cp;
- int n;
-
- cp = str;
- for (n = 0; n < idlen && n < SSL_MAX_SSL_SESSION_ID_LENGTH; n++) {
- ap_snprintf(cp, sizeof(str)-(cp-str), "%02X", id[n]);
- cp += 2;
- }
- *cp = NUL;
- return str;
-}
-
diff --git a/modules/ssl/ssl_util_ssl.h b/modules/ssl/ssl_util_ssl.h
deleted file mode 100644
index 23aaaaa40d..0000000000
--- a/modules/ssl/ssl_util_ssl.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/* _ _
-** _ __ ___ ___ __| | ___ ___| | mod_ssl
-** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
-** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
-** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
-** |_____|
-** ssl_util_ssl.h
-** Additional Utility Functions for OpenSSL
-*/
-
-/* ====================================================================
- * Copyright (c) 1998-2001 Ralf S. Engelschall. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * 4. The names "mod_ssl" must not be used to endorse or promote
- * products derived from this software without prior written
- * permission. For written permission, please contact
- * rse@engelschall.com.
- *
- * 5. Products derived from this software may not be called "mod_ssl"
- * nor may "mod_ssl" appear in their names without prior
- * written permission of Ralf S. Engelschall.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by
- * Ralf S. Engelschall <rse@engelschall.com> for use in the
- * mod_ssl project (http://www.modssl.org/)."
- *
- * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
- * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
-
-#ifndef SSL_UTIL_SSL_H
-#define SSL_UTIL_SSL_H
-
-/*
- * Determine SSL library version number
- */
-#ifdef OPENSSL_VERSION_NUMBER
-#define SSL_LIBRARY_VERSION OPENSSL_VERSION_NUMBER
-#define SSL_LIBRARY_NAME "OpenSSL"
-#define SSL_LIBRARY_TEXT OPENSSL_VERSION_TEXT
-#else
-#define SSL_LIBRARY_VERSION 0x0000
-#define SSL_LIBRARY_NAME "OtherSSL"
-#define SSL_LIBRARY_TEXT "OtherSSL 0.0.0 00 XXX 0000"
-#endif
-
-/*
- * Support for retrieving/overriding states
- */
-#ifndef SSL_get_state
-#define SSL_get_state(ssl) SSL_state(ssl)
-#endif
-#define SSL_set_state(ssl,val) (ssl)->state = val
-
-/*
- * Maximum length of a DER encoded session.
- * FIXME: There is no define in OpenSSL, but OpenSSL uses 1024*10,
- * so this value should be ok. Although we have no warm feeling.
- */
-#define SSL_SESSION_MAX_DER 1024*10
-
-/*
- * Additional Functions
- */
-int SSL_get_app_data2_idx(void);
-void *SSL_get_app_data2(SSL *);
-void SSL_set_app_data2(SSL *, void *);
-X509 *SSL_read_X509(FILE *, X509 **, int (*)());
-EVP_PKEY *SSL_read_PrivateKey(FILE *, EVP_PKEY **, int (*)());
-int SSL_smart_shutdown(SSL *ssl);
-X509_STORE *SSL_X509_STORE_create(char *, char *);
-int SSL_X509_STORE_lookup(X509_STORE *, int, X509_NAME *, X509_OBJECT *);
-char *SSL_make_ciphersuite(pool *, SSL *);
-BOOL SSL_X509_isSGC(X509 *);
-BOOL SSL_X509_getBC(X509 *, int *, int *);
-BOOL SSL_X509_getCN(pool *, X509 *, char **);
-#ifdef SSL_EXPERIMENTAL_PROXY
-BOOL SSL_load_CrtAndKeyInfo_file(pool *, STACK_OF(X509_INFO) *, char *);
-BOOL SSL_load_CrtAndKeyInfo_path(pool *, STACK_OF(X509_INFO) *, char *);
-#endif /* SSL_EXPERIMENTAL_PROXY */
-int SSL_CTX_use_certificate_chain(SSL_CTX *, char *, int, int (*)());
-char *SSL_SESSION_id2sz(unsigned char *, int);
-
-#endif /* SSL_UTIL_SSL_H */
diff --git a/modules/test/.cvsignore b/modules/test/.cvsignore
deleted file mode 100644
index 02736007bd..0000000000
--- a/modules/test/.cvsignore
+++ /dev/null
@@ -1,7 +0,0 @@
-.deps
-Makefile
-*.lo
-*.so
-modules.mk
-Debug
-Release
diff --git a/modules/test/.indent.pro b/modules/test/.indent.pro
deleted file mode 100644
index a9fbe9f9a1..0000000000
--- a/modules/test/.indent.pro
+++ /dev/null
@@ -1,54 +0,0 @@
--i4 -npsl -di0 -br -nce -d0 -cli0 -npcs -nfc1
--TBUFF
--TFILE
--TTRANS
--TUINT4
--T_trans
--Tallow_options_t
--Tapache_sfio
--Tarray_header
--Tbool_int
--Tbuf_area
--Tbuff_struct
--Tbuffy
--Tcmd_how
--Tcmd_parms
--Tcommand_rec
--Tcommand_struct
--Tconn_rec
--Tcore_dir_config
--Tcore_server_config
--Tdir_maker_func
--Tevent
--Tglobals_s
--Thandler_func
--Thandler_rec
--Tjoblist_s
--Tlisten_rec
--Tmerger_func
--Tmode_t
--Tmodule
--Tmodule_struct
--Tmutex
--Tn_long
--Tother_child_rec
--Toverrides_t
--Tparent_score
--Tpid_t
--Tpiped_log
--Tpool
--Trequest_rec
--Trequire_line
--Trlim_t
--Tscoreboard
--Tsemaphore
--Tserver_addr_rec
--Tserver_rec
--Tserver_rec_chain
--Tshort_score
--Ttable
--Ttable_entry
--Tthread
--Tu_wide_int
--Tvtime_t
--Twide_int
diff --git a/modules/test/README b/modules/test/README
deleted file mode 100644
index c61763c1dd..0000000000
--- a/modules/test/README
+++ /dev/null
@@ -1,3 +0,0 @@
-This directory is intended to house modules which are used for testing
-server functionality. They're unsupported, and not guaranteed to remain
-consistant between releases. You're on your own completely with these.
diff --git a/modules/test/mod_autoindex.c b/modules/test/mod_autoindex.c
deleted file mode 100644
index d875082a85..0000000000
--- a/modules/test/mod_autoindex.c
+++ /dev/null
@@ -1,1711 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * mod_autoindex.c: Handles the on-the-fly html index generation
- *
- * Rob McCool
- * 3/23/93
- *
- * Adapted to Apache by rst.
- *
- * Version sort added by Martin Pool <mbp@humbug.org.au>. */
-
-#include "apr_strings.h"
-#include "ap_config.h"
-#include "httpd.h"
-#include "http_config.h"
-#include "http_core.h"
-#include "http_request.h"
-#include "http_protocol.h"
-#include "http_log.h"
-#include "http_main.h"
-#include "util_script.h"
-#include "apr_fnmatch.h"
-#include "apr_strings.h"
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-
-module AP_MODULE_DECLARE_DATA autoindex_module;
-
-/****************************************************************
- *
- * Handling configuration directives...
- */
-
-#define HRULE 1
-#define NO_HRULE 0
-#define FRONT_MATTER 1
-#define END_MATTER 0
-
-#define FANCY_INDEXING 1 /* Indexing options */
-#define ICONS_ARE_LINKS 2
-#define SCAN_HTML_TITLES 4
-#define SUPPRESS_LAST_MOD 8
-#define SUPPRESS_SIZE 16
-#define SUPPRESS_DESC 32
-#define SUPPRESS_PREAMBLE 64
-#define SUPPRESS_COLSORT 128
-#define NO_OPTIONS 256
-#define VERSION_SORT 512
-
-#define K_PAD 1
-#define K_NOPAD 0
-
-#define K_NOADJUST 0
-#define K_ADJUST 1
-#define K_UNSET 2
-
-/*
- * Define keys for sorting.
- */
-#define K_NAME 'N' /* Sort by file name (default) */
-#define K_LAST_MOD 'M' /* Last modification date */
-#define K_SIZE 'S' /* Size (absolute, not as displayed) */
-#define K_DESC 'D' /* Description */
-
-#define D_ASCENDING 'A'
-#define D_DESCENDING 'D'
-
-/*
- * These are the dimensions of the default icons supplied with Apache.
- */
-#define DEFAULT_ICON_WIDTH 20
-#define DEFAULT_ICON_HEIGHT 22
-
-/*
- * Other default dimensions.
- */
-#define DEFAULT_NAME_WIDTH 23
-
-struct item {
- char *type;
- char *apply_to;
- char *apply_path;
- char *data;
-};
-
-typedef struct ai_desc_t {
- char *pattern;
- char *description;
- int full_path;
- int wildcards;
-} ai_desc_t;
-
-typedef struct autoindex_config_struct {
-
- char *default_icon;
- int opts;
- int incremented_opts;
- int decremented_opts;
- int name_width;
- int name_adjust;
- int icon_width;
- int icon_height;
- char *default_order;
-
- apr_array_header_t *icon_list;
- apr_array_header_t *alt_list;
- apr_array_header_t *desc_list;
- apr_array_header_t *ign_list;
- apr_array_header_t *hdr_list;
- apr_array_header_t *rdme_list;
-
-} autoindex_config_rec;
-
-static char c_by_encoding, c_by_type, c_by_path;
-
-#define BY_ENCODING &c_by_encoding
-#define BY_TYPE &c_by_type
-#define BY_PATH &c_by_path
-
-/*
- * Return true if the specified string refers to the parent directory (i.e.,
- * matches ".." or "../"). Hopefully this one call is significantly less
- * expensive than multiple strcmp() calls.
- */
-static apr_inline int is_parent(const char *name)
-{
- /*
- * Now, IFF the first two bytes are dots, and the third byte is either
- * EOS (\0) or a slash followed by EOS, we have a match.
- */
- if (((name[0] == '.') && (name[1] == '.'))
- && ((name[2] == '\0')
- || ((name[2] == '/') && (name[3] == '\0')))) {
- return 1;
- }
- return 0;
-}
-
-/*
- * This routine puts the standard HTML header at the top of the index page.
- * We include the DOCTYPE because we may be using features therefrom (i.e.,
- * HEIGHT and WIDTH attributes on the icons if we're FancyIndexing).
- */
-static void emit_preamble(request_rec *r, char *title)
-{
- ap_rvputs(r, DOCTYPE_HTML_3_2,
- "<HTML>\n <HEAD>\n <TITLE>Index of ", title,
- "</TITLE>\n </HEAD>\n <BODY>\n", NULL);
-}
-
-static void push_item(apr_array_header_t *arr, char *type, const char *to,
- const char *path, const char *data)
-{
- struct item *p = (struct item *) apr_array_push(arr);
-
- if (!to) {
- to = "";
- }
- if (!path) {
- path = "";
- }
-
- p->type = type;
- p->data = data ? apr_pstrdup(arr->cont, data) : NULL;
- p->apply_path = apr_pstrcat(arr->cont, path, "*", NULL);
-
- if ((type == BY_PATH) && (!ap_is_matchexp(to))) {
- p->apply_to = apr_pstrcat(arr->cont, "*", to, NULL);
- }
- else if (to) {
- p->apply_to = apr_pstrdup(arr->cont, to);
- }
- else {
- p->apply_to = NULL;
- }
-}
-
-static const char *add_alt(cmd_parms *cmd, void *d, const char *alt,
- const char *to)
-{
- if (cmd->info == BY_PATH) {
- if (!strcmp(to, "**DIRECTORY**")) {
- to = "^^DIRECTORY^^";
- }
- }
- if (cmd->info == BY_ENCODING) {
- char *tmp = apr_pstrdup(cmd->pool, to);
- ap_str_tolower(tmp);
- to = tmp;
- }
-
- push_item(((autoindex_config_rec *) d)->alt_list, cmd->info, to,
- cmd->path, alt);
- return NULL;
-}
-
-static const char *add_icon(cmd_parms *cmd, void *d, const char *icon,
- const char *to)
-{
- char *iconbak = apr_pstrdup(cmd->pool, icon);
-
- if (icon[0] == '(') {
- char *alt;
- char *cl = strchr(iconbak, ')');
-
- if (cl == NULL) {
- return "missing closing paren";
- }
- alt = ap_getword_nc(cmd->pool, &iconbak, ',');
- *cl = '\0'; /* Lose closing paren */
- add_alt(cmd, d, &alt[1], to);
- }
- if (cmd->info == BY_PATH) {
- if (!strcmp(to, "**DIRECTORY**")) {
- to = "^^DIRECTORY^^";
- }
- }
- if (cmd->info == BY_ENCODING) {
- char *tmp = apr_pstrdup(cmd->pool, to);
- ap_str_tolower(tmp);
- to = tmp;
- }
-
- push_item(((autoindex_config_rec *) d)->icon_list, cmd->info, to,
- cmd->path, iconbak);
- return NULL;
-}
-
-/*
- * Add description text for a filename pattern. If the pattern has
- * wildcards already (or we need to add them), add leading and
- * trailing wildcards to it to ensure substring processing. If the
- * pattern contains a '/' anywhere, force wildcard matching mode,
- * add a slash to the prefix so that "bar/bletch" won't be matched
- * by "foobar/bletch", and make a note that there's a delimiter;
- * the matching routine simplifies to just the actual filename
- * whenever it can. This allows definitions in parent directories
- * to be made for files in subordinate ones using relative paths.
- */
-
-/*
- * Absent a strcasestr() function, we have to force wildcards on
- * systems for which "AAA" and "aaa" mean the same file.
- */
-#ifdef CASE_BLIND_FILESYSTEM
-#define WILDCARDS_REQUIRED 1
-#else
-#define WILDCARDS_REQUIRED 0
-#endif
-
-static const char *add_desc(cmd_parms *cmd, void *d, const char *desc,
- const char *to)
-{
- autoindex_config_rec *dcfg = (autoindex_config_rec *) d;
- ai_desc_t *desc_entry;
- char *prefix = "";
-
- desc_entry = (ai_desc_t *) apr_array_push(dcfg->desc_list);
- desc_entry->full_path = (ap_strchr_c(to, '/') == NULL) ? 0 : 1;
- desc_entry->wildcards = (WILDCARDS_REQUIRED
- || desc_entry->full_path
- || apr_is_fnmatch(to));
- if (desc_entry->wildcards) {
- prefix = desc_entry->full_path ? "*/" : "*";
- desc_entry->pattern = apr_pstrcat(dcfg->desc_list->cont,
- prefix, to, "*", NULL);
- }
- else {
- desc_entry->pattern = apr_pstrdup(dcfg->desc_list->cont, to);
- }
- desc_entry->description = apr_pstrdup(dcfg->desc_list->cont, desc);
- return NULL;
-}
-
-static const char *add_ignore(cmd_parms *cmd, void *d, const char *ext)
-{
- push_item(((autoindex_config_rec *) d)->ign_list, 0, ext, cmd->path, NULL);
- return NULL;
-}
-
-static const char *add_header(cmd_parms *cmd, void *d, const char *name)
-{
- push_item(((autoindex_config_rec *) d)->hdr_list, 0, NULL, cmd->path,
- name);
- return NULL;
-}
-
-static const char *add_readme(cmd_parms *cmd, void *d, const char *name)
-{
- push_item(((autoindex_config_rec *) d)->rdme_list, 0, NULL, cmd->path,
- name);
- return NULL;
-}
-
-/* A legacy directive, FancyIndexing is superseded by the IndexOptions
- * keyword. But for compatibility..
- */
-static const char *fancy_indexing(cmd_parms *cmd, void *d, int arg)
-{
- int curopts;
- int newopts;
- autoindex_config_rec *cfg;
-
- cfg = (autoindex_config_rec *) d;
- curopts = cfg->opts;
- if (curopts & NO_OPTIONS) {
- return "FancyIndexing directive conflicts with existing "
- "IndexOptions None";
- }
- newopts = (arg ? (curopts | FANCY_INDEXING) : (curopts & ~FANCY_INDEXING));
- cfg->opts = newopts;
- return NULL;
-}
-
-static const char *add_opts(cmd_parms *cmd, void *d, const char *optstr)
-{
- char *w;
- int opts;
- int opts_add;
- int opts_remove;
- char action;
- autoindex_config_rec *d_cfg = (autoindex_config_rec *) d;
-
- opts = d_cfg->opts;
- opts_add = d_cfg->incremented_opts;
- opts_remove = d_cfg->decremented_opts;
- while (optstr[0]) {
- int option = 0;
-
- w = ap_getword_conf(cmd->pool, &optstr);
- if ((*w == '+') || (*w == '-')) {
- action = *(w++);
- }
- else {
- action = '\0';
- }
- if (!strcasecmp(w, "FancyIndexing")) {
- option = FANCY_INDEXING;
- }
- else if (!strcasecmp(w, "IconsAreLinks")) {
- option = ICONS_ARE_LINKS;
- }
- else if (!strcasecmp(w, "ScanHTMLTitles")) {
- option = SCAN_HTML_TITLES;
- }
- else if (!strcasecmp(w, "SuppressLastModified")) {
- option = SUPPRESS_LAST_MOD;
- }
- else if (!strcasecmp(w, "SuppressSize")) {
- option = SUPPRESS_SIZE;
- }
- else if (!strcasecmp(w, "SuppressDescription")) {
- option = SUPPRESS_DESC;
- }
- else if (!strcasecmp(w, "SuppressHTMLPreamble")) {
- option = SUPPRESS_PREAMBLE;
- }
- else if (!strcasecmp(w, "SuppressColumnSorting")) {
- option = SUPPRESS_COLSORT;
- }
- else if (!strcasecmp(w, "VersionSort")) {
- option = VERSION_SORT;
- }
- else if (!strcasecmp(w, "None")) {
- if (action != '\0') {
- return "Cannot combine '+' or '-' with 'None' keyword";
- }
- opts = NO_OPTIONS;
- opts_add = 0;
- opts_remove = 0;
- }
- else if (!strcasecmp(w, "IconWidth")) {
- if (action != '-') {
- d_cfg->icon_width = DEFAULT_ICON_WIDTH;
- }
- else {
- d_cfg->icon_width = 0;
- }
- }
- else if (!strncasecmp(w, "IconWidth=", 10)) {
- if (action == '-') {
- return "Cannot combine '-' with IconWidth=n";
- }
- d_cfg->icon_width = atoi(&w[10]);
- }
- else if (!strcasecmp(w, "IconHeight")) {
- if (action != '-') {
- d_cfg->icon_height = DEFAULT_ICON_HEIGHT;
- }
- else {
- d_cfg->icon_height = 0;
- }
- }
- else if (!strncasecmp(w, "IconHeight=", 11)) {
- if (action == '-') {
- return "Cannot combine '-' with IconHeight=n";
- }
- d_cfg->icon_height = atoi(&w[11]);
- }
- else if (!strcasecmp(w, "NameWidth")) {
- if (action != '-') {
- return "NameWidth with no value may only appear as "
- "'-NameWidth'";
- }
- d_cfg->name_width = DEFAULT_NAME_WIDTH;
- d_cfg->name_adjust = K_NOADJUST;
- }
- else if (!strncasecmp(w, "NameWidth=", 10)) {
- if (action == '-') {
- return "Cannot combine '-' with NameWidth=n";
- }
- if (w[10] == '*') {
- d_cfg->name_adjust = K_ADJUST;
- }
- else {
- int width = atoi(&w[10]);
-
- if (width < 5) {
- return "NameWidth value must be greater than 5";
- }
- d_cfg->name_width = width;
- d_cfg->name_adjust = K_NOADJUST;
- }
- }
- else {
- return "Invalid directory indexing option";
- }
- if (action == '\0') {
- opts |= option;
- opts_add = 0;
- opts_remove = 0;
- }
- else if (action == '+') {
- opts_add |= option;
- opts_remove &= ~option;
- }
- else {
- opts_remove |= option;
- opts_add &= ~option;
- }
- }
- if ((opts & NO_OPTIONS) && (opts & ~NO_OPTIONS)) {
- return "Cannot combine other IndexOptions keywords with 'None'";
- }
- d_cfg->incremented_opts = opts_add;
- d_cfg->decremented_opts = opts_remove;
- d_cfg->opts = opts;
- return NULL;
-}
-
-static const char *set_default_order(cmd_parms *cmd, void *m, const char *direction,
- const char *key)
-{
- char temp[4];
- autoindex_config_rec *d_cfg = (autoindex_config_rec *) m;
-
- apr_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 = apr_palloc(cmd->pool, 4);
- d_cfg->default_order[3] = '\0';
- }
- apr_cpystrn(d_cfg->default_order, temp, sizeof(temp));
- return NULL;
-}
-
-#define DIR_CMD_PERMS OR_INDEXES
-
-static const command_rec autoindex_cmds[] =
-{
- AP_INIT_ITERATE2("AddIcon", add_icon, BY_PATH, DIR_CMD_PERMS,
- "an icon URL followed by one or more filenames"),
- AP_INIT_ITERATE2("AddIconByType", add_icon, BY_TYPE, DIR_CMD_PERMS,
- "an icon URL followed by one or more MIME types"),
- AP_INIT_ITERATE2("AddIconByEncoding", add_icon, BY_ENCODING, DIR_CMD_PERMS,
- "an icon URL followed by one or more content encodings"),
- AP_INIT_ITERATE2("AddAlt", add_alt, BY_PATH, DIR_CMD_PERMS,
- "alternate descriptive text followed by one or more filenames"),
- AP_INIT_ITERATE2("AddAltByType", add_alt, BY_TYPE, DIR_CMD_PERMS,
- "alternate descriptive text followed by one or more MIME types"),
- AP_INIT_ITERATE2("AddAltByEncoding", add_alt, BY_ENCODING, DIR_CMD_PERMS,
- "alternate descriptive text followed by one or more content encodings"),
- AP_INIT_RAW_ARGS("IndexOptions", add_opts, NULL, DIR_CMD_PERMS,
- "one or more index options"),
- AP_INIT_TAKE2("IndexOrderDefault", set_default_order, NULL, DIR_CMD_PERMS,
- "{Ascending,Descending} {Name,Size,Description,Date}"),
- AP_INIT_ITERATE("IndexIgnore", add_ignore, NULL, DIR_CMD_PERMS,
- "one or more file extensions"),
- AP_INIT_ITERATE2("AddDescription", add_desc, BY_PATH, DIR_CMD_PERMS,
- "Descriptive text followed by one or more filenames"),
- AP_INIT_TAKE1("HeaderName", add_header, NULL, DIR_CMD_PERMS,
- "a filename"),
- AP_INIT_TAKE1("ReadmeName", add_readme, NULL, DIR_CMD_PERMS,
- "a filename"),
- AP_INIT_FLAG("FancyIndexing", fancy_indexing, NULL, DIR_CMD_PERMS,
- "Limited to 'on' or 'off' (superseded by IndexOptions FancyIndexing)"),
- AP_INIT_TAKE1("DefaultIcon", ap_set_string_slot,
- (void *) XtOffsetOf(autoindex_config_rec, default_icon),
- DIR_CMD_PERMS, "an icon URL"),
- {NULL}
-};
-
-static void *create_autoindex_config(apr_pool_t *p, char *dummy)
-{
- autoindex_config_rec *new =
- (autoindex_config_rec *) apr_pcalloc(p, sizeof(autoindex_config_rec));
-
- new->icon_width = 0;
- new->icon_height = 0;
- new->name_width = DEFAULT_NAME_WIDTH;
- new->name_adjust = K_UNSET;
- new->icon_list = apr_array_make(p, 4, sizeof(struct item));
- new->alt_list = apr_array_make(p, 4, sizeof(struct item));
- new->desc_list = apr_array_make(p, 4, sizeof(ai_desc_t));
- new->ign_list = apr_array_make(p, 4, sizeof(struct item));
- new->hdr_list = apr_array_make(p, 4, sizeof(struct item));
- new->rdme_list = apr_array_make(p, 4, sizeof(struct item));
- new->opts = 0;
- new->incremented_opts = 0;
- new->decremented_opts = 0;
- new->default_order = NULL;
-
- return (void *) new;
-}
-
-static void *merge_autoindex_configs(apr_pool_t *p, void *basev, void *addv)
-{
- autoindex_config_rec *new;
- autoindex_config_rec *base = (autoindex_config_rec *) basev;
- autoindex_config_rec *add = (autoindex_config_rec *) addv;
-
- new = (autoindex_config_rec *) apr_pcalloc(p, sizeof(autoindex_config_rec));
- new->default_icon = add->default_icon ? add->default_icon
- : base->default_icon;
- new->icon_height = add->icon_height ? add->icon_height : base->icon_height;
- new->icon_width = add->icon_width ? add->icon_width : base->icon_width;
-
- new->alt_list = apr_array_append(p, add->alt_list, base->alt_list);
- new->ign_list = apr_array_append(p, add->ign_list, base->ign_list);
- new->hdr_list = apr_array_append(p, add->hdr_list, base->hdr_list);
- new->desc_list = apr_array_append(p, add->desc_list, base->desc_list);
- new->icon_list = apr_array_append(p, add->icon_list, base->icon_list);
- new->rdme_list = apr_array_append(p, add->rdme_list, base->rdme_list);
- if (add->opts & NO_OPTIONS) {
- /*
- * If the current directory says 'no options' then we also
- * clear any incremental mods from being inheritable further down.
- */
- new->opts = NO_OPTIONS;
- new->incremented_opts = 0;
- new->decremented_opts = 0;
- }
- else {
- /*
- * If there were any nonincremental options selected for
- * this directory, they dominate and we don't inherit *anything.*
- * Contrariwise, we *do* inherit if the only settings here are
- * incremental ones.
- */
- if (add->opts == 0) {
- new->incremented_opts = (base->incremented_opts
- | add->incremented_opts)
- & ~add->decremented_opts;
- new->decremented_opts = (base->decremented_opts
- | add->decremented_opts);
- /*
- * We may have incremental settings, so make sure we don't
- * inadvertently inherit an IndexOptions None from above.
- */
- new->opts = (base->opts & ~NO_OPTIONS);
- }
- else {
- /*
- * There are local nonincremental settings, which clear
- * all inheritance from above. They *are* the new base settings.
- */
- new->opts = add->opts;;
- }
- /*
- * We're guaranteed that there'll be no overlap between
- * the add-options and the remove-options.
- */
- new->opts |= new->incremented_opts;
- new->opts &= ~new->decremented_opts;
- }
- /*
- * Inherit the NameWidth settings if there aren't any specific to
- * the new location; otherwise we'll end up using the defaults set in the
- * config-rec creation routine.
- */
- if (add->name_adjust == K_UNSET) {
- new->name_width = base->name_width;
- new->name_adjust = base->name_adjust;
- }
- else {
- new->name_width = add->name_width;
- new->name_adjust = add->name_adjust;
- }
-
- new->default_order = (add->default_order != NULL)
- ? add->default_order : base->default_order;
- return new;
-}
-
-/****************************************************************
- *
- * Looking things up in config entries...
- */
-
-/* Structure used to hold entries when we're actually building an index */
-
-struct ent {
- char *name;
- char *icon;
- char *alt;
- char *desc;
- off_t size;
- apr_time_t lm;
- struct ent *next;
- int ascending, version_sort;
- char key;
-};
-
-static char *find_item(request_rec *r, apr_array_header_t *list, int path_only)
-{
- const char *content_type = ap_field_noparam(r->pool, r->content_type);
- const char *content_encoding = r->content_encoding;
- char *path = r->filename;
-
- struct item *items = (struct item *) list->elts;
- int i;
-
- for (i = 0; i < list->nelts; ++i) {
- struct item *p = &items[i];
-
- /* Special cased for ^^DIRECTORY^^ and ^^BLANKICON^^ */
- if ((path[0] == '^') || (!ap_strcmp_match(path, p->apply_path))) {
- if (!*(p->apply_to)) {
- return p->data;
- }
- else if (p->type == BY_PATH || path[0] == '^') {
- if (!ap_strcmp_match(path, p->apply_to)) {
- return p->data;
- }
- }
- else if (!path_only) {
- if (!content_encoding) {
- if (p->type == BY_TYPE) {
- if (content_type
- && !ap_strcasecmp_match(content_type,
- p->apply_to)) {
- return p->data;
- }
- }
- }
- else {
- if (p->type == BY_ENCODING) {
- if (!ap_strcasecmp_match(content_encoding,
- p->apply_to)) {
- return p->data;
- }
- }
- }
- }
- }
- }
- return NULL;
-}
-
-#define find_icon(d,p,t) find_item(p,d->icon_list,t)
-#define find_alt(d,p,t) find_item(p,d->alt_list,t)
-#define find_header(d,p) find_item(p,d->hdr_list,0)
-#define find_readme(d,p) find_item(p,d->rdme_list,0)
-
-static char *find_default_icon(autoindex_config_rec *d, char *bogus_name)
-{
- request_rec r;
-
- /* Bleah. I tried to clean up find_item, and it lead to this bit
- * of ugliness. Note that the fields initialized are precisely
- * those that find_item looks at...
- */
-
- r.filename = bogus_name;
- r.content_type = r.content_encoding = NULL;
-
- return find_item(&r, d->icon_list, 1);
-}
-
-/*
- * Look through the list of pattern/description pairs and return the first one
- * if any) that matches the filename in the request. If multiple patterns
- * match, only the first one is used; since the order in the array is the
- * same as the order in which directives were processed, earlier matching
- * directives will dominate.
- */
-
-#ifdef CASE_BLIND_FILESYSTEM
-#define MATCH_FLAGS FNM_CASE_BLIND
-#else
-#define MATCH_FLAGS 0
-#endif
-
-static char *find_desc(autoindex_config_rec *dcfg, request_rec *r)
-{
- int i;
- ai_desc_t *list = (ai_desc_t *) dcfg->desc_list->elts;
- const char *filename_full = r->filename;
- const char *filename_only;
- const char *filename;
-
- /*
- * If the filename includes a path, extract just the name itself
- * for the simple matches.
- */
- if ((filename_only = ap_strrchr_c(filename_full, '/')) == NULL) {
- filename_only = filename_full;
- }
- else {
- filename_only++;
- }
- for (i = 0; i < dcfg->desc_list->nelts; ++i) {
- ai_desc_t *tuple = &list[i];
- int found;
-
- /*
- * Only use the full-path filename if the pattern contains '/'s.
- */
- filename = (tuple->full_path) ? filename_full : filename_only;
- /*
- * Make the comparison using the cheapest method; only do
- * wildcard checking if we must.
- */
- if (tuple->wildcards) {
- found = (apr_fnmatch(tuple->pattern, filename, MATCH_FLAGS) == 0);
- }
- else {
- found = (ap_strstr_c(filename, tuple->pattern) != NULL);
- }
- if (found) {
- return tuple->description;
- }
- }
- return NULL;
-}
-
-static int ignore_entry(autoindex_config_rec *d, char *path)
-{
- apr_array_header_t *list = d->ign_list;
- struct item *items = (struct item *) list->elts;
- char *tt;
- int i;
-
- if ((tt = strrchr(path, '/')) == NULL) {
- tt = path;
- }
- else {
- tt++;
- }
-
- for (i = 0; i < list->nelts; ++i) {
- struct item *p = &items[i];
- char *ap;
-
- if ((ap = strrchr(p->apply_to, '/')) == NULL) {
- ap = p->apply_to;
- }
- else {
- ap++;
- }
-
-#ifndef CASE_BLIND_FILESYSTEM
- if (!ap_strcmp_match(path, p->apply_path)
- && !ap_strcmp_match(tt, ap)) {
- return 1;
- }
-#else /* !CASE_BLIND_FILESYSTEM */
- /*
- * On some platforms, the match must be case-blind. This is really
- * a factor of the filesystem involved, but we can't detect that
- * reliably - so we have to granularise at the OS level.
- */
- if (!ap_strcasecmp_match(path, p->apply_path)
- && !ap_strcasecmp_match(tt, ap)) {
- return 1;
- }
-#endif /* !CASE_BLIND_FILESYSTEM */
- }
- return 0;
-}
-
-/*****************************************************************
- *
- * Actually generating output
- */
-
-/*
- * Elements of the emitted document:
- * Preamble
- * Emitted unless SUPPRESS_PREAMBLE is set AND ap_run_sub_req
- * succeeds for the (content_type == text/html) header file.
- * Header file
- * Emitted if found (and able).
- * H1 tag line
- * Emitted if a header file is NOT emitted.
- * Directory stuff
- * Always emitted.
- * HR
- * Emitted if FANCY_INDEXING is set.
- * Readme file
- * Emitted if found (and able).
- * ServerSig
- * Emitted if ServerSignature is not Off AND a readme file
- * is NOT emitted.
- * Postamble
- * Emitted unless SUPPRESS_PREAMBLE is set AND ap_run_sub_req
- * succeeds for the (content_type == text/html) readme file.
- */
-
-
-/*
- * emit a plain text file
- */
-static void do_emit_plain(request_rec *r, apr_file_t *f)
-{
- char buf[AP_IOBUFSIZE + 1];
- int i, c, ch;
- apr_size_t n;
- apr_status_t stat;
-
- ap_rputs("<PRE>\n", r);
- while (!apr_file_eof(f)) {
- do {
- n = sizeof(char) * AP_IOBUFSIZE;
- stat = apr_file_read(f, buf, &n);
- }
- while (stat != APR_SUCCESS && APR_STATUS_IS_EINTR(stat));
- if (n == -1 || n == 0) {
- break;
- }
- buf[n] = '\0';
- c = 0;
- while (c < n) {
- for (i = c; i < n; i++) {
- if (buf[i] == '<' || buf[i] == '>' || buf[i] == '&') {
- break;
- }
- }
- ch = buf[i];
- buf[i] = '\0';
- ap_rputs(&buf[c], r);
- if (ch == '<') {
- ap_rputs("&lt;", r);
- }
- else if (ch == '>') {
- ap_rputs("&gt;", r);
- }
- else if (ch == '&') {
- ap_rputs("&amp;", r);
- }
- c = i + 1;
- }
- }
- ap_rputs("</PRE>\n", r);
-}
-
-/*
- * Handle the preamble through the H1 tag line, inclusive. Locate
- * the file with a subrequests. Process text/html documents by actually
- * running the subrequest; text/xxx documents get copied verbatim,
- * and any other content type is ignored. This means that a non-text
- * document (such as HEADER.gif) might get multiviewed as the result
- * instead of a text document, meaning nothing will be displayed, but
- * oh well.
- */
-static void emit_head(request_rec *r, char *header_fname, int suppress_amble,
- char *title)
-{
- apr_file_t *f = NULL;
- request_rec *rr = NULL;
- int emit_amble = 1;
- int emit_H1 = 1;
-
- /*
- * If there's a header file, send a subrequest to look for it. If it's
- * found and a text file, handle it -- otherwise fall through and
- * pretend there's nothing there.
- */
- if ((header_fname != NULL)
- && (rr = ap_sub_req_lookup_uri(header_fname, r, NULL))
- && (rr->status == HTTP_OK)
- && (rr->filename != NULL)
- && rr->finfo.filetype == APR_REG) {
- /*
- * Check for the two specific cases we allow: text/html and
- * text/anything-else. The former is allowed to be processed for
- * SSIs.
- */
- if (rr->content_type != NULL) {
- if (!strcasecmp(ap_field_noparam(r->pool, rr->content_type),
- "text/html")) {
- /* Hope everything will work... */
- emit_amble = 0;
- emit_H1 = 0;
-
- if (! suppress_amble) {
- emit_preamble(r, title);
- }
- /*
- * If there's a problem running the subrequest, display the
- * preamble if we didn't do it before -- the header file
- * didn't get displayed.
- */
- if (ap_run_sub_req(rr) != OK) {
- /* It didn't work */
- emit_amble = suppress_amble;
- emit_H1 = 1;
- }
- }
- else if (!strncasecmp("text/", rr->content_type, 5)) {
- /*
- * If we can open the file, prefix it with the preamble
- * regardless; since we'll be sending a <PRE> block around
- * the file's contents, any HTML header it had won't end up
- * where it belongs.
- */
- if (apr_file_open(&f, rr->filename, APR_READ,
- APR_OS_DEFAULT, r->pool) == APR_SUCCESS) {
- emit_preamble(r, title);
- emit_amble = 0;
- do_emit_plain(r, f);
- apr_file_close(f);
- emit_H1 = 0;
- }
- }
- }
- }
-
- if (emit_amble) {
- emit_preamble(r, title);
- }
- if (emit_H1) {
- ap_rvputs(r, "<H1>Index of ", title, "</H1>\n", NULL);
- }
- if (rr != NULL) {
- ap_destroy_sub_req(rr);
- }
-}
-
-
-/*
- * Handle the Readme file through the postamble, inclusive. Locate
- * the file with a subrequests. Process text/html documents by actually
- * running the subrequest; text/xxx documents get copied verbatim,
- * and any other content type is ignored. This means that a non-text
- * document (such as FOOTER.gif) might get multiviewed as the result
- * instead of a text document, meaning nothing will be displayed, but
- * oh well.
- */
-static void emit_tail(request_rec *r, char *readme_fname, int suppress_amble)
-{
- apr_file_t *f = NULL;
- request_rec *rr = NULL;
- int suppress_post = 0;
- int suppress_sig = 0;
-
- /*
- * If there's a readme file, send a subrequest to look for it. If it's
- * found and a text file, handle it -- otherwise fall through and
- * pretend there's nothing there.
- */
- if ((readme_fname != NULL)
- && (rr = ap_sub_req_lookup_uri(readme_fname, r, NULL))
- && (rr->status == HTTP_OK)
- && (rr->filename != NULL)
- && rr->finfo.filetype == APR_REG) {
- /*
- * Check for the two specific cases we allow: text/html and
- * text/anything-else. The former is allowed to be processed for
- * SSIs.
- */
- if (rr->content_type != NULL) {
- if (!strcasecmp(ap_field_noparam(r->pool, rr->content_type),
- "text/html")) {
- if (ap_run_sub_req(rr) == OK) {
- /* worked... */
- suppress_sig = 1;
- suppress_post = suppress_amble;
- }
- }
- else if (!strncasecmp("text/", rr->content_type, 5)) {
- /*
- * If we can open the file, suppress the signature.
- */
- if (apr_file_open(&f, rr->filename, APR_READ,
- APR_OS_DEFAULT, r->pool) == APR_SUCCESS) {
- do_emit_plain(r, f);
- apr_file_close(f);
- suppress_sig = 1;
- }
- }
- }
- }
-
- if (!suppress_sig) {
- ap_rputs(ap_psignature("", r), r);
- }
- if (!suppress_post) {
- ap_rputs("</BODY></HTML>\n", r);
- }
- if (rr != NULL) {
- ap_destroy_sub_req(rr);
- }
-}
-
-
-static char *find_title(request_rec *r)
-{
- char titlebuf[MAX_STRING_LEN], *find = "<TITLE>";
- apr_file_t *thefile = NULL;
- int x, y, p;
- apr_size_t n;
-
- if (r->status != HTTP_OK) {
- return NULL;
- }
- if ((r->content_type != NULL)
- && (!strcasecmp(ap_field_noparam(r->pool, r->content_type),
- "text/html")
- || !strcmp(r->content_type, INCLUDES_MAGIC_TYPE))
- && !r->content_encoding) {
- if (apr_file_open(&thefile, r->filename, APR_READ,
- APR_OS_DEFAULT, r->pool) != APR_SUCCESS) {
- return NULL;
- }
- n = sizeof(char) * (MAX_STRING_LEN - 1);
- apr_file_read(thefile, titlebuf, &n);
- if (n <= 0) {
- apr_file_close(thefile);
- return NULL;
- }
- titlebuf[n] = '\0';
- for (x = 0, p = 0; titlebuf[x]; x++) {
- if (apr_toupper(titlebuf[x]) == find[p]) {
- if (!find[++p]) {
- if ((p = ap_ind(&titlebuf[++x], '<')) != -1) {
- titlebuf[x + p] = '\0';
- }
- /* Scan for line breaks for Tanmoy's secretary */
- for (y = x; titlebuf[y]; y++) {
- if ((titlebuf[y] == CR) || (titlebuf[y] == LF)) {
- if (y == x) {
- x++;
- }
- else {
- titlebuf[y] = ' ';
- }
- }
- }
- apr_file_close(thefile);
- return apr_pstrdup(r->pool, &titlebuf[x]);
- }
- }
- else {
- p = 0;
- }
- }
- apr_file_close(thefile);
- }
- return NULL;
-}
-
-static struct ent *make_autoindex_entry(const char *name, int autoindex_opts,
- autoindex_config_rec *d,
- request_rec *r, char keyid,
- char direction)
-{
- struct ent *p;
-
- if ((name[0] == '.') && (!name[1])) {
- return (NULL);
- }
-
- if (ignore_entry(d, ap_make_full_path(r->pool, r->filename, name))) {
- return (NULL);
- }
-
- p = (struct ent *) apr_pcalloc(r->pool, sizeof(struct ent));
- p->name = apr_pstrdup(r->pool, name);
- p->size = -1;
- p->icon = NULL;
- p->alt = NULL;
- p->desc = NULL;
- p->lm = -1;
- p->key = apr_toupper(keyid);
- p->ascending = (apr_toupper(direction) == D_ASCENDING);
- p->version_sort = autoindex_opts & VERSION_SORT;
-
- if (autoindex_opts & FANCY_INDEXING) {
- request_rec *rr = ap_sub_req_lookup_file(name, r, NULL);
-
- if (rr->finfo.filetype != 0) {
- p->lm = rr->finfo.mtime;
- if (rr->finfo.filetype == APR_DIR) {
- if (!(p->icon = find_icon(d, rr, 1))) {
- p->icon = find_default_icon(d, "^^DIRECTORY^^");
- }
- if (!(p->alt = find_alt(d, rr, 1))) {
- p->alt = "DIR";
- }
- p->size = -1;
- p->name = apr_pstrcat(r->pool, name, "/", NULL);
- }
- else {
- p->icon = find_icon(d, rr, 0);
- p->alt = find_alt(d, rr, 0);
- p->size = rr->finfo.size;
- }
- }
-
- p->desc = find_desc(d, rr);
-
- if ((!p->desc) && (autoindex_opts & SCAN_HTML_TITLES)) {
- p->desc = apr_pstrdup(r->pool, find_title(rr));
- }
-
- ap_destroy_sub_req(rr);
- }
- /*
- * We don't need to take any special action for the file size key. If
- * we did, it would go here.
- */
- if (keyid == K_LAST_MOD) {
- if (p->lm < 0) {
- p->lm = 0;
- }
- }
- return (p);
-}
-
-static char *terminate_description(autoindex_config_rec *d, char *desc,
- int autoindex_opts)
-{
- int maxsize = 23;
- register int x;
-
- if (autoindex_opts & SUPPRESS_LAST_MOD) {
- maxsize += 19;
- }
- if (autoindex_opts & SUPPRESS_SIZE) {
- maxsize += 7;
- }
-
- for (x = 0; desc[x] && (maxsize > 0 || desc[x]=='<'); x++) {
- if (desc[x] == '<') {
- while (desc[x] != '>') {
- if (!desc[x]) {
- maxsize = 0;
- break;
- }
- ++x;
- }
- }
- else if (desc[x] == '&') {
- /* entities like &auml; count as one character */
- --maxsize;
- for ( ; desc[x] != ';'; ++x) {
- if (desc[x] == '\0') {
- maxsize = 0;
- break;
- }
- }
- }
- else {
- --maxsize;
- }
- }
- if (!maxsize && desc[x] != '\0') {
- desc[x - 1] = '>'; /* Grump. */
- desc[x] = '\0'; /* Double Grump! */
- }
- return desc;
-}
-
-/*
- * Emit the anchor for the specified field. If a field is the key for the
- * current request, the link changes its meaning to reverse the order when
- * selected again. Non-active fields always start in ascending order.
- */
-static void emit_link(request_rec *r, char *anchor, char fname, char curkey,
- char curdirection, int nosort)
-{
- char qvalue[5];
- int reverse;
-
- if (!nosort) {
- qvalue[0] = '?';
- qvalue[1] = fname;
- qvalue[2] = '=';
- qvalue[4] = '\0';
- reverse = ((curkey == fname) && (curdirection == D_ASCENDING));
- qvalue[3] = reverse ? D_DESCENDING : D_ASCENDING;
- ap_rvputs(r, "<A HREF=\"", qvalue, "\">", anchor, "</A>", NULL);
- }
- else {
- ap_rputs(anchor, r);
- }
-}
-
-static void output_directories(struct ent **ar, int n,
- autoindex_config_rec *d, request_rec *r,
- int autoindex_opts, char keyid, char direction)
-{
- int x;
- apr_size_t rv;
- char *name = r->uri;
- char *tp;
- int static_columns = (autoindex_opts & SUPPRESS_COLSORT);
- apr_pool_t *scratch;
- int name_width;
- char *name_scratch;
- char *pad_scratch;
-
- apr_pool_create(&scratch, r->pool);
- if (name[0] == '\0') {
- name = "/";
- }
-
- name_width = d->name_width;
- if (d->name_adjust == K_ADJUST) {
- for (x = 0; x < n; x++) {
- int t = strlen(ar[x]->name);
- if (t > name_width) {
- name_width = t;
- }
- }
- }
- name_scratch = apr_palloc(r->pool, name_width + 1);
- pad_scratch = apr_palloc(r->pool, name_width + 1);
- memset(pad_scratch, ' ', name_width);
- pad_scratch[name_width] = '\0';
-
- if (autoindex_opts & FANCY_INDEXING) {
- ap_rputs("<PRE>", r);
- if ((tp = find_default_icon(d, "^^BLANKICON^^"))) {
- ap_rvputs(r, "<IMG SRC=\"", ap_escape_html(scratch, tp),
- "\" ALT=\" \"", NULL);
- if (d->icon_width && d->icon_height) {
- ap_rprintf
- (
- r,
- " HEIGHT=\"%d\" WIDTH=\"%d\"",
- d->icon_height,
- d->icon_width
- );
- }
- ap_rputs("> ", r);
- }
- emit_link(r, "Name", K_NAME, keyid, direction, static_columns);
- ap_rputs(pad_scratch + 4, r);
- /*
- * Emit the guaranteed-at-least-one-space-between-columns byte.
- */
- ap_rputs(" ", r);
- if (!(autoindex_opts & SUPPRESS_LAST_MOD)) {
- emit_link(r, "Last modified", K_LAST_MOD, keyid, direction,
- static_columns);
- ap_rputs(" ", r);
- }
- if (!(autoindex_opts & SUPPRESS_SIZE)) {
- emit_link(r, "Size", K_SIZE, keyid, direction, static_columns);
- ap_rputs(" ", r);
- }
- if (!(autoindex_opts & SUPPRESS_DESC)) {
- emit_link(r, "Description", K_DESC, keyid, direction,
- static_columns);
- }
- ap_rputs("\n<HR>\n", r);
- }
- else {
- ap_rputs("<UL>", r);
- }
-
- for (x = 0; x < n; x++) {
- char *anchor, *t, *t2;
- int nwidth;
-
- apr_pool_clear(scratch);
-
- if (is_parent(ar[x]->name)) {
- t = ap_make_full_path(scratch, name, "../");
- ap_getparents(t);
- if (t[0] == '\0') {
- t = "/";
- }
- t2 = "Parent Directory";
- anchor = ap_escape_html(scratch, ap_os_escape_path(scratch, t, 0));
- }
- else {
- t = ar[x]->name;
- t2 = t;
- anchor = ap_escape_html(scratch, ap_os_escape_path(scratch, t, 0));
- }
-
- if (autoindex_opts & FANCY_INDEXING) {
- if (autoindex_opts & ICONS_ARE_LINKS) {
- ap_rvputs(r, "<A HREF=\"", anchor, "\">", NULL);
- }
- if ((ar[x]->icon) || d->default_icon) {
- ap_rvputs(r, "<IMG SRC=\"",
- ap_escape_html(scratch,
- ar[x]->icon ? ar[x]->icon
- : d->default_icon),
- "\" ALT=\"[", (ar[x]->alt ? ar[x]->alt : " "),
- "]\"", NULL);
- if (d->icon_width && d->icon_height) {
- ap_rprintf(r, " HEIGHT=\"%d\" WIDTH=\"%d\"",
- d->icon_height, d->icon_width);
- }
- ap_rputs(">", r);
- }
- if (autoindex_opts & ICONS_ARE_LINKS) {
- ap_rputs("</A>", r);
- }
-
- nwidth = strlen(t2);
- if (nwidth > name_width) {
- memcpy(name_scratch, t2, name_width - 3);
- name_scratch[name_width - 3] = '.';
- name_scratch[name_width - 2] = '.';
- name_scratch[name_width - 1] = '>';
- name_scratch[name_width] = 0;
- t2 = name_scratch;
- nwidth = name_width;
- }
- ap_rvputs(r, " <A HREF=\"", anchor, "\">",
- ap_escape_html(scratch, t2), "</A>", pad_scratch + nwidth,
- NULL);
- /*
- * The blank before the storm.. er, before the next field.
- */
- ap_rputs(" ", r);
- if (!(autoindex_opts & SUPPRESS_LAST_MOD)) {
- if (ar[x]->lm != -1) {
- char time_str[MAX_STRING_LEN];
- apr_exploded_time_t ts;
- apr_explode_localtime(&ts, ar[x]->lm);
- apr_strftime(time_str, &rv, MAX_STRING_LEN,
- "%d-%b-%Y %H:%M ", &ts);
- ap_rputs(time_str, r);
- }
- else {
- /*Length="22-Feb-1998 23:42 " (see 4 lines above) */
- ap_rputs(" ", r);
- }
- }
- if (!(autoindex_opts & SUPPRESS_SIZE)) {
- ap_send_size(ar[x]->size, r);
- ap_rputs(" ", r);
- }
- if (!(autoindex_opts & SUPPRESS_DESC)) {
- if (ar[x]->desc) {
- ap_rputs(terminate_description(d, ar[x]->desc,
- autoindex_opts), r);
- }
- }
- }
- else {
- ap_rvputs(r, "<LI><A HREF=\"", anchor, "\"> ", t2,
- "</A>", NULL);
- }
- ap_rputc('\n', r);
- }
- if (autoindex_opts & FANCY_INDEXING) {
- ap_rputs("</PRE>", r);
- }
- else {
- ap_rputs("</UL>", r);
- }
-}
-
-/*
- * Compare two file entries according to the sort criteria. The return
- * is essentially a signum function value.
- */
-
-static int dsortf(struct ent **e1, struct ent **e2)
-{
- struct ent *c1;
- struct ent *c2;
- int result = 0;
-
- /*
- * First, see if either of the entries is for the parent directory.
- * If so, that *always* sorts lower than anything else.
- */
- if (is_parent((*e1)->name)) {
- return -1;
- }
- if (is_parent((*e2)->name)) {
- return 1;
- }
- /*
- * All of our comparisons will be of the c1 entry against the c2 one,
- * so assign them appropriately to take care of the ordering.
- */
- if ((*e1)->ascending) {
- c1 = *e1;
- c2 = *e2;
- }
- else {
- c1 = *e2;
- c2 = *e1;
- }
-
- switch (c1->key) {
- case K_LAST_MOD:
- if (c1->lm > c2->lm) {
- return 1;
- }
- else if (c1->lm < c2->lm) {
- return -1;
- }
- break;
- case K_SIZE:
- if (c1->size > c2->size) {
- return 1;
- }
- else if (c1->size < c2->size) {
- return -1;
- }
- break;
- case K_DESC:
- if (c1->version_sort)
- result = apr_strnatcmp(c1->desc ? c1->desc : "", c2->desc ? c2->desc : "");
- else
- result = strcmp(c1->desc ? c1->desc : "", c2->desc ? c2->desc : "");
- if (result) {
- return result;
- }
- break;
- }
- if (c1->version_sort)
- return apr_strnatcmp(c1->name, c2->name);
- else
- return strcmp(c1->name, c2->name);
-}
-
-
-static int index_directory(request_rec *r,
- autoindex_config_rec *autoindex_conf)
-{
- char *title_name = ap_escape_html(r->pool, r->uri);
- char *title_endp;
- char *name = r->filename;
- apr_finfo_t dirent;
- apr_dir_t *thedir;
- apr_status_t status;
- int num_ent = 0, x;
- struct ent *head, *p;
- struct ent **ar = NULL;
- const char *qstring;
- int autoindex_opts = autoindex_conf->opts;
- char keyid;
- char direction;
-
- if ((status = apr_dir_open(&thedir, name, r->pool)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r,
- "Can't open directory for index: %s", r->filename);
- return HTTP_FORBIDDEN;
- }
-
-#if APR_HAS_UNICODE_FS
- r->content_type = "text/html;charset=utf-8";
-#else
- r->content_type = "text/html";
-#endif
- ap_update_mtime(r, r->finfo.mtime);
- ap_set_last_modified(r);
- ap_set_etag(r);
-
- if (r->header_only) {
- apr_dir_close(thedir);
- return 0;
- }
-
- /* Spew HTML preamble */
-
- title_endp = title_name + strlen(title_name) - 1;
-
- while (title_endp > title_name && *title_endp == '/') {
- *title_endp-- = '\0';
- }
-
- emit_head(r, find_header(autoindex_conf, r),
- autoindex_opts & SUPPRESS_PREAMBLE, title_name);
-
- /*
- * Figure out what sort of indexing (if any) we're supposed to use.
- *
- * If no QUERY_STRING was specified or column sorting has been
- * explicitly disabled, we use the default specified by the
- * IndexOrderDefault directive (if there is one); otherwise,
- * we fall back to ascending by name.
- */
- qstring = r->args;
- if ((autoindex_opts & SUPPRESS_COLSORT)
- || ((qstring == NULL) || (*qstring == '\0'))) {
- qstring = autoindex_conf->default_order;
- }
- /*
- * If there is no specific ordering defined for this directory,
- * default to ascending by filename.
- */
- if ((qstring == NULL) || (*qstring == '\0')) {
- keyid = K_NAME;
- direction = D_ASCENDING;
- }
- else {
- keyid = *qstring;
- ap_getword(r->pool, &qstring, '=');
- if (qstring != '\0') {
- direction = *qstring;
- }
- else {
- direction = D_ASCENDING;
- }
- }
-
- /*
- * Since we don't know how many dir. entries there are, put them into a
- * linked list and then arrayificate them so qsort can use them.
- */
- head = NULL;
- while (apr_dir_read(&dirent, APR_FINFO_DIRENT, thedir) == APR_SUCCESS) {
- p = make_autoindex_entry(dirent.name, autoindex_opts,
- autoindex_conf, r, keyid, direction);
- if (p != NULL) {
- p->next = head;
- head = p;
- num_ent++;
- }
- }
- if (num_ent > 0) {
- ar = (struct ent **) apr_palloc(r->pool,
- num_ent * sizeof(struct ent *));
- p = head;
- x = 0;
- while (p) {
- ar[x++] = p;
- p = p->next;
- }
-
- qsort((void *) ar, num_ent, sizeof(struct ent *),
- (int (*)(const void *, const void *)) dsortf);
- }
- output_directories(ar, num_ent, autoindex_conf, r, autoindex_opts, keyid,
- direction);
- apr_dir_close(thedir);
-
- if (autoindex_opts & FANCY_INDEXING) {
- ap_rputs("<HR>\n", r);
- }
- emit_tail(r, find_readme(autoindex_conf, r),
- autoindex_opts & SUPPRESS_PREAMBLE);
-
- return 0;
-}
-
-/* The formal handler... */
-
-static int handle_autoindex(request_rec *r)
-{
- autoindex_config_rec *d;
- int allow_opts;
-
- if(strcmp(r->handler,DIR_MAGIC_TYPE))
- return DECLINED;
-
- allow_opts = ap_allow_options(r);
-
- d = (autoindex_config_rec *) ap_get_module_config(r->per_dir_config,
- &autoindex_module);
-
- r->allowed |= (1 << M_GET);
- if (r->method_number != M_GET) {
- return DECLINED;
- }
-
- /* OK, nothing easy. Trot out the heavy artillery... */
-
- if (allow_opts & OPT_INDEXES) {
- /* KLUDGE --- make the sub_req lookups happen in the right directory.
- * Fixing this in the sub_req_lookup functions themselves is difficult,
- * and would probably break virtual includes...
- */
-
- if (r->filename[strlen(r->filename) - 1] != '/') {
- r->filename = apr_pstrcat(r->pool, r->filename, "/", NULL);
- }
- return index_directory(r, d);
- }
- else {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
- "Directory index forbidden by rule: %s", r->filename);
- return HTTP_FORBIDDEN;
- }
-}
-
-static void register_hooks(apr_pool_t *p)
-{
- ap_hook_handler(handle_autoindex,NULL,NULL,APR_HOOK_MIDDLE);
-}
-
-module AP_MODULE_DECLARE_DATA autoindex_module =
-{
- STANDARD20_MODULE_STUFF,
- create_autoindex_config, /* dir config creater */
- merge_autoindex_configs, /* dir merger --- default is to override */
- NULL, /* server config */
- NULL, /* merge server config */
- autoindex_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
diff --git a/modules/test/mod_autoindex.exp b/modules/test/mod_autoindex.exp
deleted file mode 100644
index 90f4057e9c..0000000000
--- a/modules/test/mod_autoindex.exp
+++ /dev/null
@@ -1 +0,0 @@
-autoindex_module
diff --git a/modules/test/mod_optional_fn_export.c b/modules/test/mod_optional_fn_export.c
deleted file mode 100644
index b214a36621..0000000000
--- a/modules/test/mod_optional_fn_export.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "httpd.h"
-#include "http_config.h"
-#include "http_log.h"
-#include "mod_optional_fn_export.h"
-
-/* The alert will note a strange mirror-image style resemblance to
- * mod_generic_hook_import.c. Yes, I _did_ mean import. Think about it.
- */
-
-static int TestOptionalFn(const char *szStr)
-{
- ap_log_error(APLOG_MARK,APLOG_ERR,OK,NULL,
- "Optional function test said: %s",szStr);
-
- return OK;
-}
-
-static void ExportRegisterHooks(apr_pool_t *p)
-{
- APR_REGISTER_OPTIONAL_FN(TestOptionalFn);
-}
-
-module optional_fn_export_module=
-{
- STANDARD20_MODULE_STUFF,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- ExportRegisterHooks
-};
diff --git a/modules/test/mod_optional_fn_export.h b/modules/test/mod_optional_fn_export.h
deleted file mode 100644
index a1950f373b..0000000000
--- a/modules/test/mod_optional_fn_export.h
+++ /dev/null
@@ -1,3 +0,0 @@
-#include "apr_optional.h"
-
-APR_DECLARE_OPTIONAL_FN(int,TestOptionalFn,(const char *));
diff --git a/modules/test/mod_optional_fn_import.c b/modules/test/mod_optional_fn_import.c
deleted file mode 100644
index 3be3b6be6d..0000000000
--- a/modules/test/mod_optional_fn_import.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
-#include "httpd.h"
-#include "http_config.h"
-#include "mod_optional_fn_export.h"
-#include "http_protocol.h"
-
-/* The alert will note a strange mirror-image style resemblance to
- * mod_generic_hook_export.c. Yes, I _did_ mean export. Think about it.
- */
-
-static APR_OPTIONAL_FN_TYPE(TestOptionalFn) *pfn;
-
-static int ImportLogTransaction(request_rec *r)
-{
- if(pfn)
- return pfn(r->the_request);
- return DECLINED;
-}
-
-static void ImportFnRetrieve(void)
-{
- pfn=APR_RETRIEVE_OPTIONAL_FN(TestOptionalFn);
-}
-
-static void ImportRegisterHooks(apr_pool_t *p)
-{
- ap_hook_log_transaction(ImportLogTransaction,NULL,NULL,APR_HOOK_MIDDLE);
- ap_hook_optional_fn_retrieve(ImportFnRetrieve,NULL,NULL,APR_HOOK_MIDDLE);
-}
-
-module optional_fn_import_module =
-{
- STANDARD20_MODULE_STUFF,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- ImportRegisterHooks
-};
diff --git a/modules/test/mod_rndchunk.c b/modules/test/mod_rndchunk.c
deleted file mode 100644
index 6eeae175ac..0000000000
--- a/modules/test/mod_rndchunk.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * This module is intended to be used for testing chunked encoding. It
- * generates a whole whack of output using ap_bputc() and ap_bputs(). It
- * also exercises start_chunk() and end_chunk() in buff.c. To use it
- * you should use a tool like netcat and the src/test/check_chunked
- * tool. Add something like this to your access.conf file:
- *
- * <Location /rndchunk>
- * SetHandler rndchunk
- * </Location>
- *
- * Then fake requests such as:
- *
- * GET /rndchunk?0,1000000 HTTP/1.1
- * Host: localhost
- *
- * The first arg is the random seed, the second is the number of
- * "things" to do. You should try a few seeds.
- *
- * You should also edit main/buff.c and change DEFAULT_BUFSIZE (and
- * CHUNK_HEADER_SIZE). Small values are particularly useful for
- * finding bugs. Try a few different values.
- *
- * -djg
- */
-
-#include "httpd.h"
-#include "http_protocol.h"
-#include "http_config.h"
-#include "http_main.h"
-
-#define MAX_SEGMENT 32
-#define ONE_WEIGHT (256-32)
-
-static int send_rndchunk(request_rec *r)
-{
- const char *args;
- char *endptr;
- unsigned int seed;
- unsigned int count;
- int i;
- char buf[MAX_SEGMENT + 1];
- unsigned int len;
-
- r->allowed |= (1 << M_GET);
- if (r->method_number != M_GET)
- return DECLINED;
-
- r->content_type = "text/html";
- if(r->header_only) {
- return 0;
- }
- ap_hard_timeout("send_rndchunk", r);
-
- if (!r->chunked) {
- ap_rputs("Not chunked!", r);
- ap_kill_timeout(r);
- return 0;
- }
-
- args = r->args;
- if (!args) {
-error:
- ap_rputs("Must include args! ... of the form <code>?seed,count</code>", r);
- ap_kill_timeout(r);
- return 0;
- }
- seed = strtol(args, &endptr, 0);
- if (!endptr || *endptr != ',') {
- goto error;
- }
- ++endptr;
- count = strtol(endptr, &endptr, 0);
-
- srandom(seed);
- for (i = 0; i < count; ++i) {
- len = random() % (MAX_SEGMENT + ONE_WEIGHT);
- if (len >= MAX_SEGMENT) {
- ap_rputc((i & 1) ? '0' : '1', r);
- }
- else if (len == 0) {
- /* not a really nice thing to do, but we need to test
- * beginning/ending chunks as well
- */
- ap_bsetflag(r->connection->client, B_CHUNK, 0);
- ap_bsetflag(r->connection->client, B_CHUNK, 1);
- }
- else {
- memset(buf, '2' + len, len);
- buf[len] = 0;
- ap_rputs(buf, r);
- }
- }
- ap_kill_timeout(r);
- return 0;
-}
-
-static const handler_rec rndchunk_handlers[] =
-{
- {"rndchunk", send_rndchunk},
- {NULL}
-};
-
-module rndchunk_module = {
- STANDARD_MODULE_STUFF,
- NULL, /* initializer */
- NULL, /* dir config creater */
- NULL, /* dir merger --- default is to override */
- NULL, /* server config */
- NULL, /* merge server config */
- NULL, /* command apr_table_t */
- rndchunk_handlers, /* handlers */
- NULL, /* filename translation */
- NULL, /* check_user_id */
- NULL, /* check auth */
- NULL, /* check access */
- NULL, /* type_checker */
- NULL, /* fixups */
- NULL, /* logger */
- NULL /* header parser */
-};
diff --git a/modules/test/mod_test_util_uri.c b/modules/test/mod_test_util_uri.c
deleted file mode 100644
index 5472243568..0000000000
--- a/modules/test/mod_test_util_uri.c
+++ /dev/null
@@ -1,354 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-/*
- * This module is intended to test the util_uri routines by parsing a
- * bunch of urls and comparing the results with what we expect to
- * see.
- *
- * Usage:
- *
- * <Location /test-util-uri>
- * SetHandler test-util-uri
- * </Location>
- *
- * Then make a request to /test-util-uri. An html apr_table_t of errors will
- * be output... and a total count of errors.
- */
-
-#include "httpd.h"
-#include "http_protocol.h"
-#include "http_config.h"
-#include "http_main.h"
-
-typedef struct {
- const char *scheme;
- const char *user;
- const char *password;
- const char *hostname;
- const char *port_str;
- const char *path;
- const char *query;
- const char *fragment;
-} test_uri_t;
-
-#define T_scheme 0x01
-#define T_user 0x02
-#define T_password 0x04
-#define T_hostname 0x08
-#define T_port_str 0x10
-#define T_path 0x20
-#define T_query 0x40
-#define T_fragment 0x80
-#define T_MAX 0x100
-
-/* The idea is that we list here a bunch of url pieces that we want
- * stitched together in every way that's valid.
- */
-static const test_uri_t uri_tests[] = {
- { "http", "userid", "passwd", "hostname.goes.here", "80", "/path/goes/here", "query-here", "frag-here" },
- { "http", "", "passwd", "hostname.goes.here", "80", "/path/goes/here", "query-here", "frag-here" },
- { "http", "userid", "", "hostname.goes.here", "80", "/path/goes/here", "query-here", "frag-here" },
- { "http", "userid", "passwd", "", "80", "/path/goes/here", "query-here", "frag-here" },
- { "http", "userid", "passwd", "hostname.goes.here", "", "/path/goes/here", "query-here", "frag-here" },
-#if 0
- /* An empty path means two different things depending on whether this is a
- * relative or an absolute uri... consider <a href="#frag"> versus "GET
- * http://hostname HTTP/1.1". So this is why parse_uri_components returns
- * a NULL for path when it doesn't find one, instead of returning an empty
- * string.
- *
- * We don't really need to test it explicitly since path has no explicit
- * character that indicates its precense, and so we test empty paths all
- * the time by varying T_path in the loop. It would just cost us extra
- * code to special case the empty path string...
- */
- { "http", "userid", "passwd", "hostname.goes.here", "80", "", "query-here", "frag-here" },
-#endif
- { "http", "userid", "passwd", "hostname.goes.here", "80", "/path/goes/here", "", "frag-here" },
- { "http", "userid", "passwd", "hostname.goes.here", "80", "/path/goes/here", "query-here", "" },
- { "https", "user@d", "pa:swd", "hostname.goes.here.", "", "/~path/goes/here", "query&query?crud", "frag-here?baby" }
-
-};
-
-static char *my_stpcpy(char *d, const char *s)
-{
- while((*d = *s)) {
- ++d;
- ++s;
- }
- return d;
-}
-
-/* return the number of failures */
-static unsigned iterate_pieces(request_rec *r, const test_uri_t *pieces, int row)
-{
- unsigned u;
- apr_pool_t *sub;
- char *input_uri;
- char *strp;
- uri_components result;
- unsigned expect;
- int status;
- unsigned failures;
-
- failures = 0;
-
- input_uri = apr_palloc(r->pool,
- strlen(pieces->scheme) + 3
- + strlen(pieces->user) + 1
- + strlen(pieces->password) + 1
- + strlen(pieces->hostname) + 1
- + strlen(pieces->port_str) + 1
- + strlen(pieces->path) +
- + strlen(pieces->query) + 1
- + strlen(pieces->fragment) + 1
- + 1);
-
- for (u = 0; u < T_MAX; ++u) {
- strp = input_uri;
- expect = 0;
-
- /* a scheme requires a hostinfo and vice versa */
- /* a hostinfo requires a hostname */
- if (u & (T_scheme|T_user|T_password|T_hostname|T_port_str)) {
- expect |= T_scheme;
- strp = my_stpcpy(strp, pieces->scheme);
- *strp++ = ':';
- *strp++ = '/';
- *strp++ = '/';
- /* can't have password without user */
- if (u & (T_user|T_password)) {
- expect |= T_user;
- strp = my_stpcpy(strp, pieces->user);
- if (u & T_password) {
- expect |= T_password;
- *strp++ = ':';
- strp = my_stpcpy(strp, pieces->password);
- }
- *strp++ = '@';
- }
- expect |= T_hostname;
- strp = my_stpcpy(strp, pieces->hostname);
- if (u & T_port_str) {
- expect |= T_port_str;
- *strp++ = ':';
- strp = my_stpcpy(strp, pieces->port_str);
- }
- }
- if (u & T_path) {
- expect |= T_path;
- strp = my_stpcpy(strp, pieces->path);
- }
- if (u & T_query) {
- expect |= T_query;
- *strp++ = '?';
- strp = my_stpcpy(strp, pieces->query);
- }
- if (u & T_fragment) {
- expect |= T_fragment;
- *strp++ = '#';
- strp = my_stpcpy(strp, pieces->fragment);
- }
- *strp = 0;
-
- sub = apr_pool_sub_make(r->pool);
- status = ap_parse_uri_components(sub, input_uri, &result);
- if (status == HTTP_OK) {
-#define CHECK(f) \
- if ((expect & T_##f) \
- && (result.f == NULL || strcmp(result.f, pieces->f))) { \
- status = HTTP_INTERNAL_SERVER_ERROR; \
- } \
- else if (!(expect & T_##f) && result.f != NULL) { \
- status = HTTP_INTERNAL_SERVER_ERROR; \
- }
- CHECK(scheme)
- CHECK(user)
- CHECK(password)
- CHECK(hostname)
- CHECK(port_str)
- CHECK(path)
- CHECK(query)
- CHECK(fragment)
-#undef CHECK
- }
- if (status != HTTP_OK) {
- ap_rprintf(r, "<tr><td>%d</td><td>0x%02x</td><td>0x%02x</td><td>%d</td><td>\"%s\"</td>", row, u, expect, status, input_uri);
-#define DUMP(f) \
- if (result.f) { \
- ap_rvputs(r, "<td>\"", result.f, "\"<br>", NULL); \
- } \
- else { \
- ap_rputs("<td>NULL<br>", r); \
- } \
- if (expect & T_##f) { \
- ap_rvputs(r, "\"", pieces->f, "\"</td>", NULL); \
- } \
- else { \
- ap_rputs("NULL</td>", r); \
- }
- DUMP(scheme);
- DUMP(user);
- DUMP(password);
- DUMP(hostname);
- DUMP(port_str);
- DUMP(path);
- DUMP(query);
- DUMP(fragment);
-#undef DUMP
- ap_rputs("</tr>\n", r);
- ++failures;
- }
- apr_pool_destroy(sub);
- }
- return failures;
-}
-
-static int test_util_uri(request_rec *r)
-{
- unsigned total_failures;
- int i;
-
- r->allowed |= (1 << M_GET);
- if (r->method_number != M_GET)
- return DECLINED;
-
- r->content_type = "text/html";
- if(r->header_only) {
- return 0;
- }
- ap_hard_timeout("test_util_uri", r);
-
- ap_rputs(
-DOCTYPE_HTML_2_0 "
-<html><body>
-<p>Key:
-<dl>
-<dt>row
-<dd>entry number in the uri_tests array
-<dt>u
-<dd>fields under test
-<dt>expected
-<dd>fields expected in the result
-<dt>status
-<dd>response from parse_uri_components, or 500 if unexpected results
-<dt>input uri
-<dd>the uri given to parse_uri_components
-</dl>
-<p>The remaining fields are the pieces returned from parse_uri_components, and
-the values we expected for each piece (resp.).
-<p>Only failures are displayed.
-<p>
-<table><tr><th>row</th><th>u</th><th>expect</th><th>status</th><th>input uri</th>", r);
-#define HEADER(f) ap_rprintf(r, "<th>" #f "<br>0x%02x</th>", T_##f)
- HEADER(scheme);
- HEADER(user);
- HEADER(password);
- HEADER(hostname);
- HEADER(port_str);
- HEADER(path);
- HEADER(query);
- HEADER(fragment);
-#undef HEADER
-
- if (r->args) {
- i = atoi(r->args);
- total_failures = iterate_pieces(r, &uri_tests[i], i);
- }
- else {
- total_failures = 0;
- for (i = 0; i < sizeof(uri_tests) / sizeof(uri_tests[0]); ++i) {
- total_failures += iterate_pieces(r, &uri_tests[i], i);
- if (total_failures > 256) {
- ap_rprintf(r, "</table>\n<b>Stopped early to save your browser "
- "from certain death!</b>\nTOTAL FAILURES = %u\n",
- total_failures);
- return OK;
- }
- }
- }
- ap_rprintf(r, "</table>\nTOTAL FAILURES = %u\n", total_failures);
-
- return OK;
-}
-
-static const handler_rec test_util_uri_handlers[] =
-{
- {"test-util-uri", test_util_uri},
- {NULL}
-};
-
-module test_util_uri_module = {
- STANDARD_MODULE_STUFF,
- NULL, /* initializer */
- NULL, /* dir config creater */
- NULL, /* dir merger --- default is to override */
- NULL, /* server config */
- NULL, /* merge server config */
- NULL, /* command apr_table_t */
- test_util_uri_handlers, /* handlers */
- NULL, /* filename translation */
- NULL, /* check_user_id */
- NULL, /* check auth */
- NULL, /* check access */
- NULL, /* type_checker */
- NULL, /* fixups */
- NULL, /* logger */
- NULL /* header parser */
-};
diff --git a/modules/tls/.cvsignore b/modules/tls/.cvsignore
deleted file mode 100644
index 239bc29765..0000000000
--- a/modules/tls/.cvsignore
+++ /dev/null
@@ -1,6 +0,0 @@
-.libs
-.deps
-Makefile
-modules.mk
-*.lo
-*.la
diff --git a/modules/tls/Makefile.in b/modules/tls/Makefile.in
deleted file mode 100644
index d8187ddf06..0000000000
--- a/modules/tls/Makefile.in
+++ /dev/null
@@ -1,2 +0,0 @@
-include $(top_srcdir)/build/special.mk
-
diff --git a/modules/tls/README b/modules/tls/README
deleted file mode 100644
index 064ce839fe..0000000000
--- a/modules/tls/README
+++ /dev/null
@@ -1,20 +0,0 @@
-This currently won't work with Apache unaided. The manual things I
-have to do to make it work are:
-
-To configure this module you must use:
-
---enable-tls
---with-ssl=/path/to/ssl/library
-
-For example:
-
---enable-tls
---with-ssl=/home/rbb/openssl-0.9.6
-
-NOTE: You must be using OpenSSL 0.9.6 or later in order for this to work.
-
-Then all you need is "TLSFilter on" and "TLSCertificateFile <file>" in
-your config, and you are away (note that the cert file must also
-contain the private key at present).
-
-Ben Laurie, 11 Feb 2001.
diff --git a/modules/tls/config.m4 b/modules/tls/config.m4
deleted file mode 100644
index 2ecee966e0..0000000000
--- a/modules/tls/config.m4
+++ /dev/null
@@ -1,43 +0,0 @@
-AC_MSG_CHECKING(for SSL library)
-APACHE_MODPATH_INIT(tls)
-
-tls_objs="mod_tls.lo openssl_state_machine.lo"
-
-APACHE_MODULE(tls, TLS/SSL support, $tls_objs, , no, [
- AC_ARG_WITH(ssl, [ --with-ssl use a specific SSL library installation ],
- [
- searchfile="$withval/inc/ssl.h"
- if test -f $searchfile ; then
- APR_ADDTO(INCLUDES, [-I$withval/inc])
- APR_ADDTO(LIBS, [-L$withval -lsslc])
- ssl_lib="SSLC"
- else
- searchfile="$withval/ssl/ssl.h"
- if test -f $searchfile ; then
- APR_ADDTO(INCLUDES, [-I$withval/include])
- APR_ADDTO(LIBS, [-L$withval -lssl -lcrypto])
- ssl_lib="OpenSSL"
- else
- searchfile="$withval/openssl/ssl.h"
- if test -f $searchfile ; then
- APR_ADDTO(INCLUDES, [-I$withval/openssl])
- APR_ADDTO(LIBS, [-L$withval -lssl -lcrypto])
- ssl_lib="OpenSSL"
- else
- searchfile="$withval/include/openssl/ssl.h"
- if test -f $searchfile ; then
- APR_ADDTO(INCLUDES, [-I$withval/include])
- APR_ADDTO(LIBS, [-L$withval/lib -lssl -lcrypto])
- ssl_lib="OpenSSL"
- else
- AC_MSG_ERROR(no - Unable to locate $withval/inc/ssl.h)
- fi
- fi
- fi
- fi
- AC_MSG_RESULT(found $ssl_lib)
- ],[
- AC_MSG_ERROR(--with-ssl not given)
- ] ) ] )
-
-APACHE_MODPATH_FINISH
diff --git a/modules/tls/mod_tls.c b/modules/tls/mod_tls.c
deleted file mode 100644
index 2fd8cc75d3..0000000000
--- a/modules/tls/mod_tls.c
+++ /dev/null
@@ -1,417 +0,0 @@
-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2001 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
- */
-
-#include "httpd.h"
-#include "http_config.h"
-#include "util_filter.h"
-#include "http_connection.h"
-#include "openssl_state_machine.h"
-#include "apr_strings.h"
-#include "http_protocol.h"
-#include "http_log.h"
-
-/* temp */
-#include <assert.h>
-
-module AP_MODULE_DECLARE_DATA tls_module;
-static const char s_szTLSFilterName[]="TLSFilter";
-typedef struct
-{
- int bEnabled;
- const char *szCertificateFile;
- const char *szKeyFile;
-} TLSServerConfig;
-
-typedef struct
-{
- SSLStateMachine *pStateMachine;
- ap_filter_t *pInputFilter;
- ap_filter_t *pOutputFilter;
- apr_bucket_brigade *pbbInput; /* encrypted input */
- apr_bucket_brigade *pbbPendingInput; /* decrypted input */
-} TLSFilterCtx;
-
-static void *create_tls_server_config(apr_pool_t *p, server_rec *s)
-{
- TLSServerConfig *pConfig = apr_pcalloc(p, sizeof *pConfig);
-
- pConfig->bEnabled = 0;
- pConfig->szCertificateFile = pConfig->szKeyFile = NULL;
-
- return pConfig;
-}
-
-static const char *tls_on(cmd_parms *cmd, void *dummy, int arg)
-{
- TLSServerConfig *pConfig = ap_get_module_config(cmd->server->module_config,
- &tls_module);
- pConfig->bEnabled = arg;
-
- return NULL;
-}
-
-static const char *tls_cert_file(cmd_parms *cmd, void *dummy, const char *arg)
-{
- TLSServerConfig *pConfig = ap_get_module_config(cmd->server->module_config,
- &tls_module);
- pConfig->szCertificateFile = ap_server_root_relative(cmd->pool, arg);
-
- /* temp */
- pConfig->szKeyFile=pConfig->szCertificateFile;
-
- return NULL;
-}
-
-static int tls_filter_inserter(conn_rec *c)
-{
- TLSServerConfig *pConfig =
- ap_get_module_config(c->base_server->module_config,
- &tls_module);
- TLSFilterCtx *pCtx;
-
- if (!pConfig->bEnabled)
- return DECLINED;
-
- pCtx=apr_pcalloc(c->pool,sizeof *pCtx);
- pCtx->pStateMachine=SSLStateMachine_new(pConfig->szCertificateFile,
- pConfig->szKeyFile);
-
- pCtx->pInputFilter=ap_add_input_filter(s_szTLSFilterName,pCtx,NULL,c);
- pCtx->pOutputFilter=ap_add_output_filter(s_szTLSFilterName,pCtx,NULL,c);
- pCtx->pbbInput=apr_brigade_create(c->pool);
- pCtx->pbbPendingInput=apr_brigade_create(c->pool);
-
- return OK;
-}
-
-static apr_status_t churn_output(TLSFilterCtx *pCtx)
-{
- apr_bucket_brigade *pbbOutput=NULL;
- int done;
-
- do {
- char buf[1024];
- int n;
- apr_bucket *pbkt;
-
- done=0;
-
- if(SSLStateMachine_write_can_extract(pCtx->pStateMachine)) {
- n=SSLStateMachine_write_extract(pCtx->pStateMachine,buf,
- sizeof buf);
- if(n > 0) {
- char *pbuf;
-
- if(!pbbOutput)
- pbbOutput=apr_brigade_create(pCtx->pOutputFilter->c->pool);
-
- pbuf=apr_pmemdup(pCtx->pOutputFilter->c->pool,buf,n);
- pbkt=apr_bucket_pool_create(pbuf,n,
- pCtx->pOutputFilter->c->pool);
- APR_BRIGADE_INSERT_TAIL(pbbOutput,pbkt);
- done=1;
- /* } else if(n == 0) {
- apr_bucket *pbktEOS=apr_bucket_create_eos();
- APR_BRIGADE_INSERT_TAIL(pbbOutput,pbktEOS);*/
- }
- assert(n > 0);
- }
- } while(done);
-
- /* XXX: check for errors */
- if(pbbOutput) {
- apr_bucket *pbkt;
-
- /* XXX: it may be possible to not always flush */
- pbkt=apr_bucket_flush_create();
- APR_BRIGADE_INSERT_TAIL(pbbOutput,pbkt);
- ap_pass_brigade(pCtx->pOutputFilter->next,pbbOutput);
- }
-
- return APR_SUCCESS;
-}
-
-static apr_status_t churn(TLSFilterCtx *pCtx,apr_read_type_e eReadType,apr_size_t *readbytes)
-{
- ap_input_mode_t eMode=eReadType == APR_BLOCK_READ ? AP_MODE_BLOCKING
- : AP_MODE_NONBLOCKING;
- apr_bucket *pbktIn;
-
- if(APR_BRIGADE_EMPTY(pCtx->pbbInput)) {
- ap_get_brigade(pCtx->pInputFilter->next,pCtx->pbbInput,eMode,readbytes);
- if(APR_BRIGADE_EMPTY(pCtx->pbbInput))
- return APR_EOF;
- }
-
- APR_BRIGADE_FOREACH(pbktIn,pCtx->pbbInput) {
- const char *data;
- apr_size_t len;
- int n;
- char buf[1024];
- apr_status_t ret;
-
- if(APR_BUCKET_IS_EOS(pbktIn)) {
- /* XXX: why can't I reuse pbktIn??? */
- /* Write eof! */
- break;
- }
-
- /* read filter */
- ret=apr_bucket_read(pbktIn,&data,&len,eReadType);
-
- APR_BUCKET_REMOVE(pbktIn);
-
- if(ret == APR_SUCCESS && len == 0 && eReadType == APR_BLOCK_READ)
- ret=APR_EOF;
-
- if(len == 0) {
- /* Lazy frickin browsers just reset instead of shutting down. */
- if(ret == APR_EOF || ret == APR_ECONNRESET) {
- if(APR_BRIGADE_EMPTY(pCtx->pbbPendingInput))
- return APR_EOF;
- else
- /* Next time around, the incoming brigade will be empty,
- * so we'll return EOF then
- */
- return APR_SUCCESS;
- }
-
- if(eReadType != APR_NONBLOCK_READ)
- ap_log_error(APLOG_MARK,APLOG_ERR,ret,NULL,
- "Read failed in tls_in_filter");
- assert(eReadType == APR_NONBLOCK_READ);
- assert(ret == APR_SUCCESS || APR_STATUS_IS_EAGAIN(ret));
- /* In this case, we have data in the output bucket, or we were
- * non-blocking, so returning nothing is fine.
- */
- return APR_SUCCESS;
- }
-
- assert(len > 0);
-
- /* write SSL */
- SSLStateMachine_read_inject(pCtx->pStateMachine,data,len);
-
- n=SSLStateMachine_read_extract(pCtx->pStateMachine,buf,sizeof buf);
- if(n > 0) {
- apr_bucket *pbktOut;
- char *pbuf;
-
- pbuf=apr_pmemdup(pCtx->pInputFilter->c->pool,buf,n);
- /* XXX: should we use a heap bucket instead? Or a transient (in
- * which case we need a separate brigade for each bucket)?
- */
- pbktOut=apr_bucket_pool_create(pbuf,n,pCtx->pInputFilter->c->pool);
- APR_BRIGADE_INSERT_TAIL(pCtx->pbbPendingInput,pbktOut);
-
- /* Once we've read something, we can move to non-blocking mode (if
- * we weren't already).
- */
- eReadType=APR_NONBLOCK_READ;
-
- /* XXX: deal with EOF! */
- /* } else if(n == 0) {
- apr_bucket *pbktEOS=apr_bucket_create_eos();
- APR_BRIGADE_INSERT_TAIL(pbbInput,pbktEOS);*/
- }
- assert(n >= 0);
-
- ret=churn_output(pCtx);
- if(ret != APR_SUCCESS)
- return ret;
- }
-
- return churn_output(pCtx);
-}
-
-static apr_status_t tls_out_filter(ap_filter_t *f,apr_bucket_brigade *pbbIn)
-{
- TLSFilterCtx *pCtx=f->ctx;
- apr_bucket *pbktIn;
- apr_size_t zero = 0;
-
- APR_BRIGADE_FOREACH(pbktIn,pbbIn) {
- const char *data;
- apr_size_t len;
- apr_status_t ret;
-
- if(APR_BUCKET_IS_EOS(pbktIn)) {
- /* XXX: demote to debug */
- ap_log_error(APLOG_MARK,APLOG_ERR,0,NULL,"Got EOS on output");
- SSLStateMachine_write_close(pCtx->pStateMachine);
- /* XXX: dubious - does this always terminate? Does it return the right thing? */
- for( ; ; ) {
- ret=churn_output(pCtx);
- if(ret != APR_SUCCESS)
- return ret;
- ret=churn(pCtx,APR_NONBLOCK_READ,&zero);
- if(ret != APR_SUCCESS) {
- if(ret == APR_EOF)
- return APR_SUCCESS;
- else
- return ret;
- }
- }
- break;
- }
-
- if(APR_BUCKET_IS_FLUSH(pbktIn)) {
- /* assume that churn will flush (or already has) if there's output */
- ret=churn(pCtx,APR_NONBLOCK_READ,&zero);
- if(ret != APR_SUCCESS)
- return ret;
- continue;
- }
-
- /* read filter */
- apr_bucket_read(pbktIn,&data,&len,APR_BLOCK_READ);
-
- /* write SSL */
- SSLStateMachine_write_inject(pCtx->pStateMachine,data,len);
-
- /* churn the state machine */
- ret=churn_output(pCtx);
- if(ret != APR_SUCCESS)
- return ret;
- }
-
- return APR_SUCCESS;
-}
-
-static apr_status_t tls_in_filter(ap_filter_t *f,apr_bucket_brigade *pbbOut,
- ap_input_mode_t eMode, apr_size_t *readbytes)
-{
- TLSFilterCtx *pCtx=f->ctx;
- apr_read_type_e eReadType=eMode == AP_MODE_BLOCKING ? APR_BLOCK_READ :
- APR_NONBLOCK_READ;
- apr_status_t ret;
-
- /* XXX: we don't currently support peek */
- assert(eMode != AP_MODE_PEEK);
-
- /* churn the state machine */
- ret=churn(pCtx,eReadType,readbytes);
- if(ret != APR_SUCCESS)
- return ret;
-
- /* XXX: shame that APR_BRIGADE_FOREACH doesn't work here */
- while(!APR_BRIGADE_EMPTY(pCtx->pbbPendingInput)) {
- apr_bucket *pbktIn=APR_BRIGADE_FIRST(pCtx->pbbPendingInput);
- APR_BUCKET_REMOVE(pbktIn);
- APR_BRIGADE_INSERT_TAIL(pbbOut,pbktIn);
- }
-
- return APR_SUCCESS;
-}
-
-static const char *tls_method(const request_rec *r)
-{
- TLSServerConfig *pConfig =
- ap_get_module_config(r->connection->base_server->module_config,
- &tls_module);
-
- if (!pConfig->bEnabled)
- return NULL;
-
- return "https";
-}
-
-static unsigned short tls_port(const request_rec *r)
-{
- TLSServerConfig *pConfig =
- ap_get_module_config(r->connection->base_server->module_config,
- &tls_module);
-
- if (!pConfig->bEnabled)
- return 0;
-
- return 443;
-}
-
-static const command_rec tls_cmds[] =
-{
- /* XXX: We should be able to add the filter using AddOutputFilter */
- AP_INIT_FLAG("TLSFilter", tls_on, NULL, RSRC_CONF,
- "Run TLS/SSL on this host"),
- AP_INIT_TAKE1("TLSCertificateFile", tls_cert_file, NULL, RSRC_CONF,
- "Set the certificate file for this host"),
- { NULL }
-};
-
-static void register_hooks(apr_pool_t *p)
-{
- SSLStateMachine_init();
-
- ap_register_output_filter(s_szTLSFilterName,tls_out_filter,
- AP_FTYPE_NETWORK);
- ap_register_input_filter(s_szTLSFilterName,tls_in_filter,
- AP_FTYPE_NETWORK);
- ap_hook_pre_connection(tls_filter_inserter,NULL,NULL,APR_HOOK_MIDDLE);
- ap_hook_default_port(tls_port,NULL,NULL,APR_HOOK_MIDDLE);
- ap_hook_http_method(tls_method,NULL,NULL,APR_HOOK_MIDDLE);
-}
-
-module AP_MODULE_DECLARE_DATA tls_module = {
- STANDARD20_MODULE_STUFF,
- NULL, /* create per-directory config structure */
- NULL, /* merge per-directory config structures */
- create_tls_server_config, /* create per-server config structure */
- NULL, /* merge per-server config structures */
- tls_cmds, /* command apr_table_t */
- register_hooks /* register hooks */
-};
diff --git a/modules/tls/openssl_state_machine.c b/modules/tls/openssl_state_machine.c
deleted file mode 100644
index 171a1aa23d..0000000000
--- a/modules/tls/openssl_state_machine.c
+++ /dev/null
@@ -1,268 +0,0 @@
-/* This is adapted from the OpenSSL state_machine demo */
-
-/* ====================================================================
- * Copyright (c) 2000 The OpenSSL Project. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- * software must display the following acknowledgment:
- * "This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- * endorse or promote products derived from this software without
- * prior written permission. For written permission, please contact
- * openssl-core@openssl.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- * nor may "OpenSSL" appear in their names without prior written
- * permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- * acknowledgment:
- * "This product includes software developed by the OpenSSL Project
- * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com). This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com).
- *
- */
-
-/*
- * Nuron, a leader in hardware encryption technology, generously
- * sponsored the development of this demo by Ben Laurie.
- *
- * See http://www.nuron.com/.
- */
-
-/*
- * the aim of this demo is to provide a fully working state-machine
- * style SSL implementation, i.e. one where the main loop acquires
- * some data, then converts it from or to SSL by feeding it into the
- * SSL state machine. It then does any I/O required by the state machine
- * and loops.
- *
- * In order to keep things as simple as possible, this implementation
- * listens on a TCP socket, which it expects to get an SSL connection
- * on (for example, from s_client) and from then on writes decrypted
- * data to stdout and encrypts anything arriving on stdin. Verbose
- * commentary is written to stderr.
- *
- * This implementation acts as a server, but it can also be done for a client. */
-
-#include "apr.h"
-
-#include <openssl/ssl.h>
-#include <assert.h>
-#if APR_HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <string.h>
-#include <openssl/err.h>
-#include "openssl_state_machine.h"
-
-/* die_unless is intended to work like assert, except that it happens
- always, even if NDEBUG is defined. Use assert as a stopgap. */
-
-#define die_unless(x) assert(x)
-
-struct SSLStateMachine
- {
- SSL_CTX *pCtx;
- BIO *pbioRead;
- BIO *pbioWrite;
- SSL *pSSL;
- };
-
-void SSLStateMachine_init(void)
-{
- static int s_bInitDone;
-
- if(s_bInitDone)
- return;
-
- SSL_library_init();
- OpenSSL_add_ssl_algorithms();
- SSL_load_error_strings();
- ERR_load_crypto_strings();
-
- s_bInitDone=1;
-}
-
-static void SSLStateMachine_print_error(SSLStateMachine *pMachine,
- const char *szErr)
- {
- unsigned long l;
-
- fprintf(stderr,"%s\n",szErr);
- while((l=ERR_get_error()))
- {
- char buf[1024];
-
- ERR_error_string_n(l,buf,sizeof buf);
- fprintf(stderr,"Error %lx: %s\n",l,buf);
- }
- }
-
-SSLStateMachine *SSLStateMachine_new(const char *szCertificateFile,
- const char *szKeyFile)
- {
- SSLStateMachine *pMachine=malloc(sizeof *pMachine);
- int n;
-
- die_unless(pMachine);
-
- pMachine->pCtx=SSL_CTX_new(SSLv23_server_method());
- die_unless(pMachine->pCtx);
-
- n=SSL_CTX_use_certificate_file(pMachine->pCtx,szCertificateFile,
- SSL_FILETYPE_PEM);
- die_unless(n > 0);
-
- n=SSL_CTX_use_PrivateKey_file(pMachine->pCtx,szKeyFile,SSL_FILETYPE_PEM);
- die_unless(n > 0);
-
- pMachine->pSSL=SSL_new(pMachine->pCtx);
- die_unless(pMachine->pSSL);
-
- pMachine->pbioRead=BIO_new(BIO_s_mem());
-
- pMachine->pbioWrite=BIO_new(BIO_s_mem());
-
- SSL_set_bio(pMachine->pSSL,pMachine->pbioRead,pMachine->pbioWrite);
-
- SSL_set_accept_state(pMachine->pSSL);
-
- return pMachine;
- }
-
-void SSLStateMachine_read_inject(SSLStateMachine *pMachine,
- const unsigned char *aucBuf,int nBuf)
- {
- int n=BIO_write(pMachine->pbioRead,aucBuf,nBuf);
- /* If it turns out this assert fails, then buffer the data here
- * and just feed it in in churn instead. Seems to me that it
- * should be guaranteed to succeed, though.
- */
- assert(n == nBuf);
- fprintf(stderr,"%d bytes of encrypted data fed to state machine\n",n);
- }
-
-int SSLStateMachine_read_extract(SSLStateMachine *pMachine,
- unsigned char *aucBuf,int nBuf)
- {
- int n;
-
- if(!SSL_is_init_finished(pMachine->pSSL))
- {
- fprintf(stderr,"Doing SSL_accept\n");
- n=SSL_accept(pMachine->pSSL);
- if(n == 0)
- fprintf(stderr,"SSL_accept returned zero\n");
- if(n < 0)
- {
- int err;
-
- if((err=SSL_get_error(pMachine->pSSL,n)) == SSL_ERROR_WANT_READ)
- {
- fprintf(stderr,"SSL_accept wants more data\n");
- return 0;
- }
-
- SSLStateMachine_print_error(pMachine,"SSL_accept error");
- exit(7);
- }
- return 0;
- }
-
- n=SSL_read(pMachine->pSSL,aucBuf,nBuf);
- if(n < 0)
- {
- int err=SSL_get_error(pMachine->pSSL,n);
-
- if(err == SSL_ERROR_WANT_READ)
- {
- fprintf(stderr,"SSL_read wants more data\n");
- return 0;
- }
- SSLStateMachine_print_error(pMachine,"SSL_read error");
- exit(8);
- }
-
- fprintf(stderr,"%d bytes of decrypted data read from state machine\n",n);
- return n;
- }
-
-int SSLStateMachine_write_can_extract(SSLStateMachine *pMachine)
- {
- int n=BIO_pending(pMachine->pbioWrite);
- if(n)
- fprintf(stderr,"There is encrypted data available to write\n");
- else
- fprintf(stderr,"There is no encrypted data available to write\n");
-
- return n;
- }
-
-int SSLStateMachine_write_extract(SSLStateMachine *pMachine,
- unsigned char *aucBuf,int nBuf)
- {
- int n;
-
- n=BIO_read(pMachine->pbioWrite,aucBuf,nBuf);
- fprintf(stderr,"%d bytes of encrypted data read from state machine\n",n);
- return n;
- }
-
-void SSLStateMachine_write_inject(SSLStateMachine *pMachine,
- const unsigned char *aucBuf,int nBuf)
- {
- int n=SSL_write(pMachine->pSSL,aucBuf,nBuf);
- if(n < 0)
- {
- if(ERR_peek_error() == ERR_PACK(ERR_LIB_SSL,SSL_F_SSL_WRITE,
- SSL_R_PROTOCOL_IS_SHUTDOWN))
- {
- SSLStateMachine_print_error(pMachine,"SSL_write error (someone wrote after shutdown)");
- return;
- }
- SSLStateMachine_print_error(pMachine,"SSL_write error");
- }
- /* If it turns out this assert fails, then buffer the data here
- * and just feed it in in churn instead. Seems to me that it
- * should be guaranteed to succeed, though.
- */
- assert(n == nBuf);
- fprintf(stderr,"%d bytes of unencrypted data fed to state machine\n",n);
- }
-
-void SSLStateMachine_write_close(SSLStateMachine *pMachine)
- {
- SSL_shutdown(pMachine->pSSL);
- }
diff --git a/modules/tls/openssl_state_machine.h b/modules/tls/openssl_state_machine.h
deleted file mode 100644
index 10be69a3b0..0000000000
--- a/modules/tls/openssl_state_machine.h
+++ /dev/null
@@ -1,15 +0,0 @@
-typedef struct SSLStateMachine SSLStateMachine;
-
-void SSLStateMachine_init(void);
-SSLStateMachine *SSLStateMachine_new(const char *szCertificateFile,
- const char *szKeyFile);
-void SSLStateMachine_read_inject(SSLStateMachine *pMachine,
- const unsigned char *aucBuf,int nBuf);
-int SSLStateMachine_read_extract(SSLStateMachine *pMachine,
- unsigned char *aucBuf,int nBuf);
-int SSLStateMachine_write_can_extract(SSLStateMachine *pMachine);
-int SSLStateMachine_write_extract(SSLStateMachine *pMachine,
- unsigned char *aucBuf,int nBuf);
-void SSLStateMachine_write_inject(SSLStateMachine *pMachine,
- const unsigned char *aucBuf,int nBuf);
-void SSLStateMachine_write_close(SSLStateMachine *pMachine);