diff --git a/src/core/Makefile b/src/core/Makefile index ca885fe..ac74b3b 100644 --- a/src/core/Makefile +++ b/src/core/Makefile @@ -12,6 +12,7 @@ SRCS= xmpp-commands.c \ stanzas.c \ tools.c \ popenRWE.c \ + xep/carbons.c \ xep/chatstates.c \ xep/composing.c \ xep/datetime.c \ diff --git a/src/core/xep/carbons.c b/src/core/xep/carbons.c new file mode 100644 index 0000000..d652776 --- /dev/null +++ b/src/core/xep/carbons.c @@ -0,0 +1,122 @@ +/* + * XEP-0280: Message Carbons + */ + +#include "module.h" +#include "misc.h" +#include "settings.h" +#include "signals.h" + +#include "rosters-tools.h" +#include "xmpp-servers.h" +#include "disco.h" +#include "tools.h" +#include "muc.h" + +#define XMLNS_CARBONS "urn:xmpp:carbons:2" + +static void +sig_server_features(XMPP_SERVER_REC *server) +{ + if (disco_have_feature(server->server_features, XMLNS_CARBONS)) { + LmMessage *lmsg; + LmMessageNode *node; + + lmsg = lm_message_new_with_sub_type(NULL, + LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_SET); + node = lm_message_node_add_child(lmsg->node, "enable", NULL); + lm_message_node_set_attribute(node, XMLNS, XMLNS_CARBONS); + signal_emit("xmpp send iq", 2, server, lmsg); + lm_message_unref(lmsg); + } +} + +static void +sig_recv_message(XMPP_SERVER_REC *server, LmMessage *lmsg, const int type, + const char *id, const char *from, const char *to) +{ + LmMessageNode *node = NULL; + LmMessageNode *forwarded = NULL; + LmMessageNode *message = NULL; + char *ffrom, *fto; + + node = lm_find_node(lmsg->node, "received", "xmlns", XMLNS_CARBONS); + if(node) { + forwarded = lm_find_node(node, "forwarded", "xmlns", "urn:xmpp:forward:0"); + if(forwarded) message = lm_find_node(forwarded, "message", "xmlns", "jabber:client"); + if(message) { + ffrom = xmpp_recode_in(lm_message_node_get_attribute(message, "from")); + if (from == NULL) + from = g_strdup(""); + fto = xmpp_recode_in(lm_message_node_get_attribute(message, "to")); + if (to == NULL) + to = g_strdup(""); + + node = lmsg->node; + lmsg->node = message; + signal_emit("xmpp recv message", 6, server, lmsg, type, id, ffrom, fto); + lmsg->node = node; + goto done; + } + } + + node = lm_find_node(lmsg->node, "sent", "xmlns", XMLNS_CARBONS); + if(!node) return; // Not for us + + forwarded = lm_find_node(node, "forwarded", "xmlns", "urn:xmpp:forward:0"); + if(forwarded) message = lm_find_node(forwarded, "message", "xmlns", "jabber:client"); + if(message) { + MUC_REC *channel; + char *nick, *str; + node = lm_message_node_get_child(message, "body"); + if(node == NULL || node->value == NULL || *node->value == '\0') return; + str = xmpp_recode_in(node->value); + + ffrom = xmpp_recode_in(lm_message_node_get_attribute(message, "from")); + if (from == NULL) + from = g_strdup(""); + fto = xmpp_recode_in(lm_message_node_get_attribute(message, "to")); + if (to == NULL) + to = g_strdup(""); + + nick = rosters_resolve_name(server, fto); + if(nick) fto = nick; + + if (type == LM_MESSAGE_SUB_TYPE_GROUPCHAT + && (channel = get_muc(server, fto)) != NULL + && (nick = muc_extract_nick(ffrom)) != NULL) { + signal_emit("message xmpp carbons sent", 6, server, + str, nick, channel->name, + GINT_TO_POINTER(SEND_TARGET_CHANNEL)); + g_free(nick); + } else if ((type == LM_MESSAGE_SUB_TYPE_NOT_SET + || type == LM_MESSAGE_SUB_TYPE_HEADLINE + || type == LM_MESSAGE_SUB_TYPE_NORMAL + || type == LM_MESSAGE_SUB_TYPE_CHAT)) { + signal_emit("message xmpp carbons sent", 6, server, + str, ffrom, fto, + GINT_TO_POINTER(SEND_TARGET_NICK)); + } + + g_free(str); + } + +done: + g_free(fto); + g_free(ffrom); + signal_stop(); +} + +void +carbons_init(void) +{ + signal_add("xmpp server features", sig_server_features); + signal_add_first("xmpp recv message", sig_recv_message); +} + +void +carbons_deinit(void) +{ + signal_remove("xmpp server features", sig_server_features); + signal_remove("xmpp recv message", sig_recv_message); +} diff --git a/src/core/xep/carbons.h b/src/core/xep/carbons.h new file mode 100644 index 0000000..3380bc1 --- /dev/null +++ b/src/core/xep/carbons.h @@ -0,0 +1,9 @@ +#ifndef __CARBONS_H +#define __CARBONS_H + +__BEGIN_DECLS +void carbons_init(void); +void carbons_deinit(void); +__END_DECLS + +#endif diff --git a/src/core/xep/xep.c b/src/core/xep/xep.c index 8c7bcdf..a47cddd 100644 --- a/src/core/xep/xep.c +++ b/src/core/xep/xep.c @@ -17,6 +17,7 @@ #include "module.h" +#include "carbons.h" #include "chatstates.h" #include "composing.h" #include "delay.h" @@ -32,6 +33,7 @@ void xep_init(void) { disco_init(); /* init sevice discovery first */ + carbons_init(); chatstates_init(); composing_init(); delay_init(); @@ -47,6 +49,7 @@ void xep_deinit(void) { disco_deinit(); + carbons_deinit(); chatstates_deinit(); composing_deinit(); delay_deinit(); diff --git a/src/fe-common/Makefile b/src/fe-common/Makefile index 487d125..c84ccdd 100644 --- a/src/fe-common/Makefile +++ b/src/fe-common/Makefile @@ -9,6 +9,7 @@ SRCS= fe-xmpp-messages.c \ module-formats.c \ xmpp-completion.c \ xmpp-formats.c \ + xep/fe-carbons.c \ xep/fe-composing.c \ xep/fe-delay.c \ xep/fe-muc.c \ diff --git a/src/fe-common/xep/fe-carbons.c b/src/fe-common/xep/fe-carbons.c new file mode 100644 index 0000000..fe95496 --- /dev/null +++ b/src/fe-common/xep/fe-carbons.c @@ -0,0 +1,63 @@ +#include "module.h" +#include "levels.h" +#include "module-formats.h" +#include "printtext.h" +#include "settings.h" +#include "signals.h" +#include "window-items.h" +#include "fe-messages.h" +#include "fe-queries.h" +#include "fe-common/core/module-formats.h" +#include "fe-common/core/fe-messages.h" +#include "fe-common/irc/module-formats.h" + +#include "xmpp-servers.h" +#include "rosters-tools.h" +#include "xep/muc.h" + +static void +sig_message_carbons_sent(SERVER_REC *server, const char *msg, const char *nick, + const char *target, gpointer gpointer_type) +{ + void *item; + char *freemsg = NULL; + int level, type; + + g_return_if_fail(server != NULL); + g_return_if_fail(msg != NULL); + g_return_if_fail(nick != NULL); + g_return_if_fail(target != NULL); + + type = GPOINTER_TO_INT(gpointer_type); + level = MSGLEVEL_NO_ACT | MSGLEVEL_NOHILIGHT + | (type == SEND_TARGET_CHANNEL ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS); + item = type == SEND_TARGET_CHANNEL ? + (void *)get_muc((XMPP_SERVER_REC *)server, target) : + query_find(server, target); + + if (settings_get_bool("emphasis")) + msg = freemsg = expand_emphasis(item, msg); + + if (type == SEND_TARGET_CHANNEL) { + char *nickmode = channel_get_nickmode(item, nick); + printformat_module(CORE_MODULE_NAME, server, target, + level, TXT_OWN_MSG_CHANNEL, nick, target, msg, nickmode); + } else if(item) { // If no query, why do we want to see carbons? + printformat_module(CORE_MODULE_NAME, server, target, + level, TXT_OWN_MSG_PRIVATE_QUERY, target, msg, nick); + } + + g_free_not_null(freemsg); +} + +void +fe_carbons_init(void) +{ + signal_add("message xmpp carbons sent", sig_message_carbons_sent); +} + +void +fe_carbons_deinit(void) +{ + signal_remove("message xmpp carbons sent", sig_message_carbons_sent); +} diff --git a/src/fe-common/xep/fe-carbons.h b/src/fe-common/xep/fe-carbons.h new file mode 100644 index 0000000..ee8ba85 --- /dev/null +++ b/src/fe-common/xep/fe-carbons.h @@ -0,0 +1,9 @@ +#ifndef __FE_CARBONS_H +#define __FE_CARBONS_H + +__BEGIN_DECLS +void fe_carbons_init(void); +void fe_carbons_deinit(void); +__END_DECLS + +#endif diff --git a/src/fe-common/xep/fe-xep.c b/src/fe-common/xep/fe-xep.c index 605922b..46069f3 100644 --- a/src/fe-common/xep/fe-xep.c +++ b/src/fe-common/xep/fe-xep.c @@ -17,6 +17,7 @@ #include "module.h" +#include "fe-carbons.h" #include "fe-composing.h" #include "fe-delay.h" #include "fe-muc.h" @@ -28,6 +29,7 @@ void fe_xep_init(void) { + fe_carbons_init(); fe_composing_init(); fe_delay_init(); fe_muc_init(); @@ -40,6 +42,7 @@ fe_xep_init(void) void fe_xep_deinit(void) { + fe_carbons_deinit(); fe_composing_deinit(); fe_delay_deinit(); fe_muc_deinit();