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

Last change on this file since 1284 was 1284, checked in by sjboddie, 24 years ago

added GPL headers to some of the windows local library files

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