]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-plist.c
Updated Oriya Translation
[empathy.git] / libempathy-gtk / empathy-plist.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2008 Christophe Fergeau <teuf@gnome.org>
4  * Based on itdb_plist parser from the gtkpod project.
5  *
6  * The code contained in this file is free software; you can redistribute
7  * it and/or modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either version
9  * 2.1 of the License, or (at your option) any later version.
10  *
11  * This file is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this code; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20
21 #include "config.h"
22
23 #include <string.h>
24 #include <libxml/parser.h>
25 #include <libxml/tree.h>
26 #include <telepathy-glib/util.h>
27 #include <telepathy-glib/dbus.h>
28
29 #include "empathy-plist.h"
30
31 static GValue *empathy_plist_parse_node (xmlNode *a_node);
32
33 static GValue *
34 empathy_plist_parse_integer (xmlNode *a_node)
35 {
36         char *str_val;
37         char *end_ptr;
38         gint int_val;
39
40         str_val = (char *) xmlNodeGetContent (a_node);
41         int_val = strtol (str_val, &end_ptr, 0);
42         if (*end_ptr != '\0') {
43                 xmlFree (str_val);
44                 return NULL;
45         }
46         xmlFree (str_val);
47
48         return tp_g_value_slice_new_int (int_val);
49 }
50
51 static GValue *
52 empathy_plist_parse_string (xmlNode *a_node)
53 {
54         char *str_val;
55         GValue *value;
56
57         str_val = (char *) xmlNodeGetContent (a_node);
58
59         value = tp_g_value_slice_new_string (str_val);
60
61         xmlFree (str_val);
62
63         return value;
64 }
65
66 static GValue *
67 empathy_plist_parse_real (xmlNode *a_node)
68 {
69         char *str_val;
70         char *end_ptr;
71         gdouble double_val;
72
73         str_val = (char *) xmlNodeGetContent (a_node);
74         double_val = g_ascii_strtod (str_val, &end_ptr);
75         if (*end_ptr != '\0') {
76                 xmlFree (str_val);
77                 return NULL;
78         }
79         xmlFree (str_val);
80
81         return tp_g_value_slice_new_double (double_val);
82 }
83
84 static GValue *
85 empathy_plist_parse_boolean (xmlNode *a_node)
86 {
87         gboolean bool_val;
88
89         if (strcmp ((char *) a_node->name, "true") == 0) {
90                 bool_val = TRUE;
91         } else if (strcmp ((char *) a_node->name, "false") == 0) {
92                 bool_val = FALSE;
93         } else {
94                 return NULL;
95         }
96
97         return tp_g_value_slice_new_boolean (bool_val);
98 }
99
100 static GValue *
101 empathy_plist_parse_data (xmlNode *a_node)
102 {
103         char *str_val;
104         guchar *raw_data;
105         gsize len;
106         GValue *value;
107
108         str_val = (char *) xmlNodeGetContent (a_node);
109         raw_data = g_base64_decode (str_val, &len);
110         xmlFree (str_val);
111
112         value = tp_g_value_slice_new_bytes (len, raw_data);
113
114         g_free (raw_data);
115
116         return value;
117 }
118
119 static xmlNode *
120 empathy_plist_parse_one_dict_entry (xmlNode *a_node, GHashTable *dict)
121 {
122         xmlNode *cur_node = a_node;
123         xmlChar *key_name;
124         GValue *value;
125
126         while (cur_node &&
127                (xmlStrcmp (cur_node->name, (xmlChar *) "key") != 0)) {
128                 cur_node = cur_node->next;
129         }
130         if (!cur_node) {
131                 return NULL;
132         }
133         key_name = xmlNodeGetContent (cur_node);
134         cur_node = cur_node->next;
135         while (cur_node && xmlIsBlankNode (cur_node)) {
136                 cur_node = cur_node->next;
137         }
138         if (!cur_node) {
139                 xmlFree (key_name);
140                 return NULL;
141         }
142
143         value = empathy_plist_parse_node (cur_node);
144         if (value) {
145                 g_hash_table_insert (dict, g_strdup ((char *) key_name), value);
146         }
147         xmlFree (key_name);
148
149         return cur_node->next;
150 }
151
152 static GValue *
153 empathy_plist_parse_dict (xmlNode *a_node)
154 {
155         xmlNode *cur_node = a_node->children;
156         GHashTable *dict;
157
158         dict = g_hash_table_new_full (g_str_hash, g_str_equal,
159                                       g_free, (GDestroyNotify) tp_g_value_slice_free);
160
161         while (cur_node) {
162                 if (xmlIsBlankNode (cur_node)) {
163                         cur_node = cur_node->next;
164                 } else {
165                         cur_node = empathy_plist_parse_one_dict_entry (cur_node, dict);
166                 }
167         }
168
169         return tp_g_value_slice_new_take_boxed (G_TYPE_HASH_TABLE, dict);
170 }
171
172 static GValue *
173 empathy_plist_parse_array (xmlNode *a_node)
174 {
175         xmlNode *cur_node = a_node->children;
176         GValueArray *array;
177
178         array = g_value_array_new (4);
179
180         while (cur_node) {
181                 GValue *cur_value;
182
183                 cur_value = empathy_plist_parse_node (cur_node);
184                 if (cur_value) {
185                         g_value_array_append (array, cur_value);
186                         tp_g_value_slice_free (cur_value);
187                 }
188
189                 /* When an array contains an element enclosed in "unknown" tags (ie
190                  * non-type ones), we silently skip them since early
191                  * SysInfoExtended files used to have <key> values enclosed within
192                  * <array> tags.
193                  */
194                 cur_node = cur_node->next;
195         }
196
197         return tp_g_value_slice_new_take_boxed (G_TYPE_VALUE_ARRAY, array);
198 }
199
200 typedef GValue *(*ParseCallback) (xmlNode *);
201
202 struct Parser {
203         const char * const type_name;
204         ParseCallback parser;
205 };
206
207 static const struct Parser parsers[] = { {"integer", empathy_plist_parse_integer},
208                                          {"real",    empathy_plist_parse_real},
209                                          {"string",  empathy_plist_parse_string},
210                                          {"true",    empathy_plist_parse_boolean},
211                                          {"false",   empathy_plist_parse_boolean},
212                                          {"data",    empathy_plist_parse_data},
213                                          {"dict",    empathy_plist_parse_dict},
214                                          {"array",   empathy_plist_parse_array},
215                                          {NULL,   NULL} };
216
217 static ParseCallback
218 empathy_plist_get_parser_for_type (const xmlChar *type)
219 {
220         guint i = 0;
221
222         while (parsers[i].type_name) {
223                 if (xmlStrcmp (type, (xmlChar *) parsers[i].type_name) == 0) {
224                         if (parsers[i].parser) {
225                                 return parsers[i].parser;
226                         }
227                 }
228                 i++;
229         }
230         return NULL;
231 }
232
233 static GValue *
234 empathy_plist_parse_node (xmlNode *a_node)
235 {
236         ParseCallback parser;
237
238         g_return_val_if_fail (a_node != NULL, NULL);
239         parser = empathy_plist_get_parser_for_type (a_node->name);
240         if (parser) {
241                 return parser (a_node);
242         } else {
243                 return NULL;
244         }
245 }
246
247 static GValue *
248 empathy_plist_parse (xmlNode * a_node)
249 {
250         xmlNode *cur_node;
251
252         if (!a_node) {
253                 return NULL;
254         }
255         if (xmlStrcmp (a_node->name, (xmlChar *) "plist") != 0) {
256                 return NULL;
257         }
258         cur_node = a_node->xmlChildrenNode;
259         while (cur_node && (xmlIsBlankNode (cur_node))) {
260                 cur_node = cur_node->next;
261         }
262         if (cur_node) {
263                 return empathy_plist_parse_node (cur_node);
264         }
265
266         return NULL;
267 }
268
269 /**
270  * empathy_plist_parse_from_file:
271  * @filename: file containing XML plist data to parse
272  *
273  * Parses the XML plist file. If an error occurs during the parsing,
274  * empathy_plist_parse_from_file() will return NULL.
275  *
276  * Returns: NULL on error, a newly allocated
277  * #GValue otherwise. Free it using tp_g_value_slice_free()
278  */
279 GValue *
280 empathy_plist_parse_from_file (const char *filename)
281 {
282         xmlDoc *doc = NULL;
283         xmlNode *root_element = NULL;
284         GValue *parsed_doc;
285
286         doc = xmlReadFile (filename, NULL, 0);
287
288         if (!doc) {
289                 return NULL;
290         }
291
292         root_element = xmlDocGetRootElement (doc);
293
294         parsed_doc = empathy_plist_parse (root_element);
295
296         xmlFreeDoc (doc);
297         xmlCleanupParser ();
298
299         return parsed_doc;
300 }
301
302 /**
303  * empathy_plist_parse_from_memory:
304  * @data:   memory location containing XML plist data to parse
305  * @len:        length in bytes of the string to parse
306  *
307  * Parses the XML plist file stored in @data which length is @len
308  * bytes. If an error occurs during the parsing,
309  * empathy_plist_parse_from_memory() will return NULL.
310  *
311  * Returns: NULL on error, a newly allocated
312  * #GValue otherwise. Free it using tp_g_value_slice_free()
313  */
314 GValue *
315 empathy_plist_parse_from_memory (const char *data, gsize len)
316 {
317         xmlDoc *doc = NULL;
318         xmlNode *root_element = NULL;
319         GValue *parsed_doc;
320
321         doc = xmlReadMemory (data, len, "noname.xml", NULL, 0);
322
323         if (doc == NULL) {
324                 return NULL;
325         }
326
327         root_element = xmlDocGetRootElement (doc);
328
329         parsed_doc = empathy_plist_parse (root_element);
330
331         xmlFreeDoc (doc);
332         xmlCleanupParser ();
333
334         return parsed_doc;
335 }
336