Mercurial > pidgin
annotate src/status.c @ 7166:e6b01bd8d6cd
[gaim-migrate @ 7733]
I fixed the notify_added function, Chip had two of the variables swapped :-)
I changed the way tlvlists are done in ssi.c a little bit. You can alias
ICQ buddies that you don't have authorization for yet, and when you alias
a buddy you will no longer lose any Buddy Alerts that may be set.
Why is this? Previously tlvlists (data associated with each server stored
item) were just deleted and recreated when you set an alias, or changed your
permit/deny setting. Now the lists are modified and TLVs that libfaim
doesn't know about are just left in place.
Why did I wait so long to do this? I'm lazy, it's not really all that fun,
and I don't consider it all that important.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Sun, 05 Oct 2003 22:41:29 +0000 |
parents | 8f94cce8faa5 |
children | fa6395637e2c |
rev | line source |
---|---|
6065 | 1 /* |
2 * gaim | |
3 * | |
4 * Copyright (C) 2003 Jason Priestly | |
5 * Copyright (C) 2003 Luke Perry | |
6 * | |
7 * This program is free software; you can redistribute it and/or modify | |
8 * it under the terms of the GNU General Public License as published by | |
9 * the Free Software Foundation; either version 2 of the License, or | |
10 * (at your option) any later version. | |
11 * | |
12 * This program is distributed in the hope that it will be useful, | |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 * GNU General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU General Public License | |
18 * along with this program; if not, write to the Free Software | |
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
20 */ | |
21 | |
22 #include "status.h" | |
23 #include "internal.h" | |
24 #include "debug.h" | |
25 #include "util.h" | |
26 | |
6371
8f94cce8faa5
[gaim-migrate @ 6876]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
27 /* XXX CORE/UI */ |
8f94cce8faa5
[gaim-migrate @ 6876]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
28 #include "gtkinternal.h" |
8f94cce8faa5
[gaim-migrate @ 6876]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
29 #include "ui.h" |
8f94cce8faa5
[gaim-migrate @ 6876]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
30 |
8f94cce8faa5
[gaim-migrate @ 6876]
Christian Hammond <chipx86@chipx86.com>
parents:
6321
diff
changeset
|
31 |
6065 | 32 /* for people like myself who are too lazy to add an away msg :) */ |
33 /* I don't know who "myself" is in this context. The exclamation point | |
34 * makes it slightly less boring ;) */ | |
35 #define BORING_DEFAULT_AWAY_MSG _("Sorry, I ran out for a bit!") | |
36 | |
37 /* XML File Saving */ | |
38 | |
39 /* All of this code is adapted from Nathan Walp's. It's adapted all over the place | |
40 * for accounts, the buddy list, pounces, preferences, and the likes. It would be | |
41 * neat if we could somehow make this more generic. */ | |
42 static gboolean status_loaded = FALSE; | |
43 static guint status_save_timer = 0; | |
44 | |
45 | |
46 typedef enum | |
47 { | |
48 TAG_NONE = 0, | |
49 TAG_STATUS, | |
50 TAG_STATE, | |
51 TAG_MESSAGE, | |
52 | |
53 } StatusParserTag; | |
54 | |
55 | |
56 typedef struct | |
57 { | |
58 StatusParserTag tag; | |
59 GString *buffer; | |
60 struct away_message *am; | |
61 | |
62 } StatusParserData; | |
63 | |
64 static void | |
65 free_parser_data(gpointer user_data) | |
66 { | |
67 StatusParserData *data = user_data; | |
68 | |
69 if (data->buffer != NULL) | |
70 g_string_free(data->buffer, TRUE); | |
71 | |
72 g_free(data); | |
73 } | |
74 | |
75 static void gaim_status_write(FILE *fp, struct away_message *am) | |
76 { | |
77 char *esc = NULL; | |
6216 | 78 |
6065 | 79 esc = g_markup_escape_text(am->name, -1); |
6216 | 80 fprintf(fp, "\t<status name=\"%s\">\n", esc); |
6065 | 81 g_free(esc); |
82 | |
6216 | 83 fprintf(fp, "\t\t<state>away</state>\n"); |
84 | |
85 esc = g_markup_escape_text(am->message, -1); | |
86 fprintf(fp, "\t\t<message>%s</message>\n", esc); | |
87 g_free(esc); | |
88 | |
89 fprintf(fp, "\t</status>\n"); | |
6065 | 90 } |
91 | |
92 static gboolean | |
93 status_save_cb(gpointer unused) | |
94 { | |
95 gaim_status_sync(); | |
96 status_save_timer = 0; | |
97 | |
98 return FALSE; | |
99 } | |
100 | |
101 static void | |
102 schedule_status_save() | |
103 { | |
104 if (!status_save_timer) | |
105 status_save_timer = g_timeout_add(5000, status_save_cb, NULL); | |
106 } | |
107 | |
108 static void | |
109 start_element_handler(GMarkupParseContext *context, | |
110 const gchar *element_name, | |
111 const gchar **attribute_names, | |
112 const gchar **attribute_values, | |
113 gpointer user_data, GError **error) | |
114 { | |
115 const char *value; | |
116 StatusParserData *data = user_data; | |
117 GHashTable *atts; | |
118 int i; | |
119 | |
120 atts = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); | |
121 | |
122 for (i = 0; attribute_names[i] != NULL; i++) { | |
123 g_hash_table_insert(atts, g_strdup(attribute_names[i]), | |
124 g_strdup(attribute_values[i])); | |
125 } | |
126 | |
127 if (data->buffer != NULL) { | |
128 g_string_free(data->buffer, TRUE); | |
129 data->buffer = NULL; | |
130 } | |
131 | |
132 if (!strcmp(element_name, "status")) { | |
133 data->tag = TAG_STATUS; | |
134 if ((value = g_hash_table_lookup(atts, "name")) != NULL) { | |
135 data->am = g_new0(struct away_message, 1); | |
136 g_snprintf(data->am->name, sizeof(data->am->name), "%s", value); | |
137 away_messages = g_slist_append(away_messages, data->am); | |
138 } | |
139 } else if (!strcmp(element_name, "message")) { | |
140 data->tag = TAG_MESSAGE; | |
6216 | 141 |
6065 | 142 } |
6113 | 143 |
144 g_hash_table_destroy(atts); | |
6065 | 145 } |
146 | |
147 static void | |
148 end_element_handler(GMarkupParseContext *context, const gchar *element_name, | |
149 gpointer user_data, GError **error) | |
150 { | |
151 StatusParserData *data = user_data; | |
152 gchar *buffer; | |
153 | |
154 if (data->buffer == NULL) | |
155 return; | |
156 | |
157 buffer = g_string_free(data->buffer, FALSE); | |
158 data->buffer = NULL; | |
159 | |
160 if (data->tag == TAG_MESSAGE) { | |
161 if (*buffer != '\0') | |
162 g_snprintf(data->am->message, sizeof(data->am->message), "%s", buffer); | |
163 } | |
164 | |
165 data->tag = TAG_NONE; | |
166 | |
167 g_free(buffer); | |
168 } | |
169 | |
170 static void | |
171 text_handler(GMarkupParseContext *context, const gchar *text, | |
172 gsize text_len, gpointer user_data, GError **error) | |
173 { | |
174 StatusParserData *data = user_data; | |
175 | |
176 if (data->buffer == NULL) | |
177 data->buffer = g_string_new_len(text, text_len); | |
178 else | |
179 g_string_append_len(data->buffer, text, text_len); | |
180 } | |
181 | |
182 static GMarkupParser status_parser = | |
183 { | |
184 start_element_handler, | |
185 end_element_handler, | |
186 text_handler, | |
187 NULL, | |
188 NULL | |
189 }; | |
190 | |
191 void gaim_status_sync() | |
192 { | |
193 FILE *fp; | |
194 const char *user_dir = gaim_user_dir(); | |
195 char *filename, *filename_real; | |
196 | |
197 if (!status_loaded) { | |
198 gaim_debug(GAIM_DEBUG_WARNING, "status", "Writing status to disk.\n"); | |
199 schedule_status_save(); | |
200 return; | |
201 } | |
202 | |
203 if (user_dir == NULL) | |
204 return; | |
205 | |
206 gaim_debug(GAIM_DEBUG_INFO, "status", "Saving statuses to disk\n"); | |
207 | |
208 fp = fopen(user_dir, "r"); | |
209 | |
210 if (fp == NULL) | |
211 mkdir(user_dir, S_IRUSR | S_IWUSR | S_IXUSR); | |
212 else | |
213 fclose(fp); | |
214 | |
215 filename = g_build_filename(user_dir, "status.xml.save", NULL); | |
216 | |
217 if ((fp = fopen(filename, "w")) != NULL) { | |
218 GSList *l; | |
219 | |
220 fprintf(fp, "<?xml version='1.0' encoding='UTF-8' ?>\n\n"); | |
221 fprintf(fp, "<statuses>\n"); | |
222 | |
223 for (l = away_messages; l != NULL; l = l->next) | |
224 gaim_status_write(fp, l->data); | |
225 | |
226 fprintf(fp, "</statuses>\n"); | |
227 | |
228 fclose(fp); | |
229 chmod(filename, S_IRUSR | S_IWUSR); | |
230 } | |
231 else { | |
232 gaim_debug(GAIM_DEBUG_ERROR, "status", "Unable to write %s\n", | |
233 filename); | |
234 } | |
235 | |
236 filename_real = g_build_filename(user_dir, "status.xml", NULL); | |
237 | |
238 if (rename(filename, filename_real) < 0) { | |
239 gaim_debug(GAIM_DEBUG_ERROR, "status", "Error renaming %s to %s\n", | |
240 filename, filename_real); | |
241 } | |
242 | |
243 g_free(filename); | |
244 g_free(filename_real); | |
245 | |
246 } | |
247 | |
248 void gaim_status_load() | |
249 { | |
250 gchar *filename = g_build_filename(gaim_user_dir(), "status.xml", NULL); | |
251 gchar *contents = NULL; | |
252 gsize length; | |
253 GMarkupParseContext *context; | |
254 GError *error = NULL; | |
255 StatusParserData *parser_data; | |
256 | |
257 if (filename == NULL) { | |
258 status_loaded = TRUE; | |
259 return; | |
260 } | |
261 | |
262 if (!g_file_get_contents(filename, &contents, &length, &error)) { | |
263 gaim_debug(GAIM_DEBUG_ERROR, "status", | |
264 "Error reading statuses: %s\n", error->message); | |
265 g_error_free(error); | |
266 g_free(filename); | |
267 status_loaded = TRUE; | |
268 if (!away_messages) { | |
269 struct away_message *a = g_new0(struct away_message, 1); | |
270 g_snprintf(a->name, sizeof(a->name), _("Slightly less boring default")); | |
6321 | 271 g_snprintf(a->message, sizeof(a->message), "%s", _(BORING_DEFAULT_AWAY_MSG)); |
6065 | 272 away_messages = g_slist_append(away_messages, a); |
273 } | |
274 return; | |
275 } | |
276 | |
277 parser_data = g_new0(StatusParserData, 1); | |
278 | |
279 context = g_markup_parse_context_new(&status_parser, 0, | |
280 parser_data, free_parser_data); | |
281 | |
282 if (!g_markup_parse_context_parse(context, contents, length, NULL)) { | |
283 g_markup_parse_context_free(context); | |
284 g_free(contents); | |
285 g_free(filename); | |
286 status_loaded = TRUE; | |
287 return; | |
288 } | |
289 | |
290 if (!g_markup_parse_context_end_parse(context, NULL)) { | |
291 gaim_debug(GAIM_DEBUG_ERROR, "status", "Error parsing %s\n", | |
292 filename); | |
293 g_markup_parse_context_free(context); | |
294 g_free(contents); | |
295 g_free(filename); | |
296 status_loaded = TRUE; | |
297 return; | |
298 } | |
299 | |
300 g_markup_parse_context_free(context); | |
301 g_free(contents); | |
302 g_free(filename); | |
303 status_loaded = TRUE; | |
304 return; | |
305 } |