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

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

added GPL notice

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