Mercurial > pidgin.yaz
annotate src/protocols/jabber/presence.c @ 11013:7653143dec36
[gaim-migrate @ 12879]
This fixes signing off and on again with jabber for me. I haven't tested being disconnected but it works if I choose Offline from the status box.
Oh, I'm not exactly sure this is the right way to fix this but it works for me. Nathan (or anyone else) feel free to tell me I'm wrong or fix it.
committer: Tailor Script <tailor@pidgin.im>
author | Etan Reisner <pidgin@unreliablesource.net> |
---|---|
date | Fri, 17 Jun 2005 07:37:35 +0000 |
parents | 1adca5a37fb8 |
children | 719779387f96 |
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; |
10755 | 94 gboolean connected; |
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 | |
10755 | 105 connected = gaim_account_is_connected(account); |
106 primitive = gaim_status_type_get_primitive(gaim_status_get_type(status)); | |
107 | |
108 if(primitive != GAIM_STATUS_OFFLINE && !connected) { | |
10738 | 109 gaim_account_connect(account); |
10755 | 110 } |
111 | |
112 if(!connected) | |
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 | |
11013
7653143dec36
[gaim-migrate @ 12879]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10949
diff
changeset
|
140 if(primitive == GAIM_STATUS_OFFLINE && connected) { |
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 { |
147 xmlnode *show, *status, *presence; | |
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 | |
171 return presence; | |
172 } | |
173 | |
174 struct _jabber_add_permit { | |
175 GaimConnection *gc; | |
176 char *who; | |
177 }; | |
178 | |
179 static void authorize_add_cb(struct _jabber_add_permit *jap) | |
180 { | |
181 if(g_list_find(gaim_connections_get_all(), jap->gc)) { | |
182 jabber_presence_subscription_set(jap->gc->proto_data, jap->who, | |
183 "subscribed"); | |
184 | |
185 if(!gaim_find_buddy(jap->gc->account, jap->who)) | |
7015
dece74f05509
[gaim-migrate @ 7578]
Christian Hammond <chipx86@chipx86.com>
parents:
7014
diff
changeset
|
186 gaim_account_notify_added(jap->gc->account, NULL, jap->who, NULL, NULL); |
7014 | 187 } |
188 | |
189 g_free(jap->who); | |
190 g_free(jap); | |
191 } | |
192 | |
193 static void deny_add_cb(struct _jabber_add_permit *jap) | |
194 { | |
195 if(g_list_find(gaim_connections_get_all(), jap->gc)) { | |
196 jabber_presence_subscription_set(jap->gc->proto_data, jap->who, | |
197 "unsubscribed"); | |
198 } | |
199 | |
200 g_free(jap->who); | |
201 g_free(jap); | |
202 } | |
203 | |
10189 | 204 static void jabber_vcard_parse_avatar(JabberStream *js, xmlnode *packet, gpointer blah) |
205 { | |
10941 | 206 JabberBuddy *jb = NULL; |
10189 | 207 GaimBuddy *b = NULL; |
10941 | 208 xmlnode *vcard, *photo, *binval; |
10189 | 209 char *text, *data; |
210 int size; | |
211 const char *from = xmlnode_get_attrib(packet, "from"); | |
212 | |
213 if(!from) | |
214 return; | |
215 | |
10941 | 216 jb = jabber_buddy_find(js, from, TRUE); |
217 | |
218 js->pending_avatar_requests = g_slist_remove(js->pending_avatar_requests, jb); | |
219 | |
10189 | 220 if((vcard = xmlnode_get_child(packet, "vCard")) || |
221 (vcard = xmlnode_get_child_with_namespace(packet, "query", "vcard-temp"))) { | |
10941 | 222 if((photo = xmlnode_get_child(vcard, "PHOTO")) && |
223 (binval = xmlnode_get_child(photo, "BINVAL")) && | |
224 (text = xmlnode_get_data(binval))) { | |
225 gaim_base64_decode(text, &data, &size); | |
10189 | 226 |
10941 | 227 gaim_buddy_icons_set_for_user(js->gc->account, from, data, size); |
228 if((b = gaim_find_buddy(js->gc->account, from))) { | |
229 unsigned char hashval[20]; | |
230 char hash[41], *p; | |
231 int i; | |
10189 | 232 |
10941 | 233 gaim_cipher_digest_region("sha1", (guint8 *)data, size, |
234 sizeof(hashval), hashval, NULL); | |
235 p = hash; | |
236 for(i=0; i<20; i++, p+=2) | |
237 snprintf(p, 3, "%02x", hashval[i]); | |
238 gaim_blist_node_set_string((GaimBlistNode*)b, "avatar_hash", hash); | |
10189 | 239 } |
10941 | 240 g_free(text); |
10189 | 241 } |
242 } | |
243 } | |
244 | |
7014 | 245 void jabber_presence_parse(JabberStream *js, xmlnode *packet) |
246 { | |
247 const char *from = xmlnode_get_attrib(packet, "from"); | |
248 const char *type = xmlnode_get_attrib(packet, "type"); | |
7944 | 249 const char *real_jid = NULL; |
9152 | 250 const char *affiliation = NULL; |
251 const char *role = NULL; | |
7014 | 252 char *status = NULL; |
253 int priority = 0; | |
254 JabberID *jid; | |
255 JabberChat *chat; | |
256 JabberBuddy *jb; | |
9954 | 257 JabberBuddyResource *jbr = NULL, *found_jbr = NULL; |
9554 | 258 GaimConvChatBuddyFlags flags = GAIM_CBFLAGS_NONE; |
9846 | 259 gboolean delayed = FALSE; |
10189 | 260 GaimBuddy *b = NULL; |
7014 | 261 char *buddy_name; |
9954 | 262 JabberBuddyState state = JABBER_BUDDY_STATE_UNKNOWN; |
7014 | 263 xmlnode *y; |
264 gboolean muc = FALSE; | |
10189 | 265 char *avatar_hash = NULL; |
7014 | 266 |
267 | |
8043 | 268 if(!(jb = jabber_buddy_find(js, from, TRUE))) |
269 return; | |
270 | |
271 if(!(jid = jabber_id_new(from))) | |
7280 | 272 return; |
273 | |
7014 | 274 if(jb->error_msg) { |
275 g_free(jb->error_msg); | |
276 jb->error_msg = NULL; | |
277 } | |
278 | |
7813 | 279 if(type && !strcmp(type, "error")) { |
8401 | 280 char *msg = jabber_parse_error(js, packet); |
7644 | 281 |
9954 | 282 state = JABBER_BUDDY_STATE_ERROR; |
8401 | 283 jb->error_msg = msg ? msg : g_strdup(_("Unknown Error in presence")); |
7813 | 284 } else if(type && !strcmp(type, "subscribe")) { |
7014 | 285 struct _jabber_add_permit *jap = g_new0(struct _jabber_add_permit, 1); |
10949 | 286 char *msg; |
287 | |
288 msg = g_strdup_printf(_("The user %s wants to add %s to his or " | |
289 "her buddy list."), | |
290 from, gaim_account_get_username(js->gc->account)); | |
7014 | 291 jap->gc = js->gc; |
292 jap->who = g_strdup(from); | |
293 | |
10189 | 294 gaim_request_action(js->gc, NULL, msg, NULL, GAIM_DEFAULT_ACTION_NONE, |
10116 | 295 jap, 2, |
7014 | 296 _("Authorize"), G_CALLBACK(authorize_add_cb), |
297 _("Deny"), G_CALLBACK(deny_add_cb)); | |
298 g_free(msg); | |
8043 | 299 jabber_id_free(jid); |
7145 | 300 return; |
7813 | 301 } else if(type && !strcmp(type, "subscribed")) { |
7014 | 302 /* we've been allowed to see their presence, but we don't care */ |
8043 | 303 jabber_id_free(jid); |
7014 | 304 return; |
305 } else { | |
306 if((y = xmlnode_get_child(packet, "show"))) { | |
307 char *show = xmlnode_get_data(y); | |
9954 | 308 state = jabber_buddy_status_id_get_state(show); |
7014 | 309 g_free(show); |
310 } else { | |
9954 | 311 state = JABBER_BUDDY_STATE_ONLINE; |
7014 | 312 } |
313 } | |
314 | |
7310 | 315 |
7014 | 316 for(y = packet->child; y; y = y->next) { |
8135 | 317 if(y->type != XMLNODE_TYPE_TAG) |
7014 | 318 continue; |
319 | |
320 if(!strcmp(y->name, "status")) { | |
7615 | 321 g_free(status); |
7014 | 322 status = xmlnode_get_data(y); |
323 } else if(!strcmp(y->name, "priority")) { | |
324 char *p = xmlnode_get_data(y); | |
325 if(p) { | |
326 priority = atoi(p); | |
327 g_free(p); | |
328 } | |
329 } else if(!strcmp(y->name, "x")) { | |
330 const char *xmlns = xmlnode_get_attrib(y, "xmlns"); | |
9846 | 331 if(xmlns && !strcmp(xmlns, "jabber:x:delay")) { |
9847 | 332 /* XXX: compare the time. jabber:x:delay can happen on presence packets that aren't really and truly delayed */ |
9846 | 333 delayed = TRUE; |
334 } else if(xmlns && !strcmp(xmlns, "http://jabber.org/protocol/muc#user")) { | |
7629 | 335 xmlnode *z; |
336 | |
7014 | 337 muc = TRUE; |
7629 | 338 if((z = xmlnode_get_child(y, "status"))) { |
339 const char *code = xmlnode_get_attrib(z, "code"); | |
340 if(code && !strcmp(code, "201")) { | |
7895 | 341 chat = jabber_chat_find(js, jid->node, jid->domain); |
8396 | 342 chat->config_dialog_type = GAIM_REQUEST_ACTION; |
343 chat->config_dialog_handle = | |
344 gaim_request_action(js->gc, _("Create New Room"), | |
7895 | 345 _("Create New Room"), |
346 _("You are creating a new room. Would you like to " | |
347 "configure it, or accept the default settings?"), | |
348 1, chat, 2, _("Configure Room"), | |
7923 | 349 G_CALLBACK(jabber_chat_request_room_configure), |
7895 | 350 _("Accept Defaults"), |
351 G_CALLBACK(jabber_chat_create_instant_room)); | |
7629 | 352 } |
353 } | |
7944 | 354 if((z = xmlnode_get_child(y, "item"))) { |
355 real_jid = xmlnode_get_attrib(z, "jid"); | |
9152 | 356 affiliation = xmlnode_get_attrib(z, "affiliation"); |
357 role = xmlnode_get_attrib(z, "role"); | |
9931 | 358 if(affiliation != NULL && !strcmp(affiliation, "owner")) |
359 flags |= GAIM_CBFLAGS_FOUNDER; | |
9743 | 360 if (role != NULL) { |
361 if (!strcmp(role, "moderator")) | |
9931 | 362 flags |= GAIM_CBFLAGS_OP; |
9743 | 363 else if (!strcmp(role, "participant")) |
9931 | 364 flags |= GAIM_CBFLAGS_VOICE; |
9743 | 365 } |
7944 | 366 } |
10189 | 367 } else if(xmlns && !strcmp(xmlns, "vcard-temp:x:update")) { |
368 xmlnode *photo = xmlnode_get_child(y, "photo"); | |
369 if(photo) { | |
370 if(avatar_hash) | |
371 g_free(avatar_hash); | |
372 avatar_hash = xmlnode_get_data(photo); | |
373 } | |
7014 | 374 } |
375 } | |
376 } | |
377 | |
378 | |
7322 | 379 if(jid->node && (chat = jabber_chat_find(js, jid->node, jid->domain))) { |
8462 | 380 static int i = 1; |
7014 | 381 char *room_jid = g_strdup_printf("%s@%s", jid->node, jid->domain); |
382 | |
9954 | 383 if(state == JABBER_BUDDY_STATE_ERROR) { |
8401 | 384 char *title, *msg = jabber_parse_error(js, packet); |
7014 | 385 |
7321 | 386 if(chat->conv) { |
8401 | 387 title = g_strdup_printf(_("Error in chat %s"), from); |
7321 | 388 serv_got_chat_left(js->gc, chat->id); |
389 } else { | |
8401 | 390 title = g_strdup_printf(_("Error joining chat %s"), from); |
7321 | 391 } |
8401 | 392 gaim_notify_error(js->gc, title, title, msg); |
393 g_free(title); | |
394 g_free(msg); | |
7014 | 395 |
396 jabber_chat_destroy(chat); | |
7310 | 397 jabber_id_free(jid); |
7615 | 398 g_free(status); |
8182 | 399 g_free(room_jid); |
10189 | 400 if(avatar_hash) |
401 g_free(avatar_hash); | |
7014 | 402 return; |
403 } | |
404 | |
405 | |
7813 | 406 if(type && !strcmp(type, "unavailable")) { |
7972 | 407 gboolean nick_change = FALSE; |
7973 | 408 |
9152 | 409 /* If we haven't joined the chat yet, we don't care that someone |
410 * left, or it was us leaving after we closed the chat */ | |
8182 | 411 if(!chat->conv) { |
10558 | 412 if(jid->resource && chat->handle && !strcmp(jid->resource, chat->handle)) |
9152 | 413 jabber_chat_destroy(chat); |
8182 | 414 jabber_id_free(jid); |
415 g_free(status); | |
416 g_free(room_jid); | |
10189 | 417 if(avatar_hash) |
418 g_free(avatar_hash); | |
8182 | 419 return; |
420 } | |
421 | |
7973 | 422 jabber_buddy_remove_resource(jb, jid->resource); |
7972 | 423 if(chat->muc) { |
424 xmlnode *x; | |
8135 | 425 for(x = xmlnode_get_child(packet, "x"); x; x = xmlnode_get_next_twin(x)) { |
7972 | 426 const char *xmlns, *nick, *code; |
427 xmlnode *stat, *item; | |
428 if(!(xmlns = xmlnode_get_attrib(x, "xmlns")) || | |
429 strcmp(xmlns, "http://jabber.org/protocol/muc#user")) | |
430 continue; | |
431 if(!(stat = xmlnode_get_child(x, "status"))) | |
432 continue; | |
9152 | 433 if(!(code = xmlnode_get_attrib(stat, "code"))) |
7972 | 434 continue; |
9152 | 435 if(!strcmp(code, "301")) { |
436 /* XXX: we got banned */ | |
437 } else if(!strcmp(code, "303")) { | |
438 if(!(item = xmlnode_get_child(x, "item"))) | |
439 continue; | |
440 if(!(nick = xmlnode_get_attrib(item, "nick"))) | |
441 continue; | |
442 nick_change = TRUE; | |
443 if(!strcmp(jid->resource, chat->handle)) { | |
444 g_free(chat->handle); | |
445 chat->handle = g_strdup(nick); | |
446 } | |
447 gaim_conv_chat_rename_user(GAIM_CONV_CHAT(chat->conv), jid->resource, nick); | |
448 jabber_chat_remove_handle(chat, jid->resource); | |
449 break; | |
450 } else if(!strcmp(code, "307")) { | |
451 /* XXX: we got kicked */ | |
452 } else if(!strcmp(code, "321")) { | |
453 /* XXX: removed due to an affiliation change */ | |
454 } else if(!strcmp(code, "322")) { | |
455 /* XXX: removed because room is now members-only */ | |
456 } else if(!strcmp(code, "332")) { | |
457 /* XXX: removed due to system shutdown */ | |
8401 | 458 } |
7972 | 459 } |
460 } | |
461 if(!nick_change) { | |
9152 | 462 if(!g_utf8_collate(jid->resource, chat->handle)) { |
7972 | 463 serv_got_chat_left(js->gc, chat->id); |
464 jabber_chat_destroy(chat); | |
465 } else { | |
466 gaim_conv_chat_remove_user(GAIM_CONV_CHAT(chat->conv), jid->resource, | |
7974 | 467 status); |
9152 | 468 jabber_chat_remove_handle(chat, jid->resource); |
7972 | 469 } |
7014 | 470 } |
471 } else { | |
8182 | 472 if(!chat->conv) { |
473 chat->id = i++; | |
474 chat->muc = muc; | |
475 chat->conv = serv_got_joined_chat(js->gc, chat->id, room_jid); | |
10722 | 476 gaim_conv_chat_set_nick(GAIM_CONV_CHAT(chat->conv), chat->handle); |
10486 | 477 |
10941 | 478 jabber_chat_disco_traffic(chat); |
8182 | 479 } |
480 | |
7973 | 481 jabber_buddy_track_resource(jb, jid->resource, priority, state, |
482 status); | |
483 | |
9152 | 484 jabber_chat_track_handle(chat, jid->resource, real_jid, affiliation, role); |
485 | |
7014 | 486 if(!jabber_chat_find_buddy(chat->conv, jid->resource)) |
7118
bf630f7dfdcd
[gaim-migrate @ 7685]
Christian Hammond <chipx86@chipx86.com>
parents:
7095
diff
changeset
|
487 gaim_conv_chat_add_user(GAIM_CONV_CHAT(chat->conv), jid->resource, |
9846 | 488 real_jid, flags, !delayed); |
9554 | 489 else |
490 gaim_conv_chat_user_set_flags(GAIM_CONV_CHAT(chat->conv), jid->resource, | |
491 flags); | |
7014 | 492 } |
493 g_free(room_jid); | |
494 } else { | |
10486 | 495 if(state != JABBER_BUDDY_STATE_ERROR && !(jb->subscription & JABBER_SUB_TO || jb->subscription & JABBER_SUB_PENDING)) { |
7014 | 496 gaim_debug(GAIM_DEBUG_INFO, "jabber", |
497 "got unexpected presence from %s, ignoring\n", from); | |
498 jabber_id_free(jid); | |
7615 | 499 g_free(status); |
10189 | 500 if(avatar_hash) |
501 g_free(avatar_hash); | |
7014 | 502 return; |
503 } | |
504 | |
7322 | 505 buddy_name = g_strdup_printf("%s%s%s", jid->node ? jid->node : "", |
506 jid->node ? "@" : "", jid->domain); | |
7014 | 507 if((b = gaim_find_buddy(js->gc->account, buddy_name)) == NULL) { |
508 jabber_id_free(jid); | |
10189 | 509 if(avatar_hash) |
510 g_free(avatar_hash); | |
7014 | 511 g_free(buddy_name); |
7615 | 512 g_free(status); |
7014 | 513 return; |
514 } | |
515 | |
10189 | 516 if(avatar_hash) { |
517 const char *avatar_hash2 = gaim_blist_node_get_string((GaimBlistNode*)b, "avatar_hash"); | |
518 if(!avatar_hash2 || strcmp(avatar_hash, avatar_hash2)) { | |
519 JabberIq *iq; | |
520 xmlnode *vcard; | |
521 | |
10941 | 522 /* XXX this is a crappy way of trying to prevent |
523 * someone from spamming us with presence packets | |
524 * and causing us to DoS ourselves...what we really | |
525 * need is a queue system that can throttle itself, | |
526 * but i'm too tired to write that right now */ | |
527 if(!g_slist_find(js->pending_avatar_requests, jb)) { | |
528 | |
529 js->pending_avatar_requests = g_slist_prepend(js->pending_avatar_requests, jb); | |
10189 | 530 |
10941 | 531 iq = jabber_iq_new(js, JABBER_IQ_GET); |
532 xmlnode_set_attrib(iq->node, "to", buddy_name); | |
533 vcard = xmlnode_new_child(iq->node, "vCard"); | |
534 xmlnode_set_attrib(vcard, "xmlns", "vcard-temp"); | |
535 | |
536 jabber_iq_set_callback(iq, jabber_vcard_parse_avatar, NULL); | |
537 jabber_iq_send(iq); | |
538 } | |
10189 | 539 } |
540 } | |
541 | |
9954 | 542 if(state == JABBER_BUDDY_STATE_ERROR || |
7813 | 543 (type && (!strcmp(type, "unavailable") || |
544 !strcmp(type, "unsubscribed")))) { | |
8043 | 545 GaimConversation *conv; |
546 | |
7014 | 547 jabber_buddy_remove_resource(jb, jid->resource); |
8043 | 548 if((conv = jabber_find_unnormalized_conv(from, js->gc->account))) |
549 gaim_conversation_set_name(conv, buddy_name); | |
550 | |
7395 | 551 } else { |
9954 | 552 jbr = jabber_buddy_track_resource(jb, jid->resource, priority, |
553 state, status); | |
7395 | 554 } |
7014 | 555 |
9954 | 556 if((found_jbr = jabber_buddy_find_resource(jb, NULL))) { |
557 if(!jbr || jbr == found_jbr) { | |
9990 | 558 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 | 559 } |
560 } else { | |
9990 | 561 gaim_prpl_got_user_status(js->gc->account, buddy_name, "offline", status ? "message" : NULL, status, NULL); |
9954 | 562 } |
7014 | 563 g_free(buddy_name); |
564 } | |
565 g_free(status); | |
566 jabber_id_free(jid); | |
10189 | 567 if(avatar_hash) |
568 g_free(avatar_hash); | |
7014 | 569 } |
570 | |
571 void jabber_presence_subscription_set(JabberStream *js, const char *who, const char *type) | |
572 { | |
573 xmlnode *presence = xmlnode_new("presence"); | |
574 | |
575 xmlnode_set_attrib(presence, "to", who); | |
576 xmlnode_set_attrib(presence, "type", type); | |
577 | |
578 jabber_send(js, presence); | |
579 xmlnode_free(presence); | |
580 } | |
9954 | 581 |
582 void gaim_status_to_jabber(const GaimStatus *status, JabberBuddyState *state, const char **msg, int *priority) | |
583 { | |
10216 | 584 const char *status_id = NULL; |
585 | |
586 *state = JABBER_BUDDY_STATE_UNKNOWN; | |
587 *msg = NULL; | |
588 *priority = 0; | |
9954 | 589 |
590 if(!status) { | |
10216 | 591 *state = JABBER_BUDDY_STATE_UNAVAILABLE; |
592 } else { | |
593 if(state) { | |
594 status_id = gaim_status_get_id(status); | |
595 *state = jabber_buddy_status_id_get_state(status_id); | |
596 } | |
597 | |
598 if(msg) | |
599 *msg = gaim_status_get_attr_string(status, "message"); | |
600 | |
601 if(priority) | |
602 *priority = gaim_status_get_attr_int(status, "priority"); | |
9954 | 603 } |
604 | |
605 } |