Mercurial > pidgin.yaz
annotate src/protocols/jabber/presence.c @ 11620:fbc4eeab2227
[gaim-migrate @ 13894]
this lets you leave a highlighted tab by control-tab (forward) or
control-shift-tab (backwards). its not 100% intuitive though, because it
leaves the tab highlighed, which means that in the case of 1 highlighted
tab, the current one, you will leave the tab on the first control-tab,
then immediately return to it on the second one. For this reason, removing
the highlighting of current tabs would be a better permanent solution.
In talking with Tim however, he suggested we do both, on the off chance we
change our minds about the tab highlighting and go back to the
autoswitching.
committer: Tailor Script <tailor@pidgin.im>
author | Luke Schierer <lschiere@pidgin.im> |
---|---|
date | Thu, 06 Oct 2005 15:01:08 +0000 |
parents | e36f0f9debb5 |
children | 11e95968c9ff |
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 | |
10684
72a5babfa8b4
[gaim-migrate @ 12231]
Luke Schierer <lschiere@pidgin.im>
parents:
10646
diff
changeset
|
23 #include "cipher.h" |
7014 | 24 #include "debug.h" |
25 #include "notify.h" | |
26 #include "request.h" | |
27 #include "server.h" | |
9954 | 28 #include "status.h" |
7095
c8bf2da398e3
[gaim-migrate @ 7660]
Christian Hammond <chipx86@chipx86.com>
parents:
7015
diff
changeset
|
29 #include "util.h" |
7014 | 30 |
31 #include "buddy.h" | |
32 #include "chat.h" | |
33 #include "presence.h" | |
34 #include "iq.h" | |
35 #include "jutil.h" | |
36 #include "xmlnode.h" | |
37 | |
38 | |
39 static void chats_send_presence_foreach(gpointer key, gpointer val, | |
40 gpointer user_data) | |
41 { | |
42 JabberChat *chat = val; | |
43 xmlnode *presence = user_data; | |
8577 | 44 char *chat_full_jid; |
45 | |
46 if(!chat->conv) | |
47 return; | |
48 | |
49 chat_full_jid = g_strdup_printf("%s@%s/%s", chat->room, chat->server, | |
8401 | 50 chat->handle); |
7014 | 51 |
8401 | 52 xmlnode_set_attrib(presence, "to", chat_full_jid); |
7014 | 53 jabber_send(chat->js, presence); |
8401 | 54 g_free(chat_full_jid); |
7014 | 55 } |
56 | |
9954 | 57 void jabber_presence_fake_to_self(JabberStream *js, const GaimStatus *gstatus) { |
10286 | 58 char *my_base_jid; |
59 | |
60 if(!js->user) | |
61 return; | |
62 | |
63 my_base_jid = g_strdup_printf("%s@%s", js->user->node, js->user->domain); | |
8185 | 64 if(gaim_find_buddy(js->gc->account, my_base_jid)) { |
65 JabberBuddy *jb; | |
66 JabberBuddyResource *jbr; | |
67 if((jb = jabber_buddy_find(js, my_base_jid, TRUE))) { | |
9954 | 68 JabberBuddyState state; |
69 const char *msg; | |
70 int priority; | |
71 | |
72 gaim_status_to_jabber(gstatus, &state, &msg, &priority); | |
73 | |
10490 | 74 if (state == JABBER_BUDDY_STATE_UNAVAILABLE || state == JABBER_BUDDY_STATE_UNKNOWN) { |
9744 | 75 jabber_buddy_remove_resource(jb, js->user->resource); |
76 } else { | |
9954 | 77 jabber_buddy_track_resource(jb, js->user->resource, priority, state, msg); |
9744 | 78 } |
9954 | 79 if((jbr = jabber_buddy_find_resource(jb, NULL))) { |
9990 | 80 gaim_prpl_got_user_status(js->gc->account, my_base_jid, jabber_buddy_state_get_status_id(jbr->state), "priority", jbr->priority, jbr->status ? "message" : NULL, jbr->status, NULL); |
9954 | 81 } else { |
9990 | 82 gaim_prpl_got_user_status(js->gc->account, my_base_jid, "offline", msg ? "message" : NULL, msg, NULL); |
9954 | 83 } |
8185 | 84 } |
85 } | |
86 g_free(my_base_jid); | |
87 } | |
88 | |
7014 | 89 |
10216 | 90 void jabber_presence_send(GaimAccount *account, GaimStatus *status) |
7014 | 91 { |
10382
9f28196ed769
[gaim-migrate @ 11608]
Luke Schierer <lschiere@pidgin.im>
parents:
10286
diff
changeset
|
92 GaimConnection *gc = NULL; |
9f28196ed769
[gaim-migrate @ 11608]
Luke Schierer <lschiere@pidgin.im>
parents:
10286
diff
changeset
|
93 JabberStream *js = NULL; |
11251 | 94 gboolean disconnected; |
10755 | 95 int primitive; |
10189 | 96 xmlnode *presence, *x, *photo; |
7014 | 97 char *stripped = NULL; |
9954 | 98 const char *msg; |
99 JabberBuddyState state; | |
100 int priority; | |
7014 | 101 |
10486 | 102 if(!gaim_status_is_active(status)) |
103 return; | |
104 | |
11251 | 105 disconnected = gaim_account_is_disconnected(account); |
10755 | 106 primitive = gaim_status_type_get_primitive(gaim_status_get_type(status)); |
107 | |
11251 | 108 if(primitive != GAIM_STATUS_OFFLINE && disconnected) { |
10738 | 109 gaim_account_connect(account); |
10755 | 110 } |
111 | |
11251 | 112 if(disconnected) |
10755 | 113 return; |
114 | |
115 gc = gaim_account_get_connection(account); | |
116 js = gc->proto_data; | |
117 | |
9954 | 118 gaim_status_to_jabber(status, &state, &msg, &priority); |
119 | |
120 if(msg) | |
7095
c8bf2da398e3
[gaim-migrate @ 7660]
Christian Hammond <chipx86@chipx86.com>
parents:
7015
diff
changeset
|
121 gaim_markup_html_to_xhtml(msg, NULL, &stripped); |
7014 | 122 |
9954 | 123 presence = jabber_presence_create(state, stripped, priority); |
124 g_free(stripped); | |
7014 | 125 |
126 jabber_send(js, presence); | |
10189 | 127 |
128 if(js->avatar_hash) { | |
129 x = xmlnode_new_child(presence, "x"); | |
130 xmlnode_set_attrib(x, "xmlns", "vcard-temp:x:update"); | |
131 photo = xmlnode_new_child(x, "photo"); | |
132 xmlnode_insert_data(photo, js->avatar_hash, -1); | |
133 } | |
134 | |
7014 | 135 g_hash_table_foreach(js->chats, chats_send_presence_foreach, presence); |
136 xmlnode_free(presence); | |
8185 | 137 |
9954 | 138 jabber_presence_fake_to_self(js, status); |
139 | |
11251 | 140 if(primitive == GAIM_STATUS_OFFLINE && !disconnected) { |
11013
7653143dec36
[gaim-migrate @ 12879]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10949
diff
changeset
|
141 gaim_account_disconnect(account); |
7653143dec36
[gaim-migrate @ 12879]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10949
diff
changeset
|
142 } |
7014 | 143 } |
144 | |
9954 | 145 xmlnode *jabber_presence_create(JabberBuddyState state, const char *msg, int priority) |
7014 | 146 { |
11568 | 147 xmlnode *show, *status, *presence, *pri; |
9954 | 148 const char *show_string = NULL; |
7014 | 149 |
150 | |
151 presence = xmlnode_new("presence"); | |
152 | |
153 | |
9954 | 154 if(state == JABBER_BUDDY_STATE_UNAVAILABLE) |
155 xmlnode_set_attrib(presence, "type", "unavailable"); | |
156 else if(state != JABBER_BUDDY_STATE_ONLINE && | |
157 state != JABBER_BUDDY_STATE_UNKNOWN && | |
158 state != JABBER_BUDDY_STATE_ERROR) | |
159 show_string = jabber_buddy_state_get_status_id(state); | |
160 | |
161 if(show_string) { | |
162 show = xmlnode_new_child(presence, "show"); | |
163 xmlnode_insert_data(show, show_string, -1); | |
7014 | 164 } |
165 | |
9954 | 166 if(msg) { |
7014 | 167 status = xmlnode_new_child(presence, "status"); |
168 xmlnode_insert_data(status, msg, -1); | |
169 } | |
170 | |
11568 | 171 if(priority) { |
172 char *pstr = g_strdup_printf("%d", priority); | |
173 pri = xmlnode_new_child(presence, "priority"); | |
174 xmlnode_insert_data(pri, pstr, -1); | |
175 g_free(pstr); | |
176 } | |
177 | |
7014 | 178 return presence; |
179 } | |
180 | |
181 struct _jabber_add_permit { | |
182 GaimConnection *gc; | |
183 char *who; | |
184 }; | |
185 | |
186 static void authorize_add_cb(struct _jabber_add_permit *jap) | |
187 { | |
188 if(g_list_find(gaim_connections_get_all(), jap->gc)) { | |
189 jabber_presence_subscription_set(jap->gc->proto_data, jap->who, | |
190 "subscribed"); | |
191 | |
192 if(!gaim_find_buddy(jap->gc->account, jap->who)) | |
7015
dece74f05509
[gaim-migrate @ 7578]
Christian Hammond <chipx86@chipx86.com>
parents:
7014
diff
changeset
|
193 gaim_account_notify_added(jap->gc->account, NULL, jap->who, NULL, NULL); |
7014 | 194 } |
195 | |
196 g_free(jap->who); | |
197 g_free(jap); | |
198 } | |
199 | |
200 static void deny_add_cb(struct _jabber_add_permit *jap) | |
201 { | |
202 if(g_list_find(gaim_connections_get_all(), jap->gc)) { | |
203 jabber_presence_subscription_set(jap->gc->proto_data, jap->who, | |
204 "unsubscribed"); | |
205 } | |
206 | |
207 g_free(jap->who); | |
208 g_free(jap); | |
209 } | |
210 | |
10189 | 211 static void jabber_vcard_parse_avatar(JabberStream *js, xmlnode *packet, gpointer blah) |
212 { | |
10941 | 213 JabberBuddy *jb = NULL; |
10189 | 214 GaimBuddy *b = NULL; |
10941 | 215 xmlnode *vcard, *photo, *binval; |
11127 | 216 char *text; |
11137 | 217 guchar *data; |
11127 | 218 gsize size; |
10189 | 219 const char *from = xmlnode_get_attrib(packet, "from"); |
220 | |
221 if(!from) | |
222 return; | |
223 | |
10941 | 224 jb = jabber_buddy_find(js, from, TRUE); |
225 | |
226 js->pending_avatar_requests = g_slist_remove(js->pending_avatar_requests, jb); | |
227 | |
10189 | 228 if((vcard = xmlnode_get_child(packet, "vCard")) || |
229 (vcard = xmlnode_get_child_with_namespace(packet, "query", "vcard-temp"))) { | |
10941 | 230 if((photo = xmlnode_get_child(vcard, "PHOTO")) && |
11361 | 231 (( (binval = xmlnode_get_child(photo, "BINVAL")) && |
232 (text = xmlnode_get_data(binval))) || | |
233 (text = xmlnode_get_data(photo)))) { | |
11127 | 234 data = gaim_base64_decode(text, &size); |
10189 | 235 |
10941 | 236 gaim_buddy_icons_set_for_user(js->gc->account, from, data, size); |
237 if((b = gaim_find_buddy(js->gc->account, from))) { | |
238 unsigned char hashval[20]; | |
239 char hash[41], *p; | |
240 int i; | |
10189 | 241 |
11183 | 242 gaim_cipher_digest_region("sha1", (guchar *)data, size, |
10941 | 243 sizeof(hashval), hashval, NULL); |
244 p = hash; | |
245 for(i=0; i<20; i++, p+=2) | |
246 snprintf(p, 3, "%02x", hashval[i]); | |
247 gaim_blist_node_set_string((GaimBlistNode*)b, "avatar_hash", hash); | |
10189 | 248 } |
10941 | 249 g_free(text); |
10189 | 250 } |
251 } | |
252 } | |
253 | |
7014 | 254 void jabber_presence_parse(JabberStream *js, xmlnode *packet) |
255 { | |
256 const char *from = xmlnode_get_attrib(packet, "from"); | |
257 const char *type = xmlnode_get_attrib(packet, "type"); | |
7944 | 258 const char *real_jid = NULL; |
9152 | 259 const char *affiliation = NULL; |
260 const char *role = NULL; | |
7014 | 261 char *status = NULL; |
262 int priority = 0; | |
263 JabberID *jid; | |
264 JabberChat *chat; | |
265 JabberBuddy *jb; | |
9954 | 266 JabberBuddyResource *jbr = NULL, *found_jbr = NULL; |
9554 | 267 GaimConvChatBuddyFlags flags = GAIM_CBFLAGS_NONE; |
9846 | 268 gboolean delayed = FALSE; |
10189 | 269 GaimBuddy *b = NULL; |
7014 | 270 char *buddy_name; |
9954 | 271 JabberBuddyState state = JABBER_BUDDY_STATE_UNKNOWN; |
7014 | 272 xmlnode *y; |
273 gboolean muc = FALSE; | |
10189 | 274 char *avatar_hash = NULL; |
7014 | 275 |
276 | |
8043 | 277 if(!(jb = jabber_buddy_find(js, from, TRUE))) |
278 return; | |
279 | |
280 if(!(jid = jabber_id_new(from))) | |
7280 | 281 return; |
282 | |
7014 | 283 if(jb->error_msg) { |
284 g_free(jb->error_msg); | |
285 jb->error_msg = NULL; | |
286 } | |
287 | |
7813 | 288 if(type && !strcmp(type, "error")) { |
8401 | 289 char *msg = jabber_parse_error(js, packet); |
7644 | 290 |
9954 | 291 state = JABBER_BUDDY_STATE_ERROR; |
8401 | 292 jb->error_msg = msg ? msg : g_strdup(_("Unknown Error in presence")); |
7813 | 293 } else if(type && !strcmp(type, "subscribe")) { |
7014 | 294 struct _jabber_add_permit *jap = g_new0(struct _jabber_add_permit, 1); |
10949 | 295 char *msg; |
296 | |
297 msg = g_strdup_printf(_("The user %s wants to add %s to his or " | |
298 "her buddy list."), | |
299 from, gaim_account_get_username(js->gc->account)); | |
7014 | 300 jap->gc = js->gc; |
301 jap->who = g_strdup(from); | |
302 | |
10189 | 303 gaim_request_action(js->gc, NULL, msg, NULL, GAIM_DEFAULT_ACTION_NONE, |
10116 | 304 jap, 2, |
7014 | 305 _("Authorize"), G_CALLBACK(authorize_add_cb), |
306 _("Deny"), G_CALLBACK(deny_add_cb)); | |
307 g_free(msg); | |
8043 | 308 jabber_id_free(jid); |
7145 | 309 return; |
7813 | 310 } else if(type && !strcmp(type, "subscribed")) { |
7014 | 311 /* we've been allowed to see their presence, but we don't care */ |
8043 | 312 jabber_id_free(jid); |
7014 | 313 return; |
314 } else { | |
315 if((y = xmlnode_get_child(packet, "show"))) { | |
316 char *show = xmlnode_get_data(y); | |
9954 | 317 state = jabber_buddy_status_id_get_state(show); |
7014 | 318 g_free(show); |
319 } else { | |
9954 | 320 state = JABBER_BUDDY_STATE_ONLINE; |
7014 | 321 } |
322 } | |
323 | |
7310 | 324 |
7014 | 325 for(y = packet->child; y; y = y->next) { |
8135 | 326 if(y->type != XMLNODE_TYPE_TAG) |
7014 | 327 continue; |
328 | |
329 if(!strcmp(y->name, "status")) { | |
7615 | 330 g_free(status); |
7014 | 331 status = xmlnode_get_data(y); |
332 } else if(!strcmp(y->name, "priority")) { | |
333 char *p = xmlnode_get_data(y); | |
334 if(p) { | |
335 priority = atoi(p); | |
336 g_free(p); | |
337 } | |
338 } else if(!strcmp(y->name, "x")) { | |
339 const char *xmlns = xmlnode_get_attrib(y, "xmlns"); | |
9846 | 340 if(xmlns && !strcmp(xmlns, "jabber:x:delay")) { |
9847 | 341 /* XXX: compare the time. jabber:x:delay can happen on presence packets that aren't really and truly delayed */ |
9846 | 342 delayed = TRUE; |
343 } else if(xmlns && !strcmp(xmlns, "http://jabber.org/protocol/muc#user")) { | |
7629 | 344 xmlnode *z; |
345 | |
7014 | 346 muc = TRUE; |
7629 | 347 if((z = xmlnode_get_child(y, "status"))) { |
348 const char *code = xmlnode_get_attrib(z, "code"); | |
349 if(code && !strcmp(code, "201")) { | |
7895 | 350 chat = jabber_chat_find(js, jid->node, jid->domain); |
8396 | 351 chat->config_dialog_type = GAIM_REQUEST_ACTION; |
352 chat->config_dialog_handle = | |
353 gaim_request_action(js->gc, _("Create New Room"), | |
7895 | 354 _("Create New Room"), |
355 _("You are creating a new room. Would you like to " | |
356 "configure it, or accept the default settings?"), | |
357 1, chat, 2, _("Configure Room"), | |
7923 | 358 G_CALLBACK(jabber_chat_request_room_configure), |
7895 | 359 _("Accept Defaults"), |
360 G_CALLBACK(jabber_chat_create_instant_room)); | |
7629 | 361 } |
362 } | |
7944 | 363 if((z = xmlnode_get_child(y, "item"))) { |
364 real_jid = xmlnode_get_attrib(z, "jid"); | |
9152 | 365 affiliation = xmlnode_get_attrib(z, "affiliation"); |
366 role = xmlnode_get_attrib(z, "role"); | |
9931 | 367 if(affiliation != NULL && !strcmp(affiliation, "owner")) |
368 flags |= GAIM_CBFLAGS_FOUNDER; | |
9743 | 369 if (role != NULL) { |
370 if (!strcmp(role, "moderator")) | |
9931 | 371 flags |= GAIM_CBFLAGS_OP; |
9743 | 372 else if (!strcmp(role, "participant")) |
9931 | 373 flags |= GAIM_CBFLAGS_VOICE; |
9743 | 374 } |
7944 | 375 } |
10189 | 376 } else if(xmlns && !strcmp(xmlns, "vcard-temp:x:update")) { |
377 xmlnode *photo = xmlnode_get_child(y, "photo"); | |
378 if(photo) { | |
379 if(avatar_hash) | |
380 g_free(avatar_hash); | |
381 avatar_hash = xmlnode_get_data(photo); | |
382 } | |
7014 | 383 } |
384 } | |
385 } | |
386 | |
387 | |
7322 | 388 if(jid->node && (chat = jabber_chat_find(js, jid->node, jid->domain))) { |
8462 | 389 static int i = 1; |
7014 | 390 char *room_jid = g_strdup_printf("%s@%s", jid->node, jid->domain); |
391 | |
9954 | 392 if(state == JABBER_BUDDY_STATE_ERROR) { |
8401 | 393 char *title, *msg = jabber_parse_error(js, packet); |
7014 | 394 |
7321 | 395 if(chat->conv) { |
8401 | 396 title = g_strdup_printf(_("Error in chat %s"), from); |
7321 | 397 serv_got_chat_left(js->gc, chat->id); |
398 } else { | |
8401 | 399 title = g_strdup_printf(_("Error joining chat %s"), from); |
7321 | 400 } |
8401 | 401 gaim_notify_error(js->gc, title, title, msg); |
402 g_free(title); | |
403 g_free(msg); | |
7014 | 404 |
405 jabber_chat_destroy(chat); | |
7310 | 406 jabber_id_free(jid); |
7615 | 407 g_free(status); |
8182 | 408 g_free(room_jid); |
10189 | 409 if(avatar_hash) |
410 g_free(avatar_hash); | |
7014 | 411 return; |
412 } | |
413 | |
414 | |
7813 | 415 if(type && !strcmp(type, "unavailable")) { |
7972 | 416 gboolean nick_change = FALSE; |
7973 | 417 |
9152 | 418 /* If we haven't joined the chat yet, we don't care that someone |
419 * left, or it was us leaving after we closed the chat */ | |
8182 | 420 if(!chat->conv) { |
10558 | 421 if(jid->resource && chat->handle && !strcmp(jid->resource, chat->handle)) |
9152 | 422 jabber_chat_destroy(chat); |
8182 | 423 jabber_id_free(jid); |
424 g_free(status); | |
425 g_free(room_jid); | |
10189 | 426 if(avatar_hash) |
427 g_free(avatar_hash); | |
8182 | 428 return; |
429 } | |
430 | |
7973 | 431 jabber_buddy_remove_resource(jb, jid->resource); |
7972 | 432 if(chat->muc) { |
433 xmlnode *x; | |
8135 | 434 for(x = xmlnode_get_child(packet, "x"); x; x = xmlnode_get_next_twin(x)) { |
7972 | 435 const char *xmlns, *nick, *code; |
436 xmlnode *stat, *item; | |
437 if(!(xmlns = xmlnode_get_attrib(x, "xmlns")) || | |
438 strcmp(xmlns, "http://jabber.org/protocol/muc#user")) | |
439 continue; | |
440 if(!(stat = xmlnode_get_child(x, "status"))) | |
441 continue; | |
9152 | 442 if(!(code = xmlnode_get_attrib(stat, "code"))) |
7972 | 443 continue; |
9152 | 444 if(!strcmp(code, "301")) { |
445 /* XXX: we got banned */ | |
446 } else if(!strcmp(code, "303")) { | |
447 if(!(item = xmlnode_get_child(x, "item"))) | |
448 continue; | |
449 if(!(nick = xmlnode_get_attrib(item, "nick"))) | |
450 continue; | |
451 nick_change = TRUE; | |
452 if(!strcmp(jid->resource, chat->handle)) { | |
453 g_free(chat->handle); | |
454 chat->handle = g_strdup(nick); | |
455 } | |
456 gaim_conv_chat_rename_user(GAIM_CONV_CHAT(chat->conv), jid->resource, nick); | |
457 jabber_chat_remove_handle(chat, jid->resource); | |
458 break; | |
459 } else if(!strcmp(code, "307")) { | |
460 /* XXX: we got kicked */ | |
461 } else if(!strcmp(code, "321")) { | |
462 /* XXX: removed due to an affiliation change */ | |
463 } else if(!strcmp(code, "322")) { | |
464 /* XXX: removed because room is now members-only */ | |
465 } else if(!strcmp(code, "332")) { | |
466 /* XXX: removed due to system shutdown */ | |
8401 | 467 } |
7972 | 468 } |
469 } | |
470 if(!nick_change) { | |
9152 | 471 if(!g_utf8_collate(jid->resource, chat->handle)) { |
7972 | 472 serv_got_chat_left(js->gc, chat->id); |
473 jabber_chat_destroy(chat); | |
474 } else { | |
475 gaim_conv_chat_remove_user(GAIM_CONV_CHAT(chat->conv), jid->resource, | |
7974 | 476 status); |
9152 | 477 jabber_chat_remove_handle(chat, jid->resource); |
7972 | 478 } |
7014 | 479 } |
480 } else { | |
8182 | 481 if(!chat->conv) { |
482 chat->id = i++; | |
483 chat->muc = muc; | |
484 chat->conv = serv_got_joined_chat(js->gc, chat->id, room_jid); | |
10722 | 485 gaim_conv_chat_set_nick(GAIM_CONV_CHAT(chat->conv), chat->handle); |
10486 | 486 |
10941 | 487 jabber_chat_disco_traffic(chat); |
8182 | 488 } |
489 | |
7973 | 490 jabber_buddy_track_resource(jb, jid->resource, priority, state, |
491 status); | |
492 | |
9152 | 493 jabber_chat_track_handle(chat, jid->resource, real_jid, affiliation, role); |
494 | |
7014 | 495 if(!jabber_chat_find_buddy(chat->conv, jid->resource)) |
7118
bf630f7dfdcd
[gaim-migrate @ 7685]
Christian Hammond <chipx86@chipx86.com>
parents:
7095
diff
changeset
|
496 gaim_conv_chat_add_user(GAIM_CONV_CHAT(chat->conv), jid->resource, |
9846 | 497 real_jid, flags, !delayed); |
9554 | 498 else |
499 gaim_conv_chat_user_set_flags(GAIM_CONV_CHAT(chat->conv), jid->resource, | |
500 flags); | |
7014 | 501 } |
502 g_free(room_jid); | |
503 } else { | |
10486 | 504 if(state != JABBER_BUDDY_STATE_ERROR && !(jb->subscription & JABBER_SUB_TO || jb->subscription & JABBER_SUB_PENDING)) { |
7014 | 505 gaim_debug(GAIM_DEBUG_INFO, "jabber", |
506 "got unexpected presence from %s, ignoring\n", from); | |
507 jabber_id_free(jid); | |
7615 | 508 g_free(status); |
10189 | 509 if(avatar_hash) |
510 g_free(avatar_hash); | |
7014 | 511 return; |
512 } | |
513 | |
7322 | 514 buddy_name = g_strdup_printf("%s%s%s", jid->node ? jid->node : "", |
515 jid->node ? "@" : "", jid->domain); | |
7014 | 516 if((b = gaim_find_buddy(js->gc->account, buddy_name)) == NULL) { |
517 jabber_id_free(jid); | |
10189 | 518 if(avatar_hash) |
519 g_free(avatar_hash); | |
7014 | 520 g_free(buddy_name); |
7615 | 521 g_free(status); |
7014 | 522 return; |
523 } | |
524 | |
10189 | 525 if(avatar_hash) { |
526 const char *avatar_hash2 = gaim_blist_node_get_string((GaimBlistNode*)b, "avatar_hash"); | |
527 if(!avatar_hash2 || strcmp(avatar_hash, avatar_hash2)) { | |
528 JabberIq *iq; | |
529 xmlnode *vcard; | |
530 | |
10941 | 531 /* XXX this is a crappy way of trying to prevent |
532 * someone from spamming us with presence packets | |
533 * and causing us to DoS ourselves...what we really | |
534 * need is a queue system that can throttle itself, | |
535 * but i'm too tired to write that right now */ | |
536 if(!g_slist_find(js->pending_avatar_requests, jb)) { | |
537 | |
538 js->pending_avatar_requests = g_slist_prepend(js->pending_avatar_requests, jb); | |
10189 | 539 |
10941 | 540 iq = jabber_iq_new(js, JABBER_IQ_GET); |
541 xmlnode_set_attrib(iq->node, "to", buddy_name); | |
542 vcard = xmlnode_new_child(iq->node, "vCard"); | |
543 xmlnode_set_attrib(vcard, "xmlns", "vcard-temp"); | |
544 | |
545 jabber_iq_set_callback(iq, jabber_vcard_parse_avatar, NULL); | |
546 jabber_iq_send(iq); | |
547 } | |
10189 | 548 } |
549 } | |
550 | |
9954 | 551 if(state == JABBER_BUDDY_STATE_ERROR || |
7813 | 552 (type && (!strcmp(type, "unavailable") || |
553 !strcmp(type, "unsubscribed")))) { | |
8043 | 554 GaimConversation *conv; |
555 | |
7014 | 556 jabber_buddy_remove_resource(jb, jid->resource); |
8043 | 557 if((conv = jabber_find_unnormalized_conv(from, js->gc->account))) |
558 gaim_conversation_set_name(conv, buddy_name); | |
559 | |
7395 | 560 } else { |
9954 | 561 jbr = jabber_buddy_track_resource(jb, jid->resource, priority, |
562 state, status); | |
7395 | 563 } |
7014 | 564 |
9954 | 565 if((found_jbr = jabber_buddy_find_resource(jb, NULL))) { |
566 if(!jbr || jbr == found_jbr) { | |
9990 | 567 gaim_prpl_got_user_status(js->gc->account, buddy_name, jabber_buddy_state_get_status_id(state), "priority", found_jbr->priority, found_jbr->status ? "message" : NULL, found_jbr->status, NULL); |
9954 | 568 } |
569 } else { | |
9990 | 570 gaim_prpl_got_user_status(js->gc->account, buddy_name, "offline", status ? "message" : NULL, status, NULL); |
9954 | 571 } |
7014 | 572 g_free(buddy_name); |
573 } | |
574 g_free(status); | |
575 jabber_id_free(jid); | |
10189 | 576 if(avatar_hash) |
577 g_free(avatar_hash); | |
7014 | 578 } |
579 | |
580 void jabber_presence_subscription_set(JabberStream *js, const char *who, const char *type) | |
581 { | |
582 xmlnode *presence = xmlnode_new("presence"); | |
583 | |
584 xmlnode_set_attrib(presence, "to", who); | |
585 xmlnode_set_attrib(presence, "type", type); | |
586 | |
587 jabber_send(js, presence); | |
588 xmlnode_free(presence); | |
589 } | |
9954 | 590 |
591 void gaim_status_to_jabber(const GaimStatus *status, JabberBuddyState *state, const char **msg, int *priority) | |
592 { | |
10216 | 593 const char *status_id = NULL; |
594 | |
595 *state = JABBER_BUDDY_STATE_UNKNOWN; | |
596 *msg = NULL; | |
597 *priority = 0; | |
9954 | 598 |
599 if(!status) { | |
10216 | 600 *state = JABBER_BUDDY_STATE_UNAVAILABLE; |
601 } else { | |
602 if(state) { | |
603 status_id = gaim_status_get_id(status); | |
604 *state = jabber_buddy_status_id_get_state(status_id); | |
605 } | |
606 | |
607 if(msg) | |
608 *msg = gaim_status_get_attr_string(status, "message"); | |
609 | |
610 if(priority) | |
611 *priority = gaim_status_get_attr_int(status, "priority"); | |
9954 | 612 } |
613 | |
614 } |