void jabber_roster_parse(JabberStream *js, xmlnode *packet) { int nCount = 0; /*VOXOX - JRT - 2009.04.08 */ int nGroupCnt = 0; //VOXOX - JRT - 2009.05.07 xmlnode *query, *item, *group; const char *from = xmlnode_get_attrib(packet, "from"); if(from) { char *from_norm; gboolean invalid; from_norm = g_strdup(jabber_normalize(js->gc->account, from)); if(!from_norm) return; invalid = g_utf8_collate(from_norm, jabber_normalize(js->gc->account, purple_account_get_username(js->gc->account))); g_free(from_norm); if(invalid) return; } query = xmlnode_get_child(packet, "query"); if(!query) return; //VOXOX - JRT - 2009.04.11 - So we can notify UI of initial contact list loading is starting. if(!js->roster_parsed) { set_purple_initial_load( 1 ); } //End VoxOx js->currently_parsing_roster_push = TRUE; //VOXOX - JRT - 2009.04.08 - We parsed about 1200 in less than 1 second with add_purple_buddies_to_groups() commented. for(item = xmlnode_get_child(query, "item"); item; item = xmlnode_get_next_twin(item)) { const char *jid, *name, *subscription, *ask; JabberBuddy *jb; subscription = xmlnode_get_attrib(item, "subscription"); jid = xmlnode_get_attrib(item, "jid"); name = xmlnode_get_attrib(item, "name"); ask = xmlnode_get_attrib(item, "ask"); if(!jid) continue; if(!(jb = jabber_buddy_find(js, jid, TRUE))) continue; if(subscription) { gint me = -1; char *jid_norm; const char *username; jid_norm = g_strdup(jabber_normalize(js->gc->account, jid)); username = purple_account_get_username(js->gc->account); me = g_utf8_collate(jid_norm, jabber_normalize(js->gc->account, username)); g_free(jid_norm); if(me == 0) jb->subscription = JABBER_SUB_BOTH; else if(!strcmp(subscription, "none")) jb->subscription = JABBER_SUB_NONE; else if(!strcmp(subscription, "to")) jb->subscription = JABBER_SUB_TO; else if(!strcmp(subscription, "from")) jb->subscription = JABBER_SUB_FROM; else if(!strcmp(subscription, "both")) jb->subscription = JABBER_SUB_BOTH; else if(!strcmp(subscription, "remove")) jb->subscription = JABBER_SUB_REMOVE; /* XXX: if subscription is now "from" or "none" we need to * fake a signoff, since we won't get any presence from them * anymore */ /* YYY: I was going to use this, but I'm not sure it's necessary * anymore, but it's here in case it is. */ /* if ((jb->subscription & JABBER_SUB_FROM) || (jb->subscription & JABBER_SUB_NONE)) { purple_prpl_got_user_status(js->gc->account, jid, "offline", NULL); } */ } if(ask && !strcmp(ask, "subscribe")) jb->subscription |= JABBER_SUB_PENDING; else jb->subscription &= ~JABBER_SUB_PENDING; if(jb->subscription == JABBER_SUB_REMOVE) { remove_purple_buddies(js, jid); } else { GSList *groups = NULL; if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER) if (!jabber_google_roster_incoming(js, item)) continue; for(group = xmlnode_get_child(item, "group"); group; group = xmlnode_get_next_twin(group)) { char *group_name; if(!(group_name = xmlnode_get_data(group))) group_name = g_strdup(""); else nGroupCnt++; //VOXOX - JRT - 2009.05.07 if (g_slist_find_custom(groups, group_name, (GCompareFunc)purple_utf8_strcasecmp) == NULL) groups = g_slist_append(groups, group_name); else g_free(group_name); } add_purple_buddies_to_groups(js, jid, name, groups); nCount++; //VOXOX - JRT - 2009.04.08 } } //VOXOX - JRT - 2009.05.07 - We are getting inconsistent data from server. Log so Developers are less likely to chase wrong problem. #ifdef _WINDOWS if ( nCount == 0 ) { g_print( "(WARNING) roster.c - jabber_roster_parse() - NO contacts found. XML appears empty.\n"); } else { g_print( "(INFO) roster.c - jabber_roster_parse() - %d contacts found.\n", nCount); if ( nGroupCnt == 0 ) { g_print( "(WARNING) roster.c - jabber_roster_parse() - NO groups found. Found %d contacts.\n", nCount ); } } #endif //End VoxOx js->currently_parsing_roster_push = FALSE; //VOXOX - JRT - 2009.04.11 - So we can notify UI of initial contact list loading is complete. if(!js->roster_parsed) { set_purple_initial_load( 0 ); } //End VoxOx /* if we're just now parsing the roster for the first time, * then now would be the time to send our initial presence */ if(!js->roster_parsed) { js->roster_parsed = TRUE; jabber_presence_send(js->gc->account, NULL); } }
void jabber_roster_parse(JabberStream *js, const char *from, JabberIqType type, const char *id, xmlnode *query) { xmlnode *item, *group; if (!jabber_is_own_account(js, from)) { purple_debug_warning("jabber", "Received bogon roster push from %s\n", from); return; } js->currently_parsing_roster_push = TRUE; for(item = xmlnode_get_child(query, "item"); item; item = xmlnode_get_next_twin(item)) { const char *jid, *name, *subscription, *ask; JabberBuddy *jb; subscription = xmlnode_get_attrib(item, "subscription"); jid = xmlnode_get_attrib(item, "jid"); name = xmlnode_get_attrib(item, "name"); ask = xmlnode_get_attrib(item, "ask"); if(!jid) continue; if(!(jb = jabber_buddy_find(js, jid, TRUE))) continue; if(subscription) { if (jb == js->user_jb) jb->subscription = JABBER_SUB_BOTH; else if(!strcmp(subscription, "none")) jb->subscription = JABBER_SUB_NONE; else if(!strcmp(subscription, "to")) jb->subscription = JABBER_SUB_TO; else if(!strcmp(subscription, "from")) jb->subscription = JABBER_SUB_FROM; else if(!strcmp(subscription, "both")) jb->subscription = JABBER_SUB_BOTH; else if(!strcmp(subscription, "remove")) jb->subscription = JABBER_SUB_REMOVE; } if(purple_strequal(ask, "subscribe")) jb->subscription |= JABBER_SUB_PENDING; else jb->subscription &= ~JABBER_SUB_PENDING; if(jb->subscription & JABBER_SUB_REMOVE) { remove_purple_buddies(js, jid); } else { GSList *groups = NULL; gboolean seen_empty = FALSE; if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER) if (!jabber_google_roster_incoming(js, item)) continue; for(group = xmlnode_get_child(item, "group"); group; group = xmlnode_get_next_twin(group)) { char *group_name = xmlnode_get_data(group); if (!group_name && !seen_empty) { group_name = g_strdup(""); seen_empty = TRUE; } groups = g_slist_prepend(groups, group_name); } add_purple_buddy_to_groups(js, jid, name, groups); if (jb == js->user_jb) jabber_presence_fake_to_self(js, NULL); } } js->currently_parsing_roster_push = FALSE; /* if we're just now parsing the roster for the first time, * then now would be the time to declare ourselves connected. */ if (js->state != JABBER_STREAM_CONNECTED) jabber_stream_set_state(js, JABBER_STREAM_CONNECTED); }
void jabber_roster_parse(JabberStream *js, const char *from, JabberIqType type, const char *id, xmlnode *query) { xmlnode *item, *group; #if 0 const char *ver; #endif if (!jabber_is_own_account(js, from)) { purple_debug_warning("jabber", "Received bogon roster push from %s\n", from); return; } js->currently_parsing_roster_push = TRUE; for(item = xmlnode_get_child(query, "item"); item; item = xmlnode_get_next_twin(item)) { const char *jid, *name, *subscription, *ask; JabberBuddy *jb; subscription = xmlnode_get_attrib(item, "subscription"); jid = xmlnode_get_attrib(item, "jid"); name = xmlnode_get_attrib(item, "name"); ask = xmlnode_get_attrib(item, "ask"); if(!jid) continue; if(!(jb = jabber_buddy_find(js, jid, TRUE))) continue; if(subscription) { if (g_str_equal(subscription, "remove")) jb->subscription = JABBER_SUB_REMOVE; else if (jb == js->user_jb) jb->subscription = JABBER_SUB_BOTH; else if (g_str_equal(subscription, "none")) jb->subscription = JABBER_SUB_NONE; else if (g_str_equal(subscription, "to")) jb->subscription = JABBER_SUB_TO; else if (g_str_equal(subscription, "from")) jb->subscription = JABBER_SUB_FROM; else if (g_str_equal(subscription, "both")) jb->subscription = JABBER_SUB_BOTH; } if(purple_strequal(ask, "subscribe")) jb->subscription |= JABBER_SUB_PENDING; else jb->subscription &= ~JABBER_SUB_PENDING; if(jb->subscription & JABBER_SUB_REMOVE) { remove_purple_buddies(js, jid); } else { GSList *groups = NULL; gboolean seen_empty = FALSE; if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER) if (!jabber_google_roster_incoming(js, item)) continue; for(group = xmlnode_get_child(item, "group"); group; group = xmlnode_get_next_twin(group)) { char *group_name = xmlnode_get_data(group); if (!group_name && !seen_empty) { group_name = g_strdup(""); seen_empty = TRUE; } /* * See the note in add_purple_buddy_to_groups; the core handles * names case-insensitively and this is required to not * end up with duplicates if a buddy is in, e.g., * 'XMPP' and 'xmpp' */ if (g_slist_find_custom(groups, group_name, (GCompareFunc)purple_utf8_strcasecmp)) g_free(group_name); else groups = g_slist_prepend(groups, group_name); } add_purple_buddy_to_groups(js, jid, name, groups); if (jb == js->user_jb) jabber_presence_fake_to_self(js, NULL); } } #if 0 ver = xmlnode_get_attrib(query, "ver"); if (ver) { PurpleAccount *account = purple_connection_get_account(js->gc); purple_account_set_string(account, "roster_ver", ver); } #endif if (type == JABBER_IQ_SET) { JabberIq *ack = jabber_iq_new(js, JABBER_IQ_RESULT); jabber_iq_set_id(ack, id); jabber_iq_send(ack); } js->currently_parsing_roster_push = FALSE; }