42414fc25836518365721d15c28e5f672b3ba392
[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                 g_guser = gum_user_get_sync(g_uid, FALSE);
738                 if (NULL == g_guser) {
739                         LOGE("[ERROR] g_guser is NULL");
740                         return -1;
741                 }
742
743                 g_object_get(G_OBJECT(g_guser), "usertype", &g_ut, NULL);
744                 g_user_type = g_strdup(gum_user_type_to_string(g_ut));
745
746                 LOGD("[DEBUG] g_user_type: %s (%d)", g_user_type, globalapp_uid);
747         }
748
749         if (NULL == g_user_type) {
750                 LOGE("[ERROR] Fail to allocate memory");
751                 if (NULL != g_guser) {
752                         g_object_unref(g_guser);
753                         g_guser = NULL;
754                 }
755                 return -1;
756         }
757
758         if (0 == strcmp(g_user_type, "none")) {
759                 /* GUM_USERTYPE_NONE */
760                 LOGE("[ERROR] Fail to get target uid");
761                 g_object_unref(g_guser);
762                 g_guser = NULL;
763                 G_FREE(g_user_type)
764                 return -1;
765         }
766
767         if (globalapp_uid == g_uid) {
768                 /* global directory */
769                 LOGD("[DEBUG] usertype: %s", g_user_type);
770
771                 /* Remove files in /etc/skel/share/ */
772                 g_dir_engine_info = strdup(TTS_GLOBAL_ENGINE_INFO);
773                 if (NULL == g_dir_engine_info) {
774                         LOGE("[ERROR] Fail to allocate memory");
775                         G_FREE(g_user_type)
776                         return -1;
777                 }
778
779                 if (0 != __remove_engine_info_xml(pkgid, g_user_type, g_uid)) {
780                         LOGE("[ERROR] Fail to remove engine info file");
781                 }
782
783                 /* Get user data by using libgum */
784
785                 GumUserService *gus = NULL;
786                 GumUserList *users = NULL;
787                 GumUserList *iter = NULL;
788                 GumUser *user = NULL;
789                 gchar **query;
790                 GumUserType gumut = GUM_USERTYPE_NONE;
791                 gchar *user_type = NULL;
792
793                 uid_t uid;
794                 gchar *home_dir = NULL;
795
796                 GList *md_iter = NULL;
797                 metadata *md = NULL;
798
799                 gus = gum_user_service_create_sync(TRUE);
800                 if (!gus) {
801                         LOGE("Failed to create gum user service");
802                         G_FREE(g_user_type)
803                         return -1;
804                 }
805
806                 query = g_strsplit("admin,normal", ",", -1);
807
808                 users = gum_user_service_get_user_list_sync(gus, (const gchar *const *)query);
809                 g_strfreev(query);
810
811                 if (!users) {
812                         LOGD("NO users");
813                         g_object_unref(gus);
814                         gus = NULL;
815                         G_FREE(g_user_type)
816                         return 0;
817                 }
818
819                 /* Make new user list */
820
821                 iter = users;
822                 while (iter != NULL) {
823                         user = (GumUser*) iter->data;
824                         g_object_get(G_OBJECT(user), "uid", &uid, NULL);
825                         G_FREE(home_dir)
826                         g_object_get(G_OBJECT(user), "homedir", &home_dir, NULL);
827                         g_object_get(G_OBJECT(user), "usertype", &gumut, NULL);
828                         user_type = g_strdup(gum_user_type_to_string(gumut));
829                         if (NULL == user_type) {
830                                 gum_user_service_list_free(users);
831                                 G_FREE(home_dir)
832                                 g_object_unref(gus);
833                                 gus = NULL;
834                                 return -1;
835                         }
836
837                         if (NULL != home_dir) {
838                                 g_dir_engine_info = (char*)calloc(strlen(home_dir) + 34, sizeof(char));
839                                 if (NULL == g_dir_engine_info) {
840                                         gum_user_service_list_free(users);
841                                         G_FREE(home_dir)
842                                         g_object_unref(gus);
843                                         gus = NULL;
844                                         G_FREE(user_type)
845                                         return -1;
846                                 }
847
848                                 snprintf(g_dir_engine_info, strlen(home_dir) + 34, "%s/share/.voice/tts/1.0/engine-info", home_dir);
849
850                                 md_iter = g_list_first(list);
851                                 while (NULL != md_iter) {
852                                         md = (metadata *)md_iter->data;
853                                         LOGD(" - key(%s) value(%s)", md->key, md->value);
854                                         md_iter = g_list_next(md_iter);
855                                 }
856
857                                 if (0 != __remove_engine_info_xml(pkgid, user_type, uid)) {
858                                         LOGE("[ERROR] Fail to remove engine info file");
859                                 }
860
861                                 G_FREE(home_dir)
862                                 FREE(g_dir_engine_info)
863                         }
864                         G_FREE(user_type)
865
866                         LOGD("Finish release memory");
867                         iter = g_list_next(iter);
868                         LOGD("Finish next iter");
869                 }
870
871                 gum_user_service_list_free(users);
872                 g_object_unref(gus);
873                 gus = NULL;
874         } else {
875                 /* user directory */
876                 LOGD("[DEBUG] usertype: %s", g_user_type);
877
878                 ret = tzplatform_set_user(g_uid);
879                 if (ret < 0) {
880                         LOGE("[ERROR] Invalid uid");
881                         g_object_unref(g_guser);
882                         g_guser = NULL;
883                         G_FREE(g_user_type)
884                         return -1;
885                 } else {
886                         LOGD("TZ_USER_HOME: %s", tzplatform_mkstr(TZ_USER_HOME, "/"));
887                         printf("[Parser Debug][DEBUG] TZ_USER_HOME: %s", tzplatform_mkstr(TZ_USER_HOME, "/"));
888                 }
889
890                 g_dir_engine_info = strdup(TTS_ENGINE_INFO);
891                 if (NULL == g_dir_engine_info) {
892                         LOGE("[ERROR] Fail to allocate memory");
893                         g_object_unref(g_guser);
894                         g_guser = NULL;
895                         G_FREE(g_user_type)
896                         return -1;
897                 }
898
899                 if (0 != __remove_engine_info_xml(pkgid, g_user_type, g_uid)) {
900                         LOGE("[ERROR] Fail to remove engine info file");
901                 }
902
903         }
904
905         if (NULL != g_guser) {
906                 g_object_unref(g_guser);
907                 g_guser = NULL;
908         }
909         G_FREE(g_user_type)
910
911         FREE(g_dir_engine_info)
912
913         LOGD("");
914         return 0;
915 }
916
917 EXPORT_API
918 int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgid, const char *appid, GList *list)
919 {
920         LOGD("METADATA UPGRADE");
921         LOGD("pkgid(%s) appid(%s) list(%d)", pkgid, appid, g_list_length(list));
922
923         PKGMGR_MDPARSER_PLUGIN_UNINSTALL(pkgid, appid, list);
924         PKGMGR_MDPARSER_PLUGIN_INSTALL(pkgid, appid, list);
925
926         LOGD("");
927         return 0;
928 }