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

Last change on this file since 379 was 377, checked in by rjmcnab, 25 years ago

Added authenaction and usersaction

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