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

Last change on this file since 21324 was 21324, checked in by ak19, 14 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
File size: 30.3 KB
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"
[21324]71#ifdef ENABLE_MGPP
[2487]72#include "phindaction.h"
[21324]73#endif
[4291]74#include "configaction.h"
[611]75
[902]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"
[2487]83#include "phindbrowserclass.h"
[902]84
[611]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;
[1203]104#if !defined (GSDL_USE_IOS_H)
105 char buffer[256];
106#endif
[611]107};
108
109textstreambuf::textstreambuf() {
110 tsbreset();
[1203]111#if !defined (GSDL_USE_IOS_H)
112 setp (&buffer[0], &buffer[255]);
113#else
[611]114 if (base() == ebuf()) allocate();
115 setp (base(), ebuf());
[1203]116#endif
[611]117};
118
119int textstreambuf::sync () {
120 if ((RInfo != NULL) &&
[1203]121 (Send_String_N(pbase(), pptr()-pbase(), RInfo) < 0)) {
[611]122 RInfo = NULL;
123 }
124
125 if (casostr != NULL) {
126 char *thepbase=pbase();
[9598]127 for (int i=0;i<(pptr()-pbase());++i) (*casostr).put(thepbase[i]);
[611]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;}
[1203]151
152#if !defined (GSDL_USE_IOS_H)
153private:
154 char buffer[256];
155#endif
[611]156};
157
158logstreambuf::logstreambuf () {
[1203]159#if !defined (GSDL_USE_IOS_H)
160 setp (&buffer[0], &buffer[255]);
161#else
[611]162 if (base() == ebuf()) allocate();
163 setp (base(), ebuf());
[1203]164#endif
[611]165}
166
167int logstreambuf::sync () {
[902]168 if (gsdl_keep_log || gsdl_show_console) {
[611]169 log_message ("LOCAL LIB MESSAGE: ");
[1203]170 log_message_N (pbase(), pptr()-pbase());
[611]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
[2212]222static void page_errorparseargs (const text_t &/*gsdlhome*/) {
[611]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
[2212]232static void page_errorcgipage (const text_t &/*gsdlhome*/) {
[611]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
[9636]306 delete []cstrmessage;
[611]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
[9636]318 delete []cstrthedir;
[611]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
[6023]331receptionist recpt;
332nullproto nproto;
333collectset *cservers = NULL;
334
335textstreambuf textstream;
336logstreambuf logstream;
337DWORD lastlibaccesstime;
338DWORD baseavailvirtual;
339text_t current_gsdlhome;
[16975]340text_t current_collecthome;
[6023]341colinfo_tmap translated_collectinfo;
342
343statusaction *astatusaction = NULL;
344pageaction *apageaction = NULL;
345pingaction *apingaction = NULL;
346tipaction *atipaction = NULL;
347queryaction *aqueryaction = NULL;
348documentaction *adocumentaction = NULL;
[15852]349dynamicclassifieraction *adynamicclassifieraction = NULL;
[6023]350usersaction *ausersaction = NULL;
351extlinkaction *anextlinkaction = NULL;
352collectoraction *acollectoraction = NULL;
353authenaction *aauthenaction = NULL;
[21324]354#ifdef ENABLE_MGPP
[6023]355phindaction *aphindaction = NULL;
[21324]356#endif
[6023]357configaction *aconfigaction = NULL;
358vlistbrowserclass *avlistbrowserclass = NULL;
359hlistbrowserclass *ahlistbrowserclass = NULL;
360datelistbrowserclass *adatelistbrowserclass = NULL;
361invbrowserclass *ainvbrowserclass = NULL;
362pagedbrowserclass *apagedbrowserclass = NULL;
363htmlbrowserclass *ahtmlbrowserclass = NULL;
364phindbrowserclass *aphindbrowserclass = NULL;
[14407]365text_t userdbfile = NULL;
366userdbclass *udb = NULL;
367text_t keydbfile = NULL;
368keydbclass *kdb = NULL;
[6023]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) {
[1205]376#if defined (GSDL_USE_IOS_H)
[6023]377 cerr = &logstream;
378 cout = &textstream;
[1205]379#else
[6023]380 cerr.rdbuf(&logstream);
381 cout.rdbuf(&textstream);
[1205]382#endif
[6023]383 }
[902]384
[1615]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
[611]388 text_t collection = "";
[15625]389 text_tset dbhomes;
[16975]390 text_tset clhomes; // collecthome companion for dbhome
[1739]391 text_tset collections;
[611]392
[6023]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;
[16310]400 if (!checkdir (gsdl_collecthome + "\\")) return 0;
[6023]401 if (!checkdir (gsdl_gsdlhome + "\\macros\\")) return 0;
402 }
[902]403
[6023]404 // deleting cservers clears all the collection servers
405 if (cservers != NULL) delete cservers;
[902]406
[6023]407 cservers = new collectset();
[1886]408
[1739]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);
[15625]415 dbhomes.insert (gsdl_dbhome);
[16975]416 clhomes.insert (gsdl_collecthome);
[1739]417 collectioninfo_t tmp;
418 tmp.gsdl_gsdlhome = gsdl_gsdlhome;
[16310]419 tmp.gsdl_collecthome = gsdl_collecthome;
[15625]420 tmp.gsdl_dbhome = gsdl_dbhome;
[1739]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();
[902]432 while (this_info != end_info) {
[15625]433 if (dbhomes.find ((*this_info).second.gsdl_dbhome) == dbhomes.end()) {
[1739]434 these_collections.erase (these_collections.begin(), these_collections.end());
[16320]435 read_dir ((*this_info).second.gsdl_collecthome, these_collections);
[1739]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).
[16310]444 text_t build_cfg = filename_cat ((*this_info).second.gsdl_collecthome,
[1739]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 }
[9598]455 ++colhere;
[1739]456 }
[15625]457 dbhomes.insert ((*this_info).second.gsdl_dbhome);
[16975]458 clhomes.insert ((*this_info).second.gsdl_collecthome);
[902]459 }
[9598]460 ++this_info;
[902]461 }
[1739]462
[15625]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()) {
[1739]466 these_collections.erase (these_collections.begin(), these_collections.end());
[15625]467 read_dir (filename_cat (gsdl_dbhome, "collect"), these_collections);
[1739]468 colhere = these_collections.begin();
469 colend = these_collections.end();
470 while (colhere != colend) {
[19728]471
[19788]472 //text_t build_cfg = filename_cat (gsdl_dbhome,"collect",
473 // *colhere, "index", "build.cfg");
474 //if (file_exists (build_cfg)) {
[19728]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;
[19788]482 //}
[9598]483 ++colhere;
[1739]484 }
[15625]485 dbhomes.insert (gsdl_dbhome);
[16975]486 clhomes.insert (gsdl_collecthome);
[1739]487 }
[902]488 }
489
[1739]490 text_tset::const_iterator thiscol = collections.begin();
491 text_tset::const_iterator endcol = collections.end();
492
[611]493 while (thiscol != endcol) {
494
[1649]495 // ignore the modelcol
496 if (*thiscol == "modelcol") {
[9598]497 ++thiscol;
[1649]498 continue;
499 }
[611]500
[1649]501 // create collection server and add to null protocol
[1739]502 text_t this_gsdlhome = gsdl_gsdlhome;
[16310]503 text_t this_collecthome = gsdl_collecthome;
[15625]504 text_t this_dbhome = gsdl_dbhome;
[1739]505 colinfo_tmap::const_iterator it = translated_collectinfo.find (*thiscol);
506 assert (it != translated_collectinfo.end());
507 this_gsdlhome = (*it).second.gsdl_gsdlhome;
[16310]508 this_collecthome = (*it).second.gsdl_collecthome;
[15625]509 this_dbhome = (*it).second.gsdl_dbhome;
[1739]510
[16320]511 cservers->add_collection (*thiscol, this_gsdlhome, this_collecthome);
[18979]512 // in case it is a collection group
513 cservers->add_collection_group(*thiscol, this_gsdlhome, this_collecthome);
514
[9598]515 ++thiscol;
[611]516 }
[18979]517
[1886]518 // set up the null protocol
519 nproto.set_collectset(cservers);
[611]520
[14407]521 if ((ausersaction == NULL) && (aauthenaction == NULL)){
[19062]522 userdbfile = filename_cat(gsdl_gsdlhome, "etc", "users.gdb");
[14407]523 udb = new userdbclass(userdbfile);
[19062]524 keydbfile = filename_cat(gsdl_gsdlhome, "etc", "key.gdb");
[14407]525 kdb = new keydbclass(keydbfile);
526 }
[611]527 // add the protocol to the receptionist
[6023]528 if (atStartup) recpt.add_protocol (&nproto);
[611]529
530 // the list of actions.
[6023]531 if (astatusaction == NULL) {
532 astatusaction = new statusaction();
533 astatusaction->set_receptionist (&recpt);
534 recpt.add_action (astatusaction);
535 }
[611]536
[6023]537 if (apageaction == NULL) {
538 apageaction = new pageaction();
539 apageaction->set_receptionist (&recpt);
540 recpt.add_action (apageaction);
541 }
[611]542
[6023]543 if (apingaction == NULL) {
544 apingaction = new pingaction();
545 recpt.add_action (apingaction);
546 }
[611]547
[6023]548 if (atipaction == NULL) {
549 atipaction = new tipaction();
550 recpt.add_action (atipaction);
551 }
[1193]552
[6023]553 if (aqueryaction == NULL) {
554 aqueryaction = new queryaction();
555 aqueryaction->set_receptionist (&recpt);
556 recpt.add_action (aqueryaction);
557 }
[611]558
[6023]559 if (adocumentaction == NULL) {
560 adocumentaction = new documentaction();
561 adocumentaction->set_receptionist (&recpt);
562 recpt.add_action (adocumentaction);
563 }
[611]564
[6023]565 if (ausersaction == NULL) {
566 ausersaction = new usersaction();
[14388]567 ausersaction->set_userdb(udb);
[6023]568 recpt.add_action (ausersaction);
569 }
[902]570
[6023]571 if (anextlinkaction == NULL) {
572 anextlinkaction = new extlinkaction();
573 recpt.add_action (anextlinkaction);
574 }
[902]575
[6023]576 if (acollectoraction == NULL) {
577 acollectoraction = new collectoraction();
578 acollectoraction->set_receptionist (&recpt);
579 recpt.add_action (acollectoraction);
580 }
[611]581
[6023]582 if (aauthenaction == NULL) {
583 aauthenaction = new authenaction();
[14388]584 aauthenaction->set_userdb(udb);
585 aauthenaction->set_keydb(kdb);
[6023]586 aauthenaction->set_receptionist(&recpt);
587 recpt.add_action (aauthenaction);
588 }
[902]589
[21324]590#ifdef ENABLE_MGPP
[6023]591 if (aphindaction == NULL) {
592 aphindaction = new phindaction();
593 recpt.add_action (aphindaction);
594 }
[21324]595#endif
[4291]596
[6023]597 if (aconfigaction == NULL) {
598 aconfigaction = new configaction();
599 aconfigaction->set_receptionist(&recpt);
600 recpt.add_action (aconfigaction);
601 }
[15852]602
603 if (adynamicclassifieraction == NULL) {
604 adynamicclassifieraction = new dynamicclassifieraction();
605 adynamicclassifieraction->set_receptionist(&recpt);
606 recpt.add_action (adynamicclassifieraction);
607 }
[902]608
[2487]609
[902]610 // list of browsers
[6023]611 if (avlistbrowserclass == NULL) {
612 avlistbrowserclass = new vlistbrowserclass();
613 recpt.add_browser (avlistbrowserclass);
614 recpt.setdefaultbrowser ("VList");
615 }
[902]616
[6023]617 if (ahlistbrowserclass == NULL) {
618 ahlistbrowserclass = new hlistbrowserclass();
619 recpt.add_browser (ahlistbrowserclass);
620 }
[902]621
[6023]622 if (adatelistbrowserclass == NULL) {
623 adatelistbrowserclass = new datelistbrowserclass();
624 recpt.add_browser (adatelistbrowserclass);
625 }
[902]626
[6023]627 if (ainvbrowserclass == NULL) {
628 ainvbrowserclass = new invbrowserclass();
629 recpt.add_browser (ainvbrowserclass);
630 }
[902]631
[6023]632 if (apagedbrowserclass == NULL) {
633 apagedbrowserclass = new pagedbrowserclass();
634 recpt.add_browser (apagedbrowserclass);
635 }
[902]636
[6023]637 if (ahtmlbrowserclass == NULL) {
638 ahtmlbrowserclass = new htmlbrowserclass();
639 recpt.add_browser (ahtmlbrowserclass);
640 }
[2487]641
[6023]642 if (aphindbrowserclass == NULL) {
643 aphindbrowserclass = new phindbrowserclass();;
644 recpt.add_browser (aphindbrowserclass);
645 }
[611]646
647 // set defaults
[902]648 recpt.configure ("gsdlhome", gsdl_gsdlhome);
[16310]649 recpt.configure ("collecthome", gsdl_collecthome);
[15625]650 recpt.configure ("gdbmhome", gsdl_dbhome);
[611]651 recpt.configure ("collection", collection);
652
653 int maxrequests = 1;
[902]654
[1739]655 // configure collections (and receptionist) with collectinfo stuff
[902]656 // different from the default
[1739]657 colinfo_tmap::const_iterator this_info = translated_collectinfo.begin();
658 colinfo_tmap::const_iterator end_info = translated_collectinfo.end();
659
[902]660 while (this_info != end_info) {
[1739]661 text_tarray tmpconf;
662 tmpconf.push_back ((*this_info).first);
663 tmpconf.push_back ((*this_info).second.gsdl_gsdlhome);
[16310]664 tmpconf.push_back ((*this_info).second.gsdl_collecthome);
[15625]665 tmpconf.push_back ((*this_info).second.gsdl_dbhome);
[1739]666 recpt.configure ("collectinfo", tmpconf);
[9598]667 ++this_info;
[611]668 }
669
[15625]670 // read in config files of each dbhome (in no particular order)
[902]671 // those read in last will override those read earlier
672 // collections being used together in this way should be
[1193]673 // careful not to have main.cfg files that might
[16310]674 // interfere with each other.
[15625]675 text_tset::const_iterator thome = dbhomes.begin();
676 text_tset::const_iterator ehome = dbhomes.end();
[16975]677 text_tset::const_iterator tchome = clhomes.begin(); // collecthome companion for dbhome
678
[902]679 while (thome != ehome) {
[16975]680 if (!main_cfg_read (recpt, *thome, *tchome, collection)) {
[902]681 // couldn't find the main configuration file
682 page_errormaincfg (*thome, collection);
683 return 0;
684 }
[9598]685 ++thome;
[16975]686 ++tchome;
[902]687 }
688
[19147]689 // w32server relies on gwcgi being set to "gsdl", and httpweb to web
[2343]690 recpt.configure ("gwcgi", "gsdl");
[19147]691 recpt.configure ("httpweb", "web");
692
[611]693 // initialise the library software
694 if (!recpt.init(cerr)) {
695 // an error occurred during the initialisation
[902]696 page_errorinit(gsdl_gsdlhome);
[611]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
[1886]705
[611]706 return 1;
707}
708
709
[2286]710static void rememberpref (const text_t &tailstr) {
711 gsdl_enterlib = tailstr;
[611]712}
713
714
[2286]715static void send_file_from_disk(text_t filename,
[611]716 RequestInfoT *RInfo,
[2286]717 RequestFieldsT *RFields) {
[611]718
[2286]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;
[9598]726 ++it;
[611]727 }
[2286]728 if (lastdot < end) ext = substr(lastdot+1, end);
[611]729
[2286]730 text_t mime = "unknown";
731 int len = ext.size();
[2997]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) {
[2286]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";
[2293]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";
[2997]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";
[2293]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";
[2997]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";
[11055]773 } else if ((ext[0] == 'm' || ext[0] == 'M') &&
774 (ext[1] == 'p' || ext[1] == 'P') &&
775 (ext[2] == '3')) {
776 mime = "audio/mpeg";
[2286]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 }
[611]791
[2286]792 // try to open the file
[16975]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
[7519]813 /* Feb 2002 - handle files with spaces in their name. */
[3020]814 text_t::iterator space_start;
815 space_start=findword(filename.begin(),filename.end(),"%20");
[7519]816 while (space_start != filename.end()) {
[3020]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;
[7519]823 space_start=findword(filename.begin(),filename.end(),"%20");
[3020]824 }
825
[2286]826 char *filenamec = filename.getcstr();
[12761]827 TranslateEscapeString(filenamec); // Resolve any %xx values
[2286]828 FILE *thefile = fopen(filenamec, "rb");
[9636]829 delete []filenamec;
[611]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 }
[2286]836 int nr;
[611]837 char buffer[2048];
838 // send back required information
[2286]839 char *mimec = mime.getcstr();
840 if (send_header(mimec, RInfo) >= 0) {
[3810]841 if (RFields->MethodStr != "HEAD") {
[611]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 }
[9636]851 delete []mimec;
[611]852 fclose(thefile);
853}
854
[2286]855static void handle_library_request(const text_t &argstr, RequestInfoT *RInfo,
[611]856 RequestFieldsT *RequestFields) {
857
858 // parse the cgi arguments and produce the resulting page if there
[2286]859 // have been no errors so far
[611]860 cgiargsclass args;
[12527]861 fileupload_tmap fileuploads;
[902]862 text_tmap empty; // don't use this (it's for fastcgi on unix)
[12527]863 if (!recpt.parse_cgi_args (argstr, fileuploads, args, cerr, empty)) {
[902]864 page_errorparseargs(gsdl_gsdlhome);
[611]865 return;
866 }
[1739]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;
[16975]871 current_collecthome = (*it).second.gsdl_collecthome;
[1739]872 } else {
873 current_gsdlhome = gsdl_gsdlhome;
[16975]874 current_collecthome = gsdl_collecthome;
[1739]875 }
876
[611]877 // produce cgi header
878 response_t response;
879 text_t response_data;
880
[902]881 recpt.get_cgihead_info (args, response, response_data, cerr, empty);
[611]882
883 if (response == location) {
884 // location response
[902]885 response_data = "@" + recpt.expandmacros (response_data, args, cerr);
886 char *response_data_c = response_data.getcstr();
887 send_header(response_data_c, RInfo);
[9636]888 delete []response_data_c;
[902]889 return;
[611]890 } else if (response == content) {
891 // content response
[902]892 char *response_data_c = response_data.getcstr();
893 if (send_header(response_data_c, RInfo) < 0) {
[9636]894 delete []response_data_c;
[902]895 return;
896 }
[9636]897 delete []response_data_c;
[9138]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 {
[611]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)) {
[902]916 page_errorcgipage(gsdl_gsdlhome);
[611]917 return;
918 }
[902]919 recpt.log_cgi_args (args, cerr, empty);
[611]920
921 cout << flush;
922 cerr << flush;
923
[9598]924 ++libaccessnum;
[611]925}
926
[2286]927static void handle_server_request(text_t &tailstr,
[611]928 RequestInfoT *RequestInfo,
929 RequestFieldsT *RequestFields) {
930
[2286]931 text_t argstr;
932
[611]933 // do any url adjustments necessary
[2286]934 if (tailstr.empty() || tailstr == "/") {
[2343]935 tailstr = "/gsdl";
[2286]936 }
937
938 text_t::const_iterator begin = tailstr.begin();
939 text_t::const_iterator end = tailstr.end();
[611]940
941 // test to see if this is a library request or a local
942 // file request
[2343]943 if ((tailstr == "/gsdl") ||
944 ((tailstr.size() > 5) && (substr(begin, begin+6) == "/gsdl?"))) {
[2286]945
[611]946 // library request
947
[2286]948 // argstr is the bit after the '?'
[2343]949 if (tailstr != "/gsdl") {
950 argstr = substr(begin+6, end);
[2286]951 }
952
[611]953 // log the difference in access times
954 DWORD thislibaccesstime = GetTickCount();
[2286]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);
[611]959 }
960 lastlibaccesstime = thislibaccesstime;
961
962 // log this request
[2286]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);
[9636]967 delete []logstrc;
[611]968 }
969
[2286]970 handle_library_request (argstr, RequestInfo, RequestFields);
[611]971
972 // remember the preferences
[2286]973 // rememberpref (tailstr);
[611]974
975 // log memory information
[2286]976 if (gsdl_keep_log || gsdl_show_console) {
[611]977 MEMORYSTATUS memstatus;
978 memstatus.dwLength = sizeof(MEMORYSTATUS);
979 GlobalMemoryStatus(&memstatus);
[2286]980 char logstr[256];
981 sprintf (logstr, "BDELTA AVAIL VIRTUAL: %i K\n",
[611]982 (int)((baseavailvirtual - memstatus.dwAvailVirtual)/1024));
[2286]983 log_message (logstr);
[611]984 }
985
986 } else {
987 // local file
[2286]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);
[9636]992 delete []logstrc;
[611]993 }
994 send_file_from_disk (tailstr, RequestInfo, RequestFields);
995 }
996}
997
[2280]998int ExamineURIStr(text_t &URIStr, RequestInfoT *RequestInfo,
[611]999 RequestFieldsT *RequestFields)
1000{
[2286]1001 text_t protocol, machine, rest;
1002 int port;
[1624]1003
1004 if (RequestFields->ContentLength > 0) {
1005 // POST data
[2280]1006 URIStr.push_back('?');
[9598]1007 for (int i = 0; i < RequestFields->ContentLength; ++i) {
[2286]1008 URIStr.push_back(RequestFields->Content[i]);
1009 }
[1624]1010 }
[2280]1011
[2286]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);
[611]1017 }
1018
[2286]1019 if (machine == "gsdl") {
[611]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 repository browser.