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