##                      _             _ 
##  _ __ ___   ___   __| |    ___ ___| |  
## | '_ ` _ \ / _ \ / _` |   / __/ __| |  
## | | | | | | (_) | (_| |   \__ \__ \ | mod_ssl - Apache Interface to SSLeay  
## |_| |_| |_|\___/ \__,_|___|___/___/_| http://www.engelschall.com/sw/mod_ssl/
##                      |_____|         
## ____________________________________________________________________________
##
## Annotated mod_ssl patch file: eapi.patch
## Copyright (c) 1998 Ralf S. Engelschall, All Rights Reserved. 
## Created on: 11-Nov-1998
##
## This file assembles changes to existing Apache source files
## between the original Apache and the patched variant. It can be
## automatically applied to a vanilla Apache source tree with the
## 'patch' tool to upgrade those files.  Each patch snippet is
## annotated with a short description.
##
## This file contains all patches to the Apache source
## tree which add the Extended API (EAPI) support.
##

+---------------------------------------------------------------------------
| Add the EAPI configuration rule which triggers the EAPI patches.
+---------------------------------------------------------------------------
Index: src/Configuration.tmpl
--- src/Configuration.tmpl	1998/09/22 08:42:44	1.1.1.3
+++ src/Configuration.tmpl	1998/11/08 15:34:28	1.9
@@ -155,12 +181,20 @@
 #  is performing this function. If PARANOID is set to yes, it will
 #  actually print-out the code that the modules execute
 #
+# EAPI:
+#  Enable the Extended API which provides more module hooks, a generic
+#  low-level hook mechanism and a generic context mechanism. Please notice
+#  that enabling this rule forces you to recompile (with -DEAPI) all existing
+#  modules which are already built and installed as DSOs.  Because under EAPI
+#  the module configuration structure has a different size.
+#
 
 Rule SOCKS4=no
 Rule SOCKS5=no
 Rule IRIXNIS=no
 Rule IRIXN32=yes
 Rule PARANOID=no
+Rule EAPI=no
 
 # The following rules should be set automatically by Configure. However, if
 # they are not set by Configure (because we don't know the correct value for

+---------------------------------------------------------------------------
| Patch in implementation of the EAPI rule.
+---------------------------------------------------------------------------
Index: src/Configure
--- src/Configure	1998/10/07 11:28:04	1.1.1.4
+++ src/Configure	1998/10/25 15:11:19	1.2
@@ -237,6 +237,7 @@
 RULE_IRIXNIS=`./helpers/CutRule IRIXNIS $file`
 RULE_IRIXN32=`./helpers/CutRule IRIXN32 $file`
 RULE_PARANOID=`./helpers/CutRule PARANOID $file`
+RULE_EAPI=`./helpers/CutRule EAPI $file`
 RULE_SHARED_CORE=`./helpers/CutRule SHARED_CORE $file`
 RULE_SHARED_CHAIN=`./helpers/CutRule SHARED_CHAIN $file`
 
@@ -1467,6 +1468,13 @@
     REGLIB="regex/libregex.a"
     SUBDIRS="regex $SUBDIRS"
     CFLAGS="$CFLAGS -DUSE_HSREGEX"
+fi
+
+####################################################################
+# Extended API support:
+if [ "$RULE_EAPI" = "yes" ]; then
+    echo " + enabling Extended API (EAPI)"
+    CFLAGS="$CFLAGS -DEAPI"
 fi
 
 ####################################################################

+---------------------------------------------------------------------------
| Add the build support for the ap_hook.c and ap_ctx.c sources (Unix)
+---------------------------------------------------------------------------
Index: src/ap/Makefile.tmpl
--- src/ap/Makefile.tmpl	1998/09/22 08:42:47	1.1.1.3
+++ src/ap/Makefile.tmpl	1998/10/25 15:11:20	1.2
@@ -6,7 +6,7 @@
 LIB=libap.a
 
 OBJS=ap_execve.o ap_cpystrn.o ap_signal.o \
-     ap_slack.o ap_snprintf.o ap_fnmatch.o
+     ap_slack.o ap_snprintf.o ap_fnmatch.o ap_hook.o ap_ctx.o
 
 .c.o:
 	$(CC) -c $(INCLUDES) $(CFLAGS) $<

