Remove memory leak from notification_wait_response
[platform/core/api/notification.git] / src / notification.c
1 /*
2  *  libnotification
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Seungtaek Chung <seungtaek.chung@samsung.com>, Mi-Ju Lee <miju52.lee@samsung.com>, Xi Zhichan <zhichan.xi@samsung.com>, Youngsub Ko <ys4610.ko@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #define _GNU_SOURCE
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <sys/socket.h>
29 #include <sys/syscall.h>
30 #include <sys/time.h>
31 #include <sys/un.h>
32 #include <libintl.h>
33 #include <dbus/dbus.h>
34 #include <dbus/dbus-glib-lowlevel.h>
35
36 #include <aul.h>
37 #include <ail.h>
38 #include <appsvc.h>
39 #include <vconf-keys.h>
40 #include <vconf.h>
41
42 #include <notification.h>
43 #include <notification_list.h>
44 #include <notification_debug.h>
45 #include <notification_internal.h>
46 #include <notification_noti.h>
47 #include <notification_ongoing.h>
48 #include <notification_group.h>
49 #include <notification_ipc.h>
50
51 typedef struct _notification_cb_list notification_cb_list_s;
52
53 typedef enum __notification_cb_type {
54         NOTIFICATION_CB_NORMAL = 1,
55         NOTIFICATION_CB_DETAILED,
56 } _notification_cb_type_e;
57
58 struct _notification_cb_list {
59         notification_cb_list_s *prev;
60         notification_cb_list_s *next;
61
62         _notification_cb_type_e cb_type;
63         void (*changed_cb) (void *data, notification_type_e type);
64         void (*detailed_changed_cb) (void *data, notification_type_e type, notification_op *op_list, int num_op);
65         void *data;
66 };
67
68 static notification_cb_list_s *g_notification_cb_list = NULL;
69
70 #define NOTI_TEXT_RESULT_LEN 2048
71 #define NOTI_PKGNAME_LEN        512
72
73 static char *_notification_get_pkgname_by_pid(void)
74 {
75         char pkgname[NOTI_PKGNAME_LEN + 1] = { 0, };
76         int pid = 0, ret = AUL_R_OK;
77         int fd;
78         char  *dup_pkgname;
79
80         pid = getpid();
81
82         ret = aul_app_get_pkgname_bypid(pid, pkgname, sizeof(pkgname));
83         if (ret != AUL_R_OK) {
84                 char buf[NOTI_PKGNAME_LEN + 1] = { 0, };
85
86                 snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
87
88                 fd = open(buf, O_RDONLY);
89                 if (fd < 0) {
90                         return NULL;
91                 }
92
93                 ret = read(fd, pkgname, sizeof(pkgname) - 1);
94                 close(fd);
95
96                 if (ret <= 0) {
97                         return NULL;
98                 }
99
100                 pkgname[ret] = '\0';
101                 /*!
102                  * \NOTE
103                  * "ret" is not able to be larger than "sizeof(pkgname) - 1",
104                  * if the system is not going wrong.
105                  */
106         } else {
107                 if (strlen(pkgname) <= 0) {
108                         return NULL;
109                 }
110         }
111
112         dup_pkgname = strdup(pkgname);
113         if (!dup_pkgname)
114                 NOTIFICATION_ERR("Heap: %s\n", strerror(errno));
115
116         return dup_pkgname;
117 }
118
119 static void _notification_get_text_domain(notification_h noti)
120 {
121         if (noti->domain != NULL) {
122
123         }
124
125         if (noti->dir != NULL) {
126
127         }
128 }
129
130 EXPORT_API notification_error_e notification_set_image(notification_h noti,
131                                                        notification_image_type_e type,
132                                                        const char *image_path)
133 {
134         bundle *b = NULL;
135         char buf_key[32] = { 0, };
136         const char *ret_val = NULL;
137
138         /* Check noti and image_path are valid data */
139         if (noti == NULL || image_path == NULL) {
140                 return NOTIFICATION_ERROR_INVALID_DATA;
141         }
142
143         /* Check image type is valid type */
144         if (type <= NOTIFICATION_IMAGE_TYPE_NONE
145             || type >= NOTIFICATION_IMAGE_TYPE_MAX) {
146                 return NOTIFICATION_ERROR_INVALID_DATA;
147         }
148
149         /* Check image path bundle is exist */
150         if (noti->b_image_path) {
151                 /* If image path bundle is exist, store local bundle value */
152                 b = noti->b_image_path;
153
154                 /* Set image type to key as char string type */
155                 snprintf(buf_key, sizeof(buf_key), "%d", type);
156
157                 /* Get value using key */
158                 ret_val = bundle_get_val(b, buf_key);
159                 if (ret_val != NULL) {
160                         /* If key is exist, remove this value to store new image path */
161                         bundle_del(b, buf_key);
162                 }
163
164                 /* Add new image path with type key */
165                 bundle_add(b, buf_key, image_path);
166         } else {
167                 /* If image path bundle is not exist, create new one */
168                 b = bundle_create();
169
170                 /* Set image type to key as char string type */
171                 snprintf(buf_key, sizeof(buf_key), "%d", type);
172
173                 /* Add new image path with type key */
174                 bundle_add(b, buf_key, image_path);
175
176                 /* Save to image path bundle */
177                 noti->b_image_path = b;
178         }
179
180         return NOTIFICATION_ERROR_NONE;
181 }
182
183 EXPORT_API notification_error_e notification_get_image(notification_h noti,
184                                                        notification_image_type_e type,
185                                                        char **image_path)
186 {
187         bundle *b = NULL;
188         char buf_key[32] = { 0, };
189         const char *ret_val = NULL;
190
191         /* Check noti and image_path is valid data */
192         if (noti == NULL || image_path == NULL) {
193                 return NOTIFICATION_ERROR_INVALID_DATA;
194         }
195
196         /* Check image type is valid data */
197         if (type <= NOTIFICATION_IMAGE_TYPE_NONE
198             || type >= NOTIFICATION_IMAGE_TYPE_MAX) {
199                 return NOTIFICATION_ERROR_INVALID_DATA;
200         }
201
202         /* Check image path bundle exist */
203         if (noti->b_image_path) {
204                 /* If image path bundle exist, store local bundle data */
205                 b = noti->b_image_path;
206
207                 /* Set image type to key as char string type */
208                 snprintf(buf_key, sizeof(buf_key), "%d", type);
209
210                 /* Get value of key */
211                 ret_val = bundle_get_val(b, buf_key);
212
213                 *image_path = (char *)ret_val;
214         } else {
215                 /* If image path bundle does not exist, image path is NULL */
216                 *image_path = NULL;
217         }
218
219         /* If image path is NULL and type is ICON, icon path set from AIL */
220         /* order : user icon -> launch_pkgname icon -> caller_pkgname icon -> service app icon */
221         if (*image_path == NULL && type == NOTIFICATION_IMAGE_TYPE_ICON) {
222                 /* Check App icon path is already set */
223                 if (noti->app_icon_path != NULL) {
224                         /* image path will be app icon path */
225                         *image_path = noti->app_icon_path;
226                 } else {
227                         *image_path = NULL;
228                 }
229         }
230
231         return NOTIFICATION_ERROR_NONE;
232 }
233
234 EXPORT_API notification_error_e notification_set_time(notification_h noti,
235                                                       time_t input_time)
236 {
237         /* Check noti is valid data */
238         if (noti == NULL) {
239                 return NOTIFICATION_ERROR_INVALID_DATA;
240         }
241
242         if (input_time == 0) {
243                 /* If input time is 0, set current time */
244                 noti->time = time(NULL);
245         } else {
246                 /* save input time */
247                 noti->time = input_time;
248         }
249
250         return NOTIFICATION_ERROR_NONE;
251 }
252
253 EXPORT_API notification_error_e notification_get_time(notification_h noti,
254                                                       time_t * ret_time)
255 {
256         /* Check noti and time is valid data */
257         if (noti == NULL || ret_time == NULL) {
258                 return NOTIFICATION_ERROR_INVALID_DATA;
259         }
260
261         /* Set time infomation */
262         *ret_time = noti->time;
263
264         return NOTIFICATION_ERROR_NONE;
265 }
266
267 EXPORT_API notification_error_e notification_get_insert_time(notification_h noti,
268                                                              time_t * ret_time)
269 {
270         /* Check noti and ret_time is valid data */
271         if (noti == NULL || ret_time == NULL) {
272                 return NOTIFICATION_ERROR_INVALID_DATA;
273         }
274
275         /* Set insert time information */
276         *ret_time = noti->insert_time;
277
278         return NOTIFICATION_ERROR_NONE;
279 }
280
281 EXPORT_API notification_error_e notification_set_text(notification_h noti,
282                                                       notification_text_type_e type,
283                                                       const char *text,
284                                                       const char *key,
285                                                       int args_type, ...)
286 {
287         bundle *b = NULL;
288         char buf_key[32] = { 0, };
289         char buf_val[1024] = { 0, };
290         const char *ret_val = NULL;
291         va_list var_args;
292         notification_variable_type_e var_type;
293         int num_args = 0;
294         notification_error_e noti_err = NOTIFICATION_ERROR_NONE;
295         int var_value_int = 0;
296         double var_value_double = 0.0;
297         char *var_value_string = NULL;
298         notification_count_pos_type_e var_value_count =
299             NOTIFICATION_COUNT_POS_NONE;
300
301         /* Check noti is valid data */
302         if (noti == NULL) {
303                 return NOTIFICATION_ERROR_INVALID_DATA;
304         }
305
306         /* Check text type is valid type */
307         if (type <= NOTIFICATION_TEXT_TYPE_NONE
308             || type >= NOTIFICATION_TEXT_TYPE_MAX) {
309                 return NOTIFICATION_ERROR_INVALID_DATA;
310         }
311
312         /* Check text bundle exist */
313         if (text != NULL) {
314                 if (noti->b_text != NULL) {
315                         /* If text bundle exist, store local bundle data */
316                         b = noti->b_text;
317
318                         /* Make type to key as char string */
319                         snprintf(buf_key, sizeof(buf_key), "%d", type);
320
321                         /* Get value using type key */
322                         ret_val = bundle_get_val(b, buf_key);
323                         if (ret_val != NULL) {
324                                 /* If value exist, remove this to add new value */
325                                 bundle_del(b, buf_key);
326                         }
327
328                         snprintf(buf_val, sizeof(buf_val), "%s", text);
329
330                         /* Add new text value */
331                         bundle_add(b, buf_key, buf_val);
332                 } else {
333                         /* If text bundle does not exist, create new one */
334                         b = bundle_create();
335
336                         /* Make type to key as char string */
337                         snprintf(buf_key, sizeof(buf_key), "%d", type);
338
339                         snprintf(buf_val, sizeof(buf_val), "%s", text);
340
341                         /* Add new text value */
342                         bundle_add(b, buf_key, buf_val);
343
344                         /* Save text bundle */
345                         noti->b_text = b;
346                 }
347         } else {
348                 /* Reset if text is NULL */
349                 if (noti->b_text != NULL) {
350                         /* If text bundle exist, store local bundle data */
351                         b = noti->b_text;
352
353                         /* Make type to key as char string */
354                         snprintf(buf_key, sizeof(buf_key), "%d", type);
355
356                         /* Get value using type key */
357                         ret_val = bundle_get_val(b, buf_key);
358                         if (ret_val != NULL) {
359                                 /* If value exist, remove this */
360                                 bundle_del(b, buf_key);
361                         }
362                 }
363         }
364
365         /* Save key if key is valid data */
366         if (key != NULL) {
367                 /* Check key bundle exist */
368                 if (noti->b_key != NULL) {
369                         /* If key bundle exist,  store local bundle data */
370                         b = noti->b_key;
371
372                         /* Make type to key as char string */
373                         snprintf(buf_key, sizeof(buf_key), "%d", type);
374
375                         /* Get value using type key */
376                         ret_val = bundle_get_val(b, buf_key);
377                         if (ret_val != NULL) {
378                                 /* If value exist, remove this to add new value */
379                                 bundle_del(b, buf_key);
380                         }
381
382                         snprintf(buf_val, sizeof(buf_val), "%s", key);
383
384                         /* Add new key value */
385                         bundle_add(b, buf_key, buf_val);
386                 } else {
387                         /* If key bundle does not exist, create new one */
388                         b = bundle_create();
389
390                         /* Make type to key as char string */
391                         snprintf(buf_key, sizeof(buf_key), "%d", type);
392
393                         snprintf(buf_val, sizeof(buf_val), "%s", key);
394
395                         /* Add new key value */
396                         bundle_add(b, buf_key, buf_val);
397
398                         /* Save key bundle */
399                         noti->b_key = b;
400                 }
401         } else {
402                 /* Reset if key is NULL */
403                 if (noti->b_key != NULL) {
404                         /* If key bundle exist,  store local bundle data */
405                         b = noti->b_key;
406
407                         /* Make type to key as char string */
408                         snprintf(buf_key, sizeof(buf_key), "%d", type);
409
410                         /* Get value using type key */
411                         ret_val = bundle_get_val(b, buf_key);
412                         if (ret_val != NULL) {
413                                 /* If value exist, remove this */
414                                 bundle_del(b, buf_key);
415                         }
416                 }
417         }
418
419         if (noti->b_format_args != NULL) {
420                 b = noti->b_format_args;
421         } else {
422                 b = bundle_create();
423         }
424
425         va_start(var_args, args_type);
426
427         var_type = args_type;
428         num_args = 0;
429
430         while (var_type != NOTIFICATION_VARIABLE_TYPE_NONE) {
431                 /* Type */
432                 snprintf(buf_key, sizeof(buf_key), "%dtype%d", type, num_args);
433                 snprintf(buf_val, sizeof(buf_val), "%d", var_type);
434
435                 ret_val = bundle_get_val(b, buf_key);
436                 if (ret_val != NULL) {
437                         bundle_del(b, buf_key);
438                 }
439
440                 bundle_add(b, buf_key, buf_val);
441
442                 switch (var_type) {
443                 case NOTIFICATION_VARIABLE_TYPE_INT:
444                         var_value_int = va_arg(var_args, int);
445
446                         /* Value */
447                         snprintf(buf_key, sizeof(buf_key), "%dvalue%d", type,
448                                  num_args);
449                         snprintf(buf_val, sizeof(buf_val), "%d", var_value_int);
450
451                         ret_val = bundle_get_val(b, buf_key);
452                         if (ret_val != NULL) {
453                                 bundle_del(b, buf_key);
454                         }
455
456                         bundle_add(b, buf_key, buf_val);
457                         break;
458                 case NOTIFICATION_VARIABLE_TYPE_DOUBLE:
459                         var_value_double = va_arg(var_args, double);
460
461                         /* Value */
462                         snprintf(buf_key, sizeof(buf_key), "%dvalue%d", type,
463                                  num_args);
464                         snprintf(buf_val, sizeof(buf_val), "%.2f",
465                                  var_value_double);
466
467                         ret_val = bundle_get_val(b, buf_key);
468                         if (ret_val != NULL) {
469                                 bundle_del(b, buf_key);
470                         }
471
472                         bundle_add(b, buf_key, buf_val);
473                         break;
474                 case NOTIFICATION_VARIABLE_TYPE_STRING:
475                         var_value_string = va_arg(var_args, char *);
476
477                         /* Value */
478                         snprintf(buf_key, sizeof(buf_key), "%dvalue%d", type,
479                                  num_args);
480                         snprintf(buf_val, sizeof(buf_val), "%s",
481                                  var_value_string);
482
483                         ret_val = bundle_get_val(b, buf_key);
484                         if (ret_val != NULL) {
485                                 bundle_del(b, buf_key);
486                         }
487
488                         bundle_add(b, buf_key, buf_val);
489                         break;
490                 case NOTIFICATION_VARIABLE_TYPE_COUNT:
491                         var_value_count =
492                             va_arg(var_args, notification_count_pos_type_e);
493
494                         /* Value */
495                         snprintf(buf_key, sizeof(buf_key), "%dvalue%d", type,
496                                  num_args);
497                         snprintf(buf_val, sizeof(buf_val), "%d",
498                                  var_value_count);
499
500                         ret_val = bundle_get_val(b, buf_key);
501                         if (ret_val != NULL) {
502                                 bundle_del(b, buf_key);
503                         }
504
505                         bundle_add(b, buf_key, buf_val);
506                         break;
507                 default:
508                         NOTIFICATION_ERR("Error. invalid variable type. : %d",
509                                          var_type);
510                         noti_err = NOTIFICATION_ERROR_INVALID_DATA;
511                         break;
512                 }
513
514                 num_args++;
515                 var_type = va_arg(var_args, notification_variable_type_e);
516         }
517         va_end(var_args);
518
519         if (noti_err == NOTIFICATION_ERROR_NONE) {
520                 noti->num_format_args = num_args;
521         } else {
522                 noti->num_format_args = 0;
523         }
524
525         snprintf(buf_key, sizeof(buf_key), "num%d", type);
526         snprintf(buf_val, sizeof(buf_val), "%d", noti->num_format_args);
527
528         ret_val = bundle_get_val(b, buf_key);
529         if (ret_val != NULL) {
530                 bundle_del(b, buf_key);
531         }
532
533         bundle_add(b, buf_key, buf_val);
534
535         noti->b_format_args = b;
536
537         return noti_err;
538 }
539
540 EXPORT_API notification_error_e notification_get_text(notification_h noti,
541                                                       notification_text_type_e type,
542                                                       char **text)
543 {
544         bundle *b = NULL;
545         char buf_key[32] = { 0, };
546         const char *ret_val = NULL;
547         const char *get_str = NULL;
548         const char *get_check_type_str = NULL;
549         notification_text_type_e check_type = NOTIFICATION_TEXT_TYPE_NONE;
550         int display_option_flag = 0;
551
552         char *temp_str = NULL;
553         char result_str[NOTI_TEXT_RESULT_LEN] = { 0, };
554         char buf_str[1024] = { 0, };
555         int num_args = 0;
556         notification_variable_type_e ret_var_type = 0;
557         int ret_variable_int = 0;
558         double ret_variable_double = 0.0;
559
560         /* Check noti is valid data */
561         if (noti == NULL || text == NULL) {
562                 return NOTIFICATION_ERROR_INVALID_DATA;
563         }
564
565         /* Check text type is valid type */
566         if (type <= NOTIFICATION_TEXT_TYPE_NONE
567             || type >= NOTIFICATION_TEXT_TYPE_MAX) {
568                 return NOTIFICATION_ERROR_INVALID_DATA;
569         }
570
571         /* Check key */
572         if (noti->b_key != NULL) {
573                 b = noti->b_key;
574
575                 /* Get text domain and dir */
576                 _notification_get_text_domain(noti);
577
578                 snprintf(buf_key, sizeof(buf_key), "%d", type);
579
580                 ret_val = bundle_get_val(b, buf_key);
581                 if (ret_val != NULL && noti->domain != NULL
582                     && noti->dir != NULL) {
583                         /* Get application string */
584                         bindtextdomain(noti->domain, noti->dir);
585
586                         get_str = dgettext(noti->domain, ret_val);
587                 } else if (ret_val != NULL) {
588                         /* Get system string */
589                         get_str = dgettext("sys_string", ret_val);
590                 } else {
591                         get_str = NULL;
592                 }
593         }
594
595         if (get_str == NULL && noti->b_text != NULL) {
596                 b = noti->b_text;
597                 /* Get basic text */
598                 snprintf(buf_key, sizeof(buf_key), "%d", type);
599
600                 get_str = bundle_get_val(b, buf_key);
601         }
602
603         check_type = type;
604
605         /* Set display option is off type when option is off, type is noti */
606         if (get_str != NULL && display_option_flag == 1
607             && noti->type == NOTIFICATION_TYPE_NOTI) {
608                 if (type == NOTIFICATION_TEXT_TYPE_CONTENT
609                     || type == NOTIFICATION_TEXT_TYPE_GROUP_CONTENT) {
610                         /* Set check_type to option content string */
611                         if (type == NOTIFICATION_TEXT_TYPE_CONTENT) {
612                                 check_type =
613                                     NOTIFICATION_TEXT_TYPE_CONTENT_FOR_DISPLAY_OPTION_IS_OFF;
614                         } else if (type == NOTIFICATION_TEXT_TYPE_GROUP_CONTENT) {
615                                 check_type =
616                                     NOTIFICATION_TEXT_TYPE_GROUP_CONTENT_FOR_DISPLAY_OPTION_IS_OFF;
617                         }
618
619                         /* Check key */
620                         if (noti->b_key != NULL) {
621                                 b = noti->b_key;
622
623                                 /* Get text domain and dir */
624                                 _notification_get_text_domain(noti);
625
626                                 snprintf(buf_key, sizeof(buf_key), "%d",
627                                          check_type);
628
629                                 ret_val = bundle_get_val(b, buf_key);
630                                 if (ret_val != NULL && noti->domain != NULL
631                                     && noti->dir != NULL) {
632                                         /* Get application string */
633                                         bindtextdomain(noti->domain, noti->dir);
634
635                                         get_check_type_str =
636                                             dgettext(noti->domain, ret_val);
637                                 } else if (ret_val != NULL) {
638                                         /* Get system string */
639                                         get_check_type_str =
640                                             dgettext("sys_string", ret_val);
641                                 } else {
642                                         get_check_type_str = NULL;
643                                 }
644                         }
645
646                         if (get_check_type_str == NULL && noti->b_text != NULL) {
647                                 b = noti->b_text;
648                                 /* Get basic text */
649                                 snprintf(buf_key, sizeof(buf_key), "%d",
650                                          check_type);
651
652                                 get_check_type_str = bundle_get_val(b, buf_key);
653                         }
654                 }
655
656                 if (get_check_type_str != NULL) {
657                         /* Replace option off type string */
658                         get_str = get_check_type_str;
659                 } else {
660                         /* Set default string */
661                         get_str =
662                             dgettext("sys_string", "IDS_COM_POP_MISSED_EVENT");
663                 }
664         }
665
666         if (get_str != NULL) {
667                 /* Get number format args */
668                 b = noti->b_format_args;
669                 noti->num_format_args = 0;
670
671                 if (b != NULL) {
672                         snprintf(buf_key, sizeof(buf_key), "num%d", check_type);
673                         ret_val = bundle_get_val(b, buf_key);
674                         if (ret_val != NULL) {
675                                 noti->num_format_args = atoi(ret_val);
676                         }
677                 }
678
679                 if (noti->num_format_args == 0) {
680                         *text = (char *)get_str;
681                 } else {
682                         /* Check first variable is count, LEFT pos */
683                         snprintf(buf_key, sizeof(buf_key), "%dtype%d",
684                                  check_type, num_args);
685                         ret_val = bundle_get_val(b, buf_key);
686                         ret_var_type = atoi(ret_val);
687
688                         if (ret_var_type == NOTIFICATION_VARIABLE_TYPE_COUNT) {
689                                 /* Get var Value */
690                                 snprintf(buf_key, sizeof(buf_key), "%dvalue%d",
691                                          check_type, num_args);
692                                 ret_val = bundle_get_val(b, buf_key);
693                                 ret_variable_int = atoi(ret_val);
694
695                                 if (ret_variable_int ==
696                                     NOTIFICATION_COUNT_POS_LEFT) {
697                                         notification_noti_get_count(noti->type,
698                                                                     noti->caller_pkgname,
699                                                                     noti->group_id,
700                                                                     noti->priv_id,
701                                                                     &ret_variable_int);
702                                         snprintf(buf_str, sizeof(buf_str),
703                                                  "%d ", ret_variable_int);
704
705                                         int src_len = strlen(result_str);
706                                         int max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
707
708                                         strncat(result_str, buf_str,
709                                                         max_len);
710
711                                         num_args++;
712                                 }
713
714                         }
715
716                         /* Check variable IN pos */
717                         for (temp_str = (char *)get_str; *temp_str != '\0';
718                              temp_str++) {
719                                 if (*temp_str != '%') {
720                                         strncat(result_str, temp_str, 1);
721                                 } else {
722                                         if (*(temp_str + 1) == '%') {
723                                                 strncat(result_str, temp_str,
724                                                         1);
725                                         } else if (*(temp_str + 1) == 'd') {
726                                                 /* Get var Type */
727                                                 ret_variable_int = 0;
728
729                                                 snprintf(buf_key,
730                                                          sizeof(buf_key),
731                                                          "%dtype%d", check_type,
732                                                          num_args);
733                                                 ret_val =
734                                                     bundle_get_val(b, buf_key);
735                                                 ret_var_type = atoi(ret_val);
736                                                 if (ret_var_type ==
737                                                     NOTIFICATION_VARIABLE_TYPE_COUNT)
738                                                 {
739                                                         /* Get notification count */
740                                                         notification_noti_get_count
741                                                             (noti->type,
742                                                              noti->caller_pkgname,
743                                                              noti->group_id,
744                                                              noti->priv_id,
745                                                              &ret_variable_int);
746                                                 } else {
747                                                         /* Get var Value */
748                                                         snprintf(buf_key,
749                                                                  sizeof
750                                                                  (buf_key),
751                                                                  "%dvalue%d",
752                                                                  check_type,
753                                                                  num_args);
754                                                         ret_val =
755                                                             bundle_get_val(b,
756                                                                            buf_key);
757                                                         ret_variable_int =
758                                                             atoi(ret_val);
759                                                 }
760
761                                                 snprintf(buf_str,
762                                                          sizeof(buf_str), "%d",
763                                                          ret_variable_int);
764
765                                                 int src_len = strlen(result_str);
766                                                 int max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
767
768                                                 strncat(result_str, buf_str,
769                                                                 max_len);
770
771                                                 temp_str++;
772
773                                                 num_args++;
774                                         } else if (*(temp_str + 1) == 's') {
775                                                 /* Get var Value */
776                                                 snprintf(buf_key,
777                                                          sizeof(buf_key),
778                                                          "%dvalue%d",
779                                                          check_type, num_args);
780                                                 ret_val =
781                                                     bundle_get_val(b, buf_key);
782
783                                                 snprintf(buf_str,
784                                                          sizeof(buf_str), "%s",
785                                                          ret_val);
786
787                                                 int src_len = strlen(result_str);
788                                                 int max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
789
790                                                 strncat(result_str, buf_str,
791                                                                 max_len);
792
793                                                 temp_str++;
794
795                                                 num_args++;
796                                         } else if (*(temp_str + 1) == 'f') {
797                                                 /* Get var Value */
798                                                 snprintf(buf_key,
799                                                          sizeof(buf_key),
800                                                          "%dvalue%d",
801                                                          check_type, num_args);
802                                                 ret_val =
803                                                     bundle_get_val(b, buf_key);
804                                                 ret_variable_double =
805                                                     atof(ret_val);
806
807                                                 snprintf(buf_str,
808                                                          sizeof(buf_str),
809                                                          "%.2f",
810                                                          ret_variable_double);
811
812                                                 int src_len = strlen(result_str);
813                                                 int max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
814
815                                                 strncat(result_str, buf_str,
816                                                                 max_len);
817
818                                                 temp_str++;
819
820                                                 num_args++;
821                                         }
822                                 }
823
824                         }
825
826                         /* Check last variable is count, LEFT pos */
827                         if (num_args < noti->num_format_args) {
828                                 snprintf(buf_key, sizeof(buf_key), "%dtype%d",
829                                          check_type, num_args);
830                                 ret_val = bundle_get_val(b, buf_key);
831                                 ret_var_type = atoi(ret_val);
832                                 if (ret_var_type ==
833                                     NOTIFICATION_VARIABLE_TYPE_COUNT) {
834                                         /* Get var Value */
835                                         snprintf(buf_key, sizeof(buf_key),
836                                                  "%dvalue%d", check_type,
837                                                  num_args);
838                                         ret_val = bundle_get_val(b, buf_key);
839                                         ret_variable_int = atoi(ret_val);
840
841                                         if (ret_variable_int ==
842                                             NOTIFICATION_COUNT_POS_RIGHT) {
843                                                 notification_noti_get_count
844                                                     (noti->type,
845                                                      noti->caller_pkgname,
846                                                      noti->group_id,
847                                                      noti->priv_id,
848                                                      &ret_variable_int);
849                                                 snprintf(buf_str,
850                                                          sizeof(buf_str), " %d",
851                                                          ret_variable_int);
852
853                                                 int src_len = strlen(result_str);
854                                                 int max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
855
856                                                 strncat(result_str, buf_str,
857                                                                 max_len);
858
859                                                 num_args++;
860                                         }
861
862                                 }
863                         }
864
865                         switch (check_type) {
866                         case NOTIFICATION_TEXT_TYPE_TITLE:
867                         case NOTIFICATION_TEXT_TYPE_GROUP_TITLE:
868                                 if (noti->temp_title != NULL)
869                                         free(noti->temp_title);
870
871                                 noti->temp_title = strdup(result_str);
872
873                                 *text = noti->temp_title;
874                                 break;
875                         case NOTIFICATION_TEXT_TYPE_CONTENT:
876                         case NOTIFICATION_TEXT_TYPE_CONTENT_FOR_DISPLAY_OPTION_IS_OFF:
877                         case NOTIFICATION_TEXT_TYPE_GROUP_CONTENT:
878                         case NOTIFICATION_TEXT_TYPE_GROUP_CONTENT_FOR_DISPLAY_OPTION_IS_OFF:
879                                 if (noti->temp_content !=
880                                     NULL)
881                                         free(noti->temp_content);
882
883                                 noti->temp_content = strdup(result_str);
884
885                                 *text = noti->temp_content;
886                                 break;
887                         default:
888                                 break;
889                         }
890
891                 }
892
893         } else {
894                 *text = NULL;
895         }
896
897         return NOTIFICATION_ERROR_NONE;
898 }
899
900 EXPORT_API notification_error_e notification_set_text_domain(notification_h noti,
901                                                              const char *domain,
902                                                              const char *dir)
903 {
904         /* check noti and domain is valid data */
905         if (noti == NULL || domain == NULL) {
906                 return NOTIFICATION_ERROR_INVALID_DATA;
907         }
908
909         /* Check domain */
910         if (noti->domain) {
911                 /* Remove previous domain */
912                 free(noti->domain);
913         }
914         /* Copy domain */
915         noti->domain = strdup(domain);
916
917         /* Check locale dir */
918         if (noti->dir) {
919                 /* Remove previous locale dir */
920                 free(noti->dir);
921         }
922         /* Copy locale dir */
923         noti->dir = strdup(dir);
924
925         return NOTIFICATION_ERROR_NONE;
926 }
927
928 EXPORT_API notification_error_e notification_get_text_domain(notification_h noti,
929                                                              char **domain,
930                                                              char **dir)
931 {
932         /* Check noti is valid data */
933         if (noti == NULL) {
934                 return NOTIFICATION_ERROR_INVALID_DATA;
935         }
936
937         /* Get domain */
938         if (domain != NULL && noti->domain != NULL) {
939                 *domain = noti->domain;
940         }
941
942         /* Get locale dir */
943         if (dir != NULL && noti->dir != NULL) {
944                 *dir = noti->dir;
945         }
946
947         return NOTIFICATION_ERROR_NONE;
948 }
949
950 EXPORT_API notification_error_e notification_set_time_to_text(notification_h noti, notification_text_type_e type,
951                                                                 time_t time)
952 {
953         notification_error_e ret = NOTIFICATION_ERROR_NONE;
954         char buf[256] = { 0, };
955         char buf_tag[512] = { 0, };
956
957         if (noti == NULL) {
958                 return NOTIFICATION_ERROR_INVALID_DATA;
959         }
960         if (time <= 0) {
961                 return NOTIFICATION_ERROR_INVALID_DATA;
962         }
963
964         snprintf(buf, sizeof(buf), "%lu", time);
965         ret = notification_noti_set_tag(TAG_TIME, buf, buf_tag, sizeof(buf_tag));
966
967         if (ret != NOTIFICATION_ERROR_NONE) {
968                 return ret;
969         }
970
971         return notification_set_text(noti, type, buf_tag, NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
972 }
973
974 EXPORT_API notification_error_e notification_get_time_from_text(notification_h noti, notification_text_type_e type,
975                                                                 time_t *time)
976 {
977         notification_error_e ret = NOTIFICATION_ERROR_NONE;
978
979         if (noti == NULL) {
980                 return NOTIFICATION_ERROR_INVALID_DATA;
981         }
982         if (time == NULL) {
983                 return NOTIFICATION_ERROR_INVALID_DATA;
984         }
985
986         char *ret_text = NULL;
987         ret = notification_get_text(noti, type, &ret_text);
988
989         if (ret != NOTIFICATION_ERROR_NONE || ret_text == NULL) {
990                 return NOTIFICATION_ERROR_INVALID_DATA;
991         }
992
993         if (notification_noti_get_tag_type(ret_text) == TAG_TYPE_INVALID) {
994                 return NOTIFICATION_ERROR_INVALID_DATA;
995         }
996
997         char *tag_value = NULL;
998         tag_value = notification_noti_strip_tag(ret_text);
999         if (tag_value == NULL) {
1000                 return NOTIFICATION_ERROR_INVALID_DATA;
1001         }
1002
1003         *time = atol(tag_value);
1004         free(tag_value);
1005
1006         return NOTIFICATION_ERROR_NONE;
1007 }
1008
1009 EXPORT_API notification_error_e notification_set_sound(notification_h noti,
1010                                                        notification_sound_type_e type,
1011                                                        const char *path)
1012 {
1013         /* Check noti is valid data */
1014         if (noti == NULL) {
1015                 return NOTIFICATION_ERROR_INVALID_DATA;
1016         }
1017
1018         /* Check type is valid */
1019         if (type < NOTIFICATION_SOUND_TYPE_NONE
1020             || type >= NOTIFICATION_SOUND_TYPE_MAX) {
1021                 return NOTIFICATION_ERROR_INVALID_DATA;
1022         }
1023
1024         /* Save sound type */
1025         noti->sound_type = type;
1026
1027         /* Save sound path if user data type */
1028         if (type == NOTIFICATION_SOUND_TYPE_USER_DATA && path != NULL) {
1029                 if (noti->sound_path != NULL) {
1030                         free(noti->sound_path);
1031                 }
1032
1033                 noti->sound_path = strdup(path);
1034         } else {
1035                 if (noti->sound_path != NULL) {
1036                         free(noti->sound_path);
1037                         noti->sound_path = NULL;
1038                 }
1039         }
1040
1041         return NOTIFICATION_ERROR_NONE;
1042 }
1043
1044 EXPORT_API notification_error_e notification_get_sound(notification_h noti,
1045                                                        notification_sound_type_e *type,
1046                                                        const char **path)
1047 {
1048         /* check noti and type is valid data */
1049         if (noti == NULL || type == NULL) {
1050                 return NOTIFICATION_ERROR_INVALID_DATA;
1051         }
1052
1053         /* Set sound type */
1054         *type = noti->sound_type;
1055
1056         /* Set sound path if user data type */
1057         if (noti->sound_type == NOTIFICATION_SOUND_TYPE_USER_DATA
1058             && path != NULL) {
1059                 *path = noti->sound_path;
1060         }
1061
1062         return NOTIFICATION_ERROR_NONE;
1063 }
1064
1065 EXPORT_API notification_error_e notification_set_vibration(notification_h noti,
1066                                                            notification_vibration_type_e type,
1067                                                            const char *path)
1068 {
1069         /* Check noti is valid data */
1070         if (noti == NULL) {
1071                 return NOTIFICATION_ERROR_INVALID_DATA;
1072         }
1073
1074         /* Check type is valid */
1075         if (type < NOTIFICATION_VIBRATION_TYPE_NONE
1076             || type >= NOTIFICATION_VIBRATION_TYPE_MAX) {
1077                 return NOTIFICATION_ERROR_INVALID_DATA;
1078         }
1079
1080         /* Save vibration type */
1081         noti->vibration_type = type;
1082
1083         /* Save sound path if user data type */
1084         if (type == NOTIFICATION_VIBRATION_TYPE_USER_DATA && path != NULL) {
1085                 if (noti->vibration_path != NULL) {
1086                         free(noti->vibration_path);
1087                 }
1088
1089                 noti->vibration_path = strdup(path);
1090         } else {
1091                 if (noti->vibration_path != NULL) {
1092                         free(noti->vibration_path);
1093                         noti->vibration_path = NULL;
1094                 }
1095         }
1096
1097         return NOTIFICATION_ERROR_NONE;
1098
1099 }
1100
1101 EXPORT_API notification_error_e notification_get_vibration(notification_h noti,
1102                                                            notification_vibration_type_e *type,
1103                                                            const char **path)
1104 {
1105         /* check noti and type is valid data */
1106         if (noti == NULL || type == NULL) {
1107                 return NOTIFICATION_ERROR_INVALID_DATA;
1108         }
1109
1110         /* Set vibration type */
1111         *type = noti->vibration_type;
1112
1113         /* Set sound path if user data type */
1114         if (noti->vibration_type == NOTIFICATION_VIBRATION_TYPE_USER_DATA
1115             && path != NULL) {
1116                 *path = noti->vibration_path;
1117         }
1118
1119         return NOTIFICATION_ERROR_NONE;
1120 }
1121
1122 EXPORT_API notification_error_e notification_set_led(notification_h noti,
1123                                                            notification_led_op_e operation,
1124                                                            int led_argb)
1125 {
1126         /* Check noti is valid data */
1127         if (noti == NULL) {
1128                 return NOTIFICATION_ERROR_INVALID_DATA;
1129         }
1130
1131         /* Check operation is valid */
1132         if (operation < NOTIFICATION_LED_OP_OFF
1133             || operation >= NOTIFICATION_LED_OP_MAX) {
1134                 return NOTIFICATION_ERROR_INVALID_DATA;
1135         }
1136
1137         /* Save led operation */
1138         noti->led_operation = operation;
1139
1140         /* Save led argb if operation is turning on LED with custom color */
1141         if (operation == NOTIFICATION_LED_OP_ON_CUSTOM_COLOR) {
1142                 noti->led_argb = led_argb;
1143         }
1144
1145         return NOTIFICATION_ERROR_NONE;
1146 }
1147
1148 EXPORT_API notification_error_e notification_get_led(notification_h noti,
1149                                                            notification_led_op_e *operation,
1150                                                            int *led_argb)
1151 {
1152         /* check noti and operation is valid data */
1153         if (noti == NULL || operation == NULL) {
1154                 return NOTIFICATION_ERROR_INVALID_DATA;
1155         }
1156
1157         /* Set led operation */
1158         *operation = noti->led_operation;
1159
1160         /* Save led argb if operation is turning on LED with custom color */
1161         if (noti->led_operation == NOTIFICATION_LED_OP_ON_CUSTOM_COLOR
1162             && led_argb != NULL) {
1163                 *led_argb = noti->led_argb;
1164         }
1165
1166         return NOTIFICATION_ERROR_NONE;
1167 }
1168
1169 EXPORT_API notification_error_e notification_set_led_time_period(notification_h noti,
1170                                                                         int on_ms, int off_ms)
1171 {
1172         /* Check noti is valid data */
1173         if (noti == NULL) {
1174                 return NOTIFICATION_ERROR_INVALID_DATA;
1175         }
1176
1177         /* Save led operation */
1178         noti->led_on_ms = on_ms;
1179         noti->led_off_ms = off_ms;
1180
1181         return NOTIFICATION_ERROR_NONE;
1182 }
1183
1184 EXPORT_API notification_error_e notification_get_led_time_period(notification_h noti,
1185                                                                         int *on_ms, int *off_ms)
1186 {
1187         /* check noti and operation is valid data */
1188         if (noti == NULL) {
1189                 return NOTIFICATION_ERROR_INVALID_DATA;
1190         }
1191
1192         if (on_ms)
1193                 *(on_ms) = noti->led_on_ms;
1194         if (off_ms)
1195                 *(off_ms) = noti->led_off_ms;
1196
1197         return NOTIFICATION_ERROR_NONE;
1198 }
1199
1200 EXPORT_API notification_error_e notification_set_application(notification_h noti,
1201                                                              const char *pkgname)
1202 {
1203         if (noti == NULL || pkgname == NULL) {
1204                 return NOTIFICATION_ERROR_INVALID_DATA;
1205         }
1206
1207         if (noti->launch_pkgname) {
1208                 free(noti->launch_pkgname);
1209         }
1210
1211         noti->launch_pkgname = strdup(pkgname);
1212
1213         return NOTIFICATION_ERROR_NONE;
1214 }
1215
1216 EXPORT_API notification_error_e notification_get_application(notification_h noti,
1217                                                              char **pkgname)
1218 {
1219         if (noti == NULL || pkgname == NULL) {
1220                 return NOTIFICATION_ERROR_INVALID_DATA;
1221         }
1222
1223         if (noti->launch_pkgname) {
1224                 *pkgname = noti->launch_pkgname;
1225         } else {
1226                 *pkgname = noti->caller_pkgname;
1227         }
1228
1229         return NOTIFICATION_ERROR_NONE;
1230 }
1231
1232 EXPORT_API notification_error_e notification_set_execute_option(notification_h noti,
1233                                                                 notification_execute_type_e type,
1234                                                                 const char *text,
1235                                                                 const char *key,
1236                                                                 bundle *service_handle)
1237 {
1238         char buf_key[32] = { 0, };
1239         const char *ret_val = NULL;
1240         bundle *b = NULL;
1241
1242         if (noti == NULL) {
1243                 return NOTIFICATION_ERROR_INVALID_DATA;
1244         }
1245
1246         if (type <= NOTIFICATION_EXECUTE_TYPE_NONE
1247             || type >= NOTIFICATION_EXECUTE_TYPE_MAX) {
1248                 return NOTIFICATION_ERROR_INVALID_DATA;
1249         }
1250
1251         /* Create execute option bundle if does not exist */
1252         if (noti->b_execute_option != NULL) {
1253                 noti->b_execute_option = bundle_create();
1254         }
1255
1256         b = noti->b_execute_option;
1257
1258         /* Save text */
1259         if (text != NULL) {
1260                 /* Make text key */
1261                 snprintf(buf_key, sizeof(buf_key), "text%d", type);
1262
1263                 /* Check text key exist */
1264                 ret_val = bundle_get_val(b, buf_key);
1265                 if (ret_val != NULL) {
1266                         /* Remove previous data */
1267                         bundle_del(b, buf_key);
1268                 }
1269
1270                 /* Add text data */
1271                 bundle_add(b, buf_key, text);
1272         }
1273
1274         /* Save key */
1275         if (key != NULL) {
1276                 /* Make key key */
1277                 snprintf(buf_key, sizeof(buf_key), "key%d", type);
1278
1279                 /* Check key key exist */
1280                 ret_val = bundle_get_val(b, buf_key);
1281                 if (ret_val != NULL) {
1282                         /* Remove previous data */
1283                         bundle_del(b, buf_key);
1284                 }
1285
1286                 /* Add text data */
1287                 bundle_add(b, buf_key, key);
1288         }
1289
1290         switch ((int)type) {
1291                 case NOTIFICATION_EXECUTE_TYPE_RESPONDING:
1292                         /* Remove previous data if exist */
1293                         if (noti->b_service_responding != NULL) {
1294                                 bundle_free(noti->b_service_responding);
1295                                 noti->b_service_responding = NULL;
1296                         }
1297
1298                         /* Save service handle */
1299                         if (service_handle != NULL) {
1300                                 noti->b_service_responding = bundle_dup(service_handle);
1301                         }
1302                         break;
1303                 case NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH:
1304                         /* Remove previous data if exist */
1305                         if (noti->b_service_single_launch != NULL) {
1306                                 bundle_free(noti->b_service_single_launch);
1307                                 noti->b_service_single_launch = NULL;
1308                         }
1309
1310                         /* Save service handle */
1311                         if (service_handle != NULL) {
1312                                 noti->b_service_single_launch =
1313                                         bundle_dup(service_handle);
1314                         }
1315                         break;
1316                 case NOTIFICATION_EXECUTE_TYPE_MULTI_LAUNCH:
1317                         /* Remove previous data if exist */
1318                         if (noti->b_service_multi_launch != NULL) {
1319                                 bundle_free(noti->b_service_multi_launch);
1320                                 noti->b_service_multi_launch = NULL;
1321                         }
1322
1323                         /* Save service handle */
1324                         if (service_handle != NULL) {
1325                                 noti->b_service_multi_launch =
1326                                         bundle_dup(service_handle);
1327                         }
1328                         break;
1329         }
1330
1331         return NOTIFICATION_ERROR_NONE;
1332 }
1333
1334 EXPORT_API notification_error_e notification_get_execute_option(notification_h noti,
1335                                                                 notification_execute_type_e type,
1336                                                                 const char **text,
1337                                                                 bundle **service_handle)
1338 {
1339         char buf_key[32] = { 0, };
1340         const char *ret_val = NULL;
1341         char *get_str = NULL;
1342         bundle *b = NULL;
1343
1344         if (noti == NULL) {
1345                 return NOTIFICATION_ERROR_INVALID_DATA;
1346         }
1347
1348         if (type <= NOTIFICATION_EXECUTE_TYPE_NONE
1349             || type >= NOTIFICATION_EXECUTE_TYPE_MAX) {
1350                 return NOTIFICATION_ERROR_INVALID_DATA;
1351         }
1352
1353         switch (type) {
1354         case NOTIFICATION_EXECUTE_TYPE_RESPONDING:
1355                 b = noti->b_service_responding;
1356                 break;
1357         case NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH:
1358                 b = noti->b_service_single_launch;
1359                 break;
1360         case NOTIFICATION_EXECUTE_TYPE_MULTI_LAUNCH:
1361                 b = noti->b_service_multi_launch;
1362                 break;
1363         default:
1364                 b = NULL;
1365                 break;
1366         }
1367
1368         if (b != NULL) {
1369                 // Return text
1370                 if (text != NULL) {
1371                         // Get text domain and dir
1372                         if (noti->domain == NULL || noti->dir == NULL) {
1373                                 _notification_get_text_domain(noti);
1374                         }
1375
1376                         /* Make key */
1377                         snprintf(buf_key, sizeof(buf_key), "key%d", type);
1378
1379                         /* Check key key exist */
1380                         ret_val = bundle_get_val(b, buf_key);
1381                         if (ret_val != NULL && noti->domain != NULL
1382                             && noti->dir != NULL) {
1383                                 /* Get application string */
1384                                 bindtextdomain(noti->domain, noti->dir);
1385
1386                                 get_str = dgettext(noti->domain, ret_val);
1387
1388                                 *text = get_str;
1389                         } else if (ret_val != NULL) {
1390                                 /* Get system string */
1391                                 get_str = dgettext("sys_string", ret_val);
1392
1393                                 *text = get_str;
1394                         } else {
1395                                 /* Get basic text */
1396                                 snprintf(buf_key, sizeof(buf_key), "text%d",
1397                                          type);
1398
1399                                 ret_val = bundle_get_val(b, buf_key);
1400
1401                                 *text = ret_val;
1402                         }
1403                 }
1404         }
1405
1406         switch (type) {
1407         case NOTIFICATION_EXECUTE_TYPE_RESPONDING:
1408                 b = noti->b_service_responding;
1409                 break;
1410         case NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH:
1411                 b = noti->b_service_single_launch;
1412                 break;
1413         case NOTIFICATION_EXECUTE_TYPE_MULTI_LAUNCH:
1414                 b = noti->b_service_multi_launch;
1415                 break;
1416         default:
1417                 b = NULL;
1418                 break;
1419         }
1420
1421         if (service_handle != NULL) {
1422                 *service_handle = b;
1423         }
1424
1425         return NOTIFICATION_ERROR_NONE;
1426 }
1427
1428 EXPORT_API notification_error_e notification_set_property(notification_h noti,
1429                                                           int flags)
1430 {
1431         /* Check noti is valid data */
1432         if (noti == NULL) {
1433                 return NOTIFICATION_ERROR_INVALID_DATA;
1434         }
1435
1436         /* Set flags */
1437         noti->flags_for_property = flags;
1438
1439         return NOTIFICATION_ERROR_NONE;
1440 }
1441
1442 EXPORT_API notification_error_e notification_get_property(notification_h noti,
1443                                                           int *flags)
1444 {
1445         /* Check noti and flags are valid data */
1446         if (noti == NULL || flags == NULL) {
1447                 return NOTIFICATION_ERROR_INVALID_DATA;
1448         }
1449
1450         /* Set flags */
1451         *flags = noti->flags_for_property;
1452
1453         return NOTIFICATION_ERROR_NONE;
1454 }
1455
1456 EXPORT_API notification_error_e notification_set_display_applist(notification_h noti,
1457                                                                  int applist)
1458 {
1459         /* Check noti is valid data */
1460         if (noti == NULL) {
1461                 return NOTIFICATION_ERROR_INVALID_DATA;
1462         }
1463
1464         /* Set app list */
1465         noti->display_applist = applist;
1466
1467         return NOTIFICATION_ERROR_NONE;
1468 }
1469
1470 EXPORT_API notification_error_e notification_get_display_applist(notification_h noti,
1471                                                                  int *applist)
1472 {
1473         /* Check noti and applist are valid data */
1474         if (noti == NULL || applist == NULL) {
1475                 return NOTIFICATION_ERROR_INVALID_DATA;
1476         }
1477
1478         /* Set app list */
1479         *applist = noti->display_applist;
1480
1481         return NOTIFICATION_ERROR_NONE;
1482 }
1483
1484 EXPORT_API notification_error_e notification_set_size(notification_h noti,
1485                                                       double size)
1486 {
1487         /* Check noti is valid data */
1488         if (noti == NULL) {
1489                 return NOTIFICATION_ERROR_INVALID_DATA;
1490         }
1491
1492         /* Save progress size */
1493         noti->progress_size = size;
1494
1495         return NOTIFICATION_ERROR_NONE;
1496 }
1497
1498 EXPORT_API notification_error_e notification_get_size(notification_h noti,
1499                                                       double *size)
1500 {
1501         /* Check noti and size is valid data */
1502         if (noti == NULL || size == NULL) {
1503                 return NOTIFICATION_ERROR_INVALID_DATA;
1504         }
1505
1506         /* Set progress size */
1507         *size = noti->progress_size;
1508
1509         return NOTIFICATION_ERROR_NONE;
1510 }
1511
1512 EXPORT_API notification_error_e notification_set_progress(notification_h noti,
1513                                                           double percentage)
1514 {
1515         /* Check noti is valid data */
1516         if (noti == NULL) {
1517                 return NOTIFICATION_ERROR_INVALID_DATA;
1518         }
1519
1520         /* Save progress percentage */
1521         noti->progress_percentage = percentage;
1522
1523         return NOTIFICATION_ERROR_NONE;
1524 }
1525
1526 EXPORT_API notification_error_e notification_get_progress(notification_h noti,
1527                                                           double *percentage)
1528 {
1529         /* Check noti and percentage are valid data */
1530         if (noti == NULL || percentage == NULL) {
1531                 return NOTIFICATION_ERROR_INVALID_DATA;
1532         }
1533
1534         /* Set progress percentage */
1535         *percentage = noti->progress_percentage;
1536
1537         return NOTIFICATION_ERROR_NONE;
1538 }
1539
1540 EXPORT_API notification_error_e notification_set_pkgname(notification_h noti,
1541                                                          const char *pkgname)
1542 {
1543         /* check noti and pkgname are valid data */
1544         if (noti == NULL || pkgname == NULL) {
1545                 return NOTIFICATION_ERROR_INVALID_DATA;
1546         }
1547
1548         /* Remove previous caller pkgname */
1549         if (noti->caller_pkgname) {
1550                 free(noti->caller_pkgname);
1551                 noti->caller_pkgname = NULL;
1552         }
1553
1554         noti->caller_pkgname = strdup(pkgname);
1555
1556         return NOTIFICATION_ERROR_NONE;
1557 }
1558
1559 EXPORT_API notification_error_e notification_get_pkgname(notification_h noti,
1560                                                          char **pkgname)
1561 {
1562         /* Check noti and pkgname are valid data */
1563         if (noti == NULL || pkgname == NULL) {
1564                 return NOTIFICATION_ERROR_INVALID_DATA;
1565         }
1566
1567         /* Get caller pkgname */
1568         if (noti->caller_pkgname) {
1569                 *pkgname = noti->caller_pkgname;
1570         } else {
1571                 *pkgname = NULL;
1572         }
1573
1574         return NOTIFICATION_ERROR_NONE;
1575 }
1576
1577 EXPORT_API notification_error_e notification_set_layout(notification_h noti,
1578                 notification_ly_type_e layout)
1579 {
1580         /* check noti and pkgname are valid data */
1581         if (noti == NULL || (layout < NOTIFICATION_LY_NONE || layout >= NOTIFICATION_LY_MAX)) {
1582                 return NOTIFICATION_ERROR_INVALID_DATA;
1583         }
1584
1585         noti->layout = layout;
1586
1587         return NOTIFICATION_ERROR_NONE;
1588 }
1589
1590 EXPORT_API notification_error_e notification_get_layout(notification_h noti,
1591                 notification_ly_type_e *layout)
1592 {
1593         /* Check noti and pkgname are valid data */
1594         if (noti == NULL || layout == NULL) {
1595                 return NOTIFICATION_ERROR_INVALID_DATA;
1596         }
1597
1598         *layout = noti->layout;
1599
1600         return NOTIFICATION_ERROR_NONE;
1601 }
1602
1603 EXPORT_API notification_error_e notification_get_id(notification_h noti,
1604                                                     int *group_id, int *priv_id)
1605 {
1606         /* check noti is valid data */
1607         if (noti == NULL) {
1608                 return NOTIFICATION_ERROR_INVALID_DATA;
1609         }
1610
1611         /* Check group_id is valid data */
1612         if (group_id) {
1613                 /* Set group id */
1614                 if (noti->group_id < NOTIFICATION_GROUP_ID_NONE) {
1615                         *group_id = NOTIFICATION_GROUP_ID_NONE;
1616                 } else {
1617                         *group_id = noti->group_id;
1618                 }
1619         }
1620
1621         /* Check priv_id is valid data */
1622         if (priv_id) {
1623                 /* Set priv_id */
1624                 *priv_id = noti->priv_id;
1625         }
1626
1627         return NOTIFICATION_ERROR_NONE;
1628 }
1629
1630 EXPORT_API notification_error_e notification_get_type(notification_h noti,
1631                                                       notification_type_e *type)
1632 {
1633         /* Check noti and type is valid data */
1634         if (noti == NULL || type == NULL) {
1635                 return NOTIFICATION_ERROR_INVALID_DATA;
1636         }
1637
1638         /* Set noti type */
1639         *type = noti->type;
1640
1641         return NOTIFICATION_ERROR_NONE;
1642 }
1643
1644 EXPORT_API notification_error_e notification_insert(notification_h noti,
1645                                                     int *priv_id)
1646 {
1647         int ret = 0;
1648         int id = 0;
1649
1650         /* Check noti is vaild data */
1651         if (noti == NULL) {
1652                 return NOTIFICATION_ERROR_INVALID_DATA;
1653         }
1654
1655         /* Check noti type is valid type */
1656         if (noti->type <= NOTIFICATION_TYPE_NONE
1657             || noti->type >= NOTIFICATION_TYPE_MAX) {
1658                 return NOTIFICATION_ERROR_INVALID_DATA;
1659         }
1660
1661         /* Save insert time */
1662         noti->insert_time = time(NULL);
1663         ret = notification_ipc_request_insert(noti, &id);
1664         if (ret != NOTIFICATION_ERROR_NONE) {
1665                 return ret;
1666         }
1667         noti->priv_id = id;
1668         NOTIFICATION_DBG("from master:%d", id);
1669
1670         /* If priv_id is valid data, set priv_id */
1671         if (priv_id != NULL) {
1672                 *priv_id = noti->priv_id;
1673         }
1674
1675         return NOTIFICATION_ERROR_NONE;
1676 }
1677
1678 EXPORT_API notification_error_e notification_update(notification_h noti)
1679 {
1680         int ret = 0;
1681
1682         /* Check noti is valid data */
1683         if (noti != NULL) {
1684                 /* Update insert time ? */
1685                 noti->insert_time = time(NULL);
1686                 ret = notification_ipc_request_update(noti);
1687                 if (ret != NOTIFICATION_ERROR_NONE) {
1688                         return ret;
1689                 }
1690         } else {
1691                 ret = notification_ipc_request_refresh();
1692                 if (ret != NOTIFICATION_ERROR_NONE) {
1693                         return ret;
1694                 }
1695         }
1696         return NOTIFICATION_ERROR_NONE;
1697 }
1698
1699 EXPORT_API notification_error_e notification_update_async(notification_h noti,
1700                 void (*result_cb)(int priv_id, int result, void *data), void *user_data)
1701 {
1702         int ret = 0;
1703
1704         /* Check noti is valid data */
1705         if (noti != NULL) {
1706                 /* Update insert time ? */
1707                 noti->insert_time = time(NULL);
1708                 ret = notification_ipc_request_update_async(noti, result_cb, user_data);
1709                 if (ret != NOTIFICATION_ERROR_NONE) {
1710                         return ret;
1711                 }
1712         }
1713         return NOTIFICATION_ERROR_NONE;
1714 }
1715
1716 EXPORT_API notification_error_e notifiation_clear(notification_type_e type)
1717 {
1718         int ret = 0;
1719
1720         ret = notification_ipc_request_delete_multiple(type, NULL);
1721         if (ret != NOTIFICATION_ERROR_NONE) {
1722                 return ret;
1723         }
1724
1725         return NOTIFICATION_ERROR_NONE;
1726 }
1727
1728 EXPORT_API notification_error_e notification_delete_all_by_type(const char *pkgname,
1729                                                                 notification_type_e type)
1730 {
1731         int ret = 0;
1732         char *caller_pkgname = NULL;
1733
1734         if (pkgname == NULL) {
1735                 caller_pkgname = _notification_get_pkgname_by_pid();
1736         } else {
1737                 caller_pkgname = strdup(pkgname);
1738         }
1739
1740         ret = notification_ipc_request_delete_multiple(type, caller_pkgname);
1741         if (ret != NOTIFICATION_ERROR_NONE) {
1742                 if (caller_pkgname) {
1743                         free(caller_pkgname);
1744                 }
1745                 return ret;
1746         }
1747
1748         if (caller_pkgname) {
1749                 free(caller_pkgname);
1750         }
1751         return NOTIFICATION_ERROR_NONE;
1752 }
1753
1754 EXPORT_API notification_error_e notification_delete_by_priv_id(const char *pkgname,
1755                                                                notification_type_e type,
1756                                                                int priv_id)
1757 {
1758         int ret = 0;
1759         char *caller_pkgname = NULL;
1760
1761         if (priv_id <= NOTIFICATION_PRIV_ID_NONE) {
1762                 return NOTIFICATION_ERROR_INVALID_DATA;
1763         }
1764
1765         if (pkgname == NULL) {
1766                 caller_pkgname = _notification_get_pkgname_by_pid();
1767         } else {
1768                 caller_pkgname = strdup(pkgname);
1769         }
1770
1771         ret = notification_ipc_request_delete_single(type, caller_pkgname, priv_id);
1772         if (ret != NOTIFICATION_ERROR_NONE) {
1773                 if (caller_pkgname) {
1774                         free(caller_pkgname);
1775                 }
1776                 return ret;
1777         }
1778
1779         if (caller_pkgname) {
1780                 free(caller_pkgname);
1781         }
1782         return ret;
1783 }
1784
1785 EXPORT_API notification_error_e notification_delete(notification_h noti)
1786 {
1787         int ret = 0;
1788
1789         if (noti == NULL) {
1790                 return NOTIFICATION_ERROR_INVALID_DATA;
1791         }
1792
1793         ret = notification_ipc_request_delete_single(NOTIFICATION_TYPE_NONE, noti->caller_pkgname, noti->priv_id);
1794         if (ret != NOTIFICATION_ERROR_NONE) {
1795                 return ret;
1796         }
1797
1798         return NOTIFICATION_ERROR_NONE;
1799 }
1800
1801 EXPORT_API notification_error_e notification_update_progress(notification_h noti,
1802                                                              int priv_id,
1803                                                              double progress)
1804 {
1805         char *caller_pkgname = NULL;
1806         int input_priv_id = 0;
1807         double input_progress = 0.0;
1808
1809         if (priv_id <= NOTIFICATION_PRIV_ID_NONE) {
1810                 if (noti == NULL) {
1811                         return NOTIFICATION_ERROR_INVALID_DATA;
1812                 } else {
1813                         input_priv_id = noti->priv_id;
1814                 }
1815         } else {
1816                 input_priv_id = priv_id;
1817         }
1818
1819         if (noti == NULL) {
1820                 caller_pkgname = _notification_get_pkgname_by_pid();
1821         } else {
1822                 caller_pkgname = strdup(noti->caller_pkgname);
1823         }
1824
1825         if (progress < 0.0) {
1826                 input_progress = 0.0;
1827         } else if (progress > 1.0) {
1828                 input_progress = 1.0;
1829         } else {
1830                 input_progress = progress;
1831         }
1832
1833         notification_ongoing_update_progress(caller_pkgname, input_priv_id,
1834                                              input_progress);
1835
1836         if (caller_pkgname) {
1837                 free(caller_pkgname);
1838         }
1839
1840         return NOTIFICATION_ERROR_NONE;
1841 }
1842
1843 EXPORT_API notification_error_e notification_update_size(notification_h noti,
1844                                                          int priv_id,
1845                                                          double size)
1846 {
1847         char *caller_pkgname = NULL;
1848         int input_priv_id = 0;
1849         double input_size = 0.0;
1850
1851         if (priv_id <= NOTIFICATION_PRIV_ID_NONE) {
1852                 if (noti == NULL) {
1853                         return NOTIFICATION_ERROR_INVALID_DATA;
1854                 } else {
1855                         input_priv_id = noti->priv_id;
1856                 }
1857         } else {
1858                 input_priv_id = priv_id;
1859         }
1860
1861         if (noti == NULL) {
1862                 caller_pkgname = _notification_get_pkgname_by_pid();
1863         } else {
1864                 caller_pkgname = strdup(noti->caller_pkgname);
1865         }
1866
1867         if (size < 0.0) {
1868                 input_size = 0.0;
1869         } else {
1870                 input_size = size;
1871         }
1872
1873         notification_ongoing_update_size(caller_pkgname, input_priv_id,
1874                                          input_size);
1875
1876         if (caller_pkgname) {
1877                 free(caller_pkgname);
1878         }
1879
1880         return NOTIFICATION_ERROR_NONE;
1881 }
1882
1883 EXPORT_API notification_error_e notification_update_content(notification_h noti,
1884                                                          int priv_id,
1885                                                          const char *content)
1886 {
1887         char *caller_pkgname = NULL;
1888         int input_priv_id = 0;
1889
1890         if (priv_id <= NOTIFICATION_PRIV_ID_NONE) {
1891                 if (noti == NULL) {
1892                         return NOTIFICATION_ERROR_INVALID_DATA;
1893                 } else {
1894                         input_priv_id = noti->priv_id;
1895                 }
1896         } else {
1897                 input_priv_id = priv_id;
1898         }
1899
1900         if (noti == NULL) {
1901                 caller_pkgname = _notification_get_pkgname_by_pid();
1902         } else {
1903                 caller_pkgname = strdup(noti->caller_pkgname);
1904         }
1905
1906         notification_ongoing_update_content(caller_pkgname, input_priv_id,
1907                                          content);
1908
1909         if (caller_pkgname) {
1910                 free(caller_pkgname);
1911         }
1912
1913         return NOTIFICATION_ERROR_NONE;
1914 }
1915
1916 static notification_h _notification_create(notification_type_e type)
1917 {
1918         notification_h noti = NULL;
1919
1920         if (type <= NOTIFICATION_TYPE_NONE || type >= NOTIFICATION_TYPE_MAX) {
1921                 NOTIFICATION_ERR("INVALID TYPE : %d", type);
1922                 return NULL;
1923         }
1924
1925         noti = (notification_h) calloc(1, sizeof(struct _notification));
1926         if (noti == NULL) {
1927                 NOTIFICATION_ERR("NO MEMORY : noti == NULL");
1928                 return NULL;
1929         }
1930
1931         noti->type = type;
1932
1933         if (type == NOTIFICATION_TYPE_NOTI)
1934                 noti->layout = NOTIFICATION_LY_NOTI_EVENT_SINGLE;
1935         else if (type == NOTIFICATION_TYPE_ONGOING)
1936                 noti->layout = NOTIFICATION_LY_ONGOING_PROGRESS;
1937
1938         noti->caller_pkgname = _notification_get_pkgname_by_pid();
1939         noti->group_id = NOTIFICATION_GROUP_ID_NONE;
1940         noti->priv_id = NOTIFICATION_PRIV_ID_NONE;
1941         noti->sound_type = NOTIFICATION_SOUND_TYPE_NONE;
1942         noti->vibration_type = NOTIFICATION_VIBRATION_TYPE_NONE;
1943         noti->led_operation = NOTIFICATION_LED_OP_OFF;
1944         noti->display_applist = NOTIFICATION_DISPLAY_APP_ALL;
1945         /*!
1946          * \NOTE
1947          * Other fields are already initialized with ZERO.
1948          */
1949         return noti;
1950 }
1951
1952 EXPORT_API notification_h notification_new(notification_type_e type,
1953                                            int group_id, int priv_id)
1954 {
1955         return _notification_create(type);
1956 }
1957
1958 EXPORT_API notification_h notification_create(notification_type_e type)
1959 {
1960         return _notification_create(type);
1961 }
1962
1963 EXPORT_API notification_h notification_load(char *pkgname,
1964                                                       int priv_id)
1965 {
1966         int ret = 0;
1967         notification_h noti = NULL;
1968
1969         noti = (notification_h) calloc(1, sizeof(struct _notification));
1970         if (noti == NULL) {
1971                 NOTIFICATION_ERR("NO MEMORY : noti == NULL");
1972                 return NULL;
1973         }
1974
1975         ret = notification_noti_get_by_priv_id(noti, pkgname, priv_id);
1976         if (ret != NOTIFICATION_ERROR_NONE) {
1977                 notification_free(noti);
1978                 return NULL;
1979         }
1980
1981         return noti;
1982 }
1983
1984 EXPORT_API notification_error_e notification_clone(notification_h noti, notification_h *clone)
1985 {
1986         notification_h new_noti = NULL;
1987
1988         if (noti == NULL || clone == NULL) {
1989                 NOTIFICATION_ERR("INVALID PARAMETER.");
1990                 return NOTIFICATION_ERROR_INVALID_DATA;
1991         }
1992
1993         new_noti = (notification_h) calloc(1, sizeof(struct _notification));
1994         if (new_noti == NULL) {
1995                 NOTIFICATION_ERR("NO MEMORY : noti == NULL");
1996                 return NOTIFICATION_ERROR_NO_MEMORY;
1997         }
1998
1999         new_noti->type = noti->type;
2000         new_noti->layout = noti->layout;
2001
2002         new_noti->group_id = noti->group_id;
2003         new_noti->internal_group_id = noti->internal_group_id;
2004         new_noti->priv_id = noti->priv_id;
2005
2006         if(noti->caller_pkgname != NULL) {
2007                 new_noti->caller_pkgname = strdup(noti->caller_pkgname);
2008         } else {
2009                 new_noti->caller_pkgname = _notification_get_pkgname_by_pid();
2010         }
2011         if(noti->launch_pkgname != NULL) {
2012                 new_noti->launch_pkgname = strdup(noti->launch_pkgname);
2013         } else {
2014                 new_noti->launch_pkgname = NULL;
2015         }
2016
2017         if(noti->args != NULL) {
2018                 new_noti->args = bundle_dup(noti->args);
2019         } else {
2020                 new_noti->args = NULL;
2021         }
2022         if(noti->group_args != NULL) {
2023                 new_noti->group_args = bundle_dup(noti->group_args);
2024         } else {
2025                 new_noti->group_args = NULL;
2026         }
2027
2028         if(noti->b_execute_option != NULL) {
2029                 new_noti->b_execute_option = bundle_dup(noti->b_execute_option);
2030         } else {
2031                 new_noti->b_execute_option = NULL;
2032         }
2033         if(noti->b_service_responding != NULL) {
2034                 new_noti->b_service_responding = bundle_dup(noti->b_service_responding);
2035         } else {
2036                 new_noti->b_service_responding = NULL;
2037         }
2038         if(noti->b_service_single_launch != NULL) {
2039                 new_noti->b_service_single_launch = bundle_dup(noti->b_service_single_launch);
2040         } else {
2041                 new_noti->b_service_single_launch = NULL;
2042         }
2043         if(noti->b_service_multi_launch != NULL) {
2044                 new_noti->b_service_multi_launch = bundle_dup(noti->b_service_multi_launch);
2045         } else {
2046                 new_noti->b_service_multi_launch = NULL;
2047         }
2048
2049         new_noti->sound_type = noti->sound_type;
2050         if(noti->sound_path != NULL) {
2051                 new_noti->sound_path = strdup(noti->sound_path);
2052         } else {
2053                 new_noti->sound_path = NULL;
2054         }
2055         new_noti->vibration_type = noti->vibration_type;
2056         if(noti->vibration_path != NULL) {
2057                 new_noti->vibration_path = strdup(noti->vibration_path);
2058         } else {
2059                 new_noti->vibration_path = NULL;
2060         }
2061         new_noti->led_operation = noti->led_operation;
2062         new_noti->led_argb = noti->led_argb;
2063         new_noti->led_on_ms = noti->led_on_ms;
2064         new_noti->led_off_ms = noti->led_off_ms;
2065
2066         if(noti->domain != NULL) {
2067                 new_noti->domain = strdup(noti->domain);
2068         } else {
2069                 new_noti->domain = NULL;
2070         }
2071         if(noti->dir != NULL) {
2072                 new_noti->dir = strdup(noti->dir);
2073         } else {
2074                 new_noti->dir = NULL;
2075         }
2076
2077         if(noti->b_text != NULL) {
2078                 new_noti->b_text = bundle_dup(noti->b_text);
2079         } else {
2080                 new_noti->b_text = NULL;
2081         }
2082         if(noti->b_key != NULL) {
2083                 new_noti->b_key = bundle_dup(noti->b_key);
2084         } else {
2085                 new_noti->b_key = NULL;
2086         }
2087         if(noti->b_format_args != NULL) {
2088                 new_noti->b_format_args = bundle_dup(noti->b_format_args);
2089         } else {
2090                 new_noti->b_format_args = NULL;
2091         }
2092         new_noti->num_format_args = noti->num_format_args;
2093
2094         if(noti->b_image_path != NULL) {
2095                 new_noti->b_image_path = bundle_dup(noti->b_image_path);
2096         } else {
2097                 new_noti->b_image_path = NULL;
2098         }
2099
2100         new_noti->time = noti->time;
2101         new_noti->insert_time = noti->insert_time;
2102
2103         new_noti->flags_for_property = noti->flags_for_property;
2104         new_noti->display_applist = noti->display_applist;
2105
2106         new_noti->progress_size = noti->progress_size;
2107         new_noti->progress_percentage = noti->progress_percentage;
2108
2109         new_noti->app_icon_path = NULL;
2110         new_noti->app_name = NULL;
2111         new_noti->temp_title = NULL;
2112         new_noti->temp_content = NULL;
2113
2114         *clone = new_noti;
2115
2116         return NOTIFICATION_ERROR_NONE;
2117 }
2118
2119
2120 EXPORT_API notification_error_e notification_free(notification_h noti)
2121 {
2122         if (noti == NULL) {
2123                 return NOTIFICATION_ERROR_INVALID_DATA;
2124         }
2125
2126         if (noti->caller_pkgname) {
2127                 free(noti->caller_pkgname);
2128         }
2129         if (noti->launch_pkgname) {
2130                 free(noti->launch_pkgname);
2131         }
2132         if (noti->args) {
2133                 bundle_free(noti->args);
2134         }
2135         if (noti->group_args) {
2136                 bundle_free(noti->group_args);
2137         }
2138
2139         if (noti->b_execute_option) {
2140                 bundle_free(noti->b_execute_option);
2141         }
2142         if (noti->b_service_responding) {
2143                 bundle_free(noti->b_service_responding);
2144         }
2145         if (noti->b_service_single_launch) {
2146                 bundle_free(noti->b_service_single_launch);
2147         }
2148         if (noti->b_service_multi_launch) {
2149                 bundle_free(noti->b_service_multi_launch);
2150         }
2151
2152         if (noti->sound_path) {
2153                 free(noti->sound_path);
2154         }
2155         if (noti->vibration_path) {
2156                 free(noti->vibration_path);
2157         }
2158
2159         if (noti->domain) {
2160                 free(noti->domain);
2161         }
2162         if (noti->dir) {
2163                 free(noti->dir);
2164         }
2165
2166         if (noti->b_text) {
2167                 bundle_free(noti->b_text);
2168         }
2169         if (noti->b_key) {
2170                 bundle_free(noti->b_key);
2171         }
2172         if (noti->b_format_args) {
2173                 bundle_free(noti->b_format_args);
2174         }
2175
2176         if (noti->b_image_path) {
2177                 bundle_free(noti->b_image_path);
2178         }
2179
2180         if (noti->app_icon_path) {
2181                 free(noti->app_icon_path);
2182         }
2183         if (noti->app_name) {
2184                 free(noti->app_name);
2185         }
2186         if (noti->temp_title) {
2187                 free(noti->temp_title);
2188         }
2189         if (noti->temp_content) {
2190                 free(noti->temp_content);
2191         }
2192
2193         free(noti);
2194
2195         return NOTIFICATION_ERROR_NONE;
2196 }
2197
2198 EXPORT_API notification_error_e
2199 notification_resister_changed_cb(void (*changed_cb)
2200                                  (void *data, notification_type_e type),
2201                                  void *user_data)
2202 {
2203         notification_cb_list_s *noti_cb_list_new = NULL;
2204         notification_cb_list_s *noti_cb_list = NULL;
2205
2206         if (changed_cb == NULL) {
2207                 return NOTIFICATION_ERROR_INVALID_DATA;
2208         }
2209         if (notification_ipc_monitor_init() != NOTIFICATION_ERROR_NONE) {
2210                 return NOTIFICATION_ERROR_IO;
2211         }
2212
2213         noti_cb_list_new =
2214             (notification_cb_list_s *) malloc(sizeof(notification_cb_list_s));
2215
2216         noti_cb_list_new->next = NULL;
2217         noti_cb_list_new->prev = NULL;
2218
2219         noti_cb_list_new->cb_type = NOTIFICATION_CB_NORMAL;
2220         noti_cb_list_new->changed_cb = changed_cb;
2221         noti_cb_list_new->detailed_changed_cb = NULL;
2222         noti_cb_list_new->data = user_data;
2223
2224         if (g_notification_cb_list == NULL) {
2225                 g_notification_cb_list = noti_cb_list_new;
2226         } else {
2227                 noti_cb_list = g_notification_cb_list;
2228
2229                 while (noti_cb_list->next != NULL) {
2230                         noti_cb_list = noti_cb_list->next;
2231                 }
2232
2233                 noti_cb_list->next = noti_cb_list_new;
2234                 noti_cb_list_new->prev = noti_cb_list;
2235         }
2236         return NOTIFICATION_ERROR_NONE;
2237 }
2238
2239 EXPORT_API notification_error_e
2240 notification_unresister_changed_cb(void (*changed_cb)
2241                                    (void *data, notification_type_e type))
2242 {
2243         notification_cb_list_s *noti_cb_list = NULL;
2244         notification_cb_list_s *noti_cb_list_prev = NULL;
2245         notification_cb_list_s *noti_cb_list_next = NULL;
2246
2247         noti_cb_list = g_notification_cb_list;
2248
2249         if (changed_cb == NULL) {
2250                 return NOTIFICATION_ERROR_INVALID_DATA;
2251         }
2252         if (noti_cb_list == NULL) {
2253                 return NOTIFICATION_ERROR_INVALID_DATA;
2254         }
2255
2256         while (noti_cb_list->prev != NULL) {
2257                 noti_cb_list = noti_cb_list->prev;
2258         }
2259
2260         do {
2261                 if (noti_cb_list->changed_cb == changed_cb) {
2262                         noti_cb_list_prev = noti_cb_list->prev;
2263                         noti_cb_list_next = noti_cb_list->next;
2264
2265                         if (noti_cb_list_prev == NULL) {
2266                                 g_notification_cb_list = noti_cb_list_next;
2267                         } else {
2268                                 noti_cb_list_prev->next = noti_cb_list_next;
2269                         }
2270
2271                         if (noti_cb_list_next == NULL) {
2272                                 if (noti_cb_list_prev != NULL) {
2273                                         noti_cb_list_prev->next = NULL;
2274                                 }
2275                         } else {
2276                                 noti_cb_list_next->prev = noti_cb_list_prev;
2277                         }
2278
2279                         free(noti_cb_list);
2280
2281                         if (g_notification_cb_list == NULL)
2282                                 notification_ipc_monitor_fini();
2283
2284                         return NOTIFICATION_ERROR_NONE;
2285                 }
2286                 noti_cb_list = noti_cb_list->next;
2287         } while (noti_cb_list != NULL);
2288
2289         return NOTIFICATION_ERROR_INVALID_DATA;
2290 }
2291
2292 EXPORT_API notification_error_e
2293 notification_register_detailed_changed_cb(
2294                 void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op),
2295                 void *user_data)
2296 {
2297         notification_cb_list_s *noti_cb_list_new = NULL;
2298         notification_cb_list_s *noti_cb_list = NULL;
2299
2300         if (detailed_changed_cb == NULL) {
2301                 return NOTIFICATION_ERROR_INVALID_DATA;
2302         }
2303         if (notification_ipc_monitor_init() != NOTIFICATION_ERROR_NONE) {
2304                 return NOTIFICATION_ERROR_IO;
2305         }
2306
2307         noti_cb_list_new =
2308             (notification_cb_list_s *) malloc(sizeof(notification_cb_list_s));
2309
2310         noti_cb_list_new->next = NULL;
2311         noti_cb_list_new->prev = NULL;
2312
2313         noti_cb_list_new->cb_type = NOTIFICATION_CB_DETAILED;
2314         noti_cb_list_new->changed_cb = NULL;
2315         noti_cb_list_new->detailed_changed_cb = detailed_changed_cb;
2316         noti_cb_list_new->data = user_data;
2317
2318         if (g_notification_cb_list == NULL) {
2319                 g_notification_cb_list = noti_cb_list_new;
2320         } else {
2321                 noti_cb_list = g_notification_cb_list;
2322
2323                 while (noti_cb_list->next != NULL) {
2324                         noti_cb_list = noti_cb_list->next;
2325                 }
2326
2327                 noti_cb_list->next = noti_cb_list_new;
2328                 noti_cb_list_new->prev = noti_cb_list;
2329         }
2330         return NOTIFICATION_ERROR_NONE;
2331 }
2332
2333 EXPORT_API notification_error_e
2334 notification_unregister_detailed_changed_cb(
2335                 void (*detailed_changed_cb)(void *data, notification_type_e type, notification_op *op_list, int num_op),
2336                 void *user_data)
2337 {
2338         notification_cb_list_s *noti_cb_list = NULL;
2339         notification_cb_list_s *noti_cb_list_prev = NULL;
2340         notification_cb_list_s *noti_cb_list_next = NULL;
2341
2342         noti_cb_list = g_notification_cb_list;
2343
2344         if (detailed_changed_cb == NULL) {
2345                 return NOTIFICATION_ERROR_INVALID_DATA;
2346         }
2347         if (noti_cb_list == NULL) {
2348                 return NOTIFICATION_ERROR_INVALID_DATA;
2349         }
2350
2351         while (noti_cb_list->prev != NULL) {
2352                 noti_cb_list = noti_cb_list->prev;
2353         }
2354
2355         do {
2356                 if (noti_cb_list->detailed_changed_cb == detailed_changed_cb) {
2357                         noti_cb_list_prev = noti_cb_list->prev;
2358                         noti_cb_list_next = noti_cb_list->next;
2359
2360                         if (noti_cb_list_prev == NULL) {
2361                                 g_notification_cb_list = noti_cb_list_next;
2362                         } else {
2363                                 noti_cb_list_prev->next = noti_cb_list_next;
2364                         }
2365
2366                         if (noti_cb_list_next == NULL) {
2367                                 if (noti_cb_list_prev != NULL) {
2368                                         noti_cb_list_prev->next = NULL;
2369                                 }
2370                         } else {
2371                                 noti_cb_list_next->prev = noti_cb_list_prev;
2372                         }
2373
2374                         free(noti_cb_list);
2375
2376                         if (g_notification_cb_list == NULL)
2377                                 notification_ipc_monitor_fini();
2378
2379                         return NOTIFICATION_ERROR_NONE;
2380                 }
2381                 noti_cb_list = noti_cb_list->next;
2382         } while (noti_cb_list != NULL);
2383
2384         return NOTIFICATION_ERROR_INVALID_DATA;
2385 }
2386
2387 EXPORT_API notification_error_e notification_get_count(notification_type_e type,
2388                                                        const char *pkgname,
2389                                                        int group_id,
2390                                                        int priv_id, int *count)
2391 {
2392         int ret = 0;
2393         int noti_count = 0;
2394
2395         if (count == NULL) {
2396                 return NOTIFICATION_ERROR_INVALID_DATA;
2397         }
2398
2399         ret =
2400             notification_noti_get_count(type, pkgname, group_id, priv_id,
2401                                         &noti_count);
2402         if (ret != NOTIFICATION_ERROR_NONE) {
2403                 return ret;
2404         }
2405
2406         *count = noti_count;
2407
2408         return NOTIFICATION_ERROR_NONE;
2409 }
2410
2411 EXPORT_API notification_error_e notification_get_list(notification_type_e type,
2412                                                       int count,
2413                                                       notification_list_h *list)
2414 {
2415         notification_list_h get_list = NULL;
2416         int ret = 0;
2417
2418         if (list == NULL) {
2419                 return NOTIFICATION_ERROR_INVALID_DATA;
2420         }
2421
2422         ret = notification_noti_get_grouping_list(type, count, &get_list);
2423         if (ret != NOTIFICATION_ERROR_NONE) {
2424                 return ret;
2425         }
2426
2427         *list = get_list;
2428
2429         return NOTIFICATION_ERROR_NONE;
2430 }
2431
2432 EXPORT_API notification_error_e
2433 notification_get_grouping_list(notification_type_e type, int count,
2434                                notification_list_h * list)
2435 {
2436         notification_list_h get_list = NULL;
2437         int ret = 0;
2438
2439         if (list == NULL) {
2440                 return NOTIFICATION_ERROR_INVALID_DATA;
2441         }
2442
2443         ret = notification_noti_get_grouping_list(type, count, &get_list);
2444         if (ret != NOTIFICATION_ERROR_NONE) {
2445                 return ret;
2446         }
2447
2448         *list = get_list;
2449
2450         return NOTIFICATION_ERROR_NONE;
2451 }
2452
2453 EXPORT_API notification_error_e notification_get_detail_list(const char *pkgname,
2454                                                              int group_id,
2455                                                              int priv_id,
2456                                                              int count,
2457                                                              notification_list_h *list)
2458 {
2459         notification_list_h get_list = NULL;
2460         int ret = 0;
2461
2462         if (list == NULL) {
2463                 return NOTIFICATION_ERROR_INVALID_DATA;
2464         }
2465
2466         ret =
2467             notification_noti_get_detail_list(pkgname, group_id, priv_id, count,
2468                                               &get_list);
2469         if (ret != NOTIFICATION_ERROR_NONE) {
2470                 return ret;
2471         }
2472
2473         *list = get_list;
2474
2475         return NOTIFICATION_ERROR_NONE;
2476 }
2477
2478 EXPORT_API notification_error_e notification_free_list(notification_list_h list)
2479 {
2480         notification_list_h cur_list = NULL;
2481         notification_h noti = NULL;
2482
2483         if (list == NULL) {
2484                 return NOTIFICATION_ERROR_INVALID_DATA;
2485         }
2486
2487         cur_list = notification_list_get_head(list);
2488
2489         while (cur_list != NULL) {
2490                 noti = notification_list_get_data(cur_list);
2491                 cur_list = notification_list_remove(cur_list, noti);
2492
2493                 notification_free(noti);
2494         }
2495
2496         return NOTIFICATION_ERROR_NONE;
2497 }
2498
2499 EXPORT_API notification_error_e notification_op_get_data(notification_op *noti_op, notification_op_data_type_e type,
2500                                                        void *data)
2501 {
2502         if (noti_op == NULL || data == NULL) {
2503                 return NOTIFICATION_ERROR_INVALID_DATA;
2504         }
2505
2506         switch (type) {
2507                 case NOTIFICATION_OP_DATA_TYPE:
2508                         *((int*)data) = noti_op->type;
2509                         break;
2510                 case NOTIFICATION_OP_DATA_PRIV_ID:
2511                         *((int*)data) = noti_op->priv_id;
2512                         break;
2513                 case NOTIFICATION_OP_DATA_NOTI:
2514                         *((notification_h *)data) = noti_op->noti;
2515                         break;
2516                 case NOTIFICATION_OP_DATA_EXTRA_INFO_1:
2517                         *((int*)data) = noti_op->extra_info_1;
2518                         break;
2519                 case NOTIFICATION_OP_DATA_EXTRA_INFO_2:
2520                         *((int*)data) = noti_op->extra_info_2;
2521                         break;
2522                 default:
2523                         return NOTIFICATION_ERROR_INVALID_DATA;
2524                         break;
2525         }
2526
2527         return NOTIFICATION_ERROR_NONE;
2528 }
2529
2530 void notification_call_changed_cb(notification_op *op_list, int op_num)
2531 {
2532         notification_cb_list_s *noti_cb_list = NULL;
2533
2534
2535         if (g_notification_cb_list == NULL) {
2536                 return;
2537         }
2538         noti_cb_list = g_notification_cb_list;
2539
2540         while (noti_cb_list->prev != NULL) {
2541                 noti_cb_list = noti_cb_list->prev;
2542         }
2543
2544         if (op_list == NULL) {
2545                 NOTIFICATION_ERR("invalid data");
2546                 return ;
2547         }
2548
2549         while (noti_cb_list != NULL) {
2550                 if (noti_cb_list->cb_type == NOTIFICATION_CB_NORMAL && noti_cb_list->changed_cb) {
2551                         noti_cb_list->changed_cb(noti_cb_list->data,
2552                                                  NOTIFICATION_TYPE_NOTI);
2553                 }
2554                 if (noti_cb_list->cb_type == NOTIFICATION_CB_DETAILED && noti_cb_list->detailed_changed_cb) {
2555                         noti_cb_list->detailed_changed_cb(noti_cb_list->data,
2556                                                  NOTIFICATION_TYPE_NOTI, op_list, op_num);
2557                 }
2558
2559                 noti_cb_list = noti_cb_list->next;
2560         }
2561 }
2562
2563 EXPORT_API int notification_is_service_ready(void)
2564 {
2565         /*
2566          * The notification service is now socket activated so as far
2567          * as clients are concerned it is always ready
2568          */
2569         return 1;
2570 }
2571
2572 EXPORT_API notification_error_e
2573 notification_add_deffered_task(
2574                 void (*deffered_task_cb)(void *data), void *user_data)
2575 {
2576         if (deffered_task_cb == NULL) {
2577                 return NOTIFICATION_ERROR_INVALID_DATA;
2578         }
2579
2580         return notification_ipc_add_deffered_task(deffered_task_cb, user_data);
2581 }
2582
2583 EXPORT_API notification_error_e
2584 notification_del_deffered_task(
2585                 void (*deffered_task_cb)(void *data))
2586 {
2587         if (deffered_task_cb == NULL) {
2588                 return NOTIFICATION_ERROR_INVALID_DATA;
2589         }
2590
2591         return notification_ipc_del_deffered_task(deffered_task_cb);
2592 }
2593
2594 /* notification_set_icon will be removed */
2595 EXPORT_API notification_error_e notification_set_icon(notification_h noti,
2596                                                       const char *icon_path)
2597 {
2598         int ret_err = NOTIFICATION_ERROR_NONE;
2599
2600         ret_err =
2601             notification_set_image(noti, NOTIFICATION_IMAGE_TYPE_ICON,
2602                                    icon_path);
2603
2604         return ret_err;
2605 }
2606
2607 /* notification_get_icon will be removed */
2608 EXPORT_API notification_error_e notification_get_icon(notification_h noti,
2609                                                       char **icon_path)
2610 {
2611         int ret_err = NOTIFICATION_ERROR_NONE;
2612         char *ret_image_path = NULL;
2613
2614         ret_err =
2615             notification_get_image(noti, NOTIFICATION_IMAGE_TYPE_ICON,
2616                                    &ret_image_path);
2617
2618         if (ret_err == NOTIFICATION_ERROR_NONE && icon_path != NULL) {
2619                 *icon_path = ret_image_path;
2620
2621                 //NOTIFICATION_DBG("Get icon : %s", *icon_path);
2622         }
2623
2624         return ret_err;
2625 }
2626
2627 EXPORT_API notification_error_e notification_set_title(notification_h noti,
2628                                                        const char *title,
2629                                                        const char *loc_title)
2630 {
2631         int noti_err = NOTIFICATION_ERROR_NONE;
2632
2633         noti_err = notification_set_text(noti, NOTIFICATION_TEXT_TYPE_TITLE,
2634                                          title, loc_title,
2635                                          NOTIFICATION_VARIABLE_TYPE_NONE);
2636
2637         return noti_err;
2638 }
2639
2640 EXPORT_API notification_error_e notification_get_title(notification_h noti,
2641                                                        char **title,
2642                                                        char **loc_title)
2643 {
2644         int noti_err = NOTIFICATION_ERROR_NONE;
2645         char *ret_text = NULL;
2646
2647         noti_err =
2648             notification_get_text(noti, NOTIFICATION_TEXT_TYPE_TITLE,
2649                                   &ret_text);
2650
2651         if (title != NULL) {
2652                 *title = ret_text;
2653         }
2654
2655         if (loc_title != NULL) {
2656                 *loc_title = NULL;
2657         }
2658
2659         return noti_err;
2660 }
2661
2662 EXPORT_API notification_error_e notification_set_content(notification_h noti,
2663                                                          const char *content,
2664                                                          const char *loc_content)
2665 {
2666         int noti_err = NOTIFICATION_ERROR_NONE;
2667
2668         noti_err = notification_set_text(noti, NOTIFICATION_TEXT_TYPE_CONTENT,
2669                                          content, loc_content,
2670                                          NOTIFICATION_VARIABLE_TYPE_NONE);
2671
2672         return noti_err;
2673 }
2674
2675 EXPORT_API notification_error_e notification_get_content(notification_h noti,
2676                                                          char **content,
2677                                                          char **loc_content)
2678 {
2679         int noti_err = NOTIFICATION_ERROR_NONE;
2680         char *ret_text = NULL;
2681
2682         noti_err =
2683             notification_get_text(noti, NOTIFICATION_TEXT_TYPE_CONTENT,
2684                                   &ret_text);
2685
2686         if (content != NULL) {
2687                 *content = ret_text;
2688         }
2689
2690         if (loc_content != NULL) {
2691                 *loc_content = NULL;
2692         }
2693
2694         return noti_err;
2695
2696 #if 0
2697         ret =
2698             vconf_get_bool
2699             (VCONFKEY_SETAPPL_STATE_TICKER_NOTI_DISPLAY_CONTENT_BOOL, &boolval);
2700
2701         if (ret == -1 || boolval == 0) {
2702                 if (content != NULL && noti->default_content != NULL) {
2703                         *content = noti->default_content;
2704                 }
2705
2706                 if (loc_content != NULL && noti->loc_default_content != NULL) {
2707                         *loc_content = noti->loc_default_content;
2708                 }
2709         }
2710 #endif
2711 }
2712
2713 EXPORT_API notification_error_e notification_set_args(notification_h noti,
2714                                                       bundle * args,
2715                                                       bundle * group_args)
2716 {
2717         if (noti == NULL || args == NULL) {
2718                 return NOTIFICATION_ERROR_INVALID_DATA;
2719         }
2720
2721         if (noti->args) {
2722                 bundle_free(noti->args);
2723         }
2724
2725         noti->args = bundle_dup(args);
2726
2727         if (noti->group_args) {
2728                 bundle_free(noti->group_args);
2729                 noti->group_args = NULL;
2730         }
2731
2732         if (group_args != NULL) {
2733                 noti->group_args = bundle_dup(group_args);
2734         }
2735
2736         return NOTIFICATION_ERROR_NONE;
2737 }
2738
2739 EXPORT_API notification_error_e notification_get_args(notification_h noti,
2740                                                       bundle ** args,
2741                                                       bundle ** group_args)
2742 {
2743         if (noti == NULL || args == NULL) {
2744                 return NOTIFICATION_ERROR_INVALID_DATA;
2745         }
2746
2747         if (noti->args) {
2748                 *args = noti->args;
2749         } else {
2750                 *args = NULL;
2751         }
2752
2753         if (group_args != NULL && noti->group_args) {
2754                 *group_args = noti->group_args;
2755         }
2756
2757         return NOTIFICATION_ERROR_NONE;
2758 }
2759
2760 EXPORT_API notification_error_e notification_delete_group_by_group_id(const char *pkgname,
2761                                                                       notification_type_e type,
2762                                                                       int group_id)
2763 {
2764         int ret = 0;
2765         char *caller_pkgname = NULL;
2766
2767         if (pkgname == NULL) {
2768                 caller_pkgname = _notification_get_pkgname_by_pid();
2769         } else {
2770                 caller_pkgname = strdup(pkgname);
2771         }
2772
2773         ret = notification_ipc_request_delete_multiple(type, caller_pkgname);
2774         if (ret != NOTIFICATION_ERROR_NONE) {
2775                 if (caller_pkgname) {
2776                         free(caller_pkgname);
2777                 }
2778                 return ret;
2779         }
2780
2781         if (caller_pkgname) {
2782                 free(caller_pkgname);
2783         }
2784         return NOTIFICATION_ERROR_NONE;
2785 }
2786
2787 EXPORT_API notification_error_e notification_delete_group_by_priv_id(const char *pkgname,
2788                                                                      notification_type_e type,
2789                                                                      int priv_id)
2790 {
2791         int ret = 0;
2792         char *caller_pkgname = NULL;
2793
2794         if (pkgname == NULL) {
2795                 caller_pkgname = _notification_get_pkgname_by_pid();
2796         } else {
2797                 caller_pkgname = strdup(pkgname);
2798         }
2799
2800         ret = notification_ipc_request_delete_single(type, caller_pkgname, priv_id);
2801         if (ret != NOTIFICATION_ERROR_NONE) {
2802                 if (caller_pkgname) {
2803                         free(caller_pkgname);
2804                 }
2805                 return ret;
2806         }
2807
2808         if (caller_pkgname) {
2809                 free(caller_pkgname);
2810         }
2811         return NOTIFICATION_ERROR_NONE;
2812 }
2813
2814 EXPORT_API notification_error_e notification_wait_response(notification_h noti,
2815                                                            int timeout,
2816                                                            int *respi,
2817                                                            char **respc)
2818 {
2819         bundle *b, *bc = NULL;
2820         pid_t tid;
2821         const char *tid_c;
2822         int sock_fd, msg_fd;
2823         char *sock_path;
2824         struct sockaddr_un sock_addr;
2825         char msg_buffer[1024];
2826         ssize_t msg_size;
2827         struct timeval timeout_tv;
2828         char *resp;
2829
2830         memset(msg_buffer, 0, sizeof(msg_buffer));
2831
2832     /* a response packet *must* have an execute option TYPE_RESPONDING
2833             with an associated bundle.
2834             If its bundle does not already contain a "tid" hint (which
2835             complex applications such as xwalk may overwrite), we will
2836             try to find the TID and set it in the bundle ourselves. */
2837         notification_get_execute_option (noti, NOTIFICATION_EXECUTE_TYPE_RESPONDING,
2838         NULL, &b);
2839
2840         if (b == NULL)
2841                 return NOTIFICATION_ERROR_INVALID_DATA;
2842
2843         tid_c = bundle_get_val(b, "tid");
2844         if (tid_c == NULL) {
2845                 tid = syscall(SYS_gettid);
2846                 asprintf((char **)&tid_c, "%d", tid);
2847                 bc = bundle_dup(b);
2848                 bundle_add(bc, "tid", tid_c);
2849                 notification_set_execute_option (noti, NOTIFICATION_EXECUTE_TYPE_RESPONDING,
2850                                                  NULL, NULL, bc);
2851                 bundle_free(bc);
2852                 notification_update(noti);
2853         }
2854
2855         sock_fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
2856         if (sock_fd == -1)
2857                 return NOTIFICATION_ERROR_NO_MEMORY;
2858
2859         sock_addr.sun_family = AF_UNIX;
2860         asprintf(&sock_path, "/tmp/.notification-%s", tid_c);
2861         strncpy(sock_addr.sun_path, sock_path, sizeof(sock_addr.sun_path) - 1);
2862         if (bind(sock_fd, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) == -1) {
2863                 close(sock_fd);
2864                 free(sock_path);
2865                 free((char *)tid_c);
2866                 return NOTIFICATION_ERROR_NO_MEMORY;
2867         }
2868
2869         if (timeout > 0) {
2870                 timeout_tv.tv_sec = timeout;
2871                 timeout_tv.tv_usec = 0;
2872                 setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout_tv, sizeof(timeout_tv));
2873                 setsockopt(sock_fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout_tv, sizeof(timeout_tv));
2874         }
2875
2876         listen(sock_fd, 1);
2877         msg_fd = accept(sock_fd, NULL, 0);
2878         do {
2879                 msg_size = read(msg_fd, msg_buffer, 1024);
2880         } while (msg_size > 0);
2881
2882         resp = strtok(msg_buffer, "\n");
2883         if (resp) {
2884                 *respi = atoi(resp);
2885                 if (respc != NULL) {
2886                         resp = strtok(NULL, "\n");
2887                         if (resp)
2888                                 *respc = resp;
2889                         else
2890                                 *respc = NULL;
2891                 }
2892         } else {
2893                 *respi = 0;
2894                 if (respc != NULL)
2895                         *respc = NULL;
2896         }
2897
2898         close(sock_fd);
2899         unlink(sock_path);
2900         free(sock_path);
2901         free((char *)tid_c);
2902
2903         return NOTIFICATION_ERROR_NONE;
2904 }
2905
2906 EXPORT_API notification_error_e notification_send_response(notification_h noti,
2907                                                            int respi,
2908                                                            char *respc)
2909 {
2910         bundle *b = NULL;
2911         notification_h notic;
2912         int notic_id;
2913         char *notic_pkgname;
2914         int tid;
2915         const char *tid_c;
2916         int sock_fd;
2917         char *sock_path;
2918         struct sockaddr_un sock_addr;
2919         char *msg_buffer;
2920
2921         notification_get_id(noti, NULL, &notic_id);
2922         notification_get_pkgname(noti, &notic_pkgname);
2923         notic = notification_load(notic_pkgname, notic_id);
2924         notification_get_execute_option (notic, NOTIFICATION_EXECUTE_TYPE_RESPONDING,
2925         NULL, &b);
2926
2927         if (b == NULL)
2928                 return NOTIFICATION_ERROR_INVALID_DATA;
2929
2930         tid_c = bundle_get_val(b, "tid");
2931         if (tid_c == NULL)
2932                 return NOTIFICATION_ERROR_INVALID_DATA;
2933         tid = atoi(tid_c);
2934
2935         sock_fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
2936         if (sock_fd == -1)
2937                 return NOTIFICATION_ERROR_NO_MEMORY;
2938
2939         sock_addr.sun_family = AF_UNIX;
2940         asprintf(&sock_path, "/tmp/.notification-%d", tid);
2941         strncpy(sock_addr.sun_path, sock_path, sizeof(sock_addr.sun_path) - 1);
2942         if (connect(sock_fd, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) == -1) {
2943                 close(sock_fd);
2944                 free(sock_path);
2945                 return NOTIFICATION_ERROR_NO_MEMORY;
2946         }
2947
2948         if (respc)
2949                 asprintf(&msg_buffer, "%d\n%s\n", respi, respc);
2950         else
2951                 asprintf(&msg_buffer, "%d\n", respi);
2952         write(sock_fd, msg_buffer, strlen(msg_buffer) + 1);
2953
2954         close(sock_fd);
2955         free(sock_path);
2956         free(msg_buffer);
2957
2958         return NOTIFICATION_ERROR_NONE;
2959 }