2 * Copyright (c) 2011-2015 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <app_manager.h>
19 #include <libxml/parser.h>
23 #include "vc_cmd_db.h"
25 #include "vc_info_parser.h"
27 #include "voice_control_command.h"
28 #include "voice_control_common.h"
31 #define VC_TAG_CMD_BASE_TAG "vc_commands"
33 #define VC_TAG_CMD_COMMAND "command"
34 #define VC_TAG_CMD_ID "cmd_id"
35 #define VC_TAG_CMD_PID "cmd_pid"
36 #define VC_TAG_CMD_TYPE "cmd_type"
37 #define VC_TAG_CMD_FORMAT "cmd_format"
38 #define VC_TAG_CMD_COMMAND_TEXT "cmd_cmd_text"
39 #define VC_TAG_CMD_PARAMETER_TEXT "cmd_param_text"
40 #define VC_TAG_CMD_DOMAIN "cmd_domain"
41 #define VC_TAG_CMD_KEY "cmd_key"
42 #define VC_TAG_CMD_MODIFIER "cmd_modifier"
43 #define VC_TAG_CMD_IS_ACTION "cmd_is_action"
45 #define VC_TAG_RESULT_BASE_TAG "vc_results"
46 #define VC_TAG_RESULT_TEXT "result_text"
47 #define VC_TAG_RESULT_EVENT "result_event"
48 #define VC_TAG_RESULT_MESSAGE "result_message"
50 #define VC_TAG_INFO_BASE_TAG "vc_info_option"
51 #define VC_TAG_INFO_FOREGROUND "foreground_pid"
53 #define VC_TAG_DEMANDABLE_CLIENT_BASE_TAG "vc_demandable_client"
54 #define VC_TAG_DEMANDABLE_CLIENT_APPID "appid"
56 #define VC_TAG_CLIENT_BASE_TAG "vc_client_info"
57 #define VC_TAG_CLIENT_CLIENT "client"
58 #define VC_TAG_CLIENT_PID "pid"
59 #define VC_TAG_CLIENT_FGCMD "fgcmd"
60 #define VC_TAG_CLIENT_BGCMD "bgcmd"
61 #define VC_TAG_CLIENT_EXCMD "excmd"
64 const char* vc_info_tag()
69 int __vc_cmd_parser_print_commands(GSList* cmd_list);
72 static int __vc_info_parser_set_file_mode(const char* filename)
74 if (NULL == filename) {
75 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Invalid parameter");
79 if (0 > chmod(filename, 0600)) {
80 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Fail to change file mode");
86 int vc_cmd_parser_save_file(int pid, vc_cmd_type_e type, GSList* cmd_list, char* invocation_name)
88 if (0 >= g_slist_length(cmd_list)) {
89 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Command list is invalid");
93 int ret = vc_db_insert_commands_list(pid, type, cmd_list, invocation_name, false);
95 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Insert db is failed, ret = %d", ret);
100 int vc_cmd_parser_delete_file(int pid, vc_cmd_type_e type)
106 // Get appid by pid using app control
107 ret = app_manager_get_app_id(pid, &appid);
108 if (APP_MANAGER_ERROR_NONE != ret) {
109 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] fail to get app id, ret(%d)", ret);
111 SLOG(LOG_DEBUG, vc_info_tag(), "Background cmd: appid = %s", appid);
115 ret = vc_db_delete_commands(pid, type, appid);
117 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] get commands from db is failed, ret = %d", ret);
127 int vc_cmd_parser_get_commands(int pid, vc_cmd_type_e type, GSList** cmd_list)
129 int ret = vc_db_get_commands(pid, type, cmd_list);
131 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] get commands from db is failed, ret = %d", ret);
133 __vc_cmd_parser_print_commands(*cmd_list);
137 int vc_cmd_parser_append_commands(int pid, vc_cmd_type_e type, vc_cmd_list_h vc_cmd_list)
139 int ret = vc_db_append_commands(pid, type, vc_cmd_list);
141 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] get commands from db is failed, ret = %d", ret);
143 vc_cmd_print_list(vc_cmd_list);
147 void __vc_info_parser_demandable_client_free(void* data)
149 vc_demandable_client_s* d_client = (vc_demandable_client_s*)data;
151 if (NULL != d_client) {
152 if (NULL != d_client->appid) {
153 free(d_client->appid);
154 d_client->appid = NULL;
161 int vc_info_parser_get_demandable_clients(GSList** client_list)
164 xmlDocPtr doc = NULL;
165 xmlNodePtr cur = NULL;
168 doc = xmlParseFile(VC_RUNTIME_INFO_DEMANDABLE_LIST);
170 SECURE_SLOG(LOG_WARN, vc_info_tag(), "[WARNING] Fail to parse file error : %s", VC_RUNTIME_INFO_FOREGROUND);
174 cur = xmlDocGetRootElement(doc);
176 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Empty document");
181 if (xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_DEMANDABLE_CLIENT_BASE_TAG)) {
182 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] The wrong type, root node is NOT '%s'", VC_TAG_DEMANDABLE_CLIENT_BASE_TAG);
187 cur = cur->xmlChildrenNode;
189 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Empty document");
194 GSList* temp_client_list = NULL;
196 while (cur != NULL) {
197 if (0 == xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_DEMANDABLE_CLIENT_APPID)) {
198 key = xmlNodeGetContent(cur);
200 SLOG(LOG_DEBUG, vc_info_tag(), "App id : %s", (char *)key);
202 vc_demandable_client_s* temp_client;
203 temp_client = (vc_demandable_client_s*)calloc(1, sizeof(vc_demandable_client_s));
205 if (NULL == temp_client) {
206 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Memory alloc error!!");
208 if (NULL != temp_client_list) {
209 g_slist_free_full(temp_client_list, __vc_info_parser_demandable_client_free);
210 temp_client_list = NULL;
217 if (0 < xmlStrlen(key)) {
218 temp_client->appid = strdup((char*)key);
220 /* NULL for appid is available */
221 temp_client->appid = NULL;
225 temp_client_list = g_slist_append(temp_client_list, temp_client);
227 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] enable is NULL");
235 *client_list = temp_client_list;
237 if (0 != remove(VC_RUNTIME_INFO_DEMANDABLE_LIST)) {
238 SLOG(LOG_WARN, vc_info_tag(), "[WARNING] remove file(%s) is failed", VC_RUNTIME_INFO_DEMANDABLE_LIST);
244 int vc_info_parser_set_demandable_client(const char* filepath)
246 if (NULL == filepath) {
247 if (0 != remove(VC_RUNTIME_INFO_DEMANDABLE_LIST)) {
248 SLOG(LOG_WARN, vc_info_tag(), "[WARNING] remove file(%s) is failed", VC_RUNTIME_INFO_DEMANDABLE_LIST);
254 xmlDocPtr doc = NULL;
255 xmlNodePtr cur = NULL;
258 doc = xmlParseFile(filepath);
260 SECURE_SLOG(LOG_WARN, vc_info_tag(), "[WARNING] Fail to parse file error : %s", filepath);
264 cur = xmlDocGetRootElement(doc);
266 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Empty document");
271 if (xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_DEMANDABLE_CLIENT_BASE_TAG)) {
272 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] The wrong type, root node is NOT '%s'", VC_TAG_DEMANDABLE_CLIENT_BASE_TAG);
277 cur = cur->xmlChildrenNode;
279 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Empty document");
284 while (cur != NULL) {
285 if (0 == xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_DEMANDABLE_CLIENT_APPID)) {
286 key = xmlNodeGetContent(cur);
288 SLOG(LOG_DEBUG, vc_info_tag(), "App id : %s", (char *)key);
291 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] enable is NULL");
299 int ret = xmlSaveFormatFile(VC_RUNTIME_INFO_DEMANDABLE_LIST, doc, 1);
300 SLOG(LOG_DEBUG, vc_info_tag(), "Save demandable file info : %d", ret);
306 int vc_info_parser_set_result(const char* result_text, int event, const char* msg, vc_cmd_list_h vc_cmd_list, bool exclusive)
308 char* temp_text = NULL;
309 if (NULL == result_text) {
310 temp_text = strdup("#NULL");
312 temp_text = strdup(result_text);
315 int ret = vc_db_insert_result(temp_text, event, msg, vc_cmd_list, exclusive);
317 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Insert db is failed, ret = %d", ret);
319 SLOG(LOG_DEBUG, vc_info_tag(), "[Success] Save result command file");
321 if (NULL != temp_text) {
329 int vc_info_parser_get_result(char** result_text, int* event, char** result_message, int pid, vc_cmd_list_h vc_cmd_list, bool exclusive)
331 if (NULL == result_text || NULL == event || NULL == vc_cmd_list) {
332 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Input parameter is NULL");
336 char* temp_text = NULL;
337 int ret = vc_db_get_result(&temp_text, event, result_message, pid, vc_cmd_list, exclusive);
339 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Insert db is failed, ret = %d", ret);
342 if (NULL == temp_text || !strcmp(temp_text, "#NULL")) {
345 *result_text = strdup(temp_text);
348 if (NULL != temp_text) {
356 int vc_info_parser_unset_result(bool exclusive)
359 ret = vc_db_delete_table(VC_RESULT_TABLE);
361 SLOG(LOG_DEBUG, vc_info_tag(), "[ERROR] Fail to delete result table");
366 static int __is_symbolic_link(const char* path, bool* is_symbolic)
369 int ret = VC_ERROR_NONE;
371 char real_path[PATH_MAX];
372 SLOG(LOG_DEBUG, vc_info_tag(), "[DEBUG] path: %s ", path);
373 if (realpath(path, real_path) != NULL) {
374 if (strncmp(path, real_path, strlen(path) + 1) == 0) {
375 SLOG(LOG_DEBUG, vc_info_tag(), "[DEBUG] %s is real file, not symbolic link", path);
376 *is_symbolic = false;
378 char current_working_directory[PATH_MAX/2];
379 char temp_path[PATH_MAX];
380 if (getcwd(current_working_directory, PATH_MAX/2)) {
381 if (strlen(current_working_directory) + strlen(path) <= PATH_MAX) {
382 snprintf(temp_path, PATH_MAX, "%s/%s", current_working_directory, path);
383 if (strncmp(temp_path, real_path, strlen(temp_path) + 1) == 0) {
384 SLOG(LOG_DEBUG, vc_info_tag(), "[DEBUG] %s is real file, not symbolic link", path);
385 *is_symbolic = false;
391 if (*is_symbolic == true)
392 SLOG(LOG_ERROR, vc_info_tag(), "[INFO] %s is symbolic link", path);
393 return VC_ERROR_NONE;
395 *is_symbolic = false;
396 if (errno == ENOENT) {
397 SLOG(LOG_DEBUG, vc_info_tag(), "[DEBUG] No such file or directory: %s", path);
398 return VC_ERROR_OPERATION_REJECTED;
400 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] error is %d", errno);
401 return VC_ERROR_OPERATION_FAILED;
407 int vc_info_parser_set_nlu_result(const char* nlu_result)
409 if (NULL == nlu_result) {
410 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] nlu result is NULL");
414 if (0 != remove(VC_RUNTIME_INFO_NLU_RESULT)) {
415 SLOG(LOG_WARN, vc_info_tag(), "[WARNING] remove file(%s) is failed", VC_RUNTIME_INFO_NLU_RESULT);
418 SLOG(LOG_DEBUG, vc_info_tag(), "[RESULT] %s", nlu_result);
423 bool is_symbolic = true;
424 int ret = __is_symbolic_link(VC_RUNTIME_INFO_NLU_RESULT, &is_symbolic);
425 if (is_symbolic || VC_ERROR_OPERATION_FAILED == ret) {
426 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Fail to open file, it is symbolic link : %s", VC_RUNTIME_INFO_NLU_RESULT);
430 fp = fopen(VC_RUNTIME_INFO_NLU_RESULT, "w+");
432 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Fail to open file %s", VC_RUNTIME_INFO_NLU_RESULT);
437 fprintf(fp, "size(%d)\n", (int)strlen(nlu_result));
439 write_size = fwrite(nlu_result, 1, strlen(nlu_result), fp);
442 if (0 >= write_size) {
443 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Fail to write file");
447 if (0 != __vc_info_parser_set_file_mode(VC_RUNTIME_INFO_NLU_RESULT)) {
448 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Fail to set file mode - %s", VC_RUNTIME_INFO_NLU_RESULT);
451 SLOG(LOG_DEBUG, vc_info_tag(), "[SUCCESS] Write file (%s) size (%zu)", VC_RUNTIME_INFO_NLU_RESULT, strlen(nlu_result));
456 int vc_info_parser_get_nlu_result(char** nlu_result)
458 if (NULL == nlu_result) {
459 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] nlu_result is NULL");
466 fp = fopen(VC_RUNTIME_INFO_NLU_RESULT, "r");
468 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Fail to open file %s", VC_RUNTIME_INFO_NLU_RESULT);
473 ret = fscanf(fp, "size(%d)\n", &readn);
475 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Fail to get buffer size");
480 SLOG(LOG_DEBUG, vc_info_tag(), "[DEBUG] buffer size (%d)", readn);
481 if (10000000 < readn || 0 > readn) {
482 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Invalid buffer size");
486 int tmp_readn = readn + 10;
488 *nlu_result = (char*)calloc(tmp_readn, sizeof(char));
489 if (NULL == *nlu_result) {
490 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Out of memory");
495 readn = fread(*nlu_result, 1, readn, fp);
498 SLOG(LOG_DEBUG, vc_info_tag(), "[DEBUG] Read buffer (%d)", readn);
500 /* remove(VC_RUNTIME_INFO_NLU_RESULT); */
505 int vc_info_parser_get_result_pid_list(GSList** pid_list, const char* result)
507 int ret = vc_db_get_result_pid_list(result, pid_list);
509 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Fail to delete result table");
515 int vc_info_parser_set_client_info(GSList* client_info_list)
517 if (0 >= g_slist_length(client_info_list)) {
518 SLOG(LOG_WARN, vc_info_tag(), "[WARNING] client list is empty");
523 if (0 != remove(VC_RUNTIME_INFO_CLIENT)) {
524 SLOG(LOG_WARN, vc_info_tag(), "[WARNING] remove file(%s) is failed", VC_RUNTIME_INFO_CLIENT);
528 xmlNodePtr root_node;
529 xmlNodePtr client_node;
532 doc = xmlNewDoc((const xmlChar*)"1.0");
534 root_node = xmlNewNode(NULL, (const xmlChar*)VC_TAG_CLIENT_BASE_TAG);
535 xmlDocSetRootElement(doc, root_node);
538 vc_client_info_s *client = NULL;
541 int count = g_slist_length(client_info_list);
542 iter = g_slist_nth(client_info_list, 0);
544 SLOG(LOG_DEBUG, vc_info_tag(), "client count : %d", count);
545 char temp[16] = {0, };
547 for (i = 0; i < count; i++) {
553 if (NULL != client) {
554 SLOG(LOG_DEBUG, vc_info_tag(), "[%dth] pid(%d) fgcmd(%d) bgcmd(%d) excmd(%d)",
555 i, client->pid, client->fg_cmd, client->bg_cmd, client->exclusive_cmd);
557 /* Make new client node */
558 client_node = xmlNewNode(NULL, (const xmlChar*)VC_TAG_CLIENT_CLIENT);
561 snprintf(temp, 16, "%d", client->pid);
563 tmp_node = xmlNewNode(NULL, (const xmlChar*)VC_TAG_CLIENT_PID);
564 xmlNodeSetContent(tmp_node, (const xmlChar *)temp);
565 xmlAddChild(client_node, tmp_node);
568 snprintf(temp, 16, "%d", client->fg_cmd);
570 tmp_node = xmlNewNode(NULL, (const xmlChar*)VC_TAG_CLIENT_FGCMD);
571 xmlNodeSetContent(tmp_node, (const xmlChar *)temp);
572 xmlAddChild(client_node, tmp_node);
575 snprintf(temp, 16, "%d", client->bg_cmd);
577 tmp_node = xmlNewNode(NULL, (const xmlChar*)VC_TAG_CLIENT_BGCMD);
578 xmlNodeSetContent(tmp_node, (const xmlChar *)temp);
579 xmlAddChild(client_node, tmp_node);
582 snprintf(temp, 16, "%d", client->exclusive_cmd);
584 tmp_node = xmlNewNode(NULL, (const xmlChar*)VC_TAG_CLIENT_EXCMD);
585 xmlNodeSetContent(tmp_node, (const xmlChar *)temp);
586 xmlAddChild(client_node, tmp_node);
588 xmlAddChild(root_node, client_node);
590 iter = g_slist_next(iter);
593 int ret = xmlSaveFormatFile(VC_RUNTIME_INFO_CLIENT, doc, 1);
594 /*xmlFreeDoc(doc); */
596 SLOG(LOG_DEBUG, vc_info_tag(), "[ERROR] Fail to save client file : %d", ret);
600 SLOG(LOG_DEBUG, vc_info_tag(), "[Success] Save client file");
605 int vc_info_parser_get_client_info(GSList** client_info_list)
607 xmlDocPtr doc = NULL;
608 xmlNodePtr cur = NULL;
611 doc = xmlParseFile(VC_RUNTIME_INFO_CLIENT);
613 SLOG(LOG_WARN, vc_info_tag(), "[WARNING] Fail to parse file error : %s", VC_RUNTIME_INFO_CLIENT);
617 cur = xmlDocGetRootElement(doc);
619 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Empty document");
624 if (xmlStrcmp(cur->name, (const xmlChar *)VC_TAG_CLIENT_BASE_TAG)) {
625 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] The wrong type, root node is NOT '%s'", VC_TAG_CLIENT_BASE_TAG);
630 cur = cur->xmlChildrenNode;
632 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Empty document");
637 GSList* temp_client_list = NULL;
639 while (cur != NULL) {
644 } else if (0 == xmlStrcmp(cur->name, (const xmlChar *)"text")) {
648 xmlNodePtr client_node = NULL;
649 client_node = cur->xmlChildrenNode;
650 client_node = client_node->next;
652 vc_client_info_s *client = NULL;
653 client = (vc_client_info_s*)calloc(1, sizeof(vc_client_info_s));
655 if (NULL == client) {
656 SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] Memory alloc error!!");
658 if (NULL != temp_client_list) {
659 g_slist_free_full(temp_client_list, free);
660 temp_client_list = NULL;
667 if (0 == xmlStrcmp(client_node->name, (const xmlChar *)VC_TAG_CLIENT_PID)) {
668 key = xmlNodeGetContent(client_node);
670 SLOG(LOG_DEBUG, vc_info_tag(), "pid : %s", (char *)key);
671 client->pid = atoi((char*)key);
674 SECURE_SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CLIENT_PID);
680 client_node = client_node->next;
681 client_node = client_node->next;
683 /* Foreground command */
684 if (0 == xmlStrcmp(client_node->name, (const xmlChar *)VC_TAG_CLIENT_FGCMD)) {
685 key = xmlNodeGetContent(client_node);
687 SLOG(LOG_DEBUG, vc_info_tag(), "fgcmd : %s", (char *)key);
688 client->fg_cmd = atoi((char*)key);
691 SECURE_SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CLIENT_FGCMD);
697 client_node = client_node->next;
698 client_node = client_node->next;
700 /* Background command */
701 if (0 == xmlStrcmp(client_node->name, (const xmlChar *)VC_TAG_CLIENT_BGCMD)) {
702 key = xmlNodeGetContent(client_node);
704 SLOG(LOG_DEBUG, vc_info_tag(), "bgcmd : %s", (char *)key);
705 client->bg_cmd = atoi((char*)key);
708 SECURE_SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CLIENT_BGCMD);
714 client_node = client_node->next;
715 client_node = client_node->next;
718 if (0 == xmlStrcmp(client_node->name, (const xmlChar *)VC_TAG_CMD_COMMAND_TEXT)) {
719 key = xmlNodeGetContent(client_node);
721 SLOG(LOG_DEBUG, vc_info_tag(), "excmd : %s", (char *)key);
722 client->exclusive_cmd = atoi((char*)key);
725 SECURE_SLOG(LOG_ERROR, vc_info_tag(), "[ERROR] <%s> has no content", VC_TAG_CMD_COMMAND_TEXT);
731 temp_client_list = g_slist_append(temp_client_list, client);
736 *client_info_list = temp_client_list;
741 int __vc_cmd_parser_print_commands(GSList* cmd_list)
743 int count = g_slist_length(cmd_list);
748 iter = g_slist_nth(cmd_list, 0);
750 for (i = 0; i < count; i++) {
757 SLOG(LOG_WARN, vc_info_tag(), "[WARNING] NULL data from command list");
758 iter = g_slist_next(iter);
762 SLOG(LOG_DEBUG, vc_info_tag(), " [%d][%p] PID(%d) ID(%d) Type(%d) Format(%d) Command(%s) Param(%s), Appid(%s), Invocation(%s), Fixed(%s)",
763 i, cmd, cmd->pid, cmd->id, cmd->type, cmd->format, cmd->command, cmd->parameter, cmd->appid, cmd->invocation_name, cmd->fixed);
765 iter = g_slist_next(iter);