source: main/tags/2.80/gsdl/src/recpt/cgiwrapper.cpp@ 24528

Last change on this file since 24528 was 12794, checked in by davidb, 18 years ago

Changes to make depositor action work under Windows. Main change is to
make sure 'standard input' is in binary mode before MIME multi-part posts
are parsed.

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