Bug fix and authoring
[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 int fill_desc(struct wgt_desc *desc, int want_icons, int want_features, int want_preferences)
79 {
80         xmlNodePtr node, pnode;
81         struct wgt_desc_icon *icon, **icontail;
82         struct wgt_desc_feature *feature, **featuretail;
83         struct wgt_desc_preference *preference, **preferencetail;
84         struct wgt_desc_param *param, **paramtail;
85
86         node = wgt_config_widget();
87         if (!node) {
88                 WARNING("no widget");
89                 errno = EINVAL;
90                 return -1;
91         }
92         desc->id = xmlGetProp(node, wgt_config_string_id);
93         desc->version = xmlGetProp(node, wgt_config_string_version);
94         desc->width = getpropnum(node, wgt_config_string_width, 0);
95         desc->height = getpropnum(node, wgt_config_string_height, 0);
96         desc->viewmodes = xmlGetProp(node, wgt_config_string_viewmodes);
97         desc->defaultlocale = xmlGetProp(node, wgt_config_string_defaultlocale);
98
99         node = wgt_config_name();
100         desc->name = optcontent(node);
101         desc->name_short = optprop(node, wgt_config_string_short);
102
103         node = wgt_config_description();
104         desc->description = optcontent(node);
105
106         node = wgt_config_author();
107         desc->author = optcontent(node);
108         desc->author_href = optprop(node, wgt_config_string_href);
109         desc->author_email = optprop(node, wgt_config_string_email);
110
111         node = wgt_config_license();
112         desc->license = optcontent(node);
113         desc->license_href = optprop(node, wgt_config_string_href);
114         
115         node = wgt_config_content();
116         desc->content_src = optprop(node, wgt_config_string_src);
117         if (node && desc->content_src == NULL) {
118                 WARNING("content without src");
119                 errno = EINVAL;
120                 return -1;
121         }
122         desc->content_type = optprop(node, wgt_config_string_type);
123         desc->content_encoding = optprop(node, wgt_config_string_encoding);
124
125         if (want_icons) {
126                 icontail = &desc->icons;
127                 node = wgt_config_first_icon();
128                 while (node) {
129                         icon = malloc(sizeof * icon);
130                         if (icon == NULL) {
131                                 errno = ENOMEM;
132                                 return -1;
133                         }
134                         icon->src = xmlGetProp(node, wgt_config_string_src);
135                         icon->width = getpropnum(node, wgt_config_string_width, 0);
136                         icon->height = getpropnum(node, wgt_config_string_height, 0);
137
138                         icon->next = NULL;
139                         *icontail = icon;
140
141                         if (icon->src == NULL) {
142                                 WARNING("icon without src");
143                                 errno = EINVAL;
144                                 return -1;
145                         }
146                         icontail = &icon->next;
147                         node = wgt_config_next_icon(node);
148                 }
149         }
150
151         if (want_features) {
152                 featuretail = &desc->features;
153                 node = wgt_config_first_feature();
154                 while (node) {
155                         feature = malloc(sizeof * feature);
156                         if (feature == NULL) {
157                                 errno = ENOMEM;
158                                 return -1;
159                         }
160                         feature->name = xmlGetProp(node, wgt_config_string_name);
161                         feature->required = getpropbool(node, wgt_config_string_required, 1);
162                         feature->params = NULL;
163
164                         feature->next = NULL;
165                         *featuretail = feature;
166
167                         if (feature->name == NULL) {
168                                 WARNING("feature without name");
169                                 errno = EINVAL;
170                                 return -1;
171                         }
172
173                         paramtail = &feature->params;
174                         pnode = wgt_config_first_param(node);
175                         while (pnode) {
176                                 param = malloc(sizeof * param);
177                                 if (param == NULL) {
178                                         errno = ENOMEM;
179                                         return -1;
180                                 }
181                                 param->name = xmlGetProp(pnode, wgt_config_string_name);
182                                 param->value = xmlGetProp(pnode, wgt_config_string_value);
183
184                                 param->next = NULL;
185                                 *paramtail = param;
186
187                                 if (param->name == NULL || param->value == NULL) {
188                                         WARNING("param without name or value");
189                                         errno = EINVAL;
190                                         return -1;
191                                 }
192
193                                 paramtail = &param->next;
194                                 pnode = wgt_config_next_param(pnode);
195                         }
196
197                         featuretail = &feature->next;
198                         node = wgt_config_next_feature(node);
199                 }
200         }
201
202         if (want_preferences) {
203                 preferencetail = &desc->preferences;
204                 node = wgt_config_first_preference();
205                 while (node) {
206                         preference = malloc(sizeof * preference);
207                         if (preference == NULL) {
208                                 errno = ENOMEM;
209                                 return -1;
210                         }
211                         preference->name = xmlGetProp(node, wgt_config_string_name);
212                         preference->value = xmlGetProp(node, wgt_config_string_value);
213                         preference->readonly = getpropbool(node, wgt_config_string_readonly, 0);
214
215                         *preferencetail = preference;
216                         preference->next = NULL;
217
218                         if (preference->name == NULL) {
219                                 WARNING("preference without name");
220                                 errno = EINVAL;
221                                 return -1;
222                         }
223
224                         preferencetail = &preference->next;
225                         node = wgt_config_next_preference(node);
226                 }
227         }
228         return 0;
229 }
230
231 static void free_desc(struct wgt_desc *desc)
232 {
233         struct wgt_desc_icon *icon;
234         struct wgt_desc_feature *feature;
235         struct wgt_desc_preference *preference;
236         struct wgt_desc_param *param;
237
238         xmlFree(desc->id);
239         xmlFree(desc->version);
240         xmlFree(desc->viewmodes);
241         xmlFree(desc->defaultlocale);
242         xmlFree(desc->name);
243         xmlFree(desc->name_short);
244         xmlFree(desc->description);
245         xmlFree(desc->author);
246         xmlFree(desc->author_href);
247         xmlFree(desc->author_email);
248         xmlFree(desc->license);
249         xmlFree(desc->license_href);
250         xmlFree(desc->content_src);
251         xmlFree(desc->content_type);
252         xmlFree(desc->content_encoding);
253
254         while(desc->icons) {
255                 icon = desc->icons;
256                 desc->icons = icon->next;
257                 xmlFree(icon->src);
258                 free(icon);
259         }
260
261         while(desc->features) {
262                 feature = desc->features;
263                 desc->features = feature->next;
264                 xmlFree(feature->name);
265                 while(feature->params) {
266                         param = feature->params;
267                         feature->params = param->next;
268                         xmlFree(param->name);
269                         xmlFree(param->value);
270                         free(param);
271                 }
272                 free(feature);
273         }
274
275         while(desc->preferences) {
276                 preference = desc->preferences;
277                 desc->preferences = preference->next;
278                 xmlFree(preference->name);
279                 xmlFree(preference->value);
280                 free(preference);
281         }
282 }
283
284 static void dump_desc(struct wgt_desc *desc, FILE *f, const char *prefix)
285 {
286         struct wgt_desc_icon *icon;
287         struct wgt_desc_feature *feature;
288         struct wgt_desc_preference *preference;
289         struct wgt_desc_param *param;
290
291         if (desc->id) fprintf(f, "%sid: %s\n", prefix, desc->id);
292         if (desc->width) fprintf(f, "%swidth: %d\n", prefix, desc->width);
293         if (desc->height) fprintf(f, "%sheight: %d\n", prefix, desc->height);
294         if (desc->version) fprintf(f, "%sversion: %s\n", prefix, desc->version);
295         if (desc->viewmodes) fprintf(f, "%sviewmodes: %s\n", prefix, desc->viewmodes);
296         if (desc->defaultlocale) fprintf(f, "%sdefaultlocale: %s\n", prefix, desc->defaultlocale);
297         if (desc->name) fprintf(f, "%sname: %s\n", prefix, desc->name);
298         if (desc->name_short) fprintf(f, "%sname_short: %s\n", prefix, desc->name_short);
299         if (desc->description) fprintf(f, "%sdescription: %s\n", prefix, desc->description);
300         if (desc->author) fprintf(f, "%sauthor: %s\n", prefix, desc->author);
301         if (desc->author_href) fprintf(f, "%sauthor_href: %s\n", prefix, desc->author_href);
302         if (desc->author_email) fprintf(f, "%sauthor_email: %s\n", prefix, desc->author_email);
303         if (desc->license) fprintf(f, "%slicense: %s\n", prefix, desc->license);
304         if (desc->license_href) fprintf(f, "%slicense_href: %s\n", prefix, desc->license_href);
305         if (desc->content_src) fprintf(f, "%scontent_src: %s\n", prefix, desc->content_src);
306         if (desc->content_type) fprintf(f, "%scontent_type: %s\n", prefix, desc->content_type);
307         if (desc->content_encoding) fprintf(f, "%scontent_encoding: %s\n", prefix, desc->content_encoding);
308
309         icon = desc->icons;
310         while(icon) {
311                 fprintf(f, "%s+ icon src: %s\n", prefix, icon->src);
312                 if (icon->width) fprintf(f, "%s       width: %d\n", prefix, icon->width);
313                 if (icon->height) fprintf(f, "%s       height: %d\n", prefix, icon->height);
314                 icon = icon->next;
315         }
316
317         feature = desc->features;
318         while(feature) {
319                 fprintf(f, "%s+ feature name: %s\n", prefix, feature->name);
320                 fprintf(f, "%s          required: %s\n", prefix, feature->required ? "true" : "false");
321                 param = feature->params;
322                 while(param) {
323                         fprintf(f, "%s          + param name: %s\n", prefix, param->name);
324                         fprintf(f, "%s                  value: %s\n", prefix, param->value);
325                         param = param->next;
326                 }
327                 feature = feature->next;
328         }
329
330         preference = desc->preferences;
331         while(preference) {
332                 fprintf(f, "%s+ preference name: %s\n", prefix, preference->name);
333                 if (preference->value) fprintf(f, "%s             value: %s\n", prefix, preference->value);
334                 fprintf(f, "%s             readonly: %s\n", prefix, preference->readonly ? "true" : "false");
335                 preference = preference->next;
336         }
337 }
338
339 struct wgt_info *wgt_info_create(struct wgt *wgt, int icons, int features, int preferences)
340 {
341         int rc;
342         struct wgt_info *result;
343
344         assert(wgt);
345         assert(wgt_is_connected(wgt));
346         rc = wgt_config_open(wgt);
347         if (rc) {
348                 errno = EINVAL;
349                 return NULL;
350         }
351
352         result = calloc(sizeof * result, 1);
353         if (!result) {
354                 wgt_config_close();
355                 errno = ENOMEM;
356                 return NULL;
357         }
358         result->refcount = 1;
359         result->wgt = wgt;
360         wgt_addref(wgt);
361
362         rc = fill_desc(&result->desc, icons, features, preferences);
363         wgt_config_close();
364         if (rc) {
365                 wgt_info_unref(result);
366                 return NULL;
367         }
368         return result;
369 }
370
371 struct wgt_info *wgt_info_createat(int dirfd, const char *pathname, int icons, int features, int preferences)
372 {
373         struct wgt_info *result = NULL;
374         struct wgt *wgt = wgt_createat(dirfd, pathname);
375         if (wgt) {
376                 result = wgt_info_create(wgt, icons, features, preferences);
377                 wgt_unref(wgt);
378         }
379         return result;
380 }
381
382 const struct wgt_desc *wgt_info_desc(struct wgt_info *ifo)
383 {
384         assert(ifo);
385         return &ifo->desc;
386 }
387
388 struct wgt *wgt_info_wgt(struct wgt_info *ifo)
389 {
390         assert(ifo);
391         assert(ifo->wgt);
392         return ifo->wgt;
393 }
394
395 void wgt_info_addref(struct wgt_info *ifo)
396 {
397         assert(ifo);
398         assert(ifo->refcount > 0);
399         ifo->refcount++;
400 }
401
402 void wgt_info_unref(struct wgt_info *ifo)
403 {
404         assert(ifo);
405         assert(ifo->refcount > 0);
406         if (--ifo->refcount)
407                 return;
408
409         free_desc(&ifo->desc);
410         wgt_unref(ifo->wgt);
411         free(ifo);
412 }
413
414 void wgt_info_dump(struct wgt_info *ifo, int fd, const char *prefix)
415 {
416         FILE *f;
417
418         assert(ifo);
419         f = fdopen(fd, "w");
420         if (f == NULL)
421                 WARNING("can't fdopen in wgt_info_dump");
422         else {
423                 dump_desc(&ifo->desc, f, prefix);
424                 fclose(f);
425         }
426 }
427
428 const struct wgt_desc_feature *wgt_info_feature(struct wgt_info *ifo, const char *name)
429 {
430         const struct wgt_desc_feature *result = ifo->desc.features;
431         while(result && strcmp(result->name, name))
432                 result = result->next;
433         return result;
434 }
435
436 const char *wgt_info_param(const struct wgt_desc_feature *feature, const char *name)
437 {
438         const struct wgt_desc_param *param = feature->params;
439         while(param) {
440                 if (0 == strcmp(name, param->name))
441                         return param->value;
442         }
443         return NULL;
444 }
445