Update version (1.90.2)
[platform/core/uifw/stt.git] / engine-parser / src / stt-engine-parser.c
1 //
2 // Copyright (c) 2016 Samsung Electronics Co., Ltd.
3 //
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
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
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.
15 //
16
17 #include <app_manager.h>
18 #include <dlog.h>
19 #include <errno.h>
20 #include <glib.h>
21 #include <libxml/parser.h>
22 #include <libxml/tree.h>
23 #include <pkgmgr-info.h>
24 #include <pkgmgr_installer_info.h>
25 #include <stdio.h>
26 #include <sys/stat.h>
27 #include <fcntl.h>
28 #include <sys/types.h>
29 #include <tzplatform_config.h>
30
31 #include <gum/gum-user.h>
32 #include <gum/gum-user-service.h>
33 #include <gum/common/gum-user-types.h>
34
35 /* Define EXPORT_API */
36 #ifndef EXPORT_API
37 #define EXPORT_API __attribute__((visibility("default")))
38 #endif
39
40 #ifdef LOG_TAG
41 #undef LOG_TAG
42 #endif
43 #define LOG_TAG "stt-engine-parser"
44
45 #define STT_TAG_ENGINE_BASE                     "stt-engine"
46 #define STT_TAG_ENGINE_NAME                     "name"
47 #define STT_TAG_ENGINE_ID                       "id"
48 #define STT_TAG_ENGINE_SETTING                  "setting"
49 #define STT_TAG_ENGINE_LANGUAGE_SET             "languages"
50 #define STT_TAG_ENGINE_LANGUAGE                 "lang"
51 #define STT_TAG_ENGINE_SILENCE_DETECTION_SUPPORT        "silence-detection-support"
52 #define STT_TAG_ENGINE_CREDENTIAL               "credential"
53
54 #define STT_CONFIG_BASE         tzplatform_mkpath(tzplatform_getid("TZ_USER_HOME"), "share/.voice")
55 #define STT_HOME                tzplatform_mkpath(tzplatform_getid("TZ_USER_HOME"), "share/.voice/stt")
56 #define STT_ENGINE_BASE         tzplatform_mkpath(tzplatform_getid("TZ_USER_HOME"), "share/.voice/stt/1.0")
57 #define STT_ENGINE_INFO         tzplatform_mkpath(tzplatform_getid("TZ_USER_SHARE"), ".voice/stt/1.0/engine-info")
58
59 #define STT_GLOBAL_CONFIG_BASE          "/etc/skel/share/.voice"
60 #define STT_GLOBAL_HOME         "/etc/skel/share/.voice/stt"
61 #define STT_GLOBAL_ENGINE_BASE          "/etc/skel/share/.voice/stt/1.0"
62 #define STT_GLOBAL_ENGINE_INFO          "/etc/skel/share/.voice/stt/1.0/engine-info"
63
64 #define STT_METADATA_LANGUAGE                   "http://tizen.org/metadata/stt-engine/language"
65 #define STT_METADATA_SILENCE_DETECTION          "http://tizen.org/metadata/stt-engine/silence-detection"
66 #define STT_METADATA_CREDENTIAL_REQUIRED        "http://tizen.org/metadata/stt-engine/credential-required"
67 #define STT_METADATA_ENGINE_SETTING             "http://tizen.org/metadata/stt-engine/setting"
68 #define STT_METADATA_ENGINE_NAME                "http://tizen.org/metadata/stt-engine/name"
69
70 /* Define Macro */
71 #define FREE(x) { if (NULL != x)        { free(x);      x = NULL; } }
72 #define G_FREE(x)       { if (NULL != x) { g_free(x);   x = NULL; } }
73
74 typedef struct metadata {
75         const char *key;
76         const char *value;
77 } metadata;
78
79 static xmlDocPtr g_doc;
80 GumUser *g_guser = NULL;
81 uid_t g_uid = 301;      // app_fw
82 gid_t g_gid = 301;      // app_fw
83 GumUserType g_ut = GUM_USERTYPE_NONE;
84 gchar *g_user_type = NULL;
85
86 char *g_dir_config_base = NULL;
87 char *g_dir_home = NULL;
88 char *g_dir_engine_base = NULL;
89 char *g_dir_engine_info = NULL;
90
91
92 static int __create_engine_info_xml(const char *pkgid)
93 {
94         LOGD("=== Create engine info doc");
95         g_doc = xmlNewDoc((xmlChar*)"1.0");
96         if (NULL == g_doc) {
97                 LOGE("[ERROR] Fail to new doc");
98                 return -1;
99         }
100         LOGD("===");
101         return 0;
102 }
103
104 static int __save_engine_info_xml(const char *pkgid, gchar *ut, uid_t uid, gid_t gid)
105 {
106         LOGD("=== Save engine info doc");
107         char *dir_config_base = NULL;
108         char *dir_home = NULL;
109         char *dir_engine_base = NULL;
110         char *dir_engine_info = NULL;
111
112         if (NULL == ut || (NULL != ut && 0 == strcmp(ut, "none"))) {
113                 LOGE("[ERROR] Usertype is NONE");
114                 return -1;
115         }
116
117         uid_t globalapp_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
118         uid_t tmp_uid = 0;
119         gid_t tmp_gid = 0;
120         LOGD("uid(%u)", uid);
121
122         if (globalapp_uid == uid) {
123                 /* Global app */
124                 dir_config_base = strdup(STT_GLOBAL_CONFIG_BASE);
125                 dir_home = strdup(STT_GLOBAL_HOME);
126                 dir_engine_base = strdup(STT_GLOBAL_ENGINE_BASE);
127                 dir_engine_info = strdup(STT_GLOBAL_ENGINE_INFO);
128                 tmp_uid = 301;  // app_fw
129                 tmp_gid = 301;  // app_fw
130         } else {
131                 /* User app, Guest app, Security app */
132                 if (NULL != g_dir_config_base)
133                         dir_config_base = strdup(g_dir_config_base);
134                 if (NULL != g_dir_home)
135                         dir_home = strdup(g_dir_home);
136                 if (NULL != g_dir_engine_base)
137                         dir_engine_base = strdup(g_dir_engine_base);
138                 if (NULL != g_dir_engine_info)
139                         dir_engine_info = strdup(g_dir_engine_info);
140                 tmp_uid = uid;
141                 tmp_gid = gid;
142         }
143
144         if (NULL == dir_config_base || NULL == dir_home || NULL == dir_engine_base || NULL == dir_engine_info) {
145                 LOGE("[ERROR] Fail to allocate memory");
146                 FREE(dir_config_base)
147                 FREE(dir_home)
148                 FREE(dir_engine_base)
149                 FREE(dir_engine_info)
150                 return -1;
151         }
152
153         LOGD("[DEBUG] dir_engine_info(%s)", dir_engine_info);
154
155         /* Make directories */
156         int fd = -1;
157 //      if (0 != access(dir_config_base, F_OK)) {
158         fd = open(dir_config_base, O_DIRECTORY);
159         if (-1 == fd) {
160                 LOGE("[INFO] No directory : %s, errno : %d", dir_config_base, errno);
161                 if (0 != mkdir(dir_config_base, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
162                         LOGE("[ERROR] Fail to make directory : %s, errno : %d", dir_config_base, errno);
163                         FREE(dir_config_base)
164                         FREE(dir_home)
165                         FREE(dir_engine_base)
166                         FREE(dir_engine_info)
167                         return -1;
168                 } else {
169                         LOGD("Success to make directory : %s", dir_config_base);
170                         if (0 != chown(dir_config_base, tmp_uid, tmp_gid)) {
171                                 LOGD("[ERROR] Fail to change user and group, errno : %d", errno);
172                         } else {
173                                 LOGD("[DEBUG] Success to change user and group");
174                         }
175                 }
176         } else {
177                 close(fd);
178         }
179
180 //      if (0 != access(dir_home, F_OK)) {
181         fd = open(dir_home, O_DIRECTORY);
182         if (-1 == fd) {
183                 LOGE("[INFO] No directory : %s, errno : %d", dir_home, errno);
184                 if (0 != mkdir(dir_home, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
185                         LOGE("[ERROR] Fail to make directory : %s, errno : %d", dir_home, errno);
186                         FREE(dir_config_base)
187                         FREE(dir_home)
188                         FREE(dir_engine_base)
189                         FREE(dir_engine_info)
190                         return -1;
191                 } else {
192                         LOGD("Success to make directory : %s", dir_home);
193                         if (0 != chown(dir_home, tmp_uid, tmp_gid)) {
194                                 LOGD("[ERROR] Fail to change user and group, errno : %d", errno);
195                         } else {
196                                 LOGD("[DEBUG] Success to change user and group");
197                         }
198                 }
199         } else {
200                 close(fd);
201         }
202
203 //      if (0 != access(dir_engine_base, F_OK)) {
204         fd = open(dir_engine_base, O_DIRECTORY);
205         if (-1 == fd) {
206                 LOGE("[INFO] No directory : %s, errno : %d", dir_engine_base, errno);
207                 if (0 != mkdir(dir_engine_base, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
208                         LOGE("[ERROR] Fail to make directory : %s, errno : %d", dir_engine_base, errno);
209                         FREE(dir_config_base)
210                         FREE(dir_home)
211                         FREE(dir_engine_base)
212                         FREE(dir_engine_info)
213                         return -1;
214                 } else {
215                         LOGD("Success to make directory : %s", dir_engine_base);
216                         if (0 != chown(dir_engine_base, tmp_uid, tmp_gid)) {
217                                 LOGD("[ERROR] Fail to change user and group, errno : %d", errno);
218                         } else {
219                                 LOGD("[DEBUG] Success to change user and group");
220                         }
221                 }
222         } else {
223                 close(fd);
224         }
225
226 //      if (0 != access(dir_engine_info, F_OK)) {
227         fd = open(dir_engine_info, O_DIRECTORY);
228         if (-1 == fd) {
229                 LOGE("[INFO] No directory : %s, errno : %d", dir_engine_info, errno);
230                 if (0 != mkdir(dir_engine_info, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
231                         LOGE("[ERROR] Fail to make directory : %s, errno : %d", dir_engine_info, errno);
232                         FREE(dir_config_base)
233                         FREE(dir_home)
234                         FREE(dir_engine_base)
235                         FREE(dir_engine_info)
236                         return -1;
237                 } else {
238                         LOGD("Success to make directory : %s", dir_engine_info);
239                         if (0 != chown(dir_engine_info, tmp_uid, tmp_gid)) {
240                                 LOGD("[ERROR] Fail to change user and group, errno : %d", errno);
241                         } else {
242                                 LOGD("[DEBUG] Success to change user and group");
243                         }
244                 }
245         } else {
246                 close(fd);
247         }
248
249         char path[256] = {'\0',};
250         snprintf(path, 256, "%s/%s.xml", dir_engine_info, pkgid);
251         int ret = xmlSaveFormatFile(path, g_doc, 1);
252         LOGD("xmlSaveFile (%d)", ret);
253         if (0 == ret) {
254                 if (0 != chown(path, tmp_uid, tmp_gid)) {
255                         LOGD("[ERROR] Fail to change user and group");
256                 } else {
257                         LOGD("[DEBUG] Success to change user and group");
258                 }
259         }
260
261         FREE(dir_config_base)
262         FREE(dir_home)
263         FREE(dir_engine_base)
264         FREE(dir_engine_info)
265
266         LOGD("===");
267
268         return 0;
269 }
270
271 static int __remove_engine_info_xml(const char *pkgid, gchar *ut, uid_t uid)
272 {
273         LOGD("=== Remove engine info doc");
274         char *dir_engine_info = NULL;
275
276         if (NULL == ut || (NULL != ut && 0 == strcmp(ut, "none"))) {
277                 LOGE("[ERROR] Usertype is NONE");
278                 return -1;
279         }
280
281         uid_t globalapp_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
282
283         LOGD("uid(%u)", uid);
284
285         if (globalapp_uid == uid) {
286                 /* Global app */
287                 dir_engine_info = strdup(STT_GLOBAL_ENGINE_INFO);
288         } else {
289                 /* User app, Guest app, Security app */
290                 if (NULL != g_dir_engine_info)
291                         dir_engine_info = strdup(g_dir_engine_info);
292         }
293
294         if (NULL == dir_engine_info) {
295                 LOGE("[ERROR] Fail to allocate memory");
296                 return -1;
297         }
298
299         LOGD("[DEBUG] dir_engine_info(%s)", dir_engine_info);
300
301         char path[256] = {'\0',};
302         snprintf(path, 256, "%s/%s.xml", dir_engine_info, pkgid);
303         LOGD("Remove engine info xml(%s)", path);
304         if (0 != remove(path)) {
305                 LOGE("[ERROR] Fail to remove engine info xml(%s)", path);
306         }
307
308         FREE(dir_engine_info)
309
310         LOGD("===");
311
312         return 0;
313 }
314
315 static void __insert_language_from_metadata(xmlNodePtr root, const char *language)
316 {
317         LOGD("==== Insert language");
318         char* lang = NULL;
319
320         if (NULL == root || NULL == language) {
321                 LOGE("Invalid parameter, root(%p), language(%s)", root, language);
322                 return;
323         }
324
325         char *tmp_lang, *tmp_free;
326         tmp_free = tmp_lang = strdup(language);
327         xmlNodePtr languages_node = NULL;
328         xmlNodePtr lang_node = NULL;
329
330         languages_node = xmlNewNode(NULL, (const xmlChar*)STT_TAG_ENGINE_LANGUAGE_SET);
331
332         lang = strsep(&tmp_lang, ",");
333         while (NULL != lang) {
334                 LOGD("lang (%s)", lang);
335                 lang_node = xmlNewNode(NULL, (const xmlChar*)STT_TAG_ENGINE_LANGUAGE);
336                 xmlNodeSetContent(lang_node, (const xmlChar*)lang);
337                 xmlAddChild(languages_node, lang_node);
338                 lang = strsep(&tmp_lang, ",");
339         }
340         xmlAddChild(root, languages_node);
341
342         FREE(tmp_free)
343 }
344
345 static int __write_metadata_inxml(const char *pkgid, const char *appid, GList *list)
346 {
347         GList *iter = NULL;
348         metadata *md = NULL;
349
350         __create_engine_info_xml(pkgid);
351
352         xmlNodePtr root = NULL;
353         xmlNodePtr cur = NULL;
354
355         root = xmlNewNode(NULL, (const xmlChar*)STT_TAG_ENGINE_BASE);
356
357         if (NULL == root) {
358                 LOGE("[ERROR] Fail to get new node");
359 //              xmlFreeDoc(g_doc);
360                 return -1;
361         }
362         xmlDocSetRootElement(g_doc, root);
363
364         iter = g_list_first(list);
365         while (NULL != iter) {
366                 md = (metadata *)iter->data;
367                 if (NULL != md && NULL != md->key && NULL != md->value) {
368                         LOGD(" - key(%s) value(%s)", md->key, md->value);
369                         if (!strcmp(md->key, STT_METADATA_LANGUAGE)) {
370                                 __insert_language_from_metadata(root, md->value);
371                         } else if (!strcmp(md->key, STT_METADATA_SILENCE_DETECTION)) {
372                                 cur = xmlNewNode(NULL, (const xmlChar*)STT_TAG_ENGINE_SILENCE_DETECTION_SUPPORT);
373                                 xmlNodeSetContent(cur, (const xmlChar*)md->value);
374                                 xmlAddChild(root, cur);
375                         } else if (!strcmp(md->key, STT_METADATA_CREDENTIAL_REQUIRED)) {
376                                 cur = xmlNewNode(NULL, (const xmlChar*)STT_TAG_ENGINE_CREDENTIAL);
377                                 xmlNodeSetContent(cur, (const xmlChar*)md->value);
378                                 xmlAddChild(root, cur);
379                         } else if (!strcmp(md->key, STT_METADATA_ENGINE_SETTING)) {
380                                 cur = xmlNewNode(NULL, (const xmlChar*)STT_TAG_ENGINE_SETTING);
381                                 xmlNodeSetContent(cur, (const xmlChar*)md->value);
382                                 xmlAddChild(root, cur);
383                         } else if (!strcmp(md->key, STT_METADATA_ENGINE_NAME)) {
384                                 cur = xmlNewNode(NULL, (const xmlChar*)STT_TAG_ENGINE_NAME);
385                                 xmlNodeSetContent(cur, (const xmlChar*)md->value);
386                                 xmlAddChild(root, cur);
387                         } else {
388                                 LOGW("[WARNING] Unknown metadata type");
389                         }
390                 }
391                 iter = g_list_next(iter);
392         }
393
394         cur = xmlNewNode(NULL, (const xmlChar*)STT_TAG_ENGINE_ID);
395         xmlNodeSetContent(cur, (const xmlChar*)appid);
396         xmlAddChild(root, cur);
397
398         LOGD("");
399         return 0;
400 }
401
402 EXPORT_API
403 int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgid, const char *appid, GList *list)
404 {
405         LOGD("METADATA INSTALL");
406         LOGD("pkgid(%s) appid(%s) list(%d)", pkgid, appid, g_list_length(list));
407
408         int ret = -1;
409         ret = pkgmgr_installer_info_get_target_uid(&g_uid);
410         if (ret < 0) {
411                 LOGE("[ERROR] Fail to get target uid");
412                 return 0;
413         } else {
414                 LOGD("uid(%u)", g_uid);
415                 printf("[Parser Debug][DEBUG] uid(%u)", g_uid);
416         }
417
418         uid_t globalapp_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
419         if (globalapp_uid == g_uid) {
420                 g_user_type = g_strdup("admin");
421         } else {
422                 g_guser = gum_user_get_sync(g_uid, FALSE);
423                 if (NULL == g_guser) {
424                         LOGE("[ERROR] g_guser is NULL");
425                         return -1;
426                 }
427
428                 g_object_get(G_OBJECT(g_guser), "gid", &g_gid, NULL);
429                 g_object_get(G_OBJECT(g_guser), "usertype", &g_ut, NULL);
430                 g_user_type = g_strdup(gum_user_type_to_string(g_ut));
431         }
432
433         if (NULL == g_user_type) {
434                 LOGE("[ERROR] Fail to allocate memory");
435                 if (NULL != g_guser) {
436                         g_object_unref(g_guser);
437                         g_guser = NULL;
438                 }
439                 return -1;
440         }
441
442         if (0 == strcmp(g_user_type, "none")) {
443                 /* GUM_USERTYPE_NONE */
444                 LOGE("[ERROR] Fail to get target uid");
445                 g_object_unref(g_guser);
446                 g_guser = NULL;
447                 G_FREE(g_user_type)
448                 return -1;
449         }
450
451         if (globalapp_uid == g_uid) {
452                 /* global directory */
453                 LOGD("[DEBUG] usertype: %s", g_user_type);
454                 if (0 >= g_list_length(list)) {
455                         LOGE("[ERROR] No Engine Metadata");
456                         G_FREE(g_user_type)
457                         return 0;
458                 }
459
460                 if (0 != __write_metadata_inxml(pkgid, appid, list)) {
461                         LOGE("[ERROR] Fail to write metadata in the xml");
462                         xmlFreeDoc(g_doc);
463                         G_FREE(g_user_type)
464                         return -1;
465                 }
466
467                 /* Save in /etc/skel/share/ */
468                 g_dir_config_base = strdup(STT_GLOBAL_CONFIG_BASE);
469                 g_dir_home = strdup(STT_GLOBAL_HOME);
470                 g_dir_engine_base = strdup(STT_GLOBAL_ENGINE_BASE);
471                 g_dir_engine_info = strdup(STT_GLOBAL_ENGINE_INFO);
472
473                 if (NULL == g_dir_config_base || NULL == g_dir_home || NULL == g_dir_engine_base || NULL == g_dir_engine_info) {
474                         LOGE("[ERROR] Fail to allocate memory");
475                         FREE(g_dir_config_base)
476                         FREE(g_dir_home)
477                         FREE(g_dir_engine_base)
478                         FREE(g_dir_engine_info)
479                         xmlFreeDoc(g_doc);
480                         G_FREE(g_user_type)
481                         return -1;
482                 }
483
484                 if (0 != __save_engine_info_xml(pkgid, g_user_type, g_uid, g_gid)) {
485                         LOGE("[ERROR] Fail to make engine info file");
486                         xmlFreeDoc(g_doc);
487                         G_FREE(g_user_type)
488                         return -1;
489                 }
490
491                 /* Get user data by using libgum */
492
493                 GumUserService *gus = NULL;
494                 GumUserList *users = NULL;
495                 GumUserList *iter = NULL;
496                 GumUser *user = NULL;
497                 gchar **query;
498                 GumUserType gumut = GUM_USERTYPE_NONE;
499                 gchar *user_type = NULL;
500
501                 uid_t uid;
502                 gid_t gid;
503                 gchar *home_dir = NULL;
504
505                 gus = gum_user_service_create_sync(TRUE);
506                 if (!gus) {
507                         LOGE("Failed to create gum user service");
508                         G_FREE(g_user_type)
509                         return -1;
510                 }
511
512                 query = g_strsplit("admin,normal", ",", -1);
513
514                 users = gum_user_service_get_user_list_sync(gus, (const gchar *const *)query);
515                 g_strfreev(query);
516
517                 if (!users) {
518                         LOGD("NO users");
519                         g_object_unref(gus);
520                         gus = NULL;
521                         G_FREE(g_user_type)
522                         return 0;
523                 }
524
525                 /* Make new user list */
526
527                 iter = users;
528                 while (iter != NULL) {
529                         user = (GumUser*) iter->data;
530                         g_object_get(G_OBJECT(user), "uid", &uid, NULL);
531                         G_FREE(home_dir)
532
533                         g_object_get(G_OBJECT(user), "gid", &gid, NULL);
534                         g_object_get(G_OBJECT(user), "homedir", &home_dir, NULL);
535                         g_object_get(G_OBJECT(user), "usertype", &gumut, NULL);
536                         user_type = g_strdup(gum_user_type_to_string(gumut));
537                         if (NULL == user_type) {
538                                 gum_user_service_list_free(users);
539                                 G_FREE(home_dir)
540                                 g_object_unref(gus);
541                                 gus = NULL;
542                                 return -1;
543                         }
544
545                         LOGD("[DEBUG] user info");
546                         if (NULL != home_dir) {
547                                 LOGD("[DEBUG] uid(%u), gid(%u), user_type(%s), home_dir(%s)", uid, gid, user_type, home_dir);
548
549                                 FREE(g_dir_config_base)
550                                 FREE(g_dir_home)
551                                 FREE(g_dir_engine_base)
552                                 FREE(g_dir_engine_info)
553                                 g_dir_config_base = (char*)calloc(strlen(home_dir) + 14, sizeof(char));
554                                 g_dir_home = (char*)calloc(strlen(home_dir) + 18, sizeof(char));
555                                 g_dir_engine_base = (char*)calloc(strlen(home_dir) + 22, sizeof(char));
556                                 g_dir_engine_info = (char*)calloc(strlen(home_dir) + 34, sizeof(char));
557
558                                 if (NULL == g_dir_config_base || NULL == g_dir_home || NULL == g_dir_engine_base || NULL == g_dir_engine_info) {
559                                         LOGE("[ERROR] Fail to allocate memory");
560                                         FREE(g_dir_config_base)
561                                         FREE(g_dir_home)
562                                         FREE(g_dir_engine_base)
563                                         FREE(g_dir_engine_info)
564                                         gum_user_service_list_free(users);
565                                         g_object_unref(gus);
566                                         gus = NULL;
567                                         G_FREE(user_type)
568                                         G_FREE(home_dir)
569                                         return -1;
570                                 }
571                                 snprintf(g_dir_config_base, strlen(home_dir) + 14, "%s/share/.voice", home_dir);
572                                 snprintf(g_dir_home, strlen(home_dir) + 18, "%s/share/.voice/stt", home_dir);
573                                 snprintf(g_dir_engine_base, strlen(home_dir) + 22, "%s/share/.voice/stt/1.0", home_dir);
574                                 snprintf(g_dir_engine_info, strlen(home_dir) + 34, "%s/share/.voice/stt/1.0/engine-info", home_dir);
575
576                                 LOGD("[DEBUG] g_dir_engine_info(%s)", g_dir_engine_info);
577
578                                 if (0 != __save_engine_info_xml(pkgid, user_type, uid, gid)) {
579                                         LOGE("[ERROR] Fail to make engine info file");
580                                 }
581
582                                 G_FREE(home_dir)
583                         }
584
585                         G_FREE(user_type)
586                         iter = g_list_next(iter);
587                 }
588
589                 gum_user_service_list_free(users);
590                 g_object_unref(gus);
591                 gus = NULL;
592         } else {
593                 /* user directory */
594                 LOGD("[DEBUG] usertype: %s", g_user_type);
595
596                 ret = tzplatform_set_user(g_uid);
597                 if (ret < 0) {
598                         LOGE("[ERROR] Invalid uid");
599                         g_object_unref(g_guser);
600                         g_guser = NULL;
601                         G_FREE(g_user_type)
602                         return 0;
603                 } else {
604                         LOGD("TZ_USER_HOME: %s", tzplatform_mkstr(TZ_USER_HOME, "/"));
605                         printf("[Parser Debug][DEBUG] TZ_USER_HOME: %s", tzplatform_mkstr(TZ_USER_HOME, "/"));
606                 }
607
608                 if (0 >= g_list_length(list)) {
609                         LOGE("[ERROR] No Engine Metadata");
610                         g_object_unref(g_guser);
611                         g_guser = NULL;
612                         G_FREE(g_user_type)
613                         return 0;
614                 }
615
616                 if (0 != __write_metadata_inxml(pkgid, appid, list)) {
617                         LOGE("[ERROR] Fail to write metadata in the xml");
618                         xmlFreeDoc(g_doc);
619                         g_object_unref(g_guser);
620                         g_guser = NULL;
621                         G_FREE(g_user_type)
622                         return -1;
623                 }
624
625                 g_dir_config_base = strdup(STT_CONFIG_BASE);
626                 g_dir_home = strdup(STT_HOME);
627                 g_dir_engine_base = strdup(STT_ENGINE_BASE);
628                 g_dir_engine_info = strdup(STT_ENGINE_INFO);
629
630                 if (NULL == g_dir_config_base || NULL == g_dir_home || NULL == g_dir_engine_base || NULL == g_dir_engine_info) {
631                         LOGE("[ERROR] Fail to allocate memory");
632                         FREE(g_dir_config_base)
633                         FREE(g_dir_home)
634                         FREE(g_dir_engine_base)
635                         FREE(g_dir_engine_info)
636                         xmlFreeDoc(g_doc);
637                         g_object_unref(g_guser);
638                         g_guser = NULL;
639                         G_FREE(g_user_type)
640                         return -1;
641                 }
642
643                 if (0 != __save_engine_info_xml(pkgid, g_user_type, g_uid, g_gid)) {
644                         LOGE("[ERROR] Fail to make engine info file");
645                         xmlFreeDoc(g_doc);
646                         if (NULL != g_guser) {
647                                 g_object_unref(g_guser);
648                                 g_guser = NULL;
649                         }
650                         G_FREE(g_user_type)
651                         return -1;
652                 }
653         }
654
655         xmlFreeDoc(g_doc);
656         if (NULL != g_guser) {
657                 g_object_unref(g_guser);
658                 g_guser = NULL;
659         }
660         G_FREE(g_user_type)
661
662         FREE(g_dir_config_base)
663         FREE(g_dir_home)
664         FREE(g_dir_engine_base)
665         FREE(g_dir_engine_info)
666
667         return 0;
668 }
669
670 EXPORT_API
671 int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(const char *pkgid, const char *appid, GList *list)
672 {
673         LOGD("METADATA UNINSTALL");
674         LOGD("pkgid(%s) appid(%s) list(%u)", pkgid, appid, g_list_length(list));
675
676         int ret = -1;
677         ret = pkgmgr_installer_info_get_target_uid(&g_uid);
678         if (ret < 0) {
679                 LOGE("[ERROR] Fail to get target uid");
680                 return 0;
681         } else {
682                 LOGD("uid(%u)", g_uid);
683                 printf("[Parser Debug][DEBUG] uid(%u)", g_uid);
684         }
685
686         uid_t globalapp_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
687         if (globalapp_uid == g_uid) {
688                 g_user_type = g_strdup("admin");
689         } else {
690                 g_guser = gum_user_get_sync(g_uid, FALSE);
691                 if (NULL == g_guser) {
692                         LOGE("[ERROR] g_guser is NULL");
693                         return -1;
694                 }
695
696                 g_object_get(G_OBJECT(g_guser), "usertype", &g_ut, NULL);
697                 g_user_type = g_strdup(gum_user_type_to_string(g_ut));
698         }
699
700         if (NULL == g_user_type) {
701                 LOGE("[ERROR] Fail to allocate memory");
702                 if (NULL != g_guser) {
703                         g_object_unref(g_guser);
704                         g_guser = NULL;
705                 }
706                 return -1;
707         }
708
709         if (0 == strcmp(g_user_type, "none")) {
710                 /* GUM_USERTYPE_NONE */
711                 LOGE("[ERROR] Fail to get target uid");
712                 g_object_unref(g_guser);
713                 g_guser = NULL;
714                 G_FREE(g_user_type)
715                 return -1;
716         }
717
718         if (globalapp_uid == g_uid) {
719                 /* global directory */
720                 LOGD("[DEBUG] usertype: %s", g_user_type);
721
722                 /* Remove files in /etc/skel/share/ */
723                 g_dir_engine_info = strdup(STT_GLOBAL_ENGINE_INFO);
724                 if (NULL == g_dir_engine_info) {
725                         LOGE("[ERROR] Fail to allocate memory");
726                         G_FREE(g_user_type)
727                         return -1;
728                 }
729
730                 if (0 != __remove_engine_info_xml(pkgid, g_user_type, g_uid)) {
731                         LOGE("[ERROR] Fail to remove engine info file");
732                 }
733
734                 /* Get user data by using libgum */
735
736                 GumUserService *gus = NULL;
737                 GumUserList *users = NULL;
738                 GumUserList *iter = NULL;
739                 GumUser *user = NULL;
740                 gchar **query;
741                 GumUserType gumut = GUM_USERTYPE_NONE;
742                 gchar *user_type = NULL;
743
744                 uid_t uid;
745                 gchar *home_dir = NULL;
746
747                 GList *md_iter = NULL;
748                 metadata *md = NULL;
749
750                 gus = gum_user_service_create_sync(TRUE);
751                 if (!gus) {
752                         LOGE("Failed to create gum user service");
753                         G_FREE(g_user_type)
754                         return -1;
755                 }
756
757                 query = g_strsplit("admin,normal", ",", -1);
758
759                 users = gum_user_service_get_user_list_sync(gus, (const gchar *const *)query);
760                 g_strfreev(query);
761
762                 if (!users) {
763                         LOGD("NO users");
764                         g_object_unref(gus);
765                         gus = NULL;
766                         G_FREE(g_user_type)
767                         return 0;
768                 }
769
770                 /* Make new user list */
771
772                 iter = users;
773                 while (iter != NULL) {
774                         user = (GumUser*) iter->data;
775                         g_object_get(G_OBJECT(user), "uid", &uid, NULL);
776                         G_FREE(home_dir)
777                         g_object_get(G_OBJECT(user), "homedir", &home_dir, NULL);
778                         g_object_get(G_OBJECT(user), "usertype", &gumut, NULL);
779                         user_type = g_strdup(gum_user_type_to_string(gumut));
780                         if (NULL == user_type) {
781                                 gum_user_service_list_free(users);
782                                 G_FREE(home_dir)
783                                 g_object_unref(gus);
784                                 gus = NULL;
785                                 return -1;
786                         }
787
788                         if (NULL != home_dir) {
789                                 FREE(g_dir_engine_info)
790                                 g_dir_engine_info = (char*)calloc(strlen(home_dir) + 34, sizeof(char));
791                                 if (NULL == g_dir_engine_info) {
792                                         gum_user_service_list_free(users);
793                                         G_FREE(home_dir)
794                                         g_object_unref(gus);
795                                         gus = NULL;
796                                         G_FREE(user_type)
797                                         return -1;
798                                 }
799
800                                 snprintf(g_dir_engine_info, strlen(home_dir) + 34, "%s/share/.voice/stt/1.0/engine-info", home_dir);
801
802                                 md_iter = g_list_first(list);
803                                 while (NULL != md_iter) {
804                                         md = (metadata *)md_iter->data;
805                                         LOGD(" - key(%s) value(%s)", md->key, md->value);
806                                         md_iter = g_list_next(md_iter);
807                                 }
808
809                                 if (0 != __remove_engine_info_xml(pkgid, user_type, uid)) {
810                                         LOGE("[ERROR] Fail to remove engine info file");
811                                 }
812
813                                 G_FREE(home_dir)
814                         }
815                         G_FREE(user_type)
816
817                         LOGD("Finish release memory");
818                         iter = g_list_next(iter);
819                         LOGD("Finish next iter");
820                 }
821
822                 gum_user_service_list_free(users);
823                 g_object_unref(gus);
824                 gus = NULL;
825         } else {
826                 /* user directory */
827                 LOGD("[DEBUG] usertype: %s", g_user_type);
828
829                 ret = tzplatform_set_user(g_uid);
830                 if (ret < 0) {
831                         LOGE("[ERROR] Invalid uid");
832                         g_object_unref(g_guser);
833                         g_guser = NULL;
834                         G_FREE(g_user_type)
835                         return -1;
836                 } else {
837                         LOGD("TZ_USER_HOME: %s", tzplatform_mkstr(TZ_USER_HOME, "/"));
838                         printf("[Parser Debug][DEBUG] TZ_USER_HOME: %s", tzplatform_mkstr(TZ_USER_HOME, "/"));
839                 }
840
841                 g_dir_engine_info = strdup(STT_ENGINE_INFO);
842                 if (NULL == g_dir_engine_info) {
843                         LOGE("[ERROR] Fail to allocate memory");
844                         g_object_unref(g_guser);
845                         g_guser = NULL;
846                         G_FREE(g_user_type)
847                         return -1;
848                 }
849
850                 if (0 != __remove_engine_info_xml(pkgid, g_user_type, g_uid)) {
851                         LOGE("[ERROR] Fail to remove engine info file");
852                 }
853
854         }
855
856         if (NULL != g_guser) {
857                 g_object_unref(g_guser);
858                 g_guser = NULL;
859         }
860         G_FREE(g_user_type)
861
862         FREE(g_dir_engine_info)
863
864         LOGD("");
865         return 0;
866 }
867
868 EXPORT_API
869 int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgid, const char *appid, GList *list)
870 {
871         LOGD("METADATA UPGRADE");
872         LOGD("pkgid(%s) appid(%s) list(%u)", pkgid, appid, g_list_length(list));
873
874         PKGMGR_MDPARSER_PLUGIN_UNINSTALL(pkgid, appid, list);
875         PKGMGR_MDPARSER_PLUGIN_INSTALL(pkgid, appid, list);
876
877         LOGD("");
878         return 0;
879 }