Move function definition to aul header
[platform/core/appfw/aul-1.git] / src / aul_rsc_mgr_internal.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
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
18 #include <stdlib.h>
19 #include <string.h>
20
21 #include <glib.h>
22 #include <libxml/tree.h>
23 #include <libxml/xmlschemas.h>
24
25 #include <dlog.h>
26 #include <bundle.h>
27
28 #include "aul_rsc_mgr_internal.h"
29 #include "aul_rsc_mgr_schema.h"
30
31 static char *__get_attribute(xmlNode *xml_node, const char *name)
32 {
33         xmlChar *val;
34         char *attr = NULL;
35
36         val = xmlGetProp(xml_node, (const xmlChar *)name);
37         if (val) {
38                 attr = strdup((const char *)val);
39                 xmlFree(val);
40         }
41
42         return attr;
43 }
44
45 static void __get_attribute_into_bundle(xmlNode *xml_node, const char *name,
46                 bundle *b)
47 {
48         char *attr;
49
50         attr = __get_attribute(xml_node, name);
51         if (attr) {
52                 bundle_add_str(b, name, attr);
53                 free(attr);
54         }
55 }
56
57 static int __parse_node(xmlNode *xml_node, GList **nodes)
58 {
59         resource_node_t *node;
60
61         if (strcmp((char *)xml_node->name, "node"))
62                 return -1;
63
64         node = calloc(1, sizeof(resource_node_t));
65         if (!node) {
66                 LOGE("Out of memory");
67                 return -1;
68         }
69
70         node->folder = __get_attribute(xml_node, "folder");
71         /* why we should use bundle here? */
72         node->attr = bundle_create();
73         if (node->attr == NULL) {
74                 LOGE("Out of memory");
75                 free(node->folder);
76                 free(node);
77                 return -1;
78         }
79
80         __get_attribute_into_bundle(xml_node, RSC_NODE_ATTR_SCREEN_DPI,
81                         node->attr);
82         __get_attribute_into_bundle(xml_node, RSC_NODE_ATTR_SCREEN_DPI_RANGE,
83                         node->attr);
84         __get_attribute_into_bundle(xml_node, RSC_NODE_ATTR_SCREEN_WIDTH_RANGE,
85                         node->attr);
86         __get_attribute_into_bundle(xml_node, RSC_NODE_ATTR_SCREEN_LARGE,
87                         node->attr);
88         __get_attribute_into_bundle(xml_node, RSC_NODE_ATTR_SCREEN_BPP,
89                         node->attr);
90         __get_attribute_into_bundle(xml_node, RSC_NODE_ATTR_PLATFORM_VER,
91                         node->attr);
92         __get_attribute_into_bundle(xml_node, RSC_NODE_ATTR_LANGUAGE,
93                         node->attr);
94
95         *nodes = g_list_append(*nodes, node);
96
97         return 0;
98 }
99
100 static char *_get_group_type(xmlNode *xml_node)
101 {
102         static const char delim[] = "-";
103         char *str;
104         char *tok;
105         char *ptr;
106
107         /* copy original string */
108         str = strdup((const char *)xml_node->name);
109         if (str == NULL) {
110                 LOGE("Out of memory");
111                 return NULL;
112         }
113
114         tok = strtok_r(str, delim, &ptr);
115         /* not a group element */
116         if (tok == NULL || strcmp(tok, "group")) {
117                 free(str);
118                 return NULL;
119         }
120
121         tok = strtok_r(NULL, delim, &ptr);
122         /* invalid element */
123         if (tok == NULL) {
124                 free(str);
125                 return NULL;
126         }
127
128         ptr = strdup(tok);
129         free(str);
130
131         return ptr;
132 }
133
134 static int __parse_group(xmlNode *xml_node, GList **groups)
135 {
136         xmlNode *tmp;
137         char *type;
138         resource_group_t *group;
139
140         type = _get_group_type(xml_node);
141         if (type == NULL)
142                 return -1;
143
144         group = calloc(1, sizeof(resource_group_t));
145         if (group == NULL) {
146                 LOGE("Out of memory");
147                 free(type);
148                 return -1;
149         }
150
151         group->type = type;
152         group->folder = __get_attribute(xml_node, "folder");
153
154         for (tmp = xml_node->children; tmp; tmp = tmp->next) {
155                 if (xml_node->type != XML_ELEMENT_NODE)
156                         continue;
157                 if (__parse_node(tmp, &group->node_list))
158                         continue;
159         }
160
161         *groups = g_list_append(*groups, group);
162
163         return 0;
164 }
165
166 static int __parse_resource(xmlNode *xml_node, resource_data_t **data)
167 {
168         xmlNode *tmp;
169
170         *data = calloc(1, sizeof(resource_data_t));
171         if (*data == NULL) {
172                 LOGE("out of memory");
173                 return -1;
174         }
175
176         for (tmp = xml_node->children; tmp; tmp = tmp->next) {
177                 if (tmp->type != XML_ELEMENT_NODE)
178                         continue;
179                 __parse_group(tmp, &(*data)->group_list);
180         }
181
182         return 0;
183 }
184
185 static int __validate_schema(const char *path)
186 {
187         xmlSchemaParserCtxt *parser_ctxt;
188         xmlSchema *schema;
189         xmlSchemaValidCtxt *valid_ctxt;
190         int ret;
191
192         parser_ctxt = xmlSchemaNewMemParserCtxt(res_schema, sizeof(res_schema));
193         if (parser_ctxt == NULL) {
194                 LOGE("failed to create parser context");
195                 return -1;
196         }
197
198         schema = xmlSchemaParse(parser_ctxt);
199         if (schema == NULL) {
200                 LOGE("failed to create schema");
201                 xmlSchemaFreeParserCtxt(parser_ctxt);
202                 return -1;
203         }
204
205         valid_ctxt = xmlSchemaNewValidCtxt(schema);
206         if (valid_ctxt == NULL) {
207                 LOGE("failed to create valid context");
208                 xmlSchemaFree(schema);
209                 xmlSchemaFreeParserCtxt(parser_ctxt);
210                 return -1;
211         }
212
213         ret = xmlSchemaValidateFile(valid_ctxt, path, 0);
214         if (ret)
215                 LOGE("%s: validation failed(%d)", path, ret);
216
217         xmlSchemaFreeValidCtxt(valid_ctxt);
218         xmlSchemaFree(schema);
219         xmlSchemaFreeParserCtxt(parser_ctxt);
220
221         return ret;
222 }
223
224 int _resource_open(const char *path, resource_data_t **data)
225 {
226         int ret;
227         xmlDoc *doc;
228         xmlNode *root;
229
230         if (__validate_schema(path))
231                 return -1;
232         doc = xmlReadFile(path, NULL, 0);
233         if (doc == NULL)
234                 return -1;
235         root = xmlDocGetRootElement(doc);
236
237         ret = __parse_resource(root, data);
238
239         xmlFreeDoc(doc);
240
241         return ret;
242 }
243
244 static void __free_resource_node(gpointer data)
245 {
246         resource_node_t *node = (resource_node_t *)data;
247
248         free(node->folder);
249         bundle_free(node->attr);
250         free(node);
251 }
252
253 static void __free_resource_group(gpointer data)
254 {
255         resource_group_t *group = (resource_group_t *)data;
256
257         free(group->folder);
258         free(group->type);
259
260         g_list_free_full(group->node_list, __free_resource_node);
261
262         free(group);
263 }
264
265 int _resource_close(resource_data_t *data)
266 {
267         /*
268         free(data->package);
269         */
270         g_list_free_full(data->group_list, __free_resource_group);
271
272         free(data);
273
274         return 0;
275 }