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