root/main/trunk/greenstone2/runtime-src/src/w32server/cgiwrapper.cpp @ 22833

Revision 22833, 31.8 KB (checked in by ak19, 10 years ago)

Code for loading collections from the default Greenstone collect directory is already duplicated in new method load_collections_from_collectdir, so it's now being called. There were some minor changes to make the references to collecthome consistent for the default GS collectdir case. Also fixed the new method load_collections_from_collectdir method so that it works with collect groups (just as the code for the standard collect dir has been working for collectgroups), by not checking for the existence of build_cfg, since colgroups don't have this but ought to be loaded on the home page nevertheless.

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1/**********************************************************************
2 *
3 * cgiwrapper.cpp -- windows local library cgiwrapper
4 * Copyright (C) 1999  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 "text_t.h"
27
28#include <windows.h>
29#include <string.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <assert.h>
33#include <direct.h>
34#include "cgiwrapper.h"
35#include "netio.h"
36#include "wincgiutils.h"
37#include "settings.h"
38#include "fileutil.h"
39#include "parse.h"
40
41#include "gsdlconf.h"
42#include "maincfg.h"
43
44#if defined (GSDL_USE_OBJECTSPACE)
45#include <ospace\std\iostream>
46#include <ospace\std\fstream>
47#elif defined (GSDL_USE_IOS_H)
48#include <iostream.h>
49#include <fstream.h>
50#else
51#include <iostream>
52#include <fstream>
53#endif
54
55#include "receptionist.h"
56#include "nullproto.h"
57
58// actions
59#include "statusaction.h"
60#include "pageaction.h"
61#include "pingaction.h"
62#include "queryaction.h"
63#include "documentaction.h"
64#include "dynamicclassifieraction.h"
65#include "tipaction.h"
66#include "authenaction.h"
67#include "usersaction.h"
68#include "userdb.h"
69#include "extlinkaction.h"
70#include "collectoraction.h"
71#ifdef ENABLE_MGPP
72#include "phindaction.h"
73#endif
74#include "configaction.h"
75
76// browsers
77#include "vlistbrowserclass.h"
78#include "hlistbrowserclass.h"
79#include "datelistbrowserclass.h"
80#include "invbrowserclass.h"
81#include "pagedbrowserclass.h"
82#include "htmlbrowserclass.h"
83#include "phindbrowserclass.h"
84
85// the number of times the library has been accessed
86int libaccessnum = 0;
87
88// used to output the text from receptionist
89class textstreambuf : public streambuf
90{
91public:
92  textstreambuf ();
93  int sync ();
94  int overflow (int ch);
95  int underflow () {return EOF;}
96 
97  void tsbreset() {RInfo=NULL;casostr=NULL;}
98  void setrequestinfo (RequestInfoT *theRInfo) {RInfo=theRInfo;}
99  void cascadeoutput (ostream *thecasostr) {casostr=thecasostr;}
100 
101private:
102  RequestInfoT *RInfo;
103  ostream *casostr;
104#if !defined (GSDL_USE_IOS_H)
105  char buffer[256];
106#endif
107};
108
109textstreambuf::textstreambuf() {
110  tsbreset();
111#if !defined (GSDL_USE_IOS_H)
112  setp (&buffer[0], &buffer[255]);
113#else
114  if (base() == ebuf()) allocate();
115  setp (base(), ebuf());
116#endif
117};
118
119int textstreambuf::sync () {
120  if ((RInfo != NULL) &&
121      (Send_String_N(pbase(), pptr()-pbase(), RInfo) < 0)) {
122    RInfo = NULL;
123  }
124 
125  if (casostr != NULL) {
126    char *thepbase=pbase();
127    for (int i=0;i<(pptr()-pbase());++i) (*casostr).put(thepbase[i]);
128  }
129 
130  setp (pbase(), epptr());
131 
132  return 0;
133}
134
135int textstreambuf::overflow (int ch) {
136  if (sync () == EOF) return EOF;
137  if (ch != EOF) sputc (ch);
138  return 0;
139}
140
141
142// used to output all the log and error messages
143// from receptionist
144class logstreambuf : public streambuf
145{
146public:
147  logstreambuf ();
148  int sync ();
149  int overflow (int ch);
150  int underflow () {return EOF;}
151
152#if !defined (GSDL_USE_IOS_H)
153private:
154  char buffer[256];
155#endif
156};
157
158logstreambuf::logstreambuf () {
159#if !defined (GSDL_USE_IOS_H)
160  setp (&buffer[0], &buffer[255]);
161#else
162  if (base() == ebuf()) allocate();
163  setp (base(), ebuf());
164#endif
165}
166
167int logstreambuf::sync () {
168  if (gsdl_keep_log || gsdl_show_console) {
169    log_message ("LOCAL LIB MESSAGE: ");
170        log_message_N (pbase(), pptr()-pbase());
171  }
172
173  setp (pbase(), epptr());
174  return 0;
175}
176
177int logstreambuf::overflow (int ch) {
178  if (sync () == EOF) return EOF;
179  if (ch != EOF) sputc (ch);
180  return 0;
181}
182
183static void page_errormaincfg (const text_t &gsdlhome, const text_t &collection) {
184
185  if (collection.empty()) {
186    text_t message = "Error\n\n"
187      "The main.cfg configuration file could not be found. This file\n"
188      "should contain configuration information relating to the\n"
189      "setup of the interface. As this program is not being run\n"
190      "in collection specific mode the file should reside at\n" +
191      gsdlhome + "\\etc\\main.cfg.\n";
192
193    MessageBox(NULL, message.getcstr(),
194           "Greenstone Digital Library Software"
195           ,MB_OK|MB_SYSTEMMODAL);
196  } else {
197    text_t message = "Neither the collect.cfg or main.cfg configuration files could\n"
198      "be found. This file should contain configuration information\n"
199      "relating to the setup of the interface. As this cgi script is\n"
200      "being run in collection specific mode the file should reside\n"
201      "at either " + gsdlhome + "\\collect\\" + collection + "\\etc\\collect.cfg,\n" +
202      gsdlhome + "\\etc\\collect.cfg or " + gsdlhome + "\\etc\\main.cfg.\n";
203
204    MessageBox(NULL, message.getcstr(),
205           "Greenstone Digital Library Software"
206           ,MB_OK|MB_SYSTEMMODAL);
207  }
208}
209
210static void page_errorinit (const text_t &/*gsdlhome*/) {
211
212  text_t message = "Error\n\n"
213    "An error occurred during the initialisation of the Greenstone Digital\n"
214    "Library software. It is likely that the software has not been setup\n"
215    "correctly.\n";
216
217  MessageBox(NULL, message.getcstr(),
218         "Greenstone Digital Library Software"
219         ,MB_OK|MB_SYSTEMMODAL);
220}
221
222static void page_errorparseargs (const text_t &/*gsdlhome*/) {
223
224  text_t message = "Error\n\n"
225    "An error occurred during the parsing of the cgi arguments.\n";
226
227  MessageBox(NULL, message.getcstr(),
228         "Greenstone Digital Library Software"
229         ,MB_OK|MB_SYSTEMMODAL);
230}
231
232static void page_errorcgipage (const text_t &/*gsdlhome*/) {
233
234  text_t message = "Error\n\n"
235    "An error occurred during the construction of the cgi page.\n";
236
237  MessageBox(NULL, message.getcstr(),
238         "Greenstone Digital Library Software"
239         ,MB_OK|MB_SYSTEMMODAL);
240}
241
242// returns 0 if the directories can't be found
243// and the user wants to quit (it returns 1
244// if everything is ok)
245int checkdir (const text_t &thedir) {
246  UINT curerrormode;
247  int drive = _getdrive();
248  char cwd[1024];
249  char rootpath[4];
250  UINT drivetype;
251  char *cstrthedir = thedir.getcstr();
252  int returnvalue = 1;
253 
254  // make sure no rude error messages are presented to the user
255  curerrormode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
256 
257  // get the drive name
258  if (thedir.size() >= 2 && thedir[1] == ':') {
259    if (thedir[0] >= 'a' && thedir[0] <= 'z') {
260      drive = thedir[0] - 'a' + 1;
261     
262    } else if (thedir[0] >= 'A' && thedir[0] <= 'Z') {
263      drive = thedir[0] - 'A' + 1;
264    }
265  }
266 
267  // find the drive type
268  rootpath[0] = drive + 'A' - 1;
269  rootpath[1] = ':';
270  rootpath[2] = '\\';
271  rootpath[3] = '\0';
272  drivetype = GetDriveType (rootpath);
273 
274  // try and set this directory to be the current working
275  // directory
276  _getcwd(cwd, 1024);
277  while (_chdir(cstrthedir) != 0) {
278    // failed
279    if (drivetype == DRIVE_CDROM) {
280      // message to insert the cdrom
281      if (MessageBox (NULL,
282              "Please insert the Greenstone Digital Library\n"
283              "CD-ROM into the CD-ROM drive and press 'OK'.\n\n"
284              "If you don't have the CD-ROM press 'Cancel' to exit\n"
285              "this program.", "Greenstone Digital Library Software",
286              MB_OKCANCEL | MB_TASKMODAL) == IDCANCEL) {
287   
288    returnvalue = 0;
289    break;
290      }
291     
292    } else {
293      // message saying that the system was unable
294      // to find a certain directory
295      text_t message = "Failed to find the directory:\n\n" + thedir;
296      message += "\n\n"
297    "This directory is needed for the successful operation\n"
298    "of this software. Make sure it hasn't been deleted or\n"
299    "moved, and restart the software. You may need to\n"
300    "reinstall this software to correct the problem.";
301      char *cstrmessage = message.getcstr();
302     
303      MessageBox (NULL, cstrmessage, "Greenstone Digital Library Software",
304          MB_OK | MB_TASKMODAL);
305     
306      delete []cstrmessage;
307     
308      returnvalue = 0;
309      break;
310    }
311  }
312 
313  // revert to the previous error and cwd states
314  _chdir(cwd);
315  SetErrorMode(curerrormode);
316 
317  // free the allocated C string
318  delete []cstrthedir;
319 
320  return returnvalue;
321}
322
323
324// c-string version of checkdir for the outside
325// world
326int cstrcheckdir (char *cstrthedir) {
327  return checkdir (cstrthedir);
328}
329
330
331receptionist recpt;
332nullproto nproto;
333collectset *cservers = NULL;
334
335textstreambuf textstream;
336logstreambuf logstream;
337DWORD lastlibaccesstime;
338DWORD baseavailvirtual;
339text_t current_gsdlhome;
340text_t current_collecthome;
341colinfo_tmap translated_collectinfo;
342 
343statusaction *astatusaction = NULL;
344pageaction *apageaction = NULL;
345pingaction *apingaction = NULL;
346tipaction *atipaction = NULL;
347queryaction *aqueryaction = NULL;
348documentaction *adocumentaction = NULL;
349dynamicclassifieraction *adynamicclassifieraction = NULL;
350usersaction *ausersaction = NULL;
351extlinkaction *anextlinkaction = NULL;
352collectoraction *acollectoraction = NULL;
353authenaction *aauthenaction = NULL;
354#ifdef ENABLE_MGPP
355phindaction *aphindaction = NULL;
356#endif
357configaction *aconfigaction = NULL;
358vlistbrowserclass *avlistbrowserclass = NULL;
359hlistbrowserclass *ahlistbrowserclass = NULL;
360datelistbrowserclass *adatelistbrowserclass = NULL;
361invbrowserclass *ainvbrowserclass = NULL;
362pagedbrowserclass *apagedbrowserclass = NULL;
363htmlbrowserclass *ahtmlbrowserclass = NULL;
364phindbrowserclass *aphindbrowserclass = NULL;
365text_t userdbfile = NULL;
366userdbclass *udb = NULL;
367text_t keydbfile = NULL;
368keydbclass *kdb = NULL;
369
370
371// When (1) the "collecthome" collect dir is not the standard greenstone collect dir,
372// or when (2) this collecthome is specified in a section other than [gsdl] in the (lls/gli)site.cfg file,
373// this method gets called to load in that collect dir's collections into the server during gsdl_init
374static void load_collections_from_collectdir(
375    colinfo_tmap &translated_colinfo,
376    text_tset::const_iterator &colhere,
377    text_tset::const_iterator &colend,
378    text_tset &these_collections,
379    text_tset &dbhomes,
380    text_tset &clhomes,
381    text_tset &collections,
382    const text_t &my_gsdl_home,
383    const text_t &my_gsdl_collecthome,
384    const text_t &my_gsdl_dbhome)
385{   
386    these_collections.erase (these_collections.begin(), these_collections.end());
387    read_dir (my_gsdl_collecthome, these_collections);
388    colhere = these_collections.begin();
389    colend = these_collections.end();
390    while (colhere != colend) {     
391      if ((collections.find (*colhere)) == collections.end()) {
392        // make sure the build.cfg file is at gsdlhome (as it's possible that
393        // the collection appears at this gsdlhome only because it's gdbm
394        // file is installed here -- it's real gdbm will therefore be
395        // somewhere else).     
396       
397        // commenting out the following build_cfg test since the server won't know to load
398        // collection groups otherwise, as these don't have build_cfg files but ought to be loaded along
399        // with collections (the real test for whether something ought to be loaded--whether an item read
400        // in by read_dir is a collection or collection group--happens at a later time in the GS runtime code).
401       
402        //text_t build_cfg = filename_cat (my_gsdl_collecthome,*colhere, "index", "build.cfg");                     
403        //if (file_exists (build_cfg)) {
404          collections.insert (*colhere);
405
406          // since gsdl_collectinfo keys will be stuff like collection#1
407          // for a multiple volume collection we want to translate it
408          // so that the keys are the actual collection names
409          collectioninfo_t tmp;
410          tmp.gsdl_gsdlhome = my_gsdl_home;
411          tmp.gsdl_collecthome = my_gsdl_collecthome;
412          tmp.gsdl_dbhome = my_gsdl_dbhome;         
413          translated_colinfo[*colhere] = tmp;
414        //}
415      }
416      ++colhere;
417    }
418    dbhomes.insert (gsdl_dbhome);
419    clhomes.insert (gsdl_collecthome);
420}
421
422
423// returns 1 if successful, 0 if unsuccessful (note that as well as being
424// called when the server first starts up this function is called when the
425// "restart library" button is pressed)
426int gsdl_init (bool atStartup) {         
427  if (atStartup) {
428#if defined (GSDL_USE_IOS_H)
429    cerr = &logstream;
430    cout = &textstream;
431#else
432    cerr.rdbuf(&logstream);
433    cout.rdbuf(&textstream);
434#endif
435  }
436
437  // collection should be set to "" unless in collection specific mode -
438  // changing this to the name of the collection should be all that's
439  // required to create a collection specific receptionist
440  text_t collection = "";
441  text_tset dbhomes;
442  text_tset clhomes; // collecthome companion for dbhome
443  text_tset collections;
444
445  if (atStartup) {
446    // note the current time
447    lastlibaccesstime = GetTickCount();
448   
449    // before we do the init we should make sure
450    // that we can find the relevant directories
451    if (!checkdir (gsdl_gsdlhome + "\\")) return 0;
452    if (!checkdir (gsdl_collecthome + "\\")) return 0;
453    if (!checkdir (gsdl_gsdlhome + "\\macros\\")) return 0;
454  }   
455
456  // deleting cservers clears all the collection servers
457  if (cservers != NULL) delete cservers;
458
459  cservers = new collectset();
460
461  // get all collections from each gsdlhome (this relies
462  // on there not being more than one collection with the same
463  // name)
464  if (!collection.empty()) { 
465    // collection specific receptionist - one collection, one gsdlhome
466    collections.insert (collection);
467    dbhomes.insert (gsdl_dbhome);
468    clhomes.insert (gsdl_collecthome);
469    collectioninfo_t tmp;
470    tmp.gsdl_gsdlhome = gsdl_gsdlhome;
471    tmp.gsdl_collecthome = gsdl_collecthome;
472    tmp.gsdl_dbhome = gsdl_dbhome;
473    translated_collectinfo[collection] = tmp;
474
475  } else {
476    text_tset::const_iterator colhere;
477    text_tset::const_iterator colend;
478    text_tset these_collections;
479 
480    // First volume gsdlhome's
481    // read in all the collections from sections other than [gsdl] in the site config file (llssite/glisite)
482    colinfo_tmap::const_iterator this_info = gsdl_collectinfo.begin();
483    colinfo_tmap::const_iterator end_info = gsdl_collectinfo.end();
484    while (this_info != end_info) {
485      if (dbhomes.find ((*this_info).second.gsdl_dbhome) == dbhomes.end()) {
486            load_collections_from_collectdir(translated_collectinfo,
487                    colhere, colend, these_collections,
488                    dbhomes, clhomes, collections,
489                    (*this_info).second.gsdl_gsdlhome,
490                    (*this_info).second.gsdl_collecthome,
491                    (*this_info).second.gsdl_dbhome);   
492      }
493      ++this_info;
494    }
495   
496    // if non-standard collecthome under [gsdl] section of site config file (llssite or glisite),
497    // then need to read in all the collections from this collecthome
498    if(gsdl_collecthome != filename_cat(gsdl_gsdlhome,"collect")) {
499        load_collections_from_collectdir(translated_collectinfo,
500                colhere, colend, these_collections,
501                dbhomes, clhomes, collections,
502                gsdl_gsdlhome, gsdl_collecthome, gsdl_dbhome);     
503    }   
504 
505  // But when the default greenstone collect dir (gsdlhome\collect) is used, the following is used to load the collections:
506 
507    // then if necessary the main dbhome (this should only happen if the
508    // gsdl.ini is a little screwed up and no volume dbhomes occurred)
509    if (dbhomes.find (gsdl_dbhome) == dbhomes.end()) {
510      load_collections_from_collectdir(translated_collectinfo,
511                colhere, colend, these_collections,
512                dbhomes, clhomes, collections,
513                gsdl_gsdlhome, filename_cat (gsdl_dbhome, "collect"), gsdl_dbhome);
514    }   
515  }
516
517  text_tset::const_iterator thiscol = collections.begin();
518  text_tset::const_iterator endcol = collections.end();
519
520  while (thiscol != endcol) {
521   
522    // ignore the modelcol
523    if (*thiscol == "modelcol") {
524      ++thiscol;
525      continue;
526    }
527   
528    // create collection server and add to null protocol
529    text_t this_gsdlhome = gsdl_gsdlhome;
530    text_t this_collecthome = gsdl_collecthome;
531    text_t this_dbhome = gsdl_dbhome;
532    colinfo_tmap::const_iterator it = translated_collectinfo.find (*thiscol);
533    assert (it != translated_collectinfo.end());
534    this_gsdlhome = (*it).second.gsdl_gsdlhome;
535    this_collecthome = (*it).second.gsdl_collecthome;
536    this_dbhome = (*it).second.gsdl_dbhome;
537
538    cservers->add_collection (*thiscol, this_gsdlhome, this_collecthome);
539    // in case it is a collection group
540    cservers->add_collection_group(*thiscol, this_gsdlhome, this_collecthome);
541   
542    ++thiscol;
543  }
544 
545  // set up the null protocol
546  nproto.set_collectset(cservers);
547 
548  if ((ausersaction == NULL) && (aauthenaction == NULL)){
549    userdbfile = filename_cat(gsdl_gsdlhome, "etc", "users.gdb");
550    udb = new userdbclass(userdbfile);
551    keydbfile = filename_cat(gsdl_gsdlhome, "etc", "key.gdb");
552    kdb = new keydbclass(keydbfile);
553  }
554  // add the protocol to the receptionist
555  if (atStartup) recpt.add_protocol (&nproto);
556 
557  // the list of actions.
558  if (astatusaction == NULL) {
559    astatusaction = new statusaction();
560    astatusaction->set_receptionist (&recpt);
561    recpt.add_action (astatusaction);
562  }
563 
564  if (apageaction == NULL) {
565    apageaction = new pageaction();
566    apageaction->set_receptionist (&recpt);
567    recpt.add_action (apageaction);
568  }
569 
570  if (apingaction == NULL) {
571    apingaction = new pingaction();
572    recpt.add_action (apingaction);
573  }
574 
575  if (atipaction == NULL) {
576    atipaction = new tipaction();
577    recpt.add_action (atipaction);
578  }
579 
580  if (aqueryaction == NULL) {
581    aqueryaction = new queryaction();
582    aqueryaction->set_receptionist (&recpt);
583    recpt.add_action (aqueryaction);
584  }
585 
586  if (adocumentaction == NULL) {
587    adocumentaction = new documentaction();
588    adocumentaction->set_receptionist (&recpt);
589    recpt.add_action (adocumentaction);
590  }
591 
592  if (ausersaction == NULL) {
593    ausersaction = new usersaction();
594    ausersaction->set_userdb(udb);
595    recpt.add_action (ausersaction);
596  }
597
598  if (anextlinkaction == NULL) {
599    anextlinkaction = new extlinkaction();
600    recpt.add_action (anextlinkaction);
601  }
602
603  if (acollectoraction == NULL) {
604    acollectoraction = new collectoraction();
605    acollectoraction->set_receptionist (&recpt);
606    recpt.add_action (acollectoraction);
607  }
608 
609  if (aauthenaction == NULL) {
610    aauthenaction = new authenaction();
611    aauthenaction->set_userdb(udb);
612    aauthenaction->set_keydb(kdb);
613    aauthenaction->set_receptionist(&recpt);
614    recpt.add_action (aauthenaction);
615  }
616
617#ifdef ENABLE_MGPP
618  if (aphindaction == NULL) {
619    aphindaction = new phindaction();
620    recpt.add_action (aphindaction);
621  }
622#endif
623 
624  if (aconfigaction == NULL) {
625    aconfigaction = new configaction();
626    aconfigaction->set_receptionist(&recpt);
627    recpt.add_action (aconfigaction);
628  }
629 
630  if (adynamicclassifieraction == NULL) {
631    adynamicclassifieraction = new dynamicclassifieraction();
632    adynamicclassifieraction->set_receptionist(&recpt);
633    recpt.add_action (adynamicclassifieraction);
634  }
635
636
637  // list of browsers
638  if (avlistbrowserclass == NULL) {
639    avlistbrowserclass = new vlistbrowserclass();
640    recpt.add_browser (avlistbrowserclass);
641    recpt.setdefaultbrowser ("VList");
642  }
643
644  if (ahlistbrowserclass == NULL) {
645    ahlistbrowserclass = new hlistbrowserclass();
646    recpt.add_browser (ahlistbrowserclass);
647  }
648
649  if (adatelistbrowserclass == NULL) {
650    adatelistbrowserclass = new datelistbrowserclass();
651    recpt.add_browser (adatelistbrowserclass);
652  }
653
654  if (ainvbrowserclass == NULL) {
655    ainvbrowserclass = new invbrowserclass();
656    recpt.add_browser (ainvbrowserclass);
657  }
658
659  if (apagedbrowserclass == NULL) {
660    apagedbrowserclass = new pagedbrowserclass();
661    recpt.add_browser (apagedbrowserclass);
662  }
663
664  if (ahtmlbrowserclass == NULL) {
665    ahtmlbrowserclass = new htmlbrowserclass();
666    recpt.add_browser (ahtmlbrowserclass);
667  }
668
669  if (aphindbrowserclass == NULL) {
670    aphindbrowserclass = new phindbrowserclass();;
671    recpt.add_browser (aphindbrowserclass);
672  }
673 
674  // set defaults
675  recpt.configure ("gsdlhome", gsdl_gsdlhome);
676  recpt.configure ("collecthome", gsdl_collecthome);
677  recpt.configure ("gdbmhome", gsdl_dbhome);
678  recpt.configure ("collection", collection);
679
680  int maxrequests = 1;
681
682  // configure collections (and receptionist) with collectinfo stuff
683  // different from the default
684  colinfo_tmap::const_iterator this_info = translated_collectinfo.begin();
685  colinfo_tmap::const_iterator end_info = translated_collectinfo.end();
686
687  while (this_info != end_info) {
688    text_tarray tmpconf;
689    tmpconf.push_back ((*this_info).first);
690    tmpconf.push_back ((*this_info).second.gsdl_gsdlhome);
691    tmpconf.push_back ((*this_info).second.gsdl_collecthome);
692    tmpconf.push_back ((*this_info).second.gsdl_dbhome);
693    recpt.configure ("collectinfo", tmpconf);
694    ++this_info;
695  }
696
697  // read in config files of each dbhome (in no particular order)
698  // those read in last will override those read earlier
699  // collections being used together in this way should be
700  // careful not to have main.cfg files that might
701  // interfere with each other.
702  text_tset::const_iterator thome = dbhomes.begin();
703  text_tset::const_iterator ehome = dbhomes.end();
704  text_tset::const_iterator tchome = clhomes.begin(); // collecthome companion for dbhome
705
706  while (thome != ehome) {
707    if (!main_cfg_read (recpt, *thome, *tchome, collection)) {
708      // couldn't find the main configuration file
709      page_errormaincfg (*thome, collection);
710      return 0;
711    }
712    ++thome;
713    ++tchome;
714  }
715
716  // w32server relies on gwcgi being set to "gsdl", and httpweb to web
717  recpt.configure ("gwcgi", "gsdl");
718  recpt.configure ("httpweb", "web");
719
720  // initialise the library software
721  if (!recpt.init(cerr)) {
722    // an error occurred during the initialisation
723    page_errorinit(gsdl_gsdlhome);
724    return 0;
725  }
726
727  // get memory information
728  MEMORYSTATUS memstatus;
729  memstatus.dwLength = sizeof(MEMORYSTATUS);
730  GlobalMemoryStatus(&memstatus);
731  baseavailvirtual = memstatus.dwAvailVirtual; // save for later comparison
732
733  return 1;
734}
735
736
737static void rememberpref (const text_t &tailstr) {
738  gsdl_enterlib = tailstr;
739}
740
741
742static void send_file_from_disk(text_t filename,
743                                RequestInfoT *RInfo,
744                                RequestFieldsT *RFields) {
745 
746  // select appropriate mime type from file extension
747  text_t ext;
748  text_t::const_iterator end = filename.end();
749  text_t::const_iterator it = filename.begin();
750  text_t::const_iterator lastdot = end;
751  while ((it = findchar(it, end, '.')) != end) {
752    lastdot = it;
753    ++it;
754  }
755  if (lastdot < end) ext = substr(lastdot+1, end);
756
757  text_t mime = "unknown";
758  int len = ext.size();
759  if (len == 2) {
760    if ((ext[0] == 'p' || ext[0] == 'P') &&
761    (ext[1] == 's' || ext[1] == 'S'))
762      mime = "application/postscript";
763  }  else if (len == 3) {
764    if((ext[0] == 'c' || ext[0] == 'C') &&
765    (ext[1] == 's' || ext[1] == 'S') &&
766    (ext[2] == 's' || ext[2] == 'S')){
767      mime = "text/css";
768    } else if ((ext[0] == 'g' || ext[0] == 'G') &&
769    (ext[1] == 'i' || ext[1] == 'I') &&
770    (ext[2] == 'f' || ext[2] == 'F')) {
771      mime = "image/gif";
772    } else if ((ext[0] == 'j' || ext[0] == 'J') &&
773           (ext[1] == 'p' || ext[1] == 'P') &&
774           (ext[2] == 'g' || ext[2] == 'G')) {
775      mime = "image/jpeg";
776    } else if ((ext[0] == 'h' || ext[0] == 'H') &&
777           (ext[1] == 't' || ext[1] == 'T') &&
778           (ext[2] == 'm' || ext[2] == 'M')) {
779      mime = "text/html";
780    } else if ((ext[0] == 'p' || ext[0] == 'P') &&
781           (ext[1] == 'd' || ext[1] == 'D') &&
782           (ext[2] == 'f' || ext[2] == 'F')) {
783      mime = "application/pdf";
784    } else if ((ext[0] == 'p' || ext[0] == 'P') &&
785           (ext[1] == 'n' || ext[1] == 'N') &&
786           (ext[2] == 'g' || ext[2] == 'G')) {
787      mime = "image/png";
788    } else if ((ext[0] == 'd' || ext[0] == 'D') &&
789           (ext[1] == 'o' || ext[1] == 'O') &&
790           (ext[2] == 'c' || ext[2] == 'C')) {
791      mime = "application/msword";
792    } else if ((ext[0] == 'r' || ext[0] == 'R') &&
793           (ext[1] == 't' || ext[1] == 'T') &&
794           (ext[2] == 'f' || ext[2] == 'F')) {
795      mime = "application/rtf";
796    } else if ((ext[0] == 'x' || ext[0] == 'X') &&
797           (ext[1] == 'l' || ext[1] == 'L') &&
798           (ext[2] == 's' || ext[2] == 'S')) {
799      mime = "application/vnd.ms-excel";
800    } else if ((ext[0] == 'p' || ext[0] == 'P') &&
801           (ext[1] == 'p' || ext[1] == 'P') &&
802           (ext[2] == 'T' || ext[2] == 'T')) {
803      mime = "application/vnd.ms-powerpoint";
804    } else if ((ext[0] == 'm' || ext[0] == 'M') &&
805           (ext[1] == 'p' || ext[1] == 'P') &&
806           (ext[2] == '3')) {
807      mime = "audio/mpeg";
808    }
809  } else if (len == 4) {
810    if ((ext[0] == 'j' || ext[0] == 'J') &&
811    (ext[1] == 'p' || ext[1] == 'P') &&
812    (ext[2] == 'e' || ext[2] == 'E') &&
813    (ext[3] == 'g' || ext[3] == 'G')) {
814      mime = "image/jpeg";
815    } else if ((ext[0] == 'h' || ext[0] == 'H') &&
816           (ext[1] == 't' || ext[1] == 'T') &&
817           (ext[2] == 'm' || ext[2] == 'M') &&
818           (ext[3] == 'l' || ext[3] == 'L')) {
819      mime = "text/html";
820    }
821  }
822   
823  // try to open the file
824  //cerr << "*** filename = " << filename.getcstr() << endl;
825  //cerr << "**** collect_home = " << current_collecthome.getcstr() << endl;
826
827  if (filename.size()>=9) {
828    text_t prefix = substr(filename.begin(),filename.begin()+9);
829    //cerr << "**** prefix = " << prefix.getcstr() << endl;
830
831    text_t tail = substr(filename.begin()+9,filename.end());
832    //cerr << "**** tail = " << tail.getcstr() << endl;
833
834    if (prefix == "/collect/") {
835      filename = filename_cat (current_collecthome, tail);
836    }
837    else {
838      filename = filename_cat (current_gsdlhome, filename);
839    }
840  }
841
842  cerr << "#### filename = " << filename.getcstr() << endl;
843
844  /* Feb 2002 - handle files with spaces in their name. */
845  text_t::iterator space_start;
846  space_start=findword(filename.begin(),filename.end(),"%20");
847  while (space_start != filename.end()) {
848    // we found a space...
849    text_t::iterator after_space=space_start+3;
850    text_t new_filename=substr(filename.begin(), space_start);
851    new_filename += " ";
852    new_filename += substr(after_space,filename.end());
853    filename=new_filename;
854    space_start=findword(filename.begin(),filename.end(),"%20");
855  }
856
857  char *filenamec = filename.getcstr();
858  TranslateEscapeString(filenamec);  // Resolve any %xx values
859  FILE *thefile = fopen(filenamec, "rb");
860  delete []filenamec;
861  if (thefile == NULL) {
862    log_message("file not found\n");
863    send_retrieve_error(404, "File not found",
864            "Could not find the local file requested", RInfo);
865    return;
866  }
867  int nr;
868  char buffer[2048];
869  // send back required information
870  char *mimec = mime.getcstr();
871  if (send_header(mimec, RInfo) >= 0) {
872    if (RFields->MethodStr != "HEAD") {
873      for (;;) {
874        nr = fread(buffer, 1, 2048, thefile);
875        if (nr <= 0) break;
876        if (SendData(RInfo->ClientSocket,
877                     (BYTE *)buffer, nr,
878             RInfo->ThreadNum) < 0) break;       
879      }
880    }
881  }
882  delete []mimec;
883  fclose(thefile);
884}
885
886static void handle_library_request(const text_t &argstr, RequestInfoT *RInfo,
887                   RequestFieldsT *RequestFields) {
888
889  // parse the cgi arguments and produce the resulting page if there
890  // have been no errors so far
891  cgiargsclass args;
892  fileupload_tmap fileuploads;
893  text_tmap empty; // don't use this (it's for fastcgi on unix)
894  if (!recpt.parse_cgi_args (argstr, fileuploads, args, cerr, empty)) {
895    page_errorparseargs(gsdl_gsdlhome);
896    return;
897  }
898
899  colinfo_tmap::const_iterator it = translated_collectinfo.find (args["c"]);
900  if (it != translated_collectinfo.end()) {
901    current_gsdlhome = (*it).second.gsdl_gsdlhome;
902    current_collecthome = (*it).second.gsdl_collecthome;
903  } else {
904    current_gsdlhome = gsdl_gsdlhome;
905    current_collecthome = gsdl_collecthome;
906  }
907
908  // produce cgi header
909  response_t response;
910  text_t response_data;
911
912  recpt.get_cgihead_info (args, response, response_data, cerr, empty);
913
914  if (response == location) {
915    // location response
916    response_data = "@" + recpt.expandmacros (response_data, args, cerr);
917    char *response_data_c = response_data.getcstr();
918    send_header(response_data_c, RInfo);
919    delete []response_data_c;
920    return;
921  } else if (response == content) {
922    // content response
923    char *response_data_c = response_data.getcstr();
924    if (send_header(response_data_c, RInfo) < 0) {
925      delete []response_data_c;
926      return;
927    }
928    delete []response_data_c;
929  }
930  else if (response == undecided_location) {
931    // We know this is a relocation request but at the moment we don't know exactly where to
932    // Just output the start of the header and wait until later to output the target location
933    // Used for the "I'm feeling lucky" functionality
934    cout << "HTTP/1.0 302 Relocation\r\n";
935    cout << "Server: GSDL\r\n";
936    cout << "Content-type: text/html \r\n";
937  }
938  else {
939    // unknown response
940    cerr << "Error: get_cgihead_info returned an unknown response type.\n";
941    return;
942  }
943
944  textstream.tsbreset();
945  textstream.setrequestinfo (RInfo);
946  if (!recpt.produce_content (args, cout, cerr)) {
947    page_errorcgipage(gsdl_gsdlhome);
948    return;
949  }
950  recpt.log_cgi_args (args, cerr, empty);
951
952  cout << flush;
953  cerr << flush;
954 
955  ++libaccessnum;
956}
957
958static void handle_server_request(text_t &tailstr,
959                  RequestInfoT *RequestInfo,
960                  RequestFieldsT *RequestFields) {
961 
962  text_t argstr;
963
964  // do any url adjustments necessary
965  if (tailstr.empty() || tailstr == "/") {
966    tailstr = "/gsdl";
967  }
968
969  text_t::const_iterator begin = tailstr.begin();
970  text_t::const_iterator end = tailstr.end();
971 
972  // test to see if this is a library request or a local
973  // file request
974  if ((tailstr == "/gsdl") ||
975      ((tailstr.size() > 5) && (substr(begin, begin+6) == "/gsdl?"))) {
976
977    // library request
978   
979    // argstr is the bit after the '?'
980    if (tailstr != "/gsdl") {
981      argstr = substr(begin+6, end);
982    }
983
984    // log the difference in access times
985    DWORD thislibaccesstime = GetTickCount();
986    if (gsdl_keep_log || gsdl_show_console) {
987      char logstr[256];
988      sprintf(logstr, "DELTA LIB ACCESS TIME: %i\n", (int)(thislibaccesstime - lastlibaccesstime));
989      log_message (logstr);
990    }
991    lastlibaccesstime = thislibaccesstime;
992   
993    // log this request
994    if (gsdl_keep_log || gsdl_show_console) {
995      text_t logstr = "LOCAL LIB: " + tailstr + "\n";
996      char *logstrc = logstr.getcstr();
997      log_message (logstrc);
998      delete []logstrc;
999    }
1000   
1001    handle_library_request (argstr, RequestInfo, RequestFields);
1002   
1003    // remember the preferences
1004    // rememberpref (tailstr);
1005   
1006    // log memory information
1007    if (gsdl_keep_log || gsdl_show_console) {
1008      MEMORYSTATUS memstatus;
1009      memstatus.dwLength = sizeof(MEMORYSTATUS);
1010      GlobalMemoryStatus(&memstatus);
1011      char logstr[256];
1012      sprintf (logstr, "BDELTA AVAIL VIRTUAL: %i K\n",
1013           (int)((baseavailvirtual - memstatus.dwAvailVirtual)/1024));
1014      log_message (logstr);
1015    }
1016   
1017  } else {
1018    // local file
1019    if (gsdl_keep_log || gsdl_show_console) {
1020      text_t logstr = "LOCAL FILE: " + tailstr + "\n";
1021      char *logstrc = logstr.getcstr();
1022      log_message (logstrc);
1023      delete []logstrc;
1024    }
1025    send_file_from_disk (tailstr, RequestInfo, RequestFields);
1026  }
1027}
1028
1029int ExamineURIStr(text_t &URIStr, RequestInfoT *RequestInfo,
1030          RequestFieldsT *RequestFields)
1031{
1032  text_t protocol, machine, rest;
1033  int port;
1034
1035  if (RequestFields->ContentLength > 0) {
1036    // POST data
1037    URIStr.push_back('?');
1038    for (int i = 0; i < RequestFields->ContentLength; ++i) {
1039      URIStr.push_back(RequestFields->Content[i]);
1040    }
1041  }
1042 
1043  if (parse_url(URIStr, protocol, machine, &port, rest)!=http_ok) {
1044    // Alter local file request to address 'gsdl'
1045    if (*(URIStr.begin()) != '/') URIStr = "http://gsdl/" + URIStr;
1046    else URIStr = "http://gsdl" + URIStr;
1047    parse_url(URIStr, protocol, machine, &port, rest);
1048  }
1049
1050  if (machine == "gsdl") {
1051    // a local file request
1052    handle_server_request(rest, RequestInfo, RequestFields);
1053   
1054  } else {
1055    send_retrieve_error(404, "File not found",
1056            "Could not find the local file requested", RequestInfo);
1057  }
1058 
1059  return 1;
1060}
Note: See TracBrowser for help on using the browser.