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

Last change on this file since 1507 was 1507, checked in by sjboddie, 24 years ago

More minor changes to the collector

  • Property svn:keywords set to Author Date Id Revision
File size: 45.4 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// note that the collectoraction relies on having direct access to a
27// collections configuration file. this breaks the separation between
28// receptionist and collection server and so is not suitable (at least
29// in its current form) for use when collection servers are separate
30// from the receptionist (e.g. when using the CORBA protocol).
31
32#include "collectoraction.h"
33#include "OIDtools.h"
34#include "fileutil.h"
35#include "cfgread.h"
36#include "gsdltools.h"
37
38#if !defined (__WIN32__)
39#include <sys/utsname.h>
40#include <unistd.h>
41#endif
42
43collectoraction::collectoraction () {
44
45 recpt = NULL;
46 do_mkcol = false;
47
48 cgiarginfo arg_ainfo;
49 arg_ainfo.shortname = "a";
50 arg_ainfo.longname = "action";
51 arg_ainfo.multiplechar = true;
52 arg_ainfo.defaultstatus = cgiarginfo::weak;
53 arg_ainfo.argdefault = "collector";
54 arg_ainfo.savedarginfo = cgiarginfo::must;
55 argsinfo.addarginfo (NULL, arg_ainfo);
56
57 arg_ainfo.shortname = "cp";
58 arg_ainfo.longname = "collector page";
59 arg_ainfo.multiplechar = true;
60 arg_ainfo.defaultstatus = cgiarginfo::weak;
61 arg_ainfo.argdefault = "intro";
62 arg_ainfo.savedarginfo = cgiarginfo::must;
63 argsinfo.addarginfo (NULL, arg_ainfo);
64
65 // temporary directory name for this collector
66 // session
67 arg_ainfo.shortname = "bc1tmp";
68 arg_ainfo.longname = "collector specific";
69 arg_ainfo.multiplechar = true;
70 arg_ainfo.defaultstatus = cgiarginfo::weak;
71 arg_ainfo.argdefault = "";
72 arg_ainfo.savedarginfo = cgiarginfo::must;
73 argsinfo.addarginfo (NULL, arg_ainfo);
74
75 arg_ainfo.shortname = "bc1fullname";
76 arg_ainfo.longname = "collector specific";
77 arg_ainfo.multiplechar = true;
78 arg_ainfo.defaultstatus = cgiarginfo::weak;
79 arg_ainfo.argdefault = "";
80 arg_ainfo.savedarginfo = cgiarginfo::must;
81 argsinfo.addarginfo (NULL, arg_ainfo);
82
83 arg_ainfo.shortname = "bc1dirname";
84 arg_ainfo.longname = "collector specific";
85 arg_ainfo.multiplechar = true;
86 arg_ainfo.defaultstatus = cgiarginfo::weak;
87 arg_ainfo.argdefault = "";
88 arg_ainfo.savedarginfo = cgiarginfo::must;
89 argsinfo.addarginfo (NULL, arg_ainfo);
90
91 arg_ainfo.shortname = "bc1contactemail";
92 arg_ainfo.longname = "collector specific";
93 arg_ainfo.multiplechar = true;
94 arg_ainfo.defaultstatus = cgiarginfo::weak;
95 arg_ainfo.argdefault = "";
96 arg_ainfo.savedarginfo = cgiarginfo::must;
97 argsinfo.addarginfo (NULL, arg_ainfo);
98
99 arg_ainfo.shortname = "bc1aboutdesc";
100 arg_ainfo.longname = "collector specific";
101 arg_ainfo.multiplechar = true;
102 arg_ainfo.defaultstatus = cgiarginfo::weak;
103 arg_ainfo.argdefault = "";
104 arg_ainfo.savedarginfo = cgiarginfo::must;
105 argsinfo.addarginfo (NULL, arg_ainfo);
106
107 arg_ainfo.shortname = "bc1clone";
108 arg_ainfo.longname = "collector specific";
109 arg_ainfo.multiplechar = false;
110 arg_ainfo.defaultstatus = cgiarginfo::weak;
111 arg_ainfo.argdefault = "0";
112 arg_ainfo.savedarginfo = cgiarginfo::must;
113 argsinfo.addarginfo (NULL, arg_ainfo);
114
115 arg_ainfo.shortname = "bc1clonecol";
116 arg_ainfo.longname = "collector specific";
117 arg_ainfo.multiplechar = true;
118 arg_ainfo.defaultstatus = cgiarginfo::weak;
119 arg_ainfo.argdefault = "";
120 arg_ainfo.savedarginfo = cgiarginfo::must;
121 argsinfo.addarginfo (NULL, arg_ainfo);
122
123 // set when cloning option has changed
124 arg_ainfo.shortname = "bc1clonechanged";
125 arg_ainfo.longname = "collector specific";
126 arg_ainfo.multiplechar = false;
127 arg_ainfo.defaultstatus = cgiarginfo::weak;
128 arg_ainfo.argdefault = "0";
129 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
130 argsinfo.addarginfo (NULL, arg_ainfo);
131
132 arg_ainfo.shortname = "bc1inputdir1";
133 arg_ainfo.longname = "collector specific";
134 arg_ainfo.multiplechar = true;
135 arg_ainfo.defaultstatus = cgiarginfo::weak;
136 arg_ainfo.argdefault = "";
137 arg_ainfo.savedarginfo = cgiarginfo::must;
138 argsinfo.addarginfo (NULL, arg_ainfo);
139
140 arg_ainfo.shortname = "bc1inputdir2";
141 arg_ainfo.longname = "collector specific";
142 arg_ainfo.multiplechar = true;
143 arg_ainfo.defaultstatus = cgiarginfo::weak;
144 arg_ainfo.argdefault = "";
145 arg_ainfo.savedarginfo = cgiarginfo::must;
146 argsinfo.addarginfo (NULL, arg_ainfo);
147
148 arg_ainfo.shortname = "bc1inputdir3";
149 arg_ainfo.longname = "collector specific";
150 arg_ainfo.multiplechar = true;
151 arg_ainfo.defaultstatus = cgiarginfo::weak;
152 arg_ainfo.argdefault = "";
153 arg_ainfo.savedarginfo = cgiarginfo::must;
154 argsinfo.addarginfo (NULL, arg_ainfo);
155
156 arg_ainfo.shortname = "bc1inputdir4";
157 arg_ainfo.longname = "collector specific";
158 arg_ainfo.multiplechar = true;
159 arg_ainfo.defaultstatus = cgiarginfo::weak;
160 arg_ainfo.argdefault = "";
161 arg_ainfo.savedarginfo = cgiarginfo::must;
162 argsinfo.addarginfo (NULL, arg_ainfo);
163
164 // only set when one of the fields was changed in
165 // the "collection info" page
166 arg_ainfo.shortname = "bc1infochanged";
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);
173
174 // only set when cfg file is altered from within
175 // "configure collection" page
176 arg_ainfo.shortname = "bc1cfgchanged";
177 arg_ainfo.longname = "collector specific";
178 arg_ainfo.multiplechar = false;
179 arg_ainfo.defaultstatus = cgiarginfo::weak;
180 arg_ainfo.argdefault = "0";
181 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
182 argsinfo.addarginfo (NULL, arg_ainfo);
183
184 arg_ainfo.shortname = "bc1dodelete";
185 arg_ainfo.longname = "collector specific";
186 arg_ainfo.multiplechar = false;
187 arg_ainfo.defaultstatus = cgiarginfo::weak;
188 arg_ainfo.argdefault = "0";
189 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
190 argsinfo.addarginfo (NULL, arg_ainfo);
191
192 // will be set if we arrived at the "configure collection" page
193 // via the "changing an existing collection" page
194 arg_ainfo.shortname = "bc1econf";
195 arg_ainfo.longname = "collector specific";
196 arg_ainfo.multiplechar = false;
197 arg_ainfo.defaultstatus = cgiarginfo::weak;
198 arg_ainfo.argdefault = "0";
199 arg_ainfo.savedarginfo = cgiarginfo::must;
200 argsinfo.addarginfo (NULL, arg_ainfo);
201
202 // will be set if we arrived at the "source data" page
203 // via the "changing an existing collection" page
204 arg_ainfo.shortname = "bc1esrce";
205 arg_ainfo.longname = "collector specific";
206 arg_ainfo.multiplechar = false;
207 arg_ainfo.defaultstatus = cgiarginfo::weak;
208 arg_ainfo.argdefault = "0";
209 arg_ainfo.savedarginfo = cgiarginfo::must;
210 argsinfo.addarginfo (NULL, arg_ainfo);
211}
212
213collectoraction::~collectoraction () {
214 delete gsdlosc;
215 delete gsdlhomec;
216}
217
218bool collectoraction::init (ostream & /*logout*/) {
219
220 // set up GSDLOS and GSDLHOME environment variables
221 text_t gsdlos;
222#if defined (__WIN32__)
223 gsdlos = "windows";
224#else
225 utsname *buf = new utsname();
226 int i = uname (buf);
227 if (i == -1) gsdlos = "linux"; // uname failed
228 else gsdlos.setcstr (buf->sysname);
229 delete buf;
230 lc (gsdlos);
231#endif
232
233 gsdlos = "GSDLOS=" + gsdlos;
234 text_t setgsdlhome = "GSDLHOME=" + gsdlhome;
235
236 // these will be cleaned up in the destructor
237 gsdlosc = gsdlos.getcstr();
238 gsdlhomec = setgsdlhome.getcstr();
239
240 putenv (gsdlosc);
241 putenv (gsdlhomec);
242
243 return true;
244}
245
246bool collectoraction::check_cgiargs (cgiargsinfoclass &/*argsinfo*/, cgiargsclass &args,
247 ostream &logout) {
248
249 text_t &current_page = args["cp"];
250
251 // note that the "bildstatus" and "bildframe1" pages don't actually do anything
252 // functional so we don't need to worry about authenticating them (it's the
253 // underlying "bild" page that does the building (and creates the frameset))
254 // This helps us overcome a bit of a problem we have with multiple pages trying
255 // to read from the key.db database at the same time.
256 if (current_page != "intro" && current_page != "bildstatus" && current_page != "bildframe1") {
257 // authenticate the user if authentication is available
258 args["uan"] = 1;
259 args["ug"] = "colbuilder";
260 }
261
262 if (current_page == "new" || current_page == "existing") {
263
264 // assign (and create) a temporary directory
265 assign_tmpname (args, logout);
266
267 // clean up any old builds left laying about in the tmp directory
268 // (note that it's possible this could take some time if there's a huge
269 // partially built collection laying about -- may need to think about doing
270 // this in the background).
271 text_t cleantmp_cmd = "perl " + filename_cat (gsdlhome, "bin", "script", "cleantmp.pl");
272 char *cleantmp_cmdc = cleantmp_cmd.getcstr();
273 system (cleantmp_cmdc);
274 delete cleantmp_cmdc;
275 }
276
277 if (args["bc1infochanged"] == "1") {
278
279 if (args["bc1dirname"].empty()) {
280 // we've just come from the "collection information" page for the
281 // first time so we'll need to create the collection with mkcol.pl
282 // and set up bc1dirname - we do this part here instead of in do_action
283 // because the bc1dirname argument must be set to its new value before
284 // the compressedoptions macros are set.
285 args["bc1dirname"] = get_directory_name (args["bc1fullname"]);
286
287 text_t createfile = filename_cat (gsdlhome, "tmp", args["bc1tmp"], ".create");
288 if (!file_exists (createfile)) {
289 // we could do the mkcol.pl here but I guess it's nicer to do it in do_action()
290 do_mkcol = true;
291 } else {
292 // .create file already exists but bc1dirname wasn't set ... this should only be
293 // able to occur when the "reload" (and possibly the "back" and "forward" buttons)
294 // have been used to get us here.
295 // we'll check that the bc1dirname directory exists (in case of the unlikely
296 // possibility that get_directory_name returned a different value this time
297 // than it did originally).
298 text_t coldir = filename_cat (get_collectdir(args), args["bc1dirname"]);
299 if (!directory_exists (coldir)) {
300 message = "reloaderror";
301 return true;
302 }
303 }
304 } else {
305 // "collection information" has been changed after collection already exists
306 // so we'll need to update the cfg file.
307 update_cfgfile_partial (args, logout);
308 }
309 }
310
311 if (args["bc1cfgchanged"] == "1") {
312 // configuration file has been changed from the "configure collection"
313 // page. we need to update the file on disk and catch bc1 arguments up
314 // with changes.
315 update_cfgfile_complete (args, logout);
316 }
317
318 if (args["bc1clonechanged"] == "1") {
319 // cloning option has been changed on "source data" page. if it was turned
320 // on we want to create a new collect.cfg file using the bc1clonecol cfg file
321 // as a model (we'll save the old file as collect.cfg.org). if cloning was
322 // turned off we'll revert to using the collect.cfg.org file (which will need
323 // updating in case the bc1 arguments have been altered since cloning was
324 // turned on).
325 update_cfgfile_clone (args, logout);
326
327 // if cloning has just been turned on we'll also copy the rest of the files
328 // (excluding collect.cfg which we've already done) from the cloned collections
329 // etc directory to the new collection.
330 if (args["bc1clone"] == "1") {
331 text_t clone_etc = filename_cat(gsdlhome, "collect", args["bc1clonecol"], "etc");
332 text_t new_etc = filename_cat(get_collectdir(args), args["bc1dirname"], "etc");
333 text_tarray files;
334
335 if (read_dir (clone_etc, files)) {
336 text_tarray::const_iterator here = files.begin();
337 text_tarray::const_iterator end = files.end();
338 while (here != end) {
339 if (*here != "collect.cfg" && *here != "collect.cfg.org") {
340 file_copy (filename_cat(clone_etc, *here), filename_cat(new_etc, *here));
341 }
342 here ++;
343 }
344 } else {
345 outconvertclass text_t2ascii;
346 logout <<text_t2ascii << "collectoraction::check_cgiargs couldn't read from "
347 << clone_etc << " directory\n";
348 }
349 }
350 }
351
352 if (current_page == "bildstatus" || current_page == "bildcancel") {
353 // if .final file exists then build has finished
354 text_t fbld = filename_cat (gsdlhome, "tmp", args["bc1tmp"], args["bc1dirname"] + ".bld.final");
355 if (file_exists (fbld)) {
356 char *fbldc = fbld.getcstr();
357 ifstream fbld_in (fbldc);
358 if (fbld_in) {
359 char c = fbld_in.get();
360 fbld_in.close();
361 if (c == '0') current_page = "bilddone";
362 else if (c == '4' || c == '5') message = "installfail";
363 else current_page = "bildfail";
364 } else {
365 // assume build failed (we shouldn't get here though ... right?)
366 current_page = "bildfail";
367 }
368 delete fbldc;
369 }
370 }
371
372 return true;
373}
374
375void collectoraction::update_cfgfile_clone (cgiargsclass &args, ostream &logout) {
376
377 text_t tmpdir = filename_cat(gsdlhome, "tmp", args["bc1tmp"]);
378 text_t cfgfile = filename_cat(tmpdir, args["bc1dirname"], "etc", "collect.cfg");
379 if (!file_exists (cfgfile)) {
380 message = "tmpfail";
381 return;
382 }
383
384 text_t cfgfile_org = filename_cat (tmpdir, "collect.cfg.org");
385
386 if (args["bc1clone"] == "1") {
387 // cloning was turned on
388
389 text_t cfgfile_clone = filename_cat(gsdlhome, "collect", args["bc1clonecol"], "etc", "collect.cfg");
390 if (file_exists (cfgfile_clone)) {
391 // if .org file doesn't exist already create it
392 if (!file_exists (cfgfile_org)) {
393 if (!file_copy (cfgfile, cfgfile_org)) {
394 message = "tmpfail";
395 return;
396 }
397 }
398 // copy clone collections cfg file to new collection
399 if (!file_copy (cfgfile_clone, cfgfile)) {
400 message = "tmpfail";
401 return;
402 }
403 // update the new cfg file
404 update_cfgfile_partial (args, logout);
405
406 } else {
407 // can't clone non-existant or read-protected collection
408 message = "clonefail";
409 }
410
411 } else {
412 // cloning has been turned off having been on at some point. the .org file
413 // should exist, if it doesn't we'll bail out and leave the user with the
414 // cloned copy
415 if (file_exists (cfgfile_org)) {
416 // copy original back again and update it with any recent changes
417 if (file_copy (cfgfile_org, cfgfile)) {
418 update_cfgfile_partial (args, logout);
419 } else {
420 message = "tmpfail";
421 }
422 }
423 }
424}
425
426// update configuration file on disk to match bc1 arguments
427void collectoraction::update_cfgfile_partial (cgiargsclass &args, ostream &logout) {
428
429 text_t cfgfile = filename_cat(get_collectdir(args), args["bc1dirname"], "etc", "collect.cfg");
430 char *cfgfilec = cfgfile.getcstr();
431
432 vector<text_tarray> cfgarray;
433
434 // read in cfg file
435 ifstream cfg_in (cfgfilec);
436 if (cfg_in) {
437 text_tarray cfgline;
438 while (read_cfg_line(cfg_in, cfgline) >= 0) {
439 if (cfgline.size () >= 2) {
440 if (cfgline[0] == "creator" || cfgline[0] == "maintainer") {
441 cfgline[1] = args["bc1contactemail"];
442 } else if (cfgline[0] == "collectionmeta") {
443 if (cfgline[1] == "collectionname") {
444 cfgline[2] = args["bc1fullname"];
445 } else if (cfgline[1] == "collectionextra") {
446 cfgline[2] = carriage_replace (args["bc1aboutdesc"], 0);
447 }
448 }
449 }
450 cfgarray.push_back (cfgline);
451 }
452 cfg_in.close();
453
454 // now write cfg file back out
455#ifdef __WIN32__
456 ofstream cfg_out (cfgfilec, ios::binary);
457#else
458 ofstream cfg_out (cfgfilec);
459#endif
460 if (cfg_out) {
461 // lock the file
462 int fd = GSDL_GET_FILEDESC(cfg_out);
463 int lock_val = 1;
464 GSDL_LOCK_FILE (fd);
465 if (lock_val != 0) {
466 logout << "Error: Couldn't lock file " << cfgfilec << "\n";
467 cfg_out.close();
468 message = "tmpfail";
469
470 } else {
471
472 vector<text_tarray>::const_iterator this_line = cfgarray.begin();
473 vector<text_tarray>::const_iterator end_line = cfgarray.end();
474 while (this_line != end_line) {
475 write_cfg_line (cfg_out, *this_line);
476 this_line ++;
477 }
478 GSDL_UNLOCK_FILE (fd);
479 cfg_out.close();
480 }
481
482 } else {
483 logout << "collectoraction::update_cfgfile_partial: unable to open "
484 << cfgfilec << " for output\n";
485 message = "tmpfail";
486 }
487
488 } else {
489 logout << "collectoraction::update_cfgfile_partial: unable to open "
490 << cfgfilec << " for input\n";
491 message = "tmpfail";
492 }
493 delete cfgfilec;
494}
495
496// replace configuration file on disk with that in the bc1cfgfile argument and
497// catch other bc1 arguments up with those the new cfgfile contains
498void collectoraction::update_cfgfile_complete (cgiargsclass &args, ostream &logout) {
499
500 text_t cfgfile = filename_cat(get_collectdir(args), args["bc1dirname"], "etc", "collect.cfg");
501 char *cfgfilec = cfgfile.getcstr();
502#ifdef __WIN32__
503 ofstream cfg_out (cfgfilec, ios::binary);
504#else
505 ofstream cfg_out (cfgfilec);
506#endif
507
508 if (cfg_out) {
509 // lock the file
510 int fd = GSDL_GET_FILEDESC(cfg_out);
511 int lock_val = 1;
512 GSDL_LOCK_FILE (fd);
513 if (lock_val != 0) {
514 logout << "Error: Couldn't lock file " << cfgfilec << "\n";
515 cfg_out.close();
516 message = "tmpfail";
517
518 } else {
519
520 outconvertclass text_t2ascii;
521 cfg_out << text_t2ascii << args["bc1cfgfile"];
522 GSDL_UNLOCK_FILE (fd);
523 cfg_out.close();
524
525 // now that we've written the file we'll read it back again and
526 // update our bc1 arguments
527 ifstream cfg_in (cfgfilec);
528 if (cfg_in) {
529 text_tarray cfgline;
530 while (read_cfg_line(cfg_in, cfgline) >= 0) {
531 if (cfgline.size () >= 2) {
532 if (cfgline[0] == "creator") {
533 args["bc1contactemail"] = cfgline[1];
534 } else if (cfgline[0] == "collectionmeta") {
535 if (cfgline[1] == "collectionname") {
536 args["bc1fullname"] = cfgline[2];
537 } else if (cfgline[1] == "collectionextra") {
538 args["bc1aboutdesc"] = carriage_replace (cfgline[2], 1);
539 }
540 }
541 }
542 }
543 cfg_in.close();
544 } else {
545 logout << "collectoraction::update_cfgfile_complete: unable to open "
546 << cfgfilec << " for input\n";
547 message = "tmpfail";
548 }
549 }
550 } else {
551 logout << "collectoraction::update_cfgfile_complete: unable to open "
552 << cfgfilec << " for output\n";
553 message = "tmpfail";
554 }
555 delete cfgfilec;
556}
557
558void collectoraction::get_cgihead_info (cgiargsclass &/*args*/, recptprotolistclass * /*protos*/,
559 response_t &response,text_t &response_data,
560 ostream &/*logout*/) {
561 response = content;
562 response_data = "text/html";
563}
564
565// return html for buttons used in collector bar
566// color may be "green", "grey", or "yellow"
567// type may be:
568// "info" --> "collection information" button
569// "srce" --> "source data" button
570// "conf" --> "configure collection" button
571// "bild" --> "build collection" button
572// "view" --> "view collection" button
573// if enabled is true button will be flashy rollover type and
574// will be hyperlinked
575
576text_t collectoraction::get_button (const text_t &thispage, const text_t &color,
577 const text_t &type, bool enabled) {
578
579 if ((color != "green" && color != "grey" && color != "yellow") ||
580 (type != "info" && type != "srce" && type != "conf" && type != "bild" && type != "view"))
581 return "";
582
583 text_t prefix = "gc";
584 if (color == "grey") prefix = "nc";
585 else if (color == "yellow") prefix = "yc";
586
587 text_t httpicon = "httpicon" + prefix + type;
588
589 if (enabled) {
590 text_t gsmacro = "_gsimage_";
591 if (thispage == "info" || thispage == "srce" || thispage == "conf" ||
592 thispage == "bildcancel" || thispage == "bildfail") {
593 gsmacro = "_gsjimage_";
594 } else if (type == "view") {
595 // view button is special case as it needs a target=_top
596 gsmacro = "_gstimage_";
597 }
598 return "<td>" + gsmacro + "(_collector:http" + type + "_,_collector:" + httpicon +
599 "of_,_collector:" + httpicon + "on_," + type + ",_collector:text" + type + "_)</td>\n";
600 } else {
601 return "<td>_icon" + prefix + type + "of_</td>\n";
602 }
603}
604
605// set the _fullnamemenu_ macro (and _warnindex_ if we're on the "srce" page)
606void collectoraction::set_fullnamemenu (displayclass &disp, cgiargsclass &args,
607 recptprotolistclass *protos, ostream &logout) {
608
609 if (recpt == NULL) {
610 logout << "ERROR (collectoraction::set_fullnamemenu): This action does not contain\n"
611 << " information about any receptionists. The method set_receptionist was\n"
612 << " probably not called from the module which instantiated this action.\n";
613 return;
614 }
615
616 text_t &current_page = args["cp"];
617 text_t currentname = args["bc1dirname"];
618 if (current_page == "srce") currentname = args["bc1clonecol"];
619
620 text_tarray dirnames;
621 text_tarray fullnames;
622 vector<bool> write_protected;
623 int selected_index = 0;
624 int index = 0;
625
626 recptprotolistclass::iterator rprotolist_here = protos->begin();
627 recptprotolistclass::iterator rprotolist_end = protos->end();
628 while (rprotolist_here != rprotolist_end) {
629 if ((*rprotolist_here).p != NULL) {
630
631 // don't include z39.50 collection
632 if ((*rprotolist_here).p->get_protocol_name () == "z3950proto") {
633 rprotolist_here ++;
634 continue;
635 }
636
637 text_tarray collist;
638 comerror_t err;
639 (*rprotolist_here).p->get_collection_list (collist, err, logout);
640 if (err == noError) {
641 text_tarray::iterator collist_here = collist.begin();
642 text_tarray::iterator collist_end = collist.end();
643 FilterResponse_t response;
644 text_tset metadata;
645 metadata.insert ("collectionname");
646 while (collist_here != collist_end) {
647 ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr ((*rprotolist_here).p, *collist_here, logout);
648 if (cinfo != NULL) {
649 text_t collectionname = *collist_here;
650 if (!cinfo->collectionmeta["collectionname"].empty()) {
651 // get collection name from the collection cfg file
652 collectionname = cinfo->collectionmeta["collectionname"];
653 } else if (get_info ("collection", *collist_here, metadata, false,
654 (*rprotolist_here).p, response, logout)) {
655 // get collection name from gdbm file
656 collectionname = response.docInfo[0].metadata["collectionname"].values[0];
657 }
658 dirnames.push_back(*collist_here);
659 fullnames.push_back(collectionname);
660 // check to see if the collection is writable
661 if (collection_protected (*collist_here)) write_protected.push_back(true);
662 else write_protected.push_back(false);
663
664 if (*collist_here == currentname) selected_index = index;
665 index ++;
666 }
667 collist_here ++;
668 }
669 }
670 }
671 rprotolist_here ++;
672 }
673
674 bool first = true;
675 text_t warnindex;
676 text_t fullnamemenu = "<select name=\"bc1dirname\">\n";
677 if (current_page == "srce") fullnamemenu = "<select name=\"bc1clonecol\" onChange=\"menuchange();\">\n";
678 for (int i = 0; i < index; i ++) {
679 // don't want write protected collections in list on "change existing
680 // collection" page
681 if (write_protected[i] && current_page == "existing") continue;
682 fullnamemenu += "<option value=\"" + dirnames[i] + "\"";
683 if (i == selected_index) fullnamemenu += " selected";
684 fullnamemenu.push_back ('>');
685 fullnamemenu += fullnames[i];
686 fullnamemenu.push_back ('\n');
687
688 // add to Warnindex if collection uses any dubious plugins
689 // (if creating clone collection list)
690 if (current_page == "srce") {
691 if (!first) warnindex.push_back(',');
692 if (uses_weird_plugin (dirnames[i])) {
693 warnindex += text_t (1);
694 } else {
695 warnindex += text_t (0);
696 }
697 }
698 first = false;
699 }
700 fullnamemenu += "</select>\n";
701
702 if (!first) {
703 disp.setmacro ("fullnamemenu", "collector", fullnamemenu);
704 if (current_page == "srce")
705 disp.setmacro ("warnindex", "collector", warnindex);
706 }
707}
708
709// set the _cfgfile_ macro
710void collectoraction::set_cfgfile (displayclass &disp, cgiargsclass &args, ostream &logout) {
711
712 text_t &collection = args["bc1dirname"];
713 if (collection.empty()) {
714 message = "nocollection";
715 return;
716 }
717
718 // read in collect.cfg
719 text_t cfgfile = filename_cat(get_collectdir(args), collection, "etc", "collect.cfg");
720 char *cfgfilec = cfgfile.getcstr();
721
722#ifdef GSDL_USE_IOS_H
723 ifstream cfg_ifs (cfgfilec, ios::in | ios::nocreate);
724#else
725 ifstream cfg_ifs (cfgfilec, ios::in);
726#endif
727
728 if (cfg_ifs) {
729 // read in collect.cfg
730 text_t cfgtext;
731 char c;
732 cfg_ifs.get(c);
733 while (!cfg_ifs.eof ()) {
734 if (c=='\\') cfgtext.push_back('\\');
735 cfgtext.push_back(c);
736 cfg_ifs.get(c);
737 }
738 cfg_ifs.close();
739
740 // define it as a macro
741 disp.setmacro("cfgfile","collector",cfgtext);
742
743 } else {
744 logout << "collectoraction::set_cfgfile: couldn't open configuration file ("
745 << cfgfilec << ") for reading\n";
746 message = "tmpfail";
747 }
748 delete cfgfilec;
749}
750
751// set the _statusline_ macro
752void collectoraction::set_statusline (displayclass &disp, cgiargsclass &args, ostream & /*logout*/) {
753
754 // the build command creates .bld.download, .bld.import, and .bld.build files (in that
755 // order) and deletes them (also in that order) when each stage is complete. the .bld
756 // file is the concatenation of all these files.
757 text_t bld_file = filename_cat (gsdlhome, "tmp", args["bc1tmp"], args["bc1dirname"] + ".bld");
758 text_t statusline;
759
760 if (file_exists (bld_file + ".download")) {
761 statusline = "Downloading files ...<br>\n";
762 statusline += file_tail (bld_file + ".download", 1);
763 } else if (file_exists (bld_file + ".import")) {
764 statusline = "Importing collection ...<br>\n";
765 statusline += file_tail (bld_file + ".import", 1);
766 } else if (file_exists (bld_file + ".build")) {
767 statusline = "Building collection ...<br>\n";
768 statusline += file_tail (bld_file + ".build", 1);
769 } else {
770 statusline += "creating collection ...<br>\n";
771 statusline += file_tail (bld_file, 1);
772 }
773
774 disp.setmacro ("statusline", "collector", statusline);
775
776}
777
778void collectoraction::define_internal_macros (displayclass &disp, cgiargsclass &args,
779 recptprotolistclass *protos, ostream &logout) {
780
781 // define_internal_macros sets the following macros:
782 // _collectorbar_
783 // _pagescriptextra_
784 // _fullnamemenu_ -- if displaying the "source data" page or the "changing existing
785 // collection" page
786 // _cfgfile_ -- if displaying the "configure collection" page
787 // _statusline_ -- if displaying the bildstatus page
788 // _header_ -- may be set for pages that require it
789 // _faillog_ - set to last 6 lines of .bld file if build failed
790
791 text_t &collector_page = args["cp"];
792 int esrce = args["bc1esrce"].getint();
793 int econf = args["bc1econf"].getint();
794
795 // set _pagescriptextra_ macro to _cpagescriptextra_
796 disp.setmacro ("pagescriptextra", "collector", "_" + collector_page + "scriptextra_");
797
798 if (collector_page == "bildstatus" || collector_page == "bilddone" ||
799 collector_page == "bildfail" || collector_page == "bildframe1") {
800 disp.setmacro ("header", "collector", "_" + collector_page + "header_");
801 }
802
803 // set the collectorbar macro
804 text_t collectorbar = "<table border=0 cellspacing=4 cellpadding=0><tr>\n";
805
806 if (collector_page == "new") {
807 collectorbar += "<td>_icongreyarrow_</td>\n";
808 collectorbar += get_button (collector_page, "green", "info", true);
809 collectorbar += "<td>_icongreyarrow_</td>\n";
810 collectorbar += get_button (collector_page, "grey", "srce", false);
811 collectorbar += "<td>_icongreyarrow_</td>\n";
812 collectorbar += get_button (collector_page, "grey", "conf", false);
813 collectorbar += "<td>_icongreyarrow_</td>\n";
814 collectorbar += get_button (collector_page, "grey", "bild", false);
815 collectorbar += "<td>_icongreyarrow_</td>\n";
816 collectorbar += get_button (collector_page, "grey", "view", false);
817
818 } else if (collector_page == "info") {
819 collectorbar += "<td>_icongreyarrow_</td>\n";
820 collectorbar += get_button (collector_page, "yellow", "info", false);
821 collectorbar += "<td>_icongreyarrow_</td>\n";
822 collectorbar += get_button (collector_page, "green", "srce", true);
823 collectorbar += "<td>_icongreyarrow_</td>\n";
824 collectorbar += get_button (collector_page, "grey", "conf", false);
825 collectorbar += "<td>_icongreyarrow_</td>\n";
826 collectorbar += get_button (collector_page, "grey", "bild", false);
827 collectorbar += "<td>_icongreyarrow_</td>\n";
828 collectorbar += get_button (collector_page, "grey", "view", false);
829 collectorbar += "</tr><tr><td></td><td align=center>_icongreyuparrow_</td><td colspan=8></td>\n";
830
831 } else if (collector_page == "srce") {
832 collectorbar += "<td>_icongreyarrow_</td>\n";
833 if (esrce == 1) {
834 // if we came from the "change an existing collection" page previous button(s)
835 // are disabled
836 collectorbar += get_button (collector_page, "grey", "info", false);
837 } else {
838 collectorbar += get_button (collector_page, "yellow", "info", true);
839 }
840 collectorbar += "<td>_icongreyarrow_</td>\n";
841 collectorbar += get_button (collector_page, "yellow", "srce", false);
842 collectorbar += "<td>_icongreyarrow_</td>\n";
843 collectorbar += get_button (collector_page, "green", "conf", true);
844 collectorbar += "<td>_icongreyarrow_</td>\n";
845 collectorbar += get_button (collector_page, "green", "bild", true);
846 collectorbar += "<td>_icongreyarrow_</td>\n";
847 collectorbar += get_button (collector_page, "grey", "view", false);
848 collectorbar += "</tr><tr><td colspan=3></td><td align=center>_icongreyuparrow_</td><td colspan=6></td>\n";
849
850 } else if (collector_page == "conf") {
851 collectorbar += "<td>_icongreyarrow_</td>\n";
852 // disable appropriate buttons if we came from "change an existing collection"
853 // page
854 if (esrce == 1 || econf == 1) {
855 collectorbar += get_button (collector_page, "grey", "info", false);
856 } else {
857 collectorbar += get_button (collector_page, "yellow", "info", true);
858 }
859 collectorbar += "<td>_icongreyarrow_</td>\n";
860 if (econf == 1) {
861 collectorbar += get_button (collector_page, "grey", "srce", false);
862 } else {
863 collectorbar += get_button (collector_page, "yellow", "srce", true);
864 }
865 collectorbar += "<td>_icongreyarrow_</td>\n";
866 collectorbar += get_button (collector_page, "yellow", "conf", false);
867 collectorbar += "<td>_icongreyarrow_</td>\n";
868 collectorbar += get_button (collector_page, "green", "bild", true);
869 collectorbar += "<td>_icongreyarrow_</td>\n";
870 collectorbar += get_button (collector_page, "grey", "view", false);
871 collectorbar += "</tr><tr><td colspan=5></td><td align=center>_icongreyuparrow_</td><td colspan=4></td>\n";
872
873 } else if (collector_page == "bilddone") {
874 collectorbar += "<td>_icongreyarrow_</td>\n";
875 // all previous buttons grey after build was completed
876 collectorbar += get_button (collector_page, "grey", "info", false);
877 collectorbar += "<td>_icongreyarrow_</td>\n";
878 collectorbar += get_button (collector_page, "grey", "srce", false);
879 collectorbar += "<td>_icongreyarrow_</td>\n";
880 collectorbar += get_button (collector_page, "grey", "conf", false);
881 collectorbar += "<td>_icongreyarrow_</td>\n";
882 collectorbar += get_button (collector_page, "yellow", "bild", false);
883 collectorbar += "<td>_icongreyarrow_</td>\n";
884 collectorbar += get_button (collector_page, "green", "view", true);
885 collectorbar += "</tr><tr><td colspan=7></td><td align=center>_icongreyuparrow_</td><td colspan=2></td>\n";
886
887 } else if (collector_page == "bildcancel" || collector_page == "bildfail") {
888 collectorbar += "<td>_icongreyarrow_</td>\n";
889 // disable appropriate buttons if we came from "change an existing collection"
890 // page
891 if (esrce == 1 || econf == 1) {
892 collectorbar += get_button (collector_page, "grey", "info", false);
893 } else {
894 collectorbar += get_button (collector_page, "yellow", "info", true);
895 }
896 collectorbar += "<td>_icongreyarrow_</td>\n";
897 if (econf == 1) {
898 collectorbar += get_button (collector_page, "grey", "srce", false);
899 } else {
900 collectorbar += get_button (collector_page, "yellow", "srce", true);
901 }
902 collectorbar += "<td>_icongreyarrow_</td>\n";
903 collectorbar += get_button (collector_page, "yellow", "conf", true);
904 collectorbar += "<td>_icongreyarrow_</td>\n";
905 collectorbar += get_button (collector_page, "yellow", "bild", true);
906 collectorbar += "<td>_icongreyarrow_</td>\n";
907 collectorbar += get_button (collector_page, "grey", "view", false);
908 }
909
910 if (collector_page == "bildfail") {
911 text_t bldlog = filename_cat(gsdlhome, "tmp", args["bc1tmp"], args["bc1dirname"] + ".bld");
912 text_t rawlog = file_tail (bldlog, 6);
913 // we'll shove in some <br> tags where \n's occur
914 text_t faillog;
915 text_t::const_iterator here = rawlog.begin();
916 text_t::const_iterator end = rawlog.end();
917 while (here != end) {
918 if (*here == '\n') faillog += "<br>";
919 faillog.push_back (*here);
920 here ++;
921 }
922 disp.setmacro ("faillog", "collector", faillog);
923 }
924
925 collectorbar += "</tr></table>\n";
926 disp.setmacro ("collectorbar", "collector", collectorbar);
927
928 if (collector_page == "srce" || collector_page == "existing")
929 set_fullnamemenu (disp, args, protos, logout);
930 if (collector_page == "conf")
931 set_cfgfile (disp, args, logout);
932 if (collector_page == "bildstatus")
933 set_statusline (disp, args, logout);
934}
935
936bool collectoraction::do_action (cgiargsclass &args, recptprotolistclass * /*protos*/,
937 browsermapclass * /*browsers*/, displayclass &disp,
938 outconvertclass &outconvert, ostream &textout,
939 ostream &logout) {
940
941 text_t &collector_page = args["cp"];
942 text_t &collection = args["bc1dirname"];
943
944 if (collector_page == "bild") {
945 // do the work (download, import, build)
946 gsdl_build (args, logout);
947
948 if (message.empty()) {
949 // bild page is a frameset so we don't want headers and stuff
950 textout << outconvert << disp << ("_collector:bildcontent_\n");
951 }
952 }
953
954 if (do_mkcol == true) {
955 // execute mkcol.pl (do_mkcol is set from within check_cgiargs)
956 gsdl_mkcol (args, logout);
957 do_mkcol = false; // reset for fast-cgi
958 }
959
960 if (args["bc1dodelete"] == "1") {
961 // delete bcidirname collection
962 if (collection_protected (collection)) {
963 message = "delinvalid";
964
965 } else {
966
967 text_t delete_cmd = "perl " + filename_cat (gsdlhome, "bin", "script", "delcol.pl");
968 delete_cmd += " -f " + collection;
969 char *delete_cmdc = delete_cmd.getcstr();
970 int rv = system (delete_cmdc);
971 delete delete_cmdc;
972 if (rv != 0) {
973 // deletion failed -- permissions?
974 message = "delpermission";
975 } else {
976 message = "delsuccess";
977 }
978 }
979 }
980
981 if (collector_page == "bildcancel" || collector_page == "bildfail") {
982 // cancel the build (we'll also use the cancel_build script to tidy
983 // up if the build failed)
984 gsdl_cancel_build (args, logout);
985 }
986
987 if (message.empty()) {
988 if (collector_page != "bild") {
989 // output page ("bild" page was already output above)
990 textout << outconvert << disp << ("_collector:header_\n")
991 << ("_collector:" + collector_page + "content_\n")
992 << ("_collector:footer_\n");
993 }
994 } else {
995 // message was set somewhere (probably an error), output message page
996 textout << outconvert << disp << ("_collector:header_\n")
997 << ("_collector:" + message + "content_\n")
998 << ("_collector:footer_\n");
999 message.clear();
1000 }
1001 return true;
1002}
1003
1004// if sw = 0 replace all carriage returns in intext with the string "\n"
1005// else replace all occurances of "\n" with a carriage return
1006text_t collectoraction::carriage_replace (const text_t &intext, int sw) {
1007
1008 text_t outtext;
1009 text_t::const_iterator here = intext.begin();
1010 text_t::const_iterator end = intext.end();
1011 while (here != end) {
1012 if (sw == 0) {
1013 if (*here == '\n') {
1014 if ((here+1) != end && *(here+1) == '\r') here ++;
1015 outtext += "\\n";
1016 } else if (*here == '\r') {
1017 if ((here+1) != end && *(here+1) == '\n') here ++;
1018 outtext += "\\n";
1019 } else {
1020 outtext.push_back (*here);
1021 }
1022 } else if (*here == '\\' && (here+1) != end && *(here+1) == 'n') {
1023 outtext.push_back ('\n');
1024 here ++;
1025 } else {
1026 outtext.push_back (*here);
1027 }
1028 here ++;
1029 }
1030 return outtext;
1031}
1032
1033// create a short directory name from fullname
1034text_t collectoraction::get_directory_name (const text_t &fullname) {
1035
1036 text_t shortname;
1037 if (fullname.empty()) {
1038 shortname = "coll";
1039
1040 } else {
1041
1042 // first make all lowercase and remove any dodgy characters
1043 // (i.e. anything not [a-z]
1044 text_t::const_iterator here = fullname.begin();
1045 text_t::const_iterator end = fullname.end();
1046 while (here != end) {
1047 if ((*here >= 'A' && *here <= 'Z') || (*here >= 'a' && *here <= 'z') ||
1048 (*here == ' ')) {
1049 if (*here >= 'A' && *here <= 'Z') shortname.push_back (*here+32);
1050 else if (*here == ' ') {
1051 while ((*(here+1)) == ' ') here ++;
1052 shortname.push_back (*here);
1053 } else shortname.push_back (*here);
1054 }
1055 here ++;
1056 }
1057
1058 text_tarray words;
1059 splitchar (shortname.begin(), shortname.end(), ' ', words);
1060 int num_words = words.size();
1061
1062 if (num_words == 0) {
1063 shortname = "coll";
1064
1065 } else {
1066
1067 shortname.clear();
1068 int use_words = (num_words <= 6) ? num_words : 6;
1069 int substr_len = 6 / use_words;
1070
1071 for (int i = 0; i < use_words; i++) {
1072 if (words[i].size() < substr_len) shortname += words[i];
1073 else shortname += substr (words[i].begin(), words[i].begin()+substr_len);
1074 }
1075 }
1076 }
1077
1078 // check to see if shortname is unique
1079 text_t fulldirname = filename_cat (gsdlhome, "collect", shortname);
1080 if (directory_exists (fulldirname)) {
1081 int version = 0;
1082 text_t newname;
1083 do {
1084 version ++;
1085 newname = shortname;
1086 newname.push_back ('v');
1087 newname.appendint (version);
1088 fulldirname = filename_cat (gsdlhome, "collect", newname);
1089 } while (directory_exists (fulldirname));
1090
1091 shortname = newname;
1092 }
1093
1094 return shortname;
1095}
1096
1097// tests if collection is write protected (currently just checks if
1098// collect.cfg file is writable
1099bool collectoraction::collection_protected (const text_t &collection) {
1100 text_t cfgfile = filename_cat(gsdlhome, "collect", collection, "etc", "collect.cfg");
1101 if (file_writable(cfgfile)) return false;
1102 return true;
1103}
1104
1105// assigns a temporary directory name for this collector session
1106// and creates temporary directory
1107void collectoraction::assign_tmpname (cgiargsclass &args, ostream &logout) {
1108
1109 int i = 0;
1110 text_t tmpname = "tbuild";
1111 while (directory_exists (filename_cat (gsdlhome, "tmp", tmpname + text_t(i)))) {
1112 i++;
1113 }
1114 tmpname.appendint (i);
1115
1116 text_t fulltmpdir = filename_cat (gsdlhome, "tmp", tmpname);
1117 if (!mk_dir (fulltmpdir)) {
1118 outconvertclass text_t2ascii;
1119 logout << text_t2ascii << "collectoraction::assign_tmpname unable to create directory ("
1120 << fulltmpdir << ")\n";
1121 }
1122
1123 args["bc1tmp"] = tmpname;
1124}
1125
1126void collectoraction::gsdl_mkcol (cgiargsclass &args, ostream &logout) {
1127
1128 text_t tmpdir = filename_cat (gsdlhome, "tmp", args["bc1tmp"]);
1129 if (!directory_exists (tmpdir)) {
1130 message = "tmpfail";
1131 return;
1132 }
1133
1134 text_t &collection = args["bc1dirname"];
1135 if (collection.empty()) {
1136 message = "nocollection";
1137 return;
1138 }
1139
1140 // check for a .create file - if it exists then we've already created the collection
1141 text_t createfile = filename_cat (tmpdir, ".create");
1142 if (file_exists (createfile)) {
1143 return;
1144 } else {
1145 // create the .create file (this file is just a place holder to let any future
1146 // pages know that the collection already exists).
1147 char *createfilec = createfile.getcstr();
1148 ofstream cfile_out (createfilec);
1149 delete createfilec;
1150 if (cfile_out) {
1151 cfile_out << "collection created\n";
1152 cfile_out.close();
1153 } else {
1154 message = "tmpfail";
1155 return;
1156 }
1157 }
1158
1159 // set up options
1160 text_t options = "-creator \"" + args["bc1contactemail"] + "\"";
1161 options += " -title \"" + args["bc1fullname"] + "\"";
1162 options += " -about \"" + carriage_replace (args["bc1aboutdesc"], 0) + "\"";
1163 options += " -collectdir \"" + tmpdir + "\" ";
1164 text_t optionfile = filename_cat (tmpdir, "mkcol.opt");
1165 char *optionfilet = optionfile.getcstr();
1166 ofstream ofile_out (optionfilet);
1167 delete optionfilet;
1168 if (!ofile_out) {
1169 message = "tmpfail";
1170 return;
1171 }
1172 outconvertclass text_t2ascii;
1173 ofile_out << text_t2ascii << options << "\n";
1174 ofile_out.close();
1175
1176 // set up the mkcol.pl command
1177 text_t mkcol_cmd = "perl ";
1178 mkcol_cmd += filename_cat (gsdlhome, "bin", "script", "mkcol.pl");
1179 mkcol_cmd += " -optionfile \"" + optionfile + "\" " + collection;
1180 char *mkcol_cmdc = mkcol_cmd.getcstr();
1181
1182 // just an ordinary system call running in the foreground. we're assuming (hoping??)
1183 // that mkcol.pl will run through fast enough that nothing more elaborate is required.
1184 system (mkcol_cmdc);
1185 delete mkcol_cmdc;
1186
1187 // make sure it went ok
1188 text_t cfgfile = filename_cat (tmpdir, collection, "etc", "collect.cfg");
1189 if (!file_writable (cfgfile)) {
1190 message = "mkcolfail";
1191 }
1192}
1193
1194void collectoraction::gsdl_build (cgiargsclass &args, ostream &logout) {
1195
1196 text_t tmpdir = filename_cat (gsdlhome, "tmp", args["bc1tmp"]);
1197 if (!directory_exists (tmpdir)) {
1198 message = "tmpfail";
1199 return;
1200 }
1201
1202 text_t &collection = args["bc1dirname"];
1203 if (collection.empty()) {
1204 message = "nocollection";
1205 return;
1206 }
1207
1208 // check for a .build file - if it exists then we've already built
1209 // the collection (or are in the process of building it)
1210 text_t buildfile = filename_cat (tmpdir, ".build");
1211 if (file_exists (buildfile)) {
1212 return;
1213 } else {
1214 // create the .build file (this file is just a place holder to let any future
1215 // pages know that we've already been here)
1216 char *buildfilec = buildfile.getcstr();
1217 ofstream bfile_out (buildfilec);
1218 delete buildfilec;
1219 if (bfile_out) {
1220 bfile_out << "collection building\n";
1221 bfile_out.close();
1222 } else {
1223 message = "tmpfail";
1224 return;
1225 }
1226 }
1227
1228 // set up build options
1229 text_t options = "-remove_import -out \"";
1230 options += filename_cat (tmpdir, collection + ".bld");
1231 options += "\" -collectdir \"" + get_collectdir (args) + "\"";
1232
1233 if (args["bc1esrce"] == 1) {
1234 // we're adding data to an existing collection
1235 options += "\" -save_archives -append";
1236 }
1237
1238 if (!args["bc1inputdir1"].empty())
1239 options += " -download \"" + args["bc1inputdir1"] + "\"";
1240 if (!args["bc1inputdir2"].empty())
1241 options += " -download \"" + args["bc1inputdir2"] + "\"";
1242 if (!args["bc1inputdir3"].empty())
1243 options += " -download \"" + args["bc1inputdir3"] + "\"";
1244 if (!args["bc1inputdir4"].empty())
1245 options += " -download \"" + args["bc1inputdir4"] + "\"";
1246 text_t optionfile = filename_cat (tmpdir, "build.opt");
1247 char *optionfilet = optionfile.getcstr();
1248 ofstream ofile_out (optionfilet);
1249 delete optionfilet;
1250 if (!ofile_out) {
1251 message = "tmpfail";
1252 return;
1253 }
1254 outconvertclass text_t2ascii;
1255 ofile_out << text_t2ascii << options << "\n";
1256 ofile_out.close();
1257
1258 // set up the build command
1259 text_t build_cmd = "perl " + filename_cat (gsdlhome, "bin", "script", "build");
1260 build_cmd += " -optionfile \"" + optionfile + "\" " + collection;
1261#if !defined (__WIN32__)
1262 // run in background on unix systems
1263 // build_cmd += " &";
1264#endif
1265 char *build_cmdc = build_cmd.getcstr();
1266 //#if defined (__WIN32__)
1267 gsdl_system (build_cmdc, logout);
1268 //#else
1269 // system (build_cmdc);
1270 //#endif
1271 delete build_cmdc;
1272}
1273
1274void collectoraction::gsdl_cancel_build (cgiargsclass &args, ostream &logout) {
1275 // I really wanted to do what this perl script does from within the library
1276 // c++ code. I ran into some problems though (like how do you write a portable
1277 // "rm -r" in c++?). One day I'll spend some time sorting it out ... maybe.
1278 text_t cancel_cmd = "perl " + filename_cat (gsdlhome, "bin", "script", "cancel_build.pl");
1279 cancel_cmd += " -collectdir \"" + filename_cat (gsdlhome, "tmp", args["bc1tmp"]) +
1280 "\" " + args["bc1dirname"];
1281 char *cancel_cmdc = cancel_cmd.getcstr();
1282 system (cancel_cmdc);
1283 delete (cancel_cmdc);
1284}
1285
1286text_t collectoraction::get_collectdir (cgiargsclass &args) {
1287
1288 if ((args["bc1econf"] == 1) || (args["bc1esrce"] == 1)) {
1289 // we're adding to a collection in place
1290 return filename_cat(gsdlhome, "collect");
1291
1292 } else {
1293 return filename_cat (gsdlhome, "tmp", args["bc1tmp"]);
1294 }
1295}
1296
1297// checks to see if any of the plugins in pluginset occur in
1298// collections configuration file
1299bool collectoraction::uses_weird_plugin (const text_t &collection) {
1300
1301 text_tset pluginset;
1302 pluginset.insert ("HBPlug");
1303
1304 text_t cfgfile_content;
1305 text_t cfgfile_name = filename_cat (gsdlhome, "collect", collection, "etc", "collect.cfg");
1306 text_t pluginstr, pluginname;
1307
1308 if (read_file (cfgfile_name, cfgfile_content)) {
1309 text_t::const_iterator here = cfgfile_content.begin();
1310 text_t::const_iterator end = cfgfile_content.end();
1311 while (here != end) {
1312 here = findchar (here, end, 'p');
1313 if (here == end) break;
1314 if ((here+6 < end) && (substr (here, here+6) == "plugin")) {
1315 getdelimitstr (here+6, end, '\n', pluginstr);
1316 text_t::const_iterator hp = pluginstr.begin();
1317 text_t::const_iterator ep = pluginstr.end();
1318 bool found = false;
1319 // remove any leading whitespace, trailing options etc.
1320 while (hp != ep) {
1321 if (*hp == '\t' || *hp == ' ' || *hp == '\n') {
1322 if (found) break;
1323 } else {
1324 pluginname.push_back (*hp);
1325 found = true;
1326 }
1327 hp ++;
1328 }
1329 text_tset::const_iterator it = pluginset.find (pluginname);
1330 if (it != pluginset.end()) return true; // found matching plugin
1331 pluginname.clear();
1332 }
1333 here ++;
1334 }
1335 }
1336 return false;
1337}
Note: See TracBrowser for help on using the repository browser.