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

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

lots of small changes

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