~ubuntu-branches/ubuntu/trusty/irssi-plugin-xmpp/trusty-proposed

« back to all changes in this revision

Viewing changes to .pc/singpolyma-0011-Fix-some-potential-crashing-issues.patch/src/core/rosters.c

  • Committer: Package Import Robot
  • Author(s): Florian Schlichting, Florian Schlichting
  • Date: 2014-01-03 00:25:20 UTC
  • mfrom: (1.3.6)
  • Revision ID: package-import@ubuntu.com-20140103002520-zc3sfydzt1wp03i0
Tags: 0.52+git20140102-1
[ Florian Schlichting ]
* Import Upstream version 0.52+git20140102
* Add VCS-* fields for collab-maint on alioth
* Add upstream git URL to Source field in debian/copyright
* Drop patches plucked from upstream CVS
* Refresh hardening.patch (offset, drop hunk fixed upstream)
* Provide xmpp-admin.pl script by Seth Difley
* Add GTalk-MUC-support.patch, plucked from github/freemandrew
* Add support for XMPP-PGP, plucked from github/singpolyma
* New useless-dependency-on-libidn.patch, to fix a lintian warning
* Declare compliance with Debian Policy 3.9.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2007 Colin DIDIER
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License version 2 as
 
6
 * published by the Free Software Foundation.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful,
 
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
 * GNU General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU General Public License along
 
14
 * with this program; if not, write to the Free Software Foundation, Inc.,
 
15
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
16
 */
 
17
 
 
18
#include <stdlib.h>
 
19
#include <string.h>
 
20
 
 
21
#include "module.h"
 
22
#include "signals.h"
 
23
 
 
24
#include "xmpp-servers.h"
 
25
#include "rosters-tools.h"
 
26
#include "tools.h"
 
27
 
 
28
#define XMLNS_ROSTER "jabber:iq:roster"
 
29
 
 
30
const char *xmpp_presence_show[] = {
 
31
        "-",
 
32
        "X",
 
33
        "xa",
 
34
        "dnd",
 
35
        "away",
 
36
        "+",
 
37
        "chat",
 
38
        "online",
 
39
        NULL
 
40
};
 
41
 
 
42
const char *xmpp_subscription[] = {
 
43
        "remove",
 
44
        "none",
 
45
        "to",
 
46
        "from",
 
47
        "both",
 
48
        NULL
 
49
};
 
50
 
 
51
static int
 
52
func_find_group(gconstpointer group, gconstpointer name)
 
53
{
 
54
        char *group_name;
 
55
 
 
56
        group_name = ((XMPP_ROSTER_GROUP_REC *)group)->name;
 
57
        if (group_name == name)
 
58
                return 0;
 
59
        if (group_name == NULL || name == NULL)
 
60
                return -1;
 
61
        return strcmp(group_name, name);
 
62
}
 
63
 
 
64
static int
 
65
func_sort_group(gconstpointer group1, gconstpointer group2)
 
66
{
 
67
        char *group1_name, *group2_name;
 
68
 
 
69
        group1_name = ((XMPP_ROSTER_GROUP_REC *)group1)->name;
 
70
        group2_name = ((XMPP_ROSTER_GROUP_REC *)group2)->name;
 
71
        if (group1_name == NULL)
 
72
                return -1;
 
73
        if (group2_name == NULL)
 
74
                 return 1;
 
75
        return strcmp(group1_name, group2_name);
 
76
}
 
77
 
 
78
static int
 
79
func_sort_resource(gconstpointer resource1_ptr, gconstpointer resource2_ptr)
 
80
{
 
81
        int cmp;
 
82
        XMPP_ROSTER_RESOURCE_REC *resource1, *resource2;
 
83
 
 
84
        resource1 = (XMPP_ROSTER_RESOURCE_REC *)resource1_ptr;
 
85
        resource2 = (XMPP_ROSTER_RESOURCE_REC *)resource2_ptr;
 
86
        if ((cmp = resource2->priority - resource1->priority) == 0
 
87
            && (cmp = resource2->show - resource1->show) == 0)
 
88
                return strcmp(resource1->name, resource2->name);
 
89
        return cmp;
 
90
}
 
91
 
 
92
static int
 
93
func_sort_user_by_name(XMPP_ROSTER_USER_REC *user1, XMPP_ROSTER_USER_REC *user2)
 