+---------------------------------------------------------------------------
| Add the build support for the ap_hook.c and ap_ctx.c sources (Win32)
+---------------------------------------------------------------------------
Index: src/ap/ap.mak
--- src/ap/ap.mak	1998/09/22 08:42:48	1.1.1.3
+++ src/ap/ap.mak	1998/10/26 16:48:19	1.2
@@ -48,6 +48,8 @@
 CLEAN :
 	-@erase "$(INTDIR)\ap_cpystrn.obj"
 	-@erase "$(INTDIR)\ap_fnmatch.obj"
+	-@erase "$(INTDIR)\ap_hook.obj"
+	-@erase "$(INTDIR)\ap_ctx.obj"
 	-@erase "$(INTDIR)\ap_signal.obj"
 	-@erase "$(INTDIR)\ap_slack.obj"
 	-@erase "$(INTDIR)\ap_snprintf.obj"
@@ -70,6 +72,8 @@
 LIB32_OBJS= \
 	"$(INTDIR)\ap_cpystrn.obj" \
 	"$(INTDIR)\ap_fnmatch.obj" \
+	"$(INTDIR)\ap_hook.obj" \
+	"$(INTDIR)\ap_ctx.obj" \
 	"$(INTDIR)\ap_signal.obj" \
 	"$(INTDIR)\ap_slack.obj" \
 	"$(INTDIR)\ap_snprintf.obj"
@@ -100,6 +104,8 @@
 CLEAN :
 	-@erase "$(INTDIR)\ap_cpystrn.obj"
 	-@erase "$(INTDIR)\ap_fnmatch.obj"
+	-@erase "$(INTDIR)\ap_hook.obj"
+	-@erase "$(INTDIR)\ap_ctx.obj"
 	-@erase "$(INTDIR)\ap_signal.obj"
 	-@erase "$(INTDIR)\ap_slack.obj"
 	-@erase "$(INTDIR)\ap_snprintf.obj"
@@ -122,6 +128,8 @@
 LIB32_OBJS= \
 	"$(INTDIR)\ap_cpystrn.obj" \
 	"$(INTDIR)\ap_fnmatch.obj" \
+	"$(INTDIR)\ap_hook.obj" \
+	"$(INTDIR)\ap_ctx.obj" \
 	"$(INTDIR)\ap_signal.obj" \
 	"$(INTDIR)\ap_slack.obj" \
 	"$(INTDIR)\ap_snprintf.obj"

+---------------------------------------------------------------------------
| Add the additional context variable `ctx' for BUFF structures.
+---------------------------------------------------------------------------
Index: src/include/buff.h
--- src/include/buff.h	1998/07/21 18:46:42	1.1.1.2
+++ src/include/buff.h	1998/10/29 14:57:51	1.5
@@ -124,6 +124,10 @@
     /* transport handle, for RPC binding handle or some such */
     void *t_handle;
 
+#ifdef EAPI
+    ap_ctx *ctx;
+#endif /* EAPI */
+
 #ifdef B_SFIO
     Sfio_t *sf_in;
     Sfio_t *sf_out;

+---------------------------------------------------------------------------
| Add the four additional Apache API module hooks.
+---------------------------------------------------------------------------
Index: src/include/http_config.h
--- src/include/http_config.h	1998/09/22 08:42:56	1.1.1.3
+++ src/include/http_config.h	1998/11/08 13:55:28	1.3
@@ -269,6 +269,55 @@
     void (*child_exit) (server_rec *, pool *);
 #endif
     int (*post_read_request) (request_rec *);
+
+#ifdef EAPI
+    /*
+     * ANSI C guarantees us that we can at least _extend_ the module structure
+     * with additional hooks without the need to change all existing modules.
+     * Because: ``If there are fewer initializers in the list than members of
+     * the structure, the trailing members are initialized with 0.'' (The C
+     * Programming Language, 2nd Ed., A8.7 Initialization). So we just
+     * have to put our additional hooks here:
+     *
+     * add_module: 
+     *     Called from within ap_add_module() right after the module structure
+     *     was linked into the Apache internal module list.  It is mainly
+     *     intended to be used to define configuration defines (<IfDefine>)
+     *     which have to be available directly after a LoadModule/AddModule.
+     *     Actually this is the earliest possible hook a module can use.
+     *
+     * remove_module: 
+     *     Called from within ap_remove_module() right before the module
+     *     structure is kicked out from the Apache internal module list.
+     *     Actually this is last possible hook a module can use and exists for
+     *     consistency with the add_module hook.
+     *
+     * rewrite_command:
+     *     Called right after a configuration directive line was read and
+     *     before it is processed. It is mainly intended to be used for
+     *     rewriting directives in order to provide backward compatibility to
+     *     old directive variants.
+     *
+     * new_connection:
+     *     Called from within the internal new_connection() function, right
+     *     after the conn_rec structure for the new established connection was
+     *     created and before Apache starts processing the request with
+     *     ap_read_request().  It is mainly intended to be used to setup/run
+     *     connection dependent things like sending start headers for
+     *     on-the-fly compression, etc.
+     */
+#ifdef ULTRIX_BRAIN_DEATH
+    void  (*add_module) ();
+    void  (*remove_module) ();
+    char *(*rewrite_command) ();
+    void  (*new_connection) ();
+#else
+    void  (*add_module) (struct module_struct *);
+    void  (*remove_module) (struct module_struct *);
+    char *(*rewrite_command) (cmd_parms *, const char *);
+    void  (*new_connection) (conn_rec *);
+#endif
+#endif /* EAPI */
 } module;
 
 /* Initializer for the first few module slots, which are only

+---------------------------------------------------------------------------
| Add the additional variable `ap_global_ctx' for holding
| global module context.
+---------------------------------------------------------------------------
Index: src/include/http_conf_globals.h
--- src/include/http_conf_globals.h	1998/09/22 08:42:56	1.1.1.3
+++ src/include/http_conf_globals.h	1998/10/30 20:37:21	1.4
@@ -86,6 +86,9 @@
 extern int ap_listenbacklog;
 extern int ap_dump_settings;
 extern API_VAR_EXPORT int ap_extended_status;
