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