source: gsdl/trunk/src/recpt/depositoraction.cpp@ 16310

Last change on this file since 16310 was 16310, checked in by davidb, 12 years ago

Introduction of 'collecthome' which parallels 'gsdlhome' to allow the toplevel collect folder to be outside of the gsdlhome area

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