Index: /gsdl/trunk/runtime-src/src/recpt/Makefile.in
===================================================================
--- /gsdl/trunk/runtime-src/src/recpt/Makefile.in	(revision 19258)
+++ /gsdl/trunk/runtime-src/src/recpt/Makefile.in	(revision 19259)
@@ -28,4 +28,6 @@
 COMMON_DIR = $(GSDL_DIR)/common-src
 RUNTIME_DIR = $(GSDL_DIR)/runtime-src
+
+GSDLOS = @gsdlos@
 
 INDEXERS_DIR = $(COMMON_DIR)/indexers
@@ -71,4 +73,22 @@
 Z3950_INCLUDES = 
 Z3950_LIBS = 
+endif
+
+USE_APACHE_HTTPD=@USE_APACHE_HTTPD@
+ifeq ($(USE_APACHE_HTTPD), 1)
+APACHE_OBJS = string_pool.o mod_gsdl.o
+
+APXS=$(GSDL_DIR)/apache-httpd/$(GSDLOS)/bin/apxs
+APXS_CFLAGS=`$(APXS) -q CFLAGS`   
+APXS_CFLAGS_SHLIB=`$(APXS) -q CFLAGS_SHLIB`   
+APXS_INCLUDEDIR=`$(APXS) -q INCLUDEDIR`   
+APXS_LIBEXECDIR=`$(APXS) -q LIBEXECDIR`
+APXS_LDFLAGS_SHLIB=`$(APXS) -q LDFLAGS_SHLIB`
+APXS_SYSCONFDIR=`$(APXS) -q SYSCONFDIR`
+APXS_LIBS_SHLIB=`$(APXS) -q LIBS_SHLIB`
+APACHE_MODULE = mod_gsdl.so
+else
+APACHE_OBJS =
+APACHE_MODULE = mod_gsdl.so
 endif
 
@@ -95,10 +115,4 @@
 
 
-.SUFFIXES:
-.SUFFIXES: .cpp .o
-.cpp.o:
-	$(CXXCOMPILE) $< 
-
-
 SOURCES = \
 	action.cpp \
@@ -113,4 +127,5 @@
 	cgiwrapper.cpp \
 	collectoraction.cpp \
+	configaction.cpp \
         converter.cpp \
 	datelistbrowserclass.cpp \
@@ -157,4 +172,5 @@
 	cgiwrapper.o \
 	collectoraction.o \
+	configaction.o \
         converter.o \
 	datelistbrowserclass.o \
@@ -187,5 +203,5 @@
 	usersaction.o \
 	vlistbrowserclass.o \
-	wizardaction.o
+	wizardaction.o 
 
 LIBRARY = gsdlrecpt.a
@@ -208,5 +224,5 @@
 
 # Default target: make both gsdlrecpt.a and the library executable
-all: $(LIBRARY) $(EXECUTABLE)
+all: $(LIBRARY) $(EXECUTABLE) $(APACHE_MODULE)
 
 gsdlrecpt.a: $(OBJECTS)
@@ -218,9 +234,23 @@
 	$(CXXLINK) $(EXECUTABLE_OBJECTS) $(LIBS)
 
+mod_gsdl.o: mod_gsdl.cpp
+	$(CXX) -c  $(CXXFLAGS) $(DEFS) $(INCLUDES) -D_APACHE_MOD=2 -fPIC -I$(APXS_INCLUDEDIR) -I. -iquote $(APXS_CFLAGS) $(APXS_CFLAGS_SHLIB) -Wall -o $@ $< 
+
+mod_gsdl.so: $(APACHE_OBJS) $(LIBRARY)
+	$(CXX) -fPIC -shared -o $@ $(APACHE_OBJS) $(APXS_LIBS_SHLIB) $(LIBRARY) $(GSDL_LIBS) $(LIBS)
+
+
+.SUFFIXES:
+.SUFFIXES: .cpp .o
+.cpp.o:
+	$(CXXCOMPILE) $< 
+
+
 install: $(EXECUTABLE)
 	$(INSTALL) -m 755 -s $(EXECUTABLE) $(GSDL_DIR)/cgi-bin
