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

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

Fixed a bug that was causing the local library server to attempt to write
files to gsdlhome (i.e. the cd-rom drive if served from a cd) under certain
circumstances.

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