+#ifdef EAPI
+extern API_VAR_EXPORT ap_ctx *ap_global_ctx;
+#endif /* EAPI */
 
 extern char *ap_pid_fname;
 extern char *ap_scoreboard_fname;

+---------------------------------------------------------------------------
| First add support for the HTTPS protocol scheme via hooks,
| second add the additional context variable `ctx' for the
| conn_rec, server_rec and request_rec structures. And third
| add a prototype for the additional ap_add_config_define()
| function.
+---------------------------------------------------------------------------
Index: src/include/httpd.h
--- src/include/httpd.h	1998/10/07 11:28:12	1.1.1.4
+++ src/include/httpd.h	1998/11/08 15:34:28	1.11
@@ -70,6 +70,15 @@
 
 #include "ap_config.h"
 #include "alloc.h"
+/*
+ * Include the Extended API headers.
+ * Don't move the position. It has to be after alloc.h because it uses the
+ * pool stuff but before buff.h because the buffer stuff uses the EAPI, too. 
+ */
+#ifdef EAPI
+#include "ap_hook.h"
+#include "ap_ctx.h"
+#endif /* EAPI */
 #include "buff.h"
 #include "ap.h"
 
@@ -131,8 +140,13 @@
 #define DEFAULT_HTTP_PORT	80
 #define DEFAULT_HTTPS_PORT	443
 #define ap_is_default_port(port,r)	((port) == ap_default_port(r))
+#ifdef EAPI
+#define ap_http_method(r)   (ap_ctx_get((r)->ctx, "ap::http::method") != NULL ? ((char *)ap_ctx_get((r)->ctx, "ap::http::method")) : "http")
+#define ap_default_port(r)  (ap_ctx_get((r)->ctx, "ap::default::port") != NULL ? atoi((char *)ap_ctx_get((r)->ctx, "ap::default::port")) : DEFAULT_HTTP_PORT)
+#else /* EAPI */
 #define ap_http_method(r)	"http"
 #define ap_default_port(r)	DEFAULT_HTTP_PORT
+#endif /* EAPI */
 
 /* --------- Default user name and group name running standalone ---------- */
 /* --- These may be specified as numbers by placing a # before a number --- */
@@ -421,6 +435,9 @@
 API_EXPORT(const char *) ap_get_server_version(void);
 API_EXPORT(void) ap_add_version_component(const char *component);
 API_EXPORT(const char *) ap_get_server_built(void);
+#ifdef EAPI
+API_EXPORT(void) ap_add_config_define(const char *define);
+#endif /* EAPI */
 
 /* Numeric release version identifier: major minor bugfix betaseq
  * Always increases along the same track as the source branch.
@@ -759,6 +776,10 @@
  * binary compatibility for some other reason.
  */
     unsigned expecting_100;     /* is client waiting for a 100 response? */
+
+#ifdef EAPI
+    ap_ctx *ctx;
+#endif /* EAPI */
 };
 
 
@@ -803,6 +824,10 @@
     signed int double_reverse:2;/* have we done double-reverse DNS?
 				 * -1 yes/failure, 0 not yet, 1 yes/success */
     int keepalives;		/* How many times have we used it? */
+
+#ifdef EAPI
+    ap_ctx *ctx;
+#endif /* EAPI */
 };
 
 /* Per-vhost config... */
@@ -875,6 +900,10 @@
     int limit_req_line;      /* limit on size of the HTTP request line    */
     int limit_req_fieldsize; /* limit on size of any request header field */
     int limit_req_fields;    /* limit on number of request header fields  */
+
+#ifdef EAPI
+    ap_ctx *ctx;
+#endif /* EAPI */
 };
 
 /* These are more like real hosts than virtual hosts */

+---------------------------------------------------------------------------
| We have to disable writev() support because
| we don't support it for EAPI.
+---------------------------------------------------------------------------
Index: src/include/ap_config.h
--- src/include/ap_config.h	1998/10/07 11:28:10	1.1.1.3
+++ src/include/ap_config.h	1998/11/08 16:10:12	1.8
@@ -1225,6 +1225,15 @@
 #define ap_wait_t int
 #endif
 
+/*
+ * We've still no support for writev() in EAPI...
+ */
+#ifdef EAPI
+#ifndef NO_WRITEV
+#define NO_WRITEV
+#endif
+#endif /* EAPI */
+
 #ifdef __cplusplus
 }
 #endif

+---------------------------------------------------------------------------
| Patch the low-level buffer routines to additionally allow
| modules to intercept the I/O processing via hooks.
+---------------------------------------------------------------------------
Index: src/main/buff.c
--- src/main/buff.c	1998/10/07 11:28:14	1.1.1.4
+++ src/main/buff.c	1998/11/08 15:34:28	1.11
@@ -125,7 +125,11 @@
   select() sometimes returns 1 even though the write will block. We must work around this.
 */
 
+#ifdef EAPI
+API_EXPORT(int) sendwithtimeout(int sock, const char *buf, int len, int flags)
+#else /* EAPI */
 int sendwithtimeout(int sock, const char *buf, int len, int flags)
+#endif /* EAPI */
 {
     int iostate = 1;
     fd_set fdset;
@@ -183,8 +187,11 @@
     return (rv);
 }
 
-
+#ifdef EAPI
+API_EXPORT(int) recvwithtimeout(int sock, char *buf, int len, int flags)
+#else /* EAPI */
 int recvwithtimeout(int sock, char *buf, int len, int flags)
+#endif /* EAPI */
 {
     int iostate = 1;
     fd_set fdset;
@@ -242,6 +249,9 @@
     }
     else
 #endif
+#ifdef EAPI
+	if (!ap_hook_call("ap::buff::read", &rv, fb, buf, nbyte))
+#endif /* EAPI */
 	rv = read(fb->fd_in, buf, nbyte);
     
     return rv;
@@ -253,6 +263,9 @@
 
 #if defined (WIN32)
     if (fb->flags & B_SOCKET) {
+#ifdef EAPI
+	if (!ap_hook_call("ap::buff::recvwithtimeout", &rv, fb, buf, nbyte))
+#endif /* EAPI */
 	rv = recvwithtimeout(fb->fd_in, buf, nbyte, 0);
 	if (rv == SOCKET_ERROR)
 	    errno = WSAGetLastError();
@@ -277,6 +290,9 @@
     }
     else
 #endif
+#ifdef EAPI
+	if (!ap_hook_call("ap::buff::write", &rv, fb, buf, nbyte))
+#endif /* EAPI */
 #if defined (B_SFIO)
 	rv = sfwrite(fb->sf_out, buf, nbyte);
 #else
@@ -292,6 +308,9 @@
 
 #if defined(WIN32)
     if (fb->flags & B_SOCKET) {
+#ifdef EAPI
+	if (!ap_hook_call("ap::buff::sendwithtimeout", &rv, fb, buf, nbyte))
+#endif /* EAPI */
 	rv = sendwithtimeout(fb->fd, buf, nbyte, 0);
 	if (rv == SOCKET_ERROR)
 	    errno = WSAGetLastError();
@@ -366,6 +385,10 @@
     fb->sf_out = sfnew(fb->sf_out, NIL(Void_t *),
 		       (size_t) SF_UNBOUND, 1, SF_WRITE);
 #endif
+
+#ifdef EAPI
+    fb->ctx = ap_ctx_new(p);
+#endif /* EAPI */
 
     return fb;
 }

+---------------------------------------------------------------------------
| Add the implementation of the additional `add_module' and
| `rewrite_command' module hooks. Additionally the `ctx'
| variables are initialized.
+---------------------------------------------------------------------------
Index: src/main/http_config.c
--- src/main/http_config.c	1998/10/07 11:28:15	1.1.1.4
+++ src/main/http_config.c	1998/11/08 15:34:28	1.5
@@ -580,6 +580,19 @@
 	m->name = tmp;
     }
 #endif /*_OSD_POSIX*/
