Mercurial > pidgin
annotate src/protocols/jabber/roster.c @ 10725:de26e6e198a4
[gaim-migrate @ 12325]
" With the status rewrite we don't need some of these old
legacy members in the buddy structure. I'm trying to
clean them up by novell hasn't been ported to the new
status, and I have nfi what I'm doing with novell.. So
here's jabber." -- grim
committer: Tailor Script <tailor@pidgin.im>
author | Luke Schierer <lschiere@pidgin.im> |
---|---|
date | Fri, 25 Mar 2005 13:13:16 +0000 |
parents | 5683613ea692 |
children | cef48e318125 |
rev | line source |
---|---|
7014 | 1 /* |
2 * gaim - Jabber Protocol Plugin | |
3 * | |
4 * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com> | |
5 * | |
6 * This program is free software; you can redistribute it and/or modify | |
7 * it under the terms of the GNU General Public License as published by | |
8 * the Free Software Foundation; either version 2 of the License, or | |
9 * (at your option) any later version. | |
10 * | |
11 * This program is distributed in the hope that it will be useful, | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 * GNU General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU General Public License | |
17 * along with this program; if not, write to the Free Software | |
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 * | |
20 */ | |
21 #include "internal.h" | |
22 #include "debug.h" | |
23 #include "server.h" | |
24 | |
25 #include "buddy.h" | |
26 #include "presence.h" | |
27 #include "roster.h" | |
28 #include "iq.h" | |
29 | |
30 #include <string.h> | |
31 | |
32 | |
33 void jabber_roster_request(JabberStream *js) | |
34 { | |
35 JabberIq *iq; | |
36 | |
37 iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:roster"); | |
38 | |
39 jabber_iq_send(iq); | |
40 } | |
41 | |
42 static void remove_gaim_buddies(JabberStream *js, const char *jid) | |
43 { | |
44 GSList *buddies, *l; | |
45 | |
46 buddies = gaim_find_buddies(js->gc->account, jid); | |
47 | |
48 for(l = buddies; l; l = l->next) | |
49 gaim_blist_remove_buddy(l->data); | |
50 | |
51 g_slist_free(buddies); | |
52 } | |
53 | |
54 static void add_gaim_buddies_in_groups(JabberStream *js, const char *jid, | |
55 const char *alias, GSList *groups) | |
56 { | |
10725
de26e6e198a4
[gaim-migrate @ 12325]
Luke Schierer <lschiere@pidgin.im>
parents:
10289
diff
changeset
|
57 GaimPresence *presence = NULL; |
7014 | 58 GSList *buddies, *g2, *l; |
59 | |
60 buddies = gaim_find_buddies(js->gc->account, jid); | |
61 | |
62 g2 = groups; | |
63 | |
64 if(!groups) { | |
65 if(!buddies) | |
66 g2 = g_slist_append(g2, g_strdup(_("Buddies"))); | |
67 else | |
68 return; | |
69 } | |
70 | |
71 if(buddies) { | |
10725
de26e6e198a4
[gaim-migrate @ 12325]
Luke Schierer <lschiere@pidgin.im>
parents:
10289
diff
changeset
|
72 presence = gaim_buddy_get_presence((GaimBuddy*)buddies->data); |
7014 | 73 } |
74 | |
75 while(buddies) { | |
76 GaimBuddy *b = buddies->data; | |
77 GaimGroup *g = gaim_find_buddys_group(b); | |
78 | |
79 buddies = g_slist_remove(buddies, b); | |
80 | |
81 if((l = g_slist_find_custom(g2, g->name, (GCompareFunc)strcmp))) { | |
7955 | 82 const char *servernick; |
83 | |
84 if((servernick = gaim_blist_node_get_string((GaimBlistNode*)b, "servernick"))) | |
85 serv_got_alias(js->gc, jid, servernick); | |
86 | |
7014 | 87 if(alias && (!b->alias || strcmp(b->alias, alias))) |
88 gaim_blist_alias_buddy(b, alias); | |
89 g_free(l->data); | |
90 g2 = g_slist_delete_link(g2, l); | |
91 } else { | |
92 gaim_blist_remove_buddy(b); | |
93 } | |
94 } | |
95 | |
96 while(g2) { | |
97 GaimBuddy *b = gaim_buddy_new(js->gc->account, jid, alias); | |
98 GaimGroup *g = gaim_find_group(g2->data); | |
99 | |
100 if(!g) { | |
101 g = gaim_group_new(g2->data); | |
102 gaim_blist_add_group(g, NULL); | |
103 } | |
104 | |
9954 | 105 /* XXX: this hack may need to change */ |
10725
de26e6e198a4
[gaim-migrate @ 12325]
Luke Schierer <lschiere@pidgin.im>
parents:
10289
diff
changeset
|
106 /* Is this change better? */ |
de26e6e198a4
[gaim-migrate @ 12325]
Luke Schierer <lschiere@pidgin.im>
parents:
10289
diff
changeset
|
107 b->presence = presence; |
7014 | 108 |
109 gaim_blist_add_buddy(b, NULL, g, NULL); | |
7955 | 110 gaim_blist_alias_buddy(b, alias); |
7014 | 111 g_free(g2->data); |
112 g2 = g_slist_delete_link(g2, g2); | |
113 } | |
114 | |
115 g_slist_free(buddies); | |
116 } | |
117 | |
118 void jabber_roster_parse(JabberStream *js, xmlnode *packet) | |
119 { | |
120 xmlnode *query, *item, *group; | |
121 const char *from = xmlnode_get_attrib(packet, "from"); | |
7310 | 122 |
123 if(from) { | |
7445 | 124 char *from_norm; |
7310 | 125 gboolean invalid; |
7175 | 126 |
7445 | 127 from_norm = g_strdup(jabber_normalize(js->gc->account, from)); |
128 | |
129 if(!from_norm) | |
7310 | 130 return; |
131 | |
7445 | 132 invalid = g_utf8_collate(from_norm, |
133 jabber_normalize(js->gc->account, | |
134 gaim_account_get_username(js->gc->account))); | |
7175 | 135 |
7310 | 136 g_free(from_norm); |
137 | |
138 if(invalid) | |
139 return; | |
7175 | 140 } |
141 | |
7014 | 142 query = xmlnode_get_child(packet, "query"); |
143 if(!query) | |
144 return; | |
145 | |
146 js->roster_parsed = TRUE; | |
147 | |
8135 | 148 for(item = xmlnode_get_child(query, "item"); item; item = xmlnode_get_next_twin(item)) |
7014 | 149 { |
150 const char *jid, *name, *subscription, *ask; | |
151 JabberBuddy *jb; | |
152 | |
153 subscription = xmlnode_get_attrib(item, "subscription"); | |
154 jid = xmlnode_get_attrib(item, "jid"); | |
155 name = xmlnode_get_attrib(item, "name"); | |
156 ask = xmlnode_get_attrib(item, "ask"); | |
157 | |
8347 | 158 if(!jid) |
159 continue; | |
160 | |
161 if(!(jb = jabber_buddy_find(js, jid, TRUE))) | |
162 continue; | |
7014 | 163 |
10289 | 164 if(subscription) { |
165 if(!strcmp(subscription, "to")) | |
166 jb->subscription = JABBER_SUB_TO; | |
167 else if(!strcmp(subscription, "from")) | |
168 jb->subscription = JABBER_SUB_FROM; | |
169 else if(!strcmp(subscription, "both")) | |
170 jb->subscription = JABBER_SUB_BOTH; | |
171 else if(!strcmp(subscription, "remove")) | |
172 jb->subscription = JABBER_SUB_REMOVE; | |
173 } | |
7014 | 174 |
175 if(ask && !strcmp(ask, "subscribe")) | |
176 jb->subscription |= JABBER_SUB_PENDING; | |
177 else | |
178 jb->subscription &= ~JABBER_SUB_PENDING; | |
179 | |
8194 | 180 if(jb->subscription == JABBER_SUB_REMOVE) { |
7014 | 181 remove_gaim_buddies(js, jid); |
182 } else { | |
183 GSList *groups = NULL; | |
8135 | 184 for(group = xmlnode_get_child(item, "group"); group; group = xmlnode_get_next_twin(group)) { |
7316 | 185 char *group_name; |
186 | |
187 if(!(group_name = xmlnode_get_data(group))) | |
188 group_name = g_strdup(""); | |
189 groups = g_slist_append(groups, group_name); | |
7014 | 190 } |
191 add_gaim_buddies_in_groups(js, jid, name, groups); | |
192 } | |
193 } | |
194 } | |
195 | |
196 static void jabber_roster_update(JabberStream *js, const char *name, | |
197 GSList *grps) | |
198 { | |
199 GaimBuddy *b; | |
200 GaimGroup *g; | |
201 GSList *groups = NULL, *l; | |
202 JabberIq *iq; | |
203 xmlnode *query, *item, *group; | |
204 | |
205 if(grps) { | |
206 groups = grps; | |
207 } else { | |
208 GSList *buddies = gaim_find_buddies(js->gc->account, name); | |
209 if(!buddies) | |
210 return; | |
211 while(buddies) { | |
212 b = buddies->data; | |
213 g = gaim_find_buddys_group(b); | |
214 groups = g_slist_append(groups, g->name); | |
215 buddies = g_slist_remove(buddies, b); | |
216 } | |
217 } | |
218 | |
8120 | 219 if(!(b = gaim_find_buddy(js->gc->account, name))) |
220 return; | |
7014 | 221 |
222 iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:roster"); | |
223 | |
224 query = xmlnode_get_child(iq->node, "query"); | |
225 item = xmlnode_new_child(query, "item"); | |
226 | |
227 xmlnode_set_attrib(item, "jid", name); | |
228 | |
229 if(b->alias) | |
230 xmlnode_set_attrib(item, "name", b->alias); | |
231 | |
232 for(l = groups; l; l = l->next) { | |
233 group = xmlnode_new_child(item, "group"); | |
234 xmlnode_insert_data(group, l->data, -1); | |
235 } | |
236 | |
237 if(!grps) | |
238 g_slist_free(groups); | |
239 | |
240 jabber_iq_send(iq); | |
241 } | |
242 | |
9285 | 243 void jabber_roster_add_buddy(GaimConnection *gc, GaimBuddy *buddy, |
244 GaimGroup *group) | |
7014 | 245 { |
246 JabberStream *js = gc->proto_data; | |
247 char *who; | |
7425 | 248 GSList *groups = NULL; |
7014 | 249 JabberBuddy *jb; |
7488 | 250 JabberBuddyResource *jbr; |
8194 | 251 char *my_bare_jid; |
7014 | 252 |
253 if(!js->roster_parsed) | |
254 return; | |
255 | |
9285 | 256 if(!(who = jabber_get_bare_jid(buddy->name))) |
7425 | 257 return; |
7014 | 258 |
9285 | 259 jb = jabber_buddy_find(js, buddy->name, FALSE); |
7425 | 260 |
261 if(!jb || !(jb->subscription & JABBER_SUB_TO)) { | |
9285 | 262 groups = g_slist_append(groups, group->name); |
7425 | 263 } |
7014 | 264 |
7449 | 265 jabber_roster_update(js, who, groups); |
7014 | 266 |
8194 | 267 my_bare_jid = g_strdup_printf("%s@%s", js->user->node, js->user->domain); |
9954 | 268 if(!strcmp(who, my_bare_jid)) { |
269 GaimPresence *gpresence; | |
270 GaimStatus *status; | |
271 | |
272 gpresence = gaim_account_get_presence(js->gc->account); | |
273 status = gaim_presence_get_active_status(gpresence); | |
274 jabber_presence_fake_to_self(js, status); | |
275 } else if(!jb || !(jb->subscription & JABBER_SUB_TO)) { | |
7014 | 276 jabber_presence_subscription_set(js, who, "subscribe"); |
9954 | 277 } else if((jbr =jabber_buddy_find_resource(jb, NULL))) { |
278 gaim_prpl_got_user_status(gc->account, who, | |
279 jabber_buddy_state_get_status_id(jbr->state), | |
9990 | 280 "priority", jbr->priority, jbr->status ? "message" : NULL, jbr->status, NULL); |
9954 | 281 } |
7425 | 282 |
8194 | 283 g_free(my_bare_jid); |
7014 | 284 g_free(who); |
285 } | |
286 | |
287 void jabber_roster_alias_change(GaimConnection *gc, const char *name, const char *alias) | |
288 { | |
7449 | 289 GaimBuddy *b = gaim_find_buddy(gc->account, name); |
7482 | 290 char *a; |
7449 | 291 |
7482 | 292 a = g_strdup(alias); |
293 gaim_blist_alias_buddy(b, a); | |
294 g_free(a); | |
7449 | 295 |
7014 | 296 jabber_roster_update(gc->proto_data, name, NULL); |
297 } | |
298 | |
299 void jabber_roster_group_change(GaimConnection *gc, const char *name, | |
300 const char *old_group, const char *new_group) | |
301 { | |
302 GSList *buddies, *groups = NULL; | |
303 GaimBuddy *b; | |
304 GaimGroup *g; | |
305 | |
306 if(!old_group || !new_group || !strcmp(old_group, new_group)) | |
307 return; | |
308 | |
309 buddies = gaim_find_buddies(gc->account, name); | |
310 while(buddies) { | |
311 b = buddies->data; | |
312 g = gaim_find_buddys_group(b); | |
313 if(!strcmp(g->name, old_group)) | |
314 groups = g_slist_append(groups, (char*)new_group); /* ick */ | |
315 else | |
316 groups = g_slist_append(groups, g->name); | |
317 buddies = g_slist_remove(buddies, b); | |
318 } | |
319 jabber_roster_update(gc->proto_data, name, groups); | |
320 g_slist_free(groups); | |
321 } | |
322 | |
9285 | 323 void jabber_roster_group_rename(GaimConnection *gc, const char *old_name, |
324 GaimGroup *group, GList *moved_buddies) | |
7014 | 325 { |
326 GList *l; | |
9285 | 327 for(l = moved_buddies; l; l = l->next) { |
328 GaimBuddy *buddy = l->data; | |
329 jabber_roster_group_change(gc, buddy->name, old_name, group->name); | |
7014 | 330 } |
331 } | |
332 | |
9285 | 333 void jabber_roster_remove_buddy(GaimConnection *gc, GaimBuddy *buddy, |
334 GaimGroup *group) { | |
335 GSList *buddies = gaim_find_buddies(gc->account, buddy->name); | |
7014 | 336 GSList *groups = NULL; |
337 | |
9285 | 338 buddies = g_slist_remove(buddies, buddy); |
7014 | 339 if(g_slist_length(buddies)) { |
9285 | 340 GaimBuddy *tmpbuddy; |
341 GaimGroup *tmpgroup; | |
342 | |
7014 | 343 while(buddies) { |
9285 | 344 tmpbuddy = buddies->data; |
345 tmpgroup = gaim_find_buddys_group(tmpbuddy); | |
346 groups = g_slist_append(groups, tmpgroup->name); | |
347 buddies = g_slist_remove(buddies, tmpbuddy); | |
7014 | 348 } |
9285 | 349 |
350 jabber_roster_update(gc->proto_data, buddy->name, groups); | |
7014 | 351 } else { |
7171 | 352 JabberIq *iq = jabber_iq_new_query(gc->proto_data, JABBER_IQ_SET, |
353 "jabber:iq:roster"); | |
354 xmlnode *query = xmlnode_get_child(iq->node, "query"); | |
355 xmlnode *item = xmlnode_new_child(query, "item"); | |
356 | |
9285 | 357 xmlnode_set_attrib(item, "jid", buddy->name); |
7171 | 358 xmlnode_set_attrib(item, "subscription", "remove"); |
359 | |
360 jabber_iq_send(iq); | |
7014 | 361 } |
362 | |
363 if(buddies) | |
364 g_slist_free(buddies); | |
365 if(groups) | |
366 g_slist_free(groups); | |
367 } |