Merge from private master branch
[platform/core/api/notification.git] / src / notification_noti.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>
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 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25
26 #include <vconf.h>
27 #include <Ecore.h>
28 #include <Elementary.h>
29 #include <Edje.h>
30 #include <Eina.h>
31
32 #include <notification.h>
33 #include <notification_db.h>
34 #include <notification_noti.h>
35 #include <notification_debug.h>
36 #include <notification_private.h>
37
38 #define NOTI_BURST_DELETE_UNIT 10
39 static int toast_height;
40 static Eina_List *toast_list;
41 static Eina_List *toast_popup;
42
43 static void __free_and_set(void **target_ptr, void *new_ptr) {
44         if (target_ptr != NULL) {
45                 if (*target_ptr != NULL) {
46                         free(*target_ptr);
47                 }
48                 *target_ptr = new_ptr;
49         }
50 }
51
52 static int _notification_noti_bind_query_text(sqlite3_stmt * stmt, const char *name,
53                                          const char *str)
54 {
55         int ret = 0;
56         int index = 0;
57
58         index = sqlite3_bind_parameter_index(stmt, name);
59         if (index == 0) {
60                 NOTIFICATION_ERR("Insert : invalid column name");
61                 return NOTIFICATION_ERROR_FROM_DB;
62         }
63
64         ret =
65             sqlite3_bind_text(stmt, index, NOTIFICATION_CHECK_STR(str), -1,
66                               SQLITE_STATIC);
67         if (ret != SQLITE_OK) {
68                 NOTIFICATION_ERR("Insert text : %s",
69                                  NOTIFICATION_CHECK_STR(str));
70                 return NOTIFICATION_ERROR_FROM_DB;
71         }
72
73         return NOTIFICATION_ERROR_NONE;
74 }
75
76 static int _notification_noti_bind_query_double(sqlite3_stmt * stmt, const char *name,
77                                          double val)
78 {
79         int ret = 0;
80         int index = 0;
81
82         index = sqlite3_bind_parameter_index(stmt, name);
83         if (index == 0) {
84                 NOTIFICATION_ERR("Insert : invalid column name");
85                 return NOTIFICATION_ERROR_FROM_DB;
86         }
87
88         ret = sqlite3_bind_double(stmt, index, val);
89         if (ret != SQLITE_OK) {
90                 NOTIFICATION_ERR("Insert double : %f", val);
91                 return NOTIFICATION_ERROR_FROM_DB;
92         }
93
94         return NOTIFICATION_ERROR_NONE;
95 }
96
97 static int _notification_noti_check_priv_id(notification_h noti, sqlite3 * db)
98 {
99         int result = 0;
100         int ret = NOTIFICATION_ERROR_NONE;
101         char *query = NULL;
102         sqlite3_stmt *stmt = NULL;
103
104         /* Make query to check priv_id exist */
105         query = sqlite3_mprintf("SELECT count(*) FROM noti_list WHERE caller_pkgname = '%s' AND priv_id = %d",
106                  noti->caller_pkgname, noti->priv_id);
107         if (query == NULL) {
108                 ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
109                 goto err;
110         }
111
112         ret = sqlite3_prepare(db, query, strlen(query), &stmt, NULL);
113         if (ret != SQLITE_OK) {
114                 NOTIFICATION_ERR("Get count DB err(%d) : %s", ret,
115                                  sqlite3_errmsg(db));
116                 ret = NOTIFICATION_ERROR_FROM_DB;
117                 goto err;
118         }
119
120         ret = sqlite3_step(stmt);
121         if (ret == SQLITE_ROW) {
122                 result = sqlite3_column_int(stmt, 0);
123         } else {
124                 result = 0;
125         }
126
127         sqlite3_finalize(stmt);
128
129         /* If result > 0, there is priv_id in DB */
130         if (result > 0) {
131                 ret = NOTIFICATION_ERROR_ALREADY_EXIST_ID;
132         }
133
134 err:
135         if (query) {
136                 sqlite3_free(query);
137         }
138
139         return ret;
140 }
141
142 static int _notification_noti_get_internal_group_id_by_priv_id(const char *pkgname,
143                                                                int priv_id,
144                                                                sqlite3 * db)
145 {
146         char *query = NULL;
147         sqlite3_stmt *stmt = NULL;
148         int ret = NOTIFICATION_ERROR_NONE, result = 0;
149
150         query = sqlite3_mprintf("SELECT internal_group_id FROM noti_list WHERE caller_pkgname = '%s' AND priv_id = %d",
151                  pkgname, priv_id);
152         if (query == NULL) {
153                 ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
154                 goto err;
155         }
156
157         ret = sqlite3_prepare(db, query, strlen(query), &stmt, NULL);
158         if (ret != SQLITE_OK) {
159                 NOTIFICATION_ERR("Get count DB err(%d) : %s", ret,
160                                  sqlite3_errmsg(db));
161                 ret = NOTIFICATION_ERROR_FROM_DB;
162                 goto err;
163         }
164
165         ret = sqlite3_step(stmt);
166         if (ret == SQLITE_ROW) {
167                 result = sqlite3_column_int(stmt, 0);
168         } else {
169                 result = 0;
170         }
171
172 err:
173         if (stmt) {
174                 sqlite3_finalize(stmt);
175         }
176
177         if (query) {
178                 sqlite3_free(query);
179         }
180
181         if (ret != NOTIFICATION_ERROR_NONE) {
182                 NOTIFICATION_ERR("failed to internal group ID:%d", ret);
183         }
184
185         return result;
186 }
187
188 static int _insertion_query_create(notification_h noti, char **query)
189 {
190         int b_encode_len = 0;
191         char *args = NULL;
192         char *group_args = NULL;
193         char *b_image_path = NULL;
194         char *b_execute_option = NULL;
195         char *b_service_responding = NULL;
196         char *b_service_single_launch = NULL;
197         char *b_service_multi_launch = NULL;
198         char *b_text = NULL;
199         char *b_key = NULL;
200         char *b_format_args = NULL;
201         int flag_simmode = 0;
202
203         if (query == NULL) {
204                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
205         }
206
207         /* Decode bundle to insert DB */
208         if (noti->args) {
209                 bundle_encode(noti->args, (bundle_raw **) & args, &b_encode_len);
210         }
211         if (noti->group_args) {
212                 bundle_encode(noti->group_args, (bundle_raw **) & group_args,
213                               &b_encode_len);
214         }
215
216         if (noti->b_execute_option) {
217                 bundle_encode(noti->b_execute_option,
218                               (bundle_raw **) & b_execute_option, &b_encode_len);
219         }
220         if (noti->b_service_responding) {
221                 bundle_encode(noti->b_service_responding,
222                               (bundle_raw **) & b_service_responding, &b_encode_len);
223         }
224         if (noti->b_service_single_launch) {
225                 bundle_encode(noti->b_service_single_launch,
226                               (bundle_raw **) & b_service_single_launch, &b_encode_len);
227         }
228         if (noti->b_service_multi_launch) {
229                 bundle_encode(noti->b_service_multi_launch,
230                               (bundle_raw **) & b_service_multi_launch, &b_encode_len);
231         }
232
233         if (noti->b_text) {
234                 bundle_encode(noti->b_text, (bundle_raw **) & b_text, &b_encode_len);
235         }
236         if (noti->b_key) {
237                 bundle_encode(noti->b_key, (bundle_raw **) & b_key, &b_encode_len);
238         }
239         if (noti->b_format_args) {
240                 bundle_encode(noti->b_format_args,
241                               (bundle_raw **) & b_format_args, &b_encode_len);
242         }
243
244         if (noti->b_image_path) {
245                 bundle_encode(noti->b_image_path,
246                               (bundle_raw **) & b_image_path, &b_encode_len);
247         }
248
249         /* Check only simmode property is enable */
250         if (noti->flags_for_property & NOTIFICATION_PROP_DISPLAY_ONLY_SIMMODE) {
251                 flag_simmode = 1;
252         }
253
254         /* Make query */
255         *query = sqlite3_mprintf("INSERT INTO noti_list ("
256                  "type, "
257                  "layout, "
258                  "caller_pkgname, launch_pkgname, "
259                  "image_path, "
260                  "group_id, internal_group_id, priv_id, "
261                  "title_key, "
262                  "b_text, b_key, tag, b_format_args, num_format_args, "
263                  "text_domain, text_dir, "
264                  "time, insert_time, "
265                  "args, group_args, "
266                  "b_execute_option, "
267                  "b_service_responding, b_service_single_launch, b_service_multi_launch, "
268                  "sound_type, sound_path, vibration_type, vibration_path, led_operation, led_argb, led_on_ms, led_off_ms, "
269                  "flags_for_property, flag_simmode, display_applist, "
270                  "progress_size, progress_percentage) values ("
271                  "%d, "
272                  "%d, "
273                  "'%s', '%s', "
274                  "'%s', "
275                  "%d, %d, %d, "
276                  "$title_key, "
277                  "'%s', '%s', $tag, '%s', %d, "
278                  "'%s', '%s', "
279                  "%d, %d, "
280                  "'%s', '%s', "
281                  "'%s', "
282                  "'%s', '%s', '%s', "
283                  "%d, '%s', %d, '%s', %d, %d, %d, %d,"
284                  "%d, %d, %d, "
285                  "$progress_size, $progress_percentage)",
286                  noti->type,
287                  noti->layout,
288                  NOTIFICATION_CHECK_STR(noti->caller_pkgname),
289                  NOTIFICATION_CHECK_STR(noti->launch_pkgname),
290                  NOTIFICATION_CHECK_STR(b_image_path), noti->group_id,
291                  noti->internal_group_id, noti->priv_id,
292                  NOTIFICATION_CHECK_STR(b_text), NOTIFICATION_CHECK_STR(b_key),
293                  NOTIFICATION_CHECK_STR(b_format_args), noti->num_format_args,
294                  NOTIFICATION_CHECK_STR(noti->domain),
295                  NOTIFICATION_CHECK_STR(noti->dir), (int)noti->time,
296                  (int)noti->insert_time, NOTIFICATION_CHECK_STR(args),
297                  NOTIFICATION_CHECK_STR(group_args),
298                  NOTIFICATION_CHECK_STR(b_execute_option),
299                  NOTIFICATION_CHECK_STR(b_service_responding),
300                  NOTIFICATION_CHECK_STR(b_service_single_launch),
301                  NOTIFICATION_CHECK_STR(b_service_multi_launch),
302                  noti->sound_type, NOTIFICATION_CHECK_STR(noti->sound_path),
303                  noti->vibration_type,
304                  NOTIFICATION_CHECK_STR(noti->vibration_path),
305                  noti->led_operation,
306                  noti->led_argb,
307                  noti->led_on_ms,
308                  noti->led_off_ms,
309                  noti->flags_for_property, flag_simmode, noti->display_applist);
310
311         /* Free decoded data */
312         if (args) {
313                 free(args);
314         }
315         if (group_args) {
316                 free(group_args);
317         }
318
319         if (b_execute_option) {
320                 free(b_execute_option);
321         }
322         if (b_service_responding) {
323                 free(b_service_responding);
324         }
325         if (b_service_single_launch) {
326                 free(b_service_single_launch);
327         }
328         if (b_service_multi_launch) {
329                 free(b_service_multi_launch);
330         }
331
332         if (b_text) {
333                 free(b_text);
334         }
335         if (b_key) {
336                 free(b_key);
337         }
338         if (b_format_args) {
339                 free(b_format_args);
340         }
341
342         if (b_image_path) {
343                 free(b_image_path);
344         }
345
346         if (*query == NULL) {
347                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
348         }
349
350         return NOTIFICATION_ERROR_NONE;
351 }
352
353
354 static int _update_query_create(notification_h noti, char **query)
355 {
356         int b_encode_len = 0;
357         char *args = NULL;
358         char *group_args = NULL;
359         char *b_image_path = NULL;
360         char *b_execute_option = NULL;
361         char *b_service_responding = NULL;
362         char *b_service_single_launch = NULL;
363         char *b_service_multi_launch = NULL;
364         char *b_text = NULL;
365         char *b_key = NULL;
366         char *b_format_args = NULL;
367         int flag_simmode = 0;
368
369         if (query == NULL) {
370                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
371         }
372
373         /* Decode bundle to update DB */
374         if (noti->args) {
375                 bundle_encode(noti->args, (bundle_raw **) & args, &b_encode_len);
376         }
377         if (noti->group_args) {
378                 bundle_encode(noti->group_args, (bundle_raw **) & group_args,
379                               &b_encode_len);
380         }
381
382         if (noti->b_execute_option) {
383                 bundle_encode(noti->b_execute_option,
384                               (bundle_raw **) & b_execute_option, &b_encode_len);
385         }
386         if (noti->b_service_responding) {
387                 bundle_encode(noti->b_service_responding,
388                               (bundle_raw **) & b_service_responding, &b_encode_len);
389         }
390         if (noti->b_service_single_launch) {
391                 bundle_encode(noti->b_service_single_launch,
392                               (bundle_raw **) & b_service_single_launch, &b_encode_len);
393         }
394         if (noti->b_service_multi_launch) {
395                 bundle_encode(noti->b_service_multi_launch,
396                               (bundle_raw **) & b_service_multi_launch, &b_encode_len);
397         }
398
399         if (noti->b_text) {
400                 bundle_encode(noti->b_text, (bundle_raw **) & b_text, &b_encode_len);
401         }
402         if (noti->b_key) {
403                 bundle_encode(noti->b_key, (bundle_raw **) & b_key, &b_encode_len);
404         }
405         if (noti->b_format_args) {
406                 bundle_encode(noti->b_format_args,
407                               (bundle_raw **) & b_format_args, &b_encode_len);
408         }
409
410         if (noti->b_image_path) {
411                 bundle_encode(noti->b_image_path,
412                               (bundle_raw **) & b_image_path, &b_encode_len);
413         }
414
415         /* Check only simmode property is enable */
416         if (noti->flags_for_property & NOTIFICATION_PROP_DISPLAY_ONLY_SIMMODE) {
417                 flag_simmode = 1;
418         }
419
420         /* Make query */
421         *query = sqlite3_mprintf("UPDATE noti_list SET "
422                  "type = %d, "
423                  "layout = %d, "
424                  "launch_pkgname = '%s', "
425                  "image_path = '%s', "
426                  "b_text = '%s', b_key = '%s', tag = $tag, "
427                  "b_format_args = '%s', num_format_args = %d, "
428                  "text_domain = '%s', text_dir = '%s', "
429                  "time = %d, insert_time = %d, "
430                  "args = '%s', group_args = '%s', "
431                  "b_execute_option = '%s', "
432                  "b_service_responding = '%s', "
433                  "b_service_single_launch = '%s', "
434                  "b_service_multi_launch = '%s', "
435                  "sound_type = %d, sound_path = '%s', "
436                  "vibration_type = %d, vibration_path = '%s', "
437                  "led_operation = %d, led_argb = %d, "
438                  "led_on_ms = %d, led_off_ms = %d, "
439                  "flags_for_property = %d, flag_simmode = %d, "
440                  "display_applist = %d, "
441                  "progress_size = $progress_size, progress_percentage = $progress_percentage "
442                  "where priv_id = %d ",
443                  noti->type,
444                  noti->layout,
445                  NOTIFICATION_CHECK_STR(noti->launch_pkgname),
446                  NOTIFICATION_CHECK_STR(b_image_path),
447                  NOTIFICATION_CHECK_STR(b_text), NOTIFICATION_CHECK_STR(b_key),
448                  NOTIFICATION_CHECK_STR(b_format_args), noti->num_format_args,
449                  NOTIFICATION_CHECK_STR(noti->domain),
450                  NOTIFICATION_CHECK_STR(noti->dir),
451                  (int)noti->time, (int)noti->insert_time,
452                  NOTIFICATION_CHECK_STR(args), NOTIFICATION_CHECK_STR(group_args),
453                  NOTIFICATION_CHECK_STR(b_execute_option),
454                  NOTIFICATION_CHECK_STR(b_service_responding),
455                  NOTIFICATION_CHECK_STR(b_service_single_launch),
456                  NOTIFICATION_CHECK_STR(b_service_multi_launch),
457                  noti->sound_type, NOTIFICATION_CHECK_STR(noti->sound_path),
458                  noti->vibration_type,
459                  NOTIFICATION_CHECK_STR(noti->vibration_path),
460                  noti->led_operation,
461                  noti->led_argb,
462                  noti->led_on_ms,
463                  noti->led_off_ms,
464                  noti->flags_for_property, flag_simmode, noti->display_applist,
465                  noti->priv_id);
466
467         /* Free decoded data */
468         if (args) {
469                 free(args);
470         }
471         if (group_args) {
472                 free(group_args);
473         }
474
475         if (b_execute_option) {
476                 free(b_execute_option);
477         }
478         if (b_service_responding) {
479                 free(b_service_responding);
480         }
481         if (b_service_single_launch) {
482                 free(b_service_single_launch);
483         }
484         if (b_service_multi_launch) {
485                 free(b_service_multi_launch);
486         }
487
488         if (b_text) {
489                 free(b_text);
490         }
491         if (b_key) {
492                 free(b_key);
493         }
494         if (b_format_args) {
495                 free(b_format_args);
496         }
497
498         if (b_image_path) {
499                 free(b_image_path);
500         }
501
502         if (*query == NULL) {
503                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
504         }
505
506         return NOTIFICATION_ERROR_NONE;
507 }
508
509 static void _notification_noti_populate_from_stmt(sqlite3_stmt * stmt, notification_h noti) {
510         int col = 0;
511
512         if (stmt == NULL || noti == NULL) {
513                 return ;
514         }
515
516         noti->type = sqlite3_column_int(stmt, col++);
517         noti->layout = sqlite3_column_int(stmt, col++);
518         __free_and_set((void **)&(noti->caller_pkgname), notification_db_column_text(stmt, col++));
519         __free_and_set((void **)&(noti->launch_pkgname), notification_db_column_text(stmt, col++));
520         noti->b_image_path = notification_db_column_bundle(stmt, col++);
521         noti->group_id = sqlite3_column_int(stmt, col++);
522         noti->internal_group_id = 0;
523         noti->priv_id = sqlite3_column_int(stmt, col++);
524         __free_and_set((void **)&(noti->tag), notification_db_column_text(stmt, col++));
525
526         noti->b_text = notification_db_column_bundle(stmt, col++);
527         noti->b_key = notification_db_column_bundle(stmt, col++);
528         noti->b_format_args = notification_db_column_bundle(stmt, col++);
529         noti->num_format_args = sqlite3_column_int(stmt, col++);
530
531         __free_and_set((void **)&(noti->domain), notification_db_column_text(stmt, col++));
532         __free_and_set((void **)&(noti->dir), notification_db_column_text(stmt, col++));
533         noti->time = sqlite3_column_int(stmt, col++);
534         noti->insert_time = sqlite3_column_int(stmt, col++);
535         noti->args = notification_db_column_bundle(stmt, col++);
536         noti->group_args = notification_db_column_bundle(stmt, col++);
537
538         noti->b_execute_option = notification_db_column_bundle(stmt, col++);
539         noti->b_service_responding = notification_db_column_bundle(stmt, col++);
540         noti->b_service_single_launch =
541             notification_db_column_bundle(stmt, col++);
542         noti->b_service_multi_launch =
543             notification_db_column_bundle(stmt, col++);
544
545         noti->sound_type = sqlite3_column_int(stmt, col++);
546         __free_and_set((void **)&(noti->sound_path), notification_db_column_text(stmt, col++));
547         noti->vibration_type = sqlite3_column_int(stmt, col++);
548         __free_and_set((void **)&(noti->vibration_path), notification_db_column_text(stmt, col++));
549         noti->led_operation = sqlite3_column_int(stmt, col++);
550         noti->led_argb = sqlite3_column_int(stmt, col++);
551         noti->led_on_ms = sqlite3_column_int(stmt, col++);
552         noti->led_off_ms = sqlite3_column_int(stmt, col++);
553
554         noti->flags_for_property = sqlite3_column_int(stmt, col++);
555         noti->display_applist = sqlite3_column_int(stmt, col++);
556         noti->progress_size = sqlite3_column_double(stmt, col++);
557         noti->progress_percentage = sqlite3_column_double(stmt, col++);
558
559         noti->app_icon_path = NULL;
560         noti->app_name = NULL;
561         noti->temp_title = NULL;
562         noti->temp_content = NULL;
563 }
564
565 static notification_h _notification_noti_get_item(sqlite3_stmt * stmt)
566 {
567         notification_h noti = NULL;
568
569         noti = (notification_h) calloc(1, sizeof(struct _notification));
570         if (noti == NULL) {
571                 return NULL;
572         }
573
574         _notification_noti_populate_from_stmt(stmt, noti);
575
576         return noti;
577 }
578
579 int notification_noti_set_tag(const char *tag, char *value, char *buf, int buf_len)
580 {
581         int len_total = 0;
582
583         len_total += (strlen(tag) * 2) + 5 + strlen(value) + 1;
584
585         if (buf_len <= len_total)
586                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
587
588         snprintf(buf, buf_len, "<%s>%s</%s>", tag, value, tag);
589
590         return NOTIFICATION_ERROR_NONE;
591 }
592
593 char *notification_noti_strip_tag(const char *tagged_str)
594 {
595         if (tagged_str == NULL)
596                 return NULL;
597
598         int len_total = strlen(tagged_str);
599
600         if (len_total == 0)
601                 return NULL;
602
603         char *b_f_e = strstr(tagged_str, ">");
604         char *b_e_s = strstr(tagged_str, "</");
605
606         if (b_f_e == NULL || b_e_s == NULL || (b_e_s - b_f_e - 1) <= 0)
607                 return NULL;
608
609         return strndup(b_f_e + 1, b_e_s - b_f_e - 1);
610 }
611
612 int notification_noti_get_tag_type(const char *tagged_str)
613 {
614         if (tagged_str == NULL)
615                 return TAG_TYPE_INVALID;
616
617         if (strlen(tagged_str)== 0)
618                 return TAG_TYPE_INVALID;
619
620         char *b_f_s = strstr(tagged_str, "<");
621         char *b_f_e = strstr(tagged_str, ">");
622
623         if (b_f_s == NULL || b_f_e == NULL || (b_f_e - b_f_s - 1) <= 0)
624                 return TAG_TYPE_INVALID;
625
626         char *start = b_f_s + 1;
627         int len_tag = b_f_e - b_f_s - 1;
628
629         if (strncmp(start,TAG_TIME,len_tag) == 0) {
630                 return TAG_TYPE_TIME;
631         }
632
633         return TAG_TYPE_INVALID;
634 }
635
636 static int _notification_noti_update_priv_id(sqlite3 * db, int rowid)
637 {
638         int ret = NOTIFICATION_ERROR_NONE;
639         char *query = NULL;
640
641         if (db == NULL) {
642                 ret = NOTIFICATION_ERROR_INVALID_PARAMETER;
643                 goto err;
644         }
645
646         query = sqlite3_mprintf("UPDATE noti_list SET "
647                         "priv_id = %d, internal_group_id = %d WHERE rowid = %d",
648                         rowid, rowid, rowid);
649         if (query == NULL) {
650                 ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
651                 goto err;
652         }
653
654         ret = notification_db_exec(db, query, NULL);
655
656 err:
657         if (query) {
658                 sqlite3_free(query);
659         }
660
661         return ret;
662 }
663
664 EXPORT_API int notification_noti_insert(notification_h noti)
665 {
666         int ret = 0;
667         sqlite3 *db = NULL;
668         sqlite3_stmt *stmt = NULL;
669         char *query = NULL;
670         char buf_key[32] = { 0, };
671         const char *title_key = NULL;
672
673         /* Open DB */
674         db = notification_db_open(DBPATH);
675         if (!db) {
676                 return get_last_result();
677         }
678
679         /* Initialize private ID */
680         noti->priv_id = NOTIFICATION_PRIV_ID_NONE;
681         noti->group_id = NOTIFICATION_GROUP_ID_NONE;
682         noti->internal_group_id = NOTIFICATION_GROUP_ID_NONE;
683
684         /* make query */
685         ret = _insertion_query_create(noti, &query);
686         if (ret != NOTIFICATION_ERROR_NONE) {
687                 goto err;
688         }
689
690         ret = sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
691         if (ret != SQLITE_OK) {
692                 NOTIFICATION_ERR("Insert Query : %s", query);
693                 NOTIFICATION_ERR("Insert DB error(%d) : %s", ret,
694                                  sqlite3_errmsg(db));
695                 ret = NOTIFICATION_ERROR_FROM_DB;
696                 goto err;
697         }
698
699         /* Get title key */
700         if (noti->b_key != NULL) {
701                 snprintf(buf_key, sizeof(buf_key), "%d",
702                          NOTIFICATION_TEXT_TYPE_TITLE);
703
704                 title_key = bundle_get_val(noti->b_key, buf_key);
705         }
706
707         if (title_key == NULL && noti->b_text != NULL) {
708                 snprintf(buf_key, sizeof(buf_key), "%d",
709                          NOTIFICATION_TEXT_TYPE_TITLE);
710
711                 title_key = bundle_get_val(noti->b_text, buf_key);
712         }
713
714         if (title_key == NULL) {
715                 title_key = noti->caller_pkgname;
716         }
717
718         /* Bind query */
719         ret = _notification_noti_bind_query_text(stmt, "$tag", noti->tag);
720         if (ret != NOTIFICATION_ERROR_NONE) {
721                 NOTIFICATION_ERR("Bind error : %s", sqlite3_errmsg(db));
722                 goto err;
723         }
724         ret = _notification_noti_bind_query_text(stmt, "$title_key", title_key);
725         if (ret != NOTIFICATION_ERROR_NONE) {
726                 NOTIFICATION_ERR("Bind error : %s", sqlite3_errmsg(db));
727                 goto err;
728         }
729         ret = _notification_noti_bind_query_double(stmt, "$progress_size",noti->progress_size);
730         if (ret != NOTIFICATION_ERROR_NONE) {
731                 NOTIFICATION_ERR("Bind error : %s", sqlite3_errmsg(db));
732                 if (stmt) {
733                         sqlite3_finalize(stmt);
734                 }
735                 return ret;
736         }
737         ret = _notification_noti_bind_query_double(stmt, "$progress_percentage",noti->progress_percentage);
738         if (ret != NOTIFICATION_ERROR_NONE) {
739                 NOTIFICATION_ERR("Bind error : %s", sqlite3_errmsg(db));
740                 if (stmt) {
741                         sqlite3_finalize(stmt);
742                 }
743                 return ret;
744         }
745
746         ret = sqlite3_step(stmt);
747         if (ret == SQLITE_OK || ret == SQLITE_DONE) {
748                 noti->priv_id = (int)sqlite3_last_insert_rowid(db);
749                 if (_notification_noti_update_priv_id(db, noti->priv_id) == 0) {
750                         ret = NOTIFICATION_ERROR_NONE;
751                 } else {
752                         ret = NOTIFICATION_ERROR_FROM_DB;
753                 }
754         } else {
755                 ret = NOTIFICATION_ERROR_FROM_DB;
756         }
757 err:
758         if (stmt) {
759                 sqlite3_finalize(stmt);
760         }
761
762         /* Close DB */
763         if (db) {
764                 notification_db_close(&db);
765         }
766
767         if (query) {
768                 sqlite3_free(query);
769         }
770
771         return ret;
772 }
773
774 int notification_noti_get_by_priv_id(notification_h noti, char *pkgname, int priv_id)
775 {
776         int ret = 0;
777         char *query = NULL;
778         sqlite3 *db = NULL;
779         sqlite3_stmt *stmt = NULL;
780
781         if (priv_id < 0 || noti == NULL) {
782                 ret = NOTIFICATION_ERROR_INVALID_PARAMETER;
783                 goto err;
784         }
785
786         /* Open DB */
787         db = notification_db_open(DBPATH);
788         if (!db) {
789                 return get_last_result();
790         }
791
792         char *base_query = "select "
793                          "type, layout, caller_pkgname, launch_pkgname, image_path, group_id, priv_id, "
794                          "tag, b_text, b_key, b_format_args, num_format_args, "
795                          "text_domain, text_dir, time, insert_time, args, group_args, "
796                          "b_execute_option, b_service_responding, b_service_single_launch, b_service_multi_launch, "
797                          "sound_type, sound_path, vibration_type, vibration_path, led_operation, led_argb, led_on_ms, led_off_ms, "
798                          "flags_for_property, display_applist, progress_size, progress_percentage "
799                          "from noti_list ";
800
801         if (pkgname != NULL) {
802                 query = sqlite3_mprintf("%s where caller_pkgname = '%s' and priv_id = %d",
803                                 base_query ,pkgname, priv_id);
804         } else {
805                 query = sqlite3_mprintf("%s where priv_id = %d", base_query,  priv_id);
806         }
807         if (query == NULL) {
808                 ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
809                 goto err;
810         }
811
812         ret = sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
813         if (ret != SQLITE_OK) {
814                 NOTIFICATION_ERR("select Query : %s", query);
815                 NOTIFICATION_ERR("select DB error(%d) : %s", ret,
816                                  sqlite3_errmsg(db));
817                 ret = NOTIFICATION_ERROR_FROM_DB;
818                 goto err;
819         }
820
821         ret = sqlite3_step(stmt);
822         if (ret == SQLITE_ROW) {
823                 _notification_noti_populate_from_stmt(stmt, noti);
824                 ret = NOTIFICATION_ERROR_NONE;
825         } else {
826                 ret = NOTIFICATION_ERROR_FROM_DB;
827         }
828 err:
829         if (query) {
830                 sqlite3_free(query);
831         }
832
833         if (stmt) {
834                 sqlite3_finalize(stmt);
835         }
836
837         /* Close DB */
838         if (db != NULL) {
839                 notification_db_close(&db);
840         }
841
842         return ret;
843 }
844
845 EXPORT_API int notification_noti_get_by_tag(notification_h noti, char *pkgname, char* tag)
846 {
847         int ret = 0;
848         char *query = NULL;
849         sqlite3 *db = NULL;
850         sqlite3_stmt *stmt = NULL;
851
852         if (tag == NULL || noti == NULL) {
853                 ret = NOTIFICATION_ERROR_INVALID_PARAMETER;
854                 goto err;
855         }
856
857         /* Open DB */
858         db = notification_db_open(DBPATH);
859         if (!db) {
860                 return get_last_result();
861         }
862
863         if (pkgname != NULL) {
864                 ret = sqlite3_prepare_v2(db, "select "
865                          "type, layout, caller_pkgname, launch_pkgname, image_path, group_id, priv_id, "
866                          "tag, b_text, b_key, b_format_args, num_format_args, "
867                          "text_domain, text_dir, time, insert_time, args, group_args, "
868                          "b_execute_option, b_service_responding, b_service_single_launch, b_service_multi_launch, "
869                          "sound_type, sound_path, vibration_type, vibration_path, led_operation, led_argb, led_on_ms, led_off_ms, "
870                          "flags_for_property, display_applist, progress_size, progress_percentage "
871                          "from noti_list where caller_pkgname = ? and tag = ?", -1, &stmt, NULL);
872                 if (ret != SQLITE_OK) {
873                         NOTIFICATION_ERR("Error: %s\n", sqlite3_errmsg(db));
874                         return NOTIFICATION_ERROR_OUT_OF_MEMORY;
875                 }
876
877                 ret = sqlite3_bind_text(stmt, 1, pkgname, -1, SQLITE_TRANSIENT);
878                 if (ret != SQLITE_OK) {
879                         NOTIFICATION_ERR("Error: %s\n", sqlite3_errmsg(db));
880                         goto err;
881                 }
882
883                 ret = sqlite3_bind_text(stmt, 2,  tag, -1, SQLITE_TRANSIENT);
884                 if (ret != SQLITE_OK) {
885                         NOTIFICATION_ERR("Error: %s\n", sqlite3_errmsg(db));
886                         goto err;
887                 } 
888         } else {
889                 ret = sqlite3_prepare_v2(db, "select "
890                          "type, layout, caller_pkgname, launch_pkgname, image_path, group_id, priv_id, "
891                          "tag, b_text, b_key, b_format_args, num_format_args, "
892                          "text_domain, text_dir, time, insert_time, args, group_args, "
893                          "b_execute_option, b_service_responding, b_service_single_launch, b_service_multi_launch, "
894                          "sound_type, sound_path, vibration_type, vibration_path, led_operation, led_argb, led_on_ms, led_off_ms, "
895                          "flags_for_property, display_applist, progress_size, progress_percentage "
896                          "from noti_list where  tag = ?", -1, &stmt, NULL);
897                 if (ret != SQLITE_OK) {
898                         NOTIFICATION_ERR("Error: %s\n", sqlite3_errmsg(db));
899                         return NOTIFICATION_ERROR_OUT_OF_MEMORY;
900                 }
901
902                 ret = sqlite3_bind_text(stmt, 1, tag, -1, SQLITE_TRANSIENT);
903                 if (ret != SQLITE_OK) {
904                         NOTIFICATION_ERR("Error: %s\n", sqlite3_errmsg(db));
905                         goto err;
906                 }
907         }
908 /*
909         char *base_query = "select "
910                          "type, layout, caller_pkgname, launch_pkgname, image_path, group_id, priv_id, "
911                          "tag, b_text, b_key, b_format_args, num_format_args, "
912                          "text_domain, text_dir, time, insert_time, args, group_args, "
913                          "b_execute_option, b_service_responding, b_service_single_launch, b_service_multi_launch, "
914                          "sound_type, sound_path, vibration_type, vibration_path, led_operation, led_argb, led_on_ms, led_off_ms, "
915                          "flags_for_property, display_applist, progress_size, progress_percentage "
916                          "from noti_list ";
917
918         if (pkgname != NULL) {
919                 query = sqlite3_mprintf("%s where caller_pkgname = '%s' and tag = '%s'",
920                                 base_query ,pkgname, tag);
921         } else {
922                 query = sqlite3_mprintf("%s where tag = '%s'", base_query,  tag);
923         }
924         if (query == NULL) {
925                 ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
926                 goto err;
927         }
928
929         ret = sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
930         if (ret != SQLITE_OK) {
931                 NOTIFICATION_ERR("select Query : %s", query);
932                 NOTIFICATION_ERR("select DB error(%d) : %s", ret,
933                                  sqlite3_errmsg(db));
934                 ret = NOTIFICATION_ERROR_FROM_DB;
935                 goto err;
936         }
937 */
938         ret = sqlite3_step(stmt);
939         if (ret == SQLITE_ROW) {
940                 _notification_noti_populate_from_stmt(stmt, noti);
941                 ret = NOTIFICATION_ERROR_NONE;
942         } else {
943                 ret = NOTIFICATION_ERROR_FROM_DB;
944         }
945 err:
946         if (query) {
947                 sqlite3_free(query);
948         }
949
950         if (stmt) {
951                 sqlite3_finalize(stmt);
952         }
953
954         /* Close DB */
955         if (db != NULL) {
956                 notification_db_close(&db);
957         }
958
959         return ret;
960 }
961
962 EXPORT_API int notification_noti_update(notification_h noti)
963 {
964         int ret = 0;
965         sqlite3 *db;
966         sqlite3_stmt *stmt = NULL;
967         char *query = NULL;
968
969         /* Open DB */
970         db = notification_db_open(DBPATH);
971         if (!db) {
972                 return get_last_result();
973         }
974
975         /* Check private ID is exist */
976         ret = _notification_noti_check_priv_id(noti, db);
977         if (ret != NOTIFICATION_ERROR_ALREADY_EXIST_ID) {
978                 ret = NOTIFICATION_ERROR_NOT_EXIST_ID;
979                 goto err;
980         }
981
982         /* make update query */
983         ret = _update_query_create(noti, &query);
984         if (ret != NOTIFICATION_ERROR_NONE) {
985                 goto err;
986         }
987
988         ret = sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
989         if (ret != SQLITE_OK) {
990                 NOTIFICATION_ERR("Insert Query : %s", query);
991                 NOTIFICATION_ERR("Insert DB error(%d) : %s", ret,
992                                  sqlite3_errmsg(db));
993                 ret = NOTIFICATION_ERROR_FROM_DB;
994                 goto err;
995         }
996
997         ret = _notification_noti_bind_query_text(stmt, "$tag", noti->tag);
998         if (ret != NOTIFICATION_ERROR_NONE) {
999                 NOTIFICATION_ERR("Bind error : %s", sqlite3_errmsg(db));
1000                 goto err;
1001         }
1002         ret = _notification_noti_bind_query_double(stmt, "$progress_size",noti->progress_size);
1003         if (ret != NOTIFICATION_ERROR_NONE) {
1004                 NOTIFICATION_ERR("Bind error : %s", sqlite3_errmsg(db));
1005                 goto err;
1006         }
1007         ret = _notification_noti_bind_query_double(stmt, "$progress_percentage",noti->progress_percentage);
1008         if (ret != NOTIFICATION_ERROR_NONE) {
1009                 NOTIFICATION_ERR("Bind error : %s", sqlite3_errmsg(db));
1010                 goto err;
1011         }
1012
1013         ret = sqlite3_step(stmt);
1014         if (ret == SQLITE_OK || ret == SQLITE_DONE) {
1015                 ret = NOTIFICATION_ERROR_NONE;
1016         } else {
1017                 ret = NOTIFICATION_ERROR_FROM_DB;
1018         }
1019 err:
1020         if (stmt) {
1021                 sqlite3_finalize(stmt);
1022         }
1023
1024         /* Close DB */
1025         if (db) {
1026                 notification_db_close(&db);
1027         }
1028
1029         if (query) {
1030                 sqlite3_free(query);
1031         }
1032
1033         return ret;
1034 }
1035
1036 EXPORT_API int notification_noti_delete_all(notification_type_e type, const char *pkgname, int *num_deleted, int **list_deleted_rowid)
1037 {
1038         int ret = NOTIFICATION_ERROR_NONE;
1039         int ret_tmp = NOTIFICATION_ERROR_NONE;
1040         int i = 0, data_cnt = 0;
1041         sqlite3 *db = NULL;
1042         sqlite3_stmt *stmt = NULL;
1043         char buf[128] = { 0, };
1044         char query[NOTIFICATION_QUERY_MAX] = { 0, };
1045         char query_base[NOTIFICATION_QUERY_MAX] = { 0, };
1046         char query_where[NOTIFICATION_QUERY_MAX] = { 0, };
1047
1048         /* Open DB */
1049         db = notification_db_open(DBPATH);
1050         if (!db) {
1051                 return get_last_result();
1052         }
1053
1054         if (pkgname == NULL) {
1055                 if (type != NOTIFICATION_TYPE_NONE) {
1056                         snprintf(query_where, sizeof(query_where),
1057                                  "where type = %d ", type);
1058                 }
1059         } else {
1060                 if (type == NOTIFICATION_TYPE_NONE) {
1061                         snprintf(query_where, sizeof(query_where),
1062                                  "where caller_pkgname = '%s' ", pkgname);
1063                 } else {
1064                         snprintf(query_where, sizeof(query_where),
1065                                  "where caller_pkgname = '%s' and type = %d ",
1066                                  pkgname, type);
1067                 }
1068         }
1069
1070         if (num_deleted != NULL) {
1071                 *num_deleted = 0;
1072         }
1073         if (list_deleted_rowid != NULL) {
1074                 *list_deleted_rowid = NULL;
1075                 snprintf(query, sizeof(query),
1076                                 "select priv_id from noti_list %s ", query_where);
1077
1078                 ret = sqlite3_prepare(db, query, strlen(query), &stmt, NULL);
1079                 if (ret != SQLITE_OK) {
1080                         NOTIFICATION_ERR("Select Query : %s", query);
1081                         NOTIFICATION_ERR("Select DB error(%d) : %s", ret,
1082                                          sqlite3_errmsg(db));
1083
1084                         ret = NOTIFICATION_ERROR_FROM_DB;
1085                         goto err;
1086                 }
1087
1088                 while(sqlite3_step(stmt) == SQLITE_ROW) {
1089                         if (data_cnt % 8 == 0) {
1090                                 int *tmp;
1091
1092                                 tmp = (int *)realloc(*list_deleted_rowid, sizeof(int) * (data_cnt + 8 + 1));
1093                                 if (tmp) {
1094                                         *list_deleted_rowid = tmp;
1095                                 } else {
1096                                         NOTIFICATION_ERR("Heap: %s\n", strerror(errno));
1097                                         /*!
1098                                          * \TODO
1099                                          * How can I handle this?
1100                                          */
1101                                         free(*list_deleted_rowid);
1102                                         *list_deleted_rowid = NULL;
1103                                         ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
1104                                         goto err;
1105                                 }
1106                         }
1107                         *((*list_deleted_rowid) + data_cnt) = sqlite3_column_int(stmt, 0);
1108                         data_cnt++;
1109                 }
1110
1111                 if (stmt) {
1112                         sqlite3_finalize(stmt);
1113                         stmt = NULL;
1114                 }
1115
1116                 if (data_cnt > 0) {
1117                         query_where[0] = '\0';
1118                         snprintf(query_base, sizeof(query_base) - 1, "delete from noti_list");
1119                         for (i = 0; i < data_cnt ; i++) {
1120                                 if (i % NOTI_BURST_DELETE_UNIT == 0 && i != 0) {
1121                                         snprintf(query, sizeof(query) - 1, "%s where priv_id in (%s)", query_base, query_where);
1122                                         ret_tmp = notification_db_exec(db, query, NULL);
1123                                         query_where[0] = '\0';
1124                                         if (ret == NOTIFICATION_ERROR_NONE) {
1125                                                 ret = ret_tmp;
1126                                         }
1127                                 }
1128                                 snprintf(buf, sizeof(buf) - 1, "%s%d", (i % NOTI_BURST_DELETE_UNIT == 0) ? "" : ",", *((*list_deleted_rowid) + i));
1129                                 strncat(query_where, buf,sizeof(query_where) - strlen(query_where) - 1);
1130                         }
1131                         if ((i <= NOTI_BURST_DELETE_UNIT) || ((i % NOTI_BURST_DELETE_UNIT) > 0) ) {
1132                                 snprintf(query, sizeof(query) - 1, "%s where priv_id in (%s)", query_base, query_where);
1133                                 ret_tmp = notification_db_exec(db, query, NULL);
1134                                 if (ret == NOTIFICATION_ERROR_NONE) {
1135                                         ret = ret_tmp;
1136                                 }
1137                         }
1138                 } else {
1139                         free(*list_deleted_rowid);
1140                         *list_deleted_rowid = NULL;
1141                 }
1142
1143                 if (num_deleted != NULL) {
1144                         *num_deleted = data_cnt;
1145                 }
1146         } else {
1147                 /* Make main query */
1148                 snprintf(query_base, sizeof(query_base), "delete from noti_list ");
1149                 snprintf(query, sizeof(query), "%s %s", query_base, query_where);
1150
1151                 ret = notification_db_exec(db, query, NULL);
1152
1153                 if (num_deleted != NULL) {
1154                         *num_deleted = sqlite3_changes(db);
1155                 }
1156         }
1157
1158 err:
1159         if (stmt) {
1160                 sqlite3_finalize(stmt);
1161         }
1162         /* Close DB */
1163         if (db) {
1164                 notification_db_close(&db);
1165         }
1166
1167         return ret;
1168 }
1169
1170 int notification_noti_delete_group_by_group_id(const char *pkgname,
1171                                                int group_id, int *num_deleted, int **list_deleted_rowid)
1172 {
1173         int ret = NOTIFICATION_ERROR_NONE;
1174         int ret_tmp = NOTIFICATION_ERROR_NONE;
1175         sqlite3 *db = NULL;
1176         int i = 0, data_cnt = 0;
1177         sqlite3_stmt *stmt = NULL;
1178         char buf[128] = { 0, };
1179         char query[NOTIFICATION_QUERY_MAX] = { 0, };
1180         char query_base[NOTIFICATION_QUERY_MAX] = { 0, };
1181         char query_where[NOTIFICATION_QUERY_MAX] = { 0, };
1182
1183         /* Check pkgname is valid */
1184         if (pkgname == NULL) {
1185                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1186         }
1187
1188         snprintf(query_where, sizeof(query_where),
1189                         "where caller_pkgname = '%s' and group_id = %d", pkgname, group_id);
1190
1191         /* Open DB */
1192         db = notification_db_open(DBPATH);
1193         if (!db) {
1194                 return get_last_result();
1195         }
1196
1197         if (num_deleted != NULL) {
1198                 *num_deleted = 0;
1199         }
1200         if (list_deleted_rowid != NULL) {
1201                 *list_deleted_rowid = NULL;
1202                 snprintf(query, sizeof(query),
1203                                 "select priv_id from noti_list %s ", query_where);
1204
1205                 ret = sqlite3_prepare(db, query, strlen(query), &stmt, NULL);
1206                 if (ret != SQLITE_OK) {
1207                         NOTIFICATION_ERR("Select Query : %s", query);
1208                         NOTIFICATION_ERR("Select DB error(%d) : %s", ret,
1209                                          sqlite3_errmsg(db));
1210
1211                         ret = NOTIFICATION_ERROR_FROM_DB;
1212                         goto err;
1213                 }
1214
1215                 while(sqlite3_step(stmt) == SQLITE_ROW) {
1216                         if (data_cnt % 8 == 0) {
1217                                 int *tmp;
1218                                 tmp = (int *)realloc(*list_deleted_rowid, sizeof(int) * (data_cnt + 8 + 1));
1219                                 if (tmp) {
1220                                         *list_deleted_rowid = tmp;
1221                                 } else {
1222                                         free(*list_deleted_rowid);
1223                                         *list_deleted_rowid = NULL;
1224                                         ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
1225                                         goto err;
1226                                 }
1227                         }
1228                         *((*list_deleted_rowid) + data_cnt) = sqlite3_column_int(stmt, 0);
1229                         data_cnt++;
1230                 }
1231
1232                 if (stmt) {
1233                         sqlite3_finalize(stmt);
1234                         stmt = NULL;
1235                 }
1236
1237                 if (data_cnt > 0) {
1238                         query_where[0] = '\0';
1239                         snprintf(query_base, sizeof(query_base) - 1, "delete from noti_list");
1240                         for (i = 0; i < data_cnt ; i++) {
1241                                 if (i % NOTI_BURST_DELETE_UNIT == 0 && i != 0) {
1242                                         snprintf(query, sizeof(query) - 1, "%s where priv_id in (%s)", query_base, query_where);
1243                                         ret_tmp = notification_db_exec(db, query, NULL);
1244                                         query_where[0] = '\0';
1245                                         if (ret == NOTIFICATION_ERROR_NONE) {
1246                                                 ret = ret_tmp;
1247                                         }
1248                                 }
1249                                 snprintf(buf, sizeof(buf) - 1, "%s%d", (i % NOTI_BURST_DELETE_UNIT == 0) ? "" : ",", *((*list_deleted_rowid) + i));
1250                                 strncat(query_where, buf,sizeof(query_where) - strlen(query_where) - 1);
1251                         }
1252                         if ((i <= NOTI_BURST_DELETE_UNIT) || ((i % NOTI_BURST_DELETE_UNIT) > 0) ) {
1253                                 snprintf(query, sizeof(query) - 1, "%s where priv_id in (%s)", query_base, query_where);
1254                                 ret_tmp = notification_db_exec(db, query, NULL);
1255                                 if (ret == NOTIFICATION_ERROR_NONE) {
1256                                         ret = ret_tmp;
1257                                 }
1258                         }
1259                 } else {
1260                         free(*list_deleted_rowid);
1261                         *list_deleted_rowid = NULL;
1262                 }
1263
1264                 if (num_deleted != NULL) {
1265                         *num_deleted = data_cnt;
1266                 }
1267         } else {
1268                 /* Make query */
1269                 snprintf(query, sizeof(query), "delete from noti_list %s", query_where);
1270
1271                 /* execute DB */
1272                 ret = notification_db_exec(db, query, NULL);
1273         }
1274
1275 err:
1276         if (stmt) {
1277                 sqlite3_finalize(stmt);
1278         }
1279         /* Close DB */
1280         if (db) {
1281                 notification_db_close(&db);
1282         }
1283
1284         return ret;
1285 }
1286
1287 int notification_noti_delete_group_by_priv_id(const char *pkgname, int priv_id)
1288 {
1289         sqlite3 *db = NULL;
1290         char query[NOTIFICATION_QUERY_MAX] = { 0, };
1291         int internal_group_id = 0;
1292         int ret;
1293
1294         /* Check pkgname is valid */
1295         if (pkgname == NULL) {
1296                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1297         }
1298
1299         /* Open DB */
1300         db = notification_db_open(DBPATH);
1301         if (!db) {
1302                 return get_last_result();
1303         }
1304
1305         /* Get internal group id using priv id */
1306         internal_group_id =
1307             _notification_noti_get_internal_group_id_by_priv_id(pkgname,
1308                                                                 priv_id, db);
1309
1310         /* Make query */
1311         snprintf(query, sizeof(query), "delete from noti_list "
1312                  "where caller_pkgname = '%s' and internal_group_id = %d",
1313                  pkgname, internal_group_id);
1314
1315         /* execute DB */
1316         ret = notification_db_exec(db, query, NULL);
1317
1318         /* Close DB */
1319         notification_db_close(&db);
1320
1321         return ret;
1322 }
1323
1324 EXPORT_API int notification_noti_delete_by_priv_id(const char *pkgname, int priv_id)
1325 {
1326         sqlite3 *db = NULL;
1327         char query[NOTIFICATION_QUERY_MAX] = { 0, };
1328         int ret;
1329
1330         /* Check pkgname is valid */
1331         if (pkgname == NULL) {
1332                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1333         }
1334
1335         /* Open DB */
1336         db = notification_db_open(DBPATH);
1337         if (!db) {
1338                 return get_last_result();
1339         }
1340
1341         /* Make query */
1342         snprintf(query, sizeof(query), "delete from noti_list "
1343                  "where caller_pkgname = '%s' and priv_id = %d", pkgname,
1344                  priv_id);
1345
1346         /* execute DB */
1347         ret = notification_db_exec(db, query, NULL);
1348
1349         /* Close DB */
1350         if (db) {
1351                 notification_db_close(&db);
1352         }
1353
1354         return ret;
1355 }
1356
1357 EXPORT_API int notification_noti_delete_by_priv_id_get_changes(const char *pkgname, int priv_id, int *num_changes)
1358 {
1359         sqlite3 *db = NULL;
1360         char query[NOTIFICATION_QUERY_MAX] = { 0, };
1361         int ret;
1362
1363         /* Check pkgname is valid */
1364         if (pkgname == NULL) {
1365                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1366         }
1367
1368         /* Open DB */
1369         db = notification_db_open(DBPATH);
1370         if (!db) {
1371                 return get_last_result();
1372         }
1373
1374         /* Make query */
1375         snprintf(query, sizeof(query), "delete from noti_list "
1376                  "where caller_pkgname = '%s' and priv_id = %d", pkgname,
1377                  priv_id);
1378
1379         /* execute DB */
1380         ret = notification_db_exec(db, query, num_changes);
1381
1382         if (num_changes != NULL) {
1383                 NOTIFICATION_DBG("deleted num:%d", *num_changes);
1384         }
1385
1386         /* Close DB */
1387         if (db) {
1388                 notification_db_close(&db);
1389         }
1390
1391         return ret;
1392 }
1393
1394 int notification_noti_get_count(notification_type_e type,
1395                                                  const char *pkgname,
1396                                                  int group_id, int priv_id,
1397                                                  int *count)
1398 {
1399         sqlite3 *db = NULL;
1400         sqlite3_stmt *stmt = NULL;
1401         char query[NOTIFICATION_QUERY_MAX] = { 0, };
1402         char query_base[NOTIFICATION_QUERY_MAX] = { 0, };
1403         char query_where[NOTIFICATION_QUERY_MAX] = { 0, };
1404         char query_where_more[NOTIFICATION_QUERY_MAX] = { 0, };
1405
1406         int ret = 0, get_count = 0, internal_group_id = 0;
1407         int status = VCONFKEY_TELEPHONY_SIM_UNKNOWN;
1408         int flag_where = 0;
1409         int flag_where_more = 0;
1410         int ret_vconf = 0;
1411
1412         /* Open DB */
1413         db = notification_db_open(DBPATH);
1414         if (!db) {
1415                 return get_last_result();
1416         }
1417
1418         /* Check current sim status */
1419         ret_vconf = vconf_get_int(VCONFKEY_TELEPHONY_SIM_SLOT, &status);
1420
1421         /* Make query */
1422         snprintf(query_base, sizeof(query_base),
1423                  "select count(*) from noti_list ");
1424
1425         if (pkgname != NULL) {
1426                 if (group_id == NOTIFICATION_GROUP_ID_NONE) {
1427                         if (priv_id == NOTIFICATION_PRIV_ID_NONE) {
1428                                 snprintf(query_where, sizeof(query_where),
1429                                          "where caller_pkgname = '%s' ",
1430                                          pkgname);
1431                                 flag_where = 1;
1432                         } else {
1433                                 internal_group_id =
1434                                     _notification_noti_get_internal_group_id_by_priv_id
1435                                     (pkgname, priv_id, db);
1436                                 snprintf(query_where, sizeof(query_where),
1437                                          "where caller_pkgname = '%s' and internal_group_id = %d ",
1438                                          pkgname, internal_group_id);
1439                                 flag_where = 1;
1440                         }
1441                 } else {
1442                         if (priv_id == NOTIFICATION_PRIV_ID_NONE) {
1443                                 snprintf(query_where, sizeof(query_where),
1444                                          "where caller_pkgname = '%s' and group_id = %d ",
1445                                          pkgname, group_id);
1446                                 flag_where = 1;
1447                         } else {
1448                                 internal_group_id =
1449                                     _notification_noti_get_internal_group_id_by_priv_id
1450                                     (pkgname, priv_id, db);
1451                                 snprintf(query_where, sizeof(query_where),
1452                                          "where caller_pkgname = '%s' and internal_group_id = %d ",
1453                                          pkgname, internal_group_id);
1454                                 flag_where = 1;
1455                         }
1456                 }
1457
1458         }
1459
1460         if (ret_vconf == 0 && status == VCONFKEY_TELEPHONY_SIM_INSERTED) {
1461                 if (type != NOTIFICATION_TYPE_NONE) {
1462                         snprintf(query_where_more, sizeof(query_where_more),
1463                                  "type = %d ", type);
1464                         flag_where_more = 1;
1465                 }
1466         } else {
1467                 if (type != NOTIFICATION_TYPE_NONE) {
1468                         snprintf(query_where_more, sizeof(query_where_more),
1469                                  "type = %d and flag_simmode = 0 ", type);
1470                         flag_where_more = 1;
1471                 } else {
1472                         snprintf(query_where_more, sizeof(query_where_more),
1473                                  "flag_simmode = 0 ");
1474                         flag_where_more = 1;
1475                 }
1476         }
1477
1478         if (flag_where == 1) {
1479                 if (flag_where_more == 1) {
1480                         snprintf(query, sizeof(query), "%s %s and %s",
1481                                  query_base, query_where, query_where_more);
1482                 } else {
1483                         snprintf(query, sizeof(query), "%s %s", query_base,
1484                                  query_where);
1485                 }
1486
1487         } else {
1488                 if (flag_where_more == 1) {
1489                         snprintf(query, sizeof(query), "%s where %s",
1490                                  query_base, query_where_more);
1491                 } else {
1492                         snprintf(query, sizeof(query), "%s", query_base);
1493                 }
1494         }
1495
1496         ret = sqlite3_prepare(db, query, strlen(query), &stmt, NULL);
1497         if (ret != SQLITE_OK) {
1498                 NOTIFICATION_ERR("Select Query : %s", query);
1499                 NOTIFICATION_ERR("Select DB error(%d) : %s", ret,
1500                                  sqlite3_errmsg(db));
1501
1502                 ret = NOTIFICATION_ERROR_FROM_DB;
1503                 goto err;
1504         }
1505
1506         ret = sqlite3_step(stmt);
1507         if (ret == SQLITE_ROW) {
1508                 get_count = sqlite3_column_int(stmt, 0);
1509         }
1510
1511         ret = NOTIFICATION_ERROR_NONE;
1512
1513 err:
1514         if (stmt) {
1515                 sqlite3_finalize(stmt);
1516         }
1517
1518         /* Close DB */
1519         if (db) {
1520                 notification_db_close(&db);
1521         }
1522
1523         *count = get_count;
1524
1525         return ret;
1526 }
1527
1528 int notification_noti_get_grouping_list(notification_type_e type,
1529                                                          int count,
1530                                                          notification_list_h *
1531                                                          list)
1532 {
1533         sqlite3 *db = NULL;
1534         sqlite3_stmt *stmt = NULL;
1535         char query[NOTIFICATION_QUERY_MAX] = { 0, };
1536         char query_base[NOTIFICATION_QUERY_MAX] = { 0, };
1537         char query_where[NOTIFICATION_QUERY_MAX] = { 0, };
1538
1539         int ret = 0;
1540         notification_list_h get_list = NULL;
1541         notification_h noti = NULL;
1542         int internal_count = 0;
1543         int status;
1544
1545         /* Open DB */
1546         db = notification_db_open(DBPATH);
1547         if (!db) {
1548                 return get_last_result();
1549         }
1550
1551         /* Check current sim status */
1552         ret = vconf_get_int(VCONFKEY_TELEPHONY_SIM_SLOT, &status);
1553
1554         /* Make query */
1555         snprintf(query_base, sizeof(query_base), "select "
1556                  "type, layout, caller_pkgname, launch_pkgname, image_path, group_id, priv_id, "
1557                  "tag, b_text, b_key, b_format_args, num_format_args, "
1558                  "text_domain, text_dir, time, insert_time, args, group_args, "
1559                  "b_execute_option, b_service_responding, b_service_single_launch, b_service_multi_launch, "
1560                  "sound_type, sound_path, vibration_type, vibration_path, led_operation, led_argb, led_on_ms, led_off_ms, "
1561                  "flags_for_property, display_applist, progress_size, progress_percentage "
1562                  "from noti_list ");
1563
1564         if (status == VCONFKEY_TELEPHONY_SIM_INSERTED) {
1565                 if (type != NOTIFICATION_TYPE_NONE) {
1566                         snprintf(query_where, sizeof(query_where),
1567                                  "where type = %d ", type);
1568                 }
1569         } else {
1570                 if (type != NOTIFICATION_TYPE_NONE) {
1571                         snprintf(query_where, sizeof(query_where),
1572                                  "where type = %d and flag_simmode = 0 ", type);
1573                 } else {
1574                         snprintf(query_where, sizeof(query_where),
1575                                  "where flag_simmode = 0 ");
1576                 }
1577         }
1578
1579         snprintf(query, sizeof(query),
1580                  "%s %s "
1581                  "group by internal_group_id "
1582                  "order by rowid desc, time desc", query_base, query_where);
1583
1584         ret = sqlite3_prepare(db, query, strlen(query), &stmt, NULL);
1585         if (ret != SQLITE_OK) {
1586                 NOTIFICATION_ERR("Select Query : %s", query);
1587                 NOTIFICATION_ERR("Select DB error(%d) : %s", ret,
1588                                  sqlite3_errmsg(db));
1589
1590                 ret = NOTIFICATION_ERROR_FROM_DB;
1591                 goto err;
1592         }
1593
1594         while (sqlite3_step(stmt) == SQLITE_ROW) {
1595                 /* Make notification list */
1596                 noti = _notification_noti_get_item(stmt);
1597                 if (noti != NULL) {
1598                         internal_count++;
1599
1600                         get_list = notification_list_append(get_list, noti);
1601
1602                         if (count != -1 && internal_count >= count) {
1603                                 NOTIFICATION_INFO
1604                                     ("internal count %d >= count %d",
1605                                      internal_count, count);
1606                                 break;
1607                         }
1608                 }
1609         }
1610
1611         ret = NOTIFICATION_ERROR_NONE;
1612
1613 err:
1614         if (stmt) {
1615                 sqlite3_finalize(stmt);
1616         }
1617
1618         /* Close DB */
1619         if (db) {
1620                 notification_db_close(&db);
1621         }
1622
1623         if (get_list != NULL) {
1624                 *list = notification_list_get_head(get_list);
1625         }
1626
1627         return ret;
1628 }
1629
1630 int notification_noti_get_detail_list(const char *pkgname,
1631                                                        int group_id,
1632                                                        int priv_id, int count,
1633                                                        notification_list_h *list)
1634 {
1635         sqlite3 *db = NULL;
1636         sqlite3_stmt *stmt = NULL;
1637         char query_base[NOTIFICATION_QUERY_MAX] = { 0, };
1638         char query_where[NOTIFICATION_QUERY_MAX] = { 0, };
1639
1640         char query[NOTIFICATION_QUERY_MAX] = { 0, };
1641         int ret = 0;
1642         notification_list_h get_list = NULL;
1643         notification_h noti = NULL;
1644         int internal_count = 0;
1645         int internal_group_id = 0;
1646         int status = 0; /* If the vconf_get_int failed, the status will be the garbage value */
1647
1648         /* Open DB */
1649         db = notification_db_open(DBPATH);
1650         if (!db) {
1651                 return get_last_result();
1652         }
1653
1654         /* Check current sim status */
1655         ret = vconf_get_int(VCONFKEY_TELEPHONY_SIM_SLOT, &status);
1656
1657         /* Make query */
1658         snprintf(query_base, sizeof(query_base), "select "
1659                  "type, layout, caller_pkgname, launch_pkgname, image_path, group_id, priv_id, "
1660                  "tag, b_text, b_key, b_format_args, num_format_args, "
1661                  "text_domain, text_dir, time, insert_time, args, group_args, "
1662                  "b_execute_option, b_service_responding, b_service_single_launch, b_service_multi_launch, "
1663                  "sound_type, sound_path, vibration_type, vibration_path, led_operation, led_argb, led_on_ms, led_off_ms, "
1664                  "flags_for_property, display_applist, progress_size, progress_percentage "
1665                  "from noti_list ");
1666
1667         if (priv_id == NOTIFICATION_PRIV_ID_NONE && group_id == NOTIFICATION_GROUP_ID_NONE) {
1668                 if (status == VCONFKEY_TELEPHONY_SIM_INSERTED) {
1669                         snprintf(query_where, sizeof(query_where),
1670                                  "where  caller_pkgname = '%s' ", pkgname);
1671                 } else {
1672                         snprintf(query_where, sizeof(query_where),
1673                                  "where  caller_pkgname = '%s' and flag_simmode = 0 ", pkgname);
1674                 }
1675         } else {
1676                 internal_group_id =
1677                     _notification_noti_get_internal_group_id_by_priv_id(pkgname,
1678                                                                         priv_id, db);
1679
1680                 if (status == VCONFKEY_TELEPHONY_SIM_INSERTED) {
1681                         snprintf(query_where, sizeof(query_where),
1682                                  "where  caller_pkgname = '%s' and internal_group_id = %d ",
1683                                  pkgname, internal_group_id);
1684                 } else {
1685                         snprintf(query_where, sizeof(query_where),
1686                                  "where  caller_pkgname = '%s' and internal_group_id = %d and flag_simmode = 0 ",
1687                                  pkgname, internal_group_id);
1688                 }
1689         }
1690
1691         snprintf(query, sizeof(query),
1692                  "%s %s "
1693                  "order by rowid desc, time desc", query_base, query_where);
1694
1695         ret = sqlite3_prepare(db, query, strlen(query), &stmt, NULL);
1696         if (ret != SQLITE_OK) {
1697                 NOTIFICATION_ERR("Select Query : %s", query);
1698                 NOTIFICATION_ERR("Select DB error(%d) : %s", ret,
1699                                  sqlite3_errmsg(db));
1700
1701                 ret = NOTIFICATION_ERROR_FROM_DB;
1702                 goto err;
1703         }
1704
1705         while (sqlite3_step(stmt) == SQLITE_ROW) {
1706                 /* Make notification list */
1707                 noti = _notification_noti_get_item(stmt);
1708                 if (noti != NULL) {
1709                         internal_count++;
1710
1711                         get_list = notification_list_append(get_list, noti);
1712
1713                         if (count != -1 && internal_count >= count) {
1714                                 NOTIFICATION_INFO
1715                                     ("internal count %d >= count %d",
1716                                      internal_count, count);
1717                                 break;
1718                         }
1719                 }
1720         }
1721
1722         ret = NOTIFICATION_ERROR_NONE;
1723
1724 err:
1725         if (stmt) {
1726                 sqlite3_finalize(stmt);
1727         }
1728
1729         /* Close DB */
1730         if (db) {
1731                 notification_db_close(&db);
1732         }
1733
1734         if (get_list != NULL) {
1735                 *list = notification_list_get_head(get_list);
1736         }
1737
1738         return ret;
1739 }
1740
1741 EXPORT_API int notification_noti_check_tag(notification_h noti)
1742 {
1743         int result = 0;
1744         int ret = NOTIFICATION_ERROR_NONE;
1745         char *query = NULL;
1746         sqlite3 *db;
1747         sqlite3_stmt *stmt = NULL;
1748
1749         if (noti->tag == NULL) {
1750                 return NOTIFICATION_ERROR_NOT_EXIST_ID;
1751         }
1752
1753         /* Open DB */
1754         db = notification_db_open(DBPATH);
1755         if (!db) {
1756                 return get_last_result();
1757         }
1758
1759         ret = sqlite3_prepare_v2(db, "SELECT priv_id FROM noti_list WHERE caller_pkgname = ? and tag = ?", -1, &stmt, NULL);
1760         if (ret != SQLITE_OK) {
1761                 NOTIFICATION_ERR("Error: %s\n", sqlite3_errmsg(db));
1762                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
1763         }
1764
1765         ret = sqlite3_bind_text(stmt, 1, noti->caller_pkgname, -1, SQLITE_TRANSIENT);
1766         if (ret != SQLITE_OK) {
1767                 NOTIFICATION_ERR("Error: %s\n", sqlite3_errmsg(db));
1768                 goto err;
1769         }
1770
1771         ret = sqlite3_bind_text(stmt, 2, noti->tag, -1, SQLITE_TRANSIENT);
1772         if (ret != SQLITE_OK) {
1773                 NOTIFICATION_ERR("Error: %s\n", sqlite3_errmsg(db));
1774                 goto err;
1775         }
1776
1777 /*
1778         query = sqlite3_mprintf("select priv_id from noti_list where caller_pkgname = '%s' and tag = '%s'",
1779                  noti->caller_pkgname, noti->tag);
1780         if (query == NULL) {
1781                 ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
1782                 goto err;
1783         }
1784
1785         ret = sqlite3_prepare(db, query, strlen(query), &stmt, NULL);
1786         if (ret != SQLITE_OK) {
1787                 NOTIFICATION_ERR("Get priv id DB err(%d) : %s", ret,
1788                                  sqlite3_errmsg(db));
1789                 ret = NOTIFICATION_ERROR_FROM_DB;
1790                 goto err;
1791         }
1792 */
1793         ret = sqlite3_step(stmt);
1794         if (ret == SQLITE_ROW) {
1795                 result = sqlite3_column_int(stmt, 0);
1796         } else {
1797                 result = 0;
1798         }
1799
1800         sqlite3_finalize(stmt);
1801
1802         /* If result > 0, there is priv_id in DB */
1803         if (result > 0) {
1804                 noti->priv_id = result;
1805                 ret = NOTIFICATION_ERROR_ALREADY_EXIST_ID;
1806         } else {
1807                 ret = NOTIFICATION_ERROR_NOT_EXIST_ID;
1808         }
1809
1810 err:
1811         if (query) {
1812                 sqlite3_free(query);
1813         }
1814
1815         return ret;
1816 }
1817
1818 static void
1819 popup_timeout_cb(void *data, Evas_Object *obj, void *event_info)
1820 {
1821         Eina_List *list = NULL;
1822         char *msg = NULL;
1823         int count = 0;
1824
1825         evas_object_del(toast_popup);
1826         toast_popup = NULL;
1827         evas_object_del((Evas_Object *)data);
1828
1829         count = eina_list_count(toast_list);
1830
1831         if (count == 1){
1832                 msg = (char *)eina_list_data_get(toast_list);
1833                 free(msg);
1834
1835                 eina_list_free(toast_list);
1836                 toast_list = NULL;
1837         } else if (count > 1) {
1838                 msg = (char *)eina_list_data_get(toast_list);
1839                 toast_list = eina_list_remove(toast_list, msg);
1840                 free(msg);
1841                 _post_toast_message((char *)eina_list_data_get(toast_list));
1842         }
1843 }
1844
1845 int _post_toast_message(char *message)
1846 {
1847         int let = 0;
1848         Evas_Object *toast_window;
1849         Evas *e;
1850         Ecore_Evas *ee;
1851         double scale = elm_config_scale_get();
1852
1853
1854         toast_window = elm_win_add(NULL, "toast", ELM_WIN_BASIC);
1855
1856         elm_win_alpha_set(toast_window, EINA_TRUE);
1857         elm_win_title_set(toast_window, "toast");
1858
1859         elm_win_indicator_mode_set(toast_window, ELM_WIN_INDICATOR_SHOW);
1860         elm_win_indicator_type_set(toast_window,ELM_WIN_INDICATOR_TYPE_1);
1861
1862         //elm_win_autodel_set(toast_win, EINA_TRUE);
1863         if (elm_win_wm_rotation_supported_get(toast_window)) {
1864                 int rots[4] = { 0, 90, 180, 270 };
1865                 elm_win_wm_rotation_available_rotations_set(toast_window, (const int*)(&rots), 4);
1866         }
1867
1868         e = evas_object_evas_get(toast_window);
1869         ee = ecore_evas_ecore_evas_get(e);
1870         ecore_evas_name_class_set(ee, "TOAST_POPUP", "SYSTEM_POPUP");
1871
1872         evas_object_resize(toast_window, (480 * scale), (650 * scale));
1873         ecore_x_window_shape_input_rectangle_set(elm_win_xwindow_get(toast_window), 0, 0, (480 * scale), (650 * scale));
1874
1875         toast_popup = elm_popup_add(toast_window);
1876
1877         elm_object_style_set(toast_popup, "toast");
1878         evas_object_size_hint_weight_set(toast_popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1879
1880         elm_object_part_text_set(toast_popup,"elm.text", message);
1881
1882         if (eina_list_count(toast_list) != 1) {
1883                 elm_popup_timeout_set(toast_popup, 1.0);
1884         }
1885         else {
1886                 elm_popup_timeout_set(toast_popup, 3.0);
1887         }
1888         evas_object_smart_callback_add(toast_popup, "timeout", popup_timeout_cb, (void *)toast_window);
1889
1890         elm_win_prop_focus_skip_set(toast_window, EINA_TRUE);
1891
1892         evas_object_show(toast_window);
1893         evas_object_show(toast_popup);
1894
1895         return 0;
1896 }
1897
1898 EXPORT_API int notification_noti_post_toast_message(const char *message)
1899 {
1900         int let = 0;
1901         char *msg = NULL;
1902         int count = 0;
1903
1904         msg = (char *)calloc(strlen(message) + 1, sizeof(char));
1905         strcpy(msg, message);
1906
1907 /*
1908         if (eina_list_count(toast_list) == 10) {
1909                 toast_list = eina_list_last(toast_list);
1910                 eina_list_data_set(toast_list, msg);
1911                 toast_list = eina_list_nth_list(toast_list, 0);
1912         }
1913         else {
1914 */
1915
1916         count = eina_list_count(toast_list);
1917         if (count == 0) {
1918                 toast_list = eina_list_append(toast_list, msg);
1919                 let = _post_toast_message(msg);
1920         }
1921         else if (count == 1) {
1922                 if (strcmp(msg, (char *)eina_list_nth(toast_list, count - 1)) == 0) {
1923                         elm_popup_timeout_set(toast_popup, 3.0);
1924                 }
1925                 else {
1926                         toast_list = eina_list_append(toast_list, msg);
1927                         elm_popup_timeout_set(toast_popup, 1.0);
1928                 }
1929         }
1930         else if (count >= 2) {
1931                 if (strcmp(msg, (char *)eina_list_nth(toast_list, count - 1)) == 0) {
1932                         free(msg);
1933                         return 0;
1934                 }
1935                 else {
1936                         toast_list = eina_list_append(toast_list, msg);
1937                 }
1938         }
1939
1940         return 0;
1941 }