#include "sessionXml.h" #include "uuid.h" #include #include #include #include #include #include #include /// Session implementation that stores its contents in an XML file on the local filesystem class SessionXml : public Session { public: SessionXml(UUID & sid); SessionXml(const xmlpp::Element *); virtual ~SessionXml(); 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; friend class SessionContainerXml; }; typedef boost::intrusive_ptr SessionXmlPtr; const char * xmlFile = "/tmp/project2sessions.xml"; SessionXmlPtr currentSession; SessionContainerXml::SessionContainerXml() { } SessionContainerXml::~SessionContainerXml() { CleanUp(); } void SessionContainerXml::CleanUp() { 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(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; } currentSession = NULL; } } SessionPtr SessionContainerXml::getSession(UUID & sid) { 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(sess[0])); } else { currentSession = new SessionXml(sid); } } catch (...) { currentSession = new SessionXml(sid); } } return currentSession; } SessionXml::SessionXml(UUID & sid) : sessionID(sid.is_nil() ? sid = UUID::generate_random() : sid) { } SessionXml::SessionXml(const xmlpp::Element * p) : sessionID(p->get_attribute_value("id")), expires(boost::lexical_cast(p->get_attribute_value("expires"))) { xmlpp::NodeSet xvars = p->find("var"); BOOST_FOREACH(const xmlpp::Node * n, xvars) { const xmlpp::Element * e = dynamic_cast(n); if (e) { vars[e->get_attribute_value("name")] = e->get_child_text() ? e->get_child_text()->get_content() : ""; } } } SessionXml::~SessionXml() { } void SessionXml::ExpiryTime(time_t t) { expires = t; } time_t SessionXml::ExpiryTime() const { return expires; } const 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; } void SessionXml::SetValue(const Glib::ustring & name, const VariableType & value) { vars[name] = value; } void SessionXml::ClearValue(const Glib::ustring & name) { vars.erase(name); } Session::Values SessionXml::GetValuesCopy() const { return vars; }