--- /dev/null
+//
+// Copyright (c) 2016 Samsung Electronics Co., Ltd.
+//
+// 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 <app_manager.h>
+#include <dlog.h>
+#include <errno.h>
+#include <glib.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <pkgmgr-info.h>
+#include <pkgmgr_installer_info.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <tzplatform_config.h>
+
+/* Define EXPORT_API */
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "stt-engine-parser"
+
+#define STT_TAG_ENGINE_BASE "stt-engine"
+#define STT_TAG_ENGINE_NAME "name"
+#define STT_TAG_ENGINE_ID "id"
+#define STT_TAG_ENGINE_SETTING "setting"
+#define STT_TAG_ENGINE_LANGUAGE_SET "languages"
+#define STT_TAG_ENGINE_LANGUAGE "lang"
+#define STT_TAG_ENGINE_SILENCE_DETECTION_SUPPORT "silence-detection-support"
+#define STT_TAG_ENGINE_CREDENTIAL "credential"
+
+#define STT_CONFIG_BASE tzplatform_mkpath(TZ_USER_HOME, "share/.voice")
+#define STT_HOME tzplatform_mkpath(TZ_USER_HOME, "share/.voice/stt")
+#define STT_ENGINE_BASE tzplatform_mkpath(TZ_USER_HOME, "share/.voice/stt/1.0")
+#define STT_ENGINE_INFO tzplatform_mkpath(TZ_USER_HOME, "/share/.voice/stt/1.0/engine-info")
+
+#define STT_METADATA_LANGUAGE "http://tizen.org/metadata/stt-engine/language"
+#define STT_METADATA_SILENCE_DETECTION "http://tizen.org/metadata/stt-engine/silence-detection"
+#define STT_METADATA_CREDENTIAL_REQUIRED "http://tizen.org/metadata/stt-engine/credential-required"
+
+typedef struct metadata {
+ const char *key;
+ const char *value;
+} metadata;
+
+static xmlDocPtr g_doc;
+
+static int __create_engine_info_xml(const char *pkgid)
+{
+ LOGD("=== Create engine info doc");
+ g_doc = xmlNewDoc((xmlChar*)"1.0");
+ if (NULL == g_doc) {
+ LOGE("[ERROR] Fail to new doc");
+ return -1;
+ }
+ LOGD("===");
+ return 0;
+}
+
+static int __save_engine_info_xml(const char *pkgid)
+{
+ LOGD("=== Save engine info doc");
+ /* Make directories */
+ if (0 != access(STT_CONFIG_BASE, F_OK)) {
+ if (0 != mkdir(STT_CONFIG_BASE, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
+ LOGE("[ERROR] Fail to make directory : %s", STT_CONFIG_BASE);
+ return -1;
+ } else {
+ LOGD("Success to make directory : %s", STT_CONFIG_BASE);
+ }
+ }
+
+ if (0 != access(STT_HOME, F_OK)) {
+ if (0 != mkdir(STT_HOME, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
+ LOGE("[ERROR] Fail to make directory : %s", STT_HOME);
+ return -1;
+ } else {
+ LOGD("Success to make directory : %s", STT_HOME);
+ }
+ }
+
+ if (0 != access(STT_ENGINE_BASE, F_OK)) {
+ if (0 != mkdir(STT_ENGINE_BASE, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
+ LOGE("[ERROR] Fail to make directory : %s", STT_ENGINE_BASE);
+ return -1;
+ } else {
+ LOGD("Success to make directory : %s", STT_ENGINE_BASE);
+ }
+ }
+
+ if (0 != access(STT_ENGINE_INFO, F_OK)) {
+ if (0 != mkdir(STT_ENGINE_INFO, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
+ LOGE("[ERROR] Fail to make directory : %s", STT_ENGINE_INFO);
+ return -1;
+ } else {
+ LOGD("Success to make directory : %s", STT_ENGINE_INFO);
+ }
+ }
+
+ char path[256] = {'\0',};
+ snprintf(path, 256, "%s/%s.xml", STT_ENGINE_INFO, pkgid);
+ int ret = xmlSaveFormatFile(path, g_doc, 1);
+ LOGD("xmlSaveFile (%d)", ret);
+ LOGD("===");
+ return 0;
+}
+
+static int __remove_engine_info_xml(const char *pkgid)
+{
+ LOGD("=== Remove engine info doc");
+ char path[256] = {'\0',};
+ snprintf(path, 256, "%s/%s.xml", STT_ENGINE_INFO, pkgid);
+ if (0 == access(path, F_OK)) {
+ LOGD("Remove engine info xml(%s)", path);
+ remove(path);
+ }
+ LOGD("===");
+ return 0;
+}
+
+static void __insert_language_from_metadata(xmlNodePtr root, const char *language)
+{
+ LOGD("==== Insert language");
+ char* lang = NULL;
+
+ char *tmp_lang, *tmp_free;
+ tmp_free = tmp_lang = strdup(language);
+ xmlNodePtr languages_node = NULL;
+ xmlNodePtr lang_node = NULL;
+
+ languages_node = xmlNewNode(NULL, (const xmlChar*)STT_TAG_ENGINE_LANGUAGE_SET);
+
+ lang = strsep(&tmp_lang, ",");
+ while(NULL != lang) {
+ LOGD("lang (%s)", lang);
+ lang_node = xmlNewNode(NULL, (const xmlChar*)STT_TAG_ENGINE_LANGUAGE);
+ xmlNodeSetContent(lang_node, (const xmlChar*)lang);
+ xmlAddChild(languages_node, lang_node);
+ lang = strsep(&tmp_lang, ",");
+ }
+ xmlAddChild(root, languages_node);
+
+ free(tmp_free);
+}
+
+EXPORT_API
+int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgid, const char *appid, GList *list)
+{
+ LOGD("METADATA INSTALL");
+ LOGD("pkgid(%s) appid(%s) list(%d)", pkgid, appid, g_list_length(list));
+
+ uid_t uid = 0;
+ int ret = -1;
+ ret = pkgmgr_installer_info_get_target_uid(&uid);
+ if (ret < 0 ) {
+ LOGE("[ERROR] Fail to get target uid");
+ return 0;
+ } else {
+ LOGD("uid(%d)", uid);
+ }
+
+ ret = tzplatform_set_user(uid);
+ if (ret < 0) {
+ LOGE("[ERROR] Invalid uid");
+ return 0;
+ } else {
+ LOGD("TZ_USER_HOME: %s", tzplatform_mkstr(TZ_USER_HOME, "/"));
+ }
+
+ if (0 >= g_list_length(list)) {
+ LOGE("[ERROR] No Engine Metadata");
+ return 0;
+ }
+
+ GList *iter = NULL;
+ metadata *md = NULL;
+
+ __create_engine_info_xml(pkgid);
+
+ xmlNodePtr root = NULL;
+ xmlNodePtr cur = NULL;
+
+ root = xmlNewNode(NULL, (const xmlChar*)STT_TAG_ENGINE_BASE);
+ if (NULL == root) {
+ LOGE("[ERROR] Fail to get new node");
+ xmlFreeDoc(g_doc);
+ return -1;
+ }
+ xmlDocSetRootElement(g_doc, root);
+
+ /* Save name */
+ cur = xmlNewNode(NULL, (const xmlChar*)STT_TAG_ENGINE_NAME);
+ xmlNodeSetContent(cur, (const xmlChar*)pkgid);
+ xmlAddChild(root, cur);
+
+ iter = g_list_first(list);
+ while (NULL != iter) {
+ md = (metadata *)iter->data;
+ if (NULL != md && NULL != md->key && NULL != md->value) {
+ LOGD(" - key(%s) value(%s)", md->key, md->value);
+ if (!strcmp(md->key, STT_METADATA_LANGUAGE)) {
+ __insert_language_from_metadata(root, md->value);
+ } else if (!strcmp(md->key, STT_METADATA_SILENCE_DETECTION)) {
+ cur = xmlNewNode(NULL, (const xmlChar*)STT_TAG_ENGINE_SILENCE_DETECTION_SUPPORT);
+ xmlNodeSetContent(cur, (const xmlChar*)md->value);
+ xmlAddChild(root, cur);
+ } else if (!strcmp(md->key, STT_METADATA_CREDENTIAL_REQUIRED)) {
+ cur = xmlNewNode(NULL, (const xmlChar*)STT_TAG_ENGINE_CREDENTIAL);
+ xmlNodeSetContent(cur, (const xmlChar*)md->value);
+ xmlAddChild(root, cur);
+ } else {
+ LOGW("[WARNING] Unknown metadata type");
+ }
+ }
+ iter = g_list_next(iter);
+ }
+
+ cur = xmlNewNode(NULL, (const xmlChar*)STT_TAG_ENGINE_ID);
+ xmlNodeSetContent(cur, (const xmlChar*)appid);
+ xmlAddChild(root, cur);
+
+ LOGD("");
+
+ if (0 != __save_engine_info_xml(pkgid)) {
+ LOGE("[ERROR] Fail to make engine info file");
+ return -1;
+ }
+
+ xmlFreeDoc(g_doc);
+
+ return 0;
+}
+
+EXPORT_API
+int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(const char *pkgid, const char *appid, GList *list)
+{
+ LOGD("METADATA UNINSTALL");
+ LOGD("pkgid(%s) appid(%s) list(%d)", pkgid, appid, g_list_length(list));
+
+ GList *iter = NULL;
+ metadata *md = NULL;
+
+ iter = g_list_first(list);
+ while (NULL != iter) {
+ md = (metadata *)iter->data;
+ LOGD(" - key(%s) value(%s)", md->key, md->value);
+ iter = g_list_next(iter);
+ }
+
+ __remove_engine_info_xml(pkgid);
+
+ LOGD("");
+ return 0;
+}
+
+EXPORT_API
+int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgid, const char *appid, GList *list)
+{
+ LOGD("METADATA UPGRADE");
+ LOGD("pkgid(%s) appid(%s) list(%d)", pkgid, appid, g_list_length(list));
+
+ PKGMGR_MDPARSER_PLUGIN_UNINSTALL(pkgid, appid, list);
+ PKGMGR_MDPARSER_PLUGIN_INSTALL(pkgid, appid, list);
+
+ LOGD("");
+ return 0;
+}