94
{
 
95
        if (user1->name == NULL && user2->name != NULL)
 
96
                return strcmp(user1->jid, user2->name);
 
97
        if (user1->name != NULL && user2->name == NULL)
 
98
                return strcmp(user1->name, user2->jid);
 
99
        if (user1->name != NULL && user2->name != NULL)
 
100
                return strcmp(user1->name, user2->name);
 
101
        return strcmp(user1->jid, user2->jid);
 
102
}
 
103
 
 
104
static int
 
105
func_sort_user(gconstpointer user1_ptr, gconstpointer user2_ptr)
 
106
{
 
107
        GSList *resources1_list, *resources2_list;
 
108
        XMPP_ROSTER_USER_REC *user1, *user2;
 
109
        XMPP_ROSTER_RESOURCE_REC *fisrt_resources1, *fisrt_resources2;
 
110
 
 
111
        user1 = (XMPP_ROSTER_USER_REC *)user1_ptr;
 
112
        resources1_list = user1->resources;
 
113
        user2 = (XMPP_ROSTER_USER_REC *)user2_ptr;
 
114
        resources2_list = user2->resources;
 
115
        if (resources1_list == NULL && resources2_list == NULL
 
116
            && user1->error == user2->error)
 
117
                return func_sort_user_by_name(user1, user2);
 
118
        if (user1->error || resources1_list == NULL)
 
119
                return 1;
 
120
        if (user2->error || resources2_list == NULL)
 
121
                return -1;
 
122
        fisrt_resources1 = (XMPP_ROSTER_RESOURCE_REC *)resources1_list->data;
 
123
        fisrt_resources2 = (XMPP_ROSTER_RESOURCE_REC *)resources2_list->data;
 
124
        if (fisrt_resources1->show == fisrt_resources2->show)
 
125
                return func_sort_user_by_name(user1, user2);
 
126
        return fisrt_resources2->show - fisrt_resources1->show;
 
127
}
 
128
 
 
129
static XMPP_ROSTER_RESOURCE_REC *
 
130
create_resource(const char *name)
 
131
{
 
132
        XMPP_ROSTER_RESOURCE_REC *resource;
 
133
 
 
134
        resource = g_new(XMPP_ROSTER_RESOURCE_REC, 1);
 
135
        resource->name = g_strdup(name == NULL ? "" : name);
 
136
        resource->priority = 0;
 
137
        resource->show= XMPP_PRESENCE_UNAVAILABLE;
 
138
        resource->status = NULL;
 
139
        resource->composing_id = NULL;
 
140
        resource->pgp_keyid = NULL;
 
141
        resource->pgp_encrypt = 0;
 
142
        return resource;
 
143
}
 
144
 
 
145
static void
 
146
cleanup_resource(gpointer data, gpointer user_data)
 
147
{
 
148
        XMPP_ROSTER_RESOURCE_REC *resource;
 
149
        
 
150
        if (data == NULL)
 
151
                return;
 
152
        resource = (XMPP_ROSTER_RESOURCE_REC *)data;
 
153
        g_free(resource->name);
 
154
        g_free(resource->status);
 
155
        g_free(resource->composing_id);
 
156
        if(resource->pgp_keyid) free(resource->pgp_keyid);
 
157
        g_free(resource);
 
158
}
 
159
 
 
160
static XMPP_ROSTER_USER_REC *
 
161
create_user(const char *jid, const char *name)
 
162
{
 
163
        XMPP_ROSTER_USER_REC *user;
 
164
 
 
165
        g_return_val_if_fail(jid != NULL, NULL);
 
166
        user = g_new(XMPP_ROSTER_USER_REC, 1);
 
167
        user->jid = g_strdup(jid);
 
168
        user->name = g_strdup(name);
 
169
        user->subscription = XMPP_SUBSCRIPTION_NONE;
 
170
        user->error = FALSE;
 
171
        user->resources = NULL;
 
172
        return user;
 
173
}
 
174
 
 
175
static void
 
176
cleanup_user(gpointer data, gpointer user_data)
 
177
{
 
178
        XMPP_ROSTER_USER_REC *user;
 
179
   
 
180
        if (data == NULL)
 
181
                return;
 
182
        user = (XMPP_ROSTER_USER_REC *)data;
 
183
        g_slist_foreach(user->resources, cleanup_resource, NULL);
 
184
        g_slist_free(user->resources);
 
185
        g_free(user->name);
 
186
        g_free(user->jid);
 
187
        g_free(user);
 
188
}
 
