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