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