a5e76d483fca002d09b93bed5979225f5b37da9c
[platform/core/pim/calendar-service.git] / server / db / cal_db_plugin_event_helper.c
1 /*
2  * Calendar Service
3  *
4  * Copyright (c) 2012 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <stdlib.h>
21
22 #include "cal_internal.h"
23 #include "cal_typedef.h"
24 #include "cal_view.h"
25 #include "cal_record.h"
26 #include "cal_time.h"
27 #include "cal_access_control.h"
28 #include "cal_db_query.h"
29 #include "cal_db_rrule.h"
30 #include "cal_db_query.h"
31 #include "cal_db_plugin_alarm_helper.h"
32 #include "cal_db_instance.h"
33 #include "cal_db_plugin_attendee_helper.h"
34 #include "cal_db_plugin_extended_helper.h"
35 #include "cal_db_plugin_event_helper.h"
36 #include "cal_db_plugin_timezone_helper.h"
37 #include "cal_db.h"
38 #include "cal_db_util.h"
39 #include "cal_utils.h"
40
41 enum {
42         CAL_RECURRENCE_ID_RANGE_NONE,
43         CAL_RECURRENCE_ID_RANGE_THISANDFUTURE,
44         CAL_RECURRENCE_ID_RANGE_THISANDPRIOR,
45         CAL_RECURRENCE_ID_RANGE_MAX,
46 };
47
48 #define DEBUG_DATETIME(x) DBG("%04d-%02d-%02dT%02d:%02d:%02d",\
49                 x->time.date.year,\
50                 x->time.date.month,\
51                 x->time.date.mday,\
52                 x->time.date.hour,\
53                 x->time.date.minute,\
54                 x->time.date.second)
55
56 int cal_db_event_update_original_event_version(int original_event_id, int version)
57 {
58         int ret = 0;
59         char query[CAL_DB_SQL_MAX_LEN] = {0};
60
61         DBG("original_event(%d) changed_ver updated", original_event_id);
62         if (0 < original_event_id) {
63                 snprintf(query, sizeof(query), "UPDATE %s SET changed_ver=%d, has_exception = 1 WHERE id=%d ",
64                                 CAL_TABLE_SCHEDULE, version, original_event_id);
65
66                 ret = cal_db_util_query_exec(query);
67                 if (CALENDAR_ERROR_NONE != ret) {
68                         ERR("cal_db_util_query_exec() Fail(%d)", ret);
69                         SECURE("[%s]", query);
70                         return ret;
71                 }
72         }
73         return CALENDAR_ERROR_NONE;
74 }
75
76 int cal_db_event_check_value_validation(cal_event_s *event)
77 {
78         long long int slli = 0;
79         long long int elli = 0;
80
81         RETV_IF(NULL == event, CALENDAR_ERROR_INVALID_PARAMETER);
82
83         if (event->start.type != event->end.type) {
84                 ERR("normal end(%lld) < start(%lld)",
85                                 event->end.time.utime, event->start.time.utime);
86                 return CALENDAR_ERROR_INVALID_PARAMETER;
87         }
88
89         switch (event->start.type) {
90         case CALENDAR_TIME_UTIME:
91                 if (event->end.time.utime < event->start.time.utime) {
92                         ERR("normal end(%lld) < start(%lld) so set same", event->end.time.utime, event->start.time.utime);
93                         event->end.time.utime =  event->start.time.utime;
94                         return CALENDAR_ERROR_INVALID_PARAMETER;
95                 }
96                 break;
97
98         case CALENDAR_TIME_LOCALTIME:
99                 /* check invalid value */
100                 if (event->start.time.date.month < 1 || 12 < event->start.time.date.month) {
101                         ERR("Error check start month(input:%d)", event->start.time.date.month);
102                         return CALENDAR_ERROR_INVALID_PARAMETER;
103                 } else if (event->start.time.date.mday < 1 || 31 < event->start.time.date.mday) {
104                         ERR("Error check start mday(input:%d)", event->start.time.date.mday);
105                         return CALENDAR_ERROR_INVALID_PARAMETER;
106                 } else if (event->end.time.date.month < 1 || 12 < event->end.time.date.month) {
107                         ERR("Error check end month(input:%d)", event->end.time.date.month);
108                         return CALENDAR_ERROR_INVALID_PARAMETER;
109                 } else if (event->end.time.date.mday < 1 || 31 < event->end.time.date.mday) {
110                         ERR("Error check end mday(input:%d)", event->end.time.date.mday);
111                         return CALENDAR_ERROR_INVALID_PARAMETER;
112                 } else {
113                         /* handle hour, minute, second */
114                         if (event->start.time.date.hour < 0 || 24 < event->start.time.date.hour)
115                                 event->start.time.date.hour = 0;
116                         if (event->start.time.date.minute < 0 || 60 < event->start.time.date.minute)
117                                 event->start.time.date.minute = 0;
118                         if (event->start.time.date.second < 0 || 60 < event->start.time.date.second)
119                                 event->start.time.date.second = 0;
120                         if (event->end.time.date.hour < 0 || 24 < event->end.time.date.hour)
121                                 event->end.time.date.hour = 0;
122                         if (event->end.time.date.minute < 0 || 60 < event->end.time.date.minute)
123                                 event->end.time.date.minute = 0;
124                         if (event->end.time.date.second < 0 || 60 < event->end.time.date.second)
125                                 event->end.time.date.second = 0;
126                 }
127
128                 /* check end < start; convert long long int */
129                 slli = cal_time_convert_itol(NULL,
130                                 event->start.time.date.year, event->start.time.date.month, event->start.time.date.mday,
131                                 event->start.time.date.hour, event->start.time.date.minute, event->start.time.date.second);
132                 elli = cal_time_convert_itol(NULL,
133                                 event->end.time.date.year, event->end.time.date.month, event->end.time.date.mday,
134                                 event->end.time.date.hour, event->end.time.date.minute, event->end.time.date.second);
135
136                 if (1 < slli - elli) {
137                         /* 1 is to ignore milliseconds */
138                         ERR("allday end(%lld) < start(%lld) so set same", elli, slli);
139                         return CALENDAR_ERROR_INVALID_PARAMETER;
140                 }
141                 break;
142         }
143
144         return CALENDAR_ERROR_NONE;
145 }
146
147 GList* cal_db_event_get_list_with_uid(char *uid, int parent_id)
148 {
149         int ret = 0;
150         RETV_IF(NULL == uid, NULL);
151         RETV_IF('\0' == *uid, NULL);
152
153         char query[CAL_DB_SQL_MAX_LEN] = {0};
154         snprintf(query, sizeof(query), "SELECT id FROM %s WHERE original_event_id=-1 AND uid LIKE '%s' AND id!=%d",
155                         CAL_TABLE_SCHEDULE, uid, parent_id);
156
157         sqlite3_stmt *stmt = NULL;
158         ret = cal_db_util_query_prepare(query, &stmt);
159         if (CALENDAR_ERROR_NONE != ret) {
160                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
161                 SECURE("query[%s]", query);
162                 return NULL;
163         }
164
165         GList *l = NULL;
166         while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
167                 int id = sqlite3_column_int(stmt, 0);
168                 l = g_list_append(l, GINT_TO_POINTER(id));
169         }
170         sqlite3_finalize(stmt);
171         return l;
172 }
173
174 void cal_db_event_update_child_origina_event_id(int child_id, int parent_id)
175 {
176         CAL_FN_CALL();
177
178         int ret = 0;
179         char query[CAL_DB_SQL_MAX_LEN] = {0};
180         snprintf(query, sizeof(query), "UPDATE %s SET original_event_id=%d WHERE id=%d",
181                         CAL_TABLE_SCHEDULE, parent_id, child_id);
182         ret = cal_db_util_query_exec(query);
183         if (CALENDAR_ERROR_NONE != ret) {
184                 ERR("cal_db_util_query_exec() Fail(%d)", ret);
185                 SECURE("[%s]", query);
186         }
187 }
188
189 char* cal_db_event_get_recurrence_id_from_exception(int child_id)
190 {
191         int ret = 0;
192         char query[CAL_DB_SQL_MAX_LEN] = {0};
193         snprintf(query, sizeof(query), "SELECT recurrence_id FROM %s WHERE id=%d",
194                         CAL_TABLE_SCHEDULE, child_id);
195
196         sqlite3_stmt *stmt = NULL;
197         ret = cal_db_util_query_prepare(query, &stmt);
198         if (CALENDAR_ERROR_NONE != ret) {
199                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
200                 SECURE("query[%s]", query);
201                 return NULL;
202         }
203
204         char *recurrence_id = NULL;
205         if (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt))
206                 recurrence_id = cal_strdup((const char*)sqlite3_column_text(stmt, 0));
207
208         sqlite3_finalize(stmt);
209         return recurrence_id;
210 }
211
212 static void __get_tzid_and_range(char *p, char **out_tzid, int *out_range)
213 {
214         RET_IF(NULL == p);
215         RET_IF('\0' == *p);
216         RET_IF(NULL == out_tzid);
217         RET_IF(NULL == out_range);
218
219         char **s = NULL;
220         s = g_strsplit(p, ";", -1);
221         RETM_IF(NULL == s, "g_strsplit() Fail");
222
223         int count = g_strv_length(s);
224         int i;
225         char *tzid = NULL;
226         int range = CAL_RECURRENCE_ID_RANGE_NONE;
227         for (i = 0; i < count; i++) {
228                 if (NULL == s[i] || '\0' == *s[i])
229                         continue;
230
231                 if (CAL_STRING_EQUAL == strncmp(s[i], "TZID=", strlen("TZID="))) {
232                         if (tzid)
233                                 continue;
234                         tzid = strdup(s[i] + strlen("TZID="));
235                         DBG("tzid [%s]", tzid);
236                 } else if (CAL_STRING_EQUAL == strncmp(s[i], "RANGE=", strlen("RANGE="))) {
237                         char *param = s[i] + strlen("RANGE=");
238                         if (CAL_STRING_EQUAL == strncmp(param, "THISANDFUTURE", strlen("THISANDFUTURE")))
239                                 range = CAL_RECURRENCE_ID_RANGE_THISANDFUTURE;
240                         else if (CAL_STRING_EQUAL == strncmp(param, "THISANDPRIOR", strlen("THISANDPRIOR")))
241                                 range = CAL_RECURRENCE_ID_RANGE_THISANDPRIOR;
242                         else
243                                 ERR("Invalid param[%s]", s[i]);
244                 } else {
245                         ERR("Invalid param[%s]", s[i]);
246                 }
247         }
248         *out_tzid = tzid;
249         *out_range = range;
250         g_strfreev(s);
251 }
252
253 static void cal_db_event_apply_recurrence_id_child(int child_id, cal_event_s *event, calendar_time_s until, bool is_prior)
254 {
255         int ret = 0;
256         calendar_record_h record = NULL;
257         ret = cal_db_get_record(_calendar_event._uri, child_id, &record);
258         RETM_IF(CALENDAR_ERROR_NONE != ret, "cal_db_get_record() Fail(%d)", ret);
259
260         if (true == is_prior) {
261                 cal_record_set_caltime(record, _calendar_event.start_time, event->start);
262                 cal_record_set_caltime(record, _calendar_event.end_time, event->end);
263                 switch (event->start.type) {
264                 case CALENDAR_TIME_UTIME:
265                         DBG("dtstart(%lld) dtend(%lld)", event->start.time.utime, event->end.time.utime);
266                         break;
267                 case CALENDAR_TIME_LOCALTIME:
268                         DBG("dtstart(%04d-%02d-%02dT%02d:%02d:%02d) dtend(%04d-%02d-%02dT%02d:%02d:%02d)",
269                                         event->start.time.date.year, event->start.time.date.month, event->start.time.date.mday,
270                                         event->start.time.date.hour, event->start.time.date.minute, event->start.time.date.second,
271                                         event->end.time.date.year, event->end.time.date.month, event->end.time.date.mday,
272                                         event->end.time.date.hour, event->end.time.date.minute, event->end.time.date.second);
273                         break;
274                 }
275         }
276
277         cal_record_set_int(record, _calendar_event.freq, event->freq);
278         cal_record_set_int(record, _calendar_event.interval, event->interval);
279         cal_record_set_int(record, _calendar_event.wkst, event->wkst);
280         if (event->byyearday && *event->byyearday)
281                 cal_record_set_str(record, _calendar_event.byyearday, event->byyearday);
282         if (event->byweekno && *event->byweekno)
283                 cal_record_set_str(record, _calendar_event.byweekno, event->byweekno);
284         if (event->bymonth && *event->bymonth)
285                 cal_record_set_str(record, _calendar_event.bymonth, event->bymonth);
286         if (event->bymonthday && *event->bymonthday)
287                 cal_record_set_str(record, _calendar_event.bymonthday, event->bymonthday);
288         if (event->byday && *event->byday)
289                 cal_record_set_str(record, _calendar_event.byday, event->byday);
290         if (event->bysetpos && *event->bysetpos)
291                 cal_record_set_str(record, _calendar_event.bysetpos, event->bysetpos);
292
293         /* until */
294         cal_record_set_int(record, _calendar_event.range_type, CALENDAR_RANGE_UNTIL);
295         cal_record_set_caltime(record, _calendar_event.until_time, until);
296
297         /* reset */
298         cal_record_set_str(record, _calendar_event.uid, "");
299         cal_record_set_int(record, _calendar_event.original_event_id, -1);
300
301         cal_db_update_record(record);
302         calendar_record_destroy(record, true);
303 }
304 static void __get_next_instance_caltime(int parent_id, calendar_time_s *caltime, calendar_time_s *dtstart, calendar_time_s *dtend)
305 {
306         int ret = 0;
307         char query[CAL_DB_SQL_MAX_LEN] = {0};
308         sqlite3_stmt *stmt = NULL;
309
310         switch (caltime->type) {
311         case CALENDAR_TIME_UTIME:
312                 snprintf(query, sizeof(query), "SELECT dtstart_utime, dtend_utime FROM %s WHERE event_id=%d AND dtstart_utime>%lld "
313                                 "ORDER BY dtstart_utime ASC LIMIT 1",
314                                 CAL_TABLE_NORMAL_INSTANCE, parent_id, caltime->time.utime);
315
316                 ret = cal_db_util_query_prepare(query, &stmt);
317                 if (CALENDAR_ERROR_NONE != ret) {
318                         ERR("cal_db_util_query_prepare() Fail(%d)", ret);
319                         SECURE("query[%s]", query);
320                         return;
321                 }
322
323                 while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
324                         dtstart->type = CALENDAR_TIME_UTIME;
325                         dtstart->time.utime = sqlite3_column_int64(stmt, 0);
326                         dtend->type = CALENDAR_TIME_UTIME;
327                         dtend->time.utime = sqlite3_column_int64(stmt, 0);
328                         break;
329                 }
330                 break;
331         case CALENDAR_TIME_LOCALTIME:
332                 snprintf(query, sizeof(query), "SELECT dtstart_datetime, dtend_datetime FROM %s "
333                                 "WHERE event_id=%d AND dtstart_datetime>'%04d-%02d-%02dT%02d:%02d:%02d' "
334                                 "ORDER BY dtstart_datetime ASC LIMIT 1",
335                                 CAL_TABLE_ALLDAY_INSTANCE, parent_id,
336                                 caltime->time.date.year, caltime->time.date.month, caltime->time.date.mday,
337                                 caltime->time.date.hour, caltime->time.date.minute, caltime->time.date.second);
338
339                 ret = cal_db_util_query_prepare(query, &stmt);
340                 if (CALENDAR_ERROR_NONE != ret) {
341                         ERR("cal_db_util_query_prepare() Fail(%d)", ret);
342                         SECURE("query[%s]", query);
343                         return;
344                 }
345
346                 if (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
347                         char *temp = NULL;
348                         dtstart->type = CALENDAR_TIME_LOCALTIME;
349                         temp = (char *)sqlite3_column_text(stmt, 0);
350                         if (temp && *temp) {
351                                 sscanf(temp, CAL_FORMAT_LOCAL_DATETIME,
352                                                 &(dtstart->time.date.year), &(dtstart->time.date.month), &(dtstart->time.date.mday),
353                                                 &(dtstart->time.date.hour), &(dtstart->time.date.minute), &(dtstart->time.date.second));
354                         }
355                         dtend->type = CALENDAR_TIME_LOCALTIME;
356                         temp = (char *)sqlite3_column_text(stmt, 1);
357                         if (temp && *temp) {
358                                 sscanf(temp, CAL_FORMAT_LOCAL_DATETIME,
359                                                 &(dtend->time.date.year), &(dtend->time.date.month), &(dtend->time.date.mday),
360                                                 &(dtend->time.date.hour), &(dtend->time.date.minute), &(dtend->time.date.second));
361                         }
362                 }
363                 break;
364         }
365         sqlite3_finalize(stmt);
366 }
367 static void __get_last_instance_caltime(int parent_id, int type, calendar_time_s *dtstart)
368 {
369         int ret = 0;
370         char query[CAL_DB_SQL_MAX_LEN] = {0};
371         sqlite3_stmt *stmt = NULL;
372
373         switch (type) {
374         case CALENDAR_TIME_UTIME:
375                 snprintf(query, sizeof(query), "SELECT dtstart_utime FROM %s WHERE event_id=%d "
376                                 "ORDER BY dtstart_utime DESC LIMIT 1",
377                                 CAL_TABLE_NORMAL_INSTANCE, parent_id);
378                 ret = cal_db_util_query_prepare(query, &stmt);
379                 if (CALENDAR_ERROR_NONE != ret) {
380                         ERR("cal_db_util_query_prepare() Fail(%d)", ret);
381                         SECURE("query[%s]", query);
382                         return;
383                 }
384                 while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
385                         dtstart->type = CALENDAR_TIME_UTIME;
386                         dtstart->time.utime = sqlite3_column_int64(stmt, 0);
387                         break;
388                 }
389                 break;
390         case CALENDAR_TIME_LOCALTIME:
391                 snprintf(query, sizeof(query), "SELECT dtstart_datetime FROM %s WHERE event_id=%d "
392                                 "ORDER BY dtstart_datetime DESC LIMIT 1",
393                                 CAL_TABLE_ALLDAY_INSTANCE, parent_id);
394                 ret = cal_db_util_query_prepare(query, &stmt);
395                 if (CALENDAR_ERROR_NONE != ret) {
396                         ERR("cal_db_util_query_prepare() Fail(%d)", ret);
397                         SECURE("query[%s]", query);
398                         return;
399                 }
400                 if (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
401                         char *temp = NULL;
402                         dtstart->type = CALENDAR_TIME_LOCALTIME;
403                         temp = (char *)sqlite3_column_text(stmt, 0);
404                         if (temp && *temp) {
405                                 sscanf(temp, CAL_FORMAT_LOCAL_DATETIME,
406                                                 &(dtstart->time.date.year), &(dtstart->time.date.month), &(dtstart->time.date.mday),
407                                                 &(dtstart->time.date.hour), &(dtstart->time.date.minute), &(dtstart->time.date.second));
408                         } else {
409                                 ERR("datetime is NULL");
410                         }
411                 }
412                 break;
413         }
414         sqlite3_finalize(stmt);
415 }
416
417 static void __del_recurence_id_instance(calendar_time_s *rectime, int parent_id)
418 {
419         int ret = 0;
420         char query[CAL_DB_SQL_MAX_LEN] = {0};
421         switch (rectime->type) {
422         case CALENDAR_TIME_UTIME:
423                 snprintf(query, sizeof(query), "DELETE FROM %s WHERE dtstart_utime=%lld AND event_id=%d",
424                                 CAL_TABLE_NORMAL_INSTANCE, rectime->time.utime, parent_id);
425                 break;
426         case CALENDAR_TIME_LOCALTIME:
427                 snprintf(query, sizeof(query), "DELETE FROM %s WHERE dtstart_datetime='%04d-%02d-%02dT%02d:%02d:%02d' AND event_id=%d",
428                                 CAL_TABLE_ALLDAY_INSTANCE, rectime->time.date.year, rectime->time.date.month, rectime->time.date.mday,
429                                 rectime->time.date.hour, rectime->time.date.minute, rectime->time.date.second, parent_id);
430                 break;
431         }
432         ret = cal_db_util_query_exec(query);
433         if (CALENDAR_ERROR_NONE != ret) {
434                 ERR("cal_db_util_query_exec() Fail(%d)", ret);
435                 SECURE("[%s]", query);
436                 return;
437         }
438
439         int y = 0, m = 0, d = 0;
440         int h = 0, n = 0, s = 0;
441         switch (rectime->type) {
442         case CALENDAR_TIME_UTIME:
443                 cal_time_get_datetime(rectime->time.utime, &y, &m, &d, &h, &n, &s);
444                 DBG("[DELETED] %04d-%02d-%02dT%02d:%02d:%02d (utime)", y, m, d, h, n, s);
445                 break;
446         case CALENDAR_TIME_LOCALTIME:
447                 DBG("[DELETED] %04d-%02d-%02dT%02d:%02d:%02d (local)",
448                                 rectime->time.date.year, rectime->time.date.month, rectime->time.date.mday,
449                                 rectime->time.date.hour, rectime->time.date.minute, rectime->time.date.second);
450                 break;
451         }
452 }
453
454 static void __set_original_event_id_in_child(int child_id, int parent_id)
455 {
456         int ret = 0;
457         char query[CAL_DB_SQL_MAX_LEN] = {0};
458         snprintf(query, sizeof(query), "UPDATE %s SET original_event_id=%d WHERE id=%d",
459                         CAL_TABLE_SCHEDULE, parent_id, child_id);
460
461         ret = cal_db_util_query_exec(query);
462         if (CALENDAR_ERROR_NONE != ret) {
463                 ERR("cal_db_util_query_exec() Fail(%d)", ret);
464                 SECURE("[%s]", query);
465         }
466 }
467
468 /*
469  * RECURRENCE-ID;VALUE=DATE:19960401
470  * RECURRENCE-ID;RANGE=THISANDFUTURE:19960120T120000Z
471  * RECURRENCE-ID;RANGE=THISANDPRIOR:19980401T133000Z
472  * RECURRENCE-ID;TZID=Asia/Seoul:20150106T090000
473  */
474 void cal_db_event_apply_recurrence_id(int parent_id, cal_event_s *event, char *recurrence_id, int child_id)
475 {
476         CAL_FN_CALL();
477
478         RET_IF(NULL == recurrence_id);
479         RET_IF('\0' == *recurrence_id);
480
481         char **t = NULL;
482         t =  g_strsplit(recurrence_id, ":", -1);
483         RETM_IF(NULL == t, "g_strsplit() Fail");
484
485         if ('\0' == *t[0]) { /* no param */
486                 g_strfreev(t);
487                 return;
488         }
489         int count = g_strv_length(t);
490         int len_param = strlen(t[count -1]);
491         *(recurrence_id + strlen(recurrence_id) - len_param -1) = '\0';
492         g_strfreev(t);
493
494         char *datetime = recurrence_id + strlen(recurrence_id) +1;
495         int len_datetime = strlen(datetime);
496         DBG("datetime[%s]", datetime);
497
498         char *tzid = NULL;
499         int range = CAL_RECURRENCE_ID_RANGE_NONE;
500         __get_tzid_and_range(recurrence_id, &tzid, &range);
501
502         int y = 0, m = 0, d = 0;
503         int h = 0, n = 0, s = 0;
504         char dtstart_datetime[CAL_STR_SHORT_LEN32] = {0};
505         long long int dtstart_utime = 0;
506         calendar_time_s rectime = {0};
507         switch (len_datetime) {
508         case 8:
509                 sscanf(datetime, CAL_DATETIME_FORMAT_YYYYMMDD, &y, &m, &d);
510                 snprintf(dtstart_datetime, sizeof(dtstart_datetime), CAL_FORMAT_LOCAL_DATETIME, y, m, d, 0, 0, 0);
511                 rectime.type = CALENDAR_TIME_LOCALTIME;
512                 rectime.time.date.year = y;
513                 rectime.time.date.month = m;
514                 rectime.time.date.mday = d;
515                 rectime.time.date.hour = 0;
516                 rectime.time.date.minute = 0;
517                 rectime.time.date.second = 0;
518                 break;
519         case 15:
520                 sscanf(datetime, CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSS, &y, &m, &d, &h, &n, &s);
521                 if (tzid && *tzid) {
522                         dtstart_utime = cal_time_convert_itol(tzid, y, m, d, h, n, s);
523                         rectime.type = CALENDAR_TIME_UTIME;
524                         rectime.time.utime = dtstart_utime;
525                 } else {
526                         snprintf(dtstart_datetime, sizeof(dtstart_datetime), CAL_FORMAT_LOCAL_DATETIME, y, m, d, h, n, s);
527                         rectime.type = CALENDAR_TIME_LOCALTIME;
528                         rectime.time.date.year = y;
529                         rectime.time.date.month = m;
530                         rectime.time.date.mday = d;
531                         rectime.time.date.hour = h;
532                         rectime.time.date.minute = n;
533                         rectime.time.date.second = s;
534                 }
535                 break;
536         case 16:
537                 sscanf(datetime, CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSSZ, &y, &m, &d, &h, &n, &s);
538                 dtstart_utime = cal_time_convert_itol(tzid, y, m, d, h, n, s);
539                 rectime.type = CALENDAR_TIME_UTIME;
540                 rectime.time.utime = dtstart_utime;
541                 break;
542         }
543         free(tzid);
544
545         calendar_time_s until = {0};
546         calendar_time_s dtstart = {0};
547         calendar_time_s dtend = {0};
548         calendar_record_h record = (calendar_record_h)event;
549         switch (range) {
550         case CAL_RECURRENCE_ID_RANGE_THISANDFUTURE:
551                 DBG("update child");
552                 switch (event->range_type) {
553                 case CALENDAR_RANGE_UNTIL:
554                 case CALENDAR_RANGE_NONE:
555                         until = event->start;
556                         break;
557                 case CALENDAR_RANGE_COUNT:
558                         __get_last_instance_caltime(parent_id, rectime.type, &until);
559                         break;
560                 }
561                 cal_db_event_apply_recurrence_id_child(child_id, event, until, false);
562
563                 DBG("update parent");
564                 until = rectime;
565                 cal_time_modify_caltime(&until, -1);
566                 cal_record_set_int(record, _calendar_event.range_type, CALENDAR_RANGE_UNTIL);
567                 cal_record_set_caltime(record, _calendar_event.until_time, until);
568                 cal_record_set_str(record, _calendar_event.recurrence_id, "");
569                 cal_record_set_str(record, _calendar_event.uid, "");
570                 cal_db_update_record(record);
571                 break;
572         case CAL_RECURRENCE_ID_RANGE_THISANDPRIOR:
573                 DBG("update child");
574                 until = rectime;
575                 cal_db_event_apply_recurrence_id_child(child_id, event, until, true);
576
577                 DBG("update parent");
578                 __get_next_instance_caltime(parent_id, &until, &dtstart, &dtend);
579                 cal_record_set_caltime(record, _calendar_event.start_time, dtstart);
580                 cal_record_set_caltime(record, _calendar_event.end_time, dtend);
581                 switch (event->range_type) {
582                 case CALENDAR_RANGE_UNTIL:
583                 case CALENDAR_RANGE_NONE:
584                         break;
585                 case CALENDAR_RANGE_COUNT:
586                         __get_last_instance_caltime(parent_id, rectime.type, &until);
587                         cal_record_set_int(record, _calendar_event.range_type, CALENDAR_RANGE_UNTIL);
588                         cal_record_set_caltime(record, _calendar_event.until_time, until);
589                         DBG(CAL_FORMAT_LOCAL_DATETIME,
590                                         until.time.date.year, until.time.date.month, until.time.date.mday,
591                                         until.time.date.hour, until.time.date.minute, until.time.date.second);
592                         break;
593                 }
594                 cal_record_set_str(record, _calendar_event.recurrence_id, "");
595                 cal_db_update_record(record);
596                 break;
597         default:
598                 __del_recurence_id_instance(&rectime, parent_id);
599                 __set_original_event_id_in_child(child_id, parent_id);
600                 break;
601         }
602 }
603 static int __get_parent_id_with_uid(char *uid, int child_id)
604 {
605         int ret = 0;
606         char query[CAL_DB_SQL_MAX_LEN] = {0};
607         int parent_id = -1;
608         snprintf(query, sizeof(query), "SELECT id FROM %s WHERE original_event_id=-1 AND id!=%d AND uid='%s'",
609                         CAL_TABLE_SCHEDULE, child_id, uid);
610
611         sqlite3_stmt *stmt = NULL;
612         ret = cal_db_util_query_prepare(query, &stmt);
613         if (CALENDAR_ERROR_NONE != ret) {
614                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
615                 SECURE("query[%s]", query);
616                 return ret;
617         }
618         if (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt))
619                 parent_id = sqlite3_column_int64(stmt, 0);
620
621         sqlite3_finalize(stmt);
622         DBG("found parent_id(%d)", parent_id);
623         return parent_id;
624 }
625
626 int cal_db_event_insert_record(calendar_record_h record, int original_event_id, int *id)
627 {
628         int ret = -1;
629         int event_id = -1;
630         int index;
631         int input_ver;
632         char query[CAL_DB_SQL_MAX_LEN] = {0};
633         char dtstart_datetime[CAL_STR_SHORT_LEN32] = {0};
634         char dtend_datetime[CAL_STR_SHORT_LEN32] = {0};
635         sqlite3_stmt *stmt = NULL;
636         cal_event_s* event =  (cal_event_s*)(record);
637         cal_rrule_s *rrule = NULL;
638         int tmp = 0;
639         int calendar_book_id = 0;
640         calendar_record_h record_calendar = NULL;
641         int has_alarm = 0;
642         int timezone_id = 0;
643
644         RETV_IF(NULL == event, CALENDAR_ERROR_INVALID_PARAMETER);
645
646         ret = cal_db_event_check_value_validation(event);
647         if (CALENDAR_ERROR_NONE != ret) {
648                 ERR("cal_db_event_check_value_validation() Fail(%d)", ret);
649                 return ret;
650         }
651
652         /* access control */
653         if (cal_access_control_have_write_permission(event->calendar_id) == false) {
654                 ERR("cal_access_control_have_write_permission() Fail");
655                 return CALENDAR_ERROR_PERMISSION_DENIED;
656         }
657
658         ret = calendar_record_get_int(record, _calendar_event.calendar_book_id, &calendar_book_id);
659         DBG("calendar_book_id(%d)", calendar_book_id);
660
661         ret = cal_db_get_record(_calendar_book._uri, calendar_book_id, &record_calendar);
662         RETVM_IF(CALENDAR_ERROR_NONE != ret, CALENDAR_ERROR_INVALID_PARAMETER, "cal_db_get_record() Fail(%d)", ret);
663
664         calendar_record_destroy(record_calendar, true);
665
666         has_alarm = cal_db_alarm_has_alarm(event->alarm_list);
667         cal_db_timezone_search_with_tzid(event->calendar_id, event->start_tzid, &timezone_id);
668         input_ver = cal_db_util_get_next_ver();
669
670         int is_allday = 0;
671         if (CALENDAR_TIME_LOCALTIME == event->start.type
672                         && (0 == event->start.time.date.hour)
673                         && (0 == event->start.time.date.minute)
674                         && (0 == event->start.time.date.second)
675                         && (0 == event->end.time.date.hour)
676                         && (0 == event->end.time.date.minute)
677                         && (0 == event->end.time.date.second)) {
678                 is_allday = 1;
679         }
680
681         snprintf(query, sizeof(query), "INSERT INTO %s ("
682                         "type, "
683                         "created_ver, changed_ver, "
684                         "summary, description, location, categories, exdate, "
685                         "task_status, priority, "
686                         "timezone, "
687                         "contact_id, busy_status, sensitivity, uid, "
688                         "organizer_name, organizer_email, meeting_status, "
689                         "calendar_id, "
690                         "original_event_id, "
691                         "latitude, longitude, "
692                         "email_id, "
693                         "created_time, completed_time, progress, "
694                         "dtstart_type, dtstart_utime, dtstart_datetime, dtstart_tzid, "
695                         "dtend_type, dtend_utime, dtend_datetime, dtend_tzid, "
696                         "last_mod, rrule_id, "
697                         "recurrence_id, rdate, has_attendee, "
698                         "has_alarm, system_type, updated, "
699                         "sync_data1, sync_data2, sync_data3, sync_data4,"
700                         "has_exception, has_extended, freq, is_allday "
701                         ") VALUES ("
702                         "%d, "
703                         "%d, %d, "
704                         "?, ?, ?, ?, ?, "
705                         "%d, %d, "
706                         "%d, "
707                         "%d, %d, %d, ?, "
708                         "?, ?, %d, "
709                         "%d, "
710                         "%d, "
711                         "%lf, %lf, "
712                         "%d, "
713                         "strftime('%%s', 'now'), %lld, %d, "
714                         "%d, %lld, ?, ?, "
715                         "%d, %lld, ?, ?, "
716                         "strftime('%%s', 'now'), %d, "
717                         "?, ?, %d, %d, %d, %d, "
718                         "?, ?, ?, ?, "
719                         "%d, %d, %d, %d) ",
720                 CAL_TABLE_SCHEDULE,
721                 CAL_SCH_TYPE_EVENT, /*event->cal_type,*/
722                 input_ver, input_ver,
723                 event->event_status, event->priority,
724                 event->timezone ? event->timezone : timezone_id,
725                 event->contact_id, event->busy_status, event->sensitivity,
726                 event->meeting_status,
727                 event->calendar_id,
728                 original_event_id,
729                 event->latitude, event->longitude,
730                 event->email_id,
731                 (long long int)0, 0, /* event->completed_time, event->progress */
732                 event->start.type, event->start.type == CALENDAR_TIME_UTIME ? event->start.time.utime : 0,
733                 event->end.type, event->end.type == CALENDAR_TIME_UTIME ? event->end.time.utime : 0,
734                 0 < event->freq ? 1 : 0,
735                 (0 < event->attendee_list->count) ? 1 : 0,
736                 has_alarm,
737                 event->system_type,
738                 event->updated,
739                 (0 < event->exception_list->count) ? 1 : 0,
740                 (0 < event->extended_list->count) ? 1 : 0,
741                 event->freq, is_allday);
742
743         ret = cal_db_util_query_prepare(query, &stmt);
744         if (CALENDAR_ERROR_NONE != ret) {
745                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
746                 SECURE("query[%s]", query);
747                 return ret;
748         }
749
750         index = 1;
751
752         if (event->summary)
753                 cal_db_util_stmt_bind_text(stmt, index, event->summary);
754         index++;
755
756         if (event->description)
757                 cal_db_util_stmt_bind_text(stmt, index, event->description);
758         index++;
759
760         if (event->location)
761                 cal_db_util_stmt_bind_text(stmt, index, event->location);
762         index++;
763
764         if (event->categories)
765                 cal_db_util_stmt_bind_text(stmt, index, event->categories);
766         index++;
767
768         if (event->exdate)
769                 cal_db_util_stmt_bind_text(stmt, index, event->exdate);
770         index++;
771
772         if (event->uid)
773                 cal_db_util_stmt_bind_text(stmt, index, event->uid);
774         index++;
775
776         if (event->organizer_name)
777                 cal_db_util_stmt_bind_text(stmt, index, event->organizer_name);
778         index++;
779
780         if (event->organizer_email)
781                 cal_db_util_stmt_bind_text(stmt, index, event->organizer_email);
782         index++;
783
784         if (CALENDAR_TIME_LOCALTIME == event->start.type) {
785                 snprintf(dtstart_datetime, sizeof(dtstart_datetime), CAL_FORMAT_LOCAL_DATETIME,
786                                 event->start.time.date.year,
787                                 event->start.time.date.month,
788                                 event->start.time.date.mday,
789                                 event->start.time.date.hour,
790                                 event->start.time.date.minute,
791                                 event->start.time.date.second);
792                 cal_db_util_stmt_bind_text(stmt, index, dtstart_datetime);
793         }
794         index++;
795
796         if (event->start_tzid)
797                 cal_db_util_stmt_bind_text(stmt, index, event->start_tzid);
798         index++;
799
800         if (CALENDAR_TIME_LOCALTIME == event->end.type) {
801                 snprintf(dtend_datetime, sizeof(dtend_datetime), CAL_FORMAT_LOCAL_DATETIME,
802                                 event->end.time.date.year,
803                                 event->end.time.date.month,
804                                 event->end.time.date.mday,
805                                 event->end.time.date.hour,
806                                 event->end.time.date.minute,
807                                 event->end.time.date.second);
808                 cal_db_util_stmt_bind_text(stmt, index, dtend_datetime);
809         }
810         index++;
811
812         if (event->end_tzid)
813                 cal_db_util_stmt_bind_text(stmt, index, event->end_tzid);
814         index++;
815
816         if (event->recurrence_id)
817                 cal_db_util_stmt_bind_text(stmt, index, event->recurrence_id);
818         index++;
819
820         if (event->rdate)
821                 cal_db_util_stmt_bind_text(stmt, index, event->rdate);
822         index++;
823
824         if (event->sync_data1)
825                 cal_db_util_stmt_bind_text(stmt, index, event->sync_data1);
826         index++;
827
828         if (event->sync_data2)
829                 cal_db_util_stmt_bind_text(stmt, index, event->sync_data2);
830         index++;
831
832         if (event->sync_data3)
833                 cal_db_util_stmt_bind_text(stmt, index, event->sync_data3);
834         index++;
835
836         if (event->sync_data4)
837                 cal_db_util_stmt_bind_text(stmt, index, event->sync_data4);
838         index++;
839
840         ret = cal_db_util_stmt_step(stmt);
841         sqlite3_finalize(stmt);
842         if (CALENDAR_ERROR_NONE != ret) {
843                 ERR("cal_db_util_stmt_step() Fail(%d)", ret);
844                 return ret;
845         }
846         event_id = cal_db_util_last_insert_id();
847
848         /*
849          * update parent event changed ver in case this event is exception mod
850          * which is original_event_id > 0
851          */
852         cal_db_event_update_original_event_version(original_event_id, input_ver);
853
854         calendar_record_get_int(record, _calendar_event.id, &tmp);
855         cal_record_set_int(record, _calendar_event.id, event_id);
856         if (id)
857                 *id = event_id;
858
859         cal_db_rrule_get_rrule_from_record(record, &rrule);
860         if (rrule) {
861                 cal_db_rrule_insert_record(event_id, rrule);
862                 CAL_FREE(rrule);
863         }
864
865         if (0 < original_event_id)
866                 cal_record_set_int(record, _calendar_event.original_event_id, original_event_id);
867
868         cal_db_instance_publish_record(record);
869
870         while (event->uid && *event->uid) {
871                 if (NULL == event->recurrence_id || '\0' == *event->recurrence_id) {
872                         DBG("this is parent");
873                         /*
874                          * parent exception event is inserted in case child exception existed already.
875                          * find child exceptions and link(one exception) or devide(this and future/prior)
876                          */
877
878                         GList *list = NULL;
879                         list = cal_db_event_get_list_with_uid(event->uid, event_id);
880                         if (NULL == list)
881                                 break;
882                         GList *l = g_list_first(list);
883                         if (l) {
884                                 int child_id = GPOINTER_TO_INT(l->data);
885                                 /* update children original_event_id */
886                                 cal_db_event_update_child_origina_event_id(child_id, event_id);
887                                 char *recurrence_id = NULL;
888                                 recurrence_id = cal_db_event_get_recurrence_id_from_exception(child_id);
889                                 if (NULL == recurrence_id || '\0' == *recurrence_id) {
890                                         if (recurrence_id) free(recurrence_id);
891                                         l = g_list_next(l);
892                                         continue;
893                                 }
894                                 /* remove parent instance */
895                                 cal_db_event_apply_recurrence_id(event_id, event, recurrence_id, child_id);
896                                 free(recurrence_id);
897                                 l = g_list_next(l);
898                         }
899                         g_list_free(list);
900                 } else {
901                         DBG("this is child");
902                         /* get parent with uid and update original_event_id */
903                         int parent_id = 0;
904                         parent_id = __get_parent_id_with_uid(event->uid, event_id);
905                         if (parent_id < 0) {
906                                 ERR("__get_parent_id_with_uid() Fail");
907                                 break;
908                         }
909                         calendar_record_h parent = NULL;
910                         cal_db_get_record(_calendar_event._uri, parent_id, &parent);
911                         cal_db_event_apply_recurrence_id(parent_id, (cal_event_s *)parent, event->recurrence_id, event_id);
912                         calendar_record_destroy(parent, true);
913                 }
914                 break;
915         }
916
917         if (event->alarm_list->count)   {
918                 DBG("insert alarm");
919                 ret = cal_db_alarm_insert_records(event->alarm_list, event_id);
920                 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_db_alarm_insert_records() Fail(%d)", ret);
921         } else {
922                 DBG("No alarm");
923         }
924
925         if (0 < event->attendee_list->count) {
926                 DBG("insert attendee");
927                 ret = cal_db_attendee_insert_records(event->attendee_list, event_id);
928                 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_db_attendee_insert_records() Fail(%d)", ret);
929         } else {
930                 DBG("No attendee");
931         }
932
933         if (original_event_id <= 0 && 0 < event->exception_list->count) {
934                 DBG("insert exception");
935                 ret = cal_db_event_insert_records(event->exception_list, event_id);
936                 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_db_event_insert_records() Fail(%d)", ret);
937         } else {
938                 DBG("No exception");
939         }
940
941         if (0 < event->extended_list->count) {
942                 DBG("insert extended");
943                 ret = cal_db_extended_insert_records(event->extended_list, event_id, CALENDAR_RECORD_TYPE_EVENT);
944                 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_db_extended_insert_records() Fail(%d)", ret);
945         } else {
946                 DBG("No extended");
947         }
948
949         cal_db_util_notify(CAL_NOTI_TYPE_EVENT);
950
951         cal_record_set_int(record, _calendar_event.id, tmp);
952         return CALENDAR_ERROR_NONE;
953 }
954
955 int cal_db_event_insert_records(cal_list_s *list_s, int original_event_id)
956 {
957         int ret;
958         int count = 0;
959         calendar_record_h record = NULL;
960         calendar_list_h list = (calendar_list_h)list_s;
961
962         RETV_IF(NULL == list, CALENDAR_ERROR_INVALID_PARAMETER);
963
964         calendar_list_get_count(list, &count);
965         if (0 == count)
966                 return CALENDAR_ERROR_NONE;
967
968         calendar_list_first(list);
969         while (CALENDAR_ERROR_NONE == calendar_list_get_current_record_p(list, &record)) {
970                 ret = cal_db_event_insert_record(record, original_event_id, NULL);
971                 RETVM_IF(CALENDAR_ERROR_NONE != ret, ret, "cal_db_extended_insert_record() Fail(%d)", ret);
972                 calendar_list_next(list);
973         }
974         return CALENDAR_ERROR_NONE;
975 }