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

Last change on this file since 16347 was 16310, checked in by davidb, 16 years ago

Introduction of 'collecthome' which parallels 'gsdlhome' to allow the toplevel collect folder to be outside of the gsdlhome area

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 23.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 *********************************************************************/
25
26#include <stdio.h>
27#ifdef __WIN32__
28#include <fcntl.h>
29#endif
30
31#include "gsdlconf.h"
32#include "cgiwrapper.h"
33#include "gsdlsitecfg.h"
34#include "maincfg.h"
35#include "fileutil.h"
36#include "cgiutils.h"
37#include <stdlib.h>
38#include <assert.h>
39
40#if defined(GSDL_USE_OBJECTSPACE)
41# include <ospace/std/iostream>
42# include <ospace/std/fstream>
43#elif defined(GSDL_USE_IOS_H)
44# include <iostream.h>
45# include <fstream.h>
46#else
47# include <iostream>
48# include <fstream>
49#endif
50
51#ifdef USE_FASTCGI
52#include "fcgiapp.h"
53#endif
54
55
56#ifdef USE_FASTCGI
57// used to output the text from receptionist
58class fcgistreambuf : public streambuf {
59public:
60 fcgistreambuf ();
61 int sync ();
62 int overflow (int ch);
63 int underflow () {return EOF;}
64
65 void fcgisbreset() {fcgx_stream = NULL; other_ostream = NULL;};
66 void set_fcgx_stream(FCGX_Stream *newone) {fcgx_stream=newone;};
67 void set_other_ostream(ostream *newone) {other_ostream=newone;};
68
69private:
70 FCGX_Stream *fcgx_stream;
71 ostream *other_ostream;
72};
73
74fcgistreambuf::fcgistreambuf() {
75 fcgisbreset();
76 if (base() == ebuf()) allocate();
77 setp (base(), ebuf());
78};
79
80int fcgistreambuf::sync () {
81 if ((fcgx_stream != NULL) &&
82 (FCGX_PutStr (pbase(), out_waiting(), fcgx_stream) < 0)) {
83 fcgx_stream = NULL;
84 }
85
86 if (other_ostream != NULL) {
87 char *thepbase=pbase();
88 for (int i=0;i<out_waiting();++i) (*other_ostream).put(thepbase[i]);
89 }
90
91 setp (pbase(), epptr());
92
93 return 0;
94}
95
96int fcgistreambuf::overflow (int ch) {
97 if (sync () == EOF) return EOF;
98 if (ch != EOF) sputc (ch);
99 return 0;
100}
101
102#endif
103
104static void format_error_string (text_t &errorpage, const text_t &errortext, bool debug) {
105
106 errorpage.clear();
107
108 if (debug) {
109 errorpage += "\n";
110 errorpage += "ERROR: " + errortext;
111 errorpage += "\n";
112
113 } else {
114
115 errorpage += "Content-type: text/html\n\n";
116
117 errorpage += "<html>\n";
118 errorpage += "<head>\n";
119 errorpage += "<title>Error</title>\n";
120 errorpage += "</head>\n";
121 errorpage += "<body>\n";
122 errorpage += "<h2>Oops!</h2>\n";
123 errorpage += errortext;
124 errorpage += "</body>\n";
125 errorpage += "</html>\n";
126 }
127}
128
129static void page_errorcollect (const text_t &gsdlhome, text_t &errorpage, bool debug) {
130
131 text_t collecthome = filename_cat (gsdlhome, "collect");
132
133 text_t errortext = "No valid collections were found: Check that your collect directory\n";
134 errortext += "(" + collecthome + ") is readable and contains at least one valid collection.\n";
135 errortext += "Note that modelcol is NOT a valid collection.\n";
136 errortext += "If the path to your collect directory is wrong edit the 'gsdlhome' field\n";
137 errortext += "in your gsdlsite.cfg configuration file.\n";
138
139 format_error_string (errorpage, errortext, debug);
140}
141
142static void page_errorsitecfg (text_t &errorpage, bool debug, int mode) {
143
144 text_t errortext;
145
146 if (mode == 0) {
147 errortext += "The gsdlsite.cfg configuration file could not be found. This\n";
148 errortext += "file should contain configuration information relating to this\n";
149 errortext += "site's setup.\n";
150
151 } else if (mode == 1) {
152 errortext += "The gsdlsite.cfg configuration file does not contain a valid\n";
153 errortext += "gsdlhome entry.\n";
154 }
155
156 if (debug) {
157 errortext += "gsdlsite.cfg should reside in the directory from which the\n";
158 errortext += "library executable was run.\n";
159 } else {
160 errortext += "gsdlsite.cfg should reside in the same directory as the library\n";
161 errortext += "executable file.\n";
162 }
163
164 format_error_string (errorpage, errortext, debug);
165}
166
167
168static void page_errormaincfg (const text_t &gsdlhome, const text_t &collection,
169 bool debug, text_t &errorpage) {
170
171 text_t errortext;
172
173 if (collection.empty()) {
174 text_t main_cfg_file = filename_cat (gsdlhome, "etc", "main.cfg");
175 errortext += "The main.cfg configuration file could not be found. This file\n";
176 errortext += "should contain configuration information relating to the\n";
177 errortext += "setup of the interface. As this receptionist is not being run\n";
178 errortext += "in collection specific mode the file should reside at\n";
179 errortext += main_cfg_file + ".\n";
180 } else {
181 text_t collect_cfg_file = filename_cat (gsdlhome, "collect", collection, "etc", "collect.cfg");
182 text_t main_collect_cfg_file = filename_cat (gsdlhome, "etc", "collect.cfg");
183 text_t main_cfg_file = filename_cat (gsdlhome, "etc", "main.cfg");
184 errortext += "Either the collect.cfg or main.cfg configuration file could\n";
185 errortext += "not be found. This file should contain configuration information\n";
186 errortext += "relating to the setup of the interface. As this receptionist is\n";
187 errortext += "being run in collection specific mode the file should reside\n";
188 errortext += "at either " + collect_cfg_file + ",\n";
189 errortext += main_collect_cfg_file + " or " + main_cfg_file + ".\n";
190 }
191
192 format_error_string (errorpage, errortext, debug);
193}
194
195
196static void page_errorinit (const text_t &gsdlhome, bool debug, text_t &errorpage) {
197
198 text_t errortext = "An error occurred during the initialisation of the Greenstone Digital\n";
199 errortext += "Library software. It is likely that the software has not been setup\n";
200 errortext += "correctly.\n";
201
202 text_t error_file = filename_cat (gsdlhome, "etc", "error.txt");
203 char *efile = error_file.getcstr();
204 ifstream errin (efile);
205 delete []efile;
206 if (errin) {
207 errortext += "The error log, " + error_file + ", contains the\n";
208 errortext += "following information:\n\n";
209 if (!debug) errortext += "<pre>\n";
210
211 char c;
212 errin.get(c);
213 while (!errin.eof ()) {
214 errortext.push_back(c);
215 errin.get(c);
216 }
217
218 if (!debug) errortext += "</pre>\n";
219
220 errin.close();
221
222 } else {
223 errortext += "Please consult " + error_file + " for more information.\n";
224 }
225
226 format_error_string (errorpage, errortext, debug);
227}
228
229static void page_errorparseargs (const text_t &gsdlhome, bool debug, text_t &errorpage) {
230
231 text_t errortext = "An error occurred during the parsing of the cgi arguments.\n";
232
233 text_t error_file = filename_cat (gsdlhome, "etc", "error.txt");
234 char *efile = error_file.getcstr();
235 ifstream errin (efile);
236 delete []efile;
237 if (errin) {
238 errortext += "The error log, " + error_file + ", contains the\n";
239 errortext += "following information:\n\n";
240 if (!debug) errortext += "<pre>\n";
241
242 char c;
243 errin.get(c);
244 while (!errin.eof ()) {
245 errortext.push_back(c);
246 errin.get(c);
247 }
248 if (!debug) errortext += "</pre>\n";
249 errin.close();
250
251 } else {
252 errortext += "Please consult " + error_file + " for more information.\n";
253 }
254
255 format_error_string (errorpage, errortext, debug);
256}
257
258static void page_errorcgipage (const text_t &gsdlhome, bool debug, text_t &errorpage) {
259
260 text_t errortext = "An error occurred during the construction of the cgi page.\n";
261
262 text_t error_file = filename_cat (gsdlhome, "etc", "error.txt");
263 char *efile = error_file.getcstr();
264 ifstream errin (efile);
265 delete []efile;
266 if (errin) {
267 errortext += "The error log, " + error_file + ", contains the\n";
268 errortext += "following information:\n\n";
269 if (!debug) errortext += "<pre>\n";
270
271 char c;
272 errin.get(c);
273 while (!errin.eof ()) {
274 errortext.push_back(c);
275 errin.get(c);
276 }
277 if (!debug) errortext += "</pre>\n";
278 errin.close();
279
280 } else {
281 errortext += "Please consult " + error_file + " for more information.\n";
282 }
283
284 format_error_string (errorpage, errortext, debug);
285}
286
287static void print_debug_info (receptionist &recpt) {
288
289 outconvertclass text_t2ascii;
290 const recptconf &configinfo = recpt.get_configinfo ();
291 text_t etc_dir = filename_cat (configinfo.gsdlhome, "etc");
292
293 cout << "\n";
294 cout << text_t2ascii
295 << "------------------------------------------------------------\n"
296 << "Configuration and initialization completed successfully.\n"
297 << " Note that more debug information may be available in the\n"
298 << " initialization and error log error.txt in " << etc_dir << ".\n"
299 << "------------------------------------------------------------\n\n";
300
301 bool colspec = false;
302 if (configinfo.collection.empty()) {
303 cout << "Receptionist is running in \"general\" (i.e. not \"collection "
304 << "specific\") mode.\n";
305 } else {
306 cout << text_t2ascii
307 << "Receptionist is running in \"collection specific\" mode.\n"
308 << " collection=" << configinfo.collection << "\n"
309 << " collection directory=" << configinfo.collectdir << "\n";
310 colspec = true;
311 }
312
313 cout << text_t2ascii << " gsdlhome=" << configinfo.gsdlhome << "\n";
314 if (!configinfo.collecthome.empty())
315 cout << text_t2ascii << " collecthome=" << configinfo.collecthome << "\n";
316 if (!configinfo.dbhome.empty())
317 cout << text_t2ascii << " dbhome=" << configinfo.dbhome << "\n";
318 cout << text_t2ascii << " httpprefix=" << configinfo.httpprefix << "\n";
319 cout << text_t2ascii << " httpimg=" << configinfo.httpimg << "\n";
320 cout << text_t2ascii << " gwcgi=" << configinfo.gwcgi << "\n\n"
321 << " Note that unless gwcgi has been set from a configuration\n"
322 << " file it is dependent on environment variables set by your\n"
323 << " webserver. Therefore it may not have the same value when run\n"
324 << " from the command line as it would be when run from your\n"
325 << " web server.\n";
326 if (configinfo.usecookies)
327 cout << "cookies are enabled\n";
328 else
329 cout << "cookies are disabled\n";
330 if (configinfo.logcgiargs)
331 cout << "logging is enabled\n";
332 else
333 cout << "logging is disabled\n";
334 cout << "------------------------------------------------------------\n\n";
335
336 text_tset::const_iterator this_mfile = configinfo.macrofiles.begin();
337 text_tset::const_iterator end_mfile = configinfo.macrofiles.end();
338 cout << "Macro Files:\n"
339 << "------------\n";
340 text_t mfile;
341 bool found;
342 while (this_mfile != end_mfile) {
343 cout << text_t2ascii << *this_mfile;
344 int spaces = (22 - (*this_mfile).size());
345 if (spaces < 2) spaces = 2;
346 text_t outspaces;
347 for (int i = 0; i < spaces; ++i) outspaces.push_back (' ');
348 cout << text_t2ascii << outspaces;
349
350 found = false;
351 if (colspec) {
352 // collection specific - try collectdir/macros first
353 mfile = filename_cat (configinfo.collectdir, "macros", *this_mfile);
354 if (file_exists (mfile)) {
355 cout << text_t2ascii << "found (" << mfile << ")\n";
356 found = true;
357 }
358 }
359
360 if (!found) {
361 // try main macro directory
362 mfile = filename_cat (configinfo.gsdlhome, "macros", *this_mfile);
363 if (file_exists (mfile)) {
364 cout << text_t2ascii << "found (" << mfile << ")\n";
365 found = true;
366 }
367 }
368
369 if (!found)
370 cout << text_t2ascii << "NOT FOUND\n";
371
372 ++this_mfile;
373 }
374
375 cout << "------------------------------------------------------------\n\n"
376 << "Collections:\n"
377 << "------------\n"
378 << " Note that collections will only appear as \"running\" if\n"
379 << " their build.cfg files exist, are readable, contain a valid\n"
380 << " builddate field (i.e. > 0), and are in the collection's\n"
381 << " index directory (i.e. NOT the building directory)\n\n";
382
383 recptprotolistclass *protos = recpt.get_recptprotolist_ptr();
384 recptprotolistclass::iterator rprotolist_here = protos->begin();
385 recptprotolistclass::iterator rprotolist_end = protos->end();
386
387 bool is_z3950 = false;
388 bool found_valid_col = false;
389
390
391 while (rprotolist_here != rprotolist_end) {
392 comerror_t err;
393 if ((*rprotolist_here).p == NULL) continue;
394 else if (is_z3950==false &&
395 (*rprotolist_here).p->get_protocol_name(err) == "z3950proto") {
396 cout << "\nZ39.50 Servers: (always public)\n"
397 << "---------------\n";
398 is_z3950=true;
399 }
400
401 text_tarray collist;
402 (*rprotolist_here).p->get_collection_list (collist, err, cerr);
403 if (err == noError) {
404 text_tarray::iterator collist_here = collist.begin();
405 text_tarray::iterator collist_end = collist.end();
406
407 while (collist_here != collist_end) {
408
409 cout << text_t2ascii << *collist_here;
410
411 int spaces = (22 - (*collist_here).size());
412 if (spaces < 2) spaces = 2;
413 text_t outspaces;
414 for (int i = 0; i < spaces; ++i) outspaces.push_back (' ');
415 cout << text_t2ascii << outspaces;
416
417 ColInfoResponse_t *cinfo = recpt.get_collectinfo_ptr ((*rprotolist_here).p, *collist_here, cerr);
418 if (cinfo != NULL) {
419 if (cinfo->isPublic) cout << "public ";
420 else cout << "private";
421
422 if (cinfo->buildDate > 0) {
423 cout << " running ";
424 found_valid_col = true;
425 } else {
426 cout << " not running";
427 }
428 }
429
430 cout << "\n";
431
432 ++collist_here;
433 }
434 }
435 is_z3950=false;
436 ++rprotolist_here;
437 } // end of while loop
438
439 if (!found_valid_col) {
440 cout << "WARNING: No \"running\" collections were found. You need to\n";
441 cout << " build one of the above collections\n";
442 }
443
444 cout << "\n------------------------------------------------------------\n";
445 cout << "------------------------------------------------------------\n\n";
446 cout << "receptionist running in command line debug mode\n";
447 cout << "enter cgi arguments as name=value pairs (e.g. 'a=p&p=home'):\n";
448
449}
450
451// cgiwrapper does everything necessary to output a page
452// using the cgi protocol. If this is being run for a particular
453// collection then "collection" should be set, otherwise it
454// should equal "".
455void cgiwrapper (receptionist &recpt, text_t collection) {
456 int numrequests = 0;
457 bool debug = false;
458 const recptconf &configinfo = recpt.get_configinfo ();
459
460 // find out whether this is being run as a cgi-script
461 // or a fastcgi script
462#ifdef USE_FASTCGI
463 fcgistreambuf outbuf;
464 int isfastcgi = !FCGX_IsCGI();
465 FCGX_Stream *fcgiin, *fcgiout, *fcgierr;
466 FCGX_ParamArray fcgienvp;
467#else
468 int isfastcgi = 0;
469#endif
470
471 // we need gsdlhome to do fileupload stuff, so moved this configure stuff before the get argstr stuff
472 // init stuff - we can't output error pages directly with
473 // fastcgi so the pages are stored until we can output them
474 text_t errorpage;
475 outconvertclass text_t2ascii;
476
477 // set defaults
478 int maxrequests = 10000;
479 recpt.configure ("collection", collection);
480 recpt.configure ("httpimg", "/gsdl/images");
481 char *script_name = getenv("SCRIPT_NAME");
482 if (script_name != NULL) recpt.configure("gwcgi", script_name);
483 else recpt.configure("gwcgi", "/gsdl");
484
485 // read in the configuration files.
486 text_t gsdlhome;
487 text_t collecthome;
488 configurator gsdlconfigurator(&recpt);
489 if (!site_cfg_read (gsdlconfigurator, gsdlhome, collecthome, maxrequests)) {
490 // couldn't find the site configuration file
491 page_errorsitecfg (errorpage, debug, 0);
492 } else if (gsdlhome.empty()) {
493 // no gsdlhome in gsdlsite.cfg
494 page_errorsitecfg (errorpage, debug, 1);
495 } else if (!directory_exists(gsdlhome)) {
496 // gsdlhome not a valid directory
497 page_errorsitecfg (errorpage, debug, 1);
498 } else if (!main_cfg_read (recpt, gsdlhome, collecthome, collection)) {
499 // couldn't find the main configuration file
500 page_errormaincfg (gsdlhome, collection, debug, errorpage);
501 } else if (configinfo.collectinfo.empty() && false) { // commented out for corba
502 // don't have any collections
503 page_errorcollect (gsdlhome, errorpage, debug);
504 }
505 // get the query string if it is not being run as a fastcgi
506 // script
507 text_t argstr = g_EmptyText;
508 fileupload_tmap fileuploads;
509 cgiargsclass args;
510 char *aURIStr;
511 if (!isfastcgi) {
512 char *request_method_str = getenv("REQUEST_METHOD");
513 char *content_length_str = getenv("CONTENT_LENGTH");
514 if (request_method_str != NULL && strcmp(request_method_str, "POST") == 0 &&
515 content_length_str != NULL) {
516 // POST form data
517 long content_length = (content_length_str ? atoi(content_length_str) : 0);
518 if (content_length > 0) {
519#ifdef __WIN32__
520 // On Windows it is important that standard input be read in binary
521 // mode, otherwise end of line "<CR><LF>" is turned into <LF> only
522 // which breaks the MIME standard (and our parsing code!)
523
524 int result = _setmode( _fileno( stdin ), _O_BINARY );
525 if( result == -1 ) {
526 cerr << "Warning: Failed to set standard input to binary mode." << endl;
527 cerr << " Parsing of multi-part MIME will most likely fail" << endl;
528 }
529#endif
530
531 long length = content_length;
532 unsigned char * buffer = new unsigned char[content_length];
533
534 int chars_read = fread(buffer,1,content_length,stdin);
535
536 if (chars_read != content_length) {
537 cerr << "Warning: mismatch between CONTENT_LENGTH and data read from standard in" << endl;
538 }
539
540 argstr.setcarr((char *)buffer, content_length);
541
542 text_t content_type;
543 char *content_type_str = getenv("CONTENT_TYPE");
544 if (content_type_str) content_type = content_type_str;
545 argstr = parse_post_data(content_type, argstr, fileuploads, gsdlhome);
546 }
547 } else {
548 aURIStr = getenv("QUERY_STRING");
549 if ((request_method_str != NULL && strcmp(request_method_str, "GET") == 0)
550 || aURIStr != NULL) {
551 // GET form data
552 if (aURIStr != NULL) argstr = aURIStr;
553 } else {
554 // debugging from command line
555 debug = true;
556 }
557 }
558 }
559
560 if (debug) {
561 cout << "Configuring Greenstone...\n";
562 cout << flush;
563 }
564
565
566 if (errorpage.empty()) {
567
568 // initialise the library software
569 if (debug) {
570 cout << "Initializing...\n";
571 cout << flush;
572 }
573
574 text_t error_file = filename_cat (gsdlhome, "etc", "error.txt");
575 char *eout = error_file.getcstr();
576 ofstream errout (eout, ios::app);
577 delete []eout;
578 if (!recpt.init(errout)) {
579 // an error occurred during the initialisation
580 errout.close();
581 page_errorinit(gsdlhome, debug, errorpage);
582 }
583 errout.close();
584 }
585
586 if (debug && errorpage.empty()) {
587 // get query string from command line
588 print_debug_info (recpt);
589 char cinURIStr[1024];
590 cin.get(cinURIStr, 1024);
591 argstr = cinURIStr;
592 }
593
594 // cgi scripts only deal with one request
595 if (!isfastcgi) maxrequests = 1;
596
597 // Page-request loop. If this is not being run as a fastcgi
598 // process then only one request will be processed and then
599 // the process will exit.
600 while (numrequests < maxrequests) {
601#ifdef USE_FASTCGI
602 if (isfastcgi) {
603 if (FCGX_Accept(&fcgiin, &fcgiout, &fcgierr, &fcgienvp) < 0) break;
604
605 char *request_method_str = FCGX_GetParam ("REQUEST_METHOD", fcgienvp);
606 char *content_length_str = FCGX_GetParam ("CONTENT_LENGTH", fcgienvp);
607
608 if (request_method_str != NULL && strcmp(request_method_str, "POST") == 0 &&
609 content_length_str != NULL) {
610 // POST form data
611 int content_length = text_t(content_length_str).getint();
612 if (content_length > 0) {
613 argstr.clear();
614 int c;
615 do {
616 c = FCGX_GetChar (fcgiin);
617 if (c < 0) break;
618 argstr.push_back (c);
619 --content_length;
620 } while (content_length > 0);
621 }
622
623 } else {
624 // GET form data
625 aURIStr = FCGX_GetParam("QUERY_STRING", fcgienvp);
626 if (aURIStr != NULL) argstr = aURIStr;
627 else argstr = g_EmptyText;
628 }
629 }
630#endif
631
632 // get output streams ready
633#ifdef USE_FASTCGI
634 outbuf.fcgisbreset ();
635 if (isfastcgi) outbuf.set_fcgx_stream (fcgiout);
636 else outbuf.set_other_ostream (&cout);
637 ostream pageout (&outbuf);
638#else
639#define pageout cout
640#endif
641
642 // if using fastcgi we'll load environment into a map,
643 // otherwise simply pass empty map (can't get environment
644 // variables using getenv() while using FCGX versions
645 // of fastcgi - at least I can't ;-) - Stefan)
646 text_tmap fastcgienv;
647#ifdef USE_FASTCGI
648 if (isfastcgi) {
649 for(; *fcgienvp != NULL; ++fcgienvp) {
650 text_t fvalue = *fcgienvp;
651 text_t::const_iterator begin = fvalue.begin();
652 text_t::const_iterator end = fvalue.end();
653 text_t::const_iterator equals_sign = findchar (begin, end, '=');
654 if (equals_sign != end)
655 fastcgienv[substr(begin, equals_sign)] = substr(equals_sign+1, end);
656 }
657 }
658#endif
659
660 // temporarily need to configure gwcgi here when using fastcgi as I can't
661 // get it to pass the SCRIPT_NAME environment variable to the initial
662 // environment (if anyone can work out how to do this using the apache
663 // server, let me know). Note that this overrides the gwcgi field in
664 // site.cfg (which it shouldn't do) but I can't at present set gwcgi
665 // from site.cfg as I have old receptionists laying around that wouldn't
666 // appreciate it. The following 5 lines of code should be deleted once
667 // I either a: get the server to pass SCRIPT_NAME at initialization
668 // time or b: convert all the collections using old receptionists over
669 // to this version and uncomment gwcgi in the site.cfg file -- Stefan.
670#ifdef USE_FASTCGI
671 if (isfastcgi) {
672 recpt.configure("gwcgi", fastcgienv["SCRIPT_NAME"]);
673 }
674#endif
675
676
677 // if there has been no error so far, perform the production of the
678 // output page
679 if (errorpage.empty()) {
680 text_t error_file = filename_cat (gsdlhome, "etc", "error.txt");
681 char *eout = error_file.getcstr();
682 ofstream errout (eout, ios::app);
683 delete []eout;
684
685#if defined(__WIN32__) && defined(GSDL_USE_IOS_H)
686 // old Windows compilers (VC++4.2)
687 cerr = errout;
688#else
689 // can't do this anymore according to c++ standard...
690 // cerr = errout;
691 // ... but can do this instead
692 streambuf* errbuf = cerr.rdbuf(errout.rdbuf());
693#endif
694
695 // parse the cgi arguments and produce the resulting page if there
696 // has been no errors so far
697 if (!recpt.parse_cgi_args (argstr, fileuploads, args, errout, fastcgienv)) {
698 errout.close ();
699 page_errorparseargs(gsdlhome, debug, errorpage);
700 } else {
701 // produce the output page
702
703 if (!recpt.produce_cgi_page (args, pageout, errout, fastcgienv)) {
704 errout.close ();
705 page_errorcgipage(gsdlhome, debug, errorpage);
706 }
707 recpt.log_cgi_args (args, errout, fastcgienv);
708 errout.close ();
709 }
710
711#if !defined(__WIN32__) || !defined(GSDL_USE_IOS_H)
712 // restore the cerr buffer
713 cerr.rdbuf(errbuf);
714#endif
715 }
716 // clean up any files that were uploaded
717 fileupload_tmap::const_iterator this_file = fileuploads.begin();
718 fileupload_tmap::const_iterator end_file = fileuploads.end();
719 while (this_file != end_file)
720 {
721 if (file_exists((*this_file).second.tmp_name))
722 {
723 char *thefile = (*this_file).second.tmp_name.getcstr();
724 unlink(thefile);
725 delete [] thefile;
726 }
727 ++this_file;
728 }
729
730 // there was an error, output the error page
731 if (!errorpage.empty()) {
732 pageout << text_t2ascii << errorpage;
733 errorpage.clear();
734 numrequests = maxrequests; // make this the last page
735 }
736 pageout << flush;
737
738 // finish with the output streams
739#ifdef USE_FASTCGI
740 if (isfastcgi) FCGX_Finish();
741#endif
742
743 ++numrequests;
744 }
745
746 return;
747}
Note: See TracBrowser for help on using the repository browser.