189
 
 
190
static XMPP_ROSTER_GROUP_REC *
 
191
create_group(const char *name)
 
192
{
 
193
        XMPP_ROSTER_GROUP_REC *group;
 
194
 
 
195
        group = g_new(XMPP_ROSTER_GROUP_REC, 1);
 
196
        group->name = g_strdup(name);
 
197
        group->users = NULL;
 
198
        return group;
 
199
}
 
200
 
 
201
static void
 
202
cleanup_group(gpointer data, gpointer user_data)
 
203
{
 
204
        XMPP_ROSTER_GROUP_REC *group;
 
205
 
 
206
        if (data == NULL)
 
207
                return;
 
208
        group = (XMPP_ROSTER_GROUP_REC *)data;
 
209
        g_slist_foreach(group->users, cleanup_user, group);
 
210
        g_slist_free(group->users);
 
211
        g_free(group->name);
 
212
        g_free(group);
 
213
}
 
214
 
 
215
static void
 
216
roster_cleanup(XMPP_SERVER_REC *server)
 
217
{
 
218
        if (!IS_XMPP_SERVER(server) || server->roster == NULL)
 
219
                return;
 
220
        g_slist_foreach(server->roster, cleanup_group, server);
 
221
        g_slist_free(server->roster);
 
222
        server->roster = NULL;
 
223
        g_slist_foreach(server->my_resources, cleanup_resource, NULL);
 
224
        g_slist_free(server->my_resources);
 
225
        server->my_resources = NULL;
 
226
}
 
227
 
 
228
static XMPP_ROSTER_GROUP_REC *
 
229
find_or_add_group(XMPP_SERVER_REC *server, const char *group_name)
 
230
{
 
231
        GSList *group_list;
 
232
        XMPP_ROSTER_GROUP_REC *group;
 
233
 
 
234
        g_return_val_if_fail(IS_XMPP_SERVER(server), NULL);
 
235
        group_list = g_slist_find_custom(server->roster, group_name,
 
236
            func_find_group);
 
237
        if (group_list == NULL) {
 
238
                group = create_group(group_name);
 
239
                server->roster = g_slist_insert_sorted(server->roster, group,
 
240
                    func_sort_group);
 
241
        } else 
 
242
                group = group_list->data;
 
243
        return group;
 
244
}
 
245
 
 
246
static XMPP_ROSTER_USER_REC *
 
247
add_user(XMPP_SERVER_REC *server, const char *jid, const char *name,
 
248
    const char *group_name, XMPP_ROSTER_GROUP_REC **return_group)
 
249
{
 
250
        XMPP_ROSTER_GROUP_REC *group;
 
251
        XMPP_ROSTER_USER_REC *user;
 
252
 
 
253
        g_return_val_if_fail(IS_XMPP_SERVER(server), NULL);
 
254
        g_return_val_if_fail(jid != NULL, NULL);
 
255
        group = find_or_add_group(server, group_name);
 
256
        user = create_user(jid, name);
 
257
        group->users = g_slist_append(group->users, user);
 
258
        if (return_group != NULL)
 
259
                *return_group = group;
 
260
        return user;
 
261
}
 
262
 
 
263
static XMPP_ROSTER_GROUP_REC *
 
264
move_user(XMPP_SERVER_REC *server, XMPP_ROSTER_USER_REC *user,
 
265
    XMPP_ROSTER_GROUP_REC *group, const char *group_name)
 
266
{
 
267
        XMPP_ROSTER_GROUP_REC *new_group;
 
268
 
 
269
        g_return_val_if_fail(IS_XMPP_SERVER(server), group);
 
270
        g_return_val_if_fail(user != NULL, group);
 
271
        new_group = find_or_add_group(server, group_name);
 
272
        group->users = g_slist_remove(group->users, user);
 
273
        new_group->users = g_slist_append(new_group->users, user);
 
274
        return new_group;
 
275
}
 
276
 
 
277
static void
 
278
update_subscription(XMPP_SERVER_REC *server, XMPP_ROSTER_USER_REC *user,
 
279
    XMPP_ROSTER_GROUP_REC *group, const char *subscription)
 