+
+#ifdef EAPI
+    /*
+     * Invoke the `add_module' hook inside the now existing set
+     * of modules to let them all now that this module was added.
+     */
+    {
+        module *m2;
+        for (m2 = top_module; m2 != NULL; m2 = m2->next)
+            if (m2->add_module != NULL)
+                (*m2->add_module)(m);
+    }
+#endif /* EAPI */
 }
 
 /* 
@@ -594,6 +607,20 @@
 {
     module *modp;
 
+#ifdef EAPI
+    /*
+     * Invoke the `remove_module' hook inside the now existing
+     * set of modules to let them all now that this module is
+     * beeing removed.
+     */
+    {
+        module *m2;
+        for (m2 = top_module; m2 != NULL; m2 = m2->next)
+            if (m2->remove_module != NULL)
+                (*m2->remove_module)(m);
+    }
+#endif /* EAPI */
+
     modp = top_module;
     if (modp == m) {
 	/* We are the top module, special case */
@@ -960,6 +987,25 @@
     const command_rec *cmd;
     module *mod = top_module;
 
+#ifdef EAPI
+    /*
+     * Invoke the `rewrite_command' of modules to allow
+     * they to rewrite the directive line before we
+     * process it.
+     */
+    {
+        module *m;
+        char *cp;
+        for (m = top_module; m != NULL; m = m->next) {
+            if (m->rewrite_command != NULL) {
+                cp = (m->rewrite_command)(parms, l);
+                if (cp != NULL)
+                    l = cp;
+            }
+        }
+    }
+#endif /* EAPI */
+
     if ((l[0] == '#') || (!l[0]))
 	return NULL;
 
@@ -1319,6 +1365,10 @@
     s->limit_req_fieldsize = main_server->limit_req_fieldsize;
     s->limit_req_fields = main_server->limit_req_fields;
 
+#ifdef EAPI
+    s->ctx = ap_ctx_new(p);
+#endif /* EAPI */
+
     *ps = s;
 
     return ap_parse_vhost_addrs(p, hostname, s);
@@ -1429,6 +1479,10 @@
 
     s->module_config = create_server_config(p, s);
     s->lookup_defaults = create_default_per_dir_config(p);
+
+#ifdef EAPI
+    s->ctx = ap_ctx_new(p);
+#endif /* EAPI */
 
     return s;
 }

