/**********************************************************************
 *
 * depositoraction.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"
#ifdef GSDL_USE_DEPOSITOR_ACTION

// note that the collectoraction 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???
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 1
#endif
// This was added for Solaris, but it makes things worse on Solaris for me...
// #define _XOPEN_SOURCE_EXTENDED 1

#include "depositoraction.h"
#include "OIDtools.h"
#include "fileutil.h"
#include "cfgread.h"
#include "gsdltools.h"
#include "gsdlunicode.h"
#include "gsdltimes.h"
#include "argdb.h"
#include "cgiutils.h"

#include <stdio.h>
//#include <strings.h> // seems to be needed for gcc 2.95, but not particularly happy it
#include <fcntl.h>
#include <time.h>

#if !defined (__WIN32__)
#include <sys/utsname.h>
#include <unistd.h>
#endif

#include <new>
//#include <string>
#include <vector>
#include <stdexcept>
#include <iostream>
//#include <cstdlib>

depositoraction::depositoraction () 
  : wizardaction()
{
  macro_prefix = "di1";  //deposit item
  lastpage = 0; 

  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 = "depositor";
  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 = "select";   
  arg_ainfo.savedarginfo = cgiarginfo::must;
  argsinfo.addarginfo (NULL, arg_ainfo);

  //furthest page that has been visited
  arg_ainfo.shortname = "di1lastpage";
  arg_ainfo.longname = "depositor specific"; 
  arg_ainfo.multiplechar = true;
  arg_ainfo.multiplevalue = false;
  arg_ainfo.defaultstatus = cgiarginfo::weak;
  arg_ainfo.argdefault = "0";   
  arg_ainfo.savedarginfo = cgiarginfo::must;
  argsinfo.addarginfo (NULL, arg_ainfo);
  
  // the fileupload info that cgiwrapper produces - we parse the fileupload_t
  // and set di1userfile, di1userfilesize
  arg_ainfo.shortname = "di1userfileinfo";
  arg_ainfo.longname = "depositor specific"; 
  arg_ainfo.fileupload = true;
  arg_ainfo.multiplevalue = false;
  arg_ainfo.savedarginfo = cgiarginfo::mustnot;  
  argsinfo.addarginfo (NULL, arg_ainfo);

  // essential: reset fileupload to default as we are not setting 
  // it for each arg
  arg_ainfo.fileupload = false;

  //the name of the file to be added
  arg_ainfo.shortname = "di1userfile";
  arg_ainfo.longname = "depositor specific"; 
  arg_ainfo.multiplechar = true;
  arg_ainfo.multiplevalue = false;
  arg_ainfo.defaultstatus = cgiarginfo::weak;
  arg_ainfo.argdefault = g_EmptyText;   
  arg_ainfo.savedarginfo = cgiarginfo::must;
  argsinfo.addarginfo (NULL, arg_ainfo);

  //the file size
  arg_ainfo.shortname = "di1userfilesize";
  arg_ainfo.longname = "depositor specific"; 
  arg_ainfo.multiplechar = true;
  arg_ainfo.multiplevalue = false;
  arg_ainfo.defaultstatus = cgiarginfo::weak;
  arg_ainfo.argdefault = "0";   
  arg_ainfo.savedarginfo = cgiarginfo::must;
  argsinfo.addarginfo (NULL, arg_ainfo);

 //the file timestamp
  arg_ainfo.shortname = "di1timestamp";
  arg_ainfo.longname = "depositor specific"; 
  arg_ainfo.multiplechar = true;
  arg_ainfo.multiplevalue = false;
  arg_ainfo.defaultstatus = cgiarginfo::weak;
  arg_ainfo.argdefault = "0";   
  arg_ainfo.savedarginfo = cgiarginfo::must;
  argsinfo.addarginfo (NULL, arg_ainfo);

  // temporary directory name for this collector
  // session
  arg_ainfo.shortname = "di1tmp";
  arg_ainfo.longname = "depositor specific";
  arg_ainfo.multiplechar = true;
  arg_ainfo.multiplevalue = false;
  arg_ainfo.defaultstatus = cgiarginfo::weak;
  arg_ainfo.argdefault = g_EmptyText;
  arg_ainfo.savedarginfo = cgiarginfo::must;
  argsinfo.addarginfo (NULL, arg_ainfo);

  arg_ainfo.shortname = "di1dirname";
  arg_ainfo.longname = "depositor specific";
  arg_ainfo.multiplechar = true;
  arg_ainfo.multiplevalue = false;
  arg_ainfo.defaultstatus = cgiarginfo::weak;
  arg_ainfo.argdefault = g_EmptyText;
  arg_ainfo.savedarginfo = cgiarginfo::must;
  argsinfo.addarginfo (NULL, arg_ainfo);

  arg_ainfo.shortname = "di1contactemail";
  arg_ainfo.longname = "depositor specific";
  arg_ainfo.multiplechar = true;
  arg_ainfo.multiplevalue = false;
  arg_ainfo.defaultstatus = cgiarginfo::weak;
  arg_ainfo.argdefault = g_EmptyText;
  arg_ainfo.savedarginfo = cgiarginfo::mustnot; // saved on disk
  argsinfo.addarginfo (NULL, arg_ainfo);


  // wizard uses this to see if we are working with an existing collection:
  // set the default to 1
  arg_ainfo.shortname = "di1esrce";
  arg_ainfo.longname = "depositor specific";
  arg_ainfo.multiplechar = false;
  arg_ainfo.multiplevalue = false;
  arg_ainfo.defaultstatus = cgiarginfo::weak;
  arg_ainfo.argdefault = "1";
  arg_ainfo.savedarginfo = cgiarginfo::must;
  argsinfo.addarginfo (NULL, arg_ainfo);

  // collection specific depositing. We are bypassing the select page. Need to do the clearing that happens at select. And depositor link at top right should be back to local deposit 
  arg_ainfo.shortname = "di1local";
  arg_ainfo.longname = "depositor specific";
  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);
 
  // shall we cache the metadata values? Made this an arg so we can turn it off if wanted
  arg_ainfo.shortname = "di1cache";
  arg_ainfo.longname = "depositor specific";
  arg_ainfo.multiplechar = false;
  arg_ainfo.multiplevalue = false;
  arg_ainfo.defaultstatus = cgiarginfo::weak;
  arg_ainfo.argdefault = "1";
  arg_ainfo.savedarginfo = cgiarginfo::must;
  argsinfo.addarginfo (NULL, arg_ainfo);

}

depositoraction::~depositoraction () {
}


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

  wizardaction::check_cgiargs(argsinfo,args,protos,logout);

  text_t &current_page = args["p"];

  // note that the "bildstatus" and "bildframe1" pages don't actually do anything
  // functional so we don't need to worry about authenticating them (it's the 
  // underlying "bild" page that does the building (and creates the frameset))
  // This helps us overcome a bit of a problem we have with multiple pages trying
  // to read from the key.gdb database at the same time.

  //right now, anyone can do anything until it's time to build

  // Used to check current page was "select", now changed to "step1".
  // (i.e. one page later).  This is needed so users that belong to
  // specific collection-edit groups (e.g. demo-collection-editor) are able
  // to log in successfully.
  //   

  if (current_page == "step1") { 
    //authenticate the user if authentication is available
    args["uan"] = 1;
    args["ug"] = "all-collections-editor," + args["c"] + "-collection-editor";
  }


  //Check to see if a file was specified
  //if so, upload it and set the di1userfile, di1userfilesize, and 
  //di1timestamp args.
  //every time a new file is specified, a new timestamped folder is 
  //created.  

  // This doesn't create a problem but is inefficient (wasted space)
  // Consider recoding at some point in the future.

  fileupload_t *fileupload = args.getargfile("di1userfileinfo");

  if (fileupload != NULL) {

    if (!(*fileupload).tmp_name.empty() && file_exists((*fileupload).tmp_name)) {
      // create the timestamp
      time_t timestamp = time(NULL);
      text_t timestamp_str(timestamp); 

      args["di1timestamp"] = timestamp_str;

      // set filename and size from the fileupload struct
      args["di1userfilesize"] = (*fileupload).size;
      args["di1userfile"] = (*fileupload).name;
      // copy the file into its temporary location
      text_t tmpdir = filename_cat(gsdlhome,"tmp",args["di1tmp"],timestamp_str);
      bool tflag = mk_dir(tmpdir);
      text_t tmpfile = filename_cat(tmpdir,(*fileupload).name);
      if (!file_copy((*fileupload).tmp_name, tmpfile)) {
	cerr << "Depositor error: cannot save uploaded fileto  "<<tmpfile<<endl;
      } else {
	cerr << "Depositor: saved uploaded file to "<<tmpfile<<endl;
      }
    } 
  }
  
  if (current_page == "select" || (current_page == "step1" && args["di1local"] == "1")) {  
 
    //make sure the last page arg is re-set to zero 
    //since a new collection is being chosen
    args["di1lastpage"] = "0";

    // assign (and create) a temporary directory This will create a new
    // tbuild directory every time the user goes back to select a new
    // collection.  It causes no problems except wasted space.  Should be
    // addressed in the future
    if (assign_tmpname (args, logout)==false) {
      // there was an error creating the tmp dir
      message="tmpfail";
      return true; // true because we could still parse the arguments
    }

    // 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 collecton laying about so we'll make it an asynchronous
    // system call)
    gsdl_system ("perl -S cleantmp.pl", false, logout);

  }

  if (current_page == "bildstatus" || current_page == "bildcancel") {
    // if .final file exists then build has finished
    text_t fbld = filename_cat (gsdlhome, "tmp", args[macro_prefix + "tmp"], args[macro_prefix + "dirname"] + ".bld.final");
    if (file_exists (fbld)) {
      char *fbldc = fbld.getcstr();
      ifstream fbld_in (fbldc);
      if (fbld_in) {
	failcode = fbld_in.get();
	fbld_in.close();
	if (failcode == '0') {
	  // success - we need to create and configure a collection server for the
	  // newly built collection (for fastcgi and local library where
	  // initialization isn't going to be redone when the user clicks the
	  // "view your new collection" button
	  create_colserver (args[macro_prefix + "dirname"], logout);
	  current_page = "bilddone";
	}
	else current_page = "bildfail";
      } else {
	// assume build failed (we shouldn't get here though ... right?)
	current_page = "bildfail";
      }
      delete []fbldc;
    }
  }

  //is it a step page?
  text_t::const_iterator here = current_page.begin();
  text_t::const_iterator end = current_page.end();
  text_t stepstring = substr(here,here+4);

  //if so, increment the step count 
  //this should not be going up more than one at a time. 
  if(stepstring == "step") {
    text_t currpage_textt = substr(here+4,here+5);
    int currpage = currpage_textt.getint();

    text_t lastpage_textt = args["di1lastpage"]; 
    int lastpage = lastpage_textt.getint(); 
    if (currpage > lastpage) {
      lastpage++; 
      text_t lastpage_textt(lastpage); 
      args["di1lastpage"] = lastpage_textt;      
    }

    // create cached metadata values
    if (args["di1cache"] == "1") {
    text_t cached_metadata_values = "";
    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();
	  int args_name_len = args_name.size();

	  if(args_name_len >= prefix_len+3) { // Only now can we substring args_name by prefix_len+3
		  text_t args_prefix;
		  if(args_name_len == prefix_len+3) {
			  args_prefix = args_name;
		  } else { // >, so substring
			  args_prefix = substr(args_name.begin(),args_name.begin()+prefix_len+3);
		  }

		  if (args_prefix == (macro_prefix+"md.")) {     
			text_t args_val = args[args_name];
			cerr << "caching md arg "<<args_val<<endl;
			decode_cgi_arg(args_val);
			text_t args_suffix = substr(args_name.begin()+prefix_len+3,args_name.end()); 

			text_tarray mdvalues;
			splitchar (args_val.begin(), args_val.end(), ',', mdvalues);
			int numvalues = mdvalues.size();

			for (int i = 0; i < numvalues; ++i) {
			  if (!mdvalues[i].empty()) {
			    
			    //decode_cgi_arg(mdvalues[i]);
				
				if (cached_metadata_values == "") {
				  cached_metadata_values = "var CachedMDValues = new Array(\\{";
				} else {
				  cached_metadata_values += ",";
				}

				cached_metadata_values += "\"" + args_name + "\":\"" + encodeForJavascript(args_val) + "\"";
			  }
			}	
		  }
	  }
      ++args_here;
    }

    if (cached_metadata_values != "") {
      cached_metadata_values += "\\});";
      args["cachedMDValues"] = cached_metadata_values;
    }
    }
  }
  return true;
}  


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

  // define_internal_macros sets some/all of the following macros (depending
  // on cgiargs):
  //
  // _pagescriptextra_
  // _header_
  // _depositorbar_
  // _textfailmsg_
  // _di1userfile_
  // _di1userfilesize_

  text_t &depositor_page = args["p"];
  
  // set _pagescriptextra_ macro to _cpagescriptextra_
  disp.setmacro ("pagescriptextra", "depositor", "_" + depositor_page + "scriptextra_");

  if (depositor_page == "bildstatus" || depositor_page == "bilddone" || 
      depositor_page == "bildfail" || depositor_page == "bildframe1" || 
      depositor_page == "select") {
    disp.setmacro ("header", "depositor", "_" + depositor_page + "header_");
  }

  if (depositor_page == "bildstatus") {
    set_statusline (disp, args, logout);
  }

  if (depositor_page == "select") {
    set_fullnamemenu (disp, args, protos, logout);
  }

  //how many pages in collection?
  //we need a _depositorbar_ for each

  text_t numsteps_str;
  disp.expandstring("depositor", "_numsteps_", numsteps_str);
  int numsteps = numsteps_str.getint();
   
  //is the page a step page? 

  text_t::const_iterator here = depositor_page.begin();
  text_t::const_iterator end = depositor_page.end();
  text_t stepstring = substr(here,here+4);

  if((stepstring) == "step" || (depositor_page == "depositonly") ) {
    disp.setmacro("di1userfile","depositor",args["di1userfile"]);
    disp.setmacro("di1userfilesize","depositor",args["di1userfilesize"]);
  }

  //set up the depositor bar
  text_t depositorbar = "<table class=wizardbar border=0 cellspacing=4 cellpadding=0><tr>\n";

  if(stepstring == "step") {   
    // check configured metadata elements
    if (args["metadataconf"] == "var DepositorMDFields = new Array();" || args["metadataconf"] == "") {

      text_t cfgfile_name = filename_cat (collecthome, args[macro_prefix + "dirname"], "etc", "collect.cfg");
      text_t key;
      text_t params;
      text_tarray cfgline;
      char *cstr = cfgfile_name.getcstr();
      ifstream confin (cstr);
      delete []cstr;

      text_t metadata_str;
      text_t default_metadata_str;
      if (confin) {
	while (read_cfg_line(confin, cfgline) >= 0) {
	  if (cfgline.size () >= 3) {
	    key = cfgline[0];
	    if (key == "collectionmeta") {
	      if (cfgline[1] == "depositormetadata") {
		if (cfgline.size() == 3) {
		  // no lang arg
		  default_metadata_str = cfgline[2];
		} else {
		  params = cfgline[2];
		  text_t::const_iterator first=params.begin()+1;
		  text_t::const_iterator last=params.end()-1;
		  params=substr(first, last);
		  // get the lang out of params
		  paramhashtype params_hash;
		  splitparams(params, params_hash);
	  
		  text_t lang = params_hash["l"];
		  if (lang == args["l"]) {
		    metadata_str = cfgline[3];
		    break;
		  }
		  if (default_metadata_str.empty()) {
		    default_metadata_str = cfgline[3];
		  }
		}
	      }
	    }
	  }
	}
      }
      confin.close ();
      // use default value if there was one
     if (metadata_str.empty()) {
	metadata_str = default_metadata_str;
      }
     // if there still isn't one set, use this default setting
      if (metadata_str == "") {
	metadata_str = "{\"name\":\"dc.Title\",\"label\":\"Title\",\"tooltip\":\"dc.Title: A name given to the resource.\",\"type\":\"text\"}, {\"name\":\"dc.Creator\",\"label\":\"Creator\",\"tooltip\":\"dc.Creator: An entity primarily responsible for making the content of the resource.\",\"type\":\"text\"}, {\"name\":\"dc.Description\",\"label\":\"Description\",\"tooltip\":\"dc.Description: An account of the content of the resource.\",\"type\":\"textarea\"}";
      }
      args["metadataconf"] = "var DepositorMDFields = new Array("+metadata_str+");";
 
    }

    here = depositor_page.begin();
    text_t stepnums = substr(here+4,here+5); 
    int stepnum = stepnums.getint();

    text_t lastpage_textt = args["di1lastpage"];
    int lastpage = lastpage_textt.getint(); 
    
    // again, begin with the select bar...
    //the first button - selecting a collection
    for(int i = 1; i <= numsteps; i++) {
      text_t numstr(i); 
      if(i <= lastpage && i == stepnum) {
	depositorbar += get_button (args,depositor_page, "yellow", "step"+numstr, false);
      } else if (i <= lastpage) {
	depositorbar += get_button (args,depositor_page, "yellow", "step"+numstr, true); 
      } else if((i == lastpage+1)){
	depositorbar += get_button (args,depositor_page, "green", "step"+numstr, true);       
      } else { 
	depositorbar += get_button (args,depositor_page, "grey", "step"+numstr, false);       
      }
      depositorbar += "<td>_icongreyarrow_</td>\n";

    }    

    //the build and preview pages are always last
    if(lastpage == numsteps) {
      depositorbar += get_button (args,depositor_page, "green", "laststep", true);
    } else {
      depositorbar += get_button (args,depositor_page, "grey", "laststep", false);
    }

    text_t laststep_textt;
    disp.expandstring("depositor", "_laststep_", laststep_textt);
    if(laststep_textt == "bild") {
      depositorbar += "<td>_icongreyarrow_</td>\n";
      depositorbar += get_button (args,depositor_page, "grey", "view", false);
    }
    depositorbar += "</tr><tr>"; 

    for(int j = 1; j <= 2*(stepnum-1); j++) {
      depositorbar += "<td></td>";
    }
    depositorbar += "<td align=center>_icongreyuparrow_</td>\n";    

    depositorbar += "</tr></table>\n";

    // set the javascript so that the metadata form can read the existing values
    if (args["cachedMDValues"] != "") {
      disp.setmacro("cachedmetadatavalues", "depositor", args["cachedMDValues"]);
    }
    if (args["metadataconf"] != "") {
      disp.setmacro("metadataconf", "depositor", args["metadataconf"]);
    }    
  }
  
  if ((depositor_page == "bildcancel") || (depositor_page == "bildfail")) {
  
    for(int i = 1; i <= numsteps; i++) {

      text_t numstr(i); 
      depositorbar += get_button (args,depositor_page, "yellow", "step"+numstr, true);       
      depositorbar += "<td>_icongreyarrow_</td>\n";

    }

    //the build and preview pages are always last
    depositorbar += get_button (args,depositor_page, "green", "laststep", true);
    depositorbar += "<td>_icongreyarrow_</td>\n";
    depositorbar += get_button (args,depositor_page, "grey", "view", false); 

    depositorbar += "</tr><tr>"; 

    for(int j = 1; j <= 2*numsteps; j++) {
      depositorbar += "<td></td>";
    }
    depositorbar += "<td align=center>_icongreyuparrow_</td>\n";    

    depositorbar += "</tr></table>\n";

  }

  if(depositor_page == "bilddone"){
    
    for(int i = 1; i <= numsteps; i++) {

      text_t numstr(i); 
      depositorbar += get_button (args, depositor_page, "grey", "step"+numstr, false);       
      depositorbar += "<td>_icongreyarrow_</td>\n";

    }

    //the build and preview pages are always last
    depositorbar += get_button (args,depositor_page, "yellow", "laststep", false);
    depositorbar += "<td>_icongreyarrow_</td>\n";
    depositorbar += get_button (args,depositor_page, "green", "view", true);

    depositorbar += "</tr><tr>"; 

    for(int j = 1; j <= 2*numsteps; j++) {
      depositorbar += "<td></td>";
    }
    depositorbar += "<td align=center>_icongreyuparrow_</td>\n";    

    depositorbar += "</tr></table>\n";
  }
  disp.setmacro ("depositorbar", "depositor", depositorbar);

  if (depositor_page == "bildfail") {
 
    text_t textfailmsg = "_textfailmsg";
    textfailmsg.push_back(failcode);
    textfailmsg.push_back('_');
    disp.setmacro("textfailmsg", "depositor", textfailmsg);

    text_t bldlog = filename_cat(gsdlhome, "tmp", args["di1tmp"], args["di1dirname"] + ".bld");
    //text_t rawlog = file_tail (bldlog, 6, 0);
    text_t rawlog;
    read_file(bldlog, rawlog);
    // we'll shove in some <br> tags where \n's occur
    text_t faillog;
    text_t::const_iterator here = rawlog.begin();
    text_t::const_iterator end = rawlog.end();
    while (here != end) {
      if (*here == '\n') faillog += "<br>";
      faillog.push_back (*here);
      ++here;
    }
    disp.setmacro ("faillog", "depositor", dm_safe(faillog));
  }
}


//basic framework
bool depositoraction::do_action (cgiargsclass &args, recptprotolistclass * /*protos*/, 
				 browsermapclass * /*browsers*/, displayclass &disp, 
				 outconvertclass &outconvert, ostream &textout, 
				 ostream &logout) {
  // make sure the depositor is enabled
  if (disabled) {
    textout << outconvert 
	    << "<html>\n"
	    << "<head>\n"
	    << "<title>Depositor disabled</title>\n"
	    << "</head>\n"
	    << "<body bgcolor=\"#ffffff\" text=\"#000000\" link=\"#006666\" "
	    << "alink=\"#cc9900\" vlink=\"#666633\">\n"
	    << "<h2>Facility disabled</h2>\n" 
	    << "Sorry, the Depositor end-user collecation update facility is currently disabled\n"
	    << "\n</body>\n"
	    << "</html>\n";
    return true;
  }

  text_t &depositor_page = args["p"];
  text_t &collection = args["di1dirname"];

  // make sure we have perl (we won't bother with this check for the 
  // building status pages to avoid slowing things down unneccessarily)
  if (depositor_page != "bildstatus" && depositor_page != "bildframe1" && !perl_ok(logout)) {
    textout << outconvert 
	    << "<html>\n"
	    << "<head>\n"
	    << "<title>Perl not found</title>\n"
	    << "</head>\n"
	    << "<body bgcolor=\"#ffffff\" text=\"#000000\" link=\"#006666\" "
	    << "alink=\"#cc9900\" vlink=\"#666633\">\n"
	    << "<h2>Perl not found</h2>\n" 
	    << "Greenstone could not detect perl on this system. It is therefore not\n"
	    << "possible to build a Greenstone collection, either from the Collector or the \n"
	    << "command-line tools, or to use the Collector for any other task.\n"
	    << "<p>Please refer to the Greenstone Installer's Guide for details on\n"
	    << "installing perl on your system.\n"
	    << "\n</body>\n"
	    << "</html>\n";
    return true;

  }

  text_t::const_iterator here = depositor_page.begin();
  text_t::const_iterator end = depositor_page.end();
  text_t stepstring = substr(here,here+4);

  if ((depositor_page == "select") || (stepstring == "step")) {
          textout << outconvert << disp << ("_depositor:header_\n")
		  << ("_depositor:" + encodeForHTML(depositor_page) + "content_\n")
	      << ("_depositor:footer_\n");
	  
  }

  if ((depositor_page == "bild") || (depositor_page == "depositonly")) {

    text_t filename_textt = args["di1userfile"];
    text_t timestamp_str = args["di1timestamp"];
    //check to make sure a file was uploaded
    //if more than one upload occurred, the last one is taken
    if(filename_textt == "") {
      textout << outconvert << disp << "<p> no file available</p>\n"; 
    } else {
    
      text_t col_dirname = filename_cat(collecthome,args[macro_prefix+"dirname"]);
      text_t import_dirname = filename_cat(col_dirname,"import");
      if(!directory_exists(import_dirname)) {
	bool flag = mk_dir(import_dirname);
	if(!flag) {
	  cerr << "Error: unable to make directory " << import_dirname << endl;
	  return true; 
	}
      } 

      text_t dirname = filename_cat(import_dirname,timestamp_str);
      bool flag = mk_dir(dirname);
      if(!flag) {
	cerr << "Error: unable to make timestamp directory " << dirname << endl;
	return true; 
      }

      text_t filename_textt = args["di1userfile"]; 
      text_t tmpdir = filename_cat(gsdlhome,"tmp",args["di1tmp"],timestamp_str);
      text_t tmpfile = filename_cat(tmpdir,filename_textt);
      text_t filename = filename_cat(dirname, filename_textt);  
      if(!file_copy(tmpfile, filename)) {
	cerr << "Unable to copy " << tmpfile << " to " << filename << endl; 
      }
      
      //write the metadata file
      write_metadata_file(args, filename_textt, timestamp_str); 

      if(depositor_page == "bild"){

	//create a manifest file 
	write_manifest_file(args, filename_textt, timestamp_str);
	
	// do the work (download, import, build) 
	gsdl_build (args, logout);

	if (message.empty()) {
	  // bild page is a frameset so we don't want headers and stuff
	  textout << outconvert << disp << ("_depositor:bildcontent_\n");
	}
      }
    }
  }

  if (message.empty()) {

    if (depositor_page != "bild" && stepstring != "step" && depositor_page != "select") {
      // output page ("bild" page was already output above)
      textout << outconvert << disp << ("_depositor:header_\n")
	      << ("_depositor:" + encodeForHTML(depositor_page) + "content_\n")
	      << ("_depositor:footer_\n");
    }
  } else {
    // message was set somewhere (probably an error), output message page
    textout << outconvert << disp << ("_depositor:header_\n")
	    << ("_depositor:" + message + "content_\n")
	    << ("_depositor:footer_\n");
    message.clear();
  }
 
  return true;

}


