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

Last change on this file since 16975 was 16975, checked in by davidb, 16 years ago

support for /collect in URL pointing to area designated by 'collecthome'

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 29.8 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);
[9117]502
[9598]503 ++thiscol;
[611]504 }
[1886]505
506 // set up the null protocol
507 nproto.set_collectset(cservers);
[611]508
[14407]509 if ((ausersaction == NULL) && (aauthenaction == NULL)){
510 userdbfile = filename_cat(gsdl_gsdlhome, "etc", "users.db");
511 udb = new userdbclass(userdbfile);
512 keydbfile = filename_cat(gsdl_gsdlhome, "etc", "key.db");
513 kdb = new keydbclass(keydbfile);
514 }
[611]515 // add the protocol to the receptionist
[6023]516 if (atStartup) recpt.add_protocol (&nproto);
[611]517
518 // the list of actions.
[6023]519 if (astatusaction == NULL) {
520 astatusaction = new statusaction();
521 astatusaction->set_receptionist (&recpt);
522 recpt.add_action (astatusaction);
523 }
[611]524
[6023]525 if (apageaction == NULL) {
526 apageaction = new pageaction();
527 apageaction->set_receptionist (&recpt);
528 recpt.add_action (apageaction);
529 }
[611]530
[6023]531 if (apingaction == NULL) {
532 apingaction = new pingaction();
533 recpt.add_action (apingaction);
534 }
[611]535
[6023]536 if (atipaction == NULL) {
537 atipaction = new tipaction();
538 recpt.add_action (atipaction);
539 }
[1193]540
[6023]541 if (aqueryaction == NULL) {
542 aqueryaction = new queryaction();
543 aqueryaction->set_receptionist (&recpt);
544 recpt.add_action (aqueryaction);
545 }
[611]546
[6023]547 if (adocumentaction == NULL) {
548 adocumentaction = new documentaction();
549 adocumentaction->set_receptionist (&recpt);
550 recpt.add_action (adocumentaction);
551 }
[611]552
[6023]553 if (ausersaction == NULL) {
554 ausersaction = new usersaction();
[14388]555 ausersaction->set_userdb(udb);
[6023]556 recpt.add_action (ausersaction);
557 }
[902]558
[6023]559 if (anextlinkaction == NULL) {
560 anextlinkaction = new extlinkaction();
561 recpt.add_action (anextlinkaction);
562 }
[902]563
[6023]564 if (acollectoraction == NULL) {
565 acollectoraction = new collectoraction();
566 acollectoraction->set_receptionist (&recpt);
567 recpt.add_action (acollectoraction);
568 }
[611]569
[6023]570 if (aauthenaction == NULL) {
571 aauthenaction = new authenaction();
[14388]572 aauthenaction->set_userdb(udb);
573 aauthenaction->set_keydb(kdb);
[6023]574 aauthenaction->set_receptionist(&recpt);
575 recpt.add_action (aauthenaction);
576 }
[902]577
[6023]578 if (aphindaction == NULL) {
579 aphindaction = new phindaction();
580 recpt.add_action (aphindaction);
581 }
[4291]582
[6023]583 if (aconfigaction == NULL) {
584 aconfigaction = new configaction();
585 aconfigaction->set_receptionist(&recpt);
586 recpt.add_action (aconfigaction);
587 }
[15852]588
589 if (adynamicclassifieraction == NULL) {
590 adynamicclassifieraction = new dynamicclassifieraction();
591 adynamicclassifieraction->set_receptionist(&recpt);
592 recpt.add_action (adynamicclassifieraction);
593 }
[902]594
[2487]595
[902]596 // list of browsers
[6023]597 if (avlistbrowserclass == NULL) {
598 avlistbrowserclass = new vlistbrowserclass();
599 recpt.add_browser (avlistbrowserclass);
600 recpt.setdefaultbrowser ("VList");
601 }
[902]602
[6023]603 if (ahlistbrowserclass == NULL) {
604 ahlistbrowserclass = new hlistbrowserclass();
605 recpt.add_browser (ahlistbrowserclass);
606 }
[902]607
[6023]608 if (adatelistbrowserclass == NULL) {
609 adatelistbrowserclass = new datelistbrowserclass();
610 recpt.add_browser (adatelistbrowserclass);
611 }
[902]612
[6023]613 if (ainvbrowserclass == NULL) {
614 ainvbrowserclass = new invbrowserclass();
615 recpt.add_browser (ainvbrowserclass);
616 }
[902]617
[6023]618 if (apagedbrowserclass == NULL) {
619 apagedbrowserclass = new pagedbrowserclass();
620 recpt.add_browser (apagedbrowserclass);
621 }
[902]622
[6023]623 if (ahtmlbrowserclass == NULL) {
624 ahtmlbrowserclass = new htmlbrowserclass();
625 recpt.add_browser (ahtmlbrowserclass);
626 }
[2487]627
[6023]628 if (aphindbrowserclass == NULL) {
629 aphindbrowserclass = new phindbrowserclass();;
630 recpt.add_browser (aphindbrowserclass);
631 }
[611]632
633 // set defaults
[902]634 recpt.configure ("gsdlhome", gsdl_gsdlhome);
[16310]635 recpt.configure ("collecthome", gsdl_collecthome);
[15625]636 recpt.configure ("gdbmhome", gsdl_dbhome);
[611]637 recpt.configure ("collection", collection);
638
639 int maxrequests = 1;
[902]640
[1739]641 // configure collections (and receptionist) with collectinfo stuff
[902]642 // different from the default
[1739]643 colinfo_tmap::const_iterator this_info = translated_collectinfo.begin();
644 colinfo_tmap::const_iterator end_info = translated_collectinfo.end();
645
[902]646 while (this_info != end_info) {
[1739]647 text_tarray tmpconf;
648 tmpconf.push_back ((*this_info).first);
649 tmpconf.push_back ((*this_info).second.gsdl_gsdlhome);
[16310]650 tmpconf.push_back ((*this_info).second.gsdl_collecthome);
[15625]651 tmpconf.push_back ((*this_info).second.gsdl_dbhome);
[1739]652 recpt.configure ("collectinfo", tmpconf);
[9598]653 ++this_info;
[611]654 }
655
[15625]656 // read in config files of each dbhome (in no particular order)
[902]657 // those read in last will override those read earlier
658 // collections being used together in this way should be
[1193]659 // careful not to have main.cfg files that might
[16310]660 // interfere with each other.
[15625]661 text_tset::const_iterator thome = dbhomes.begin();
662 text_tset::const_iterator ehome = dbhomes.end();
[16975]663 text_tset::const_iterator tchome = clhomes.begin(); // collecthome companion for dbhome
664
[902]665 while (thome != ehome) {
[16975]666 if (!main_cfg_read (recpt, *thome, *tchome, collection)) {
[902]667 // couldn't find the main configuration file
668 page_errormaincfg (*thome, collection);
669 return 0;
670 }
[9598]671 ++thome;
[16975]672 ++tchome;
[902]673 }
674
[2343]675 // w32server relies on gwcgi being set to "gsdl"
676 recpt.configure ("gwcgi", "gsdl");
[611]677
678 // initialise the library software
679 if (!recpt.init(cerr)) {
680 // an error occurred during the initialisation
[902]681 page_errorinit(gsdl_gsdlhome);
[611]682 return 0;
683 }
684
685 // get memory information
686 MEMORYSTATUS memstatus;
687 memstatus.dwLength = sizeof(MEMORYSTATUS);
688 GlobalMemoryStatus(&memstatus);
689 baseavailvirtual = memstatus.dwAvailVirtual; // save for later comparison
[1886]690
[611]691 return 1;
692}
693
694
[2286]695static void rememberpref (const text_t &tailstr) {
696 gsdl_enterlib = tailstr;
[611]697}
698
699
[2286]700static void send_file_from_disk(text_t filename,
[611]701 RequestInfoT *RInfo,
[2286]702 RequestFieldsT *RFields) {
[611]703
[2286]704 // select appropriate mime type from file extension
705 text_t ext;
706 text_t::const_iterator end = filename.end();
707 text_t::const_iterator it = filename.begin();
708 text_t::const_iterator lastdot = end;
709 while ((it = findchar(it, end, '.')) != end) {
710 lastdot = it;
[9598]711 ++it;
[611]712 }
[2286]713 if (lastdot < end) ext = substr(lastdot+1, end);
[611]714
[2286]715 text_t mime = "unknown";
716 int len = ext.size();
[2997]717 if (len == 2) {
718 if ((ext[0] == 'p' || ext[0] == 'P') &&
719 (ext[1] == 's' || ext[1] == 'S'))
720 mime = "application/postscript";
721 } else if (len == 3) {
[2286]722 if ((ext[0] == 'g' || ext[0] == 'G') &&
723 (ext[1] == 'i' || ext[1] == 'I') &&
724 (ext[2] == 'f' || ext[2] == 'F')) {
725 mime = "image/gif";
726 } else if ((ext[0] == 'j' || ext[0] == 'J') &&
727 (ext[1] == 'p' || ext[1] == 'P') &&
728 (ext[2] == 'g' || ext[2] == 'G')) {
729 mime = "image/jpeg";
730 } else if ((ext[0] == 'h' || ext[0] == 'H') &&
731 (ext[1] == 't' || ext[1] == 'T') &&
732 (ext[2] == 'm' || ext[2] == 'M')) {
733 mime = "text/html";
[2293]734 } else if ((ext[0] == 'p' || ext[0] == 'P') &&
735 (ext[1] == 'd' || ext[1] == 'D') &&
736 (ext[2] == 'f' || ext[2] == 'F')) {
737 mime = "application/pdf";
[2997]738 } else if ((ext[0] == 'p' || ext[0] == 'P') &&
739 (ext[1] == 'n' || ext[1] == 'N') &&
740 (ext[2] == 'g' || ext[2] == 'G')) {
741 mime = "image/png";
[2293]742 } else if ((ext[0] == 'd' || ext[0] == 'D') &&
743 (ext[1] == 'o' || ext[1] == 'O') &&
744 (ext[2] == 'c' || ext[2] == 'C')) {
745 mime = "application/msword";
746 } else if ((ext[0] == 'r' || ext[0] == 'R') &&
747 (ext[1] == 't' || ext[1] == 'T') &&
748 (ext[2] == 'f' || ext[2] == 'F')) {
749 mime = "application/rtf";
[2997]750 } else if ((ext[0] == 'x' || ext[0] == 'X') &&
751 (ext[1] == 'l' || ext[1] == 'L') &&
752 (ext[2] == 's' || ext[2] == 'S')) {
753 mime = "application/vnd.ms-excel";
754 } else if ((ext[0] == 'p' || ext[0] == 'P') &&
755 (ext[1] == 'p' || ext[1] == 'P') &&
756 (ext[2] == 'T' || ext[2] == 'T')) {
757 mime = "application/vnd.ms-powerpoint";
[11055]758 } else if ((ext[0] == 'm' || ext[0] == 'M') &&
759 (ext[1] == 'p' || ext[1] == 'P') &&
760 (ext[2] == '3')) {
761 mime = "audio/mpeg";
[2286]762 }
763 } else if (len == 4) {
764 if ((ext[0] == 'j' || ext[0] == 'J') &&
765 (ext[1] == 'p' || ext[1] == 'P') &&
766 (ext[2] == 'e' || ext[2] == 'E') &&
767 (ext[3] == 'g' || ext[3] == 'G')) {
768 mime = "image/jpeg";
769 } else if ((ext[0] == 'h' || ext[0] == 'H') &&
770 (ext[1] == 't' || ext[1] == 'T') &&
771 (ext[2] == 'm' || ext[2] == 'M') &&
772 (ext[3] == 'l' || ext[3] == 'L')) {
773 mime = "text/html";
774 }
775 }
[611]776
[2286]777 // try to open the file
[16975]778 //cerr << "*** filename = " << filename.getcstr() << endl;
779 //cerr << "**** collect_home = " << current_collecthome.getcstr() << endl;
780
781 if (filename.size()>=9) {
782 text_t prefix = substr(filename.begin(),filename.begin()+9);
783 //cerr << "**** prefix = " << prefix.getcstr() << endl;
784
785 text_t tail = substr(filename.begin()+9,filename.end());
786 //cerr << "**** tail = " << tail.getcstr() << endl;
787
788 if (prefix == "/collect/") {
789 filename = filename_cat (current_collecthome, tail);
790 }
791 else {
792 filename = filename_cat (current_gsdlhome, filename);
793 }
794 }
795
796 cerr << "#### filename = " << filename.getcstr() << endl;
797
[7519]798 /* Feb 2002 - handle files with spaces in their name. */
[3020]799 text_t::iterator space_start;
800 space_start=findword(filename.begin(),filename.end(),"%20");
[7519]801 while (space_start != filename.end()) {
[3020]802 // we found a space...
803 text_t::iterator after_space=space_start+3;
804 text_t new_filename=substr(filename.begin(), space_start);
805 new_filename += " ";
806 new_filename += substr(after_space,filename.end());
807 filename=new_filename;
[7519]808 space_start=findword(filename.begin(),filename.end(),"%20");
[3020]809 }
810
[2286]811 char *filenamec = filename.getcstr();
[12761]812 TranslateEscapeString(filenamec); // Resolve any %xx values
[2286]813 FILE *thefile = fopen(filenamec, "rb");
[9636]814 delete []filenamec;
[611]815 if (thefile == NULL) {
816 log_message("file not found\n");
817 send_retrieve_error(404, "File not found",
818 "Could not find the local file requested", RInfo);
819 return;
820 }
[2286]821 int nr;
[611]822 char buffer[2048];
823 // send back required information
[2286]824 char *mimec = mime.getcstr();
825 if (send_header(mimec, RInfo) >= 0) {
[3810]826 if (RFields->MethodStr != "HEAD") {
[611]827 for (;;) {
828 nr = fread(buffer, 1, 2048, thefile);
829 if (nr <= 0) break;
830 if (SendData(RInfo->ClientSocket,
831 (BYTE *)buffer, nr,
832 RInfo->ThreadNum) < 0) break;
833 }
834 }
835 }
[9636]836 delete []mimec;
[611]837 fclose(thefile);
838}
839
[2286]840static void handle_library_request(const text_t &argstr, RequestInfoT *RInfo,
[611]841 RequestFieldsT *RequestFields) {
842
843 // parse the cgi arguments and produce the resulting page if there
[2286]844 // have been no errors so far
[611]845 cgiargsclass args;
[12527]846 fileupload_tmap fileuploads;
[902]847 text_tmap empty; // don't use this (it's for fastcgi on unix)
[12527]848 if (!recpt.parse_cgi_args (argstr, fileuploads, args, cerr, empty)) {
[902]849 page_errorparseargs(gsdl_gsdlhome);
[611]850 return;
851 }
[1739]852
853 colinfo_tmap::const_iterator it = translated_collectinfo.find (args["c"]);
854 if (it != translated_collectinfo.end()) {
855 current_gsdlhome = (*it).second.gsdl_gsdlhome;
[16975]856 current_collecthome = (*it).second.gsdl_collecthome;
[1739]857 } else {
858 current_gsdlhome = gsdl_gsdlhome;
[16975]859 current_collecthome = gsdl_collecthome;
[1739]860 }
861
[611]862 // produce cgi header
863 response_t response;
864 text_t response_data;
865
[902]866 recpt.get_cgihead_info (args, response, response_data, cerr, empty);
[611]867
868 if (response == location) {
869 // location response
[902]870 response_data = "@" + recpt.expandmacros (response_data, args, cerr);
871 char *response_data_c = response_data.getcstr();
872 send_header(response_data_c, RInfo);
[9636]873 delete []response_data_c;
[902]874 return;
[611]875 } else if (response == content) {
876 // content response
[902]877 char *response_data_c = response_data.getcstr();
878 if (send_header(response_data_c, RInfo) < 0) {
[9636]879 delete []response_data_c;
[902]880 return;
881 }
[9636]882 delete []response_data_c;
[9138]883 }
884 else if (response == undecided_location) {
885 // We know this is a relocation request but at the moment we don't know exactly where to
886 // Just output the start of the header and wait until later to output the target location
887 // Used for the "I'm feeling lucky" functionality
888 cout << "HTTP/1.0 302 Relocation\r\n";
889 cout << "Server: GSDL\r\n";
890 cout << "Content-type: text/html \r\n";
891 }
892 else {
[611]893 // unknown response
894 cerr << "Error: get_cgihead_info returned an unknown response type.\n";
895 return;
896 }
897
898 textstream.tsbreset();
899 textstream.setrequestinfo (RInfo);
900 if (!recpt.produce_content (args, cout, cerr)) {
[902]901 page_errorcgipage(gsdl_gsdlhome);
[611]902 return;
903 }
[902]904 recpt.log_cgi_args (args, cerr, empty);
[611]905
906 cout << flush;
907 cerr << flush;
908
[9598]909 ++libaccessnum;
[611]910}
911
[2286]912static void handle_server_request(text_t &tailstr,
[611]913 RequestInfoT *RequestInfo,
914 RequestFieldsT *RequestFields) {
915
[2286]916 text_t argstr;
917
[611]918 // do any url adjustments necessary
[2286]919 if (tailstr.empty() || tailstr == "/") {
[2343]920 tailstr = "/gsdl";
[2286]921 }
922
923 text_t::const_iterator begin = tailstr.begin();
924 text_t::const_iterator end = tailstr.end();
[611]925
926 // test to see if this is a library request or a local
927 // file request
[2343]928 if ((tailstr == "/gsdl") ||
929 ((tailstr.size() > 5) && (substr(begin, begin+6) == "/gsdl?"))) {
[2286]930
[611]931 // library request
932
[2286]933 // argstr is the bit after the '?'
[2343]934 if (tailstr != "/gsdl") {
935 argstr = substr(begin+6, end);
[2286]936 }
937
[611]938 // log the difference in access times
939 DWORD thislibaccesstime = GetTickCount();
[2286]940 if (gsdl_keep_log || gsdl_show_console) {
941 char logstr[256];
942 sprintf(logstr, "DELTA LIB ACCESS TIME: %i\n", (int)(thislibaccesstime - lastlibaccesstime));
943 log_message (logstr);
[611]944 }
945 lastlibaccesstime = thislibaccesstime;
946
947 // log this request
[2286]948 if (gsdl_keep_log || gsdl_show_console) {
949 text_t logstr = "LOCAL LIB: " + tailstr + "\n";
950 char *logstrc = logstr.getcstr();
951 log_message (logstrc);
[9636]952 delete []logstrc;
[611]953 }
954
[2286]955 handle_library_request (argstr, RequestInfo, RequestFields);
[611]956
957 // remember the preferences
[2286]958 // rememberpref (tailstr);
[611]959
960 // log memory information
[2286]961 if (gsdl_keep_log || gsdl_show_console) {
[611]962 MEMORYSTATUS memstatus;
963 memstatus.dwLength = sizeof(MEMORYSTATUS);
964 GlobalMemoryStatus(&memstatus);
[2286]965 char logstr[256];
966 sprintf (logstr, "BDELTA AVAIL VIRTUAL: %i K\n",
[611]967 (int)((baseavailvirtual - memstatus.dwAvailVirtual)/1024));
[2286]968 log_message (logstr);
[611]969 }
970
971 } else {
972 // local file
[2286]973 if (gsdl_keep_log || gsdl_show_console) {
974 text_t logstr = "LOCAL FILE: " + tailstr + "\n";
975 char *logstrc = logstr.getcstr();
976 log_message (logstrc);
[9636]977 delete []logstrc;
[611]978 }
979 send_file_from_disk (tailstr, RequestInfo, RequestFields);
980 }
981}
982
[2280]983int ExamineURIStr(text_t &URIStr, RequestInfoT *RequestInfo,
[611]984 RequestFieldsT *RequestFields)
985{
[2286]986 text_t protocol, machine, rest;
987 int port;
[1624]988
989 if (RequestFields->ContentLength > 0) {
990 // POST data
[2280]991 URIStr.push_back('?');
[9598]992 for (int i = 0; i < RequestFields->ContentLength; ++i) {
[2286]993 URIStr.push_back(RequestFields->Content[i]);
994 }
[1624]995 }
[2280]996
[2286]997 if (parse_url(URIStr, protocol, machine, &port, rest)!=http_ok) {
998 // Alter local file request to address 'gsdl'
999 if (*(URIStr.begin()) != '/') URIStr = "http://gsdl/" + URIStr;
1000 else URIStr = "http://gsdl" + URIStr;
1001 parse_url(URIStr, protocol, machine, &port, rest);
[611]1002 }
1003
[2286]1004 if (machine == "gsdl") {
[611]1005 // a local file request
1006 handle_server_request(rest, RequestInfo, RequestFields);
1007
1008 } else {
1009 send_retrieve_error(404, "File not found",
1010 "Could not find the local file requested", RequestInfo);
1011 }
1012
1013 return 1;
1014}
Note: See TracBrowser for help on using the repository browser.