Index: trunk/gsdl/src/recpt/Makefile.in
===================================================================
--- trunk/gsdl/src/recpt/Makefile.in	(revision 11997)
+++ trunk/gsdl/src/recpt/Makefile.in	(revision 11998)
@@ -55,4 +55,5 @@
 	   -I../../packages/mg/lib -I../../packages/mg/src/text \
            -I../../packages/expat/include \
+           -I../../packages/cgicc/include \
 	   -I../mgpp/lib -I../mgpp/text -I../..
 else 
@@ -61,4 +62,5 @@
 	   -I../../packages/mg/lib -I../../packages/mg/src/text \
            -I../../packages/expat/include \
+           -I../../packages/cgicc/include \
            -I../../packages/fcgi/include -I../mgpp/lib \
 	   -I../mgpp/text -I../..
@@ -93,5 +95,5 @@
 LDFLAGS = @LDFLAGS@
 GDBM_LIBS=@GDBM_LIBPATH@ -lgdbm
-LIBS = $(GDBM_LIBS) $(LC_LIBS) @LIBS@
+LIBS = $(GDBM_LIBS) $(LC_LIBS) -L../../packages/cgicc/lib -lcgicc @LIBS@
 GSDLOS = @gsdlos@
 INSTALL = @INSTALL@
@@ -109,5 +111,5 @@
 
 # in case gdbm.h/libgdbm.a are in a non-standard place...
-GDBM_OBJS=argdb.o authenaction.o collectoraction.o infodbclass.o userdb.o usersaction.o historydb.o librarymain.o nullproto.o queryaction.o z3950proto.o
+GDBM_OBJS=argdb.o authenaction.o collectoraction.o depositoraction.o wizardaction.o infodbclass.o userdb.o usersaction.o historydb.o librarymain.o nullproto.o queryaction.o z3950proto.o
 
 ifeq ($(USE_CORBA), 1)
@@ -154,5 +156,5 @@
                 userdb.h usersaction.h vlistbrowserclass.h hlistbrowserclass.h \
 		datelistbrowserclass.h invbrowserclass.h pagedbrowserclass.h \
-		htmlbrowserclass.h phindbrowserclass.h historydb.h collectoraction.h \
+		htmlbrowserclass.h phindbrowserclass.h historydb.h collectoraction.h depositoraction.h wizardaction.h \
 		phindaction.h summarise.h highlighttext.h gtiaction.h
 
@@ -176,5 +178,5 @@
 		vlistbrowserclass.cpp hlistbrowserclass.cpp datelistbrowserclass.cpp \
 		invbrowserclass.cpp pagedbrowserclass.cpp htmlbrowserclass.cpp \
-		phindbrowserclass.cpp  historydb.cpp collectoraction.cpp argdb.cpp \
+		phindbrowserclass.cpp  historydb.cpp collectoraction.cpp depositoraction.cpp wizardaction.cpp argdb.cpp \
 		browseactiontools.h formattools.cpp phindaction.cpp summarise.cpp \
 		highlighttext.cpp gtiaction.cpp
@@ -210,5 +212,5 @@
 		hlistbrowserclass.o datelistbrowserclass.o invbrowserclass.o \
 		pagedbrowserclass.o htmlbrowserclass.o phindbrowserclass.o \
-		historydb.o $(Z_COMOBJS) collectoraction.o phindaction.o \
+		historydb.o $(Z_COMOBJS) collectoraction.o depositoraction.o wizardaction.o phindaction.o \
 		summarise.o highlighttext.o gtiaction.o
 
Index: trunk/gsdl/src/recpt/cgiutils.cpp
===================================================================
--- trunk/gsdl/src/recpt/cgiutils.cpp	(revision 11997)
+++ trunk/gsdl/src/recpt/cgiutils.cpp	(revision 11998)
@@ -26,5 +26,7 @@
 #include "cgiutils.h"
 #include "gsdlunicode.h"
+#include "fileutil.h"
 #include "unitool.h" // in mg, for output_utf8_char
