Mercurial > pidgin
annotate src/protocols/jabber/roster.c @ 11202:ff4884029708
[gaim-migrate @ 13330]
Some compile warning fixes. It's very possible the perl warnings
were caused by some of my changes to the core last week
committer: Tailor Script <tailor@pidgin.im>
| author | Mark Doliner <mark@kingant.net> |
|---|---|
| date | Mon, 08 Aug 2005 02:21:57 +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 } |