+---------------------------------------------------------------------------
| Add the ap_global_ctx variable and the new
| ap_add_config_define() function. Additionally the
| implementation of the additional `new_connection' module hook
| is added plus the initialization of one more `ctx' variable.
+---------------------------------------------------------------------------
Index: src/main/http_main.c
--- src/main/http_main.c	1998/10/07 11:28:19	1.1.1.4
+++ src/main/http_main.c	1998/11/08 15:34:28	1.13
@@ -249,6 +249,9 @@
 int ap_listenbacklog;
 int ap_dump_settings;
 API_VAR_EXPORT int ap_extended_status = 0;
+#ifdef EAPI
+API_VAR_EXPORT ap_ctx *ap_global_ctx;
+#endif /* EAPI */
 
 /*
  * The max child slot ever assigned, preserved across restarts.  Necessary
@@ -413,6 +416,16 @@
     }
 }
 
+#ifdef EAPI
+API_EXPORT(void) ap_add_config_define(const char *define)
+{
+    char **var;
+    var = (char **)ap_push_array(ap_server_config_defines);
+    *var = ap_pstrdup(pcommands, define);
+    return;
+}
+#endif /* EAPI */
+
 static APACHE_TLS int volatile exit_after_unblock = 0;
 
 #ifdef GPROF
@@ -2945,7 +2958,24 @@
     conn->remote_addr = *remaddr;
     conn->remote_ip = ap_pstrdup(conn->pool,
 			      inet_ntoa(conn->remote_addr.sin_addr));
+#ifdef EAPI
+    conn->ctx = ap_ctx_new(conn->pool);
+#endif /* EAPI */
 
