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