Initial commit
[platform/core/uifw/capi-ui-sticker.git] / server / stickerd_data_manager.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 <stdio.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <tzplatform_config.h>
21 #include <gio/gunixfdlist.h>
22 #include <dlog.h>
23 #include <json-glib/json-glib.h>
24 #include <package_manager.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <errno.h>
28 #include <dirent.h>
29 #include <fcntl.h>
30
31 #include "stickerd_dbus.h"
32 #include "stickerd_data_manager.h"
33 #include "stickerd_db_manager.h"
34 #include "sticker_defs.h"
35 #include "stickerd_error.h"
36
37 #ifdef LOG_TAG
38 #undef LOG_TAG
39 #endif
40 #define LOG_TAG "STICKERD_DATA_MANAGER"
41
42 #define STICKER_DIRECTORY tzplatform_mkpath(TZ_SYS_SHARE, "sticker-data")
43 #define MAX_ERROR_BUFFER  256
44
45 static GHashTable *_monitoring_hash;
46 static char error_buffer[MAX_ERROR_BUFFER];
47
48 static void _on_name_appeared(GDBusConnection *connection,
49         const gchar     *name,
50         const gchar     *name_owner,
51         gpointer         user_data)
52 {
53     LOGD("name: %s", name);
54 }
55
56 static void _on_name_vanished(GDBusConnection *connection,
57         const gchar     *name,
58         gpointer         user_data)
59 {
60     monitoring_info_s *info = (monitoring_info_s *)user_data;
61
62     if (info) {
63         LOGD("name: %s", name);
64         g_bus_unwatch_name(info->watcher_id);
65         delete_monitoring_list(&_monitoring_hash, info->bus_name, info->uid);
66
67         if (info->bus_name)
68             free(info->bus_name);
69         free(info);
70         info = NULL;
71     }
72 }
73
74 static void _stickerd_client_dbus_method_call_handler(GDBusConnection *conn, const gchar *sender, const gchar *object_path,
75         const gchar *iface_name, const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation,
76         gpointer user_data)
77 {
78     LOGD("stickerd method_name: %s, sender: %s", method_name, sender);
79
80     GVariant *reply_body = NULL;
81     int ret = STICKERD_SERVER_ERROR_OPERATION_FAILED;
82
83     if (g_strcmp0(method_name, "sticker_service_register") == 0) {
84         ret = stickerd_server_register(parameters, &reply_body, sender,
85             _on_name_appeared, _on_name_vanished, &_monitoring_hash);
86     } else if (g_strcmp0(method_name, "insert_sticker_info") == 0) {
87         ret = stickerd_insert_sticker_info(parameters, &reply_body);
88     } else if  (g_strcmp0(method_name, "update_sticker_info_by_json") == 0) {
89         ret = stickerd_insert_sticker_info_by_json(parameters, &reply_body, sender);
90     } else if (g_strcmp0(method_name, "delete_sticker_info") == 0) {
91         ret = stickerd_del_sticker_info(parameters, &reply_body);
92     } else if (g_strcmp0(method_name, "update_sticker_type") == 0) {
93         ret = stickerd_update_sticker_type(parameters, &reply_body);
94     } else if (g_strcmp0(method_name, "update_sticker_uri") == 0) {
95         ret = stickerd_update_sticker_uri(parameters, &reply_body);
96     } else if (g_strcmp0(method_name, "update_sticker_thumbnail") == 0) {
97         ret = stickerd_update_sticker_thumbnail(parameters, &reply_body);
98     } else if (g_strcmp0(method_name, "update_sticker_description") == 0) {
99         ret = stickerd_update_sticker_description(parameters, &reply_body);
100     } else if (g_strcmp0(method_name, "update_sticker_group") == 0) {
101         ret = stickerd_update_sticker_group(parameters, &reply_body);
102     } else if (g_strcmp0(method_name, "update_sticker_keyword") == 0) {
103         ret = stickerd_update_sticker_keyword(parameters, &reply_body);
104     } else if (g_strcmp0(method_name, "get_sticker_info") == 0) {
105         ret = stickerd_get_sticker_info(parameters, &reply_body);
106     } else if (g_strcmp0(method_name, "get_group_list") == 0) {
107         ret = stickerd_get_group_list(parameters, &reply_body);
108     } else if (g_strcmp0(method_name, "get_keyword_list") == 0) {
109         ret = stickerd_get_keyword_list(parameters, &reply_body);
110     } else if (g_strcmp0(method_name, "get_sticker_count") == 0) {
111         ret = stickerd_get_sticker_count(parameters, &reply_body);
112     } else if (g_strcmp0(method_name, "get_all_sticker_info") == 0) {
113         ret = stickerd_get_all_sticker_info(parameters, &reply_body);
114     } else if (g_strcmp0(method_name, "get_sticker_info_by_appid") == 0) {
115         ret = stickerd_get_sticker_info_by_app_id(parameters, &reply_body);
116     } else if (g_strcmp0(method_name, "get_sticker_info_by_type") == 0) {
117         ret = stickerd_get_sticker_info_by_type(parameters, &reply_body);
118     } else if (g_strcmp0(method_name, "get_sticker_info_by_group") == 0) {
119         ret = stickerd_get_sticker_info_by_group(parameters, &reply_body);
120     } else if (g_strcmp0(method_name, "get_sticker_info_by_keyword") == 0) {
121         ret = stickerd_get_sticker_info_by_keyword(parameters, &reply_body);
122     }
123
124     if (ret == STICKERD_SERVER_ERROR_NONE) {
125         LOGD("method_call successful, method_name : %s", method_name);
126         g_dbus_method_invocation_return_value(invocation, reply_body);
127     } else {
128         LOGE("method_call failed, method_name : %s", method_name);
129         g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, ret, "sticker error");
130     }
131
132     if (reply_body)
133         g_variant_unref(reply_body);
134 }
135
136 static const GDBusInterfaceVTable _sticker_interface_vtable = {
137         _stickerd_client_dbus_method_call_handler,
138         NULL,
139         NULL
140 };
141
142 int stickerd_register_dbus_interface(void)
143 {
144     static gchar introspection_xml[] =
145             "  <node>"
146             "  <interface name='org.tizen.sticker_service'>"
147             "        <method name='sticker_service_register'>"
148             "        </method>"
149
150             "        <method name='insert_sticker_info'>"
151             "          <arg type='a{iv}' name='sticker_info' direction='in'/>"
152             "          <arg type='a(s)' name='keyword_list' direction='in'/>"
153             "          <arg type='i' name='record_id' direction='out'/>"
154             "        </method>"
155
156             "        <method name='update_sticker_info_by_json'>"
157             "          <arg type='s' name='app_id' direction='in'/>"
158             "          <arg type='s' name='json_path' direction='in'/>"
159             "        </method>"
160
161             "        <method name='delete_sticker_info'>"
162             "          <arg type='i' name='record_id' direction='in'/>"
163             "        </method>"
164
165             "        <method name='update_sticker_type'>"
166             "          <arg type='i' name='record_id' direction='in'/>"
167             "          <arg type='i' name='type' direction='in'/>"
168             "        </method>"
169
170             "        <method name='update_sticker_uri'>"
171             "          <arg type='i' name='record_id' direction='in'/>"
172             "          <arg type='s' name='app_id' direction='in'/>"
173             "          <arg type='i' name='type' direction='in'/>"
174             "          <arg type='s' name='uri' direction='in'/>"
175             "        </method>"
176
177             "        <method name='update_sticker_thumbnail'>"
178             "          <arg type='i' name='record_id' direction='in'/>"
179             "          <arg type='s' name='thumbnail' direction='in'/>"
180             "        </method>"
181
182             "        <method name='update_sticker_description'>"
183             "          <arg type='i' name='record_id' direction='in'/>"
184             "          <arg type='s' name='description' direction='in'/>"
185             "        </method>"
186
187             "        <method name='update_sticker_group'>"
188             "          <arg type='i' name='record_id' direction='in'/>"
189             "          <arg type='s' name='group' direction='in'/>"
190             "        </method>"
191
192             "        <method name='update_sticker_keyword'>"
193             "          <arg type='i' name='record_id' direction='in'/>"
194             "          <arg type='a(s)' name='keyword' direction='in'/>"
195             "        </method>"
196
197             "        <method name='get_sticker_info'>"
198             "          <arg type='i' name='record_id' direction='in'/>"
199             "          <arg type='a{iv}' name='sticker_info' direction='out'/>"
200             "          <arg type='a(s)' name='keyword_list' direction='out'/>"
201             "        </method>"
202
203             "        <method name='get_group_list'>"
204             "          <arg type='a(s)' name='group_list' direction='out'/>"
205             "        </method>"
206
207             "        <method name='get_keyword_list'>"
208             "          <arg type='a(s)' name='keyword_list' direction='out'/>"
209             "        </method>"
210
211             "        <method name='get_sticker_count'>"
212             "          <arg type='s' name='app_id' direction='in'/>"
213             "          <arg type='i' name='count' direction='out'/>"
214             "        </method>"
215
216             "        <method name='get_all_sticker_info'>"
217             "          <arg type='i' name='offset' direction='in'/>"
218             "          <arg type='i' name='count' direction='in'/>"
219             "          <arg type='a(i)' name='id_list' direction='out'/>"
220             "        </method>"
221
222             "        <method name='get_sticker_info_by_appid'>"
223             "          <arg type='s' name='app_id' direction='in'/>"
224             "          <arg type='i' name='offset' direction='in'/>"
225             "          <arg type='i' name='count' direction='in'/>"
226             "          <arg type='a(i)' name='id_list' direction='out'/>"
227             "        </method>"
228
229             "        <method name='get_sticker_info_by_type'>"
230             "          <arg type='i' name='type' direction='in'/>"
231             "          <arg type='i' name='offset' direction='in'/>"
232             "          <arg type='i' name='count' direction='in'/>"
233             "          <arg type='a(i)' name='id_list' direction='out'/>"
234             "        </method>"
235
236             "        <method name='get_sticker_info_by_group'>"
237             "          <arg type='s' name='group' direction='in'/>"
238             "          <arg type='i' name='offset' direction='in'/>"
239             "          <arg type='i' name='count' direction='in'/>"
240             "          <arg type='a(i)' name='id_list' direction='out'/>"
241             "        </method>"
242
243             "        <method name='get_sticker_info_by_keyword'>"
244             "          <arg type='s' name='keyword' direction='in'/>"
245             "          <arg type='i' name='offset' direction='in'/>"
246             "          <arg type='i' name='count' direction='in'/>"
247             "          <arg type='a(i)' name='id_list' direction='out'/>"
248             "        </method>"
249             "  </interface>"
250             "  </node>";
251
252     return stickerd_server_register_dbus_interface(introspection_xml, _sticker_interface_vtable);
253 }
254
255 int stickerd_dbus_init(void)
256 {
257     int ret;
258
259     ret = stickerd_register_dbus_interface();
260     if (ret != STICKERD_SERVER_ERROR_NONE) {
261         LOGE("Failed to register dbus interface : %d", ret);
262         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
263     }
264
265     return STICKERD_SERVER_ERROR_NONE;
266 }
267
268 static int _check_file_exist(const char *app_id, const char *path)
269 {
270     int ret = 0;
271     package_info_h package_info = NULL;
272     char *app_path = NULL;
273     char *file_path = NULL;
274
275     if (access(path, F_OK) == 0) {
276         ret = 0;
277         goto cleanup;
278     }
279
280     ret = package_info_create(app_id, &package_info);
281     if (ret != PACKAGE_MANAGER_ERROR_NONE || package_info == NULL) {
282         LOGE("faild to create package_info. ret: %d", ret);
283         ret = -1;
284         goto cleanup;
285     }
286
287     ret = package_info_get_root_path(package_info, &app_path);
288     if (ret != PACKAGE_MANAGER_ERROR_NONE || app_path == NULL) {
289         LOGE("faild to create package_info. ret: %d", ret);
290         ret = -1;
291         goto cleanup;
292     }
293
294     int path_len = strlen(app_path) + strlen(path) + 2;
295     file_path = (char *)calloc(path_len, sizeof(char));
296     if (!file_path) {
297         LOGE("Failed to alloc memory");
298         ret = -1;
299         goto cleanup;
300     }
301
302     if(path[0] == '/')
303         snprintf(file_path, path_len, "%s%s",app_path, path);
304     else
305         snprintf(file_path, path_len, "%s%s%s",app_path, "/", path);
306
307     if (access(file_path, F_OK) != 0) {
308         LOGE("%s does not exist", file_path);
309         ret = -1;
310     } else
311         ret = 0;
312
313 cleanup:
314     if (package_info)
315         package_info_destroy(package_info);
316
317     if (app_path) {
318         free(app_path);
319         app_path = NULL;
320     }
321
322     if (file_path) {
323         free(file_path);
324         file_path = NULL;
325     }
326
327     return ret;
328 }
329
330 static int _mkdirs(const char *path, mode_t mode)
331 {
332     int len = 0;
333     char prev_path[2048];
334     const char *tmp = path;
335
336     if (!path || strlen(path) > 2048)
337         return -1;
338
339     memset(prev_path, '\0', 2048);
340     while ((tmp = strchr(tmp, '/')) != NULL) {
341         len = tmp - path;
342         tmp++;
343
344         if (len == 0)
345             continue;
346
347         strncpy(prev_path, path, len);
348         prev_path[len] = 0x00;
349
350         if (mkdir(prev_path, mode) == -1 && errno != EEXIST) {
351             strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
352             LOGE("directory create error : %s", error_buffer);
353             return -1;
354         }
355     }
356
357     if (mkdir(prev_path, mode) == -1 && errno != EEXIST) {
358         strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
359         LOGE("directory create error : %s", error_buffer);
360         return -1;
361     }
362
363     return 0;
364 }
365
366 static int _file_copy(const char *src, const char *dest)
367 {
368     int ret = 0;
369     int fd = -1, n_fd = -1;
370     char buf[4096];
371     int tmp_err = 0;
372     int size;
373
374     memset(buf, '\0', 4096);
375     fd = open(src, O_RDONLY);
376     n_fd = open(dest, O_WRONLY | O_CREAT | O_TRUNC, 0755);
377
378     if (fd == -1 || n_fd == -1) {
379         tmp_err = errno;
380         ret = -1;
381         goto cleanup;
382     }
383
384     while((size = read(fd, buf, 4096))) {
385         if (size == -1) {
386             if(errno == EINTR)
387                 continue;
388
389             tmp_err = errno;
390             ret = -1;
391             goto cleanup;
392         }
393
394         while(write(n_fd, buf, size) == -1) {
395             if(errno == EINTR) {
396                 continue;
397             } else {
398                 tmp_err = errno;
399                 goto cleanup;
400             }
401         }
402     }
403
404 cleanup:
405     if (fd != -1)
406         close(fd);
407
408     if (n_fd != -1)
409         close(n_fd);
410
411     errno = tmp_err;
412     return ret;
413 }
414
415 static char* _convert_sticker_uri(const char *uri, const char *appid)
416 {
417     int ret;
418     int len = strlen(STICKER_DIRECTORY) + strlen(appid) + strlen(uri) + 3;
419     char * new_path = (char *)calloc(len, sizeof(char));
420     if (new_path == NULL) {
421         LOGE("Failed to alloc memory");
422         return NULL;
423     }
424
425     if (uri[0] == '/')
426         snprintf(new_path, len, "%s/%s%s",STICKER_DIRECTORY, appid, uri);
427     else
428         snprintf(new_path, len, "%s/%s/%s",STICKER_DIRECTORY, appid, uri);
429
430     if (access(new_path, F_OK) == 0) {
431         LOGE("sticker file already exists");
432         ret = -1;
433         goto cleanup;
434     }
435
436     ret = _mkdirs(new_path, 0755);
437     if (ret != 0) {
438         strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
439         LOGE("directory create error : %s", error_buffer);
440         goto cleanup;
441     }
442
443     ret = _file_copy(uri, new_path);
444     if (ret != 0) {
445         strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
446         LOGE("failed to copy sticker file : %s", error_buffer);
447     }
448
449 cleanup:
450     if (ret == 0) {
451         return new_path;
452     } else {
453         free(new_path);
454         new_path = NULL;
455         return NULL;
456     }
457 }
458
459 int stickerd_insert_sticker_info(GVariant *parameters, GVariant **reply_body)
460 {
461     int ret;
462     int record_id = 0;
463     STICKER_DAT_TYPE key;
464     sticker_info_db *sticker_info = NULL;
465     GVariant *value = NULL;
466     GVariantIter *info_iter = NULL;
467     GVariantIter *keyword_iter = NULL;
468     char *keyword;
469
470     g_variant_get(parameters, "(a{iv}a(s))", &info_iter, &keyword_iter);
471     if (!info_iter || !keyword_iter) {
472         LOGD("failed to get iter");
473         ret = STICKERD_SERVER_ERROR_OUT_OF_MEMORY;
474         goto cleanup;
475     }
476
477     sticker_info = (sticker_info_db *)calloc(1, sizeof(sticker_info_db));
478
479     if (!sticker_info) {
480         ret = STICKERD_SERVER_ERROR_OUT_OF_MEMORY;
481         goto cleanup;
482     }
483
484     while (g_variant_iter_loop (info_iter, "{iv}", &key, &value)) {
485         switch(key) {
486             case STICKER_DATA_TYPE_APP_ID:
487             sticker_info->app_id = (char *) g_variant_get_string(value, NULL);
488             break;
489             case STICKER_DATA_TYPE_URI_TYPE:
490             sticker_info->type = g_variant_get_int32(value);
491             break;
492             case STICKER_DATA_TYPE_URI:
493             sticker_info->uri = (char *) g_variant_get_string(value, NULL);
494             break;
495             case STICKER_DATA_TYPE_THUMBNAIL:
496             sticker_info->thumbnail = (char *) g_variant_get_string(value, NULL);
497             break;
498             case STICKER_DATA_TYPE_DESCRIPTION:
499             sticker_info->description = (char *) g_variant_get_string(value, NULL);
500             break;
501             case STICKER_DATA_TYPE_GROUP:
502             sticker_info->group = (char *) g_variant_get_string(value, NULL);
503             break;
504             default:
505             break;
506         }
507     }
508
509     while (g_variant_iter_loop (keyword_iter, "(s)", &keyword)) {
510         sticker_info->keyword = g_list_append(sticker_info->keyword, strdup((const char *)keyword));
511     }
512
513     if (sticker_info->type == 1) {
514         if (_check_file_exist(sticker_info->app_id, sticker_info->uri) == 0) {
515             sticker_info->uri = _convert_sticker_uri(sticker_info->uri, sticker_info->app_id);
516             if (!sticker_info->uri) {
517                 LOGE("failed to copy sticker file");
518                 ret = STICKERD_SERVER_ERROR_OPERATION_FAILED;
519                 goto cleanup;
520             }
521         } else {
522             LOGE("sticker file does not exist");
523             ret = STICKERD_SERVER_ERROR_OPERATION_FAILED;
524             goto cleanup;
525         }
526     }
527
528     ret = stickerd_db_insert_sticker_info(&record_id, sticker_info);
529     if (ret != STICKERD_SERVER_ERROR_NONE) {
530         LOGE("Failed to insert sticker info");
531         ret = STICKERD_SERVER_ERROR_OPERATION_FAILED;
532         goto cleanup;
533     }
534
535     *reply_body = g_variant_new("(i)", record_id);
536     if (*reply_body == NULL) {
537         LOGE("Failed to create reply_body");
538         ret = STICKERD_SERVER_ERROR_OPERATION_FAILED;
539     }
540
541 cleanup:
542     if (value)
543         g_variant_unref(value);
544
545     if (info_iter)
546         g_variant_iter_free(info_iter);
547
548     if (keyword_iter)
549         g_variant_iter_free(keyword_iter);
550
551     if (sticker_info) {
552         free(sticker_info);
553         sticker_info = NULL;
554     }
555
556     return ret;
557 }
558
559 static char* _get_string_from_object(JsonObject *object, const char *key)
560 {
561     if (json_object_has_member(object, key) == false)
562         return NULL;
563
564     const char *str = json_object_get_string_member(object, key);
565     if (str != NULL)
566         return strdup(str);
567     else
568         return NULL;
569 }
570
571 static int _get_int_from_object(JsonObject *object, const char *key)
572 {
573     if (json_object_has_member(object, key) == false)
574         return -1;
575
576     int type = json_object_get_int_member(object, key);
577
578     return type;
579 }
580
581 int stickerd_insert_sticker_info_by_json(GVariant *parameters, GVariant **reply_body, const char *sender)
582 {
583     int ret = STICKERD_SERVER_ERROR_OPERATION_FAILED;
584     int record_id;
585     sticker_info_db *sticker_info = NULL;
586     char *app_id = NULL;
587     char *json_path = NULL;
588     JsonParser* parser = NULL;
589     GError* err_msg = NULL;
590     GVariant *body = NULL;
591     char *cmd = "send_insert_result";
592
593     *reply_body = g_variant_new("()");
594         if (*reply_body == NULL) {
595         LOGE("Failed to create reply_body");
596         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
597     }
598
599     g_variant_get(parameters, "(&s&s)", &app_id, &json_path);
600
601     if (!app_id || !json_path) {
602         LOGE("failed to get parameter");
603         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
604     }
605
606     SECURE_LOGD("app_id: %s, json path: %s", app_id, json_path);
607
608     parser = json_parser_new();
609     json_parser_load_from_file(parser, json_path, &err_msg);
610     if (err_msg) {
611         LOGE("failed to load json file. error message: %s", err_msg->message);
612         ret = STICKERD_SERVER_ERROR_OPERATION_FAILED;
613         goto cleanup;
614     }
615
616     JsonNode *root = json_parser_get_root(parser);
617     if (root == NULL) {
618         LOGE("failed to get root");
619         ret = STICKERD_SERVER_ERROR_OPERATION_FAILED;
620         goto cleanup;
621     }
622
623     JsonObject *root_obj = json_node_get_object(root);
624     if (root_obj == NULL) {
625         LOGE("failed to get object");
626         ret = STICKERD_SERVER_ERROR_OPERATION_FAILED;
627         goto cleanup;
628     }
629
630     JsonArray *sticker_arr = json_object_get_array_member(root_obj, "sticker");
631     if (sticker_arr == NULL) {
632         LOGE("failed to get array member");
633         ret = STICKERD_SERVER_ERROR_OPERATION_FAILED;
634         goto cleanup;
635     }
636
637     int arr_len = json_array_get_length(sticker_arr);
638     for (int i = 0; i < arr_len; i++) {
639         JsonObject *info_object = json_array_get_object_element(sticker_arr, i);
640         if (info_object != NULL) {
641             sticker_info = (sticker_info_db *)calloc(1, sizeof(sticker_info_db));
642             if (!sticker_info) {
643                 LOGE("Failed to alloc memory");
644                 continue;
645             }
646
647             sticker_info->app_id = app_id;
648             sticker_info->type = _get_int_from_object(info_object, "type");
649             if (sticker_info->type < 1)
650                 goto free_memory;
651
652             sticker_info->uri = _get_string_from_object(info_object, "uri");
653             if (!sticker_info->uri)
654                 goto free_memory;
655
656             if (sticker_info->type == 1) {
657                 if (_check_file_exist(sticker_info->app_id, sticker_info->uri) == 0) {
658                     sticker_info->uri = _convert_sticker_uri(sticker_info->uri, sticker_info->app_id);
659                     if (!sticker_info->uri)
660                         goto free_memory;
661                 }
662             }
663
664             sticker_info->group = _get_string_from_object(info_object, "group");
665             if (!sticker_info->group)
666                 goto free_memory;
667
668             sticker_info->thumbnail = _get_string_from_object(info_object, "thumbnail");
669             if (!sticker_info->thumbnail)
670                 goto free_memory;
671
672             sticker_info->description = _get_string_from_object(info_object, "description");
673
674             JsonArray *keyword_arr = json_object_get_array_member(info_object, "keyword");
675             int keyword_arr_len = json_array_get_length(keyword_arr);
676             if (keyword_arr_len < 1)
677                 goto free_memory;
678
679             for (int j = 0; j < keyword_arr_len; j++) {
680                 sticker_info->keyword = g_list_append(sticker_info->keyword, strdup((const char *)json_array_get_string_element(keyword_arr, j)));
681             }
682
683             ret = stickerd_db_insert_sticker_info(&record_id, sticker_info);
684             if (ret != STICKERD_SERVER_ERROR_NONE) {
685                 LOGE("Failed to insert sticker info");
686                 ret = STICKERD_SERVER_ERROR_OPERATION_FAILED;
687             }
688
689 free_memory:
690             free(sticker_info);
691             sticker_info = NULL;
692         }
693     }
694
695 cleanup:
696     if (err_msg)
697         g_error_free(err_msg);
698     if (parser)
699         g_object_unref(parser);
700
701     body = g_variant_new("(i)", ret);
702
703     ret = stickerd_send_dbus_message(body, sender, cmd, STICKER_CLIENT_LIB_PROVIDER);
704     if (ret != STICKERD_SERVER_ERROR_NONE)
705         LOGE("Failed to send insert result to client");
706
707     if(body)
708         g_variant_unref(body);
709
710     return ret;
711 }
712
713 int stickerd_del_sticker_info(GVariant *parameters, GVariant **reply_body)
714 {
715     int ret;
716     int record_id;
717
718     *reply_body = g_variant_new("()");
719     if (*reply_body == NULL) {
720         LOGE("Failed to create reply_body");
721         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
722     }
723
724     g_variant_get(parameters, "(i)", &record_id);
725
726     ret = stickerd_db_delete_sticker_info(record_id);
727     if (ret != STICKERD_SERVER_ERROR_NONE) {
728         LOGE("Failed to delete sticker info");
729         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
730     }
731
732     return ret;
733 }
734
735 int stickerd_update_sticker_type(GVariant *parameters, GVariant **reply_body)
736 {
737     int ret;
738     int record_id;
739     int type;
740
741     *reply_body = g_variant_new("()");
742     if (*reply_body == NULL) {
743         LOGE("Failed to create reply_body");
744         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
745     }
746
747     g_variant_get(parameters, "(ii)", &record_id, &type);
748
749     ret = stickerd_db_update_sticker_info(record_id, STICKER_DB_STICKER_TYPE, &type);
750     if (ret != STICKERD_SERVER_ERROR_NONE) {
751         LOGE("Failed to update sticker type");
752         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
753     }
754
755     return ret;
756 }
757
758 int stickerd_update_sticker_uri(GVariant *parameters, GVariant **reply_body)
759 {
760     int ret;
761     int record_id;
762     int type;
763     char *app_id;
764     char *uri;
765
766     *reply_body = g_variant_new("()");
767     if (*reply_body == NULL) {
768         LOGE("Failed to create reply_body");
769         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
770     }
771
772     g_variant_get(parameters, "(i&si&s)", &record_id, &app_id, &type, &uri);
773
774     if (type == 1) {
775         if (_check_file_exist(app_id, uri) == 0) {
776             uri = _convert_sticker_uri(uri, app_id);
777             if (!uri) {
778                 LOGE("failed to copy sticker file");
779                 return STICKERD_SERVER_ERROR_OPERATION_FAILED;
780             }
781         }
782     }
783
784     ret = stickerd_db_update_sticker_info(record_id, STICKER_DB_STICKER_URI, (void *)uri);
785     if (ret != STICKERD_SERVER_ERROR_NONE) {
786         LOGE("Failed to update sticker uri");
787         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
788     }
789
790     return ret;
791 }
792
793 int stickerd_update_sticker_thumbnail(GVariant *parameters, GVariant **reply_body)
794 {
795     int ret;
796     int record_id;
797     char *thumbnail;
798
799     *reply_body = g_variant_new("()");
800     if (*reply_body == NULL) {
801         LOGE("Failed to create reply_body");
802         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
803     }
804
805     g_variant_get(parameters, "(i&s)", &record_id, &thumbnail);
806
807     ret = stickerd_db_update_sticker_info(record_id, STICKER_DB_STICKER_THUMBNAIL, (void *)thumbnail);
808     if (ret != STICKERD_SERVER_ERROR_NONE) {
809         LOGE("Failed to update sticker thumbnail");
810         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
811     }
812
813     return ret;
814 }
815
816 int stickerd_update_sticker_description(GVariant *parameters, GVariant **reply_body)
817 {
818     int ret;
819     int record_id;
820     char *description;
821
822     *reply_body = g_variant_new("()");
823     if (*reply_body == NULL) {
824         LOGE("Failed to create reply_body");
825         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
826     }
827
828     g_variant_get(parameters, "(i&s)", &record_id, &description);
829
830     ret = stickerd_db_update_sticker_info(record_id, STICKER_DB_STICKER_DESCRIPTION, (void *)description);
831     if (ret != STICKERD_SERVER_ERROR_NONE) {
832         LOGE("Failed to update sticker description");
833         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
834     }
835
836     return ret;
837 }
838
839 int stickerd_update_sticker_group(GVariant *parameters, GVariant **reply_body)
840 {
841     int ret;
842     int record_id;
843     char *group;
844
845     *reply_body = g_variant_new("()");
846     if (*reply_body == NULL) {
847         LOGE("Failed to create reply_body");
848         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
849     }
850
851     g_variant_get(parameters, "(i&s)", &record_id, &group);
852
853     ret = stickerd_db_update_sticker_info(record_id, STICKER_DB_STICKER_GROUP, (void *)group);
854     if (ret != STICKERD_SERVER_ERROR_NONE) {
855         LOGE("Failed to update sticker group");
856         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
857     }
858
859     return ret;
860 }
861
862 int stickerd_update_sticker_keyword(GVariant *parameters, GVariant **reply_body)
863 {
864     int ret;
865     int record_id;
866     GVariantIter *keyword_iter = NULL;
867     char *keyword = NULL;
868     GList *keyword_list = NULL;
869
870     *reply_body = g_variant_new("()");
871     if (*reply_body == NULL) {
872         LOGE("Failed to create reply_body");
873         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
874     }
875
876     g_variant_get(parameters, "(ia(s))", &record_id, &keyword_iter);
877
878     if (!keyword_iter) {
879         LOGD("failed to get iter");
880         return STICKERD_SERVER_ERROR_OUT_OF_MEMORY;
881     }
882
883     while (g_variant_iter_loop (keyword_iter, "(s)", &keyword)) {
884         keyword_list = g_list_append(keyword_list, strdup((const char *)keyword));
885     }
886
887     g_variant_iter_free(keyword_iter);
888
889     ret = stickerd_db_update_sticker_info(record_id, STICKER_DB_STICKER_KEYWORD, (void *)keyword_list);
890     if (ret != STICKERD_SERVER_ERROR_NONE) {
891         LOGE("Failed to update sticker keyword");
892         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
893     }
894
895     return ret;
896 }
897
898 static void _set_keyword_builder(char *keyword, GVariantBuilder *keyword_builder)
899 {
900     if (!keyword) {
901         LOGE("keyword doesn't exist");
902         return;
903     }
904
905     g_variant_builder_add(keyword_builder, "(s)", strdup((const char *)keyword));
906 }
907
908 int stickerd_get_sticker_info(GVariant *parameters, GVariant **reply_body)
909 {
910     int ret;
911     int record_id;
912     GVariantBuilder *info_builder;
913     GVariantBuilder *keyword_builder;
914
915     g_variant_get(parameters, "(i)", &record_id);
916     sticker_info_db *sticker_info = (sticker_info_db *)calloc(1, sizeof(sticker_info_db));
917
918     if (!sticker_info)
919         return STICKERD_SERVER_ERROR_OUT_OF_MEMORY;
920
921     ret = stickerd_db_get_sticker_info_by_record_id(record_id, sticker_info);
922     if (ret != STICKERD_SERVER_ERROR_NONE) {
923         LOGE("Failed to get sticker info");
924         free(sticker_info);
925         sticker_info = NULL;
926         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
927     }
928
929     info_builder = g_variant_builder_new(G_VARIANT_TYPE("a{iv}"));
930     g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_APP_ID, g_variant_new_string((const gchar *)sticker_info->app_id));
931     g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_URI_TYPE, g_variant_new_int32(sticker_info->type));
932     g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_URI, g_variant_new_string((const gchar *)sticker_info->uri));
933     g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_THUMBNAIL, g_variant_new_string((const gchar *)sticker_info->thumbnail));
934     g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_DESCRIPTION, g_variant_new_string((const gchar *)sticker_info->description));
935     g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_GROUP, g_variant_new_string((const gchar *)sticker_info->group));
936     g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_DATE, g_variant_new_string((const gchar *)sticker_info->date));
937
938     keyword_builder = g_variant_builder_new(G_VARIANT_TYPE("a(s)"));
939     g_list_foreach(sticker_info->keyword, (GFunc) _set_keyword_builder, keyword_builder);
940
941     *reply_body = g_variant_new("(a{iv}a(s))", info_builder, keyword_builder);
942     g_variant_builder_unref(info_builder);
943     g_variant_builder_unref(keyword_builder);
944
945     if (*reply_body == NULL) {
946         LOGE("Failed to create reply_body");
947         free(sticker_info);
948         sticker_info = NULL;
949         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
950     }
951
952     free(sticker_info);
953     sticker_info = NULL;
954     return ret;
955 }
956
957 int stickerd_get_group_list(GVariant *parameters, GVariant **reply_body)
958 {
959     int ret;
960     GVariantBuilder *builder = NULL;
961
962     builder = g_variant_builder_new(G_VARIANT_TYPE("a(s)"));
963     ret = stickerd_db_get_group_list(builder);
964
965     if (ret != STICKERD_SERVER_ERROR_NONE) {
966         LOGE("Failed to get sticker group list");
967         g_variant_builder_unref(builder);
968         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
969     }
970
971     *reply_body = g_variant_new("(a(s))", builder);
972     g_variant_builder_unref(builder);
973
974     if (*reply_body == NULL) {
975         LOGE("Failed to create reply_body");
976         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
977     }
978
979     return ret;
980 }
981
982 int stickerd_get_keyword_list(GVariant *parameters, GVariant **reply_body)
983 {
984     int ret;
985     GVariantBuilder *builder = NULL;
986
987     builder = g_variant_builder_new(G_VARIANT_TYPE("a(s)"));
988     ret = stickerd_db_get_keyword_list(builder);
989     if (ret != STICKERD_SERVER_ERROR_NONE) {
990         LOGE("Failed to get sticker keyword list");
991         g_variant_builder_unref(builder);
992         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
993     }
994
995     *reply_body = g_variant_new("(a(s))", builder);
996     g_variant_builder_unref(builder);
997
998     if (*reply_body == NULL) {
999         LOGE("Failed to create reply_body");
1000         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
1001     }
1002
1003     return ret;
1004 }
1005
1006 int stickerd_get_sticker_count(GVariant *parameters, GVariant **reply_body)
1007 {
1008     int ret;
1009     int count;
1010     char *app_id = NULL;
1011
1012     g_variant_get(parameters, "(&s)", &app_id);
1013
1014     ret = stickerd_db_get_sticker_count(&count, app_id);
1015     if (ret != STICKERD_SERVER_ERROR_NONE) {
1016         LOGE("Failed to get sticker count");
1017         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
1018     }
1019
1020     *reply_body = g_variant_new("(i)", count);
1021     if (*reply_body == NULL) {
1022         LOGE("Failed to create reply_body");
1023         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
1024     }
1025
1026     return ret;
1027 }
1028
1029 #if 0
1030 // Send the sticker information by asynchronous communication.
1031 static int send_sticker_info_async(int record_id, sticker_info_db_type type, const char *sender)
1032 {
1033     int ret;
1034     char *cmd = NULL;
1035
1036     sticker_info_db *sticker_info = (sticker_info_db *)calloc(1, sizeof(sticker_info_db));
1037
1038     if (!sticker_info)
1039         return STICKERD_SERVER_ERROR_OUT_OF_MEMORY;
1040
1041     ret = stickerd_db_get_sticker_info_by_record_id(record_id, sticker_info);
1042     if (ret != STICKERD_SERVER_ERROR_NONE) {
1043         LOGE("Failed to get sticker info");
1044         free(sticker_info);
1045         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
1046     }
1047
1048     switch (type) {
1049         case STICKER_DB_STICKER_ALL:
1050         cmd = "send_all_sticker_info";
1051         break;
1052         case STICKER_DB_STICKER_APPID:
1053         cmd = "send_sticker_info_by_appid";
1054         break;
1055         case STICKER_DB_STICKER_TYPE:
1056         cmd = "send_sticker_info_by_type";
1057         break;
1058         case STICKER_DB_STICKER_GROUP:
1059         cmd = "send_sticker_info_by_goup";
1060         break;
1061         case STICKER_DB_STICKER_KEYWORD:
1062         cmd = "send_sticker_info_by_keyword";
1063         break;
1064         default:
1065         cmd = "";
1066         break;
1067     }
1068
1069     GVariantBuilder *info_builder;
1070     GVariantBuilder *keyword_builder;
1071
1072     info_builder = g_variant_builder_new(G_VARIANT_TYPE("a{iv}"));
1073     g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_INFO_ID, g_variant_new_int32(record_id));
1074     g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_APP_ID, g_variant_new_string((const gchar *)sticker_info->app_id));
1075     g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_URI_TYPE, g_variant_new_int32(sticker_info->type));
1076     g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_URI, g_variant_new_string((const gchar *)sticker_info->uri));
1077     g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_THUMBNAIL, g_variant_new_string((const gchar *)sticker_info->thumbnail));
1078     g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_DESCRIPTION, g_variant_new_string((const gchar *)sticker_info->description));
1079     g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_GROUP, g_variant_new_string((const gchar *)sticker_info->group));
1080     g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_DATE, g_variant_new_string((const gchar *)sticker_info->date));
1081
1082     keyword_builder = g_variant_builder_new(G_VARIANT_TYPE("a(s)"));
1083     g_list_foreach(sticker_info->keyword, (GFunc) _set_keyword_builder, keyword_builder);
1084
1085     GVariant *body = g_variant_new("(a{iv}a(s))", info_builder, keyword_builder);
1086     g_variant_builder_unref(info_builder);
1087     g_variant_builder_unref(keyword_builder);
1088
1089     ret = stickerd_send_dbus_message(body, sender, cmd);
1090     if (ret != STICKERD_SERVER_ERROR_NONE) {
1091         LOGE("Failed to send sticker info to client");
1092         free(sticker_info);
1093         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
1094     }
1095
1096     free(sticker_info);
1097     return ret;
1098 }
1099 #endif
1100
1101 static void _set_id_builder(char *id, GVariantBuilder *id_builder)
1102 {
1103     if (!id) {
1104         LOGE("id doesn't exist");
1105         return;
1106     }
1107
1108     g_variant_builder_add(id_builder, "(i)", atoi(id));
1109 }
1110
1111 int stickerd_get_all_sticker_info(GVariant *parameters, GVariant **reply_body)
1112 {
1113     int ret;
1114     int offset, count;
1115     GList *id_list = NULL;
1116     GVariantBuilder *id_builder = NULL;
1117
1118     g_variant_get(parameters, "(ii)", &offset, &count);
1119
1120     ret = stickerd_db_get_record_id(STICKER_DB_STICKER_ALL, &id_list, NULL, offset, count);
1121     if (ret != STICKERD_SERVER_ERROR_NONE) {
1122         LOGE("Failed to get all sticker id");
1123         if(id_list)
1124             g_list_free_full(id_list, free);
1125         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
1126     }
1127
1128     id_builder = g_variant_builder_new(G_VARIANT_TYPE("a(i)"));
1129     g_list_foreach(id_list, (GFunc) _set_id_builder, id_builder);
1130
1131     *reply_body = g_variant_new("(a(i))", id_builder);
1132     if (*reply_body == NULL) {
1133         LOGE("Failed to create reply_body");
1134         ret = STICKERD_SERVER_ERROR_OPERATION_FAILED;
1135     }
1136
1137     if (id_list)
1138         g_list_free_full(id_list, free);
1139
1140     if (id_builder)
1141         g_variant_builder_unref(id_builder);
1142
1143     return ret;
1144 }
1145
1146 int stickerd_get_sticker_info_by_app_id(GVariant *parameters, GVariant **reply_body)
1147 {
1148     int ret;
1149     GList *id_list = NULL;
1150     char *app_id = NULL;
1151     int offset, count;
1152     GVariantBuilder *id_builder = NULL;
1153
1154     g_variant_get(parameters, "(&sii)", &app_id, &offset, &count);
1155
1156     ret = stickerd_db_get_record_id(STICKER_DB_STICKER_APPID, &id_list, (void *)app_id, offset, count);
1157     if (ret != STICKERD_SERVER_ERROR_NONE) {
1158         LOGE("Failed to get all sticker id");
1159         if(id_list)
1160             g_list_free_full(id_list, free);
1161         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
1162     }
1163
1164     id_builder = g_variant_builder_new(G_VARIANT_TYPE("a(i)"));
1165     g_list_foreach(id_list, (GFunc) _set_id_builder, id_builder);
1166
1167     *reply_body = g_variant_new("(a(i))", id_builder);
1168     if (*reply_body == NULL) {
1169         LOGE("Failed to create reply_body");
1170         ret = STICKERD_SERVER_ERROR_OPERATION_FAILED;
1171     }
1172
1173     if (id_list)
1174         g_list_free_full(id_list, free);
1175
1176     if (id_builder)
1177         g_variant_builder_unref(id_builder);
1178
1179     return ret;
1180 }
1181
1182 int stickerd_get_sticker_info_by_type(GVariant *parameters, GVariant **reply_body)
1183 {
1184     int ret;
1185     GList *id_list = NULL;
1186     int type, offset, count;
1187     GVariantBuilder *id_builder = NULL;
1188
1189     g_variant_get(parameters, "(iii)", &type, &offset, &count);
1190
1191     ret = stickerd_db_get_record_id(STICKER_DB_STICKER_TYPE, &id_list, &type, offset, count);
1192     if (ret != STICKERD_SERVER_ERROR_NONE) {
1193         LOGE("Failed to get all sticker id");
1194         if(id_list)
1195             g_list_free_full(id_list, free);
1196         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
1197     }
1198
1199     id_builder = g_variant_builder_new(G_VARIANT_TYPE("a(i)"));
1200     g_list_foreach(id_list, (GFunc) _set_id_builder, id_builder);
1201
1202     *reply_body = g_variant_new("(a(i))", id_builder);
1203     if (*reply_body == NULL) {
1204         LOGE("Failed to create reply_body");
1205         ret = STICKERD_SERVER_ERROR_OPERATION_FAILED;
1206     }
1207
1208     if (id_list)
1209         g_list_free_full(id_list, free);
1210
1211     if (id_builder)
1212         g_variant_builder_unref(id_builder);
1213
1214     return ret;
1215 }
1216
1217 int stickerd_get_sticker_info_by_group(GVariant *parameters, GVariant **reply_body)
1218 {
1219     int ret;
1220     GList *id_list = NULL;
1221     char *group = NULL;
1222     int offset, count;
1223     GVariantBuilder *id_builder = NULL;
1224
1225     g_variant_get(parameters, "(&sii)", &group, &offset, &count);
1226
1227     ret = stickerd_db_get_record_id(STICKER_DB_STICKER_GROUP, &id_list, (void *)group, offset, count);
1228     if (ret != STICKERD_SERVER_ERROR_NONE) {
1229         LOGE("Failed to get all sticker id");
1230         if(id_list)
1231             g_list_free_full(id_list, free);
1232         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
1233     }
1234
1235     id_builder = g_variant_builder_new(G_VARIANT_TYPE("a(i)"));
1236     g_list_foreach(id_list, (GFunc) _set_id_builder, id_builder);
1237
1238     *reply_body = g_variant_new("(a(i))", id_builder);
1239     if (*reply_body == NULL) {
1240         LOGE("Failed to create reply_body");
1241         ret = STICKERD_SERVER_ERROR_OPERATION_FAILED;
1242     }
1243
1244     if (id_list)
1245         g_list_free_full(id_list, free);
1246
1247     if (id_builder)
1248         g_variant_builder_unref(id_builder);
1249
1250     return ret;
1251 }
1252
1253 int stickerd_get_sticker_info_by_keyword(GVariant *parameters, GVariant **reply_body)
1254 {
1255     int ret;
1256     GList *id_list = NULL;
1257     char *keyword = NULL;
1258     int offset, count;
1259     GVariantBuilder *id_builder = NULL;
1260
1261     g_variant_get(parameters, "(&sii)", &keyword, &offset, &count);
1262
1263     ret = stickerd_db_get_record_id(STICKER_DB_STICKER_KEYWORD, &id_list, (void *)keyword, offset, count);
1264     if (ret != STICKERD_SERVER_ERROR_NONE) {
1265         LOGE("Failed to get all sticker id");
1266         if(id_list)
1267             g_list_free_full(id_list, free);
1268         return STICKERD_SERVER_ERROR_OPERATION_FAILED;
1269     }
1270
1271     id_builder = g_variant_builder_new(G_VARIANT_TYPE("a(i)"));
1272     g_list_foreach(id_list, (GFunc) _set_id_builder, id_builder);
1273
1274     *reply_body = g_variant_new("(a(i))", id_builder);
1275     if (*reply_body == NULL) {
1276         LOGE("Failed to create reply_body");
1277         ret = STICKERD_SERVER_ERROR_OPERATION_FAILED;
1278     }
1279
1280     if (id_list)
1281         g_list_free_full(id_list, free);
1282
1283     if (id_builder)
1284         g_variant_builder_unref(id_builder);
1285
1286     return ret;
1287 }