diff options
author | randomdan <randomdan@localhost> | 2011-09-06 14:06:44 +0000 |
---|---|---|
committer | randomdan <randomdan@localhost> | 2011-09-06 14:06:44 +0000 |
commit | 55c3def82c32eaebb0feadebbcadd986d8f51941 (patch) | |
tree | b55b4edeac7882b419344b1845e8338b8df947e1 | |
parent | Minor shuffle (diff) | |
download | project2-55c3def82c32eaebb0feadebbcadd986d8f51941.tar.bz2 project2-55c3def82c32eaebb0feadebbcadd986d8f51941.tar.xz project2-55c3def82c32eaebb0feadebbcadd986d8f51941.zip |
More flexible Curl helpers with boost::bind
Remove lots of duplicate code with safeMapFind
Rework the session code into something slightly more sensible
Add a doobry for forcing a CGI error
-rw-r--r-- | project2/cgi/cgiAppEngine.cpp | 43 | ||||
-rw-r--r-- | project2/cgi/cgiAppEngine.h | 2 | ||||
-rw-r--r-- | project2/cgi/cgiStageFail.cpp | 52 | ||||
-rw-r--r-- | project2/common/commonObjects.cpp | 13 | ||||
-rw-r--r-- | project2/common/config.cpp | 13 | ||||
-rw-r--r-- | project2/common/iHaveParameters.cpp | 7 | ||||
-rw-r--r-- | project2/common/session.cpp | 3 | ||||
-rw-r--r-- | project2/common/session.h | 7 | ||||
-rw-r--r-- | project2/common/sessionContainer.cpp | 2 | ||||
-rw-r--r-- | project2/common/sessionContainer.h | 5 | ||||
-rw-r--r-- | project2/console/consoleAppEngine.cpp | 17 | ||||
-rw-r--r-- | project2/url/curlHelper.cpp | 74 | ||||
-rw-r--r-- | project2/url/curlHelper.h | 36 | ||||
-rw-r--r-- | project2/url/urlRows.cpp | 29 | ||||
-rw-r--r-- | project2/url/urlRows.h | 11 | ||||
-rw-r--r-- | project2/xml/sessionXml.cpp | 110 | ||||
-rw-r--r-- | project2/xml/sessionXml.h | 5 | ||||
-rw-r--r-- | project2/xml/xslPreFetch.cpp | 4 | ||||
-rw-r--r-- | project2/xml/xslPreFetch.h | 4 | ||||
-rw-r--r-- | project2/xml/xslRows.cpp | 4 | ||||
-rw-r--r-- | project2/xml/xslRows.h | 4 | ||||
-rw-r--r-- | project2/xml/xslRowsCache.cpp | 31 | ||||
-rw-r--r-- | project2/xml/xslRowsCache.h | 5 |
23 files changed, 284 insertions, 197 deletions
diff --git a/project2/cgi/cgiAppEngine.cpp b/project2/cgi/cgiAppEngine.cpp index 2c4feb0..877f9a6 100644 --- a/project2/cgi/cgiAppEngine.cpp +++ b/project2/cgi/cgiAppEngine.cpp @@ -17,17 +17,23 @@ typedef std::string SValue; SimpleMessageException(UnknownDomain); +static UUID +getSessionID(const std::vector<cgicc::HTTPCookie> & cookies) { + BOOST_FOREACH(const cgicc::HTTPCookie & c, cookies) { + if (c.getName() == SESSIONID) { + return c.getValue(); + } + } + return UUID(); +} CgiApplicationEngine::CgiApplicationEngine(const CgiEnvironment * e, std::ostream & io) : ApplicationEngine("web/host"), _env(e), sessionsContainer(LoaderBase::getLoader<SessionContainerLoader, NotSupported>(e->sessionModule)->open()), IO(io) { - BOOST_FOREACH(const cgicc::HTTPCookie c, e->getCookieList()) { - if (c.getName() == SESSIONID) { - sessionID = c.getValue(); - } - } + UUID sessID = getSessionID(e->getCookieList()); + cursession = sessionsContainer->GetSession(sessID); currentStage = NextStage(new InitialStage(e)); } @@ -80,10 +86,8 @@ CgiApplicationEngine::process() const 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(".")), env()->sessionTimeOut, "/", false)); - } + header->setCookie(cgicc::HTTPCookie(SESSIONID, cursession->ID.str(), "Session ID", + _env->getServerName().substr(_env->getServerName().find(".")), env()->sessionTimeOut, "/", false)); header->render(IO); if (currentStage.get<2>()) { TransformSourcePtr ts = currentStage.get<2>(); @@ -98,6 +102,7 @@ CgiApplicationEngine::process() const delete ddd; } } + sessionsContainer->SaveSession(cursession); } CgiApplicationEngine::Stage::Stage(const CgiEnvironment * env) : @@ -139,18 +144,16 @@ CgiApplicationEngine::addAppData(const Presenter * p) const { addCoreAppData(p); // Sessions variables - if (!sessionID.is_nil()) { - p->pushSub("session", env()->xmlPrefix); - p->addField("id", sessionID.str()); - Session::Values session(sessionsContainer->GetSession(sessionID)->GetValuesCopy()); - BOOST_FOREACH(Session::Values::value_type sv, session) { - p->pushSub("var", env()->xmlPrefix); - p->addAttr("value", sv.second); - p->addAttr("name", sv.first); - p->popSub(); - } + p->pushSub("session", env()->xmlPrefix); + p->addField("id", cursession->ID.str()); + Session::Values session(cursession->GetValuesCopy()); + BOOST_FOREACH(Session::Values::value_type sv, session) { + p->pushSub("var", env()->xmlPrefix); + p->addAttr("value", sv.second); + p->addAttr("name", sv.first); p->popSub(); } + p->popSub(); // Timing info p->pushSub("timing", env()->xmlPrefix); @@ -165,7 +168,7 @@ CgiApplicationEngine::addAppData(const Presenter * p) const SessionPtr CgiApplicationEngine::session() const { - return sessionsContainer->GetSession(sessionID); + return cursession; } bool diff --git a/project2/cgi/cgiAppEngine.h b/project2/cgi/cgiAppEngine.h index 0f534e8..6e202e4 100644 --- a/project2/cgi/cgiAppEngine.h +++ b/project2/cgi/cgiAppEngine.h @@ -143,7 +143,7 @@ class CgiApplicationEngine : public ApplicationEngine, public TransformChainLink private: mutable NextStage currentStage; - mutable UUID sessionID; + SessionPtr cursession; mutable std::ostream & IO; }; diff --git a/project2/cgi/cgiStageFail.cpp b/project2/cgi/cgiStageFail.cpp new file mode 100644 index 0000000..04e131b --- /dev/null +++ b/project2/cgi/cgiStageFail.cpp @@ -0,0 +1,52 @@ +#include <pch.hpp> +#include "cgiAppEngine.h" +#include "cgiEnvironment.h" +#include "cgiHttpHeader.h" +#include "logger.h" + +namespace CgiApplicationExtras { + class FailStage : public CgiApplicationEngine::ResponseStage { + public: + FailStage(const CgiEnvironment * env, int c, const std::string & m) : + ResponseStage(env), + code(c), + message(m) { + } + + CgiApplicationEngine::HttpHeaderPtr getHeader() const + { + Project2HttpHeader * header = new Project2HttpHeader(boost::lexical_cast<std::string>(code) + " " + message); + return CgiApplicationEngine::HttpHeaderPtr(header); + } + + CgiApplicationEngine::NextStage run() + { + return CgiApplicationEngine::NextStage(NULL, this, NULL, NULL); + } + private: + const int code; + const std::string message; + }; + + class CgiFail : public View { + public: + CgiFail(const xmlpp::Element * e) : + SourceObject(e), + View(e), + code(e, "code", false, 500), + message(e, "message", false, "Application error") { + } + void loadComplete(const CommonObjects *) { + } + void execute(const Presenter *) const { + throw CgiApplicationEngine::ResponseStagePtr( + new FailStage(dynamic_cast<const CgiEnvironment *>(Environment::getCurrent()), code(), message())); + } + private: + Variable code, message; + }; +} + +typedef CgiApplicationExtras::CgiFail cgif; +DECLARE_LOADER("cgifail", cgif); + diff --git a/project2/common/commonObjects.cpp b/project2/common/commonObjects.cpp index f398e07..2ffa353 100644 --- a/project2/common/commonObjects.cpp +++ b/project2/common/commonObjects.cpp @@ -1,5 +1,6 @@ #include <pch.hpp> #include "commonObjects.h" +#include "safeMapFind.h" #include "appEngine.h" #include "xmlObjectLoader.h" #include "xmlScriptParser.h" @@ -11,11 +12,7 @@ CommonObjects::~CommonObjects() RowSetPtr CommonObjects::getSource(const std::string & name) const { - RowSets::const_iterator i = rowSets.find(name); - if (i != rowSets.end()) { - return i->second; - } - throw CommonObjects::DataSourceNotFound(name); + return safeMapFind<DataSourceNotFound>(rowSets, name)->second; } CommonObjects::DataSources::const_iterator @@ -28,10 +25,6 @@ CommonObjects::loadDataSource(const std::string & name) const loader.supportedStorers.insert(Storer::into(&datasources)); loader.collectAll(xml.get_document()->get_root_node(), false); - DataSources::const_iterator i = datasources.find(name); - if (i == datasources.end()) { - throw DataSourceNotFound(name); - } - return i; + return safeMapFind<DataSourceNotFound>(datasources, name); } diff --git a/project2/common/config.cpp b/project2/common/config.cpp index adeacf2..6f5b243 100644 --- a/project2/common/config.cpp +++ b/project2/common/config.cpp @@ -1,5 +1,6 @@ #include <pch.hpp> #include "config.h" +#include "safeMapFind.h" #include "exceptions.h" #include <boost/filesystem/operations.hpp> #include <boost/foreach.hpp> @@ -50,21 +51,13 @@ Configuration::getCurrentConfig() const { load(); Glib::ustring platformName(resolveCurrentConfig()); - Platforms::const_iterator i = platforms.find(platformName); - if (i == platforms.end()) { - throw NoSuchPlatform(platformName); - } - return i->second; + return safeMapFind<NoSuchPlatform>(platforms, platformName)->second; } const Glib::ustring & Configuration::Platform::getValue(const Glib::ustring & key) const { - Values::const_iterator i = values.find(key); - if (i == values.end()) { - throw NoSuchConfigurationValue(key); - } - return i->second; + return safeMapFind<NoSuchConfigurationValue>(values, key)->second; } Configuration::Platform::Platform(const xmlpp::Element * e) diff --git a/project2/common/iHaveParameters.cpp b/project2/common/iHaveParameters.cpp index d3f9776..7d750b3 100644 --- a/project2/common/iHaveParameters.cpp +++ b/project2/common/iHaveParameters.cpp @@ -1,6 +1,7 @@ #include <pch.hpp> #include "iHaveParameters.h" #include "exceptions.h" +#include "safeMapFind.h" #include "appEngine.h" #include <boost/foreach.hpp> @@ -22,11 +23,7 @@ IHaveParameters::~IHaveParameters() VariableType IHaveParameters::getParameter(const Glib::ustring & name) const { - Parameters::const_iterator i = parameters.find(name); - if (i != parameters.end()) { - return i->second; - } - throw ParamNotFound(name); + return safeMapFind<ParamNotFound>(parameters, name)->second; } void diff --git a/project2/common/session.cpp b/project2/common/session.cpp index 548fa4f..d796f83 100644 --- a/project2/common/session.cpp +++ b/project2/common/session.cpp @@ -1,7 +1,8 @@ #include <pch.hpp> #include "session.h" -Session::Session() +Session::Session(const UUID & sid) : + ID(sid) { } diff --git a/project2/common/session.h b/project2/common/session.h index 7b66db9..ea72c54 100644 --- a/project2/common/session.h +++ b/project2/common/session.h @@ -1,6 +1,7 @@ #ifndef SESSION_H #define SESSION_H +#include <uuid.h> #include <map> #include <glibmm/ustring.h> #include <boost/intrusive_ptr.hpp> @@ -14,15 +15,17 @@ class Session : public virtual IntrusivePtrBase { SimpleMessageException(VariableNotFound); typedef std::map<Glib::ustring, VariableType> Values; - Session(); + Session(const UUID & id); virtual ~Session() = 0; - virtual const VariableType & GetValue(const Glib::ustring & name) const = 0; + virtual VariableType GetValue(const Glib::ustring & name) const = 0; virtual Values GetValuesCopy() const = 0; virtual void SetValue(const Glib::ustring & name, const VariableType & value) = 0; virtual void ClearValue(const Glib::ustring & name) = 0; virtual time_t ExpiryTime() const = 0; + const UUID ID; + protected: virtual void ExpiryTime(time_t) = 0; friend class SessionContainer; diff --git a/project2/common/sessionContainer.cpp b/project2/common/sessionContainer.cpp index 15e8d47..87c5729 100644 --- a/project2/common/sessionContainer.cpp +++ b/project2/common/sessionContainer.cpp @@ -11,7 +11,7 @@ SessionContainer::~SessionContainer() } SessionPtr -SessionContainer::GetSession(UUID & id) +SessionContainer::GetSession(UUID & id) const { SessionPtr s = getSession(id); s->ExpiryTime(time(NULL) + Environment::getCurrent()->sessionTimeOut); diff --git a/project2/common/sessionContainer.h b/project2/common/sessionContainer.h index fcad4b9..9f1851a 100644 --- a/project2/common/sessionContainer.h +++ b/project2/common/sessionContainer.h @@ -10,10 +10,11 @@ class SessionContainer : public IntrusivePtrBase { SessionContainer(); virtual ~SessionContainer() = 0; - SessionPtr GetSession(UUID & sid); + SessionPtr GetSession(UUID & sid) const; + virtual void SaveSession(SessionPtr sess) const = 0; protected: - virtual SessionPtr getSession(UUID & sid) = 0; + virtual SessionPtr getSession(UUID & sid) const = 0; }; typedef boost::intrusive_ptr<SessionContainer> SessionContainerPtr; diff --git a/project2/console/consoleAppEngine.cpp b/project2/console/consoleAppEngine.cpp index c5b9e3f..f2dcaa8 100644 --- a/project2/console/consoleAppEngine.cpp +++ b/project2/console/consoleAppEngine.cpp @@ -1,6 +1,7 @@ #include <pch.hpp> #include "consoleAppEngine.h" #include "consoleEnvironment.h" +#include "safeMapFind.h" #include "iterate.h" #include "xmlObjectLoader.h" #include <boost/foreach.hpp> @@ -12,20 +13,16 @@ SimpleMessageException(UnknownPlatformAlias); /// Session implementation that stores its contents locally in memory, it has no long term persistence class ConsoleSession : public Session { public: - ConsoleSession() : expiry(0) + ConsoleSession() : Session(UUID::generate_random()), expiry(0) { } virtual ~ConsoleSession() { } - virtual const VariableType & GetValue(const Glib::ustring & name) const + virtual VariableType GetValue(const Glib::ustring & name) const { - Values::const_iterator i = vars.find(name); - if (i == vars.end()) { - throw Session::VariableNotFound(name); - } - return i->second; + return safeMapFind<VariableNotFound>(vars, name)->second; } virtual Values GetValuesCopy() const { @@ -110,11 +107,7 @@ ConsoleApplicationEngine::addAppData(const Presenter *) const Glib::ustring ConsoleApplicationEngine::resolveCurrentConfig() const { - ConsolePlatforms::const_iterator i = conplat.find(_env->getPlatform()); - if (i != conplat.end()) { - return i->second; - } - throw UnknownPlatformAlias(_env->getPlatform()); + return safeMapFind<UnknownPlatformAlias>(conplat, _env->getPlatform())->second; } void diff --git a/project2/url/curlHelper.cpp b/project2/url/curlHelper.cpp index bec779e..1b98d3b 100644 --- a/project2/url/curlHelper.cpp +++ b/project2/url/curlHelper.cpp @@ -1,6 +1,6 @@ #include "curlHelper.h" -CurlHelper::CurlHelper(const xmlpp::Element * p) : +VariableCurlHelper::VariableCurlHelper(const xmlpp::Element * p) : url(p, "url"), userAgent(p, "useragent", false, "project2/0.3"), cookieJar(p, "cookiejar", false), @@ -13,17 +13,45 @@ CurlHelper::CurlHelper(const xmlpp::Element * p) : { } +VariableCurlHelper::~VariableCurlHelper() +{ +} + +CurlHelper::CurlHelper() +{ +} + CurlHelper::~CurlHelper() { } -CurlHandle::Ptr +size_t +Curl::curlReadHelperHandle(const char * ptr, size_t size, size_t nmemb, void *stream) +{ + return (*static_cast<const Curl::ReadHandler *>(stream))(ptr, size * nmemb); +} + +size_t +Curl::curlSendHelperHandle(char * ptr, size_t size, size_t nmemb, void *stream) +{ + return (*static_cast<const Curl::SendHandler *>(stream))(ptr, size * nmemb); +} + +CurlPtr CurlHelper::newCurl() const { - CurlHandle::Ptr c = new CurlHandle(); + CurlPtr c = new Curl(); c->setopt(CURLOPT_FOLLOWLOCATION, 1); c->setopt(CURLOPT_ENCODING, "deflate, gzip"); - setopt_s(c, CURLOPT_URL, url()); + c->setopt(CURLOPT_URL, getUrl().c_str()); + c->setopt(CURLOPT_FAILONERROR, 1); + return c; +} + +CurlPtr +VariableCurlHelper::newCurl() const +{ + CurlPtr c = CurlHelper::newCurl(); setopt_s(c, CURLOPT_USERAGENT, userAgent()); setopt_s(c, CURLOPT_PROXY, proxy()); setopt_s(c, CURLOPT_REFERER, referer()); @@ -34,14 +62,48 @@ CurlHelper::newCurl() const } void -CurlHelper::setopt_s(CurlHandle::Ptr c, CURLoption o, const char * v) +Curl::performRead(const ReadHandler & h) +{ + setReadHandler(h); + CurlHandle::perform(); +} + +void +Curl::setReadHandler(const ReadHandler & h) +{ + setopt(CURLOPT_WRITEDATA, &h); + setopt(CURLOPT_WRITEFUNCTION, &curlReadHelperHandle); +} + +void +Curl::performSend(const SendHandler & h) +{ + setSendHandler(h); + CurlHandle::perform(); +} + +void +Curl::setSendHandler(const SendHandler & h) +{ + setopt(CURLOPT_READDATA, &h); + setopt(CURLOPT_READFUNCTION, &curlSendHelperHandle); +} + +void +VariableCurlHelper::setopt_s(CurlPtr c, CURLoption o, const char * v) { c->setopt(o, v); } void -CurlHelper::setopt_l(CurlHandle::Ptr c, CURLoption o, int64_t v) +VariableCurlHelper::setopt_l(CurlPtr c, CURLoption o, int64_t v) { c->setopt(o, (long)v); } +std::string +VariableCurlHelper::getUrl() const +{ + return url(); +} + diff --git a/project2/url/curlHelper.h b/project2/url/curlHelper.h index 111823f..28395e5 100644 --- a/project2/url/curlHelper.h +++ b/project2/url/curlHelper.h @@ -5,20 +5,48 @@ #include "variables.h" #include "../libmisc/curlsup.h" +class Curl : public CurlHandle { + public: + typedef boost::function2<size_t, const char *, size_t> ReadHandler; + typedef boost::function2<size_t, char *, size_t> SendHandler; + void performRead(const ReadHandler &); + void setReadHandler(const ReadHandler &); + void performSend(const SendHandler &); + void setSendHandler(const SendHandler &); + + private: + static size_t curlReadHelperHandle(const char * ptr, size_t size, size_t nmemb, void *stream); + static size_t curlSendHelperHandle(char * ptr, size_t size, size_t nmemb, void *stream); +}; +typedef boost::intrusive_ptr<Curl> CurlPtr; + /// Project2 helper component to provide common access to remote resources via libcurl class CurlHelper { public: - CurlHelper(const xmlpp::Element * p); + CurlHelper(); ~CurlHelper(); + virtual CurlPtr newCurl() const; + + protected: + virtual std::string getUrl() const = 0; +}; + +/// Project2 helper component to configure CurlHelper from variables +class VariableCurlHelper : public CurlHelper { + public: + VariableCurlHelper(const xmlpp::Element * p); + ~VariableCurlHelper(); + const Variable url; protected: - CurlHandle::Ptr newCurl() const; + virtual CurlPtr newCurl() const; + virtual std::string getUrl() const; private: - static void setopt_s(CurlHandle::Ptr, CURLoption, const char *); - static void setopt_l(CurlHandle::Ptr, CURLoption, int64_t); + static void setopt_s(CurlPtr, CURLoption, const char *); + static void setopt_l(CurlPtr, CURLoption, int64_t); const Variable userAgent; const Variable cookieJar; diff --git a/project2/url/urlRows.cpp b/project2/url/urlRows.cpp index f8f7eed..cfacea4 100644 --- a/project2/url/urlRows.cpp +++ b/project2/url/urlRows.cpp @@ -10,7 +10,7 @@ DECLARE_LOADER("urlrows", UrlRows); UrlRows::UrlRows(const xmlpp::Element * p) : StreamRows(p), - CurlHelper(p), + VariableCurlHelper(p), convertRequired(encoding != "utf-8") { } @@ -25,20 +25,12 @@ UrlRows::loadComplete(const CommonObjects *) } size_t -UrlRows::handleDataHelper(const char * ptr, size_t size, size_t nmemb, void *stream) -{ - const callback * cb = static_cast<const callback *>(stream); - size_t used = cb->urlRows->handleData(cb->ps, ptr, size * nmemb); - return used; -} - -size_t -UrlRows::handleData(ParseState & ps, const char * bytes, size_t bytesLen) const +UrlRows::handleData(ParseState * ps, const char * bytes, size_t bytesLen) const { size_t used = 0, len = 0; const gchar * utf8 = convertRequired ? g_convert(bytes, bytesLen, "utf-8", encoding.c_str(), &used, &len, NULL) : bytes; for (const gchar * iter = utf8; *iter; iter = g_utf8_next_char(iter)) { - this->pushChar(*iter, ps); + this->pushChar(*iter, *ps); } if (convertRequired) { // We allocated it.. sooo.... @@ -53,17 +45,8 @@ UrlRows::handleData(ParseState & ps, const char * bytes, size_t bytesLen) const void UrlRows::execute(const Glib::ustring &, const RowProcessor * rp) const { - CurlHandle::Ptr c = newCurl(); - callback cb(this, rp); - c->setopt(CURLOPT_WRITEDATA, &cb); - c->setopt(CURLOPT_WRITEFUNCTION, &handleDataHelper); - c->perform(); -} - -UrlRows::callback::callback(const UrlRows * u, const RowProcessor * r) : - urlRows(u), - rp(r), - ps(u, r) -{ + ParseState ps(this, rp); + CurlPtr c = newCurl(); + c->performRead(boost::bind(&UrlRows::handleData, this, &ps, _1, _2)); } diff --git a/project2/url/urlRows.h b/project2/url/urlRows.h index 98273bd..cd209c8 100644 --- a/project2/url/urlRows.h +++ b/project2/url/urlRows.h @@ -9,7 +9,7 @@ #include "curlHelper.h" /// Project2 component to create a row set from the contents of a file accessible via libcurl -class UrlRows : public StreamRows, CurlHelper { +class UrlRows : public StreamRows, VariableCurlHelper { public: UrlRows(const xmlpp::Element * p); ~UrlRows(); @@ -18,15 +18,8 @@ class UrlRows : public StreamRows, CurlHelper { void execute(const Glib::ustring &, const RowProcessor *) const; private: - struct callback { - callback(const UrlRows * urlRows, const RowProcessor * rp); - const UrlRows * urlRows; - const RowProcessor * rp; - mutable ParseState ps; - }; - static size_t handleDataHelper(const char * ptr, size_t size, size_t nmemb, void * stream); - size_t handleData(ParseState &, const char * bytes, size_t bytesLen) const; bool convertRequired; + size_t handleData(ParseState * ps, const char * bytes, size_t bytesLen) const; }; diff --git a/project2/xml/sessionXml.cpp b/project2/xml/sessionXml.cpp index dd4e01c..b363f65 100644 --- a/project2/xml/sessionXml.cpp +++ b/project2/xml/sessionXml.cpp @@ -17,15 +17,13 @@ class SessionXml : public Session { SessionXml(const xmlpp::Element *); virtual ~SessionXml(); - const VariableType & GetValue(const Glib::ustring & name) const; + VariableType GetValue(const Glib::ustring & name) const; Values GetValuesCopy() const; void SetValue(const Glib::ustring & name, const VariableType & value); void ClearValue(const Glib::ustring & name); time_t ExpiryTime() const; void ExpiryTime(time_t); - const UUID sessionID; - private: Values vars; time_t expires; @@ -63,71 +61,71 @@ SessionContainerXml::SessionContainerXml() SessionContainerXml::~SessionContainerXml() { - if (currentSession) { - xmlpp::DomParser parser; - xmlpp::Document * doc; - try { - parser.parse_file(xmlFile); - doc = parser.get_document(); - char xpath[200]; - snprintf(xpath, 200, "/sessions/session[@id='%s' or @expires < %lu]", - currentSession->sessionID.str().c_str(), time(NULL)); - xmlpp::NodeSet sess = doc->get_root_node()->find(xpath); - BOOST_FOREACH(xmlpp::Node * n, sess) { - n->get_parent()->remove_child(n); - } - } - catch (...) { - doc = new xmlpp::Document(); - doc->create_root_node("sessions"); - } - xmlpp::Element * sess = doc->get_root_node()->add_child("session"); - sess->set_attribute("id", currentSession->sessionID.str()); - sess->set_attribute("expires", boost::lexical_cast<Glib::ustring>(currentSession->expires)); - BOOST_FOREACH(const SessionXml::Values::value_type & nvp, currentSession->vars) { - xmlpp::Element * v = sess->add_child("var"); - v->add_child_text(nvp.second); - v->set_attribute("name", nvp.first); - } - doc->write_to_file(xmlFile); - if (!parser) { - delete doc; +} + +void +SessionContainerXml::SaveSession(SessionPtr currentSession) const +{ + xmlpp::DomParser parser; + xmlpp::Document * doc; + try { + parser.parse_file(xmlFile); + doc = parser.get_document(); + char xpath[200]; + snprintf(xpath, 200, "/sessions/session[@id='%s' or @expires < %lu]", + currentSession->ID.str().c_str(), time(NULL)); + xmlpp::NodeSet sess = doc->get_root_node()->find(xpath); + BOOST_FOREACH(xmlpp::Node * n, sess) { + n->get_parent()->remove_child(n); } - currentSession = NULL; } + catch (...) { + doc = new xmlpp::Document(); + doc->create_root_node("sessions"); + } + xmlpp::Element * sess = doc->get_root_node()->add_child("session"); + sess->set_attribute("id", currentSession->ID.str()); + sess->set_attribute("expires", boost::lexical_cast<Glib::ustring>(currentSession->ExpiryTime())); + BOOST_FOREACH(const Session::Values::value_type & nvp, currentSession->GetValuesCopy()) { + xmlpp::Element * v = sess->add_child("var"); + v->add_child_text(nvp.second); + v->set_attribute("name", nvp.first); + } + doc->write_to_file(xmlFile); + if (!parser) { + delete doc; + } + currentSession = NULL; } SessionPtr -SessionContainerXml::getSession(UUID & sid) +SessionContainerXml::getSession(UUID & sid) const { - if (!currentSession || currentSession->sessionID != sid) { - try { - xmlpp::DomParser sessions(xmlFile); - char xpath[200]; - snprintf(xpath, 200, "/sessions/session[@id='%s' and @expires > %lu]", - sid.str().c_str(), time(NULL)); - xmlpp::NodeSet sess = sessions.get_document()->get_root_node()->find(xpath); - if (sess.size() == 1) { - currentSession = new SessionXml(dynamic_cast<const xmlpp::Element *>(sess[0])); - } - else { - currentSession = new SessionXml(sid); - } + try { + xmlpp::DomParser sessions(xmlFile); + char xpath[200]; + snprintf(xpath, 200, "/sessions/session[@id='%s' and @expires > %lu]", + sid.str().c_str(), time(NULL)); + xmlpp::NodeSet sess = sessions.get_document()->get_root_node()->find(xpath); + if (sess.size() == 1) { + return new SessionXml(dynamic_cast<const xmlpp::Element *>(sess[0])); } - catch (...) { - currentSession = new SessionXml(sid); + else { + return new SessionXml(sid); } } - return currentSession; + catch (...) { + return new SessionXml(sid); + } } SessionXml::SessionXml(UUID & sid) : - sessionID(sid.is_nil() ? sid = UUID::generate_random() : sid) + Session(sid) { } SessionXml::SessionXml(const xmlpp::Element * p) : - sessionID(p->get_attribute_value("id")), + Session(UUID(p->get_attribute_value("id"))), expires(boost::lexical_cast<time_t>(p->get_attribute_value("expires"))) { xmlpp::NodeSet xvars = p->find("var"); @@ -155,14 +153,10 @@ SessionXml::ExpiryTime() const return expires; } -const VariableType & +VariableType SessionXml::GetValue(const Glib::ustring & name) const { - Values::const_iterator i = vars.find(name); - if (i == vars.end()) { - throw Session::VariableNotFound(name); - } - return i->second; + return safeMapFind<VariableNotFound>(vars, name)->second; } void diff --git a/project2/xml/sessionXml.h b/project2/xml/sessionXml.h index 9b5c3e1..96cd1d2 100644 --- a/project2/xml/sessionXml.h +++ b/project2/xml/sessionXml.h @@ -10,10 +10,9 @@ class SessionContainerXml : public SessionContainer { SessionContainerXml(); ~SessionContainerXml(); + void SaveSession(SessionPtr) const; protected: - SessionPtr getSession(UUID & sid); - typedef boost::intrusive_ptr<SessionXml> SessionXmlPtr; - SessionXmlPtr currentSession; + SessionPtr getSession(UUID & sid) const; private: // Configurables diff --git a/project2/xml/xslPreFetch.cpp b/project2/xml/xslPreFetch.cpp index 136e20f..74cb0eb 100644 --- a/project2/xml/xslPreFetch.cpp +++ b/project2/xml/xslPreFetch.cpp @@ -8,7 +8,7 @@ XslPreFetch::XslPreFetch(const xmlpp::Element * p) : SourceObject(p), View(p), Task(p), - CurlHelper(p), + VariableCurlHelper(p), html(p->get_attribute_value("html") == "true"), warnings(p->get_attribute_value("warnings") != "false"), encoding(p, "encoding", false) @@ -37,7 +37,7 @@ XslPreFetch::loadComplete(const CommonObjects *) } -CurlHandle::Ptr +CurlPtr XslPreFetch::newCurl() const { return CurlHelper::newCurl(); diff --git a/project2/xml/xslPreFetch.h b/project2/xml/xslPreFetch.h index c9e6a9a..fb453d5 100644 --- a/project2/xml/xslPreFetch.h +++ b/project2/xml/xslPreFetch.h @@ -8,7 +8,7 @@ #include <libxml++/nodes/element.h> /// Project2 component to queue up CURL objects to be downloaded -class XslPreFetch : public View, public Task, XslRowsCache, CurlHelper { +class XslPreFetch : public View, public Task, XslRowsCache, VariableCurlHelper { public: XslPreFetch(const xmlpp::Element * p); ~XslPreFetch(); @@ -21,7 +21,7 @@ class XslPreFetch : public View, public Task, XslRowsCache, CurlHelper { const bool warnings; const Variable encoding; - CurlHandle::Ptr newCurl() const; + CurlPtr newCurl() const; bool asHtml() const; bool withWarnings() const; }; diff --git a/project2/xml/xslRows.cpp b/project2/xml/xslRows.cpp index 666b607..38b7338 100644 --- a/project2/xml/xslRows.cpp +++ b/project2/xml/xslRows.cpp @@ -19,7 +19,7 @@ SimpleMessageException(XpathEvalError); XslRows::XslRows(const xmlpp::Element * p) : RowSet(p), - CurlHelper(p), + VariableCurlHelper(p), html(p->get_attribute_value("html") == "true"), warnings(p->get_attribute_value("warnings") != "false"), encoding(p, "encoding", false) @@ -60,7 +60,7 @@ XslRows::withWarnings() const return warnings; } -CurlHandle::Ptr +CurlPtr XslRows::newCurl() const { return CurlHelper::newCurl(); diff --git a/project2/xml/xslRows.h b/project2/xml/xslRows.h index e33932f..9611ca4 100644 --- a/project2/xml/xslRows.h +++ b/project2/xml/xslRows.h @@ -12,7 +12,7 @@ #include "definedColumns.h" /// Project2 component to create a row set based on the contents of an XML resource and specific XPaths with its hierarchy -class XslRows : public RowSet, XslRowsCache, CurlHelper { +class XslRows : public RowSet, XslRowsCache, VariableCurlHelper { public: XslRows(const xmlpp::Element * p); ~XslRows(); @@ -44,7 +44,7 @@ class XslRows : public RowSet, XslRowsCache, CurlHelper { typedef std::map<const Glib::ustring, FilterViewPtr> FilterViews; FilterViews fvs; - virtual CurlHandle::Ptr newCurl() const; + virtual CurlPtr newCurl() const; virtual bool asHtml() const; virtual bool withWarnings() const; diff --git a/project2/xml/xslRowsCache.cpp b/project2/xml/xslRowsCache.cpp index 51fd6c0..f229dda 100644 --- a/project2/xml/xslRowsCache.cpp +++ b/project2/xml/xslRowsCache.cpp @@ -3,6 +3,8 @@ #include <string.h> #include <libxml/HTMLparser.h> #include "exceptions.h" +#include "curlHelper.h" +#include "safeMapFind.h" XslRowsCache::Documents XslRowsCache::documents; XslRowsCache::Queued XslRowsCache::queued; @@ -13,15 +15,15 @@ SimpleMessageException(DownloadFailed); class XslCachePopulator : public CurlCompleteCallback { public: - XslCachePopulator(CurlHandle::Ptr ch, const Glib::ustring & u, bool h, bool w, const char * e) : + XslCachePopulator(CurlPtr ch, const Glib::ustring & u, bool h, bool w, const char * e) : CurlCompleteCallback(ch), + handler(boost::bind(&XslCachePopulator::append, this, _1, _2)), url(u), html(h), warnings(w), encoding(e ? strdup(e) : NULL) { - curl->setopt(CURLOPT_WRITEDATA, &buf); - curl->setopt(CURLOPT_WRITEFUNCTION, &XslRowsCache::handleDataHelper); + ch->setReadHandler(handler); } ~XslCachePopulator() { @@ -40,7 +42,13 @@ class XslCachePopulator : public CurlCompleteCallback { XslRowsCache::documents.insert(XslRowsCache::Documents::value_type(url, XslRowsCache::Documents::value_type::second_type(doc, xmlFreeDoc))); } + size_t append(const char * c, size_t b) + { + buf.append(c, b); + return b; + } + Curl::ReadHandler handler; std::string buf; const Glib::ustring url; const bool html; @@ -48,14 +56,6 @@ class XslCachePopulator : public CurlCompleteCallback { char * encoding; }; -size_t -XslRowsCache::handleDataHelper(const char * ptr, size_t size, size_t nmemb, void *stream) -{ - std::string * buf = static_cast<std::string *>(stream); - buf->append(ptr, size * nmemb); - return size * nmemb; -} - xmlDocPtr XslRowsCache::getDocument(const Glib::ustring & url, const char * encoding) const { @@ -65,14 +65,7 @@ XslRowsCache::getDocument(const Glib::ustring & url, const char * encoding) cons cbf.perform(); queued.clear(); } - i = documents.find(url); - if (i == documents.end()) { - // This should never happen - throw DownloadFailed(url); - } - else { - return i->second.get(); - } + return safeMapFind<DownloadFailed>(documents, url)->second.get(); } void diff --git a/project2/xml/xslRowsCache.h b/project2/xml/xslRowsCache.h index 55b8674..8fb9940 100644 --- a/project2/xml/xslRowsCache.h +++ b/project2/xml/xslRowsCache.h @@ -5,7 +5,7 @@ #include <boost/shared_ptr.hpp> #include <map> #include <set> -#include "../libmisc/curlsup.h" +#include <curlHelper.h> #include <glibmm/ustring.h> class XslRowsCache { @@ -18,7 +18,7 @@ class XslRowsCache { void queue(const Glib::ustring & url, const char * encoding) const; - virtual CurlHandle::Ptr newCurl() const = 0; + virtual CurlPtr newCurl() const = 0; virtual bool asHtml() const = 0; virtual bool withWarnings() const = 0; @@ -26,7 +26,6 @@ class XslRowsCache { xmlDocPtr getDocument(const Glib::ustring & url, const char * encoding) const; private: - static size_t handleDataHelper(const char * ptr, size_t size, size_t nmemb, void *stream); static CurlBulkFetcher cbf; friend class XslCachePopulator; |