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

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

changed the local library's cryptic "gw" url to the slightly less
cryptic gsdl

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