+	$(GSDL_DIR)/apache-httpd/$(GSDLOS)/bin/apxs  -i -n gsdl mod_gsdl.so
 
 clean:
-	rm -f $(OBJECTS) $(LIBRARY) $(EXECUTABLE)
+	rm -f $(OBJECTS) $(LIBRARY) $(EXECUTABLE) $(APACHE_MODULE) $(APACHE_OBJS)
 
 distclean:
Index: /gsdl/trunk/runtime-src/src/recpt/mod_gsdl.cpp
===================================================================
--- /gsdl/trunk/runtime-src/src/recpt/mod_gsdl.cpp	(revision 19259)
+++ /gsdl/trunk/runtime-src/src/recpt/mod_gsdl.cpp	(revision 19259)
@@ -0,0 +1,604 @@
+/**********************************************************************
+ *
+ * mod_gsdl.cpp -- front end for apache 1.3 or 2.x module
+ * Copyright (C) 2003 DL Consulting Ltd
+ *
+ * A component of the Greenstone digital library software
+ * from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *********************************************************************/
+
+#include "httpd.h"
+#include "http_core.h"
+#include "http_config.h"
+#include "http_protocol.h"
+#include "http_main.h"
+#include "util_script.h"
+#include "ap_config.h"
+#include "http_log.h"
+
+
+#if _APACHE_MOD >= 2
+
+#include "ap_compat.h"
+
+// In addition to the backward compatible features defined in
+// ap_compat.h, define 
+
+typedef apr_pool_t ap_pool; // map old type to new apr_* version
+
+// In Apache 2.x, ap_log_error takes extra parameter -- status code
+// from the previous command; define macro to automatically add in
+// surrogate value of 0 for this
+#define ap_log_error(file,line,level,server,fmt) \
+	ap_log_error(file,line,level,0,server,fmt)
+
+#endif
+
+#if defined(USE_MYSQL)
+#include "mysqlclass.h"
+#endif
+#if defined(USE_ACCESS)
+#include "accessclass.h"
+#endif
+
+#include "maincfg.h"
+#include "string_pool.h"
+
+#include "receptionist.h"
+#include "cgiwrapper.h"
+#include "cgiutils.h"
+#include "fileutil.h"
+#include "nullproto.h"
+#include "collectserver.h"
+#include "filter.h"
+#include "browsefilter.h"
+#include "mgqueryfilter.h"
+#include "infodbclass.h"
+#include "mgsource.h"
+#include "mgsearch.h"
+#include "collectset.h"
+
+#include "gdbmclass.h"
+
+#include "action.h"
+#include "pageaction.h"
+#include "queryaction.h"
+#include "documentaction.h"
+#include "extlinkaction.h"
+#include "phindaction.h"
+#if defined(USE_MYSQL) || defined(USE_ACCESS)
+#include "orderaction.h"
+#endif
+#include "configaction.h"
+
+#include "browserclass.h"
+#include "vlistbrowserclass.h"
+#include "hlistbrowserclass.h"
+#include "datelistbrowserclass.h"
+#include "invbrowserclass.h"
+#include "pagedbrowserclass.h"
+#include "phindbrowserclass.h"
+
+#include <strstream>
+
+receptionist recpt;
+nullproto nproto;
+
+extern "C" module MODULE_VAR_EXPORT gsdl_module;
+
+typedef struct {
+  char *config_gsdlhome;
+  char *config_collecthome;
+  char *config_httpprefix;
+  char *config_httpweb;
+} gsdl_config;
+
+static void *gsdl_create_config(ap_pool *p, server_rec *s) {
+
+#if _APACHE_MOD >= 2
+  gsdl_config *cfg = (gsdl_config *)apr_pcalloc(p, sizeof(gsdl_config));
+#else
+  gsdl_config *cfg = (gsdl_config *)ap_pcalloc(p, sizeof(gsdl_config));
+#endif
+
+  return (void *)cfg;
+}
+
+static void *gsdl_create_dir_config(ap_pool *p, char *path) {
+
+  return (gsdl_config *) gsdl_create_config(p, NULL);
+}
+
+static const char *gsdl_cmd(cmd_parms *cmd, void *mconfig,
+			    char *val) {
+
+  server_rec *s = cmd->server;
+  gsdl_config *cfg = (gsdl_config *) ap_get_module_config(s->module_config, &gsdl_module);
+
+  if (strcmp(cmd->cmd->name, "gsdlhome") == 0) {
+    cfg->config_gsdlhome = val;
+  } else if (strcmp(cmd->cmd->name, "collecthome") == 0) {
+    cfg->config_collecthome = val;
+  } else if (strcmp(cmd->cmd->name, "httpprefix") == 0) {
+    cfg->config_httpprefix = val;
+  } else if (strcmp(cmd->cmd->name, "httpweb") == 0) {
+    cfg->config_httpweb = val;
+  }
+
+  return NULL;
+}
+
+#if _APACHE_MOD < 2
+static void gsdl_exit(void* d) {
+#else
+static apr_status_t gsdl_exit(void* d) {
+#endif
+
+#if defined(USE_ACCESS)
+  // shut down com
+  CoUninitialize();
+#endif  
+
+#if _APACHE_MOD >= 2
+  return APR_SUCCESS; 
+#endif
+}
+
+#if _APACHE_MOD < 2
+static void gsdl_init(server_rec *s, ap_pool *p) {
+#else
+static void gsdl_init(ap_pool *p, server_rec *s) {
+#endif
+
+  // Register gsdl_exit has cleanup operation for when pchild (process id
+  // of child) exits
+#if _APACHE_MOD >= 2
+  apr_pool_cleanup_register(p,s, apr_pool_cleanup_null, gsdl_exit);
+#else
+  ap_register_cleanup(p,s, ap_null_cleanup, gsdl_exit);
+#endif
+
+  recpt.loaded = false;
+
+  gsdl_config *cfg = (gsdl_config *) ap_get_module_config(s->module_config, &gsdl_module);
+
+  if (!cfg->config_gsdlhome) {
+    ap_log_error("", 0, APLOG_ERR, s, "gsdlhome not set\n");
+    return;
+  }
+  text_t gsdlhome = cfg->config_gsdlhome;
+
+  if (!directory_exists(gsdlhome)) {
+    ap_log_error("", 0, APLOG_ERR, s, "gsdlhome directory does not exist\n");
+    return;
+  }
+
+  if (!cfg->config_collecthome) {
+    ap_log_error("", 0, APLOG_ERR, s, "collecthome not set\n");
+    return;
+  }
+  text_t collecthome = cfg->config_collecthome;
+
+  if (!directory_exists(collecthome)) {
+    ap_log_error("", 0, APLOG_ERR, s, "collecthome directory does not exist\n");
+    return;
+  }
+
+
+  if (!cfg->config_httpprefix) {
+    ap_log_error("", 0, APLOG_ERR, s, "httpprefix not set\n");
+    return;
+  }
+
+  if (!cfg->config_httpweb) {
+    ap_log_error("", 0, APLOG_ERR, s, "httpweb not set\n");
+    return;
+  }
+    
+  text_t httpprefix = cfg->config_httpprefix;
+  text_t httpweb = cfg->config_httpweb;
+
+  text_t collection = "";
+
+  collectset *cservers = new collectset();
+
+  cservers->add_all_collections(gsdlhome,collecthome);
+
+  // set up the null protocol
+  nproto.set_collectset(cservers);
+  
+  // add the protocol to the receptionist
+  recpt.add_protocol(&nproto);
+
+  // add database object to receptionist
+#if defined(USE_MYSQL)
+  mysqlclass *db = new mysqlclass();
+#elif defined(USE_ACCESS)
+  // start up com
+  if(FAILED(CoInitialize(NULL))) {
+    cout << "CoInitialize failed\n";
+    exit(-1);
+  }
+  accessclass *db = new accessclass();
+#else
+
+  // not using either mysql or access database - we'll use the gdbmclass
+  // class as a filler (but most likely won't work) - only useful
+  // if creating a binary that doesn't require access to the database
+  dbclass *db = new gdbmclass();
+
+#endif
+
+#if defined(USE_MYSQL) || defined(USE_ACCESS) 
+  recpt.add_dbclass(db);
+#endif
+
+  // the list of actions.
+  pageaction *apageaction = new pageaction();
+  apageaction->set_receptionist(&recpt);
+  recpt.add_action(apageaction);
+  
+  queryaction *aqueryaction = new queryaction();
+  aqueryaction->set_receptionist(&recpt);
+  recpt.add_action(aqueryaction);
+  
+  documentaction *adocumentaction = new documentaction();
+  adocumentaction->set_receptionist(&recpt);
+  recpt.add_action(adocumentaction);
+
+  extlinkaction *anextlinkaction = new extlinkaction();
+  recpt.add_action(anextlinkaction);
+
+  phindaction *aphindaction = new phindaction();
+  recpt.add_action(aphindaction);
+
+#if defined(USE_MYSQL) || defined(USE_ACCESS)
+  orderaction *aorderaction = new orderaction();
+  aorderaction->set_receptionist(&recpt);
+  recpt.add_action(aorderaction);
+#endif
+
+  configaction *aconfigaction = new configaction();
+  aconfigaction->set_receptionist(&recpt);
+  recpt.add_action(aconfigaction);
+
+  // list of browsers
+  vlistbrowserclass *avlistbrowserclass = new vlistbrowserclass();
+  recpt.add_browser(avlistbrowserclass);
+  recpt.setdefaultbrowser("VList");
+
+  hlistbrowserclass *ahlistbrowserclass = new hlistbrowserclass();
+  recpt.add_browser(ahlistbrowserclass);
+
+  datelistbrowserclass *adatelistbrowserclass = new datelistbrowserclass();
+  recpt.add_browser(adatelistbrowserclass);
+
+  invbrowserclass *ainvbrowserclass = new invbrowserclass();
+  recpt.add_browser(ainvbrowserclass);
+
+  pagedbrowserclass *apagedbrowserclass = new pagedbrowserclass();
+  recpt.add_browser(apagedbrowserclass);
+
+  phindbrowserclass *aphindbrowserclass = new phindbrowserclass();;
+  recpt.add_browser(aphindbrowserclass);
+  
+  // configure everything
+  recpt.configure("gsdlhome", gsdlhome);
+  recpt.configure("collecthome", collecthome);
+  recpt.configure("collection", collection);
+  recpt.configure("httpweb", httpweb);
+  recpt.configure("httpprefix", httpprefix);
+  // set httpprefixfull - if httpprefix is a relative path we need to get
+  // the server name and port from the web server environment (note that
+  // gwcgi and gwcgifull will be configured for each page request (in gsdl_handler)
+  // as we need to know that directory info etc.)
+  text_t httpprefixfull = httpprefix;
+  if ((httpprefixfull.size() < 7) || 
+      (substr(httpprefixfull.begin(), httpprefixfull.begin()+7) != "http://")) {
+    if (s->server_hostname && s->port) {
+      httpprefixfull = "http://" + text_t(s->server_hostname) + ":" + text_t(s->port) + httpprefixfull;
+    }
+  }
+  recpt.configure("httpprefixfull", httpprefixfull);
+
+  // read in main.cfg file
+  if (!main_cfg_read(recpt, gsdlhome, collecthome, collection)) {
+    ap_log_error("", 0, APLOG_ERR, s, "failed to read main.cfg file\n");
+    return;
+  }
+
+  text_t error_file = filename_cat (gsdlhome, "etc", "error.txt");
+  char *eout = error_file.getcstr();
+  ofstream errout (eout, ios::app);
+  delete eout;
+
+  // initialise the library software
+  if (!recpt.init(errout)) {
+    ap_log_error("", 0, APLOG_ERR, s, "Greenstone failed to initialize\n");
+    errout.close();
+    return;
+  }
+
+  errout.close();
+
+  // set flag so gsdl_handler can check that everything initialized
+  // successfully
+  recpt.loaded = true;
+}
+
+
+#if _APACHE_MOD < 2
+
+typedef const char *(*CMD_HAND_TYPE) ();
+static command_rec gsdl_cmds[] = {
+  {"gsdlhome", (CMD_HAND_TYPE)gsdl_cmd,
+   (void *)XtOffsetOf(gsdl_config, config_gsdlhome),
+   OR_ALL, TAKE1, "GSDLHOME directory."},
+  {"collecthome", (CMD_HAND_TYPE)gsdl_cmd,
+   (void *)XtOffsetOf(gsdl_config, config_collecthome),
+   OR_ALL, TAKE1, "COLLECTHOME directory."},
+  {"httpprefix", (CMD_HAND_TYPE)gsdl_cmd,
+   (void *)XtOffsetOf(gsdl_config, config_httpprefix),
+   OR_ALL, TAKE1, "GSDLHOME http path."},
+  {"httpweb", (CMD_HAND_TYPE)gsdl_cmd,
+   (void *)XtOffsetOf(gsdl_config, config_httpweb),
+   OR_ALL, TAKE1, "GSDLHOME http web path."},
+  {NULL, NULL, NULL, 0, cmd_how(0), NULL}
+};
+#else
+
+/* 
+static const char 
+*set_max_cache_size(cmd_parms *parms, void *in_struct_ptr, const char *arg)
+{
+    apr_size_t val;
+
+    return NULL;
+}
+
+  AP_INIT_TAKE1("MCacheSize", set_max_cache_size, NULL, RSRC_CONF,
+		"The maximum amount of memory used by the cache in KBytes"),
+
+*/
+
+// const char *(*cmd_func)();
+
+static const command_rec gsdl_cmds[] = {
+  AP_INIT_TAKE1("gsdlhome", (cmd_func)gsdl_cmd, NULL, OR_ALL,"GSDLHOME directory."),
+  AP_INIT_TAKE1("collecthome", (cmd_func)gsdl_cmd, NULL, OR_ALL,"COLLECTHOME directory."),
+  AP_INIT_TAKE1("httpprefix", (cmd_func)gsdl_cmd, NULL, OR_ALL,"GSDLHOME http path."),
+  AP_INIT_TAKE1("httpweb", (cmd_func)gsdl_cmd, NULL, OR_ALL,"GSDLHOME http web path."),
+  {NULL}
+};
+
+
+#endif
+
+static int gsdl_handler(request_rec *r) {
+
+  if (strcmp(r->handler, "gsdl")) {
+    return DECLINED;
+  }
+
+  // check that everything has been initialized
+  if (!recpt.loaded) {
+    ap_log_error("", 0, APLOG_ERR, r->server,  "gsdl_handler: attempt to use uninitialized receptionist - aborting\n");
+    return 500;
+  }
+
+  gsdl_config *cfg = (gsdl_config *) ap_get_module_config(r->server->module_config, &gsdl_module);
+
+  if (!cfg->config_gsdlhome) {
+    ap_log_error("", 0, APLOG_ERR, r->server,  "gsdl_handler: gsdlhome not set\n");
+    return 500;
+  }
+
+  if (!cfg->config_collecthome) {
+    ap_log_error("", 0, APLOG_ERR, r->server,  "gsdl_handler: collecthome not set\n");
+    return 500;
+  }
+
+  // configure gwcgi and gwcgifull
+  recpt.configure("gwcgi", r->uri);
+  recpt.configure("gwcgifull", "http://" + text_t(r->server->server_hostname) + 
+		  ":" + text_t(r->server->port) + r->uri);
+  
+  string_pool str_pool;
+
+  text_t gsdlhome = cfg->config_gsdlhome;
+
+  text_t error_file = filename_cat (gsdlhome, "etc", "error.txt");
+  char *eout = str_pool.get_cstr_from_pool(error_file);
+  ofstream errout (eout, ios::app);
+
+  text_t argstr;
+  fileupload_tmap fileuploads;
+
+  char *request_method_str = getenv("REQUEST_METHOD");
+  char *content_length_str = getenv("CONTENT_LENGTH");
+  if (request_method_str != NULL && strcmp(request_method_str, "POST") == 0 &&
+      content_length_str != NULL)  {
+    // POST form data
+    long content_length = (content_length_str ? atoi(content_length_str) : 0);
+    if (content_length > 0) {
+#ifdef __WIN32__
+      // On Windows it is important that standard input be read in binary
+      // mode, otherwise end of line "<CR><LF>" is turned into <LF> only
+      // which breaks the MIME standard (and our parsing code!)
+      
+      int result = _setmode( _fileno( stdin ), _O_BINARY );
+      if( result == -1 ) {
+	cerr << "Warning: Failed to set standard input to binary mode." << endl;
+	cerr << "         Parsing of multi-part MIME will most likely fail" << endl;
+      }
+#endif
+      
+      long length = content_length;
+      unsigned char * buffer = new unsigned char[content_length];
+      
+      int chars_read = fread(buffer,1,content_length,stdin);
+      
+      if (chars_read != content_length) {
+	cerr << "Warning: mismatch between CONTENT_LENGTH and data read from standard in" << endl;
+      }
+      
+      argstr.setcarr((char *)buffer, content_length);     
+      
+      text_t content_type;
+      char *content_type_str = getenv("CONTENT_TYPE");
+      if (content_type_str) content_type = content_type_str;
+      argstr = parse_post_data(content_type, argstr, fileuploads, gsdlhome);
+    }
+  } else {
+    
+    if (r->args) argstr = r->args;
+  }
+
+  // parse the cgi arguments and produce the resulting page if there
+  // have been no errors so far
+  cgiargsclass args;
+  text_tmap fastcgienv; // Not being used in this case
+  if (!recpt.parse_cgi_args (argstr, fileuploads, args, errout, fastcgienv)) {
+    errout.close();
+    ap_log_error("", 0, APLOG_ERR, r->server,  "parse_cgi_args failed\n");
+    return 500;
+  } 
+
+  ostrstream pageout;
+
+  // get http headers
+  text_tmap headers;
+  recpt.get_cgihead_info(args, headers, errout, fastcgienv);
+
+  if (headers.find("Location") != headers.end()) {
+    // redirect
+    char *val = str_pool.get_cstr_from_pool(headers.find("Location")->second);
+#if _APACHE_MOD >= 2
+    apr_table_set(r->headers_out, "location", val);
+#else
+    ap_table_set(r->headers_out, "location", val);
+#endif
+    return HTTP_MOVED_TEMPORARILY;
+  }
+
+  text_tmap::iterator here = headers.begin();
+  text_tmap::iterator end = headers.end();
+  while (here != end) {
+    text_t namet = (*here).first;
+    lc(namet);
+    char *name = str_pool.get_cstr_from_pool(namet);
+    char *val = str_pool.get_cstr_from_pool((*here).second);
+
+    if ((*here).first == "content-type") {
+#if _APACHE_MOD < 2
+      r->content_type = val;
+#else
+
+      char* val_copy = strdup(val); // if note freed by r->content_type => Memory leak!
+      ap_set_content_type(r, val_copy);
+#endif
+    } else if ((*here).first == "content-encoding") {
+      r->content_encoding = val;
+    } else {
+#if _APACHE_MOD >= 2
+      apr_table_set(r->headers_out, name, val);
+#else
+      ap_table_set(r->headers_out, name, val);
+#endif
+    }
+
+    here++;
+  }
+  ap_send_http_header(r);
+
+  if (!r->header_only) {
+    if (!recpt.produce_content(args, pageout, errout)) {
+      ap_log_error("", 0, APLOG_ERR, r->server,  "produce_content failed\n");
+      return 500;
+    } 
+    char *out = pageout.str();
+    ap_rwrite(out, pageout.pcount(), r);
+    pageout.rdbuf()->freeze(0);
+  }
+
+  errout.close();  
+
+  return OK;
+}
+
+#if _APACHE_MOD < 2
+
+static const handler_rec gsdl_handlers[] = { 
+  { "gsdl", gsdl_handler }, 
+  { NULL, NULL }
+};
+
+
+extern "C" {
+  module MODULE_VAR_EXPORT gsdl_module = {
+    STANDARD_MODULE_STUFF, 
+    NULL,                       /* module \initializer                  */
+    gsdl_create_dir_config,     /* create per-dir    config structures */
+    NULL,                       /* merge  per-dir    config structures */
+    gsdl_create_config,         /* create per-server config structures */
+    NULL,                       /* merge  per-server config structures */
+    gsdl_cmds,                  /* table of config file commands       */
+    gsdl_handlers,              /* [#8] MIME-typed-dispatched handlers */
+    NULL,                       /* [#1] URI to filename translation    */
+    NULL,                       /* [#4] validate user id from request  */
+    NULL,                       /* [#5] check if the user is ok _here_ */
+    NULL,                       /* [#3] check access by host address   */
+    NULL,                       /* [#6] determine MIME type            */
+    NULL,                       /* [#7] pre-run fixups                 */
+    NULL,                       /* [#9] log a transaction              */
+    NULL,                       /* [#2] header parser                  */
+    gsdl_init,                  /* child_init                          */
+    NULL,                       /* child_exit                          */
+    NULL                        /* [#0] post read-request              */
+#ifdef EAPI
+    ,NULL,                      /* EAPI: add_module                    */
+    NULL,                       /* EAPI: remove_module                 */
+    NULL,                       /* EAPI: rewrite_command               */
+    NULL,                       /* EAPI: new_connection                */
+    NULL                        /* EAPI: close_connection              */
+#endif
+  };
+};
+
+#else
+
+static void gsdl_register_hooks(ap_pool *p)
+{
+  ap_hook_child_init(gsdl_init,NULL,NULL,APR_HOOK_MIDDLE);
+  ap_hook_handler(gsdl_handler, NULL, NULL, APR_HOOK_MIDDLE);
+
+}
+
+extern "C" {
+  module AP_MODULE_DECLARE_DATA gsdl_module = {
+    STANDARD20_MODULE_STUFF, 
+    gsdl_create_dir_config,     /* create per-dir    config structures   */
+    NULL,                       /* merge  per-dir    config structures   */
+    gsdl_create_config,         /* create per-server config structures   */
+    NULL,                       /* merge  per-server config structures   */
+    gsdl_cmds,                  /* command handlers                      */
+    gsdl_register_hooks,        /* set up other request processing hooks */
+  };
+};
+#endif
Index: /gsdl/trunk/runtime-src/src/recpt/receptionist.cpp
===================================================================
--- /gsdl/trunk/runtime-src/src/recpt/receptionist.cpp	(revision 19258)
+++ /gsdl/trunk/runtime-src/src/recpt/receptionist.cpp	(revision 19259)
@@ -1448,4 +1448,5 @@
 }
 
+
 void receptionist::define_general_macros (cgiargsclass &args, outconvertclass &/*outconvert*/, 
 					  ostream &logout) {
@@ -1457,5 +1458,4 @@
   disp.setmacro ("httpweb", displayclass::defaultpackage, configinfo.httpweb);
   disp.setmacro ("httpprefix", displayclass::defaultpackage, configinfo.httpprefix);
-
 
   text_t compressedoptions = get_compressed_arg(args, logout);
@@ -1559,5 +1559,5 @@
     }
   }
