File: carbons.c

package info (click to toggle)
irssi-plugin-xmpp 0.54-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster, sid
  • size: 1,952 kB
  • sloc: ansic: 8,831; makefile: 113; perl: 58
file content (122 lines) | stat: -rw-r--r-- 3,476 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
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);
}