280
{
 
281
        g_return_if_fail(IS_XMPP_SERVER(server));
 
282
        g_return_if_fail(user != NULL);
 
283
        g_return_if_fail(group != NULL);
 
284
        g_return_if_fail(subscription != NULL);
 
285
        if (g_ascii_strcasecmp(subscription,
 
286
            xmpp_subscription[XMPP_SUBSCRIPTION_NONE]) == 0)
 
287
                user->subscription = XMPP_SUBSCRIPTION_NONE;
 
288
        else if (g_ascii_strcasecmp(subscription,
 
289
            xmpp_subscription[XMPP_SUBSCRIPTION_FROM]) == 0)
 
290
                user->subscription = XMPP_SUBSCRIPTION_FROM;
 
291
        else if (g_ascii_strcasecmp(subscription,
 
292
            xmpp_subscription[XMPP_SUBSCRIPTION_TO]) == 0)
 
293
                user->subscription = XMPP_SUBSCRIPTION_TO;
 
294
        else if (g_ascii_strcasecmp(subscription,
 
295
            xmpp_subscription[XMPP_SUBSCRIPTION_BOTH]) == 0)
 
296
                user->subscription = XMPP_SUBSCRIPTION_BOTH;
 
297
        else if (g_ascii_strcasecmp(subscription,
 
298
            xmpp_subscription[XMPP_SUBSCRIPTION_REMOVE]) == 0) {
 
299
                group->users = g_slist_remove(group->users, user);
 
300
                cleanup_user(user, server);
 
301
                /* remove empty group */
 
302
                if (group->users == NULL) {
 
303
                        server->roster = g_slist_remove(server->roster, group);
 
304
                        cleanup_group(group, server);
 
305
                }
 
306
        }
 
307
}
 
308
 
 
309
static void
 
310
update_user(XMPP_SERVER_REC *server, const char *jid, const char *subscription,
 
311
    const char *name, const char *group_name)
 
312
{
 
313
        XMPP_ROSTER_GROUP_REC *group;
 
314
        XMPP_ROSTER_USER_REC *user;
 
315
 
 
316
        g_return_if_fail(IS_XMPP_SERVER(server));
 
317
        g_return_if_fail(jid != NULL);
 
318
        user = rosters_find_user(server->roster, jid, &group, NULL);
 
319
        if (user == NULL)
 
320
                user = add_user(server, jid, name, group_name, &group);
 
321
        else {
 
322
                /* move to another group and sort it */
 
323
                if ((group->name == NULL && group_name != NULL)
 
324
                    || (group->name != NULL && group_name == NULL)
 
325
                    || (group->name != NULL && group_name != NULL
 
326
                    && strcmp(group->name, group_name) != 0)) {
 
327
                        group = move_user(server, user, group, group_name);
 
328
                        group->users = g_slist_sort(group->users,
 
329
                            func_sort_user);
 
330
                }
 
331
                /* change name */
 
332
                if ((user->name == NULL && name != NULL)
 
333
                    || (user->name != NULL && name == NULL)
 
334
                    || (user->name != NULL && name != NULL
 
335
                    && strcmp(user->name, name) != 0)) {
 
336
                        g_free(user->name);
 
337
                        user->name = g_strdup(name);
 
338
                        group->users = g_slist_sort(group->users,
 
339
                            func_sort_user);
 
340
                }
 
341
        }
 
342
        update_subscription(server, user, group, subscription);
 
343
}
 
344
 
 
345
static void
 
346
update_user_presence(XMPP_SERVER_REC *server, const char *full_jid,
 
347
    const char *show_str, const char *status, const char *priority_str,
 
348
    char *pgp_keyid)
 
