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

Revision 21324, 30.3 KB (checked in by ak19, 10 years ago)

Changes to makefiles, configure files, and source code to work with the new configure flags that allow indexers to be individually compiled up by setting each indexer to be enabled or disabled (enable-mg, enable-mgpp, enable-lucene)

  • 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// returns 1 if successful, 0 if unsuccessful (note that as well as being
371// called when the server first starts up this function is called when the
372// "restart library" button is pressed)
373int gsdl_init (bool atStartup) {
374
375  if (atStartup) {
376#if defined (GSDL_USE_IOS_H)
377    cerr = &logstream;
378    cout = &textstream;
379#else
380    cerr.rdbuf(&logstream);
381    cout.rdbuf(&textstream);
382#endif
383  }
384
385  // collection should be set to "" unless in collection specific mode -
386  // changing this to the name of the collection should be all that's
387  // required to create a collection specific receptionist
388  text_t collection = "";
389  text_tset dbhomes;
390  text_tset clhomes; // collecthome companion for dbhome
391  text_tset collections;
392
393  if (atStartup) {
394    // note the current time
395    lastlibaccesstime = GetTickCount();
396   
397    // before we do the init we should make sure
398    // that we can find the relevant directories
399    if (!checkdir (gsdl_gsdlhome + "\\")) return 0;
400    if (!checkdir (gsdl_collecthome + "\\")) return 0;
401    if (!checkdir (gsdl_gsdlhome + "\\macros\\")) return 0;
402  }   
403
404  // deleting cservers clears all the collection servers
405  if (cservers != NULL) delete cservers;
406
407  cservers = new collectset();
408
409  // get all collections from each gsdlhome (this relies
410  // on there not being more than one collection with the same
411  // name)
412  if (!collection.empty()) {
413    // collection specific receptionist - one collection, one gsdlhome
414    collections.insert (collection);
415    dbhomes.insert (gsdl_dbhome);
416    clhomes.insert (gsdl_collecthome);
417    collectioninfo_t tmp;
418    tmp.gsdl_gsdlhome = gsdl_gsdlhome;
419    tmp.gsdl_collecthome = gsdl_collecthome;
420    tmp.gsdl_dbhome = gsdl_dbhome;
421    translated_collectinfo[collection] = tmp;
422
423  } else {
424
425    text_tset::const_iterator colhere;
426    text_tset::const_iterator colend;
427    text_tset these_collections;
428
429    // first volume gsdlhome's
430    colinfo_tmap::const_iterator this_info = gsdl_collectinfo.begin();
431    colinfo_tmap::const_iterator end_info = gsdl_collectinfo.end();
432    while (this_info != end_info) {
433      if (dbhomes.find ((*this_info).second.gsdl_dbhome) == dbhomes.end()) {
434    these_collections.erase (these_collections.begin(), these_collections.end());
435    read_dir ((*this_info).second.gsdl_collecthome, these_collections);
436    colhere = these_collections.begin();
437    colend = these_collections.end();
438    while (colhere != colend) {
439      if ((collections.find (*colhere)) == collections.end()) {
440        // make sure the build.cfg file is at gsdlhome (as it's possible that
441        // the collection appears at this gsdlhome only because it's gdbm
442        // file is installed here -- it's real gdbm will therefore be
443        // somewhere else).
444        text_t build_cfg = filename_cat ((*this_info).second.gsdl_collecthome,
445                         *colhere, "index", "build.cfg");
446        if (file_exists (build_cfg)) {
447          collections.insert (*colhere);
448
449          // since gsdl_collectinfo keys will be stuff like collection#1
450          // for a multiple volume collection we want to translate it
451          // so that the keys are the actual collection names
452          translated_collectinfo[*colhere] = (*this_info).second;
453        }
454      }
455      ++colhere;
456    }
457    dbhomes.insert ((*this_info).second.gsdl_dbhome);
458    clhomes.insert ((*this_info).second.gsdl_collecthome);
459      }
460      ++this_info;
461    }
462 
463    // then if necessary the main dbhome (this should only happen if the
464    // gsdl.ini is a little screwed up and no volume dbhomes occurred)
465    if (dbhomes.find (gsdl_dbhome) == dbhomes.end()) {
466      these_collections.erase (these_collections.begin(), these_collections.end());
467      read_dir (filename_cat (gsdl_dbhome, "collect"), these_collections);
468      colhere = these_collections.begin();
469      colend = these_collections.end();
470      while (colhere != colend) {
471   
472    //text_t build_cfg = filename_cat (gsdl_dbhome,"collect",
473    //           *colhere, "index", "build.cfg");
474      //if (file_exists (build_cfg)) {
475      collections.insert (*colhere);
476     
477      collectioninfo_t tmp;
478      tmp.gsdl_gsdlhome = gsdl_gsdlhome;
479      tmp.gsdl_collecthome = gsdl_collecthome;
480      tmp.gsdl_dbhome = gsdl_dbhome;
481      translated_collectinfo[*colhere] = tmp;
482      //}
483    ++colhere;
484      }
485      dbhomes.insert (gsdl_dbhome);
486      clhomes.insert (gsdl_collecthome);
487    }
488  }
489
490  text_tset::const_iterator thiscol = collections.begin();
491  text_tset::const_iterator endcol = collections.end();
492
493  while (thiscol != endcol) {
494   
495    // ignore the modelcol
496    if (*thiscol == "modelcol") {
497      ++thiscol;
498      continue;
499    }
500   
501    // create collection server and add to null protocol
502    text_t this_gsdlhome = gsdl_gsdlhome;
503    text_t this_collecthome = gsdl_collecthome;
504    text_t this_dbhome = gsdl_dbhome;
505    colinfo_tmap::const_iterator it = translated_collectinfo.find (*thiscol);
506    assert (it != translated_collectinfo.end());
507    this_gsdlhome = (*it).second.gsdl_gsdlhome;
508    this_collecthome = (*it).second.gsdl_collecthome;
509    this_dbhome = (*it).second.gsdl_dbhome;
510
511    cservers->add_collection (*thiscol, this_gsdlhome, this_collecthome);
512    // in case it is a collection group
513    cservers->add_collection_group(*thiscol, this_gsdlhome, this_collecthome);
514   
515    ++thiscol;
516  }
517 
518  // set up the null protocol
519  nproto.set_collectset(cservers);
520 
521  if ((ausersaction == NULL) && (aauthenaction == NULL)){
522    userdbfile = filename_cat(gsdl_gsdlhome, "etc", "users.gdb");
523    udb = new userdbclass(userdbfile);
524    keydbfile = filename_cat(gsdl_gsdlhome, "etc", "key.gdb");
525    kdb = new keydbclass(keydbfile);
526  }
527  // add the protocol to the receptionist
528  if (atStartup) recpt.add_protocol (&nproto);
529 
530  // the list of actions.
531  if (astatusaction == NULL) {
532    astatusaction = new statusaction();
533    astatusaction->set_receptionist (&recpt);
534    recpt.add_action (astatusaction);
535  }
536 
537  if (apageaction == NULL) {
538    apageaction = new pageaction();
539    apageaction->set_receptionist (&recpt);
540    recpt.add_action (apageaction);
541  }
542 
543  if (apingaction == NULL) {
544    apingaction = new pingaction();
545    recpt.add_action (apingaction);
546  }
547 
548  if (atipaction == NULL) {
549    atipaction = new tipaction();
550    recpt.add_action (atipaction);
551  }
552 
553  if (aqueryaction == NULL) {
554    aqueryaction = new queryaction();
555    aqueryaction->set_receptionist (&recpt);
556    recpt.add_action (aqueryaction);
557  }
558 
559  if (adocumentaction == NULL) {
560    adocumentaction = new documentaction();
561    adocumentaction->set_receptionist (&recpt);
562    recpt.add_action (adocumentaction);
563  }
564 
565  if (ausersaction == NULL) {
566    ausersaction = new usersaction();
567    ausersaction->set_userdb(udb);
568    recpt.add_action (ausersaction);
569  }
570
571  if (anextlinkaction == NULL) {
572    anextlinkaction = new extlinkaction();
573    recpt.add_action (anextlinkaction);
574  }
575
576  if (acollectoraction == NULL) {
577    acollectoraction = new collectoraction();
578    acollectoraction->set_receptionist (&recpt);
579    recpt.add_action (acollectoraction);
580  }
581 
582  if (aauthenaction == NULL) {
583    aauthenaction = new authenaction();
584    aauthenaction->set_userdb(udb);
585    aauthenaction->set_keydb(kdb);
586    aauthenaction->set_receptionist(&recpt);
587    recpt.add_action (aauthenaction);
588  }
589
590#ifdef ENABLE_MGPP
591  if (aphindaction == NULL) {
592    aphindaction = new phindaction();
593    recpt.add_action (aphindaction);
594  }
595#endif
596 
597  if (aconfigaction == NULL) {
598    aconfigaction = new configaction();
599    aconfigaction->set_receptionist(&recpt);
600    recpt.add_action (aconfigaction);
601  }
602 
603  if (adynamicclassifieraction == NULL) {
604    adynamicclassifieraction = new dynamicclassifieraction();
605    adynamicclassifieraction->set_receptionist(&recpt);
606    recpt.add_action (adynamicclassifieraction);
607  }
608
609
610  // list of browsers
611  if (avlistbrowserclass == NULL) {
612    avlistbrowserclass = new vlistbrowserclass();
613    recpt.add_browser (avlistbrowserclass);
614    recpt.setdefaultbrowser ("VList");
615  }
616
617  if (ahlistbrowserclass == NULL) {
618    ahlistbrowserclass = new hlistbrowserclass();
619    recpt.add_browser (ahlistbrowserclass);
620  }
621
622  if (adatelistbrowserclass == NULL) {
623    adatelistbrowserclass = new datelistbrowserclass();
624    recpt.add_browser (adatelistbrowserclass);
625  }
626
627  if (ainvbrowserclass == NULL) {
628    ainvbrowserclass = new invbrowserclass();
629    recpt.add_browser (ainvbrowserclass);
630  }
631
632  if (apagedbrowserclass == NULL) {
633    apagedbrowserclass = new pagedbrowserclass();
634    recpt.add_browser (apagedbrowserclass);
635  }
636
637  if (ahtmlbrowserclass == NULL) {
638    ahtmlbrowserclass = new htmlbrowserclass();
639    recpt.add_browser (ahtmlbrowserclass);
640  }
641
642  if (aphindbrowserclass == NULL) {
643    aphindbrowserclass = new phindbrowserclass();;
644    recpt.add_browser (aphindbrowserclass);
645  }
646 
647  // set defaults
648  recpt.configure ("gsdlhome", gsdl_gsdlhome);
649  recpt.configure ("collecthome", gsdl_collecthome);
650  recpt.configure ("gdbmhome", gsdl_dbhome);
651  recpt.configure ("collection", collection);
652
653  int maxrequests = 1;
654
655  // configure collections (and receptionist) with collectinfo stuff
656  // different from the default
657  colinfo_tmap::const_iterator this_info = translated_collectinfo.begin();
658  colinfo_tmap::const_iterator end_info = translated_collectinfo.end();
659
660  while (this_info != end_info) {
661    text_tarray tmpconf;
662    tmpconf.push_back ((*this_info).first);
663    tmpconf.push_back ((*this_info).second.gsdl_gsdlhome);
664    tmpconf.push_back ((*this_info).second.gsdl_collecthome);
665    tmpconf.push_back ((*this_info).second.gsdl_dbhome);
666    recpt.configure ("collectinfo", tmpconf);
667    ++this_info;
668  }
669
670  // read in config files of each dbhome (in no particular order)
671  // those read in last will override those read earlier
672  // collections being used together in this way should be
673  // careful not to have main.cfg files that might
674  // interfere with each other.
675  text_tset::const_iterator thome = dbhomes.begin();
676  text_tset::const_iterator ehome = dbhomes.end();
677  text_tset::const_iterator tchome = clhomes.begin(); // collecthome companion for dbhome
678
679  while (thome != ehome) {
680    if (!main_cfg_read (recpt, *thome, *tchome, collection)) {
681      // couldn't find the main configuration file
682      page_errormaincfg (*thome, collection);
683      return 0;
684    }
685    ++thome;
686    ++tchome;
687  }
688
689  // w32server relies on gwcgi being set to "gsdl", and httpweb to web
690  recpt.configure ("gwcgi", "gsdl");
691  recpt.configure ("httpweb", "web");
692
693  // initialise the library software
694  if (!recpt.init(cerr)) {
695    // an error occurred during the initialisation
696    page_errorinit(gsdl_gsdlhome);
697    return 0;
698  }
699
700  // get memory information
701  MEMORYSTATUS memstatus;
702  memstatus.dwLength = sizeof(MEMORYSTATUS);
703  GlobalMemoryStatus(&memstatus);
704  baseavailvirtual = memstatus.dwAvailVirtual; // save for later comparison
705
706  return 1;
707}
708
709
710static void rememberpref (const text_t &tailstr) {
711  gsdl_enterlib = tailstr;
712}
713
714
715static void send_file_from_disk(text_t filename,
716                                RequestInfoT *RInfo,
717                                RequestFieldsT *RFields) {
718 
719  // select appropriate mime type from file extension
720  text_t ext;
721  text_t::const_iterator end = filename.end();
722  text_t::const_iterator it = filename.begin();
723  text_t::const_iterator lastdot = end;
724  while ((it = findchar(it, end, '.')) != end) {
725    lastdot = it;
726    ++it;
727  }
728  if (lastdot < end) ext = substr(lastdot+1, end);
729
730  text_t mime = "unknown";
731  int len = ext.size();
732  if (len == 2) {
733    if ((ext[0] == 'p' || ext[0] == 'P') &&
734    (ext[1] == 's' || ext[1] == 'S'))
735      mime = "application/postscript";
736  }  else if (len == 3) {
737    if ((ext[0] == 'g' || ext[0] == 'G') &&
738    (ext[1] == 'i' || ext[1] == 'I') &&
739    (ext[2] == 'f' || ext[2] == 'F')) {
740      mime = "image/gif";
741    } else if ((ext[0] == 'j' || ext[0] == 'J') &&
742           (ext[1] == 'p' || ext[1] == 'P') &&
743           (ext[2] == 'g' || ext[2] == 'G')) {
744      mime = "image/jpeg";
745    } else if ((ext[0] == 'h' || ext[0] == 'H') &&
746           (ext[1] == 't' || ext[1] == 'T') &&
747           (ext[2] == 'm' || ext[2] == 'M')) {
748      mime = "text/html";
749    } else if ((ext[0] == 'p' || ext[0] == 'P') &&
750           (ext[1] == 'd' || ext[1] == 'D') &&
751           (ext[2] == 'f' || ext[2] == 'F')) {
752      mime = "application/pdf";
753    } else if ((ext[0] == 'p' || ext[0] == 'P') &&
754           (ext[1] == 'n' || ext[1] == 'N') &&
755           (ext[2] == 'g' || ext[2] == 'G')) {
756      mime = "image/png";
757    } else if ((ext[0] == 'd' || ext[0] == 'D') &&
758           (ext[1] == 'o' || ext[1] == 'O') &&
759           (ext[2] == 'c' || ext[2] == 'C')) {
760      mime = "application/msword";
761    } else if ((ext[0] == 'r' || ext[0] == 'R') &&
762           (ext[1] == 't' || ext[1] == 'T') &&
763           (ext[2] == 'f' || ext[2] == 'F')) {
764      mime = "application/rtf";
765    } else if ((ext[0] == 'x' || ext[0] == 'X') &&
766           (ext[1] == 'l' || ext[1] == 'L') &&
767           (ext[2] == 's' || ext[2] == 'S')) {
768      mime = "application/vnd.ms-excel";
769    } else if ((ext[0] == 'p' || ext[0] == 'P') &&
770           (ext[1] == 'p' || ext[1] == 'P') &&
771           (ext[2] == 'T' || ext[2] == 'T')) {
772      mime = "application/vnd.ms-powerpoint";
773    } else if ((ext[0] == 'm' || ext[0] == 'M') &&
774           (ext[1] == 'p' || ext[1] == 'P') &&
775           (ext[2] == '3')) {
776      mime = "audio/mpeg";
777    }
778  } else if (len == 4) {
779    if ((ext[0] == 'j' || ext[0] == 'J') &&
780    (ext[1] == 'p' || ext[1] == 'P') &&
781    (ext[2] == 'e' || ext[2] == 'E') &&
782    (ext[3] == 'g' || ext[3] == 'G')) {
783      mime = "image/jpeg";
784    } else if ((ext[0] == 'h' || ext[0] == 'H') &&
785           (ext[1] == 't' || ext[1] == 'T') &&
786           (ext[2] == 'm' || ext[2] == 'M') &&
787           (ext[3] == 'l' || ext[3] == 'L')) {
788      mime = "text/html";
789    }
790  }
791   
792  // try to open the file
793  //cerr << "*** filename = " << filename.getcstr() << endl;
794  //cerr << "**** collect_home = " << current_collecthome.getcstr() << endl;
795
796  if (filename.size()>=9) {
797    text_t prefix = substr(filename.begin(),filename.begin()+9);
798    //cerr << "**** prefix = " << prefix.getcstr() << endl;
799
800    text_t tail = substr(filename.begin()+9,filename.end());
801    //cerr << "**** tail = " << tail.getcstr() << endl;
802
803    if (prefix == "/collect/") {
804      filename = filename_cat (current_collecthome, tail);
805    }
806    else {
807      filename = filename_cat (current_gsdlhome, filename);
808    }
809  }
810
811  cerr << "#### filename = " << filename.getcstr() << endl;
812
813  /* Feb 2002 - handle files with spaces in their name. */
814  text_t::iterator space_start;
815  space_start=findword(filename.begin(),filename.end(),"%20");
816  while (space_start != filename.end()) {
817    // we found a space...
818    text_t::iterator after_space=space_start+3;
819    text_t new_filename=substr(filename.begin(), space_start);
820    new_filename += " ";
821    new_filename += substr(after_space,filename.end());
822    filename=new_filename;
823    space_start=findword(filename.begin(),filename.end(),"%20");
824  }
825
826  char *filenamec = filename.getcstr();
827  TranslateEscapeString(filenamec);  // Resolve any %xx values
828  FILE *thefile = fopen(filenamec, "rb");
829  delete []filenamec;
830  if (thefile == NULL) {
831    log_message("file not found\n");
832    send_retrieve_error(404, "File not found",
833            "Could not find the local file requested", RInfo);
834    return;
835  }
836  int nr;
837  char buffer[2048];
838  // send back required information
839  char *mimec = mime.getcstr();
840  if (send_header(mimec, RInfo) >= 0) {
841    if (RFields->MethodStr != "HEAD") {
842      for (;;) {
843        nr = fread(buffer, 1, 2048, thefile);
844        if (nr <= 0) break;
845        if (SendData(RInfo->ClientSocket,
846                     (BYTE *)buffer, nr,
847             RInfo->ThreadNum) < 0) break;       
848      }
849    }
850  }
851  delete []mimec;
852  fclose(thefile);
853}
854
855static void handle_library_request(const text_t &argstr, RequestInfoT *RInfo,
856                   RequestFieldsT *RequestFields) {
857
858  // parse the cgi arguments and produce the resulting page if there
859  // have been no errors so far
860  cgiargsclass args;
861  fileupload_tmap fileuploads;
862  text_tmap empty; // don't use this (it's for fastcgi on unix)
863  if (!recpt.parse_cgi_args (argstr, fileuploads, args, cerr, empty)) {
864    page_errorparseargs(gsdl_gsdlhome);
865    return;
866  }
867
868  colinfo_tmap::const_iterator it = translated_collectinfo.find (args["c"]);
869  if (it != translated_collectinfo.end()) {
870    current_gsdlhome = (*it).second.gsdl_gsdlhome;
871    current_collecthome = (*it).second.gsdl_collecthome;
872  } else {
873    current_gsdlhome = gsdl_gsdlhome;
874    current_collecthome = gsdl_collecthome;
875  }
876
877  // produce cgi header
878  response_t response;
879  text_t response_data;
880
881  recpt.get_cgihead_info (args, response, response_data, cerr, empty);
882
883  if (response == location) {
884    // location response
885    response_data = "@" + recpt.expandmacros (response_data, args, cerr);
886    char *response_data_c = response_data.getcstr();
887    send_header(response_data_c, RInfo);
888    delete []response_data_c;
889    return;
890  } else if (response == content) {
891    // content response
892    char *response_data_c = response_data.getcstr();
893    if (send_header(response_data_c, RInfo) < 0) {
894      delete []response_data_c;
895      return;
896    }
897    delete []response_data_c;
898  }
899  else if (response == undecided_location) {
900    // We know this is a relocation request but at the moment we don't know exactly where to
901    // Just output the start of the header and wait until later to output the target location
902    // Used for the "I'm feeling lucky" functionality
903    cout << "HTTP/1.0 302 Relocation\r\n";
904    cout << "Server: GSDL\r\n";
905    cout << "Content-type: text/html \r\n";
906  }
907  else {
908    // unknown response
909    cerr << "Error: get_cgihead_info returned an unknown response type.\n";
910    return;
911  }
912
913  textstream.tsbreset();
914  textstream.setrequestinfo (RInfo);
915  if (!recpt.produce_content (args, cout, cerr)) {
916    page_errorcgipage(gsdl_gsdlhome);
917    return;
918  }
919  recpt.log_cgi_args (args, cerr, empty);
920
921  cout << flush;
922  cerr << flush;
923 
924  ++libaccessnum;
925}
926
927static void handle_server_request(text_t &tailstr,
928                  RequestInfoT *RequestInfo,
929                  RequestFieldsT *RequestFields) {
930 
931  text_t argstr;
932
933  // do any url adjustments necessary
934  if (tailstr.empty() || tailstr == "/") {
935    tailstr = "/gsdl";
936  }
937
938  text_t::const_iterator begin = tailstr.begin();
939  text_t::const_iterator end = tailstr.end();
940 
941  // test to see if this is a library request or a local
942  // file request
943  if ((tailstr == "/gsdl") ||
944      ((tailstr.size() > 5) && (substr(begin, begin+6) == "/gsdl?"))) {
945
946    // library request
947   
948    // argstr is the bit after the '?'
949    if (tailstr != "/gsdl") {
950      argstr = substr(begin+6, end);
951    }
952
953    // log the difference in access times
954    DWORD thislibaccesstime = GetTickCount();
955    if (gsdl_keep_log || gsdl_show_console) {
956      char logstr[256];
957      sprintf(logstr, "DELTA LIB ACCESS TIME: %i\n", (int)(thislibaccesstime - lastlibaccesstime));
958      log_message (logstr);
959    }
960    lastlibaccesstime = thislibaccesstime;
961   
962    // log this request
963    if (gsdl_keep_log || gsdl_show_console) {
964      text_t logstr = "LOCAL LIB: " + tailstr + "\n";
965      char *logstrc = logstr.getcstr();
966      log_message (logstrc);
967      delete []logstrc;
968    }
969   
970    handle_library_request (argstr, RequestInfo, RequestFields);
971   
972    // remember the preferences
973    // rememberpref (tailstr);
974   
975    // log memory information
976    if (gsdl_keep_log || gsdl_show_console) {
977      MEMORYSTATUS memstatus;
978      memstatus.dwLength = sizeof(MEMORYSTATUS);
979      GlobalMemoryStatus(&memstatus);
980      char logstr[256];
981      sprintf (logstr, "BDELTA AVAIL VIRTUAL: %i K\n",
982           (int)((baseavailvirtual - memstatus.dwAvailVirtual)/1024));
983      log_message (logstr);
984    }
985   
986  } else {
987    // local file
988    if (gsdl_keep_log || gsdl_show_console) {
989      text_t logstr = "LOCAL FILE: " + tailstr + "\n";
990      char *logstrc = logstr.getcstr();
991      log_message (logstrc);
992      delete []logstrc;
993    }
994    send_file_from_disk (tailstr, RequestInfo, RequestFields);
995  }
996}
997
998int ExamineURIStr(text_t &URIStr, RequestInfoT *RequestInfo,
999          RequestFieldsT *RequestFields)
1000{
1001  text_t protocol, machine, rest;
1002  int port;
1003
1004  if (RequestFields->ContentLength > 0) {
1005    // POST data
1006    URIStr.push_back('?');
1007    for (int i = 0; i < RequestFields->ContentLength; ++i) {
1008      URIStr.push_back(RequestFields->Content[i]);
1009    }
1010  }
1011 
1012  if (parse_url(URIStr, protocol, machine, &port, rest)!=http_ok) {
1013    // Alter local file request to address 'gsdl'
1014    if (*(URIStr.begin()) != '/') URIStr = "http://gsdl/" + URIStr;
1015    else URIStr = "http://gsdl" + URIStr;
1016    parse_url(URIStr, protocol, machine, &port, rest);
1017  }
1018
1019  if (machine == "gsdl") {
1020    // a local file request
1021    handle_server_request(rest, RequestInfo, RequestFields);
1022   
1023  } else {
1024    send_retrieve_error(404, "File not found",
1025            "Could not find the local file requested", RequestInfo);
1026  }
1027 
1028  return 1;
1029}
Note: See TracBrowser for help on using the browser.