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