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