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

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

Lots of changes - mostly to get collectoraction working

  • Property svn:keywords set to Author Date Id Revision
File size: 30.1 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 clone_failed = 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 arg_ainfo.shortname = "bc1fullname";
67 arg_ainfo.longname = "collector specific";
68 arg_ainfo.multiplechar = true;
69 arg_ainfo.defaultstatus = cgiarginfo::weak;
70 arg_ainfo.argdefault = "";
71 arg_ainfo.savedarginfo = cgiarginfo::must;
72 argsinfo.addarginfo (NULL, arg_ainfo);
73
74 arg_ainfo.shortname = "bc1dirname";
75 arg_ainfo.longname = "collector specific";
76 arg_ainfo.multiplechar = true;
77 arg_ainfo.defaultstatus = cgiarginfo::weak;
78 arg_ainfo.argdefault = "";
79 arg_ainfo.savedarginfo = cgiarginfo::must;
80 argsinfo.addarginfo (NULL, arg_ainfo);
81
82 arg_ainfo.shortname = "bc1contactemail";
83 arg_ainfo.longname = "collector specific";
84 arg_ainfo.multiplechar = true;
85 arg_ainfo.defaultstatus = cgiarginfo::weak;
86 arg_ainfo.argdefault = "";
87 arg_ainfo.savedarginfo = cgiarginfo::must;
88 argsinfo.addarginfo (NULL, arg_ainfo);
89
90 arg_ainfo.shortname = "bc1aboutdesc";
91 arg_ainfo.longname = "collector specific";
92 arg_ainfo.multiplechar = true;
93 arg_ainfo.defaultstatus = cgiarginfo::weak;
94 arg_ainfo.argdefault = "";
95 arg_ainfo.savedarginfo = cgiarginfo::must;
96 argsinfo.addarginfo (NULL, arg_ainfo);
97
98 arg_ainfo.shortname = "bc1clone";
99 arg_ainfo.longname = "collector specific";
100 arg_ainfo.multiplechar = false;
101 arg_ainfo.defaultstatus = cgiarginfo::weak;
102 arg_ainfo.argdefault = "0";
103 arg_ainfo.savedarginfo = cgiarginfo::must;
104 argsinfo.addarginfo (NULL, arg_ainfo);
105
106 arg_ainfo.shortname = "bc1clonecol";
107 arg_ainfo.longname = "collector specific";
108 arg_ainfo.multiplechar = true;
109 arg_ainfo.defaultstatus = cgiarginfo::weak;
110 arg_ainfo.argdefault = "";
111 arg_ainfo.savedarginfo = cgiarginfo::must;
112 argsinfo.addarginfo (NULL, arg_ainfo);
113
114 // set when cloning option has changed
115 arg_ainfo.shortname = "bc1clonechanged";
116 arg_ainfo.longname = "collector specific";
117 arg_ainfo.multiplechar = false;
118 arg_ainfo.defaultstatus = cgiarginfo::weak;
119 arg_ainfo.argdefault = "0";
120 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
121 argsinfo.addarginfo (NULL, arg_ainfo);
122
123 arg_ainfo.shortname = "bc1inputdir1";
124 arg_ainfo.longname = "collector specific";
125 arg_ainfo.multiplechar = true;
126 arg_ainfo.defaultstatus = cgiarginfo::weak;
127 arg_ainfo.argdefault = "";
128 arg_ainfo.savedarginfo = cgiarginfo::must;
129 argsinfo.addarginfo (NULL, arg_ainfo);
130
131 arg_ainfo.shortname = "bc1inputdir2";
132 arg_ainfo.longname = "collector specific";
133 arg_ainfo.multiplechar = true;
134 arg_ainfo.defaultstatus = cgiarginfo::weak;
135 arg_ainfo.argdefault = "";
136 arg_ainfo.savedarginfo = cgiarginfo::must;
137 argsinfo.addarginfo (NULL, arg_ainfo);
138
139 arg_ainfo.shortname = "bc1inputdir3";
140 arg_ainfo.longname = "collector specific";
141 arg_ainfo.multiplechar = true;
142 arg_ainfo.defaultstatus = cgiarginfo::weak;
143 arg_ainfo.argdefault = "";
144 arg_ainfo.savedarginfo = cgiarginfo::must;
145 argsinfo.addarginfo (NULL, arg_ainfo);
146
147 arg_ainfo.shortname = "bc1inputdir4";
148 arg_ainfo.longname = "collector specific";
149 arg_ainfo.multiplechar = true;
150 arg_ainfo.defaultstatus = cgiarginfo::weak;
151 arg_ainfo.argdefault = "";
152 arg_ainfo.savedarginfo = cgiarginfo::must;
153 argsinfo.addarginfo (NULL, arg_ainfo);
154
155 // only set when one of the fields was changed in
156 // the "collection info" page
157 arg_ainfo.shortname = "bc1infochanged";
158 arg_ainfo.longname = "collector specific";
159 arg_ainfo.multiplechar = false;
160 arg_ainfo.defaultstatus = cgiarginfo::weak;
161 arg_ainfo.argdefault = "0";
162 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
163 argsinfo.addarginfo (NULL, arg_ainfo);
164
165 // only set when cfg file is altered from within
166 // "configure collection" page
167 arg_ainfo.shortname = "bc1cfgchanged";
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 arg_ainfo.shortname = "bc1dodelete";
176 arg_ainfo.longname = "collector specific";
177 arg_ainfo.multiplechar = false;
178 arg_ainfo.defaultstatus = cgiarginfo::weak;
179 arg_ainfo.argdefault = "0";
180 arg_ainfo.savedarginfo = cgiarginfo::mustnot;
181 argsinfo.addarginfo (NULL, arg_ainfo);
182
183 // will be set if we arrived at the "configure collection" page
184 // via the "changing an existing collection" page
185 arg_ainfo.shortname = "bc1econf";
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::must;
191 argsinfo.addarginfo (NULL, arg_ainfo);
192
193 // will be set if we arrived at the "source data" page
194 // via the "changing an existing collection" page
195 arg_ainfo.shortname = "bc1esrce";
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
204collectoraction::~collectoraction () {
205 delete gsdlosc;
206 delete gsdlhomec;
207}
208
209bool collectoraction::init (ostream & /*logout*/) {
210
211 // set up GSDLOS and GSDLHOME environment variables
212 text_t gsdlos;
213#if defined (__WIN32__)
214 gsdlos = "windows";
215#else
216 utsname *buf = new utsname();
217 int i = uname (buf);
218 if (i == -1) gsdlos = "linux"; // uname failed
219 else gsdlos.setcstr (buf->sysname);
220 delete buf;
221 lc (gsdlos);
222#endif
223
224 gsdlos = "GSDLOS=" + gsdlos;
225 text_t setgsdlhome = "GSDLHOME=" + gsdlhome;
226
227 // these will be cleaned up in the destructor
228 gsdlosc = gsdlos.getcstr();
229 gsdlhomec = setgsdlhome.getcstr();
230
231 putenv (gsdlosc);
232 putenv (gsdlhomec);
233
234 return true;
235}
236
237bool collectoraction::check_cgiargs (cgiargsinfoclass &/*argsinfo*/, cgiargsclass &args,
238 ostream &logout) {
239
240 if (args["cp"] != "intro") {
241 // authenticate the user if authentication is available
242 args["uan"] = 1;
243 args["ug"] = "colbuilder";
244 }
245
246 if (args["bc1infochanged"] == "1") {
247
248 if (args["bc1dirname"].empty()) {
249 // we've just come from the "collection information" page for the
250 // first time so we'll need to create the collection with mkcol.pl
251 // and set up bc1dirname - we do this part here instead of in do_action
252 // because the bc1dirname argument must be set to its new value before
253 // the compressedoptions macros are set.
254 args["bc1dirname"] = get_directory_name (args["bc1fullname"]);
255 do_mkcol = true;
256 } else {
257 // "collection information" has been changed after collection was made
258 // so we'll need to update the cfg file.
259 update_cfgfile_partial (args, logout);
260 }
261 }
262
263 if (args["bc1cfgchanged"] == "1") {
264 // configuration file has been changed from the "configure collection"
265 // page. we need to update the file on disk and catch bc1 arguments up
266 // with changes.
267 update_cfgfile_complete (args, logout);
268 }
269
270 if (args["bc1clonechanged"] == "1") {
271 // cloning option has been changed on "source data" page. if it was turned
272 // on we want to create a new collect.cfg file using the bc1clonecol cfg file
273 // as a model (we'll save the old file as collect.cfg.org). if cloning was
274 // turned off we'll revert to using the collect.cfg.org file (which will need
275 // updating in case the bc1 arguments have been altered since cloning was
276 // turned on).
277 update_cfgfile_clone (args, logout);
278 }
279
280 return true;
281}
282
283void collectoraction::update_cfgfile_clone (cgiargsclass &args, ostream &logout) {
284
285 text_t cfgfile = filename_cat(gsdlhome, "collect", args["bc1dirname"], "etc", "collect.cfg");
286 text_t cfgfile_org = cfgfile + ".org";
287
288 if (args["bc1clone"] == "1") {
289 // cloning was turned on
290
291 text_t cfgfile_clone = filename_cat(gsdlhome, "collect", args["bc1clonecol"], "etc", "collect.cfg");
292 if (file_exists (cfgfile_clone)) {
293 // if .org file doesn't exist already create it
294 if (!file_exists (cfgfile_org)) {
295 file_copy (cfgfile, cfgfile_org);
296 }
297 // copy clone collections cfg file to new collection
298 file_copy (cfgfile_clone, cfgfile);
299 // update the new cfg file
300 update_cfgfile_partial (args, logout);
301
302 } else {
303 // can't clone non-existant collection
304 clone_failed = true;
305 }
306
307 } else {
308 // cloning has been turned off having been on at some point. the .org file
309 // should exist, if it doesn't we'll bail out and leave the user with the
310 // cloned copy
311 if (file_exists (cfgfile_org)) {
312 // copy original back again and update it with any recent changes
313 file_copy (cfgfile_org, cfgfile);
314 update_cfgfile_partial (args, logout);
315 }
316 }
317}
318
319// update configuration file on disk to match bc1 arguments
320void collectoraction::update_cfgfile_partial (cgiargsclass &args, ostream &logout) {
321
322 text_t cfgfile = filename_cat(gsdlhome, "collect", args["bc1dirname"], "etc", "collect.cfg");
323 char *cfgfilec = cfgfile.getcstr();
324
325 vector<text_tarray> cfgarray;
326
327 // read in cfg file
328 ifstream cfg_in (cfgfilec);
329 if (cfg_in) {
330 text_tarray cfgline;
331 while (read_cfg_line(cfg_in, cfgline) >= 0) {
332 if (cfgline.size () >= 2) {
333 if (cfgline[0] == "creator" || cfgline[0] == "maintainer") {
334 cfgline[1] = args["bc1contactemail"];
335 } else if (cfgline[0] == "collectionmeta") {
336 if (cfgline[1] == "collectionname") {
337 cfgline[2] = args["bc1fullname"];
338 } else if (cfgline[1] == "collectionextra") {
339 cfgline[2] = carriage_replace (args["bc1aboutdesc"], 0);
340 }
341 }
342 }
343 cfgarray.push_back (cfgline);
344 }
345 cfg_in.close();
346
347 // now write cfg file back out
348#ifdef __WIN32__
349 ofstream cfg_out (cfgfilec, ios::binary);
350#else
351 ofstream cfg_out (cfgfilec);
352#endif
353 if (cfg_out) {
354 // lock the file
355 int fd = GSDL_GET_FILEDESC(cfg_out);
356 int lock_val = 1;
357 GSDL_LOCK_FILE (fd);
358 if (lock_val != 0) {
359 logout << "Error: Couldn't lock file " << cfgfilec << "\n";
360 cfg_out.close();
361
362 } else {
363
364 vector<text_tarray>::const_iterator this_line = cfgarray.begin();
365 vector<text_tarray>::const_iterator end_line = cfgarray.end();
366 while (this_line != end_line) {
367 write_cfg_line (cfg_out, *this_line);
368 this_line ++;
369 }
370 GSDL_UNLOCK_FILE (fd);
371 cfg_out.close();
372 }
373
374 } else {
375 logout << "collectoraction::update_cfgfile_partial: unable to open "
376 << cfgfilec << " for output\n";
377 }
378
379 } else {
380 logout << "collectoraction::update_cfgfile_partial: unable to open "
381 << cfgfilec << " for input\n";
382 }
383 delete cfgfilec;
384}
385
386// replace configuration file on disk with that in the bc1cfgfile argument and
387// catch other bc1 arguments up with those the new cfgfile contains
388void collectoraction::update_cfgfile_complete (cgiargsclass &args, ostream &logout) {
389
390 text_t cfgfile = filename_cat(gsdlhome, "collect", args["bc1dirname"], "etc", "collect.cfg");
391 char *cfgfilec = cfgfile.getcstr();
392#ifdef __WIN32__
393 ofstream cfg_out (cfgfilec, ios::binary);
394#else
395 ofstream cfg_out (cfgfilec);
396#endif
397
398 if (cfg_out) {
399 // lock the file
400 int fd = GSDL_GET_FILEDESC(cfg_out);
401 int lock_val = 1;
402 GSDL_LOCK_FILE (fd);
403 if (lock_val != 0) {
404 logout << "Error: Couldn't lock file " << cfgfilec << "\n";
405 cfg_out.close();
406
407 } else {
408
409 outconvertclass text_t2ascii;
410 cfg_out << text_t2ascii << args["bc1cfgfile"];
411 GSDL_UNLOCK_FILE (fd);
412 cfg_out.close();
413
414 // now that we've written the file we'll read it back again and
415 // update our bc1 arguments
416 ifstream cfg_in (cfgfilec);
417 if (cfg_in) {
418 text_tarray cfgline;
419 while (read_cfg_line(cfg_in, cfgline) >= 0) {
420 if (cfgline.size () >= 2) {
421 if (cfgline[0] == "creator") {
422 args["bc1contactemail"] = cfgline[1];
423 } else if (cfgline[0] == "collectionmeta") {
424 if (cfgline[1] == "collectionname") {
425 args["bc1fullname"] = cfgline[2];
426 } else if (cfgline[1] == "collectionextra") {
427 args["bc1aboutdesc"] = carriage_replace (cfgline[2], 1);
428 }
429 }
430 }
431 }
432 cfg_in.close();
433 } else {
434 logout << "collectoraction::update_cfgfile_complete: unable to open "
435 << cfgfilec << " for input\n";
436 }
437 }
438 } else {
439 logout << "collectoraction::update_cfgfile_complete: unable to open "
440 << cfgfilec << " for output\n";
441 }
442 delete cfgfilec;
443}
444
445void collectoraction::get_cgihead_info (cgiargsclass &/*args*/, recptprotolistclass * /*protos*/,
446 response_t &response,text_t &response_data,
447 ostream &/*logout*/) {
448 response = content;
449 response_data = "text/html";
450}
451
452// return html for buttons used in collector bar
453// color may be "green", "grey", or "yellow"
454// type may be:
455// "info" --> "collection information" button
456// "srce" --> "source data" button
457// "conf" --> "configure collection" button
458// "bild" --> "build collection" button
459// "view" --> "view collection" button
460// if enabled is true button will be flashy rollover type and
461// will be hyperlinked
462
463text_t collectoraction::get_button (const text_t &thispage, const text_t &color,
464 const text_t &type, bool enabled) {
465
466 if ((color != "green" && color != "grey" && color != "yellow") ||
467 (type != "info" && type != "srce" && type != "conf" && type != "bild" && type != "view"))
468 return "";
469
470 text_t prefix = "gc";
471 if (color == "grey") prefix = "nc";
472 else if (color == "yellow") prefix = "yc";
473
474 text_t httpicon = "httpicon" + prefix + type;
475
476 if (enabled) {
477 text_t gsmacro = "_gsimage_";
478 if (thispage == "info" || thispage == "srce" || thispage == "conf") {
479 gsmacro = "_gsjimage_";
480 }
481 return "<td>" + gsmacro + "(_collector:http" + type + "_,_collector:" + httpicon +
482 "of_,_collector:" + httpicon + "on_," + type + ",_collector:text" + type + "_)</td>\n";
483 } else {
484 return "<td>_icon" + prefix + type + "of_</td>\n";
485 }
486}
487
488// set the _fullnamemenu_ macro
489void collectoraction::set_fullnamemenu (displayclass &disp, cgiargsclass &args,
490 recptprotolistclass *protos, ostream &logout) {
491
492 if (recpt == NULL) {
493 logout << "ERROR (collectoraction::set_fullnamemenu): This action does not contain\n"
494 << " information about any receptionists. The method set_receptionist was\n"
495 << " probably not called from the module which instantiated this action.\n";
496 return;
497 }
498
499 text_t &current_page = args["cp"];
500 text_t currentname = args["bc1dirname"];
501 if (current_page == "srce") currentname = args["bc1clonecol"];
502
503 text_tarray dirnames;
504 text_tarray fullnames;
505 vector<bool> write_protected;
506 int selected_index = 0;
507 int index = 0;
508
509 recptprotolistclass::iterator rprotolist_here = protos->begin();
510 recptprotolistclass::iterator rprotolist_end = protos->end();
511 while (rprotolist_here != rprotolist_end) {
512 if ((*rprotolist_here).p != NULL) {
513 text_tarray collist;
514 comerror_t err;
515 (*rprotolist_here).p->get_collection_list (collist, err, logout);
516 if (err == noError) {
517 text_tarray::iterator collist_here = collist.begin();
518 text_tarray::iterator collist_end = collist.end();
519 FilterResponse_t response;
520 text_tset metadata;
521 metadata.insert ("collectionname");
522 while (collist_here != collist_end) {
523 ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr ((*rprotolist_here).p, *collist_here, logout);
524 if (cinfo != NULL) {
525 text_t collectionname = *collist_here;
526 if (!cinfo->collectionmeta["collectionname"].empty()) {
527 // get collection name from the collection cfg file
528 collectionname = cinfo->collectionmeta["collectionname"];
529 } else if (get_info ("collection", *collist_here, metadata, false,
530 (*rprotolist_here).p, response, logout)) {
531 // get collection name from gdbm file
532 collectionname = response.docInfo[0].metadata["collectionname"].values[0];
533 }
534 dirnames.push_back(*collist_here);
535 fullnames.push_back(collectionname);
536 // check to see if the "collection" is writable
537 if (collection_protected (*collist_here)) write_protected.push_back(true);
538 else write_protected.push_back(false);
539 if (*collist_here == currentname) selected_index = index;
540
541 index ++;
542 }
543 collist_here ++;
544 }
545 }
546 }
547 rprotolist_here ++;
548 }
549
550 bool have_one = false;
551 text_t fullnamemenu = "<select name=\"bc1dirname\">\n";
552 if (current_page == "srce") fullnamemenu = "<select name=\"bc1clonecol\">\n";
553 for (int i = 0; i < index; i ++) {
554 // don't want write protected collections in list on "change existing
555 // collection" page
556 if (write_protected[i] && current_page == "existing") continue;
557 have_one = true;
558 fullnamemenu += "<option value=\"" + dirnames[i] + "\"";
559 if (i == selected_index) fullnamemenu += " selected";
560 fullnamemenu.push_back ('>');
561 fullnamemenu += fullnames[i];
562 if (write_protected[i]) fullnamemenu += " <b>(write protected)</b>";
563 }
564 fullnamemenu += "</select>\n";
565 if (have_one) disp.setmacro ("fullnamemenu", "collector", fullnamemenu);
566}
567
568// set the _cfgfile_ macro
569void collectoraction::set_cfgfile (displayclass &disp, const text_t &dirname, ostream &logout) {
570
571 // read in collect.cfg
572 text_t cfgfile = filename_cat(gsdlhome, "collect", dirname, "etc", "collect.cfg");
573 char *cfgfilec = cfgfile.getcstr();
574
575#ifdef GSDL_USE_IOS_H
576 ifstream cfg_ifs (cfgfilec, ios::in | ios::nocreate);
577#else
578 ifstream cfg_ifs (cfgfilec, ios::in);
579#endif
580
581 if (cfg_ifs) {
582 // read in collect.cfg
583 text_t cfgtext;
584 char c;
585 cfg_ifs.get(c);
586 while (!cfg_ifs.eof ()) {
587 if (c=='\\') cfgtext.push_back('\\');
588 cfgtext.push_back(c);
589 cfg_ifs.get(c);
590 }
591 cfg_ifs.close();
592
593 // define it as a macro
594 disp.setmacro("cfgfile","collector",cfgtext);
595
596 } else {
597 logout << "collectoraction::set_cfgfile: couldn't open configuration file ("
598 << cfgfilec << ") for reading\n";
599 }
600 delete cfgfilec;
601}
602
603void collectoraction::define_internal_macros (displayclass &disp, cgiargsclass &args,
604 recptprotolistclass *protos, ostream &logout) {
605
606 // define_internal_macros sets the following macros:
607 // _collectorbar_
608 // _pagescriptextra_
609 // _fullnamemenu_ -- if displaying the "source data" page or the "changing existing
610 // collection" page
611 // _cfgfile_ -- if displaying the "configure collection" page
612
613 text_t &collector_page = args["cp"];
614 int esrce = args["bc1esrce"].getint();
615 int econf = args["bc1econf"].getint();
616
617 // set _pagescriptextra_ macro to _cpagescriptextra_
618 disp.setmacro ("pagescriptextra", "collector", "_" + collector_page + "scriptextra_");
619
620 // set the collectorbar macro
621 text_t collectorbar = "<table border=0 cellspacing=4 cellpadding=0><tr>\n";
622
623 if (collector_page == "new") {
624 collectorbar += get_button (collector_page, "green", "info", true);
625 collectorbar += "<td>_icongreyarrow_</td>\n";
626 collectorbar += get_button (collector_page, "grey", "srce", false);
627 collectorbar += "<td>_icongreyarrow_</td>\n";
628 collectorbar += get_button (collector_page, "grey", "conf", false);
629 collectorbar += "<td>_icongreyarrow_</td>\n";
630 collectorbar += get_button (collector_page, "grey", "bild", false);
631 collectorbar += "<td>_icongreyarrow_</td>\n";
632 collectorbar += get_button (collector_page, "grey", "view", false);
633
634 } else if (collector_page == "info") {
635 collectorbar += get_button (collector_page, "yellow", "info", false);
636 collectorbar += "<td>_icongreyarrow_</td>\n";
637 collectorbar += get_button (collector_page, "green", "srce", true);
638 collectorbar += "<td>_icongreyarrow_</td>\n";
639 collectorbar += get_button (collector_page, "grey", "conf", false);
640 collectorbar += "<td>_icongreyarrow_</td>\n";
641 collectorbar += get_button (collector_page, "grey", "bild", false);
642 collectorbar += "<td>_icongreyarrow_</td>\n";
643 collectorbar += get_button (collector_page, "grey", "view", false);
644 collectorbar += "</tr><tr><td align=center>_icongreyuparrow_</td><td colspan=8></td>\n";
645
646 } else if (collector_page == "srce") {
647 if (esrce == 1) {
648 // if we came from the "change an existing collection" page previous button(s)
649 // are disabled
650 collectorbar += get_button (collector_page, "grey", "info", false);
651 } else {
652 collectorbar += get_button (collector_page, "yellow", "info", true);
653 }
654 collectorbar += "<td>_icongreyarrow_</td>\n";
655 collectorbar += get_button (collector_page, "yellow", "srce", false);
656 collectorbar += "<td>_icongreyarrow_</td>\n";
657 collectorbar += get_button (collector_page, "green", "conf", true);
658 collectorbar += "<td>_icongreyarrow_</td>\n";
659 collectorbar += get_button (collector_page, "grey", "bild", false);
660 collectorbar += "<td>_icongreyarrow_</td>\n";
661 collectorbar += get_button (collector_page, "grey", "view", false);
662 collectorbar += "</tr><tr><td colspan=2></td><td align=center>_icongreyuparrow_</td><td colspan=6></td>\n";
663
664 } else if (collector_page == "conf") {
665 // disable appropriate buttons if we came from "change an existing collection"
666 // page
667 if (esrce == 1 || econf == 1) {
668 collectorbar += get_button (collector_page, "grey", "info", false);
669 } else {
670 collectorbar += get_button (collector_page, "yellow", "info", true);
671 }
672 collectorbar += "<td>_icongreyarrow_</td>\n";
673 if (econf == 1) {
674 collectorbar += get_button (collector_page, "grey", "srce", false);
675 } else {
676 collectorbar += get_button (collector_page, "yellow", "srce", true);
677 }
678 collectorbar += "<td>_icongreyarrow_</td>\n";
679 collectorbar += get_button (collector_page, "yellow", "conf", false);
680 collectorbar += "<td>_icongreyarrow_</td>\n";
681 collectorbar += get_button (collector_page, "green", "bild", true);
682 collectorbar += "<td>_icongreyarrow_</td>\n";
683 collectorbar += get_button (collector_page, "grey", "view", false);
684 collectorbar += "</tr><tr><td colspan=4></td><td align=center>_icongreyuparrow_</td><td colspan=4></td>\n";
685
686 } else if (collector_page == "bild") {
687
688
689 }
690
691 collectorbar += "</tr></table>\n";
692 disp.setmacro ("collectorbar", "collector", collectorbar);
693
694 if (collector_page == "srce" || collector_page == "existing")
695 set_fullnamemenu (disp, args, protos, logout);
696 if (collector_page == "conf")
697 set_cfgfile (disp, args["bc1dirname"], logout);
698}
699
700bool collectoraction::do_action (cgiargsclass &args, recptprotolistclass * /*protos*/,
701 browsermapclass * /*browsers*/, displayclass &disp,
702 outconvertclass &outconvert, ostream &textout,
703 ostream &logout) {
704
705 text_t &collector_page = args["cp"];
706 text_t &collection = args["bc1dirname"];
707 text_t message;
708
709 if (do_mkcol) {
710 // execute mkcol.pl (do_mkcol is set from within check_cgiargs)
711 text_t mkcol_cmd = "perl ";
712 mkcol_cmd += filename_cat (gsdlhome, "bin", "script", "mkcol.pl");
713 mkcol_cmd += " -creator \"" + args["bc1contactemail"] + "\"";
714 mkcol_cmd += " -title \"" + args["bc1fullname"] + "\"";
715 mkcol_cmd += " -about \"" + carriage_replace (args["bc1aboutdesc"], 0) + "\" ";
716 mkcol_cmd += collection;
717 char *mkcol_cmdc = mkcol_cmd.getcstr();
718 system (mkcol_cmdc);
719 delete mkcol_cmdc;
720
721 // make sure it went ok
722 text_t cfgfile = filename_cat (gsdlhome, "collect", collection,
723 "etc", "collect.cfg");
724 if (!file_writable (cfgfile)) message = "mkcolfail";
725 do_mkcol = false; // reset for fast-cgi
726 }
727
728 if (collector_page == "bild") {
729 // do the work (download, import, build)
730 text_t tmpdir = filename_cat (gsdlhome, "tmp", collection + ".bld");
731
732 text_t build_cmd = "perl " + filename_cat (gsdlhome, "bin", "script", "build");
733 build_cmd += " -append -remove_import";
734 build_cmd += " -out \"" + tmpdir + "\"";
735 if (!args["bc1inputdir1"].empty()) {
736 build_cmd += " -download \"" + args["bc1inputdir1"] + "\"";
737 }
738 if (!args["bc1inputdir2"].empty()) {
739 build_cmd += " -download \"" + args["bc1inputdir2"] + "\"";
740 }
741 if (!args["bc1inputdir3"].empty()) {
742 build_cmd += " -download \"" + args["bc1inputdir3"] + "\"";
743 }
744 if (!args["bc1inputdir4"].empty()) {
745 build_cmd += " -download \"" + args["bc1inputdir4"] + "\"";
746 }
747 build_cmd.push_back (' ');
748 build_cmd += collection;
749
750#if !defined (__WIN32__)
751 // run in background on unix systems
752 build_cmd += " &";
753#endif
754 char *build_cmdc = build_cmd.getcstr();
755#if defined (__WIN32__)
756 gsdl_system (build_cmdc, logout);
757#else
758 system (build_cmdc);
759#endif
760 delete build_cmdc;
761 }
762
763 if (args["bc1dodelete"] == "1") {
764 // delete bcidirname collection
765 if (collection_protected (collection)) {
766 message = "delinvalid";
767
768 } else {
769
770 text_t delete_cmd = "perl " + filename_cat (gsdlhome, "bin", "script", "delcol.pl");
771 delete_cmd += " -f " + collection;
772 char *delete_cmdc = delete_cmd.getcstr();
773 int rv = system (delete_cmdc);
774 delete delete_cmdc;
775 if (rv != 0) {
776 // deletion failed -- permissions?
777 message = "delpermission";
778 } else {
779 message = "delsuccess";
780 }
781 }
782 }
783
784 if (clone_failed) {
785 // clone_failed is set from check_cgiargs if an attempt was made
786 // to clone an invalid collection
787 message = "clonefail";
788 clone_failed = false;
789 }
790
791 if (message.empty()) {
792 textout << outconvert << disp << ("_collector:header_\n")
793 << ("_collector:" + collector_page + "content_\n")
794 << ("_collector:footer_\n");
795 } else {
796 textout << outconvert << disp << ("_collector:header_\n")
797 << ("_collector:" + message + "content_\n")
798 << ("_collector:footer_\n");
799 }
800
801 return true;
802}
803
804// if sw = 0 replace all carriage returns in intext with the string "\n"
805// else replace all occurances of "\n" with a carriage return
806text_t collectoraction::carriage_replace (const text_t &intext, int sw) {
807
808 text_t outtext;
809 text_t::const_iterator here = intext.begin();
810 text_t::const_iterator end = intext.end();
811 while (here != end) {
812 if (sw == 0) {
813 if (*here == '\n') {
814 if ((here+1) != end && *(here+1) == '\r') here ++;
815 outtext += "\\n";
816 } else if (*here == '\r') {
817 if ((here+1) != end && *(here+1) == '\n') here ++;
818 outtext += "\\n";
819 } else {
820 outtext.push_back (*here);
821 }
822 } else if (*here == '\\' && (here+1) != end && *(here+1) == 'n') {
823 outtext.push_back ('\n');
824 here ++;
825 } else {
826 outtext.push_back (*here);
827 }
828 here ++;
829 }
830 return outtext;
831}
832
833// create a short directory name from fullname
834text_t collectoraction::get_directory_name (const text_t &fullname) {
835
836 text_t shortname;
837 if (fullname.empty()) {
838 shortname = "coll";
839
840 } else {
841
842 // first make all lowercase and remove any dodgy characters
843 // (i.e. anything not [a-z]
844 text_t::const_iterator here = fullname.begin();
845 text_t::const_iterator end = fullname.end();
846 while (here != end) {
847 if ((*here >= 'A' && *here <= 'Z') || (*here >= 'a' && *here <= 'z') ||
848 (*here == ' ')) {
849 if (*here >= 'A' && *here <= 'Z') shortname.push_back (*here+32);
850 else if (*here == ' ') {
851 while ((*(here+1)) == ' ') here ++;
852 shortname.push_back (*here);
853 } else shortname.push_back (*here);
854 }
855 here ++;
856 }
857
858 text_tarray words;
859 splitchar (shortname.begin(), shortname.end(), ' ', words);
860 int num_words = words.size();
861
862 if (num_words == 0) {
863 shortname = "coll";
864
865 } else {
866
867 shortname.clear();
868 int use_words = (num_words <= 6) ? num_words : 6;
869 int substr_len = 6 / use_words;
870
871 for (int i = 0; i < use_words; i++) {
872 if (words[i].size() < substr_len) shortname += words[i];
873 else shortname += substr (words[i].begin(), words[i].begin()+substr_len);
874 }
875 }
876 }
877
878 // check to see if shortname is unique
879 text_t fulldirname = filename_cat (gsdlhome, "collect", shortname);
880 if (directory_exists (fulldirname)) {
881 int version = 0;
882 text_t newname;
883 do {
884 version ++;
885 newname = shortname;
886 newname.push_back ('v');
887 newname.appendint (version);
888 fulldirname = filename_cat (gsdlhome, "collect", newname);
889 } while (directory_exists (fulldirname));
890
891 shortname = newname;
892 }
893
894 return shortname;
895}
896
897// tests if collection is write protected (currently just checks if
898// collect.cfg file is writable
899bool collectoraction::collection_protected (const text_t &collection) {
900 text_t cfgfile = filename_cat(gsdlhome, "collect", collection, "etc", "collect.cfg");
901 if (file_writable(cfgfile)) return false;
902 return true;
903}
Note: See TracBrowser for help on using the repository browser.