/**********************************************************************
 *
 * pageaction.cpp -- 
 * Copyright (C) 1999  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.
 *
 *********************************************************************/

// Changelog:

// 11th July 2003:

//   Added 3 functions to deal with the collection style
//   A deciding function and then 2 functions that actually
//   do the work for us, either images or pulldown.


#include "pageaction.h"
#include "receptionist.h"
#include "recptprototools.h"
#include "fileutil.h"
#include "gsdltools.h"
#include "querytools.h"
#include <time.h>

pageaction::pageaction () {

  status_disabled = true;
  collector_disabled = true;
  depositor_disabled = true; 
  translator_disabled = true;
  gliapplet_disabled = true;
  recpt = NULL;

  // this action uses cgi variables "a", "p", and "hp"
  cgiarginfo arg_ainfo;
  arg_ainfo.shortname = "a";
  arg_ainfo.longname = "action";
  arg_ainfo.multiplechar = true;
  arg_ainfo.multiplevalue = false;
  arg_ainfo.defaultstatus = cgiarginfo::weak;
  arg_ainfo.argdefault = "p";
  arg_ainfo.savedarginfo = cgiarginfo::must;
  argsinfo.addarginfo (NULL, arg_ainfo);

  arg_ainfo.shortname = "p";
  arg_ainfo.longname = "page";
  arg_ainfo.multiplechar = true;
  arg_ainfo.multiplevalue = false;
  arg_ainfo.defaultstatus = cgiarginfo::weak;
  arg_ainfo.argdefault = "home";
  arg_ainfo.savedarginfo = cgiarginfo::must;
  argsinfo.addarginfo (NULL, arg_ainfo);

  arg_ainfo.shortname = "hp";
  arg_ainfo.longname = "html page";
  arg_ainfo.multiplechar = true;
  arg_ainfo.multiplevalue = false;
  arg_ainfo.defaultstatus = cgiarginfo::weak;
  arg_ainfo.argdefault = g_EmptyText;
  arg_ainfo.savedarginfo = cgiarginfo::mustnot;
  argsinfo.addarginfo (NULL, arg_ainfo);

  arg_ainfo.shortname = "bp";
  arg_ainfo.longname = "set preferences button";
  arg_ainfo.multiplechar = true;
  arg_ainfo.multiplevalue = false;
  arg_ainfo.defaultstatus = cgiarginfo::weak;
  arg_ainfo.argdefault = g_EmptyText;
  arg_ainfo.savedarginfo = cgiarginfo::mustnot;
  argsinfo.addarginfo (NULL, arg_ainfo);

  // the "u" argument will disable the search facility, remove links to the
  // home and preferences pages, and disable the DocumentButton buttons
  // (for use when generating static html versions of collections)
  arg_ainfo.shortname = "u";
  arg_ainfo.longname = "static page";
  arg_ainfo.multiplechar = false;
  arg_ainfo.multiplevalue = false;
  arg_ainfo.defaultstatus = cgiarginfo::weak;
  arg_ainfo.argdefault = "0";
  arg_ainfo.savedarginfo = cgiarginfo::mustnot;
  argsinfo.addarginfo (NULL, arg_ainfo);

  arg_ainfo.shortname = "book";
  arg_ainfo.longname = "book switch";
  arg_ainfo.multiplechar = true;
  arg_ainfo.multiplevalue = false;
  arg_ainfo.defaultstatus = cgiarginfo::weak;
  arg_ainfo.argdefault = "off";
  arg_ainfo.savedarginfo = cgiarginfo::must;
  argsinfo.addarginfo (NULL, arg_ainfo);

  arg_ainfo.shortname = "talkback";
  arg_ainfo.longname = "DL talkback";
  arg_ainfo.multiplechar = false;
  arg_ainfo.multiplevalue = false;
  arg_ainfo.defaultstatus = cgiarginfo::weak;
  arg_ainfo.argdefault = "0";
  arg_ainfo.savedarginfo = cgiarginfo::must;
  argsinfo.addarginfo (NULL, arg_ainfo);

}

pageaction::~pageaction () {
}

bool pageaction::check_cgiargs (cgiargsinfoclass &/*argsinfo*/, cgiargsclass &args, 
				recptprotolistclass * /*protos*/, ostream &/*logout*/) {

  if (args["p"] == "preferences" && !args["bp"].empty()) {
    if (args["hd"] != "0") args["hd"] = args["hdn"];
  }

  return true;
}

