Mercurial > pidgin.yaz
annotate src/protocols/jabber/roster.c @ 11110:f7ce10cad83d
[gaim-migrate @ 13162]
Make drag-and-drop buddy icon setting work for protocols that don't have file transfer.
committer: Tailor Script <tailor@pidgin.im>
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Sun, 17 Jul 2005 21:38:59 +0000 |
parents | cef48e318125 |
children | 980c877bd238 |
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; | |
10941 | 173 /* XXX: if subscription is now "from" or "none" we need to |
174 * fake a signoff, since we won't get any presence from them | |
175 * anymore */ | |
10289 | 176 } |
7014 | 177 |
178 if(ask && !strcmp(ask, "subscribe")) | |
179 jb->subscription |= JABBER_SUB_PENDING; | |
180 else | |
181 jb->subscription &= ~JABBER_SUB_PENDING; | |
182 | |
8194 | 183 if(jb->subscription == JABBER_SUB_REMOVE) { |
7014 | 184 remove_gaim_buddies(js, jid); |
185 } else { | |
186 GSList *groups = NULL; | |
8135 | 187 for(group = xmlnode_get_child(item, "group"); group; group = xmlnode_get_next_twin(group)) { |
7316 | 188 char *group_name; |
189 | |
190 if(!(group_name = xmlnode_get_data(group))) | |
191 group_name = g_strdup(""); | |
192 groups = g_slist_append(groups, group_name); | |
7014 | 193 } |
194 add_gaim_buddies_in_groups(js, jid, name, groups); | |
195 } | |
196 } | |
197 } | |
198 | |
199 static void jabber_roster_update(JabberStream *js, const char *name, | |
200 GSList *grps) | |
201 { | |
202 GaimBuddy *b; | |
203 GaimGroup *g; | |
204 GSList *groups = NULL, *l; | |
205 JabberIq *iq; | |
206 xmlnode *query, *item, *group; | |
207 | |
208 if(grps) { | |
209 groups = grps; | |
210 } else { | |
211 GSList *buddies = gaim_find_buddies(js->gc->account, name); | |
212 if(!buddies) | |
213 return; | |
214 while(buddies) { | |
215 b = buddies->data; | |
216 g = gaim_find_buddys_group(b); | |
217 groups = g_slist_append(groups, g->name); | |
218 buddies = g_slist_remove(buddies, b); | |
219 } | |
220 } | |
221 | |
8120 | 222 if(!(b = gaim_find_buddy(js->gc->account, name))) |
223 return; | |
7014 | 224 |
225 iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:roster"); | |
226 | |
227 query = xmlnode_get_child(iq->node, "query"); | |
228 item = xmlnode_new_child(query, "item"); | |
229 | |
230 xmlnode_set_attrib(item, "jid", name); | |
231 | |
232 if(b->alias) | |
233 xmlnode_set_attrib(item, "name", b->alias); | |
234 | |
235 for(l = groups; l; l = l->next) { | |
236 group = xmlnode_new_child(item, "group"); | |
237 xmlnode_insert_data(group, l->data, -1); | |
238 } | |
239 | |
240 if(!grps) | |
241 g_slist_free(groups); | |
242 | |
243 jabber_iq_send(iq); | |
244 } | |
245 | |
9285 | 246 void jabber_roster_add_buddy(GaimConnection *gc, GaimBuddy *buddy, |
247 GaimGroup *group) | |
7014 | 248 { |
249 JabberStream *js = gc->proto_data; | |
250 char *who; | |
7425 | 251 GSList *groups = NULL; |
7014 | 252 JabberBuddy *jb; |
7488 | 253 JabberBuddyResource *jbr; |
8194 | 254 char *my_bare_jid; |
7014 | 255 |
256 if(!js->roster_parsed) | |
257 return; | |
258 | |
9285 | 259 if(!(who = jabber_get_bare_jid(buddy->name))) |
7425 | 260 return; |
7014 | 261 |
9285 | 262 jb = jabber_buddy_find(js, buddy->name, FALSE); |
7425 | 263 |
264 if(!jb || !(jb->subscription & JABBER_SUB_TO)) { | |
9285 | 265 groups = g_slist_append(groups, group->name); |
7425 | 266 } |
7014 | 267 |
7449 | 268 jabber_roster_update(js, who, groups); |
7014 | 269 |
8194 | 270 my_bare_jid = g_strdup_printf("%s@%s", js->user->node, js->user->domain); |
9954 | 271 if(!strcmp(who, my_bare_jid)) { |
272 GaimPresence *gpresence; | |
273 GaimStatus *status; | |
274 | |
275 gpresence = gaim_account_get_presence(js->gc->account); | |
276 status = gaim_presence_get_active_status(gpresence); | |
277 jabber_presence_fake_to_self(js, status); | |
278 } else if(!jb || !(jb->subscription & JABBER_SUB_TO)) { | |
7014 | 279 jabber_presence_subscription_set(js, who, "subscribe"); |
9954 | 280 } else if((jbr =jabber_buddy_find_resource(jb, NULL))) { |
281 gaim_prpl_got_user_status(gc->account, who, | |
282 jabber_buddy_state_get_status_id(jbr->state), | |
9990 | 283 "priority", jbr->priority, jbr->status ? "message" : NULL, jbr->status, NULL); |
9954 | 284 } |
7425 | 285 |
8194 | 286 g_free(my_bare_jid); |
7014 | 287 g_free(who); |
288 } | |
289 | |
290 void jabber_roster_alias_change(GaimConnection *gc, const char *name, const char *alias) | |
291 { | |
7449 | 292 GaimBuddy *b = gaim_find_buddy(gc->account, name); |
7482 | 293 char *a; |
7449 | 294 |
7482 | 295 a = g_strdup(alias); |
296 gaim_blist_alias_buddy(b, a); | |
297 g_free(a); | |
7449 | 298 |
7014 | 299 jabber_roster_update(gc->proto_data, name, NULL); |
300 } | |
301 | |
302 void jabber_roster_group_change(GaimConnection *gc, const char *name, | |
303 const char *old_group, const char *new_group) | |
304 { | |
305 GSList *buddies, *groups = NULL; | |
306 GaimBuddy *b; | |
307 GaimGroup *g; | |
308 | |
309 if(!old_group || !new_group || !strcmp(old_group, new_group)) | |
310 return; | |
311 | |
312 buddies = gaim_find_buddies(gc->account, name); | |
313 while(buddies) { | |
314 b = buddies->data; | |
315 g = gaim_find_buddys_group(b); | |
316 if(!strcmp(g->name, old_group)) | |
317 groups = g_slist_append(groups, (char*)new_group); /* ick */ | |
318 else | |
319 groups = g_slist_append(groups, g->name); | |
320 buddies = g_slist_remove(buddies, b); | |
321 } | |
322 jabber_roster_update(gc->proto_data, name, groups); | |
323 g_slist_free(groups); | |
324 } | |
325 | |
9285 | 326 void jabber_roster_group_rename(GaimConnection *gc, const char *old_name, |
327 GaimGroup *group, GList *moved_buddies) | |
7014 | 328 { |
329 GList *l; | |
9285 | 330 for(l = moved_buddies; l; l = l->next) { |
331 GaimBuddy *buddy = l->data; | |
332 jabber_roster_group_change(gc, buddy->name, old_name, group->name); | |
7014 | 333 } |
334 } | |
335 | |
9285 | 336 void jabber_roster_remove_buddy(GaimConnection *gc, GaimBuddy *buddy, |
337 GaimGroup *group) { | |
338 GSList *buddies = gaim_find_buddies(gc->account, buddy->name); | |
7014 | 339 GSList *groups = NULL; |
340 | |
9285 | 341 buddies = g_slist_remove(buddies, buddy); |
7014 | 342 if(g_slist_length(buddies)) { |
9285 | 343 GaimBuddy *tmpbuddy; |
344 GaimGroup *tmpgroup; | |
345 | |
7014 | 346 while(buddies) { |
9285 | 347 tmpbuddy = buddies->data; |
348 tmpgroup = gaim_find_buddys_group(tmpbuddy); | |
349 groups = g_slist_append(groups, tmpgroup->name); | |
350 buddies = g_slist_remove(buddies, tmpbuddy); | |
7014 | 351 } |
9285 | 352 |
353 jabber_roster_update(gc->proto_data, buddy->name, groups); | |
7014 | 354 } else { |
7171 | 355 JabberIq *iq = jabber_iq_new_query(gc->proto_data, JABBER_IQ_SET, |
356 "jabber:iq:roster"); | |
357 xmlnode *query = xmlnode_get_child(iq->node, "query"); | |
358 xmlnode *item = xmlnode_new_child(query, "item"); | |
359 | |
9285 | 360 xmlnode_set_attrib(item, "jid", buddy->name); |
7171 | 361 xmlnode_set_attrib(item, "subscription", "remove"); |
362 | |
363 jabber_iq_send(iq); | |
7014 | 364 } |
365 | |
366 if(buddies) | |
367 g_slist_free(buddies); | |
368 if(groups) | |
369 g_slist_free(groups); | |
370 } |