/********************************************************************** * * cgiwrapper.cpp -- windows local library cgiwrapper * 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. * *********************************************************************/ #include "text_t.h" #include #include #include #include #include #include #include "cgiwrapper.h" #include "netio.h" #include "wincgiutils.h" #include "settings.h" #include "fileutil.h" #include "parse.h" #include "gsdlconf.h" #include "recptconfig.h" #if defined (GSDL_USE_OBJECTSPACE) #include #include #elif defined (GSDL_USE_IOS_H) #include #include #else #include #include #endif #include "receptionist.h" #include "nullproto.h" // actions #include "statusaction.h" #include "pageaction.h" #include "pingaction.h" #include "queryaction.h" #include "documentaction.h" #include "tipaction.h" #include "authenaction.h" #include "usersaction.h" #include "userdb.h" #include "extlinkaction.h" #include "collectoraction.h" #include "phindaction.h" #include "configaction.h" // browsers #include "vlistbrowserclass.h" #include "hlistbrowserclass.h" #include "datelistbrowserclass.h" #include "invbrowserclass.h" #include "pagedbrowserclass.h" #include "htmlbrowserclass.h" #include "phindbrowserclass.h" // the number of times the library has been accessed int libaccessnum = 0; // used to output the text from receptionist class textstreambuf : public streambuf { public: textstreambuf (); int sync (); int overflow (int ch); int underflow () {return EOF;} void tsbreset() {RInfo=NULL;casostr=NULL;} void setrequestinfo (RequestInfoT *theRInfo) {RInfo=theRInfo;} void cascadeoutput (ostream *thecasostr) {casostr=thecasostr;} private: RequestInfoT *RInfo; ostream *casostr; #if !defined (GSDL_USE_IOS_H) char buffer[256]; #endif }; textstreambuf::textstreambuf() { tsbreset(); #if !defined (GSDL_USE_IOS_H) setp (&buffer[0], &buffer[255]); #else if (base() == ebuf()) allocate(); setp (base(), ebuf()); #endif }; int textstreambuf::sync () { if ((RInfo != NULL) && (Send_String_N(pbase(), pptr()-pbase(), RInfo) < 0)) { RInfo = NULL; } if (casostr != NULL) { char *thepbase=pbase(); for (int i=0;i<(pptr()-pbase());++i) (*casostr).put(thepbase[i]); } setp (pbase(), epptr()); return 0; } int textstreambuf::overflow (int ch) { if (sync () == EOF) return EOF; if (ch != EOF) sputc (ch); return 0; } // used to output all the log and error messages // from receptionist class logstreambuf : public streambuf { public: logstreambuf (); int sync (); int overflow (int ch); int underflow () {return EOF;} #if !defined (GSDL_USE_IOS_H) private: char buffer[256]; #endif }; logstreambuf::logstreambuf () { #if !defined (GSDL_USE_IOS_H) setp (&buffer[0], &buffer[255]); #else if (base() == ebuf()) allocate(); setp (base(), ebuf()); #endif } int logstreambuf::sync () { if (gsdl_keep_log || gsdl_show_console) { log_message ("LOCAL LIB MESSAGE: "); log_message_N (pbase(), pptr()-pbase()); } setp (pbase(), epptr()); return 0; } int logstreambuf::overflow (int ch) { if (sync () == EOF) return EOF; if (ch != EOF) sputc (ch); return 0; } static void page_errormaincfg (const text_t &gsdlhome, const text_t &collection) { if (collection.empty()) { text_t message = "Error\n\n" "The main.cfg configuration file could not be found. This file\n" "should contain configuration information relating to the\n" "setup of the interface. As this program is not being run\n" "in collection specific mode the file should reside at\n" + gsdlhome + "\\etc\\main.cfg.\n"; MessageBox(NULL, message.getcstr(), "Greenstone Digital Library Software" ,MB_OK|MB_SYSTEMMODAL); } else { text_t message = "Neither the collect.cfg or main.cfg configuration files could\n" "be found. This file should contain configuration information\n" "relating to the setup of the interface. As this cgi script is\n" "being run in collection specific mode the file should reside\n" "at either " + gsdlhome + "\\collect\\" + collection + "\\etc\\collect.cfg,\n" + gsdlhome + "\\etc\\collect.cfg or " + gsdlhome + "\\etc\\main.cfg.\n"; MessageBox(NULL, message.getcstr(), "Greenstone Digital Library Software" ,MB_OK|MB_SYSTEMMODAL); } } static void page_errorinit (const text_t &/*gsdlhome*/) { text_t message = "Error\n\n" "An error occurred during the initialisation of the Greenstone Digital\n" "Library software. It is likely that the software has not been setup\n" "correctly.\n"; MessageBox(NULL, message.getcstr(), "Greenstone Digital Library Software" ,MB_OK|MB_SYSTEMMODAL); } static void page_errorparseargs (const text_t &/*gsdlhome*/) { text_t message = "Error\n\n" "An error occurred during the parsing of the cgi arguments.\n"; MessageBox(NULL, message.getcstr(), "Greenstone Digital Library Software" ,MB_OK|MB_SYSTEMMODAL); } static void page_errorcgipage (const text_t &/*gsdlhome*/) { text_t message = "Error\n\n" "An error occurred during the construction of the cgi page.\n"; MessageBox(NULL, message.getcstr(), "Greenstone Digital Library Software" ,MB_OK|MB_SYSTEMMODAL); } // returns 0 if the directories can't be found // and the user wants to quit (it returns 1 // if everything is ok) int checkdir (const text_t &thedir) { UINT curerrormode; int drive = _getdrive(); char cwd[1024]; char rootpath[4]; UINT drivetype; char *cstrthedir = thedir.getcstr(); int returnvalue = 1; // make sure no rude error messages are presented to the user curerrormode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); // get the drive name if (thedir.size() >= 2 && thedir[1] == ':') { if (thedir[0] >= 'a' && thedir[0] <= 'z') { drive = thedir[0] - 'a' + 1; } else if (thedir[0] >= 'A' && thedir[0] <= 'Z') { drive = thedir[0] - 'A' + 1; } } // find the drive type rootpath[0] = drive + 'A' - 1; rootpath[1] = ':'; rootpath[2] = '\\'; rootpath[3] = '\0'; drivetype = GetDriveType (rootpath); // try and set this directory to be the current working // directory _getcwd(cwd, 1024); while (_chdir(cstrthedir) != 0) { // failed if (drivetype == DRIVE_CDROM) { // message to insert the cdrom if (MessageBox (NULL, "Please insert the Greenstone Digital Library\n" "CD-ROM into the CD-ROM drive and press 'OK'.\n\n" "If you don't have the CD-ROM press 'Cancel' to exit\n" "this program.", "Greenstone Digital Library Software", MB_OKCANCEL | MB_TASKMODAL) == IDCANCEL) { returnvalue = 0; break; } } else { // message saying that the system was unable // to find a certain directory text_t message = "Failed to find the directory:\n\n" + thedir; message += "\n\n" "This directory is needed for the successful operation\n" "of this software. Make sure it hasn't been deleted or\n" "moved, and restart the software. You may need to\n" "reinstall this software to correct the problem."; char *cstrmessage = message.getcstr(); MessageBox (NULL, cstrmessage, "Greenstone Digital Library Software", MB_OK | MB_TASKMODAL); delete []cstrmessage; returnvalue = 0; break; } } // revert to the previous error and cwd states _chdir(cwd); SetErrorMode(curerrormode); // free the allocated C string delete []cstrthedir; return returnvalue; } // c-string version of checkdir for the outside // world int cstrcheckdir (char *cstrthedir) { return checkdir (cstrthedir); } receptionist recpt; nullproto nproto; collectset *cservers = NULL; textstreambuf textstream; logstreambuf logstream; DWORD lastlibaccesstime; DWORD baseavailvirtual; text_t current_gsdlhome; colinfo_tmap translated_collectinfo; statusaction *astatusaction = NULL; pageaction *apageaction = NULL; pingaction *apingaction = NULL; tipaction *atipaction = NULL; queryaction *aqueryaction = NULL; documentaction *adocumentaction = NULL; usersaction *ausersaction = NULL; extlinkaction *anextlinkaction = NULL; collectoraction *acollectoraction = NULL; authenaction *aauthenaction = NULL; phindaction *aphindaction = NULL; configaction *aconfigaction = NULL; vlistbrowserclass *avlistbrowserclass = NULL; hlistbrowserclass *ahlistbrowserclass = NULL; datelistbrowserclass *adatelistbrowserclass = NULL; invbrowserclass *ainvbrowserclass = NULL; pagedbrowserclass *apagedbrowserclass = NULL; htmlbrowserclass *ahtmlbrowserclass = NULL; phindbrowserclass *aphindbrowserclass = NULL; text_t userdbfile = NULL; userdbclass *udb = NULL; text_t keydbfile = NULL; keydbclass *kdb = NULL; // returns 1 if successful, 0 if unsuccessful (note that as well as being // called when the server first starts up this function is called when the // "restart library" button is pressed) int gsdl_init (bool atStartup) { if (atStartup) { #if defined (GSDL_USE_IOS_H) cerr = &logstream; cout = &textstream; #else cerr.rdbuf(&logstream); cout.rdbuf(&textstream); #endif } // collection should be set to "" unless in collection specific mode - // changing this to the name of the collection should be all that's // required to create a collection specific receptionist text_t collection = ""; text_tset gdbmhomes; text_tset collections; if (atStartup) { // note the current time lastlibaccesstime = GetTickCount(); // before we do the init we should make sure // that we can find the relevant directories if (!checkdir (gsdl_gsdlhome + "\\")) return 0; if (!checkdir (gsdl_gsdlhome + "\\macros\\")) return 0; } // deleting cservers clears all the collection servers if (cservers != NULL) delete cservers; cservers = new collectset(); // get all collections from each gsdlhome (this relies // on there not being more than one collection with the same // name) if (!collection.empty()) { // collection specific receptionist - one collection, one gsdlhome collections.insert (collection); gdbmhomes.insert (gsdl_gdbmhome); collectioninfo_t tmp; tmp.gsdl_gsdlhome = gsdl_gsdlhome; tmp.gsdl_gdbmhome = gsdl_gdbmhome; translated_collectinfo[collection] = tmp; } else { text_tset::const_iterator colhere; text_tset::const_iterator colend; text_tset these_collections; // first volume gsdlhome's colinfo_tmap::const_iterator this_info = gsdl_collectinfo.begin(); colinfo_tmap::const_iterator end_info = gsdl_collectinfo.end(); while (this_info != end_info) { if (gdbmhomes.find ((*this_info).second.gsdl_gdbmhome) == gdbmhomes.end()) { these_collections.erase (these_collections.begin(), these_collections.end()); read_dir (filename_cat ((*this_info).second.gsdl_gsdlhome, "collect"), these_collections); colhere = these_collections.begin(); colend = these_collections.end(); while (colhere != colend) { if ((collections.find (*colhere)) == collections.end()) { // make sure the build.cfg file is at gsdlhome (as it's possible that // the collection appears at this gsdlhome only because it's gdbm // file is installed here -- it's real gdbm will therefore be // somewhere else). text_t build_cfg = filename_cat ((*this_info).second.gsdl_gsdlhome, "collect", *colhere, "index", "build.cfg"); if (file_exists (build_cfg)) { collections.insert (*colhere); // since gsdl_collectinfo keys will be stuff like collection#1 // for a multiple volume collection we want to translate it // so that the keys are the actual collection names translated_collectinfo[*colhere] = (*this_info).second; } } ++colhere; } gdbmhomes.insert ((*this_info).second.gsdl_gdbmhome); } ++this_info; } // then if necessary the main gdbmhome (this should only happen if the // gsdl.ini is a little screwed up and no volume gdbmhomes occurred) if (gdbmhomes.find (gsdl_gdbmhome) == gdbmhomes.end()) { these_collections.erase (these_collections.begin(), these_collections.end()); read_dir (filename_cat (gsdl_gdbmhome, "collect"), these_collections); colhere = these_collections.begin(); colend = these_collections.end(); while (colhere != colend) { collections.insert (*colhere); collectioninfo_t tmp; tmp.gsdl_gsdlhome = gsdl_gsdlhome; tmp.gsdl_gdbmhome = gsdl_gdbmhome; translated_collectinfo[*colhere] = tmp; ++colhere; } gdbmhomes.insert (gsdl_gdbmhome); } } text_tset::const_iterator thiscol = collections.begin(); text_tset::const_iterator endcol = collections.end(); while (thiscol != endcol) { // ignore the modelcol if (*thiscol == "modelcol") { ++thiscol; continue; } // create collection server and add to null protocol text_t this_gsdlhome = gsdl_gsdlhome; text_t this_gdbmhome = gsdl_gdbmhome; colinfo_tmap::const_iterator it = translated_collectinfo.find (*thiscol); assert (it != translated_collectinfo.end()); this_gsdlhome = (*it).second.gsdl_gsdlhome; this_gdbmhome = (*it).second.gsdl_gdbmhome; cservers->add_collection (*thiscol, this_gsdlhome); ++thiscol; } // set up the null protocol nproto.set_collectset(cservers); if ((ausersaction == NULL) && (aauthenaction == NULL)){ userdbfile = filename_cat(gsdl_gsdlhome, "etc", "users.db"); udb = new userdbclass(userdbfile); keydbfile = filename_cat(gsdl_gsdlhome, "etc", "key.db"); kdb = new keydbclass(keydbfile); } // add the protocol to the receptionist if (atStartup) recpt.add_protocol (&nproto); // the list of actions. if (astatusaction == NULL) { astatusaction = new statusaction(); astatusaction->set_receptionist (&recpt); recpt.add_action (astatusaction); } if (apageaction == NULL) { apageaction = new pageaction(); apageaction->set_receptionist (&recpt); recpt.add_action (apageaction); } if (apingaction == NULL) { apingaction = new pingaction(); recpt.add_action (apingaction); } if (atipaction == NULL) { atipaction = new tipaction(); recpt.add_action (atipaction); } if (aqueryaction == NULL) { aqueryaction = new queryaction(); aqueryaction->set_receptionist (&recpt); recpt.add_action (aqueryaction); } if (adocumentaction == NULL) { adocumentaction = new documentaction(); adocumentaction->set_receptionist (&recpt); recpt.add_action (adocumentaction); } if (ausersaction == NULL) { ausersaction = new usersaction(); ausersaction->set_userdb(udb); recpt.add_action (ausersaction); } if (anextlinkaction == NULL) { anextlinkaction = new extlinkaction(); recpt.add_action (anextlinkaction); } if (acollectoraction == NULL) { acollectoraction = new collectoraction(); acollectoraction->set_receptionist (&recpt); recpt.add_action (acollectoraction); } if (aauthenaction == NULL) { aauthenaction = new authenaction(); aauthenaction->set_userdb(udb); aauthenaction->set_keydb(kdb); aauthenaction->set_receptionist(&recpt); recpt.add_action (aauthenaction); } if (aphindaction == NULL) { aphindaction = new phindaction(); recpt.add_action (aphindaction); } if (aconfigaction == NULL) { aconfigaction = new configaction(); aconfigaction->set_receptionist(&recpt); recpt.add_action (aconfigaction); } // list of browsers if (avlistbrowserclass == NULL) { avlistbrowserclass = new vlistbrowserclass(); recpt.add_browser (avlistbrowserclass); recpt.setdefaultbrowser ("VList"); } if (ahlistbrowserclass == NULL) { ahlistbrowserclass = new hlistbrowserclass(); recpt.add_browser (ahlistbrowserclass); } if (adatelistbrowserclass == NULL) { adatelistbrowserclass = new datelistbrowserclass(); recpt.add_browser (adatelistbrowserclass); } if (ainvbrowserclass == NULL) { ainvbrowserclass = new invbrowserclass(); recpt.add_browser (ainvbrowserclass); } if (apagedbrowserclass == NULL) { apagedbrowserclass = new pagedbrowserclass(); recpt.add_browser (apagedbrowserclass); } if (ahtmlbrowserclass == NULL) { ahtmlbrowserclass = new htmlbrowserclass(); recpt.add_browser (ahtmlbrowserclass); } if (aphindbrowserclass == NULL) { aphindbrowserclass = new phindbrowserclass();; recpt.add_browser (aphindbrowserclass); } // set defaults recpt.configure ("gsdlhome", gsdl_gsdlhome); recpt.configure ("gdbmhome", gsdl_gdbmhome); recpt.configure ("collection", collection); int maxrequests = 1; // configure collections (and receptionist) with collectinfo stuff // different from the default colinfo_tmap::const_iterator this_info = translated_collectinfo.begin(); colinfo_tmap::const_iterator end_info = translated_collectinfo.end(); while (this_info != end_info) { text_tarray tmpconf; tmpconf.push_back ((*this_info).first); tmpconf.push_back ((*this_info).second.gsdl_gsdlhome); tmpconf.push_back ((*this_info).second.gsdl_gdbmhome); recpt.configure ("collectinfo", tmpconf); ++this_info; } // read in config files of each gdbmhome (in no particular order) // those read in last will override those read earlier // collections being used together in this way should be // careful not to have main.cfg files that might // screw with each other. text_tset::const_iterator thome = gdbmhomes.begin(); text_tset::const_iterator ehome = gdbmhomes.end(); while (thome != ehome) { if (!main_cfg_read (recpt, *thome, collection)) { // couldn't find the main configuration file page_errormaincfg (*thome, collection); return 0; } ++thome; } // w32server relies on gwcgi being set to "gsdl" recpt.configure ("gwcgi", "gsdl"); // initialise the library software if (!recpt.init(cerr)) { // an error occurred during the initialisation page_errorinit(gsdl_gsdlhome); return 0; } // get memory information MEMORYSTATUS memstatus; memstatus.dwLength = sizeof(MEMORYSTATUS); GlobalMemoryStatus(&memstatus); baseavailvirtual = memstatus.dwAvailVirtual; // save for later comparison return 1; } static void rememberpref (const text_t &tailstr) { gsdl_enterlib = tailstr; } static void send_file_from_disk(text_t filename, RequestInfoT *RInfo, RequestFieldsT *RFields) { // select appropriate mime type from file extension text_t ext; text_t::const_iterator end = filename.end(); text_t::const_iterator it = filename.begin(); text_t::const_iterator lastdot = end; while ((it = findchar(it, end, '.')) != end) { lastdot = it; ++it; } if (lastdot < end) ext = substr(lastdot+1, end); text_t mime = "unknown"; int len = ext.size(); if (len == 2) { if ((ext[0] == 'p' || ext[0] == 'P') && (ext[1] == 's' || ext[1] == 'S')) mime = "application/postscript"; } else if (len == 3) { if ((ext[0] == 'g' || ext[0] == 'G') && (ext[1] == 'i' || ext[1] == 'I') && (ext[2] == 'f' || ext[2] == 'F')) { mime = "image/gif"; } else if ((ext[0] == 'j' || ext[0] == 'J') && (ext[1] == 'p' || ext[1] == 'P') && (ext[2] == 'g' || ext[2] == 'G')) { mime = "image/jpeg"; } else if ((ext[0] == 'h' || ext[0] == 'H') && (ext[1] == 't' || ext[1] == 'T') && (ext[2] == 'm' || ext[2] == 'M')) { mime = "text/html"; } else if ((ext[0] == 'p' || ext[0] == 'P') && (ext[1] == 'd' || ext[1] == 'D') && (ext[2] == 'f' || ext[2] == 'F')) { mime = "application/pdf"; } else if ((ext[0] == 'p' || ext[0] == 'P') && (ext[1] == 'n' || ext[1] == 'N') && (ext[2] == 'g' || ext[2] == 'G')) { mime = "image/png"; } else if ((ext[0] == 'd' || ext[0] == 'D') && (ext[1] == 'o' || ext[1] == 'O') && (ext[2] == 'c' || ext[2] == 'C')) { mime = "application/msword"; } else if ((ext[0] == 'r' || ext[0] == 'R') && (ext[1] == 't' || ext[1] == 'T') && (ext[2] == 'f' || ext[2] == 'F')) { mime = "application/rtf"; } else if ((ext[0] == 'x' || ext[0] == 'X') && (ext[1] == 'l' || ext[1] == 'L') && (ext[2] == 's' || ext[2] == 'S')) { mime = "application/vnd.ms-excel"; } else if ((ext[0] == 'p' || ext[0] == 'P') && (ext[1] == 'p' || ext[1] == 'P') && (ext[2] == 'T' || ext[2] == 'T')) { mime = "application/vnd.ms-powerpoint"; } else if ((ext[0] == 'm' || ext[0] == 'M') && (ext[1] == 'p' || ext[1] == 'P') && (ext[2] == '3')) { mime = "audio/mpeg"; } } else if (len == 4) { if ((ext[0] == 'j' || ext[0] == 'J') && (ext[1] == 'p' || ext[1] == 'P') && (ext[2] == 'e' || ext[2] == 'E') && (ext[3] == 'g' || ext[3] == 'G')) { mime = "image/jpeg"; } else if ((ext[0] == 'h' || ext[0] == 'H') && (ext[1] == 't' || ext[1] == 'T') && (ext[2] == 'm' || ext[2] == 'M') && (ext[3] == 'l' || ext[3] == 'L')) { mime = "text/html"; } } // try to open the file filename = filename_cat (current_gsdlhome, filename); /* Feb 2002 - handle files with spaces in their name. */ text_t::iterator space_start; space_start=findword(filename.begin(),filename.end(),"%20"); while (space_start != filename.end()) { // we found a space... text_t::iterator after_space=space_start+3; text_t new_filename=substr(filename.begin(), space_start); new_filename += " "; new_filename += substr(after_space,filename.end()); filename=new_filename; space_start=findword(filename.begin(),filename.end(),"%20"); } char *filenamec = filename.getcstr(); TranslateEscapeString(filenamec); // Resolve any %xx values FILE *thefile = fopen(filenamec, "rb"); delete []filenamec; if (thefile == NULL) { log_message("file not found\n"); send_retrieve_error(404, "File not found", "Could not find the local file requested", RInfo); return; } int nr; char buffer[2048]; // send back required information char *mimec = mime.getcstr(); if (send_header(mimec, RInfo) >= 0) { if (RFields->MethodStr != "HEAD") { for (;;) { nr = fread(buffer, 1, 2048, thefile); if (nr <= 0) break; if (SendData(RInfo->ClientSocket, (BYTE *)buffer, nr, RInfo->ThreadNum) < 0) break; } } } delete []mimec; fclose(thefile); } static void handle_library_request(const text_t &argstr, RequestInfoT *RInfo, RequestFieldsT *RequestFields) { // parse the cgi arguments and produce the resulting page if there // have been no errors so far cgiargsclass args; fileupload_tmap fileuploads; text_tmap empty; // don't use this (it's for fastcgi on unix) if (!recpt.parse_cgi_args (argstr, fileuploads, args, cerr, empty)) { page_errorparseargs(gsdl_gsdlhome); return; } colinfo_tmap::const_iterator it = translated_collectinfo.find (args["c"]); if (it != translated_collectinfo.end()) { current_gsdlhome = (*it).second.gsdl_gsdlhome; } else { current_gsdlhome = gsdl_gsdlhome; } // produce cgi header response_t response; text_t response_data; recpt.get_cgihead_info (args, response, response_data, cerr, empty); if (response == location) { // location response response_data = "@" + recpt.expandmacros (response_data, args, cerr); char *response_data_c = response_data.getcstr(); send_header(response_data_c, RInfo); delete []response_data_c; return; } else if (response == content) { // content response char *response_data_c = response_data.getcstr(); if (send_header(response_data_c, RInfo) < 0) { delete []response_data_c; return; } delete []response_data_c; } else if (response == undecided_location) { // We know this is a relocation request but at the moment we don't know exactly where to // Just output the start of the header and wait until later to output the target location // Used for the "I'm feeling lucky" functionality cout << "HTTP/1.0 302 Relocation\r\n"; cout << "Server: GSDL\r\n"; cout << "Content-type: text/html \r\n"; } else { // unknown response cerr << "Error: get_cgihead_info returned an unknown response type.\n"; return; } textstream.tsbreset(); textstream.setrequestinfo (RInfo); if (!recpt.produce_content (args, cout, cerr)) { page_errorcgipage(gsdl_gsdlhome); return; } recpt.log_cgi_args (args, cerr, empty); cout << flush; cerr << flush; ++libaccessnum; } static void handle_server_request(text_t &tailstr, RequestInfoT *RequestInfo, RequestFieldsT *RequestFields) { text_t argstr; // do any url adjustments necessary if (tailstr.empty() || tailstr == "/") { tailstr = "/gsdl"; } text_t::const_iterator begin = tailstr.begin(); text_t::const_iterator end = tailstr.end(); // test to see if this is a library request or a local // file request if ((tailstr == "/gsdl") || ((tailstr.size() > 5) && (substr(begin, begin+6) == "/gsdl?"))) { // library request // argstr is the bit after the '?' if (tailstr != "/gsdl") { argstr = substr(begin+6, end); } // log the difference in access times DWORD thislibaccesstime = GetTickCount(); if (gsdl_keep_log || gsdl_show_console) { char logstr[256]; sprintf(logstr, "DELTA LIB ACCESS TIME: %i\n", (int)(thislibaccesstime - lastlibaccesstime)); log_message (logstr); } lastlibaccesstime = thislibaccesstime; // log this request if (gsdl_keep_log || gsdl_show_console) { text_t logstr = "LOCAL LIB: " + tailstr + "\n"; char *logstrc = logstr.getcstr(); log_message (logstrc); delete []logstrc; } handle_library_request (argstr, RequestInfo, RequestFields); // remember the preferences // rememberpref (tailstr); // log memory information if (gsdl_keep_log || gsdl_show_console) { MEMORYSTATUS memstatus; memstatus.dwLength = sizeof(MEMORYSTATUS); GlobalMemoryStatus(&memstatus); char logstr[256]; sprintf (logstr, "BDELTA AVAIL VIRTUAL: %i K\n", (int)((baseavailvirtual - memstatus.dwAvailVirtual)/1024)); log_message (logstr); } } else { // local file if (gsdl_keep_log || gsdl_show_console) { text_t logstr = "LOCAL FILE: " + tailstr + "\n"; char *logstrc = logstr.getcstr(); log_message (logstrc); delete []logstrc; } send_file_from_disk (tailstr, RequestInfo, RequestFields); } } int ExamineURIStr(text_t &URIStr, RequestInfoT *RequestInfo, RequestFieldsT *RequestFields) { text_t protocol, machine, rest; int port; if (RequestFields->ContentLength > 0) { // POST data URIStr.push_back('?'); for (int i = 0; i < RequestFields->ContentLength; ++i) { URIStr.push_back(RequestFields->Content[i]); } } if (parse_url(URIStr, protocol, machine, &port, rest)!=http_ok) { // Alter local file request to address 'gsdl' if (*(URIStr.begin()) != '/') URIStr = "http://gsdl/" + URIStr; else URIStr = "http://gsdl" + URIStr; parse_url(URIStr, protocol, machine, &port, rest); } if (machine == "gsdl") { // a local file request handle_server_request(rest, RequestInfo, RequestFields); } else { send_retrieve_error(404, "File not found", "Could not find the local file requested", RequestInfo); } return 1; }