void pageaction::get_cgihead_info (cgiargsclass &/*args*/, recptprotolistclass * /*protos*/,
				   response_t &response,text_t &response_data, 
				   ostream &/*logout*/) {
  response = content;
  response_data = "text/html";
}

// This function helps decide whether we want a
// images or pulldown style collection display
// We refer to the macro files for the options
// for images or pulldown menu and use that to
// switch to the appropriate function to do the job

// Aly Dharshi
// 11th July 2003

void pageaction::homepagestyle(displayclass &disp, recptprotolistclass *protos,
			       cgiargsclass &args, ostream &logout)
{

  const recptconf &configinfo = recpt->get_configinfo();

  if (configinfo.HomePageType == "images") {
     home_images(disp, protos, args, configinfo, logout);

  } else
     {
	home_pulldown(disp, protos, args, configinfo, logout);
     }
}

// This function allows for the Greenstone
// collection to be displayed in a pull down
// menu similar to that in documentaction.cpp

// Aly Dharshi
// 11th July 2003

void pageaction::home_pulldown(displayclass &disp, recptprotolistclass *protos, 
			       cgiargsclass &args, const recptconf &configinfo,
			       ostream &logout) {

   text_t homeextra = "<form method=\"get\" name=\"browse\">\n";
   homeextra += "<select name=\"collections\" onChange=\"location.href=";
   homeextra += "document.browse.collections.options[document.browse.collections.selectedIndex].value\">\n";
   homeextra += "<option value=\"\">_textdescrselcol_</option>\n";
   
  recptprotolistclass::iterator rprotolist_here = protos->begin();
  recptprotolistclass::iterator rprotolist_end = protos->end();
  while (rprotolist_here != rprotolist_end) {
    if ((*rprotolist_here).p != NULL) {

      text_tarray collist;
      comerror_t err;
      (*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();

	int count = 0;
	bool first = true;
	while (collist_here != collist_end) {

	  ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr ((*rprotolist_here).p, *collist_here, logout);
	  
	  if (cinfo != NULL) {
	    if (cinfo->isPublic && (cinfo->buildDate > 0)) {

	      text_t collectionname = cinfo->get_collectionmeta("collectionname", args["l"]);
	      if (collectionname.empty()) {
		collectionname = *collist_here;
	      }
	      
	      comerror_t err;
	      text_t optsite = g_EmptyText;
	      text_t site_name = (*rprotolist_here).p->get_site_name (err);
	      if (!site_name.empty()) { optsite = "site="+site_name+"&amp;"; }
	      
	      text_t link = "_gwcgi_?"+optsite+"a=p&amp;p=about&amp;c=" + *collist_here;
	      link += "&amp;l=" + encodeForURL(args["l"]) + "&amp;w=" + encodeForURL(args["w"]);

	      // We are "dynamically" overriding so to speak the
	      // link to the collection aka receptionist.
	      
	      if (!cinfo->receptionist.empty()) 
		 link = cinfo->receptionist;
	      
	      
	      homeextra += "<option value=\"" + link + "\"";
	      homeextra += ">" + collectionname + "</option>\n";
	      	    
	    }

	    ++collist_here;
	    }
	    
	  }
      }
	++rprotolist_here;
    }
    
    }
  homeextra += "</select>\n";
  homeextra += "</form>\n";
  
  disp.setmacro ("homeextra", "home", homeextra); 
}
  
// originally called set_homeextra_macro
// this function displays the Greenstone
// main page as usual with the graphics for
// the collections.

// Aly Dharshi
// 11th July 2003

