Fix memory leak
[platform/core/uifw/capi-ui-sticker.git] / sticker-parser / sticker-parser.c
1 /*
2  * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
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 <unistd.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <dlog.h>
22 #include <glib.h>
23 #include <json-glib/json-glib.h>
24 #include <pkgmgr-info.h>
25 #include <sqlite3.h>
26 #include <tzplatform_config.h>
27 #include <package_manager.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <errno.h>
31 #include <dirent.h>
32 #include <fcntl.h>
33
34 #ifndef EXPORT_API
35 #define EXPORT_API __attribute__((visibility("default")))
36 #endif
37
38 #ifdef LOG_TAG
39 #undef LOG_TAG
40 #endif
41 #define LOG_TAG "STICKER_PARSER"
42
43 #define STICKER_DIRECTORY tzplatform_mkpath(TZ_SYS_SHARE, "sticker-data")
44 #define UIFW_ID           502
45 #define APPFW_ID          301
46 #define MAX_ERROR_BUFFER  256
47
48 static char error_buffer[MAX_ERROR_BUFFER];
49
50 typedef struct metadata {
51     const char *key;
52     const char *value;
53 } metadata;
54
55 static char* __get_string_from_object(JsonObject *object, const char *key)
56 {
57     if (json_object_has_member(object, key) == false)
58         return NULL;
59
60     const char *str = json_object_get_string_member(object, key);
61     if (str != NULL)
62         return strdup(str);
63     else
64         return NULL;
65 }
66
67 static int __get_int_from_object(JsonObject *object, const char *key)
68 {
69     if (json_object_has_member(object, key) == false)
70         return -1;
71
72     int type = json_object_get_int_member(object, key);
73
74     return type;
75 }
76
77 static sqlite3 *__db_open(const char *path)
78 {
79     int ret;
80     sqlite3 *db = NULL;
81     char *err = NULL;
82
83     ret = sqlite3_open(path, &db);
84     if (ret != SQLITE_OK) {
85         LOGE("Failed to open db : %s", sqlite3_errmsg(db));
86         return NULL;
87     }
88
89     ret = sqlite3_exec(db, "PRAGMA foreign_keys = ON", NULL, NULL, &err);
90     if (ret != SQLITE_OK) {
91         LOGE("Failed to turn on foreign keys : %s", err);
92     }
93
94     if (err)
95         sqlite3_free(err);
96
97     return db;
98 }
99
100 static int __change_ownership(const char *path, int user, int group)
101 {
102     int ret;
103     uid_t uid = (uid_t)user;
104     gid_t gid = (gid_t)group;
105
106     ret = chown(path, uid, gid);
107     if (ret != 0) {
108         strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
109         LOGE("chown() failed : %s", error_buffer);
110     }
111
112     return ret;
113 }
114
115 static int __remove_app_path(char *uri, const char *app_path)
116 {
117     int n = 0;
118     int k = 0;
119     for (int i = 0; uri[i] != '\0'; i++) {
120         if (uri[i] == app_path[n]) {
121             k = i;
122             while (uri[i] == app_path[n]) {
123                 if (app_path[++n] == '\0') {
124                     for(; uri[k + n] != '\0'; k++) {
125                         uri[k] = uri[k + n];
126                     }
127                     uri[k] = '\0';
128                     return 1;
129                 }
130                 i++;
131             }
132             n = 0;
133             i--;
134         }
135     }
136     return 0;
137 }
138
139 static int __mkdirs(const char *path, mode_t mode)
140 {
141     int len = 0;
142     char prev_path[2048];
143     const char *tmp = path;
144
145     if (!path || strlen(path) > 2048)
146         return -1;
147
148     memset(prev_path, '\0', 2048);
149     while ((tmp = strchr(tmp, '/')) != NULL) {
150         len = tmp - path;
151         tmp++;
152
153         if (len == 0)
154             continue;
155
156         strncpy(prev_path, path, len);
157         prev_path[len] = 0x00;
158
159         if (mkdir(prev_path, mode) == -1) {
160             if (errno != EEXIST) {
161                 strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
162                 LOGE("directory create error : %s", error_buffer);
163                 return -1;
164             }
165         } else {
166             if (__change_ownership(prev_path, UIFW_ID, UIFW_ID) != 0)
167                 LOGE("failed to change ownership");
168         }
169     }
170
171     if (mkdir(prev_path, mode) == -1) {
172         if (errno != EEXIST) {
173             strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
174             LOGE("directory create error : %s", error_buffer);
175             return -1;
176         }
177     } else {
178         if (__change_ownership(prev_path, UIFW_ID, UIFW_ID) != 0)
179             LOGE("failed to change ownership");
180     }
181     return 0;
182 }
183
184 static int __file_copy(const char *src, const char *dest)
185 {
186     int ret = 0;
187     int fd = -1, n_fd = -1;
188     char buf[4096];
189     int tmp_err = 0;
190     int size;
191
192     memset(buf, '\0', 4096);
193     fd = open(src, O_RDONLY);
194     n_fd = open(dest, O_WRONLY | O_CREAT | O_TRUNC, 0755);
195
196     if (fd == -1 || n_fd == -1) {
197         tmp_err = errno;
198         ret = -1;
199         goto cleanup;
200     }
201
202     while((size = read(fd, buf, 4096))) {
203         if (size == -1) {
204             if(errno == EINTR)
205                 continue;
206
207             tmp_err = errno;
208             ret = -1;
209             goto cleanup;
210         }
211
212         while(write(n_fd, buf, size) == -1) {
213             if(errno == EINTR) {
214                 continue;
215             } else {
216                 tmp_err = errno;
217                 goto cleanup;
218             }
219         }
220     }
221
222 cleanup:
223     if (fd != -1)
224         close(fd);
225
226     if (n_fd != -1)
227         close(n_fd);
228
229     errno = tmp_err;
230     return ret;
231 }
232
233 static char* __convert_sticker_uri(const char *uri, const char *appid, const char *app_path)
234 {
235     int ret;
236     char *rel_path = strdup(uri);
237
238     __remove_app_path(rel_path, app_path);
239     int len = strlen(STICKER_DIRECTORY) + strlen(appid) + strlen(rel_path) + 2;
240     char *new_path = (char *)calloc(len, sizeof(char));
241     if (new_path == NULL) {
242         free(rel_path);
243         rel_path = NULL;
244         return NULL;
245     }
246
247     snprintf(new_path, len, "%s/%s%s",STICKER_DIRECTORY, appid, rel_path);
248
249     if (access(new_path, F_OK) == 0) {
250         LOGE("sticker file already exists");
251         ret = -1;
252         goto cleanup;
253     }
254
255     ret = __mkdirs(new_path, 0755);
256     if (ret != 0) {
257         LOGE("directory create error");
258         goto cleanup;
259     }
260
261     if (__file_copy(uri, new_path) == -1) {
262         strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
263         LOGE("failed to copy sticker file : %s", error_buffer);
264         ret = -1;
265         goto cleanup;
266     }
267
268     ret = unlink(uri);
269     if (ret != 0) {
270         strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
271         LOGE("failed to remove sticker file : %s", error_buffer);
272     }
273
274     if (__change_ownership(new_path, UIFW_ID, UIFW_ID) != 0)
275         LOGE("failed to change ownership");
276
277 cleanup:
278     free(rel_path);
279     rel_path = NULL;
280
281     if (ret == 0) {
282         return new_path;
283     } else {
284         free(new_path);
285         new_path = NULL;
286         return NULL;
287     }
288 }
289
290 static void __insert_sticker_info(const char *app_id, int type, const char *uri, const char *group, const char *thumbnail, const char *description)
291 {
292     int ret;
293     sqlite3 *db = NULL;
294     sqlite3_stmt *stmt = NULL;
295     const char *db_path;
296
297     db_path = tzplatform_mkpath(TZ_SYS_DB, ".sticker_info.db");
298     db = __db_open(db_path);
299     if (!db)
300         return;
301
302     ret = sqlite3_prepare_v2(db, "INSERT INTO sticker_info (app_id, type, uri, thumbnail, description, group_name, date) VALUES (?, ?, ?, ?, ?, ?, DateTime('now','localtime'))",-1, &stmt, NULL);
303     if (ret == SQLITE_OK) {
304         sqlite3_bind_text(stmt, 1, app_id, -1, SQLITE_TRANSIENT);
305         sqlite3_bind_int(stmt, 2, type);
306         sqlite3_bind_text(stmt, 3, uri, -1, SQLITE_TRANSIENT);
307         sqlite3_bind_text(stmt, 4, thumbnail, -1, SQLITE_TRANSIENT);
308         sqlite3_bind_text(stmt, 5, description, -1, SQLITE_TRANSIENT);
309         sqlite3_bind_text(stmt, 6, group, -1, SQLITE_TRANSIENT);
310
311         ret = sqlite3_step(stmt);
312         if (ret != SQLITE_OK && ret != SQLITE_DONE)
313             LOGE("sqlite3_step() failed : ret(%d)", ret);
314
315         if (sqlite3_changes(db) == 0)
316             LOGE("No changes to DB");
317
318         sqlite3_finalize(stmt);
319         sqlite3_close(db);
320     } else {
321         LOGE("failed to insert sticker information : %s", sqlite3_errmsg(db));
322         sqlite3_finalize(stmt);
323         sqlite3_close(db);
324     }
325
326     return;
327 }
328
329 static void __insert_sticker_keyword_info(const char *keyword)
330 {
331     int ret;
332     int record_id;
333     sqlite3 *db = NULL;
334     sqlite3_stmt *stmt = NULL;
335     const char *db_path;
336
337     db_path = tzplatform_mkpath(TZ_SYS_DB, ".sticker_info.db");
338     db = __db_open(db_path);
339     if (!db)
340         return;
341
342     ret = sqlite3_prepare_v2(db, "SELECT sticker_info_id FROM sticker_info ORDER BY sticker_info_id DESC LIMIT 1", -1, &stmt, NULL);
343     if (ret == SQLITE_OK) {
344         ret = sqlite3_step(stmt);
345         if (ret == SQLITE_ERROR) {
346             LOGE("sqlite3_step() failed : ret(%d)", ret);
347             sqlite3_finalize(stmt);
348             sqlite3_close(db);
349         } else {
350             record_id = sqlite3_column_int(stmt, 0);
351
352             sqlite3_finalize(stmt);
353             stmt = NULL;
354
355             ret = sqlite3_prepare_v2(db, "INSERT INTO sticker_keyword_info (sticker_info_id, keyword) VALUES (?, ?)", -1, &stmt, NULL);
356             if (ret == SQLITE_OK) {
357                 sqlite3_bind_int(stmt, 1, record_id);
358                 sqlite3_bind_text(stmt, 2, keyword, -1, SQLITE_TRANSIENT);
359
360                 ret = sqlite3_step(stmt);
361                 if (ret != SQLITE_OK && ret != SQLITE_DONE)
362                     LOGE("sqlite3_step() failed : ret(%d)", ret);
363
364                 if (sqlite3_changes(db) == 0)
365                     LOGE("No changes to DB");
366
367                 sqlite3_finalize(stmt);
368                 sqlite3_close(db);
369             } else {
370                 LOGE("fail to insert sticker keyword : %s", sqlite3_errmsg(db));
371                 sqlite3_finalize(stmt);
372                 sqlite3_close(db);
373             }
374         }
375     } else {
376         LOGE("fail to insert sticker information : %s", sqlite3_errmsg(db));
377         sqlite3_finalize(stmt);
378         sqlite3_close(db);
379     }
380
381     return;
382 }
383
384 static int __get_sticker_info_from_json(const char *appid, const char *file_path, const char *app_path)
385 {
386     int ret = 1;
387     JsonParser* parser = NULL;
388     GError* err_msg = NULL;
389     char *uri = NULL;
390     char *group = NULL;
391     char *description = NULL;
392     char *thumbnail = NULL;
393     char *uri_path = NULL;
394
395     parser = json_parser_new();
396     json_parser_load_from_file(parser, file_path, &err_msg);
397     if (err_msg) {
398         LOGE("failed to load json file. error message: %s", err_msg->message);
399         ret = 0;
400         goto cleanup;
401     }
402
403     JsonNode *root = json_parser_get_root(parser);
404     if (root == NULL) {
405         LOGE("failed to get root");
406         ret = 0;
407         goto cleanup;
408     }
409
410     JsonObject *root_obj = json_node_get_object(root);
411     if (root_obj == NULL) {
412         LOGE("failed to get object");
413         ret = 0;
414         goto cleanup;
415     }
416
417     JsonArray *sticker_arr = json_object_get_array_member(root_obj, "sticker");
418     if (sticker_arr == NULL) {
419         LOGE("failed to get array member");
420         ret = 0;
421         goto cleanup;
422     }
423
424     int arr_len = json_array_get_length(sticker_arr);
425     for (int i = 0; i < arr_len; i++) {
426         JsonObject *info_object = json_array_get_object_element(sticker_arr, i);
427         if (info_object != NULL) {
428             int type = __get_int_from_object(info_object, "type");
429             if (type < 1)
430                 continue;
431
432             uri = __get_string_from_object(info_object, "uri");
433             if (!uri)
434                 goto free_memory;
435
436             group = __get_string_from_object(info_object, "group");
437             if (!group)
438                 goto free_memory;
439
440             thumbnail = __get_string_from_object(info_object, "thumbnail");
441             description = __get_string_from_object(info_object, "description");
442
443             JsonArray *keyword_arr = json_object_get_array_member(info_object, "keyword");
444             int keyword_arr_len = json_array_get_length(keyword_arr);
445             if (keyword_arr_len < 1)
446                 goto free_memory;
447
448             if (type == 1) {
449                 if (access(uri, F_OK) == 0) {
450                     char *new_uri = __convert_sticker_uri(uri, appid, app_path);
451                     if (!new_uri)
452                         goto free_memory;
453                     __insert_sticker_info(appid, type, new_uri, group, thumbnail, description);
454
455                     if (new_uri) {
456                         free(new_uri);
457                         new_uri = NULL;
458                     }
459                 } else {
460                     int path_len = strlen(app_path) + strlen(uri) + 2;
461                     uri_path = (char *)calloc(path_len, sizeof(char));
462                     if (!uri_path) {
463                         LOGE("failed to alloc memory");
464                         goto free_memory;
465                     }
466
467                     if (uri[0] == '/')
468                         snprintf(uri_path, path_len, "%s%s",app_path, uri);
469                     else
470                         snprintf(uri_path, path_len, "%s%s%s",app_path, "/", uri);
471
472                     if (access(uri_path, F_OK) == 0) {
473                         char *new_uri = __convert_sticker_uri(uri_path, appid, app_path);
474                         if (!new_uri) {
475                             free(uri_path);
476                             uri_path = NULL;
477                             goto free_memory;
478                         }
479                         __insert_sticker_info(appid, type, new_uri, group, thumbnail, description);
480
481                         free(new_uri);
482                         new_uri = NULL;
483
484                         free(uri_path);
485                         uri_path = NULL;
486                     } else {
487                         LOGE("%s does not exist", uri_path);
488                         free(uri_path);
489                         uri_path = NULL;
490                         goto free_memory;
491                     }
492                 }
493             } else {
494                 __insert_sticker_info(appid, type, uri, group, thumbnail, description);
495             }
496
497             for (int j = 0; j < keyword_arr_len; j++) {
498                 __insert_sticker_keyword_info(json_array_get_string_element(keyword_arr, j));
499             }
500
501 free_memory:
502             if (uri) {
503                 free(uri);
504                 uri = NULL;
505             }
506
507             if (group) {
508                 free(group);
509                 group = NULL;
510             }
511
512             if (thumbnail) {
513                 free(thumbnail);
514                 thumbnail = NULL;
515             }
516
517             if (description) {
518                 free(description);
519                 description = NULL;
520             }
521         }
522     }
523
524 cleanup:
525     if (err_msg)
526         g_error_free(err_msg);
527
528     if (parser)
529         g_object_unref(parser);
530
531     return ret;
532 }
533
534 static void __delete_sticker_info(const char *db_path, int record_id)
535 {
536     int ret;
537     sqlite3 *db = NULL;
538     sqlite3_stmt *stmt = NULL;
539
540     db = __db_open(db_path);
541         if (!db)
542             return;
543
544     ret = sqlite3_prepare_v2(db, "DELETE FROM sticker_info WHERE sticker_info_id = ?", -1, &stmt, NULL);
545     if (ret != SQLITE_OK) {
546         LOGE("failed to delete sticker information : %s", sqlite3_errmsg(db));
547         sqlite3_finalize(stmt);
548         sqlite3_close(db);
549         goto cleanup;
550     }
551
552     sqlite3_bind_int(stmt, 1, record_id);
553
554     ret = sqlite3_step(stmt);
555     if (ret != SQLITE_OK && ret != SQLITE_DONE) {
556         LOGE("sqlite3_step() failed : ret(%d)", ret);
557         goto cleanup;
558     }
559
560     if (sqlite3_changes(db) == 0) {
561         LOGE("No changes to DB");
562         goto cleanup;
563     }
564
565     sqlite3_finalize(stmt);
566     sqlite3_close(db);
567     return;
568
569 cleanup:
570     sqlite3_finalize(stmt);
571     sqlite3_close(db);
572     return;
573 }
574
575 static int __remove_directory(const char *path, int is_error_stop)
576 {
577     DIR *dir_ptr = NULL;
578     struct dirent *file = NULL;
579     struct stat buf;
580     char filename[1024];
581
582     memset(filename, '\0', 1024);
583
584     if (__change_ownership(path, APPFW_ID, APPFW_ID) != 0)
585         LOGE("failed to change ownership");
586
587     dir_ptr = opendir(path);
588     if (dir_ptr == NULL)
589         return unlink(path);
590
591     while ((file = readdir(dir_ptr)) != NULL) {
592         if (strcmp(file->d_name, ".") == 0 || strcmp(file->d_name, "..") == 0)
593             continue;
594
595         snprintf(filename, strlen(path) + strlen(file->d_name) + 2, "%s/%s", path, file->d_name);
596
597         if (lstat(filename, &buf) == -1)
598             continue;
599
600         if (S_ISDIR(buf.st_mode)) {
601             if (__remove_directory(filename, is_error_stop) == -1 && is_error_stop) {
602                 closedir(dir_ptr);
603                 return -1;
604             }
605         } else if (S_ISREG(buf.st_mode) || S_ISLNK(buf.st_mode)) {
606             if (unlink(filename) == -1 && is_error_stop) {
607                 closedir(dir_ptr);
608                 return -1;
609             }
610         }
611     }
612
613     closedir(dir_ptr);
614     return rmdir(path);
615 }
616
617 EXPORT_API
618 int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgid, const char *appid, GList *list)
619 {
620     LOGD("METADATA INSTALL");
621     LOGD("pkgid: %s, appid: %s", pkgid, appid);
622
623     metadata *md = NULL;
624     GList *md_list = NULL;
625     package_info_h package_info = NULL;
626     char *app_path = NULL;
627     char *file_path = NULL;
628     int ret = 0;
629
630     ret = package_info_create(pkgid, &package_info);
631     if (ret != PACKAGE_MANAGER_ERROR_NONE || package_info == NULL) {
632         LOGE("failed to create package_info. ret: %d", ret);
633         goto cleanup;
634     }
635
636     ret = package_info_get_root_path(package_info, &app_path);
637     if (ret != PACKAGE_MANAGER_ERROR_NONE || app_path == NULL) {
638         LOGE("failed to create package_info. ret: %d", ret);
639         goto cleanup;
640     }
641
642     for(md_list = g_list_first(list); md_list != NULL; md_list = md_list->next) {
643         md = (metadata *)md_list->data;
644         int path_len = strlen(app_path) + strlen((char *)md->value) + 2;
645         file_path = (char *)calloc(path_len, sizeof(char));
646         if (!file_path) {
647             LOGE("failed to alloc memory");
648             continue;
649         }
650
651         if ((char)md->value[0] == '/')
652             snprintf(file_path, path_len, "%s%s",app_path, (char *)md->value);
653         else
654             snprintf(file_path, path_len, "%s%s%s",app_path, "/", (char *)md->value);
655
656         if (__get_sticker_info_from_json(appid, file_path, app_path) == 0)
657             LOGE("failed to get sticker information [path : %s]", file_path);
658
659         free(file_path);
660         file_path = NULL;
661     }
662
663 cleanup:
664     if (package_info)
665         package_info_destroy(package_info);
666
667     if (app_path) {
668         free(app_path);
669         app_path = NULL;
670     }
671
672     return 0;
673 }
674
675 EXPORT_API
676 int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(const char *pkgid, const char *appid, GList *list)
677 {
678     LOGD("METADATA UNINSTALL");
679     LOGD("pkgid: %s, appid: %s", pkgid, appid);
680
681     int ret;
682     int del_id;
683     sqlite3 *db = NULL;
684     sqlite3_stmt *stmt = NULL;
685     const char *db_path;
686     GList *id_list = NULL;
687
688     db_path = tzplatform_mkpath(TZ_SYS_DB, ".sticker_info.db");
689     db = __db_open(db_path);
690     if (!db)
691         return 0;
692
693     ret = sqlite3_prepare_v2(db, "SELECT sticker_info_id from sticker_info WHERE app_id = ?", -1, &stmt, NULL);
694     if (ret == SQLITE_OK) {
695         sqlite3_bind_text(stmt, 1, appid, -1, SQLITE_TRANSIENT);
696         while (sqlite3_step(stmt) == SQLITE_ROW) {
697             const unsigned char *record_id = sqlite3_column_text(stmt, 0);
698             if (record_id)
699                 id_list = g_list_append(id_list, strdup((const char *)record_id));
700         }
701
702         sqlite3_finalize(stmt);
703         sqlite3_close(db);
704
705         for(GList *tmp = g_list_first(id_list); tmp != NULL; tmp = tmp->next) {
706             del_id = atoi((const char*)tmp->data);
707             __delete_sticker_info(db_path, del_id);
708         }
709
710         if (id_list)
711             g_list_free_full(id_list, free);
712     } else {
713         LOGE("failed to get sticker id");
714         sqlite3_finalize(stmt);
715         sqlite3_close(db);
716     }
717
718     return 0;
719 }
720
721 EXPORT_API
722 int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgid, const char *appid, GList *list)
723 {
724     LOGD("METADATA UPGRADE");
725     LOGD("pkgid: %s, appid: %s", pkgid, appid);
726
727     PKGMGR_MDPARSER_PLUGIN_UNINSTALL(pkgid, appid, list);
728     PKGMGR_MDPARSER_PLUGIN_INSTALL(pkgid, appid, list);
729     return 0;
730 }
731
732 EXPORT_API
733 int PKGMGR_CATEGORY_PARSER_PLUGIN_INSTALL(const char *pkgid, const char *appid, GList *list)
734 {
735     LOGD("STICKER CATEGORY INSTALL");
736     LOGD("pkgid: %s, appid: %s", pkgid, appid);
737
738     int len = strlen(STICKER_DIRECTORY) + strlen(appid) + 2;
739     char *dir_path = (char *)calloc(len, sizeof(char));
740
741     if (dir_path != NULL) {
742         snprintf(dir_path, len, "%s%s%s", STICKER_DIRECTORY, "/", appid);
743         LOGD("directory path : %s", dir_path);
744
745         if (mkdir(dir_path, 0755) == -1 && errno != EEXIST) {
746             strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
747             LOGE("directory create error : %s", error_buffer);
748         } else {
749             if (__change_ownership(dir_path, UIFW_ID, UIFW_ID) != 0)
750                 LOGE("failed to change ownership");
751         }
752
753         free(dir_path);
754         dir_path = NULL;
755     }
756
757     return 0;
758 }
759
760 EXPORT_API
761 int PKGMGR_CATEGORY_PARSER_PLUGIN_UNINSTALL(const char *pkgid, const char *appid, GList *list)
762 {
763     LOGD("STICKER CATEGORY UNINSTALL");
764     LOGD("pkgid: %s, appid: %s", pkgid, appid);
765
766     int len = strlen(STICKER_DIRECTORY) + strlen(appid) + 2;
767     char * dir_path = (char *)calloc(len, sizeof(char));
768
769     if (dir_path != NULL) {
770         snprintf(dir_path, len, "%s%s%s", STICKER_DIRECTORY, "/", appid);
771         LOGD("directory path : %s", dir_path);
772
773         if (__remove_directory(dir_path, 0) < 0) {
774             strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
775             LOGE("directory remove error : %s", error_buffer);
776         }
777
778         free(dir_path);
779         dir_path = NULL;
780     }
781
782     return 0;
783 }
784
785 EXPORT_API
786 int PKGMGR_CATEGORY_PARSER_PLUGIN_UPGRADE(const char *pkgid, const char *appid, GList *list)
787 {
788     LOGD("STICKER CATEGORY UPGRADE");
789     LOGD("pkgid: %s, appid: %s", pkgid, appid);
790
791     PKGMGR_CATEGORY_PARSER_PLUGIN_UNINSTALL(pkgid, appid, list);
792     PKGMGR_CATEGORY_PARSER_PLUGIN_INSTALL(pkgid, appid, list);
793
794     return 0;
795 }