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