void pageaction::home_images(displayclass &disp, recptprotolistclass *protos, 
			     cgiargsclass &args, const recptconf &configinfo,
			     ostream &logout) {
  
  text_t homeextra = "<table class=\"collections\">\n";
  bool found_valid_col = false;
  recptprotolistclass::iterator rprotolist_here = protos->begin();
  recptprotolistclass::iterator rprotolist_end = protos->end();
  while (rprotolist_here != rprotolist_end) {
    if ((*rprotolist_here).p != NULL) {

      text_tarray collist;
      comerror_t err;
      (*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();

	int count = 0;
	while (collist_here != collist_end) {

	  ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr ((*rprotolist_here).p, *collist_here, logout);

	  text_t arg_g = args["g"];
	  text_t colname_dir = *collist_here;
	  
	  if (arg_g.empty()) {
	    // normal top-level home page
	    text_t::const_iterator begin = colname_dir.begin();
	    text_t::const_iterator end = colname_dir.end();

	    if (findchar(begin,end,'/')!=end) {
	      // no g argument, so generating top level home page
	      // => if colname_dir has "/" in collection name, filter it out

	      ++collist_here;
	      continue;
	    }
	  }
	  else {
	    // show only collections in the named group

	    
	    if (colname_dir == arg_g) {
	      // display about this collect text

	      text_t collectionextra = cinfo->get_collectionmeta("collectionextra", args["l"]);
	      if (!collectionextra.empty()) {
		// prepend text on at start
		homeextra = "<p>" + collectionextra + "</p>" + homeextra;
	      }

	      ++collist_here;
	      continue;
	    }


	    // => filter out anything that does not start with the group prefix
	    
	    if (!starts_with(colname_dir,arg_g + "/")) {
	      ++collist_here;
	      continue;
	    }
	  }


	  if (cinfo != NULL) {
	    if (cinfo->isPublic && ((cinfo->buildDate > 0)) || (cinfo->isCollectGroup)) {

	      found_valid_col = true;
	      text_t collectionname = *collist_here;
	      text_t alt = cinfo->get_collectionmeta("collectionname", args["l"]);
	      if (alt.empty()) {
		alt = collectionname;
	      }


	      comerror_t err;
	      text_t optsite = g_EmptyText;
	      text_t site_name = (*rprotolist_here).p->get_site_name (err);
	      if (!site_name.empty()) { optsite = "site="+site_name+"&amp;"; }

	      text_t link;

	      if (cinfo->isCollectGroup) {
		link = "<a class=\"collectiontitle\" href=\"_gwcgi_?"+optsite+"a=p&amp;p=home&amp;g=" + *collist_here;
		link += "&amp;l=" + encodeForURL(args["l"]) + "&amp;w=" + encodeForURL(args["w"]) + "\">";
	      }
	      else {
		link = "<a class=\"collectiontitle\" href=\"_gwcgi_?"+optsite+"a=p&amp;p=about&amp;c=" + *collist_here;
		link += "&amp;l=" + encodeForURL(args["l"]) + "&amp;w=" + encodeForURL(args["w"]) + "\">";
	      }
	      
	      if (!cinfo->receptionist.empty()) 
		link = "<a class=\"collectiontitle\" href=\"" + cinfo->receptionist + "\">";
	      
	      
	      // url to image: try iconcollectionsmall, then iconcollection
	      text_t iconurl = cinfo->get_collectionmeta("iconcollectionsmall", args["l"]);
	      if (iconurl.empty()) {
		iconurl = cinfo->get_collectionmeta("iconcollection", args["l"]);
	      }
	      
	      if (!iconurl.empty()) {
		
		// check to see URL is local to colserver
		text_t::iterator iconurl_head = iconurl.begin();
		text_t iconhead = substr(iconurl_head,iconurl_head+16);
		if (iconhead=="_httpcollection_") {
		  
		  // local and using _httpcollection_
		  text_t icontail = substr(iconurl_head+16,iconurl.end());
		  iconurl = "http://" + cinfo->httpdomain 
		    + cinfo->httpprefix + "/collect/" 
		    + *collist_here + "/" + icontail;
		}
		else if (iconurl[0]=='/') {
		  
		  // local but with full path
		  iconurl = "http://" + cinfo->httpdomain + iconurl;
		}
		
		collectionname 
		  = link + "<img width=\"150\" src=\"" + iconurl + "\" alt=\"" + alt + "\">" + "</a>";
	      } else {		

		collectionname = "<div class=\"collecttitle\" style=\"width: 150px; border: 1px solid; \"><p class=\"collectiontitle\" style=\"font-size: 18px; width: 150px; white-space:normal; text-align: left;\">";
		collectionname += alt + "</p></div>";

		collectionname = link + collectionname + "</a>";

	      }
	      
	      if (count%configinfo.HomePageCols == 0)
		homeextra += "<tr valign=\"top\">\n";	      

	      homeextra += "<td align=\"center\">" + collectionname + "</td>\n";
	      
	      ++count;
	      if (count%configinfo.HomePageCols == 0)
		homeextra += "</tr>\n";
	    }
	  }
	  ++collist_here;
	}

	// Finish off the last row, if necessary
	if (count%configinfo.HomePageCols != 0) {
	  while (count%configinfo.HomePageCols != 0) {
	    homeextra += "<td></td>\n";
	    ++count;
	  }
	  homeextra += "</tr>\n";
	}
      }
    }
    ++rprotolist_here;
  }

  if (!found_valid_col) {
    homeextra += "<tr><td>_textnocollections_</td></tr>\n";
  }
  homeextra += "</table>\n";
  disp.setmacro ("homeextra", "home", homeextra); 
}

