Index: trunk/gsdl/lib/cfgread.cpp
===================================================================
--- trunk/gsdl/lib/cfgread.cpp	(revision 1738)
+++ trunk/gsdl/lib/cfgread.cpp	(revision 1739)
@@ -49,5 +49,5 @@
     filein.get(c);
   }
-  if (key.empty()) return -1;
+  if (key.empty()) return 0; // blank line maybe?
   return 0;
 } 
Index: trunk/gsdl/lib/fileutil.cpp
===================================================================
--- trunk/gsdl/lib/fileutil.cpp	(revision 1738)
+++ trunk/gsdl/lib/fileutil.cpp	(revision 1739)
@@ -170,4 +170,36 @@
 }
 
+bool read_dir (const text_t &dirname, text_tset &filelist) {
+  
+  WIN32_FIND_DATA FileData;  
+  HANDLE hSearch; 
+  char *dirpath = dirname.getcstr();
+  strcat (dirpath, "\\*");
+  
+  hSearch = FindFirstFile(dirpath, &FileData); 
+  // freeing this memory can cause a runtime error on some (particularly
+  // debug) versions of VC++
+  delete dirpath;
+  
+  if (hSearch == INVALID_HANDLE_VALUE) {
+    return false;
+  }
+  
+  text_t filename = FileData.cFileName;
+  if (filename != "." && filename != ".." && filename != "CVS")
+    filelist.insert (filename); 
+  
+  while (FindNextFile(hSearch, &FileData)) {
+    filename = FileData.cFileName;
+    if (filename == "." || filename == ".." || filename == "CVS")
+      continue;
+    filelist.insert (filename); 
+  }
+  
+  FindClose(hSearch);
+  
+  return true;
+}
+
 bool read_dir (const text_t &dirname, text_tarray &filelist) {
   
@@ -217,7 +249,26 @@
 }
 
