source: trunk/gsdl/src/recpt/cgiwrapper.cpp@ 248

Last change on this file since 248 was 248, checked in by sjboddie, 25 years ago

lots of stuff - getting documentaction working (documentaction replaces
old browseaction)

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 12.9 KB
RevLine 
[144]1/**********************************************************************
2 *
3 * cgiwrapper.cpp -- output pages using the cgi protocol
4 * Copyright (C) 1999 The New Zealand Digital Library Project
5 *
6 * PUT COPYRIGHT NOTICE HERE
7 *
8 * $Id: cgiwrapper.cpp 248 1999-04-30 01:59:44Z sjboddie $
9 *
10 *********************************************************************/
11
12/*
13 $Log$
[248]14 Revision 1.12 1999/04/30 01:59:40 sjboddie
15 lots of stuff - getting documentaction working (documentaction replaces
16 old browseaction)
17
[210]18 Revision 1.11 1999/03/25 03:12:01 sjboddie
19
20 subjectbrowseaction was replaced with browseaction
21
[189]22 Revision 1.10 1999/03/05 03:53:54 sjboddie
23
24 fixed some bugs
25
[188]26 Revision 1.9 1999/03/04 22:38:21 sjboddie
27
28 Added subjectbrowseaction. - Doesn't do anything yet.
29
[173]30 Revision 1.8 1999/02/28 20:00:13 rjmcnab
31
32
33 Fixed a few things.
34
[165]35 Revision 1.7 1999/02/21 22:33:53 rjmcnab
36
37 Lots of stuff :-)
38
[160]39 Revision 1.6 1999/02/12 02:40:17 sjboddie
40
41 Added page action
42
[158]43 Revision 1.5 1999/02/11 01:24:04 rjmcnab
44
45 Fixed a few compiler warnings.
46
[155]47 Revision 1.4 1999/02/08 01:28:01 rjmcnab
48
49 Got the receptionist producing something using the statusaction.
50
[150]51 Revision 1.3 1999/02/05 10:42:44 rjmcnab
52
53 Continued working on receptionist
54
[146]55 Revision 1.2 1999/02/04 10:00:56 rjmcnab
56
57 Developed the idea of an "action" and having them define the cgi arguments
58 which they need and how those cgi arguments function.
59
[144]60 Revision 1.1 1999/02/04 01:16:17 rjmcnab
61
62 Initial revision.
63
64 Revision 1.5 1999/01/19 01:38:18 rjmcnab
65
66 Made the source more portable.
67
68 Revision 1.4 1999/01/12 01:51:04 rjmcnab
69
70 Standard header.
71
72 */
73
74
75#include "gsdlconf.h"
76#include "cgiwrapper.h"
[150]77#include "recptconfig.h"
[155]78#include "action.h"
79#include "statusaction.h"
[160]80#include "pageaction.h"
[165]81#include "pingaction.h"
[173]82#include "queryaction.h"
[248]83#include "documentaction.h"
[144]84#include <stdlib.h>
85
[150]86
[144]87#if defined(GSDL_USE_OBJECTSPACE)
88# include <ospace/std/iostream>
89# include <ospace/std/fstream>
90#elif defined(GSDL_USE_IOS_H)
91# include <iostream.h>
92# include <fstream.h>
93#else
94# include <iostream>
95# include <fstream>
96#endif
97
98#ifdef USE_FASTCGI
99#include "fcgiapp.h"
100#endif
101
102// Note: site.h would not be needed if we could
103// dynamically find out gsdlhome.
104#include "site.h"
105
106
107#ifdef USE_FASTCGI
108// used to output the text from receptionist
109class fcgistreambuf : public streambuf {
110public:
111 fcgistreambuf ();
112 int sync ();
113 int overflow (int ch);
114 int underflow () {return EOF;}
115
116 void fcgisbreset() {fcgx_stream = NULL; other_ostream = NULL;};
117 void set_fcgx_stream(FCGX_Stream *newone) {fcgx_stream=newone;};
118 void set_other_ostream(ostream *newone) {other_ostream=newone;};
119
120private:
121 FCGX_Stream *fcgx_stream;
122 ostream *other_ostream;
123};
124
125fcgistreambuf::fcgistreambuf() {
126 fcgisbreset();
127 if (base() == ebuf()) allocate();
128 setp (base(), ebuf());
129};
130
131int fcgistreambuf::sync () {
132 if ((fcgx_stream != NULL) &&
133 (FCGX_PutStr (pbase(), out_waiting(), fcgx_stream) < 0)) {
134 fcgx_stream = NULL;
135 }
136
137 if (other_ostream != NULL) {
138 char *thepbase=pbase();
139 for (int i=0;i<out_waiting();i++) (*other_ostream).put(thepbase[i]);
140 }
141
142 setp (pbase(), epptr());
143
144 return 0;
145}
146
147int fcgistreambuf::overflow (int ch) {
148 if (sync () == EOF) return EOF;
149 if (ch != EOF) sputc (ch);
150 return 0;
151}
152
153#endif
154
155
[155]156static void page_errorsitecfg (const text_t &gsdlhome, const text_t &collection,
157 text_t &errorpage) {
158 errorpage += "Content-type: text/html\n\n";
[144]159
[155]160 errorpage += "<html>\n";
161 errorpage += "<head>\n";
162 errorpage += "<title>Error</title>\n";
163 errorpage += "</head>\n";
164 errorpage += "<body>\n";
165 errorpage += "<h2>Oops!</h2>\n";
166 errorpage += "The site.cfg configuration file could not be found. This file\n";
167 errorpage += "should contain configuration information relating to this\n";
168 errorpage += "site's setup. ";
169 if (collection.empty()) {
170 errorpage += "As this cgi script is not being run in collection specific mode,\n";
171 errorpage += "the file should reside at ";
172 errorpage += gsdlhome;
173 errorpage += "/etc/site.cfg.\n";
174 } else {
175 errorpage += "As this cgi script is being run in collection specific mode,\n";
176 errorpage += "the file can reside in ";
177 errorpage += gsdlhome;
178 errorpage += "/collect/";
179 errorpage += collection;
180 errorpage += "/etc/site.cfg or ";
181 errorpage += gsdlhome;
182 errorpage += "/etc/site.cfg.\n";
183 }
184 errorpage += "</body>\n";
185 errorpage += "</html>\n";
186}
[144]187
[155]188
189static void page_errormaincfg (const text_t &gsdlhome, const text_t &collection,
190 text_t &errorpage) {
191 errorpage += "Content-type: text/html\n\n";
192
193 errorpage += "<html>\n";
194 errorpage += "<head>\n";
195 errorpage += "<title>Error</title>\n";
196 errorpage += "</head>\n";
197 errorpage += "<body>\n";
198 errorpage += "<h2>Oops!</h2>\n";
[144]199 if (collection.empty()) {
[155]200 errorpage += "The main.cfg configuration file could not be found. This file\n";
201 errorpage += "should contain configuration information relating to the\n";
202 errorpage += "setup of the interface. As this cgi script is not being run\n";
203 errorpage += "in collection specific mode the file should reside at\n";
204 errorpage += gsdlhome;
205 errorpage += "/etc/main.cfg.\n";
[144]206 } else {
[155]207 errorpage += "Neither the collect.cfg or main.cfg configuration files could\n";
208 errorpage += "not be found. This file should contain configuration information\n";
209 errorpage += "relating to the setup of the interface. As this cgi script is\n";
210 errorpage += "being run in collection specific mode the file should reside\n";
211 errorpage += "at either ";
212 errorpage += gsdlhome;
213 errorpage += "/collect/";
214 errorpage += collection;
215 errorpage += "/etc/collect.cfg, ";
216 errorpage += gsdlhome;
217 errorpage += "/etc/collect.cfg or ";
218 errorpage += gsdlhome;
219 errorpage += "/etc/main.cfg.\n";
[144]220 }
[155]221 errorpage += "</body>\n";
222 errorpage += "</html>\n";
[144]223}
224
225
[158]226static void page_errorinit (const text_t &/*gsdlhome*/, text_t &errorpage) {
[155]227 errorpage += "Content-type: text/html\n\n";
[150]228
[155]229 errorpage += "<html>\n";
230 errorpage += "<head>\n";
231 errorpage += "<title>Error</title>\n";
232 errorpage += "</head>\n";
233 errorpage += "<body>\n";
234 errorpage += "<h2>Oops!</h2>\n";
235 errorpage += "An error occurred during the initialisation of the Greenstone Digital\n";
236 errorpage += "Library software. It is likely that the software has not been setup\n";
237 errorpage += "correctly.\n";
[144]238
[155]239 ifstream initin (GSDL_GSDLHOME "/etc/initout.txt");
240 if (initin) {
241 errorpage += "The initialisation error log, " GSDL_GSDLHOME "/etc/initout.txt, contains the\n";
242 errorpage += "following information:\n\n";
243 errorpage += "<pre>\n";
244
245 char c;
246 initin.get(c);
247 while (!initin.eof ()) {
248 errorpage.push_back(c);
249 initin.get(c);
250 }
251
252 errorpage += "</pre>\n";
253
254 initin.close();
255
[150]256 } else {
[155]257 errorpage += "Please consult " GSDL_GSDLHOME "/etc/initout.txt for more information.\n";
[150]258 }
[155]259
260 errorpage += "</body>\n";
261 errorpage += "</html>\n";
[150]262}
263
[158]264static void page_errorparseargs (const text_t &/*gsdlhome*/, text_t &errorpage) {
[155]265 errorpage += "Content-type: text/html\n\n";
[150]266
[155]267 errorpage += "<html>\n";
268 errorpage += "<head>\n";
269 errorpage += "<title>Error</title>\n";
270 errorpage += "</head>\n";
271 errorpage += "<body>\n";
272 errorpage += "<h2>Oops!</h2>\n";
273 errorpage += "An error occurred during the parsing of the cgi arguments.\n";
[150]274
[155]275 ifstream errin (GSDL_GSDLHOME "/etc/errout.txt");
276 if (errin) {
277 errorpage += "The error log, " GSDL_GSDLHOME "/etc/errout.txt, contains the\n";
278 errorpage += "following information:\n\n";
279 errorpage += "<pre>\n";
[150]280
[155]281 char c;
282 errin.get(c);
283 while (!errin.eof ()) {
284 errorpage.push_back(c);
285 errin.get(c);
286 }
287 errorpage += "</pre>\n";
288 errin.close();
289
290 } else {
291 errorpage += "Please consult " GSDL_GSDLHOME "/etc/errout.txt for more information.\n";
292 }
293
294 errorpage += "</body>\n";
295 errorpage += "</html>\n";
[144]296}
297
[158]298static void page_errorcgipage (const text_t &/*gsdlhome*/, text_t &errorpage) {
[155]299 errorpage += "Content-type: text/html\n\n";
[144]300
[155]301 errorpage += "<html>\n";
302 errorpage += "<head>\n";
303 errorpage += "<title>Error</title>\n";
304 errorpage += "</head>\n";
305 errorpage += "<body>\n";
306 errorpage += "<h2>Oops!</h2>\n";
307 errorpage += "An error occurred during the construction of the cgi page.\n";
308
309 ifstream errin (GSDL_GSDLHOME "/etc/errout.txt");
310 if (errin) {
311 errorpage += "The error log, " GSDL_GSDLHOME "/etc/errout.txt, contains the\n";
312 errorpage += "following information:\n\n";
313 errorpage += "<pre>\n";
314
315 char c;
316 errin.get(c);
317 while (!errin.eof ()) {
318 errorpage.push_back(c);
319 errin.get(c);
320 }
321 errorpage += "</pre>\n";
322 errin.close();
323
324 } else {
325 errorpage += "Please consult " GSDL_GSDLHOME "/etc/errout.txt for more information.\n";
326 }
327
328 errorpage += "</body>\n";
329 errorpage += "</html>\n";
330}
331
332
[144]333// cgiwrapper does everything necessary to output a page
334// using the cgi protocol. If this is being run for a particular
335// collection then "collection" should be set, otherwise it
336// should equal "".
[189]337void cgiwrapper (receptionist &recpt, text_t collection) {
[144]338#ifdef USE_FASTCGI
339 fcgistreambuf outbuf;
340#endif
341
[155]342 // init stuff - we can't output error pages directly with
343 // fastcgi so the pages are stored until we can output them
344 text_t errorpage;
345 outconvertclass text_t2ascii;
[144]346
[165]347 // the list of actions. Note: these actions will become invalid
348 // at the end of this function.
349 statusaction astatusaction;
350 astatusaction.set_receptionist (&recpt);
351 recpt.add_action (&astatusaction);
[155]352
[165]353 pageaction apageaction;
354 recpt.add_action (&apageaction);
[160]355
[165]356 pingaction apingaction;
357 recpt.add_action (&apingaction);
[160]358
[173]359 queryaction aqueryaction;
360 recpt.add_action (&aqueryaction);
[165]361
[248]362 documentaction adocumentaction;
363 recpt.add_action (&adocumentaction);
[173]364
[144]365 // set defaults
366 int maxrequests = 10000;
[165]367 recpt.configure ("gsdlhome", GSDL_GSDLHOME);
368 recpt.configure ("collection", collection);
369 recpt.configure ("httpimg", "/gsdl/images");
[144]370 char *script_name = getenv("SCRIPT_NAME");
[165]371 if (script_name != NULL) recpt.configure("gwcgi", script_name);
372 else recpt.configure("gwcgi", "/cgi-bin/gw");
[144]373
[150]374 // read in the configuration files.
375 if (!site_cfg_read (recpt, GSDL_GSDLHOME, collection, maxrequests)) {
376 // couldn't find the site configuration file
[155]377 page_errorsitecfg (GSDL_GSDLHOME, collection, errorpage);
378 } else if (!main_cfg_read (recpt, GSDL_GSDLHOME, collection)) {
[150]379 // couldn't find the main configuration file
[155]380 page_errormaincfg (GSDL_GSDLHOME, collection, errorpage);
[144]381 }
382
383 // initialise the library software
[155]384 if (errorpage.empty()) {
385 ofstream initout (GSDL_GSDLHOME "/etc/initout.txt");
386 if (!recpt.init(initout)) {
387 // an error occurred during the initialisation
388 initout.close();
389 page_errorinit(GSDL_GSDLHOME, errorpage);
390 }
[144]391 initout.close();
392 }
393
394 // find out whether this is being run as a cgi-script
395 // or a fastcgi script
396 int numrequests = 0;
397#ifdef USE_FASTCGI
398 int isfastcgi = !FCGX_IsCGI();
399 FCGX_Stream *fcgiin, *fcgiout, *fcgierr;
400 FCGX_ParamArray fcgienvp;
401#else
402 int isfastcgi = 0;
403#endif
404
405 // get the query string if it is not being run as a fastcgi
406 // script
407 text_t argstr = "";
[155]408 cgiargsclass args;
[144]409 char *aURIStr;
410 if (!isfastcgi) {
411 aURIStr = getenv("QUERY_STRING");
412 if (aURIStr != NULL) argstr = aURIStr;
413 else {
414 char cinURIStr[1024];
415 cin >> cinURIStr;
416 argstr = cinURIStr;
417 }
418 maxrequests = 1;
419 }
420
421 // Page-request loop. If this is not being run as a fastcgi
422 // process then only one request will be processed and then
423 // the process will exit.
424 while (numrequests < maxrequests) {
425#ifdef USE_FASTCGI
426 if (isfastcgi) {
427 if (FCGX_Accept(&fcgiin, &fcgiout, &fcgierr, &fcgienvp) < 0) break;
428 aURIStr = FCGX_GetParam("QUERY_STRING", fcgienvp);
429 if (aURIStr != NULL) argstr = aURIStr;
430 else argstr = "";
431 }
432#endif
433
434 // get output streams ready
435#ifdef USE_FASTCGI
436 outbuf.fcgisbreset ();
437 if (isfastcgi) outbuf.set_fcgx_stream (fcgiout);
438 else outbuf.set_other_ostream (&cout);
439 ostream pageout (&outbuf);
440#else
441#define pageout cout
442#endif
[155]443
444 if (errorpage.empty()) {
445 ofstream errout (GSDL_GSDLHOME "/etc/errout.txt");
446 cerr = errout;
[144]447
[155]448 // parse the cgi arguments and produce the resulting page if there
449 // has been no errors so far
450 if (!recpt.parse_cgi_args (argstr, args, errout)) {
451 errout.close ();
452 page_errorparseargs(GSDL_GSDLHOME, errorpage);
453 } else {
454 if (!recpt.produce_cgi_page (args, pageout, errout)) {
455 errout.close ();
456 page_errorcgipage(GSDL_GSDLHOME, errorpage);
457 } else {
458 errout.close ();
459 }
460 }
461 }
462 // there was an error, output the error page
463 if (!errorpage.empty()) {
464 pageout << text_t2ascii << errorpage;
465 errorpage.clear();
466 numrequests = maxrequests; // make this the last page
467 }
468 pageout << flush;
[144]469
470 // finish with the output streams
471#ifdef USE_FASTCGI
472 if (isfastcgi) FCGX_Finish();
473#endif
474
475 numrequests++;
476 }
477
478 return;
479}
480
Note: See TracBrowser for help on using the repository browser.