void pageaction::set_collectionlist_macro (displayclass &disp, 
					   recptprotolistclass *protos, 
					   cgiargsclass &args, 
					   ostream &logout) {

  text_t collectionlist;
  int count = 0;
  
  recptprotolistclass::iterator rprotolist_here = protos->begin();
  recptprotolistclass::iterator rprotolist_end = protos->end();
  while (rprotolist_here != rprotolist_end) {
    if ((*rprotolist_here).p != NULL) {

      text_tarray collist;
      comerror_t err;
      (*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) {
	    if (cinfo->isPublic && (cinfo->buildDate > 0)) {

	      ++count;

	      text_t collectionname = cinfo->get_collectionmeta("collectionname", args["l"]);
	      if (collectionname.empty()) {
		collectionname = *collist_here;
	      }
	      
	      comerror_t err;
	      text_t optsite = g_EmptyText;
	      text_t site_name = (*rprotolist_here).p->get_site_name (err);
	      if (!site_name.empty()) { optsite = "site="+site_name+"&amp;"; }

	      text_t link = "<a href=\"_gwcgi_?"+optsite+"a=p&p=about&c=" + *collist_here + "\">";

	      if (!cinfo->receptionist.empty()) 
		link = "<a href=\"" + cinfo->receptionist + "\">";
	      
	     collectionlist += "<li>" + link + collectionname + "</a>\n";
	    }
	  }
	  ++collist_here;
	}
      }
    }
    ++rprotolist_here;
  }

  if (count == 1) {
    collectionlist = "<p>_text1coll_\n<ul>" +
      collectionlist + "</ul>\n";
  } else if (count > 1) {
    collectionlist = "<p>_textmorecolls_(" + text_t(count) + 
      ")\n<ul>" + collectionlist + "</ul>\n";
  }

  disp.setmacro ("collectionlist", "homehelp", collectionlist); 
}

void pageaction::set_documentation_macro (displayclass &disp) {

  text_t documentation;
  text_t docsdir = filename_cat(gsdlhome, "docs");
  
  if (file_exists(filename_cat(docsdir, "User.pdf"))) {
    documentation += "<tr valign=middle><td><a href=\"_httpdocs_/User.pdf\">_iconpdf_"
      "</a></td><td>_textuserguide_</td></tr>";
  }
  
  if (file_exists(filename_cat(docsdir, "Install.pdf"))) {
    documentation += "<tr valign=middle><td><a href=\"_httpdocs_/Install.pdf\">_iconpdf_"
      "</a></td><td>_textinstallerguide_</td></tr>";
  }
  
  if (file_exists(filename_cat(docsdir, "Develop.pdf"))) {
    documentation += "<tr valign=middle><td><a href=\"_httpdocs_/Develop.pdf\">_iconpdf_"
      "</a></td><td>_textdeveloperguide_</td></tr>";
  }
  
  if (file_exists(filename_cat(docsdir, "Paper.pdf"))) {
    documentation += "<tr valign=middle><td><a href=\"_httpdocs_/Paper.pdf\">_iconpdf_"
      "</a></td><td>_textpaperguide_</td></tr>";
  }
  
  if (file_exists(filename_cat(docsdir, "Organize.pdf"))) {
    documentation += "<tr valign=middle><td><a href=\"_httpdocs_/Organize.pdf\">_iconpdf_"
      "</a></td><td>_textorganizerguide_</td></tr>";
  }

  if (!documentation.empty()) {
    disp.setmacro("documentation", "docs", "<p>\n<table border=0>\n" + documentation + "\n</table>\n");
  }
}

void pageaction::set_macro_to_file_contents (displayclass &disp, const text_t &macroname,
					     const text_t &packagename, const text_t &filename, bool encode) {

  text_t filecontent;
  char *filenamec = filename.getcstr();
  ifstream file_in (filenamec);
  delete []filenamec;
  if (file_in) {
    char c;
    file_in.get(c);
    while (!file_in.eof ()) {
      if (c == '\n') filecontent += "<br>";
      filecontent.push_back(c);
      file_in.get(c);
    }
    file_in.close();
  }

  // if we ever need to encode the contents into HTML, call this function with encode=true
  if(encode) {
    filecontent = encodeForHTML(filecontent);
  }

  disp.setmacro (macroname, packagename, dm_safe(filecontent));
}