+bool read_dir (const text_t &dirname, text_tset &filelist) {
+  
+  char *tmp = dirname.getcstr();
+  DIR *dirin = opendir (tmp);
+  delete tmp;
+  
+  if (dirin == NULL) return false;
+  
+  dirent *dirp; 
+  
+  text_t filename;
+  while ((dirp = readdir (dirin)) != NULL) {
+    filename = dirp->d_name;
+    if (filename == "." || filename == ".." || filename == "CVS")
+      continue;
+    filelist.insert (filename);
+  }
+  closedir (dirin);
+  return true;
+}
+
 bool read_dir (const text_t &dirname, text_tarray &filelist) {
-  
-  filelist.erase (filelist.begin(), filelist.end());
   
   char *tmp = dirname.getcstr();
Index: trunk/gsdl/lib/fileutil.h
===================================================================
--- trunk/gsdl/lib/fileutil.h	(revision 1738)
+++ trunk/gsdl/lib/fileutil.h	(revision 1739)
@@ -49,5 +49,8 @@
 bool directory_exists (const text_t &dirname);
 
+// note that read_dir appends to filelist, it doesn't clear
+// it first
 bool read_dir (const text_t &dirname, text_tarray &filelist);
+bool read_dir (const text_t &dirname, text_tset &filelist);
 
 bool file_copy (const text_t &fromfile, const text_t &tofile);
Index: trunk/gsdl/src/recpt/nullproto.h
===================================================================
--- trunk/gsdl/src/recpt/nullproto.h	(revision 1738)
+++ trunk/gsdl/src/recpt/nullproto.h	(revision 1739)
@@ -41,6 +41,6 @@
   // add_collection sets up the collectionserver and calls
   // add_collectserver
-  void add_collection (const text_t &collection, void *recpt, 
-		       const text_t &gsdlhome, const text_t &gdbmhome);
+  virtual void add_collection (const text_t &collection, void *recpt, 
+			       const text_t &gsdlhome, const text_t &gdbmhome);
 
   // add_collectserver should be called for each collection server
Index: trunk/gsdl/src/w32server/cgiwrapper.cpp
===================================================================
--- trunk/gsdl/src/w32server/cgiwrapper.cpp	(revision 1738)
+++ trunk/gsdl/src/w32server/cgiwrapper.cpp	(revision 1739)
@@ -187,4 +187,6 @@
 DWORD lastlibaccesstime;
 DWORD baseavailvirtual;
+text_t current_gsdlhome;
+colinfo_tmap translated_collectinfo;
 
 static void page_errormaincfg (const text_t &gsdlhome, const text_t &collection) {
@@ -351,7 +353,5 @@
   text_t collection = "";
   text_tset gsdlhomes;
-  text_tarray collections;
-  colinfo_tmap::const_iterator this_info = gsdl_collectinfo.begin();
-  colinfo_tmap::const_iterator end_info = gsdl_collectinfo.end();
+  text_tset collections;
 
   // note the current time
@@ -363,25 +363,77 @@
   if (!checkdir (gsdl_gsdlhome + "\\macros\\")) return 0;
 
-  if (collection.empty()) {
-
-    // get all collections from each gsdlhome (this relies 
-    // on there not being more than one collection with the same 
-    // name)
-    read_dir (filename_cat (gsdl_gsdlhome, "collect"), collections);
+  // get all collections from each gsdlhome (this relies 
+  // on there not being more than one collection with the same 
+  // name)
+
+  if (!collection.empty()) {
+    // collection specific receptionist - one collection, one gsdlhome
+    collections.insert (collection);
     gsdlhomes.insert (gsdl_gsdlhome);
+    collectioninfo_t tmp;
+    tmp.gsdl_gsdlhome = gsdl_gsdlhome;
+    tmp.gsdl_gdbmhome = gsdl_gdbmhome;
+    translated_collectinfo[collection] = tmp;
+
+  } else {
+
+    text_tset::const_iterator colhere;
+    text_tset::const_iterator colend;
+    text_tset these_collections;
+
+    // first volume gsdlhome's
+    colinfo_tmap::const_iterator this_info = gsdl_collectinfo.begin();
+    colinfo_tmap::const_iterator end_info = gsdl_collectinfo.end();
     while (this_info != end_info) {
       if (gsdlhomes.find ((*this_info).second.gsdl_gsdlhome) == gsdlhomes.end()) {
-	read_dir (filename_cat ((*this_info).second.gsdl_gsdlhome, "collect"), collections);
+	these_collections.erase (these_collections.begin(), these_collections.end());
+	read_dir (filename_cat ((*this_info).second.gsdl_gsdlhome, "collect"), these_collections);
+	colhere = these_collections.begin();
+	colend = these_collections.end();
+	while (colhere != colend) {
+	  if ((collections.find (*colhere)) == collections.end()) {
+	    // make sure the build.cfg file is at gsdlhome (as it's possible that
+	    // the collection appears at this gsdlhome only because it's gdbm
+	    // file is installed here -- it's real gdbm will therefore be 
+	    // somewhere else).
+	    text_t build_cfg = filename_cat ((*this_info).second.gsdl_gsdlhome, "collect",
+					     *colhere, "index", "build.cfg");
+	    if (file_exists (build_cfg)) {
+	      collections.insert (*colhere);
+
+	      // since gsdl_collectinfo keys will be stuff like collection#1
+	      // for a multiple volume collection we want to translate it
+	      // so that the keys are the actual collection names
+	      translated_collectinfo[*colhere] = (*this_info).second;
+	    }
+	  }
+	  colhere ++;
+	}
 	gsdlhomes.insert ((*this_info).second.gsdl_gsdlhome);
       }
       this_info ++;
     }
-  } else {
-    collections.push_back (collection);
-    gsdlhomes.insert (gsdl_gsdlhome);
-  }
-  
-  text_tarray::const_iterator thiscol = collections.begin();
-  text_tarray::const_iterator endcol = collections.end();
+  
+    // then if necessary the main gsdlhome (this should only happen if the 
+    // gsdl.ini is a little screwed up and no volume gsdlhomes occurred
+    if (gsdlhomes.find (gsdl_gsdlhome) == gsdlhomes.end()) {
+      these_collections.erase (these_collections.begin(), these_collections.end());
+      read_dir (filename_cat (gsdl_gsdlhome, "collect"), these_collections);
+      colhere = these_collections.begin();
+      colend = these_collections.end();
+      while (colhere != colend) {
+	collections.insert (*colhere);
+	collectioninfo_t tmp;
+	tmp.gsdl_gsdlhome = gsdl_gsdlhome;
+	tmp.gsdl_gdbmhome = gsdl_gdbmhome;
+	translated_collectinfo[*colhere] = tmp;
+	colhere ++;
+      }
+      gsdlhomes.insert (gsdl_gsdlhome);
+    }
+  }
+
+  text_tset::const_iterator thiscol = collections.begin();
+  text_tset::const_iterator endcol = collections.end();
 
   while (thiscol != endcol) {
@@ -394,5 +446,12 @@
     
     // create collection server and add to null protocol
-    nproto.add_collection (*thiscol, &recpt, gsdl_gsdlhome, gsdl_gsdlhome);
+    text_t this_gsdlhome = gsdl_gsdlhome;
+    text_t this_gdbmhome = gsdl_gdbmhome;
+    colinfo_tmap::const_iterator it = translated_collectinfo.find (*thiscol);
+    assert (it != translated_collectinfo.end());
+    this_gsdlhome = (*it).second.gsdl_gsdlhome;
+    this_gdbmhome = (*it).second.gsdl_gdbmhome;
+
+    nproto.add_collection (*thiscol, &recpt, this_gsdlhome, this_gdbmhome);
     
     thiscol ++;
@@ -479,22 +538,16 @@
 
   int maxrequests = 1;
-  text_tset seenhomes;
-  this_info = gsdl_collectinfo.begin();
-
-  // configure any collections with gsdlhome (or gdbmhome) 
+
+  // configure collections (and receptionist) with collectinfo stuff
   // different from the default
+  colinfo_tmap::const_iterator this_info = translated_collectinfo.begin();
+  colinfo_tmap::const_iterator end_info = translated_collectinfo.end();
+
   while (this_info != end_info) {
-    if (((*this_info).second.gsdl_gsdlhome != gsdl_gsdlhome) ||
-	((*this_info).second.gsdl_gdbmhome != gsdl_gdbmhome) &&
-	(seenhomes.find ((*this_info).second.gsdl_gsdlhome + 
-			 (*this_info).second.gsdl_gdbmhome) == seenhomes.end())) {
-      text_tarray tmpconf;
-      tmpconf.push_back ((*this_info).first);
-      tmpconf.push_back ((*this_info).second.gsdl_gsdlhome);
-      tmpconf.push_back ((*this_info).second.gsdl_gdbmhome);
-      recpt.configure ("collectinfo", tmpconf);
-      seenhomes.insert ((*this_info).second.gsdl_gsdlhome + 
-			(*this_info).second.gsdl_gdbmhome);
-    }
+    text_tarray tmpconf;
+    tmpconf.push_back ((*this_info).first);
+    tmpconf.push_back ((*this_info).second.gsdl_gsdlhome);
+    tmpconf.push_back ((*this_info).second.gsdl_gdbmhome);
+    recpt.configure ("collectinfo", tmpconf);
     this_info ++;
   }
@@ -563,12 +616,5 @@
 
   // set up file name
-  text_t filenamet = text_t(gsdl_gsdlhome) + filename;
-  text_t::iterator here = filenamet.begin();
-  text_t::iterator end = filenamet.end();
-  while (here != end) {
-	  if (*here == '/') *here = '\\';
-	  here ++;
-  }
-
+  text_t filenamet = filename_cat (current_gsdlhome, filename);
   filename = filenamet.getcstr();
 	
@@ -613,5 +659,12 @@
     return;
   } 
-  
+
+  colinfo_tmap::const_iterator it = translated_collectinfo.find (args["c"]);
+  if (it != translated_collectinfo.end()) {
+    current_gsdlhome = (*it).second.gsdl_gsdlhome;
+  } else {
+    current_gsdlhome = gsdl_gsdlhome;
+  }
+
   // produce cgi header
   response_t response;
Index: trunk/gsdl/src/w32server/cgiwrapper.h
===================================================================
--- trunk/gsdl/src/w32server/cgiwrapper.h	(revision 1738)
+++ trunk/gsdl/src/w32server/cgiwrapper.h	(revision 1739)
@@ -34,6 +34,4 @@
 extern int libaccessnum;
 
-//void configure_httpprefix ();
-
 int ExamineURIStr(char *URIStr,RequestInfoT *RequestInfo,
 		  RequestFieldsT *RequestFields);
Index: trunk/gsdl/src/w32server/settings.cpp
===================================================================
--- trunk/gsdl/src/w32server/settings.cpp	(revision 1738)
+++ trunk/gsdl/src/w32server/settings.cpp	(revision 1739)
@@ -376,4 +376,5 @@
   if (conf) {
     while (read_ini_line(conf, key, value) >= 0) {
+      if (key.empty()) continue;
       if (value.empty()) {
 	// should be a section title
