summaryrefslogtreecommitdiffstats
path: root/common/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/utils.c')
-rw-r--r--common/utils.c195
1 files changed, 195 insertions, 0 deletions
diff --git a/common/utils.c b/common/utils.c
index 68b23b9..aa0332d 100644
--- a/common/utils.c
+++ b/common/utils.c
@@ -27,6 +27,8 @@
27#include <stdlib.h> 27#include <stdlib.h>
28#include <string.h> 28#include <string.h>
29#include <time.h> 29#include <time.h>
30#include <sys/time.h>
31#include <inttypes.h>
30 32
31#include "utils.h" 33#include "utils.h"
32 34
@@ -222,3 +224,196 @@ int plist_write_to_filename(plist_t plist, const char *filename, enum plist_form
222 224
223 return 1; 225 return 1;
224} 226}
227
228static const char base64_str[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
229static const char base64_pad = '=';
230
231static char *base64encode(const unsigned char *buf, size_t size)
232{
233 if (!buf || !(size > 0)) return NULL;
234 int outlen = (size / 3) * 4;
235 char *outbuf = (char*)malloc(outlen+5); // 4 spare bytes + 1 for '\0'
236 size_t n = 0;
237 size_t m = 0;
238 unsigned char input[3];
239 unsigned int output[4];
240 while (n < size) {
241 input[0] = buf[n];
242 input[1] = (n+1 < size) ? buf[n+1] : 0;
243 input[2] = (n+2 < size) ? buf[n+2] : 0;
244 output[0] = input[0] >> 2;
245 output[1] = ((input[0] & 3) << 4) + (input[1] >> 4);
246 output[2] = ((input[1] & 15) << 2) + (input[2] >> 6);
247 output[3] = input[2] & 63;
248 outbuf[m++] = base64_str[(int)output[0]];
249 outbuf[m++] = base64_str[(int)output[1]];
250 outbuf[m++] = (n+1 < size) ? base64_str[(int)output[2]] : base64_pad;
251 outbuf[m++] = (n+2 < size) ? base64_str[(int)output[3]] : base64_pad;
252 n+=3;
253 }
254 outbuf[m] = 0; // 0-termination!
255 return outbuf;
256}
257
258static void plist_node_print_to_stream(plist_t node, int* indent_level, FILE* stream);
259
260static void plist_array_print_to_stream(plist_t node, int* indent_level, FILE* stream)
261{
262 /* iterate over items */
263 int i, count;
264 plist_t subnode = NULL;
265
266 count = plist_array_get_size(node);
267
268 for (i = 0; i < count; i++) {
269 subnode = plist_array_get_item(node, i);
270 fprintf(stream, "%*s", *indent_level, "");
271 fprintf(stream, "%d: ", i);
272 plist_node_print_to_stream(subnode, indent_level, stream);
273 }
274}
275
276static void plist_dict_print_to_stream(plist_t node, int* indent_level, FILE* stream)
277{
278 /* iterate over key/value pairs */
279 plist_dict_iter it = NULL;
280
281 char* key = NULL;
282 plist_t subnode = NULL;
283 plist_dict_new_iter(node, &it);
284 plist_dict_next_item(node, it, &key, &subnode);
285 while (subnode)
286 {
287 fprintf(stream, "%*s", *indent_level, "");
288 fprintf(stream, "%s", key);
289 if (plist_get_node_type(subnode) == PLIST_ARRAY)
290 fprintf(stream, "[%d]: ", plist_array_get_size(subnode));
291 else
292 fprintf(stream, ": ");
293 free(key);
294 key = NULL;
295 plist_node_print_to_stream(subnode, indent_level, stream);
296 plist_dict_next_item(node, it, &key, &subnode);
297 }
298 free(it);
299}
300
301static void plist_node_print_to_stream(plist_t node, int* indent_level, FILE* stream)
302{
303 char *s = NULL;
304 char *data = NULL;
305 double d;
306 uint8_t b;
307 uint64_t u = 0;
308 struct timeval tv = { 0, 0 };
309
310 plist_type t;
311
312 if (!node)
313 return;
314
315 t = plist_get_node_type(node);
316
317 switch (t) {
318 case PLIST_BOOLEAN:
319 plist_get_bool_val(node, &b);
320 fprintf(stream, "%s\n", (b ? "true" : "false"));
321 break;
322
323 case PLIST_UINT:
324 plist_get_uint_val(node, &u);
325 fprintf(stream, "%"PRIu64"\n", (long long)u);
326 break;
327
328 case PLIST_REAL:
329 plist_get_real_val(node, &d);
330 fprintf(stream, "%f\n", d);
331 break;
332
333 case PLIST_STRING:
334 plist_get_string_val(node, &s);
335 fprintf(stream, "%s\n", s);
336 free(s);
337 break;
338
339 case PLIST_KEY:
340 plist_get_key_val(node, &s);
341 fprintf(stream, "%s: ", s);
342 free(s);
343 break;
344
345 case PLIST_DATA:
346 plist_get_data_val(node, &data, &u);
347 if (u > 0) {
348 s = base64encode((unsigned char*)data, u);
349 free(data);
350 if (s) {
351 fprintf(stream, "%s\n", s);
352 free(s);
353 } else {
354 fprintf(stream, "\n");
355 }
356 } else {
357 fprintf(stream, "\n");
358 }
359 break;
360
361 case PLIST_DATE:
362 plist_get_date_val(node, (int32_t*)&tv.tv_sec, (int32_t*)&tv.tv_usec);
363 {
364 time_t ti = (time_t)tv.tv_sec;
365 struct tm *btime = localtime(&ti);
366 if (btime) {
367 s = (char*)malloc(24);
368 memset(s, 0, 24);
369 if (strftime(s, 24, "%Y-%m-%dT%H:%M:%SZ", btime) <= 0) {
370 free (s);
371 s = NULL;
372 }
373 }
374 }
375 if (s) {
376 fprintf(stream, "%s\n", s);
377 free(s);
378 } else {
379 fprintf(stream, "\n");
380 }
381 break;
382
383 case PLIST_ARRAY:
384 fprintf(stream, "\n");
385 (*indent_level)++;
386 plist_array_print_to_stream(node, indent_level, stream);
387 (*indent_level)--;
388 break;
389
390 case PLIST_DICT:
391 fprintf(stream, "\n");
392 (*indent_level)++;
393 plist_dict_print_to_stream(node, indent_level, stream);
394 (*indent_level)--;
395 break;
396
397 default:
398 break;
399 }
400}
401
402void plist_print_to_stream(plist_t plist, FILE* stream)
403{
404 int indent = 0;
405
406 if (!plist || !stream)
407 return;
408
409 switch (plist_get_node_type(plist)) {
410 case PLIST_DICT:
411 plist_dict_print_to_stream(plist, &indent, stream);
412 break;
413 case PLIST_ARRAY:
414 plist_array_print_to_stream(plist, &indent, stream);
415 break;
416 default:
417 plist_node_print_to_stream(plist, &indent, stream);
418 }
419}