source: gsdl/trunk/src/w32server/cgiwrapper.cpp@ 15852

Last change on this file since 15852 was 15852, checked in by mdewsnip, 16 years ago

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

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