change strdup to array
[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_object_unref(gus);
561                                 gus = NULL;
562                                 return -1;
563                         }
564
565                         LOGD("[DEBUG] user info");
566                         if (NULL != home_dir) {
567                                 LOGD("[DEBUG] uid(%d), gid(%d),  user_type(%s), home_dir(%s)", uid, gid, user_type, home_dir);
568
569                                 g_dir_config_base = (char*)calloc(strlen(home_dir) + 14, sizeof(char));
570                                 g_dir_home = (char*)calloc(strlen(home_dir) + 18, sizeof(char));
571                                 g_dir_engine_base = (char*)calloc(strlen(home_dir) + 22, sizeof(char));
572                                 g_dir_engine_info = (char*)calloc(strlen(home_dir) + 34, sizeof(char));
573
574                                 if (NULL == g_dir_config_base || NULL == g_dir_home || NULL == g_dir_engine_base || NULL == g_dir_engine_info) {
575                                         LOGE("[ERROR] Fail to allocate memory");
576                                         FREE(g_dir_config_base)
577                                         FREE(g_dir_home)
578                                         FREE(g_dir_engine_base)
579                                         FREE(g_dir_engine_info)
580                                         gum_user_service_list_free(users);
581                                         g_object_unref(gus);
582                                         gus = NULL;
583                                         G_FREE(user_type)
584                                         return -1;
585                                 }
586                                 snprintf(g_dir_config_base, strlen(home_dir) + 14, "%s/share/.voice", home_dir);
587                                 snprintf(g_dir_home, strlen(home_dir) + 18, "%s/share/.voice/tts", home_dir);
588                                 snprintf(g_dir_engine_base, strlen(home_dir) + 22, "%s/share/.voice/tts/1.0", home_dir);
589                                 snprintf(g_dir_engine_info, strlen(home_dir) + 34, "%s/share/.voice/tts/1.0/engine-info", home_dir);
590
591                                 LOGD("[DEBUG] g_dir_engine_info(%s)", g_dir_engine_info);
592
593                                 if (0 != __save_engine_info_xml(pkgid, user_type, uid, gid)) {
594                                         LOGE("[ERROR] Fail to make engine info file");
595                                 }
596
597                                 FREE(g_dir_config_base)
598                                 FREE(g_dir_home)
599                                 FREE(g_dir_engine_base)
600                                 FREE(g_dir_engine_info)
601
602                                 G_FREE(user_type)
603                                 G_FREE(home_dir)
604
605                                 iter = g_list_next(iter);
606                         } else {
607                                 iter = g_list_next(iter);
608                         }
609
610                         G_FREE(user_type)
611                 }
612
613                 gum_user_service_list_free(users);
614                 g_object_unref(gus);
615                 gus = NULL;
616         } else {
617                 /* user directory */
618                 LOGD("[DEBUG] usertype: %s", g_user_type);
619
620                 ret = tzplatform_set_user(g_uid);
621                 if (ret < 0) {
622                         LOGE("[ERROR] Invalid uid");
623                         g_object_unref(g_guser);
624                         g_guser = NULL;
625                         G_FREE(g_user_type)
626                         return 0;
627                 } else {
628                         LOGD("TZ_USER_HOME: %s", tzplatform_mkstr(TZ_USER_HOME, "/"));
629                         printf("[Parser Debug][DEBUG] TZ_USER_HOME: %s", tzplatform_mkstr(TZ_USER_HOME, "/"));
630                 }
631
632                 if (0 >= g_list_length(list)) {
633                         LOGE("[ERROR] No Engine Metadata");
634                         g_object_unref(g_guser);
635                         g_guser = NULL;
636                         G_FREE(g_user_type)
637                         return 0;
638                 }
639
640                 if (0 != __write_metadata_inxml(pkgid, appid, list)) {
641                         LOGE("[ERROR] Fail to write metadata in the xml");
642                         xmlFreeDoc(g_doc);
643                         g_object_unref(g_guser);
644                         g_guser = NULL;
645                         G_FREE(g_user_type)
646                         return -1;
647                 }
648
649                 g_dir_config_base = strdup(TTS_CONFIG_BASE);
650                 g_dir_home = strdup(TTS_HOME);
651                 g_dir_engine_base = strdup(TTS_ENGINE_BASE);
652                 g_dir_engine_info = strdup(TTS_ENGINE_INFO);
653
654                 if (NULL == g_dir_config_base || NULL == g_dir_home || NULL == g_dir_engine_base || NULL == g_dir_engine_info) {
655                         LOGE("[ERROR] Fail to allocate memory");
656                         FREE(g_dir_config_base)
657                         FREE(g_dir_home)
658                         FREE(g_dir_engine_base)
659                         FREE(g_dir_engine_info)
660                         xmlFreeDoc(g_doc);
661                         g_object_unref(g_guser);
662                         g_guser = NULL;
663                         G_FREE(g_user_type)
664                         return -1;
665                 }
666
667                 if (0 != __save_engine_info_xml(pkgid, g_user_type, g_uid, g_gid)) {
668                         LOGE("[ERROR] Fail to make engine info file");
669                         xmlFreeDoc(g_doc);
670                         if (NULL != g_guser) {
671                                 g_object_unref(g_guser);
672                                 g_guser = NULL;
673                         }
674                         G_FREE(g_user_type)
675                         return -1;
676                 }
677         }
678
679         xmlFreeDoc(g_doc);
680         if (NULL != g_guser) {
681                 g_object_unref(g_guser);
682                 g_guser = NULL;
683         }
684         G_FREE(g_user_type)
685
686         FREE(g_dir_config_base)
687         FREE(g_dir_home)
688         FREE(g_dir_engine_base)
689         FREE(g_dir_engine_info)
690
691         return 0;
692 }
693
694 EXPORT_API
695 int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(const char *pkgid, const char *appid, GList *list)
696 {
697         LOGD("METADATA UNINSTALL");
698         LOGD("pkgid(%s) appid(%s) list(%d)", pkgid, appid, g_list_length(list));
699
700         int ret = -1;
701         ret = pkgmgr_installer_info_get_target_uid(&g_uid);
702         if (ret < 0) {
703                 LOGE("[ERROR] Fail to get target uid");
704                 return 0;
705         } else {
706                 LOGD("uid(%d)", g_uid);
707                 printf("[Parser Debug][DEBUG] uid(%d)", g_uid);
708         }
709
710         uid_t globalapp_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
711         if (globalapp_uid == g_uid) {
712                 g_user_type = g_strdup("admin");
713         } else {
714                 g_guser = gum_user_get_sync(g_uid, FALSE);
715                 if (NULL == g_guser) {
716                         LOGE("[ERROR] g_guser is NULL");
717                         return -1;
718                 }
719
720                 g_object_get(G_OBJECT(g_guser), "usertype", &g_ut, NULL);
721                 g_user_type = g_strdup(gum_user_type_to_string(g_ut));
722         }
723
724         if (NULL == g_user_type) {
725                 LOGE("[ERROR] Fail to allocate memory");
726                 if (NULL != g_guser) {
727                         g_object_unref(g_guser);
728                         g_guser = NULL;
729                 }
730                 return -1;
731         }
732
733         if (0 == strcmp(g_user_type, "none")) {
734                 /* GUM_USERTYPE_NONE */
735                 LOGE("[ERROR] Fail to get target uid");
736                 g_object_unref(g_guser);
737                 g_guser = NULL;
738                 G_FREE(g_user_type)
739                 return -1;
740         }
741
742         if (globalapp_uid == g_uid) {
743                 /* global directory */
744                 LOGD("[DEBUG] usertype: %s", g_user_type);
745
746                 /* Remove files in /etc/skel/share/ */
747                 g_dir_engine_info = strdup(TTS_GLOBAL_ENGINE_INFO);
748                 if (NULL == g_dir_engine_info) {
749                         LOGE("[ERROR] Fail to allocate memory");
750                         G_FREE(g_user_type)
751                         return -1;
752                 }
753
754                 if (0 != __remove_engine_info_xml(pkgid, g_user_type, g_uid)) {
755                         LOGE("[ERROR] Fail to remove engine info file");
756                 }
757
758                 /* Get user data by using libgum */
759
760                 GumUserService *gus = NULL;
761                 GumUserList *users = NULL;
762                 GumUserList *iter = NULL;
763                 GumUser *user = NULL;
764                 gchar **query;
765                 GumUserType gumut = GUM_USERTYPE_NONE;
766                 gchar *user_type = NULL;
767
768                 uid_t uid;
769                 gchar *home_dir = NULL;
770
771                 GList *md_iter = NULL;
772                 metadata *md = NULL;
773
774                 gus = gum_user_service_create_sync(TRUE);
775                 if (!gus) {
776                         LOGE("Failed to create gum user service");
777                         G_FREE(g_user_type)
778                         return -1;
779                 }
780
781                 query = g_strsplit("admin,normal", ",", -1);
782
783                 users = gum_user_service_get_user_list_sync(gus, (const gchar *const *)query);
784                 g_strfreev(query);
785
786                 if (!users) {
787                         LOGE("Failed to get gum user list");
788                         g_object_unref(gus);
789                         gus = NULL;
790                         G_FREE(g_user_type)
791                         return -1;
792                 }
793
794                 /* Make new user list */
795
796                 iter = users;
797                 while (iter != NULL) {
798                         user = (GumUser*) iter->data;
799                         g_object_get(G_OBJECT(user), "uid", &uid, NULL);
800                         G_FREE(home_dir)
801                         g_object_get(G_OBJECT(user), "homedir", &home_dir, NULL);
802                         g_object_get(G_OBJECT(user), "usertype", &gumut, NULL);
803                         user_type = g_strdup(gum_user_type_to_string(gumut));
804                         if (NULL == user_type) {
805                                 gum_user_service_list_free(users);
806                                 G_FREE(home_dir)
807                                 g_object_unref(gus);
808                                 gus = NULL;
809                                 return -1;
810                         }
811
812                         if (NULL != home_dir) {
813                                 g_dir_engine_info = (char*)calloc(strlen(home_dir) + 34, sizeof(char));
814                                 if (NULL == g_dir_engine_info) {
815                                         gum_user_service_list_free(users);
816                                         G_FREE(home_dir)
817                                         g_object_unref(gus);
818                                         gus = NULL;
819                                         G_FREE(user_type)
820                                         return -1;
821                                 }
822
823                                 snprintf(g_dir_engine_info, strlen(home_dir) + 34, "%s/share/.voice/tts/1.0/engine-info", home_dir);
824
825                                 md_iter = g_list_first(list);
826                                 while (NULL != md_iter) {
827                                         md = (metadata *)md_iter->data;
828                                         LOGD(" - key(%s) value(%s)", md->key, md->value);
829                                         md_iter = g_list_next(md_iter);
830                                 }
831
832                                 if (0 != __remove_engine_info_xml(pkgid, user_type, uid)) {
833                                         LOGE("[ERROR] Fail to remove engine info file");
834                                 }
835
836                                 G_FREE(home_dir)
837                                 FREE(g_dir_engine_info)
838                         }
839                         G_FREE(user_type)
840
841                         LOGD("Finish release memory");
842                         iter = g_list_next(iter);
843                         LOGD("Finish next iter");
844                 }
845
846                 gum_user_service_list_free(users);
847                 g_object_unref(gus);
848                 gus = NULL;
849         } else {
850                 /* user directory */
851                 LOGD("[DEBUG] usertype: %s", g_user_type);
852
853                 ret = tzplatform_set_user(g_uid);
854                 if (ret < 0) {
855                         LOGE("[ERROR] Invalid uid");
856                         g_object_unref(g_guser);
857                         g_guser = NULL;
858                         G_FREE(g_user_type)
859                         return -1;
860                 } else {
861                         LOGD("TZ_USER_HOME: %s", tzplatform_mkstr(TZ_USER_HOME, "/"));
862                         printf("[Parser Debug][DEBUG] TZ_USER_HOME: %s", tzplatform_mkstr(TZ_USER_HOME, "/"));
863                 }
864
865                 g_dir_engine_info = strdup(TTS_ENGINE_INFO);
866                 if (NULL == g_dir_engine_info) {
867                         LOGE("[ERROR] Fail to allocate memory");
868                         g_object_unref(g_guser);
869                         g_guser = NULL;
870                         G_FREE(g_user_type)
871                         return -1;
872                 }
873
874                 if (0 != __remove_engine_info_xml(pkgid, g_user_type, g_uid)) {
875                         LOGE("[ERROR] Fail to remove engine info file");
876                 }
877
878         }
879
880         if (NULL != g_guser) {
881                 g_object_unref(g_guser);
882                 g_guser = NULL;
883         }
884         G_FREE(g_user_type)
885
886         FREE(g_dir_engine_info)
887
888         LOGD("");
889         return 0;
890 }
891
892 EXPORT_API
893 int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgid, const char *appid, GList *list)
894 {
895         LOGD("METADATA UPGRADE");
896         LOGD("pkgid(%s) appid(%s) list(%d)", pkgid, appid, g_list_length(list));
897
898         PKGMGR_MDPARSER_PLUGIN_UNINSTALL(pkgid, appid, list);
899         PKGMGR_MDPARSER_PLUGIN_INSTALL(pkgid, appid, list);
900
901         LOGD("");
902         return 0;
903 }