Remove ail dependancy
[platform/core/api/notification.git] / src / notification.c
1 /*
2  * Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <unistd.h>
21 #include <fcntl.h>
22 #include <libintl.h>
23 #include <dbus/dbus.h>
24 #include <dbus/dbus-glib-lowlevel.h>
25
26 #include <app.h>
27 #include <app_internal.h>
28 #include <app_manager.h>
29 #include <app_control_internal.h>
30 #include <package_manager.h>
31 #include <aul.h>
32 #include <appsvc.h>
33 #include <tizen.h>
34 #include <vconf-keys.h>
35 #include <vconf.h>
36
37 #include <notification.h>
38 #include <notification_list.h>
39 #include <notification_debug.h>
40 #include <notification_private.h>
41 #include <notification_noti.h>
42 #include <notification_ongoing.h>
43 #include <notification_group.h>
44 #include <notification_ipc.h>
45 #include <notification_internal.h>
46
47 static void (*posted_toast_message_cb) (void *data);
48
49 #define NOTI_TEXT_RESULT_LEN 2048
50 #define NOTI_PKGNAME_LEN        512
51
52 char *notification_get_pkgname_by_pid(void)
53 {
54         char pkgname[NOTI_PKGNAME_LEN + 1] = { 0, };
55         int pid = 0, ret = AUL_R_OK;
56         int fd;
57         char  *dup_pkgname;
58         char buf[NOTI_PKGNAME_LEN + 1] = { 0, };
59
60         pid = getpid();
61
62         ret = aul_app_get_pkgname_bypid(pid, pkgname, sizeof(pkgname));
63         if (ret != AUL_R_OK) {
64
65                 snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
66
67                 fd = open(buf, O_RDONLY);
68                 if (fd < 0)
69                         return NULL;
70
71                 ret = read(fd, pkgname, sizeof(pkgname) - 1);
72                 close(fd);
73
74                 if (ret <= 0)
75                         return NULL;
76
77                 pkgname[ret] = '\0';
78                 /*!
79                  * \NOTE
80                  * "ret" is not able to be larger than "sizeof(pkgname) - 1",
81                  * if the system is not going wrong.
82                  */
83         } else {
84                 if (strlen(pkgname) <= 0)
85                         return NULL;
86         }
87
88         dup_pkgname = strdup(pkgname);
89         if (!dup_pkgname)
90                 NOTIFICATION_ERR("Heap: %d\n", errno);
91
92         return dup_pkgname;
93 }
94
95 EXPORT_API int notification_set_image(notification_h noti,
96                                                        notification_image_type_e type,
97                                                        const char *image_path)
98 {
99         bundle *b = NULL;
100         char buf_key[32] = { 0, };
101         char *ret_val = NULL;
102
103         /* Check noti and image_path are valid data */
104         if (noti == NULL || image_path == NULL)
105                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
106
107         /* Check image type is valid type */
108         if (type <= NOTIFICATION_IMAGE_TYPE_NONE
109             || type >= NOTIFICATION_IMAGE_TYPE_MAX)
110                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
111
112         /* Check image path bundle is exist */
113         if (noti->b_image_path) {
114                 /* If image path bundle is exist, store local bundle value */
115                 b = noti->b_image_path;
116
117                 /* Set image type to key as char string type */
118                 snprintf(buf_key, sizeof(buf_key), "%d", type);
119
120                 /* Get value using key */
121                 bundle_get_str(b, buf_key, &ret_val);
122                 if (ret_val != NULL)
123                         /* If key is exist, remove this value to store new image path */
124                         bundle_del(b, buf_key);
125
126                 /* Add new image path with type key */
127                 bundle_add_str(b, buf_key, image_path);
128         } else {
129                 /* If image path bundle is not exist, create new one */
130                 b = bundle_create();
131
132                 /* Set image type to key as char string type */
133                 snprintf(buf_key, sizeof(buf_key), "%d", type);
134
135                 /* Add new image path with type key */
136                 bundle_add_str(b, buf_key, image_path);
137
138                 /* Save to image path bundle */
139                 noti->b_image_path = b;
140         }
141
142         return NOTIFICATION_ERROR_NONE;
143 }
144
145 EXPORT_API int notification_get_image(notification_h noti,
146                                                        notification_image_type_e type,
147                                                        char **image_path)
148 {
149         bundle *b = NULL;
150         char buf_key[32] = { 0, };
151         char *ret_val = NULL;
152
153         /* Check noti and image_path is valid data */
154         if (noti == NULL || image_path == NULL)
155                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
156
157         /* Check image type is valid data */
158         if (type <= NOTIFICATION_IMAGE_TYPE_NONE
159             || type >= NOTIFICATION_IMAGE_TYPE_MAX)
160                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
161
162         /* Check image path bundle exist */
163         if (noti->b_image_path) {
164                 /* If image path bundle exist, store local bundle data */
165                 b = noti->b_image_path;
166
167                 /* Set image type to key as char string type */
168                 snprintf(buf_key, sizeof(buf_key), "%d", type);
169
170                 /* Get value of key */
171                 bundle_get_str(b, buf_key, &ret_val);
172
173                 *image_path = ret_val;
174         } else {
175                 /* If image path bundle does not exist, image path is NULL */
176                 *image_path = NULL;
177         }
178
179         /* If image path is NULL and type is ICON, icon path set from AIL */
180         /* order : user icon -> launch_pkgname icon -> caller_pkgname icon -> service app icon */
181         if (*image_path == NULL && type == NOTIFICATION_IMAGE_TYPE_ICON) {
182                 /* Check App icon path is already set */
183                 if (noti->app_icon_path != NULL)
184                         /* image path will be app icon path */
185                         *image_path = noti->app_icon_path;
186                 else
187                         *image_path = NULL;
188         }
189
190         return NOTIFICATION_ERROR_NONE;
191 }
192
193 EXPORT_API int notification_set_time(notification_h noti, time_t input_time)
194 {
195         /* Check noti is valid data */
196         if (noti == NULL)
197                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
198
199         if (input_time == 0)
200                 /* If input time is 0, set current time */
201                 noti->time = time(NULL);
202         else
203                 /* save input time */
204                 noti->time = input_time;
205
206         return NOTIFICATION_ERROR_NONE;
207 }
208
209 EXPORT_API int notification_get_time(notification_h noti, time_t *ret_time)
210 {
211         /* Check noti and time is valid data */
212         if (noti == NULL || ret_time == NULL)
213                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
214
215         /* Set time infomation */
216         *ret_time = noti->time;
217
218         return NOTIFICATION_ERROR_NONE;
219 }
220
221 EXPORT_API int notification_get_insert_time(notification_h noti,
222                 time_t *ret_time)
223 {
224         /* Check noti and ret_time is valid data */
225         if (noti == NULL || ret_time == NULL)
226                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
227
228         /* Set insert time information */
229         *ret_time = noti->insert_time;
230
231         return NOTIFICATION_ERROR_NONE;
232 }
233
234 EXPORT_API int notification_set_text(notification_h noti,
235                 notification_text_type_e type, const char *text,
236                 const char *key, int args_type, ...)
237 {
238         bundle *b = NULL;
239         char buf_key[32] = { 0, };
240         char buf_val[1024] = { 0, };
241         char *ret_val = NULL;
242         va_list var_args;
243         notification_variable_type_e var_type;
244         int num_args = 0;
245         int noti_err = NOTIFICATION_ERROR_NONE;
246         int var_value_int = 0;
247         double var_value_double = 0.0;
248         char *var_value_string = NULL;
249         notification_count_pos_type_e var_value_count =
250             NOTIFICATION_COUNT_POS_NONE;
251
252         /* Check noti is valid data */
253         if (noti == NULL)
254                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
255
256         /* Check text type is valid type */
257         if (type <= NOTIFICATION_TEXT_TYPE_NONE
258             || type >= NOTIFICATION_TEXT_TYPE_MAX)
259                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
260
261         /* Check text bundle exist */
262         if (text != NULL) {
263                 if (noti->b_text != NULL) {
264                         /* If text bundle exist, store local bundle data */
265                         b = noti->b_text;
266
267                         /* Make type to key as char string */
268                         snprintf(buf_key, sizeof(buf_key), "%d", type);
269
270                         /* Get value using type key */
271                         bundle_get_str(b, buf_key, &ret_val);
272
273                         if (ret_val != NULL)
274                                 /* If value exist, remove this to add new value */
275                                 bundle_del(b, buf_key);
276
277                         snprintf(buf_val, sizeof(buf_val), "%s", text);
278
279                         /* Add new text value */
280                         bundle_add_str(b, buf_key, buf_val);
281                 } else {
282                         /* If text bundle does not exist, create new one */
283                         b = bundle_create();
284
285                         /* Make type to key as char string */
286                         snprintf(buf_key, sizeof(buf_key), "%d", type);
287
288                         snprintf(buf_val, sizeof(buf_val), "%s", text);
289
290                         /* Add new text value */
291                         bundle_add_str(b, buf_key, buf_val);
292
293                         /* Save text bundle */
294                         noti->b_text = b;
295                 }
296         } else {
297                 /* Reset if text is NULL */
298                 if (noti->b_text != NULL) {
299                         /* If text bundle exist, store local bundle data */
300                         b = noti->b_text;
301
302                         /* Make type to key as char string */
303                         snprintf(buf_key, sizeof(buf_key), "%d", type);
304
305                         /* Get value using type key */
306                         bundle_get_str(b, buf_key, &ret_val);
307                         if (ret_val != NULL)
308                                 /* If value exist, remove this */
309                                 bundle_del(b, buf_key);
310                 }
311         }
312
313         /* Save key if key is valid data */
314         if (key != NULL) {
315                 /* Check key bundle exist */
316                 if (noti->b_key != NULL) {
317                         /* If key bundle exist,  store local bundle data */
318                         b = noti->b_key;
319
320                         /* Make type to key as char string */
321                         snprintf(buf_key, sizeof(buf_key), "%d", type);
322
323                         /* Get value using type key */
324                         bundle_get_str(b, buf_key, &ret_val);
325                         if (ret_val != NULL)
326                                 /* If value exist, remove this to add new value */
327                                 bundle_del(b, buf_key);
328
329                         snprintf(buf_val, sizeof(buf_val), "%s", key);
330
331                         /* Add new key value */
332                         bundle_add_str(b, buf_key, buf_val);
333                 } else {
334                         /* If key bundle does not exist, create new one */
335                         b = bundle_create();
336
337                         /* Make type to key as char string */
338                         snprintf(buf_key, sizeof(buf_key), "%d", type);
339
340                         snprintf(buf_val, sizeof(buf_val), "%s", key);
341
342                         /* Add new key value */
343                         bundle_add_str(b, buf_key, buf_val);
344
345                         /* Save key bundle */
346                         noti->b_key = b;
347                 }
348         } else {
349                 /* Reset if key is NULL */
350                 if (noti->b_key != NULL) {
351                         /* If key bundle exist,  store local bundle data */
352                         b = noti->b_key;
353
354                         /* Make type to key as char string */
355                         snprintf(buf_key, sizeof(buf_key), "%d", type);
356
357                         /* Get value using type key */
358                         bundle_get_str(b, buf_key, &ret_val);
359                         if (ret_val != NULL)
360                                 /* If value exist, remove this */
361                                 bundle_del(b, buf_key);
362                 }
363         }
364
365         if (noti->b_format_args != NULL)
366                 b = noti->b_format_args;
367         else
368                 b = bundle_create();
369
370         va_start(var_args, args_type);
371
372         var_type = args_type;
373         num_args = 0;
374
375         while (var_type != NOTIFICATION_VARIABLE_TYPE_NONE) {
376                 /* Type */
377                 snprintf(buf_key, sizeof(buf_key), "%dtype%d", type, num_args);
378                 snprintf(buf_val, sizeof(buf_val), "%d", var_type);
379
380                 bundle_get_str(b, buf_key, &ret_val);
381                 if (ret_val != NULL)
382                         bundle_del(b, buf_key);
383
384                 bundle_add_str(b, buf_key, buf_val);
385
386                 switch (var_type) {
387                 case NOTIFICATION_VARIABLE_TYPE_INT:
388                         var_value_int = va_arg(var_args, int);
389
390                         /* Value */
391                         snprintf(buf_key, sizeof(buf_key), "%dvalue%d", type,
392                                  num_args);
393                         snprintf(buf_val, sizeof(buf_val), "%d", var_value_int);
394
395                         bundle_get_str(b, buf_key, &ret_val);
396                         if (ret_val != NULL)
397                                 bundle_del(b, buf_key);
398
399                         bundle_add_str(b, buf_key, buf_val);
400                         break;
401
402                 case NOTIFICATION_VARIABLE_TYPE_DOUBLE:
403                         var_value_double = va_arg(var_args, double);
404
405                         /* Value */
406                         snprintf(buf_key, sizeof(buf_key), "%dvalue%d", type,
407                                  num_args);
408                         snprintf(buf_val, sizeof(buf_val), "%.2f",
409                                  var_value_double);
410
411                         bundle_get_str(b, buf_key, &ret_val);
412                         if (ret_val != NULL)
413                                 bundle_del(b, buf_key);
414
415                         bundle_add_str(b, buf_key, buf_val);
416                         break;
417
418                 case NOTIFICATION_VARIABLE_TYPE_STRING:
419                         var_value_string = va_arg(var_args, char *);
420
421                         /* Value */
422                         snprintf(buf_key, sizeof(buf_key), "%dvalue%d", type,
423                                  num_args);
424                         snprintf(buf_val, sizeof(buf_val), "%s",
425                                  var_value_string);
426
427                         bundle_get_str(b, buf_key, &ret_val);
428                         if (ret_val != NULL)
429                                 bundle_del(b, buf_key);
430
431                         bundle_add_str(b, buf_key, buf_val);
432                         break;
433
434                 case NOTIFICATION_VARIABLE_TYPE_COUNT:
435                         var_value_count =
436                             va_arg(var_args, notification_count_pos_type_e);
437
438                         /* Value */
439                         snprintf(buf_key, sizeof(buf_key), "%dvalue%d", type,
440                                  num_args);
441                         snprintf(buf_val, sizeof(buf_val), "%d",
442                                  var_value_count);
443
444                         bundle_get_str(b, buf_key, &ret_val);
445                         if (ret_val != NULL)
446                                 bundle_del(b, buf_key);
447
448                         bundle_add_str(b, buf_key, buf_val);
449                         break;
450
451                 default:
452                         NOTIFICATION_ERR("Error. invalid variable type. : %d",
453                                          var_type);
454                         noti_err = NOTIFICATION_ERROR_INVALID_PARAMETER;
455                         break;
456                 }
457
458                 num_args++;
459                 var_type = va_arg(var_args, notification_variable_type_e);
460         }
461         va_end(var_args);
462
463         if (noti_err == NOTIFICATION_ERROR_NONE)
464                 noti->num_format_args = num_args;
465         else
466                 noti->num_format_args = 0;
467
468         snprintf(buf_key, sizeof(buf_key), "num%d", type);
469         snprintf(buf_val, sizeof(buf_val), "%d", noti->num_format_args);
470
471         bundle_get_str(b, buf_key, &ret_val);
472         if (ret_val != NULL)
473                 bundle_del(b, buf_key);
474
475         bundle_add_str(b, buf_key, buf_val);
476
477         noti->b_format_args = b;
478
479         return noti_err;
480 }
481
482 EXPORT_API int notification_get_text(notification_h noti,
483                                                       notification_text_type_e type,
484                                                       char **text)
485 {
486         bundle *b = NULL;
487         char buf_key[32] = { 0, };
488         char *ret_val = NULL;
489         char *get_str = NULL;
490         notification_text_type_e check_type = NOTIFICATION_TEXT_TYPE_NONE;
491         /* int display_option_flag = 0; */
492
493         char *temp_str = NULL;
494         char *translated_str = NULL;
495         char result_str[NOTI_TEXT_RESULT_LEN] = { 0, };
496         char buf_str[1024] = { 0, };
497         int num_args = 0;
498         notification_variable_type_e ret_var_type = 0;
499         int ret_variable_int = 0;
500         double ret_variable_double = 0.0;
501         int src_len = 0;
502         int max_len = 0;
503
504         /* Check noti is valid data */
505         if (noti == NULL || text == NULL)
506                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
507
508         /* Check text type is valid type */
509         if (type <= NOTIFICATION_TEXT_TYPE_NONE
510             || type >= NOTIFICATION_TEXT_TYPE_MAX)
511                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
512
513
514         /* Check key */
515         if (noti->b_key != NULL) {
516                 b = noti->b_key;
517
518                 /* Get text domain and dir */
519                 /* _notification_get_text_domain(noti); */
520
521                 snprintf(buf_key, sizeof(buf_key), "%d", type);
522
523                 bundle_get_str(b, buf_key, &ret_val);
524                 if (ret_val != NULL && noti->domain != NULL
525                     && noti->dir != NULL) {
526                         /* Get application string */
527                         bindtextdomain(noti->domain, noti->dir);
528
529                         get_str = dgettext(noti->domain, ret_val);
530                 } else if (ret_val != NULL) {
531                         /* Get system string */
532                         get_str = dgettext("sys_string", ret_val);
533                 } else {
534                         get_str = NULL;
535                 }
536         }
537
538         if (get_str == NULL && noti->b_text != NULL) {
539                 b = noti->b_text;
540                 /* Get basic text */
541                 snprintf(buf_key, sizeof(buf_key), "%d", type);
542
543                 bundle_get_str(b, buf_key, &get_str);
544         }
545
546         check_type = type;
547
548         if (get_str != NULL) {
549                 /* Get number format args */
550                 b = noti->b_format_args;
551                 noti->num_format_args = 0;
552
553                 if (b != NULL) {
554                         snprintf(buf_key, sizeof(buf_key), "num%d", check_type);
555                         bundle_get_str(b, buf_key, &ret_val);
556                         if (ret_val != NULL)
557                                 noti->num_format_args = atoi(ret_val);
558                 }
559
560                 if (noti->num_format_args == 0) {
561                         *text = (char *)get_str;
562                 } else {
563                         /* Check first variable is count, LEFT pos */
564                         snprintf(buf_key, sizeof(buf_key), "%dtype%d",
565                                  check_type, num_args);
566                         bundle_get_str(b, buf_key, &ret_val);
567                         if (ret_val != NULL)
568                                 ret_var_type = atoi(ret_val);
569
570                         if (ret_var_type == NOTIFICATION_VARIABLE_TYPE_COUNT) {
571                                 /* Get var Value */
572                                 snprintf(buf_key, sizeof(buf_key), "%dvalue%d",
573                                          check_type, num_args);
574                                 bundle_get_str(b, buf_key, &ret_val);
575                                 if (ret_val != NULL)
576                                         ret_variable_int = atoi(ret_val);
577
578                                 if (ret_variable_int ==
579                                     NOTIFICATION_COUNT_POS_LEFT) {
580                                         notification_get_count(noti->type,
581                                                         noti->caller_pkgname,
582                                                         noti->group_id,
583                                                         noti->priv_id,
584                                                         &ret_variable_int);
585                                         snprintf(buf_str, sizeof(buf_str),
586                                                  "%d ", ret_variable_int);
587
588                                         src_len = strlen(result_str);
589                                         max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
590
591                                         strncat(result_str, buf_str,
592                                                         max_len);
593                                         num_args++;
594                                 }
595                         }
596
597                         /* Check variable IN pos */
598                         for (temp_str = (char *)get_str; *temp_str != '\0';
599                              temp_str++) {
600                                 if (*temp_str != '%') {
601                                         strncat(result_str, temp_str, 1);
602                                 } else {
603                                         if (*(temp_str + 1) == '%') {
604                                                 strncat(result_str, temp_str,
605                                                         1);
606                                         } else if (*(temp_str + 1) == 'd') {
607                                                 /* Get var Type */
608                                                 ret_variable_int = 0;
609
610                                                 snprintf(buf_key,
611                                                          sizeof(buf_key),
612                                                          "%dtype%d", check_type,
613                                                          num_args);
614                                                 bundle_get_str(b, buf_key, &ret_val);
615                                                 if (ret_val != NULL)
616                                                         ret_var_type = atoi(ret_val);
617
618                                                 if (ret_var_type ==
619                                                     NOTIFICATION_VARIABLE_TYPE_COUNT) {
620                                                         /* Get notification count */
621                                                         notification_get_count(noti->type,
622                                                                         noti->caller_pkgname,
623                                                                         noti->group_id,
624                                                                         noti->priv_id,
625                                                                         &ret_variable_int);
626                                                 } else {
627                                                         /* Get var Value */
628                                                         snprintf(buf_key,
629                                                                  sizeof(buf_key),
630                                                                  "%dvalue%d",
631                                                                  check_type,
632                                                                  num_args);
633                                                         bundle_get_str(b, buf_key, &ret_val);
634                                                         if (ret_val != NULL)
635                                                                 ret_variable_int = atoi(ret_val);
636                                                 }
637
638                                                 snprintf(buf_str,
639                                                          sizeof(buf_str), "%d",
640                                                          ret_variable_int);
641
642                                                 src_len = strlen(result_str);
643                                                 max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
644
645                                                 strncat(result_str, buf_str,
646                                                                 max_len);
647
648                                                 temp_str++;
649
650                                                 num_args++;
651                                         } else if (*(temp_str + 1) == 's') {
652                                                 /* Get var Value */
653                                                 snprintf(buf_key,
654                                                          sizeof(buf_key),
655                                                          "%dvalue%d",
656                                                          check_type, num_args);
657                                                 bundle_get_str(b, buf_key, &ret_val);
658
659                                                 if (ret_val != NULL && noti->domain != NULL     && noti->dir != NULL) {
660                                                         /* Get application string */
661                                                         bindtextdomain(noti->domain, noti->dir);
662                                                         translated_str = dgettext(noti->domain, ret_val);
663                                                         NOTIFICATION_INFO("translated_str[%s]", translated_str);
664                                                 } else if (ret_val != NULL) {
665                                                         /* Get system string */
666                                                         translated_str = dgettext("sys_string", ret_val);
667                                                         NOTIFICATION_INFO("translated_str[%s]", translated_str);
668                                                 } else {
669                                                         translated_str = NULL;
670                                                 }
671
672                                                 if (translated_str != NULL) {
673                                                         strncpy(buf_str, translated_str, sizeof(buf_str) - 1);
674                                                         src_len = strlen(result_str);
675                                                         max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
676                                                         strncat(result_str, buf_str, max_len);
677                                                 }
678                                                 temp_str++;
679                                                 num_args++;
680                                         } else if (*(temp_str + 1) == 'f') {
681                                                 /* Get var Value */
682                                                 snprintf(buf_key,
683                                                          sizeof(buf_key),
684                                                          "%dvalue%d",
685                                                          check_type, num_args);
686                                                 bundle_get_str(b, buf_key, &ret_val);
687                                                 if (ret_val != NULL)
688                                                         ret_variable_double = atof(ret_val);
689
690                                                 snprintf(buf_str,
691                                                          sizeof(buf_str),
692                                                          "%.2f",
693                                                          ret_variable_double);
694
695                                                 src_len = strlen(result_str);
696                                                 max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
697                                                 strncat(result_str, buf_str, max_len);
698
699                                                 temp_str++;
700                                                 num_args++;
701                                         } else if (*(temp_str + 1) >= '1' && *(temp_str + 1) <= '9') {
702                                                 if (*(temp_str + 3) == 'd') {
703                                                         /* Get var Type */
704                                                         ret_variable_int = 0;
705
706                                                         snprintf(buf_key,
707                                                                  sizeof(buf_key),
708                                                                  "%dtype%d", check_type,
709                                                                  num_args + *(temp_str + 1) - 49);
710                                                         bundle_get_str(b, buf_key, &ret_val);
711                                                         if (ret_val != NULL)
712                                                                 ret_var_type = atoi(ret_val);
713
714                                                         if (ret_var_type ==
715                                                             NOTIFICATION_VARIABLE_TYPE_COUNT) {
716                                                                 /* Get notification count */
717                                                                 notification_get_count(noti->type,
718                                                                                 noti->caller_pkgname,
719                                                                                 noti->group_id,
720                                                                                 noti->priv_id,
721                                                                                 &ret_variable_int);
722                                                         } else {
723                                                                 /* Get var Value */
724                                                                 snprintf(buf_key,
725                                                                          sizeof
726                                                                          (buf_key),
727                                                                          "%dvalue%d",
728                                                                          check_type,
729                                                                          num_args + *(temp_str + 1) - 49);
730                                                                 bundle_get_str(b, buf_key, &ret_val);
731                                                                 if (ret_val != NULL)
732                                                                         ret_variable_int = atoi(ret_val);
733
734                                                         }
735
736                                                         snprintf(buf_str,
737                                                                  sizeof(buf_str), "%d",
738                                                                  ret_variable_int);
739
740                                                         src_len = strlen(result_str);
741                                                         max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
742
743                                                         strncat(result_str, buf_str, max_len);
744
745                                                         temp_str += 3;
746                                                 } else if (*(temp_str + 3) == 's') {
747                                                         /* Get var Value */
748                                                         snprintf(buf_key,
749                                                                  sizeof(buf_key),
750                                                                  "%dvalue%d",
751                                                                  check_type, num_args + *(temp_str + 1) - 49);
752                                                         bundle_get_str(b, buf_key, &ret_val);
753
754                                                         snprintf(buf_str,
755                                                                  sizeof(buf_str), "%s",
756                                                                  ret_val);
757
758                                                         src_len = strlen(result_str);
759                                                         max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
760
761                                                         strncat(result_str, buf_str, max_len);
762
763                                                         temp_str += 3;
764                                                 } else if (*(temp_str + 3) == 'f') {
765                                                         /* Get var Value */
766                                                         snprintf(buf_key,
767                                                                  sizeof(buf_key),
768                                                                  "%dvalue%d",
769                                                                  check_type, num_args + *(temp_str + 1) - 49);
770                                                         bundle_get_str(b, buf_key, &ret_val);
771                                                         if (ret_val != NULL)
772                                                                 ret_variable_double = atof(ret_val);
773
774                                                         snprintf(buf_str,
775                                                                  sizeof(buf_str),
776                                                                  "%.2f",
777                                                                  ret_variable_double);
778
779                                                         src_len = strlen(result_str);
780                                                         max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
781
782                                                         strncat(result_str, buf_str, max_len);
783
784                                                         temp_str += 3;
785                                                 }
786                                         }
787                                 }
788
789                         }
790
791                         /* Check last variable is count, LEFT pos */
792                         if (num_args < noti->num_format_args) {
793                                 snprintf(buf_key, sizeof(buf_key), "%dtype%d",
794                                          check_type, num_args);
795                                 bundle_get_str(b, buf_key, &ret_val);
796                                 if (ret_val != NULL)
797                                         ret_var_type = atoi(ret_val);
798
799                                 if (ret_var_type ==
800                                     NOTIFICATION_VARIABLE_TYPE_COUNT) {
801                                         /* Get var Value */
802                                         snprintf(buf_key, sizeof(buf_key),
803                                                  "%dvalue%d", check_type,
804                                                  num_args);
805                                         bundle_get_str(b, buf_key, &ret_val);
806                                         if (ret_val != NULL)
807                                                 ret_variable_int = atoi(ret_val);
808
809                                         if (ret_variable_int ==
810                                             NOTIFICATION_COUNT_POS_RIGHT) {
811                                                 notification_get_count(noti->type,
812                                                                 noti->caller_pkgname,
813                                                                 noti->group_id,
814                                                                 noti->priv_id,
815                                                                 &ret_variable_int);
816                                                 snprintf(buf_str,
817                                                          sizeof(buf_str), " %d",
818                                                          ret_variable_int);
819
820                                                 src_len = strlen(result_str);
821                                                 max_len = NOTI_TEXT_RESULT_LEN - src_len - 1;
822
823                                                 strncat(result_str, buf_str, max_len);
824
825                                                 num_args++;
826                                         }
827
828                                 }
829                         }
830
831                         switch (check_type) {
832                         case NOTIFICATION_TEXT_TYPE_TITLE:
833                         case NOTIFICATION_TEXT_TYPE_GROUP_TITLE:
834                                 if (noti->temp_title != NULL)
835                                         free(noti->temp_title);
836
837                                 noti->temp_title = strdup(result_str);
838
839                                 *text = noti->temp_title;
840                                 break;
841                         case NOTIFICATION_TEXT_TYPE_CONTENT:
842                         case NOTIFICATION_TEXT_TYPE_CONTENT_FOR_DISPLAY_OPTION_IS_OFF:
843                         case NOTIFICATION_TEXT_TYPE_GROUP_CONTENT:
844                         case NOTIFICATION_TEXT_TYPE_GROUP_CONTENT_FOR_DISPLAY_OPTION_IS_OFF:
845                                 if (noti->temp_content !=
846                                     NULL)
847                                         free(noti->temp_content);
848
849                                 noti->temp_content = strdup(result_str);
850
851                                 *text = noti->temp_content;
852                                 break;
853                         default:
854                                 break;
855                         }
856
857                 }
858
859         } else {
860                 *text = NULL;
861         }
862
863         return NOTIFICATION_ERROR_NONE;
864 }
865
866 EXPORT_API int notification_set_text_domain(notification_h noti,
867                                                              const char *domain,
868                                                              const char *dir)
869 {
870         /* check noti and domain is valid data */
871         if (noti == NULL || domain == NULL || dir == NULL)
872                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
873
874         /* Check domain */
875         if (noti->domain)
876                 /* Remove previous domain */
877                 free(noti->domain);
878
879         /* Copy domain */
880         noti->domain = strdup(domain);
881
882         /* Check locale dir */
883         if (noti->dir)
884                 /* Remove previous locale dir */
885                 free(noti->dir);
886
887         /* Copy locale dir */
888         noti->dir = strdup(dir);
889
890         return NOTIFICATION_ERROR_NONE;
891 }
892
893 EXPORT_API int notification_get_text_domain(notification_h noti,
894                                                              char **domain,
895                                                              char **dir)
896 {
897         /* Check noti is valid data */
898         if (noti == NULL)
899                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
900
901         /* Get domain */
902         if (domain != NULL && noti->domain != NULL)
903                 *domain = noti->domain;
904
905         /* Get locale dir */
906         if (dir != NULL && noti->dir != NULL)
907                 *dir = noti->dir;
908
909         return NOTIFICATION_ERROR_NONE;
910 }
911
912 EXPORT_API int notification_set_time_to_text(notification_h noti, notification_text_type_e type,
913                                                                 time_t time)
914 {
915         int ret = NOTIFICATION_ERROR_NONE;
916         char buf[256] = { 0, };
917         char buf_tag[512] = { 0, };
918
919         if (noti == NULL)
920                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
921
922         if (time <= 0)
923                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
924
925         if (type <= NOTIFICATION_TEXT_TYPE_NONE
926             || type >= NOTIFICATION_TEXT_TYPE_MAX)
927                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
928
929
930         snprintf(buf, sizeof(buf), "%lu", time);
931         ret = notification_noti_set_tag(TAG_TIME, buf, buf_tag, sizeof(buf_tag));
932
933         if (ret != NOTIFICATION_ERROR_NONE)
934                 return ret;
935
936         return notification_set_text(noti, type, buf_tag, NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
937 }
938
939 EXPORT_API int notification_get_time_from_text(notification_h noti, notification_text_type_e type,
940                                                                 time_t *time)
941 {
942         int ret = NOTIFICATION_ERROR_NONE;
943         char *ret_text = NULL;
944         char *tag_value;
945
946         if (noti == NULL)
947                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
948
949         if (time == NULL)
950                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
951
952         if (type <= NOTIFICATION_TEXT_TYPE_NONE
953             || type >= NOTIFICATION_TEXT_TYPE_MAX)
954                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
955
956         ret = notification_get_text(noti, type, &ret_text);
957
958         if (ret != NOTIFICATION_ERROR_NONE || ret_text == NULL)
959                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
960
961         if (notification_noti_get_tag_type(ret_text) == TAG_TYPE_INVALID)
962                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
963
964         tag_value = notification_noti_strip_tag(ret_text);
965         if (tag_value == NULL)
966                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
967
968         *time = atol(tag_value);
969         free(tag_value);
970
971         return NOTIFICATION_ERROR_NONE;
972 }
973
974 EXPORT_API int notification_set_sound(notification_h noti,
975                                                        notification_sound_type_e type,
976                                                        const char *path)
977 {
978         /* Check noti is valid data */
979         if (noti == NULL)
980                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
981
982
983         /* Check type is valid */
984         if (type < NOTIFICATION_SOUND_TYPE_NONE
985             || type >= NOTIFICATION_SOUND_TYPE_MAX)
986                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
987
988         /* Save sound type */
989         noti->sound_type = type;
990
991         /* Save sound path if user data type */
992         if (type == NOTIFICATION_SOUND_TYPE_USER_DATA && path != NULL) {
993                 if (noti->sound_path != NULL)
994                         free(noti->sound_path);
995
996                 noti->sound_path = strdup(path);
997         } else {
998                 if (noti->sound_path != NULL) {
999                         free(noti->sound_path);
1000                         noti->sound_path = NULL;
1001                 }
1002                 if (type == NOTIFICATION_SOUND_TYPE_USER_DATA) {
1003                         noti->sound_type = NOTIFICATION_SOUND_TYPE_DEFAULT;
1004                         return NOTIFICATION_ERROR_INVALID_PARAMETER;
1005                 }
1006         }
1007
1008         return NOTIFICATION_ERROR_NONE;
1009 }
1010
1011 EXPORT_API int notification_get_sound(notification_h noti,
1012                                                        notification_sound_type_e *type,
1013                                                        const char **path)
1014 {
1015         /* check noti and type is valid data */
1016         if (noti == NULL || type == NULL)
1017                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1018
1019         /* Set sound type */
1020         *type = noti->sound_type;
1021
1022         /* Set sound path if user data type */
1023         if (noti->sound_type == NOTIFICATION_SOUND_TYPE_USER_DATA
1024             && path != NULL)
1025                 *path = noti->sound_path;
1026
1027         return NOTIFICATION_ERROR_NONE;
1028 }
1029
1030 EXPORT_API int notification_set_vibration(notification_h noti,
1031                                                            notification_vibration_type_e type,
1032                                                            const char *path)
1033 {
1034         /* Check noti is valid data */
1035         if (noti == NULL)
1036                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1037
1038         /* Check type is valid */
1039         if (type < NOTIFICATION_VIBRATION_TYPE_NONE
1040             || type >= NOTIFICATION_VIBRATION_TYPE_MAX)
1041                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1042
1043         /* Save vibration type */
1044         noti->vibration_type = type;
1045
1046         /* Save sound path if user data type */
1047         if (type == NOTIFICATION_VIBRATION_TYPE_USER_DATA && path != NULL) {
1048                 if (noti->vibration_path != NULL)
1049                         free(noti->vibration_path);
1050
1051                 noti->vibration_path = strdup(path);
1052         } else {
1053                 if (noti->vibration_path != NULL) {
1054                         free(noti->vibration_path);
1055                         noti->vibration_path = NULL;
1056                 }
1057                 if (type == NOTIFICATION_VIBRATION_TYPE_USER_DATA) {
1058                         noti->vibration_type = NOTIFICATION_VIBRATION_TYPE_DEFAULT;
1059                         return NOTIFICATION_ERROR_INVALID_PARAMETER;
1060                 }
1061         }
1062
1063         return NOTIFICATION_ERROR_NONE;
1064
1065 }
1066
1067 EXPORT_API int notification_get_vibration(notification_h noti,
1068                                                            notification_vibration_type_e *type,
1069                                                            const char **path)
1070 {
1071         /* check noti and type is valid data */
1072         if (noti == NULL || type == NULL)
1073                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1074
1075         /* Set vibration type */
1076         *type = noti->vibration_type;
1077
1078         /* Set sound path if user data type */
1079         if (noti->vibration_type == NOTIFICATION_VIBRATION_TYPE_USER_DATA
1080             && path != NULL)
1081                 *path = noti->vibration_path;
1082
1083         return NOTIFICATION_ERROR_NONE;
1084 }
1085
1086 EXPORT_API int notification_set_led(notification_h noti,
1087                                                            notification_led_op_e operation,
1088                                                            int led_argb)
1089 {
1090         /* Check noti is valid data */
1091         if (noti == NULL)
1092                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1093
1094         /* Check operation is valid */
1095         if (operation < NOTIFICATION_LED_OP_OFF
1096             || operation >= NOTIFICATION_LED_OP_MAX)
1097                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1098
1099         /* Save led operation */
1100         noti->led_operation = operation;
1101
1102         /* Save led argb if operation is turning on LED with custom color */
1103         if (operation == NOTIFICATION_LED_OP_ON_CUSTOM_COLOR)
1104                 noti->led_argb = led_argb;
1105
1106         return NOTIFICATION_ERROR_NONE;
1107 }
1108
1109 EXPORT_API int notification_get_led(notification_h noti,
1110                                                            notification_led_op_e *operation,
1111                                                            int *led_argb)
1112 {
1113         /* check noti and operation is valid data */
1114         if (noti == NULL || operation == NULL)
1115                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1116
1117         /* Set led operation */
1118         *operation = noti->led_operation;
1119
1120         /* Save led argb if operation is turning on LED with custom color */
1121         if (noti->led_operation == NOTIFICATION_LED_OP_ON_CUSTOM_COLOR
1122             && led_argb != NULL)
1123                 *led_argb = noti->led_argb;
1124
1125         return NOTIFICATION_ERROR_NONE;
1126 }
1127
1128 EXPORT_API int notification_set_led_time_period(notification_h noti,
1129                                                                         int on_ms, int off_ms)
1130 {
1131         /* Check noti is valid data */
1132         if (noti == NULL || on_ms < 0 || off_ms < 0)
1133                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1134
1135         /* Save led operation */
1136         noti->led_on_ms = on_ms;
1137         noti->led_off_ms = off_ms;
1138
1139         return NOTIFICATION_ERROR_NONE;
1140 }
1141
1142 EXPORT_API int notification_get_led_time_period(notification_h noti,
1143                                                                         int *on_ms, int *off_ms)
1144 {
1145         /* check noti and operation is valid data */
1146         if (noti == NULL)
1147                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1148
1149         if (on_ms)
1150                 *(on_ms) = noti->led_on_ms;
1151         if (off_ms)
1152                 *(off_ms) = noti->led_off_ms;
1153
1154         return NOTIFICATION_ERROR_NONE;
1155 }
1156
1157 EXPORT_API int notification_set_launch_option(notification_h noti,
1158                                                                 notification_launch_option_type type, void *option)
1159 {
1160         int err = NOTIFICATION_ERROR_NONE;
1161         int ret = 0;
1162         bundle *b = NULL;
1163         app_control_h app_control = option;
1164
1165         if (noti == NULL || app_control == NULL || type != NOTIFICATION_LAUNCH_OPTION_APP_CONTROL) {
1166                 err = NOTIFICATION_ERROR_INVALID_PARAMETER;
1167                 goto out;
1168         }
1169
1170         if ((ret = app_control_export_as_bundle(app_control, &b)) != APP_CONTROL_ERROR_NONE) {
1171                 NOTIFICATION_ERR("Failed to convert appcontrol to bundle:%d", ret);
1172                 err = NOTIFICATION_ERROR_INVALID_PARAMETER;
1173                 goto out;
1174         }
1175
1176         err = notification_set_execute_option(noti, NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, NULL, NULL, b);
1177
1178 out:
1179         if (b)
1180                 bundle_free(b);
1181
1182         return err;
1183 }
1184
1185 EXPORT_API int notification_get_launch_option(notification_h noti,
1186                                                                 notification_launch_option_type type, void *option)
1187 {
1188         int ret = 0;
1189         bundle *b = NULL;
1190         app_control_h *app_control = (app_control_h *)option;
1191         app_control_h app_control_new = NULL;
1192
1193         if (noti == NULL)
1194                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1195
1196         if (app_control == NULL)
1197                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1198
1199         if (type != NOTIFICATION_LAUNCH_OPTION_APP_CONTROL)
1200                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1201
1202
1203         ret = notification_get_execute_option(noti,
1204                                 NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH,
1205                                 NULL,
1206                                 &b);
1207         if (ret == NOTIFICATION_ERROR_NONE && b != NULL) {
1208                 ret = app_control_create(&app_control_new);
1209                 if (ret == APP_CONTROL_ERROR_NONE && app_control_new != NULL) {
1210                         ret = app_control_import_from_bundle(app_control_new, b);
1211                         if (ret == APP_CONTROL_ERROR_NONE) {
1212                                 *app_control = app_control_new;
1213                         } else {
1214                                 app_control_destroy(app_control_new);
1215                                 NOTIFICATION_ERR("Failed to import app control from bundle:%d", ret);
1216                                 return NOTIFICATION_ERROR_IO_ERROR;
1217                         }
1218                 } else {
1219                         NOTIFICATION_ERR("Failed to create app control:%d", ret);
1220                         return NOTIFICATION_ERROR_IO_ERROR;
1221                 }
1222         } else {
1223                 NOTIFICATION_ERR("Failed to get execute option:%d", ret);
1224                 return ret;
1225         }
1226
1227         return NOTIFICATION_ERROR_NONE;
1228 }
1229
1230 EXPORT_API int notification_set_event_handler(notification_h noti, notification_event_type_e event_type, app_control_h event_handler)
1231 {
1232         int err = NOTIFICATION_ERROR_NONE;
1233         bundle *app_control_bundle = NULL;
1234
1235         if (noti == NULL) {
1236                 err = NOTIFICATION_ERROR_INVALID_PARAMETER;
1237                 NOTIFICATION_ERR("NOTIFICATION_ERROR_INVALID_PARAMETER");
1238                 goto out;
1239         }
1240
1241         if (event_type < NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_1
1242                 || event_type > NOTIFICATION_EVENT_TYPE_CLICK_ON_THUMBNAIL) {
1243                 NOTIFICATION_ERR("NOTIFICATION_ERROR_INVALID_PARAMETER");
1244                 err = NOTIFICATION_ERROR_INVALID_PARAMETER;
1245                 goto out;
1246         }
1247
1248         if ((err = app_control_export_as_bundle(event_handler, &app_control_bundle)) != APP_CONTROL_ERROR_NONE) {
1249                 NOTIFICATION_ERR("app_control_to_bundle failed [%d]", err);
1250                 goto out;
1251         }
1252
1253         if (noti->b_event_handler[event_type] != NULL)
1254                 bundle_free(noti->b_event_handler[event_type]);
1255
1256         noti->b_event_handler[event_type] = app_control_bundle;
1257
1258 out:
1259         return err;
1260 }
1261
1262 EXPORT_API int notification_get_event_handler(notification_h noti, notification_event_type_e event_type, app_control_h *event_handler)
1263 {
1264         int err = NOTIFICATION_ERROR_NONE;
1265         bundle *b = NULL;
1266         app_control_h app_control_new = NULL;
1267
1268         if (noti == NULL) {
1269                 err = NOTIFICATION_ERROR_INVALID_PARAMETER;
1270                 NOTIFICATION_ERR("NOTIFICATION_ERROR_INVALID_PARAMETER");
1271                 goto out;
1272         }
1273         if (event_handler == NULL) {
1274                 err = NOTIFICATION_ERROR_INVALID_PARAMETER;
1275                 NOTIFICATION_ERR("NOTIFICATION_ERROR_INVALID_PARAMETER");
1276                 goto out;
1277         }
1278         if (event_type < NOTIFICATION_EVENT_TYPE_CLICK_ON_BUTTON_1
1279                 || event_type > NOTIFICATION_EVENT_TYPE_CLICK_ON_THUMBNAIL) {
1280                 NOTIFICATION_ERR("NOTIFICATION_ERROR_INVALID_PARAMETER");
1281                 err = NOTIFICATION_ERROR_INVALID_PARAMETER;
1282                 goto out;
1283         }
1284
1285         b = noti->b_event_handler[event_type];
1286
1287         if (b == NULL) {
1288                 NOTIFICATION_DBG("No event handler\n");
1289                 err = NOTIFICATION_ERROR_NOT_EXIST_ID;
1290                 goto out;
1291         }
1292
1293         err = app_control_create(&app_control_new);
1294         if (err != APP_CONTROL_ERROR_NONE || app_control_new == NULL) {
1295                 NOTIFICATION_ERR("app_control_create failed [%d]", err);
1296                 err = NOTIFICATION_ERROR_IO_ERROR;
1297                 goto out;
1298         }
1299
1300         err = app_control_import_from_bundle(app_control_new, b);
1301         if (err == APP_CONTROL_ERROR_NONE) {
1302                 *event_handler = app_control_new;
1303         } else {
1304                 app_control_destroy(app_control_new);
1305                 app_control_new = NULL;
1306                 NOTIFICATION_ERR("Failed to import app control from bundle [%d]", err);
1307                 err = NOTIFICATION_ERROR_IO_ERROR;
1308                 goto out;
1309         }
1310
1311 out:
1312         if (event_handler)
1313                 *event_handler = app_control_new;
1314
1315         return err;
1316 }
1317
1318
1319
1320
1321
1322 EXPORT_API int notification_set_property(notification_h noti,
1323                                                           int flags)
1324 {
1325         /* Check noti is valid data */
1326         if (noti == NULL)
1327                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1328
1329         /* Set flags */
1330         noti->flags_for_property = flags;
1331
1332         return NOTIFICATION_ERROR_NONE;
1333 }
1334
1335 EXPORT_API int notification_get_property(notification_h noti,
1336                                                           int *flags)
1337 {
1338         /* Check noti and flags are valid data */
1339         if (noti == NULL || flags == NULL)
1340                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1341
1342         /* Set flags */
1343         *flags = noti->flags_for_property;
1344
1345         return NOTIFICATION_ERROR_NONE;
1346 }
1347
1348 EXPORT_API int notification_set_display_applist(notification_h noti,
1349                                                                  int applist)
1350 {
1351         /* Check noti is valid data */
1352         if (noti == NULL)
1353                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1354
1355
1356         /* Set app list */
1357         if (applist == 0xffffffff) /* 0xffffffff means old NOTIFICATION_DISPLAY_APP_ALL */
1358                 applist = NOTIFICATION_DISPLAY_APP_ALL;
1359
1360         noti->display_applist = applist;
1361
1362         return NOTIFICATION_ERROR_NONE;
1363 }
1364
1365 EXPORT_API int notification_get_display_applist(notification_h noti,
1366                                                                  int *applist)
1367 {
1368         /* Check noti and applist are valid data */
1369         if (noti == NULL || applist == NULL)
1370                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1371
1372         /* Set app list */
1373         *applist = noti->display_applist;
1374
1375         return NOTIFICATION_ERROR_NONE;
1376 }
1377
1378 EXPORT_API int notification_set_size(notification_h noti,
1379                                                       double size)
1380 {
1381         /* Check noti is valid data */
1382         if (noti == NULL)
1383                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1384
1385         /* Save progress size */
1386         noti->progress_size = size;
1387
1388         return NOTIFICATION_ERROR_NONE;
1389 }
1390
1391 EXPORT_API int notification_get_size(notification_h noti,
1392                                                       double *size)
1393 {
1394         /* Check noti and size is valid data */
1395         if (noti == NULL || size == NULL)
1396                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1397
1398         /* Set progress size */
1399         *size = noti->progress_size;
1400
1401         return NOTIFICATION_ERROR_NONE;
1402 }
1403
1404 EXPORT_API int notification_set_progress(notification_h noti,
1405                                                           double percentage)
1406 {
1407         /* Check noti is valid data */
1408         if (noti == NULL)
1409                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1410
1411         /* Save progress percentage */
1412         noti->progress_percentage = percentage;
1413
1414         return NOTIFICATION_ERROR_NONE;
1415 }
1416
1417 EXPORT_API int notification_get_progress(notification_h noti,
1418                                                           double *percentage)
1419 {
1420         /* Check noti and percentage are valid data */
1421         if (noti == NULL || percentage == NULL)
1422                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1423
1424         /* Set progress percentage */
1425         *percentage = noti->progress_percentage;
1426
1427         return NOTIFICATION_ERROR_NONE;
1428 }
1429
1430 EXPORT_API int notification_get_pkgname(notification_h noti,
1431                                                          char **pkgname)
1432 {
1433         /* Check noti and pkgname are valid data */
1434         if (noti == NULL || pkgname == NULL)
1435                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1436
1437         /* Get caller pkgname */
1438         if (noti->caller_pkgname)
1439                 *pkgname = noti->caller_pkgname;
1440         else
1441                 *pkgname = NULL;
1442
1443         return NOTIFICATION_ERROR_NONE;
1444 }
1445
1446 EXPORT_API int notification_set_layout(notification_h noti,
1447                 notification_ly_type_e layout)
1448 {
1449         /* check noti and pkgname are valid data */
1450         if (noti == NULL || (layout < NOTIFICATION_LY_NONE || layout >= NOTIFICATION_LY_MAX))
1451                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1452
1453         noti->layout = layout;
1454
1455         return NOTIFICATION_ERROR_NONE;
1456 }
1457
1458 EXPORT_API int notification_get_layout(notification_h noti,
1459                 notification_ly_type_e *layout)
1460 {
1461         /* Check noti and pkgname are valid data */
1462         if (noti == NULL || layout == NULL)
1463                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1464
1465         *layout = noti->layout;
1466
1467         return NOTIFICATION_ERROR_NONE;
1468 }
1469
1470
1471
1472 EXPORT_API int notification_get_type(notification_h noti,
1473                                                       notification_type_e *type)
1474 {
1475         /* Check noti and type is valid data */
1476         if (noti == NULL || type == NULL)
1477                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1478
1479         /* Set noti type */
1480         *type = noti->type;
1481
1482         return NOTIFICATION_ERROR_NONE;
1483 }
1484
1485 EXPORT_API int notification_post(notification_h noti)
1486 {
1487         int ret = 0;
1488         int id = 0;
1489
1490         /* Check noti is vaild data */
1491         if (noti == NULL)
1492                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1493
1494         /* Check noti type is valid type */
1495         if (noti->type <= NOTIFICATION_TYPE_NONE
1496             || noti->type >= NOTIFICATION_TYPE_MAX)
1497                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1498
1499         /* Save insert time */
1500         noti->insert_time = time(NULL);
1501
1502         ret = notification_ipc_request_insert(noti, &id);
1503         if (ret != NOTIFICATION_ERROR_NONE)
1504                 return ret;
1505
1506         noti->priv_id = id;
1507         NOTIFICATION_DBG("from master:%d", id);
1508
1509         return NOTIFICATION_ERROR_NONE;
1510 }
1511
1512
1513
1514 EXPORT_API int notification_update(notification_h noti)
1515 {
1516         int ret = 0;
1517
1518         /* Check noti is valid data */
1519         if (noti != NULL) {
1520                 /* Update insert time ? */
1521                 noti->insert_time = time(NULL);
1522                 ret = notification_ipc_request_update(noti);
1523         } else {
1524                 notification_ipc_request_refresh();
1525                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1526         }
1527         return ret;
1528 }
1529
1530 EXPORT_API int notification_delete_all(notification_type_e type)
1531 {
1532         int ret = 0;
1533         char *caller_pkgname = NULL;
1534
1535         if (type <= NOTIFICATION_TYPE_NONE || type >= NOTIFICATION_TYPE_MAX)
1536                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1537
1538         caller_pkgname = notification_get_pkgname_by_pid();
1539
1540         ret = notification_ipc_request_delete_multiple(type, caller_pkgname);
1541
1542         if (caller_pkgname)
1543                 free(caller_pkgname);
1544
1545         return ret;
1546 }
1547
1548 EXPORT_API int notification_delete(notification_h noti)
1549 {
1550         int ret = 0;
1551
1552         if (noti == NULL)
1553                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1554
1555         ret = notification_ipc_request_delete_single(NOTIFICATION_TYPE_NONE, noti->caller_pkgname, noti->priv_id);
1556
1557         return ret;
1558 }
1559
1560 static notification_h _notification_create(notification_type_e type)
1561 {
1562         notification_h noti = NULL;
1563         package_info_h package_info = NULL;
1564         char *app_id = NULL;
1565         char *domain_name = NULL;
1566         char *app_root_path = NULL;
1567         char locale_directory[PATH_MAX] = { 0, }; /* PATH_MAX 4096 */
1568         int err_app_manager = APP_MANAGER_ERROR_NONE;
1569
1570         if (type <= NOTIFICATION_TYPE_NONE || type >= NOTIFICATION_TYPE_MAX) {
1571                 NOTIFICATION_ERR("INVALID TYPE : %d", type);
1572                 set_last_result(NOTIFICATION_ERROR_INVALID_PARAMETER);
1573                 return NULL;
1574         }
1575
1576         noti = (notification_h) calloc(1, sizeof(struct _notification));
1577         if (noti == NULL) {
1578                 NOTIFICATION_ERR("NO MEMORY : noti == NULL");
1579                 set_last_result(NOTIFICATION_ERROR_OUT_OF_MEMORY);
1580                 return NULL;
1581         }
1582
1583         noti->type = type;
1584
1585         if (type == NOTIFICATION_TYPE_NOTI)
1586                 noti->layout = NOTIFICATION_LY_NOTI_EVENT_SINGLE;
1587         else if (type == NOTIFICATION_TYPE_ONGOING)
1588                 noti->layout = NOTIFICATION_LY_ONGOING_PROGRESS;
1589
1590         noti->caller_pkgname = notification_get_pkgname_by_pid();
1591         noti->group_id = NOTIFICATION_GROUP_ID_NONE;
1592         noti->priv_id = NOTIFICATION_PRIV_ID_NONE;
1593         noti->sound_type = NOTIFICATION_SOUND_TYPE_NONE;
1594         noti->vibration_type = NOTIFICATION_VIBRATION_TYPE_NONE;
1595         noti->led_operation = NOTIFICATION_LED_OP_OFF;
1596         noti->display_applist = NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY | NOTIFICATION_DISPLAY_APP_TICKER | NOTIFICATION_DISPLAY_APP_INDICATOR;
1597         noti->auto_remove = true;
1598
1599         err_app_manager = app_manager_get_app_id(getpid(), &app_id);
1600         if (err_app_manager != APP_MANAGER_ERROR_NONE || app_id == NULL) {
1601                 NOTIFICATION_WARN("app_manager_get_app_id failed err[%d] app_id[%p]", err_app_manager, app_id);
1602                 goto out;
1603         }
1604
1605         /* app name is used as domain name */
1606         /* domain_name is allocated by app_get_package_app_name */
1607         err_app_manager = app_get_package_app_name(app_id, &domain_name);
1608
1609         if (err_app_manager != APP_ERROR_NONE || domain_name == NULL) {
1610                 NOTIFICATION_WARN("app_get_package_app_name failed err[%d] domain_name[%p]", err_app_manager, domain_name);
1611                 goto out;
1612         }
1613
1614         err_app_manager = package_info_create(noti->caller_pkgname, &package_info);
1615
1616         if (err_app_manager != PACKAGE_MANAGER_ERROR_NONE || package_info == NULL) {
1617                 NOTIFICATION_WARN("package_info_create failed err[%d] package_info[%p] caller_pkgname[%s]",
1618                                 err_app_manager, package_info, noti->caller_pkgname);
1619                 goto out;
1620         }
1621
1622         err_app_manager = package_info_get_root_path(package_info, &app_root_path);
1623
1624         if (err_app_manager != PACKAGE_MANAGER_ERROR_NONE || app_root_path == NULL) {
1625                 NOTIFICATION_WARN("package_info_get_root_path failed err[%d] app_root_path[%p]", err_app_manager, app_root_path);
1626                 goto out;
1627         }
1628
1629         snprintf(locale_directory, PATH_MAX, "%s/res/locale", app_root_path);
1630
1631         noti->domain = strdup(domain_name);
1632         noti->dir    = strdup(locale_directory);
1633
1634 out:
1635         if (domain_name)
1636                 free(domain_name);
1637
1638         if (app_id)
1639                 free(app_id);
1640
1641         if (app_root_path)
1642                 free(app_root_path);
1643
1644         if (package_info)
1645                 package_info_destroy(package_info);
1646
1647         /*!
1648          * \NOTE
1649          * Other fields are already initialized with ZERO.
1650          */
1651         set_last_result(NOTIFICATION_ERROR_NONE);
1652         return noti;
1653 }
1654
1655 EXPORT_API notification_h notification_create(notification_type_e type)
1656 {
1657         return _notification_create(type);
1658 }
1659
1660 EXPORT_API notification_h  notification_load_by_tag(const char *tag)
1661 {
1662         int ret = 0;
1663         notification_h noti = NULL;
1664         char *caller_pkgname = NULL;
1665
1666         if (tag == NULL) {
1667                 NOTIFICATION_ERR("Invalid parameter");
1668                 set_last_result(NOTIFICATION_ERROR_INVALID_PARAMETER);
1669                 return NULL;
1670         }
1671
1672         caller_pkgname = notification_get_pkgname_by_pid();
1673         if (!caller_pkgname) {
1674                 NOTIFICATION_ERR("Failed to get a package name");
1675                 set_last_result(NOTIFICATION_ERROR_OUT_OF_MEMORY);
1676                 return NULL;
1677         }
1678
1679         noti = (notification_h)calloc(1, sizeof(struct _notification));
1680         if (noti == NULL) {
1681                 NOTIFICATION_ERR("Failed to alloc a new notification");
1682                 set_last_result(NOTIFICATION_ERROR_OUT_OF_MEMORY);
1683                 free(caller_pkgname);
1684
1685                 return NULL;
1686         }
1687
1688         ret = notification_ipc_request_load_noti_by_tag(noti, caller_pkgname, (char *)tag);
1689         free(caller_pkgname);
1690
1691         set_last_result(ret);
1692         if (ret != NOTIFICATION_ERROR_NONE) {
1693                 notification_free(noti);
1694                 return NULL;
1695         }
1696
1697         return noti;
1698 }
1699
1700 EXPORT_API int notification_clone(notification_h noti, notification_h *clone)
1701 {
1702         int i = 0;
1703         notification_h new_noti = NULL;
1704
1705         if (noti == NULL || clone == NULL) {
1706                 NOTIFICATION_ERR("INVALID PARAMETER.");
1707                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1708         }
1709
1710         new_noti = (notification_h) calloc(1, sizeof(struct _notification));
1711         if (new_noti == NULL) {
1712                 NOTIFICATION_ERR("NO MEMORY : noti == NULL");
1713                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
1714         }
1715
1716         new_noti->type = noti->type;
1717         new_noti->layout = noti->layout;
1718
1719         new_noti->group_id = noti->group_id;
1720         new_noti->internal_group_id = noti->internal_group_id;
1721         new_noti->priv_id = noti->priv_id;
1722
1723         if (noti->caller_pkgname != NULL)
1724                 new_noti->caller_pkgname = strdup(noti->caller_pkgname);
1725         else
1726                 new_noti->caller_pkgname = notification_get_pkgname_by_pid();
1727
1728         if (noti->launch_pkgname != NULL)
1729                 new_noti->launch_pkgname = strdup(noti->launch_pkgname);
1730         else
1731                 new_noti->launch_pkgname = NULL;
1732
1733         if (noti->args != NULL)
1734                 new_noti->args = bundle_dup(noti->args);
1735         else
1736                 new_noti->args = NULL;
1737
1738         if (noti->group_args != NULL)
1739                 new_noti->group_args = bundle_dup(noti->group_args);
1740         else
1741                 new_noti->group_args = NULL;
1742
1743         if (noti->b_execute_option != NULL)
1744                 new_noti->b_execute_option = bundle_dup(noti->b_execute_option);
1745         else
1746                 new_noti->b_execute_option = NULL;
1747
1748         if (noti->b_service_responding != NULL)
1749                 new_noti->b_service_responding = bundle_dup(noti->b_service_responding);
1750         else
1751                 new_noti->b_service_responding = NULL;
1752
1753         if (noti->b_service_single_launch != NULL)
1754                 new_noti->b_service_single_launch = bundle_dup(noti->b_service_single_launch);
1755         else
1756                 new_noti->b_service_single_launch = NULL;
1757
1758         if (noti->b_service_multi_launch != NULL)
1759                 new_noti->b_service_multi_launch = bundle_dup(noti->b_service_multi_launch);
1760         else
1761                 new_noti->b_service_multi_launch = NULL;
1762
1763         for (i = 0; i < NOTIFICATION_EVENT_TYPE_MAX; i++) {
1764                 if (noti->b_event_handler[i] != NULL)
1765                         new_noti->b_event_handler[i] = bundle_dup(noti->b_event_handler[i]);
1766                 else
1767                         new_noti->b_event_handler[i] = NULL;
1768         }
1769
1770         new_noti->sound_type = noti->sound_type;
1771         if (noti->sound_path != NULL)
1772                 new_noti->sound_path = strdup(noti->sound_path);
1773         else
1774                 new_noti->sound_path = NULL;
1775
1776         new_noti->vibration_type = noti->vibration_type;
1777         if (noti->vibration_path != NULL)
1778                 new_noti->vibration_path = strdup(noti->vibration_path);
1779         else
1780                 new_noti->vibration_path = NULL;
1781
1782         new_noti->led_operation = noti->led_operation;
1783         new_noti->led_argb = noti->led_argb;
1784         new_noti->led_on_ms = noti->led_on_ms;
1785         new_noti->led_off_ms = noti->led_off_ms;
1786
1787         if (noti->domain != NULL)
1788                 new_noti->domain = strdup(noti->domain);
1789         else
1790                 new_noti->domain = NULL;
1791
1792         if (noti->dir != NULL)
1793                 new_noti->dir = strdup(noti->dir);
1794         else
1795                 new_noti->dir = NULL;
1796
1797         if (noti->b_text != NULL)
1798                 new_noti->b_text = bundle_dup(noti->b_text);
1799         else
1800                 new_noti->b_text = NULL;
1801
1802         if (noti->b_key != NULL)
1803                 new_noti->b_key = bundle_dup(noti->b_key);
1804         else
1805                 new_noti->b_key = NULL;
1806
1807         if (noti->b_format_args != NULL)
1808                 new_noti->b_format_args = bundle_dup(noti->b_format_args);
1809         else
1810                 new_noti->b_format_args = NULL;
1811
1812         new_noti->num_format_args = noti->num_format_args;
1813
1814         if (noti->b_image_path != NULL)
1815                 new_noti->b_image_path = bundle_dup(noti->b_image_path);
1816         else
1817                 new_noti->b_image_path = NULL;
1818
1819         new_noti->time = noti->time;
1820         new_noti->insert_time = noti->insert_time;
1821
1822         new_noti->flags_for_property = noti->flags_for_property;
1823         new_noti->display_applist = noti->display_applist;
1824
1825         new_noti->progress_size = noti->progress_size;
1826         new_noti->progress_percentage = noti->progress_percentage;
1827
1828         new_noti->ongoing_flag = noti->ongoing_flag;
1829         new_noti->auto_remove = noti->auto_remove;
1830
1831         new_noti->app_icon_path = NULL;
1832         new_noti->app_name = NULL;
1833         new_noti->temp_title = NULL;
1834         new_noti->temp_content = NULL;
1835
1836         *clone = new_noti;
1837
1838         return NOTIFICATION_ERROR_NONE;
1839 }
1840
1841
1842 EXPORT_API int notification_free(notification_h noti)
1843 {
1844         int i = 0;
1845         if (noti == NULL)
1846                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1847
1848         if (noti->caller_pkgname)
1849                 free(noti->caller_pkgname);
1850
1851         if (noti->launch_pkgname)
1852                 free(noti->launch_pkgname);
1853
1854         if (noti->args)
1855                 bundle_free(noti->args);
1856
1857         if (noti->group_args)
1858                 bundle_free(noti->group_args);
1859
1860         if (noti->b_execute_option)
1861                 bundle_free(noti->b_execute_option);
1862
1863         if (noti->b_service_responding)
1864                 bundle_free(noti->b_service_responding);
1865
1866         if (noti->b_service_single_launch)
1867                 bundle_free(noti->b_service_single_launch);
1868
1869         if (noti->b_service_multi_launch)
1870                 bundle_free(noti->b_service_multi_launch);
1871
1872         for (i = 0; i < NOTIFICATION_EVENT_TYPE_MAX; i++) {
1873                 if (noti->b_event_handler[i] != NULL)
1874                         bundle_free(noti->b_event_handler[i]);
1875         }
1876
1877         if (noti->sound_path)
1878                 free(noti->sound_path);
1879
1880         if (noti->vibration_path)
1881                 free(noti->vibration_path);
1882
1883         if (noti->domain)
1884                 free(noti->domain);
1885
1886         if (noti->dir)
1887                 free(noti->dir);
1888
1889         if (noti->b_text)
1890                 bundle_free(noti->b_text);
1891
1892         if (noti->b_key)
1893                 bundle_free(noti->b_key);
1894
1895         if (noti->b_format_args)
1896                 bundle_free(noti->b_format_args);
1897
1898         if (noti->b_image_path)
1899                 bundle_free(noti->b_image_path);
1900
1901         if (noti->app_icon_path)
1902                 free(noti->app_icon_path);
1903
1904         if (noti->app_name)
1905                 free(noti->app_name);
1906
1907         if (noti->temp_title)
1908                 free(noti->temp_title);
1909
1910         if (noti->temp_content)
1911                 free(noti->temp_content);
1912
1913         if (noti->tag)
1914                 free(noti->tag);
1915
1916         free(noti);
1917
1918         return NOTIFICATION_ERROR_NONE;
1919 }
1920
1921 EXPORT_API int notification_set_tag(notification_h noti, const char *tag)
1922 {
1923         /* Check noti is valid data */
1924         if (noti == NULL)
1925                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1926
1927         if (tag != NULL) {
1928                 /* save input TAG */
1929                 if (noti->tag != NULL)
1930                         free(noti->tag);
1931
1932                 noti->tag = strdup(tag);
1933         }
1934
1935         return NOTIFICATION_ERROR_NONE;
1936
1937 }
1938
1939 EXPORT_API int notification_get_tag(notification_h noti, const char **tag)
1940 {
1941         /* Check noti is valid data */
1942         if (noti == NULL)
1943                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1944
1945         *tag = noti->tag;
1946         return NOTIFICATION_ERROR_NONE;
1947 }
1948
1949 void notification_call_posted_toast_cb(const char *message)
1950 {
1951         if (posted_toast_message_cb != NULL)
1952                 posted_toast_message_cb((void *)message);
1953 }
1954
1955 EXPORT_API int notification_set_ongoing_flag(notification_h noti, bool ongoing_flag)
1956 {
1957         if (noti == NULL)
1958                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1959
1960         noti->ongoing_flag = ongoing_flag;
1961
1962         return NOTIFICATION_ERROR_NONE;
1963 }
1964
1965 EXPORT_API int notification_get_ongoing_flag(notification_h noti, bool *ongoing_flag)
1966 {
1967         if (noti == NULL || ongoing_flag == NULL)
1968                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1969
1970         *ongoing_flag = noti->ongoing_flag;
1971
1972         return NOTIFICATION_ERROR_NONE;
1973 }
1974
1975
1976 EXPORT_API int notification_add_button(notification_h noti, notification_button_index_e button_index)
1977 {
1978         if (noti == NULL || button_index < NOTIFICATION_BUTTON_1 || button_index > NOTIFICATION_BUTTON_6)
1979                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1980
1981         return NOTIFICATION_ERROR_NONE;
1982 }
1983
1984 EXPORT_API int notification_remove_button(notification_h noti, notification_button_index_e button_index)
1985 {
1986         if (noti == NULL || button_index < NOTIFICATION_BUTTON_1 || button_index > NOTIFICATION_BUTTON_6)
1987                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1988
1989         if (noti->b_event_handler[button_index - 1]) {
1990                 bundle_free(noti->b_event_handler[button_index - 1]);
1991                 noti->b_event_handler[button_index - 1] = NULL;
1992         }
1993
1994         return NOTIFICATION_ERROR_NONE;
1995 }
1996
1997 EXPORT_API int notification_set_auto_remove(notification_h noti, bool auto_remove)
1998 {
1999         if (noti == NULL)
2000                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
2001
2002         noti->auto_remove = auto_remove;
2003
2004         return NOTIFICATION_ERROR_NONE;
2005 }
2006
2007 EXPORT_API int notification_get_auto_remove(notification_h noti, bool *auto_remove)
2008 {
2009         if (noti == NULL || auto_remove == NULL)
2010                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
2011
2012         *auto_remove = noti->auto_remove;
2013
2014         return NOTIFICATION_ERROR_NONE;
2015 }
2016