+
 
 static unsigned short hexdigit (unsigned short c) {
@@ -120,5 +122,8 @@
   text_t::const_iterator end = argstr.end();
   text_t key, value;
-  
+
+  text_tset multivalue;
+
+ 
   // extract out the key=value pairs
   while (here != end) {
@@ -140,12 +145,27 @@
       // again before use) - it should use an array instead
       const cgiarginfo *info = argsinfo.getarginfo (key);
-      if (info != NULL && info->multiplevalue) {
-	text_t newvalue = args[key];
-	if (args.lookupcgiarg(key).source == cgiarg_t::cgi_arg) newvalue += ",";
-	newvalue += encode_commas(value);
-	args.setarg (key, newvalue, cgiarg_t::cgi_arg);
-
-      } else {
-	args.setarg (key, value, cgiarg_t::cgi_arg);
+
+      if (info==NULL) {
+	if (args.getarg(key)==NULL) {
+	  args.setarg (key, encode_commas(value), cgiarg_t::cgi_arg);
+	}
+	else {
+	  text_t newvalue = args[key];
+
+	  newvalue += "," + encode_commas(value);
+	  args.setarg (key, newvalue, cgiarg_t::cgi_arg);
+	}
+      }
+      else {
+	if (info->multiplevalue) {
+
+	  text_t newvalue = args[key];
+	  if (args.lookupcgiarg(key).source == cgiarg_t::cgi_arg) newvalue += ",";
+	  newvalue += encode_commas(value);
+	  args.setarg (key, newvalue, cgiarg_t::cgi_arg);
+
+	} else {
+	  args.setarg (key, value, cgiarg_t::cgi_arg);
+	}
       }
     }
Index: trunk/gsdl/src/recpt/cgiwrapper.cpp
===================================================================
--- trunk/gsdl/src/recpt/cgiwrapper.cpp	(revision 11997)
+++ trunk/gsdl/src/recpt/cgiwrapper.cpp	(revision 11998)
@@ -42,4 +42,10 @@
 #endif
 
+#include "cgicc/Cgicc.h"
+
+using namespace cgicc;
+extern Cgicc* formData;
+
+
 #ifdef USE_FASTCGI
 #include "fcgiapp.h"
@@ -467,31 +473,29 @@
   char *aURIStr;
   if (!isfastcgi) {
-    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
-      int content_length = text_t(content_length_str).getint();
-      if (content_length > 0) {
-	char c;
-	do {
-	  cin.get(c);
-	  if (cin.eof()) break;
-	  argstr.push_back (c);
-	  --content_length;
-	} while (content_length > 0);
+
+    
+    // Iterate through the vector, and synthesis argstr
+    bool first = true;
+
+    for(const_form_iterator iter = formData->getElements().begin();
+	iter != formData->getElements().end();
+	++iter) {
+      
+      const char* name_cstr = iter->getName().c_str();
+      const char* value_cstr = iter->getValue().c_str();
+      if (first) {
+	
+	argstr = name_cstr;
+	argstr.append("=");
+	argstr.append(value_cstr);
+	first = false;
       }
-      
-    } else {
-      aURIStr = getenv("QUERY_STRING");
-      if ((request_method_str != NULL && strcmp(request_method_str, "GET") == 0)
-	  || aURIStr != NULL) {
-	// GET form data
-	if (aURIStr != NULL) argstr = aURIStr;
-      } else {
-	// debugging from command line
-	debug = true;
+      else {
+	argstr.append("&");
+	argstr.append(name_cstr);
+	argstr.append("=");
+	argstr.append(value_cstr);
       }
-    }
+    }	
   }
 
Index: trunk/gsdl/src/recpt/collectoraction.cpp
===================================================================
--- trunk/gsdl/src/recpt/collectoraction.cpp	(revision 11997)
+++ trunk/gsdl/src/recpt/collectoraction.cpp	(revision 11998)
@@ -56,14 +56,12 @@
 #endif
 
-collectoraction::collectoraction () {
-
-  recpt = NULL;
-  disabled = true;
+collectoraction::collectoraction () 
+  : wizardaction()
+{
+  macro_prefix = "bc1";
+
   do_mkcol = false;
   badsources = false;
   failedsources.erase(failedsources.begin(), failedsources.end());
-  gsdlosc = NULL;
-  gsdlhomec = NULL;
-  pathc = NULL;
 
   cgiarginfo arg_ainfo;
@@ -245,66 +243,7 @@
 
 collectoraction::~collectoraction () {
-  if (gsdlosc != NULL) delete []gsdlosc;
-  if (gsdlhomec != NULL) delete []gsdlhomec;
-  if (pathc != NULL) delete []pathc;
 }
 
 
-void collectoraction::configure (const text_t &key, const text_tarray &cfgline) {
-  if ((key == "collector") && (cfgline.size() == 1) && 
-      (cfgline[0] == "true" || cfgline[0] == "on" || cfgline[0] == "enabled")) {
-    disabled = false;
-  } else {
-    // call the parent class to deal with the things which
-    // are not dealt with here
-    action::configure (key, cfgline);
-  }
-}
-
-
-bool collectoraction::init (ostream & /*logout*/) {
-
-  // set up GSDLOS, GSDLHOME and PATH environment variables
-  text_t gsdlos, path;
-  unsigned int path_separator = ':';
-#if defined (__WIN32__)
-  gsdlos = "windows";
-  path_separator = ';';
-
-  path = filename_cat (gsdlhome, "bin", "windows", "perl", "bin;");
-
-#else
-  struct utsname *buf = new struct utsname();
-  int i = uname (buf);
-  if (i == -1) gsdlos = "linux"; // uname failed
-  else gsdlos.setcstr (buf->sysname);
-  delete buf;
-  lc (gsdlos);
-#endif
-
-  pathc = getenv ("PATH");
-  path += filename_cat (gsdlhome, "bin", gsdlos);
-  path.push_back (path_separator);
-  path += filename_cat (gsdlhome, "bin", "script");
-  if (pathc != NULL) {
-    path.push_back (path_separator);
-    path += pathc;
-  }
-  path = "PATH=" + path;
-
-  gsdlos = "GSDLOS=" + gsdlos;
-  text_t setgsdlhome = "GSDLHOME=" + gsdlhome;
-
-  // these will be cleaned up in the destructor
-  gsdlosc = gsdlos.getcstr();
-  gsdlhomec = setgsdlhome.getcstr();
-  pathc = path.getcstr();
-  
-  putenv (gsdlosc);
-  putenv (gsdlhomec);
-  putenv (pathc);
-
-  return true;
-}
 
 bool collectoraction::check_cgiargs (cgiargsinfoclass &argsinfo, cgiargsclass &args, 
@@ -335,5 +274,5 @@
     // clean up any old builds left laying about in the tmp directory
     // (note that it's possible this could take some time if there's a huge
-    // partially built collection laying about so we'll make it an asynchronous
+    // partially built collecton laying about so we'll make it an asynchronous
     // system call)
     gsdl_system ("perl -S cleantmp.pl", false, logout);
@@ -710,10 +649,4 @@
 }
 
-void collectoraction::get_cgihead_info (cgiargsclass &/*args*/, recptprotolistclass * /*protos*/,
-					response_t &response,text_t &response_data, 
-					ostream &/*logout*/) {
-  response = content;
-  response_data = "text/html";
-}
 
 // return html for buttons used in collector bar
@@ -728,33 +661,6 @@
 // will be hyperlinked
 
-text_t collectoraction::get_button(const text_t &thispage, const text_t &color, 
-				    const text_t &type, bool enabled) {
-
-  if ((color != "green" && color != "grey" && color != "yellow") ||
-      (type != "info" && type != "srce" && type != "conf" && type != "bild" && type != "view"))
-    return g_EmptyText;
-
-  text_t href = "_http"+type+"_";
-  text_t target = "";
-  if (thispage == "info" || thispage == "srce" || thispage == "conf" || 
-      thispage == "bildcancel" || thispage == "bildfail") {
-    // call the check submit macro instead of linking directly to the page
-    href="\"javascript:check_submit('"+type+"');\"";
-  } else if (type == "view") {
-    // view button is special case as it needs a target=_top
-    target = " target=_top";
-  }
-  
-  text_t tdclass = "collectorbar"+color;
-  if (enabled) {
-    // link to the appropriate page
-    return "<td class="+tdclass+"><a href="+href+target+">_text"+type+"_</a></td>";
-  }
-  else {
-    // just display the text
-    return "<td class="+tdclass+">_text"+type+"_</td>";
-  }
-}
-
+// Wendy left a comment suggesting this be move, but where to
+// was not specified.  Into wizardaction.cpp?
 
 // set the _fullnamemenu_ macro (and _warnindex_ and _selectedindex_ if
@@ -771,6 +677,6 @@
 
   text_t &current_page = args["p"];
-  text_t currentname = args["bc1dirname"];
-  if (current_page == "srce") currentname = args["bc1clonecol"];
+  text_t currentname = args[macro_prefix+"dirname"];
+  if (current_page == "srce") currentname = args[macro_prefix + "clonecol"];
 
   text_tarray dirnames;
@@ -825,8 +731,10 @@
 
   bool first = true;
+
   text_t warnindex;
-  text_t fullnamemenu = "<select name=\"bc1dirname\">\n";
+  text_t fullnamemenu = "<select name=\""+macro_prefix+"dirname\" onChange=\"menuchange();\">\n";
+
   if (current_page == "srce") {
-    fullnamemenu = "<select name=\"bc1clonecol\" onChange=\"menuchange();\">\n";
+    fullnamemenu = "<select name=\""+macro_prefix+"clonecol\" onChange=\"menuchange();\">\n";
     fullnamemenu += "<option value=defaultstructure";
     if (!is_selected) fullnamemenu += " selected>";
@@ -834,4 +742,7 @@
     fullnamemenu += "_collector:textdefaultstructure_\n";
   }
+
+  fullnamemenu += "<option value=\"\"></option>\n";
+
   for (int i = 0; i < index; ++i) {
     // don't want write protected collections in list on "change existing
@@ -863,11 +774,12 @@
   }
   fullnamemenu += "</select>\n";
-
-  disp.setmacro ("fullnamemenu", "collector", fullnamemenu);
+  text_t action_name = get_action_name();
+  disp.setmacro ("fullnamemenu", action_name, fullnamemenu);
   if (current_page == "srce") {
-    disp.setmacro ("warnindex", "collector", warnindex);
-    disp.setmacro ("selectedindex", "collector", text_t(selected_index));
+    disp.setmacro ("warnindex",action_name , warnindex);
+    disp.setmacro ("selectedindex", action_name, text_t(selected_index));
   }
 }
+
 
 // set _sourcelist_ and _badsources_ macros
@@ -1005,30 +917,4 @@
 }
 
-// set the _statusline_ macro
-void collectoraction::set_statusline (displayclass &disp, cgiargsclass &args, ostream & /*logout*/) {
-
-  // the build command creates .bld.download, .bld.import, and .bld.build files (in that
-  // order) and deletes them (also in that order) when each stage is complete. the .bld
-  // file is the concatenation of all these files.
-  text_t bld_file = filename_cat (gsdlhome, "tmp", args["bc1tmp"], args["bc1dirname"] + ".bld");
-  text_t statusline;
-
-  if (file_exists (bld_file + ".download")) {
-    statusline = "_collector:textdownloadingfiles_<br>\n";
-    statusline += dm_safe(file_tail(bld_file + ".download", 1, 0));
-  } else if (file_exists (bld_file + ".import")) {
-    statusline = "_collector:textimportingcollection_<br>\n";
-    statusline += dm_safe(file_tail(bld_file + ".import", 1, 0));
-  } else if (file_exists (bld_file + ".build")) {
-    statusline = "_collector:textbuildingcollection_<br>\n";
-    statusline += dm_safe(file_tail(bld_file + ".build", 1, 0));
-  } else {
-    statusline += "_collector:textcreatingcollection_<br>\n";
-    statusline += dm_safe(file_tail(bld_file, 1, 0));
-  }
-
-  disp.setmacro ("statusline", "collector", statusline);
-
-}
 
 void collectoraction::define_internal_macros (displayclass &disp, cgiargsclass &args, 
@@ -1065,29 +951,29 @@
 
   // set the collectorbar macro
-  text_t collectorbar = "<table class=collectorbar border=0 cellspacing=4 cellpadding=0><tr>\n";
+  text_t collectorbar = "<table class=wizardbar border=0 cellspacing=4 cellpadding=0><tr>\n";
 
   if (collector_page == "new") {
     collectorbar += "<td>_icongreyarrow_</td>\n";
-    collectorbar += get_button (collector_page, "green", "info", true);
-    collectorbar += "<td>_icongreyarrow_</td>\n";
-    collectorbar += get_button (collector_page, "grey", "srce", false);
-    collectorbar += "<td>_icongreyarrow_</td>\n";
-    collectorbar += get_button (collector_page, "grey", "conf", false);
-    collectorbar += "<td>_icongreyarrow_</td>\n";
-    collectorbar += get_button (collector_page, "grey", "bild", false);
-    collectorbar += "<td>_icongreyarrow_</td>\n";
-    collectorbar += get_button (collector_page, "grey", "view", false);
+    collectorbar += get_button (args,collector_page, "green", "info", true);
+    collectorbar += "<td>_icongreyarrow_</td>\n";
+    collectorbar += get_button (args,collector_page, "grey", "srce", false);
+    collectorbar += "<td>_icongreyarrow_</td>\n";
+    collectorbar += get_button (args,collector_page, "grey", "conf", false);
+    collectorbar += "<td>_icongreyarrow_</td>\n";
+    collectorbar += get_button (args,collector_page, "grey", "bild", false);
+    collectorbar += "<td>_icongreyarrow_</td>\n";
+    collectorbar += get_button (args,collector_page, "grey", "view", false);
 
   } else if (collector_page == "info") {
     collectorbar += "<td>_icongreyarrow_</td>\n";
-    collectorbar += get_button (collector_page, "yellow", "info", false);
-    collectorbar += "<td>_icongreyarrow_</td>\n";
-    collectorbar += get_button (collector_page, "green", "srce", true);
-    collectorbar += "<td>_icongreyarrow_</td>\n";
-    collectorbar += get_button (collector_page, "grey", "conf", false);
-    collectorbar += "<td>_icongreyarrow_</td>\n";
-    collectorbar += get_button (collector_page, "grey", "bild", false);
-    collectorbar += "<td>_icongreyarrow_</td>\n";
-    collectorbar += get_button (collector_page, "grey", "view", false);
+    collectorbar += get_button (args,collector_page, "yellow", "info", false);
+    collectorbar += "<td>_icongreyarrow_</td>\n";
+    collectorbar += get_button (args,collector_page, "green", "srce", true);
+    collectorbar += "<td>_icongreyarrow_</td>\n";
+    collectorbar += get_button (args,collector_page, "grey", "conf", false);
+    collectorbar += "<td>_icongreyarrow_</td>\n";
+    collectorbar += get_button (args,collector_page, "grey", "bild", false);
+    collectorbar += "<td>_icongreyarrow_</td>\n";
+    collectorbar += get_button (args,collector_page, "grey", "view", false);
     collectorbar += "</tr><tr><td></td><td align=center>_icongreyuparrow_</td><td colspan=8></td>\n";
 
@@ -1097,16 +983,16 @@
       // if we came from the "change an existing collection" page previous button(s)
       // are disabled
-      collectorbar += get_button (collector_page, "grey", "info", false);
+      collectorbar += get_button (args,collector_page, "grey", "info", false);
     } else {
-      collectorbar += get_button (collector_page, "yellow", "info", true);
-    }
-    collectorbar += "<td>_icongreyarrow_</td>\n";
-    collectorbar += get_button (collector_page, "yellow", "srce", false);
-    collectorbar += "<td>_icongreyarrow_</td>\n";
-    collectorbar += get_button (collector_page, "green", "conf", true);
-    collectorbar += "<td>_icongreyarrow_</td>\n";
-    collectorbar += get_button (collector_page, "green", "bild", true);
-    collectorbar += "<td>_icongreyarrow_</td>\n";
-    collectorbar += get_button (collector_page, "grey", "view", false);
+      collectorbar += get_button (args,collector_page, "yellow", "info", true);
+    }
+    collectorbar += "<td>_icongreyarrow_</td>\n";
+    collectorbar += get_button (args,collector_page, "yellow", "srce", false);
+    collectorbar += "<td>_icongreyarrow_</td>\n";
+    collectorbar += get_button (args,collector_page, "green", "conf", true);
+    collectorbar += "<td>_icongreyarrow_</td>\n";
+    collectorbar += get_button (args,collector_page, "green", "bild", true);
+    collectorbar += "<td>_icongreyarrow_</td>\n";
+    collectorbar += get_button (args,collector_page, "grey", "view", false);
     collectorbar += "</tr><tr><td colspan=3></td><td align=center>_icongreyuparrow_</td><td colspan=6></td>\n";
 
@@ -1116,20 +1002,20 @@
     // page
     if (esrce == 1 || econf == 1) {
-      collectorbar += get_button (collector_page, "grey", "info", false);
+      collectorbar += get_button (args,collector_page, "grey", "info", false);
     } else {
-      collectorbar += get_button (collector_page, "yellow", "info", true);
+      collectorbar += get_button (args,collector_page, "yellow", "info", true);
     }
     collectorbar += "<td>_icongreyarrow_</td>\n";
     if (econf == 1) {
-      collectorbar += get_button (collector_page, "grey", "srce", false);
+      collectorbar += get_button (args,collector_page, "grey", "srce", false);
     } else {
-      collectorbar += get_button (collector_page, "yellow", "srce", true);
-    }
-    collectorbar += "<td>_icongreyarrow_</td>\n";
-    collectorbar += get_button (collector_page, "yellow", "conf", false);
-    collectorbar += "<td>_icongreyarrow_</td>\n";
-    collectorbar += get_button (collector_page, "green", "bild", true);
-    collectorbar += "<td>_icongreyarrow_</td>\n";
-    collectorbar += get_button (collector_page, "grey", "view", false);
+      collectorbar += get_button (args,collector_page, "yellow", "srce", true);
+    }
+    collectorbar += "<td>_icongreyarrow_</td>\n";
+    collectorbar += get_button (args,collector_page, "yellow", "conf", false);
+    collectorbar += "<td>_icongreyarrow_</td>\n";
+    collectorbar += get_button (args,collector_page, "green", "bild", true);
+    collectorbar += "<td>_icongreyarrow_</td>\n";
+    collectorbar += get_button (args,collector_page, "grey", "view", false);
     collectorbar += "</tr><tr><td colspan=5></td><td align=center>_icongreyuparrow_</td><td colspan=4></td>\n";
 
@@ -1137,13 +1023,13 @@
     collectorbar += "<td>_icongreyarrow_</td>\n";
     // all previous buttons grey after build was completed
-    collectorbar += get_button (collector_page, "grey", "info", false);
-    collectorbar += "<td>_icongreyarrow_</td>\n";
-    collectorbar += get_button (collector_page, "grey", "srce", false);
-    collectorbar += "<td>_icongreyarrow_</td>\n";
-    collectorbar += get_button (collector_page, "grey", "conf", false);
-    collectorbar += "<td>_icongreyarrow_</td>\n";
-    collectorbar += get_button (collector_page, "yellow", "bild", false);
-    collectorbar += "<td>_icongreyarrow_</td>\n";
-    collectorbar += get_button (collector_page, "green", "view", true);
+    collectorbar += get_button (args,collector_page, "grey", "info", false);
+    collectorbar += "<td>_icongreyarrow_</td>\n";
+    collectorbar += get_button (args,collector_page, "grey", "srce", false);
+    collectorbar += "<td>_icongreyarrow_</td>\n";
+    collectorbar += get_button (args,collector_page, "grey", "conf", false);
+    collectorbar += "<td>_icongreyarrow_</td>\n";
+    collectorbar += get_button (args,collector_page, "yellow", "bild", false);
+    collectorbar += "<td>_icongreyarrow_</td>\n";
+    collectorbar += get_button (args,collector_page, "green", "view", true);
     collectorbar += "</tr><tr><td colspan=7></td><td align=center>_icongreyuparrow_</td><td colspan=2></td>\n";
 
@@ -1153,20 +1039,20 @@
     // page
     if (esrce == 1 || econf == 1) {
-      collectorbar += get_button (collector_page, "grey", "info", false);
+      collectorbar += get_button (args,collector_page, "grey", "info", false);
     } else {
-      collectorbar += get_button (collector_page, "yellow", "info", true);
+      collectorbar += get_button (args,collector_page, "yellow", "info", true);
     }
     collectorbar += "<td>_icongreyarrow_</td>\n";
     if (econf == 1) {
-      collectorbar += get_button (collector_page, "grey", "srce", false);
+      collectorbar += get_button (args,collector_page, "grey", "srce", false);
     } else {
-      collectorbar += get_button (collector_page, "yellow", "srce", true);
-    }
-    collectorbar += "<td>_icongreyarrow_</td>\n";
-    collectorbar += get_button (collector_page, "yellow", "conf", true);
-    collectorbar += "<td>_icongreyarrow_</td>\n";
-    collectorbar += get_button (collector_page, "yellow", "bild", true);
-    collectorbar += "<td>_icongreyarrow_</td>\n";
-    collectorbar += get_button (collector_page, "grey", "view", false);
+      collectorbar += get_button (args,collector_page, "yellow", "srce", true);
+    }
+    collectorbar += "<td>_icongreyarrow_</td>\n";
+    collectorbar += get_button (args,collector_page, "yellow", "conf", true);
+    collectorbar += "<td>_icongreyarrow_</td>\n";
+    collectorbar += get_button (args,collector_page, "yellow", "bild", true);
+    collectorbar += "<td>_icongreyarrow_</td>\n";
+    collectorbar += get_button (args,collector_page, "grey", "view", false);
   }
 