void pageaction::set_language_encoding_macros(displayclass &disp, cgiargsclass &args,
					      recptprotolistclass *protos, ColInfoResponse_t *cinfo,
					      ostream &logout) {
  // _languageoption_
  // Create the "interface language" selection box for the preferences
  // pages.  You can use something like "format PreferenceLanguages
  // en|fr|zn" from within a collect.cfg file to use only a subset of
  // the available languages for any given collection (for
  // collection-specific preferences pages). This facility is kind of
  // ugly though and should be replaced by something better when the
  // configuration files are tidied up (as should all the other
  // "format Preference..." options).
  text_t &arg_l = args["l"];
  const recptconf &configinfo = recpt->get_configinfo();
  // put languages in another map to sort them by longname
  text_tmap languages;
  languageinfo_tmap::const_iterator thislang = configinfo.languages.begin();
  languageinfo_tmap::const_iterator endlang = configinfo.languages.end();
  while (thislang != endlang) {
    languages[(*thislang).second.longname] = (*thislang).first;
    ++thislang;
  }
  text_tmap::iterator tlang = languages.begin();
  text_tmap::iterator elang = languages.end();

  text_t languageoption;
  bool collection_specific = false;

  if (cinfo != NULL) {
    text_tmap::const_iterator it = cinfo->format.find ("PreferenceLanguages");
    if ((it != cinfo->format.end()) && (!(*it).second.empty())) {
      collection_specific = true;
      text_tset pref_langs;
      splitchar ((*it).second.begin(), (*it).second.end(), '|', pref_langs);
      if (pref_langs.size() > 1) {
	while (tlang != elang) {
	  if (pref_langs.find((*tlang).second) != pref_langs.end()) {
	    languageoption += "<option value=\"" + (*tlang).second + "\"";
	    if ((*tlang).second == arg_l) languageoption += " selected";
	    languageoption += ">" + (*tlang).first + "</option>\n";
	  }
	  ++tlang;
	}
      }
    }
  }

  if (!collection_specific) {
    while (tlang != elang) {
      languageoption += "<option value=\"" + (*tlang).second + "\"";
      if ((*tlang).second == arg_l) languageoption += " selected";
      languageoption += ">" + (*tlang).first + "</option>\n";
      ++tlang;
    }
  }

  if (!languageoption.empty()) {
    languageoption = "<select name=\"l\" onChange=\"updatel();\">\n" + languageoption;
    languageoption += "</select>\n";
    disp.setmacro ("languageoption", args["p"], languageoption);
  }

  // _encodingoption_
  // create the "encoding" selection box for the preferences page
  if (configinfo.encodings.size() > 1) {
    text_t &arg_w = args["w"];
    text_t encodingoption;
    text_tmap::const_iterator thisenc = configinfo.encodings.begin();
    text_tmap::const_iterator endenc = configinfo.encodings.end();
    while (thisenc != endenc) {
      encodingoption += "<option value=\"" + (*thisenc).second + "\"";
      if ((*thisenc).second == arg_w) encodingoption += " selected";
      encodingoption += ">" + (*thisenc).first + "</option>\n";
      ++thisenc;
    }

    encodingoption = "<select name=\"w\" onChange=\"updatew();\">\n" + encodingoption;
    encodingoption += "</select>\n";
    disp.setmacro ("encodingoption", args["p"], encodingoption);
  } else if (configinfo.encodings.size() == 1) {
    text_t encodingoption;
    text_tmap::const_iterator thisenc = configinfo.encodings.begin();
    encodingoption = (*thisenc).first;
    disp.setmacro ("encodingoption", args["p"], encodingoption);
  } else { // size == 0. shouldn't really happen, but allow it
    disp.setmacro ("encodingoption", args["p"], "None");
  }

}


