Commit 7f74f62e authored by louiz’'s avatar louiz’

Merge branch 'master' into dummy_chan

parents 020325db c64bb0bd
...@@ -6,7 +6,6 @@ set(${PROJECT_NAME}_VERSION_MAJOR 0) ...@@ -6,7 +6,6 @@ set(${PROJECT_NAME}_VERSION_MAJOR 0)
set(${PROJECT_NAME}_VERSION_MINOR 1) set(${PROJECT_NAME}_VERSION_MINOR 1)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pedantic -Wall -Wextra") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pedantic -Wall -Wextra")
# set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address")
# Define a __FILENAME__ macro to get the filename of each file, instead of # Define a __FILENAME__ macro to get the filename of each file, instead of
# the full path as in __FILE__ # the full path as in __FILE__
...@@ -42,13 +41,17 @@ endif() ...@@ -42,13 +41,17 @@ endif()
# #
## Documentation ## Documentation
# #
set(MAN_PAGE ${CMAKE_CURRENT_BINARY_DIR}/doc/${PROJECT_NAME}.1)
set(DOC_PAGE ${CMAKE_CURRENT_SOURCE_DIR}/doc/${PROJECT_NAME}.1.md)
find_program(RONN_EXECUTABLE NAMES ronn find_program(RONN_EXECUTABLE NAMES ronn
DOC "The ronn software, to build the man page from the markdown documentation") DOC "The ronn software, to build the man page from the markdown documentation")
if(RONN_EXECUTABLE) if(RONN_EXECUTABLE)
set(WITH_DOC true) set(WITH_DOC true)
add_custom_target(doc file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc/)
${RONN_EXECUTABLE} --roff ${CMAKE_CURRENT_BINARY_DIR}/doc/${PROJECT_NAME}.1.md add_custom_command(OUTPUT ${MAN_PAGE}
COMMENT "Generate the man page" VERBATIM) COMMAND ${RONN_EXECUTABLE} --roff < ${DOC_PAGE} > ${MAN_PAGE}
DEPENDS ${DOC_PAGE})
add_custom_target(doc DEPENDS ${MAN_PAGE})
endif() endif()
# #
...@@ -98,7 +101,7 @@ file(GLOB source_xmpp ...@@ -98,7 +101,7 @@ file(GLOB source_xmpp
src/xmpp/*.[hc]pp) src/xmpp/*.[hc]pp)
add_library(xmpp STATIC ${source_xmpp}) add_library(xmpp STATIC ${source_xmpp})
target_link_libraries(xmpp bridge network utils logger target_link_libraries(xmpp bridge network utils logger
${EXPAT_LIBRARIES} pthread) ${EXPAT_LIBRARIES})
if(LIBIDN_FOUND) if(LIBIDN_FOUND)
target_link_libraries(xmpp ${LIBIDN_LIBRARIES}) target_link_libraries(xmpp ${LIBIDN_LIBRARIES})
endif() endif()
...@@ -146,5 +149,5 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/config.h.cmake ${CMAKE_CURRENT_BI ...@@ -146,5 +149,5 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/config.h.cmake ${CMAKE_CURRENT_BI
install(TARGETS ${PROJECT_NAME} install(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION bin) RUNTIME DESTINATION bin)
if(WITH_DOC) if(WITH_DOC)
install(FILES doc/${PROJECT_NAME}.1 DESTINATION man/man1) install(FILES ${MAN_PAGE} DESTINATION man/man1)
endif() endif()
\ No newline at end of file
...@@ -208,7 +208,7 @@ void Bridge::send_message(const Iid& iid, const std::string& nick, const std::st ...@@ -208,7 +208,7 @@ void Bridge::send_message(const Iid& iid, const std::string& nick, const std::st
this->make_xmpp_body(body), this->user_jid); this->make_xmpp_body(body), this->user_jid);
else else
this->xmpp->send_message(iid.chan + "%" + iid.server, this->xmpp->send_message(iid.chan + "%" + iid.server,
this->make_xmpp_body(body), this->user_jid); this->make_xmpp_body(body), this->user_jid, "chat");
} }
void Bridge::send_muc_leave(Iid&& iid, std::string&& nick, const std::string& message, const bool self) void Bridge::send_muc_leave(Iid&& iid, std::string&& nick, const std::string& message, const bool self)
...@@ -240,7 +240,7 @@ void Bridge::send_xmpp_message(const std::string& from, const std::string& autho ...@@ -240,7 +240,7 @@ void Bridge::send_xmpp_message(const std::string& from, const std::string& autho
body = std::string("[") + author + std::string("] ") + msg; body = std::string("[") + author + std::string("] ") + msg;
else else
body = msg; body = msg;
this->xmpp->send_message(from, this->make_xmpp_body(body), this->user_jid); this->xmpp->send_message(from, this->make_xmpp_body(body), this->user_jid, "chat");
} }
void Bridge::send_user_join(const std::string& hostname, void Bridge::send_user_join(const std::string& hostname,
......
...@@ -88,7 +88,7 @@ int main() ...@@ -88,7 +88,7 @@ int main()
{ {
std::cout << stanza.to_string() << std::endl; std::cout << stanza.to_string() << std::endl;
assert(stanza.get_name() == "stream_ns:stanza"); assert(stanza.get_name() == "stream_ns:stanza");
assert(stanza["b"] == "c"); assert(stanza.get_tag("b") == "c");
assert(stanza.get_inner() == "inner"); assert(stanza.get_inner() == "inner");
assert(stanza.get_tail() == ""); assert(stanza.get_tail() == "");
assert(stanza.get_child("stream_ns:child1") != nullptr); assert(stanza.get_child("stream_ns:child1") != nullptr);
......
...@@ -135,11 +135,8 @@ void XmppComponent::clean() ...@@ -135,11 +135,8 @@ void XmppComponent::clean()
void XmppComponent::on_remote_stream_open(const XmlNode& node) void XmppComponent::on_remote_stream_open(const XmlNode& node)
{ {
log_debug("XMPP DOCUMENT OPEN: " << node.to_string()); log_debug("XMPP DOCUMENT OPEN: " << node.to_string());
try this->stream_id = node.get_tag("id");
{ if (this->stream_id.empty())
this->stream_id = node["id"];
}
catch (const AttributeNotFound& e)
{ {
log_error("Error: no attribute 'id' found"); log_error("Error: no attribute 'id' found");
this->send_stream_error("bad-format", "missing 'id' attribute"); this->send_stream_error("bad-format", "missing 'id' attribute");
...@@ -255,27 +252,27 @@ void XmppComponent::handle_handshake(const Stanza& stanza) ...@@ -255,27 +252,27 @@ void XmppComponent::handle_handshake(const Stanza& stanza)
void XmppComponent::handle_presence(const Stanza& stanza) void XmppComponent::handle_presence(const Stanza& stanza)
{ {
std::string from; std::string from = stanza.get_tag("from");
std::string id; std::string id = stanza.get_tag("id");
try { std::string to_str = stanza.get_tag("to");
id = stanza["id"]; std::string type = stanza.get_tag("type");
from = stanza["from"];
} catch (const AttributeNotFound&) {} // Check for mandatory tags
if (from.empty()) if (from.empty())
return; {
utils::ScopeGuard malformed_stanza_error([&](){ log_warning("Received an invalid presence stanza: tag 'from' is missing.");
return;
}
if (to_str.empty())
{
this->send_stanza_error("presence", from, this->served_hostname, id, this->send_stanza_error("presence", from, this->served_hostname, id,
"modify", "bad-request", ""); "modify", "bad-request", "Missing 'to' tag");
}); return;
Bridge* bridge = this->get_user_bridge(stanza["from"]); }
Jid to(stanza["to"]);
Bridge* bridge = this->get_user_bridge(from);
Jid to(to_str);
Iid iid(to.local); Iid iid(to.local);
std::string type;
try {
type = stanza["type"];
}
catch (const AttributeNotFound&) {}
malformed_stanza_error.disable();
// An error stanza is sent whenever we exit this function without // An error stanza is sent whenever we exit this function without
// disabling this scopeguard. If error_type and error_name are not // disabling this scopeguard. If error_type and error_name are not
...@@ -286,7 +283,7 @@ void XmppComponent::handle_presence(const Stanza& stanza) ...@@ -286,7 +283,7 @@ void XmppComponent::handle_presence(const Stanza& stanza)
std::string error_type("cancel"); std::string error_type("cancel");
std::string error_name("internal-server-error"); std::string error_name("internal-server-error");
utils::ScopeGuard stanza_error([&](){ utils::ScopeGuard stanza_error([&](){
this->send_stanza_error("presence", stanza["from"], stanza["to"], id, this->send_stanza_error("presence", from, to_str, id,
error_type, error_name, ""); error_type, error_name, "");
}); });
...@@ -310,41 +307,30 @@ void XmppComponent::handle_presence(const Stanza& stanza) ...@@ -310,41 +307,30 @@ void XmppComponent::handle_presence(const Stanza& stanza)
{ {
// An user wants to join an invalid IRC channel, return a presence error to him // An user wants to join an invalid IRC channel, return a presence error to him
if (type.empty()) if (type.empty())
this->send_invalid_room_error(to.local, to.resource, stanza["from"]); this->send_invalid_room_error(to.local, to.resource, from);
} }
stanza_error.disable(); stanza_error.disable();
} }
void XmppComponent::handle_message(const Stanza& stanza) void XmppComponent::handle_message(const Stanza& stanza)
{ {
std::string from; std::string from = stanza.get_tag("from");
std::string id; std::string id = stanza.get_tag("id");
try { std::string to_str = stanza.get_tag("to");
id = stanza["id"]; std::string type = stanza.get_tag("type");
from = stanza["from"];
} catch (const AttributeNotFound&) {}
if (from.empty()) if (from.empty())
return; return;
utils::ScopeGuard malformed_stanza_error([&](){ if (type.empty())
this->send_stanza_error("message", from, this->served_hostname, id,
"modify", "bad-request", "");
});
Bridge* bridge = this->get_user_bridge(stanza["from"]);
Jid to(stanza["to"]);
Iid iid(to.local);
std::string type;
try {
type = stanza["type"];
}
catch (const AttributeNotFound&) {
type = "normal"; type = "normal";
} Bridge* bridge = this->get_user_bridge(from);
malformed_stanza_error.disable(); Jid to(to_str);
Iid iid(to.local);
std::string error_type("cancel"); std::string error_type("cancel");
std::string error_name("internal-server-error"); std::string error_name("internal-server-error");
utils::ScopeGuard stanza_error([&](){ utils::ScopeGuard stanza_error([&](){
this->send_stanza_error("message", stanza["from"], stanza["to"], id, this->send_stanza_error("message", from, to_str, id,
error_type, error_name, ""); error_type, error_name, "");
}); });
XmlNode* body = stanza.get_child(COMPONENT_NS":body"); XmlNode* body = stanza.get_child(COMPONENT_NS":body");
...@@ -367,27 +353,27 @@ void XmppComponent::handle_message(const Stanza& stanza) ...@@ -367,27 +353,27 @@ void XmppComponent::handle_message(const Stanza& stanza)
void XmppComponent::handle_iq(const Stanza& stanza) void XmppComponent::handle_iq(const Stanza& stanza)
{ {
std::string id; std::string id = stanza.get_tag("id");
std::string from; std::string from = stanza.get_tag("from");
try { std::string to_str = stanza.get_tag("to");
id = stanza["id"]; std::string type = stanza.get_tag("type");
from = stanza["from"];
} catch (const AttributeNotFound&) {}
if (from.empty()) if (from.empty())
return; return;
utils::ScopeGuard malformed_stanza_error([&](){ if (id.empty() || to_str.empty() || type.empty())
{
this->send_stanza_error("iq", from, this->served_hostname, id, this->send_stanza_error("iq", from, this->served_hostname, id,
"modify", "bad-request", ""); "modify", "bad-request", "");
}); return;
Bridge* bridge = this->get_user_bridge(stanza["from"]); }
Jid to(stanza["to"]);
std::string type = stanza["type"]; Bridge* bridge = this->get_user_bridge(from);
malformed_stanza_error.disable(); Jid to(from);
std::string error_type("cancel"); std::string error_type("cancel");
std::string error_name("internal-server-error"); std::string error_name("internal-server-error");
utils::ScopeGuard stanza_error([&](){ utils::ScopeGuard stanza_error([&](){
this->send_stanza_error("iq", stanza["from"], stanza["to"], id, this->send_stanza_error("iq", from, to_str, id,
error_type, error_name, ""); error_type, error_name, "");
}); });
if (type == "set") if (type == "set")
...@@ -398,18 +384,8 @@ void XmppComponent::handle_iq(const Stanza& stanza) ...@@ -398,18 +384,8 @@ void XmppComponent::handle_iq(const Stanza& stanza)
const XmlNode* child = query->get_child(MUC_ADMIN_NS":item"); const XmlNode* child = query->get_child(MUC_ADMIN_NS":item");
if (child) if (child)
{ {
std::string nick; std::string nick = child->get_tag("nick");
std::string role; std::string role = child->get_tag("role");
try {
nick = (*child)["nick"];
role = (*child)["role"];
}
catch (const AttributeNotFound&)
{
error_type = "modify";
error_name = "bad-request";
return;
}
if (!nick.empty() && role == "none") if (!nick.empty() && role == "none")
{ {
std::string reason; std::string reason;
...@@ -419,6 +395,12 @@ void XmppComponent::handle_iq(const Stanza& stanza) ...@@ -419,6 +395,12 @@ void XmppComponent::handle_iq(const Stanza& stanza)
Iid iid(to.local); Iid iid(to.local);
bridge->send_irc_kick(iid, nick, reason); bridge->send_irc_kick(iid, nick, reason);
} }
else
{
error_type = "cancel";
error_name = "feature-not-implemented";
return;
}
} }
} }
} }
...@@ -458,11 +440,13 @@ void* XmppComponent::get_receive_buffer(const size_t size) const ...@@ -458,11 +440,13 @@ void* XmppComponent::get_receive_buffer(const size_t size) const
return this->parser.get_buffer(size); return this->parser.get_buffer(size);
} }
void XmppComponent::send_message(const std::string& from, Xmpp::body&& body, const std::string& to) void XmppComponent::send_message(const std::string& from, Xmpp::body&& body, const std::string& to, const std::string& type)
{ {
XmlNode node("message"); XmlNode node("message");
node["to"] = to; node["to"] = to;
node["from"] = from + "@" + this->served_hostname; node["from"] = from + "@" + this->served_hostname;
if (!type.empty())
node["type"] = type;
XmlNode body_node("body"); XmlNode body_node("body");
body_node.set_inner(std::get<0>(body)); body_node.set_inner(std::get<0>(body));
body_node.close(); body_node.close();
......
...@@ -81,7 +81,8 @@ public: ...@@ -81,7 +81,8 @@ public:
/** /**
* Send a message from from@served_hostname, with the given body * Send a message from from@served_hostname, with the given body
*/ */
void send_message(const std::string& from, Xmpp::body&& body, const std::string& to); void send_message(const std::string& from, Xmpp::body&& body,
const std::string& to, const std::string& type);
/** /**
* Send a join from a new participant * Send a join from a new participant
*/ */
......
...@@ -55,7 +55,8 @@ XmppParser::~XmppParser() ...@@ -55,7 +55,8 @@ XmppParser::~XmppParser()
int XmppParser::feed(const char* data, const int len, const bool is_final) int XmppParser::feed(const char* data, const int len, const bool is_final)
{ {
int res = XML_Parse(this->parser, data, len, is_final); int res = XML_Parse(this->parser, data, len, is_final);
if (res == 0) if (res == XML_STATUS_ERROR &&
(XML_GetErrorCode(this->parser) != XML_ERROR_FINISHED))
log_error("Xml_Parse encountered an error: " << log_error("Xml_Parse encountered an error: " <<
XML_ErrorString(XML_GetErrorCode(this->parser))) XML_ErrorString(XML_GetErrorCode(this->parser)))
return res; return res;
...@@ -64,7 +65,7 @@ int XmppParser::feed(const char* data, const int len, const bool is_final) ...@@ -64,7 +65,7 @@ int XmppParser::feed(const char* data, const int len, const bool is_final)
int XmppParser::parse(const int len, const bool is_final) int XmppParser::parse(const int len, const bool is_final)
{ {
int res = XML_ParseBuffer(this->parser, len, is_final); int res = XML_ParseBuffer(this->parser, len, is_final);
if (res == 0) if (res == XML_STATUS_ERROR)
log_error("Xml_Parsebuffer encountered an error: " << log_error("Xml_Parsebuffer encountered an error: " <<
XML_ErrorString(XML_GetErrorCode(this->parser))); XML_ErrorString(XML_GetErrorCode(this->parser)));
return res; return res;
......
...@@ -216,7 +216,7 @@ bool XmlNode::has_children() const ...@@ -216,7 +216,7 @@ bool XmlNode::has_children() const
return !this->children.empty(); return !this->children.empty();
} }
const std::string& XmlNode::operator[](const std::string& name) const const std::string XmlNode::get_tag(const std::string& name) const
{ {
try try
{ {
...@@ -225,7 +225,7 @@ const std::string& XmlNode::operator[](const std::string& name) const ...@@ -225,7 +225,7 @@ const std::string& XmlNode::operator[](const std::string& name) const
} }
catch (const std::out_of_range& e) catch (const std::out_of_range& e)
{ {
throw AttributeNotFound(); return "";
} }
} }
......
...@@ -8,13 +8,6 @@ ...@@ -8,13 +8,6 @@
std::string xml_escape(const std::string& data); std::string xml_escape(const std::string& data);
std::string xml_unescape(const std::string& data); std::string xml_unescape(const std::string& data);
/**
* Raised on operator[] when the attribute does not exist
*/
class AttributeNotFound: public std::exception
{
};
/** /**
* Represent an XML node. It has * Represent an XML node. It has
* - A parent XML node (in the case of the first-level nodes, the parent is * - A parent XML node (in the case of the first-level nodes, the parent is
...@@ -103,10 +96,10 @@ public: ...@@ -103,10 +96,10 @@ public:
*/ */
bool has_children() const; bool has_children() const;
/** /**
* Gets the value for the given attribute, raises AttributeNotFound if the * Gets the value for the given attribute, returns an empty string if the
* node as no such attribute. * node as no such attribute.
*/ */
const std::string& operator[](const std::string& name) const; const std::string get_tag(const std::string& name) const;
/** /**
* Use this to set an attribute's value, like node["id"] = "12"; * Use this to set an attribute's value, like node["id"] = "12";
*/ */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment