libpurple/protocols/jabber/presence.c

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

mercurial