diff options
author | randomdan <randomdan@localhost> | 2011-07-14 19:50:11 +0000 |
---|---|---|
committer | randomdan <randomdan@localhost> | 2011-07-14 19:50:11 +0000 |
commit | d2f60795927647c09acbeceb32efb8a29314c340 (patch) | |
tree | 5dc1f6f9b8331a17e67863c847ea63ca97f5d92c /project2/cgi | |
parent | Fix unused_result warning when compiled with optimization enabled (diff) | |
download | project2-d2f60795927647c09acbeceb32efb8a29314c340.tar.bz2 project2-d2f60795927647c09acbeceb32efb8a29314c340.tar.xz project2-d2f60795927647c09acbeceb32efb8a29314c340.zip |
All new dynamic transformations and processing and tidyup and stuff
Diffstat (limited to 'project2/cgi')
-rw-r--r-- | project2/cgi/cgiAppEngine.cpp | 99 | ||||
-rw-r--r-- | project2/cgi/cgiAppEngine.h | 84 | ||||
-rw-r--r-- | project2/cgi/cgiCommon.cpp | 4 | ||||
-rw-r--r-- | project2/cgi/cgiEnvironment.cpp | 4 | ||||
-rw-r--r-- | project2/cgi/cgiEnvironment.h | 3 | ||||
-rw-r--r-- | project2/cgi/cgiStageCustomError.cpp | 25 | ||||
-rw-r--r-- | project2/cgi/cgiStageCustomNotFound.cpp | 26 | ||||
-rw-r--r-- | project2/cgi/cgiStageDefaultError.cpp | 35 | ||||
-rw-r--r-- | project2/cgi/cgiStageDefaultNotFound.cpp | 34 | ||||
-rw-r--r-- | project2/cgi/cgiStageInitial.cpp | 6 | ||||
-rw-r--r-- | project2/cgi/cgiStagePresent.cpp | 43 | ||||
-rw-r--r-- | project2/cgi/cgiStageRequest.cpp | 53 | ||||
-rw-r--r-- | project2/cgi/testCgi.cpp | 70 |
13 files changed, 223 insertions, 263 deletions
diff --git a/project2/cgi/cgiAppEngine.cpp b/project2/cgi/cgiAppEngine.cpp index 52e69cf..f4eb134 100644 --- a/project2/cgi/cgiAppEngine.cpp +++ b/project2/cgi/cgiAppEngine.cpp @@ -8,6 +8,7 @@ #include <boost/regex.hpp> #include <boost/foreach.hpp> #include "../sessionXml.h" +#include "../ostreamWrapper.h" #include <boost/date_time/microsec_time_clock.hpp> const std::string SESSIONID = "sessionID"; @@ -18,29 +19,22 @@ SessionContainer * sessionsContainer = new SessionContainerXml(); SimpleMessageException(UnknownDomain); -static -int -xmlWrite(void * _out, const char * buf, int len) -{ - std::ostream * IO = static_cast<std::ostream*>(_out); - IO->write(buf, len); - return len; -} - -CgiApplicationEngine::CgiApplicationEngine(const CgiEnvironment * e) : +CgiApplicationEngine::CgiApplicationEngine(const CgiEnvironment * e, std::ostream & io) : ApplicationEngine("web/host"), - _env(e) + _env(e), + IO(io) { BOOST_FOREACH(const cgicc::HTTPCookie c, e->getCookieList()) { if (c.getName() == SESSIONID) { sessionID = c.getValue(); } } - currentStage = new InitialStage(e); + currentStage = NextStage(new InitialStage(e)); } CgiApplicationEngine::~CgiApplicationEngine() { + sessionsContainer->CleanUp(); } const Environment * @@ -49,25 +43,14 @@ CgiApplicationEngine::env() const return _env; } -void -CgiApplicationEngine::write(std::ostream & IO) const -{ - HttpHeaderPtr header = currentStage->getHeader(); - if (!sessionID.is_nil()) { - header->setCookie(cgicc::HTTPCookie(SESSIONID, sessionID.str(), "Session ID", - _env->getServerName().substr(_env->getServerName().find(".")), 3600, "/", false)); - } - header->render(IO); - xmlOutputBufferPtr out = xmlOutputBufferCreateIO( - xmlWrite, NULL, &IO, xmlGetCharEncodingHandler(XML_CHAR_ENCODING_UTF8)); - xmlSaveFileTo(out, currentStage->getDataDocument()->cobj(), "utf-8"); - sessionsContainer->CleanUp(); -#ifndef NDEBUG - if (!_env->dumpdatadoc.empty()) { - currentStage->getDataDocument()->write_to_file_formatted(_env->dumpdatadoc); - } -#endif -} +class TransformXmlToHttpStream : public TransformImpl<xmlpp::Document, ostreamWrapper> { + public: + void transform(const xmlpp::Document * doc, ostreamWrapper * o) const + { + const_cast<xmlpp::Document *>(doc)->write_to_stream_formatted(o->strm, "UTF-8"); + } +}; +DECLARE_TRANSFORM(TransformXmlToHttpStream); void CgiApplicationEngine::process() const @@ -75,34 +58,56 @@ CgiApplicationEngine::process() const startTime = boost::date_time::microsec_clock<boost::posix_time::ptime>::universal_time(); bool triedNotFound = false; bool triedOnError = false; - StagePtr nextStage; do { try { - nextStage = currentStage->run(); + currentStage = currentStage.get<0>()->run(); + } + catch (const CheckHost::CheckFailure & cf) { + currentStage = NextStage(new PresentStage(_env, cf.failedCheck->present)); } catch (const XmlScriptParser::NotFound & nf) { if (_env->notFoundPresent.empty() || triedNotFound) { - nextStage = new DefaultNotFoundStage(_env, nf); + currentStage = NextStage(new DefaultNotFoundStage(_env, nf)); } else { triedNotFound = true; - nextStage = new CustomNotFoundStage(_env, nf); + currentStage = NextStage(new CustomNotFoundStage(_env, nf)); } } catch (const std::exception & ex) { if (_env->onErrorPresent.empty() || triedOnError) { - nextStage = new DefaultErrorStage(_env, ex); + currentStage = NextStage(new DefaultErrorStage(_env, ex)); } else { triedNotFound = true; - nextStage = new CustomErrorStage(_env, ex); + currentStage = NextStage(new CustomErrorStage(_env, ex)); } } - } while (nextStage && (currentStage = nextStage)); + } while (currentStage.get<0>()); endTime = boost::date_time::microsec_clock<boost::posix_time::ptime>::universal_time(); - PresenterPtr p = boost::dynamic_pointer_cast<Presenter>(currentStage); - if (p) { - addAppData(p.get()); + ResponseStagePtr rs = currentStage.get<1>(); + if (currentStage.get<3>()) { + addAppData(currentStage.get<3>().get()); + addEnvData(currentStage.get<3>().get()); + } + HttpHeaderPtr header = rs->getHeader(); + if (!sessionID.is_nil()) { + header->setCookie(cgicc::HTTPCookie(SESSIONID, sessionID.str(), "Session ID", + _env->getServerName().substr(_env->getServerName().find(".")), 3600, "/", false)); + } + header->render(IO); + if (currentStage.get<2>()) { + TransformSourcePtr ts = currentStage.get<2>(); + std::fstream * ddd = NULL; + if (!_env->dumpdatadoc.empty()) { + ddd = new std::fstream(_env->dumpdatadoc.c_str(), std::fstream::trunc | std::fstream::out); + ts->addTarget(new ostreamWrapper(*ddd)); + } + ts->addTarget(new ostreamWrapper(IO)); + ts->doTransforms(); + if (ddd) { + delete ddd; + } } } @@ -115,18 +120,6 @@ CgiApplicationEngine::Stage::~Stage() { } -CgiApplicationEngine::HttpHeaderPtr -CgiApplicationEngine::Stage::getHeader() const -{ - return CgiApplicationEngine::HttpHeaderPtr(); -} - -CgiApplicationEngine::XmlDocPtr -CgiApplicationEngine::Stage::getDataDocument() const -{ - return XmlDocPtr(); -} - void CgiApplicationEngine::addEnvData(const Presenter * p) const { diff --git a/project2/cgi/cgiAppEngine.h b/project2/cgi/cgiAppEngine.h index 78f796f..e2ad1a2 100644 --- a/project2/cgi/cgiAppEngine.h +++ b/project2/cgi/cgiAppEngine.h @@ -4,11 +4,14 @@ #include "../appEngine.h" #include "../task.h" #include "../paramChecker.h" -#include "../xmlPresenter.h" #include "../commonObjects.h" #include "../uuid.h" -#include "../requestHost.h" +#include "../taskHost.h" +#include "../viewHost.h" +#include "../transform.h" +#include "../xmlPresenter.h" #include <boost/intrusive_ptr.hpp> +#include <boost/tuple/tuple.hpp> class CgiEnvironment; class Session; @@ -19,16 +22,15 @@ namespace xmlpp { class Document; } -class CgiApplicationEngine : public ApplicationEngine { +class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink { public: typedef boost::shared_ptr<xmlpp::Document> XmlDocPtr; typedef boost::shared_ptr<cgicc::HTTPHeader> HttpHeaderPtr; - CgiApplicationEngine(const CgiEnvironment *); + CgiApplicationEngine(const CgiEnvironment *, std::ostream &); virtual ~CgiApplicationEngine(); void process() const; - void write(std::ostream &) const; const Environment * env() const; SessionPtr session() const; virtual Glib::ustring resolveCurrentConfig() const; @@ -45,115 +47,103 @@ class CgiApplicationEngine : public ApplicationEngine { bool checkDomain(const DomainPlatforms::value_type & i) const; void loadEngineSection(const xmlpp::Element *) const; + public: class Stage; + class ResponseStage; typedef boost::intrusive_ptr<Stage> StagePtr; + typedef boost::intrusive_ptr<ResponseStage> ResponseStagePtr; + typedef boost::tuple<StagePtr, ResponseStagePtr, TransformSourcePtr, PresenterPtr> NextStage; /// Base class for a stage iteration that should eventually produce a response for the client - class Stage : public virtual CommonObjects { + class Stage : public virtual IntrusivePtrBase { public: Stage(const CgiEnvironment * e); virtual ~Stage() = 0; - virtual StagePtr run() = 0; - virtual XmlDocPtr getDataDocument() const; - virtual HttpHeaderPtr getHeader() const; + virtual NextStage run() = 0; protected: const CgiEnvironment * e; }; + /// Base class for a stage that can be a response to the client + class ResponseStage : public Stage { + public: + ResponseStage(const CgiEnvironment * e); + virtual HttpHeaderPtr getHeader() const = 0; + }; + /// Stage implementation used to bootstrap the iteration process based on the CGI environment class InitialStage : public Stage { public: InitialStage(const CgiEnvironment * e); - virtual StagePtr run(); + virtual NextStage run(); }; /// Stage to process POST requests - class RequestStage : public Stage, public XmlPresenter, RequestHost { + class RequestStage : public ResponseStage, TaskHost { public: RequestStage(const CgiEnvironment *, const std::string & id); - virtual StagePtr run(); - virtual XmlDocPtr getDataDocument() const; + virtual NextStage run(); virtual HttpHeaderPtr getHeader() const; - virtual const Glib::ustring & getResponseRootNodeName() const; - virtual const Glib::ustring & getResponseStyle() const; - protected: std::string present; - typedef Storage<ParamChecker>::Objects ParamCheckers; - ParamCheckers parameterChecks; - - private: - static const Glib::ustring resp; - static const Glib::ustring style; }; /// Stage to process GET requests and follow up RequestStages - class PresentStage : public virtual Stage, public XmlProcessPresenter { + class PresentStage : public virtual ResponseStage, ViewHost { public: PresentStage(const CgiEnvironment * e, const std::string & id); PresentStage(const CgiEnvironment * e, const std::string & group, const std::string & id); - virtual StagePtr run(); - virtual XmlDocPtr getDataDocument() const; + virtual NextStage run(); virtual HttpHeaderPtr getHeader() const; }; /// The built-in fail-safe not found stage - class DefaultNotFoundStage : public virtual Stage, public XmlPresenter { + class DefaultNotFoundStage : public virtual ResponseStage { public: DefaultNotFoundStage(const CgiEnvironment *, const XmlScriptParser::NotFound &); - virtual XmlDocPtr getDataDocument() const; + virtual NextStage run(); virtual HttpHeaderPtr getHeader() const; - virtual StagePtr run(); - virtual const Glib::ustring & getResponseRootNodeName() const; - virtual const Glib::ustring & getResponseStyle() const; private: - static const Glib::ustring resp; const XmlScriptParser::NotFound nf; + XmlPresenterPtr pres; }; /// Custom not found handling stage class CustomNotFoundStage : public DefaultNotFoundStage, public PresentStage { public: - CustomNotFoundStage(const CgiEnvironment *, const XmlScriptParser::NotFound &); - virtual StagePtr run(); - virtual XmlDocPtr getDataDocument() const; + CustomNotFoundStage(const CgiEnvironment *, const ::XmlScriptParser::NotFound &); + virtual NextStage run(); virtual HttpHeaderPtr getHeader() const; - virtual const Glib::ustring & getResponseRootNodeName() const; - virtual const Glib::ustring & getResponseStyle() const; }; /// The built-in fail-safe unhandled error stage - class DefaultErrorStage : public virtual Stage, public XmlPresenter { + class DefaultErrorStage : public virtual ResponseStage { public: DefaultErrorStage(const CgiEnvironment *, const std::exception &); ~DefaultErrorStage(); - virtual XmlDocPtr getDataDocument() const; + virtual NextStage run(); virtual HttpHeaderPtr getHeader() const; - virtual StagePtr run(); - virtual const Glib::ustring & getResponseRootNodeName() const; - virtual const Glib::ustring & getResponseStyle() const; private: - static const Glib::ustring resp; char * buf; std::string what; + XmlPresenterPtr pres; }; /// Custom unhandled error handling stage class CustomErrorStage : public DefaultErrorStage, public PresentStage { public: CustomErrorStage(const CgiEnvironment *, const std::exception &); - virtual StagePtr run(); - virtual XmlDocPtr getDataDocument() const; + virtual NextStage run(); virtual HttpHeaderPtr getHeader() const; - virtual const Glib::ustring & getResponseRootNodeName() const; - virtual const Glib::ustring & getResponseStyle() const; }; - mutable StagePtr currentStage; + private: + mutable NextStage currentStage; mutable UUID sessionID; + mutable std::ostream & IO; }; #endif diff --git a/project2/cgi/cgiCommon.cpp b/project2/cgi/cgiCommon.cpp index fa40d2b..b8a2b93 100644 --- a/project2/cgi/cgiCommon.cpp +++ b/project2/cgi/cgiCommon.cpp @@ -44,12 +44,10 @@ cgiServe(cgicc::CgiInput * i, std::ostream & IO) CgiEnvironment env(&cgi); env.init(); try { - CgiApplicationEngine app(&env); + CgiApplicationEngine app(&env, IO); Logger()->messagef(LOG_DEBUG, "%s: Processing request", __FUNCTION__); app.process(); - Logger()->messagef(LOG_DEBUG, "%s: Sending request result", __FUNCTION__); - app.write(IO); Logger()->messagef(LOG_DEBUG, "%s: Completed request", __FUNCTION__); } catch (const std::exception & e) { diff --git a/project2/cgi/cgiEnvironment.cpp b/project2/cgi/cgiEnvironment.cpp index e8d5ba3..2bc3b02 100644 --- a/project2/cgi/cgiEnvironment.cpp +++ b/project2/cgi/cgiEnvironment.cpp @@ -28,6 +28,8 @@ CgiEnvironment::addOptions(boost::program_options::positional_options_descriptio { boost::program_options::options_description cgi("Project2 CGI options"); cgi.add_options() + ("defaultpresenter", boost::program_options::value(&defaultPresenter)->default_value("xml"), + "The default engine for formatting presentations") ("defaultpresent", boost::program_options::value(&defaultPresent)->default_value("index"), "The present script to use when no other is specified") ("presentroot", boost::program_options::value(&presentRoot)->default_value("present"), @@ -44,10 +46,8 @@ CgiEnvironment::addOptions(boost::program_options::positional_options_descriptio "The present script to use when the requested script does not exist") ("onerrorpresent", boost::program_options::value(&onErrorPresent), "The present script to use when the requested script (or child) fails") -#ifndef NDEBUG ("dumpdatadoc", boost::program_options::value(&dumpdatadoc), "Write a copy of the data document before sending it to the web server") -#endif ; return cgi; } diff --git a/project2/cgi/cgiEnvironment.h b/project2/cgi/cgiEnvironment.h index ce765bf..abfe78e 100644 --- a/project2/cgi/cgiEnvironment.h +++ b/project2/cgi/cgiEnvironment.h @@ -27,9 +27,7 @@ class CgiEnvironment : public Environment, public cgicc::CgiEnvironment { boost::program_options::options_description addOptions(boost::program_options::positional_options_description &); void postinit(const boost::program_options::options_description &, const boost::program_options::variables_map &); public: -#ifndef NDEBUG std::string dumpdatadoc; -#endif Glib::ustring errorContentType; Glib::ustring errorTransformStyle; std::string defaultPresent; @@ -38,6 +36,7 @@ class CgiEnvironment : public Environment, public cgicc::CgiEnvironment { std::string errorPresentRoot; std::string notFoundPresent; std::string onErrorPresent; + std::string defaultPresenter; }; #endif diff --git a/project2/cgi/cgiStageCustomError.cpp b/project2/cgi/cgiStageCustomError.cpp index a3fbc1f..fb2f0de 100644 --- a/project2/cgi/cgiStageCustomError.cpp +++ b/project2/cgi/cgiStageCustomError.cpp @@ -4,7 +4,9 @@ #include "../logger.h" CgiApplicationEngine::CustomErrorStage::CustomErrorStage(const CgiEnvironment * env, const std::exception & ex) : - CgiApplicationEngine::Stage(env), + CgiApplicationEngine::ResponseStage(env), + ::XmlScriptParser(env->errorPresentRoot, env->onErrorPresent, false), + ::CheckHost(env->errorPresentRoot, env->onErrorPresent), CgiApplicationEngine::DefaultErrorStage(env, ex), CgiApplicationEngine::PresentStage(env, env->errorPresentRoot, env->onErrorPresent) { @@ -16,29 +18,10 @@ CgiApplicationEngine::CustomErrorStage::getHeader() const return CgiApplicationEngine::DefaultErrorStage::getHeader(); } -CgiApplicationEngine::StagePtr +CgiApplicationEngine::NextStage CgiApplicationEngine::CustomErrorStage::run() { CgiApplicationEngine::DefaultErrorStage::run(); return CgiApplicationEngine::PresentStage::run(); } -const Glib::ustring & -CgiApplicationEngine::CustomErrorStage::getResponseRootNodeName() const -{ - return CgiApplicationEngine::PresentStage::getResponseRootNodeName(); -} - -CgiApplicationEngine::XmlDocPtr -CgiApplicationEngine::CustomErrorStage::getDataDocument() const -{ - return CgiApplicationEngine::PresentStage::getDataDocument(); -} - -const Glib::ustring & -CgiApplicationEngine::CustomErrorStage::getResponseStyle() const -{ - return CgiApplicationEngine::PresentStage::getResponseStyle(); -} - - diff --git a/project2/cgi/cgiStageCustomNotFound.cpp b/project2/cgi/cgiStageCustomNotFound.cpp index a2d33dc..7c08a9f 100644 --- a/project2/cgi/cgiStageCustomNotFound.cpp +++ b/project2/cgi/cgiStageCustomNotFound.cpp @@ -3,8 +3,10 @@ #include "cgiHttpHeader.h" #include "../logger.h" -CgiApplicationEngine::CustomNotFoundStage::CustomNotFoundStage(const CgiEnvironment * env, const XmlScriptParser::NotFound & notfound) : - CgiApplicationEngine::Stage(env), +CgiApplicationEngine::CustomNotFoundStage::CustomNotFoundStage(const CgiEnvironment * env, const ::XmlScriptParser::NotFound & notfound) : + CgiApplicationEngine::ResponseStage(env), + ::XmlScriptParser(env->errorPresentRoot, env->notFoundPresent, false), + ::CheckHost(env->errorPresentRoot, env->notFoundPresent), CgiApplicationEngine::DefaultNotFoundStage(env, notfound), CgiApplicationEngine::PresentStage(env, env->errorPresentRoot, env->notFoundPresent) { @@ -16,28 +18,10 @@ CgiApplicationEngine::CustomNotFoundStage::getHeader() const return CgiApplicationEngine::DefaultNotFoundStage::getHeader(); } -CgiApplicationEngine::StagePtr +CgiApplicationEngine::NextStage CgiApplicationEngine::CustomNotFoundStage::run() { CgiApplicationEngine::DefaultNotFoundStage::run(); return CgiApplicationEngine::PresentStage::run(); } -const Glib::ustring & -CgiApplicationEngine::CustomNotFoundStage::getResponseRootNodeName() const -{ - return CgiApplicationEngine::PresentStage::getResponseRootNodeName(); -} - -CgiApplicationEngine::XmlDocPtr -CgiApplicationEngine::CustomNotFoundStage::getDataDocument() const -{ - return CgiApplicationEngine::PresentStage::getDataDocument(); -} - -const Glib::ustring & -CgiApplicationEngine::CustomNotFoundStage::getResponseStyle() const -{ - return CgiApplicationEngine::PresentStage::getResponseStyle(); -} - diff --git a/project2/cgi/cgiStageDefaultError.cpp b/project2/cgi/cgiStageDefaultError.cpp index c881da1..767a634 100644 --- a/project2/cgi/cgiStageDefaultError.cpp +++ b/project2/cgi/cgiStageDefaultError.cpp @@ -4,12 +4,13 @@ #include "cgiEnvironment.h" #include <cxxabi.h> -const Glib::ustring CgiApplicationEngine::DefaultErrorStage::resp("error"); +static const Glib::ustring DefaultErrorStageResp("error"); CgiApplicationEngine::DefaultErrorStage::DefaultErrorStage(const CgiEnvironment * env, const std::exception & ex) : - CgiApplicationEngine::Stage(env), + CgiApplicationEngine::ResponseStage(env), buf(__cxxabiv1::__cxa_demangle(typeid(ex).name(), NULL, NULL, NULL)), - what(ex.what()) + what(ex.what()), + pres(new XmlPresenter(DefaultErrorStageResp, e->errorTransformStyle, e->errorContentType)) { } @@ -21,32 +22,14 @@ CgiApplicationEngine::DefaultErrorStage::~DefaultErrorStage() CgiApplicationEngine::HttpHeaderPtr CgiApplicationEngine::DefaultErrorStage::getHeader() const { - return HttpHeaderPtr(new Project2HttpHeader("500 Internal Server Error", e->errorContentType)); + return HttpHeaderPtr(new Project2HttpHeader("500 Internal Server Error", pres->contentType)); } -CgiApplicationEngine::StagePtr +CgiApplicationEngine::NextStage CgiApplicationEngine::DefaultErrorStage::run() { - addField("error-type", e->getXmlPrefix(), buf); - addField("error-what", e->getXmlPrefix(), what.c_str()); - return NULL; -} - -const Glib::ustring & -CgiApplicationEngine::DefaultErrorStage::getResponseRootNodeName() const -{ - return resp; -} - -CgiApplicationEngine::XmlDocPtr -CgiApplicationEngine::DefaultErrorStage::getDataDocument() const -{ - return XmlPresenter::getDataDocument(); -} - -const Glib::ustring & -CgiApplicationEngine::DefaultErrorStage::getResponseStyle() const -{ - return e->errorTransformStyle; + pres->addField("error-type", e->getXmlPrefix(), buf); + pres->addField("error-what", e->getXmlPrefix(), what.c_str()); + return NextStage(NULL, this, pres.get(), pres.get()); } diff --git a/project2/cgi/cgiStageDefaultNotFound.cpp b/project2/cgi/cgiStageDefaultNotFound.cpp index f32ad1f..2e7acb1 100644 --- a/project2/cgi/cgiStageDefaultNotFound.cpp +++ b/project2/cgi/cgiStageDefaultNotFound.cpp @@ -3,9 +3,12 @@ #include "cgiHttpHeader.h" #include "../logger.h" +static const Glib::ustring DefaultNotFoundStageResp("notfound"); + CgiApplicationEngine::DefaultNotFoundStage::DefaultNotFoundStage(const CgiEnvironment * env, const XmlScriptParser::NotFound & notfound) : - CgiApplicationEngine::Stage(env), - nf(notfound) + CgiApplicationEngine::ResponseStage(env), + nf(notfound), + pres(new XmlPresenter(DefaultNotFoundStageResp, e->errorTransformStyle, e->errorContentType)) { Logger()->messagef(LOG_ERR, "%s: Resource not found: %s", __FUNCTION__, nf.what()); } @@ -13,32 +16,13 @@ CgiApplicationEngine::DefaultNotFoundStage::DefaultNotFoundStage(const CgiEnviro CgiApplicationEngine::HttpHeaderPtr CgiApplicationEngine::DefaultNotFoundStage::getHeader() const { - return HttpHeaderPtr(new Project2HttpHeader("404 Not found", e->errorContentType)); + return HttpHeaderPtr(new Project2HttpHeader("404 Not found", pres->contentType)); } -CgiApplicationEngine::StagePtr +CgiApplicationEngine::NextStage CgiApplicationEngine::DefaultNotFoundStage::run() { - addField("missing-resource", e->getXmlPrefix(), nf.what()); - return NULL; -} - -const Glib::ustring CgiApplicationEngine::DefaultNotFoundStage::resp("notfound"); -const Glib::ustring & -CgiApplicationEngine::DefaultNotFoundStage::getResponseRootNodeName() const -{ - return resp; -} - -CgiApplicationEngine::XmlDocPtr -CgiApplicationEngine::DefaultNotFoundStage::getDataDocument() const -{ - return XmlPresenter::getDataDocument(); -} - -const Glib::ustring & -CgiApplicationEngine::DefaultNotFoundStage::getResponseStyle() const -{ - return e->errorTransformStyle; + pres->addField("missing-resource", e->getXmlPrefix(), nf.what()); + return NextStage(NULL, this, pres.get(), pres.get()); } diff --git a/project2/cgi/cgiStageInitial.cpp b/project2/cgi/cgiStageInitial.cpp index d302971..1db8f8f 100644 --- a/project2/cgi/cgiStageInitial.cpp +++ b/project2/cgi/cgiStageInitial.cpp @@ -9,17 +9,17 @@ CgiApplicationEngine::InitialStage::InitialStage(const CgiEnvironment * env) : { } -CgiApplicationEngine::StagePtr +CgiApplicationEngine::NextStage CgiApplicationEngine::InitialStage::run() { if (e->getRequestMethod() == "POST") { if (e->elems.empty()) { throw EmptyRequestURL(); } - return new RequestStage(e, e->elems[0]); + return NextStage(new RequestStage(e, e->elems[0])); } else { - return new PresentStage(e, e->elems.empty() ? e->defaultPresent : e->elems[0]); + return NextStage(new PresentStage(e, e->elems.empty() ? e->defaultPresent : e->elems[0])); } } diff --git a/project2/cgi/cgiStagePresent.cpp b/project2/cgi/cgiStagePresent.cpp index 47db567..aaa1092 100644 --- a/project2/cgi/cgiStagePresent.cpp +++ b/project2/cgi/cgiStagePresent.cpp @@ -2,44 +2,45 @@ #include "cgiEnvironment.h" #include "cgiHttpHeader.h" #include <boost/foreach.hpp> +#include <boost/bind.hpp> CgiApplicationEngine::PresentStage::PresentStage(const CgiEnvironment * e, const std::string & id) : - CgiApplicationEngine::Stage(e), - XmlProcessPresenter(e->presentRoot, id, false) + CgiApplicationEngine::ResponseStage(e), + XmlScriptParser(e->presentRoot, id, false), + CheckHost(e->presentRoot, id), + ViewHost(e->presentRoot, id) { + parseDocument(); } CgiApplicationEngine::PresentStage::PresentStage(const CgiEnvironment * e, const std::string & group, const std::string & id) : - CgiApplicationEngine::Stage(e), - XmlProcessPresenter(group, id, false) + CgiApplicationEngine::ResponseStage(e), + XmlScriptParser(group, id, false), + CheckHost(group, id), + ViewHost(group, id) { + parseDocument(); } -CgiApplicationEngine::StagePtr +CgiApplicationEngine::NextStage CgiApplicationEngine::PresentStage::run() { - BOOST_FOREACH(ParamCheckers::value_type pc, parameterChecks.get<bySOOrder>()) { - if (!pc->performCheck()) { - ApplicationEngine::getCurrent()->logMessage(false, pc->group(), pc->message()); - return new PresentStage(e, pc->present); - } - } - execute(); - return NULL; + runChecks(); + executeViews(boost::bind(&PresenterLoader::createFrom, LoaderBase::getLoader<PresenterLoader, NotSupported>(e->defaultPresenter), _1)); + return NextStage(NULL, this, boost::dynamic_pointer_cast<TransformSource>(headPresenter()), headPresenter()); +} + +CgiApplicationEngine::ResponseStage::ResponseStage(const CgiEnvironment * e) : + CgiApplicationEngine::Stage(e) +{ } CgiApplicationEngine::HttpHeaderPtr CgiApplicationEngine::PresentStage::getHeader() const { - Project2HttpHeader * header = new Project2HttpHeader("200 OK", contentType); + ContentPresenter * cp = boost::dynamic_pointer_cast<ContentPresenter>(headPresenter()).get(); + Project2HttpHeader * header = new Project2HttpHeader("200 OK", cp ? cp->contentType : "text/plain"); header->addHeader("Cache-control", "no-cache"); return HttpHeaderPtr(header); } -CgiApplicationEngine::XmlDocPtr -CgiApplicationEngine::PresentStage::getDataDocument() const -{ - return XmlProcessPresenter::getDataDocument(); -} - - diff --git a/project2/cgi/cgiStageRequest.cpp b/project2/cgi/cgiStageRequest.cpp index 22cb2e8..94f3b49 100644 --- a/project2/cgi/cgiStageRequest.cpp +++ b/project2/cgi/cgiStageRequest.cpp @@ -5,57 +5,32 @@ #include <boost/foreach.hpp> CgiApplicationEngine::RequestStage::RequestStage(const CgiEnvironment * e, const std::string & id) : - CgiApplicationEngine::Stage(e) + XmlScriptParser(e->requestRoot, id, false), + ::CheckHost(e->requestRoot, id), + CgiApplicationEngine::ResponseStage(e), + ::TaskHost(e->requestRoot, id) { - XmlScriptParser request(e->requestRoot, id, false); - xmlpp::Element * requestRoot = request.get_document()->get_root_node(); + xmlpp::Element * requestRoot = get_document()->get_root_node(); present = requestRoot->get_attribute_value("present"); rollbackBeforeHandle = requestRoot->get_attribute_value("rollbackBeforeHandle") == "true"; localErrorHandling = requestRoot->get_attribute_value("errorHandling") == "local"; - - LoaderBase loader(true); - loader.supportedStorers.insert(Storer::into(¶meterChecks)); - loader.supportedStorers.insert(Storer::into(&rowSets)); - loader.supportedStorers.insert(new NOEErrorStorer(&normTasks, &errorTasks)); - loader.collectAll(this, requestRoot, true); + parseDocument(); } -CgiApplicationEngine::StagePtr +CgiApplicationEngine::NextStage CgiApplicationEngine::RequestStage::run() { - BOOST_FOREACH(const ParamCheckers::value_type & pc, parameterChecks.get<bySOOrder>()) { - if (!pc->performCheck()) { - ApplicationEngine::getCurrent()->logMessage(false, pc->group(), pc->message()); - return new PresentStage(e, pc->present); - } - } - RequestHost::run(); - return present.empty() ? NULL : new PresentStage(e, present); + runChecks(); + executeTasks(); + return NextStage(present.empty() ? NULL : new PresentStage(e, present), this); } +const std::string contentType = "text/plain"; CgiApplicationEngine::HttpHeaderPtr CgiApplicationEngine::RequestStage::getHeader() const { - return HttpHeaderPtr(new Project2HttpHeader("200 OK", "text/xml")); -} - -CgiApplicationEngine::XmlDocPtr -CgiApplicationEngine::RequestStage::getDataDocument() const -{ - return XmlPresenter::getDataDocument(); -} - -const Glib::ustring CgiApplicationEngine::RequestStage::resp("request"); -const Glib::ustring CgiApplicationEngine::RequestStage::style; -const Glib::ustring & -CgiApplicationEngine::RequestStage::getResponseRootNodeName() const -{ - return resp; + Project2HttpHeader * header = new Project2HttpHeader("200 OK", contentType); + header->addHeader("Cache-control", "no-cache"); + return HttpHeaderPtr(header); } -const Glib::ustring & -CgiApplicationEngine::RequestStage::getResponseStyle() const -{ - return style; -} - diff --git a/project2/cgi/testCgi.cpp b/project2/cgi/testCgi.cpp new file mode 100644 index 0000000..438e1b0 --- /dev/null +++ b/project2/cgi/testCgi.cpp @@ -0,0 +1,70 @@ +#include <iostream> +#include <boost/program_options.hpp> +#include <boost/filesystem/convenience.hpp> +#include "cgiCommon.h" + +namespace po = boost::program_options; + +class TestInput : public cgicc::CgiInput { + public: + TestInput(int argc, char ** argv) + { + po::options_description test("Project2 CGI test options"); + test.add_options() + ("help,h", "Print usage and exit") + ("SERVER_NAME", "FQDN of web service") + ("SERVER_SOFTWARE", po::value<std::string>()->default_value("Apache"), "") + ("GATEWAY_INTERFACE", po::value<std::string>()->default_value("CGI/1.1"), "") + ("SERVER_PROTOCOL", po::value<std::string>()->default_value("HTTP/1.1"), "") + ("SERVER_PORT", po::value<std::string>()->default_value("80"), "") + ("REQUEST_METHOD", po::value<std::string>()->default_value("GET"), "") + ("PATH_INFO", "") + ("PATH_TRANSLATED", "") + ("SCRIPT_NAME", po::value<std::string>()->default_value("p2fcgi"), "") + ("QUERY_STRING", "") + ("REMOTE_HOST", "") + ("REMOTE_ADDR", "") + ("AUTH_TYPE", "") + ("REMOTE_USER", "") + ("REMOTE_IDENT", "") + ("CONTENT_TYPE", "") + ("CONTENT_LENGTH", "") + ("HTTP_ACCEPT", po::value<std::string>()->default_value("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"), "") + ("HTTP_USER_AGENT", po::value<std::string>()->default_value("Mozilla/5.0"), "") + ("REDIRECT_REQUEST", "") + ("REDIRECT_URL", "") + ("REDIRECT_STATUS", "") + ("HTTP_REFERER", "") + ("HTTP_COOKIE", "") + ("HTTPS", po::value<std::string>()->default_value("No"), "") + ; + po::parsed_options parsed = po::command_line_parser(argc, argv).options(test).allow_unregistered().run(); + po::store(parsed, settings); + if (boost::filesystem::exists("testCgi.settings")) { + std::ifstream f("testCgi.settings"); + po::store(po::parse_config_file(f, test, true), settings); + } + po::notify(settings); + if (settings.count("help")) { + std::cout << test; + exit(1); + } + } + virtual std::string getenv(const char *varName) + { + if (settings.count(varName)) { + return settings[varName].as<std::string>(); + } + return ""; + } + private: + po::variables_map settings; +}; + +int +main(int argc, char ** argv) +{ + TestInput ti(argc, argv); + cgiServe(&ti, std::cout); +} + |