4 * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>,
7 * Jaeho Lee <jaeho81.lee@samsung.com>, Shobhit Srivastava <shobhit.s@samsung.com>
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
26 #include <sys/types.h>
32 #include <libxml/parser.h>
33 #include <libxml/xmlreader.h>
34 #include <libxml/xmlschemas.h>
36 #include "pkgmgr-info.h"
37 #include "pkgmgr-info-debug.h"
38 #include "pkgmgr_parser_resource.h"
39 #include "pkgmgr_parser_resource_db.h"
44 #define LOG_TAG "PKGMGR_PARSER"
46 #define XMLCHAR(s) (const xmlChar *)s
47 #define ASCII(s) (char *)s
49 #define FREE_AND_NULL(ptr) do { \
57 #define RSC_XML_QUALIFIER "res"
58 #define RSC_GROUP_NAME_SEPERATOR '-'
59 #define RSC_GROUP "group"
60 #define RSC_GROUP_ATTR_FOLDER "folder"
61 #define RSC_GROUP_ATTR_TYPE "type"
62 #define RSC_NODE "node"
63 #define RSC_MANIFEST_SCHEMA_FILE "/etc/package-manager/preload/res.xsd"
65 static int __next_child_element(xmlTextReaderPtr reader, int depth)
67 int ret = xmlTextReaderRead(reader);
68 int cur = xmlTextReaderDepth(reader);
70 switch (xmlTextReaderNodeType(reader)) {
71 case XML_READER_TYPE_ELEMENT:
75 case XML_READER_TYPE_TEXT:
76 /*text is handled by each function separately*/
80 case XML_READER_TYPE_END_ELEMENT:
89 ret = xmlTextReaderRead(reader);
90 cur = xmlTextReaderDepth(reader);
95 static void _free_node_list(void *data, void *user_data)
97 resource_node_t *tmp_node = (resource_node_t *)data;
99 if (tmp_node == NULL) {
100 _LOGE("node list's element is NULL");
104 FREE_AND_NULL(tmp_node->folder);
105 if (tmp_node->attr != NULL) {
106 bundle_free(tmp_node->attr);
107 tmp_node->attr = NULL;
111 static void _free_group_list(void *data, void *user_data)
113 resource_group_t *tmp_group = (resource_group_t *)data;
115 if (tmp_group == NULL) {
116 _LOGE("group list's element is NULL");
120 FREE_AND_NULL(tmp_group->folder);
121 FREE_AND_NULL(tmp_group->type);
123 g_list_free_full(tmp_group->node_list, (GDestroyNotify)_free_node_list);
126 static void __save_resource_attribute_into_bundle(xmlTextReaderPtr reader, char *attribute, bundle **b)
128 xmlChar *attr_val = xmlTextReaderGetAttribute(reader, XMLCHAR(attribute));
131 bundle_add_str(*b, attribute, (char *)attr_val);
134 static void __save_resource_attribute(xmlTextReaderPtr reader, char *attribute, char **xml_attribute, char *default_value)
136 xmlChar *attrib_val = xmlTextReaderGetAttribute(reader, XMLCHAR(attribute));
139 *xml_attribute = strdup(ASCII(attrib_val));
141 if (default_value != NULL)
142 *xml_attribute = strdup(default_value);
147 static void __psp_process_node(xmlTextReaderPtr reader, resource_node_t **res_node)
149 char *node_folder = NULL;
151 __save_resource_attribute(reader, "folder", &node_folder, NULL);
153 (*res_node)->folder = node_folder;
155 /*retrieve node's attribute and put it into bundle*/
158 __save_resource_attribute_into_bundle(reader, RSC_NODE_ATTR_SCREEN_DPI, &b);
159 __save_resource_attribute_into_bundle(reader, RSC_NODE_ATTR_SCREEN_DPI_RANGE, &b);
160 __save_resource_attribute_into_bundle(reader, RSC_NODE_ATTR_SCREEN_WIDTH_RANGE, &b);
161 __save_resource_attribute_into_bundle(reader, RSC_NODE_ATTR_SCREEN_LARGE, &b);
162 __save_resource_attribute_into_bundle(reader, RSC_NODE_ATTR_SCREEN_BPP, &b);
163 __save_resource_attribute_into_bundle(reader, RSC_NODE_ATTR_PLATFORM_VER, &b);
164 __save_resource_attribute_into_bundle(reader, RSC_NODE_ATTR_LANGUAGE, &b);
166 (*res_node)->attr = b;
169 static int __psp_process_group(xmlTextReaderPtr reader, resource_group_t **res_group, char *group_type)
173 resource_group_t *tmp_group = NULL;
174 resource_node_t *res_node = NULL;
178 if (reader == NULL || *res_group == NULL || group_type == NULL) {
179 _LOGE("invalid parameter");
180 return PMINFO_R_EINVAL;
183 tmp_group = *res_group;
184 /*handle group's own attribute*/
185 __save_resource_attribute(reader, RSC_GROUP_ATTR_FOLDER, &folder, NULL);
186 tmp_group->folder = folder;
187 tmp_group->type = group_type;
189 depth = xmlTextReaderDepth(reader);
190 while ((ret = __next_child_element(reader, depth))) {
191 node = xmlTextReaderConstName(reader);
193 _LOGE("xmlTextReaderConstName value is NULL");
194 return PMINFO_R_ERROR;
198 if (!strcmp(ASCII(node), RSC_NODE)) {
199 res_node = malloc(sizeof(resource_node_t));
200 if (res_node == NULL) {
201 _LOGE("malloc failed");
204 tmp_group->node_list = g_list_append(tmp_group->node_list, res_node);
205 __psp_process_node(reader, &res_node);
207 _LOGE("unidentified node has found[%s]", ASCII(node));
208 return PMINFO_R_ERROR;
214 static int __is_group(char *node, char **type)
219 _LOGE("node is null");
220 return PMINFO_R_EINVAL;
223 tmp = strchr(node, RSC_GROUP_NAME_SEPERATOR);
224 tmp = tmp + 1; /*remove dash seperator*/
225 if (!strcmp(tmp, PKGMGR_RSC_GROUP_TYPE_IMAGE))
227 else if (!strcmp(tmp, PKGMGR_RSC_GROUP_TYPE_LAYOUT))
229 else if (!strcmp(tmp, PKGMGR_RSC_GROUP_TYPE_SOUND))
231 else if (!strcmp(tmp, PKGMGR_RSC_GROUP_TYPE_BIN))
234 return PMINFO_R_ERROR;
237 _LOGE("strdup failed with node[%s]", node);
238 return PMINFO_R_ERROR;
244 static int __start_resource_process(xmlTextReaderPtr reader, GList **list)
246 GList *tmp_list = NULL;
248 char *group_type = NULL;
251 resource_group_t *res_group = NULL;
253 if (reader == NULL) {
254 _LOGE("reader is null");
255 return PMINFO_R_EINVAL;
258 depth = xmlTextReaderDepth(reader);
259 while ((ret = __next_child_element(reader, depth))) {
260 node = xmlTextReaderConstName(reader);
262 _LOGE("xmlTextReaderConstName value is null");
267 ret = __is_group(ASCII(node), &group_type);
269 _LOGE("unidentified node[%s] has found with error[%d]", ASCII(node), ret);
273 res_group = malloc(sizeof(resource_group_t));
274 if (res_group == NULL) {
275 _LOGE("malloc failed");
278 memset(res_group, '\0', sizeof(resource_group_t));
279 tmp_list = g_list_append(tmp_list, res_group);
280 ret = __psp_process_group(reader, &res_group, group_type);
282 FREE_AND_NULL(res_group);
283 return PMINFO_R_ERROR;
287 *list = g_list_first(tmp_list);
291 static int __process_resource_manifest(xmlTextReaderPtr reader, resource_data_t *data)
294 int ret = PMINFO_R_ERROR;
297 return PMINFO_R_ERROR;
299 ret = __next_child_element(reader, -1);
301 node = xmlTextReaderConstName(reader);
302 retvm_if(!node, PMINFO_R_ERROR, "xmlTextReaderConstName value is NULL\n");
304 if (!strcmp(ASCII(node), RSC_XML_QUALIFIER)) {
305 ret = __start_resource_process(reader, &data->group_list);
306 if (data->group_list == NULL)
307 _LOGE("__process_resource_manifest about to end but group list is null[%d]", ret);
309 _LOGE("no manifest element[res] has found");
310 return PMINFO_R_ERROR;
316 static resource_data_t *_pkgmgr_resource_parser_process_manifest_xml(const char *manifest)
318 xmlTextReaderPtr reader;
319 resource_data_t *rsc_data = NULL;
321 reader = xmlReaderForFile(manifest, NULL, 0);
323 rsc_data = malloc(sizeof(resource_data_t));
324 if (rsc_data == NULL) {
325 _LOGE("memory allocation failed");
329 memset(rsc_data, '\0', sizeof(resource_data_t));
330 if (__process_resource_manifest(reader, rsc_data) < 0) {
331 _LOGE("parsing failed with given manifest[%s]", manifest);
332 if (pkgmgr_resource_parser_close(rsc_data) != 0)
333 _LOGE("closing failed");
336 _LOGE("parsing succeed");
338 xmlFreeTextReader(reader);
340 _LOGE("creating xmlreader failed");
341 FREE_AND_NULL(rsc_data);
346 API int pkgmgr_resource_parser_open_from_db(const char *package, resource_data_t **data)
348 resource_data_t *rsc_data = NULL;
351 if (package == NULL || strlen(package) == 0) {
352 _LOGE("invalid parameter");
353 return PMINFO_R_EINVAL;
356 ret = pkgmgr_parser_resource_db_load(package, &rsc_data);
358 _LOGE("get resource data from db failed");
366 API int pkgmgr_resource_parser_open(const char *fname, const char *package, resource_data_t **data)
368 resource_data_t *rsc_data = NULL;
369 int ret = PMINFO_R_ERROR;
371 if (fname == NULL || access(fname, R_OK) != 0) {
372 _LOGE("filename is null or cannot access file");
373 return PMINFO_R_EINVAL;
376 rsc_data = _pkgmgr_resource_parser_process_manifest_xml(fname);
377 if (rsc_data == NULL) {
378 _LOGE("parsing failed");
381 rsc_data->package = strdup(package);
390 API int pkgmgr_resource_parser_close(resource_data_t *data)
393 _LOGE("parameter is NULL");
394 return PMINFO_R_EINVAL;
397 FREE_AND_NULL(data->package);
398 g_list_free_full(data->group_list, (GDestroyNotify)_free_group_list);
403 API int pkgmgr_resource_parser_insert_into_db(resource_data_t *data)
406 _LOGE("parameter is NULL");
407 return PMINFO_R_EINVAL;
410 return pkgmgr_parser_resource_db_save(data->package, data);
413 API int pkgmgr_resource_parser_delete_from_db(const char *package)
415 if (package == NULL) {
416 _LOGE("parameter is NULL");
417 return PMINFO_R_EINVAL;
420 return pkgmgr_parser_resource_db_remove(package);
423 API int pkgmgr_resource_parser_check_xml_validation(const char *xmlfile)
425 if (xmlfile == NULL) {
426 _LOGE("manifest file is NULL\n");
427 return PM_PARSER_R_EINVAL;
429 int ret = PM_PARSER_R_OK;
430 xmlSchemaParserCtxtPtr ctx = NULL;
431 xmlSchemaValidCtxtPtr vctx = NULL;
432 xmlSchemaPtr xschema = NULL;
433 ctx = xmlSchemaNewParserCtxt(RSC_MANIFEST_SCHEMA_FILE);
435 _LOGE("xmlSchemaNewParserCtxt() Failed\n");
436 return PM_PARSER_R_ERROR;
438 xschema = xmlSchemaParse(ctx);
439 if (xschema == NULL) {
440 _LOGE("xmlSchemaParse() Failed\n");
441 ret = PM_PARSER_R_ERROR;
444 vctx = xmlSchemaNewValidCtxt(xschema);
446 _LOGE("xmlSchemaNewValidCtxt() Failed\n");
447 return PM_PARSER_R_ERROR;
449 xmlSchemaSetValidErrors(vctx, (xmlSchemaValidityErrorFunc) fprintf, (xmlSchemaValidityWarningFunc) fprintf, stderr);
450 ret = xmlSchemaValidateFile(vctx, xmlfile, 0);
452 _LOGE("xmlSchemaValidateFile() failed\n");
453 ret = PM_PARSER_R_ERROR;
455 } else if (ret == 0) {
456 _LOGE("Manifest is Valid\n");
457 ret = PM_PARSER_R_OK;
460 _LOGE("Manifest Validation Failed with error code %d\n", ret);
461 ret = PM_PARSER_R_ERROR;
467 xmlSchemaFreeValidCtxt(vctx);
470 xmlSchemaFreeParserCtxt(ctx);
473 xmlSchemaFree(xschema);