@@ -1207,4 +1093,5 @@
   disp.setmacro ("gsdlhome", "collector", dm_safe(gsdlhome));
 }
+
 
 bool collectoraction::do_action (cgiargsclass &args, recptprotolistclass * /*protos*/, 
@@ -1439,129 +1326,4 @@
 }
 
-// if sw = 0 replace all carriage returns in intext with the string "\n"
-// else replace all occurances of "\n" with a carriage return
-text_t collectoraction::carriage_replace (const text_t &intext, int sw) {
-   
-  text_t outtext;
-  text_t::const_iterator here = intext.begin();
-  text_t::const_iterator end = intext.end();
-  while (here != end) {
-    if (sw == 0) {
-      if (*here == '\n') {
-	if ((here+1) != end && *(here+1) == '\r') ++here;
-	outtext += "\\n";
-      } else if (*here == '\r') {
-	if ((here+1) != end && *(here+1) == '\n') ++here;
-	outtext += "\\n";
-      } else {
-	outtext.push_back (*here);
-      }
-    } else if (*here == '\\' && (here+1) != end && *(here+1) == 'n') {
-      outtext.push_back ('\n');
-      ++here;
-    } else {
-      outtext.push_back (*here);
-    }
-    ++here;
-  }
-  return outtext;
-}
-
-// create a short directory name from fullname
-text_t collectoraction::get_directory_name (const text_t &fullname) {
-
-  text_t shortname;
-  if (fullname.empty()) {
-    shortname = "coll";
-
-  } else {
-    
-    // first make all lowercase and remove any dodgy characters
-    // (i.e. anything not [a-z]
-    text_t::const_iterator here = fullname.begin();
-    text_t::const_iterator end = fullname.end();
-    while (here != end) {
-      if ((*here >= 'A' && *here <= 'Z') || (*here >= 'a' && *here <= 'z') ||
-	  (*here == ' ')) {
-	if (*here >= 'A' && *here <= 'Z') shortname.push_back (*here+32);
-	else if (*here == ' ') {
-	  while ((*(here+1)) == ' ') ++here;
-	  shortname.push_back (*here);
-	} else shortname.push_back (*here);
-      }
-      ++here;
-    }
-
-    text_tarray words;
-    splitchar (shortname.begin(), shortname.end(), ' ', words);
-    int num_words = words.size();
-
-    if (num_words == 0) {
-      shortname = "coll";
-
-    } else {
-
-      shortname.clear();
-      int use_words = (num_words <= 6) ? num_words : 6;
-      unsigned int substr_len = 6 / use_words;
-      
-      for (int i = 0; i < use_words; ++i) {
-	if (words[i].size() < substr_len) shortname += words[i];
-	else shortname += substr (words[i].begin(), words[i].begin()+substr_len);
-      }
-    }
-  }
-
-  // check to see if shortname is unique
-  text_t fulldirname = filename_cat (gsdlhome, "collect", shortname);
-  if (directory_exists (fulldirname)) {
-    int version = 0;
-    text_t newname;
-    do {
-      ++version;
-      newname = shortname;
-      newname.push_back ('v');
-      newname.appendint (version);
-      fulldirname = filename_cat (gsdlhome, "collect", newname);
-    } while (directory_exists (fulldirname));
-
-    shortname = newname;
-  }
-  
-  return shortname;
-}
-
-// tests if collection is write protected (currently just checks if
-// collect.cfg file is writable
-bool collectoraction::collection_protected (const text_t &collection) {
-  text_t cfgfile = filename_cat(gsdlhome, "collect", collection, "etc", "collect.cfg");
-  if (file_writable(cfgfile)) return false;
-  return true;
-}
-
-// assigns a temporary directory name for this collector session
-// and creates temporary directory
-// returns false if it couldn't create the directory
-bool collectoraction::assign_tmpname (cgiargsclass &args, ostream &logout) {
-
-  int i = 0;
-  text_t tmpname = "tbuild";
-  while (directory_exists (filename_cat (gsdlhome, "tmp", tmpname + text_t(i)))) {
-    ++i;
-  }
-  tmpname.appendint (i);
-
-  text_t fulltmpdir = filename_cat (gsdlhome, "tmp", tmpname);
-  if (!mk_dir (fulltmpdir)) {
-    outconvertclass text_t2ascii;
-    logout << text_t2ascii << "collectoraction::assign_tmpname unable to create directory ("
-	   << fulltmpdir << ")\n";
-    return false;
-  }
-
-  args["bc1tmp"] = tmpname;
-  return true;
-}
-
 void collectoraction::gsdl_mkcol (cgiargsclass &args, ostream &logout) {
 
@@ -1569,4 +1331,5 @@
   if (!directory_exists (tmpdir)) {
     message = "tmpfail";
+    cerr << "WE CANNOT CREATE THE DIRECTORY!!! " << endl; 
     return;
   }
@@ -1605,4 +1368,6 @@
   text_t mkcol_cmd = "perl -S mkcol.pl -optionfile \"" + optionfile;
   mkcol_cmd += "\" " + collection;
+
+
   gsdl_system (mkcol_cmd, true, logout);
 
@@ -1627,273 +1392,4 @@
 }
 
