root/gsdl/trunk/src/w32server/cgiwrapper.cpp @ 15852

Revision 15852, 28.5 KB (checked in by mdewsnip, 11 years ago)

(Adding dynamic classifiers) Adding an instance of dynamicclassifieraction so dynamic classifiers are available with the local library.

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