comparison libpurple/protocols/jabber/roster.c @ 27494:93a41017dca9

Various roster cleanups. Refs #7008. I haven't tested it, but this may resolve the grouping/case problem (strcmp => purple_utf8_strcasecmp)
author Paul Aurich <paul@darkrain42.org>
date Sun, 07 Jun 2009 00:16:05 +0000
parents 65b5bc543214
children c8390dc125c1
comparison
equal deleted inserted replaced
27493:65b5bc543214 27494:93a41017dca9
50 purple_blist_remove_buddy(l->data); 50 purple_blist_remove_buddy(l->data);
51 51
52 g_slist_free(buddies); 52 g_slist_free(buddies);
53 } 53 }
54 54
55 static void add_purple_buddies_to_groups(JabberStream *js, const char *jid, 55 static void add_purple_buddy_to_groups(JabberStream *js, const char *jid,
56 const char *alias, GSList *groups) 56 const char *alias, GSList *groups)
57 { 57 {
58 GSList *buddies, *g2, *l; 58 GSList *buddies, *l;
59 gchar *my_bare_jid; 59 gchar *my_bare_jid;
60 GList *pool = NULL; 60 GList *pool = NULL;
61 61
62 buddies = purple_find_buddies(js->gc->account, jid); 62 buddies = purple_find_buddies(js->gc->account, jid);
63 63
64 g2 = groups;
65
66 if(!groups) { 64 if(!groups) {
67 if(!buddies) 65 if(!buddies)
68 g2 = g_slist_append(g2, g_strdup(_("Buddies"))); 66 groups = g_slist_append(groups, g_strdup(_("Buddies")));
69 else { 67 else {
68 /* TODO: What should we do here? Removing the local buddies
69 * is wrong, but so is letting the group state get out of sync with
70 * the server.
71 */
70 g_slist_free(buddies); 72 g_slist_free(buddies);
71 return; 73 return;
72 } 74 }
73 } 75 }
74 76
76 78
77 while(buddies) { 79 while(buddies) {
78 PurpleBuddy *b = buddies->data; 80 PurpleBuddy *b = buddies->data;
79 PurpleGroup *g = purple_buddy_get_group(b); 81 PurpleGroup *g = purple_buddy_get_group(b);
80 82
81 buddies = g_slist_remove(buddies, b); 83 buddies = g_slist_delete_link(buddies, buddies);
82 84
83 if((l = g_slist_find_custom(g2, purple_group_get_name(g), (GCompareFunc)strcmp))) { 85 /* XMPP groups are case-sensitive, but libpurple groups are
86 * case-insensitive. We treat a buddy in both "Friends" and "friends"
87 * as only being in one group, so if we push changes about the buddy
88 * to the server, the buddy will be dropped from one of the groups.
89 */
90 if((l = g_slist_find_custom(groups, purple_group_get_name(g), (GCompareFunc)purple_utf8_strcasecmp))) {
91 /* The buddy is already on the local list. Update info. */
84 const char *servernick, *balias; 92 const char *servernick, *balias;
85 93
86 /* Previously stored serverside / buddy-supplied alias */ 94 /* Previously stored serverside / buddy-supplied alias */
87 if((servernick = purple_blist_node_get_string((PurpleBlistNode*)b, "servernick"))) 95 if((servernick = purple_blist_node_get_string((PurpleBlistNode*)b, "servernick")))
88 serv_got_alias(js->gc, jid, servernick); 96 serv_got_alias(js->gc, jid, servernick);
89 97
90 /* Alias from our roster retrieval */ 98 /* Alias from our roster retrieval */
91 balias = purple_buddy_get_local_buddy_alias(b); 99 balias = purple_buddy_get_local_buddy_alias(b);
92 if(alias && (!balias || strcmp(balias, alias))) 100 if(alias && !purple_strequal(alias, balias))
93 purple_serv_got_private_alias(js->gc, jid, alias); 101 purple_serv_got_private_alias(js->gc, jid, alias);
94 g_free(l->data); 102 g_free(l->data);
95 g2 = g_slist_delete_link(g2, l); 103 groups = g_slist_delete_link(groups, l);
96 } else { 104 } else {
105 /* This buddy isn't in the group on the server anymore */
97 pool = g_list_prepend(pool, b); 106 pool = g_list_prepend(pool, b);
98 } 107 }
99 } 108 }
100 109
101 while(g2) { 110 while(groups) {
102 PurpleGroup *g = purple_find_group(g2->data); 111 PurpleGroup *g = purple_find_group(groups->data);
103 PurpleBuddy *b = NULL; 112 PurpleBuddy *b = NULL;
104 113
114 /* If there are buddies we would otherwise delete, move them to
115 * the new group (instead of deleting them below)
116 */
105 if (pool) { 117 if (pool) {
106 b = pool->data; 118 b = pool->data;
107 pool = g_list_delete_link(pool, pool); 119 pool = g_list_delete_link(pool, pool);
108 } else { 120 } else {
109 b = purple_buddy_new(js->gc->account, jid, alias); 121 b = purple_buddy_new(js->gc->account, jid, alias);
110 } 122 }
111 123
112 if(!g) { 124 if(!g) {
113 g = purple_group_new(g2->data); 125 g = purple_group_new(groups->data);
114 purple_blist_add_group(g, NULL); 126 purple_blist_add_group(g, NULL);
115 } 127 }
116 128
117 purple_blist_add_buddy(b, NULL, g, NULL); 129 purple_blist_add_buddy(b, NULL, g, NULL);
118 purple_blist_alias_buddy(b, alias); 130 purple_blist_alias_buddy(b, alias);
129 gpresence = purple_account_get_presence(account); 141 gpresence = purple_account_get_presence(account);
130 status = purple_presence_get_active_status(gpresence); 142 status = purple_presence_get_active_status(gpresence);
131 jabber_presence_fake_to_self(js, status); 143 jabber_presence_fake_to_self(js, status);
132 } 144 }
133 145
134 g_free(g2->data); 146 g_free(groups->data);
135 g2 = g_slist_delete_link(g2, g2); 147 groups = g_slist_delete_link(groups, groups);
136 } 148 }
137 149
150 /* Remove this person from all the groups they're no longer in on the
151 * server */
138 while (pool) { 152 while (pool) {
139 PurpleBuddy *b = pool->data; 153 PurpleBuddy *b = pool->data;
140 purple_blist_remove_buddy(b); 154 purple_blist_remove_buddy(b);
141 pool = g_list_delete_link(pool, pool); 155 pool = g_list_delete_link(pool, pool);
142 } 156 }
203 217
204 if(jb->subscription == JABBER_SUB_REMOVE) { 218 if(jb->subscription == JABBER_SUB_REMOVE) {
205 remove_purple_buddies(js, jid); 219 remove_purple_buddies(js, jid);
206 } else { 220 } else {
207 GSList *groups = NULL; 221 GSList *groups = NULL;
222 gboolean seen_empty = FALSE;
208 223
209 if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER) 224 if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER)
210 if (!jabber_google_roster_incoming(js, item)) 225 if (!jabber_google_roster_incoming(js, item))
211 continue; 226 continue;
212 227
213 for(group = xmlnode_get_child(item, "group"); group; group = xmlnode_get_next_twin(group)) { 228 for(group = xmlnode_get_child(item, "group"); group; group = xmlnode_get_next_twin(group)) {
214 char *group_name; 229 char *group_name = xmlnode_get_data(group);
215 230
216 if(!(group_name = xmlnode_get_data(group))) 231 if (!group_name && !seen_empty) {
217 group_name = g_strdup(""); 232 group_name = g_strdup("");
218 233 seen_empty = TRUE;
219 if (g_slist_find_custom(groups, group_name, (GCompareFunc)purple_utf8_strcasecmp) == NULL) 234 }
220 groups = g_slist_append(groups, group_name); 235
221 else 236 groups = g_slist_prepend(groups, group_name);
222 g_free(group_name);
223 } 237 }
224 add_purple_buddies_to_groups(js, jid, name, groups); 238
239 add_purple_buddy_to_groups(js, jid, name, groups);
225 } 240 }
226 } 241 }
227 242
228 g_free(own_jid); 243 g_free(own_jid);
229 js->currently_parsing_roster_push = FALSE; 244 js->currently_parsing_roster_push = FALSE;