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

Last change on this file since 22833 was 22833, checked in by ak19, 13 years ago

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

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