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

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