349
{
 
350
        XMPP_ROSTER_GROUP_REC *group;
 
351
        XMPP_ROSTER_USER_REC *user;
 
352
        XMPP_ROSTER_RESOURCE_REC *resource;
 
353
        char *jid, *res;
 
354
        int show, priority;
 
355
        gboolean new, own;
 
356
 
 
357
        g_return_if_fail(IS_XMPP_SERVER(server));
 
358
        g_return_if_fail(full_jid != NULL);
 
359
        new = own = FALSE;
 
360
        jid = xmpp_strip_resource(full_jid);
 
361
        res = xmpp_extract_resource(full_jid);
 
362
        user = rosters_find_user(server->roster, jid, &group, NULL);
 
363
        if (user == NULL) {
 
364
                if (!(own = strcmp(jid, server->jid) == 0
 
365
                     && strcmp(res, server->resource) != 0))
 
366
                        goto out;
 
367
        } else
 
368
                user->error = FALSE;
 
369
        /* find resource or create it if it doesn't exist */    
 
370
        resource = rosters_find_resource(!own ?
 
371
            user->resources : server->my_resources, res);
 
372
        if (resource == NULL) {
 
373
                resource = create_resource(res);
 
374
                new = TRUE;
 
375
                if (!own)
 
376
                        user->resources =
 
377
                            g_slist_prepend(user->resources, resource);
 
378
                else
 
379
                        server->my_resources =
 
380
                            g_slist_prepend(server->my_resources, resource);
 
381
                signal_emit("xmpp presence online", 4, server, full_jid,
 
382
                    jid, res);
 
383
        }
 
384
        show = xmpp_get_show(show_str);
 
385
        priority = (priority_str != NULL) ?
 
386
            atoi(priority_str) : resource->priority;
 
387
        if (new || xmpp_presence_changed(show, resource->show, status,
 
388
            resource->status, priority, resource->priority)) {
 
389
                resource->show = show;
 
390
                resource->status = g_strdup(status);
 
391
                resource->priority = priority;
 
392
                resource->pgp_keyid = pgp_keyid;
 
393
                if (!own) {
 
394
                        user->resources = g_slist_sort(
 
395
                            user->resources, func_sort_resource);
 
396
                        group->users = g_slist_sort(group->users,
 
397
                            func_sort_user);
 
398
                } else
 
399
                        server->my_resources = g_slist_sort(
 
400
                            server->my_resources, func_sort_resource);
 
401
                signal_emit("xmpp presence changed", 4, server, full_jid,
 
402
                    resource->show, resource->status);
 
403
        }
 
404
 
 
405
out:
 
406
        g_free(jid);
 
407
        g_free(res);
 
408
}
 
409
 
 
410
static void
 
411
user_unavailable(XMPP_SERVER_REC *server, const char *full_jid,
 
412
    const char *status)
 
413
{
 
414
        XMPP_ROSTER_GROUP_REC *group;
 
415
        XMPP_ROSTER_USER_REC *user;
 
416
        XMPP_ROSTER_RESOURCE_REC *resource;
 
417
        char *jid, *res;
 
418
        gboolean own;
 
419
 
 
420
        g_return_if_fail(IS_XMPP_SERVER(server));
 
421
        g_return_if_fail(full_jid != NULL);
 
422
        own = FALSE;
 
423
        jid = xmpp_strip_resource(full_jid);
 
424
        res = xmpp_extract_resource(full_jid);
 
425
        user = rosters_find_user(server->roster, jid, &group, NULL);
 
426
        if (user == NULL) {
 
427
                if (!(own = strcmp(jid, server->jid) == 0))
 
428
                        goto out;
 
429
        } else
 
430
                user->error = FALSE;
 
431
        resource = rosters_find_resource(!own ?
 
432
            user->resources : server->my_resources, res);
 
433
        if (resource == NULL)
 
434
                goto out;
 
435
        signal_emit("xmpp presence offline", 4, server, full_jid, jid, res);
 
436
        signal_emit("xmpp presence changed", 4, server, full_jid,
 
437
            XMPP_PRESENCE_UNAVAILABLE, status);
 
438
        if (!own)
 
439
                user->resources = g_slist_remove(user->resources, resource);
 
440
        else
 
441
                server->my_resources = g_slist_remove(server->my_resources,
 
442
                    resource);
 
443
        cleanup_resource(resource, NULL);
 
444
        if (!own) /* sort the group */
 
445
                group->users = g_slist_sort(group->users, func_sort_user);
 
446
 
 
447
out:
 
448
        g_free(jid);
 
449
        g_free(res);
 
450
}
 
451
 
 
452
static void
 
453
user_presence_error(XMPP_SERVER_REC *server, const char *full_jid)
 
