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

Last change on this file since 12794 was 12794, checked in by davidb, 16 years ago

Changes to make depositor action work under Windows. Main change is to
make sure 'standard input' is in binary mode before MIME multi-part posts
are parsed.

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