//This function creates a metadata.xml file
void depositoraction::write_metadata_file(cgiargsclass &args, text_t filename_str, text_t& timestamp_str)
{

    //build metadata file
    //the front
    text_t metadata_file = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
    metadata_file += "<!DOCTYPE DirectoryMetadata SYSTEM \"http://greenstone.org/dtd/DirectoryMetadata/1.0/DirectoryMetadata.dtd\">\n"; 
    metadata_file += "<DirectoryMetadata>\n";
    metadata_file += "    <FileSet>\n";
    metadata_file += "        <FileName>";

    // Generate 'regular expression' save version of filename
    // for now that means escaping any '.' characters
    // consider generalising as function in gsdltools.h/cpp?

    text_t filename_re;
    text_t::const_iterator here = filename_str.begin();
    text_t::const_iterator end = filename_str.end();
    while (here != end) {
      if (*here == '.') {
	filename_re.push_back('\\');
      }

      filename_re.push_back(*here);
      ++here;
    }

    metadata_file += filename_re;

    metadata_file += "</FileName>\n"; 
    metadata_file += "        <Description>\n";

    
    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();
	  int args_name_len = args_name.size();

	  if(args_name_len >= prefix_len+3) { // Only now can we substring args_name by prefix_len+3
	      text_t args_prefix;
		  if(args_name_len == prefix_len+3) {
			  args_prefix = args_name;
		  } else { // >, so substring
			  args_prefix = substr(args_name.begin(),args_name.begin()+prefix_len+3);
		  }

		  if (args_prefix == (macro_prefix+"md.")) {     
			text_t args_val = args[args_name];
			cerr << "args val = "<<args_val<<endl;
			decode_cgi_arg(args_val);
			cerr << "decoded = " << args_val<<endl;
			text_t args_suffix = substr(args_name.begin()+prefix_len+3,args_name.end()); 

			text_tarray mdvalues;
			splitchar (args_val.begin(), args_val.end(), ',', mdvalues);
			int numvalues = mdvalues.size();
			cerr << "numvals = "<<numvalues<<endl;
			for (int i = 0; i < numvalues; ++i) {
			  if (!mdvalues[i].empty()) {
			    //decode_cgi_arg(mdvalues[i]);
				metadata_file += "            <Metadata mode=\"accumulate\" name=\"";	    
				metadata_file += args_suffix;
				metadata_file += "\">";
				// originally literal commas entered for metadata like dc.Subject
				// come in (extra) URL encoded, as %2C at this point in the code
				// Decode any commas now before writing them into metadata.xml
				metadata_file += xml_safe(decode_commas(mdvalues[i]));
				metadata_file += "</Metadata>\n";

			  }
			}
		  }
	  }
      ++args_here;
    }
    
    //the end of the file
    metadata_file += "        </Description>\n"; 
    metadata_file += "    </FileSet>\n"; 
    metadata_file += "</DirectoryMetadata>\n"; 

    //create metadata.xml file
    text_t metadata_path = filename_cat(collecthome, args[macro_prefix+"dirname"], "import", timestamp_str, "metadata.xml");
    text_t my_path = filename_cat(gsdlhome,"tmp", "metadata.xml");

    ofstream metadata(metadata_path.getcstr());
    ofstream my_tmp(my_path.getcstr()); 

    if(!metadata.is_open()) {
      cerr << "Cannot open metadata.xml!" << endl; 
    } else {
      
      //write metadata.xml
      // need to convert to utf8 before writing it out.
      text_t utf8_meta = to_utf8(metadata_file);
      metadata.write(utf8_meta.getcstr(), utf8_meta.size()); 
      my_tmp.write(utf8_meta.getcstr(), utf8_meta.size()); 
    }
}

