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