comparison src/blist.c @ 9787:904b757835ca

[gaim-migrate @ 10655] after an utter failure to get comments on this since it was updated, and thinking that the functionality is worth having, i present to you: " This is a patch to blist.c and blist.h to modify the GaimBuddy structure to add a field for flags. It also adds a single flag GAIM_BUDDY_NO_SAVE, which can be used to indicate that a particular buddy should not be saved to file. This will be particularly useful for prpls with dynamic group support (which I am working on adding to Meanwhile), such as Oscar's recent buddies group. I used a negative flag (NO_SAVE rather than SAVE) because the default should be for saving to happen, and I didn't want to have to initiate the buddy with a save flag set. To counteract this, there is a macro called GAIM_BUDDY_SHOULD_SAVE which checks for the absense of the flag. Woo-hoo double negative!! The beefy part of this patch also factors out the deeply nested loops of the saving code into separate functions. This code also fixes a minor possible bug wherein when saving only a particular account, a group could be written containing empty contacts (due to checking for the specific account only at the group and buddy levels) Here's a version that places the flags field in the BlistNode, and checks for it at each stage (group, chat, contact, buddy). It didn't erase my buddy list when I tried it, so that's nice at least." --Christopher (siege) O'Brien committer: Tailor Script <tailor@pidgin.im>
author Luke Schierer <lschiere@pidgin.im>
date Fri, 20 Aug 2004 03:40:33 +0000
parents 4a8bf81b82ae
children b23e70bd1215
comparison
equal deleted inserted replaced
9786:3e7e294f56f3 9787:904b757835ca
916 return contact->alias; 916 return contact->alias;
917 917
918 return gaim_buddy_get_alias(contact->priority); 918 return gaim_buddy_get_alias(contact->priority);
919 } 919 }
920 920
921 gboolean gaim_contact_on_account(GaimContact *c, GaimAccount *account)
922 {
923 GaimBlistNode *bnode, *cnode = (GaimBlistNode *) c;
924
925 g_return_val_if_fail(c != NULL, FALSE);
926 g_return_val_if_fail(account != NULL, FALSE);
927
928 for (bnode = cnode->child; bnode; bnode = bnode->next) {
929 GaimBuddy *buddy;
930
931 if (! GAIM_BLIST_NODE_IS_BUDDY(bnode))
932 continue;
933
934 buddy = (GaimBuddy *)bnode;
935 if (buddy->account == account)
936 return TRUE;
937 }
938 return FALSE;
939 }
940
921 GaimGroup *gaim_group_new(const char *name) 941 GaimGroup *gaim_group_new(const char *name)
922 { 942 {
923 GaimBlistUiOps *ops = gaim_blist_get_ui_ops(); 943 GaimBlistUiOps *ops = gaim_blist_get_ui_ops();
924 GaimGroup *group = gaim_find_group(name); 944 GaimGroup *group = gaim_find_group(name);
925 945
1727 } 1747 }
1728 } 1748 }
1729 1749
1730 gboolean gaim_group_on_account(GaimGroup *g, GaimAccount *account) 1750 gboolean gaim_group_on_account(GaimGroup *g, GaimAccount *account)
1731 { 1751 {
1732 GaimBlistNode *cnode, *bnode; 1752 GaimBlistNode *cnode;
1733 for (cnode = ((GaimBlistNode *)g)->child; cnode; cnode = cnode->next) { 1753 for (cnode = ((GaimBlistNode *)g)->child; cnode; cnode = cnode->next) {
1734 if (GAIM_BLIST_NODE_IS_CONTACT(cnode)) { 1754 if (GAIM_BLIST_NODE_IS_CONTACT(cnode)) {
1735 for (bnode = cnode->child; bnode; bnode = bnode->next) { 1755 if(gaim_contact_on_account((GaimContact *) cnode, account))
1736 if (GAIM_BLIST_NODE_IS_BUDDY(bnode)) { 1756 return TRUE;
1737 GaimBuddy *buddy = (GaimBuddy *)bnode;
1738 if ((!account && gaim_account_is_connected(buddy->account))
1739 || buddy->account == account)
1740 return TRUE;
1741 }
1742 }
1743 } else if (GAIM_BLIST_NODE_IS_CHAT(cnode)) { 1757 } else if (GAIM_BLIST_NODE_IS_CHAT(cnode)) {
1744 GaimChat *chat = (GaimChat *)cnode; 1758 GaimChat *chat = (GaimChat *)cnode;
1745 if ((!account && gaim_account_is_connected(chat->account)) 1759 if ((!account && gaim_account_is_connected(chat->account))
1746 || chat->account == account) 1760 || chat->account == account)
1747 return TRUE; 1761 return TRUE;
2169 g_free(bud_name); 2183 g_free(bud_name);
2170 g_free(bud_alias); 2184 g_free(bud_alias);
2171 g_free(acct_name); 2185 g_free(acct_name);
2172 } 2186 }
2173 2187
2188
2189 /* check for flagging and account exclusion on buddy */
2190 static gboolean blist_buddy_should_save(GaimAccount *exp_acct, GaimBuddy *buddy)
2191 {
2192 if (! GAIM_BLIST_NODE_SHOULD_SAVE((GaimBlistNode *) buddy))
2193 return FALSE;
2194
2195 if (exp_acct && buddy->account != exp_acct)
2196 return FALSE;
2197
2198 return TRUE;
2199 }
2200
2201
2202 static void blist_write_buddy(FILE *file, GaimAccount *exp_acct, GaimBuddy *buddy)
2203 {
2204 if (blist_buddy_should_save(exp_acct, buddy))
2205 print_buddy(file, buddy);
2206 }
2207
2208
2209 /* check for flagging and account exclusion on contact and all members */
2210 static gboolean blist_contact_should_save(GaimAccount *exp_acct, GaimContact *contact)
2211 {
2212 GaimBlistNode *bnode, *cnode = (GaimBlistNode *) contact;
2213
2214 if (! GAIM_BLIST_NODE_SHOULD_SAVE(cnode))
2215 return FALSE;
2216
2217 for (bnode = cnode->child; bnode; bnode = bnode->next) {
2218 if (! GAIM_BLIST_NODE_IS_BUDDY(bnode))
2219 continue;
2220
2221 if (blist_buddy_should_save(exp_acct, (GaimBuddy *) bnode))
2222 return TRUE;
2223 }
2224
2225 return FALSE;
2226 }
2227
2228
2229 static void blist_write_contact(FILE *file, GaimAccount *exp_acct, GaimContact *contact)
2230 {
2231 GaimBlistNode *bnode, *cnode = (GaimBlistNode *) contact;
2232
2233 if (! blist_contact_should_save(exp_acct, contact))
2234 return;
2235
2236 fprintf(file, "\t\t\t<contact");
2237 if (contact->alias) {
2238 char *alias = g_markup_escape_text(contact->alias, -1);
2239 fprintf(file, " alias=\"%s\"", alias);
2240 g_free(alias);
2241 }
2242 fprintf(file, ">\n");
2243
2244 for (bnode = cnode->child; bnode; bnode = bnode->next) {
2245 if (GAIM_BLIST_NODE_IS_BUDDY(bnode)) {
2246 blist_write_buddy(file, exp_acct, (GaimBuddy *) bnode);
2247 }
2248 }
2249
2250 g_hash_table_foreach(cnode->settings, blist_print_cnode_settings, file);
2251 fprintf(file, "\t\t\t</contact>\n");
2252 }
2253
2254
2255 static void blist_write_chat(FILE *file, GaimAccount *exp_acct, GaimChat *chat)
2256 {
2257 char *acct_name;
2258
2259 if (! GAIM_BLIST_NODE_SHOULD_SAVE((GaimBlistNode *) chat))
2260 return;
2261
2262 if (exp_acct && chat->account != exp_acct)
2263 return;
2264
2265 acct_name = g_markup_escape_text(chat->account->username, -1);
2266 fprintf(file, "\t\t\t<chat proto=\"%s\" account=\"%s\">\n",
2267 gaim_account_get_protocol_id(chat->account), acct_name);
2268 g_free(acct_name);
2269
2270 if (chat->alias) {
2271 char *chat_alias = g_markup_escape_text(chat->alias, -1);
2272 fprintf(file, "\t\t\t\t<alias>%s</alias>\n", chat_alias);
2273 g_free(chat_alias);
2274 }
2275
2276 g_hash_table_foreach(chat->components, blist_print_chat_components, file);
2277 g_hash_table_foreach(chat->node.settings, blist_print_cnode_settings, file);
2278
2279 fprintf(file, "\t\t\t</chat>\n");
2280 }
2281
2282
2283 static void blist_write_group(FILE *file, GaimAccount *exp_acct, GaimGroup *group)
2284 {
2285 GaimBlistNode *cnode, *gnode = (GaimBlistNode *) group;
2286 char *group_name;
2287
2288 if (! GAIM_BLIST_NODE_SHOULD_SAVE(gnode))
2289 return;
2290
2291 if (exp_acct && ! gaim_group_on_account(group, exp_acct))
2292 return;
2293
2294 group_name = g_markup_escape_text(group->name, -1);
2295 fprintf(file, "\t\t<group name=\"%s\">\n", group_name);
2296 g_free(group_name);
2297
2298 g_hash_table_foreach(group->node.settings,
2299 blist_print_group_settings, file);
2300
2301 for (cnode = gnode->child; cnode; cnode = cnode->next) {
2302 if (GAIM_BLIST_NODE_IS_CONTACT(cnode)) {
2303 blist_write_contact(file, exp_acct, (GaimContact *) cnode);
2304 } else if (GAIM_BLIST_NODE_IS_CHAT(cnode)) {
2305 blist_write_chat(file, exp_acct, (GaimChat *) cnode);
2306 }
2307 }
2308
2309 fprintf(file, "\t\t</group>\n");
2310 }
2311
2312
2313 static void blist_write_privacy_account(FILE *file, GaimAccount *exp_acct, GaimAccount *account)
2314 {
2315 char *acct_name;
2316 GSList *buds;
2317
2318 if(exp_acct && exp_acct != account)
2319 return;
2320
2321 acct_name = g_markup_escape_text(account->username, -1);
2322 fprintf(file, "\t\t<account proto=\"%s\" name=\"%s\" mode=\"%d\">\n",
2323 gaim_account_get_protocol_id(account),
2324 acct_name, account->perm_deny);
2325 g_free(acct_name);
2326
2327 for (buds = account->permit; buds; buds = buds->next) {
2328 char *bud_name = g_markup_escape_text(buds->data, -1);
2329 fprintf(file, "\t\t\t<permit>%s</permit>\n", bud_name);
2330 g_free(bud_name);
2331 }
2332
2333 for (buds = account->deny; buds; buds = buds->next) {
2334 char *bud_name = g_markup_escape_text(buds->data, -1);
2335 fprintf(file, "\t\t\t<block>%s</block>\n", bud_name);
2336 g_free(bud_name);
2337 }
2338
2339 fprintf(file, "\t\t</account>\n");
2340 }
2341
2342
2174 static void gaim_blist_write(FILE *file, GaimAccount *exp_acct) 2343 static void gaim_blist_write(FILE *file, GaimAccount *exp_acct)
2175 { 2344 {
2176 GList *accounts; 2345 GList *accounts;
2177 GSList *buds; 2346 GaimBlistNode *gnode;
2178 GaimBlistNode *gnode, *cnode, *bnode; 2347
2179 fprintf(file, "<?xml version='1.0' encoding='UTF-8' ?>\n"); 2348 fprintf(file, "<?xml version='1.0' encoding='UTF-8' ?>\n");
2180 fprintf(file, "<gaim version=\"1\">\n"); 2349 fprintf(file, "<gaim version=\"1\">\n");
2181 fprintf(file, "\t<blist>\n"); 2350 fprintf(file, "\t<blist>\n");
2182 2351
2183 for (gnode = gaimbuddylist->root; gnode; gnode = gnode->next) { 2352 for (gnode = gaimbuddylist->root; gnode; gnode = gnode->next) {
2184 GaimGroup *group; 2353 if (GAIM_BLIST_NODE_IS_GROUP(gnode))
2185 2354 blist_write_group(file, exp_acct, (GaimGroup *) gnode);
2186 if (!GAIM_BLIST_NODE_IS_GROUP(gnode))
2187 continue;
2188
2189 group = (GaimGroup *)gnode;
2190 if (!exp_acct || gaim_group_on_account(group, exp_acct)) {
2191 char *group_name = g_markup_escape_text(group->name, -1);
2192 fprintf(file, "\t\t<group name=\"%s\">\n", group_name);
2193 g_hash_table_foreach(group->node.settings,
2194 blist_print_group_settings, file);
2195 for (cnode = gnode->child; cnode; cnode = cnode->next) {
2196 if (GAIM_BLIST_NODE_IS_CONTACT(cnode)) {
2197 GaimContact *contact = (GaimContact*)cnode;
2198 fprintf(file, "\t\t\t<contact");
2199 if (contact->alias) {
2200 char *alias = g_markup_escape_text(contact->alias, -1);
2201 fprintf(file, " alias=\"%s\"", alias);
2202 g_free(alias);
2203 }
2204 fprintf(file, ">\n");
2205
2206 for (bnode = cnode->child; bnode; bnode = bnode->next) {
2207 if (GAIM_BLIST_NODE_IS_BUDDY(bnode)) {
2208 GaimBuddy *buddy = (GaimBuddy *)bnode;
2209 if (!exp_acct || buddy->account == exp_acct) {
2210 print_buddy(file, buddy);
2211 }
2212 }
2213 }
2214
2215 g_hash_table_foreach(cnode->settings,
2216 blist_print_cnode_settings, file);
2217
2218 fprintf(file, "\t\t\t</contact>\n");
2219 } else if (GAIM_BLIST_NODE_IS_CHAT(cnode)) {
2220 GaimChat *chat = (GaimChat *)cnode;
2221 if (!exp_acct || chat->account == exp_acct) {
2222 char *acct_name = g_markup_escape_text(chat->account->username, -1);
2223 fprintf(file, "\t\t\t<chat proto=\"%s\" account=\"%s\">\n",
2224 gaim_account_get_protocol_id(chat->account),
2225 acct_name);
2226
2227 if (chat->alias) {
2228 char *chat_alias = g_markup_escape_text(chat->alias, -1);
2229 fprintf(file, "\t\t\t\t<alias>%s</alias>\n", chat_alias);
2230 g_free(chat_alias);
2231 }
2232 g_hash_table_foreach(chat->components,
2233 blist_print_chat_components, file);
2234 g_hash_table_foreach(chat->node.settings,
2235 blist_print_cnode_settings, file);
2236 fprintf(file, "\t\t\t</chat>\n");
2237 g_free(acct_name);
2238 }
2239 }
2240 }
2241 fprintf(file, "\t\t</group>\n");
2242 g_free(group_name);
2243 }
2244 } 2355 }
2245 2356
2246 fprintf(file, "\t</blist>\n"); 2357 fprintf(file, "\t</blist>\n");
2247 fprintf(file, "\t<privacy>\n"); 2358 fprintf(file, "\t<privacy>\n");
2248 2359
2249 for (accounts = gaim_accounts_get_all(); 2360 for (accounts = gaim_accounts_get_all(); accounts; accounts = accounts->next) {
2250 accounts != NULL; 2361 blist_write_privacy_account(file, exp_acct, (GaimAccount *) accounts->data);
2251 accounts = accounts->next) {
2252
2253 GaimAccount *account = accounts->data;
2254 char *acct_name = g_markup_escape_text(account->username, -1);
2255 if (!exp_acct || account == exp_acct) {
2256 fprintf(file, "\t\t<account proto=\"%s\" name=\"%s\" "
2257 "mode=\"%d\">\n", gaim_account_get_protocol_id(account),
2258 acct_name, account->perm_deny);
2259
2260 for (buds = account->permit; buds; buds = buds->next) {
2261 char *bud_name = g_markup_escape_text(buds->data, -1);
2262 fprintf(file, "\t\t\t<permit>%s</permit>\n", bud_name);
2263 g_free(bud_name);
2264 }
2265 for (buds = account->deny; buds; buds = buds->next) {
2266 char *bud_name = g_markup_escape_text(buds->data, -1);
2267 fprintf(file, "\t\t\t<block>%s</block>\n", bud_name);
2268 g_free(bud_name);
2269 }
2270 fprintf(file, "\t\t</account>\n");
2271 }
2272 g_free(acct_name);
2273 } 2362 }
2274 2363
2275 fprintf(file, "\t</privacy>\n"); 2364 fprintf(file, "\t</privacy>\n");
2276 fprintf(file, "</gaim>\n"); 2365 fprintf(file, "</gaim>\n");
2277 } 2366 }
2367
2278 2368
2279 void gaim_blist_sync() 2369 void gaim_blist_sync()
2280 { 2370 {
2281 FILE *file; 2371 FILE *file;
2282 char *user_dir = gaim_user_dir(); 2372 char *user_dir = gaim_user_dir();