454
{
 
455
        XMPP_ROSTER_GROUP_REC *group;
 
456
        XMPP_ROSTER_USER_REC *user;
 
457
        XMPP_ROSTER_RESOURCE_REC *resource;
 
458
        char *jid, *res;
 
459
        gboolean own;
 
460
 
 
461
        g_return_if_fail(IS_XMPP_SERVER(server));
 
462
        g_return_if_fail(full_jid != NULL);
 
463
        own = FALSE;
 
464
        jid = xmpp_strip_resource(full_jid);
 
465
        res = xmpp_extract_resource(full_jid);
 
466
        user = rosters_find_user(server->roster, jid, &group, NULL);
 
467
        if (user == NULL && !(own = strcmp(jid, server->jid) == 0))
 
468
                goto out;
 
469
        resource = rosters_find_resource(!own ?
 
470
            user->resources : server->my_resources, res);
 
471
        if (resource != NULL) {
 
472
                resource->show = XMPP_PRESENCE_ERROR;
 
473
                if (!own) /* sort the group */
 
474
                        group->users = g_slist_sort(group->users,
 
475
                            func_sort_user);
 
476
                signal_emit("xmpp presence changed", 4, server, full_jid,
 
477
                    XMPP_PRESENCE_ERROR, NULL);
 
478
        } else if (user != NULL)
 
479
                user->error = TRUE;
 
480
 
 
481
out:
 
482
        g_free(jid);
 
483
        g_free(res);
 
484
}
 
485
 
 
486
 
 
487
static void
 
488
sig_recv_presence(XMPP_SERVER_REC *server, LmMessage *lmsg, const int type,
 
489
    const char *id, const char *from, const char *to)
 
490
{
 
491
        LmMessageNode *node, *node_show, *node_priority, *signature;
 
492
        char *status, *pgp_keyid = NULL;
 
493
 
 
494
        if (server->ischannel(SERVER(server), from))
 
495
                return;
 
496
        switch(type) {
 
497
        case LM_MESSAGE_SUB_TYPE_AVAILABLE:
 
498
                node_show = lm_message_node_get_child(lmsg->node, "show");
 
499
                node = lm_message_node_get_child(lmsg->node, "status");
 
500
                status = node != NULL ? xmpp_recode_in(node->value) : NULL;
 
501
                node_priority = lm_message_node_get_child(lmsg->node, "priority");
 
502
                signature = lm_find_node(lmsg->node, "x", "xmlns", "jabber:x:signed");
 
503
                if(signature) {
 
504
                        char *send_to_gpg = malloc(sizeof( \
 
505
                                "-----BEGIN PGP SIGNATURE-----\n\n" \
 
506
                                "-----END PGP SIGNATURE-----\n")+ \
 
507
                                strlen(signature->value)+1 \
 
508
                        );
 
509
                        char *send_status = status ? status : "";
 
510
                        char *from_gpg;
 
511
 
 
512
                        send_to_gpg[0] = '\0';
 
513
                        strcat(send_to_gpg, "-----BEGIN PGP SIGNATURE-----\n\n");
 
514
                        strcat(send_to_gpg, signature->value);
 
515
                        strcat(send_to_gpg, "----- END PGP SIGNATURE-----\n");
 
516
 
 
517
                        from_gpg = call_gpg("--verify", send_to_gpg, send_status, 1, 0);
 
518
                        free(send_to_gpg);
 
519
 
 
520
                        /* If there is a good signature, grab the key ID */
 
521
                        if(from_gpg && strstr(from_gpg, "Good signature from")) {
 
522
                                char *s = strstr(from_gpg, "key ID ");
 
523
                                if(s) {
 
524
                                        pgp_keyid = malloc(sizeof(*pgp_keyid)*9);
 
525
                                        strncpy(pgp_keyid, s+7, 8);
 
526
                                        pgp_keyid[8] = '\0';
 
527
                                }
 
528
                        }
 
529
                        if(from_gpg) free(from_gpg);
 
530
                }
 
531
                update_user_presence(server, from,
 
532
                    node_show != NULL ? node_show->value : NULL, status,
 
533
                    node_priority != NULL ? node_priority->value : NULL,
 
534
                    pgp_keyid);
 
535
                g_free(status);
 
536
                break;
 
537
        case LM_MESSAGE_SUB_TYPE_UNAVAILABLE:
 
538
                node = lm_message_node_get_child(lmsg->node, "status");
 
539
                status = node != NULL ? xmpp_recode_in(node->value) : NULL;
 
540
                user_unavailable(server, from, status);
 
541
                g_free(status);
 
542
                break;
 
543
        case LM_MESSAGE_SUB_TYPE_SUBSCRIBE:
 
544
                node = lm_message_node_get_child(lmsg->node, "status");
 
545
                status = node != NULL ? xmpp_recode_in(node->value) : NULL;
 
546
                signal_emit("xmpp presence subscribe", 3, server, from, status);
 
547
                g_free(status);
 
548
                break;
 
549
        case LM_MESSAGE_SUB_TYPE_UNSUBSCRIBE:
 
550
                signal_emit("xmpp presence unsubscribe", 2, server, from);
 
551
                break;
 
552
        case LM_MESSAGE_SUB_TYPE_SUBSCRIBED:
 
553
                signal_emit("xmpp presence subscribed", 2, server, from);
 
554
                break;
 
555
        case LM_MESSAGE_SUB_TYPE_UNSUBSCRIBED:
 
556
                signal_emit("xmpp presence unsubscribed", 2, server, from);
 
557
                break;
 
558
        case LM_MESSAGE_SUB_TYPE_ERROR:
 
559
                user_presence_error(server, from);
 
560
                break;
 
561
        }
 
562
}
 