+#ifdef EAPI
+    /*
+     * Invoke the `new_connection' hook of modules to let them do
+     * some connection dependent actions before we go on with
+     * processing the request on this connection.
+     */
+    {
+        module *m;
+        for (m = top_module; m != NULL; m = m->next)
+            if (m->new_connection != NULL)
+                (*m->new_connection)(conn);
+    }
+#endif /* EAPI */
+
     return conn;
 }
 
@@ -3460,6 +3490,20 @@
     ap_server_pre_read_config  = ap_make_array(pcommands, 1, sizeof(char *));
     ap_server_post_read_config = ap_make_array(pcommands, 1, sizeof(char *));
     ap_server_config_defines   = ap_make_array(pcommands, 1, sizeof(char *));
+
+#ifdef EAPI
+    ap_hook_init();
+    ap_hook_configure("ap::buff::read", 
+                      AP_HOOK_SIG4(int,ptr,ptr,int), AP_HOOK_TOPMOST);
+    ap_hook_configure("ap::buff::write",  
+                      AP_HOOK_SIG4(int,ptr,ptr,int), AP_HOOK_TOPMOST);
+    ap_hook_configure("ap::buff::sendwithtimeout", 
+                      AP_HOOK_SIG4(int,ptr,ptr,int), AP_HOOK_TOPMOST);
+    ap_hook_configure("ap::buff::recvwithtimeout", 
+                      AP_HOOK_SIG4(int,ptr,ptr,int), AP_HOOK_TOPMOST);
+
+    ap_global_ctx = ap_ctx_new(NULL);
+#endif /* EAPI */
 }
 
 #ifndef MULTITHREAD

+---------------------------------------------------------------------------
| Just add the initialization of the `ctx' variable for
| conn_rec structures.
+---------------------------------------------------------------------------
Index: src/main/http_request.c
--- src/main/http_request.c	1998/10/07 11:28:20	1.1.1.4
+++ src/main/http_request.c	1998/11/08 15:34:29	1.3
@@ -1250,6 +1250,9 @@
     new->no_cache        = r->no_cache;
     new->no_local_copy   = r->no_local_copy;
     new->read_length     = r->read_length;     /* We can only read it once */
+#ifdef EAPI
+    new->ctx             = r->ctx;
+#endif /* EAPI */
 
     ap_table_setn(new->subprocess_env, "REDIRECT_STATUS",
 	ap_psprintf(r->pool, "%d", r->status));

+---------------------------------------------------------------------------
| Just add the initialization of the `ctx' variable for
| request_rec structures.
+---------------------------------------------------------------------------
Index: src/main/http_protocol.c
--- src/main/http_protocol.c	1998/10/07 11:28:20	1.1.1.4
+++ src/main/http_protocol.c	1998/11/08 15:34:29	1.4
@@ -821,6 +821,10 @@
     r->status          = HTTP_REQUEST_TIME_OUT;  /* Until we get a request */
     r->the_request     = NULL;
 
+#ifdef EAPI
+    r->ctx = ap_ctx_new(r->pool);
+#endif /* EAPI */
+
 #ifdef CHARSET_EBCDIC
     ap_bsetflag(r->connection->client, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 1);
 #endif
@@ -970,6 +974,11 @@
     rnew->read_body       = REQUEST_NO_BODY;
 
     rnew->main = (request_rec *) r;
+
+#ifdef EAPI
+    rnew->ctx = r->ctx;
+#endif /* EAPI */
+
 }
 
 void ap_finalize_sub_req_protocol(request_rec *sub)

+---------------------------------------------------------------------------
| Add additional logging functions to the CustomLog directive
| which can be used by other modules to create additional
| logfile tags. Actually we add two types of hooks: One hook
| for intercepting the new and generic %x (eXtension) tag and
| one hook for creating new %x tags at all.
+---------------------------------------------------------------------------
Index: src/modules/standard/mod_log_config.c
--- src/modules/standard/mod_log_config.c	1998/10/07 11:28:35	1.1.1.4
+++ src/modules/standard/mod_log_config.c	1998/11/08 15:34:29	1.14
@@ -420,6 +420,20 @@
     return ap_psprintf(r->pool, "%ld", (long) getpid());
 }
 
+#ifdef EAPI
+static const char *log_ext_var(request_rec *r, char *a)
+{
+    char *result;
+
+    result = NULL;
+    ap_hook_use("ap::log_config::expand_x_variable",
+                AP_HOOK_SIG3(ptr,ptr,ptr),
+                AP_HOOK_DECLINE(NULL),
+                &result, r, a);
+    return result;
+}
+#endif /* EAPI */
+
 /*****************************************************************
  *
  * Parsing the log format string
@@ -485,20 +499,49 @@
     {
         'P', log_child_pid, 0
     },
+#ifdef EAPI
     {
+        'x', log_ext_var, 0
+    },
+#endif /* EAPI */
+    {
         '\0'
     }
 };
 
