From e58aa4d8e5784787e78390fd72f6a3543e771693 Mon Sep 17 00:00:00 2001 From: randomdan Date: Sat, 7 Aug 2010 13:36:00 +0000 Subject: Move CGI code into its own folder --- project2/FCgiIO.cpp | 63 ------------- project2/FCgiIO.h | 153 ------------------------------- project2/Jamfile.jam | 1 + project2/cgi/FCgiIO.cpp | 63 +++++++++++++ project2/cgi/FCgiIO.h | 153 +++++++++++++++++++++++++++++++ project2/cgi/cgiAppEngine.cpp | 198 ++++++++++++++++++++++++++++++++++++++++ project2/cgi/cgiAppEngine.h | 71 ++++++++++++++ project2/cgi/cgiEnvironment.cpp | 42 +++++++++ project2/cgi/cgiEnvironment.h | 27 ++++++ project2/cgi/p2webMain.cpp | 61 +++++++++++++ project2/cgiAppEngine.cpp | 198 ---------------------------------------- project2/cgiAppEngine.h | 71 -------------- project2/cgiEnvironment.cpp | 42 --------- project2/cgiEnvironment.h | 27 ------ project2/p2webMain.cpp | 61 ------------- 15 files changed, 616 insertions(+), 615 deletions(-) delete mode 100644 project2/FCgiIO.cpp delete mode 100644 project2/FCgiIO.h create mode 100644 project2/cgi/FCgiIO.cpp create mode 100644 project2/cgi/FCgiIO.h create mode 100644 project2/cgi/cgiAppEngine.cpp create mode 100644 project2/cgi/cgiAppEngine.h create mode 100644 project2/cgi/cgiEnvironment.cpp create mode 100644 project2/cgi/cgiEnvironment.h create mode 100644 project2/cgi/p2webMain.cpp delete mode 100644 project2/cgiAppEngine.cpp delete mode 100644 project2/cgiAppEngine.h delete mode 100644 project2/cgiEnvironment.cpp delete mode 100644 project2/cgiEnvironment.h delete mode 100644 project2/p2webMain.cpp diff --git a/project2/FCgiIO.cpp b/project2/FCgiIO.cpp deleted file mode 100644 index 7a3dd09..0000000 --- a/project2/FCgiIO.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - * $Id: FCgiIO.cpp,v 1.6 2007/07/02 18:48:19 sebdiaz Exp $ - * - * Copyright (C) 2002 Steve McAndrewSmith - * Copyright (C) 2002 - 2004 Stephen F. Booth - * 2007 Sebastien DIAZ - * Part of the GNU cgicc library, http://www.gnu.org/software/cgicc - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - */ - -#ifdef __GNUG__ -# pragma implementation -#endif - -#include -#include -#include - -#include "FCgiIO.h" - -cgicc::FCgiIO::FCgiIO(FCGX_Request& request) - : std::ostream(&fOutBuf), - fRequest(request), - fOutBuf(request.out), - fErrBuf(request.err), - fErr(&fErrBuf) -{ - rdbuf(&fOutBuf); - fErr.rdbuf(&fErrBuf); - - // Parse environment - for(char **e = fRequest.envp; *e != NULL; ++e) { - std::string s(*e); - std::string::size_type i = s.find('='); - if(i == std::string::npos) - throw std::runtime_error("Illegally formed environment"); - fEnv[s.substr(0, i)] = s.substr(i + 1); - } -} - -cgicc::FCgiIO::FCgiIO(const FCgiIO& io) - : CgiInput(io), - std::ostream(&fOutBuf), - fRequest(io.fRequest), - fErr(&fErrBuf), - fEnv(io.fEnv) -{ - rdbuf(&fOutBuf); - fErr.rdbuf(&fErrBuf); -} diff --git a/project2/FCgiIO.h b/project2/FCgiIO.h deleted file mode 100644 index a8b67f3..0000000 --- a/project2/FCgiIO.h +++ /dev/null @@ -1,153 +0,0 @@ -/* -*-c++-*- */ -/* - * $Id: FCgiIO.h,v 1.3 2007/07/02 18:48:19 sebdiaz Exp $ - * - * Copyright (C) 2002 Steve McAndrewSmith - * Copyright (C) 2002 Stephen F. Booth - * 2007 Sebastien DIAZ - * Part of the GNU cgicc library, http://www.gnu.org/software/cgicc - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA* - */ - -#ifndef _FCGIIO_H_ -#define _FCGIIO_H_ 1 - -#ifdef __GNUG__ -# pragma interface -#endif - -/*! \file FCgiIO.h - * \brief Class that implements input and output through a FastCGI request. - * - * This class provides access to the input byte-stream and environment - * variable interfaces of a FastCGI request. It is fully compatible with the - * Cgicc input API. - * - * It also provides access to the request's output and error streams, using a - * similar interface. - */ - -#include -#include -#include - -#include "fcgio.h" - -#include "cgicc/CgiInput.h" - -namespace cgicc { - - // ============================================================ - // Class FCgiIO - // ============================================================ - - /*! \class FCgiIO FCgiIO.h FCgiIO.h - * \brief Class that implements input and output through a FastCGI request. - * - * This class provides access to the input byte-stream and environment - * variable interfaces of a FastCGI request. It is fully compatible with the - * Cgicc input API. - * - * It also provides access to the request's output and error streams, using a - * similar interface. - */ - class CGICC_API FCgiIO : public cgicc::CgiInput, public std::ostream - { - public: - - // ============================================================ - - /*! \name Constructor and Destructor */ - //@{ - - /*! - * \brief Constructor - * - * Create a new FCgiIO object - */ - FCgiIO(FCGX_Request& request); - - /*! - * \brief Copy constructor - * - */ - FCgiIO(const FCgiIO& io); - - /*! - * \brief Destructor - * - * Delete this FCgiIO object - */ - virtual inline - ~FCgiIO() - {} - //@} - - // ============================================================ - - /*! \name Data Sources */ - //@{ - - /*! - * \brief Read data from the request's input stream. - * - * \param data The target buffer - * \param length The number of characters to read - * \return The number of characters read - */ - virtual inline size_t read(char *data, size_t length) - { - return FCGX_GetStr(data, length, fRequest.in); - } - - /*! - * \brief Query the value of an environment variable stored in the request. - * - * \param varName The name of an environment variable - * \return The value of the requested environment variable, or an empty - * string if not found. - */ - virtual inline std::string getenv(const char *varName) - { - return fEnv[varName]; - } - //@} - - // ============================================================ - - /*! \name Data Target Streams */ - //@{ - - /*! - * \brief Provides access to the error stream. - */ - inline std::ostream& err(void) - { - return fErr; - } - //@} - - protected: - FCGX_Request& fRequest; - fcgi_streambuf fOutBuf; - fcgi_streambuf fErrBuf; - std::ostream fErr; - std::map fEnv; - }; - -} // namespace cgicc - -#endif /* ! _FCGIIO_H_ */ diff --git a/project2/Jamfile.jam b/project2/Jamfile.jam index 771a473..a57b961 100644 --- a/project2/Jamfile.jam +++ b/project2/Jamfile.jam @@ -18,6 +18,7 @@ exe p2web : libxmlpp libxslt [ glob *.cpp ] + [ glob cgi/*.cpp ] ../libmisc ../libodbcpp : ../libmisc/ diff --git a/project2/cgi/FCgiIO.cpp b/project2/cgi/FCgiIO.cpp new file mode 100644 index 0000000..7a3dd09 --- /dev/null +++ b/project2/cgi/FCgiIO.cpp @@ -0,0 +1,63 @@ +/* + * $Id: FCgiIO.cpp,v 1.6 2007/07/02 18:48:19 sebdiaz Exp $ + * + * Copyright (C) 2002 Steve McAndrewSmith + * Copyright (C) 2002 - 2004 Stephen F. Booth + * 2007 Sebastien DIAZ + * Part of the GNU cgicc library, http://www.gnu.org/software/cgicc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + */ + +#ifdef __GNUG__ +# pragma implementation +#endif + +#include +#include +#include + +#include "FCgiIO.h" + +cgicc::FCgiIO::FCgiIO(FCGX_Request& request) + : std::ostream(&fOutBuf), + fRequest(request), + fOutBuf(request.out), + fErrBuf(request.err), + fErr(&fErrBuf) +{ + rdbuf(&fOutBuf); + fErr.rdbuf(&fErrBuf); + + // Parse environment + for(char **e = fRequest.envp; *e != NULL; ++e) { + std::string s(*e); + std::string::size_type i = s.find('='); + if(i == std::string::npos) + throw std::runtime_error("Illegally formed environment"); + fEnv[s.substr(0, i)] = s.substr(i + 1); + } +} + +cgicc::FCgiIO::FCgiIO(const FCgiIO& io) + : CgiInput(io), + std::ostream(&fOutBuf), + fRequest(io.fRequest), + fErr(&fErrBuf), + fEnv(io.fEnv) +{ + rdbuf(&fOutBuf); + fErr.rdbuf(&fErrBuf); +} diff --git a/project2/cgi/FCgiIO.h b/project2/cgi/FCgiIO.h new file mode 100644 index 0000000..a8b67f3 --- /dev/null +++ b/project2/cgi/FCgiIO.h @@ -0,0 +1,153 @@ +/* -*-c++-*- */ +/* + * $Id: FCgiIO.h,v 1.3 2007/07/02 18:48:19 sebdiaz Exp $ + * + * Copyright (C) 2002 Steve McAndrewSmith + * Copyright (C) 2002 Stephen F. Booth + * 2007 Sebastien DIAZ + * Part of the GNU cgicc library, http://www.gnu.org/software/cgicc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA* + */ + +#ifndef _FCGIIO_H_ +#define _FCGIIO_H_ 1 + +#ifdef __GNUG__ +# pragma interface +#endif + +/*! \file FCgiIO.h + * \brief Class that implements input and output through a FastCGI request. + * + * This class provides access to the input byte-stream and environment + * variable interfaces of a FastCGI request. It is fully compatible with the + * Cgicc input API. + * + * It also provides access to the request's output and error streams, using a + * similar interface. + */ + +#include +#include +#include + +#include "fcgio.h" + +#include "cgicc/CgiInput.h" + +namespace cgicc { + + // ============================================================ + // Class FCgiIO + // ============================================================ + + /*! \class FCgiIO FCgiIO.h FCgiIO.h + * \brief Class that implements input and output through a FastCGI request. + * + * This class provides access to the input byte-stream and environment + * variable interfaces of a FastCGI request. It is fully compatible with the + * Cgicc input API. + * + * It also provides access to the request's output and error streams, using a + * similar interface. + */ + class CGICC_API FCgiIO : public cgicc::CgiInput, public std::ostream + { + public: + + // ============================================================ + + /*! \name Constructor and Destructor */ + //@{ + + /*! + * \brief Constructor + * + * Create a new FCgiIO object + */ + FCgiIO(FCGX_Request& request); + + /*! + * \brief Copy constructor + * + */ + FCgiIO(const FCgiIO& io); + + /*! + * \brief Destructor + * + * Delete this FCgiIO object + */ + virtual inline + ~FCgiIO() + {} + //@} + + // ============================================================ + + /*! \name Data Sources */ + //@{ + + /*! + * \brief Read data from the request's input stream. + * + * \param data The target buffer + * \param length The number of characters to read + * \return The number of characters read + */ + virtual inline size_t read(char *data, size_t length) + { + return FCGX_GetStr(data, length, fRequest.in); + } + + /*! + * \brief Query the value of an environment variable stored in the request. + * + * \param varName The name of an environment variable + * \return The value of the requested environment variable, or an empty + * string if not found. + */ + virtual inline std::string getenv(const char *varName) + { + return fEnv[varName]; + } + //@} + + // ============================================================ + + /*! \name Data Target Streams */ + //@{ + + /*! + * \brief Provides access to the error stream. + */ + inline std::ostream& err(void) + { + return fErr; + } + //@} + + protected: + FCGX_Request& fRequest; + fcgi_streambuf fOutBuf; + fcgi_streambuf fErrBuf; + std::ostream fErr; + std::map fEnv; + }; + +} // namespace cgicc + +#endif /* ! _FCGIIO_H_ */ diff --git a/project2/cgi/cgiAppEngine.cpp b/project2/cgi/cgiAppEngine.cpp new file mode 100644 index 0000000..5348246 --- /dev/null +++ b/project2/cgi/cgiAppEngine.cpp @@ -0,0 +1,198 @@ +#include "cgiAppEngine.h" +#include +#include +#include +#include "cgiEnvironment.h" +#include +#include "../xmlObjectLoader.h" +#include "../iterate.h" +#include +#include +#include +#include "../sessionShm.h" +#include + +const std::string SESSIONID = "sessionID"; +typedef boost::uuids::uuid SIDKey; +typedef std::string SValue; + +SessionContainer * sessionsContainer = new SessionContainerShm(); + +CgiApplicationEngine::CgiApplicationEngine(const CgiEnvironment * e) : + ApplicationEngine(e), + _env(e), + header(NULL), + sessionID(boost::uuids::nil_generator()()) +{ + BOOST_FOREACH(const cgicc::HTTPCookie c, e->getCookieList()) { + if (c.getName() == SESSIONID) { + sessionID = boost::uuids::string_generator()(c.getValue()); + } + } + if (_env->getRequestMethod() == "POST") { + currentStage = new RequestStage(this, e->elems[0]); + } + else { + currentStage = new PresentStage(this, e->elems.size() > 0 ? e->elems[0] : "index"); + } +} + +CgiApplicationEngine::~CgiApplicationEngine() +{ + delete header; +} + +const Environment * +CgiApplicationEngine::env() const +{ + return _env; +} + +void +CgiApplicationEngine::process() const +{ + while (!doc && currentStage) { + Stage * prev = currentStage; + currentStage = currentStage->run(); + delete prev; + } + if (!sessionID.is_nil()) { + header->setCookie(cgicc::HTTPCookie(SESSIONID, boost::lexical_cast(sessionID), "Session ID", + _env->getServerName().substr(_env->getServerName().find(".")), 3600, "/", false)); + } +} + +CgiApplicationEngine::Stage::Stage(const CgiApplicationEngine * e) : appEngine(e) +{ +} + +CgiApplicationEngine::Stage::~Stage() +{ +} + +CgiApplicationEngine::PresentStage::PresentStage(const CgiApplicationEngine * e, const std::string & id) : + CgiApplicationEngine::Stage(e), + Presenter("present", id) +{ +} +CgiApplicationEngine::PresentStage::PresentStage(const CgiApplicationEngine * e, const std::string & group, const std::string & id) : + CgiApplicationEngine::Stage(e), + Presenter(group, id) +{ +} +CgiApplicationEngine::PresentStage::~PresentStage() +{ +} +CgiApplicationEngine::Stage * +CgiApplicationEngine::PresentStage::run() +{ + BOOST_FOREACH(OrderedParamCheckers::value_type pc, parameterChecks) { + if (!pc.second->performCheck(appEngine)) { + return new PresentStage(appEngine, pc.second->present); + } + } + appEngine->doc = getDataDocument(); + sessionsContainer->CleanUp(); + return NULL; +} + +Presenter::XmlDocumentPtr +CgiApplicationEngine::PresentStage::getDataDocument() const +{ + XmlDocumentPtr responseDoc = Presenter::getDataDocument(); + xmlpp::Element * responseRoot = responseDoc->get_root_node(); + // URL elements + xmlpp::Element * uriElems = responseRoot->add_child("uriElems", "project2"); + BOOST_FOREACH(std::string s, appEngine->_env->elems) { + uriElems->add_child("uriElem", "project2")->set_child_text(s); + } + // Parameters + xmlpp::Element * paramsXml = responseRoot->add_child("params", "project2"); + BOOST_FOREACH(cgicc::FormEntry fe, appEngine->_env->cgi->getElements()) { + xmlpp::Element * param = paramsXml->add_child("param", "project2"); + param->add_child_text(fe.getValue()); + param->set_attribute("name", fe.getName()); + } + // Sessions variables + if (!appEngine->sessionID.is_nil()) { + xmlpp::Element * sessionXml = responseRoot->add_child("session", "project2"); + sessionXml->set_attribute("id", boost::lexical_cast(appEngine->sessionID)); + Session::Values session(sessionsContainer->GetSession(appEngine->sessionID)->GetValuesCopy()); + BOOST_FOREACH(SessionShm::Values::value_type sv, session) { + xmlpp::Element * param = sessionXml->add_child("var", "project2"); + param->add_child_text(sv.second); + param->set_attribute("name", sv.first); + } + } + // XSLT Style + char * buf; + if (responseStyle.length() && asprintf(&buf, "type=\"text/xsl\" href=\"%s\"", + responseStyle.c_str()) > 0) { + xmlAddPrevSibling(responseRoot->cobj(), + xmlNewDocPI(responseDoc->cobj(), BAD_CAST "xml-stylesheet", BAD_CAST buf)); + free(buf); + appEngine->header = new cgicc::HTTPContentHeader("text/xml-xslt"); + } + else { + appEngine->header = new cgicc::HTTPContentHeader("text/xml"); + } + return responseDoc; +} + +CgiApplicationEngine::RequestStage::RequestStage(const CgiApplicationEngine * e, const std::string & id) : + CgiApplicationEngine::Stage(e) +{ + xmlpp::DomParser request("request/" + id + ".xml"); + while (xmlXIncludeProcessFlags(request.get_document()->cobj(), XML_PARSE_NOXINCNODE) > 0); + xmlpp::Element * requestRoot = request.get_document()->get_root_node(); + present = requestRoot->get_attribute_value("present"); + + Loaders loaders; + _DataSource::AddLoaders(loaders, appEngine->datasources); + _ParamChecker::AddLoaders(loaders, parameterChecks); + _Task::AddLoaders(loaders, tasks); + _Iterate::AddLoaders(loaders, tasks); + _LoaderBase::collectAll(loaders, "project2", requestRoot, true, true); +} +CgiApplicationEngine::RequestStage::~RequestStage() +{ +} +CgiApplicationEngine::Stage * +CgiApplicationEngine::RequestStage::run() +{ + BOOST_FOREACH(OrderedParamCheckers::value_type pc, parameterChecks) { + if (!pc.second->performCheck(appEngine)) { + return new PresentStage(appEngine, pc.second->present); + } + } + try { + BOOST_FOREACH(NoOutputExecutes::value_type t, tasks) { + t.second->execute(); + } + // Commit data source transactions (without invoking a connection) + BOOST_FOREACH(DataSources::value_type ds, appEngine->datasources) { + ds.second->commit(); + } + } + catch (...) { + // Do something about the error + BOOST_FOREACH(DataSources::value_type ds, appEngine->datasources) { + ds.second->rollback(); + } + throw; + } + return new PresentStage(appEngine, present); +} + +SessionPtr +CgiApplicationEngine::session() const +{ + return sessionsContainer->GetSession(sessionID); +} + +PresenterPtr +CgiApplicationEngine::getPresenter(const std::string & group, const std::string & id) const +{ + return PresenterPtr(new PresentStage(this, group, id)); +} + diff --git a/project2/cgi/cgiAppEngine.h b/project2/cgi/cgiAppEngine.h new file mode 100644 index 0000000..112e672 --- /dev/null +++ b/project2/cgi/cgiAppEngine.h @@ -0,0 +1,71 @@ +#ifndef CGIAPPENGINE_H +#define CGIAPPENGINE_H + +#include "../appEngine.h" +#include "../task.h" +#include "../paramChecker.h" +#include "../presenter.h" +#include +#include +#include +#include + +class CgiEnvironment; +class Session; +namespace cgicc { + class HTTPContentHeader; +} + +class CgiApplicationEngine : public ApplicationEngine { + public: + CgiApplicationEngine(const CgiEnvironment *); + virtual ~CgiApplicationEngine(); + + void process() const; + const cgicc::HTTPContentHeader * getHeader() const { return header; } + template + void write(const Writer & w) const + { + w(doc->cobj()); + } + const Environment * env() const; + SessionPtr session() const; + PresenterPtr getPresenter(const std::string & group, const std::string & id) const; + const CgiEnvironment * _env; + protected: + mutable cgicc::HTTPContentHeader * header; + private: + mutable boost::shared_ptr doc; + class Stage { + public: + Stage(const CgiApplicationEngine *); + virtual ~Stage() = 0; + virtual Stage * run() = 0; + protected: + const CgiApplicationEngine * appEngine; + }; + class RequestStage : public Stage { + public: + RequestStage(const CgiApplicationEngine *, const std::string & id); + virtual ~RequestStage(); + virtual Stage * run(); + std::string present; + protected: + OrderedParamCheckers parameterChecks; + NoOutputExecutes tasks; + }; + class PresentStage : public Stage, public Presenter { + public: + PresentStage(const CgiApplicationEngine *, const std::string & id); + PresentStage(const CgiApplicationEngine *, const std::string & group, const std::string & id); + virtual ~PresentStage(); + virtual Stage * run(); + protected: + XmlDocumentPtr getDataDocument() const; + }; + mutable Stage * currentStage; + mutable boost::uuids::uuid sessionID; +}; + +#endif + diff --git a/project2/cgi/cgiEnvironment.cpp b/project2/cgi/cgiEnvironment.cpp new file mode 100644 index 0000000..630629a --- /dev/null +++ b/project2/cgi/cgiEnvironment.cpp @@ -0,0 +1,42 @@ +#include "cgiEnvironment.h" +#include "../appEngine.h" +#include +#include +#include + +template +std::vectormakeVector(const Y & y) +{ + return std::vector(y.begin(), y.end()); +} + +CgiEnvironment::CgiEnvironment(cgicc::Cgicc * c) : + cgicc::CgiEnvironment(c->getEnvironment()), + elems(makeVector(boost::tokenizer >(getRedirectURL(), boost::char_separator("/")))), + cgi(c) +{ +} + +CgiEnvironment::~CgiEnvironment() +{ +} + +Glib::ustring +CgiEnvironment::getParamUri(unsigned int p) const +{ + if (p >= elems.size()) { + throw ApplicationEngine::UriElementOutOfRange(); + } + return elems[p]; +} + +Glib::ustring +CgiEnvironment::getParamQuery(const std::string & p) const +{ + cgicc::const_form_iterator i = cgi->getElement(p); + if (i == cgi->getElements().end()) { + throw ApplicationEngine::ParamNotFound(); + } + return (*cgi)(p); +} + diff --git a/project2/cgi/cgiEnvironment.h b/project2/cgi/cgiEnvironment.h new file mode 100644 index 0000000..5c0455c --- /dev/null +++ b/project2/cgi/cgiEnvironment.h @@ -0,0 +1,27 @@ +#ifndef ENVPROC_H +#define ENVPROC_H + +#include +#include +#include "../environment.h" +#include + +namespace cgicc { + class Cgicc; +} + +class CgiEnvironment : public Environment, public cgicc::CgiEnvironment { + public: + CgiEnvironment(cgicc::Cgicc *); + virtual ~CgiEnvironment(); + + Glib::ustring getParamUri(unsigned int idx) const; + Glib::ustring getParamQuery(const std::string & idx) const; + std::string getServerName() const { return cgicc::CgiEnvironment::getServerName(); } + std::string getScriptName() const { return cgicc::CgiEnvironment::getScriptName(); } + + std::vector elems; + const cgicc::Cgicc * const cgi; +}; + +#endif diff --git a/project2/cgi/p2webMain.cpp b/project2/cgi/p2webMain.cpp new file mode 100644 index 0000000..ef070f0 --- /dev/null +++ b/project2/cgi/p2webMain.cpp @@ -0,0 +1,61 @@ +#include +#include +#include +#include +FILE * realstdout = stdout; +#include +#include "cgiEnvironment.h" +#include "cgiAppEngine.h" +#include +#include "FCgiIO.h" + +int +xmlWrite(void * _out, const char * buf, int len) +{ + cgicc::FCgiIO & IO = *((cgicc::FCgiIO*)_out); + IO.write(buf, len); + return len; +} + +int main(void) +{ + if (!FCGX_IsCGI()) { + FCGX_Request request; + + FCGX_Init(); + FCGX_InitRequest(&request, 0, 0); + + while (FCGX_Accept_r(&request) == 0) { + cgicc::FCgiIO IO(request); + try { + cgicc::Cgicc cgi(&IO); + CgiEnvironment env(&cgi); + CgiApplicationEngine app(&env); + app.process(); + IO << "Cache-control: no-cache" << std::endl; + app.getHeader()->render(IO); + xmlOutputBufferPtr out = xmlOutputBufferCreateIO( + xmlWrite, NULL, &IO, xmlGetCharEncodingHandler(XML_CHAR_ENCODING_UTF8)); + app.write(boost::bind(xmlSaveFileTo, out, _1, "utf-8")); + } + catch (const std::exception & e) { + cgicc::HTTPContentHeader header("text/plain"); + header.render(IO); + IO << "Kaboom!" << std::endl << std::endl << e.what(); + } + catch (...) { + cgicc::HTTPContentHeader header("text/plain"); + header.render(IO); + IO << "Kaboom!" << std::endl << std::endl << "Unknown exception."; + } + } + } + else { + cgicc::Cgicc cgi(NULL); + CgiEnvironment env(&cgi); + CgiApplicationEngine app(&env); + app.process(); + app.write(boost::bind(xmlDocDump, realstdout, _1)); + } + return 0; +} diff --git a/project2/cgiAppEngine.cpp b/project2/cgiAppEngine.cpp deleted file mode 100644 index 51bc089..0000000 --- a/project2/cgiAppEngine.cpp +++ /dev/null @@ -1,198 +0,0 @@ -#include "cgiAppEngine.h" -#include -#include -#include -#include "cgiEnvironment.h" -#include -#include "xmlObjectLoader.h" -#include "iterate.h" -#include -#include -#include -#include "sessionShm.h" -#include - -const std::string SESSIONID = "sessionID"; -typedef boost::uuids::uuid SIDKey; -typedef std::string SValue; - -SessionContainer * sessionsContainer = new SessionContainerShm(); - -CgiApplicationEngine::CgiApplicationEngine(const CgiEnvironment * e) : - ApplicationEngine(e), - _env(e), - header(NULL), - sessionID(boost::uuids::nil_generator()()) -{ - BOOST_FOREACH(const cgicc::HTTPCookie c, e->getCookieList()) { - if (c.getName() == SESSIONID) { - sessionID = boost::uuids::string_generator()(c.getValue()); - } - } - if (_env->getRequestMethod() == "POST") { - currentStage = new RequestStage(this, e->elems[0]); - } - else { - currentStage = new PresentStage(this, e->elems.size() > 0 ? e->elems[0] : "index"); - } -} - -CgiApplicationEngine::~CgiApplicationEngine() -{ - delete header; -} - -const Environment * -CgiApplicationEngine::env() const -{ - return _env; -} - -void -CgiApplicationEngine::process() const -{ - while (!doc && currentStage) { - Stage * prev = currentStage; - currentStage = currentStage->run(); - delete prev; - } - if (!sessionID.is_nil()) { - header->setCookie(cgicc::HTTPCookie(SESSIONID, boost::lexical_cast(sessionID), "Session ID", - _env->getServerName().substr(_env->getServerName().find(".")), 3600, "/", false)); - } -} - -CgiApplicationEngine::Stage::Stage(const CgiApplicationEngine * e) : appEngine(e) -{ -} - -CgiApplicationEngine::Stage::~Stage() -{ -} - -CgiApplicationEngine::PresentStage::PresentStage(const CgiApplicationEngine * e, const std::string & id) : - CgiApplicationEngine::Stage(e), - Presenter("present", id) -{ -} -CgiApplicationEngine::PresentStage::PresentStage(const CgiApplicationEngine * e, const std::string & group, const std::string & id) : - CgiApplicationEngine::Stage(e), - Presenter(group, id) -{ -} -CgiApplicationEngine::PresentStage::~PresentStage() -{ -} -CgiApplicationEngine::Stage * -CgiApplicationEngine::PresentStage::run() -{ - BOOST_FOREACH(OrderedParamCheckers::value_type pc, parameterChecks) { - if (!pc.second->performCheck(appEngine)) { - return new PresentStage(appEngine, pc.second->present); - } - } - appEngine->doc = getDataDocument(); - sessionsContainer->CleanUp(); - return NULL; -} - -Presenter::XmlDocumentPtr -CgiApplicationEngine::PresentStage::getDataDocument() const -{ - XmlDocumentPtr responseDoc = Presenter::getDataDocument(); - xmlpp::Element * responseRoot = responseDoc->get_root_node(); - // URL elements - xmlpp::Element * uriElems = responseRoot->add_child("uriElems", "project2"); - BOOST_FOREACH(std::string s, appEngine->_env->elems) { - uriElems->add_child("uriElem", "project2")->set_child_text(s); - } - // Parameters - xmlpp::Element * paramsXml = responseRoot->add_child("params", "project2"); - BOOST_FOREACH(cgicc::FormEntry fe, appEngine->_env->cgi->getElements()) { - xmlpp::Element * param = paramsXml->add_child("param", "project2"); - param->add_child_text(fe.getValue()); - param->set_attribute("name", fe.getName()); - } - // Sessions variables - if (!appEngine->sessionID.is_nil()) { - xmlpp::Element * sessionXml = responseRoot->add_child("session", "project2"); - sessionXml->set_attribute("id", boost::lexical_cast(appEngine->sessionID)); - Session::Values session(sessionsContainer->GetSession(appEngine->sessionID)->GetValuesCopy()); - BOOST_FOREACH(SessionShm::Values::value_type sv, session) { - xmlpp::Element * param = sessionXml->add_child("var", "project2"); - param->add_child_text(sv.second); - param->set_attribute("name", sv.first); - } - } - // XSLT Style - char * buf; - if (responseStyle.length() && asprintf(&buf, "type=\"text/xsl\" href=\"%s\"", - responseStyle.c_str()) > 0) { - xmlAddPrevSibling(responseRoot->cobj(), - xmlNewDocPI(responseDoc->cobj(), BAD_CAST "xml-stylesheet", BAD_CAST buf)); - free(buf); - appEngine->header = new cgicc::HTTPContentHeader("text/xml-xslt"); - } - else { - appEngine->header = new cgicc::HTTPContentHeader("text/xml"); - } - return responseDoc; -} - -CgiApplicationEngine::RequestStage::RequestStage(const CgiApplicationEngine * e, const std::string & id) : - CgiApplicationEngine::Stage(e) -{ - xmlpp::DomParser request("request/" + id + ".xml"); - while (xmlXIncludeProcessFlags(request.get_document()->cobj(), XML_PARSE_NOXINCNODE) > 0); - xmlpp::Element * requestRoot = request.get_document()->get_root_node(); - present = requestRoot->get_attribute_value("present"); - - Loaders loaders; - _DataSource::AddLoaders(loaders, appEngine->datasources); - _ParamChecker::AddLoaders(loaders, parameterChecks); - _Task::AddLoaders(loaders, tasks); - _Iterate::AddLoaders(loaders, tasks); - _LoaderBase::collectAll(loaders, "project2", requestRoot, true, true); -} -CgiApplicationEngine::RequestStage::~RequestStage() -{ -} -CgiApplicationEngine::Stage * -CgiApplicationEngine::RequestStage::run() -{ - BOOST_FOREACH(OrderedParamCheckers::value_type pc, parameterChecks) { - if (!pc.second->performCheck(appEngine)) { - return new PresentStage(appEngine, pc.second->present); - } - } - try { - BOOST_FOREACH(NoOutputExecutes::value_type t, tasks) { - t.second->execute(); - } - // Commit data source transactions (without invoking a connection) - BOOST_FOREACH(DataSources::value_type ds, appEngine->datasources) { - ds.second->commit(); - } - } - catch (...) { - // Do something about the error - BOOST_FOREACH(DataSources::value_type ds, appEngine->datasources) { - ds.second->rollback(); - } - throw; - } - return new PresentStage(appEngine, present); -} - -SessionPtr -CgiApplicationEngine::session() const -{ - return sessionsContainer->GetSession(sessionID); -} - -PresenterPtr -CgiApplicationEngine::getPresenter(const std::string & group, const std::string & id) const -{ - return PresenterPtr(new PresentStage(this, group, id)); -} - diff --git a/project2/cgiAppEngine.h b/project2/cgiAppEngine.h deleted file mode 100644 index c3bd137..0000000 --- a/project2/cgiAppEngine.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef CGIAPPENGINE_H -#define CGIAPPENGINE_H - -#include "appEngine.h" -#include "task.h" -#include "paramChecker.h" -#include "presenter.h" -#include -#include -#include -#include - -class CgiEnvironment; -class Session; -namespace cgicc { - class HTTPContentHeader; -} - -class CgiApplicationEngine : public ApplicationEngine { - public: - CgiApplicationEngine(const CgiEnvironment *); - virtual ~CgiApplicationEngine(); - - void process() const; - const cgicc::HTTPContentHeader * getHeader() const { return header; } - template - void write(const Writer & w) const - { - w(doc->cobj()); - } - const Environment * env() const; - SessionPtr session() const; - PresenterPtr getPresenter(const std::string & group, const std::string & id) const; - const CgiEnvironment * _env; - protected: - mutable cgicc::HTTPContentHeader * header; - private: - mutable boost::shared_ptr doc; - class Stage { - public: - Stage(const CgiApplicationEngine *); - virtual ~Stage() = 0; - virtual Stage * run() = 0; - protected: - const CgiApplicationEngine * appEngine; - }; - class RequestStage : public Stage { - public: - RequestStage(const CgiApplicationEngine *, const std::string & id); - virtual ~RequestStage(); - virtual Stage * run(); - std::string present; - protected: - OrderedParamCheckers parameterChecks; - NoOutputExecutes tasks; - }; - class PresentStage : public Stage, public Presenter { - public: - PresentStage(const CgiApplicationEngine *, const std::string & id); - PresentStage(const CgiApplicationEngine *, const std::string & group, const std::string & id); - virtual ~PresentStage(); - virtual Stage * run(); - protected: - XmlDocumentPtr getDataDocument() const; - }; - mutable Stage * currentStage; - mutable boost::uuids::uuid sessionID; -}; - -#endif - diff --git a/project2/cgiEnvironment.cpp b/project2/cgiEnvironment.cpp deleted file mode 100644 index 2faf165..0000000 --- a/project2/cgiEnvironment.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "cgiEnvironment.h" -#include "appEngine.h" -#include -#include -#include - -template -std::vectormakeVector(const Y & y) -{ - return std::vector(y.begin(), y.end()); -} - -CgiEnvironment::CgiEnvironment(cgicc::Cgicc * c) : - cgicc::CgiEnvironment(c->getEnvironment()), - elems(makeVector(boost::tokenizer >(getRedirectURL(), boost::char_separator("/")))), - cgi(c) -{ -} - -CgiEnvironment::~CgiEnvironment() -{ -} - -Glib::ustring -CgiEnvironment::getParamUri(unsigned int p) const -{ - if (p >= elems.size()) { - throw ApplicationEngine::UriElementOutOfRange(); - } - return elems[p]; -} - -Glib::ustring -CgiEnvironment::getParamQuery(const std::string & p) const -{ - cgicc::const_form_iterator i = cgi->getElement(p); - if (i == cgi->getElements().end()) { - throw ApplicationEngine::ParamNotFound(); - } - return (*cgi)(p); -} - diff --git a/project2/cgiEnvironment.h b/project2/cgiEnvironment.h deleted file mode 100644 index c01d50d..0000000 --- a/project2/cgiEnvironment.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef ENVPROC_H -#define ENVPROC_H - -#include -#include -#include "environment.h" -#include - -namespace cgicc { - class Cgicc; -} - -class CgiEnvironment : public Environment, public cgicc::CgiEnvironment { - public: - CgiEnvironment(cgicc::Cgicc *); - virtual ~CgiEnvironment(); - - Glib::ustring getParamUri(unsigned int idx) const; - Glib::ustring getParamQuery(const std::string & idx) const; - std::string getServerName() const { return cgicc::CgiEnvironment::getServerName(); } - std::string getScriptName() const { return cgicc::CgiEnvironment::getScriptName(); } - - std::vector elems; - const cgicc::Cgicc * const cgi; -}; - -#endif diff --git a/project2/p2webMain.cpp b/project2/p2webMain.cpp deleted file mode 100644 index ef070f0..0000000 --- a/project2/p2webMain.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include -#include -#include -FILE * realstdout = stdout; -#include -#include "cgiEnvironment.h" -#include "cgiAppEngine.h" -#include -#include "FCgiIO.h" - -int -xmlWrite(void * _out, const char * buf, int len) -{ - cgicc::FCgiIO & IO = *((cgicc::FCgiIO*)_out); - IO.write(buf, len); - return len; -} - -int main(void) -{ - if (!FCGX_IsCGI()) { - FCGX_Request request; - - FCGX_Init(); - FCGX_InitRequest(&request, 0, 0); - - while (FCGX_Accept_r(&request) == 0) { - cgicc::FCgiIO IO(request); - try { - cgicc::Cgicc cgi(&IO); - CgiEnvironment env(&cgi); - CgiApplicationEngine app(&env); - app.process(); - IO << "Cache-control: no-cache" << std::endl; - app.getHeader()->render(IO); - xmlOutputBufferPtr out = xmlOutputBufferCreateIO( - xmlWrite, NULL, &IO, xmlGetCharEncodingHandler(XML_CHAR_ENCODING_UTF8)); - app.write(boost::bind(xmlSaveFileTo, out, _1, "utf-8")); - } - catch (const std::exception & e) { - cgicc::HTTPContentHeader header("text/plain"); - header.render(IO); - IO << "Kaboom!" << std::endl << std::endl << e.what(); - } - catch (...) { - cgicc::HTTPContentHeader header("text/plain"); - header.render(IO); - IO << "Kaboom!" << std::endl << std::endl << "Unknown exception."; - } - } - } - else { - cgicc::Cgicc cgi(NULL); - CgiEnvironment env(&cgi); - CgiApplicationEngine app(&env); - app.process(); - app.write(boost::bind(xmlDocDump, realstdout, _1)); - } - return 0; -} -- cgit v1.2.3