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))) {