+#ifdef EAPI
+static struct log_item_list *find_log_func(pool *p, char k)
+#else /* EAPI */
 static struct log_item_list *find_log_func(char k)
+#endif /* EAPI */
 {
     int i;
+#ifdef EAPI
+    struct log_item_list *lil;
+	void *func;
+#endif /* EAPI */
 
     for (i = 0; log_item_keys[i].ch; ++i)
         if (k == log_item_keys[i].ch) {
             return &log_item_keys[i];
         }
 
+#ifdef EAPI
+    func = NULL;
+    if (ap_hook_use("ap::log_config::register_function", 
+                    AP_HOOK_SIG2(ptr,char),
+                    AP_HOOK_DECLINE(NULL),
+                    &func, k) && func != NULL) {
+        lil = (struct log_item_list *)ap_pcalloc(p, sizeof(struct log_item_list));
+        if (lil == NULL)
+            return NULL;
+        lil->ch = k;
+        lil->func = func;
+        lil->want_orig_default = 0;
+        return lil;
+    }
+#endif /* EAPI */
+
     return NULL;
 }
 
@@ -593,7 +636,11 @@
             break;
 
         default:
+#ifdef EAPI
+            l = find_log_func(p, *s++);
+#else /* EAPI */
             l = find_log_func(*s++);
