[11998] | 1 | /**********************************************************************
|
---|
| 2 | *
|
---|
| 3 | * wizardaction.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 | #include "gsdl_modules_cfg.h"
|
---|
[21490] | 27 | #ifdef GSDL_USE_WIZARD_ACTION
|
---|
[11998] | 28 |
|
---|
| 29 | // note that the wizardaction relies on having direct access to a
|
---|
| 30 | // collections configuration file. this breaks the separation between
|
---|
| 31 | // receptionist and collection server and so is not suitable (at least
|
---|
| 32 | // in its current form) for use when collection servers are separate
|
---|
| 33 | // from the receptionist (e.g. when using the CORBA protocol).
|
---|
| 34 |
|
---|
| 35 | // following line required to get fstream.filedesc() on darwin (Mac OS X)
|
---|
| 36 | #define _STREAM_COMPAT 1
|
---|
| 37 | // required for utsname on solaris???
|
---|
| 38 | #define _XOPEN_SOURCE 1
|
---|
[19821] | 39 | // This was added for Solaris, but it makes things worse on Solaris for me...
|
---|
| 40 | // #define _XOPEN_SOURCE_EXTENDED 1
|
---|
[11998] | 41 |
|
---|
| 42 | #include "wizardaction.h"
|
---|
| 43 | #include "OIDtools.h"
|
---|
| 44 | #include "fileutil.h"
|
---|
| 45 | #include "cfgread.h"
|
---|
| 46 | #include "gsdltools.h"
|
---|
| 47 | #include "gsdltimes.h"
|
---|
| 48 | #include "argdb.h"
|
---|
| 49 | #include "cgiutils.h"
|
---|
| 50 | #include <stdio.h>
|
---|
| 51 | #include <fcntl.h>
|
---|
| 52 |
|
---|
| 53 | #if !defined (__WIN32__)
|
---|
| 54 | #include <sys/utsname.h>
|
---|
| 55 | #include <unistd.h>
|
---|
| 56 | #endif
|
---|
| 57 |
|
---|
| 58 | wizardaction::wizardaction () {
|
---|
| 59 |
|
---|
| 60 | recpt = NULL;
|
---|
| 61 | disabled = true;
|
---|
| 62 |
|
---|
| 63 | macro_prefix = "";
|
---|
| 64 | }
|
---|
| 65 |
|
---|
| 66 | wizardaction::~wizardaction () {
|
---|
| 67 | }
|
---|
| 68 |
|
---|
| 69 | void wizardaction::configure (const text_t &key, const text_tarray &cfgline) {
|
---|
| 70 |
|
---|
| 71 | const text_t& action_name = get_action_name();
|
---|
| 72 |
|
---|
| 73 | if ((key == action_name) && (cfgline.size() == 1) &&
|
---|
| 74 | (cfgline[0] == "true" || cfgline[0] == "on" || cfgline[0] == "enabled")) {
|
---|
| 75 | disabled = false;
|
---|
| 76 | } else {
|
---|
| 77 | // call the parent class to deal with the things which
|
---|
| 78 | // are not dealt with here
|
---|
| 79 | action::configure (key, cfgline);
|
---|
| 80 | }
|
---|
| 81 | }
|
---|
| 82 |
|
---|
| 83 |
|
---|
| 84 | bool wizardaction::init (ostream & /*logout*/) {
|
---|
| 85 |
|
---|
[16910] | 86 | return set_gsdl_env_vars(gsdlhome);
|
---|
[11998] | 87 | }
|
---|
| 88 |
|
---|
| 89 |
|
---|
| 90 | void wizardaction::get_cgihead_info (cgiargsclass &/*args*/, recptprotolistclass * /*protos*/,
|
---|
| 91 | response_t &response,text_t &response_data,
|
---|
| 92 | ostream &/*logout*/) {
|
---|
| 93 | response = content;
|
---|
| 94 | response_data = "text/html";
|
---|
| 95 | }
|
---|
| 96 |
|
---|
| 97 |
|
---|
| 98 | bool wizardaction::check_cgiargs (cgiargsinfoclass &argsinfo, cgiargsclass &args,
|
---|
| 99 | recptprotolistclass * /*protos*/, ostream &logout) {
|
---|
| 100 |
|
---|
| 101 | text_t current_page = args["p"];
|
---|
| 102 |
|
---|
| 103 | if (current_page != "intro" &&
|
---|
| 104 | current_page != "bildframe1" && current_page != "new" && current_page != "select") {
|
---|
| 105 | // update arguments that were saved to the harddrive
|
---|
| 106 | text_tmap saved_args;
|
---|
| 107 |
|
---|
| 108 | // update the argdb database with any arguments that were set
|
---|
| 109 | // by previous page as denoted by prefix (eg. di1 or bc1)
|
---|
| 110 |
|
---|
| 111 | cgiargsclass::const_iterator args_here = args.begin();
|
---|
| 112 | cgiargsclass::const_iterator args_end = args.end();
|
---|
| 113 |
|
---|
| 114 | while (args_here != args_end) {
|
---|
| 115 | text_t args_name = (*args_here).first;
|
---|
| 116 |
|
---|
| 117 | int prefix_len = macro_prefix.size();
|
---|
| 118 |
|
---|
| 119 | text_t args_prefix = substr(args_name.begin(),args_name.begin()+prefix_len);
|
---|
| 120 |
|
---|
| 121 | if (args_prefix == macro_prefix) {
|
---|
| 122 | saved_args[args_name] = args[args_name];
|
---|
| 123 | }
|
---|
| 124 | ++args_here;
|
---|
| 125 | }
|
---|
| 126 |
|
---|
[19062] | 127 | text_t argfile = filename_cat(gsdlhome, "tmp", args[macro_prefix+"tmp"], "argdb.gdb");
|
---|
[11998] | 128 | argdb *args_on_disk = new argdb(argfile);
|
---|
| 129 | if (!args_on_disk->update_args(saved_args)) {
|
---|
| 130 | // error
|
---|
| 131 | logout << "wizardaction: argdb::update_args failed (" << argfile << ")\n";
|
---|
| 132 | }
|
---|
| 133 |
|
---|
| 134 | // update args from argdb
|
---|
| 135 | saved_args.erase(saved_args.begin(), saved_args.end());
|
---|
| 136 | if (!args_on_disk->get_args(saved_args)) {
|
---|
| 137 | // error
|
---|
| 138 | logout << "wizardaction: argdb::get_args failed (" << argfile << ")\n";
|
---|
| 139 | }
|
---|
| 140 | delete args_on_disk;
|
---|
| 141 |
|
---|
| 142 | text_tmap::iterator sa_here = saved_args.begin();
|
---|
| 143 | text_tmap::iterator sa_end = saved_args.end();
|
---|
| 144 | while (sa_here != sa_end) {
|
---|
| 145 | if (!(*sa_here).second.empty()) {
|
---|
| 146 | args[(*sa_here).first] = (*sa_here).second;
|
---|
| 147 | }
|
---|
| 148 | ++sa_here;
|
---|
| 149 | } bool first = true;
|
---|
| 150 |
|
---|
| 151 | }
|
---|
[12082] | 152 |
|
---|
| 153 | return true;
|
---|
[11998] | 154 | }
|
---|
| 155 |
|
---|
| 156 | // tests if collection is write protected (currently just checks if
|
---|
| 157 | // collect.cfg file is writable
|
---|
| 158 | bool wizardaction::collection_protected (const text_t &collection) {
|
---|
[16310] | 159 | text_t cfgfile = filename_cat(collecthome, collection, "etc", "collect.cfg");
|
---|
[11998] | 160 | if (file_writable(cfgfile)) return false;
|
---|
| 161 | return true;
|
---|
| 162 | }
|
---|
| 163 |
|
---|
| 164 | // set the _statusline_ macro
|
---|
| 165 | void wizardaction::set_statusline (displayclass &disp, cgiargsclass &args, ostream & /*logout*/) {
|
---|
| 166 |
|
---|
| 167 | // the build command creates .bld.download, .bld.import, and .bld.build files (in that
|
---|
| 168 | // order) and deletes them (also in that order) when each stage is complete. the .bld
|
---|
| 169 | // file is the concatenation of all these files.
|
---|
| 170 | text_t bld_file = filename_cat (gsdlhome, "tmp", args[macro_prefix+"tmp"], args[macro_prefix+"dirname"] + ".bld");
|
---|
| 171 | text_t statusline;
|
---|
| 172 |
|
---|
| 173 | if (file_exists (bld_file + ".download")) {
|
---|
| 174 | statusline = "_collector:textdownloadingfiles_<br>\n";
|
---|
| 175 | statusline += dm_safe(file_tail(bld_file + ".download", 1, 0));
|
---|
| 176 | } else if (file_exists (bld_file + ".import")) {
|
---|
| 177 | statusline = "_collector:textimportingcollection_<br>\n";
|
---|
| 178 | statusline += dm_safe(file_tail(bld_file + ".import", 1, 0));
|
---|
| 179 | } else if (file_exists (bld_file + ".build")) {
|
---|
| 180 | statusline = "_collector:textbuildingcollection_<br>\n";
|
---|
| 181 | statusline += dm_safe(file_tail(bld_file + ".build", 1, 0));
|
---|
| 182 | } else {
|
---|
| 183 | statusline += "_collector:textcreatingcollection_<br>\n";
|
---|
| 184 | statusline += dm_safe(file_tail(bld_file, 1, 0));
|
---|
| 185 | }
|
---|
| 186 |
|
---|
| 187 | disp.setmacro ("statusline", "collector", statusline);
|
---|
| 188 | disp.setmacro ("statusline", "depositor", statusline);
|
---|
| 189 | }
|
---|
| 190 |
|
---|
| 191 |
|
---|
| 192 | // if sw = 0 replace all carriage returns in intext with the string "\n"
|
---|
| 193 | // else replace all occurances of "\n" with a carriage return
|
---|
| 194 | text_t wizardaction::carriage_replace (const text_t &intext, int sw) {
|
---|
| 195 |
|
---|
| 196 | text_t outtext;
|
---|
| 197 | text_t::const_iterator here = intext.begin();
|
---|
| 198 | text_t::const_iterator end = intext.end();
|
---|
| 199 | while (here != end) {
|
---|
| 200 | if (sw == 0) {
|
---|
| 201 | if (*here == '\n') {
|
---|
| 202 | if ((here+1) != end && *(here+1) == '\r') ++here;
|
---|
| 203 | outtext += "\\n";
|
---|
| 204 | } else if (*here == '\r') {
|
---|
| 205 | if ((here+1) != end && *(here+1) == '\n') ++here;
|
---|
| 206 | outtext += "\\n";
|
---|
| 207 | } else {
|
---|
| 208 | outtext.push_back (*here);
|
---|
| 209 | }
|
---|
| 210 | } else if (*here == '\\' && (here+1) != end && *(here+1) == 'n') {
|
---|
| 211 | outtext.push_back ('\n');
|
---|
| 212 | ++here;
|
---|
| 213 | } else {
|
---|
| 214 | outtext.push_back (*here);
|
---|
| 215 | }
|
---|
| 216 | ++here;
|
---|
| 217 | }
|
---|
| 218 | return outtext;
|
---|
| 219 | }
|
---|
| 220 |
|
---|
| 221 |
|
---|
| 222 | // create a short directory name from fullname
|
---|
| 223 | text_t wizardaction::get_directory_name (const text_t &fullname) {
|
---|
| 224 |
|
---|
| 225 | text_t shortname;
|
---|
| 226 | if (fullname.empty()) {
|
---|
| 227 | shortname = "coll";
|
---|
| 228 |
|
---|
| 229 | } else {
|
---|
| 230 |
|
---|
| 231 | // first make all lowercase and remove any dodgy characters
|
---|
| 232 | // (i.e. anything not [a-z]
|
---|
| 233 | text_t::const_iterator here = fullname.begin();
|
---|
| 234 | text_t::const_iterator end = fullname.end();
|
---|
| 235 | while (here != end) {
|
---|
| 236 | if ((*here >= 'A' && *here <= 'Z') || (*here >= 'a' && *here <= 'z') ||
|
---|
| 237 | (*here == ' ')) {
|
---|
| 238 | if (*here >= 'A' && *here <= 'Z') shortname.push_back (*here+32);
|
---|
| 239 | else if (*here == ' ') {
|
---|
| 240 | while ((*(here+1)) == ' ') ++here;
|
---|
| 241 | shortname.push_back (*here);
|
---|
| 242 | } else shortname.push_back (*here);
|
---|
| 243 | }
|
---|
| 244 | ++here;
|
---|
| 245 | }
|
---|
| 246 |
|
---|
| 247 | text_tarray words;
|
---|
| 248 | splitchar (shortname.begin(), shortname.end(), ' ', words);
|
---|
| 249 | int num_words = words.size();
|
---|
| 250 |
|
---|
| 251 | if (num_words == 0) {
|
---|
| 252 | shortname = "coll";
|
---|
| 253 |
|
---|
| 254 | } else {
|
---|
| 255 |
|
---|
| 256 | shortname.clear();
|
---|
| 257 | int use_words = (num_words <= 6) ? num_words : 6;
|
---|
| 258 | unsigned int substr_len = 6 / use_words;
|
---|
| 259 |
|
---|
| 260 | for (int i = 0; i < use_words; ++i) {
|
---|
| 261 | if (words[i].size() < substr_len) shortname += words[i];
|
---|
| 262 | else shortname += substr (words[i].begin(), words[i].begin()+substr_len);
|
---|
| 263 | }
|
---|
| 264 | }
|
---|
| 265 | }
|
---|
| 266 |
|
---|
| 267 | // check to see if shortname is unique
|
---|
[16310] | 268 | text_t fulldirname = filename_cat (collecthome, shortname);
|
---|
[11998] | 269 | if (directory_exists (fulldirname)) {
|
---|
| 270 | int version = 0;
|
---|
| 271 | text_t newname;
|
---|
| 272 | do {
|
---|
| 273 | ++version;
|
---|
| 274 | newname = shortname;
|
---|
| 275 | newname.push_back ('v');
|
---|
| 276 | newname.appendint (version);
|
---|
[16310] | 277 | fulldirname = filename_cat (collecthome, newname);
|
---|
[11998] | 278 | } while (directory_exists (fulldirname));
|
---|
| 279 |
|
---|
| 280 | shortname = newname;
|
---|
| 281 | }
|
---|
| 282 |
|
---|
| 283 | return shortname;
|
---|
| 284 | }
|
---|
| 285 |
|
---|
| 286 | // assigns a temporary directory name for this collector session
|
---|
| 287 | // and creates temporary directory
|
---|
| 288 | // returns false if it couldn't create the directory
|
---|
| 289 | bool wizardaction::assign_tmpname (cgiargsclass &args, ostream &logout) {
|
---|
| 290 |
|
---|
| 291 | int i = 0;
|
---|
| 292 | text_t tmpname = "tbuild";
|
---|
| 293 | while (directory_exists (filename_cat (gsdlhome, "tmp", tmpname + text_t(i)))) {
|
---|
| 294 | ++i;
|
---|
| 295 | }
|
---|
| 296 | tmpname.appendint (i);
|
---|
| 297 |
|
---|
| 298 | text_t fulltmpdir = filename_cat (gsdlhome, "tmp", tmpname);
|
---|
| 299 | if (!mk_dir (fulltmpdir)) {
|
---|
| 300 | outconvertclass text_t2ascii;
|
---|
[12019] | 301 | logout << text_t2ascii << "wizardaction::assign_tmpname unable to create directory ("
|
---|
[11998] | 302 | << fulltmpdir << ")\n";
|
---|
| 303 | return false;
|
---|
| 304 | }
|
---|
| 305 |
|
---|
| 306 | args[macro_prefix + "tmp"] = tmpname;
|
---|
| 307 | return true;
|
---|
| 308 | }
|
---|
| 309 |
|
---|
| 310 | // set the _fullnamemenu_ macro (and _warnindex_ and _selectedindex_ if
|
---|
| 311 | // we're on the "srce" page)
|
---|
| 312 | void wizardaction::set_fullnamemenu (displayclass &disp, cgiargsclass &args,
|
---|
| 313 | recptprotolistclass *protos, ostream &logout) {
|
---|
| 314 |
|
---|
| 315 | if (recpt == NULL) {
|
---|
[12575] | 316 | logout << "ERROR (wizardaction::set_fullnamemenu): This action does not contain\n"
|
---|
[11998] | 317 | << " information about any receptionists. The method set_receptionist was\n"
|
---|
| 318 | << " probably not called from the module which instantiated this action.\n";
|
---|
| 319 | return;
|
---|
| 320 | }
|
---|
| 321 |
|
---|
| 322 | text_t ¤t_page = args["p"];
|
---|
| 323 | text_t currentname = args[macro_prefix+"dirname"];
|
---|
| 324 | if (current_page == "srce") currentname = args[macro_prefix + "clonecol"];
|
---|
| 325 |
|
---|
| 326 | text_tarray dirnames;
|
---|
| 327 | text_tarray fullnames;
|
---|
| 328 | vector<bool> write_protected;
|
---|
| 329 | text_tarray build_type;
|
---|
| 330 |
|
---|
| 331 | bool is_selected = false;
|
---|
| 332 | int selected_index = 0;
|
---|
| 333 | int index = 0;
|
---|
| 334 |
|
---|
| 335 | recptprotolistclass::iterator rprotolist_here = protos->begin();
|
---|
| 336 | recptprotolistclass::iterator rprotolist_end = protos->end();
|
---|
| 337 | while (rprotolist_here != rprotolist_end) {
|
---|
| 338 | if ((*rprotolist_here).p != NULL) {
|
---|
| 339 |
|
---|
| 340 | // don't include z39.50 collections
|
---|
| 341 | comerror_t err = noError;
|
---|
| 342 | if ((*rprotolist_here).p->get_protocol_name (err) == "z3950proto") {
|
---|
| 343 | ++rprotolist_here;
|
---|
| 344 | continue;
|
---|
| 345 | }
|
---|
| 346 |
|
---|
| 347 | text_tarray collist;
|
---|
| 348 | (*rprotolist_here).p->get_collection_list (collist, err, logout);
|
---|
| 349 | if (err == noError) {
|
---|
| 350 | text_tarray::iterator collist_here = collist.begin();
|
---|
| 351 | text_tarray::iterator collist_end = collist.end();
|
---|
| 352 | while (collist_here != collist_end) {
|
---|
| 353 | ColInfoResponse_t *cinfo = recpt->get_collectinfo_ptr ((*rprotolist_here).p, *collist_here, logout);
|
---|
| 354 | if (cinfo != NULL) {
|
---|
| 355 | text_t collectionname = cinfo->get_collectionmeta("collectionname", args["l"]);
|
---|
| 356 | if (collectionname.empty()) {
|
---|
| 357 | collectionname = *collist_here;
|
---|
| 358 | }
|
---|
| 359 | dirnames.push_back(*collist_here);
|
---|
| 360 | fullnames.push_back(collectionname);
|
---|
| 361 | // check to see if the collection is writable
|
---|
| 362 | if (collection_protected (*collist_here)) write_protected.push_back(true);
|
---|
| 363 | else write_protected.push_back(false);
|
---|
| 364 |
|
---|
| 365 | // remember build type for collection (mg, mgpp, lucene, ...)
|
---|
| 366 | // used to determine cgi arg 'ct' later on and minus option to 'build'
|
---|
| 367 | build_type.push_back(cinfo->buildType);
|
---|
| 368 |
|
---|
| 369 | if (*collist_here == currentname) {
|
---|
| 370 | is_selected = true;
|
---|
| 371 | selected_index = index;
|
---|
| 372 | }
|
---|
| 373 | ++index;
|
---|
| 374 | }
|
---|
| 375 | ++collist_here;
|
---|
| 376 | }
|
---|
| 377 | }
|
---|
| 378 | }
|
---|
| 379 | ++rprotolist_here;
|
---|
| 380 | }
|
---|
| 381 |
|
---|
| 382 | bool first = true;
|
---|
| 383 |
|
---|
| 384 | text_t warnindex;
|
---|
| 385 | text_t fullnamemenu = "<select name=\""+macro_prefix+"dirname\" onChange=\"menuchange();\">\n";
|
---|
| 386 | text_t buildtype_jsarray = "var buildtype = new Array(";
|
---|
| 387 |
|
---|
[17079] | 388 | fullnamemenu += "<option value=\"\">_textselectoption_</option>\n";
|
---|
[11998] | 389 | buildtype_jsarray += "\"\" ";
|
---|
| 390 |
|
---|
| 391 | for (int i = 0; i < index; ++i) {
|
---|
| 392 | // don't want write protected collections in list on "change existing
|
---|
| 393 | // collection" page
|
---|
| 394 | if (write_protected[i] && current_page == "existing") continue;
|
---|
| 395 | fullnamemenu += "<option value=\"" + dirnames[i] + "\"";
|
---|
| 396 | if (is_selected && i == selected_index) {
|
---|
| 397 | fullnamemenu += " selected";
|
---|
| 398 | ++selected_index;
|
---|
| 399 | is_selected = false;
|
---|
| 400 | }
|
---|
| 401 | fullnamemenu.push_back ('>');
|
---|
[12475] | 402 | fullnamemenu += fullnames[i] + " ("+dirnames[i]+")";
|
---|
[11998] | 403 | fullnamemenu.push_back ('\n');
|
---|
| 404 |
|
---|
| 405 | buildtype_jsarray += ", \"" + build_type[i] + "\"";
|
---|
| 406 |
|
---|
| 407 | first = false;
|
---|
| 408 | }
|
---|
| 409 | fullnamemenu += "</select>\n";
|
---|
| 410 |
|
---|
| 411 | buildtype_jsarray += ");";
|
---|
| 412 |
|
---|
| 413 | text_t action_name = get_action_name();
|
---|
| 414 | disp.setmacro ("fullnamemenu", action_name, fullnamemenu);
|
---|
| 415 | disp.setmacro ("buildtypearray", action_name, buildtype_jsarray);
|
---|
| 416 | }
|
---|
| 417 |
|
---|
| 418 | // checks to see if any of the plugins in pluginset occur in
|
---|
| 419 | // collections configuration file
|
---|
| 420 | bool wizardaction::uses_weird_plugin (const text_t &collection) {
|
---|
| 421 |
|
---|
| 422 | text_tset pluginset;
|
---|
| 423 | pluginset.insert ("HBPlug");
|
---|
| 424 |
|
---|
| 425 | text_t cfgfile_content;
|
---|
[16310] | 426 | text_t cfgfile_name = filename_cat (collecthome, collection, "etc", "collect.cfg");
|
---|
[11998] | 427 | text_t pluginstr, pluginname;
|
---|
| 428 |
|
---|
| 429 | if (read_file (cfgfile_name, cfgfile_content)) {
|
---|
| 430 | text_t::const_iterator here = cfgfile_content.begin();
|
---|
| 431 | text_t::const_iterator end = cfgfile_content.end();
|
---|
| 432 | while (here != end) {
|
---|
| 433 | here = findchar (here, end, 'p');
|
---|
| 434 | if (here == end) break;
|
---|
| 435 | if ((here+6 < end) && (substr (here, here+6) == "plugin")) {
|
---|
| 436 | getdelimitstr (here+6, end, '\n', pluginstr);
|
---|
| 437 | text_t::const_iterator hp = pluginstr.begin();
|
---|
| 438 | text_t::const_iterator ep = pluginstr.end();
|
---|
| 439 | bool found = false;
|
---|
| 440 | // remove any leading whitespace, trailing options etc.
|
---|
| 441 | while (hp != ep) {
|
---|
| 442 | if (*hp == '\t' || *hp == ' ' || *hp == '\n') {
|
---|
| 443 | if (found) break;
|
---|
| 444 | } else {
|
---|
| 445 | pluginname.push_back (*hp);
|
---|
| 446 | found = true;
|
---|
| 447 | }
|
---|
| 448 | ++hp;
|
---|
| 449 | }
|
---|
| 450 | text_tset::const_iterator it = pluginset.find (pluginname);
|
---|
| 451 | if (it != pluginset.end()) return true; // found matching plugin
|
---|
| 452 | pluginname.clear();
|
---|
| 453 | }
|
---|
| 454 | ++here;
|
---|
| 455 | }
|
---|
| 456 | }
|
---|
| 457 | return false;
|
---|
| 458 | }
|
---|
| 459 |
|
---|
| 460 | void wizardaction::gsdl_build (cgiargsclass &args, ostream &logout) {
|
---|
| 461 |
|
---|
| 462 | outconvertclass text_t2ascii;
|
---|
| 463 |
|
---|
| 464 | //check to see if the tbuild directory exists
|
---|
| 465 | text_t tmpdir = filename_cat (gsdlhome, "tmp", args[macro_prefix+"tmp"]);
|
---|
| 466 | if (!directory_exists (tmpdir)) {
|
---|
| 467 | message = "tmpfail";
|
---|
| 468 | return;
|
---|
| 469 | }
|
---|
| 470 |
|
---|
| 471 | //check to see if collection name specified
|
---|
| 472 | text_t &collection = args[macro_prefix+"dirname"];
|
---|
| 473 | if (collection.empty()) {
|
---|
| 474 | message = "nocollection";
|
---|
| 475 | return;
|
---|
| 476 | }
|
---|
| 477 |
|
---|
| 478 | // check for a .build file - if it exists then we've already built
|
---|
| 479 | // the collection (or are in the process of building it)
|
---|
| 480 | text_t buildfile = filename_cat (tmpdir, ".build");
|
---|
| 481 | if (file_exists (buildfile)) {
|
---|
| 482 | return;
|
---|
| 483 | } else {
|
---|
| 484 | // create the .build file (this file is just a place holder to let any future
|
---|
| 485 | // pages know that we've already been here)
|
---|
| 486 | char *buildfilec = buildfile.getcstr();
|
---|
| 487 | ofstream bfile_out (buildfilec);
|
---|
| 488 | delete []buildfilec;
|
---|
| 489 | if (bfile_out) {
|
---|
| 490 | bfile_out << "collection building\n";
|
---|
| 491 | bfile_out.close();
|
---|
| 492 | } else {
|
---|
| 493 | message = "tmpfail";
|
---|
| 494 | return;
|
---|
| 495 | }
|
---|
| 496 | }
|
---|
| 497 |
|
---|
| 498 | //FLAG!
|
---|
| 499 | const recptconf &rcinfo = recpt->get_configinfo ();
|
---|
| 500 |
|
---|
| 501 | // create the event header file if LogEvents, EmailEvents or
|
---|
| 502 | // EmailUserEvents options are turned on.
|
---|
| 503 | bool logevents =
|
---|
| 504 | (rcinfo.LogEvents == CollectorEvents || rcinfo.LogEvents == AllEvents ||
|
---|
| 505 | rcinfo.EmailEvents == CollectorEvents || rcinfo.EmailEvents == AllEvents ||
|
---|
| 506 | rcinfo.EmailUserEvents);
|
---|
| 507 | text_t ehead_file = filename_cat (tmpdir, "ehead.txt");
|
---|
| 508 | if (logevents) {
|
---|
| 509 | if (!create_event_header_file (ehead_file, args, logout)) {
|
---|
| 510 | logevents = false;
|
---|
| 511 | }
|
---|
| 512 | }
|
---|
| 513 |
|
---|
| 514 | text_t collectdir = get_collectdir (args);
|
---|
| 515 |
|
---|
| 516 | // set up build options
|
---|
| 517 | //text_t options = "-make_writable -remove_import -out \"";
|
---|
| 518 | text_t options = "-make_writable -out \"";
|
---|
| 519 | options += filename_cat (tmpdir, collection + ".bld");
|
---|
| 520 | options += "\" -collectdir \"" + collectdir + "\" -statsfile \"";
|
---|
| 521 | options += filename_cat(collectdir, collection, "etc", "import.log") + "\"";
|
---|
| 522 |
|
---|
| 523 | if (args[macro_prefix+"esrce"] == 1) {
|
---|
| 524 | // we're adding data to an existing collection
|
---|
| 525 | options += " -save_archives -append -manifest";
|
---|
| 526 | }
|
---|
| 527 |
|
---|
| 528 | text_tarray inputvalues, inputtypes;
|
---|
| 529 | splitchar (args[macro_prefix+"input"].begin(), args[macro_prefix+"input"].end(), ',', inputvalues);
|
---|
| 530 | splitchar (args[macro_prefix+"inputtype"].begin(), args[macro_prefix+"inputtype"].end(), ',', inputtypes);
|
---|
| 531 | int numvalues = inputvalues.size();
|
---|
| 532 | int numtypes = inputtypes.size();
|
---|
| 533 | for (int i = 0; i < numvalues; ++i) {
|
---|
| 534 | if (!inputvalues[i].empty()) {
|
---|
| 535 | text_t type = "file://"; // default
|
---|
| 536 | if (i < numtypes) type = inputtypes[i];
|
---|
| 537 | options += " -download \"" +
|
---|
| 538 | remove_trailing_slashes(type + format_url(decode_commas(inputvalues[i]))) + "\"";
|
---|
| 539 | }
|
---|
| 540 | }
|
---|
| 541 |
|
---|
| 542 | if (logevents) {
|
---|
| 543 | if (rcinfo.LogEvents == CollectorEvents || rcinfo.LogEvents == AllEvents)
|
---|
| 544 | options += " -log_events";
|
---|
| 545 | if (rcinfo.EmailEvents == CollectorEvents || rcinfo.EmailEvents == AllEvents) {
|
---|
| 546 | options += " -mail_server " + rcinfo.MailServer;
|
---|
| 547 | options += " -email_events " + rcinfo.maintainer;
|
---|
| 548 | if (rcinfo.EmailUserEvents) options += "," + args[macro_prefix+"contactemail"];
|
---|
| 549 | } else if (rcinfo.EmailUserEvents) {
|
---|
| 550 | options += " -mail_server " + rcinfo.MailServer;
|
---|
| 551 | options += " -email_events " + args[macro_prefix+"contactemail"];
|
---|
| 552 | }
|
---|
| 553 | options += " -event_header " + ehead_file;
|
---|
| 554 | }
|
---|
| 555 |
|
---|
| 556 | text_t indextype = args[macro_prefix+"buildtype"];
|
---|
| 557 | if(indextype == "") {
|
---|
[21324] | 558 | #ifdef ENABLE_MG
|
---|
[11998] | 559 | indextype = "mg";
|
---|
[21324] | 560 | #else
|
---|
| 561 | cerr << "Unable to choose mg as the default indextype, since the Greenstone installation was not compiled with MG enabled." << endl;
|
---|
| 562 | #endif
|
---|
[11998] | 563 | }
|
---|
| 564 | options += " -indextype \"" + indextype + "\"";
|
---|
| 565 |
|
---|
| 566 | text_t optionfile = filename_cat (tmpdir, "build.opt");
|
---|
| 567 | char *optionfilec = optionfile.getcstr();
|
---|
| 568 | ofstream ofile_out (optionfilec);
|
---|
| 569 | delete []optionfilec;
|
---|
| 570 | if (!ofile_out) {
|
---|
| 571 | message = "tmpfail";
|
---|
| 572 | return;
|
---|
| 573 | }
|
---|
| 574 | ofile_out << text_t2ascii << options << "\n";
|
---|
| 575 | ofile_out.close();
|
---|
| 576 |
|
---|
| 577 | // if we're altering an existing collection we need to kill off
|
---|
| 578 | // the existing collection server - we do this for the local library
|
---|
| 579 | // (and any other persistent version of the library) as the existing
|
---|
[15597] | 580 | // database file can't be deleted while the collection server holds it open
|
---|
[11998] | 581 | if ((args[macro_prefix+"econf"] == 1) || (args[macro_prefix+"esrce"] == 1)) {
|
---|
| 582 | remove_colservr (collection, logout);
|
---|
| 583 | }
|
---|
| 584 |
|
---|
| 585 | // set up the build command - build.bat has some issues with quoting
|
---|
| 586 | // on win2k when gsdlhome contains spaces so we'll avoid using
|
---|
| 587 | // "perl -S" here in favor of calling the "build" perl script explicitly
|
---|
| 588 | text_t build_cmd = "perl \"" + filename_cat (gsdlhome, "bin", "script", "build");
|
---|
| 589 | build_cmd += "\" -optionfile \"" + optionfile + "\" " + collection;
|
---|
| 590 |
|
---|
| 591 | // run build command in background (i.e. asynchronously)
|
---|
| 592 | gsdl_system (build_cmd, false, logout);
|
---|
| 593 |
|
---|
| 594 | }
|
---|
| 595 |
|
---|
| 596 | void wizardaction::gsdl_cancel_build (cgiargsclass &args, ostream &logout) {
|
---|
[12511] | 597 | // I really wanted to do what this perl script does from within the library
|
---|
[11998] | 598 | // c++ code. I ran into some problems though (like how do you write a portable
|
---|
| 599 | // "rm -r" in c++?). One day I'll spend some time sorting it out ... maybe.
|
---|
| 600 | text_t cancel_cmd = "perl -S cancel_build.pl -collectdir \"";
|
---|
| 601 | cancel_cmd += filename_cat (gsdlhome, "tmp", args[macro_prefix+"tmp"]) + "\" ";
|
---|
| 602 | cancel_cmd += args[macro_prefix+"dirname"];
|
---|
| 603 | // To be on the safe side we'll make this a synchronous call
|
---|
| 604 | // so that all tidying up is done before the user has a chance
|
---|
| 605 | // to do anything else (like start rebuilding their collection).
|
---|
| 606 | // This means that for a big collection where there's lots of
|
---|
| 607 | // stuff to delete etc. it might take a while before the "build
|
---|
| 608 | // cancelled" page appears.
|
---|
| 609 | gsdl_system (cancel_cmd, true, logout);
|
---|
| 610 | }
|
---|
| 611 |
|
---|
| 612 | text_t wizardaction::get_collectdir (cgiargsclass &args)
|
---|
| 613 | {
|
---|
| 614 | if ((args[macro_prefix+"econf"] == 1) || (args[macro_prefix+"esrce"] == 1)) {
|
---|
| 615 | // we're adding to a collection in place
|
---|
[16310] | 616 | return collecthome;
|
---|
[11998] | 617 | }
|
---|
| 618 | else {
|
---|
| 619 | return filename_cat (gsdlhome, "tmp", args[macro_prefix+"tmp"]);
|
---|
| 620 | }
|
---|
| 621 | }
|
---|
| 622 |
|
---|
| 623 | // create and initialize a new collection server and
|
---|
| 624 | // add it to the null protocol.
|
---|
| 625 | void wizardaction::create_colserver (const text_t &collection, ostream &logout) {
|
---|
| 626 |
|
---|
| 627 | recptprotolistclass *protos = recpt->get_recptprotolist_ptr();
|
---|
| 628 | recptprotolistclass::iterator rprotolist_here = protos->begin();
|
---|
| 629 | recptprotolistclass::iterator rprotolist_end = protos->end();
|
---|
| 630 | while (rprotolist_here != rprotolist_end) {
|
---|
| 631 | comerror_t err = noError;
|
---|
| 632 | if ((*rprotolist_here).p != NULL) {
|
---|
| 633 | if ((*rprotolist_here).p->get_protocol_name (err) == "nullproto") {
|
---|
| 634 | // create collection server and add it to nullproto
|
---|
[16310] | 635 | (*rprotolist_here).p->add_collection (collection, recpt, gsdlhome, collecthome, dbhome);
|
---|
[11998] | 636 | // make sure gsdlhome is configured
|
---|
| 637 | text_tarray tmp;
|
---|
| 638 | tmp.push_back (gsdlhome);
|
---|
| 639 | (*rprotolist_here).p->configure ("gsdlhome", tmp, err);
|
---|
| 640 | // re-initialize the null protocol
|
---|
| 641 | if (!(*rprotolist_here).p->init (err, logout)) {
|
---|
| 642 | logout << "wizardaction::create_colserver: nullproto init failed\n";
|
---|
| 643 | }
|
---|
| 644 | return;
|
---|
| 645 | }
|
---|
| 646 | }
|
---|
| 647 | ++rprotolist_here;
|
---|
| 648 | }
|
---|
| 649 |
|
---|
| 650 | logout << "wizardaction::create_colserver: no valid nullproto found\n";
|
---|
| 651 | }
|
---|
| 652 |
|
---|
| 653 | // delete a collection server from the null protocol
|
---|
| 654 | void wizardaction::remove_colservr (const text_t &collection, ostream &logout) {
|
---|
| 655 |
|
---|
| 656 | recpt->uncache_collection (collection);
|
---|
| 657 |
|
---|
| 658 | recptprotolistclass *protos = recpt->get_recptprotolist_ptr();
|
---|
| 659 | recptprotolistclass::iterator rprotolist_here = protos->begin();
|
---|
| 660 | recptprotolistclass::iterator rprotolist_end = protos->end();
|
---|
| 661 | while (rprotolist_here != rprotolist_end) {
|
---|
| 662 | comerror_t err = noError;
|
---|
| 663 | if ((*rprotolist_here).p != NULL) {
|
---|
| 664 | if ((*rprotolist_here).p->get_protocol_name (err) == "nullproto") {
|
---|
| 665 | (*rprotolist_here).p->remove_collection (collection, logout);
|
---|
| 666 | return;
|
---|
| 667 | }
|
---|
| 668 | }
|
---|
| 669 | ++rprotolist_here;
|
---|
| 670 | }
|
---|
| 671 |
|
---|
| 672 | logout << "wizardaction::create_colserver: no valid nullproto found\n";
|
---|
| 673 | }
|
---|
| 674 |
|
---|
| 675 | bool wizardaction::create_event_header_file (const text_t &filename, cgiargsclass &args,
|
---|
| 676 | ostream &logout) {
|
---|
| 677 |
|
---|
| 678 | outconvertclass text_t2ascii;
|
---|
| 679 | char *filenamec = filename.getcstr();
|
---|
| 680 | ofstream eheadfile (filenamec);
|
---|
| 681 | delete []filenamec;
|
---|
| 682 |
|
---|
| 683 | if (eheadfile) {
|
---|
| 684 | eheadfile << text_t2ascii << get_event_header (args);
|
---|
| 685 | eheadfile.close();
|
---|
| 686 | return true;
|
---|
| 687 | }
|
---|
| 688 |
|
---|
| 689 | logout << text_t2ascii << "wizardaction::create_event_header ERROR: Couldn't create "
|
---|
| 690 | << "Event Header file " << filename << ". Event logging disabled\n";
|
---|
| 691 | return false;
|
---|
| 692 | }
|
---|
| 693 |
|
---|
| 694 | text_t wizardaction::get_event_header (cgiargsclass &args) {
|
---|
| 695 | text_t header = "Greenstone Username: " + args["un"] + "\n";
|
---|
| 696 | header += "Collection: " + args[macro_prefix+"dirname"] + "\n";
|
---|
| 697 | header += "Collection Creator: " + args[macro_prefix+"contactemail"] + "\n";
|
---|
| 698 | header += "GSDLHOME: " + gsdlhome + "\n";
|
---|
| 699 | header += "Build Location: " + get_collectdir(args) + "\n";
|
---|
| 700 |
|
---|
| 701 | return header;
|
---|
| 702 | }
|
---|
| 703 |
|
---|
| 704 |
|
---|
| 705 | // format_url simply strips "http://", "ftp://", or "file://" off the
|
---|
| 706 | // beginning of url if they're there
|
---|
| 707 | text_t wizardaction::format_url (const text_t &url) {
|
---|
| 708 | text_t::const_iterator begin = url.begin();
|
---|
| 709 | text_t::const_iterator end = url.end();
|
---|
| 710 |
|
---|
| 711 | if (url.size() >= 7) {
|
---|
| 712 | text_t prefix = substr(begin, begin+7);
|
---|
| 713 | if (prefix == "http://" || prefix == "file://") {
|
---|
| 714 | return substr(begin+7, end);
|
---|
| 715 | }
|
---|
| 716 | }
|
---|
| 717 | if (url.size() >= 6) {
|
---|
| 718 | if (substr(begin, begin+6) == "ftp://") {
|
---|
| 719 | return substr(begin+6, end);
|
---|
| 720 | }
|
---|
| 721 | }
|
---|
| 722 | return url;
|
---|
| 723 | }
|
---|
| 724 |
|
---|
| 725 | text_t wizardaction::remove_trailing_slashes (text_t str) {
|
---|
| 726 |
|
---|
| 727 | while (*(str.end()-1) == '\\') {
|
---|
| 728 | str.pop_back();
|
---|
| 729 | }
|
---|
| 730 | return str;
|
---|
| 731 | }
|
---|
| 732 |
|
---|
[21490] | 733 | #endif //GSDL_USE_WIZARD_ACTION
|
---|