root/main/trunk/greenstone2/runtime-src/src/recpt/depositoraction.cpp @ 30466

Revision 30466, 31.4 KB (checked in by kjdon, 4 years ago)

metadata values might have special chars in them, so we must xml_safe the value before adding to metadata.xml

  • Property svn:keywords set to Author Date Id Revision
Line 
1/**********************************************************************
2 *
3 * depositoraction.cpp --
4 * Copyright (C) 2000  The New Zealand Digital Library Project
5 *
6 * A component of the Greenstone digital library software
7 * from the New Zealand Digital Library Project at the
8 * University of Waikato, New Zealand.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 *********************************************************************/
25
26#include "gsdl_modules_cfg.h"
27#ifdef GSDL_USE_DEPOSITOR_ACTION
28
29// note that the collectoraction relies on having direct access to a
30// collections configuration file. this breaks the separation between
31// receptionist and collection server and so is not suitable (at least
32// in its current form) for use when collection servers are separate
33// from the receptionist (e.g. when using the CORBA protocol).
34
35// following line required to get fstream.filedesc() on darwin (Mac OS X)
36#define _STREAM_COMPAT  1
37// required for utsname on solaris???
38#ifndef _XOPEN_SOURCE
39#define _XOPEN_SOURCE 1
40#endif
41// This was added for Solaris, but it makes things worse on Solaris for me...
42// #define _XOPEN_SOURCE_EXTENDED 1
43
44#include "depositoraction.h"
45#include "OIDtools.h"
46#include "fileutil.h"
47#include "cfgread.h"
48#include "gsdltools.h"
49#include "gsdlunicode.h"
50#include "gsdltimes.h"
51#include "argdb.h"
52#include "cgiutils.h"
53
54#include <stdio.h>
55//#include <strings.h> // seems to be needed for gcc 2.95, but not particularly happy it
56#include <fcntl.h>
57#include <time.h>
58
59#if !defined (__WIN32__)
60#include <sys/utsname.h>
61#include <unistd.h>
62#endif
63
64#include <new>
65//#include <string>
66#include <vector>
67#include <stdexcept>
68#include <iostream>
69//#include <cstdlib>
70
71depositoraction::depositoraction ()
72  : wizardaction()
73{
74  macro_prefix = "di1";  //deposit item
75  lastpage = 0;
76
77  cgiarginfo arg_ainfo;
78  arg_ainfo.shortname = "a";
79  arg_ainfo.longname = "action";
80  arg_ainfo.multiplechar = true;
81  arg_ainfo.multiplevalue = false;
82  arg_ainfo.defaultstatus = cgiarginfo::weak;
83  arg_ainfo.argdefault = "depositor";
84  arg_ainfo.savedarginfo = cgiarginfo::must;
85  argsinfo.addarginfo (NULL, arg_ainfo);
86
87  arg_ainfo.shortname = "p";
88  arg_ainfo.longname = "page";
89  arg_ainfo.multiplechar = true;
90  arg_ainfo.multiplevalue = false;
91  arg_ainfo.defaultstatus = cgiarginfo::weak;
92  arg_ainfo.argdefault = "select";   
93  arg_ainfo.savedarginfo = cgiarginfo::must;
94  argsinfo.addarginfo (NULL, arg_ainfo);
95
96  //furthest page that has been visited
97  arg_ainfo.shortname = "di1lastpage";
98  arg_ainfo.longname = "depositor specific";
99  arg_ainfo.multiplechar = true;
100  arg_ainfo.multiplevalue = false;
101  arg_ainfo.defaultstatus = cgiarginfo::weak;
102  arg_ainfo.argdefault = "0";   
103  arg_ainfo.savedarginfo = cgiarginfo::must;
104  argsinfo.addarginfo (NULL, arg_ainfo);
105 
106  // the fileupload info that cgiwrapper produces - we parse the fileupload_t
107  // and set di1userfile, di1userfilesize
108  arg_ainfo.shortname = "di1userfileinfo";
109  arg_ainfo.longname = "depositor specific";
110  arg_ainfo.fileupload = true;
111  arg_ainfo.multiplevalue = false;
112  arg_ainfo.savedarginfo = cgiarginfo::mustnot; 
113  argsinfo.addarginfo (NULL, arg_ainfo);
114
115  // essential: reset fileupload to default as we are not setting
116  // it for each arg
117  arg_ainfo.fileupload = false;
118
119  //the name of the file to be added
120  arg_ainfo.shortname = "di1userfile";
121  arg_ainfo.longname = "depositor specific";
122  arg_ainfo.multiplechar = true;
123  arg_ainfo.multiplevalue = false;
124  arg_ainfo.defaultstatus = cgiarginfo::weak;
125  arg_ainfo.argdefault = g_EmptyText;   
126  arg_ainfo.savedarginfo = cgiarginfo::must;
127  argsinfo.addarginfo (NULL, arg_ainfo);
128
129  //the file size
130  arg_ainfo.shortname = "di1userfilesize";
131  arg_ainfo.longname = "depositor specific";
132  arg_ainfo.multiplechar = true;
133  arg_ainfo.multiplevalue = false;
134  arg_ainfo.defaultstatus = cgiarginfo::weak;
135  arg_ainfo.argdefault = "0";   
136  arg_ainfo.savedarginfo = cgiarginfo::must;
137  argsinfo.addarginfo (NULL, arg_ainfo);
138
139 //the file timestamp
140  arg_ainfo.shortname = "di1timestamp";
141  arg_ainfo.longname = "depositor specific";
142  arg_ainfo.multiplechar = true;
143  arg_ainfo.multiplevalue = false;
144  arg_ainfo.defaultstatus = cgiarginfo::weak;
145  arg_ainfo.argdefault = "0";   
146  arg_ainfo.savedarginfo = cgiarginfo::must;
147  argsinfo.addarginfo (NULL, arg_ainfo);
148
149  // temporary directory name for this collector
150  // session
151  arg_ainfo.shortname = "di1tmp";
152  arg_ainfo.longname = "depositor specific";
153  arg_ainfo.multiplechar = true;
154  arg_ainfo.multiplevalue = false;
155  arg_ainfo.defaultstatus = cgiarginfo::weak;
156  arg_ainfo.argdefault = g_EmptyText;
157  arg_ainfo.savedarginfo = cgiarginfo::must;
158  argsinfo.addarginfo (NULL, arg_ainfo);
159
160  arg_ainfo.shortname = "di1dirname";
161  arg_ainfo.longname = "depositor specific";
162  arg_ainfo.multiplechar = true;
163  arg_ainfo.multiplevalue = false;
164  arg_ainfo.defaultstatus = cgiarginfo::weak;
165  arg_ainfo.argdefault = g_EmptyText;
166  arg_ainfo.savedarginfo = cgiarginfo::must;
167  argsinfo.addarginfo (NULL, arg_ainfo);
168
169  arg_ainfo.shortname = "di1contactemail";
170  arg_ainfo.longname = "depositor specific";
171  arg_ainfo.multiplechar = true;
172  arg_ainfo.multiplevalue = false;
173  arg_ainfo.defaultstatus = cgiarginfo::weak;
174  arg_ainfo.argdefault = g_EmptyText;
175  arg_ainfo.savedarginfo = cgiarginfo::mustnot; // saved on disk
176  argsinfo.addarginfo (NULL, arg_ainfo);
177
178
179  // wizard uses this to see if we are working with an existing collection:
180  // set the default to 1
181  arg_ainfo.shortname = "di1esrce";
182  arg_ainfo.longname = "depositor specific";
183  arg_ainfo.multiplechar = false;
184  arg_ainfo.multiplevalue = false;
185  arg_ainfo.defaultstatus = cgiarginfo::weak;
186  arg_ainfo.argdefault = "1";
187  arg_ainfo.savedarginfo = cgiarginfo::must;
188  argsinfo.addarginfo (NULL, arg_ainfo);
189
190  // 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
191  arg_ainfo.shortname = "di1local";
192  arg_ainfo.longname = "depositor specific";
193  arg_ainfo.multiplechar = false;
194  arg_ainfo.multiplevalue = false;
195  arg_ainfo.defaultstatus = cgiarginfo::weak;
196  arg_ainfo.argdefault = "0";
197  arg_ainfo.savedarginfo = cgiarginfo::must;
198  argsinfo.addarginfo (NULL, arg_ainfo);
199 
200  // shall we cache the metadata values? Made this an arg so we can turn it off if wanted
201  arg_ainfo.shortname = "di1cache";
202  arg_ainfo.longname = "depositor specific";
203  arg_ainfo.multiplechar = false;
204  arg_ainfo.multiplevalue = false;
205  arg_ainfo.defaultstatus = cgiarginfo::weak;
206  arg_ainfo.argdefault = "1";
207  arg_ainfo.savedarginfo = cgiarginfo::must;
208  argsinfo.addarginfo (NULL, arg_ainfo);
209
210}
211
212depositoraction::~depositoraction () {
213}
214
215
216bool depositoraction::check_cgiargs (cgiargsinfoclass &argsinfo, cgiargsclass &args, recptprotolistclass * protos, ostream &logout) {
217
218  wizardaction::check_cgiargs(argsinfo,args,protos,logout);
219
220  text_t &current_page = args["p"];
221
222  // note that the "bildstatus" and "bildframe1" pages don't actually do anything
223  // functional so we don't need to worry about authenticating them (it's the
224  // underlying "bild" page that does the building (and creates the frameset))
225  // This helps us overcome a bit of a problem we have with multiple pages trying
226  // to read from the key.gdb database at the same time.
227
228  //right now, anyone can do anything until it's time to build
229
230  // Used to check current page was "select", now changed to "step1".
231  // (i.e. one page later).  This is needed so users that belong to
232  // specific collection-edit groups (e.g. demo-collection-editor) are able
233  // to log in successfully.
234  //   
235
236  if (current_page == "step1") {
237    //authenticate the user if authentication is available
238    args["uan"] = 1;
239    args["ug"] = "all-collections-editor," + args["c"] + "-collection-editor";
240  }
241
242
243  //Check to see if a file was specified
244  //if so, upload it and set the di1userfile, di1userfilesize, and
245  //di1timestamp args.
246  //every time a new file is specified, a new timestamped folder is
247  //created. 
248
249  // This doesn't create a problem but is inefficient (wasted space)
250  // Consider recoding at some point in the future.
251
252  fileupload_t *fileupload = args.getargfile("di1userfileinfo");
253
254  if (fileupload != NULL) {
255
256    if (!(*fileupload).tmp_name.empty() && file_exists((*fileupload).tmp_name)) {
257      // create the timestamp
258      time_t timestamp = time(NULL);
259      text_t timestamp_str(timestamp);
260
261      args["di1timestamp"] = timestamp_str;
262
263      // set filename and size from the fileupload struct
264      args["di1userfilesize"] = (*fileupload).size;
265      args["di1userfile"] = (*fileupload).name;
266      // copy the file into its temporary location
267      text_t tmpdir = filename_cat(gsdlhome,"tmp",args["di1tmp"],timestamp_str);
268      bool tflag = mk_dir(tmpdir);
269      text_t tmpfile = filename_cat(tmpdir,(*fileupload).name);
270      if (!file_copy((*fileupload).tmp_name, tmpfile)) {
271    cerr << "Depositor error: cannot save uploaded fileto  "<<tmpfile<<endl;
272      } else {
273    cerr << "Depositor: saved uploaded file to "<<tmpfile<<endl;
274      }
275    }
276  }
277 
278  if (current_page == "select" || (current_page == "step1" && args["di1local"] == "1")) { 
279 
280    //make sure the last page arg is re-set to zero
281    //since a new collection is being chosen
282    args["di1lastpage"] = "0";
283
284    // assign (and create) a temporary directory This will create a new
285    // tbuild directory every time the user goes back to select a new
286    // collection.  It causes no problems except wasted space.  Should be
287    // addressed in the future
288    if (assign_tmpname (args, logout)==false) {
289      // there was an error creating the tmp dir
290      message="tmpfail";
291      return true; // true because we could still parse the arguments
292    }
293
294    // clean up any old builds left laying about in the tmp directory
295    // (note that it's possible this could take some time if there's a huge
296    // partially built collecton laying about so we'll make it an asynchronous
297    // system call)
298    gsdl_system ("perl -S cleantmp.pl", false, logout);
299
300  }
301
302  if (current_page == "bildstatus" || current_page == "bildcancel") {
303    // if .final file exists then build has finished
304    text_t fbld = filename_cat (gsdlhome, "tmp", args[macro_prefix + "tmp"], args[macro_prefix + "dirname"] + ".bld.final");
305    if (file_exists (fbld)) {
306      char *fbldc = fbld.getcstr();
307      ifstream fbld_in (fbldc);
308      if (fbld_in) {
309    failcode = fbld_in.get();
310    fbld_in.close();
311    if (failcode == '0') {
312      // success - we need to create and configure a collection server for the
313      // newly built collection (for fastcgi and local library where
314      // initialization isn't going to be redone when the user clicks the
315      // "view your new collection" button
316      create_colserver (args[macro_prefix + "dirname"], logout);
317      current_page = "bilddone";
318    }
319    else current_page = "bildfail";
320      } else {
321    // assume build failed (we shouldn't get here though ... right?)
322    current_page = "bildfail";
323      }
324      delete []fbldc;
325    }
326  }
327
328  //is it a step page?
329  text_t::const_iterator here = current_page.begin();
330  text_t::const_iterator end = current_page.end();
331  text_t stepstring = substr(here,here+4);
332
333  //if so, increment the step count
334  //this should not be going up more than one at a time.
335  if(stepstring == "step") {
336    text_t currpage_textt = substr(here+4,here+5);
337    int currpage = currpage_textt.getint();
338
339    text_t lastpage_textt = args["di1lastpage"];
340    int lastpage = lastpage_textt.getint();
341    if (currpage > lastpage) {
342      lastpage++;
343      text_t lastpage_textt(lastpage);
344      args["di1lastpage"] = lastpage_textt;     
345    }
346
347    // create cached metadata values
348    if (args["di1cache"] == "1") {
349    text_t cached_metadata_values = "";
350    cgiargsclass::const_iterator args_here = args.begin();
351    cgiargsclass::const_iterator args_end = args.end();
352    while (args_here != args_end) {
353      text_t args_name = (*args_here).first;
354      int prefix_len = macro_prefix.size();
355      int args_name_len = args_name.size();
356
357      if(args_name_len >= prefix_len+3) { // Only now can we substring args_name by prefix_len+3
358          text_t args_prefix;
359          if(args_name_len == prefix_len+3) {
360              args_prefix = args_name;
361          } else { // >, so substring
362              args_prefix = substr(args_name.begin(),args_name.begin()+prefix_len+3);
363          }
364
365          if (args_prefix == (macro_prefix+"md.")) {     
366            text_t args_val = args[args_name];
367            cerr << "caching md arg "<<args_val<<endl;
368            decode_cgi_arg(args_val);
369            text_t args_suffix = substr(args_name.begin()+prefix_len+3,args_name.end());
370
371            text_tarray mdvalues;
372            splitchar (args_val.begin(), args_val.end(), ',', mdvalues);
373            int numvalues = mdvalues.size();
374
375            for (int i = 0; i < numvalues; ++i) {
376              if (!mdvalues[i].empty()) {
377               
378                //decode_cgi_arg(mdvalues[i]);
379               
380                if (cached_metadata_values == "") {
381                  cached_metadata_values = "var CachedMDValues = new Array(\\{";
382                } else {
383                  cached_metadata_values += ",";
384                }
385
386                cached_metadata_values += "\"" + args_name + "\":\"" + encodeForJavascript(args_val) + "\"";
387              }
388            }   
389          }
390      }
391      ++args_here;
392    }
393
394    if (cached_metadata_values != "") {
395      cached_metadata_values += "\\});";
396      args["cachedMDValues"] = cached_metadata_values;
397    }
398    }
399  }
400  return true;
401
402
403
404void depositoraction::define_internal_macros (displayclass &disp, cgiargsclass &args,
405                          recptprotolistclass *protos, ostream &logout) {
406
407  // define_internal_macros sets some/all of the following macros (depending
408  // on cgiargs):
409  //
410  // _pagescriptextra_
411  // _header_
412  // _depositorbar_
413  // _textfailmsg_
414  // _di1userfile_
415  // _di1userfilesize_
416
417  text_t &depositor_page = args["p"];
418 
419  // set _pagescriptextra_ macro to _cpagescriptextra_
420  disp.setmacro ("pagescriptextra", "depositor", "_" + depositor_page + "scriptextra_");
421
422  if (depositor_page == "bildstatus" || depositor_page == "bilddone" ||
423      depositor_page == "bildfail" || depositor_page == "bildframe1" ||
424      depositor_page == "select") {
425    disp.setmacro ("header", "depositor", "_" + depositor_page + "header_");
426  }
427
428  if (depositor_page == "bildstatus") {
429    set_statusline (disp, args, logout);
430  }
431
432  if (depositor_page == "select") {
433    set_fullnamemenu (disp, args, protos, logout);
434  }
435
436  //how many pages in collection?
437  //we need a _depositorbar_ for each
438
439  text_t numsteps_str;
440  disp.expandstring("depositor", "_numsteps_", numsteps_str);
441  int numsteps = numsteps_str.getint();
442   
443  //is the page a step page?
444
445  text_t::const_iterator here = depositor_page.begin();
446  text_t::const_iterator end = depositor_page.end();
447  text_t stepstring = substr(here,here+4);
448
449  if((stepstring) == "step" || (depositor_page == "depositonly") ) {
450    disp.setmacro("di1userfile","depositor",args["di1userfile"]);
451    disp.setmacro("di1userfilesize","depositor",args["di1userfilesize"]);
452  }
453
454  //set up the depositor bar
455  text_t depositorbar = "<table class=wizardbar border=0 cellspacing=4 cellpadding=0><tr>\n";
456
457  if(stepstring == "step") {   
458    // check configured metadata elements
459    if (args["metadataconf"] == "var DepositorMDFields = new Array();" || args["metadataconf"] == "") {
460
461      text_t cfgfile_name = filename_cat (collecthome, args[macro_prefix + "dirname"], "etc", "collect.cfg");
462      text_t key;
463      text_tarray cfgline;
464      char *cstr = cfgfile_name.getcstr();
465      ifstream confin (cstr);
466      delete []cstr;
467
468      text_t metadata_str;
469      if (confin) {
470    while (read_cfg_line(confin, cfgline) >= 0) {
471      if (cfgline.size () >= 2) {
472        key = cfgline[0];
473        if (key == "collectionmeta") {
474          if (cfgline[1] == "depositormetadata") {
475        metadata_str = cfgline[2];
476         
477        break;
478          }
479        }
480      }
481    }
482      }
483      confin.close ();
484     
485      if (metadata_str == "") {
486    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\"}";
487      }
488      args["metadataconf"] = "var DepositorMDFields = new Array("+metadata_str+");";
489 
490    }
491
492    here = depositor_page.begin();
493    text_t stepnums = substr(here+4,here+5);
494    int stepnum = stepnums.getint();
495
496    text_t lastpage_textt = args["di1lastpage"];
497    int lastpage = lastpage_textt.getint();
498   
499    // again, begin with the select bar...
500    //the first button - selecting a collection
501    for(int i = 1; i <= numsteps; i++) {
502      text_t numstr(i);
503      if(i <= lastpage && i == stepnum) {
504    depositorbar += get_button (args,depositor_page, "yellow", "step"+numstr, false);
505      } else if (i <= lastpage) {
506    depositorbar += get_button (args,depositor_page, "yellow", "step"+numstr, true);
507      } else if((i == lastpage+1)){
508    depositorbar += get_button (args,depositor_page, "green", "step"+numstr, true);       
509      } else {
510    depositorbar += get_button (args,depositor_page, "grey", "step"+numstr, false);       
511      }
512      depositorbar += "<td>_icongreyarrow_</td>\n";
513
514    }   
515
516    //the build and preview pages are always last
517    if(lastpage == numsteps) {
518      depositorbar += get_button (args,depositor_page, "green", "laststep", true);
519    } else {
520      depositorbar += get_button (args,depositor_page, "grey", "laststep", false);
521    }
522
523    text_t laststep_textt;
524    disp.expandstring("depositor", "_laststep_", laststep_textt);
525    if(laststep_textt == "bild") {
526      depositorbar += "<td>_icongreyarrow_</td>\n";
527      depositorbar += get_button (args,depositor_page, "grey", "view", false);
528    }
529    depositorbar += "</tr><tr>";
530
531    for(int j = 1; j <= 2*(stepnum-1); j++) {
532      depositorbar += "<td></td>";
533    }
534    depositorbar += "<td align=center>_icongreyuparrow_</td>\n";   
535
536    depositorbar += "</tr></table>\n";
537
538    // set the javascript so that the metadata form can read the existing values
539    if (args["cachedMDValues"] != "") {
540      disp.setmacro("cachedmetadatavalues", "depositor", args["cachedMDValues"]);
541    }
542    if (args["metadataconf"] != "") {
543      disp.setmacro("metadataconf", "depositor", args["metadataconf"]);
544    }   
545  }
546 
547  if ((depositor_page == "bildcancel") || (depositor_page == "bildfail")) {
548 
549    for(int i = 1; i <= numsteps; i++) {
550
551      text_t numstr(i);
552      depositorbar += get_button (args,depositor_page, "yellow", "step"+numstr, true);       
553      depositorbar += "<td>_icongreyarrow_</td>\n";
554
555    }
556
557    //the build and preview pages are always last
558    depositorbar += get_button (args,depositor_page, "green", "laststep", true);
559    depositorbar += "<td>_icongreyarrow_</td>\n";
560    depositorbar += get_button (args,depositor_page, "grey", "view", false);
561
562    depositorbar += "</tr><tr>";
563
564    for(int j = 1; j <= 2*numsteps; j++) {
565      depositorbar += "<td></td>";
566    }
567    depositorbar += "<td align=center>_icongreyuparrow_</td>\n";   
568
569    depositorbar += "</tr></table>\n";
570
571  }
572
573  if(depositor_page == "bilddone"){
574   
575    for(int i = 1; i <= numsteps; i++) {
576
577      text_t numstr(i);
578      depositorbar += get_button (args, depositor_page, "grey", "step"+numstr, false);       
579      depositorbar += "<td>_icongreyarrow_</td>\n";
580
581    }
582
583    //the build and preview pages are always last
584    depositorbar += get_button (args,depositor_page, "yellow", "laststep", false);
585    depositorbar += "<td>_icongreyarrow_</td>\n";
586    depositorbar += get_button (args,depositor_page, "green", "view", true);
587
588    depositorbar += "</tr><tr>";
589
590    for(int j = 1; j <= 2*numsteps; j++) {
591      depositorbar += "<td></td>";
592    }
593    depositorbar += "<td align=center>_icongreyuparrow_</td>\n";   
594
595    depositorbar += "</tr></table>\n";
596  }
597  disp.setmacro ("depositorbar", "depositor", depositorbar);
598
599  if (depositor_page == "bildfail") {
600 
601    text_t textfailmsg = "_textfailmsg";
602    textfailmsg.push_back(failcode);
603    textfailmsg.push_back('_');
604    disp.setmacro("textfailmsg", "depositor", textfailmsg);
605
606    text_t bldlog = filename_cat(gsdlhome, "tmp", args["di1tmp"], args["di1dirname"] + ".bld");
607    //text_t rawlog = file_tail (bldlog, 6, 0);
608    text_t rawlog;
609    read_file(bldlog, rawlog);
610    // we'll shove in some <br> tags where \n's occur
611    text_t faillog;
612    text_t::const_iterator here = rawlog.begin();
613    text_t::const_iterator end = rawlog.end();
614    while (here != end) {
615      if (*here == '\n') faillog += "<br>";
616      faillog.push_back (*here);
617      ++here;
618    }
619    disp.setmacro ("faillog", "depositor", dm_safe(faillog));
620  }
621}
622
623
624//basic framework
625bool depositoraction::do_action (cgiargsclass &args, recptprotolistclass * /*protos*/,
626                 browsermapclass * /*browsers*/, displayclass &disp,
627                 outconvertclass &outconvert, ostream &textout,
628                 ostream &logout) {
629  // make sure the depositor is enabled
630  if (disabled) {
631    textout << outconvert
632        << "<html>\n"
633        << "<head>\n"
634        << "<title>Depositor disabled</title>\n"
635        << "</head>\n"
636        << "<body bgcolor=\"#ffffff\" text=\"#000000\" link=\"#006666\" "
637        << "alink=\"#cc9900\" vlink=\"#666633\">\n"
638        << "<h2>Facility disabled</h2>\n"
639        << "Sorry, the Depositor end-user collecation update facility is currently disabled\n"
640        << "\n</body>\n"
641        << "</html>\n";
642    return true;
643  }
644
645  text_t &depositor_page = args["p"];
646  text_t &collection = args["di1dirname"];
647
648  // make sure we have perl (we won't bother with this check for the
649  // building status pages to avoid slowing things down unneccessarily)
650  if (depositor_page != "bildstatus" && depositor_page != "bildframe1" && !perl_ok(logout)) {
651    textout << outconvert
652        << "<html>\n"
653        << "<head>\n"
654        << "<title>Perl not found</title>\n"
655        << "</head>\n"
656        << "<body bgcolor=\"#ffffff\" text=\"#000000\" link=\"#006666\" "
657        << "alink=\"#cc9900\" vlink=\"#666633\">\n"
658        << "<h2>Perl not found</h2>\n"
659        << "Greenstone could not detect perl on this system. It is therefore not\n"
660        << "possible to build a Greenstone collection, either from the Collector or the \n"
661        << "command-line tools, or to use the Collector for any other task.\n"
662        << "<p>Please refer to the Greenstone Installer's Guide for details on\n"
663        << "installing perl on your system.\n"
664        << "\n</body>\n"
665        << "</html>\n";
666    return true;
667
668  }
669
670  text_t::const_iterator here = depositor_page.begin();
671  text_t::const_iterator end = depositor_page.end();
672  text_t stepstring = substr(here,here+4);
673
674  if ((depositor_page == "select") || (stepstring == "step")) {
675          textout << outconvert << disp << ("_depositor:header_\n")
676          << ("_depositor:" + encodeForHTML(depositor_page) + "content_\n")
677          << ("_depositor:footer_\n");
678     
679  }
680
681  if ((depositor_page == "bild") || (depositor_page == "depositonly")) {
682
683    text_t filename_textt = args["di1userfile"];
684    text_t timestamp_str = args["di1timestamp"];
685    //check to make sure a file was uploaded
686    //if more than one upload occurred, the last one is taken
687    if(filename_textt == "") {
688      textout << outconvert << disp << "<p> no file available</p>\n";
689    } else {
690   
691      text_t col_dirname = filename_cat(collecthome,args[macro_prefix+"dirname"]);
692      text_t import_dirname = filename_cat(col_dirname,"import");
693      if(!directory_exists(import_dirname)) {
694    bool flag = mk_dir(import_dirname);
695    if(!flag) {
696      cerr << "Error: unable to make directory " << import_dirname << endl;
697      return true;
698    }
699      }
700
701      text_t dirname = filename_cat(import_dirname,timestamp_str);
702      bool flag = mk_dir(dirname);
703      if(!flag) {
704    cerr << "Error: unable to make timestamp directory " << dirname << endl;
705    return true;
706      }
707
708      text_t filename_textt = args["di1userfile"];
709      text_t tmpdir = filename_cat(gsdlhome,"tmp",args["di1tmp"],timestamp_str);
710      text_t tmpfile = filename_cat(tmpdir,filename_textt);
711      text_t filename = filename_cat(dirname, filename_textt); 
712      if(!file_copy(tmpfile, filename)) {
713    cerr << "Unable to copy " << tmpfile << " to " << filename << endl;
714      }
715     
716      //write the metadata file
717      write_metadata_file(args, filename_textt, timestamp_str);
718
719      if(depositor_page == "bild"){
720
721    //create a manifest file
722    write_manifest_file(args, filename_textt, timestamp_str);
723   
724    // do the work (download, import, build)
725    gsdl_build (args, logout);
726
727    if (message.empty()) {
728      // bild page is a frameset so we don't want headers and stuff
729      textout << outconvert << disp << ("_depositor:bildcontent_\n");
730    }
731      }
732    }
733  }
734
735  if (message.empty()) {
736
737    if (depositor_page != "bild" && stepstring != "step" && depositor_page != "select") {
738      // output page ("bild" page was already output above)
739      textout << outconvert << disp << ("_depositor:header_\n")
740          << ("_depositor:" + encodeForHTML(depositor_page) + "content_\n")
741          << ("_depositor:footer_\n");
742    }
743  } else {
744    // message was set somewhere (probably an error), output message page
745    textout << outconvert << disp << ("_depositor:header_\n")
746        << ("_depositor:" + message + "content_\n")
747        << ("_depositor:footer_\n");
748    message.clear();
749  }
750 
751  return true;
752
753}
754
755
756//This function creates a metadata.xml file
757void depositoraction::write_metadata_file(cgiargsclass &args, text_t filename_str, text_t& timestamp_str)
758{
759
760    //build metadata file
761    //the front
762    text_t metadata_file = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
763    metadata_file += "<!DOCTYPE DirectoryMetadata SYSTEM \"http://greenstone.org/dtd/DirectoryMetadata/1.0/DirectoryMetadata.dtd\">\n";
764    metadata_file += "<DirectoryMetadata>\n";
765    metadata_file += "    <FileSet>\n";
766    metadata_file += "        <FileName>";
767
768    // Generate 'regular expression' save version of filename
769    // for now that means escaping any '.' characters
770    // consider generalising as function in gsdltools.h/cpp?
771
772    text_t filename_re;
773    text_t::const_iterator here = filename_str.begin();
774    text_t::const_iterator end = filename_str.end();
775    while (here != end) {
776      if (*here == '.') {
777    filename_re.push_back('\\');
778      }
779
780      filename_re.push_back(*here);
781      ++here;
782    }
783
784    metadata_file += filename_re;
785
786    metadata_file += "</FileName>\n";
787    metadata_file += "        <Description>\n";
788
789   
790    cgiargsclass::const_iterator args_here = args.begin();
791    cgiargsclass::const_iterator args_end = args.end();
792
793    while (args_here != args_end) {
794      text_t args_name = (*args_here).first;
795
796      int prefix_len = macro_prefix.size();
797      int args_name_len = args_name.size();
798
799      if(args_name_len >= prefix_len+3) { // Only now can we substring args_name by prefix_len+3
800          text_t args_prefix;
801          if(args_name_len == prefix_len+3) {
802              args_prefix = args_name;
803          } else { // >, so substring
804              args_prefix = substr(args_name.begin(),args_name.begin()+prefix_len+3);
805          }
806
807          if (args_prefix == (macro_prefix+"md.")) {     
808            text_t args_val = args[args_name];
809            cerr << "args val = "<<args_val<<endl;
810            decode_cgi_arg(args_val);
811            cerr << "decoded" << args_val<<endl;
812            text_t args_suffix = substr(args_name.begin()+prefix_len+3,args_name.end());
813
814            text_tarray mdvalues;
815            splitchar (args_val.begin(), args_val.end(), ',', mdvalues);
816            int numvalues = mdvalues.size();
817            cerr << "numvals = "<<numvalues<<endl;
818            for (int i = 0; i < numvalues; ++i) {
819              if (!mdvalues[i].empty()) {
820                //decode_cgi_arg(mdvalues[i]);
821                metadata_file += "            <Metadata mode=\"accumulate\" name=\"";       
822                metadata_file += args_suffix;
823                metadata_file += "\">";
824                metadata_file += xml_safe(mdvalues[i]);
825                metadata_file += "</Metadata>\n";
826
827              }
828            }
829          }
830      }
831      ++args_here;
832    }
833   
834    //the end of the file
835    metadata_file += "        </Description>\n";
836    metadata_file += "    </FileSet>\n";
837    metadata_file += "</DirectoryMetadata>\n";
838
839    //create metadata.xml file
840    text_t metadata_path = filename_cat(collecthome, args[macro_prefix+"dirname"], "import", timestamp_str, "metadata.xml");
841    text_t my_path = filename_cat(gsdlhome,"tmp", "metadata.xml");
842
843    ofstream metadata(metadata_path.getcstr());
844    ofstream my_tmp(my_path.getcstr());
845
846    if(!metadata.is_open()) {
847      cerr << "Cannot open metadata.xml!" << endl;
848    } else {
849     
850      //write metadata.xml
851      // need to convert to utf8 before writing it out.
852      text_t utf8_meta = to_utf8(metadata_file);
853      metadata.write(utf8_meta.getcstr(), utf8_meta.size());
854      my_tmp.write(utf8_meta.getcstr(), utf8_meta.size());
855    }
856}
857
858//This function creates a manifest.xml file
859void depositoraction::write_manifest_file(cgiargsclass &args, text_t filename,
860                      text_t& timestamp_str)
861{
862
863    //build manifest file
864
865    //the front
866    text_t manifest_file = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
867    manifest_file += "<Manifest>\n";
868    manifest_file += "    <Index>\n";
869    manifest_file += "        <Filename>\n";
870    manifest_file += "          " + timestamp_str + "\n";
871    manifest_file += "        </Filename>\n";
872   
873    //the end of the file
874    manifest_file += "    </Index>\n";
875    manifest_file += "</Manifest>\n";
876
877    //create manifest.xml file
878    text_t manifest_path = filename_cat(collecthome, args[macro_prefix+"dirname"], "manifest.xml");
879
880    char* manifest_cstr = manifest_path.getcstr();
881
882    ofstream manifest(manifest_cstr);
883
884    if(!manifest.is_open()) {
885      cerr << "Cannot open" << manifest_cstr << endl;
886    } else {
887
888      //write manifest.xml
889      char *manifest_file_cstr = manifest_file.getcstr();
890      manifest.write(manifest_file_cstr, manifest_file.size());
891      delete [] manifest_file_cstr;
892    }
893
894    delete [] manifest_cstr;
895}
896
897
898
899text_t depositoraction::get_button(cgiargsclass &args, const text_t &thispage,
900                   const text_t &color,
901                   const text_t &type, bool enabled)
902{
903
904  text_t::const_iterator here = type.begin();
905  text_t::const_iterator end = type.end();
906  text_t stepstring = substr(here,here+4);
907  if ((color != "green" && color != "grey" && color != "yellow") ||
908      (type != "select" && type != "laststep" && stepstring != "step" && type != "view"))
909    return g_EmptyText;
910
911  text_t href = "_http"+type+"_";
912  text_t target = "";
913
914  here = thispage.begin();
915  stepstring = substr(here,here+4); 
916  if (thispage == "bildcancel" || thispage == "bildfail" || thispage == "select"|| stepstring == "step") {
917    // call the check submit macro instead of linking directly to the page
918
919    if(type == "laststep") {
920      href="\"javascript:check_submit('_"+type+"_');\"";
921    } else {
922      href="\"javascript:check_submit('"+type+"');\"";
923    }
924
925  } else if (type == "view") {
926   //target = " target=_top";
927    target = " target=_blank";
928  }
929
930  text_t tdclass = "wizardbar"+color;
931  if (enabled) {
932    // link to the appropriate page
933    return "<td class="+tdclass+"><a href="+href+target+">_text"+type+"_</a></td>";
934  }
935  else {
936    // just display the text
937    return "<td class="+tdclass+">_text"+type+"_</td>";
938  }
939}
940
941
942#endif //GSDL_USE_DEPOSITOR_ACTION
Note: See TracBrowser for help on using the browser.