-
+  
   if (!collection.empty()) {
     ColInfoResponse_t cinfo;
@@ -1566,10 +1566,28 @@
     if (collectproto != NULL) {
       collectproto->get_collectinfo (collection, cinfo, err, logout);
+
+
+      // This part of the code used to use "cinfo.httpprefix" regardless
+      // of the value it contained.  Since
+      // this can come back with an empty (in the case of gsdl_mod), the
+      // URL produced was invalid.
+      //
+      // Changed to test for empty first, and use configinfo.httpprefix as
+      // a "backup"
+      // 
+      // Point to consider: since configinfo.httpprefix has been offically 
+      // set as "httpprefix" in macros, it seems to make more sense to use
+      // always use that version and not the cinfo version at all.
+
+      text_t httpprefix 
+	= (!cinfo.httpprefix.empty()) ? cinfo.httpprefix : configinfo.httpprefix;
+    
       text_t httpcollection;
       if (!cinfo.httpdomain.empty()) httpcollection = "http://";
-      httpcollection += cinfo.httpdomain + cinfo.httpprefix + "/collect/"
+      httpcollection += cinfo.httpdomain + httpprefix + "/collect/"
 	+ collection; 
       disp.setmacro ("httpcollection", displayclass::defaultpackage,
 		     httpcollection); 
+      
       // as of gsdl 2.53, collect.cfg can specify macros
       if (cinfo.collection_macros.size() > 0) {