//This function creates a manifest.xml file
void depositoraction::write_manifest_file(cgiargsclass &args, text_t filename, 
					  text_t& timestamp_str)
{

    //build manifest file

    //the front
    text_t manifest_file = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
    manifest_file += "<Manifest>\n";
    manifest_file += "    <Index>\n";
    manifest_file += "        <Filename>\n";
    manifest_file += "          " + timestamp_str + "\n";
    manifest_file += "        </Filename>\n"; 
    
    //the end of the file
    manifest_file += "    </Index>\n"; 
    manifest_file += "</Manifest>\n"; 

    //create manifest.xml file
    text_t manifest_path = filename_cat(collecthome, args[macro_prefix+"dirname"], "manifest.xml");

    char* manifest_cstr = manifest_path.getcstr();

    ofstream manifest(manifest_cstr);

    if(!manifest.is_open()) {
      cerr << "Cannot open" << manifest_cstr << endl; 
    } else {

      //write manifest.xml
      char *manifest_file_cstr = manifest_file.getcstr();
      manifest.write(manifest_file_cstr, manifest_file.size()); 
      delete [] manifest_file_cstr;
    }

    delete [] manifest_cstr;
}



text_t depositoraction::get_button(cgiargsclass &args, const text_t &thispage, 
				   const text_t &color, 
				   const text_t &type, bool enabled) 
{

  text_t::const_iterator here = type.begin();
  text_t::const_iterator end = type.end();
  text_t stepstring = substr(here,here+4);
  if ((color != "green" && color != "grey" && color != "yellow") ||
      (type != "select" && type != "laststep" && stepstring != "step" && type != "view"))
    return g_EmptyText;

  text_t href = "_http"+type+"_";
  text_t target = "";

  here = thispage.begin();
  stepstring = substr(here,here+4);  
  if (thispage == "bildcancel" || thispage == "bildfail" || thispage == "select"|| stepstring == "step") {
    // call the check submit macro instead of linking directly to the page

    if(type == "laststep") {
      href="\"javascript:check_submit('_"+type+"_');\"";
    } else {
      href="\"javascript:check_submit('"+type+"');\"";
    }

  } else if (type == "view") {
   //target = " target=_top";
    target = " target=_blank";
  }

  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>";
  }
}


#endif //GSDL_USE_DEPOSITOR_ACTION
