From a418b6ed5d70f0e61e71bb1adce2a693ade89e30 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Thu, 7 Nov 2013 01:53:09 +0100 Subject: Send and receive messages Also correctly respond to PING with the id, escape some XML content, but not always --- src/xmpp/stanza.hpp | 18 ------------------ src/xmpp/xmpp_component.cpp | 30 ++++++++++++++++++++++++++++++ src/xmpp/xmpp_component.hpp | 5 +++++ src/xmpp/xmpp_stanza.cpp | 37 ++++++++++++++++++++++++++++++++++++- src/xmpp/xmpp_stanza.hpp | 12 ++++++++++++ 5 files changed, 83 insertions(+), 19 deletions(-) delete mode 100644 src/xmpp/stanza.hpp (limited to 'src/xmpp') diff --git a/src/xmpp/stanza.hpp b/src/xmpp/stanza.hpp deleted file mode 100644 index 697bda4..0000000 --- a/src/xmpp/stanza.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef Stanza -# define Stanza - -class Stanza -{ -public: - explicit Stanza(); - ~Stanza(); -private: - Stanza(const Stanza&) = delete; - Stanza(Stanza&&) = delete; - Stanza& operator=(const Stanza&) = delete; - Stanza& operator=(Stanza&&) = delete; -}; - -#endif // Stanza - - diff --git a/src/xmpp/xmpp_component.cpp b/src/xmpp/xmpp_component.cpp index 3a288c7..cd9cd6f 100644 --- a/src/xmpp/xmpp_component.cpp +++ b/src/xmpp/xmpp_component.cpp @@ -25,6 +25,8 @@ XmppComponent::XmppComponent(const std::string& hostname, const std::string& sec std::bind(&XmppComponent::handle_handshake, this,std::placeholders::_1)); this->stanza_handlers.emplace("presence", std::bind(&XmppComponent::handle_presence, this,std::placeholders::_1)); + this->stanza_handlers.emplace("message", + std::bind(&XmppComponent::handle_message, this,std::placeholders::_1)); } XmppComponent::~XmppComponent() @@ -151,6 +153,20 @@ void XmppComponent::handle_presence(const Stanza& stanza) bridge->join_irc_channel(iid, to.resource); } +void XmppComponent::handle_message(const Stanza& stanza) +{ + Bridge* bridge = this->get_user_bridge(stanza["from"]); + Jid to(stanza["to"]); + Iid iid(to.local); + XmlNode* body = stanza.get_child("body"); + if (stanza["type"] == "groupchat") + { + if (to.resource.empty()) + if (body && !body->get_inner().empty()) + bridge->send_channel_message(iid, body->get_inner()); + } +} + Bridge* XmppComponent::get_user_bridge(const std::string& user_jid) { try @@ -239,3 +255,17 @@ void XmppComponent::send_topic(const std::string& from, const std::string& topic message.close(); this->send_stanza(message); } + +void XmppComponent::send_muc_message(const std::string& muc_name, const std::string& nick, const std::string body_str, const std::string& jid_to) +{ + Stanza message("message"); + message["to"] = jid_to; + message["from"] = muc_name + "@" + this->served_hostname + "/" + nick; + message["type"] = "groupchat"; + XmlNode body("body"); + body.set_inner(body_str); + body.close(); + message.add_child(std::move(body)); + message.close(); + this->send_stanza(message); +} diff --git a/src/xmpp/xmpp_component.hpp b/src/xmpp/xmpp_component.hpp index 725b495..73eadd2 100644 --- a/src/xmpp/xmpp_component.hpp +++ b/src/xmpp/xmpp_component.hpp @@ -71,11 +71,16 @@ public: * Send the MUC topic to the user */ void send_topic(const std::string& from, const std::string& topic, const std::string& to); + /** + * Send a (non-private) message to the MUC + */ + void send_muc_message(const std::string& muc_name, const std::string& nick, const std::string body_str, const std::string& jid_to); /** * Handle the various stanza types */ void handle_handshake(const Stanza& stanza); void handle_presence(const Stanza& stanza); + void handle_message(const Stanza& stanza); private: /** diff --git a/src/xmpp/xmpp_stanza.cpp b/src/xmpp/xmpp_stanza.cpp index 2c98acc..4c0088e 100644 --- a/src/xmpp/xmpp_stanza.cpp +++ b/src/xmpp/xmpp_stanza.cpp @@ -2,6 +2,26 @@ #include +std::string xml_escape(const std::string& data) +{ + std::string res; + buffer.reserve(data.size()); + for(size_t pos = 0; pos != data.size(); ++pos) + { + switch(data[pos]) + { + case '&': buffer += "&"; break; + case '\"': buffer += """; break; + case '\'': buffer += "'"; break; + case '<': buffer += "<"; break; + case '>': buffer += ">"; break; + default: buffer += data[pos]; break; + } + } + return buffer; +} + + XmlNode::XmlNode(const std::string& name, XmlNode* parent): name(name), parent(parent), @@ -40,7 +60,22 @@ void XmlNode::set_tail(const std::string& data) void XmlNode::set_inner(const std::string& data) { - this->inner = data; + this->inner = xml_escape(data); +} + +std::string XmlNode::get_inner() const +{ + return this->inner; +} + +XmlNode* XmlNode::get_child(const std::string& name) const +{ + for (auto& child: this->children) + { + if (child->name == name) + return child; + } + return nullptr; } void XmlNode::add_child(XmlNode* child) diff --git a/src/xmpp/xmpp_stanza.hpp b/src/xmpp/xmpp_stanza.hpp index 277b0db..62f152d 100644 --- a/src/xmpp/xmpp_stanza.hpp +++ b/src/xmpp/xmpp_stanza.hpp @@ -7,6 +7,8 @@ #include +std::string xml_escape(const std::string& data); + /** * Raised on operator[] when the attribute does not exist */ @@ -51,8 +53,18 @@ public: void set_tail(const std::string& data); /** * Set the content of the inner, that is the text inside this node + * TODO: escape it here. */ void set_inner(const std::string& data); + /** + * Get the content of inner + * TODO: unescape it here. + */ + std::string get_inner() const; + /** + * Get a pointer to the first child element with that name + */ + XmlNode* get_child(const std::string& name) const; void add_child(XmlNode* child); void add_child(XmlNode&& child); XmlNode* get_last_child() const; -- cgit v1.2.3