]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-plist.c
remove released flag
[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 #include "empathy-plist.h"
23
24 #include <string.h>
25 #include <libxml/tree.h>
26 #include <telepathy-glib/telepathy-glib.h>
27
28 static GValue *empathy_plist_parse_node (xmlNode *a_node);
29
30 static GValue *
31 empathy_plist_parse_integer (xmlNode *a_node)
32 {
33         char *str_val;
34         char *end_ptr;
35         gint int_val;
36
37         str_val = (char *) xmlNodeGetContent (a_node);
38         int_val = strtol (str_val, &end_ptr, 0);
39         if (*end_ptr != '\0') {
40                 xmlFree (str_val);
41                 return NULL;
42         }
43         xmlFree (str_val);
44
45         return tp_g_value_slice_new_int (int_val);
46 }
47
48 static GValue *
49 empathy_plist_parse_string (xmlNode *a_node)
50 {
51         char *str_val;
52         GValue *value;
53
54         str_val = (char *) xmlNodeGetContent (a_node);
55
56         value = tp_g_value_slice_new_string (str_val);
57
58         xmlFree (str_val);
59
60         return value;
61 }
62
63 static GValue *
64 empathy_plist_parse_real (xmlNode *a_node)
65 {
66         char *str_val;
67         char *end_ptr;
68         gdouble double_val;
69
70         str_val = (char *) xmlNodeGetContent (a_node);
71         double_val = g_ascii_strtod (str_val, &end_ptr);
72         if (*end_ptr != '\0') {
73                 xmlFree (str_val);
74                 return NULL;
75         }
76         xmlFree (str_val);
77
78         return tp_g_value_slice_new_double (double_val);
79 }
80
81 static GValue *
82 empathy_plist_parse_boolean (xmlNode *a_node)
83 {
84         gboolean bool_val;
85
86         if (strcmp ((char *) a_node->name, "true") == 0) {
87                 bool_val = TRUE;
88         } else if (strcmp ((char *) a_node->name, "false") == 0) {
89                 bool_val = FALSE;
90         } else {
91                 return NULL;
92         }
93
94         return tp_g_value_slice_new_boolean (bool_val);
95 }
96
97 static GValue *
98 empathy_plist_parse_data (xmlNode *a_node)
99 {
100         char *str_val;
101         guchar *raw_data;
102         gsize len;
103         GValue *value;
104
105         str_val = (char *) xmlNodeGetContent (a_node);
106         raw_data = g_base64_decode (str_val, &len);
107         xmlFree (str_val);
108
109         value = tp_g_value_slice_new_bytes (len, raw_data);
110
111         g_free (raw_data);
112
113         return value;
114 }
115
116 static xmlNode *
117 empathy_plist_parse_one_dict_entry (xmlNode *a_node, GHashTable *dict)
118 {
119         xmlNode *cur_node = a_node;
120         xmlChar *key_name;
121         GValue *value;
122
123         while (cur_node &&
124                (xmlStrcmp (cur_node->name, (xmlChar *) "key") != 0)) {
125                 cur_node = cur_node->next;
126         }
127         if (!cur_node) {
128                 return NULL;
129         }
130         key_name = xmlNodeGetContent (cur_node);
131         cur_node = cur_node->next;
132         while (cur_node && xmlIsBlankNode (cur_node)) {
133                 cur_node = cur_node->next;
134         }
135         if (!cur_node) {
136                 xmlFree (key_name);
137                 return NULL;
138         }
139
140         value = empathy_plist_parse_node (cur_node);
141         if (value) {
142                 g_hash_table_insert (dict, g_strdup ((char *) key_name), value);
143         }
144         xmlFree (key_name);
145
146         return cur_node->next;
147 }
148
149 static GValue *
150 empathy_plist_parse_dict (xmlNode *a_node)
151 {
152         xmlNode *cur_node = a_node->children;
153         GHashTable *dict;
154
155         dict = g_hash_table_new_full (g_str_hash, g_str_equal,
156                                       g_free, (GDestroyNotify) tp_g_value_slice_free);
157
158         while (cur_node) {
159                 if (xmlIsBlankNode (cur_node)) {
160                         cur_node = cur_node->next;
161                 } else {
162                         cur_node = empathy_plist_parse_one_dict_entry (cur_node, dict);
163                 }
164         }
165
166         return tp_g_value_slice_new_take_boxed (G_TYPE_HASH_TABLE, dict);
167 }
168
169 typedef GValue *(*ParseCallback) (xmlNode *);
170
171 struct Parser {
172         const char * const type_name;
173         ParseCallback parser;
174 };
175
176 static const struct Parser parsers[] = { {"integer", empathy_plist_parse_integer},
177                                          {"real",    empathy_plist_parse_real},
178                                          {"string",  empathy_plist_parse_string},
179                                          {"true",    empathy_plist_parse_boolean},
180                                          {"false",   empathy_plist_parse_boolean},
181                                          {"data",    empathy_plist_parse_data},
182                                          {"dict",    empathy_plist_parse_dict},
183                                          {NULL,   NULL} };
184
185 static ParseCallback
186 empathy_plist_get_parser_for_type (const xmlChar *type)
187 {
188         guint i = 0;
189
190         while (parsers[i].type_name) {
191                 if (xmlStrcmp (type, (xmlChar *) parsers[i].type_name) == 0) {
192                         if (parsers[i].parser) {
193                                 return parsers[i].parser;
194                         }
195                 }
196                 i++;
197         }
198         return NULL;
199 }
200
201 static GValue *
202 empathy_plist_parse_node (xmlNode *a_node)
203 {
204         ParseCallback parser;
205
206         g_return_val_if_fail (a_node != NULL, NULL);
207         parser = empathy_plist_get_parser_for_type (a_node->name);
208         if (parser) {
209                 return parser (a_node);
210         } else {
211                 return NULL;
212         }
213 }
214
215 static GValue *
216 empathy_plist_parse (xmlNode * a_node)
217 {
218         xmlNode *cur_node;
219
220         if (!a_node) {
221                 return NULL;
222         }
223         if (xmlStrcmp (a_node->name, (xmlChar *) "plist") != 0) {
224                 return NULL;
225         }
226         cur_node = a_node->xmlChildrenNode;
227         while (cur_node && (xmlIsBlankNode (cur_node))) {
228                 cur_node = cur_node->next;
229         }
230         if (cur_node) {
231                 return empathy_plist_parse_node (cur_node);
232         }
233
234         return NULL;
235 }
236
237 /**
238  * empathy_plist_parse_from_file:
239  * @filename: file containing XML plist data to parse
240  *
241  * Parses the XML plist file. If an error occurs during the parsing,
242  * empathy_plist_parse_from_file() will return NULL.
243  *
244  * Returns: NULL on error, a newly allocated
245  * #GValue otherwise. Free it using tp_g_value_slice_free()
246  */
247 GValue *
248 empathy_plist_parse_from_file (const char *filename)
249 {
250         xmlDoc *doc = NULL;
251         xmlNode *root_element = NULL;
252         GValue *parsed_doc;
253
254         doc = xmlReadFile (filename, NULL, 0);
255
256         if (!doc) {
257                 return NULL;
258         }
259
260         root_element = xmlDocGetRootElement (doc);
261
262         parsed_doc = empathy_plist_parse (root_element);
263
264         xmlFreeDoc (doc);
265
266         return parsed_doc;
267 }
268
269 /**
270  * empathy_plist_parse_from_memory:
271  * @data:   memory location containing XML plist data to parse
272  * @len:        length in bytes of the string to parse
273  *
274  * Parses the XML plist file stored in @data which length is @len
275  * bytes. If an error occurs during the parsing,
276  * empathy_plist_parse_from_memory() will return NULL.
277  *
278  * Returns: NULL on error, a newly allocated
279  * #GValue otherwise. Free it using tp_g_value_slice_free()
280  */
281 GValue *
282 empathy_plist_parse_from_memory (const char *data, gsize len)
283 {
284         xmlDoc *doc = NULL;
285         xmlNode *root_element = NULL;
286         GValue *parsed_doc;
287
288         doc = xmlReadMemory (data, len, "noname.xml", NULL, 0);
289
290         if (doc == NULL) {
291                 return NULL;
292         }
293
294         root_element = xmlDocGetRootElement (doc);
295
296         parsed_doc = empathy_plist_parse (root_element);
297
298         xmlFreeDoc (doc);
299
300         return parsed_doc;
301 }
302