afm-udb: split read_unit_file
[src/app-framework-main.git] / src / afm-udb.c
index 80cc715..638387e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- Copyright 2015, 2016, 2017 IoT.bzh
+ Copyright (C) 2015-2018 IoT.bzh
 
  author: José Bollo <jose.bollo@iot.bzh>
 
@@ -78,6 +78,11 @@ struct afm_updt {
        struct afm_apps applications;
 };
 
+/*
+ * The default language
+ */
+static char *default_lang;
+
 /*
  * Release the data of the afm_apps object 'apps'.
  */
@@ -112,7 +117,7 @@ static int append_field(
                        array = json_object_new_array();
                        if (!array)
                                goto error;
-                       json_object_array_add(array, item);
+                       json_object_array_add(array, json_object_get(item));
                        json_object_object_add(object, name, array);
                }
                json_object_array_add(array, data);
@@ -224,7 +229,6 @@ static int addunit(
 {
        struct json_object *priv, *pub, *id;
        const char *strid;
-       char *un = NULL;
        size_t len;
 
        /* create the application structure */
@@ -240,26 +244,13 @@ static int addunit(
        len = strlen(unitname);
        assert(len >= (sizeof service_extension - 1));
        assert(!memcmp(&unitname[len - (sizeof service_extension - 1)], service_extension, sizeof service_extension));
-       if (unitname[len - sizeof service_extension] == '@') {
-               char buffer[40];
-               size_t l = (size_t)snprintf(buffer, sizeof buffer, "%d", (int)getuid());
-               un = malloc(len + l + 1);
-               if (!un)
-                       goto error;
-               memcpy(&un[0], unitname, len - (sizeof service_extension - 1));
-               if (l)
-                       memcpy(&un[len - (sizeof service_extension - 1)], buffer, l);
-               memcpy(&un[len - (sizeof service_extension - 1) + l], service_extension, sizeof service_extension);
-       }
 
        /* adds the values */
        if (add_fields_of_content(priv, pub, content, length)
         || add_field(priv, pub, key_unit_path, unitpath)
-        || add_field(priv, pub, key_unit_name, un ? : unitname)
+        || add_field(priv, pub, key_unit_name, unitname)
         || add_field(priv, pub, key_unit_scope, isuser ? scope_user : scope_system))
                goto error;
-       free(un);
-       un = NULL;
 
        /* get the id */
        if (!json_object_object_get_ex(pub, key_id, &id)) {
@@ -278,67 +269,82 @@ static int addunit(
        return 0;
 
 error:
-       free(un);
        json_object_put(pub);
        json_object_put(priv);
        return -1;
 }
 
 /*
- * read a unit file
+ * Crop and trim unit 'content' of 'length'. Return the new length.
  */
-static int read_unit_file(const char *path, char **content, size_t *length)
+static size_t crop_and_trim_unit_content(char *content, size_t length)
 {
-       int rc, st;
+       int st;
        char c, *read, *write;
 
-       /* read the file */
-       rc = getfile(path, content, length);
-       if (rc >= 0) {
-               /* removes any comment and join lines */
-               st = 0;
-               read = write = *content;
-               for (;;) {
-                       do { c = *read++; } while (c == '\r');
-                       if (!c)
+       /* removes any comment and join continued lines */
+       st = 0;
+       read = write = content;
+       for (;;) {
+               do { c = *read++; } while (c == '\r');
+               if (!c)
+                       break;
+               switch (st) {
+               case 0:
+                       /* state 0: begin of a line */
+                       if (c == ';' || c == '#') {
+                               st = 3; /* removes lines starting with ; or # */
                                break;
-                       switch (st) {
-                       case 0:
-                               if (c == ';' || c == '#') {
-                                       st = 3; /* removes lines starting with ; or # */
-                                       break;
-                               }
-                               if (c == '\n')
-                                       break; /* removes empty lines */
+                       }
+                       if (c == '\n')
+                               break; /* removes empty lines */
 enter_state_1:
-                               st = 1;
-                               /*@fallthrough@*/
-                       case 1:
-                               if (c == '\\')
-                                       st = 2;
-                               else {
-                                       *write++ = c;
-                                       if (c == '\n')
-                                               st = 0;
-                               }
-                               break;
-                       case 2:
-                               if (c == '\n')
-                                       c = ' ';
-                               else
-                                       *write++ = '\\';
-                               goto enter_state_1;
-                       case 3:
+                       st = 1;
+                       /*@fallthrough@*/
+               case 1:
+                       /* state 1: emitting a normal line */
+                       if (c == '\\')
+                               st = 2;
+                       else {
+                               *write++ = c;
                                if (c == '\n')
                                        st = 0;
-                               break;
                        }
+                       break;
+               case 2:
+                       /* state 2: character after '\' */
+                       if (c == '\n')
+                               c = ' ';
+                       else
+                               *write++ = '\\';
+                       goto enter_state_1;
+               case 3:
+                       /* state 3: inside a comment, wait its end */
+                       if (c == '\n')
+                               st = 0;
+                       break;
                }
-               if (st == 1)
-                       *write++ = '\n';
-               *write = 0;
-               *length = (size_t)(write - *content);
-               *content = realloc(*content, *length + 1);
+       }
+       if (st == 1)
+               *write++ = '\n';
+       *write = 0;
+       return (size_t)(write - content);
+}
+
+/*
+ * read a unit file
+ */
+static int read_unit_file(const char *path, char **content, size_t *length)
+{
+       int rc;
+       size_t nl;
+
+       /* read the file */
+       rc = getfile(path, content, length);
+       if (rc >= 0) {
+               /* crop and trim it */
+               *length = nl = crop_and_trim_unit_content(*content, *length);
+               *content = realloc(*content, nl + 1);
        }
        return rc;
 }
@@ -471,22 +477,32 @@ int afm_udb_update(struct afm_udb *afudb)
        tmp = afudb->applications;
        afudb->applications = updt.applications;
        apps_put(&tmp);
-       afm_udb_addref(afudb);
+       afm_udb_unref(afudb);
        return 0;
 
 error:
        apps_put(&updt.applications);
-       afm_udb_addref(afudb);
+       afm_udb_unref(afudb);
        return -1;
 }
 
+/*
+ * set the default language to 'lang'
+ */
+void afm_udb_set_default_lang(const char *lang)
+{
+       char *oldval = default_lang;
+       default_lang = lang ? strdup(lang) : NULL;
+       free(oldval);
+}
+
 /*
  * Get the list of the applications private data of the afm_udb object 'afudb'.
  * The list is returned as a JSON-array that must be released using
  * 'json_object_put'.
  * Returns NULL in case of error.
  */
-struct json_object *afm_udb_applications_private(struct afm_udb *afudb)
+struct json_object *afm_udb_applications_private(struct afm_udb *afudb, int uid)
 {
        return json_object_get(afudb->applications.prvarr);
 }
@@ -497,7 +513,7 @@ struct json_object *afm_udb_applications_private(struct afm_udb *afudb)
  * 'json_object_put'.
  * Returns NULL in case of error.
  */
-struct json_object *afm_udb_applications_public(struct afm_udb *afudb)
+struct json_object *afm_udb_applications_public(struct afm_udb *afudb, int uid, const char *lang)
 {
        return json_object_get(afudb->applications.pubarr);
 }
@@ -507,7 +523,7 @@ struct json_object *afm_udb_applications_public(struct afm_udb *afudb)
  * It returns a JSON-object that must be released using 'json_object_put'.
  * Returns NULL in case of error.
  */
-static struct json_object *get_no_case(struct json_object *object, const char *id)
+static struct json_object *get_no_case(struct json_object *object, const char *id, int uid, const char *lang)
 {
        struct json_object *result;
        struct json_object_iter i;
@@ -529,9 +545,9 @@ static struct json_object *get_no_case(struct json_object *object, const char *i
  * It returns a JSON-object that must be released using 'json_object_put'.
  * Returns NULL in case of error.
  */
-struct json_object *afm_udb_get_application_private(struct afm_udb *afudb, const char *id)
+struct json_object *afm_udb_get_application_private(struct afm_udb *afudb, const char *id, int uid)
 {
-       return get_no_case(afudb->applications.prvobj, id);
+       return get_no_case(afudb->applications.prvobj, id, uid, NULL);
 }
 
 /*
@@ -540,9 +556,9 @@ struct json_object *afm_udb_get_application_private(struct afm_udb *afudb, const
  * Returns NULL in case of error.
  */
 struct json_object *afm_udb_get_application_public(struct afm_udb *afudb,
-                                                       const char *id)
+                                                       const char *id, int uid, const char *lang)
 {
-       return get_no_case(afudb->applications.pubobj, id);
+       return get_no_case(afudb->applications.pubobj, id, uid, lang);
 }