Merge branch 'master' into dummy_chan
This commit is contained in:
+9
-6
@@ -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()
|
|||||||
#
|
#
|
||||||
## 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
|
|||||||
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
|
|||||||
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()
|
||||||
@@ -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
|
|||||||
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,
|
||||||
|
|||||||
+1
-1
@@ -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);
|
||||||
|
|||||||
+56
-72
@@ -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)
|
|||||||
|
|
||||||
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())
|
||||||
|
{
|
||||||
|
log_warning("Received an invalid presence stanza: tag 'from' is missing.");
|
||||||
return;
|
return;
|
||||||
utils::ScopeGuard malformed_stanza_error([&](){
|
|
||||||
this->send_stanza_error("presence", 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&) {}
|
if (to_str.empty())
|
||||||
malformed_stanza_error.disable();
|
{
|
||||||
|
this->send_stanza_error("presence", from, this->served_hostname, id,
|
||||||
|
"modify", "bad-request", "Missing 'to' tag");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bridge* bridge = this->get_user_bridge(from);
|
||||||
|
Jid to(to_str);
|
||||||
|
Iid iid(to.local);
|
||||||
|
|
||||||
// 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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
// 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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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
|
|||||||
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:
|
|||||||
/**
|
/**
|
||||||
* 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()
|
|||||||
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)
|
|||||||
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
|
|||||||
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
|
|||||||
}
|
}
|
||||||
catch (const std::out_of_range& e)
|
catch (const std::out_of_range& e)
|
||||||
{
|
{
|
||||||
throw AttributeNotFound();
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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:
|
|||||||
*/
|
*/
|
||||||
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";
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user