563
 
 
564
static void
 
565
sig_recv_iq(XMPP_SERVER_REC *server, LmMessage *lmsg, const int type,
 
566
    const char *id, const char *from, const char *to)
 
567
{
 
568
        LmMessageNode *node, *item, *group_node;
 
569
        char *jid, *name, *group;
 
570
        const char *subscription;
 
571
 
 
572
        if (type != LM_MESSAGE_SUB_TYPE_RESULT
 
573
            && type != LM_MESSAGE_SUB_TYPE_SET)
 
574
                return;
 
575
        node = lm_find_node(lmsg->node, "query", "xmlns", XMLNS_ROSTER);
 
576
        if (node == NULL)
 
577
                return;
 
578
        for (item = node->children; item != NULL; item = item->next) {
 
579
                if (strcmp(item->name, "item") != 0)
 
580
                        continue;
 
581
                jid = xmpp_recode_in(lm_message_node_get_attribute(item, "jid"));
 
582
                name = xmpp_recode_in(lm_message_node_get_attribute(item, "name"));
 
583
                group_node = lm_message_node_get_child(item, "group");
 
584
                group = group_node != NULL ?
 
585
                    xmpp_recode_in(group_node->value) : NULL;
 
586
                subscription = lm_message_node_get_attribute(item,
 
587
                    "subscription");
 
588
                update_user(server, jid, subscription, name, group);
 
589
                g_free(jid);
 
590
                g_free(name);
 
591
                g_free(group);
 
592
        }
 
593
}
 
594
 
 
595
static void
 
596
sig_connected(XMPP_SERVER_REC *server)
 
597
{
 
598
        LmMessage *lmsg;
 
599
        LmMessageNode *node;
 
600
 
 
601
        if (!IS_XMPP_SERVER(server))
 
602
                return;
 
603
        signal_emit("xmpp server status", 2, server, "Requesting the roster.");
 
604
        lmsg = lm_message_new_with_sub_type(NULL, LM_MESSAGE_TYPE_IQ,
 
605
            LM_MESSAGE_SUB_TYPE_GET);
 
606
        node = lm_message_node_add_child(lmsg->node, "query", NULL);
 
607
        lm_message_node_set_attribute(node, "xmlns", "jabber:iq:roster");
 
608
        signal_emit("xmpp send iq", 2, server, lmsg);
 
609
        lm_message_unref(lmsg);
 
610
}
 
611
 
 
612
void
 
613
rosters_init(void)
 
614
{
 
615
        signal_add("server connected", sig_connected);
 
616
        signal_add_first("server disconnected", roster_cleanup);
 
617
        signal_add("xmpp recv presence", sig_recv_presence);
 
618
        signal_add("xmpp recv iq", sig_recv_iq);
 
619
}
 
620
 
 
621
void
 
622
rosters_deinit(void)
 
623
{
 
624
        signal_remove("server connected", sig_connected);
 
625
        signal_remove("server disconnected", roster_cleanup);
 
626
        signal_remove("xmpp recv presence", sig_recv_presence);
 
627
        signal_remove("xmpp recv iq", sig_recv_iq);
 
628
}