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 "pkgmgrinfo_debug.h"
38 #include "pkgmgr_parser.h"
39 #include "pkgmgr_parser_resource.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(gpointer 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(gpointer 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");
276 ret = PMINFO_R_ERROR;
279 memset(res_group, '\0', sizeof(resource_group_t));
280 tmp_list = g_list_append(tmp_list, res_group);
281 ret = __psp_process_group(reader, &res_group, group_type);
283 _LOGE("resource group processing failed");
284 ret = PMINFO_R_ERROR;
289 *list = g_list_first(tmp_list);
293 FREE_AND_NULL(group_type);
294 FREE_AND_NULL(res_group);
295 g_list_free_full(tmp_list, _free_group_list);
300 static int __process_resource_manifest(xmlTextReaderPtr reader, resource_data_t *data)
303 int ret = PMINFO_R_ERROR;
306 return PMINFO_R_ERROR;
308 ret = __next_child_element(reader, -1);
310 node = xmlTextReaderConstName(reader);
311 retvm_if(!node, PMINFO_R_ERROR, "xmlTextReaderConstName value is NULL\n");
313 if (!strcmp(ASCII(node), RSC_XML_QUALIFIER)) {
314 ret = __start_resource_process(reader, &data->group_list);
315 if (data->group_list == NULL)
316 _LOGE("__process_resource_manifest about to end but group list is null[%d]", ret);
318 _LOGE("no manifest element[res] has found");
319 return PMINFO_R_ERROR;
325 static resource_data_t *_pkgmgr_resource_parser_process_manifest_xml(const char *manifest)
327 xmlTextReaderPtr reader;
328 resource_data_t *rsc_data = NULL;
330 reader = xmlReaderForFile(manifest, NULL, 0);
332 rsc_data = malloc(sizeof(resource_data_t));
333 if (rsc_data == NULL) {
334 _LOGE("memory allocation failed");
338 memset(rsc_data, '\0', sizeof(resource_data_t));
339 if (__process_resource_manifest(reader, rsc_data) < 0) {
340 _LOGE("parsing failed with given manifest[%s]", manifest);
341 if (pkgmgr_resource_parser_close(rsc_data) != 0)
342 _LOGE("closing failed");
343 FREE_AND_NULL(rsc_data);
345 _LOGE("parsing succeed");
347 xmlFreeTextReader(reader);
349 _LOGE("creating xmlreader failed");
350 FREE_AND_NULL(rsc_data);
355 API int pkgmgr_resource_parser_open(const char *fname, resource_data_t **data)
357 resource_data_t *rsc_data = NULL;
358 int ret = PMINFO_R_ERROR;
360 if (fname == NULL || access(fname, R_OK) != 0) {
361 _LOGE("filename is null or cannot access file");
362 return PMINFO_R_EINVAL;
365 rsc_data = _pkgmgr_resource_parser_process_manifest_xml(fname);
366 if (rsc_data == NULL) {
367 _LOGE("parsing failed");
371 rsc_data->package = NULL;
380 API int pkgmgr_resource_parser_close(resource_data_t *data)
383 _LOGE("parameter is NULL");
384 return PMINFO_R_EINVAL;
387 FREE_AND_NULL(data->package);
388 g_list_free_full(data->group_list, (GDestroyNotify)_free_group_list);
393 API int pkgmgr_resource_parser_check_xml_validation(const char *xmlfile)
395 if (xmlfile == NULL) {
396 _LOGE("manifest file is NULL\n");
397 return PM_PARSER_R_EINVAL;
399 int ret = PM_PARSER_R_OK;
400 xmlSchemaParserCtxtPtr ctx = NULL;
401 xmlSchemaValidCtxtPtr vctx = NULL;
402 xmlSchemaPtr xschema = NULL;
403 ctx = xmlSchemaNewParserCtxt(RSC_MANIFEST_SCHEMA_FILE);
405 _LOGE("xmlSchemaNewParserCtxt() Failed\n");
406 return PM_PARSER_R_ERROR;
408 xschema = xmlSchemaParse(ctx);
409 if (xschema == NULL) {
410 _LOGE("xmlSchemaParse() Failed\n");
411 ret = PM_PARSER_R_ERROR;
414 vctx = xmlSchemaNewValidCtxt(xschema);
416 _LOGE("xmlSchemaNewValidCtxt() Failed\n");
417 return PM_PARSER_R_ERROR;
419 xmlSchemaSetValidErrors(vctx, (xmlSchemaValidityErrorFunc) fprintf, (xmlSchemaValidityWarningFunc) fprintf, stderr);
420 ret = xmlSchemaValidateFile(vctx, xmlfile, 0);
422 _LOGE("xmlSchemaValidateFile() failed\n");
423 ret = PM_PARSER_R_ERROR;
425 } else if (ret == 0) {
426 _LOGE("Manifest is Valid\n");
427 ret = PM_PARSER_R_OK;
430 _LOGE("Manifest Validation Failed with error code %d\n", ret);
431 ret = PM_PARSER_R_ERROR;
437 xmlSchemaFreeValidCtxt(vctx);
440 xmlSchemaFreeParserCtxt(ctx);
443 xmlSchemaFree(xschema);