source: main/trunk/greenstone2/runtime-src/src/recpt/collectoraction.cpp@ 21758

Last change on this file since 21758 was 19821, checked in by mdewsnip, 15 years ago

Commented out all occurrences of

#define _XOPEN_SOURCE_EXTENDED 1

This was allegedly added for compilation on Solaris, but it just causes errors for me (on the NLNZ Solaris machines).

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