source: gsdl/trunk/src/recpt/collectoraction.cpp@ 15453

Last change on this file since 15453 was 15453, checked in by mdewsnip, 16 years ago

Removed some unnecessary inclusions of header files from colservr/protocol.

  • Property svn:keywords set to Author Date Id Revision
File size: 50.8 KB
Line 
1/**********************************************************************
2 *
3 * collectoraction.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_COLLECTOR_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 "collectoraction.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#include <stdio.h>
50#include <fcntl.h>
51
52#if !defined (__WIN32__)
53#include <sys/utsname.h>
54#include <unistd.h>
55#endif
56
57collectoraction::collectoraction ()
58 : wizardaction()
59{
60 macro_prefix = "bc1";
61
62 do_mkcol = false;
63 badsources = false;
64 failedsources.erase(failedsources.begin(), failedsources.end());
65
66 cgiarginfo arg_ainfo;
67 arg_ainfo.shortname = "a";
68 arg_ainfo.longname = "action";
69 arg_ainfo.multiplechar = true;
70 arg_ainfo.defaultstatus = cgiarginfo::weak;
71 arg_ainfo.argdefault = "collector";
72 arg_ainfo.savedarginfo = cgiarginfo::must;
73 argsinfo.addarginfo (NULL, arg_ainfo);
74
75 arg_ainfo.shortname = "p";
76 arg_ainfo.longname = "page";
77 arg_ainfo.multiplechar = true;
78 arg_ainfo.defaultstatus = cgiarginfo::weak;
79 arg_ainfo.argdefault = "intro";
80 arg_ainfo.savedarginfo = cgiarginfo::must;
81 argsinfo.addarginfo (NULL, arg_ainfo);
82
83 // temporary directory name for this collector
84 // session
85 arg_ainfo.shortname = "bc1tmp";
86 arg_ainfo.longname = "collector specific";
87 arg_ainfo.multiplechar = true;
88 arg_ainfo.defaultstatus = cgiarginfo::weak;
89 arg_ainfo.argdefault = g_EmptyText;
90 arg_ainfo.savedarginfo = cgiarginfo::must;
91 argsinfo.addarginfo (NULL, arg_ainfo);
92
93 arg_ainfo.shortname = "bc1fullname";
94 arg_ainfo.longname = "collector specific";
95 arg_ainfo.multiplechar = true;
96 arg_ainfo.defaultstatus = cgiarginfo::weak;
97 arg_ainfo.argdefault = g_EmptyText;
98 arg_ainfo.savedarginfo = cgiarginfo::mustnot; // saved on disk
99 argsinfo.addarginfo (NULL, arg_ainfo);
100
101 arg_ainfo.shortname = "bc1dirname";
102 arg_ainfo.longname = "collector specific";
103 arg_ainfo.multiplechar = true;
104 arg_ainfo.defaultstatus = cgiarginfo::weak;
105 arg_ainfo.argdefault = g_EmptyText;
106 arg_ainfo.savedarginfo = cgiarginfo::must;
107 argsinfo.addarginfo (NULL, arg_ainfo);
108
109 arg_ainfo.shortname = "bc1contactemail";
110 arg_ainfo.longname = "collector specific";
111 arg_ainfo.multiplechar = true;
112 arg_ainfo.defaultstatus = cgiarginfo::weak;
113 arg_ainfo.argdefault = g_EmptyText;
114 arg_ainfo.savedarginfo = cgiarginfo::mustnot; // saved on disk
115 argsinfo.addarginfo (NULL, arg_ainfo);
116
117 arg_ainfo.shortname = "bc1aboutdesc";
118 arg_ainfo.longname = "collector specific";
119 arg_ainfo.multiplechar = true;
120 arg_ainfo.defaultstatus = cgiarginfo::weak;
121 arg_ainfo.argdefault = g_EmptyText;
122 arg_ainfo.savedarginfo = cgiarginfo::mustnot; // saved on disk
123 argsinfo.addarginfo (NULL, arg_ainfo);
124
125 arg_ainfo.shortname = "bc1clone";
126 arg_ainfo.longname = "collector specific";
127 arg_ainfo.multiplechar = false;
128 arg_ainfo.defaultstatus = cgiarginfo::weak;
129 arg_ainfo.argdefault = "0";
130 arg_ainfo.savedarginfo = cgiarginfo::mustnot; // saved on disk
131 argsinfo.addarginfo (NULL, arg_ainfo);
132
133 arg_ainfo.shortname = "bc1clonecol";
134 arg_ainfo.longname = "collector specific";
135 arg_ainfo.multiplechar = true;
136 arg_ainfo.defaultstatus = cgiarginfo::weak;
137 arg_ainfo.argdefault = g_EmptyText;
138 arg_ainfo.savedarginfo = cgiarginfo::mustnot; // saved on disk
139 argsinfo.addarginfo (NULL, arg_ainfo);
140
141 // set when cloning option has changed
142 arg_ainfo.shortname = "bc1clonechanged";
143 arg_ainfo.longname = "collector specific";
144 arg_ainfo.multiplechar = false;
145 arg_ainfo.defaultstatus = cgiarginfo::weak;
146 arg_ainfo.argdefault = "0";
147 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
148 argsinfo.addarginfo (NULL, arg_ainfo);
149
150 // only set when one of the fields was changed in
151 // the "collection info" page
152 arg_ainfo.shortname = "bc1infochanged";
153 arg_ainfo.longname = "collector specific";
154 arg_ainfo.multiplechar = false;
155 arg_ainfo.defaultstatus = cgiarginfo::weak;
156 arg_ainfo.argdefault = "0";
157 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
158 argsinfo.addarginfo (NULL, arg_ainfo);
159
160 // only set when cfg file is altered from within
161 // "configure collection" page
162 arg_ainfo.shortname = "bc1cfgchanged";
163 arg_ainfo.longname = "collector specific";
164 arg_ainfo.multiplechar = false;
165 arg_ainfo.defaultstatus = cgiarginfo::weak;
166 arg_ainfo.argdefault = "0";
167 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
168 argsinfo.addarginfo (NULL, arg_ainfo);
169
170 arg_ainfo.shortname = "cfgfile";
171 arg_ainfo.longname = "configuration file contents";
172 arg_ainfo.multiplechar = true;
173 arg_ainfo.defaultstatus = cgiarginfo::weak;
174 arg_ainfo.argdefault = g_EmptyText;
175 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
176 argsinfo.addarginfo (NULL, arg_ainfo);
177
178 arg_ainfo.shortname = "bc1dodelete";
179 arg_ainfo.longname = "collector specific";
180 arg_ainfo.multiplechar = false;
181 arg_ainfo.defaultstatus = cgiarginfo::weak;
182 arg_ainfo.argdefault = "0";
183 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
184 argsinfo.addarginfo (NULL, arg_ainfo);
185
186 // will be set if we arrived at the "configure collection" page
187 // via the "changing an existing collection" page
188 arg_ainfo.shortname = "bc1econf";
189 arg_ainfo.longname = "collector specific";
190 arg_ainfo.multiplechar = false;
191 arg_ainfo.defaultstatus = cgiarginfo::weak;
192 arg_ainfo.argdefault = "0";
193 arg_ainfo.savedarginfo = cgiarginfo::must;
194 argsinfo.addarginfo (NULL, arg_ainfo);
195
196 // will be set if we arrived at the "source data" page
197 // via the "changing an existing collection" page
198 arg_ainfo.shortname = "bc1esrce";
199 arg_ainfo.longname = "collector 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 arg_ainfo.shortname = "bc1inputnum";
207 arg_ainfo.longname = "collector specific";
208 arg_ainfo.multiplechar = true;
209 arg_ainfo.defaultstatus = cgiarginfo::weak;
210 arg_ainfo.argdefault = "3";
211 arg_ainfo.savedarginfo = cgiarginfo::mustnot; // saved on disk
212 argsinfo.addarginfo (NULL, arg_ainfo);
213
214 arg_ainfo.shortname = "bc1input";
215 arg_ainfo.longname = "collector specific";
216 arg_ainfo.multiplechar = true;
217 arg_ainfo.multiplevalue = true;
218 arg_ainfo.defaultstatus = cgiarginfo::weak;
219 arg_ainfo.argdefault = g_EmptyText;
220 arg_ainfo.savedarginfo = cgiarginfo::mustnot; // saved on disk
221 argsinfo.addarginfo (NULL, arg_ainfo);
222
223 arg_ainfo.shortname = "bc1inputtype";
224 arg_ainfo.longname = "collector specific";
225 arg_ainfo.multiplechar = true;
226 arg_ainfo.multiplevalue = true;
227 arg_ainfo.defaultstatus = cgiarginfo::weak;
228 arg_ainfo.argdefault = g_EmptyText;
229 arg_ainfo.savedarginfo = cgiarginfo::mustnot; // saved on disk
230 argsinfo.addarginfo (NULL, arg_ainfo);
231
232 // will be set when we've just come from the "source data" page
233 arg_ainfo.shortname = "bc1fromsrce";
234 arg_ainfo.longname = "collector specific";
235 arg_ainfo.multiplechar = false;
236 arg_ainfo.multiplevalue = false;
237 arg_ainfo.defaultstatus = cgiarginfo::weak;
238 arg_ainfo.argdefault = "0";
239 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
240 argsinfo.addarginfo (NULL, arg_ainfo);
241}
242
243collectoraction::~collectoraction () {
244}
245
246
247
248bool collectoraction::check_cgiargs (cgiargsinfoclass &argsinfo, cgiargsclass &args,
249 recptprotolistclass * /*protos*/, ostream &logout) {
250
251 text_t &current_page = args["p"];
252
253 // note that the "bildstatus" and "bildframe1" pages don't actually do anything
254 // functional so we don't need to worry about authenticating them (it's the
255 // underlying "bild" page that does the building (and creates the frameset))
256 // This helps us overcome a bit of a problem we have with multiple pages trying
257 // to read from the key.db database at the same time.
258 if (current_page != "intro" && current_page != "bildstatus" && current_page != "bildframe1") {
259 // authenticate the user if authentication is available
260 args["uan"] = 1;
261 args["ug"] = "all-collections-editor";
262 }
263
264 if (current_page == "new" || current_page == "existing") {
265
266 // assign (and create) a temporary directory
267 if (assign_tmpname (args, logout)==false) {
268 // there was an error creating the tmp dir
269 message="tmpfail";
270 return true; // true because we could still parse the arguments
271 }
272
273 // clean up any old builds left laying about in the tmp directory
274 // (note that it's possible this could take some time if there's a huge
275 // partially built collecton laying about so we'll make it an asynchronous
276 // system call)
277 gsdl_system ("perl -S cleantmp.pl", false, logout);
278 }
279
280 if (current_page != "intro" && current_page != "bildstatus" &&
281 current_page != "bildframe1" && current_page != "new") {
282 // update arguments that were saved to the harddrive
283 text_tmap saved_args;
284 saved_args["bc1fullname"] = g_EmptyText;
285 saved_args["bc1contactemail"] = g_EmptyText;
286 saved_args["bc1aboutdesc"] = g_EmptyText;
287 saved_args["bc1clone"] = g_EmptyText;
288 saved_args["bc1clonecol"] = g_EmptyText;
289 saved_args["bc1inputnum"] = g_EmptyText;
290 saved_args["bc1input"] = g_EmptyText;
291 saved_args["bc1inputtype"] = g_EmptyText;
292
293 // update the argdb database with any arguments that were set
294 // by previous page
295 text_tmap::iterator here = saved_args.begin();
296 text_tmap::iterator end = saved_args.end();
297 while (here != end) {
298 if (args.lookupcgiarg((*here).first).source != cgiarg_t::default_arg) {
299 (*here).second = args[(*here).first];
300 }
301 ++here;
302 }
303
304 text_t argfile = filename_cat(gsdlhome, "tmp", args["bc1tmp"], "argdb.db");
305 argdb *args_on_disk = new argdb(argfile);
306 if (!args_on_disk->update_args(saved_args)) {
307 // error
308 logout << "collectoraction: argdb::update_args failed (" << argfile << ")\n";
309 }
310
311 // update args from argdb
312 saved_args.erase(saved_args.begin(), saved_args.end());
313 if (!args_on_disk->get_args(saved_args)) {
314 // error
315 logout << "collectoraction: argdb::get_args failed (" << argfile << ")\n";
316 }
317 delete args_on_disk;
318 here = saved_args.begin();
319 end = saved_args.end();
320 while (here != end) {
321 if (!(*here).second.empty()) {
322 args[(*here).first] = (*here).second;
323 }
324 ++here;
325 }
326 }
327
328 if (args["bc1infochanged"] == "1") {
329
330 if (args["bc1dirname"].empty()) {
331 // we've just come from the "collection information" page for the
332 // first time so we'll need to create the collection with mkcol.pl
333 // and set up bc1dirname - we do this part here instead of in do_action
334 // because the bc1dirname argument must be set to its new value before
335 // the compressedoptions macros are set.
336 args["bc1dirname"] = get_directory_name (args["bc1fullname"]);
337
338 text_t createfile = filename_cat (gsdlhome, "tmp", args["bc1tmp"], ".create");
339 if (!file_exists (createfile)) {
340 // we could do the mkcol.pl here but I guess it's nicer to do it in do_action()
341 do_mkcol = true;
342 } else {
343 // .create file already exists but bc1dirname wasn't set ... this should only be
344 // able to occur when the "reload" (and possibly the "back" and "forward" buttons)
345 // have been used to get us here.
346 // we'll check that the bc1dirname directory exists (in case of the unlikely
347 // possibility that get_directory_name returned a different value this time
348 // than it did originally).
349 text_t coldir = filename_cat (get_collectdir(args), args["bc1dirname"]);
350 if (!directory_exists (coldir)) {
351 message = "reloaderror";
352 return true;
353 }
354 }
355 } else {
356 // "collection information" has been changed after collection already exists
357 // so we'll need to update the cfg file.
358 update_cfgfile_partial (args, false, logout);
359 }
360 }
361
362 if (args["bc1cfgchanged"] == "1") {
363 // configuration file has been changed from the "configure collection"
364 // page. we need to update the file on disk and catch bc1 arguments up
365 // with changes.
366 update_cfgfile_complete (args, logout);
367 }
368
369 if (args["bc1clonechanged"] == "1") {
370 // cloning option has been changed on "source data" page. if it was turned
371 // on we want to create a new collect.cfg file using the bc1clonecol cfg file
372 // as a model (we'll save the old file as collect.cfg.org). if cloning was
373 // turned off we'll revert to using the collect.cfg.org file (which will need
374 // updating in case the bc1 arguments have been altered since cloning was
375 // turned on).
376 update_cfgfile_clone (args, logout);
377
378 // if cloning has just been turned on we'll also copy the rest of the files
379 // (excluding collect.cfg which we've already done) from the cloned collections
380 // etc directory to the new collection.
381 if (args["bc1clone"] == "1") {
382 text_t clone_etc = filename_cat(gsdlhome, "collect", args["bc1clonecol"], "etc");
383 text_t new_etc = filename_cat(get_collectdir(args), args["bc1dirname"], "etc");
384 text_tarray files;
385
386 if (read_dir (clone_etc, files)) {
387 text_tarray::const_iterator here = files.begin();
388 text_tarray::const_iterator end = files.end();
389 while (here != end) {
390 if (*here != "collect.cfg" && *here != "collect.cfg.org") {
391 file_copy (filename_cat(clone_etc, *here), filename_cat(new_etc, *here));
392 }
393 ++here;
394 }
395 } else {
396 outconvertclass text_t2ascii;
397 logout <<text_t2ascii << "collectoraction::check_cgiargs couldn't read from "
398 << clone_etc << " directory\n";
399 }
400 }
401 }
402
403 if (current_page == "bildstatus" || current_page == "bildcancel") {
404 // if .final file exists then build has finished
405 text_t fbld = filename_cat (gsdlhome, "tmp", args["bc1tmp"], args["bc1dirname"] + ".bld.final");
406 if (file_exists (fbld)) {
407 char *fbldc = fbld.getcstr();
408 ifstream fbld_in (fbldc);
409 if (fbld_in) {
410 failcode = fbld_in.get();
411 fbld_in.close();
412 if (failcode == '0') {
413 // success - we need to create and configure a collection server for the
414 // newly built collection (for fastcgi and local library where
415 // initialization isn't going to be redone when the user clicks the
416 // "view your new collection" button
417 create_colserver (args["bc1dirname"], logout);
418 current_page = "bilddone";
419 }
420 else current_page = "bildfail";
421 } else {
422 // assume build failed (we shouldn't get here though ... right?)
423 current_page = "bildfail";
424 }
425 delete []fbldc;
426 }
427 }
428
429 if (args["bc1fromsrce"] == "1") {
430
431 // we've just come from the "source data" page so we need to check that
432 // input sources are valid
433 if (!check_sources(args, logout)) {
434 args["p"] = "srce";
435 }
436 }
437
438 return true;
439}
440
441void collectoraction::update_cfgfile_clone (cgiargsclass &args, ostream &logout) {
442
443 text_t tmpdir = filename_cat(gsdlhome, "tmp", args["bc1tmp"]);
444 text_t cfgfile = filename_cat(tmpdir, args["bc1dirname"], "etc", "collect.cfg");
445 if (!file_exists (cfgfile)) {
446 message = "tmpfail";
447 return;
448 }
449
450 text_t cfgfile_org = filename_cat (tmpdir, "collect.cfg.org");
451
452 if (args["bc1clone"] == "1") {
453 // cloning was turned on
454
455 text_t cfgfile_clone = filename_cat(gsdlhome, "collect", args["bc1clonecol"], "etc", "collect.cfg");
456 if (file_exists (cfgfile_clone)) {
457 // if .org file doesn't exist already create it
458 if (!file_exists (cfgfile_org)) {
459 if (!file_copy (cfgfile, cfgfile_org)) {
460 message = "tmpfail";
461 return;
462 }
463 }
464 // copy clone collections cfg file to new collection
465 if (!file_copy (cfgfile_clone, cfgfile)) {
466 message = "tmpfail";
467 return;
468 }
469 // update the new cfg file
470 update_cfgfile_partial (args, true, logout);
471
472 } else {
473 // can't clone non-existant or read-protected collection
474 message = "clonefail";
475 }
476
477 } else {
478 // cloning has been turned off having been on at some point. the .org file
479 // should exist, if it doesn't we'll bail out and leave the user with the
480 // cloned copy
481 if (file_exists (cfgfile_org)) {
482 // copy original back again and update it with any recent changes
483 if (file_copy (cfgfile_org, cfgfile)) {
484 update_cfgfile_partial (args, false, logout);
485 } else {
486 message = "tmpfail";
487 }
488 }
489 }
490}
491
492// update configuration file on disk to match bc1 arguments
493// there's a special case if the clone option is true as certain parts of a
494// config file should not be cloned (e.g. the iconcollection stuff)
495void collectoraction::update_cfgfile_partial (cgiargsclass &args, bool clone, ostream &logout) {
496
497 text_t cfgfile = filename_cat(get_collectdir(args), args["bc1dirname"], "etc", "collect.cfg");
498 char *cfgfilec = cfgfile.getcstr();
499
500#if defined (__WIN32__)
501 // make sure collect.cfg isn't read-only
502 _chmod (cfgfilec, _S_IREAD | _S_IWRITE);
503#endif
504
505 vector<text_tarray> cfgarray;
506
507 // read in cfg file
508 ifstream cfg_in (cfgfilec);
509 if (cfg_in) {
510 text_tarray cfgline;
511 while (read_cfg_line(cfg_in, cfgline) >= 0) {
512 if (cfgline.size () >= 2) {
513 if (cfgline[0] == "creator" || cfgline[0] == "maintainer") {
514 cfgline[1] = args["bc1contactemail"];
515 } else if (cfgline[0] == "collectionmeta") {
516 if (cfgline[1] == "collectionname") {
517 cfgline[2] = args["bc1fullname"];
518 } else if (cfgline[1] == "collectionextra") {
519 cfgline[2] = carriage_replace (args["bc1aboutdesc"], 0);
520 } else if (clone && (cfgline[1] == "iconcollection" ||
521 cfgline[1] == "iconcollectionsmall")) {
522 cfgline[2] = g_EmptyText;
523 }
524 }
525 }
526 cfgarray.push_back (cfgline);
527 }
528 cfg_in.close();
529
530 // now write cfg file back out
531 int fd=open(cfgfilec, O_WRONLY | O_CREAT | O_TRUNC
532#if defined(__WIN32__)
533 | O_BINARY
534#endif
535 );
536
537 if (fd != -1) {
538 // lock the file
539 int lock_val = 1;
540 GSDL_LOCK_FILE (fd);
541 if (lock_val != 0) {
542 logout << "Error: Couldn't lock file " << cfgfilec << "\n";
543 close(fd);
544 message = "tmpfail";
545
546 } else {
547
548 vector<text_tarray>::const_iterator this_line = cfgarray.begin();
549 vector<text_tarray>::const_iterator end_line = cfgarray.end();
550 while (this_line != end_line) {
551 write_cfg_line (fd, *this_line);
552 ++this_line;
553 }
554 GSDL_UNLOCK_FILE (fd);
555 close(fd);
556 }
557
558 } else {
559 logout << "collectoraction::update_cfgfile_partial: unable to open "
560 << cfgfilec << " for output\n";
561 message = "tmpfail";
562 }
563
564 } else {
565 logout << "collectoraction::update_cfgfile_partial: unable to open "
566 << cfgfilec << " for input\n";
567 message = "tmpfail";
568 }
569
570 delete []cfgfilec;
571}
572
573// replace configuration file on disk with that in the cfgfile argument and
574// catch other bc1 arguments up with those the new cfgfile contains
575void collectoraction::update_cfgfile_complete (cgiargsclass &args, ostream &logout) {
576
577 text_t cfgfile = filename_cat(get_collectdir(args), args["bc1dirname"], "etc", "collect.cfg");
578 char *cfgfilec = cfgfile.getcstr();
579
580#ifdef __WIN32__
581 // make sure collect.cfg isn't read-only
582 _chmod (cfgfilec, _S_IREAD | _S_IWRITE);
583#endif
584
585 int fd=open(cfgfilec, O_WRONLY | O_CREAT | O_TRUNC
586#if defined(__WIN32__)
587 | O_BINARY
588#endif
589 );
590
591 if (fd) {
592 // lock the file
593 int lock_val = 1;
594 GSDL_LOCK_FILE (fd);
595 if (lock_val != 0) {
596 logout << "Error: Couldn't lock file " << cfgfilec << "\n";
597 close(fd);
598 message = "tmpfail";
599
600 } else {
601
602 outconvertclass text_t2ascii;
603 text_t2ascii.setinput(&args["cfgfile"]);
604 size_t buffersize=args["cfgfile"].size();
605 char *buffer=new char[buffersize];
606 buffer[0]='\n'; // just in case something goes wrong...
607 size_t num_chars;
608 convertclass::status_t status;
609 text_t2ascii.convert(buffer, buffersize, num_chars, status);
610 // ignore status - assume it is "finished" as buffer is big enough
611 write(fd, buffer, num_chars);
612 GSDL_UNLOCK_FILE (fd);
613 close(fd);
614 delete []buffer;
615
616 // now that we've written the file we'll read it back again and
617 // update our bc1 arguments
618 ifstream cfg_in (cfgfilec);
619 if (cfg_in) {
620 text_tarray cfgline;
621 while (read_cfg_line(cfg_in, cfgline) >= 0) {
622 if (cfgline.size () >= 2) {
623 if (cfgline[0] == "creator") {
624 args["bc1contactemail"] = cfgline[1];
625 } else if (cfgline[0] == "collectionmeta") {
626 if (cfgline[1] == "collectionname") {
627 args["bc1fullname"] = cfgline[2];
628 } else if (cfgline[1] == "collectionextra") {
629 args["bc1aboutdesc"] = carriage_replace (cfgline[2], 1);
630 }
631 }
632 }
633 }
634 cfg_in.close();
635 } else {
636 logout << "collectoraction::update_cfgfile_complete: unable to open "
637 << cfgfilec << " for input\n";
638 message = "tmpfail";
639 }
640 }
641 } else {
642 logout << "collectoraction::update_cfgfile_complete: unable to open "
643 << cfgfilec << " for output\n";
644 message = "tmpfail";
645 }
646
647 delete []cfgfilec;
648}
649
650
651// return html for buttons used in collector bar
652// color may be "green", "grey", or "yellow"
653// type may be:
654// "info" --> "collection information" button
655// "srce" --> "source data" button
656// "conf" --> "configure collection" button
657// "bild" --> "build collection" button
658// "view" --> "view collection" button
659// if enabled is true button will be flashy rollover type and
660// will be hyperlinked
661
662// Wendy left a comment suggesting this be move, but where to
663// was not specified. Into wizardaction.cpp?
664
665// set the _fullnamemenu_ macro (and _warnindex_ and _selectedindex_ if
666// we're on the "srce" page)
667void collectoraction::set_fullnamemenu (displayclass &disp, cgiargsclass &args,
668 recptprotolistclass *protos, ostream &logout) {
669
670 if (recpt == NULL) {
671 logout << "ERROR (collectoraction::set_fullnamemenu): This action does not contain\n"
672 << " information about any receptionists. The method set_receptionist was\n"
673 << " probably not called from the module which instantiated this action.\n";
674 return;
675 }
676
677 text_t &current_page = args["p"];
678 text_t currentname = args[macro_prefix+"dirname"];
679 if (current_page == "srce") currentname = args[macro_prefix + "clonecol"];
680
681 text_tarray dirnames;
682 text_tarray fullnames;
683 vector<bool> write_protected;
684 bool is_selected = false;
685 int selected_index = 0;
686 int index = 0;
687
688 recptprotolistclass::iterator rprotolist_here = protos->begin();
689 recptprotolistclass::iterator rprotolist_end = protos->end();
690 while (rprotolist_here != rprotolist_end) {
691 if ((*rprotolist_here).p != NULL) {
692
693 // don't include z39.50 collections
694 comerror_t err = noError;
695 if ((*rprotolist_here).p->get_protocol_name (err) == "z3950proto") {
696 ++rprotolist_here;
697 continue;
698 }
699
700 text_tarray collist;
701 (*rprotolist_here).p->get_collection_list (collist, err, logout);
702 if (err == noError) {
703 text_tarray::iterator collist_here = collist.begin();
704 text_tarray::iterator collist_end = collist.end();
705 while (collist_here != collist_end) {
706 ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr ((*rprotolist_here).p, *collist_here, logout);
707 if (cinfo != NULL) {
708 text_t collectionname = cinfo->get_collectionmeta("collectionname", args["l"]);
709 if (collectionname.empty()) {
710 collectionname = *collist_here;
711 }
712 dirnames.push_back(*collist_here);
713 fullnames.push_back(collectionname);
714 // check to see if the collection is writable
715 if (collection_protected (*collist_here)) write_protected.push_back(true);
716 else write_protected.push_back(false);
717
718 if (*collist_here == currentname) {
719 is_selected = true;
720 selected_index = index;
721 }
722 ++index;
723 }
724 ++collist_here;
725 }
726 }
727 }
728 ++rprotolist_here;
729 }
730
731 bool first = true;
732
733 text_t warnindex;
734 text_t fullnamemenu = "<select name=\""+macro_prefix+"dirname\" onChange=\"menuchange();\">\n";
735
736 if (current_page == "srce") {
737 fullnamemenu = "<select name=\""+macro_prefix+"clonecol\" onChange=\"menuchange();\">\n";
738 fullnamemenu += "<option value=defaultstructure";
739 if (!is_selected) fullnamemenu += " selected>";
740 else fullnamemenu.push_back('>');
741 fullnamemenu += "_collector:textdefaultstructure_\n";
742 }
743
744 fullnamemenu += "<option value=\"\"></option>\n";
745
746 for (int i = 0; i < index; ++i) {
747 // don't want write protected collections in list on "change existing
748 // collection" page
749 if (write_protected[i] && current_page == "existing") continue;
750 fullnamemenu += "<option value=\"" + dirnames[i] + "\"";
751 if ((i == 0 && !is_selected && current_page != "srce") ||
752 (is_selected && i == selected_index)) {
753 fullnamemenu += " selected";
754 ++selected_index;
755 is_selected = false;
756 }
757 fullnamemenu.push_back ('>');
758 fullnamemenu += fullnames[i];
759 fullnamemenu.push_back ('\n');
760
761 // add to Warnindex if collection uses any dubious plugins
762 // (if creating clone collection list)
763 if (current_page == "srce") {
764 if (first) warnindex += "0,";
765 else warnindex.push_back(',');
766 if (uses_weird_plugin (dirnames[i])) {
767 warnindex += text_t (1);
768 } else {
769 warnindex += text_t (0);
770 }
771 }
772 first = false;
773 }
774 fullnamemenu += "</select>\n";
775 text_t action_name = get_action_name();
776 disp.setmacro ("fullnamemenu", action_name, fullnamemenu);
777 if (current_page == "srce") {
778 disp.setmacro ("warnindex",action_name , warnindex);
779 disp.setmacro ("selectedindex", action_name, text_t(selected_index));
780 }
781}
782
783
784// set _sourcelist_ and _badsources_ macros
785void collectoraction::set_inputsourceboxes (displayclass &disp, cgiargsclass &args,
786 ostream &logout) {
787
788 if (badsources) disp.setmacro ("badsources", "collector", "1");
789
790 text_t sourcelist = get_source_box(args["bc1input"], args["bc1inputnum"].getint(),
791 args["bc1inputtype"]);
792
793 disp.setmacro("sourcelist", "collector", sourcelist);
794
795 // reset badsources and failedsources variables
796 badsources = false;
797 failedsources.erase(failedsources.begin(), failedsources.end());
798}
799
800text_t collectoraction::get_source_box (text_t inputarglist, int numboxes,
801 text_t inputtypelist) {
802
803 text_tarray inputvalues;
804 splitchar (inputarglist.begin(), inputarglist.end(), ',', inputvalues);
805 // remove any empty values from the end of the array
806 if (inputvalues.size()) {
807 text_tarray::iterator l = inputvalues.end() - 1;
808 text_tarray::iterator b = inputvalues.begin();
809 while ((*l).empty() && l >= b) {
810 --l;
811 }
812 inputvalues.erase(l+1, inputvalues.end());
813 }
814
815 text_tarray inputtypes;
816 splitchar (inputtypelist.begin(), inputtypelist.end(), ',', inputtypes);
817
818 int numvalues = inputvalues.size();
819 int numtypes = inputtypes.size();
820
821 text_t last = "file://";
822 text_t rv;
823 for (int i = 0; i < numboxes; ++i) {
824 rv += "<nobr><select name=\"bc1inputtype\">\n";
825 rv += "<option value=\"file://\"";
826 if ((i < numtypes && inputtypes[i] == "file://") ||
827 (numboxes == 3 && i == 0 && numvalues == 0) ||
828 (i >= 3 && i >= numvalues && last == "file://")) {
829 rv += " selected";
830 last = "file://";
831 }
832 rv += ">file://\n";
833 rv += "<option value=\"http://\"";
834 if ((i < numtypes && inputtypes[i] == "http://") ||
835 (numboxes == 3 && i == 1 && numvalues == 0) ||
836 (i >= 3 && i >= numvalues && last == "http://")) {
837 rv += " selected";
838 last = "http://";
839 }
840 rv += ">http://\n";
841 rv += "<option value=\"ftp://\"";
842 if ((i < numtypes && inputtypes[i] == "ftp://") ||
843 (numboxes == 3 && i == 2 && numvalues == 0) ||
844 (i >= 3 && i >= numvalues && last == "ftp://")) {
845 rv += " selected";
846 last = "ftp://";
847 }
848 rv += ">ftp://\n";
849 rv += "</select>\n";
850 rv += "<input type=text name=\"bc1input\" value=\"";
851 if (i < numvalues) {
852 rv += dm_safe(decode_commas(inputvalues[i]));
853 }
854 rv += "\" size=50>";
855 if (badsources) {
856 if ((i < numvalues) && (!inputvalues[i].empty())) {
857 if (failedsources[decode_commas(inputvalues[i])] == "1") {
858 rv += "_iconcross_";
859 } else {
860 rv += "_icontick_";
861 }
862 } else {
863 rv += "_iconblank_";
864 }
865 }
866 if (i+1 == numboxes) {
867 if (!badsources) rv += "_iconblank_";
868 rv += "_imagemore_</nobr><br>";
869 } else {
870 rv += "</nobr><br>\n";
871 }
872 }
873
874 return rv;
875}
876
877// set the _cfgfile_ macro
878void collectoraction::set_cfgfile (displayclass &disp, cgiargsclass &args, ostream &logout) {
879
880 text_t &collection = args["bc1dirname"];
881 if (collection.empty()) {
882 message = "nocollection";
883 return;
884 }
885
886 // read in collect.cfg
887 text_t cfgfile = filename_cat(get_collectdir(args), collection, "etc", "collect.cfg");
888 char *cfgfilec = cfgfile.getcstr();
889
890#ifdef GSDL_USE_IOS_H
891 ifstream cfg_ifs (cfgfilec, ios::in | ios::nocreate);
892#else
893 ifstream cfg_ifs (cfgfilec, ios::in);
894#endif
895
896 if (cfg_ifs) {
897 // read in collect.cfg
898 text_t cfgtext;
899 char c;
900 cfg_ifs.get(c);
901 while (!cfg_ifs.eof ()) {
902 cfgtext.push_back(c);
903 cfg_ifs.get(c);
904 }
905 cfg_ifs.close();
906
907 // define it as a macro
908 disp.setmacro("cfgfile", "collector", dm_safe(cfgtext));
909
910 } else {
911 logout << "collectoraction::set_cfgfile: couldn't open configuration file ("
912 << cfgfilec << ") for reading\n";
913 message = "tmpfail";
914 }
915 delete []cfgfilec;
916}
917
918
919void collectoraction::define_internal_macros (displayclass &disp, cgiargsclass &args,
920 recptprotolistclass *protos, ostream &logout) {
921
922 // define_internal_macros sets the following macros:
923 // _collectorbar_
924 // _pagescriptextra_
925 // _fullnamemenu_ -- if displaying the "source data" page or the "changing existing
926 // collection" page
927 // _cfgfile_ -- if displaying the "configure collection" page
928 // _statusline_ -- if displaying the bildstatus page
929 // _header_ -- may be set for pages that require it
930 // _textfailmsg_ -- set to different messages depending on failcode returned
931 // by build script (if build fails)
932 // _faillog_ - set to last 6 lines of .bld file if build failed
933 // _gsdlhome_ - the gsdlhome path (dm_safe)
934 // _sourcelist_ -- "input source" text boxes
935 // _badsources_ -- will be set to "1" if we've come from the
936 // "source data" page and there's a problem
937 // with the input sources
938
939 text_t &collector_page = args["p"];
940 int esrce = args["bc1esrce"].getint();
941 int econf = args["bc1econf"].getint();
942
943 // set _pagescriptextra_ macro to _cpagescriptextra_
944 disp.setmacro ("pagescriptextra", "collector", "_" + collector_page + "scriptextra_");
945
946 if (collector_page == "bildstatus" || collector_page == "bilddone" ||
947 collector_page == "bildfail" || collector_page == "bildframe1") {
948 disp.setmacro ("header", "collector", "_" + collector_page + "header_");
949 }
950
951 // set the collectorbar macro
952 text_t collectorbar = "<table class=wizardbar border=0 cellspacing=4 cellpadding=0><tr>\n";
953
954 if (collector_page == "new") {
955 collectorbar += "<td>_icongreyarrow_</td>\n";
956 collectorbar += get_button (args,collector_page, "green", "info", true);
957 collectorbar += "<td>_icongreyarrow_</td>\n";
958 collectorbar += get_button (args,collector_page, "grey", "srce", false);
959 collectorbar += "<td>_icongreyarrow_</td>\n";
960 collectorbar += get_button (args,collector_page, "grey", "conf", false);
961 collectorbar += "<td>_icongreyarrow_</td>\n";
962 collectorbar += get_button (args,collector_page, "grey", "bild", false);
963 collectorbar += "<td>_icongreyarrow_</td>\n";
964 collectorbar += get_button (args,collector_page, "grey", "view", false);
965
966 } else if (collector_page == "info") {
967 collectorbar += "<td>_icongreyarrow_</td>\n";
968 collectorbar += get_button (args,collector_page, "yellow", "info", false);
969 collectorbar += "<td>_icongreyarrow_</td>\n";
970 collectorbar += get_button (args,collector_page, "green", "srce", true);
971 collectorbar += "<td>_icongreyarrow_</td>\n";
972 collectorbar += get_button (args,collector_page, "grey", "conf", false);
973 collectorbar += "<td>_icongreyarrow_</td>\n";
974 collectorbar += get_button (args,collector_page, "grey", "bild", false);
975 collectorbar += "<td>_icongreyarrow_</td>\n";
976 collectorbar += get_button (args,collector_page, "grey", "view", false);
977 collectorbar += "</tr><tr><td></td><td align=center>_icongreyuparrow_</td><td colspan=8></td>\n";
978
979 } else if (collector_page == "srce") {
980 collectorbar += "<td>_icongreyarrow_</td>\n";
981 if (esrce == 1) {
982 // if we came from the "change an existing collection" page previous button(s)
983 // are disabled
984 collectorbar += get_button (args,collector_page, "grey", "info", false);
985 } else {
986 collectorbar += get_button (args,collector_page, "yellow", "info", true);
987 }
988 collectorbar += "<td>_icongreyarrow_</td>\n";
989 collectorbar += get_button (args,collector_page, "yellow", "srce", false);
990 collectorbar += "<td>_icongreyarrow_</td>\n";
991 collectorbar += get_button (args,collector_page, "green", "conf", true);
992 collectorbar += "<td>_icongreyarrow_</td>\n";
993 collectorbar += get_button (args,collector_page, "green", "bild", true);
994 collectorbar += "<td>_icongreyarrow_</td>\n";
995 collectorbar += get_button (args,collector_page, "grey", "view", false);
996 collectorbar += "</tr><tr><td colspan=3></td><td align=center>_icongreyuparrow_</td><td colspan=6></td>\n";
997
998 } else if (collector_page == "conf") {
999 collectorbar += "<td>_icongreyarrow_</td>\n";
1000 // disable appropriate buttons if we came from "change an existing collection"
1001 // page
1002 if (esrce == 1 || econf == 1) {
1003 collectorbar += get_button (args,collector_page, "grey", "info", false);
1004 } else {
1005 collectorbar += get_button (args,collector_page, "yellow", "info", true);
1006 }
1007 collectorbar += "<td>_icongreyarrow_</td>\n";
1008 if (econf == 1) {
1009 collectorbar += get_button (args,collector_page, "grey", "srce", false);
1010 } else {
1011 collectorbar += get_button (args,collector_page, "yellow", "srce", true);
1012 }
1013 collectorbar += "<td>_icongreyarrow_</td>\n";
1014 collectorbar += get_button (args,collector_page, "yellow", "conf", false);
1015 collectorbar += "<td>_icongreyarrow_</td>\n";
1016 collectorbar += get_button (args,collector_page, "green", "bild", true);
1017 collectorbar += "<td>_icongreyarrow_</td>\n";
1018 collectorbar += get_button (args,collector_page, "grey", "view", false);
1019 collectorbar += "</tr><tr><td colspan=5></td><td align=center>_icongreyuparrow_</td><td colspan=4></td>\n";
1020
1021 } else if (collector_page == "bilddone") {
1022 collectorbar += "<td>_icongreyarrow_</td>\n";
1023 // all previous buttons grey after build was completed
1024 collectorbar += get_button (args,collector_page, "grey", "info", false);
1025 collectorbar += "<td>_icongreyarrow_</td>\n";
1026 collectorbar += get_button (args,collector_page, "grey", "srce", false);
1027 collectorbar += "<td>_icongreyarrow_</td>\n";
1028 collectorbar += get_button (args,collector_page, "grey", "conf", false);
1029 collectorbar += "<td>_icongreyarrow_</td>\n";
1030 collectorbar += get_button (args,collector_page, "yellow", "bild", false);
1031 collectorbar += "<td>_icongreyarrow_</td>\n";
1032 collectorbar += get_button (args,collector_page, "green", "view", true);
1033 collectorbar += "</tr><tr><td colspan=7></td><td align=center>_icongreyuparrow_</td><td colspan=2></td>\n";
1034
1035 } else if (collector_page == "bildcancel" || collector_page == "bildfail") {
1036 collectorbar += "<td>_icongreyarrow_</td>\n";
1037 // disable appropriate buttons if we came from "change an existing collection"
1038 // page
1039 if (esrce == 1 || econf == 1) {
1040 collectorbar += get_button (args,collector_page, "grey", "info", false);
1041 } else {
1042 collectorbar += get_button (args,collector_page, "yellow", "info", true);
1043 }
1044 collectorbar += "<td>_icongreyarrow_</td>\n";
1045 if (econf == 1) {
1046 collectorbar += get_button (args,collector_page, "grey", "srce", false);
1047 } else {
1048 collectorbar += get_button (args,collector_page, "yellow", "srce", true);
1049 }
1050 collectorbar += "<td>_icongreyarrow_</td>\n";
1051 collectorbar += get_button (args,collector_page, "yellow", "conf", true);
1052 collectorbar += "<td>_icongreyarrow_</td>\n";
1053 collectorbar += get_button (args,collector_page, "yellow", "bild", true);
1054 collectorbar += "<td>_icongreyarrow_</td>\n";
1055 collectorbar += get_button (args,collector_page, "grey", "view", false);
1056 }
1057
1058 collectorbar += "</tr></table>\n";
1059 disp.setmacro ("collectorbar", "collector", collectorbar);
1060
1061 if (collector_page == "bildfail") {
1062
1063 text_t textfailmsg = "_textfailmsg";
1064 textfailmsg.push_back(failcode);
1065 textfailmsg.push_back('_');
1066 disp.setmacro("textfailmsg", "collector", textfailmsg);
1067
1068 text_t bldlog = filename_cat(gsdlhome, "tmp", args["bc1tmp"], args["bc1dirname"] + ".bld");
1069 text_t rawlog = file_tail (bldlog, 6, 0);
1070 // we'll shove in some <br> tags where \n's occur
1071 text_t faillog;
1072 text_t::const_iterator here = rawlog.begin();
1073 text_t::const_iterator end = rawlog.end();
1074 while (here != end) {
1075 if (*here == '\n') faillog += "<br>";
1076 faillog.push_back (*here);
1077 ++here;
1078 }
1079 disp.setmacro ("faillog", "collector", dm_safe(faillog));
1080 }
1081
1082 if (collector_page == "srce" || collector_page == "existing")
1083 set_fullnamemenu (disp, args, protos, logout);
1084 if (collector_page == "conf")
1085 set_cfgfile (disp, args, logout);
1086 if (collector_page == "bildstatus")
1087 set_statusline (disp, args, logout);
1088 if (collector_page == "srce") {
1089 set_inputsourceboxes (disp, args, logout);
1090 }
1091
1092 disp.setmacro ("gsdlhome", "collector", dm_safe(gsdlhome));
1093}
1094
1095
1096bool collectoraction::do_action (cgiargsclass &args, recptprotolistclass * /*protos*/,
1097 browsermapclass * /*browsers*/, displayclass &disp,
1098 outconvertclass &outconvert, ostream &textout,
1099 ostream &logout) {
1100
1101 // make sure the collector is enabled
1102 if (disabled) {
1103 textout << outconvert
1104 << "<html>\n"
1105 << "<head>\n"
1106 << "<title>Collector disabled</title>\n"
1107 << "</head>\n"
1108 << "<body bgcolor=\"#ffffff\" text=\"#000000\" link=\"#006666\" "
1109 << "alink=\"#cc9900\" vlink=\"#666633\">\n"
1110 << "<h2>Facility disabled</h2>\n"
1111 << "Sorry, the Collector end-user collection building facility is currently disabled\n"
1112 << "\n</body>\n"
1113 << "</html>\n";
1114 return true;
1115 }
1116
1117 text_t &collector_page = args["p"];
1118 text_t &collection = args["bc1dirname"];
1119
1120 // make sure we have perl (we won't bother with this check for the
1121 // building status pages to avoid slowing things down unneccessarily)
1122 if (collector_page != "bildstatus" && collector_page != "bildframe1" && !perl_ok(logout)) {
1123 textout << outconvert
1124 << "<html>\n"
1125 << "<head>\n"
1126 << "<title>Perl not found</title>\n"
1127 << "</head>\n"
1128 << "<body bgcolor=\"#ffffff\" text=\"#000000\" link=\"#006666\" "
1129 << "alink=\"#cc9900\" vlink=\"#666633\">\n"
1130 << "<h2>Perl not found</h2>\n"
1131 << "Greenstone could not detect perl on this system. It is therefore not\n"
1132 << "possible to build a Greenstone collection, either from the Collector or the \n"
1133 << "command-line tools, or to use the Collector for any other task.\n"
1134 << "<p>Please refer to the Greenstone Installer's Guide for details on\n"
1135 << "installing perl on your system.\n"
1136 << "\n</body>\n"
1137 << "</html>\n";
1138 return true;
1139
1140 }
1141
1142 if (collector_page == "bild") {
1143 // do the work (download, import, build)
1144 gsdl_build (args, logout);
1145
1146 if (message.empty()) {
1147 // bild page is a frameset so we don't want headers and stuff
1148 textout << outconvert << disp << ("_collector:bildcontent_\n");
1149 }
1150 }
1151
1152 if (do_mkcol == true) {
1153 // execute mkcol.pl (do_mkcol is set from within check_cgiargs)
1154 gsdl_mkcol (args, logout);
1155 do_mkcol = false; // reset for fast-cgi
1156 }
1157
1158 if (args["bc1dodelete"] == "1") {
1159 // delete bcidirname collection
1160 if (collection_protected (collection)) {
1161 message = "delinvalid";
1162
1163 } else {
1164
1165 const recptconf &rcinfo = recpt->get_configinfo ();
1166 bool emailuserevents = rcinfo.EmailUserEvents;
1167
1168 // get collection maintainer email from collect.cfg before we
1169 // delete it
1170 text_t colmaintainer;
1171 text_t cfgfile = filename_cat(gsdlhome, "collect", collection, "etc", "collect.cfg");
1172 char *cfgfilec = cfgfile.getcstr();
1173 ifstream cfg_in (cfgfilec);
1174 delete []cfgfilec;
1175 if (cfg_in) {
1176 text_tarray cfgline;
1177 while (read_cfg_line(cfg_in, cfgline) >= 0) {
1178 if (cfgline.size () == 2 && cfgline[0] == "maintainer") {
1179 colmaintainer = cfgline[1];
1180 break;
1181 }
1182 }
1183 cfg_in.close();
1184 }
1185 if (colmaintainer.empty()) {
1186 logout << outconvert
1187 << "collectoraction::do_action WARNING: Collection being deleted ("
1188 << collection << ") has no maintainer address. EmailUserEvents "
1189 << "disabled\n";
1190 emailuserevents = false;
1191 }
1192
1193 // first we need to free up the collection's collection server
1194 // we must do this for the local library (and I guess when using
1195 // fastcgi too) as you can't delete the gdbm file while it's
1196 // being kept open by the collection server
1197 remove_colservr (collection, logout);
1198
1199 text_t delete_cmd = "perl -S delcol.pl -f " + collection;
1200 int rv = gsdl_system (delete_cmd, true, logout);
1201 if (rv != 0) {
1202 // deletion failed -- permissions?
1203 message = "delpermission";
1204 } else {
1205 message = "delsuccess";
1206 }
1207
1208 // log the event
1209 if (rcinfo.LogEvents == CollectorEvents || rcinfo.LogEvents == AllEvents) {
1210
1211 text_t eventlog = filename_cat (gsdlhome, "etc", "events.txt");
1212 char *eventlogt = eventlog.getcstr();
1213 ofstream eventl (eventlogt, ios::app);
1214 delete []eventlogt;
1215
1216 if (eventl) {
1217 eventl << outconvert << "[Collector Event]\n"
1218 << "Date: " << get_date (true) << "\n"
1219 << "Greenstone Username: " << args["un"] << "\n"
1220 << "Collection: " << collection << "\n"
1221 << "Collection Maintainer: " << colmaintainer << "\n"
1222 << "GSDLHOME: " << gsdlhome << "\n";
1223
1224 if (message == "delsuccess") {
1225 eventl << outconvert
1226 << "The " << collection << " collection was successfully deleted\n\n";
1227 } else {
1228 eventl << outconvert
1229 << "Attempt to delete the " << collection << " collection failed\n\n";
1230 }
1231 eventl.close();
1232
1233 } else {
1234 logout << outconvert << "collectoraction::do_action ERROR: Couldn't open "
1235 << "event log file " << eventlog << " for appending during collection "
1236 << "deletion. LogEvents disabled\n";
1237 }
1238 }
1239
1240 if (rcinfo.EmailEvents == CollectorEvents || rcinfo.EmailEvents == AllEvents || emailuserevents) {
1241 // use sendmail.pl perl script to send email events
1242 text_t tmpmailfile = filename_cat (gsdlhome, "tmp", args["bc1tmp"], "event.txt");
1243 char *tmpmailfilec = tmpmailfile.getcstr();
1244 ofstream tmpfile (tmpmailfilec);
1245 delete []tmpmailfilec;
1246 if (tmpfile) {
1247 tmpfile << outconvert << "[Collector Event]\n"
1248 << "Date: " << get_date (true) << "\n"
1249 << "Greenstone Username: " << args["un"] << "\n"
1250 << "Collection: " << collection << "\n"
1251 << "Collection Maintainer: " << colmaintainer << "\n"
1252 << "GSDLHOME: " << gsdlhome << "\n";
1253 if (message == "delsuccess") {
1254 tmpfile << outconvert
1255 << "The " << collection << " collection was successfully deleted\n\n";
1256 } else {
1257 tmpfile << outconvert
1258 << "Attempt to delete the " << collection << " collection failed\n\n";
1259 }
1260 tmpfile.close();
1261 text_t to;
1262 if (rcinfo.EmailEvents == CollectorEvents || rcinfo.EmailEvents == AllEvents) to += rcinfo.maintainer;
1263 if (emailuserevents) {
1264 if (!to.empty()) to.push_back (',');
1265 to += colmaintainer;
1266 }
1267 text_t sendmail_cmd = "perl -S sendmail.pl -to \"" + to + "\" -from \"" + rcinfo.maintainer;
1268 sendmail_cmd += "\" -smtp \"" + rcinfo.MailServer + "\" -subject \"Greenstone Collector Event\"";
1269 sendmail_cmd += " -msgfile \"" + tmpmailfile + "\"";
1270
1271 gsdl_system (sendmail_cmd, false, logout);
1272
1273 } else {
1274 logout << outconvert << "collectoraction::do_action ERROR: Couldn't open "
1275 << "temporary event log file " << tmpmailfile << " during collection "
1276 << "deletion. EmailEvents and EmailUserEvents disabled\n";
1277 }
1278 }
1279 }
1280 }
1281
1282 if (collector_page == "bildcancel" || collector_page == "bildfail") {
1283 // cancel the build (we'll also use the cancel_build script to tidy
1284 // up if the build failed)
1285 gsdl_cancel_build (args, logout);
1286 }
1287
1288 if (collector_page == "expt") {
1289
1290 // export the collection - we'll do a synchronous system call to
1291 // exportcol.pl as that's the easiest way to do it. if it becomes a
1292 // problem that it's taking too long to export a large collection then
1293 // we may have to revisit this.
1294 text_t tmpfile = filename_cat (gsdlhome, "tmp", collection + "_export.txt");
1295 text_t export_cmd = "perl -S exportcol.pl -out \"" + tmpfile + "\" " + collection;
1296 gsdl_system (export_cmd, true, logout);
1297 if (file_exists (tmpfile)) {
1298 text_t returnline = file_tail (tmpfile, 1, 0);
1299 if (returnline.size() > 23 && (substr(returnline.begin(), returnline.begin()+23) == "exportcol.pl succeeded:")) {
1300 // success
1301 message = "exptsuccess";
1302 } else {
1303 message = "exptfail";
1304 }
1305 } else {
1306 message = "exptfail";
1307 }
1308 }
1309
1310 if (message.empty()) {
1311 if (collector_page != "bild") {
1312 // output page ("bild" page was already output above)
1313 textout << outconvert << disp << ("_collector:header_\n")
1314 << ("_collector:" + collector_page + "content_\n")
1315 << ("_collector:footer_\n");
1316 }
1317 } else {
1318 // message was set somewhere (probably an error), output message page
1319 textout << outconvert << disp << ("_collector:header_\n")
1320 << ("_collector:" + message + "content_\n")
1321 << ("_collector:footer_\n");
1322 message.clear();
1323 }
1324 return true;
1325}
1326
1327void collectoraction::gsdl_mkcol (cgiargsclass &args, ostream &logout) {
1328
1329 text_t tmpdir = filename_cat (gsdlhome, "tmp", args["bc1tmp"]);
1330 if (!directory_exists (tmpdir)) {
1331 message = "tmpfail";
1332 cerr << "WE CANNOT CREATE THE DIRECTORY!!! " << endl;
1333 return;
1334 }
1335
1336 text_t &collection = args["bc1dirname"];
1337 if (collection.empty()) {
1338 message = "nocollection";
1339 return;
1340 }
1341
1342 // check for a .create file - if it exists then we've already created the collection
1343 text_t createfile = filename_cat (tmpdir, ".create");
1344 if (file_exists (createfile)) {
1345 return;
1346 }
1347
1348 // set up options
1349 text_t options = "-quiet -creator \"" + args["bc1contactemail"] + "\"";
1350 options += " -title \"" + args["bc1fullname"] + "\"";
1351 options += " -about \"" + carriage_replace (args["bc1aboutdesc"] + "_collectorextra_", 0) + "\"";
1352 options += " -collectdir \"" + remove_trailing_slashes(tmpdir) + "\" ";
1353
1354 text_t optionfile = filename_cat (tmpdir, "mkcol.opt");
1355 char *optionfilec = optionfile.getcstr();
1356 ofstream ofile_out (optionfilec);
1357 delete []optionfilec;
1358 if (!ofile_out) {
1359 message = "tmpfail";
1360 return;
1361 }
1362 outconvertclass text_t2ascii;
1363 ofile_out << text_t2ascii << options << "\n";
1364 ofile_out.close();
1365
1366 // run mkcol.pl
1367 text_t mkcol_cmd = "perl -S mkcol.pl -optionfile \"" + optionfile;
1368 mkcol_cmd += "\" " + collection;
1369
1370
1371 gsdl_system (mkcol_cmd, true, logout);
1372
1373 // make sure it went ok
1374 text_t cfgfile = filename_cat (tmpdir, collection, "etc", "collect.cfg");
1375 if (!file_writable (cfgfile)) {
1376 message = "mkcolfail";
1377 } else {
1378 // create the .create file (this file is just a place holder to let any future
1379 // pages know that the collection already exists).
1380 char *createfilec = createfile.getcstr();
1381 ofstream cfile_out (createfilec);
1382 delete []createfilec;
1383 if (cfile_out) {
1384 cfile_out << "collection created\n";
1385 cfile_out.close();
1386 } else {
1387 message = "tmpfail";
1388 return;
1389 }
1390 }
1391}
1392
1393
1394bool collectoraction::check_sources (cgiargsclass &args, ostream &logout) {
1395
1396 bool found = false;
1397
1398 text_tarray inputvalues;
1399 splitchar (args["bc1input"].begin(), args["bc1input"].end(), ',', inputvalues);
1400
1401 text_tarray inputtypes;
1402 splitchar (args["bc1inputtype"].begin(), args["bc1inputtype"].end(), ',', inputtypes);
1403
1404 int numvalues = inputvalues.size();
1405 int numtypes = inputtypes.size();
1406
1407 for (int i = 0; i < numvalues; ++i) {
1408 text_t value = format_url(decode_commas(inputvalues[i]));
1409 text_t type = "file://"; // default
1410 if (!value.empty()) {
1411 found = true;
1412 if (i >= numtypes || inputtypes[i].empty()) {
1413 logout << "collectoraction::check_sources: WARNING type not set\n";
1414 } else {
1415 type = inputtypes[i];
1416 }
1417 if (type == "file://") {
1418 if (!file_exists(value) && !directory_exists(value)) {
1419 failedsources[decode_commas(inputvalues[i])] = "1";
1420 badsources = true;
1421 }
1422 } else if (type == "http://") {
1423 if (gsdl_system ("perl -S ping.pl -quiet http://" + value, true, logout)) {
1424 failedsources[decode_commas(inputvalues[i])] = "1";
1425 badsources = true;
1426 }
1427 } else if (type == "ftp://") {
1428 if (gsdl_system ("perl -S ping.pl -quiet ftp://" + value, true, logout)) {
1429 failedsources[decode_commas(inputvalues[i])] = "1";
1430 badsources = true;
1431 }
1432 }
1433 }
1434 }
1435
1436 // set badsources if there weren't any sources at all
1437 if (!found) badsources = true;
1438
1439 if (badsources) return false;
1440 return true;
1441}
1442
1443text_t collectoraction::get_button(cgiargsclass &args, const text_t &thispage,
1444 const text_t &color,
1445 const text_t &type, bool enabled)
1446{
1447
1448 if ((color != "green" && color != "grey" && color != "yellow") ||
1449 (type != "info" && type != "srce" && type != "conf" && type != "bild" && type != "view"))
1450 return g_EmptyText;
1451
1452 text_t href = "_http"+type+"_";
1453 text_t target = "";
1454
1455 if (thispage == "info" || thispage == "srce" || thispage == "conf" ||
1456 thispage == "bildcancel" || thispage == "bildfail") {
1457 // call the check submit macro instead of linking directly to the page
1458 href="\"javascript:check_submit('"+type+"');\"";
1459 } else if (type == "view") {
1460 // view button is special case as it needs a target=_top
1461 target = " target=_top";
1462 }
1463
1464 text_t tdclass = "wizardbar"+color;
1465 if (enabled) {
1466 // link to the appropriate page
1467 return "<td class="+tdclass+"><a href="+href+target+">_text"+type+"_</a></td>";
1468 }
1469 else {
1470 // just display the text
1471 return "<td class="+tdclass+">_text"+type+"_</td>";
1472 }
1473}
1474
1475#endif //GSDL_USE_COLLECTOR_ACTION
Note: See TracBrowser for help on using the repository browser.