### Required packages
INCLUDE(FindPkgConfig)
-pkg_check_modules(pkgs REQUIRED glib-2.0 dlog vconf sqlite3 db-util libxml-2.0 dbus-1 dbus-glib-1 libtzplatform-config libsmack)
+pkg_check_modules(pkgs REQUIRED glib-2.0 dlog vconf sqlite3 db-util libxml-2.0 dbus-1 dbus-glib-1 libtzplatform-config libsmack bundle)
FOREACH(flag ${pkgs_CFLAGS})
SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
ENDFOREACH(flag)
-pkg_check_modules(libpkgs REQUIRED glib-2.0 dlog vconf sqlite3 db-util libxml-2.0 dbus-1 dbus-glib-1 libtzplatform-config libsmack)
+pkg_check_modules(libpkgs REQUIRED glib-2.0 dlog vconf sqlite3 db-util libxml-2.0 dbus-1 dbus-glib-1 libtzplatform-config libsmack bundle)
FOREACH(flag ${libpkgs_CFLAGS})
SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
add_subdirectory(parser)
## build pkgmgr-info library
-add_library(pkgmgr-info SHARED src/pkgmgr-info.c src/pkgmgr-info-internal.c)
+add_library(pkgmgr-info SHARED src/pkgmgr-info.c src/pkgmgr-info-internal.c src/pkgmgrinfo_resource.c)
SET_TARGET_PROPERTIES(pkgmgr-info PROPERTIES SOVERSION ${VERSION_MAJOR})
INSTALL(TARGETS pkgmgr-info DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries)
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/pkgmgr-info.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/pkgmgr-info.h DESTINATION include)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/pkgmgrinfo_resource.h DESTINATION include)
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/parser_path.conf DESTINATION ${SYSCONFDIR}/package-manager/)
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/mdparser_list.txt DESTINATION ${SYSCONFDIR}/package-manager/parserlib/metadata)
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/category_parser_list.txt DESTINATION ${SYSCONFDIR}/package-manager/parserlib/category)
--- /dev/null
+#ifndef __PKGMGRINFO_RESOURCE_H_
+#define __PKGMGRINFO_RESOURCE_H_
+
+#include <glib.h>
+#include <bundle.h>
+
+#define RSC_GROUP_TYPE_IMAGE "image"
+#define RSC_GROUP_TYPE_LAYOUT "layout"
+#define RSC_GROUP_TYPE_SOUND "sound"
+#define RSC_GROUP_TYPE_BIN "bin"
+
+#define RSC_NODE_ATTR_SCREEN_DPI "screen-dpi"
+#define RSC_NODE_ATTR_SCREEN_DPI_RANGE "screen-dpi-range"
+#define RSC_NODE_ATTR_SCREEN_WIDTH_RANGE "screen-width-range"
+#define RSC_NODE_ATTR_SCREEN_LARGE "screen-large"
+#define RSC_NODE_ATTR_SCREEN_BPP "screen-bpp"
+#define RSC_NODE_ATTR_PLATFORM_VER "platform-version"
+#define RSC_NODE_ATTR_LANGUAGE "language"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ char *folder;
+ bundle *attr;
+} resource_node_t;
+
+typedef struct {
+ char *folder;
+ char *type;
+ GList *node_list;
+} resource_group_t;
+
+typedef struct {
+ char *package;
+ GList *group_list;
+} resource_data_t;
+
+/**
+ * @fn int pkgmgrinfo_resource_close(resource_data_t data)
+ * @brief This API frees given data and its own variables
+ *
+ * @par This API is for capi-appfw-application.
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in] data structure of resource_data_t
+ * @return 0 on succeed and -1 on failure, -2 on invalid parameter
+ */
+int pkgmgrinfo_resource_close(resource_data_t *data);
+
+/**
+ * @fn int pkgmgrinfo_resource_open(const char *package, resource_data_t **data)
+ * @brief This API will get resource data of specific package from db
+ *
+ * @par This API is for capi-appfw-application.
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in] package packageID
+ * @param[out]data resource_data type structure. it will filled with resource data
+ * @return 0 on succeed and -1 on failure, -2 on invalid parameter
+ */
+int pkgmgrinfo_resource_open(const char *package, resource_data_t **data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
BuildRequires: pkgconfig(dbus-glib-1)
BuildRequires: pkgconfig(libtzplatform-config)
BuildRequires: pkgconfig(libsmack)
+BuildRequires: pkgconfig(bundle)
%description
Packager Manager infomation api for packaging
%manifest %{name}.manifest
%defattr(-,root,root,-)
%{_includedir}/pkgmgr-info.h
+%{_includedir}/pkgmgrinfo_resource.h
%{_libdir}/pkgconfig/pkgmgr-info.pc
%{_libdir}/libpkgmgr-info.so
%config %{_sysconfdir}/package-manager/preload/preload_list.txt
%config %{_sysconfdir}/package-manager/preload/manifest.xsd
%config %{_sysconfdir}/package-manager/preload/xml.xsd
+%config %{_sysconfdir}/package-manager/preload/res.xsd
%config %{_sysconfdir}/package-manager/parser_path.conf
%config %{_sysconfdir}/package-manager/parserlib/metadata/mdparser_list.txt
%config %{_sysconfdir}/package-manager/parserlib/category/category_parser_list.txt
%defattr(-,root,root,-)
%{_includedir}/pkgmgr/pkgmgr_parser.h
%{_includedir}/pkgmgr/pkgmgr_parser_db.h
+%{_includedir}/pkgmgr/pkgmgr_parser_resource.h
%{_libdir}/pkgconfig/pkgmgr-parser.pc
%{_libdir}/libpkgmgr_parser.so
### Get required CFLAGS, LDFLAGS from pkg-config
include(FindPkgConfig)
-pkg_check_modules(parser_pkgs REQUIRED dlog libxml-2.0 glib-2.0 sqlite3 db-util vconf)
+pkg_check_modules(parser_pkgs REQUIRED dlog libxml-2.0 glib-2.0 sqlite3 db-util vconf bundle)
foreach(flag ${parser_pkgs_CFLAGS})
set(parser_pkgs_CFLAGS_str "${parser_pkgs_CFLAGS_str} ${flag}")
## pkgmgr_parser object (by sewook.park)
# This library is for installer backend
-add_library(pkgmgr_parser SHARED pkgmgr_parser.c pkgmgr_parser_db.c pkgmgr_parser_signature.c)
+add_library(pkgmgr_parser SHARED pkgmgr_parser.c pkgmgr_parser_db.c pkgmgr_parser_signature.c pkgmgr_parser_resource_db.c pkgmgr_parser_resource.c)
#add_library(pkgmgr_parser SHARED pkgmgr_parser.c)
set_target_properties(pkgmgr_parser PROPERTIES SOVERSION ${VERSION_MAJOR})
set_target_properties(pkgmgr_parser PROPERTIES VERSION ${VERSION})
configure_file(preload_list.txt.in preload_list.txt @ONLY)
configure_file(manifest.xsd.in manifest.xsd @ONLY)
configure_file(xml.xsd.in xml.xsd @ONLY)
+configure_file(res.xsd.in res.xsd @ONLY)
## Install
INSTALL(TARGETS
INSTALL(FILES
pkgmgr_parser_db.h
DESTINATION include/pkgmgr)
-
+INSTALL(FILES
+ pkgmgr_parser_resource.h
+ DESTINATION include/pkgmgr)
INSTALL(FILES
${CMAKE_CURRENT_BINARY_DIR}/pkgmgr-parser.pc
DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/preload_list.txt DESTINATION ${SYSCONFDIR}/package-manager/preload/)
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/manifest.xsd DESTINATION ${SYSCONFDIR}/package-manager/preload/)
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/xml.xsd DESTINATION ${SYSCONFDIR}/package-manager/preload/)
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/res.xsd DESTINATION ${SYSCONFDIR}/package-manager/preload/)
#define PKGMGR_PARSER_EMPTY_STR ""
#define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
+/**
+ * @brief API return values
+ */
+enum {
+ PM_PARSER_R_EINVAL = -2, /**< Invalid argument */
+ PM_PARSER_R_ERROR = -1, /**< General error */
+ PM_PARSER_R_OK = 0 /**< General success */
+};
/**
* @brief List definitions.
"FOREIGN KEY(app_id) " \
"REFERENCES package_app_info(app_id) " \
"ON DELETE CASCADE)"
+#define QUERY_CREATE_TABLE_PACKAGE_RESOURCE_INFO "CREATE TABLE IF NOT EXISTS package_resource_info" \
+ "(pkg_id text NOT NULL," \
+ "group_folder text NOT NULL," \
+ "group_type text NOT NULL," \
+ "PRIMARY KEY(pkg_id, group_type))"
+
+#define QUERY_CREATE_TABLE_PACKAGE_RESOURCE_DATA "CREATE TABLE IF NOT EXISTS package_resource_data" \
+ "(id integer REFERENCES package_resource_info(rowid)," \
+ "node_folder text NOT NULL," \
+ "attr_name text NOT NULL," \
+ "attr_value test NOT NULL," \
+ "PRIMARY KEY(id, node_folder, attr_name))"
static int __insert_uiapplication_info(manifest_x *mfx);
static int __insert_serviceapplication_info(manifest_x *mfx);
_LOGD("package cert index info DB initialization failed\n");
return ret;
}
+ /*resource DB*/
+ ret = __initialize_db(pkgmgr_parser_db, QUERY_CREATE_TABLE_PACKAGE_RESOURCE_INFO);
+ if (ret == -1) {
+ _LOGD("package resource info DB initialization failed\n");
+ return ret;
+ }
+ ret = __initialize_db(pkgmgr_parser_db, QUERY_CREATE_TABLE_PACKAGE_RESOURCE_DATA);
+ if (ret == -1) {
+ _LOGD("package resource data DB initialization failed\n");
+ return ret;
+ }
return 0;
}
--- /dev/null
+/*
+ * pkgmgr-info
+ *
+ * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>,
+ * Jaeho Lee <jaeho81.lee@samsung.com>, Shobhit Srivastava <shobhit.s@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <db-util.h>
+#include <glib.h>
+#include <dlfcn.h>
+#include <libxml/parser.h>
+#include <libxml/xmlreader.h>
+#include <libxml/xmlschemas.h>
+#include <bundle.h>
+#include "pkgmgr-info.h"
+#include "pkgmgr-info-debug.h"
+#include "pkgmgr_parser_resource.h"
+#include "pkgmgr_parser_resource_db.h"
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "PKGMGR_PARSER"
+
+#define XMLCHAR(s) (const xmlChar *)s
+#define ASCII(s) (char *)s
+
+#define FREE_AND_NULL(ptr) do { \
+ if (ptr) { \
+ free((void *)ptr); \
+ ptr = NULL; \
+ } \
+ } while (0)
+
+
+#define RSC_XML_QUALIFIER "res"
+#define RSC_GROUP_NAME_SEPERATOR '-'
+#define RSC_GROUP "group"
+#define RSC_GROUP_ATTR_FOLDER "folder"
+#define RSC_GROUP_ATTR_TYPE "type"
+#define RSC_NODE "node"
+#define RSC_MANIFEST_SCHEMA_FILE "/etc/package-manager/preload/res.xsd"
+
+static int __next_child_element(xmlTextReaderPtr reader, int depth)
+{
+ int ret = xmlTextReaderRead(reader);
+ int cur = xmlTextReaderDepth(reader);
+ while (ret == 1) {
+ switch (xmlTextReaderNodeType(reader)) {
+ case XML_READER_TYPE_ELEMENT:
+ if (cur == depth + 1)
+ return 1;
+ break;
+ case XML_READER_TYPE_TEXT:
+ /*text is handled by each function separately*/
+ if (cur == depth + 1)
+ return 0;
+ break;
+ case XML_READER_TYPE_END_ELEMENT:
+ if (cur == depth)
+ return 0;
+ break;
+ default:
+ if (cur <= depth)
+ return 0;
+ break;
+ }
+ ret = xmlTextReaderRead(reader);
+ cur = xmlTextReaderDepth(reader);
+ }
+ return ret;
+}
+
+static void _free_node_list(void *data, void *user_data)
+{
+ resource_node_t *tmp_node = (resource_node_t *)data;
+
+ if (tmp_node == NULL) {
+ _LOGE("node list's element is NULL");
+ return;
+ }
+
+ FREE_AND_NULL(tmp_node->folder);
+ if (tmp_node->attr != NULL) {
+ bundle_free(tmp_node->attr);
+ tmp_node->attr = NULL;
+ }
+}
+
+static void _free_group_list(void *data, void *user_data)
+{
+ resource_group_t *tmp_group = (resource_group_t *)data;
+
+ if (tmp_group == NULL) {
+ _LOGE("group list's element is NULL");
+ return;
+ }
+
+ FREE_AND_NULL(tmp_group->folder);
+ FREE_AND_NULL(tmp_group->type);
+
+ g_list_free_full(tmp_group->node_list, (GDestroyNotify)_free_node_list);
+}
+
+static void __save_resource_attribute_into_bundle(xmlTextReaderPtr reader, char *attribute, bundle **b)
+{
+ xmlChar *attr_val = xmlTextReaderGetAttribute(reader, XMLCHAR(attribute));
+
+ if (attr_val)
+ bundle_add_str(*b, attribute, (char *)attr_val);
+}
+
+static void __save_resource_attribute(xmlTextReaderPtr reader, char *attribute, char **xml_attribute, char *default_value)
+{
+ xmlChar *attrib_val = xmlTextReaderGetAttribute(reader, XMLCHAR(attribute));
+
+ if (attrib_val)
+ *xml_attribute = strdup(ASCII(attrib_val));
+ else {
+ if (default_value != NULL)
+ *xml_attribute = strdup(default_value);
+ }
+}
+
+
+static void __psp_process_node(xmlTextReaderPtr reader, resource_node_t **res_node)
+{
+ char *node_folder = NULL;
+
+ __save_resource_attribute(reader, "folder", &node_folder, NULL);
+ bundle *b = NULL;
+ (*res_node)->folder = node_folder;
+
+ /*retrieve node's attribute and put it into bundle*/
+ b = bundle_create();
+
+ __save_resource_attribute_into_bundle(reader, RSC_NODE_ATTR_SCREEN_DPI, &b);
+ __save_resource_attribute_into_bundle(reader, RSC_NODE_ATTR_SCREEN_DPI_RANGE, &b);
+ __save_resource_attribute_into_bundle(reader, RSC_NODE_ATTR_SCREEN_WIDTH_RANGE, &b);
+ __save_resource_attribute_into_bundle(reader, RSC_NODE_ATTR_SCREEN_LARGE, &b);
+ __save_resource_attribute_into_bundle(reader, RSC_NODE_ATTR_SCREEN_BPP, &b);
+ __save_resource_attribute_into_bundle(reader, RSC_NODE_ATTR_PLATFORM_VER, &b);
+ __save_resource_attribute_into_bundle(reader, RSC_NODE_ATTR_LANGUAGE, &b);
+
+ (*res_node)->attr = b;
+}
+
+static int __psp_process_group(xmlTextReaderPtr reader, resource_group_t **res_group, char *group_type)
+{
+ int depth = -1;
+ int ret = -1;
+ resource_group_t *tmp_group = NULL;
+ resource_node_t *res_node = NULL;
+ const xmlChar *node;
+ char *folder = NULL;
+
+ if (reader == NULL || *res_group == NULL || group_type == NULL) {
+ _LOGE("invalid parameter");
+ return PMINFO_R_EINVAL;
+ }
+
+ tmp_group = *res_group;
+ /*handle group's own attribute*/
+ __save_resource_attribute(reader, RSC_GROUP_ATTR_FOLDER, &folder, NULL);
+ tmp_group->folder = folder;
+ tmp_group->type = group_type;
+
+ depth = xmlTextReaderDepth(reader);
+ while ((ret = __next_child_element(reader, depth))) {
+ node = xmlTextReaderConstName(reader);
+ if (!node) {
+ _LOGE("xmlTextReaderConstName value is NULL");
+ return PMINFO_R_ERROR;
+ }
+
+ res_node = NULL;
+ if (!strcmp(ASCII(node), RSC_NODE)) {
+ res_node = malloc(sizeof(resource_node_t));
+ if (res_node == NULL) {
+ _LOGE("malloc failed");
+ return -1;
+ }
+ tmp_group->node_list = g_list_append(tmp_group->node_list, res_node);
+ __psp_process_node(reader, &res_node);
+ } else {
+ _LOGE("unidentified node has found[%s]", ASCII(node));
+ return PMINFO_R_ERROR;
+ }
+ }
+ return ret;
+}
+
+static int __is_group(char *node, char **type)
+{
+ char *tmp = NULL;
+
+ if (node == NULL) {
+ _LOGE("node is null");
+ return PMINFO_R_EINVAL;
+ }
+
+ tmp = strchr(node, RSC_GROUP_NAME_SEPERATOR);
+ tmp = tmp + 1; /*remove dash seperator*/
+ if (!strcmp(tmp, PKGMGR_RSC_GROUP_TYPE_IMAGE))
+ *type = strdup(tmp);
+ else if (!strcmp(tmp, PKGMGR_RSC_GROUP_TYPE_LAYOUT))
+ *type = strdup(tmp);
+ else if (!strcmp(tmp, PKGMGR_RSC_GROUP_TYPE_SOUND))
+ *type = strdup(tmp);
+ else if (!strcmp(tmp, PKGMGR_RSC_GROUP_TYPE_BIN))
+ *type = strdup(tmp);
+ else
+ return PMINFO_R_ERROR;
+
+ if (*type == NULL) {
+ _LOGE("strdup failed with node[%s]", node);
+ return PMINFO_R_ERROR;
+ }
+
+ return PMINFO_R_OK;
+}
+
+static int __start_resource_process(xmlTextReaderPtr reader, GList **list)
+{
+ GList *tmp_list = NULL;
+ const xmlChar *node;
+ char *group_type = NULL;
+ int ret = -1;
+ int depth = -1;
+ resource_group_t *res_group = NULL;
+
+ if (reader == NULL) {
+ _LOGE("reader is null");
+ return PMINFO_R_EINVAL;
+ }
+
+ depth = xmlTextReaderDepth(reader);
+ while ((ret = __next_child_element(reader, depth))) {
+ node = xmlTextReaderConstName(reader);
+ if (!node) {
+ _LOGE("xmlTextReaderConstName value is null");
+ return -1;
+ }
+
+ group_type = NULL;
+ ret = __is_group(ASCII(node), &group_type);
+ if (ret) {
+ _LOGE("unidentified node[%s] has found with error[%d]", ASCII(node), ret);
+ return ret;
+ }
+ res_group = NULL;
+ res_group = malloc(sizeof(resource_group_t));
+ if (res_group == NULL) {
+ _LOGE("malloc failed");
+ return -1;
+ }
+ memset(res_group, '\0', sizeof(resource_group_t));
+ tmp_list = g_list_append(tmp_list, res_group);
+ ret = __psp_process_group(reader, &res_group, group_type);
+ if (ret != 0) {
+ FREE_AND_NULL(res_group);
+ return PMINFO_R_ERROR;
+ }
+ }
+
+ *list = g_list_first(tmp_list);
+ return ret;
+}
+
+static int __process_resource_manifest(xmlTextReaderPtr reader, resource_data_t *data)
+{
+ const xmlChar *node;
+ int ret = PMINFO_R_ERROR;
+
+ if (reader == NULL)
+ return PMINFO_R_ERROR;
+
+ ret = __next_child_element(reader, -1);
+ if (ret) {
+ node = xmlTextReaderConstName(reader);
+ retvm_if(!node, PMINFO_R_ERROR, "xmlTextReaderConstName value is NULL\n");
+
+ if (!strcmp(ASCII(node), RSC_XML_QUALIFIER)) {
+ ret = __start_resource_process(reader, &data->group_list);
+ if (data->group_list == NULL)
+ _LOGE("__process_resource_manifest about to end but group list is null[%d]", ret);
+ } else {
+ _LOGE("no manifest element[res] has found");
+ return PMINFO_R_ERROR;
+ }
+ }
+ return ret;
+}
+
+static resource_data_t *_pkgmgr_resource_parser_process_manifest_xml(const char *manifest)
+{
+ xmlTextReaderPtr reader;
+ resource_data_t *rsc_data = NULL;
+
+ reader = xmlReaderForFile(manifest, NULL, 0);
+ if (reader) {
+ rsc_data = malloc(sizeof(resource_data_t));
+ if (rsc_data == NULL) {
+ _LOGE("memory allocation failed");
+ return NULL;
+ }
+
+ memset(rsc_data, '\0', sizeof(resource_data_t));
+ if (__process_resource_manifest(reader, rsc_data) < 0) {
+ _LOGE("parsing failed with given manifest[%s]", manifest);
+ if (pkgmgr_resource_parser_close(rsc_data) != 0)
+ _LOGE("closing failed");
+ rsc_data = NULL;
+ } else
+ _LOGE("parsing succeed");
+
+ xmlFreeTextReader(reader);
+ } else {
+ _LOGE("creating xmlreader failed");
+ FREE_AND_NULL(rsc_data);
+ }
+ return rsc_data;
+}
+
+API int pkgmgr_resource_parser_open_from_db(const char *package, resource_data_t **data)
+{
+ resource_data_t *rsc_data = NULL;
+ int ret = -1;
+
+ if (package == NULL || strlen(package) == 0) {
+ _LOGE("invalid parameter");
+ return PMINFO_R_EINVAL;
+ }
+
+ ret = pkgmgr_parser_resource_db_load(package, &rsc_data);
+ if (ret != 0) {
+ _LOGE("get resource data from db failed");
+ return ret;
+ }
+
+ *data = rsc_data;
+ return ret;
+}
+
+API int pkgmgr_resource_parser_open(const char *fname, const char *package, resource_data_t **data)
+{
+ resource_data_t *rsc_data = NULL;
+ int ret = PMINFO_R_ERROR;
+
+ if (fname == NULL || access(fname, R_OK) != 0) {
+ _LOGE("filename is null or cannot access file");
+ return PMINFO_R_EINVAL;
+ }
+ xmlInitParser();
+ rsc_data = _pkgmgr_resource_parser_process_manifest_xml(fname);
+ if (rsc_data == NULL) {
+ _LOGE("parsing failed");
+ goto catch;
+ }
+ rsc_data->package = strdup(package);
+
+ *data = rsc_data;
+ ret = PMINFO_R_OK;
+catch:
+ xmlCleanupParser();
+ return ret;
+}
+
+API int pkgmgr_resource_parser_close(resource_data_t *data)
+{
+ if (data == NULL) {
+ _LOGE("parameter is NULL");
+ return PMINFO_R_EINVAL;
+ }
+
+ FREE_AND_NULL(data->package);
+ g_list_free_full(data->group_list, (GDestroyNotify)_free_group_list);
+
+ return PMINFO_R_OK;
+}
+
+API int pkgmgr_resource_parser_insert_into_db(resource_data_t *data)
+{
+ if (data == NULL) {
+ _LOGE("parameter is NULL");
+ return PMINFO_R_EINVAL;
+ }
+
+ return pkgmgr_parser_resource_db_save(data->package, data);
+}
+
+API int pkgmgr_resource_parser_delete_from_db(const char *package)
+{
+ if (package == NULL) {
+ _LOGE("parameter is NULL");
+ return PMINFO_R_EINVAL;
+ }
+
+ return pkgmgr_parser_resource_db_remove(package);
+}
+
+API int pkgmgr_resource_parser_check_xml_validation(const char *xmlfile)
+{
+ if (xmlfile == NULL) {
+ _LOGE("manifest file is NULL\n");
+ return PM_PARSER_R_EINVAL;
+ }
+ int ret = PM_PARSER_R_OK;
+ xmlSchemaParserCtxtPtr ctx = NULL;
+ xmlSchemaValidCtxtPtr vctx = NULL;
+ xmlSchemaPtr xschema = NULL;
+ ctx = xmlSchemaNewParserCtxt(RSC_MANIFEST_SCHEMA_FILE);
+ if (ctx == NULL) {
+ _LOGE("xmlSchemaNewParserCtxt() Failed\n");
+ return PM_PARSER_R_ERROR;
+ }
+ xschema = xmlSchemaParse(ctx);
+ if (xschema == NULL) {
+ _LOGE("xmlSchemaParse() Failed\n");
+ ret = PM_PARSER_R_ERROR;
+ goto cleanup;
+ }
+ vctx = xmlSchemaNewValidCtxt(xschema);
+ if (vctx == NULL) {
+ _LOGE("xmlSchemaNewValidCtxt() Failed\n");
+ return PM_PARSER_R_ERROR;
+ }
+ xmlSchemaSetValidErrors(vctx, (xmlSchemaValidityErrorFunc) fprintf, (xmlSchemaValidityWarningFunc) fprintf, stderr);
+ ret = xmlSchemaValidateFile(vctx, xmlfile, 0);
+ if (ret == -1) {
+ _LOGE("xmlSchemaValidateFile() failed\n");
+ ret = PM_PARSER_R_ERROR;
+ goto cleanup;
+ } else if (ret == 0) {
+ _LOGE("Manifest is Valid\n");
+ ret = PM_PARSER_R_OK;
+ goto cleanup;
+ } else {
+ _LOGE("Manifest Validation Failed with error code %d\n", ret);
+ ret = PM_PARSER_R_ERROR;
+ goto cleanup;
+ }
+
+cleanup:
+ if(vctx != NULL)
+ xmlSchemaFreeValidCtxt(vctx);
+
+ if(ctx != NULL)
+ xmlSchemaFreeParserCtxt(ctx);
+
+ if(xschema != NULL)
+ xmlSchemaFree(xschema);
+
+ return ret;
+}
--- /dev/null
+#ifndef __PKGMGR_PARSER_RESOURCE_H_
+#define __PKGMGR_PARSER_RESOURCE_H_
+
+#include <bundle.h>
+#include <glib.h>
+#include "pkgmgr_parser.h"
+#include "pkgmgrinfo_resource.h"
+
+#define PKGMGR_RSC_GROUP_TYPE_IMAGE "image"
+#define PKGMGR_RSC_GROUP_TYPE_LAYOUT "layout"
+#define PKGMGR_RSC_GROUP_TYPE_SOUND "sound"
+#define PKGMGR_RSC_GROUP_TYPE_BIN "bin"
+
+#define RSC_NODE_ATTR_SCREEN_DPI "screen-dpi"
+#define RSC_NODE_ATTR_SCREEN_DPI_RANGE "screen-dpi-range"
+#define RSC_NODE_ATTR_SCREEN_WIDTH_RANGE "screen-width-range"
+#define RSC_NODE_ATTR_SCREEN_LARGE "screen-large"
+#define RSC_NODE_ATTR_SCREEN_BPP "screen-bpp"
+#define RSC_NODE_ATTR_PLATFORM_VER "platform-version"
+#define RSC_NODE_ATTR_LANGUAGE "language"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @fn int *pkgmgr_resource_parser_open(const char *fname, const char *package, resource_data_t **data)
+ * @brief This API initialize parses res.xml which identified by fname and package and put it into data.
+ *
+ * @par This API is for package-manager installer backends.
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in] fname pointer to xml filename
+ * @param[in] pacakage pointer to packageID
+ * @param[out]data pointer of pointer to resource_data type structure.
+ * @return 0 on succeed and -1 on failure, -2 on invalid parameter
+ */
+API int pkgmgr_resource_parser_open(const char *fname, const char *package, resource_data_t **data);
+
+/**
+ * @fn int pkgmgr_resource_parser_close(resource_data_t data)
+ * @brief This API frees given data and its own variables
+ *
+ * @par This API is for package-manager installer backends.
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in] data structure of resource_data_t
+ * @return 0 on succeed and -1 on failure, -2 on invalid parameter
+ */
+API int pkgmgr_resource_parser_close(resource_data_t *data);
+
+/**
+ * @fn int pkgmgr_resource_parser_insert_into_db(resource_data_t *data)
+ * @brief This API will put given data into db
+ *
+ * @par This API is for package-manager installer backends.
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in] data structure to be inserted into db
+ * @return 0 on succeed and -1 on failure, -2 on invalid parameter
+ */
+API int pkgmgr_resource_parser_insert_into_db(resource_data_t *data);
+
+/**
+ * @fn int pkgmgr_resource_parser_open_from_db(const char *package, resource_data_t **data)
+ * @brief This API will get resource data of specific package from db
+ *
+ * @par This API is for applications.
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in] package packageID
+ * @param[out]data resource_data type structure. it will filled with resource data
+ * @return 0 on succeed and -1 on failure, -2 on invalid parameter
+ */
+API int pkgmgr_resource_parser_open_from_db(const char *package, resource_data_t **data);
+
+/**
+ * @fn int pkgmgr_resource_parser_check_xml_validation(const char *xmlfile)
+ * @brief This API will validates given resource manifest file
+ *
+ * @par This API is for package-manager installer backends.
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in] manifest manifest filepath to be validated
+ * @return 0 on succeed and -1 on failure, -2 on invalid parameter
+ */
+API int pkgmgr_resource_parser_check_xml_validation(const char *xmlfile);
+
+/**
+ * @fn int pkgmgr_resource_parser_delete_from_db(const char *package)
+ * @brief This API will remove resource data from package_resource_info, package_resource_data
+ *
+ * @par This API is for package-manager installer backends.
+ * @par Sync (or) Async : Synchronous API
+ *
+ * @param[in] package packageID
+ * @return 0 on succeed and -1 on failure, -2 on invalid parameter
+ */
+API int pkgmgr_resource_parser_delete_from_db(const char *package);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
--- /dev/null
+/*
+ * pkgmgr-info
+ *
+ * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>,
+ * Jaeho Lee <jaeho81.lee@samsung.com>, Shobhit Srivastava <shobhit.s@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <db-util.h>
+#include <glib.h>
+#include <dlfcn.h>
+#include <bundle.h>
+
+#include "pkgmgr-info.h"
+#include "pkgmgr-info-debug.h"
+#include "pkgmgr_parser_db.h"
+#include "pkgmgr_parser_internal.h"
+#include "pkgmgr_parser_resource.h"
+#include "pkgmgr_parser_resource_db.h"
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "PKGMGR_PARSER"
+
+#define BUF_SIZE 1024
+#define PKGMGR_PARSER_DB_FILE tzplatform_mkpath(TZ_USER_DB, ".pkgmgr_parser.db")
+
+enum {
+ NODE_ATTR_MIN = 0,
+ NODE_ATTR_SCREEN_DPI,
+ NODE_ATTR_SCREEN_DPI_RANGE,
+ NODE_ATTR_SCREEN_WIDTH_RANGE,
+ NODE_ATTR_SCREEN_LARGE,
+ NODE_ATTR_SCREEN_BPP,
+ NODE_ATTR_PLATFORM_VER,
+ NODE_ATTR_LANGUAGE,
+ NODE_ATTR_MAX,
+};
+
+static int _get_attr_val(bundle *b, char **attr_name, const char **attr_val, int attr_index)
+{
+ char *buf = NULL;
+ if (b == NULL) {
+ _LOGE("bundle is null");
+ return PMINFO_R_EINVAL;
+ }
+
+ buf = malloc(BUF_SIZE);
+ if (buf == NULL) {
+ _LOGE("malloc failed");
+ return PMINFO_R_ERROR;
+ }
+ memset(buf, '\0', BUF_SIZE);
+ switch (attr_index) {
+ case NODE_ATTR_SCREEN_DPI:
+ snprintf(buf, BUF_SIZE, "%s", RSC_NODE_ATTR_SCREEN_DPI);
+ *attr_val = bundle_get_val(b, RSC_NODE_ATTR_SCREEN_DPI);
+ break;
+ case NODE_ATTR_SCREEN_DPI_RANGE:
+ snprintf(buf, BUF_SIZE, "%s", RSC_NODE_ATTR_SCREEN_DPI_RANGE);
+ *attr_val = bundle_get_val(b, RSC_NODE_ATTR_SCREEN_DPI_RANGE);
+ break;
+ case NODE_ATTR_SCREEN_WIDTH_RANGE:
+ snprintf(buf, BUF_SIZE, "%s", RSC_NODE_ATTR_SCREEN_WIDTH_RANGE);
+ *attr_val = bundle_get_val(b, RSC_NODE_ATTR_SCREEN_WIDTH_RANGE);
+ break;
+ case NODE_ATTR_SCREEN_LARGE:
+ snprintf(buf, BUF_SIZE, "%s", RSC_NODE_ATTR_SCREEN_LARGE);
+ *attr_val = bundle_get_val(b, RSC_NODE_ATTR_SCREEN_LARGE);
+ break;
+ case NODE_ATTR_SCREEN_BPP:
+ snprintf(buf, BUF_SIZE, "%s", RSC_NODE_ATTR_SCREEN_BPP);
+ *attr_val = bundle_get_val(b, RSC_NODE_ATTR_SCREEN_BPP);
+ break;
+ case NODE_ATTR_PLATFORM_VER:
+ snprintf(buf, BUF_SIZE, "%s", RSC_NODE_ATTR_PLATFORM_VER);
+ *attr_val = bundle_get_val(b, RSC_NODE_ATTR_PLATFORM_VER);
+ break;
+ case NODE_ATTR_LANGUAGE:
+ snprintf(buf, BUF_SIZE, "%s", RSC_NODE_ATTR_LANGUAGE);
+ *attr_val = bundle_get_val(b, RSC_NODE_ATTR_LANGUAGE);
+ break;
+ default:
+ _LOGE("unidentified index[%d]", attr_index);
+ free(buf);
+ buf = NULL;
+ return PMINFO_R_ERROR;
+ }
+
+ if (buf != NULL && strlen(buf) != 0)
+ *attr_name = buf;
+
+ return PMINFO_R_OK;
+}
+
+static int _insert_node_data_into_db(sqlite3 *pkginfo, const char *package, char *group_type, GList *node_list)
+{
+ char *query = NULL;
+ resource_node_t *rsc_node = NULL;
+ GList *tmp_node_list = NULL;
+ bundle *b = NULL;
+ const char *attr_val = NULL;
+ char *attr_name = NULL;
+ int i;
+ int ret = -1;
+
+ if (pkginfo == NULL || package == NULL || strlen(package) == 0 || group_type == NULL || strlen(group_type) == 0 || node_list == NULL)
+ return PMINFO_R_EINVAL;
+
+ tmp_node_list = g_list_first(node_list);
+
+ if (tmp_node_list == NULL) {
+ _LOGE("list is null");
+ return PMINFO_R_ERROR;
+ }
+
+ while (tmp_node_list != NULL) {
+ rsc_node = (resource_node_t *)tmp_node_list->data;
+ if (rsc_node == NULL) {
+ _LOGE("node is null");
+ return PMINFO_R_ERROR;
+ }
+
+ /*get bundle for each nodes*/
+ b = rsc_node->attr;
+ if (b == NULL) {
+ _LOGE("bundle is null");
+ return PMINFO_R_ERROR;
+ }
+
+ for (i = NODE_ATTR_MIN + 1; i < NODE_ATTR_MAX; i++) {
+ ret = _get_attr_val(b, &attr_name, &attr_val, i);
+ if (ret != 0) {
+ _LOGE("get attribute from bundle failed");
+ return ret;
+ }
+
+ if (attr_name == NULL || attr_val == NULL)
+ continue;
+ query = sqlite3_mprintf("insert into package_resource_data(id, node_folder, attr_name, attr_value) VALUES(" \
+ "(select rowid from package_resource_info where pkg_id=%Q and group_type=%Q), %Q, %Q, %Q)", package, group_type, rsc_node->folder, attr_name, attr_val);
+
+ /*Begin transaction*/
+ ret = sqlite3_exec(pkginfo, query, NULL, NULL, NULL);
+ if (ret != SQLITE_OK)
+ _LOGE("Failed to insert into package_resource_data, attr_name[%s], attr_val[%s]", attr_name, attr_val);
+ sqlite3_free(query);
+ query = NULL;
+ free(attr_name);
+ attr_name = NULL;
+ attr_val = NULL;
+ }
+ tmp_node_list = g_list_next(tmp_node_list);
+ }
+
+ return ret;
+}
+
+int pkgmgr_parser_resource_db_remove(const char *package)
+{
+ sqlite3 *pkginfo = NULL;
+ char *query = NULL;
+ int ret = -1;
+
+ if (package == NULL) {
+ _LOGE("parameter is NULL");
+ return PMINFO_R_EINVAL;
+ }
+
+ /*db open*/
+ ret = db_util_open(PKGMGR_PARSER_DB_FILE, &pkginfo, 0);
+ retvm_if(ret != SQLITE_OK, PMINFO_R_ERROR, "connect db [%s] failed!", PKGMGR_PARSER_DB_FILE);
+
+ /*Begin transaction*/
+ ret = sqlite3_exec(pkginfo, "BEGIN EXCLUSIVE", NULL, NULL, NULL);
+ tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Failed to begin transaction\n");
+ _LOGD("Transaction Begin\n");
+
+ /*delete data from package_resource_data*/
+ query = sqlite3_mprintf("delete from package_resource_data where id in (select rowid from package_resource_info where pkg_id=%Q)", package);
+ ret = sqlite3_exec(pkginfo, query, NULL, NULL, NULL);
+ tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Failed to delete from package_resource_info");
+ sqlite3_free(query);
+ query = NULL;
+
+ /*delete data from package_resource_info*/
+ query = sqlite3_mprintf("delete from package_resource_info where pkg_id=%Q", package);
+ ret = sqlite3_exec(pkginfo, query, NULL, NULL, NULL);
+ tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Failed to delete from package_resource_info");
+
+ /*Commit transaction*/
+ ret = sqlite3_exec(pkginfo, "COMMIT", NULL, NULL, NULL);
+ if (ret != SQLITE_OK) {
+ _LOGE("Failed to commit transaction. Rollback now\n");
+ ret = sqlite3_exec(pkginfo, "ROLLBACK", NULL, NULL, NULL);
+ tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Don't execute query = %s\n", query);
+ }
+ _LOGD("Transaction Commit and End\n");
+
+ ret = PMINFO_R_OK;
+catch:
+ sqlite3_close(pkginfo);
+ sqlite3_free(query);
+
+ return ret;
+}
+
+int pkgmgr_parser_resource_db_save(const char *package, resource_data_t *data)
+{
+ sqlite3 *pkginfo = NULL;
+ char *query = NULL;
+ int ret = -1;
+ GList *group_list = NULL;
+ GList *node_list = NULL;
+ resource_group_t *rsc_group = NULL;
+
+ if (package == NULL || strlen(package) == 0 || data == NULL) {
+ _LOGE("invalid parameter");
+ return -1;
+ }
+
+ ret = pkgmgr_parser_check_and_create_db(getuid());
+ if (ret == 0)
+ ret = pkgmgr_parser_initialize_db();
+ if (ret < 0) {
+ _LOGE("db initialization failed");
+ goto catch;
+ }
+
+
+ group_list = g_list_first(data->group_list);
+ /*db open*/
+ ret = db_util_open(PKGMGR_PARSER_DB_FILE, &pkginfo, 0);
+ retvm_if(ret != SQLITE_OK, PMINFO_R_ERROR, "connect db [%s] failed!", PKGMGR_PARSER_DB_FILE);
+
+ /*Begin transaction*/
+ ret = sqlite3_exec(pkginfo, "BEGIN EXCLUSIVE", NULL, NULL, NULL);
+ tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Failed to begin transaction\n");
+ _LOGD("Transaction Begin\n");
+
+ while (group_list != NULL) {
+ rsc_group = NULL;
+ node_list = NULL;
+
+ rsc_group = (resource_group_t *)group_list->data;
+ node_list = g_list_first(rsc_group->node_list);
+
+ if (rsc_group == NULL || node_list == NULL) {
+ _LOGE("value is null");
+ ret = -1;
+ goto catch;
+ }
+
+ query = sqlite3_mprintf("insert into package_resource_info(pkg_id, group_folder, group_type) VALUES(%Q, %Q, %Q)", \
+ package, rsc_group->folder, rsc_group->type);
+
+ /*Begin transaction*/
+ ret = sqlite3_exec(pkginfo, query, NULL, NULL, NULL);
+ tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Failed to insert into package_resource_info");
+ sqlite3_free(query);
+ query = NULL;
+
+ ret = _insert_node_data_into_db(pkginfo, package, rsc_group->type, node_list);
+
+ group_list = g_list_next(group_list);
+ }
+
+ /*Commit transaction*/
+ ret = sqlite3_exec(pkginfo, "COMMIT", NULL, NULL, NULL);
+ if (ret != SQLITE_OK) {
+ _LOGE("Failed to commit transaction. Rollback now\n");
+ ret = sqlite3_exec(pkginfo, "ROLLBACK", NULL, NULL, NULL);
+ tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "Don't execute query = %s\n", query);
+ }
+ _LOGD("Transaction Commit and End\n");
+
+ ret = PMINFO_R_OK;
+
+
+catch:
+ pkgmgr_parser_close_db();
+ sqlite3_close(pkginfo);
+ sqlite3_free(query);
+
+ return ret;
+
+}
+
+static gint _find_group_type(void *group, void *data)
+{
+ resource_group_t *rsc_group = (resource_group_t *)group;
+
+ return strcmp(rsc_group->type, (char *)data);
+}
+
+static gint _find_node_folder(void *node, void *data)
+{
+ resource_node_t *rsc_node = (resource_node_t *)node;
+ char *str = (char *)data;
+
+ return strcmp(rsc_node->folder, str);
+}
+
+static int _init_node(char *node_folder, resource_node_t **rsc_node)
+{
+ resource_node_t *tmp_node = NULL;
+
+ if (node_folder == NULL) {
+ _LOGE("invalid parameter");
+ return PMINFO_R_EINVAL;
+ }
+
+ tmp_node = malloc(sizeof(resource_node_t));
+ if (tmp_node == NULL) {
+ _LOGE("malloc failed");
+ return PMINFO_R_ERROR;
+ }
+
+ tmp_node->folder = strdup(node_folder);
+ tmp_node->attr = bundle_create();
+ *rsc_node = tmp_node;
+
+ return PMINFO_R_OK;
+}
+
+static int _init_group(char *group_type, resource_group_t **rsc_group)
+{
+ resource_group_t *tmp_group = NULL;
+
+ if (group_type == NULL) {
+ _LOGE("invalid parameter");
+ return PMINFO_R_EINVAL;
+ }
+
+ tmp_group = malloc(sizeof(resource_group_t));
+ if (tmp_group == NULL) {
+ _LOGE("malloc failed");
+ return PMINFO_R_ERROR;
+ }
+
+ tmp_group->type = strdup(group_type);
+ tmp_group->node_list = NULL;
+ *rsc_group = tmp_group;
+
+ return PMINFO_R_OK;
+}
+
+int pkgmgr_parser_resource_db_load(const char *package, resource_data_t **data)
+{
+ sqlite3 *pkginfo = NULL;
+ sqlite3_stmt *stmt = NULL;
+ char *query = NULL;
+ char *colname = NULL;
+ char *group_type = NULL;
+ char *group_folder = NULL;
+ char *node_folder = NULL;
+ char *attr_name = NULL;
+ char *attr_value = NULL;
+ int ret = -1;
+ int cols = 0;
+ int i;
+ resource_data_t *rsc_data = NULL;
+ resource_group_t *rsc_group = NULL;
+ resource_node_t *rsc_node = NULL;
+ GList *group_list = NULL;
+ GList *node_list = NULL;
+ GList *tmp_group_list = NULL;
+ GList *tmp_node_list = NULL;
+
+ ret = db_util_open(PKGMGR_PARSER_DB_FILE, &pkginfo, 0);
+ retvm_if(ret != SQLITE_OK, PMINFO_R_ERROR, "connect db [%s] failed!", PKGMGR_PARSER_DB_FILE);
+ query = sqlite3_mprintf("select " \
+ "package_resource_info.group_type, package_resource_info.group_folder, package_resource_data.node_folder, package_resource_data.attr_name, package_resource_data.attr_value " \
+ "from package_resource_info, package_resource_data where " \
+ "package_resource_info.rowid=package_resource_data.id and " \
+ "package_resource_info.pkg_id=%Q order by package_resource_data.rowid asc", \
+ package);
+ ret = sqlite3_prepare_v2(pkginfo, query, strlen(query), &stmt, NULL);
+ tryvm_if(ret != SQLITE_OK, ret = PMINFO_R_ERROR, "sqlite3_prepare_v2 query = %s\n", query);
+ cols = sqlite3_column_count(stmt);
+
+ while (1) {
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_ROW)
+ break;
+ tmp_group_list = NULL;
+ tmp_node_list = NULL;
+ rsc_group = NULL;
+ rsc_node = NULL;
+
+ for (i = 0; i < cols; i++) {
+ colname = (char *)sqlite3_column_name(stmt, i);
+ if (strcmp(colname, "group_type") == 0) {
+ /*group_type*/
+ group_type = (char *)sqlite3_column_text(stmt, i);
+ tmp_group_list = g_list_find_custom(group_list, group_type, (GCompareFunc)_find_group_type);
+ if (tmp_group_list == NULL) {
+ ret = _init_group(group_type, &rsc_group);
+ if (ret != PMINFO_R_OK) {
+ _LOGE("group initialization failed[%d]", ret);
+ goto catch;
+ }
+ group_list = g_list_append(group_list, rsc_group);
+ node_list = NULL;
+ } else {
+ rsc_group = (resource_group_t *)tmp_group_list->data;
+ node_list = rsc_group->node_list;
+ }
+ } else if (strcmp(colname, "group_folder") == 0) {
+ /*group_folder*/
+ group_folder = (char *)sqlite3_column_text(stmt, i);
+ if (rsc_group->folder != NULL && strcmp(rsc_group->folder, group_folder) == 0)
+ continue;
+ else if (rsc_group != NULL && group_folder != NULL)
+ rsc_group->folder = strdup(group_folder);
+ else {
+ _LOGE("rsc_group and group_folder should not be null");
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+ } else if (strcmp(colname, "node_folder") == 0) {
+ /*node_folder*/
+ node_folder = (char *)sqlite3_column_text(stmt, i);
+ tmp_node_list = g_list_find_custom(node_list, node_folder, (GCompareFunc)_find_node_folder);
+ if (tmp_node_list == NULL) {
+ ret = _init_node(node_folder, &rsc_node);
+ /*initialize new node*/
+ if (ret != PMINFO_R_OK) {
+ _LOGE("node initialization failed[%d]", ret);
+ goto catch;
+ }
+ node_list = g_list_append(node_list, rsc_node);
+ if (rsc_group->node_list == NULL)
+ rsc_group->node_list = node_list;
+ } else
+ rsc_node = (resource_node_t *)tmp_node_list->data;
+ } else if (strcmp(colname, "attr_name") == 0) {
+ /*attr_name*/
+ attr_name = (char *)sqlite3_column_text(stmt, i);
+ } else if (strcmp(colname, "attr_value") == 0) {
+ /*attr_value*/
+ attr_value = (char *)sqlite3_column_text(stmt, i);
+ if (rsc_node != NULL && attr_name != NULL && attr_value != NULL) {
+ if (rsc_node->attr != NULL)
+ bundle_add(rsc_node->attr, attr_name, attr_value);
+ else {
+ _LOGE("bundle is not initialized");
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+ } else {
+ _LOGE("error happened");
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+ } else {
+ /*error handling*/
+ _LOGE("unexpected column name detected:[%s]", colname);
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+ }
+ }
+ if (ret == SQLITE_DONE)
+ ret = PMINFO_R_OK;
+
+ rsc_data = malloc(sizeof(resource_data_t));
+ if (rsc_data == NULL) {
+ _LOGD("malloc failed");
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+ rsc_data->group_list = group_list;
+ rsc_data->package = strdup(package);
+ /*set return data*/
+ *data = rsc_data;
+catch:
+ sqlite3_close(pkginfo);
+ sqlite3_free(query);
+
+ return ret;
+}
--- /dev/null
+#ifndef __PKGMGR_PARSER_RESOURCE_DB_H_
+#define __PKGMGR_PARSER_RESOURCE_DB_H_
+
+#include "pkgmgrinfo_resource.h"
+#include "pkgmgr_parser.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int pkgmgr_parser_resource_db_save(const char *package, resource_data_t *data);
+int pkgmgr_parser_resource_db_load(const char *package, resource_data_t **data);
+int pkgmgr_parser_resource_db_remove(const char *package);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
+ targetNamespace="http://tizen.org/ns/rm" xmlns:packages="http://tizen.org/ns/rm">
+ <xs:import namespace="http://www.w3.org/XML/1998/namespace"/>
+ <xs:element name="res">
+ <xs:complexType>
+ <xs:all>
+ <xs:element name="group-image" type="packages:GroupContainer" maxOccurs="1" minOccurs="0"/>
+ <xs:element name="group-layout" type="packages:GroupContainer" maxOccurs="1" minOccurs="0"/>
+ <xs:element name="group-sound" type="packages:GroupContainer" maxOccurs="1" minOccurs="0"/>
+ <xs:element name="group-bin" type="packages:GroupContainer" maxOccurs="1" minOccurs="0"/>
+ </xs:all>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:complexType name="GroupContainer">
+ <xs:sequence>
+ <xs:element name="node" maxOccurs="unbounded" minOccurs="0">
+ <xs:complexType>
+ <xs:attribute name="folder" type="xs:string" use="required"/>
+ <xs:attribute name="screen-dpi" type="xs:integer"/>
+ <xs:attribute name="screen-dpi-range" type="xs:string"/>
+ <xs:attribute name="screen-width-range" type="xs:string"/>
+ <xs:attribute name="screen-large" type="xs:boolean"/>
+ <xs:attribute name="screen-bpp" type="xs:integer"/>
+ <xs:attribute name="platform-version" type="xs:string"/>
+ <xs:attribute name="language" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="folder" type="xs:string" use="required"/>
+ </xs:complexType>
+</xs:schema>
\ No newline at end of file
--- /dev/null
+#include "pkgmgr_parser_resource.h"
+
+API int pkgmgrinfo_resource_open(const char *package, resource_data_t **data)
+{
+ return pkgmgr_resource_parser_open_from_db(package, data);
+}
+
+API int pkgmgrinfo_resource_close(resource_data_t *data)
+{
+ return pkgmgr_resource_parser_close(data);
+}
+