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

Last change on this file since 22984 was 22984, checked in by ak19, 14 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
File size: 32.2 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 = "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 repository browser.