2
* $Id: xmpp-protocol.c,v 1.55 2008/04/26 11:01:11 errtu Exp $
4
* Copyright (C) 2007 Colin DIDIER
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License version 2 as
8
* published by the Free Software Foundation.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License along
16
* with this program; if not, write to the Free Software Foundation, Inc.,
17
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
#include <sys/types.h>
21
#include <sys/utsname.h>
29
#include "xmpp-protocol.h"
30
#include "xmpp-servers.h"
31
#include "xmpp-channels.h"
32
#include "xmpp-queries.h"
33
#include "xmpp-rosters.h"
34
#include "xmpp-rosters-tools.h"
35
#include "xmpp-tools.h"
39
xmpp_send_message(XMPP_SERVER_REC *server, const char *dest,
44
XMPP_ROSTER_RESOURCE_REC *resource;
45
char *jid, *jid_recoded, *message_recoded;
47
g_return_if_fail(IS_XMPP_SERVER(server));
48
g_return_if_fail(dest != NULL);
49
g_return_if_fail(message != NULL);
51
jid = xmpp_rosters_resolve_name(server, dest);
52
jid_recoded = xmpp_recode_out((jid != NULL) ? jid : dest);
54
msg = lm_message_new_with_sub_type(jid_recoded,
55
LM_MESSAGE_TYPE_MESSAGE, LM_MESSAGE_SUB_TYPE_CHAT);
58
message_recoded = xmpp_recode_out(message);
59
lm_message_node_add_child(msg->node, "body", message_recoded);
60
g_free(message_recoded);
62
xmpp_rosters_find_user(server->roster, jid, NULL, &resource);
63
if (resource != NULL && resource->composing_id != NULL) {
64
child = lm_message_node_add_child(msg->node, "x", NULL);
65
lm_message_node_set_attribute(child, XMLNS, XMLNS_EVENT);
66
lm_message_node_add_child(child, "id", resource->composing_id);
67
g_free_and_null(resource->composing_id);
70
lm_send(server, msg, NULL);
71
lm_message_unref(msg);
77
send_service_unavailable(XMPP_SERVER_REC *server, const char *dest,
84
g_return_if_fail(IS_XMPP_SERVER(server));
85
g_return_if_fail(dest != NULL);
87
recoded = xmpp_recode_out(dest);
88
msg = lm_message_new_with_sub_type(recoded,
89
LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_ERROR);
93
lm_message_node_set_attribute(msg->node, "id", id);
95
/* <error code='503' type='cancel'> */
96
child = lm_message_node_add_child(msg->node, "error", NULL);
97
lm_message_node_set_attribute(child, "code", "503");
98
lm_message_node_set_attribute(child, "type", "cancel");
100
/* <service-unavailable
101
* xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> */
102
child = lm_message_node_add_child(child,
103
"service-unavailable", NULL);
104
lm_message_node_set_attribute(child, XMLNS, XMLNS_STANZAS);
106
lm_send(server, msg, NULL);
107
lm_message_unref(msg);
111
sig_own_presence(XMPP_SERVER_REC *server, const int show, const char *status,
116
const char *show_str, *status_tmp;
117
char *status_recoded, *priority_str;
119
g_return_if_fail(IS_XMPP_SERVER(server));
121
status_tmp = server->away_reason;
122
if (status == NULL && status_tmp != NULL
123
&& strcmp(status_tmp, " ") == 0)
126
if (!xmpp_presence_changed(show, server->show, status,
127
status_tmp, priority, server->priority))
131
case XMPP_PRESENCE_AWAY:
132
show_str = xmpp_presence_show[XMPP_PRESENCE_AWAY];
135
case XMPP_PRESENCE_CHAT:
136
show_str = xmpp_presence_show[XMPP_PRESENCE_CHAT];
139
case XMPP_PRESENCE_DND:
140
show_str = xmpp_presence_show[XMPP_PRESENCE_DND];
143
case XMPP_PRESENCE_XA:
144
show_str = xmpp_presence_show[XMPP_PRESENCE_XA];
147
case XMPP_PRESENCE_AVAILABLE:
153
if (show_str != NULL) {
155
signal_emit("event 306", 2, server, server->jid);
159
server->show = XMPP_PRESENCE_AVAILABLE;
160
if (server->usermode_away)
161
signal_emit("event 305", 2, server, server->jid);
164
g_free(server->away_reason);
165
server->away_reason = g_strdup(status);
167
status_recoded = xmpp_recode_out(server->away_reason);
168
if (!xmpp_priority_out_of_bound(priority))
169
server->priority = priority;
170
priority_str = g_strdup_printf("%d", server->priority);
172
/* send presence to the server */
173
msg = lm_message_new(NULL, LM_MESSAGE_TYPE_PRESENCE);
174
if (show_str != NULL)
175
lm_message_node_add_child(msg->node, "show", show_str);
176
if (status_recoded != NULL)
177
lm_message_node_add_child(msg->node, "status", status_recoded);
178
lm_message_node_add_child(msg->node, "priority", priority_str);
179
lm_send(server, msg, NULL);
180
lm_message_unref(msg);
182
/* send presence to channels */
183
msg = lm_message_new(NULL, LM_MESSAGE_TYPE_PRESENCE);
184
if (show_str != NULL)
185
lm_message_node_add_child(msg->node, "show", show_str);
186
if (status_recoded != NULL)
187
lm_message_node_add_child(msg->node, "status", status_recoded);
189
for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
190
XMPP_CHANNEL_REC *channel;
193
channel = XMPP_CHANNEL(tmp->data);
194
if (channel == NULL || !channel->joined)
197
dest_recoded = xmpp_recode_out(channel->name);
198
lm_message_node_set_attribute(msg->node, "to", dest_recoded);
199
g_free(dest_recoded);
201
lm_send(server, msg, NULL);
204
lm_message_unref(msg);
205
g_free(status_recoded);
206
g_free(priority_str);
208
if (server->usermode_away && server->away_reason == NULL)
209
server->away_reason = g_strdup(" ");
214
* XEP-0203: Delayed Delivery
215
* XEP-0091: Delayed Delivery (Obsolete)
218
#define MAX_LEN_TIMESTAMP 255
221
get_timestamp(LmMessageNode *node)
223
LmMessageNode *child;
225
char str[MAX_LEN_TIMESTAMP];
228
/* XEP-0203: Delayed Delivery
229
* <delay xmlns="urn:xmpp:delay" from="jid" stamp="stamp">jid</delay> */
230
if ((child = lm_tools_message_node_find(node, "x", XMLNS,
231
XMLNS_DELAYED_DELIVERY)) != NULL) {
233
stamp = lm_message_node_get_attribute(child, "stamp");
235
&& strptime(stamp, "%Y-%m-%dT%T", &tm) == NULL)
238
/* TODO handle timezone */
240
/* XEP-0091: Delayed Delivery (Obsolete)
241
* <x xmlns="jabber:x:delay" from="jid" stamp="stamp">jid</x> */
242
} else if ((child = lm_tools_message_node_find(node, "x", XMLNS,
243
XMLNS_DELAYED_DELIVERY_OLD)) != NULL) {
245
stamp = lm_message_node_get_attribute(child, "stamp");
247
&& strptime(stamp, "%Y%m%dT%T", &tm) == NULL)
253
if (strftime(str, MAX_LEN_TIMESTAMP,
254
settings_get_str("xmpp_timestamp_format"), &tm) == 0)
256
str[MAX_LEN_TIMESTAMP-1] = '\0';
257
return g_strdup(str);
262
* Incoming messages handlers
265
static LmHandlerResult
266
handle_message(LmMessageHandler *handler, LmConnection *connection,
267
LmMessage *msg, gpointer user_data)
269
XMPP_SERVER_REC *server;
270
XMPP_CHANNEL_REC *channel;
271
LmMessageNode *child, *subchild;
272
char *jid, *text, *stamp;
274
if ((server = XMPP_SERVER(user_data)) == NULL)
275
return LM_HANDLER_RESULT_REMOVE_MESSAGE;
277
jid = xmpp_recode_in(lm_message_node_get_attribute(msg->node, "from"));
279
switch (lm_message_get_sub_type(msg)) {
280
case LM_MESSAGE_SUB_TYPE_ERROR:
283
text = xmpp_extract_channel(jid);
284
channel = xmpp_channel_find(server, text);
286
if (channel != NULL) {
289
child = lm_message_node_get_child(msg->node, "error");
293
code = lm_message_node_get_attribute(child, "code");
297
if (g_ascii_strcasecmp(code, "401") == 0)
298
signal_emit("xmpp channel error", 2,
299
channel, "not allowed");
304
child = lm_message_node_get_child(msg->node, "body");
306
signal_emit("message xmpp error", 2, server, jid);
308
text = xmpp_recode_in(child->value);
309
signal_emit("message xmpp error", 3, server, jid,
317
case LM_MESSAGE_SUB_TYPE_NOT_SET:
318
if ((child = lm_tools_message_node_find(msg->node,
319
"x", XMLNS, XMLNS_MUC)) != NULL) {
322
if ((child = lm_message_node_get_child(child,
323
"invite")) != NULL) {
324
char *room, *by, *password, *reason;
329
subchild = lm_message_node_get_child(
330
child->parent, "password");
331
password = subchild == NULL ? NULL :
332
xmpp_recode_in(subchild->value);
334
subchild = lm_message_node_get_child(
336
reason = subchild == NULL ? NULL :
337
xmpp_recode_in(subchild->value);
339
to = lm_message_node_get_attribute(child,
342
room = xmpp_recode_in(to);
343
signal_emit("xmpp invite", 5, server,
344
room, jid, password, reason);
353
case LM_MESSAGE_SUB_TYPE_HEADLINE:
354
case LM_MESSAGE_SUB_TYPE_NORMAL:
355
case LM_MESSAGE_SUB_TYPE_CHAT:
356
/* rfc3921.txt states in 2.1.1. Types of Message:
357
* if an application receives a message with no 'type' attribute or the
358
* application does not understand the value of the 'type' attribute
359
* provided, it MUST consider the message to be of type "normal"
360
* Thus default belongs here, whre LM_MESSAGE_SUB_TYPE_NORMAL is
363
/* XEP-0022: Message Events */
364
child = lm_message_node_get_child(msg->node, "x");
366
XMPP_QUERY_REC *query;
368
subchild = lm_message_node_get_child(child,
371
query = xmpp_query_find(server, jid);
373
query->composing_visible = (subchild != NULL);
375
if (subchild != NULL)
376
signal_emit("xmpp composing show", 2, server,
379
signal_emit("xmpp composing hide", 2, server,
383
stamp = get_timestamp(msg->node);
385
/* <subject>text</subject> */
386
child = lm_message_node_get_child(msg->node, "subject");
387
if (child != NULL && child->value != NULL) {
388
text = xmpp_recode_in(child->value);
391
signal_emit("message xmpp history", 6,
392
server, text, jid, jid, stamp,
393
GINT_TO_POINTER(SEND_TARGET_NICK));
395
signal_emit("message private", 4, server,
401
/* <body>text</body> */
402
child = lm_message_node_get_child(msg->node, "body");
403
if (child != NULL && child->value != NULL) {
404
text = xmpp_recode_in(child->value);
407
if (g_ascii_strncasecmp(text, "/me ", 4) == 0)
409
"message xmpp history action", 6,
410
server, text+4, jid, jid, stamp,
411
GINT_TO_POINTER(SEND_TARGET_NICK));
413
signal_emit("message xmpp history", 6,
414
server, text, jid, jid, stamp,
415
GINT_TO_POINTER(SEND_TARGET_NICK));
417
if (g_ascii_strncasecmp(text, "/me ", 4) == 0)
418
signal_emit("message xmpp action", 5,
419
server, text+4, jid, jid,
420
GINT_TO_POINTER(SEND_TARGET_NICK));
422
signal_emit("message private", 4, server,
432
case LM_MESSAGE_SUB_TYPE_GROUPCHAT:
433
/* <subject>text</subject> */
434
child = lm_message_node_get_child(msg->node, "subject");
436
XMPP_CHANNEL_REC *channel;
437
char *channel_name, *nick;
439
channel_name = xmpp_extract_channel(jid);
440
nick = xmpp_extract_resource(jid);
442
channel = xmpp_channel_find(server, channel_name);
443
if (channel == NULL) {
444
g_free(channel_name);
449
text = xmpp_recode_in(child->value);
450
signal_emit("xmpp channel topic", 3, channel, text,
454
g_free(channel_name);
458
/* <body>text</body> */
459
child = lm_message_node_get_child(msg->node, "body");
460
if (child != NULL && child->value != NULL) {
461
XMPP_CHANNEL_REC *channel;
462
char *channel_name, *nick;
463
gboolean own, action;
465
channel_name = xmpp_extract_channel(jid);
466
nick = xmpp_extract_resource(jid);
468
g_free(channel_name);
472
channel = xmpp_channel_find(server, channel_name);
473
own = channel != NULL
474
&& strcmp(nick, channel->nick) == 0 ? TRUE : FALSE;
476
text = xmpp_recode_in(child->value);
477
action = g_ascii_strncasecmp(text, "/me ", 4) == 0 ?
479
stamp = get_timestamp(msg->node);
484
"message xmpp history action", 6,
485
server, text+4, nick, channel_name,
487
GINT_TO_POINTER(SEND_TARGET_CHANNEL));
489
signal_emit("message xmpp history", 6,
490
server, text, nick, channel_name,
492
GINT_TO_POINTER(SEND_TARGET_CHANNEL));
495
signal_emit("message xmpp own_action", 4,
496
server, text+4, channel_name,
497
GINT_TO_POINTER(SEND_TARGET_CHANNEL));
499
signal_emit("message xmpp own_public", 3,
500
server, text, channel_name);
503
signal_emit("message xmpp action", 5,
504
server, text+4, nick, channel_name,
505
GINT_TO_POINTER(SEND_TARGET_CHANNEL));
507
signal_emit("message public", 5,
508
server, text, nick, "",
514
g_free(channel_name);
523
return LM_HANDLER_RESULT_REMOVE_MESSAGE;
526
static LmHandlerResult
527
handle_presence(LmMessageHandler *handler, LmConnection *connection,
528
LmMessage *msg, gpointer user_data)
530
XMPP_SERVER_REC *server;
531
XMPP_CHANNEL_REC *channel;
532
LmMessageNode *child, *subchild, *show, *priority;
535
if ((server = XMPP_SERVER(user_data)) == NULL)
536
return LM_HANDLER_RESULT_REMOVE_MESSAGE;
538
jid = xmpp_recode_in(lm_message_node_get_attribute(msg->node, "from"));
540
switch (lm_message_get_sub_type(msg)) {
541
case LM_MESSAGE_SUB_TYPE_ERROR:
544
text = xmpp_extract_channel(jid);
545
channel = xmpp_channel_find(server, text);
547
if (channel != NULL) {
549
char *nick = xmpp_extract_nick(jid);
551
/* <error code='code'/> */
552
child = lm_message_node_get_child(msg->node, "error");
555
code = lm_message_node_get_attribute(child, "code");
559
if (!channel->joined) {
560
/* <error code='401'/> */
561
if (strcmp(code, "401") == 0)
562
signal_emit("xmpp channel joinerror", 2,
563
channel, XMPP_CHANNELS_ERROR_PASSWORD_INVALID_OR_MISSING);
564
/* <error code='403'/> */
565
else if (strcmp(code, "403") == 0)
566
signal_emit("xmpp channel joinerror", 2,
567
channel, XMPP_CHANNELS_ERROR_USER_BANNED);
568
/* <error code='404'/> */
569
else if (strcmp(code, "404") == 0)
570
signal_emit("xmpp channel joinerror", 2,
571
channel, XMPP_CHANNELS_ERROR_ROOM_NOT_FOUND);
572
/* <error code='405'/> */
573
else if (strcmp(code, "405") == 0)
574
signal_emit("xmpp channel joinerror", 2,
575
channel, XMPP_CHANNELS_ERROR_ROOM_CREATION_RESTRICTED);
576
/* <error code='406'/> */
577
else if (strcmp(code, "406") == 0)
578
signal_emit("xmpp channel joinerror", 2,
579
channel, XMPP_CHANNELS_ERROR_USE_RESERVED_ROOM_NICK);
580
/* <error code='407'/> */
581
else if (strcmp(code, "407") == 0)
582
signal_emit("xmpp channel joinerror", 2,
583
channel, XMPP_CHANNELS_ERROR_NOT_ON_MEMBERS_LIST);
584
/* <error code='409'/> */
585
else if (strcmp(code, "409") == 0)
586
signal_emit("xmpp channel joinerror", 2,
587
channel, XMPP_CHANNELS_ERROR_NICK_IN_USE);
588
/* <error code='503'/> */
589
else if (strcmp(code, "503") == 0)
590
signal_emit("xmpp channel joinerror", 2,
591
channel, XMPP_CHANNELS_ERROR_MAXIMUM_USERS_REACHED);
593
/* <error code='409'/> */
594
if (strcmp(code, "409") == 0)
595
signal_emit("message xmpp channel nick in use",
603
signal_emit("xmpp presence error", 2, server, jid);
607
case LM_MESSAGE_SUB_TYPE_SUBSCRIBE:
608
/* <status>text</status> */
609
child = lm_message_node_get_child(msg->node, "status");
610
text = (child != NULL) ? xmpp_recode_in(child->value) : NULL;
611
signal_emit("xmpp presence subscribe", 3, server, jid, text);
615
case LM_MESSAGE_SUB_TYPE_UNSUBSCRIBE:
616
signal_emit("xmpp presence unsubscribe", 2, server, jid);
619
case LM_MESSAGE_SUB_TYPE_SUBSCRIBED:
620
signal_emit("xmpp presence subscribed", 2, server, jid);
623
case LM_MESSAGE_SUB_TYPE_UNSUBSCRIBED:
624
signal_emit("xmpp presence unsubscribed", 2, server, jid);
627
case LM_MESSAGE_SUB_TYPE_AVAILABLE:
630
text = xmpp_extract_channel(jid);
631
channel = xmpp_channel_find(server, text);
633
if (channel != NULL) {
634
const char *item_affiliation, *item_role;
635
char *nick, *item_jid, *item_nick;
636
gboolean own, forced, created;
638
nick = xmpp_extract_nick(jid);
639
item_affiliation = item_role = NULL;
640
item_jid = item_nick = NULL;
641
own = forced = created = FALSE;
643
/* <x xmlns='http://jabber.org/protocol/muc#user'> */
644
child = lm_tools_message_node_find(msg->node, "x",
645
XMLNS, XMLNS_MUC_USER);
648
if ((subchild = lm_message_node_get_child(
649
child, "item")) != NULL) {
650
/* <item affiliation='item_affiliation'
652
* nick='item_nick'/> */
654
lm_message_node_get_attribute(
655
subchild, "affiliation");
657
lm_message_node_get_attribute(
659
item_jid = xmpp_recode_in(
660
lm_message_node_get_attribute(
662
item_nick = xmpp_recode_in(
663
lm_message_node_get_attribute(
666
/* <status code='110'/> */
667
own = lm_tools_message_node_find(
668
child, "status", "code", "110")
669
!= NULL ? TRUE : FALSE;
670
/* <status code='210'/> */
671
forced = lm_tools_message_node_find(
672
child, "status", "code", "210")
673
!= NULL ? TRUE : FALSE;
674
/* <status code='201'/> */
675
created = lm_tools_message_node_find(
676
child, "status", "code", "201")
677
!= NULL ? TRUE : FALSE;
681
if (item_nick != NULL) {
688
* show event IRCTXT_CHANNEL_CREATED */
691
if (own || strcmp(nick, channel->nick) == 0)
692
signal_emit("xmpp channel nick own_event", 6,
693
channel, nick, item_jid, item_affiliation,
696
signal_emit("xmpp channel nick event", 5,
697
channel, nick, item_jid, item_affiliation,
700
/* <status>text</status> */
701
child = lm_message_node_get_child(msg->node, "status");
702
text = child != NULL ?
703
xmpp_recode_in(child->value) : NULL;
704
/* <show>show</show> */
705
show = lm_message_node_get_child(msg->node, "show");
707
signal_emit("xmpp channel nick presence", 4, channel,
708
nick, (show != NULL) ? show->value : NULL, text);
716
/* <status>text</status> */
717
child = lm_message_node_get_child(msg->node, "status");
718
text = (child != NULL) ?
719
xmpp_recode_in(child->value) : NULL;
720
/* <show>show</show> */
721
show = lm_message_node_get_child(msg->node, "show");
722
/* <priority>priority</priority> */
723
priority = lm_message_node_get_child(msg->node,
726
signal_emit("xmpp presence update", 5, server, jid,
727
(show != NULL) ? show->value : NULL, text,
728
(priority != NULL) ? priority->value : NULL);
735
case LM_MESSAGE_SUB_TYPE_UNAVAILABLE:
738
text = xmpp_extract_channel(jid);
739
channel = xmpp_channel_find(server, text);
741
if (channel != NULL) {
742
const char *status_code;
743
char *nick, *reason, *actor, *item_nick;
745
nick = xmpp_extract_nick(jid);
747
reason = actor = item_nick = NULL;
749
/* <x xmlns='http://jabber.org/protocol/muc#user'> */
750
child = lm_tools_message_node_find(msg->node, "x",
751
XMLNS, XMLNS_MUC_USER);
754
/* <status code='status_code'/> */
755
if ((subchild = lm_message_node_get_child(
756
child, "status")) != NULL)
758
lm_message_node_get_attribute(
761
/* <item nick='item_nick'> */
762
if ((child = lm_message_node_get_child(
763
child, "item")) != NULL) {
764
item_nick = xmpp_recode_in(
765
lm_message_node_get_attribute(
768
/* <reason>reason</reason>*/
770
lm_message_node_get_child(child,
772
reason = xmpp_recode_in(
775
/* <actor jid='actor'/> */
777
lm_message_node_get_child(child,
779
actor = xmpp_recode_in(
780
lm_message_node_get_attribute(
785
if (status_code != NULL) {
787
/* <status code='303'/> */
788
if (g_ascii_strcasecmp(status_code,
789
"303") == 0 && item_nick != NULL)
790
signal_emit("xmpp channel nick",
791
5, channel, nick, item_nick);
793
/* <status code='307'/> */
794
else if (g_ascii_strcasecmp(status_code,
796
signal_emit("xmpp channel nick kicked",
797
4, channel, nick, actor, reason);
799
/* ban: <status code='301'/> */
800
else if (g_ascii_strcasecmp(status_code,
802
signal_emit("xmpp channel nick kicked",
803
4, channel, nick, actor, reason);
806
/* <status>text</status> */
807
child = lm_message_node_get_child(msg->node,
809
text = (child != NULL) ?
810
xmpp_recode_in(child->value) : NULL;
812
signal_emit("xmpp channel nick part", 3,
813
channel, nick, text);
825
/* <status>text</status> */
826
child = lm_message_node_get_child(msg->node, "status");
827
text = (child != NULL) ?
828
xmpp_recode_in(child->value) : NULL;
830
signal_emit("xmpp presence unavailable", 3, server,
844
return LM_HANDLER_RESULT_REMOVE_MESSAGE;
847
static LmHandlerResult
848
handle_iq(LmMessageHandler *handler, LmConnection *connection,
849
LmMessage *msg, gpointer user_data)
851
XMPP_SERVER_REC *server;
852
XMPP_CHANNEL_REC *channel;
853
LmMessageNode *child;
857
if ((server = XMPP_SERVER(user_data)) == NULL)
858
return LM_HANDLER_RESULT_REMOVE_MESSAGE;
860
jid = xmpp_recode_in(lm_message_node_get_attribute(msg->node, "from"));
861
id = lm_message_node_get_attribute(msg->node, "id");
863
switch (lm_message_get_sub_type(msg)) {
864
case LM_MESSAGE_SUB_TYPE_ERROR:
865
if ((child = lm_message_node_get_child(msg->node,
869
if ((code = lm_message_node_get_attribute(child,
874
text = xmpp_extract_channel(jid);
875
channel = xmpp_channel_find(server, text);
877
if (channel != NULL) {
889
case LM_MESSAGE_SUB_TYPE_GET:
890
/* XEP-0092: Software Version */
891
if (lm_tools_message_node_find(msg->node,
892
"query", XMLNS, XMLNS_VERSION) != NULL)
893
xep_version_send(server, jid, id);
896
/* <service-unavailable/> */
897
send_service_unavailable(server, jid, id);
901
case LM_MESSAGE_SUB_TYPE_RESULT:
902
if ((child = lm_tools_message_node_find(msg->node,
903
"query", XMLNS, XMLNS_ROSTER)) != NULL)
904
signal_emit("xmpp roster update", 2, server, child);
906
/* XEP-0092: Software Version */
907
else if ((child = lm_tools_message_node_find(msg->node,
908
"query", XMLNS, XMLNS_VERSION)) != NULL)
909
xep_version_handle(server, jid, child);
911
/* XEP-0054: vcard-temp */
912
else if ((child = lm_tools_message_node_find(msg->node,
913
"vCard", XMLNS, XMLNS_VCARD)) != NULL)
914
xep_vcard_handle(server, jid, child);
916
/* XEP-0030: Service Discovery */
917
else if ((child = lm_tools_message_node_find(msg->node,
918
"query", XMLNS, XMLNS_DISCO_INFO)) != NULL) {
921
text = xmpp_extract_channel(jid);
922
channel = xmpp_channel_find(server, text);
925
signal_emit("xmpp channel disco", 2, channel,
929
else if (strcmp(jid, server->host) == 0)
930
signal_emit("xmpp server disco", 2, server,
939
/* XEP-0199: XMPP Ping */
940
signal_emit("xmpp ping handle", 3, server, jid,
941
lm_message_node_get_attribute(msg->node, "id"));
945
case LM_MESSAGE_SUB_TYPE_SET :
946
if ((child = lm_tools_message_node_find(msg->node,
947
"query", XMLNS, XMLNS_ROSTER)) != NULL)
948
signal_emit("xmpp roster update", 2, server, child);
958
return LM_HANDLER_RESULT_REMOVE_MESSAGE;
962
unregister_handlers(XMPP_SERVER_REC *server)
964
if (!IS_XMPP_SERVER(server))
967
/* unregister handlers */
968
if (server->hmessage != NULL) {
969
if (lm_message_handler_is_valid(server->hmessage))
970
lm_message_handler_invalidate(server->hmessage);
971
lm_message_handler_unref(server->hmessage);
972
server->hmessage = NULL;
975
if (server->hpresence != NULL) {
976
if (lm_message_handler_is_valid(server->hpresence))
977
lm_message_handler_invalidate(server->hpresence);
978
lm_message_handler_unref(server->hpresence);
979
server->hpresence = NULL;
982
if (server->hiq != NULL) {
983
if (lm_message_handler_is_valid(server->hiq))
984
lm_message_handler_invalidate(server->hiq);
985
lm_message_handler_unref(server->hiq);
991
register_handlers(XMPP_SERVER_REC *server)
993
if (!IS_XMPP_SERVER(server))
996
if (server->hmessage != NULL || server->hpresence != NULL ||
998
unregister_handlers(server);
1000
/* handle message */
1001
server->hmessage = lm_message_handler_new(
1002
(LmHandleMessageFunction)handle_message, (gpointer)server,
1004
lm_connection_register_message_handler(server->lmconn,
1005
server->hmessage, LM_MESSAGE_TYPE_MESSAGE,
1006
LM_HANDLER_PRIORITY_NORMAL);
1008
/* handle presence */
1009
server->hpresence = lm_message_handler_new(
1010
(LmHandleMessageFunction)handle_presence, (gpointer)server,
1012
lm_connection_register_message_handler(server->lmconn,
1013
server->hpresence, LM_MESSAGE_TYPE_PRESENCE,
1014
LM_HANDLER_PRIORITY_NORMAL);
1017
server->hiq = lm_message_handler_new(
1018
(LmHandleMessageFunction)handle_iq, (gpointer)server,
1020
lm_connection_register_message_handler(server->lmconn,
1021
server->hiq, LM_MESSAGE_TYPE_IQ,
1022
LM_HANDLER_PRIORITY_NORMAL);
1024
if (settings_get_bool("xmpp_raw_window"))
1025
signal_emit("xmpp register raw handler", 1, server);
1028
static LmHandlerResult
1029
handle_raw(LmMessageHandler *handler, LmConnection *connection,
1030
LmMessage *msg, gpointer user_data)
1032
char *text = xmpp_recode_in(lm_message_node_to_string(msg->node));
1033
signal_emit("xmpp raw in", 2, user_data, text);
1035
return LM_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
1039
unregister_raw_handler(XMPP_SERVER_REC *server)
1041
if (!IS_XMPP_SERVER(server) || server->hraw == NULL)
1044
if (lm_message_handler_is_valid(server->hraw))
1045
lm_message_handler_invalidate(server->hraw);
1046
lm_message_handler_unref(server->hraw);
1047
server->hraw = NULL;
1051
register_raw_handler(XMPP_SERVER_REC *server)
1053
if (!IS_XMPP_SERVER(server) || server->hraw != NULL)
1057
server->hraw = lm_message_handler_new(
1058
(LmHandleMessageFunction)handle_raw, (gpointer)server,
1060
lm_connection_register_message_handler(server->lmconn,
1061
server->hraw, LM_MESSAGE_TYPE_MESSAGE,
1062
LM_HANDLER_PRIORITY_FIRST);
1063
lm_connection_register_message_handler(server->lmconn,
1064
server->hraw, LM_MESSAGE_TYPE_PRESENCE,
1065
LM_HANDLER_PRIORITY_FIRST);
1066
lm_connection_register_message_handler(server->lmconn,
1067
server->hraw, LM_MESSAGE_TYPE_IQ,
1068
LM_HANDLER_PRIORITY_FIRST);
1072
xmpp_protocol_init(void)
1074
signal_add_first("server connected",
1075
(SIGNAL_FUNC)register_handlers);
1076
signal_add_first("server disconnected",
1077
(SIGNAL_FUNC)unregister_handlers);
1078
signal_add("xmpp register raw handler",
1079
(SIGNAL_FUNC)register_raw_handler);
1080
signal_add("xmpp unregister raw handler",
1081
(SIGNAL_FUNC)unregister_raw_handler);
1082
signal_add_first("xmpp own_presence", (SIGNAL_FUNC)sig_own_presence);
1083
signal_add_first("xmpp server disco",
1084
(SIGNAL_FUNC)xep_disco_server);
1085
signal_add("xmpp composing start", (SIGNAL_FUNC)xep_composing_start);
1086
signal_add("xmpp composing stop", (SIGNAL_FUNC)xep_composing_stop);
1088
settings_add_int("xmpp", "xmpp_priority", 0);
1089
settings_add_bool("xmpp", "xmpp_send_version", TRUE);
1090
settings_add_bool("xmpp_lookandfeel", "xmpp_raw_window", FALSE);
1091
settings_add_str("xmpp_lookandfeel", "xmpp_timestamp_format",
1096
xmpp_protocol_deinit(void)
1098
signal_remove("server connected",
1099
(SIGNAL_FUNC)register_handlers);
1100
signal_remove("server disconnected",
1101
(SIGNAL_FUNC)register_handlers);
1102
signal_remove("xmpp register raw handler",
1103
(SIGNAL_FUNC)register_raw_handler);
1104
signal_remove("xmpp unregister raw handler",
1105
(SIGNAL_FUNC)unregister_raw_handler);
1106
signal_remove("xmpp own_presence", (SIGNAL_FUNC)sig_own_presence);
1107
signal_remove("xmpp server disco", (SIGNAL_FUNC)xep_disco_server);
1108
signal_remove("xmpp composing start", (SIGNAL_FUNC)xep_composing_start);
1109
signal_remove("xmpp composing stop", (SIGNAL_FUNC)xep_composing_stop);