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