void pageaction::define_internal_macros (displayclass &disp, cgiargsclass &args, 
					 recptprotolistclass *protos, ostream &logout) {

  // define_internal_macros sets the following macros:

  // _numdocs_             the number of documents in the collection

  // _builddate_           the date last built

  // if page is "home"
  // _homeextra_           this is the list of available collections and collection info
  //                       to be displayed on the home page


  // if page is "preferences"
  // _collectionoption_    collections to search/browse (if cross-collection-searching is on)

  // _htmloptions_         set to _htmloptionson_ if DocumentUseHTML is set

  // _PreferencesDocsFromWeb_ set to 1 if corresponding format option is set


  // if page is "preferences" or "homepref"
  // _languageoption_      interface languages to select from (dependant on PreferenceLanguages)

  // _encodingoption_      encodings to select from


  // if page is "about"
  // _textsubcollections_  the text on which subcollections make up the collection (if 
  //                       cross-collection searching is being used

  // _textbrowseoptions_   the 'how to find information' text in the about and help pages

  // _numbrowseoptions_    the number of browsing options 

  // _prefschanged_        will be set to _textprefschanged_ if the "set preferences" button
  //                       was pressed

  // _aboutqueryform_      will be set to "" if the collection isn't searchable

  // if page is "help"
  // _textbrowseoptions_   the 'how to find information' text in the about and help pages

  // _numbrowseoptions_    the number of browsing options 

  // _topicreadingdocs_    this section of the help text differs depending on what type of 
  // _textreadingdocs_     collection it is (e.g. html collection, bibliographic collection etc.)
  // _texthelpreadingdocs_ 

  // 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
  // _textgogliapplet_     set to "" if gliapplet is disabled in main.cfg


  // if page is "homehelp"
  // _collectionlist_      list of available collections to be displayed on the homehelp page

  
  // if page is "docs"
  // _documentation_       links to PDF documents if they're available


  // if page is "bsummary"
  // _importlog_           set to contents of collections import.log file
  // _faillog_             set to contents of collections fail.log file
  //_buildlog_             set to contents of collections build.log file
  
  if (recpt == NULL) {
    logout << "ERROR (pageaction::define_internal_macros): 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;
  }
  // _versionnnum_   greenstone version number (hard-coded)
  disp.setmacro("versionnum", displayclass::defaultpackage, GSDL_VERSION);

  text_t &arg_p = args["p"];
  text_t &arg_c = args["c"];
  ColInfoResponse_t *cinfo = NULL;

  recptproto* collectproto = protos->getrecptproto (arg_c, logout);
  if (collectproto != NULL) {
    cinfo = recpt->get_collectinfo_ptr (collectproto, arg_c, logout);
    
    //set the tidyoption
    if (cinfo->useBook == false)
    {
        disp.setmacro ("tidyoption", displayclass::defaultpackage, "untidy");
    }
    else
    {
        disp.setmacro ("tidyoption", displayclass::defaultpackage, "tidy");
    }
    
    disp.setmacro ("numdocs", displayclass::defaultpackage, cinfo->numDocs);
    disp.setmacro ("numsections", displayclass::defaultpackage, cinfo->numSections);
    disp.setmacro ("numwords", displayclass::defaultpackage, cinfo->numWords);
    unsigned long current_time = time(NULL);
    unsigned long builddate = (current_time - cinfo->buildDate) / 86400;
    disp.setmacro ("builddate", displayclass::defaultpackage, builddate);
    
    text_t numbytes;
    if ((cinfo->numBytes/(1024*1024)) > 1) {
      numbytes = (text_t)(cinfo->numBytes/(1024*1024)) + " Mb";
    } else if ((cinfo->numBytes/1024) > 1) {
      numbytes = (text_t)(cinfo->numBytes/1024) + " kb";
    } else {
      numbytes = (text_t)cinfo->numBytes + " bytes";
    }
    disp.setmacro("numbytes", displayclass::defaultpackage, numbytes);

    // set up ct, qt, qto, sqlqto
    set_query_type_args(cinfo, args);
    // set up ks, ss, afs
    set_stem_index_args(cinfo, args);
  
  }
  
  //setting _queryformcontent_ so that the query interface is consistent.
  //also adding usability button if necessary
  if (arg_p == "about") {
    if (cinfo == NULL) {
      disp.setmacro("cvariable", displayclass::defaultpackage, encodeForHTML(arg_c));
      disp.setmacro("content", arg_p, "<p>_textbadcollection_<p>");
      return;
    }
    else {

      text_tmap::iterator check = cinfo->format.find("QueryInterface");
      if(check != cinfo->format.end()){
	if((*check).second=="DateSearch"){
	  text_t current = "_datesearch_";
	  disp.setmacro("optdatesearch","query",current);
	}
      }
      check = cinfo->format.find("Usability");
      if(check != cinfo->format.end()){
	disp.setmacro("usability", displayclass::defaultpackage, "_usablink_");
	disp.setmacro("usabinterface", displayclass::defaultpackage, ("_usab"+(*check).second+"_"));
	disp.setmacro("usabilityscript", displayclass::defaultpackage, "_usabshowscript_");
      }
    }
  }
  
  
  if (arg_p == "home" || arg_p == "homehelp") {
    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", "");

    if (arg_p == "home") {
      homepagestyle (disp, protos, args, logout);
    } else if (arg_p == "homehelp") {
      set_collectionlist_macro (disp, protos, args, logout);
    }

  } else if (arg_p == "gli") {
    if (gliapplet_disabled) disp.setmacro ("gliapplet", "gli", "");

  } else if (arg_p == "homepref") {
  
    // set _languageoption_ and _encodingoption_
    set_language_encoding_macros(disp, args, protos, cinfo, logout);

  } else if (arg_p == "preferences") {
  
    if (cinfo == NULL) {
      disp.setmacro("cvariable", displayclass::defaultpackage, encodeForHTML(arg_c));
      disp.setmacro("content", arg_p, "<p>_textbadcollection_<p>");
      return;
    }

    if (collectproto == NULL) {return;}
    
    // set _languageoption_ and _encodingoption_
    set_language_encoding_macros(disp, args, protos, cinfo, logout);

    // _collectionoption_
    if ((args["ccs"] == "1") && (cinfo->ccsCols.size() > 1)) {
      text_t collectionoption = "_textcollectionoption_";
      text_tarray::const_iterator col_here = cinfo->ccsCols.begin();
      text_tarray::const_iterator col_end = cinfo->ccsCols.end();
      int count = 0;
      while (col_here != col_end) {
	text_t colname;
	if (*col_here == arg_c) {
	    colname = cinfo->get_collectionmeta("collectionname", args["l"]);
	} else {
	  ColInfoResponse_t *this_cinfo = recpt->get_collectinfo_ptr (collectproto, *col_here, logout);
	  if (this_cinfo == NULL) {++col_here; continue;}
	  colname = this_cinfo->get_collectionmeta("collectionname", args["l"]);
	}
	if (colname.empty()) {
	  colname = *col_here;
	}
	++count;
	collectionoption += "<input type=checkbox name=\"cc\" value=\"" + 
	  *col_here + "\" onClick=\"updatecc(\'" + *col_here + "\');\"> " +
	  colname + "<br>\n";
	++col_here;
      }
      
      if (count > 1)
	disp.setmacro ("collectionoption", "preferences", collectionoption);
    }

    // _htmloptions_
    
    text_tmap::const_iterator it = cinfo->format.find ("DocumentUseHTML");
    if ((it != cinfo->format.end()) && ((*it).second == "true")) {
      disp.setmacro ("htmloptions", "preferences", "_htmloptionson_");


      // _PreferenceDocsFromWeb_

      it = cinfo->format.find ("PreferenceDocsFromWeb");
      if ((it == cinfo->format.end()) || ((*it).second == "true"))
	disp.setmacro ("PreferenceDocsFromWeb", "preferences", "1");
    }

    // _prefschanged_
    if (!args["bp"].empty()) {
      disp.setmacro ("prefschanged", "preferences", "_textprefschanged_");
    }
    
  } else if (arg_p == "about" || arg_p == "help") {
    if (collectproto == NULL) return;

    comerror_t err;
    bool has_search_button = true;
    collectproto->is_searchable(args["c"], has_search_button, err, logout);
    if (err != noError) has_search_button = true;
    
    // _textbrowseoptions_ and _numbrowseoptions_
    
    FilterResponse_t response;
    text_tset metadata;
    metadata.insert ("Title");
    //****************
    metadata.insert ("childtype");
    //****************
    bool getParents = false;
    get_children ("", args["c"], args["l"], metadata, getParents, collectproto, response, logout);

    int numbrowseoptions = response.docInfo.size();
    if (has_search_button) numbrowseoptions += 1;
    disp.setmacro ("numbrowseoptions", "help", numbrowseoptions);

    ResultDocInfo_tarray::iterator here = response.docInfo.begin();
    ResultDocInfo_tarray::iterator end = response.docInfo.end();

    text_t helptext;
    if (has_search_button) {
      helptext = "<ul><li>_textSearchhelp_\n";
    }

    // ********************************      
    int classifiernumber = 0;
    bool collage = false;

    while (here != end) {
      
      ++classifiernumber;
      text_t childtype = (*here).metadata["childtype"].values[0];
      if (childtype == "Collage" && arg_p == "about") {
	// get the classifier number
	disp.setmacro ("classifier", "about", classifiernumber);
	disp.setmacro ("aboutCollage", "about", "_collageapplet_");
	collage = true;
      }
      ++here;
    } 
    if (! collage)
      disp.setmacro ("aboutCollage", "about", "_collageempty_");
	
    // ********************************
     
    here = response.docInfo.begin();

    while (here != end) {
      
      text_t title = (*here).metadata["Title"].values[0];
    
      text_t stext;
      disp.expandstring ("help", "_text" + title + "help_", stext);
      if (stext == ("_text" + title + "help_")) {
	text_t ltext, ttext;
	disp.expandstring("Global", "_label"+title+"_", ltext);
	if (ltext == ("_label"+title+"_")) {
	  ltext = title;
	}
	disp.expandstring("Global", "_text"+title+"_", ttext);
	if (ttext == ("_text"+title+"_")) {
	  ttext = title;
	}
	helptext += "<li>_help:textdefaulthelp_("+ttext+","+ltext+")";
      } else {
	helptext += "<li>_help:text" + title + "help_";
      }

      ++here;
    }
    helptext += "</ul>\n";
    disp.setmacro ("textbrowseoptions", "help", helptext);

    if (arg_p == "help") {
      // do we need to add in the datesearch help??
      text_tmap::iterator check = cinfo->format.find("QueryInterface");
      if(check != cinfo->format.end()){
	if((*check).second=="DateSearch"){
	  text_t current = "_datesearch_";
	  disp.setmacro("optdatesearchhelp","help","_datesearchhelp_");
	  disp.setmacro("optdatesearchhelpcontents","help","_datesearchhelpcontents_");
	}
      }
      
    }
    
    if (arg_p == "about") {

      // _textsubcollections_
      if (args["ccs"] == "1" && (cinfo->ccsCols.size() > 1)) {
	text_t textsubcollections = "_textsubcols1_(" + text_t(cinfo->ccsCols.size()) + ")";
	text_tarray::const_iterator here = cinfo->ccsCols.begin();
	text_tarray::const_iterator end = cinfo->ccsCols.end();
	bool first = true;
	int count = 0;
	while (here != end) {
	  if (*here == arg_c) {
	    if (!first) textsubcollections += "<br>";
	    textsubcollections += "\n" + cinfo->get_collectionmeta("collectionname", args["l"]) + "\n";
	  } else {
	    ColInfoResponse_t *this_cinfo = recpt->get_collectinfo_ptr (collectproto, *here, logout);
	    if (this_cinfo == NULL) {++here; continue;}
	    if (!first) textsubcollections += "<br>";
	    textsubcollections += "\n" + this_cinfo->get_collectionmeta("collectionname", args["l"]) + "\n";
	  }
	  ++count;
	  first = false;
	  ++here;
	}
	textsubcollections += "_textsubcols2_";
	if (count > 1) {
	  disp.setmacro ("textsubcollections", "about", textsubcollections);
	}
      }

      comerror_t err;
      bool issearchable = true;
      collectproto->is_searchable(args["c"], issearchable, err, logout);
      if (err != noError) issearchable = true;
      outconvertclass t;
      if (!issearchable ) {
	disp.setmacro ("aboutqueryform", "about", "");
      }
    }

  } else if (arg_p == "docs") {

    set_documentation_macro (disp);

  } else if (arg_p == "bsummary" && !arg_c.empty()) {

    set_macro_to_file_contents (disp, "importlog", "bsummary",
				filename_cat(collecthome, arg_c, "etc", "import.log"));
    set_macro_to_file_contents (disp, "faillog", "bsummary",
				filename_cat(collecthome, arg_c, "etc", "fail.log"));
    set_macro_to_file_contents (disp, "buildlog", "bsummary",
				filename_cat(collecthome, arg_c, "etc", "build.log"));
  }
}

