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

Last change on this file since 2487 was 2487, checked in by sjboddie, 23 years ago

Changes to get phind working under windows

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