Line data Source code
1 : /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 : /*
3 : * packing.c
4 : * This file is part of "Sauvegarde" project.
5 : *
6 : * (C) Copyright 2014 - 2016 Olivier Delhomme
7 : * e-mail : olivier.delhomme@free.fr
8 : *
9 : * "Sauvegarde" is free software: you can redistribute it and/or modify
10 : * it under the terms of the GNU General Public License as published by
11 : * the Free Software Foundation, either version 3 of the License, or
12 : * (at your option) any later version.
13 : *
14 : * "Sauvegarde" is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with "Sauvegarde". If not, see <http://www.gnu.org/licenses/>
21 : */
22 :
23 : /**
24 : * @file packing.c
25 : * This file contains the functions to pack messages for all the
26 : * programs of "Sauvegarde" project.
27 : */
28 :
29 : #include "libcdpfgl.h"
30 :
31 : static void insert_guint8_into_json_root(json_t *root, gchar *keyname, guint8 number);
32 : static void insert_guint32_into_json_root(json_t *root, gchar *keyname, guint32 number);
33 : static void insert_guint64_into_json_root(json_t *root, gchar *keyname, guint64 number);
34 :
35 :
36 : /**
37 : * Inserts a json_t *value into the json_t *root array.
38 : * @param[in,out] root is the root that will contain all meta data values
39 : * @param keyname is the keyname associated with the value (in fact it is
40 : * variable's name)
41 : * @param value is the json_t "encoded" value to insert into the root
42 : */
43 1627067 : void insert_json_value_into_json_root(json_t *root, gchar *keyname, json_t *value)
44 : {
45 1627067 : int result = 0;
46 :
47 1627067 : if (root != NULL && keyname != NULL && value != NULL)
48 : {
49 1627067 : result = json_object_set_new(root, keyname, value);
50 :
51 1627067 : if (result != JANSSON_SUCCESS)
52 : {
53 0 : print_error( __FILE__, __LINE__, _("Error while converting to JSON\n"));
54 0 : exit(EXIT_FAILURE); /* An error here means that we will do nothing good */
55 : }
56 : }
57 1627067 : }
58 :
59 :
60 : /**
61 : * appends a string into the array (the array is ordered and should
62 : * not mess itself)
63 : * @param[in,out] array is an array of strings (may be hashs of filenames
64 : * for instance.
65 : * @param to_append is the string to be appended to the array
66 : */
67 754389 : void append_string_to_array(json_t *array, gchar *to_append)
68 : {
69 754389 : json_t *string = NULL;
70 :
71 754389 : if (array != NULL && to_append != NULL)
72 : {
73 754389 : string = json_string_nocheck((const char *) to_append);
74 :
75 754389 : json_array_append_new(array, string);
76 : }
77 754389 : }
78 :
79 :
80 : /**
81 : * Inserts the boolean data_sent into the json tree root with key keyname.
82 : * @param[in,out] root is the main json tree
83 : * @param keyname is the key for which we will insert a new value
84 : * @param data_sent is the boolean value to be inserted with key keyname.
85 : */
86 49745 : void insert_boolean_into_json_root(json_t *root, gchar *keyname, gboolean data_sent)
87 : {
88 49745 : json_t *bool = NULL;
89 :
90 49745 : if (root != NULL && keyname != NULL)
91 : {
92 49745 : if (data_sent == TRUE)
93 : {
94 3 : bool = json_true();
95 : }
96 : else
97 : {
98 49742 : bool = json_false();
99 : }
100 :
101 49745 : insert_json_value_into_json_root(root, keyname, bool);
102 : }
103 49745 : }
104 :
105 :
106 :
107 :
108 : /**
109 : * Inserts the string a_string into the json tree root with key keyname.
110 : * @param[in,out] root is the main json tree
111 : * @param keyname is the key for which we will insert a new value
112 : * @param a_string is the value to be inserted with key keyname.
113 : */
114 707081 : void insert_string_into_json_root(json_t *root, gchar *keyname, gchar *a_string)
115 : {
116 707081 : json_t *str = NULL;
117 :
118 707081 : if (root != NULL && keyname != NULL && a_string != NULL)
119 : {
120 707081 : str = json_string_nocheck((const char *) a_string);
121 707081 : insert_json_value_into_json_root(root, keyname, str);
122 : }
123 707081 : }
124 :
125 :
126 : /**
127 : * Inserts the guint8 number into the json tree root with key keyname.
128 : * @param[in,out] root is the main json tree
129 : * @param keyname is the key for which we will insert a new value
130 : * @param number is the value to be inserted with key keyname.
131 : */
132 99490 : static void insert_guint8_into_json_root(json_t *root, gchar *keyname, guint8 number)
133 : {
134 99490 : json_t *value = NULL;
135 :
136 99490 : if (root != NULL && keyname != NULL)
137 : {
138 99490 : value = json_integer(number);
139 99490 : insert_json_value_into_json_root(root, keyname, value);
140 : }
141 99490 : }
142 :
143 :
144 : /**
145 : * Inserts the guint32 number into the json tree root with key keyname.
146 : * @param[in,out] root is the main json tree
147 : * @param keyname is the key for which we will insert a new value
148 : * @param number is the value to be inserted with key keyname.
149 : */
150 149235 : static void insert_guint32_into_json_root(json_t *root, gchar *keyname, guint32 number)
151 : {
152 149235 : json_t *value = NULL;
153 :
154 149235 : if (root != NULL && keyname != NULL)
155 : {
156 149235 : value = json_integer(number);
157 149235 : insert_json_value_into_json_root(root, keyname, value);
158 : }
159 149235 : }
160 :
161 :
162 : /**
163 : * Inserts the guint64 number into the json tree root with key keyname.
164 : * @param[in,out] root is the main json tree
165 : * @param keyname is the key for which we will insert a new value
166 : * @param number is the value to be inserted with key keyname.
167 : */
168 477903 : static void insert_guint64_into_json_root(json_t *root, gchar *keyname, guint64 number)
169 : {
170 477903 : json_t *value = NULL;
171 :
172 477903 : if (root != NULL && keyname != NULL)
173 : {
174 477903 : value = json_integer(number);
175 477903 : insert_json_value_into_json_root(root, keyname, value);
176 : }
177 477903 : }
178 :
179 :
180 : /**
181 : * Converts the hash list to a json_t * array
182 : * @param hash_list : the GList * list of hashs
183 : * @returns a json_t * array with the element of the list in it (if any).
184 : */
185 99487 : json_t *convert_hash_list_to_json(GList *hash_list)
186 : {
187 99487 : json_t *array = NULL; /** json_t *array is the array that will receive base64 encoded hashs */
188 99487 : gchar *encoded_hash = NULL; /** gchar encoded_hash is an hash base64 encoded */
189 99487 : GList *head = NULL; /** GSList *head is a list to iter over that will contain the hash data list */
190 99487 : hash_data_t *hash_data = NULL; /** A pointer to get the hash_data structure */
191 :
192 : /* creating an array with the whole hash list */
193 99487 : array = json_array();
194 99487 : head = hash_list;
195 :
196 953363 : while (head != NULL)
197 : {
198 754389 : hash_data = head->data;
199 754389 : encoded_hash = g_base64_encode(hash_data->hash, HASH_LEN);
200 :
201 754389 : append_string_to_array(array, encoded_hash);
202 :
203 754389 : free_variable(encoded_hash);
204 :
205 754389 : head = g_list_next(head);
206 : }
207 :
208 99487 : return array;
209 : }
210 :
211 :
212 : /**
213 : * Converts the file list (a list of gchar *) to a json_t * array
214 : * @param file_list : the GSList * list of hashs
215 : * @returns a json_t * array with the element of the list in it (if any).
216 : */
217 0 : json_t *convert_file_list_to_json(GSList *file_list)
218 : {
219 0 : json_t *array = NULL; /** json_t *array is the array that will receive base64 encoded hashs */
220 0 : GSList *head = NULL; /** GSList *head is a list to iter over that will contain the hash list */
221 :
222 : /* creating an array with the whole hash list */
223 0 : array = json_array();
224 0 : head = file_list;
225 :
226 0 : while (head != NULL)
227 : {
228 0 : append_string_to_array(array, head->data);
229 :
230 0 : head = g_slist_next(head);
231 : }
232 :
233 0 : return array;
234 : }
235 :
236 :
237 : /**
238 : * Converts the file list (a list of gchar *) to a json string
239 : * @param file_list : the GSList * list of hashs
240 : * @returns a gchar * string json formatted with all files (if any) in a
241 : * json array
242 : */
243 0 : gchar *convert_file_list_to_json_string(GSList *file_list)
244 : {
245 0 : json_t *array = NULL;
246 0 : json_t *root = NULL;
247 0 : gchar *string = NULL;
248 :
249 0 : root = json_object();
250 :
251 0 : array = convert_file_list_to_json(file_list);
252 :
253 0 : insert_json_value_into_json_root(root, "file_list", array);
254 :
255 0 : string = json_dumps(root, 0);
256 :
257 0 : json_decref(array);
258 0 : json_decref(root);
259 :
260 0 : return string;
261 : }
262 :
263 :
264 : /**
265 : * Converts hash_data_t structure to a json_t * structure
266 : * @param hash_data the hash_data_t structure that contains the data to
267 : * be converted.
268 : * @returns a json_t * structure with informations of hash_data in it
269 : */
270 229178 : json_t *convert_hash_data_t_to_json(hash_data_t *hash_data)
271 : {
272 229178 : gchar *encoded_data = NULL;
273 229178 : gchar *encoded_hash = NULL;
274 229178 : json_t *root = NULL;
275 :
276 229178 : if (hash_data != NULL && hash_data->data != NULL && hash_data->hash != NULL && hash_data->read >= 0)
277 : {
278 229178 : encoded_data = g_base64_encode((guchar*) hash_data->data, hash_data->read);
279 229178 : encoded_hash = g_base64_encode((guchar*) hash_data->hash, HASH_LEN);
280 :
281 229178 : root = json_object();
282 229178 : insert_string_into_json_root(root, "hash", encoded_hash);
283 229178 : insert_string_into_json_root(root, "data", encoded_data);
284 229178 : insert_guint64_into_json_root(root, "size", hash_data->read);
285 229178 : free_variable(encoded_data);
286 229178 : free_variable(encoded_hash);
287 : }
288 :
289 229178 : return root;
290 : }
291 :
292 :
293 : /**
294 : * Converts hash_data_t structure to a json formatted string.
295 : * @param hash_data the hash_data_t structure that contains the data to
296 : * be converted.
297 : * @returns a json formatted string with those informations
298 : */
299 3017 : gchar *convert_hash_data_t_to_string(hash_data_t *hash_data)
300 : {
301 3017 : gchar *json_str = NULL;
302 3017 : json_t *root = NULL;
303 :
304 3017 : root = convert_hash_data_t_to_json(hash_data);
305 :
306 3017 : if (root != NULL)
307 : {
308 3017 : json_str = json_dumps(root, 0);
309 3017 : json_decref(root);
310 : }
311 :
312 3017 : return json_str;
313 : }
314 :
315 :
316 :
317 : /**
318 : * This function should return a JSON object with all informations from
319 : * the meta_data_t structure.
320 : * @param meta is the structure that contains all meta data for a file or
321 : * a directory.
322 : * @param hostname is the name of the host onw hich we are running and that
323 : * we want to include into the json string.
324 : * @param data_sent is a boolean that is TRUE when data has already been
325 : * sent to server, FALSE otherwise.
326 : * @returns a json_t structure or NULL
327 : */
328 49745 : json_t *convert_meta_data_to_json(meta_data_t *meta, const gchar *hostname, gboolean data_sent)
329 : {
330 49745 : json_t *root = NULL; /** json_t *root is the root that will contain all meta data json */
331 49745 : json_t *array = NULL; /** json_t *array is the array that will receive base64 encoded hashs */
332 :
333 49745 : if (meta != NULL)
334 : {
335 49745 : root = json_object();
336 :
337 49745 : insert_guint8_into_json_root(root, "msg_id", ENC_META_DATA);
338 49745 : insert_guint8_into_json_root(root, "filetype", meta->file_type);
339 49745 : insert_guint32_into_json_root(root, "mode", meta->mode);
340 :
341 49745 : insert_guint64_into_json_root(root, "atime", meta->atime);
342 49745 : insert_guint64_into_json_root(root, "ctime", meta->ctime);
343 49745 : insert_guint64_into_json_root(root, "mtime", meta->mtime);
344 49745 : insert_guint64_into_json_root(root, "fsize", meta->size);
345 49745 : insert_guint64_into_json_root(root, "inode", meta->inode);
346 :
347 49745 : insert_string_into_json_root(root, "owner", meta->owner);
348 49745 : insert_string_into_json_root(root, "group", meta->group);
349 :
350 49745 : insert_guint32_into_json_root(root, "uid", meta->uid);
351 49745 : insert_guint32_into_json_root(root, "gid", meta->uid);
352 :
353 49745 : insert_string_into_json_root(root, "name", meta->name);
354 49745 : insert_string_into_json_root(root, "link", meta->link);
355 49745 : insert_string_into_json_root(root, "hostname", (gchar *) hostname);
356 49745 : insert_boolean_into_json_root(root, "data_sent", data_sent);
357 :
358 49745 : array = convert_hash_list_to_json(meta->hash_data_list);
359 :
360 49745 : insert_json_value_into_json_root(root, "hash_list", array);
361 : }
362 :
363 49745 : return root;
364 : }
365 :
366 :
367 : /**
368 : * This function should return a JSON string with all informations from
369 : * the meta_data_t structure.
370 : * @param meta is the structure that contains all meta data for a file or
371 : * a directory.
372 : * @param hostname is the name of the host onw hich we are running and that
373 : * we want to include into the json string.
374 : * @param data_sent is a boolean that is TRUE when data has already been
375 : * sent to server, FALSE otherwise.
376 : * @returns a JSON formated string or NULL
377 : */
378 49745 : gchar *convert_meta_data_to_json_string(meta_data_t *meta, const gchar *hostname, gboolean data_sent)
379 : {
380 49745 : json_t *root = NULL; /** json_t *root is the root that will contain all meta data json */
381 49745 : gchar *json_str = NULL; /** gchar *json_str is the string to be returned at the end */
382 :
383 :
384 49745 : if (meta != NULL)
385 : {
386 49745 : root = convert_meta_data_to_json(meta, hostname, data_sent);
387 49745 : json_str = json_dumps(root, 0);
388 49745 : json_decref(root);
389 : }
390 :
391 49745 : return json_str;
392 : }
393 :
394 :
395 : /**
396 : * Converts to a json gchar * string. Used only by server's program
397 : * @param name : name of the program of which we want to print the version.
398 : * @param date : publication date of this version
399 : * @param version : version of the program.
400 : * @param authors : authors that contributed to this program
401 : * @param license : license in use for this program and its sources
402 : * @returns a newlly allocated gchar * string in json format that can be
403 : * freed when no longer needed.
404 : */
405 0 : gchar *convert_version_to_json(gchar *name, gchar *date, gchar *version, gchar *authors, gchar *license)
406 : {
407 0 : json_t *root = NULL; /** json_t *root is the root that will contain all data in json format */
408 0 : json_t *libs = NULL; /** json_t *libs is the array that will contain all libraries and versions */
409 0 : json_t *auths = NULL; /** json_t *auths is the array containing all authors */
410 0 : json_t *objs = NULL; /** json_t *objs will store version of libraries */
411 0 : gchar *buffer = NULL;
412 0 : gchar *json_str = NULL; /** gchar *json_str is the string to be returned at the end */
413 :
414 :
415 0 : root = json_object();
416 :
417 0 : insert_string_into_json_root(root, "name", name);
418 0 : insert_string_into_json_root(root, "date", date);
419 0 : insert_string_into_json_root(root, "version", version);
420 0 : insert_string_into_json_root(root, "revision", REVISION);
421 0 : insert_string_into_json_root(root, "licence", license);
422 :
423 : /**
424 : * @todo use g_strsplit to split authors string if more than one author
425 : * is in the string.
426 : */
427 0 : auths = json_array();
428 0 : json_array_append_new(auths, json_string(authors));
429 0 : insert_json_value_into_json_root(root, "authors", auths);
430 :
431 :
432 :
433 0 : libs = json_array();
434 :
435 : /* glib */
436 0 : buffer = g_strdup_printf("%d.%d.%d", glib_major_version, glib_minor_version, glib_micro_version);
437 0 : objs = json_object();
438 0 : json_object_set_new(objs, "glib", json_string(buffer));
439 0 : json_array_append_new(libs, objs);
440 0 : free_variable(buffer);
441 :
442 : /* libmicrohttpd */
443 0 : buffer = make_MHD_version();
444 0 : objs = json_object();
445 0 : json_object_set_new(objs, "mhd", json_string(buffer));
446 0 : json_array_append_new(libs, objs);
447 0 : free_variable(buffer);
448 :
449 : /* sqlite */
450 0 : buffer = g_strdup_printf("%s", db_version());
451 0 : objs = json_object();
452 0 : json_object_set_new(objs, "sqlite", json_string(buffer));
453 0 : json_array_append_new(libs, objs);
454 0 : free_variable(buffer);
455 :
456 : /* jansson ! */
457 0 : buffer = g_strdup_printf("%d.%d.%d", JANSSON_MAJOR_VERSION, JANSSON_MINOR_VERSION, JANSSON_MICRO_VERSION);
458 0 : objs = json_object();
459 0 : json_object_set_new(objs, "jansson", json_string(buffer));
460 0 : json_array_append_new(libs, objs);
461 0 : free_variable(buffer);
462 :
463 0 : insert_json_value_into_json_root(root, "librairies", libs);
464 :
465 0 : json_str = json_dumps(root, 0);
466 :
467 0 : json_decref(root);
468 :
469 0 : return json_str;
470 :
471 : }
472 :
473 :
474 : /**
475 : * Function that encapsulate a meta_data_t * variable into a capsule_t *
476 : * one. It does not check that meta is not NULL so it may encapsulate a
477 : * NULL pointer !
478 : * @param command is the command to be used with the encapsulated data.
479 : * @param meta is the meta_data_t * variable to be encapsulated
480 : * @returns a capsule_t * with command field set to ENC_META_DATA stating
481 : * that the data field is of type meta_data_t *.
482 : */
483 0 : capsule_t *encapsulate_meta_data_t(gint command, meta_data_t *meta)
484 : {
485 :
486 0 : capsule_t *capsule = NULL;
487 :
488 0 : capsule = (capsule_t *) g_malloc0(sizeof(capsule_t));
489 :
490 0 : capsule->command = command;
491 0 : capsule->data = (void *) meta;
492 :
493 0 : return capsule;
494 : }
495 :
496 :
497 : /**
498 : * Function that encapsulate an END command.
499 : * @returns a capsule_t * with command field set to ENC_END stating
500 : * that this is the end my friend (some famous song) !
501 : */
502 0 : capsule_t *encapsulate_end(void)
503 : {
504 0 : return encapsulate_meta_data_t(ENC_END, NULL);
505 : }
506 :
507 :
|