-void collectoraction::gsdl_build (cgiargsclass &args, ostream &logout) {
-
-  outconvertclass text_t2ascii;
-
-  text_t tmpdir = filename_cat (gsdlhome, "tmp", args["bc1tmp"]);
-  if (!directory_exists (tmpdir)) {
-    message = "tmpfail";
-    return;
-  }
-  
-  text_t &collection = args["bc1dirname"];
-  if (collection.empty()) {
-    message = "nocollection";
-    return;
-  }
-
-  // check for a .build file - if it exists then we've already built
-  // the collection (or are in the process of building it)
-  text_t buildfile = filename_cat (tmpdir, ".build");
-  if (file_exists (buildfile)) {
-    return;
-  } else {
-    // create the .build file (this file is just a place holder to let any future
-    // pages know that we've already been here)
-    char *buildfilec = buildfile.getcstr();
-    ofstream bfile_out (buildfilec);
-    delete []buildfilec;
-    if (bfile_out) {
-      bfile_out << "collection building\n";
-      bfile_out.close();
-    } else {
-      message = "tmpfail";
-      return;
-    }
-  }
-
-  const recptconf &rcinfo = recpt->get_configinfo ();
-
-  // create the event header file if LogEvents, EmailEvents or
-  // EmailUserEvents options are turned on.
-  bool logevents = 
-    (rcinfo.LogEvents == CollectorEvents || rcinfo.LogEvents == AllEvents || 
-     rcinfo.EmailEvents == CollectorEvents || rcinfo.EmailEvents == AllEvents ||
-     rcinfo.EmailUserEvents);
-  text_t ehead_file = filename_cat (tmpdir, "ehead.txt");
-  if (logevents) {
-    if (!create_event_header_file (ehead_file, args, logout)) {
-      logevents = false;
-    }
-  }
-    
-  text_t collectdir = get_collectdir (args);
-
-  // set up build options
-  text_t options = "-make_writable -remove_import -out \"";
-  options += filename_cat (tmpdir, collection + ".bld");
-  options += "\" -collectdir \"" + collectdir + "\" -statsfile \"";
-  options += filename_cat(collectdir, collection, "etc", "import.log") + "\"";
-
-  if (args["bc1esrce"] == 1) {
-    // we're adding data to an existing collection
-    options += " -save_archives -append";
-  }
-
-  text_tarray inputvalues, inputtypes;
-  splitchar (args["bc1input"].begin(), args["bc1input"].end(), ',', inputvalues);
-  splitchar (args["bc1inputtype"].begin(), args["bc1inputtype"].end(), ',', inputtypes);
-  int numvalues = inputvalues.size();
-  int numtypes = inputtypes.size();
-  for (int i = 0; i < numvalues; ++i) {
-    if (!inputvalues[i].empty()) {
-      text_t type = "file://"; // default
-      if (i < numtypes) type = inputtypes[i];
-      options += " -download \"" + 
-	remove_trailing_slashes(type + format_url(decode_commas(inputvalues[i]))) + "\"";
-    }
-  }
-
-  if (logevents) {
-    if (rcinfo.LogEvents == CollectorEvents || rcinfo.LogEvents == AllEvents) 
-      options += " -log_events";
-    if (rcinfo.EmailEvents == CollectorEvents || rcinfo.EmailEvents == AllEvents) {
-      options += " -mail_server " + rcinfo.MailServer;
-      options += " -email_events " + rcinfo.maintainer;
-      if (rcinfo.EmailUserEvents) options += "," + args["bc1contactemail"];
-    } else if (rcinfo.EmailUserEvents) {
-      options += " -mail_server " + rcinfo.MailServer;
-      options += " -email_events " + args["bc1contactemail"];
-    }
-    options += " -event_header " + ehead_file;
-  }
-
-  text_t optionfile = filename_cat (tmpdir, "build.opt");
-  char *optionfilec = optionfile.getcstr();
-  ofstream ofile_out (optionfilec);
-  delete []optionfilec;
-  if (!ofile_out) {
-    message = "tmpfail";
-    return;
-  }
-  ofile_out << text_t2ascii << options << "\n";
-  ofile_out.close();
-
-  // if we're altering an existing collection we need to kill off
-  // the existing collection server - we do this for the local library
-  // (and any other persistent version of the library) as the existing
-  // gdbm file can't be deleted while the collection server holds it open
-  if ((args["bc1econf"] == 1) || (args["bc1esrce"] == 1)) {
-    remove_colservr (collection, logout);
-  }    
-
-  // set up the build command - build.bat has some issues with quoting
-  // on win2k when gsdlhome contains spaces so we'll avoid using 
-  // "perl -S" here in favor of calling the "build" perl script explicitly
-  text_t build_cmd = "perl \"" + filename_cat (gsdlhome, "bin", "script", "build");
-  build_cmd += "\" -optionfile \"" + optionfile + "\" " + collection;
-  // run build command in background (i.e. asynchronously)
-  gsdl_system (build_cmd, false, logout);
-}
-
-void collectoraction::gsdl_cancel_build (cgiargsclass &args, ostream &logout) {
-  // I really wanted to do what this perl script does from within the library
-  // c++ code. I ran into some problems though (like how do you write a portable
-  // "rm -r" in c++?). One day I'll spend some time sorting it out ... maybe.
-  text_t cancel_cmd = "perl -S cancel_build.pl -collectdir \"";
-  cancel_cmd += filename_cat (gsdlhome, "tmp", args["bc1tmp"]) + "\" ";
-  cancel_cmd += args["bc1dirname"];
-  // To be on the safe side we'll make this a synchronous call
-  // so that all tidying up is done before the user has a chance
-  // to do anything else (like start rebuilding their collection).
-  // This means that for a big collection where there's lots of 
-  // stuff to delete etc. it might take a while before the "build
-  // cancelled" page appears.
-  gsdl_system (cancel_cmd, true, logout);
-}
-
-text_t collectoraction::get_collectdir (cgiargsclass &args)
-{
-  if ((args["bc1econf"] == 1) || (args["bc1esrce"] == 1)) {
-    // we're adding to a collection in place
-    return filename_cat(gsdlhome, "collect");  
-  }
-  else {
-    return filename_cat (gsdlhome, "tmp", args["bc1tmp"]);
-  }
-}
-
-// checks to see if any of the plugins in pluginset occur in 
-// collections configuration file
-bool collectoraction::uses_weird_plugin (const text_t &collection) {
-
-  text_tset pluginset;
-  pluginset.insert ("HBPlug");
-
-  text_t cfgfile_content;
-  text_t cfgfile_name = filename_cat (gsdlhome, "collect", collection, "etc", "collect.cfg");
-  text_t pluginstr, pluginname;
-
-  if (read_file (cfgfile_name, cfgfile_content)) {
-    text_t::const_iterator here = cfgfile_content.begin();
-    text_t::const_iterator end = cfgfile_content.end();
-    while (here != end) {
-      here = findchar (here, end, 'p');
-      if (here == end) break;
-      if ((here+6 < end) && (substr (here, here+6) == "plugin")) {
-	getdelimitstr (here+6, end, '\n', pluginstr);
-	text_t::const_iterator hp = pluginstr.begin();
-	text_t::const_iterator ep = pluginstr.end();
-	bool found = false;
-	// remove any leading whitespace, trailing options etc.
-	while (hp != ep) {
-	  if (*hp == '\t' || *hp == ' ' || *hp == '\n') {
-	    if (found) break;
-	  } else {
-	    pluginname.push_back (*hp);
-	    found = true;
-	  }
-	  ++hp;
-	}
-	text_tset::const_iterator it = pluginset.find (pluginname);
-	if (it != pluginset.end()) return true; // found matching plugin
-	pluginname.clear();
-      }
-      ++here;
-    }
-  }
-  return false;
-}
-
-// create and initialize a new collection server and
-// add it to the null protocol.
-void collectoraction::create_colserver (const text_t &collection, ostream &logout) {
-
-  recptprotolistclass *protos = recpt->get_recptprotolist_ptr();
-  recptprotolistclass::iterator rprotolist_here = protos->begin();
-  recptprotolistclass::iterator rprotolist_end = protos->end();
-  while (rprotolist_here != rprotolist_end) {
-    comerror_t err = noError;
-    if ((*rprotolist_here).p != NULL) {
-      if ((*rprotolist_here).p->get_protocol_name (err) == "nullproto") {
-	// create collection server and add it to nullproto
-	(*rprotolist_here).p->add_collection (collection, recpt, gsdlhome, gsdlhome);
-	// make sure gsdlhome is configured
-	text_tarray tmp;
-	tmp.push_back (gsdlhome);
-	(*rprotolist_here).p->configure ("gsdlhome", tmp, err);
-	// re-initialize the null protocol
-	if (!(*rprotolist_here).p->init (err, logout)) {
-	  logout << "collectoraction::create_colserver: nullproto init failed\n";
-	}
-	return;
-      }
-    }
-    ++rprotolist_here;
-  }
-
-  logout << "collectoraction::create_colserver: no valid nullproto found\n";
-}
-
-// delete a collection server from the null protocol
-void collectoraction::remove_colservr (const text_t &collection, ostream &logout) {
-
-  recpt->uncache_collection (collection);
-
-  recptprotolistclass *protos = recpt->get_recptprotolist_ptr();
-  recptprotolistclass::iterator rprotolist_here = protos->begin();
-  recptprotolistclass::iterator rprotolist_end = protos->end();
-  while (rprotolist_here != rprotolist_end) {
-    comerror_t err = noError;
-    if ((*rprotolist_here).p != NULL) {
-      if ((*rprotolist_here).p->get_protocol_name (err) == "nullproto") {
-	(*rprotolist_here).p->remove_collection (collection, logout);
-	return;
-      }
-    }
-    ++rprotolist_here;
-  }
-
-  logout << "collectoraction::create_colserver: no valid nullproto found\n";
-}
-
-bool collectoraction::create_event_header_file (const text_t &filename, cgiargsclass &args, 
-						ostream &logout) {
-
-  outconvertclass text_t2ascii;
-  char *filenamec = filename.getcstr();
-  ofstream eheadfile (filenamec);
-  delete []filenamec;
-
-  if (eheadfile) {
-    eheadfile << text_t2ascii << get_event_header (args);
-    eheadfile.close();
-    return true;
-  }
-   
-  logout << text_t2ascii << "collectoraction::create_event_header ERROR: Couldn't create "
-	 << "Event Header file " << filename << ". Event logging disabled\n";
-  return false;
-}
-
-text_t collectoraction::get_event_header (cgiargsclass &args) {
-  text_t header = "Greenstone Username: " + args["un"] + "\n";
-  header += "Collection: " + args["bc1dirname"] + "\n";
-  header += "Collection Creator: " + args["bc1contactemail"] + "\n";
-  header += "GSDLHOME: " + gsdlhome + "\n";
-  header += "Build Location: " + get_collectdir(args) + "\n";
-
-  return header;
-}
 
 bool collectoraction::check_sources (cgiargsclass &args, ostream &logout) {
@@ -1946,31 +1442,35 @@
 }
 
