comparison src/account.c @ 5573:5e7de337a053

[gaim-migrate @ 5976] Account saving and loading _mostly_ works. committer: Tailor Script <tailor@pidgin.im>
author Christian Hammond <chipx86@chipx86.com>
date Fri, 30 May 2003 23:57:11 +0000
parents c3c4aaf69f65
children a95e872e58dc
comparison
equal deleted inserted replaced
5572:dfdea22a7153 5573:5e7de337a053
1 /** 1 /*if*
2 * @file account.c Account API 2 * @file account.c Account API
3 * @ingroup core 3 * @ingroup core
4 * 4 *
5 * gaim 5 * gaim
6 * 6 *
18 * 18 *
19 * You should have received a copy of the GNU General Public License 19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software 20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */ 22 */
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <string.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <sys/stat.h>
31 #include <sys/types.h>
32 #include <glib.h>
33
23 #include "account.h" 34 #include "account.h"
24 #include "prefs.h" 35 #include "prefs.h"
36
37 typedef enum
38 {
39 TAG_PROTOCOL,
40 TAG_NAME,
41 TAG_PASSWORD,
42 TAG_ALIAS,
43 TAG_USERINFO,
44 TAG_BUDDYICON,
45 TAG_SETTING
46
47 } AccountParserTag;
25 48
26 typedef struct 49 typedef struct
27 { 50 {
28 GaimPrefType type; 51 GaimPrefType type;
29 52
35 58
36 } value; 59 } value;
37 60
38 } GaimAccountSetting; 61 } GaimAccountSetting;
39 62
40 static GList *accounts = NULL; 63 typedef struct
64 {
65 AccountParserTag tag;
66
67 GaimAccount *account;
68 GaimProtocol protocol;
69
70 GString *buffer;
71
72 GaimPrefType setting_type;
73 char *setting_name;
74
75 } AccountParserData;
76
77 static GList *accounts = NULL;
78 static guint accounts_save_timer = 0;
79 static gboolean accounts_loaded = FALSE;
41 80
42 static void 81 static void
43 __delete_setting(void *data) 82 __delete_setting(void *data)
44 { 83 {
45 GaimAccountSetting *setting = (GaimAccountSetting *)data; 84 GaimAccountSetting *setting = (GaimAccountSetting *)data;
46 85
47 if (setting->type == GAIM_PREF_STRING) 86 if (setting->type == GAIM_PREF_STRING)
48 g_free(setting->value.string); 87 g_free(setting->value.string);
49 88
50 g_free(setting); 89 g_free(setting);
90 }
91
92 static gboolean
93 __accounts_save_cb(gpointer unused)
94 {
95 gaim_accounts_sync();
96 accounts_save_timer = 0;
97
98 return FALSE;
99 }
100
101 static void
102 schedule_accounts_save()
103 {
104 if (!accounts_save_timer)
105 accounts_save_timer = g_timeout_add(5000, __accounts_save_cb, NULL);
51 } 106 }
52 107
53 GaimAccount * 108 GaimAccount *
54 gaim_account_new(const char *username, GaimProtocol protocol) 109 gaim_account_new(const char *username, GaimProtocol protocol)
55 { 110 {
125 180
126 if (account->username != NULL) 181 if (account->username != NULL)
127 g_free(account->username); 182 g_free(account->username);
128 183
129 account->username = (username == NULL ? NULL : g_strdup(username)); 184 account->username = (username == NULL ? NULL : g_strdup(username));
185
186 schedule_accounts_save();
130 } 187 }
131 188
132 void 189 void
133 gaim_account_set_password(GaimAccount *account, const char *password) 190 gaim_account_set_password(GaimAccount *account, const char *password)
134 { 191 {
137 194
138 if (account->password != NULL) 195 if (account->password != NULL)
139 g_free(account->password); 196 g_free(account->password);
140 197
141 account->password = (password == NULL ? NULL : g_strdup(password)); 198 account->password = (password == NULL ? NULL : g_strdup(password));
199
200 schedule_accounts_save();
142 } 201 }
143 202
144 void 203 void
145 gaim_account_set_alias(GaimAccount *account, const char *alias) 204 gaim_account_set_alias(GaimAccount *account, const char *alias)
146 { 205 {
149 208
150 if (account->alias != NULL) 209 if (account->alias != NULL)
151 g_free(account->alias); 210 g_free(account->alias);
152 211
153 account->alias = (alias == NULL ? NULL : g_strdup(alias)); 212 account->alias = (alias == NULL ? NULL : g_strdup(alias));
213
214 schedule_accounts_save();
154 } 215 }
155 216
156 void 217 void
157 gaim_account_set_user_info(GaimAccount *account, const char *user_info) 218 gaim_account_set_user_info(GaimAccount *account, const char *user_info)
158 { 219 {
161 222
162 if (account->user_info != NULL) 223 if (account->user_info != NULL)
163 g_free(account->user_info); 224 g_free(account->user_info);
164 225
165 account->user_info = (user_info == NULL ? NULL : g_strdup(user_info)); 226 account->user_info = (user_info == NULL ? NULL : g_strdup(user_info));
227
228 schedule_accounts_save();
166 } 229 }
167 230
168 void 231 void
169 gaim_account_set_buddy_icon(GaimAccount *account, const char *icon) 232 gaim_account_set_buddy_icon(GaimAccount *account, const char *icon)
170 { 233 {
173 236
174 if (account->buddy_icon != NULL) 237 if (account->buddy_icon != NULL)
175 g_free(account->buddy_icon); 238 g_free(account->buddy_icon);
176 239
177 account->buddy_icon = (icon == NULL ? NULL : g_strdup(icon)); 240 account->buddy_icon = (icon == NULL ? NULL : g_strdup(icon));
241
242 schedule_accounts_save();
178 } 243 }
179 244
180 void 245 void
181 gaim_account_set_protocol(GaimAccount *account, GaimProtocol protocol) 246 gaim_account_set_protocol(GaimAccount *account, GaimProtocol protocol)
182 { 247 {
183 g_return_if_fail(account != NULL); 248 g_return_if_fail(account != NULL);
184 249
185 account->protocol = protocol; 250 account->protocol = protocol;
251
252 schedule_accounts_save();
186 } 253 }
187 254
188 void 255 void
189 gaim_account_set_connection(GaimAccount *account, GaimConnection *gc) 256 gaim_account_set_connection(GaimAccount *account, GaimConnection *gc)
190 { 257 {
191 g_return_if_fail(account != NULL); 258 g_return_if_fail(account != NULL);
192 g_return_if_fail(gc != NULL); 259 g_return_if_fail(gc != NULL);
193 260
194 account->gc = gc; 261 account->gc = gc;
262
263 schedule_accounts_save();
195 } 264 }
196 265
197 void 266 void
198 gaim_account_set_remember_password(GaimAccount *account, gboolean value) 267 gaim_account_set_remember_password(GaimAccount *account, gboolean value)
199 { 268 {
200 g_return_if_fail(account != NULL); 269 g_return_if_fail(account != NULL);
201 270
202 account->remember_pass = value; 271 account->remember_pass = value;
272
273 schedule_accounts_save();
203 } 274 }
204 275
205 void 276 void
206 gaim_account_set_int(GaimAccount *account, const char *name, int value) 277 gaim_account_set_int(GaimAccount *account, const char *name, int value)
207 { 278 {
214 285
215 setting->type = GAIM_PREF_INT; 286 setting->type = GAIM_PREF_INT;
216 setting->value.integer = value; 287 setting->value.integer = value;
217 288
218 g_hash_table_insert(account->settings, g_strdup(name), setting); 289 g_hash_table_insert(account->settings, g_strdup(name), setting);
290
291 schedule_accounts_save();
219 } 292 }
220 293
221 void 294 void
222 gaim_account_set_string(GaimAccount *account, const char *name, 295 gaim_account_set_string(GaimAccount *account, const char *name,
223 const char *value) 296 const char *value)
231 304
232 setting->type = GAIM_PREF_STRING; 305 setting->type = GAIM_PREF_STRING;
233 setting->value.string = g_strdup(value); 306 setting->value.string = g_strdup(value);
234 307
235 g_hash_table_insert(account->settings, g_strdup(name), setting); 308 g_hash_table_insert(account->settings, g_strdup(name), setting);
309
310 schedule_accounts_save();
236 } 311 }
237 312
238 void 313 void
239 gaim_account_set_bool(GaimAccount *account, const char *name, gboolean value) 314 gaim_account_set_bool(GaimAccount *account, const char *name, gboolean value)
240 { 315 {
247 322
248 setting->type = GAIM_PREF_BOOLEAN; 323 setting->type = GAIM_PREF_BOOLEAN;
249 setting->value.bool = value; 324 setting->value.bool = value;
250 325
251 g_hash_table_insert(account->settings, g_strdup(name), setting); 326 g_hash_table_insert(account->settings, g_strdup(name), setting);
327
328 schedule_accounts_save();
252 } 329 }
253 330
254 gboolean 331 gboolean
255 gaim_account_is_connected(const GaimAccount *account) 332 gaim_account_is_connected(const GaimAccount *account)
256 { 333 {
387 g_return_val_if_fail(setting->type == GAIM_PREF_BOOLEAN, default_value); 464 g_return_val_if_fail(setting->type == GAIM_PREF_BOOLEAN, default_value);
388 465
389 return setting->value.bool; 466 return setting->value.bool;
390 } 467 }
391 468
469 /* XML Stuff */
470 static void
471 __free_parser_data(gpointer user_data)
472 {
473 AccountParserData *data = user_data;
474
475 if (data->buffer != NULL)
476 g_free(data->buffer);
477
478 if (data->setting_name != NULL)
479 g_free(data->setting_name);
480
481 g_free(data);
482 }
483
484 static void
485 __start_element_handler(GMarkupParseContext *context,
486 const gchar *element_name,
487 const gchar **attribute_names,
488 const gchar **attribute_values,
489 gpointer user_data, GError **error)
490 {
491 AccountParserData *data = user_data;
492 int i;
493
494 if (data->buffer != NULL) {
495 g_string_free(data->buffer, TRUE);
496 data->buffer = NULL;
497 }
498
499 if (!strcmp(element_name, "protocol"))
500 data->tag = TAG_PROTOCOL;
501 else if (!strcmp(element_name, "name"))
502 data->tag = TAG_NAME;
503 else if (!strcmp(element_name, "password"))
504 data->tag = TAG_PASSWORD;
505 else if (!strcmp(element_name, "alias"))
506 data->tag = TAG_ALIAS;
507 else if (!strcmp(element_name, "userinfo"))
508 data->tag = TAG_USERINFO;
509 else if (!strcmp(element_name, "buddyicon"))
510 data->tag = TAG_BUDDYICON;
511 else if (!strcmp(element_name, "setting")) {
512 data->tag = TAG_SETTING;
513
514 for (i = 0; attribute_names[i] != NULL; i++) {
515
516 if (!strcmp(attribute_names[i], "name"))
517 data->setting_name = g_strdup(attribute_values[i]);
518 else if (!strcmp(attribute_names[i], "type")) {
519
520 if (!strcmp(attribute_values[i], "string"))
521 data->setting_type = GAIM_PREF_STRING;
522 else if (!strcmp(attribute_values[i], "int"))
523 data->setting_type = GAIM_PREF_INT;
524 else if (!strcmp(attribute_values[i], "bool"))
525 data->setting_type = GAIM_PREF_BOOLEAN;
526 }
527 }
528 }
529 }
530
531 static void
532 __end_element_handler(GMarkupParseContext *context, const gchar *element_name,
533 gpointer user_data, GError **error)
534 {
535 AccountParserData *data = user_data;
536 gchar *buffer;
537
538 if (data->buffer == NULL)
539 return;
540
541 buffer = g_string_free(data->buffer, FALSE);
542 data->buffer = NULL;
543
544 if (data->tag == TAG_PROTOCOL) {
545 GList *l;
546 GaimPlugin *plugin;
547
548 data->protocol = -1;
549
550 for (l = gaim_plugins_get_protocols(); l != NULL; l = l->next) {
551 plugin = (GaimPlugin *)l->data;
552
553 if (GAIM_IS_PROTOCOL_PLUGIN(plugin)) {
554 if (!strcmp(plugin->info->name, buffer)) {
555 data->protocol =
556 GAIM_PLUGIN_PROTOCOL_INFO(plugin)->protocol;
557
558 break;
559 }
560 }
561 }
562 }
563 else if (data->tag == TAG_NAME)
564 data->account = gaim_account_new(buffer, data->protocol);
565 else if (data->tag == TAG_PASSWORD)
566 gaim_account_set_password(data->account, buffer);
567 else if (data->tag == TAG_ALIAS)
568 gaim_account_set_alias(data->account, buffer);
569 else if (data->tag == TAG_USERINFO)
570 gaim_account_set_user_info(data->account, buffer);
571 else if (data->tag == TAG_BUDDYICON)
572 gaim_account_set_buddy_icon(data->account, buffer);
573 else if (data->tag == TAG_SETTING) {
574 if (data->setting_type == GAIM_PREF_STRING)
575 gaim_account_set_string(data->account, data->setting_name,
576 buffer);
577 else if (data->setting_type == GAIM_PREF_INT)
578 gaim_account_set_int(data->account, data->setting_name,
579 atoi(buffer));
580 else if (data->setting_type == GAIM_PREF_BOOLEAN)
581 gaim_account_set_bool(data->account, data->setting_name,
582 (*buffer == '0' ? FALSE : TRUE));
583
584 g_free(data->setting_name);
585 data->setting_name = NULL;
586 }
587
588 g_free(buffer);
589 }
590
591 static void
592 __text_handler(GMarkupParseContext *context, const gchar *text,
593 gsize text_len, gpointer user_data, GError **error)
594 {
595 AccountParserData *data = user_data;
596
597 if (data->buffer == NULL)
598 data->buffer = g_string_new_len(text, text_len);
599 else
600 g_string_append_len(data->buffer, text, text_len);
601 }
602
603 static GMarkupParser accounts_parser =
604 {
605 __start_element_handler,
606 __end_element_handler,
607 __text_handler,
608 NULL,
609 NULL
610 };
611
612 gboolean
613 gaim_accounts_load()
614 {
615 gchar *filename = g_build_filename(gaim_user_dir(), "accounts.xml", NULL);
616 gchar *contents = NULL;
617 gsize length;
618 GMarkupParseContext *context;
619 GError *error = NULL;
620 AccountParserData *parser_data;
621
622 if (filename == NULL) {
623 accounts_loaded = TRUE;
624 return FALSE;
625 }
626
627 gaim_debug(GAIM_DEBUG_INFO, "accounts", "Reading %s\n", filename);
628
629 if (!g_file_get_contents(filename, &contents, &length, &error)) {
630 gaim_debug(GAIM_DEBUG_ERROR, "accounts",
631 "Error reading accounts: %s\n", error->message);
632
633 g_error_free(error);
634
635 accounts_loaded = TRUE;
636 return FALSE;
637 }
638
639 parser_data = g_new0(AccountParserData, 1);
640
641 context = g_markup_parse_context_new(&accounts_parser, 0,
642 parser_data, __free_parser_data);
643
644 if (!g_markup_parse_context_parse(context, contents, length, NULL)) {
645 g_markup_parse_context_free(context);
646 g_free(contents);
647
648 accounts_loaded = TRUE;
649
650 return FALSE;
651 }
652
653 if (!g_markup_parse_context_end_parse(context, NULL)) {
654 gaim_debug(GAIM_DEBUG_ERROR, "accounts", "Error parsing %s\n",
655 filename);
656
657 g_markup_parse_context_free(context);
658 g_free(contents);
659 accounts_loaded = TRUE;
660
661 return FALSE;
662 }
663
664 g_markup_parse_context_free(context);
665 g_free(contents);
666
667 gaim_debug(GAIM_DEBUG_INFO, "accounts", "Finished reading %s\n",
668 filename);
669 g_free(filename);
670
671 accounts_loaded = TRUE;
672
673 return TRUE;
674 }
675
676 static void
677 __write_setting(gpointer key, gpointer value, gpointer user_data)
678 {
679 GaimAccountSetting *setting;
680 const char *name;
681 FILE *fp;
682
683 setting = (GaimAccountSetting *)value;
684 name = (const char *)key;
685 fp = (FILE *)user_data;
686
687 if (setting->type == GAIM_PREF_INT) {
688 fprintf(fp, " <setting name='%s' type='int'>%d</setting>\n",
689 name, setting->value.integer);
690 }
691 else if (setting->type == GAIM_PREF_STRING) {
692 fprintf(fp, " <setting name='%s' type='string'>%s</setting>\n",
693 name, setting->value.string);
694 }
695 else if (setting->type == GAIM_PREF_BOOLEAN) {
696 fprintf(fp, " <setting name='%s' type='bool'>%d</setting>\n",
697 name, setting->value.bool);
698 }
699 }
700
701 static void
702 gaim_accounts_write(FILE *fp, GaimAccount *account)
703 {
704 GaimPlugin *plugin;
705 const char *password, *alias, *user_info, *buddy_icon;
706
707 plugin = gaim_find_prpl(gaim_account_get_protocol(account));
708
709 fprintf(fp, " <account>\n");
710 fprintf(fp, " <protocol>%s</protocol>\n",
711 (plugin != NULL && plugin->info != NULL && plugin->info->id != NULL
712 ? plugin->info->id : "unknown"));
713 fprintf(fp, " <name>%s</name>\n", gaim_account_get_username(account));
714
715 if (gaim_account_get_remember_password(account) &&
716 (password = gaim_account_get_password(account)) != NULL) {
717
718 fprintf(fp, " <password>%s</password>\n", password);
719 }
720
721 if ((alias = gaim_account_get_alias(account)) != NULL)
722 fprintf(fp, " <alias>%s</alias>\n", alias);
723
724 if ((user_info = gaim_account_get_user_info(account)) != NULL)
725 fprintf(fp, " <userinfo>%s</userinfo>\n", user_info);
726
727 if ((buddy_icon = gaim_account_get_buddy_icon(account)) != NULL)
728 fprintf(fp, " <buddyicon>%s</buddyicon>\n", buddy_icon);
729
730 fprintf(fp, " <settings>\n");
731 g_hash_table_foreach(account->settings, __write_setting, fp);
732 fprintf(fp, " </settings>\n");
733
734 fprintf(fp, " </account>\n");
735 }
736
737 void
738 gaim_accounts_sync(void)
739 {
740 FILE *fp;
741 const char *user_dir = gaim_user_dir();
742 char *filename;
743 char *filename_real;
744
745 if (!accounts_loaded) {
746 gaim_debug(GAIM_DEBUG_WARNING, "accounts",
747 "Writing accounts to disk.\n");
748 schedule_accounts_save();
749 return;
750 }
751
752 if (user_dir == NULL)
753 return;
754
755 gaim_debug(GAIM_DEBUG_INFO, "accounts", "Writing accounts to disk.\n");
756
757 fp = fopen(user_dir, "r");
758
759 if (fp == NULL)
760 mkdir(user_dir, S_IRUSR | S_IWUSR | S_IXUSR);
761 else
762 fclose(fp);
763
764 filename = g_build_filename(user_dir, "accounts.xml.save", NULL);
765
766 if ((fp = fopen(filename, "w")) != NULL) {
767 GList *l;
768
769 fprintf(fp, "<?xml version='1.0' encoding='UTF-8' ?>\n\n");
770 fprintf(fp, "<accounts>\n");
771
772 for (l = gaim_accounts_get_all(); l != NULL; l = l->next)
773 gaim_accounts_write(fp, l->data);
774
775 fprintf(fp, "</accounts>\n");
776
777 fclose(fp);
778 chmod(filename, S_IRUSR | S_IWUSR);
779 }
780 else {
781 gaim_debug(GAIM_DEBUG_ERROR, "accounts", "Unable to write %s\n",
782 filename);
783 }
784
785 filename_real = g_build_filename(user_dir, "accounts.xml", NULL);
786
787 if (rename(filename, filename_real) < 0) {
788 gaim_debug(GAIM_DEBUG_ERROR, "accounts", "Error renaming %s to %s\n",
789 filename, filename_real);
790 }
791
792 g_free(filename);
793 g_free(filename_real);
794 }
795
796
392 GList * 797 GList *
393 gaim_accounts_get_all(void) 798 gaim_accounts_get_all(void)
394 { 799 {
395 return accounts; 800 return accounts;
396 } 801 }