+#endif /* EAPI */
             if (!l) {
                 char dummy[2];
 

+---------------------------------------------------------------------------
| Add hooks to the scheme processing to allow other modules to
| recognize more schemes by intercepting this processing.
+---------------------------------------------------------------------------
Index: src/modules/proxy/mod_proxy.c
--- src/modules/proxy/mod_proxy.c	1998/09/22 08:43:11	1.1.1.3
+++ src/modules/proxy/mod_proxy.c	1998/11/08 15:34:29	1.7
@@ -214,6 +214,9 @@
 static int proxy_fixup(request_rec *r)
 {
     char *url, *p;
+#ifdef EAPI
+    int rc;
+#endif /* EAPI */
 
     if (!r->proxyreq || strncmp(r->filename, "proxy:", 6) != 0)
 	return DECLINED;
@@ -221,6 +224,14 @@
     url = &r->filename[6];
 
 /* canonicalise each specific scheme */
+#ifdef EAPI
+    if (ap_hook_use("ap::proxy::canon",
+                    AP_HOOK_SIG3(int,ptr,ptr),
+                    AP_HOOK_DECLINE(DECLINED),
+                    &rc, r, url) && rc != DECLINED)
+        return rc;  
+    else
+#endif /* EAPI */
     if (strncasecmp(url, "http:", 5) == 0)
 	return ap_proxy_http_canon(r, url + 5, "http", DEFAULT_HTTP_PORT);
     else if (strncasecmp(url, "ftp:", 4) == 0)
@@ -236,6 +247,30 @@
 static void proxy_init(server_rec *r, pool *p)
 {
     ap_proxy_garbage_init(r, p);
+
+#ifdef EAPI
+    /* 
+     * export: ap_proxy_http_canon() as `ap::proxy::http::canon'
+     */
+    ap_hook_configure("ap::proxy::http::canon", 
+                      AP_HOOK_SIG5(int,ptr,ptr,ptr,int), AP_HOOK_TOPMOST);
+    ap_hook_register("ap::proxy::http::canon", 
+                     ap_proxy_http_canon, AP_HOOK_NOCTX);
+    /* 
+     * export: ap_proxy_http_handler() as `ap::proxy::http::handler'
+     */
+    ap_hook_configure("ap::proxy::http::handler", 
+                      AP_HOOK_SIG6(int,ptr,ptr,ptr,ptr,int), AP_HOOK_TOPMOST);
+    ap_hook_register("ap::proxy::http::handler", 
+                     ap_proxy_http_handler, AP_HOOK_NOCTX);
+    /* 
+     * export: ap_proxyerror() as `ap::proxy::error'
+     */
+    ap_hook_configure("ap::proxy::error", 
+                      AP_HOOK_SIG3(int,ptr,ptr), AP_HOOK_TOPMOST);
+    ap_hook_register("ap::proxy::error", 
+                     ap_proxyerror, AP_HOOK_NOCTX);
+#endif /* EAPI */
 }
 
 
@@ -368,6 +403,14 @@
 		/* CONNECT is a special method that bypasses the normal
 		 * proxy code.
 		 */
+#ifdef EAPI
+		if (!ap_hook_use("ap::proxy::handler",
+				 AP_HOOK_SIG7(int,ptr,ptr,ptr,ptr,int,ptr),
+				 AP_HOOK_DECLINE(DECLINED),
+				 &rc, r, cr, url, 
+				 ents[i].hostname, ents[i].port, 
+				 ents[i].protocol) || rc == DECLINED) {
+#endif /* EAPI */
 		if (r->method_number == M_CONNECT)
 		    rc = ap_proxy_connect_handler(r, cr, url, ents[i].hostname,
 					       ents[i].port);
@@ -377,6 +420,9 @@
 					    ents[i].port);
 		else
 		    rc = DECLINED;
+#ifdef EAPI
+		}
+#endif /* EAPI */
 
 		/* an error or success */
 		if (rc != DECLINED && rc != HTTP_BAD_GATEWAY)
@@ -390,6 +436,14 @@
  * give up??
  */
     /* handle the scheme */
+#ifdef EAPI
+    if (ap_hook_use("ap::proxy::handler",
+		    AP_HOOK_SIG7(int,ptr,ptr,ptr,ptr,int,ptr),
+		    AP_HOOK_DECLINE(DECLINED),
+		    &rc, r, cr, url, 
+                    NULL, 0, scheme) && rc != DECLINED)
+        return rc;
+#endif /* EAPI */
     if (r->method_number == M_CONNECT)
 	return ap_proxy_connect_handler(r, cr, url, NULL, 0);
     if (strcasecmp(scheme, "http") == 0)

+---------------------------------------------------------------------------
| Add hooks to the HTTP processing to allow other modules
| to enhance it by intercepting this processing.
+---------------------------------------------------------------------------
Index: src/modules/proxy/proxy_http.c
--- src/modules/proxy/proxy_http.c	1998/09/22 08:43:13	1.1.1.3
+++ src/modules/proxy/proxy_http.c	1998/11/08 15:34:29	1.8
@@ -206,6 +206,12 @@
 	return HTTP_BAD_REQUEST;
     urlptr += 3;
     destport = DEFAULT_HTTP_PORT;
+#ifdef EAPI
+    ap_hook_use("ap::proxy::http::handler::set_destport", 
+                AP_HOOK_SIG2(int,ptr), 
+                AP_HOOK_TOPMOST,
+                &destport, r);
+#endif /* EAPI */
     strp = strchr(urlptr, '/');
     if (strp == NULL) {
 	desthost = ap_pstrdup(p, urlptr);
@@ -301,13 +307,41 @@
     f = ap_bcreate(p, B_RDWR | B_SOCKET);
     ap_bpushfd(f, sock, sock);
 
+#ifdef EAPI
+    {
+        char *errmsg = NULL;
+        ap_hook_use("ap::proxy::http::handler::new_connection", 
+                    AP_HOOK_SIG3(ptr,ptr,ptr), 
+                    AP_HOOK_DECLINE(NULL),
+                    &errmsg, r, f);
+        if (errmsg != NULL)
+            return ap_proxyerror(r, errmsg);
+    }
+#endif /* EAPI */
+
     ap_hard_timeout("proxy send", r);
     ap_bvputs(f, r->method, " ", proxyhost ? url : urlptr, " HTTP/1.0" CRLF,
 	   NULL);
+#ifdef EAPI
+    {
+	int rc = DECLINED;
+	ap_hook_use("ap::proxy::http::handler::write_host_header", 
+		    AP_HOOK_SIG6(int,ptr,ptr,ptr,int,ptr), 
+		    AP_HOOK_DECLINE(DECLINED),
+		    &rc, r, f, desthost, destport, destportstr);
+        if (rc == DECLINED) {
+	    if (destportstr != NULL && destport != DEFAULT_HTTP_PORT)
+		ap_bvputs(f, "Host: ", desthost, ":", destportstr, CRLF, NULL);
+	    else
+		ap_bvputs(f, "Host: ", desthost, CRLF, NULL);
+        }
+    }
+#else /* EAPI */
     if (destportstr != NULL && destport != DEFAULT_HTTP_PORT)
 	ap_bvputs(f, "Host: ", desthost, ":", destportstr, CRLF, NULL);
     else
 	ap_bvputs(f, "Host: ", desthost, CRLF, NULL);
+#endif /* EAPI */
 
     if (conf->viaopt == via_block) {
 	/* Block all outgoing Via: headers */