-// format_url simply strips "http://", "ftp://", or "file://" off the
-// beginning of url if they're there
-text_t collectoraction::format_url (const text_t &url) {
-  text_t::const_iterator begin = url.begin();
-  text_t::const_iterator end = url.end();
-
-  if (url.size() >= 7) {
-    text_t prefix = substr(begin, begin+7);
-    if (prefix == "http://" || prefix == "file://") {
-      return substr(begin+7, end);
-    }
-  }
-  if (url.size() >= 6) {
-    if (substr(begin, begin+6) == "ftp://") {
-      return substr(begin+6, end);
-    }
-  }
-  return url;
+text_t collectoraction::get_button(cgiargsclass &args, const text_t &thispage, 
+				   const text_t &color, 
+				   const text_t &type, bool enabled) 
+{
+
+  if ((color != "green" && color != "grey" && color != "yellow") ||
+      (type != "info" && type != "srce" && type != "conf" && type != "bild" && type != "view"))
+    return g_EmptyText;
+
+  text_t href = "_http"+type+"_";
+  text_t target = "";
+
+  if (thispage == "info" || thispage == "srce" || thispage == "conf" || 
+      thispage == "bildcancel" || thispage == "bildfail") {
+    // call the check submit macro instead of linking directly to the page
+    href="\"javascript:check_submit('"+type+"');\"";
+  } else if (type == "view") {
+    // view button is special case as it needs a target=_top
+    target = " target=_top";
+  }
+
+  text_t tdclass = "wizardbar"+color; 
+  if (enabled) {
+    // link to the appropriate page
+    return "<td class="+tdclass+"><a href="+href+target+">_text"+type+"_</a></td>";
+  }
+  else {
+    // just display the text
+    return "<td class="+tdclass+">_text"+type+"_</td>";
+  }
 }
 
-text_t collectoraction::remove_trailing_slashes (text_t str) {
-
-  while (*(str.end()-1) == '\\') {
-    str.pop_back();
-  }
-  return str;
-}
-
 #endif //GSDL_USE_COLLECTOR_ACTION
Index: trunk/gsdl/src/recpt/collectoraction.h
===================================================================
--- trunk/gsdl/src/recpt/collectoraction.h	(revision 11997)
+++ trunk/gsdl/src/recpt/collectoraction.h	(revision 11998)
@@ -30,19 +30,10 @@
 #define COLLECTORACTION_H
 
-#include "action.h"
+#include "wizardaction.h"
 #include "receptionist.h"
 
-class collectoraction : public action {
+class collectoraction : public wizardaction {
   
 protected:
-
-  bool disabled;
-  receptionist *recpt;
-  char *gsdlosc;
-  char *gsdlhomec;
-  char *pathc;
-
-  text_t message;
-  char failcode;
 
   bool do_mkcol;
@@ -51,9 +42,7 @@
   text_tmap failedsources;
 
-  text_t get_button (const text_t &thispage, const text_t &color, 
-		     const text_t &type, bool enabled);
+  void set_fullnamemenu (displayclass &disp, cgiargsclass &args, 
+			 recptprotolistclass *protos, ostream &logout);
 
-  void set_fullnamemenu (displayclass &disp, cgiargsclass &args,
-			 recptprotolistclass *protos, ostream &logout);
 
   void set_inputsourceboxes (displayclass &disp, cgiargsclass &args, 
@@ -65,5 +54,4 @@
   void set_cfgfile (displayclass &disp, cgiargsclass &args, ostream &logout);
 
-  void set_statusline (displayclass &disp, cgiargsclass &args, ostream &logout);
 
   void update_cfgfile_clone (cgiargsclass &args, ostream &logout);
@@ -73,36 +61,15 @@
   void update_cfgfile_complete (cgiargsclass &args, ostream &logout);
 
-  text_t carriage_replace (const text_t &intext, int sw);
-
-  text_t get_directory_name (const text_t &fullname);
-
-  bool collection_protected (const text_t &collection);
-
-  bool assign_tmpname (cgiargsclass &args, ostream &logout);
 
   void gsdl_mkcol (cgiargsclass &args, ostream &logout);
 
-  void gsdl_build (cgiargsclass &args, ostream &logout);
 
-  void gsdl_cancel_build (cgiargsclass &args, ostream &logout);
-
-  text_t get_collectdir (cgiargsclass &args);
-
-  bool uses_weird_plugin (const text_t &collection);
-
-  void create_colserver (const text_t &collection, ostream &logout);
-
-  void remove_colservr (const text_t &collection, ostream &logout);
-
-  bool create_event_header_file (const text_t &filename, cgiargsclass &args, 
-				 ostream &logout);
-
-  text_t get_event_header (cgiargsclass &args);
 
   bool check_sources (cgiargsclass &args, ostream &logout);
 
-  text_t format_url (const text_t &url);
+  text_t get_button (cgiargsclass &args, const text_t &thispage, 
+		     const text_t &color, 
+		     const text_t &type, bool enabled);
 
-  text_t remove_trailing_slashes (text_t str);
 
 public:
@@ -110,18 +77,8 @@
   virtual ~collectoraction ();
 
-  void configure (const text_t &key, const text_tarray &cfgline);
-
-  bool init (ostream &logout);
-
-  void set_receptionist (receptionist *therecpt) {recpt=therecpt;}
-
   text_t get_action_name () {return "collector";}
 
   bool check_cgiargs (cgiargsinfoclass &argsinfo, cgiargsclass &args, 
 		      recptprotolistclass *protos, ostream &logout);
-
-  void get_cgihead_info (cgiargsclass &args, recptprotolistclass *protos,
-			 response_t &response,text_t &response_data, 
-			 ostream &logout);
 
   void define_internal_macros (displayclass &disp, cgiargsclass &args, 
@@ -132,4 +89,5 @@
 		  outconvertclass &outconvert, ostream &textout, 
 		  ostream &logout);
+
 };
 
Index: trunk/gsdl/src/recpt/documentaction.cpp
===================================================================
--- trunk/gsdl/src/recpt/documentaction.cpp	(revision 11997)
+++ trunk/gsdl/src/recpt/documentaction.cpp	(revision 11998)
@@ -619,5 +619,10 @@
   if (get_info (inlink, args["c"], args["l"], metadata, false, collectproto, response, logout)) {
     if (!response.docInfo[0].metadata["section"].values[0].empty()) {
+#ifndef DOCHANDLE
       outlink = "_httpdocument_&amp;d=" + response.docInfo[0].metadata["section"].values[0];
+#else
+      outlink = "_httpdocumenthandle_("+args["c"]+","+response.docInfo[0].metadata["section"].values[0]+")";
+#endif
+
       return true;
     }
@@ -642,6 +647,11 @@
       if (get_info (inlink, *col_here, args["l"], metadata, false, collectproto, response, logout)) {
 	if (!response.docInfo[0].metadata["section"].values[0].empty()) {
+#ifndef DOCHANDLE
 	  outlink = "_httpdocument_&amp;c=" + *col_here + "&amp;d=" +
 	    response.docInfo[0].metadata["section"].values[0];
+#else
+	  outlink = "_httpdocumenthandle_("+*col_here+","+response.docInfo[0].metadata["section"].values[0]+")";
+#endif
+
 	  return true;
 	}
@@ -1003,6 +1013,11 @@
 		<< "<frameset rows=\"68,*\" noresize border=0>\n"
 		<< "<frame scrolling=no frameborder=0 src=\"_gwcgi_?_optsite_e=_compressedoptions_&a=p&p=nav\">\n"
+#ifndef DOCHANDLE
 		<< "<frame name=\"documenttop\" frameborder=0 src=\"_gwcgi_?_optsite_e=_compressedoptions_&a=d&d=" 
 		<< args["d"] << "\">"
+#else
+		<< "<frame name=\"documenttop\" frameborder=0 src=\"_httpdocumenthandle_(" 
+		<< args["c"] << "," << args["d"] << ")\">"
+#endif
 		<< "<noframes>\n"
 		<< "<p>You must have a frame enabled browser to view this.</p>\n"
@@ -1297,6 +1312,12 @@
   // work out values for next link
   if (haschildren) {
+#ifndef DOCHANLE
     disp.setmacro ("httpnextarrow", "document", "_httpdocument_&amp;cl=" + args["cl"] +
 		   "&amp;d=" + arg_d + ".fc");
+#else
+    disp.setmacro ("httpnextarrow", "document", "_httpdocumenthandle_("+args["c"]+","+arg_d + ".fc)";
+
+#endif
+
   } else {
     text_tarray::const_iterator h = next_siblings.begin();
@@ -1304,6 +1325,12 @@
     while (h != e) {
       if (!(*h).empty()) {
+#ifndef DOCHANLE
 	disp.setmacro ("httpnextarrow", "document", "_httpdocument_&amp;cl=" + args["cl"] +
 		       "&amp;d=" + *h);
+#else
+	disp.setmacro ("httpnextarrow", "document", "_httpdocumenthandle_("+args["c"]+","+*h+")";
+
+#endif
+
 	break;
       }
@@ -1314,10 +1341,22 @@
   // work out value for previous link
   if (!previous_sibling.empty()) {
+#ifndef DOCHANDLE
     disp.setmacro ("httpprevarrow", "document", "_httpdocument_&amp;cl=" + args["cl"] +
 		   "&amp;d=" + previous_sibling);
+#else
+    disp.setmacro ("httpprevarrow", "document", "_httpdocumenthandle_("+args["c"]+","+ previous_sibling+")");
+
+#endif
+
   } else {
     if (countchar(arg_d.begin(), arg_d.end(), '.')) {
+#ifndef DOCHANDLE
       disp.setmacro ("httpprevarrow", "document", "_httpdocument_&amp;cl=" + args["cl"] +
 		     "&amp;d=" + get_parent(arg_d));
+#else
+      disp.setmacro ("httpprevarrow", "document", "_httpdocumenthandle_("+args["c"]+","+get_parent(arg_d)+")");
+
+#endif
+
     }
   }
Index: trunk/gsdl/src/recpt/gsdl_modules_cfg.h
===================================================================
--- trunk/gsdl/src/recpt/gsdl_modules_cfg.h	(revision 11997)
+++ trunk/gsdl/src/recpt/gsdl_modules_cfg.h	(revision 11998)
@@ -53,4 +53,5 @@
 #define GSDL_USE_BROWSE_ACTION
 #define GSDL_USE_COLLECTOR_ACTION
+#define GSDL_USE_DEPOSITOR_ACTION
 #define GSDL_USE_EXTLINK_ACTION
 #undef  GSDL_USE_GTI_ACTION
Index: trunk/gsdl/src/recpt/librarymain.cpp
===================================================================
--- trunk/gsdl/src/recpt/librarymain.cpp	(revision 11997)
+++ trunk/gsdl/src/recpt/librarymain.cpp	(revision 11998)
@@ -85,4 +85,5 @@
 #include "tipaction.h"
 #include "collectoraction.h"
+#include "depositoraction.h"
 #include "browseaction.h"
 #include "phindaction.h"
@@ -107,4 +108,9 @@
 #endif //GSDL_USE_CLASSIFIER_BROWSER
 
+#include "cgicc/Cgicc.h"
+using namespace cgicc;
+
+Cgicc* formData;
+
 int main () {
   receptionist recpt;
@@ -115,4 +121,6 @@
 #endif
   text_t       gsdlhome;
+
+  formData = new Cgicc();
 
   cservers = new collectset(gsdlhome);
@@ -200,4 +208,10 @@
 #endif
 
+#ifdef GSDL_USE_DEPOSITOR_ACTION
+  depositoraction *adepositoraction = new depositoraction();
+  adepositoraction->set_receptionist (&recpt);
+  recpt.add_action(adepositoraction);
+#endif
+
 #ifdef GSDL_USE_BROWSE_ACTION
   browseaction *abrowseaction = new browseaction();
@@ -276,4 +290,6 @@
   thisAction = recpt.get_actionmap_ptr()->begin();
   recpt.get_actionmap_ptr()->erase(thisAction, endAction);
+
+  delete formData;
   return 0;
 }
Index: trunk/gsdl/src/recpt/pageaction.cpp
===================================================================
--- trunk/gsdl/src/recpt/pageaction.cpp	(revision 11997)
+++ trunk/gsdl/src/recpt/pageaction.cpp	(revision 11998)
@@ -45,4 +45,5 @@
   status_disabled = true;
   collector_disabled = true;
+  depositor_disabled = true; 
   translator_disabled = true;
   gliapplet_disabled = true;
@@ -586,4 +587,5 @@
   // if page is "home" or "homehelp"
   // _textgocollector_     set to "" if collector is disabled in main.cfg
+  // _textgodepositor_     set to "" if depositor is disabled in main.cfg
   // _textgoadmin_         set to "" if status is disabled in main.cfg
   // _textgotranslator_    set to "" if translator is disabled in main.cfg
@@ -669,4 +671,5 @@
     if (status_disabled) disp.setmacro ("textgoadmin", "home", "");
     if (collector_disabled) disp.setmacro ("textgocollector", "home", "");
+    if (depositor_disabled) disp.setmacro ("textgodepositor", "home", "");
     if (translator_disabled) disp.setmacro ("textgotranslator", "home", "");
 
@@ -912,5 +915,10 @@
 	     (cfgline[0] == "true" || cfgline[0] == "on" || cfgline[0] == "enabled")) {
     collector_disabled = false;
-  } else if ((key == "translator") && (cfgline.size() == 1) && 
+  }
+ else if ((key == "depositor") && (cfgline.size() == 1) && 
+	     (cfgline[0] == "true" || cfgline[0] == "on" || cfgline[0] == "enabled")) {
+    depositor_disabled = false;
+  }
+    else if ((key == "translator") && (cfgline.size() == 1) && 
 	     (cfgline[0] == "true" || cfgline[0] == "on" || cfgline[0] == "enabled")) {
     translator_disabled = false;
Index: trunk/gsdl/src/recpt/pageaction.h
===================================================================
--- trunk/gsdl/src/recpt/pageaction.h	(revision 11997)
+++ trunk/gsdl/src/recpt/pageaction.h	(revision 11998)
@@ -95,4 +95,5 @@
   bool status_disabled;
   bool collector_disabled;
+  bool depositor_disabled;
   bool translator_disabled;
   bool gliapplet_disabled;
Index: trunk/gsdl/src/recpt/wizardaction.cpp
===================================================================
--- trunk/gsdl/src/recpt/wizardaction.cpp	(revision 11998)
+++ trunk/gsdl/src/recpt/wizardaction.cpp	(revision 11998)
@@ -0,0 +1,771 @@
+/**********************************************************************
+ *
+ * wizardaction.cpp -- 
+ * Copyright (C) 2000  The New Zealand Digital Library Project
+ *
+ * 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 "gsdl_modules_cfg.h"
+
+// note that the wizardaction relies on having direct access to a
+// collections configuration file. this breaks the separation between
+// receptionist and collection server and so is not suitable (at least
+// in its current form) for use when collection servers are separate 
+// from the receptionist (e.g. when using the CORBA protocol).
+
+// following line required to get fstream.filedesc() on darwin (Mac OS X)
+#define _STREAM_COMPAT  1
+// required for utsname on solaris???
+#define _XOPEN_SOURCE 1
+#define _XOPEN_SOURCE_EXTENDED 1
+
+#include "wizardaction.h"
+#include "OIDtools.h"
+#include "fileutil.h"
+#include "cfgread.h"
+#include "gsdltools.h"
+#include "gsdltimes.h"
+#include "nullproto.h"
+#include "argdb.h"
+#include "cgiutils.h"
+#include <stdio.h>
+#include <fcntl.h>
+
+#if !defined (__WIN32__)
+#include <sys/utsname.h>
+#include <unistd.h>
+#endif
+
+wizardaction::wizardaction () {
+
+  recpt = NULL;
+  disabled = true;
+  gsdlosc = NULL;
+  gsdlhomec = NULL;
+  pathc = NULL;
+
+  macro_prefix = "";
+}
+
+wizardaction::~wizardaction () {
+  if (gsdlosc != NULL) delete []gsdlosc;
+  if (gsdlhomec != NULL) delete []gsdlhomec;
+  if (pathc != NULL) delete []pathc;
+}
+
+void wizardaction::configure (const text_t &key, const text_tarray &cfgline) {
+  
+  const text_t& action_name = get_action_name();
+
+  if ((key == action_name) && (cfgline.size() == 1) && 
+      (cfgline[0] == "true" || cfgline[0] == "on" || cfgline[0] == "enabled")) {
+    disabled = false;
+  } else {
+    // call the parent class to deal with the things which
+    // are not dealt with here
+    action::configure (key, cfgline);
+  }
+}
+
+
+bool wizardaction::init (ostream & /*logout*/) {
+
+  // set up GSDLOS, GSDLHOME and PATH environment variables
+  text_t gsdlos, path;
+  unsigned int path_separator = ':';
+#if defined (__WIN32__)
+  gsdlos = "windows";
+  path_separator = ';';
+
+  path = filename_cat (gsdlhome, "bin", "windows", "perl", "bin;");
+
+#else
+  struct utsname *buf = new struct utsname();
+  int i = uname (buf);
+  if (i == -1) gsdlos = "linux"; // uname failed
+  else gsdlos.setcstr (buf->sysname);
+  delete buf;
+  lc (gsdlos);
+#endif
+
+  pathc = getenv ("PATH");
+  path += filename_cat (gsdlhome, "bin", gsdlos);
+  path.push_back (path_separator);
+  path += filename_cat (gsdlhome, "bin", "script");
+  if (pathc != NULL) {
+    path.push_back (path_separator);
+    path += pathc;
+  }
+  path = "PATH=" + path;
+
+  gsdlos = "GSDLOS=" + gsdlos;
+  text_t setgsdlhome = "GSDLHOME=" + gsdlhome;
+
+  // these will be cleaned up in the destructor
+  gsdlosc = gsdlos.getcstr();
+  gsdlhomec = setgsdlhome.getcstr();
+  pathc = path.getcstr();
+  
+  putenv (gsdlosc);
+  putenv (gsdlhomec);
+  putenv (pathc);
+
+  return true;
+}
+
+
+void wizardaction::get_cgihead_info (cgiargsclass &/*args*/, recptprotolistclass * /*protos*/,
+					response_t &response,text_t &response_data, 
+					ostream &/*logout*/) {
+  response = content;
+  response_data = "text/html";
+}
+
+
+bool wizardaction::check_cgiargs (cgiargsinfoclass &argsinfo, cgiargsclass &args, 
+				     recptprotolistclass * /*protos*/, ostream &logout) {
+  
+  text_t current_page = args["p"];
+
+  if (current_page != "intro" && 
+      current_page != "bildframe1" && current_page != "new" && current_page != "select") {
+    // update arguments that were saved to the harddrive
+    text_tmap saved_args;
+    
+    // update the argdb database with any arguments that were set
+    // by previous page as denoted by prefix (eg. di1 or bc1)
+
+    cgiargsclass::const_iterator args_here = args.begin();
+    cgiargsclass::const_iterator args_end = args.end();
+
+    while (args_here != args_end) {
+      text_t args_name = (*args_here).first;
+      
+      int prefix_len = macro_prefix.size();
+      
+      text_t args_prefix = substr(args_name.begin(),args_name.begin()+prefix_len);
+      
+      if (args_prefix == macro_prefix) {
+	saved_args[args_name] = args[args_name];
+      }	
+      ++args_here;
+    }
+      
+    text_t argfile = filename_cat(gsdlhome, "tmp", args[macro_prefix+"tmp"], "argdb.db");
+    argdb *args_on_disk = new argdb(argfile);
+    if (!args_on_disk->update_args(saved_args)) {
+      // error
+      logout << "wizardaction: argdb::update_args failed (" << argfile << ")\n";
+    }
+    
+    // update args from argdb
+    saved_args.erase(saved_args.begin(), saved_args.end());
+    if (!args_on_disk->get_args(saved_args)) {
+      // error
+      logout << "wizardaction: argdb::get_args failed (" << argfile << ")\n";
+    }
+    delete args_on_disk;
+    
+    text_tmap::iterator sa_here = saved_args.begin();
+    text_tmap::iterator sa_end = saved_args.end();
+    while (sa_here != sa_end) {
+      if (!(*sa_here).second.empty()) {
+	args[(*sa_here).first] = (*sa_here).second;
+      }
+      ++sa_here;
+    }  bool first = true;
+
+  }
+}
+
+// tests if collection is write protected (currently just checks if
+// collect.cfg file is writable
+bool wizardaction::collection_protected (const text_t &collection) {
+  text_t cfgfile = filename_cat(gsdlhome, "collect", collection, "etc", "collect.cfg");
+  if (file_writable(cfgfile)) return false;
+  return true;
+}
+
+// set the _statusline_ macro
+void wizardaction::set_statusline (displayclass &disp, cgiargsclass &args, ostream & /*logout*/) {
+
+  // the build command creates .bld.download, .bld.import, and .bld.build files (in that
+  // order) and deletes them (also in that order) when each stage is complete. the .bld
+  // file is the concatenation of all these files.
+  text_t bld_file = filename_cat (gsdlhome, "tmp", args[macro_prefix+"tmp"], args[macro_prefix+"dirname"] + ".bld");
+  text_t statusline;
+
+  if (file_exists (bld_file + ".download")) {
+    statusline = "_collector:textdownloadingfiles_<br>\n";
+    statusline += dm_safe(file_tail(bld_file + ".download", 1, 0));
+  } else if (file_exists (bld_file + ".import")) {
+    statusline = "_collector:textimportingcollection_<br>\n";
+    statusline += dm_safe(file_tail(bld_file + ".import", 1, 0));
+  } else if (file_exists (bld_file + ".build")) {
+    statusline = "_collector:textbuildingcollection_<br>\n";
+    statusline += dm_safe(file_tail(bld_file + ".build", 1, 0));
+  } else {
+    statusline += "_collector:textcreatingcollection_<br>\n";
+    statusline += dm_safe(file_tail(bld_file, 1, 0));
+  }
+
+  disp.setmacro ("statusline", "collector", statusline);
+  disp.setmacro ("statusline", "depositor", statusline); 
+}
+
+
+// if sw = 0 replace all carriage returns in intext with the string "\n"
+// else replace all occurances of "\n" with a carriage return
+text_t wizardaction::carriage_replace (const text_t &intext, int sw) {
+   
+  text_t outtext;
+  text_t::const_iterator here = intext.begin();
+  text_t::const_iterator end = intext.end();
+  while (here != end) {
+    if (sw == 0) {
+      if (*here == '\n') {
+	if ((here+1) != end && *(here+1) == '\r') ++here;
+	outtext += "\\n";
+      } else if (*here == '\r') {
+	if ((here+1) != end && *(here+1) == '\n') ++here;
+	outtext += "\\n";
+      } else {
+	outtext.push_back (*here);
+      }
+    } else if (*here == '\\' && (here+1) != end && *(here+1) == 'n') {
+      outtext.push_back ('\n');
+      ++here;
+    } else {
+      outtext.push_back (*here);
+    }
+    ++here;
+  }
+  return outtext;
+}
+
+
+// create a short directory name from fullname
+text_t wizardaction::get_directory_name (const text_t &fullname) {
+
+  text_t shortname;
+  if (fullname.empty()) {
+    shortname = "coll";
+
+  } else {
+    
+    // first make all lowercase and remove any dodgy characters
+    // (i.e. anything not [a-z]
+    text_t::const_iterator here = fullname.begin();
+    text_t::const_iterator end = fullname.end();
+    while (here != end) {
+      if ((*here >= 'A' && *here <= 'Z') || (*here >= 'a' && *here <= 'z') ||
+	  (*here == ' ')) {
+	if (*here >= 'A' && *here <= 'Z') shortname.push_back (*here+32);
+	else if (*here == ' ') {
+	  while ((*(here+1)) == ' ') ++here;
+	  shortname.push_back (*here);
+	} else shortname.push_back (*here);
+      }
+      ++here;
+    }
+
+    text_tarray words;
+    splitchar (shortname.begin(), shortname.end(), ' ', words);
+    int num_words = words.size();
+
+    if (num_words == 0) {
+      shortname = "coll";
+
+    } else {
+
+      shortname.clear();
+      int use_words = (num_words <= 6) ? num_words : 6;
+      unsigned int substr_len = 6 / use_words;
+      
+      for (int i = 0; i < use_words; ++i) {
+	if (words[i].size() < substr_len) shortname += words[i];
+	else shortname += substr (words[i].begin(), words[i].begin()+substr_len);
+      }
+    }
+  }
+
+  // check to see if shortname is unique
+  text_t fulldirname = filename_cat (gsdlhome, "collect", shortname);
+  if (directory_exists (fulldirname)) {
+    int version = 0;
+    text_t newname;
+    do {
+      ++version;
+      newname = shortname;
+      newname.push_back ('v');
+      newname.appendint (version);
+      fulldirname = filename_cat (gsdlhome, "collect", newname);
+    } while (directory_exists (fulldirname));
+
+    shortname = newname;
+  }
+  
+  return shortname;
+}
+
+// assigns a temporary directory name for this collector session
+// and creates temporary directory
+// returns false if it couldn't create the directory
+bool wizardaction::assign_tmpname (cgiargsclass &args, ostream &logout) {
+
+  int i = 0;
+  text_t tmpname = "tbuild";
+  while (directory_exists (filename_cat (gsdlhome, "tmp", tmpname + text_t(i)))) {
+    ++i;
+  }
+  tmpname.appendint (i);
+
+  text_t fulltmpdir = filename_cat (gsdlhome, "tmp", tmpname);
+  if (!mk_dir (fulltmpdir)) {
+    outconvertclass text_t2ascii;
+    logout << text_t2ascii << "collectoraction::assign_tmpname unable to create directory ("
+	   << fulltmpdir << ")\n";
+    return false;
+  }
+
+  args[macro_prefix + "tmp"] = tmpname;
+  return true;
+}
+
+// set the _fullnamemenu_ macro (and _warnindex_ and _selectedindex_ if
+// we're on the "srce" page)
+void wizardaction::set_fullnamemenu (displayclass &disp, cgiargsclass &args, 
+					recptprotolistclass *protos, ostream &logout) {
+
+  if (recpt == NULL) {
+    logout << "ERROR (collectoraction::set_fullnamemenu): This action does not contain\n"
+	   << "       information about any receptionists. The method set_receptionist was\n"
+	   << "       probably not called from the module which instantiated this action.\n";
+    return;
+  }
+
+  text_t &current_page = args["p"];
+  text_t currentname = args[macro_prefix+"dirname"];
+  if (current_page == "srce") currentname = args[macro_prefix + "clonecol"];
+
+  text_tarray dirnames;
+  text_tarray fullnames;
+  vector<bool> write_protected;
+  text_tarray  build_type;
+
+  bool is_selected = false;
+  int selected_index = 0;
+  int index = 0;
+
+  recptprotolistclass::iterator rprotolist_here = protos->begin();
+  recptprotolistclass::iterator rprotolist_end = protos->end();
+  while (rprotolist_here != rprotolist_end) {
+    if ((*rprotolist_here).p != NULL) {
+
+      // don't include z39.50 collections
+      comerror_t err = noError;
+      if ((*rprotolist_here).p->get_protocol_name (err) == "z3950proto") {
+	++rprotolist_here;
+	continue;
+      }
+
+      text_tarray collist;
+      (*rprotolist_here).p->get_collection_list (collist, err, logout);
+      if (err == noError) {
+	text_tarray::iterator collist_here = collist.begin();
+	text_tarray::iterator collist_end = collist.end();
+	while (collist_here != collist_end) {
+	  ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr ((*rprotolist_here).p, *collist_here, logout);
+	  if (cinfo != NULL) {
+	    text_t collectionname = cinfo->get_collectionmeta("collectionname", args["l"]);
+	    if (collectionname.empty()) {
+	      collectionname = *collist_here;
+	    }
+	    dirnames.push_back(*collist_here);
+	    fullnames.push_back(collectionname);
+	    // check to see if the collection is writable
+	    if (collection_protected (*collist_here)) write_protected.push_back(true);
+	    else write_protected.push_back(false);
+
+	    // remember build type for collection (mg, mgpp, lucene, ...)
+	    // used to determine cgi arg 'ct' later on and minus option to 'build'
+	    build_type.push_back(cinfo->buildType);
+
+	    if (*collist_here == currentname) {
+	      is_selected = true;
+	      selected_index = index; 	    
+	    }
+	    ++index;
+	  }
+	  ++collist_here;
+	}
+      }
+    }
+    ++rprotolist_here;
+  }
+
+  bool first = true;
+
+  text_t warnindex;
+  text_t fullnamemenu = "<select name=\""+macro_prefix+"dirname\" onChange=\"menuchange();\">\n";
+  text_t buildtype_jsarray = "var buildtype = new Array(";
+
+  fullnamemenu += "<option value=\"\">select collection ...</option>\n";
+  buildtype_jsarray += "\"\" ";
+
+  for (int i = 0; i < index; ++i) {
+    // don't want write protected collections in list on "change existing
+    // collection" page
+    if (write_protected[i] && current_page == "existing") continue;
+    fullnamemenu += "<option value=\"" + dirnames[i] + "\"";
+    if (is_selected && i == selected_index) {
+      fullnamemenu += " selected";
+      ++selected_index;
+      is_selected = false;
+    }
+    fullnamemenu.push_back ('>');
+    fullnamemenu += fullnames[i];
+    fullnamemenu.push_back ('\n');
+
+    buildtype_jsarray += ", \"" + build_type[i] + "\"";
+    
+    first = false;
+  }
+  fullnamemenu += "</select>\n";
+
+  buildtype_jsarray += ");";
+
+  text_t action_name = get_action_name();
+  disp.setmacro ("fullnamemenu", action_name, fullnamemenu);
+  disp.setmacro ("buildtypearray", action_name, buildtype_jsarray);
+}
+
+// checks to see if any of the plugins in pluginset occur in 
+// collections configuration file
+bool wizardaction::uses_weird_plugin (const text_t &collection) {
+
+  text_tset pluginset;
+  pluginset.insert ("HBPlug");
+
+  text_t cfgfile_content;
+  text_t cfgfile_name = filename_cat (gsdlhome, "collect", collection, "etc", "collect.cfg");
+  text_t pluginstr, pluginname;
+
+  if (read_file (cfgfile_name, cfgfile_content)) {
+    text_t::const_iterator here = cfgfile_content.begin();
+    text_t::const_iterator end = cfgfile_content.end();
+    while (here != end) {
+      here = findchar (here, end, 'p');
+      if (here == end) break;
+      if ((here+6 < end) && (substr (here, here+6) == "plugin")) {
+	getdelimitstr (here+6, end, '\n', pluginstr);
+	text_t::const_iterator hp = pluginstr.begin();
+	text_t::const_iterator ep = pluginstr.end();
+	bool found = false;
+	// remove any leading whitespace, trailing options etc.
+	while (hp != ep) {
+	  if (*hp == '\t' || *hp == ' ' || *hp == '\n') {
+	    if (found) break;
+	  } else {
+	    pluginname.push_back (*hp);
+	    found = true;
+	  }
+	  ++hp;
+	}
+	text_tset::const_iterator it = pluginset.find (pluginname);
+	if (it != pluginset.end()) return true; // found matching plugin
+	pluginname.clear();
+      }
+      ++here;
+    }
+  }
+  return false;
+}
+
+void wizardaction::gsdl_build (cgiargsclass &args, ostream &logout) {
+
+  outconvertclass text_t2ascii;
+
+  //check to see if the tbuild directory exists
+  text_t tmpdir = filename_cat (gsdlhome, "tmp", args[macro_prefix+"tmp"]);
+  if (!directory_exists (tmpdir)) {
+    message = "tmpfail";
+    return;
+  }
+  
+  //check to see if collection name specified
+  text_t &collection = args[macro_prefix+"dirname"];
+  if (collection.empty()) {
+    message = "nocollection";
+    return;
+  }
+
+  // check for a .build file - if it exists then we've already built
+  // the collection (or are in the process of building it)
+  text_t buildfile = filename_cat (tmpdir, ".build");
+  if (file_exists (buildfile)) {
+    return;
+  } else {
+    // create the .build file (this file is just a place holder to let any future
+    // pages know that we've already been here)
+    char *buildfilec = buildfile.getcstr();
+    ofstream bfile_out (buildfilec);
+    delete []buildfilec;
+    if (bfile_out) {
+      bfile_out << "collection building\n";
+      bfile_out.close();
+    } else {
+      message = "tmpfail";
+      return;
+    }
+  }
+
+  //FLAG!
+  const recptconf &rcinfo = recpt->get_configinfo ();
+
+  // create the event header file if LogEvents, EmailEvents or
+  // EmailUserEvents options are turned on.
+  bool logevents = 
+    (rcinfo.LogEvents == CollectorEvents || rcinfo.LogEvents == AllEvents || 
+     rcinfo.EmailEvents == CollectorEvents || rcinfo.EmailEvents == AllEvents ||
+     rcinfo.EmailUserEvents);
+  text_t ehead_file = filename_cat (tmpdir, "ehead.txt");
+  if (logevents) {
+    if (!create_event_header_file (ehead_file, args, logout)) {
+      logevents = false;
+    }
+  }
+    
+  text_t collectdir = get_collectdir (args);
+
+  // set up build options
+  //text_t options = "-make_writable -remove_import -out \""; 
+  text_t options = "-make_writable  -out \""; 
+  options += filename_cat (tmpdir, collection + ".bld");
+  options += "\" -collectdir \"" + collectdir + "\" -statsfile \"";
+  options += filename_cat(collectdir, collection, "etc", "import.log") + "\"";
+
+  if (args[macro_prefix+"esrce"] == 1) {
+    // we're adding data to an existing collection
+    options += " -save_archives -append -manifest";
+  }
+
+  text_tarray inputvalues, inputtypes;
+  splitchar (args[macro_prefix+"input"].begin(), args[macro_prefix+"input"].end(), ',', inputvalues);
+  splitchar (args[macro_prefix+"inputtype"].begin(), args[macro_prefix+"inputtype"].end(), ',', inputtypes);
+  int numvalues = inputvalues.size();
+  int numtypes = inputtypes.size();
+  for (int i = 0; i < numvalues; ++i) {
+    if (!inputvalues[i].empty()) {
+      text_t type = "file://"; // default
+      if (i < numtypes) type = inputtypes[i];
+      options += " -download \"" + 
+	remove_trailing_slashes(type + format_url(decode_commas(inputvalues[i]))) + "\"";
+    }
+  }
+
+  if (logevents) {
+    if (rcinfo.LogEvents == CollectorEvents || rcinfo.LogEvents == AllEvents) 
+      options += " -log_events";
+    if (rcinfo.EmailEvents == CollectorEvents || rcinfo.EmailEvents == AllEvents) {
+      options += " -mail_server " + rcinfo.MailServer;
+      options += " -email_events " + rcinfo.maintainer;
+      if (rcinfo.EmailUserEvents) options += "," + args[macro_prefix+"contactemail"];
+    } else if (rcinfo.EmailUserEvents) {
+      options += " -mail_server " + rcinfo.MailServer;
+      options += " -email_events " + args[macro_prefix+"contactemail"];
+    }
+    options += " -event_header " + ehead_file;
+  }
+
+  text_t indextype = args[macro_prefix+"buildtype"];
+  if(indextype == "") {
+    indextype = "mg";
+  }
+  options += " -indextype \"" + indextype + "\"";
+
+  text_t optionfile = filename_cat (tmpdir, "build.opt");
+  char *optionfilec = optionfile.getcstr();
+  ofstream ofile_out (optionfilec);
+  delete []optionfilec;
+  if (!ofile_out) {
+    message = "tmpfail";
+    return;
+  }
+  ofile_out << text_t2ascii << options << "\n";
+  ofile_out.close();
+
+  // if we're altering an existing collection we need to kill off
+  // the existing collection server - we do this for the local library
+  // (and any other persistent version of the library) as the existing
+  // gdbm file can't be deleted while the collection server holds it open
+  if ((args[macro_prefix+"econf"] == 1) || (args[macro_prefix+"esrce"] == 1)) {
+    remove_colservr (collection, logout);
+  }    
+
+  // set up the build command - build.bat has some issues with quoting
+  // on win2k when gsdlhome contains spaces so we'll avoid using 
+  // "perl -S" here in favor of calling the "build" perl script explicitly
+  text_t build_cmd = "perl \"" + filename_cat (gsdlhome, "bin", "script", "build");
+  build_cmd += "\" -optionfile \"" + optionfile + "\" " + collection;
+
+  // run build command in background (i.e. asynchronously) 
+  gsdl_system (build_cmd, false, logout);
+
+}
+
+void wizardaction::gsdl_cancel_build (cgiargsclass &args, ostream &logout) {
+  // I really wanted to do what this perl script does fromS within the library
+  // c++ code. I ran into some problems though (like how do you write a portable
+  // "rm -r" in c++?). One day I'll spend some time sorting it out ... maybe.
+  text_t cancel_cmd = "perl -S cancel_build.pl -collectdir \"";
+  cancel_cmd += filename_cat (gsdlhome, "tmp", args[macro_prefix+"tmp"]) + "\" ";
+  cancel_cmd += args[macro_prefix+"dirname"];
+  // To be on the safe side we'll make this a synchronous call
+  // so that all tidying up is done before the user has a chance
+  // to do anything else (like start rebuilding their collection).
+  // This means that for a big collection where there's lots of 
+  // stuff to delete etc. it might take a while before the "build
+  // cancelled" page appears.
+  gsdl_system (cancel_cmd, true, logout);
+}
+
+text_t wizardaction::get_collectdir (cgiargsclass &args)
+{
+  if ((args[macro_prefix+"econf"] == 1) || (args[macro_prefix+"esrce"] == 1)) {
+    // we're adding to a collection in place
+    return filename_cat(gsdlhome, "collect");  
+  }
+  else {
+    return filename_cat (gsdlhome, "tmp", args[macro_prefix+"tmp"]);
+  }
+}
+
+// create and initialize a new collection server and
+// add it to the null protocol.
+void wizardaction::create_colserver (const text_t &collection, ostream &logout) {
+
+  recptprotolistclass *protos = recpt->get_recptprotolist_ptr();
+  recptprotolistclass::iterator rprotolist_here = protos->begin();
+  recptprotolistclass::iterator rprotolist_end = protos->end();
+  while (rprotolist_here != rprotolist_end) {
+    comerror_t err = noError;
+    if ((*rprotolist_here).p != NULL) {
+      if ((*rprotolist_here).p->get_protocol_name (err) == "nullproto") {
+	// create collection server and add it to nullproto
+	(*rprotolist_here).p->add_collection (collection, recpt, gsdlhome, gsdlhome);
+	// make sure gsdlhome is configured
+	text_tarray tmp;
+	tmp.push_back (gsdlhome);
+	(*rprotolist_here).p->configure ("gsdlhome", tmp, err);
+	// re-initialize the null protocol
+	if (!(*rprotolist_here).p->init (err, logout)) {
+	  logout << "wizardaction::create_colserver: nullproto init failed\n";
+	}
+	return;
+      }
+    }
+    ++rprotolist_here;
+  }
+
+  logout << "wizardaction::create_colserver: no valid nullproto found\n";
+}
+
+// delete a collection server from the null protocol
+void wizardaction::remove_colservr (const text_t &collection, ostream &logout) {
+
+  recpt->uncache_collection (collection);
+
+  recptprotolistclass *protos = recpt->get_recptprotolist_ptr();
+  recptprotolistclass::iterator rprotolist_here = protos->begin();
+  recptprotolistclass::iterator rprotolist_end = protos->end();
+  while (rprotolist_here != rprotolist_end) {
+    comerror_t err = noError;
+    if ((*rprotolist_here).p != NULL) {
+      if ((*rprotolist_here).p->get_protocol_name (err) == "nullproto") {
+	(*rprotolist_here).p->remove_collection (collection, logout);
+	return;
+      }
+    }
+    ++rprotolist_here;
+  }
+
+  logout << "wizardaction::create_colserver: no valid nullproto found\n";
+}
+
+bool wizardaction::create_event_header_file (const text_t &filename, cgiargsclass &args, 
+						ostream &logout) {
+
+  outconvertclass text_t2ascii;
+  char *filenamec = filename.getcstr();
+  ofstream eheadfile (filenamec);
+  delete []filenamec;
+
+  if (eheadfile) {
+    eheadfile << text_t2ascii << get_event_header (args);
+    eheadfile.close();
+    return true;
+  }
+   
+  logout << text_t2ascii << "wizardaction::create_event_header ERROR: Couldn't create "
+	 << "Event Header file " << filename << ". Event logging disabled\n";
+  return false;
+}
+
+text_t wizardaction::get_event_header (cgiargsclass &args) {
+  text_t header = "Greenstone Username: " + args["un"] + "\n";
+  header += "Collection: " + args[macro_prefix+"dirname"] + "\n";
+  header += "Collection Creator: " + args[macro_prefix+"contactemail"] + "\n";
+  header += "GSDLHOME: " + gsdlhome + "\n";
+  header += "Build Location: " + get_collectdir(args) + "\n";
+
+  return header;
+}
+
+
+// format_url simply strips "http://", "ftp://", or "file://" off the
+// beginning of url if they're there
+text_t wizardaction::format_url (const text_t &url) {
+  text_t::const_iterator begin = url.begin();
+  text_t::const_iterator end = url.end();
+
+  if (url.size() >= 7) {
+    text_t prefix = substr(begin, begin+7);
+    if (prefix == "http://" || prefix == "file://") {
+      return substr(begin+7, end);
+    }
+  }
+  if (url.size() >= 6) {
+    if (substr(begin, begin+6) == "ftp://") {
+      return substr(begin+6, end);
+    }
+  }
+  return url;
+}
+
+text_t wizardaction::remove_trailing_slashes (text_t str) {
+
+  while (*(str.end()-1) == '\\') {
+    str.pop_back();
+  }
+  return str;
+}
+
Index: trunk/gsdl/src/recpt/wizardaction.h
===================================================================
--- trunk/gsdl/src/recpt/wizardaction.h	(revision 11998)
+++ trunk/gsdl/src/recpt/wizardaction.h	(revision 11998)
@@ -0,0 +1,111 @@
+/**********************************************************************
+ *
+ * wizardaction.h -- 
+ * Copyright (C) 2000  The New Zealand Digital Library Project
+ *
+ * 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 "gsdl_modules_cfg.h"
+
+#ifndef WIZARDACTION_H
+#define WIZARDACTION_H
+
+#include "action.h"
+#include "receptionist.h"
+
+class wizardaction : public action {
+  
+
+public:
+  wizardaction ();
+  virtual ~wizardaction ();
+
+  void configure (const text_t &key, const text_tarray &cfgline);
+
+  bool init (ostream &logout);
+
+  void set_receptionist (receptionist *therecpt) {recpt=therecpt;}
+
+  text_t get_action_name () {return "wizard";}
+
+  void get_cgihead_info (cgiargsclass &args, recptprotolistclass *protos,
+			 response_t &response,text_t &response_data, 
+			 ostream &logout);
+
+  bool check_cgiargs (cgiargsinfoclass &argsinfo, cgiargsclass &args, 
+		      recptprotolistclass * protos, ostream &logout);
+
+
+protected:
+  bool disabled;
+  receptionist *recpt;
+  char *gsdlosc;
+  char *gsdlhomec;
+  char *pathc;
+
+  text_t macro_prefix;
+
+  text_t message;
+  char failcode;
+
+  virtual text_t get_button (cgiargsclass &args, const text_t &thispage, 
+			     const text_t &color, 
+			     const text_t &type, bool enabled)=0;
+			    
+
+  text_t carriage_replace (const text_t &intext, int sw);
+
+  text_t get_directory_name (const text_t &fullname);
+
+  bool collection_protected (const text_t &collection);
+
+  bool assign_tmpname (cgiargsclass &args, ostream &logout);
+
+
+  void set_statusline (displayclass &disp, cgiargsclass &args, ostream &logout);
+  void gsdl_build (cgiargsclass &args, ostream &logout);
+
+  void gsdl_cancel_build (cgiargsclass &args, ostream &logout);
+
+  text_t get_collectdir (cgiargsclass &args);
+
+  void create_colserver (const text_t &collection, ostream &logout);
+
+  void remove_colservr (const text_t &collection, ostream &logout);
+
+  bool create_event_header_file (const text_t &filename, cgiargsclass &args, 
+				 ostream &logout);
+
+  text_t get_event_header (cgiargsclass &args);
+
+  text_t format_url (const text_t &url);
+
+  text_t remove_trailing_slashes (text_t str);
+
+  void set_fullnamemenu (displayclass &disp, cgiargsclass &args,
+			 recptprotolistclass *protos, ostream &logout);
+
+  bool uses_weird_plugin (const text_t &collection);
+
+};
+
+#endif //!WIZARDACTION_H
+
