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

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

Tidied up collectoraction some more and created an add_collection
function in nullproto that does all the work of setting up a
local collection server

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