source: gsdl/trunk/runtime-src/src/w32server/cgiwrapper.cpp@ 19062

Last change on this file since 19062 was 19062, checked in by kjdon, 15 years ago

all gdbm files (key, users, history, argdb) now use gdb extension instead of db

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