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

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

subjectbrowseaction was replaced with browseaction

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