Mercurial > pidgin
comparison libpurple/protocols/jabber/presence.c @ 25168:805aadbb1a85
propagate from branch 'im.pidgin.pidgin' (head 98fe04f817ef415faebd3f7a38b7f0588c0b0cba)
to branch 'org.darkrain42.pidgin.xmpp' (head ac187cbd274e328fdc1b2f362f58333a0467f54f)
author | Paul Aurich <paul@darkrain42.org> |
---|---|
date | Sat, 22 Nov 2008 19:44:46 +0000 |
parents | 39841a84c944 7dcba13d0e28 |
children | b1b1b75a922e |
comparison
equal
deleted
inserted
replaced
24482:39841a84c944 | 25168:805aadbb1a85 |
---|---|
92 } | 92 } |
93 } | 93 } |
94 g_free(my_base_jid); | 94 g_free(my_base_jid); |
95 } | 95 } |
96 | 96 |
97 | 97 void jabber_set_status(PurpleAccount *account, PurpleStatus *status) |
98 void jabber_presence_send(PurpleAccount *account, PurpleStatus *status) | 98 { |
99 { | 99 PurpleConnection *gc; |
100 PurpleConnection *gc = NULL; | 100 JabberStream *js; |
101 JabberStream *js = NULL; | 101 |
102 if (!purple_account_is_connected(account)) | |
103 return; | |
104 | |
105 if (!purple_status_is_active(status)) | |
106 return; | |
107 | |
108 if (purple_status_is_exclusive(status) && !purple_status_is_active(status)) { | |
109 /* An exclusive status can't be deactivated. You should just | |
110 * activate some other exclusive status. */ | |
111 return; | |
112 } | |
113 | |
114 gc = purple_account_get_connection(account); | |
115 js = gc->proto_data; | |
116 jabber_presence_send(js, FALSE); | |
117 } | |
118 | |
119 void jabber_presence_send(JabberStream *js, gboolean force) | |
120 { | |
121 PurpleAccount *account; | |
102 xmlnode *presence, *x, *photo; | 122 xmlnode *presence, *x, *photo; |
103 char *stripped = NULL; | 123 char *stripped = NULL; |
104 JabberBuddyState state; | 124 JabberBuddyState state; |
105 int priority; | 125 int priority; |
106 const char *artist = NULL, *title = NULL, *source = NULL, *uri = NULL, *track = NULL; | 126 const char *artist = NULL, *title = NULL, *source = NULL, *uri = NULL, *track = NULL; |
107 int length = -1; | 127 int length = -1; |
108 gboolean allowBuzz; | 128 gboolean allowBuzz; |
109 PurplePresence *p; | 129 PurplePresence *p; |
110 PurpleStatus *tune; | 130 PurpleStatus *status, *tune; |
111 | 131 |
112 if (purple_account_is_disconnected(account)) | 132 account = purple_connection_get_account(js->gc); |
113 return; | |
114 | |
115 p = purple_account_get_presence(account); | 133 p = purple_account_get_presence(account); |
116 if (NULL == status) { | 134 status = purple_presence_get_active_status(p); |
117 status = purple_presence_get_active_status(p); | |
118 } | |
119 | |
120 if (purple_status_is_exclusive(status)) { | |
121 /* An exclusive status can't be deactivated. You should just | |
122 * activate some other exclusive status. */ | |
123 if (!purple_status_is_active(status)) | |
124 return; | |
125 } else { | |
126 /* Work with the exclusive status. */ | |
127 status = purple_presence_get_active_status(p); | |
128 } | |
129 | |
130 gc = purple_account_get_connection(account); | |
131 js = gc->proto_data; | |
132 | 135 |
133 /* we don't want to send presence before we've gotten our roster */ | 136 /* we don't want to send presence before we've gotten our roster */ |
134 if(!js->roster_parsed) { | 137 if(!js->roster_parsed) { |
135 purple_debug_info("jabber", "attempt to send presence before roster retrieved\n"); | 138 purple_debug_info("jabber", "attempt to send presence before roster retrieved\n"); |
136 return; | 139 return; |
140 | 143 |
141 /* check for buzz support */ | 144 /* check for buzz support */ |
142 allowBuzz = purple_status_get_attr_boolean(status,"buzz"); | 145 allowBuzz = purple_status_get_attr_boolean(status,"buzz"); |
143 /* changing the buzz state has to trigger a re-broadcasting of the presence for caps */ | 146 /* changing the buzz state has to trigger a re-broadcasting of the presence for caps */ |
144 | 147 |
145 if (js->googletalk && stripped == NULL && purple_presence_is_status_primitive_active(p, PURPLE_STATUS_TUNE)) { | 148 tune = purple_presence_get_status(p, "tune"); |
146 tune = purple_presence_get_status(p, "tune"); | 149 if (js->googletalk && !stripped && purple_status_is_active(tune)) { |
147 stripped = jabber_google_presence_outgoing(tune); | 150 stripped = jabber_google_presence_outgoing(tune); |
148 } | 151 } |
149 | 152 |
150 #define CHANGED(a,b) ((!a && b) || (a && a[0] == '\0' && b && b[0] != '\0') || \ | 153 #define CHANGED(a,b) ((!a && b) || (a && a[0] == '\0' && b && b[0] != '\0') || \ |
151 (a && !b) || (a && a[0] != '\0' && b && b[0] == '\0') || (a && b && strcmp(a,b))) | 154 (a && !b) || (a && a[0] != '\0' && b && b[0] == '\0') || (a && b && strcmp(a,b))) |
152 /* check if there are any differences to the <presence> and send them in that case */ | 155 /* check if there are any differences to the <presence> and send them in that case */ |
153 if (allowBuzz != js->allowBuzz || js->old_state != state || CHANGED(js->old_msg, stripped) || | 156 if (force || allowBuzz != js->allowBuzz || js->old_state != state || |
154 js->old_priority != priority || CHANGED(js->old_avatarhash, js->avatar_hash)) { | 157 CHANGED(js->old_msg, stripped) || js->old_priority != priority || |
158 CHANGED(js->old_avatarhash, js->avatar_hash)) { | |
159 /* Need to update allowBuzz before creating the presence (with caps) */ | |
155 js->allowBuzz = allowBuzz; | 160 js->allowBuzz = allowBuzz; |
156 | 161 |
157 presence = jabber_presence_create_js(js, state, stripped, priority); | 162 presence = jabber_presence_create_js(js, state, stripped, priority); |
158 | 163 |
159 if(js->avatar_hash) { | 164 if(js->avatar_hash) { |
180 js->old_priority = priority; | 185 js->old_priority = priority; |
181 } | 186 } |
182 g_free(stripped); | 187 g_free(stripped); |
183 | 188 |
184 /* next, check if there are any changes to the tune values */ | 189 /* next, check if there are any changes to the tune values */ |
185 tune = purple_presence_get_status(p, "tune"); | 190 if (purple_status_is_active(tune)) { |
186 if (tune && purple_status_is_active(tune)) { | |
187 artist = purple_status_get_attr_string(tune, PURPLE_TUNE_ARTIST); | 191 artist = purple_status_get_attr_string(tune, PURPLE_TUNE_ARTIST); |
188 title = purple_status_get_attr_string(tune, PURPLE_TUNE_TITLE); | 192 title = purple_status_get_attr_string(tune, PURPLE_TUNE_TITLE); |
189 source = purple_status_get_attr_string(tune, PURPLE_TUNE_ALBUM); | 193 source = purple_status_get_attr_string(tune, PURPLE_TUNE_ALBUM); |
190 uri = purple_status_get_attr_string(tune, PURPLE_TUNE_URL); | 194 uri = purple_status_get_attr_string(tune, PURPLE_TUNE_URL); |
191 track = purple_status_get_attr_string(tune, PURPLE_TUNE_TRACK); | 195 track = purple_status_get_attr_string(tune, PURPLE_TUNE_TRACK); |
259 xmlnode_insert_data(pri, pstr, -1); | 263 xmlnode_insert_data(pri, pstr, -1); |
260 g_free(pstr); | 264 g_free(pstr); |
261 } | 265 } |
262 | 266 |
263 /* JEP-0115 */ | 267 /* JEP-0115 */ |
268 /* calculate hash */ | |
269 jabber_caps_calculate_own_hash(js); | |
270 /* create xml */ | |
264 c = xmlnode_new_child(presence, "c"); | 271 c = xmlnode_new_child(presence, "c"); |
265 xmlnode_set_namespace(c, "http://jabber.org/protocol/caps"); | 272 xmlnode_set_namespace(c, "http://jabber.org/protocol/caps"); |
266 xmlnode_set_attrib(c, "node", CAPS0115_NODE); | 273 xmlnode_set_attrib(c, "node", CAPS0115_NODE); |
267 xmlnode_set_attrib(c, "ver", VERSION); | 274 xmlnode_set_attrib(c, "hash", "sha-1"); |
268 | 275 xmlnode_set_attrib(c, "ver", jabber_caps_get_own_hash(js)); |
276 | |
277 #if 0 | |
269 if(js != NULL) { | 278 if(js != NULL) { |
270 /* add the extensions */ | 279 /* add the extensions */ |
271 char extlist[1024]; | 280 char extlist[1024]; |
272 unsigned remaining = 1023; /* one less for the \0 */ | 281 unsigned remaining = 1023; /* one less for the \0 */ |
273 GList *feature; | 282 GList *feature; |
275 extlist[0] = '\0'; | 284 extlist[0] = '\0'; |
276 for(feature = jabber_features; feature && remaining > 0; feature = feature->next) { | 285 for(feature = jabber_features; feature && remaining > 0; feature = feature->next) { |
277 JabberFeature *feat = (JabberFeature*)feature->data; | 286 JabberFeature *feat = (JabberFeature*)feature->data; |
278 unsigned featlen; | 287 unsigned featlen; |
279 | 288 |
280 if(feat->is_enabled != NULL && feat->is_enabled(js, feat->shortname, feat->namespace) == FALSE) | 289 if(feat->is_enabled != NULL && feat->is_enabled(js, feat->namespace) == FALSE) |
281 continue; /* skip this feature */ | 290 continue; /* skip this feature */ |
282 | 291 |
283 featlen = strlen(feat->shortname); | 292 featlen = strlen(feat->shortname); |
284 | 293 |
285 /* cut off when we don't have any more space left in our buffer (too bad) */ | 294 /* cut off when we don't have any more space left in our buffer (too bad) */ |
295 } | 304 } |
296 /* did we add anything? */ | 305 /* did we add anything? */ |
297 if(remaining < 1023) | 306 if(remaining < 1023) |
298 xmlnode_set_attrib(c, "ext", extlist); | 307 xmlnode_set_attrib(c, "ext", extlist); |
299 } | 308 } |
300 | 309 #endif |
301 return presence; | 310 return presence; |
302 } | 311 } |
303 | 312 |
304 struct _jabber_add_permit { | 313 struct _jabber_add_permit { |
305 PurpleConnection *gc; | 314 PurpleConnection *gc; |
371 JabberStream *js; | 380 JabberStream *js; |
372 JabberBuddy *jb; | 381 JabberBuddy *jb; |
373 char *from; | 382 char *from; |
374 } JabberPresenceCapabilities; | 383 } JabberPresenceCapabilities; |
375 | 384 |
376 static void jabber_presence_set_capabilities(JabberCapsClientInfo *info, gpointer user_data) { | 385 static void jabber_presence_set_capabilities(JabberCapsClientInfo *info, JabberPresenceCapabilities *userdata) |
377 JabberPresenceCapabilities *userdata = user_data; | 386 { |
378 JabberID *jid; | |
379 JabberBuddyResource *jbr; | 387 JabberBuddyResource *jbr; |
380 GList *iter; | 388 char *resource = g_utf8_strrchr(userdata->from, -1, '/'); |
381 | 389 resource += 1; |
382 jid = jabber_id_new(userdata->from); | 390 |
383 jbr = jabber_buddy_find_resource(userdata->jb, jid->resource); | 391 jbr = jabber_buddy_find_resource(userdata->jb, resource); |
384 jabber_id_free(jid); | 392 if (!jbr) { |
385 | |
386 if(!jbr) { | |
387 g_free(userdata->from); | 393 g_free(userdata->from); |
388 g_free(userdata); | 394 g_free(userdata); |
389 return; | 395 return; |
390 } | 396 } |
391 | 397 |
392 if(jbr->caps) | 398 /* old value in jbr->caps is owned by caps code */ |
393 jabber_caps_free_clientinfo(jbr->caps); | |
394 jbr->caps = info; | 399 jbr->caps = info; |
395 | 400 |
396 if (info) { | 401 if (info) { |
397 for(iter = info->features; iter; iter = g_list_next(iter)) { | 402 GList *node = g_list_find_custom(info->features, "http://jabber.org/protocol/commands", (GCompareFunc)strcmp); |
398 if(!strcmp((const char*)iter->data, "http://jabber.org/protocol/commands")) { | 403 if (node) { |
399 JabberIq *iq = jabber_iq_new_query(userdata->js, JABBER_IQ_GET, "http://jabber.org/protocol/disco#items"); | 404 JabberIq *iq = jabber_iq_new_query(userdata->js, JABBER_IQ_GET, "http://jabber.org/protocol/disco#items"); |
400 xmlnode *query = xmlnode_get_child_with_namespace(iq->node,"query","http://jabber.org/protocol/disco#items"); | 405 xmlnode *query = xmlnode_get_child_with_namespace(iq->node, "query", "http://jabber.org/protocol/disco#items"); |
401 xmlnode_set_attrib(iq->node, "to", userdata->from); | 406 xmlnode_set_attrib(iq->node, "to", userdata->from); |
402 xmlnode_set_attrib(query, "node", "http://jabber.org/protocol/commands"); | 407 xmlnode_set_attrib(query, "node", "http://jabber.org/protocol/commands"); |
403 | 408 jabber_iq_set_callback(iq, jabber_adhoc_disco_result_cb, NULL); |
404 jabber_iq_set_callback(iq, jabber_adhoc_disco_result_cb, NULL); | 409 jabber_iq_send(iq); |
405 jabber_iq_send(iq); | |
406 break; | |
407 } | |
408 } | 410 } |
409 } | 411 } |
410 | 412 |
411 g_free(userdata->from); | 413 g_free(userdata->from); |
412 g_free(userdata); | 414 g_free(userdata); |
746 | 748 |
747 } else { | 749 } else { |
748 jbr = jabber_buddy_track_resource(jb, jid->resource, priority, | 750 jbr = jabber_buddy_track_resource(jb, jid->resource, priority, |
749 state, status); | 751 state, status); |
750 if(caps) { | 752 if(caps) { |
753 /* handle XEP-0115 */ | |
751 const char *node = xmlnode_get_attrib(caps,"node"); | 754 const char *node = xmlnode_get_attrib(caps,"node"); |
752 const char *ver = xmlnode_get_attrib(caps,"ver"); | 755 const char *ver = xmlnode_get_attrib(caps,"ver"); |
753 const char *ext = xmlnode_get_attrib(caps,"ext"); | 756 const char *hash = xmlnode_get_attrib(caps,"hash"); |
754 | 757 |
755 if(node && ver) { | 758 if(node && ver && hash) { |
756 JabberPresenceCapabilities *userdata = g_new0(JabberPresenceCapabilities, 1); | 759 JabberPresenceCapabilities *userdata = g_new0(JabberPresenceCapabilities, 1); |
757 userdata->js = js; | 760 userdata->js = js; |
758 userdata->jb = jb; | 761 userdata->jb = jb; |
759 userdata->from = g_strdup(from); | 762 userdata->from = g_strdup(from); |
760 jabber_caps_get_info(js, from, node, ver, ext, jabber_presence_set_capabilities, userdata); | 763 jabber_caps_get_info(js, from, node, ver, hash, |
764 (jabber_caps_get_info_cb)jabber_presence_set_capabilities, | |
765 userdata); | |
761 } | 766 } |
762 } | 767 } |
763 } | 768 } |
764 | 769 |
765 if((found_jbr = jabber_buddy_find_resource(jb, NULL))) { | 770 if((found_jbr = jabber_buddy_find_resource(jb, NULL))) { |