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

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

Caught local library up with changes brought about when corba stuff
was added.

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