summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrandomdan <randomdan@localhost>2011-09-06 14:06:44 +0000
committerrandomdan <randomdan@localhost>2011-09-06 14:06:44 +0000
commit2f482e21fb689c9476eca6741f3cdc9ca2bbb5ff (patch)
treeb55b4edeac7882b419344b1845e8338b8df947e1
parentMinor shuffle (diff)
downloadproject2-2f482e21fb689c9476eca6741f3cdc9ca2bbb5ff.tar.bz2
project2-2f482e21fb689c9476eca6741f3cdc9ca2bbb5ff.tar.xz
project2-2f482e21fb689c9476eca6741f3cdc9ca2bbb5ff.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.cpp43
-rw-r--r--project2/cgi/cgiAppEngine.h2
-rw-r--r--project2/cgi/cgiStageFail.cpp52
-rw-r--r--project2/common/commonObjects.cpp13
-rw-r--r--project2/common/config.cpp13
-rw-r--r--project2/common/iHaveParameters.cpp7
-rw-r--r--project2/common/session.cpp3
-rw-r--r--project2/common/session.h7
-rw-r--r--project2/common/sessionContainer.cpp2
-rw-r--r--project2/common/sessionContainer.h5
-rw-r--r--project2/console/consoleAppEngine.cpp17
-rw-r--r--project2/url/curlHelper.cpp74
-rw-r--r--project2/url/curlHelper.h36
-rw-r--r--project2/url/urlRows.cpp29
-rw-r--r--project2/url/urlRows.h11
-rw-r--r--project2/xml/sessionXml.cpp110
-rw-r--r--project2/xml/sessionXml.h5
-rw-r--r--project2/xml/xslPreFetch.cpp4
-rw-r--r--project2/xml/xslPreFetch.h4
-rw-r--r--project2/xml/xslRows.cpp4
-rw-r--r--project2/xml/xslRows.h4
-rw-r--r--project2/xml/xslRowsCache.cpp31
-rw-r--r--project2/xml/xslRowsCache.h5
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;