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

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

More improvements to collector

  • Property svn:keywords set to Author Date Id Revision
File size: 44.9 KB
Line 
1/**********************************************************************
2 *
3 * collectoraction.cpp --
4 * Copyright (C) 2000 The New Zealand Digital Library Project
5 *
6 * A component of the Greenstone digital library software
7 * from the New Zealand Digital Library Project at the
8 * University of Waikato, New Zealand.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 *********************************************************************/
25
26// 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") {
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 gsmacro = "_gsjimage_";
593 } else if (type == "view") {
594 // view button is special case as it needs a target=_top
595 gsmacro = "_gstimage_";
596 }
597 return "<td>" + gsmacro + "(_collector:http" + type + "_,_collector:" + httpicon +
598 "of_,_collector:" + httpicon + "on_," + type + ",_collector:text" + type + "_)</td>\n";
599 } else {
600 return "<td>_icon" + prefix + type + "of_</td>\n";
601 }
602}
603
604// set the _fullnamemenu_ macro (and _warnindex_ if we're on the "srce" page)
605void collectoraction::set_fullnamemenu (displayclass &disp, cgiargsclass &args,
606 recptprotolistclass *protos, ostream &logout) {
607
608 if (recpt == NULL) {
609 logout << "ERROR (collectoraction::set_fullnamemenu): This action does not contain\n"
610 << " information about any receptionists. The method set_receptionist was\n"
611 << " probably not called from the module which instantiated this action.\n";
612 return;
613 }
614
615 text_t &current_page = args["cp"];
616 text_t currentname = args["bc1dirname"];
617 if (current_page == "srce") currentname = args["bc1clonecol"];
618
619 text_tarray dirnames;
620 text_tarray fullnames;
621 vector<bool> write_protected;
622 int selected_index = 0;
623 int index = 0;
624
625 recptprotolistclass::iterator rprotolist_here = protos->begin();
626 recptprotolistclass::iterator rprotolist_end = protos->end();
627 while (rprotolist_here != rprotolist_end) {
628 if ((*rprotolist_here).p != NULL) {
629
630 // don't include z39.50 collection
631 if ((*rprotolist_here).p->get_protocol_name () == "z3950proto") {
632 rprotolist_here ++;
633 continue;
634 }
635
636 text_tarray collist;
637 comerror_t err;
638 (*rprotolist_here).p->get_collection_list (collist, err, logout);
639 if (err == noError) {
640 text_tarray::iterator collist_here = collist.begin();
641 text_tarray::iterator collist_end = collist.end();
642 FilterResponse_t response;
643 text_tset metadata;
644 metadata.insert ("collectionname");
645 while (collist_here != collist_end) {
646 ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr ((*rprotolist_here).p, *collist_here, logout);
647 if (cinfo != NULL) {
648 text_t collectionname = *collist_here;
649 if (!cinfo->collectionmeta["collectionname"].empty()) {
650 // get collection name from the collection cfg file
651 collectionname = cinfo->collectionmeta["collectionname"];
652 } else if (get_info ("collection", *collist_here, metadata, false,
653 (*rprotolist_here).p, response, logout)) {
654 // get collection name from gdbm file
655 collectionname = response.docInfo[0].metadata["collectionname"].values[0];
656 }
657 dirnames.push_back(*collist_here);
658 fullnames.push_back(collectionname);
659 // check to see if the collection is writable
660 if (collection_protected (*collist_here)) write_protected.push_back(true);
661 else write_protected.push_back(false);
662
663 if (*collist_here == currentname) selected_index = index;
664 index ++;
665 }
666 collist_here ++;
667 }
668 }
669 }
670 rprotolist_here ++;
671 }
672
673 bool first = true;
674 text_t warnindex;
675 text_t fullnamemenu = "<select name=\"bc1dirname\">\n";
676 if (current_page == "srce") fullnamemenu = "<select name=\"bc1clonecol\" onChange=\"menuchange();\">\n";
677 for (int i = 0; i < index; i ++) {
678 // don't want write protected collections in list on "change existing
679 // collection" page
680 if (write_protected[i] && current_page == "existing") continue;
681 fullnamemenu += "<option value=\"" + dirnames[i] + "\"";
682 if (i == selected_index) fullnamemenu += " selected";
683 fullnamemenu.push_back ('>');
684 fullnamemenu += fullnames[i];
685 if (write_protected[i]) fullnamemenu += " <b>(write protected)</b>";
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 += get_button (collector_page, "green", "info", true);
808 collectorbar += "<td>_icongreyarrow_</td>\n";
809 collectorbar += get_button (collector_page, "grey", "srce", false);
810 collectorbar += "<td>_icongreyarrow_</td>\n";
811 collectorbar += get_button (collector_page, "grey", "conf", false);
812 collectorbar += "<td>_icongreyarrow_</td>\n";
813 collectorbar += get_button (collector_page, "grey", "bild", false);
814 collectorbar += "<td>_icongreyarrow_</td>\n";
815 collectorbar += get_button (collector_page, "grey", "view", false);
816
817 } else if (collector_page == "info") {
818 collectorbar += get_button (collector_page, "yellow", "info", false);
819 collectorbar += "<td>_icongreyarrow_</td>\n";
820 collectorbar += get_button (collector_page, "green", "srce", true);
821 collectorbar += "<td>_icongreyarrow_</td>\n";
822 collectorbar += get_button (collector_page, "grey", "conf", false);
823 collectorbar += "<td>_icongreyarrow_</td>\n";
824 collectorbar += get_button (collector_page, "grey", "bild", false);
825 collectorbar += "<td>_icongreyarrow_</td>\n";
826 collectorbar += get_button (collector_page, "grey", "view", false);
827 collectorbar += "</tr><tr><td align=center>_icongreyuparrow_</td><td colspan=8></td>\n";
828
829 } else if (collector_page == "srce") {
830 if (esrce == 1) {
831 // if we came from the "change an existing collection" page previous button(s)
832 // are disabled
833 collectorbar += get_button (collector_page, "grey", "info", false);
834 } else {
835 collectorbar += get_button (collector_page, "yellow", "info", true);
836 }
837 collectorbar += "<td>_icongreyarrow_</td>\n";
838 collectorbar += get_button (collector_page, "yellow", "srce", false);
839 collectorbar += "<td>_icongreyarrow_</td>\n";
840 collectorbar += get_button (collector_page, "green", "conf", true);
841 collectorbar += "<td>_icongreyarrow_</td>\n";
842 collectorbar += get_button (collector_page, "green", "bild", true);
843 collectorbar += "<td>_icongreyarrow_</td>\n";
844 collectorbar += get_button (collector_page, "grey", "view", false);
845 collectorbar += "</tr><tr><td colspan=2></td><td align=center>_icongreyuparrow_</td><td colspan=6></td>\n";
846
847 } else if (collector_page == "conf") {
848 // disable appropriate buttons if we came from "change an existing collection"
849 // page
850 if (esrce == 1 || econf == 1) {
851 collectorbar += get_button (collector_page, "grey", "info", false);
852 } else {
853 collectorbar += get_button (collector_page, "yellow", "info", true);
854 }
855 collectorbar += "<td>_icongreyarrow_</td>\n";
856 if (econf == 1) {
857 collectorbar += get_button (collector_page, "grey", "srce", false);
858 } else {
859 collectorbar += get_button (collector_page, "yellow", "srce", true);
860 }
861 collectorbar += "<td>_icongreyarrow_</td>\n";
862 collectorbar += get_button (collector_page, "yellow", "conf", false);
863 collectorbar += "<td>_icongreyarrow_</td>\n";
864 collectorbar += get_button (collector_page, "green", "bild", true);
865 collectorbar += "<td>_icongreyarrow_</td>\n";
866 collectorbar += get_button (collector_page, "grey", "view", false);
867 collectorbar += "</tr><tr><td colspan=4></td><td align=center>_icongreyuparrow_</td><td colspan=4></td>\n";
868
869 } else if (collector_page == "bilddone") {
870 // all previous buttons grey after build was completed
871 collectorbar += get_button (collector_page, "grey", "info", false);
872 collectorbar += "<td>_icongreyarrow_</td>\n";
873 collectorbar += get_button (collector_page, "grey", "srce", false);
874 collectorbar += "<td>_icongreyarrow_</td>\n";
875 collectorbar += get_button (collector_page, "grey", "conf", false);
876 collectorbar += "<td>_icongreyarrow_</td>\n";
877 collectorbar += get_button (collector_page, "yellow", "bild", false);
878 collectorbar += "<td>_icongreyarrow_</td>\n";
879 collectorbar += get_button (collector_page, "green", "view", true);
880 collectorbar += "</tr><tr><td colspan=6></td><td align=center>_icongreyuparrow_</td><td colspan=2></td>\n";
881
882 } else if (collector_page == "bildcancel") {
883 // disable appropriate buttons if we came from "change an existing collection"
884 // page
885 if (esrce == 1 || econf == 1) {
886 collectorbar += get_button (collector_page, "grey", "info", false);
887 } else {
888 collectorbar += get_button (collector_page, "yellow", "info", true);
889 }
890 collectorbar += "<td>_icongreyarrow_</td>\n";
891 if (econf == 1) {
892 collectorbar += get_button (collector_page, "grey", "srce", false);
893 } else {
894 collectorbar += get_button (collector_page, "yellow", "srce", true);
895 }
896 collectorbar += "<td>_icongreyarrow_</td>\n";
897 collectorbar += get_button (collector_page, "yellow", "conf", true);
898 collectorbar += "<td>_icongreyarrow_</td>\n";
899 collectorbar += get_button (collector_page, "yellow", "bild", true);
900 collectorbar += "<td>_icongreyarrow_</td>\n";
901 collectorbar += get_button (collector_page, "grey", "view", false);
902 }
903
904 if (collector_page == "bildfail") {
905 text_t bldlog = filename_cat(gsdlhome, "tmp", args["bc1tmp"], args["bc1dirname"] + ".bld");
906 text_t rawlog = file_tail (bldlog, 6);
907 // we'll shove in some <br> tags where \n's occur
908 text_t faillog;
909 text_t::const_iterator here = rawlog.begin();
910 text_t::const_iterator end = rawlog.end();
911 while (here != end) {
912 if (*here == '\n') faillog += "<br>";
913 faillog.push_back (*here);
914 here ++;
915 }
916 disp.setmacro ("faillog", "collector", faillog);
917 }
918
919 collectorbar += "</tr></table>\n";
920 disp.setmacro ("collectorbar", "collector", collectorbar);
921
922 if (collector_page == "srce" || collector_page == "existing")
923 set_fullnamemenu (disp, args, protos, logout);
924 if (collector_page == "conf")
925 set_cfgfile (disp, args, logout);
926 if (collector_page == "bildstatus")
927 set_statusline (disp, args, logout);
928}
929
930bool collectoraction::do_action (cgiargsclass &args, recptprotolistclass * /*protos*/,
931 browsermapclass * /*browsers*/, displayclass &disp,
932 outconvertclass &outconvert, ostream &textout,
933 ostream &logout) {
934
935 text_t &collector_page = args["cp"];
936 text_t &collection = args["bc1dirname"];
937
938 if (collector_page == "bild") {
939 // do the work (download, import, build)
940 gsdl_build (args, logout);
941
942 if (message.empty()) {
943 // bild page is a frameset so we don't want headers and stuff
944 textout << outconvert << disp << ("_collector:bildcontent_\n");
945 }
946 }
947
948 if (do_mkcol == true) {
949 // execute mkcol.pl (do_mkcol is set from within check_cgiargs)
950 gsdl_mkcol (args, logout);
951 do_mkcol = false; // reset for fast-cgi
952 }
953
954 if (args["bc1dodelete"] == "1") {
955 // delete bcidirname collection
956 if (collection_protected (collection)) {
957 message = "delinvalid";
958
959 } else {
960
961 text_t delete_cmd = "perl " + filename_cat (gsdlhome, "bin", "script", "delcol.pl");
962 delete_cmd += " -f " + collection;
963 char *delete_cmdc = delete_cmd.getcstr();
964 int rv = system (delete_cmdc);
965 delete delete_cmdc;
966 if (rv != 0) {
967 // deletion failed -- permissions?
968 message = "delpermission";
969 } else {
970 message = "delsuccess";
971 }
972 }
973 }
974
975 if (collector_page == "bildcancel") {
976 // cancel the build
977 gsdl_cancel_build (args, logout);
978 }
979
980 if (message.empty()) {
981 if (collector_page != "bild") {
982 // output page ("bild" page was already output above)
983 textout << outconvert << disp << ("_collector:header_\n")
984 << ("_collector:" + collector_page + "content_\n")
985 << ("_collector:footer_\n");
986 }
987 } else {
988 // message was set somewhere (probably an error), output message page
989 textout << outconvert << disp << ("_collector:header_\n")
990 << ("_collector:" + message + "content_\n")
991 << ("_collector:footer_\n");
992 message.clear();
993 }
994 return true;
995}
996
997// if sw = 0 replace all carriage returns in intext with the string "\n"
998// else replace all occurances of "\n" with a carriage return
999text_t collectoraction::carriage_replace (const text_t &intext, int sw) {
1000
1001 text_t outtext;
1002 text_t::const_iterator here = intext.begin();
1003 text_t::const_iterator end = intext.end();
1004 while (here != end) {
1005 if (sw == 0) {
1006 if (*here == '\n') {
1007 if ((here+1) != end && *(here+1) == '\r') here ++;
1008 outtext += "\\n";
1009 } else if (*here == '\r') {
1010 if ((here+1) != end && *(here+1) == '\n') here ++;
1011 outtext += "\\n";
1012 } else {
1013 outtext.push_back (*here);
1014 }
1015 } else if (*here == '\\' && (here+1) != end && *(here+1) == 'n') {
1016 outtext.push_back ('\n');
1017 here ++;
1018 } else {
1019 outtext.push_back (*here);
1020 }
1021 here ++;
1022 }
1023 return outtext;
1024}
1025
1026// create a short directory name from fullname
1027text_t collectoraction::get_directory_name (const text_t &fullname) {
1028
1029 text_t shortname;
1030 if (fullname.empty()) {
1031 shortname = "coll";
1032
1033 } else {
1034
1035 // first make all lowercase and remove any dodgy characters
1036 // (i.e. anything not [a-z]
1037 text_t::const_iterator here = fullname.begin();
1038 text_t::const_iterator end = fullname.end();
1039 while (here != end) {
1040 if ((*here >= 'A' && *here <= 'Z') || (*here >= 'a' && *here <= 'z') ||
1041 (*here == ' ')) {
1042 if (*here >= 'A' && *here <= 'Z') shortname.push_back (*here+32);
1043 else if (*here == ' ') {
1044 while ((*(here+1)) == ' ') here ++;
1045 shortname.push_back (*here);
1046 } else shortname.push_back (*here);
1047 }
1048 here ++;
1049 }
1050
1051 text_tarray words;
1052 splitchar (shortname.begin(), shortname.end(), ' ', words);
1053 int num_words = words.size();
1054
1055 if (num_words == 0) {
1056 shortname = "coll";
1057
1058 } else {
1059
1060 shortname.clear();
1061 int use_words = (num_words <= 6) ? num_words : 6;
1062 int substr_len = 6 / use_words;
1063
1064 for (int i = 0; i < use_words; i++) {
1065 if (words[i].size() < substr_len) shortname += words[i];
1066 else shortname += substr (words[i].begin(), words[i].begin()+substr_len);
1067 }
1068 }
1069 }
1070
1071 // check to see if shortname is unique
1072 text_t fulldirname = filename_cat (gsdlhome, "collect", shortname);
1073 if (directory_exists (fulldirname)) {
1074 int version = 0;
1075 text_t newname;
1076 do {
1077 version ++;
1078 newname = shortname;
1079 newname.push_back ('v');
1080 newname.appendint (version);
1081 fulldirname = filename_cat (gsdlhome, "collect", newname);
1082 } while (directory_exists (fulldirname));
1083
1084 shortname = newname;
1085 }
1086
1087 return shortname;
1088}
1089
1090// tests if collection is write protected (currently just checks if
1091// collect.cfg file is writable
1092bool collectoraction::collection_protected (const text_t &collection) {
1093 text_t cfgfile = filename_cat(gsdlhome, "collect", collection, "etc", "collect.cfg");
1094 if (file_writable(cfgfile)) return false;
1095 return true;
1096}
1097
1098// assigns a temporary directory name for this collector session
1099// and creates temporary directory
1100void collectoraction::assign_tmpname (cgiargsclass &args, ostream &logout) {
1101
1102 int i = 0;
1103 text_t tmpname = "tbuild";
1104 while (directory_exists (filename_cat (gsdlhome, "tmp", tmpname + text_t(i)))) {
1105 i++;
1106 }
1107 tmpname.appendint (i);
1108
1109 text_t fulltmpdir = filename_cat (gsdlhome, "tmp", tmpname);
1110 if (!mk_dir (fulltmpdir)) {
1111 outconvertclass text_t2ascii;
1112 logout << text_t2ascii << "collectoraction::assign_tmpname unable to create directory ("
1113 << fulltmpdir << ")\n";
1114 }
1115
1116 args["bc1tmp"] = tmpname;
1117}
1118
1119void collectoraction::gsdl_mkcol (cgiargsclass &args, ostream &logout) {
1120
1121 text_t tmpdir = filename_cat (gsdlhome, "tmp", args["bc1tmp"]);
1122 if (!directory_exists (tmpdir)) {
1123 message = "tmpfail";
1124 return;
1125 }
1126
1127 text_t &collection = args["bc1dirname"];
1128 if (collection.empty()) {
1129 message = "nocollection";
1130 return;
1131 }
1132
1133 // check for a .create file - if it exists then we've already created the collection
1134 text_t createfile = filename_cat (tmpdir, ".create");
1135 if (file_exists (createfile)) {
1136 return;
1137 } else {
1138 // create the .create file (this file is just a place holder to let any future
1139 // pages know that the collection already exists).
1140 char *createfilec = createfile.getcstr();
1141 ofstream cfile_out (createfilec);
1142 delete createfilec;
1143 if (cfile_out) {
1144 cfile_out << "collection created\n";
1145 cfile_out.close();
1146 } else {
1147 message = "tmpfail";
1148 return;
1149 }
1150 }
1151
1152 // set up options
1153 text_t options = "-creator \"" + args["bc1contactemail"] + "\"";
1154 options += " -title \"" + args["bc1fullname"] + "\"";
1155 options += " -about \"" + carriage_replace (args["bc1aboutdesc"], 0) + "\"";
1156 options += " -collectdir \"" + tmpdir + "\" ";
1157 text_t optionfile = filename_cat (tmpdir, "mkcol.opt");
1158 char *optionfilet = optionfile.getcstr();
1159 ofstream ofile_out (optionfilet);
1160 delete optionfilet;
1161 if (!ofile_out) {
1162 message = "tmpfail";
1163 return;
1164 }
1165 outconvertclass text_t2ascii;
1166 ofile_out << text_t2ascii << options << "\n";
1167 ofile_out.close();
1168
1169 // set up the mkcol.pl command
1170 text_t mkcol_cmd = "perl ";
1171 mkcol_cmd += filename_cat (gsdlhome, "bin", "script", "mkcol.pl");
1172 mkcol_cmd += " -optionfile \"" + optionfile + "\" " + collection;
1173 char *mkcol_cmdc = mkcol_cmd.getcstr();
1174
1175 // just an ordinary system call running in the foreground. we're assuming (hoping??)
1176 // that mkcol.pl will run through fast enough that nothing more elaborate is required.
1177 system (mkcol_cmdc);
1178 delete mkcol_cmdc;
1179
1180 // make sure it went ok
1181 text_t cfgfile = filename_cat (tmpdir, collection, "etc", "collect.cfg");
1182 if (!file_writable (cfgfile)) {
1183 message = "mkcolfail";
1184 }
1185}
1186
1187void collectoraction::gsdl_build (cgiargsclass &args, ostream &logout) {
1188
1189 text_t tmpdir = filename_cat (gsdlhome, "tmp", args["bc1tmp"]);
1190 if (!directory_exists (tmpdir)) {
1191 message = "tmpfail";
1192 return;
1193 }
1194
1195 text_t &collection = args["bc1dirname"];
1196 if (collection.empty()) {
1197 message = "nocollection";
1198 return;
1199 }
1200
1201 // check for a .build file - if it exists then we've already built
1202 // the collection (or are in the process of building it)
1203 text_t buildfile = filename_cat (tmpdir, ".build");
1204 if (file_exists (buildfile)) {
1205 return;
1206 } else {
1207 // create the .build file (this file is just a place holder to let any future
1208 // pages know that we've already been here)
1209 char *buildfilec = buildfile.getcstr();
1210 ofstream bfile_out (buildfilec);
1211 delete buildfilec;
1212 if (bfile_out) {
1213 bfile_out << "collection building\n";
1214 bfile_out.close();
1215 } else {
1216 message = "tmpfail";
1217 return;
1218 }
1219 }
1220
1221 // set up build options
1222 text_t options = "-remove_import -out \"";
1223 options += filename_cat (tmpdir, collection + ".bld");
1224 options += "\" -collectdir \"" + get_collectdir (args) + "\"";
1225
1226 if (args["bc1esrce"] == 1) {
1227 // we're adding data to an existing collection
1228 options += "\" -save_archives -append";
1229 }
1230
1231 if (!args["bc1inputdir1"].empty())
1232 options += " -download \"" + args["bc1inputdir1"] + "\"";
1233 if (!args["bc1inputdir2"].empty())
1234 options += " -download \"" + args["bc1inputdir2"] + "\"";
1235 if (!args["bc1inputdir3"].empty())
1236 options += " -download \"" + args["bc1inputdir3"] + "\"";
1237 if (!args["bc1inputdir4"].empty())
1238 options += " -download \"" + args["bc1inputdir4"] + "\"";
1239 text_t optionfile = filename_cat (tmpdir, "build.opt");
1240 char *optionfilet = optionfile.getcstr();
1241 ofstream ofile_out (optionfilet);
1242 delete optionfilet;
1243 if (!ofile_out) {
1244 message = "tmpfail";
1245 return;
1246 }
1247 outconvertclass text_t2ascii;
1248 ofile_out << text_t2ascii << options << "\n";
1249 ofile_out.close();
1250
1251 // set up the build command
1252 text_t build_cmd = "perl " + filename_cat (gsdlhome, "bin", "script", "build");
1253 build_cmd += " -optionfile \"" + optionfile + "\" " + collection;
1254#if !defined (__WIN32__)
1255 // run in background on unix systems
1256 // build_cmd += " &";
1257#endif
1258 char *build_cmdc = build_cmd.getcstr();
1259 //#if defined (__WIN32__)
1260 gsdl_system (build_cmdc, logout);
1261 //#else
1262 // system (build_cmdc);
1263 //#endif
1264 delete build_cmdc;
1265}
1266
1267void collectoraction::gsdl_cancel_build (cgiargsclass &args, ostream &logout) {
1268 // I really wanted to do what this perl script does from within the library
1269 // c++ code. I ran into some problems though (like how do you write a portable
1270 // "rm -r" in c++?). One day I'll spend some time sorting it out ... maybe.
1271 text_t cancel_cmd = "perl " + filename_cat (gsdlhome, "bin", "script", "cancel_build.pl");
1272 cancel_cmd += " -collectdir \"" + filename_cat (gsdlhome, "tmp", args["bc1tmp"]) +
1273 "\" " + args["bc1dirname"];
1274 char *cancel_cmdc = cancel_cmd.getcstr();
1275 system (cancel_cmdc);
1276 delete (cancel_cmdc);
1277}
1278
1279text_t collectoraction::get_collectdir (cgiargsclass &args) {
1280
1281 if ((args["bc1econf"] == 1) || (args["bc1esrce"] == 1)) {
1282 // we're adding to a collection in place
1283 return filename_cat(gsdlhome, "collect");
1284
1285 } else {
1286 return filename_cat (gsdlhome, "tmp", args["bc1tmp"]);
1287 }
1288}
1289
1290// checks to see if any of the plugins in pluginset occur in
1291// collections configuration file
1292bool collectoraction::uses_weird_plugin (const text_t &collection) {
1293
1294 text_tset pluginset;
1295 pluginset.insert ("HBPlug");
1296
1297 text_t cfgfile_content;
1298 text_t cfgfile_name = filename_cat (gsdlhome, "collect", collection, "etc", "collect.cfg");
1299 text_t pluginstr, pluginname;
1300
1301 if (read_file (cfgfile_name, cfgfile_content)) {
1302 text_t::const_iterator here = cfgfile_content.begin();
1303 text_t::const_iterator end = cfgfile_content.end();
1304 while (here != end) {
1305 here = findchar (here, end, 'p');
1306 if (here == end) break;
1307 if ((here+6 < end) && (substr (here, here+6) == "plugin")) {
1308 getdelimitstr (here+6, end, '\n', pluginstr);
1309 text_t::const_iterator hp = pluginstr.begin();
1310 text_t::const_iterator ep = pluginstr.end();
1311 bool found = false;
1312 // remove any leading whitespace, trailing options etc.
1313 while (hp != ep) {
1314 if (*hp == '\t' || *hp == ' ' || *hp == '\n') {
1315 if (found) break;
1316 } else {
1317 pluginname.push_back (*hp);
1318 found = true;
1319 }
1320 hp ++;
1321 }
1322 text_tset::const_iterator it = pluginset.find (pluginname);
1323 if (it != pluginset.end()) return true; // found matching plugin
1324 pluginname.clear();
1325 }
1326 here ++;
1327 }
1328 }
1329 return false;
1330}
Note: See TracBrowser for help on using the repository browser.