No issues found
1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2 of the License, or (at your option) version 3.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with the program; if not, see <http://www.gnu.org/licenses/>
14 *
15 *
16 * Authors:
17 * Chris Lahey <clahey@ximian.com>
18 *
19 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
20 *
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <locale.h>
33 #include <unistd.h>
34 #include <fcntl.h>
35 #include <errno.h>
36 #include <math.h>
37 #include <string.h>
38
39 #include <glib/gi18n.h>
40 #include <glib/gstdio.h>
41 #include <libxml/parser.h>
42 #include <libxml/xmlmemory.h>
43
44 #include "evolution-util.h"
45 #include "e-xml-utils.h"
46
47 /* Returns the first child with the name child_name and the "lang"
48 * attribute that matches the current LC_MESSAGES, or else, the first
49 * child with the name child_name and no "lang" attribute.
50 */
51 xmlNode *
52 e_xml_get_child_by_name_by_lang (const xmlNode *parent,
53 const xmlChar *child_name,
54 const gchar *lang)
55 {
56 #ifdef G_OS_WIN32
57 gchar *freeme = NULL;
58 #endif
59 xmlNode *child;
60 /* This is the default version of the string. */
61 xmlNode *C = NULL;
62
63 g_return_val_if_fail (parent != NULL, NULL);
64 g_return_val_if_fail (child_name != NULL, NULL);
65
66 if (lang == NULL) {
67 #ifndef G_OS_WIN32
68 #ifdef HAVE_LC_MESSAGES
69 lang = setlocale (LC_MESSAGES, NULL);
70 #else
71 lang = setlocale (LC_CTYPE, NULL);
72 #endif
73 #else
74 lang = freeme = g_win32_getlocale ();
75 #endif
76 }
77 for (child = parent->xmlChildrenNode; child != NULL; child = child->next) {
78 if (xmlStrcmp (child->name, child_name) == 0) {
79 xmlChar *this_lang = xmlGetProp (
80 child, (const guchar *)"lang");
81 if (this_lang == NULL) {
82 C = child;
83 } else if (xmlStrcmp (this_lang, (xmlChar *) lang) == 0) {
84 #ifdef G_OS_WIN32
85 g_free (freeme);
86 #endif
87 return child;
88 }
89 }
90 }
91 #ifdef G_OS_WIN32
92 g_free (freeme);
93 #endif
94 return C;
95 }
96
97 static xmlNode *
98 e_xml_get_child_by_name_by_lang_list_with_score (const xmlNode *parent,
99 const gchar *name,
100 const GList *lang_list,
101 gint *best_lang_score)
102 {
103 xmlNodePtr best_node = NULL, node;
104
105 for (node = parent->xmlChildrenNode; node != NULL; node = node->next) {
106 xmlChar *lang;
107
108 if (node->name == NULL || strcmp ((gchar *) node->name, name) != 0) {
109 continue;
110 }
111 lang = xmlGetProp (node, (const guchar *)"xml:lang");
112 if (lang != NULL) {
113 const GList *l;
114 gint i;
115
116 for (l = lang_list, i = 0;
117 l != NULL && i < *best_lang_score;
118 l = l->next, i++) {
119 if (strcmp ((gchar *) l->data, (gchar *) lang) == 0) {
120 best_node = node;
121 *best_lang_score = i;
122 }
123 }
124 } else {
125 if (best_node == NULL) {
126 best_node = node;
127 }
128 }
129 xmlFree (lang);
130 if (*best_lang_score == 0) {
131 return best_node;
132 }
133 }
134
135 return best_node;
136 }
137
138 xmlNode *
139 e_xml_get_child_by_name_by_lang_list (const xmlNode *parent,
140 const gchar *name,
141 const GList *lang_list)
142 {
143 gint best_lang_score = INT_MAX;
144
145 g_return_val_if_fail (parent != NULL, NULL);
146 g_return_val_if_fail (name != NULL, NULL);
147
148 if (lang_list == NULL) {
149 const gchar * const *language_names;
150
151 language_names = g_get_language_names ();
152 while (*language_names != NULL)
153 lang_list = g_list_append (
154 (GList *) lang_list, (gchar *) * language_names++);
155 }
156 return e_xml_get_child_by_name_by_lang_list_with_score
157 (parent,name,
158 lang_list,
159 &best_lang_score);
160 }
161
162 xmlNode *
163 e_xml_get_child_by_name_no_lang (const xmlNode *parent,
164 const gchar *name)
165 {
166 xmlNodePtr node;
167
168 g_return_val_if_fail (parent != NULL, NULL);
169 g_return_val_if_fail (name != NULL, NULL);
170
171 for (node = parent->xmlChildrenNode; node != NULL; node = node->next) {
172 xmlChar *lang;
173
174 if (node->name == NULL || strcmp ((gchar *) node->name, name) != 0) {
175 continue;
176 }
177 lang = xmlGetProp (node, (const guchar *)"xml:lang");
178 if (lang == NULL) {
179 return node;
180 }
181 xmlFree (lang);
182 }
183
184 return NULL;
185 }
186
187 gint
188 e_xml_get_integer_prop_by_name (const xmlNode *parent,
189 const xmlChar *prop_name)
190 {
191 g_return_val_if_fail (parent != NULL, 0);
192 g_return_val_if_fail (prop_name != NULL, 0);
193
194 return e_xml_get_integer_prop_by_name_with_default (parent, prop_name, 0);
195 }
196
197 gint
198 e_xml_get_integer_prop_by_name_with_default (const xmlNode *parent,
199 const xmlChar *prop_name,
200 gint def)
201 {
202 xmlChar *prop;
203 gint ret_val = def;
204
205 g_return_val_if_fail (parent != NULL, 0);
206 g_return_val_if_fail (prop_name != NULL, 0);
207
208 prop = xmlGetProp ((xmlNode *) parent, prop_name);
209 if (prop != NULL) {
210 (void) sscanf ((gchar *) prop, "%d", &ret_val);
211 xmlFree (prop);
212 }
213 return ret_val;
214 }
215
216 void
217 e_xml_set_integer_prop_by_name (xmlNode *parent,
218 const xmlChar *prop_name,
219 gint value)
220 {
221 gchar *valuestr;
222
223 g_return_if_fail (parent != NULL);
224 g_return_if_fail (prop_name != NULL);
225
226 valuestr = g_strdup_printf ("%d", value);
227 xmlSetProp (parent, prop_name, (guchar *) valuestr);
228 g_free (valuestr);
229 }
230
231 guint
232 e_xml_get_uint_prop_by_name (const xmlNode *parent,
233 const xmlChar *prop_name)
234 {
235 g_return_val_if_fail (parent != NULL, 0);
236 g_return_val_if_fail (prop_name != NULL, 0);
237
238 return e_xml_get_uint_prop_by_name_with_default (parent, prop_name, 0);
239 }
240
241 guint
242 e_xml_get_uint_prop_by_name_with_default (const xmlNode *parent,
243 const xmlChar *prop_name,
244 guint def)
245 {
246 xmlChar *prop;
247 guint ret_val = def;
248
249 g_return_val_if_fail (parent != NULL, 0);
250 g_return_val_if_fail (prop_name != NULL, 0);
251
252 prop = xmlGetProp ((xmlNode *) parent, prop_name);
253 if (prop != NULL) {
254 (void) sscanf ((gchar *) prop, "%u", &ret_val);
255 xmlFree (prop);
256 }
257 return ret_val;
258 }
259
260 void
261 e_xml_set_uint_prop_by_name (xmlNode *parent,
262 const xmlChar *prop_name,
263 guint value)
264 {
265 gchar *valuestr;
266
267 g_return_if_fail (parent != NULL);
268 g_return_if_fail (prop_name != NULL);
269
270 valuestr = g_strdup_printf ("%u", value);
271 xmlSetProp (parent, prop_name, (guchar *) valuestr);
272 g_free (valuestr);
273 }
274
275 gboolean
276 e_xml_get_bool_prop_by_name (const xmlNode *parent,
277 const xmlChar *prop_name)
278 {
279 g_return_val_if_fail (parent != NULL, 0);
280 g_return_val_if_fail (prop_name != NULL, 0);
281
282 return e_xml_get_bool_prop_by_name_with_default (
283 parent, prop_name, FALSE);
284 }
285
286 gboolean
287 e_xml_get_bool_prop_by_name_with_default (const xmlNode *parent,
288 const xmlChar *prop_name,
289 gboolean def)
290 {
291 xmlChar *prop;
292 gboolean ret_val = def;
293
294 g_return_val_if_fail (parent != NULL, 0);
295 g_return_val_if_fail (prop_name != NULL, 0);
296
297 prop = xmlGetProp ((xmlNode *) parent, prop_name);
298 if (prop != NULL) {
299 if (g_ascii_strcasecmp ((gchar *) prop, "true") == 0) {
300 ret_val = TRUE;
301 } else if (g_ascii_strcasecmp ((gchar *) prop, "false") == 0) {
302 ret_val = FALSE;
303 }
304 xmlFree (prop);
305 }
306 return ret_val;
307 }
308
309 void
310 e_xml_set_bool_prop_by_name (xmlNode *parent,
311 const xmlChar *prop_name,
312 gboolean value)
313 {
314 g_return_if_fail (parent != NULL);
315 g_return_if_fail (prop_name != NULL);
316
317 if (value) {
318 xmlSetProp (parent, prop_name, (const guchar *)"true");
319 } else {
320 xmlSetProp (parent, prop_name, (const guchar *)"false");
321 }
322 }
323
324 gdouble
325 e_xml_get_double_prop_by_name (const xmlNode *parent,
326 const xmlChar *prop_name)
327 {
328 g_return_val_if_fail (parent != NULL, 0);
329 g_return_val_if_fail (prop_name != NULL, 0);
330
331 return e_xml_get_double_prop_by_name_with_default (parent, prop_name, 0.0);
332 }
333
334 gdouble
335 e_xml_get_double_prop_by_name_with_default (const xmlNode *parent,
336 const xmlChar *prop_name,
337 gdouble def)
338 {
339 xmlChar *prop;
340 gdouble ret_val = def;
341
342 g_return_val_if_fail (parent != NULL, 0);
343 g_return_val_if_fail (prop_name != NULL, 0);
344
345 prop = xmlGetProp ((xmlNode *) parent, prop_name);
346 if (prop != NULL) {
347 ret_val = e_flexible_strtod ((gchar *) prop, NULL);
348 xmlFree (prop);
349 }
350 return ret_val;
351 }
352
353 void
354 e_xml_set_double_prop_by_name (xmlNode *parent,
355 const xmlChar *prop_name,
356 gdouble value)
357 {
358 gchar buffer[E_ASCII_DTOSTR_BUF_SIZE];
359 gchar *format;
360
361 g_return_if_fail (parent != NULL);
362 g_return_if_fail (prop_name != NULL);
363
364 if (fabs (value) < 1e9 && fabs (value) > 1e-5) {
365 format = g_strdup_printf ("%%.%df", DBL_DIG);
366 } else {
367 format = g_strdup_printf ("%%.%dg", DBL_DIG);
368 }
369 e_ascii_dtostr (buffer, sizeof (buffer), format, value);
370 g_free (format);
371
372 xmlSetProp (parent, prop_name, (const guchar *) buffer);
373 }
374
375 gchar *
376 e_xml_get_string_prop_by_name (const xmlNode *parent,
377 const xmlChar *prop_name)
378 {
379 g_return_val_if_fail (parent != NULL, NULL);
380 g_return_val_if_fail (prop_name != NULL, NULL);
381
382 return e_xml_get_string_prop_by_name_with_default (parent, prop_name, NULL);
383 }
384
385 gchar *
386 e_xml_get_string_prop_by_name_with_default (const xmlNode *parent,
387 const xmlChar *prop_name,
388 const gchar *def)
389 {
390 xmlChar *prop;
391 gchar *ret_val;
392
393 g_return_val_if_fail (parent != NULL, NULL);
394 g_return_val_if_fail (prop_name != NULL, NULL);
395
396 prop = xmlGetProp ((xmlNode *) parent, prop_name);
397 if (prop != NULL) {
398 ret_val = g_strdup ((gchar *) prop);
399 xmlFree (prop);
400 } else {
401 ret_val = g_strdup (def);
402 }
403 return ret_val;
404 }
405
406 void
407 e_xml_set_string_prop_by_name (xmlNode *parent,
408 const xmlChar *prop_name,
409 const gchar *value)
410 {
411 g_return_if_fail (parent != NULL);
412 g_return_if_fail (prop_name != NULL);
413
414 if (value != NULL) {
415 xmlSetProp (parent, prop_name, (guchar *) value);
416 }
417 }
418
419 gchar *
420 e_xml_get_translated_string_prop_by_name (const xmlNode *parent,
421 const xmlChar *prop_name)
422 {
423 xmlChar *prop;
424 gchar *ret_val = NULL;
425 gchar *combined_name;
426
427 g_return_val_if_fail (parent != NULL, NULL);
428 g_return_val_if_fail (prop_name != NULL, NULL);
429
430 prop = xmlGetProp ((xmlNode *) parent, prop_name);
431 if (prop != NULL) {
432 ret_val = g_strdup ((gchar *) prop);
433 xmlFree (prop);
434 return ret_val;
435 }
436
437 combined_name = g_strdup_printf ("_%s", prop_name);
438 prop = xmlGetProp ((xmlNode *) parent, (guchar *) combined_name);
439 if (prop != NULL) {
440 ret_val = g_strdup (gettext ((gchar *) prop));
441 xmlFree (prop);
442 }
443 g_free (combined_name);
444
445 return ret_val;
446 }