bool pageaction::do_action (cgiargsclass &args, recptprotolistclass * /*protos*/, 
			    browsermapclass * /*browsers*/, displayclass &disp, 
			    outconvertclass &outconvert, ostream &textout, 
			    ostream &/*logout*/) {

  text_t &arg_p = args["p"];

  textout << outconvert << disp << ("_" + encodeForHTML(arg_p) + ":header_\n")
	  << ("_" + encodeForHTML(arg_p) + ":content_\n")
	  << ("_" + encodeForHTML(arg_p) + ":footer_\n");

  return true;
}

void pageaction::configure (const text_t &key, const text_tarray &cfgline) {
  if ((key == "status") && (cfgline.size() == 1) && 
      (cfgline[0] == "true" || cfgline[0] == "on" || cfgline[0] == "enabled")) {
    status_disabled = false;
  } else if ((key == "collector") && (cfgline.size() == 1) && 
	     (cfgline[0] == "true" || cfgline[0] == "on" || cfgline[0] == "enabled")) {
    collector_disabled = false;
  }
 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;
  } else if ((key == "gliapplet") && (cfgline.size() == 1) && 
	     (cfgline[0] == "true" || cfgline[0] == "on" || cfgline[0] == "enabled")) {
    gliapplet_disabled = false;
  }
  else {
    // call the parent class to deal with the things which
    // are not dealt with here
    action::configure (key, cfgline);
  }
}










