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

Last change on this file since 183 was 173, checked in by rjmcnab, 25 years ago

Fixed a few things.

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