summaryrefslogtreecommitdiffstats
path: root/src/xplist.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xplist.c')
-rw-r--r--src/xplist.c564
1 files changed, 292 insertions, 272 deletions
diff --git a/src/xplist.c b/src/xplist.c
index 490367e..15c9497 100644
--- a/src/xplist.c
+++ b/src/xplist.c
@@ -8,15 +8,15 @@
8 * modify it under the terms of the GNU Lesser General Public 8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either 9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version. 10 * version 2.1 of the License, or (at your option) any later version.
11 * 11 *
12 * This library is distributed in the hope that it will be useful, 12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details. 15 * Lesser General Public License for more details.
16 * 16 *
17 * You should have received a copy of the GNU Lesser General Public 17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software 18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */ 20 */
21 21
22 22
@@ -50,7 +50,7 @@ static const char *plist_base = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
50 50
51 51
52/** Formats a block of text to be a given indentation and width. 52/** Formats a block of text to be a given indentation and width.
53 * 53 *
54 * The total width of the return string will be depth + cols. 54 * The total width of the return string will be depth + cols.
55 * 55 *
56 * @param buf The string to format. 56 * @param buf The string to format.
@@ -61,303 +61,323 @@ static const char *plist_base = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
61 */ 61 */
62static gchar *format_string(const char *buf, int cols, int depth) 62static gchar *format_string(const char *buf, int cols, int depth)
63{ 63{
64 int colw = depth + cols + 1; 64 int colw = depth + cols + 1;
65 int len = strlen(buf); 65 int len = strlen(buf);
66 int nlines = len / cols + 1; 66 int nlines = len / cols + 1;
67 gchar *new_buf = (gchar *) g_malloc0(nlines * colw + depth + 1); 67 gchar *new_buf = (gchar *) g_malloc0(nlines * colw + depth + 1);
68 int i = 0; 68 int i = 0;
69 int j = 0; 69 int j = 0;
70 70
71 assert(cols >= 0); 71 assert(cols >= 0);
72 assert(depth >= 0); 72 assert(depth >= 0);
73 73
74 // Inserts new lines and tabs at appropriate locations 74 // Inserts new lines and tabs at appropriate locations
75 for (i = 0; i < nlines; i++) { 75 for (i = 0; i < nlines; i++)
76 new_buf[i * colw] = '\n'; 76 {
77 for (j = 0; j < depth; j++) 77 new_buf[i * colw] = '\n';
78 new_buf[i * colw + 1 + j] = '\t'; 78 for (j = 0; j < depth; j++)
79 memcpy(new_buf + i * colw + 1 + depth, buf + i * cols, (i + 1) * cols <= len ? cols : len - i * cols); 79 new_buf[i * colw + 1 + j] = '\t';
80 } 80 memcpy(new_buf + i * colw + 1 + depth, buf + i * cols, (i + 1) * cols <= len ? cols : len - i * cols);
81 new_buf[len + (1 + depth) * nlines] = '\n'; 81 }
82 82 new_buf[len + (1 + depth) * nlines] = '\n';
83 // Inserts final row of indentation and termination character 83
84 for (j = 0; j < depth; j++) 84 // Inserts final row of indentation and termination character
85 new_buf[len + (1 + depth) * nlines + 1 + j] = '\t'; 85 for (j = 0; j < depth; j++)
86 new_buf[len + (1 + depth) * nlines + depth + 1] = '\0'; 86 new_buf[len + (1 + depth) * nlines + 1 + j] = '\t';
87 87 new_buf[len + (1 + depth) * nlines + depth + 1] = '\0';
88 return new_buf; 88
89 return new_buf;
89} 90}
90 91
91 92
92 93
93struct xml_node { 94struct xml_node
94 xmlNodePtr xml; 95{
95 uint32_t depth; 96 xmlNodePtr xml;
97 uint32_t depth;
96}; 98};
97 99
98/** Creates a new plist XML document. 100/** Creates a new plist XML document.
99 * 101 *
100 * @return The plist XML document. 102 * @return The plist XML document.
101 */ 103 */
102static xmlDocPtr new_xml_plist(void) 104static xmlDocPtr new_xml_plist(void)
103{ 105{
104 char *plist = strdup(plist_base); 106 char *plist = strdup(plist_base);
105 xmlDocPtr plist_xml = xmlParseMemory(plist, strlen(plist)); 107 xmlDocPtr plist_xml = xmlParseMemory(plist, strlen(plist));
106 108
107 if (!plist_xml) 109 if (!plist_xml)
108 return NULL; 110 return NULL;
109 111
110 free(plist); 112 free(plist);
111 113
112 return plist_xml; 114 return plist_xml;
113} 115}
114 116
115static void node_to_xml(GNode * node, gpointer xml_struct) 117static void node_to_xml(GNode * node, gpointer xml_struct)
116{ 118{
117 struct xml_node *xstruct = NULL; 119 struct xml_node *xstruct = NULL;
118 plist_data_t node_data = NULL; 120 plist_data_t node_data = NULL;
119 121
120 xmlNodePtr child_node = NULL; 122 xmlNodePtr child_node = NULL;
121 char isStruct = FALSE; 123 char isStruct = FALSE;
122 124
123 const xmlChar *tag = NULL; 125 const xmlChar *tag = NULL;
124 gchar *val = NULL; 126 gchar *val = NULL;
125 127
126 //for base64 128 //for base64
127 gchar *valtmp = NULL; 129 gchar *valtmp = NULL;
128 130
129 uint32_t i = 0; 131 uint32_t i = 0;
130 132
131 if (!node) 133 if (!node)
132 return; 134 return;
133 135
134 xstruct = (struct xml_node *) xml_struct; 136 xstruct = (struct xml_node *) xml_struct;
135 node_data = plist_get_data(node); 137 node_data = plist_get_data(node);
136 138
137 switch (node_data->type) { 139 switch (node_data->type)
138 case PLIST_BOOLEAN: 140 {
139 { 141 case PLIST_BOOLEAN:
140 if (node_data->boolval) 142 {
141 tag = XPLIST_TRUE; 143 if (node_data->boolval)
142 else 144 tag = XPLIST_TRUE;
143 tag = XPLIST_FALSE; 145 else
144 } 146 tag = XPLIST_FALSE;
145 break; 147 }
146 148 break;
147 case PLIST_UINT: 149
148 tag = XPLIST_INT; 150 case PLIST_UINT:
149 val = g_strdup_printf("%llu", node_data->intval); 151 tag = XPLIST_INT;
150 break; 152 val = g_strdup_printf("%llu", node_data->intval);
151 153 break;
152 case PLIST_REAL: 154
153 tag = XPLIST_REAL; 155 case PLIST_REAL:
154 val = g_strdup_printf("%f", node_data->realval); 156 tag = XPLIST_REAL;
155 break; 157 val = g_strdup_printf("%f", node_data->realval);
156 158 break;
157 case PLIST_STRING: 159
158 tag = XPLIST_STRING; 160 case PLIST_STRING:
159 val = g_strdup(node_data->strval); 161 tag = XPLIST_STRING;
160 break; 162 val = g_strdup(node_data->strval);
161 163 break;
162 case PLIST_KEY: 164
163 tag = XPLIST_KEY; 165 case PLIST_KEY:
164 val = g_strdup((gchar *) node_data->strval); 166 tag = XPLIST_KEY;
165 break; 167 val = g_strdup((gchar *) node_data->strval);
166 168 break;
167 case PLIST_DATA: 169
168 tag = XPLIST_DATA; 170 case PLIST_DATA:
169 if (node_data->length) { 171 tag = XPLIST_DATA;
170 valtmp = g_base64_encode(node_data->buff, node_data->length); 172 if (node_data->length)
171 val = format_string(valtmp, 60, xstruct->depth); 173 {
172 g_free(valtmp); 174 valtmp = g_base64_encode(node_data->buff, node_data->length);
173 } 175 val = format_string(valtmp, 60, xstruct->depth);
174 break; 176 g_free(valtmp);
175 case PLIST_ARRAY: 177 }
176 tag = XPLIST_ARRAY; 178 break;
177 isStruct = TRUE; 179 case PLIST_ARRAY:
178 break; 180 tag = XPLIST_ARRAY;
179 case PLIST_DICT: 181 isStruct = TRUE;
180 tag = XPLIST_DICT; 182 break;
181 isStruct = TRUE; 183 case PLIST_DICT:
182 break; 184 tag = XPLIST_DICT;
183 case PLIST_DATE: 185 isStruct = TRUE;
184 tag = XPLIST_DATE; 186 break;
185 val = g_time_val_to_iso8601(&node_data->timeval); 187 case PLIST_DATE:
186 break; 188 tag = XPLIST_DATE;
187 default: 189 val = g_time_val_to_iso8601(&node_data->timeval);
188 break; 190 break;
189 } 191 default:
190 192 break;
191 for (i = 0; i < xstruct->depth; i++) { 193 }
192 xmlNodeAddContent(xstruct->xml, BAD_CAST("\t")); 194
193 } 195 for (i = 0; i < xstruct->depth; i++)
194 child_node = xmlNewChild(xstruct->xml, NULL, tag, BAD_CAST(val)); 196 {
195 xmlNodeAddContent(xstruct->xml, BAD_CAST("\n")); 197 xmlNodeAddContent(xstruct->xml, BAD_CAST("\t"));
196 g_free(val); 198 }
197 199 child_node = xmlNewChild(xstruct->xml, NULL, tag, BAD_CAST(val));
198 //add return for structured types 200 xmlNodeAddContent(xstruct->xml, BAD_CAST("\n"));
199 if (node_data->type == PLIST_ARRAY || node_data->type == PLIST_DICT) 201 g_free(val);
200 xmlNodeAddContent(child_node, BAD_CAST("\n")); 202
201 203 //add return for structured types
202 if (isStruct) { 204 if (node_data->type == PLIST_ARRAY || node_data->type == PLIST_DICT)
203 struct xml_node child = { child_node, xstruct->depth + 1 }; 205 xmlNodeAddContent(child_node, BAD_CAST("\n"));
204 g_node_children_foreach(node, G_TRAVERSE_ALL, node_to_xml, &child); 206
205 } 207 if (isStruct)
206 //fix indent for structured types 208 {
207 if (node_data->type == PLIST_ARRAY || node_data->type == PLIST_DICT) { 209 struct xml_node child = { child_node, xstruct->depth + 1 };
208 210 g_node_children_foreach(node, G_TRAVERSE_ALL, node_to_xml, &child);
209 for (i = 0; i < xstruct->depth; i++) { 211 }
210 xmlNodeAddContent(child_node, BAD_CAST("\t")); 212 //fix indent for structured types
211 } 213 if (node_data->type == PLIST_ARRAY || node_data->type == PLIST_DICT)
212 } 214 {
213 215
214 return; 216 for (i = 0; i < xstruct->depth; i++)
217 {
218 xmlNodeAddContent(child_node, BAD_CAST("\t"));
219 }
220 }
221
222 return;
215} 223}
216 224
217static void xml_to_node(xmlNodePtr xml_node, plist_t * plist_node) 225static void xml_to_node(xmlNodePtr xml_node, plist_t * plist_node)
218{ 226{
219 xmlNodePtr node = NULL; 227 xmlNodePtr node = NULL;
220 plist_data_t data = NULL; 228 plist_data_t data = NULL;
221 plist_t subnode = NULL; 229 plist_t subnode = NULL;
222 230
223 //for string 231 //for string
224 glong len = 0; 232 glong len = 0;
225 int type = 0; 233 int type = 0;
226 234
227 if (!xml_node) 235 if (!xml_node)
228 return; 236 return;
229 237
230 for (node = xml_node->children; node; node = node->next) { 238 for (node = xml_node->children; node; node = node->next)
231 239 {
232 while (node && !xmlStrcmp(node->name, XPLIST_TEXT)) 240
233 node = node->next; 241 while (node && !xmlStrcmp(node->name, XPLIST_TEXT))
234 if (!node) 242 node = node->next;
235 break; 243 if (!node)
236 244 break;
237 data = plist_new_plist_data(); 245
238 subnode = plist_new_node(data); 246 data = plist_new_plist_data();
239 if (*plist_node) 247 subnode = plist_new_node(data);
240 g_node_append(*plist_node, subnode); 248 if (*plist_node)
241 else 249 g_node_append(*plist_node, subnode);
242 *plist_node = subnode; 250 else
243 251 *plist_node = subnode;
244 if (!xmlStrcmp(node->name, XPLIST_TRUE)) { 252
245 data->boolval = TRUE; 253 if (!xmlStrcmp(node->name, XPLIST_TRUE))
246 data->type = PLIST_BOOLEAN; 254 {
247 data->length = 1; 255 data->boolval = TRUE;
248 continue; 256 data->type = PLIST_BOOLEAN;
249 } 257 data->length = 1;
250 258 continue;
251 if (!xmlStrcmp(node->name, XPLIST_FALSE)) { 259 }
252 data->boolval = FALSE; 260
253 data->type = PLIST_BOOLEAN; 261 if (!xmlStrcmp(node->name, XPLIST_FALSE))
254 data->length = 1; 262 {
255 continue; 263 data->boolval = FALSE;
256 } 264 data->type = PLIST_BOOLEAN;
257 265 data->length = 1;
258 if (!xmlStrcmp(node->name, XPLIST_INT)) { 266 continue;
259 xmlChar *strval = xmlNodeGetContent(node); 267 }
260 data->intval = g_ascii_strtoull((char *) strval, NULL, 0); 268
261 data->type = PLIST_UINT; 269 if (!xmlStrcmp(node->name, XPLIST_INT))
262 data->length = 8; 270 {
263 xmlFree(strval); 271 xmlChar *strval = xmlNodeGetContent(node);
264 continue; 272 data->intval = g_ascii_strtoull((char *) strval, NULL, 0);
265 } 273 data->type = PLIST_UINT;
266 274 data->length = 8;
267 if (!xmlStrcmp(node->name, XPLIST_REAL)) { 275 xmlFree(strval);
268 xmlChar *strval = xmlNodeGetContent(node); 276 continue;
269 data->realval = atof((char *) strval); 277 }
270 data->type = PLIST_REAL; 278
271 data->length = 8; 279 if (!xmlStrcmp(node->name, XPLIST_REAL))
272 xmlFree(strval); 280 {
273 continue; 281 xmlChar *strval = xmlNodeGetContent(node);
274 } 282 data->realval = atof((char *) strval);
275 283 data->type = PLIST_REAL;
276 if (!xmlStrcmp(node->name, XPLIST_DATE)) { 284 data->length = 8;
277 xmlChar *strval = xmlNodeGetContent(node); 285 xmlFree(strval);
278 g_time_val_from_iso8601((char *) strval, &data->timeval); 286 continue;
279 data->type = PLIST_DATE; 287 }
280 data->length = sizeof(GTimeVal); 288
281 xmlFree(strval); 289 if (!xmlStrcmp(node->name, XPLIST_DATE))
282 continue; 290 {
283 } 291 xmlChar *strval = xmlNodeGetContent(node);
284 292 g_time_val_from_iso8601((char *) strval, &data->timeval);
285 if (!xmlStrcmp(node->name, XPLIST_STRING)) { 293 data->type = PLIST_DATE;
286 xmlChar *strval = xmlNodeGetContent(node); 294 data->length = sizeof(GTimeVal);
287 len = strlen((char *) strval); 295 xmlFree(strval);
288 type = xmlDetectCharEncoding(strval, len); 296 continue;
289 297 }
290 if (XML_CHAR_ENCODING_UTF8 == type || XML_CHAR_ENCODING_ASCII == type || XML_CHAR_ENCODING_NONE == type) { 298
291 data->strval = strdup((char *) strval); 299 if (!xmlStrcmp(node->name, XPLIST_STRING))
292 data->type = PLIST_STRING; 300 {
293 data->length = strlen(data->strval); 301 xmlChar *strval = xmlNodeGetContent(node);
294 } 302 len = strlen((char *) strval);
295 xmlFree(strval); 303 type = xmlDetectCharEncoding(strval, len);
296 continue; 304
297 } 305 if (XML_CHAR_ENCODING_UTF8 == type || XML_CHAR_ENCODING_ASCII == type || XML_CHAR_ENCODING_NONE == type)
298 306 {
299 if (!xmlStrcmp(node->name, XPLIST_KEY)) { 307 data->strval = strdup((char *) strval);
300 xmlChar *strval = xmlNodeGetContent(node); 308 data->type = PLIST_STRING;
301 data->strval = strdup((char *) strval); 309 data->length = strlen(data->strval);
302 data->type = PLIST_KEY; 310 }
303 data->length = strlen(data->strval); 311 xmlFree(strval);
304 xmlFree(strval); 312 continue;
305 continue; 313 }
306 } 314
307 315 if (!xmlStrcmp(node->name, XPLIST_KEY))
308 if (!xmlStrcmp(node->name, XPLIST_DATA)) { 316 {
309 xmlChar *strval = xmlNodeGetContent(node); 317 xmlChar *strval = xmlNodeGetContent(node);
310 gsize size = 0; 318 data->strval = strdup((char *) strval);
311 guchar *dec = g_base64_decode((char *) strval, &size); 319 data->type = PLIST_KEY;
312 data->buff = (uint8_t *) malloc(size * sizeof(uint8_t)); 320 data->length = strlen(data->strval);
313 memcpy(data->buff, dec, size * sizeof(uint8_t)); 321 xmlFree(strval);
314 g_free(dec); 322 continue;
315 data->length = size; 323 }
316 data->type = PLIST_DATA; 324
317 xmlFree(strval); 325 if (!xmlStrcmp(node->name, XPLIST_DATA))
318 continue; 326 {
319 } 327 xmlChar *strval = xmlNodeGetContent(node);
320 328 gsize size = 0;
321 if (!xmlStrcmp(node->name, XPLIST_ARRAY)) { 329 guchar *dec = g_base64_decode((char *) strval, &size);
322 data->type = PLIST_ARRAY; 330 data->buff = (uint8_t *) malloc(size * sizeof(uint8_t));
323 xml_to_node(node, &subnode); 331 memcpy(data->buff, dec, size * sizeof(uint8_t));
324 continue; 332 g_free(dec);
325 } 333 data->length = size;
326 334 data->type = PLIST_DATA;
327 if (!xmlStrcmp(node->name, XPLIST_DICT)) { 335 xmlFree(strval);
328 data->type = PLIST_DICT; 336 continue;
329 xml_to_node(node, &subnode); 337 }
330 continue; 338
331 } 339 if (!xmlStrcmp(node->name, XPLIST_ARRAY))
332 } 340 {
341 data->type = PLIST_ARRAY;
342 xml_to_node(node, &subnode);
343 continue;
344 }
345
346 if (!xmlStrcmp(node->name, XPLIST_DICT))
347 {
348 data->type = PLIST_DICT;
349 xml_to_node(node, &subnode);
350 continue;
351 }
352 }
333} 353}
334 354
335void plist_to_xml(plist_t plist, char **plist_xml, uint32_t * length) 355void plist_to_xml(plist_t plist, char **plist_xml, uint32_t * length)
336{ 356{
337 xmlDocPtr plist_doc = NULL; 357 xmlDocPtr plist_doc = NULL;
338 xmlNodePtr root_node = NULL; 358 xmlNodePtr root_node = NULL;
339 struct xml_node root = { NULL, 0 }; 359 struct xml_node root = { NULL, 0 };
340 int size = 0; 360 int size = 0;
341 361
342 if (!plist || !plist_xml || *plist_xml) 362 if (!plist || !plist_xml || *plist_xml)
343 return; 363 return;
344 plist_doc = new_xml_plist(); 364 plist_doc = new_xml_plist();
345 root_node = xmlDocGetRootElement(plist_doc); 365 root_node = xmlDocGetRootElement(plist_doc);
346 root.xml = root_node; 366 root.xml = root_node;
347 367
348 node_to_xml(plist, &root); 368 node_to_xml(plist, &root);
349 369
350 xmlDocDumpMemory(plist_doc, (xmlChar **) plist_xml, &size); 370 xmlDocDumpMemory(plist_doc, (xmlChar **) plist_xml, &size);
351 if (size >= 0) 371 if (size >= 0)
352 *length = size; 372 *length = size;
353 xmlFreeDoc(plist_doc); 373 xmlFreeDoc(plist_doc);
354} 374}
355 375
356void plist_from_xml(const char *plist_xml, uint32_t length, plist_t * plist) 376void plist_from_xml(const char *plist_xml, uint32_t length, plist_t * plist)
357{ 377{
358 xmlDocPtr plist_doc = xmlParseMemory(plist_xml, length); 378 xmlDocPtr plist_doc = xmlParseMemory(plist_xml, length);
359 xmlNodePtr root_node = xmlDocGetRootElement(plist_doc); 379 xmlNodePtr root_node = xmlDocGetRootElement(plist_doc);
360 380
361 xml_to_node(root_node, plist); 381 xml_to_node(root_node, plist);
362 xmlFreeDoc(plist_doc); 382 xmlFreeDoc(plist_doc);
363} 383}