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

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