implementation of installation by the daemon
[src/app-framework-main.git] / src / wgt-info.c
1 /*
2  Copyright 2015 IoT.bzh
3
4  author: José Bollo <jose.bollo@iot.bzh>
5
6  Licensed under the Apache License, Version 2.0 (the "License");
7  you may not use this file except in compliance with the License.
8  You may obtain a copy of the License at
9
10      http://www.apache.org/licenses/LICENSE-2.0
11
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  See the License for the specific language governing permissions and
16  limitations under the License.
17 */
18
19 #include <stdlib.h>
20 #include <string.h>
21 #include <errno.h>
22 #include <assert.h>
23
24 #include <libxml/tree.h>
25
26 #include "verbose.h"
27 #include "wgt.h"
28 #include "wgt-config.h"
29 #include "wgt-info.h"
30
31 struct wgt_info {
32         int refcount;
33         struct wgt *wgt;
34         struct wgt_desc desc;
35 };
36
37 static int getpropbool(xmlNodePtr node, const char *prop, int def)
38 {
39         int result;
40         char *val = xmlGetProp(node, prop);
41         if (!val)
42                 result = def;
43         else {
44                 if (!strcmp(val, "true"))
45                         result = 1;
46                 else if (!strcmp(val, "false"))
47                         result = 0;
48                 else
49                         result = def;
50                 xmlFree(val);
51         }
52         return result;
53 }
54
55 static int getpropnum(xmlNodePtr node, const char *prop, int def)
56 {
57         int result;
58         char *val = xmlGetProp(node, prop);
59         if (!val)
60                 result = def;
61         else {
62                 result = atoi(val);
63                 xmlFree(val);
64         }
65         return result;
66 }
67
68 static xmlChar *optprop(xmlNodePtr node, const char *prop)
69 {
70         return node ? xmlGetProp(node, prop) : NULL;
71 }
72
73 static xmlChar *optcontent(xmlNodePtr node)
74 {
75         return node ? xmlNodeGetContent(node) : NULL;
76 }
77
78 static char *mkidaver(char *id, char *version)
79 {
80         int lid, lver;
81         char c, *r;
82         if (id && version) {
83                 lid = strlen(id);
84                 c = version[lver = 0];
85                 while(c && c != ' ') {
86                         if (c != '.')
87                                 c = version[++lver];
88                         else {
89                                 do {
90                                         c = version[++lver];
91                                 } while (c && c != ' ' && c != '.');
92                                 break;
93                         }
94                 }
95                 r = malloc(2 + lid + lver);
96                 if (r) {
97                         memcpy(r, id, lid);
98                         r[lid] = '@';
99                         memcpy(r + lid + 1, version, lver + 1);
100                         return r;
101                 }
102         }
103         return NULL;
104 }
105
106 static int fill_desc(struct wgt_desc *desc, int want_icons, int want_features, int want_preferences)
107 {
108         xmlNodePtr node, pnode;
109         struct wgt_desc_icon *icon, **icontail;
110         struct wgt_desc_feature *feature, **featuretail;
111         struct wgt_desc_preference *preference, **preferencetail;
112         struct wgt_desc_param *param, **paramtail;
113
114         node = wgt_config_widget();
115         if (!node) {
116                 WARNING("no widget");
117                 errno = EINVAL;
118                 return -1;
119         }
120         desc->id = xmlGetProp(node, wgt_config_string_id);
121         desc->version = xmlGetProp(node, wgt_config_string_version);
122         desc->idaver = mkidaver(desc->id, desc->version);
123         desc->width = getpropnum(node, wgt_config_string_width, 0);
124         desc->height = getpropnum(node, wgt_config_string_height, 0);
125         desc->viewmodes = xmlGetProp(node, wgt_config_string_viewmodes);
126         desc->defaultlocale = xmlGetProp(node, wgt_config_string_defaultlocale);
127
128         node = wgt_config_name();
129         desc->name = optcontent(node);
130         desc->name_short = optprop(node, wgt_config_string_short);
131
132         node = wgt_config_description();
133         desc->description = optcontent(node);
134
135         node = wgt_config_author();
136         desc->author = optcontent(node);
137         desc->author_href = optprop(node, wgt_config_string_href);
138         desc->author_email = optprop(node, wgt_config_string_email);
139
140         node = wgt_config_license();
141         desc->license = optcontent(node);
142         desc->license_href = optprop(node, wgt_config_string_href);
143         
144         node = wgt_config_content();
145         desc->content_src = optprop(node, wgt_config_string_src);
146         if (node && desc->content_src == NULL) {
147                 WARNING("content without src");
148                 errno = EINVAL;
149                 return -1;
150         }
151         desc->content_type = optprop(node, wgt_config_string_type);
152         desc->content_encoding = optprop(node, wgt_config_string_encoding);
153
154         if (want_icons) {
155                 icontail = &desc->icons;
156                 node = wgt_config_first_icon();
157                 while (node) {
158                         icon = malloc(sizeof * icon);
159                         if (icon == NULL) {
160                                 errno = ENOMEM;
161                                 return -1;
162                         }
163                         icon->src = xmlGetProp(node, wgt_config_string_src);
164                         icon->width = getpropnum(node, wgt_config_string_width, 0);
165                         icon->height = getpropnum(node, wgt_config_string_height, 0);
166
167                         icon->next = NULL;
168                         *icontail = icon;
169
170                         if (icon->src == NULL) {
171                                 WARNING("icon without src");
172                                 errno = EINVAL;
173                                 return -1;
174                         }
175                         icontail = &icon->next;
176                         node = wgt_config_next_icon(node);
177                 }
178         }
179
180         if (want_features) {
181                 featuretail = &desc->features;
182                 node = wgt_config_first_feature();
183                 while (node) {
184                         feature = malloc(sizeof * feature);
185                         if (feature == NULL) {
186                                 errno = ENOMEM;
187                                 return -1;
188                         }
189                         feature->name = xmlGetProp(node, wgt_config_string_name);
190                         feature->required = getpropbool(node, wgt_config_string_required, 1);
191                         feature->params = NULL;
192
193                         feature->next = NULL;
194                         *featuretail = feature;
195
196                         if (feature->name == NULL) {
197                                 WARNING("feature without name");
198                                 errno = EINVAL;
199                                 return -1;
200                         }
201
202                         paramtail = &feature->params;
203                         pnode = wgt_config_first_param(node);
204                         while (pnode) {
205                                 param = malloc(sizeof * param);
206                                 if (param == NULL) {
207                                         errno = ENOMEM;
208                                         return -1;
209                                 }
210                                 param->name = xmlGetProp(pnode, wgt_config_string_name);
211                                 param->value = xmlGetProp(pnode, wgt_config_string_value);
212
213                                 param->next = NULL;
214                                 *paramtail = param;
215
216                                 if (param->name == NULL || param->value == NULL) {
217                                         WARNING("param without name or value");
218                                         errno = EINVAL;
219                                         return -1;
220                                 }
221
222                                 paramtail = &param->next;
223                                 pnode = wgt_config_next_param(pnode);
224                         }
225
226                         featuretail = &feature->next;
227                         node = wgt_config_next_feature(node);
228                 }
229         }
230
231         if (want_preferences) {
232                 preferencetail = &desc->preferences;
233                 node = wgt_config_first_preference();
234                 while (node) {
235                         preference = malloc(sizeof * preference);
236                         if (preference == NULL) {
237                                 errno = ENOMEM;
238                                 return -1;
239                         }
240                         preference->name = xmlGetProp(node, wgt_config_string_name);
241                         preference->value = xmlGetProp(node, wgt_config_string_value);
242                         preference->readonly = getpropbool(node, wgt_config_string_readonly, 0);
243
244                         *preferencetail = preference;
245                         preference->next = NULL;
246
247                         if (preference->name == NULL) {
248                                 WARNING("preference without name");
249                                 errno = EINVAL;
250                                 return -1;
251                         }
252
253                         preferencetail = &preference->next;
254                         node = wgt_config_next_preference(node);
255                 }
256         }
257         return 0;
258 }
259
260 static void free_desc(struct wgt_desc *desc)
261 {
262         struct wgt_desc_icon *icon;
263         struct wgt_desc_feature *feature;
264         struct wgt_desc_preference *preference;
265         struct wgt_desc_param *param;
266
267         xmlFree(desc->id);
268         xmlFree(desc->version);
269         free(desc->idaver);
270         xmlFree(desc->viewmodes);
271         xmlFree(desc->defaultlocale);
272         xmlFree(desc->name);
273         xmlFree(desc->name_short);
274         xmlFree(desc->description);
275         xmlFree(desc->author);
276         xmlFree(desc->author_href);
277         xmlFree(desc->author_email);
278         xmlFree(desc->license);
279         xmlFree(desc->license_href);
280         xmlFree(desc->content_src);
281         xmlFree(desc->content_type);
282         xmlFree(desc->content_encoding);
283
284         while(desc->icons) {
285                 icon = desc->icons;
286                 desc->icons = icon->next;
287                 xmlFree(icon->src);
288                 free(icon);
289         }
290
291         while(desc->features) {
292                 feature = desc->features;
293                 desc->features = feature->next;
294                 xmlFree(feature->name);
295                 while(feature->params) {
296                         param = feature->params;
297                         feature->params = param->next;
298                         xmlFree(param->name);
299                         xmlFree(param->value);
300                         free(param);
301                 }
302                 free(feature);
303         }
304
305         while(desc->preferences) {
306                 preference = desc->preferences;
307                 desc->preferences = preference->next;
308                 xmlFree(preference->name);
309                 xmlFree(preference->value);
310                 free(preference);
311         }
312 }
313
314 static void dump_desc(struct wgt_desc *desc, FILE *f, const char *prefix)
315 {
316         struct wgt_desc_icon *icon;
317         struct wgt_desc_feature *feature;
318         struct wgt_desc_preference *preference;
319         struct wgt_desc_param *param;
320
321         if (desc->id) fprintf(f, "%sid: %s\n", prefix, desc->id);
322         if (desc->version) fprintf(f, "%sversion: %s\n", prefix, desc->version);
323         if (desc->idaver) fprintf(f, "%sidaver: %s\n", prefix, desc->idaver);
324         if (desc->width) fprintf(f, "%swidth: %d\n", prefix, desc->width);
325         if (desc->height) fprintf(f, "%sheight: %d\n", prefix, desc->height);
326         if (desc->viewmodes) fprintf(f, "%sviewmodes: %s\n", prefix, desc->viewmodes);
327         if (desc->defaultlocale) fprintf(f, "%sdefaultlocale: %s\n", prefix, desc->defaultlocale);
328         if (desc->name) fprintf(f, "%sname: %s\n", prefix, desc->name);
329         if (desc->name_short) fprintf(f, "%sname_short: %s\n", prefix, desc->name_short);
330         if (desc->description) fprintf(f, "%sdescription: %s\n", prefix, desc->description);
331         if (desc->author) fprintf(f, "%sauthor: %s\n", prefix, desc->author);
332         if (desc->author_href) fprintf(f, "%sauthor_href: %s\n", prefix, desc->author_href);
333         if (desc->author_email) fprintf(f, "%sauthor_email: %s\n", prefix, desc->author_email);
334         if (desc->license) fprintf(f, "%slicense: %s\n", prefix, desc->license);
335         if (desc->license_href) fprintf(f, "%slicense_href: %s\n", prefix, desc->license_href);
336         if (desc->content_src) fprintf(f, "%scontent_src: %s\n", prefix, desc->content_src);
337         if (desc->content_type) fprintf(f, "%scontent_type: %s\n", prefix, desc->content_type);
338         if (desc->content_encoding) fprintf(f, "%scontent_encoding: %s\n", prefix, desc->content_encoding);
339
340         icon = desc->icons;
341         while(icon) {
342                 fprintf(f, "%s+ icon src: %s\n", prefix, icon->src);
343                 if (icon->width) fprintf(f, "%s       width: %d\n", prefix, icon->width);
344                 if (icon->height) fprintf(f, "%s       height: %d\n", prefix, icon->height);
345                 icon = icon->next;
346         }
347
348         feature = desc->features;
349         while(feature) {
350                 fprintf(f, "%s+ feature name: %s\n", prefix, feature->name);
351                 fprintf(f, "%s          required: %s\n", prefix, feature->required ? "true" : "false");
352                 param = feature->params;
353                 while(param) {
354                         fprintf(f, "%s          + param name: %s\n", prefix, param->name);
355                         fprintf(f, "%s                  value: %s\n", prefix, param->value);
356                         param = param->next;
357                 }
358                 feature = feature->next;
359         }
360
361         preference = desc->preferences;
362         while(preference) {
363                 fprintf(f, "%s+ preference name: %s\n", prefix, preference->name);
364                 if (preference->value) fprintf(f, "%s             value: %s\n", prefix, preference->value);
365                 fprintf(f, "%s             readonly: %s\n", prefix, preference->readonly ? "true" : "false");
366                 preference = preference->next;
367         }
368 }
369
370 struct wgt_info *wgt_info_create(struct wgt *wgt, int icons, int features, int preferences)
371 {
372         int rc;
373         struct wgt_info *result;
374
375         assert(wgt);
376         assert(wgt_is_connected(wgt));
377         rc = wgt_config_open(wgt);
378         if (rc) {
379                 errno = EINVAL;
380                 return NULL;
381         }
382
383         result = calloc(sizeof * result, 1);
384         if (!result) {
385                 wgt_config_close();
386                 errno = ENOMEM;
387                 return NULL;
388         }
389         result->refcount = 1;
390         result->wgt = wgt;
391         wgt_addref(wgt);
392
393         rc = fill_desc(&result->desc, icons, features, preferences);
394         wgt_config_close();
395         if (rc) {
396                 wgt_info_unref(result);
397                 return NULL;
398         }
399         return result;
400 }
401
402 struct wgt_info *wgt_info_createat(int dirfd, const char *pathname, int icons, int features, int preferences)
403 {
404         struct wgt_info *result = NULL;
405         struct wgt *wgt = wgt_createat(dirfd, pathname);
406         if (wgt) {
407                 result = wgt_info_create(wgt, icons, features, preferences);
408                 wgt_unref(wgt);
409         }
410         return result;
411 }
412
413 const struct wgt_desc *wgt_info_desc(struct wgt_info *ifo)
414 {
415         assert(ifo);
416         return &ifo->desc;
417 }
418
419 struct wgt *wgt_info_wgt(struct wgt_info *ifo)
420 {
421         assert(ifo);
422         assert(ifo->wgt);
423         return ifo->wgt;
424 }
425
426 void wgt_info_addref(struct wgt_info *ifo)
427 {
428         assert(ifo);
429         assert(ifo->refcount > 0);
430         ifo->refcount++;
431 }
432
433 void wgt_info_unref(struct wgt_info *ifo)
434 {
435         assert(ifo);
436         assert(ifo->refcount > 0);
437         if (--ifo->refcount)
438                 return;
439
440         free_desc(&ifo->desc);
441         wgt_unref(ifo->wgt);
442         free(ifo);
443 }
444
445 void wgt_info_dump(struct wgt_info *ifo, int fd, const char *prefix)
446 {
447         FILE *f;
448
449         assert(ifo);
450         f = fdopen(fd, "w");
451         if (f == NULL)
452                 WARNING("can't fdopen in wgt_info_dump");
453         else {
454                 dump_desc(&ifo->desc, f, prefix);
455                 fclose(f);
456         }
457 }
458
459 const struct wgt_desc_feature *wgt_info_feature(struct wgt_info *ifo, const char *name)
460 {
461         const struct wgt_desc_feature *result = ifo->desc.features;
462         while(result && strcmp(result->name, name))
463                 result = result->next;
464         return result;
465 }
466
467 const char *wgt_info_param(const struct wgt_desc_feature *feature, const char *name)
468 {
469         const struct wgt_desc_param *param = feature->params;
470         while(param) {
471                 if (0 == strcmp(name, param->name))
472                         return param->value;
473         }
474         return NULL;
475 }
476