summaryrefslogtreecommitdiff
path: root/src/xmpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/xmpp')
-rw-r--r--src/xmpp/stanza.hpp18
-rw-r--r--src/xmpp/xmpp_component.cpp30
-rw-r--r--src/xmpp/xmpp_component.hpp5
-rw-r--r--src/xmpp/xmpp_stanza.cpp37
-rw-r--r--src/xmpp/xmpp_stanza.hpp12
5 files changed, 83 insertions, 19 deletions
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
@@ -72,10 +72,15 @@ public:
*/
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 <iostream>
+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 += "&amp;"; break;
+ case '\"': buffer += "&quot;"; break;
+ case '\'': buffer += "&apos;"; break;
+ case '<': buffer += "&lt;"; break;
+ case '>': buffer += "&gt;"; 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 <expatpp.h>
+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;