/********************************************************************** * * cgiwrapper.cpp -- output pages using the cgi protocol * Copyright (C) 1999 The New Zealand Digital Library Project * * A component of the Greenstone digital library software * from the New Zealand Digital Library Project at the * University of Waikato, New Zealand. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id: cgiwrapper.cpp 963 2000-02-21 22:01:02Z sjboddie $ * *********************************************************************/ /* $Log$ Revision 1.22 2000/02/21 21:56:46 sjboddie gsdlhome now comes from gsdlsite.cfg Revision 1.21 2000/01/25 22:45:59 sjboddie few changes to get fastcgi to work properly Revision 1.20 1999/09/07 04:56:53 sjboddie added GPL notice Revision 1.19 1999/09/02 00:24:36 rjmcnab fixed bug in getting POST arguments Revision 1.18 1999/08/20 01:02:07 sjboddie added some usage logging Revision 1.17 1999/07/15 06:03:15 rjmcnab Moved the adding of the actions to librarymain so that they can be overriden easily. Revision 1.16 1999/07/14 08:31:05 rjmcnab Fixed a small bug in the POST implementation. Revision 1.15 1999/07/13 23:32:17 rjmcnab Added authenaction and usersaction Revision 1.14 1999/07/11 01:03:37 rjmcnab Added ability to receive POST cgi form data. Revision 1.13 1999/06/24 05:12:18 sjboddie lots of small changes Revision 1.12 1999/04/30 01:59:40 sjboddie lots of stuff - getting documentaction working (documentaction replaces old browseaction) Revision 1.11 1999/03/25 03:12:01 sjboddie subjectbrowseaction was replaced with browseaction Revision 1.10 1999/03/05 03:53:54 sjboddie fixed some bugs Revision 1.9 1999/03/04 22:38:21 sjboddie Added subjectbrowseaction. - Doesn't do anything yet. Revision 1.8 1999/02/28 20:00:13 rjmcnab Fixed a few things. Revision 1.7 1999/02/21 22:33:53 rjmcnab Lots of stuff :-) Revision 1.6 1999/02/12 02:40:17 sjboddie Added page action Revision 1.5 1999/02/11 01:24:04 rjmcnab Fixed a few compiler warnings. Revision 1.4 1999/02/08 01:28:01 rjmcnab Got the receptionist producing something using the statusaction. Revision 1.3 1999/02/05 10:42:44 rjmcnab Continued working on receptionist Revision 1.2 1999/02/04 10:00:56 rjmcnab Developed the idea of an "action" and having them define the cgi arguments which they need and how those cgi arguments function. Revision 1.1 1999/02/04 01:16:17 rjmcnab Initial revision. Revision 1.5 1999/01/19 01:38:18 rjmcnab Made the source more portable. Revision 1.4 1999/01/12 01:51:04 rjmcnab Standard header. */ #include "gsdlconf.h" #include "cgiwrapper.h" #include "recptconfig.h" #include "fileutil.h" #include #include #if defined(GSDL_USE_OBJECTSPACE) # include # include #elif defined(GSDL_USE_IOS_H) # include # include #else # include # include #endif #ifdef USE_FASTCGI #include "fcgiapp.h" #endif #ifdef USE_FASTCGI // used to output the text from receptionist class fcgistreambuf : public streambuf { public: fcgistreambuf (); int sync (); int overflow (int ch); int underflow () {return EOF;} void fcgisbreset() {fcgx_stream = NULL; other_ostream = NULL;}; void set_fcgx_stream(FCGX_Stream *newone) {fcgx_stream=newone;}; void set_other_ostream(ostream *newone) {other_ostream=newone;}; private: FCGX_Stream *fcgx_stream; ostream *other_ostream; }; fcgistreambuf::fcgistreambuf() { fcgisbreset(); if (base() == ebuf()) allocate(); setp (base(), ebuf()); }; int fcgistreambuf::sync () { if ((fcgx_stream != NULL) && (FCGX_PutStr (pbase(), out_waiting(), fcgx_stream) < 0)) { fcgx_stream = NULL; } if (other_ostream != NULL) { char *thepbase=pbase(); for (int i=0;i 0) { char c; do { cin.get(c); if (cin.eof()) break; argstr.push_back (c); content_length--; } while (content_length > 0); } } else { aURIStr = getenv("QUERY_STRING"); if ((request_method_str != NULL && strcmp(request_method_str, "GET") == 0) || aURIStr != NULL) { // GET form data if (aURIStr != NULL) argstr = aURIStr; } else { // debugging from command line char cinURIStr[1024]; cin.get(cinURIStr, 1024); argstr = cinURIStr; } } // cgi scripts only deal with one request maxrequests = 1; } // Page-request loop. If this is not being run as a fastcgi // process then only one request will be processed and then // the process will exit. while (numrequests < maxrequests) { #ifdef USE_FASTCGI if (isfastcgi) { if (FCGX_Accept(&fcgiin, &fcgiout, &fcgierr, &fcgienvp) < 0) break; aURIStr = FCGX_GetParam("QUERY_STRING", fcgienvp); if (aURIStr != NULL) argstr = aURIStr; else argstr = ""; } #endif // get output streams ready #ifdef USE_FASTCGI outbuf.fcgisbreset (); if (isfastcgi) outbuf.set_fcgx_stream (fcgiout); else outbuf.set_other_ostream (&cout); ostream pageout (&outbuf); #else #define pageout cout #endif // if using fastcgi we'll load environment into a map, // otherwise simply pass empty map (can't get environment // variables using getenv() while using FCGX versions // of fastcgi - at least I can't ;-) - Stefan) text_tmap fastcgienv; #ifdef USE_FASTCGI if (isfastcgi) { for(; *fcgienvp != NULL; fcgienvp++) { text_t fvalue = *fcgienvp; text_t::const_iterator begin = fvalue.begin(); text_t::const_iterator end = fvalue.end(); text_t::const_iterator equals_sign = findchar (begin, end, '='); if (equals_sign != end) fastcgienv[substr(begin, equals_sign)] = substr(equals_sign+1, end); } } #endif // temporarily need to configure gwcgi here when using fastcgi as I can't // get it to pass the SCRIPT_NAME environment variable to the initial // environment (if anyone can work out how to do this using the apache // server, let me know). Note that this overrides the gwcgi field in // site.cfg (which it shouldn't do) but I can't at present set gwcgi // from site.cfg as I have old receptionists laying around that wouldn't // appreciate it. The following 5 lines of code should be deleted once // I either a: get the server to pass SCRIPT_NAME at initialization // time or b: convert all the collections using old receptionists over // to this version and uncomment gwcgi in the site.cfg file -- Stefan. #ifdef USE_FASTCGI if (isfastcgi) { recpt.configure("gwcgi", fastcgienv["SCRIPT_NAME"]); } #endif if (errorpage.empty()) { text_t error_file = filename_cat (gsdlhome, "etc", "errout.txt"); char *eout = error_file.getcstr(); ofstream errout (eout); delete eout; cerr = errout; // parse the cgi arguments and produce the resulting page if there // has been no errors so far if (!recpt.parse_cgi_args (argstr, args, errout, fastcgienv)) { errout.close (); page_errorparseargs(gsdlhome, errorpage); } else { if (!recpt.produce_cgi_page (args, pageout, errout, fastcgienv)) { errout.close (); page_errorcgipage(gsdlhome, errorpage); } else { errout.close (); } recpt.log_cgi_args (args, errout, fastcgienv); } } // there was an error, output the error page if (!errorpage.empty()) { pageout << text_t2ascii << errorpage; errorpage.clear(); numrequests = maxrequests; // make this the last page } pageout << flush; // finish with the output streams #ifdef USE_FASTCGI if (isfastcgi) FCGX_Finish(); #endif numrequests++; } return; }