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

Last change on this file since 30466 was 30466, checked in by kjdon, 8 years ago

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

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