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

Revision 22984, 32.2 KB (checked in by ak19, 9 years ago)

1. Undoing commit of 22934 where decode_commas was called on stem and fold comma separated list: previously separated due to url-encoding of commas. Now that the problem has been fixed at the source, the decode_commas hack is no longer necessary. 2. Commas in stem and fold are no longer url-encoded because the multiple_value field of the continuously-reused struct arg_ainfo is always set back to the default false after ever being set to true. So it no longer subtly stays at true to affect Greenstone functioning in unforeseen ways (such as suddenly and unnecessarily URL-encoding commas where this is not wanted).

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