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
Line 
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$
14 Revision 1.12 1999/04/30 01:59:40 sjboddie
15 lots of stuff - getting documentaction working (documentaction replaces
16 old browseaction)
17
18 Revision 1.11 1999/03/25 03:12:01 sjboddie
19
20 subjectbrowseaction was replaced with browseaction
21
22 Revision 1.10 1999/03/05 03:53:54 sjboddie
23
24 fixed some bugs
25
26 Revision 1.9 1999/03/04 22:38:21 sjboddie
27
28 Added subjectbrowseaction. - Doesn't do anything yet.
29
30 Revision 1.8 1999/02/28 20:00:13 rjmcnab
31
32
33 Fixed a few things.
34
35 Revision 1.7 1999/02/21 22:33:53 rjmcnab
36
37 Lots of stuff :-)
38
39 Revision 1.6 1999/02/12 02:40:17 sjboddie
40
41 Added page action
42
43 Revision 1.5 1999/02/11 01:24:04 rjmcnab
44
45 Fixed a few compiler warnings.
46
47 Revision 1.4 1999/02/08 01:28:01 rjmcnab
48
49 Got the receptionist producing something using the statusaction.
50
51 Revision 1.3 1999/02/05 10:42:44 rjmcnab
52
53 Continued working on receptionist
54
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
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"
77#include "recptconfig.h"
78#include "action.h"
79#include "statusaction.h"
80#include "pageaction.h"
81#include "pingaction.h"
82#include "queryaction.h"
83#include "documentaction.h"
84#include <stdlib.h>
85
86
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
156static void page_errorsitecfg (const text_t &gsdlhome, const text_t &collection,
157 text_t &errorpage) {
158 errorpage += "Content-type: text/html\n\n";
159
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}
187
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";
199 if (collection.empty()) {
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";
206 } else {
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";
220 }
221 errorpage += "</body>\n";
222 errorpage += "</html>\n";
223}
224
225
226static void page_errorinit (const text_t &/*gsdlhome*/, text_t &errorpage) {
227 errorpage += "Content-type: text/html\n\n";
228
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";
238
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
256 } else {
257 errorpage += "Please consult " GSDL_GSDLHOME "/etc/initout.txt for more information.\n";
258 }
259
260 errorpage += "</body>\n";
261 errorpage += "</html>\n";
262}
263
264static void page_errorparseargs (const text_t &/*gsdlhome*/, text_t &errorpage) {
265 errorpage += "Content-type: text/html\n\n";
266
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";
274
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";
280
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";
296}
297
298static void page_errorcgipage (const text_t &/*gsdlhome*/, text_t &errorpage) {
299 errorpage += "Content-type: text/html\n\n";
300
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
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 "".
337void cgiwrapper (receptionist &recpt, text_t collection) {
338#ifdef USE_FASTCGI
339 fcgistreambuf outbuf;
340#endif
341
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;
346
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);
352
353 pageaction apageaction;
354 recpt.add_action (&apageaction);
355
356 pingaction apingaction;
357 recpt.add_action (&apingaction);
358
359 queryaction aqueryaction;
360 recpt.add_action (&aqueryaction);
361
362 documentaction adocumentaction;
363 recpt.add_action (&adocumentaction);
364
365 // set defaults
366 int maxrequests = 10000;
367 recpt.configure ("gsdlhome", GSDL_GSDLHOME);
368 recpt.configure ("collection", collection);
369 recpt.configure ("httpimg", "/gsdl/images");
370 char *script_name = getenv("SCRIPT_NAME");
371 if (script_name != NULL) recpt.configure("gwcgi", script_name);
372 else recpt.configure("gwcgi", "/cgi-bin/gw");
373
374 // read in the configuration files.
375 if (!site_cfg_read (recpt, GSDL_GSDLHOME, collection, maxrequests)) {
376 // couldn't find the site configuration file
377 page_errorsitecfg (GSDL_GSDLHOME, collection, errorpage);
378 } else if (!main_cfg_read (recpt, GSDL_GSDLHOME, collection)) {
379 // couldn't find the main configuration file
380 page_errormaincfg (GSDL_GSDLHOME, collection, errorpage);
381 }
382
383 // initialise the library software
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 }
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 = "";
408 cgiargsclass args;
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
443
444 if (errorpage.empty()) {
445 ofstream errout (GSDL_GSDLHOME "/etc/errout.txt");
446 cerr = errout;
447
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;
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.