source: main/trunk/greenstone2/runtime-src/src/recpt/depositoraction.cpp@ 29381

Last change on this file since 29381 was 29381, checked in by kjdon, 6 years ago

removed the commented out args - these args are ones that collector uses. Added a couple of new args, for turning off cahcing of metadata values, and for local depositor - when we want a link from a collection to deposit. want to bypass the select a collection page.

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