1d198efd87a5e37b5eaed941bb02cbe05fc94305
[platform/core/pim/calendar-service.git] / server / db / cal_db_instance.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 <string.h>
21 #include <stdlib.h>
22 #include <glib.h>
23 #include <unicode/ucal.h>
24 #include <unicode/ustring.h>
25 #include <unicode/ustdio.h>
26 #include <unicode/udat.h>
27 #include <sys/types.h>
28
29 #include "calendar_db.h"
30 #include "calendar_types.h"
31 #include "cal_internal.h"
32 #include "cal_typedef.h"
33 #include "cal_view.h"
34 #include "cal_time.h"
35 #include "cal_record.h"
36 #include "cal_db_instance_helper.h"
37 #include "cal_db.h"
38 #include "cal_db_util.h"
39 #include "cal_db_plugin_timezone_helper.h"
40
41 #define ms2sec(ms) (long long int)(ms / 1000.0)
42 #define sec2ms(s) (s * 1000.0)
43
44 /* input order
45  * UCAL_MONTH + UCAL_DAY_OF_MONTH
46  * UCAL_MONTH + UCAL_WEEK_OF_MONTH + UCAL_DAY_OF_WEEK
47  * UCAL_MONTH + UCAL_DAY_OF_WEEK_IN_MONTH + UCAL_DAY_OF_WEEK
48  * UCAL_DAY_OF_YEAR
49  * UCAL_DAY_OF_WEEK + UCAL_WEEK_OF_YEAR
50  */
51
52 struct day {
53         int uday;
54         const char *str;
55 };
56
57 #define CAL_LUNAR_CALENDAR_BASE_YEAR 2637
58 #define CAL_ENDLESS_LIMIT_YEAR 2036
59 #define CAL_ENDLESS_LIMIT_MONTH 12
60 #define CAL_ENDLESS_LIMIT_MDAY 31
61 #define CAL_ENDLESS_LIMIT_UTIME 2114380800 /* 2037/01/01 00:00:00 GMT */
62 #define CAL_ENDLESS_LIMIT_FULL_DAY (365 * 50)
63
64 static void __print_ucal(int calendar_system_type, UCalendar *ucal, const char *tzid, int wkst)
65 {
66         UErrorCode ec = U_ZERO_ERROR;
67         if (NULL == ucal) return;
68
69         UCalendar *s_ucal = NULL;
70
71         switch (calendar_system_type) {
72         case CALENDAR_SYSTEM_EAST_ASIAN_LUNISOLAR:
73                 s_ucal = cal_time_open_ucal(-1, tzid, wkst);
74                 if (NULL == s_ucal) {
75                         ERR("cal_time_open_ucal() Fail");
76                         return;
77                 }
78                 ucal_setMillis(s_ucal, ucal_getMillis(ucal, &ec), &ec);
79                 break;
80
81         default: /* CALENDAR_SYSTEM_NONE: CALENDAR_SYSTEM_GREGORIAN: */
82                 s_ucal = ucal;
83                 break;
84         }
85         DBG(COLOR_GREEN"[INSERTED] instance %04d-%02d-%02d %02d:%02d:%02d"COLOR_END,
86                         ucal_get(s_ucal, UCAL_YEAR, &ec),
87                         ucal_get(s_ucal, UCAL_MONTH, &ec) + 1,
88                         ucal_get(s_ucal, UCAL_DATE, &ec),
89                         ucal_get(s_ucal, UCAL_HOUR_OF_DAY, &ec),
90                         ucal_get(s_ucal, UCAL_MINUTE, &ec),
91                         ucal_get(s_ucal, UCAL_SECOND, &ec));
92
93         if (CALENDAR_SYSTEM_EAST_ASIAN_LUNISOLAR == calendar_system_type)
94                 ucal_close(s_ucal);
95 }
96
97 static void __get_allday_date(cal_event_s *event, UCalendar *ucal, int *y, int *m, int *d, int *h, int *n, int *s)
98 {
99         UErrorCode ec = U_ZERO_ERROR;
100         if (NULL == ucal) return;
101
102         UCalendar *s_ucal = NULL;
103
104         switch (event->system_type) {
105         case CALENDAR_SYSTEM_EAST_ASIAN_LUNISOLAR:
106                 s_ucal = cal_time_open_ucal(-1, event->start_tzid, event->wkst);
107                 if (NULL == s_ucal) {
108                         ERR("cal_time_open_ucal() Fail");
109                         return;
110                 }
111                 ucal_setMillis(s_ucal, ucal_getMillis(ucal, &ec), &ec);
112                 break;
113
114         default:
115                 s_ucal = ucal;
116                 break;
117         }
118         if (y)
119                 *y = ucal_get(s_ucal, UCAL_YEAR, &ec);
120         if (m)
121                 *m = ucal_get(s_ucal, UCAL_MONTH, &ec) + 1;
122         if (d)
123                 *d = ucal_get(s_ucal, UCAL_DATE, &ec);
124         if (h)
125                 *h = ucal_get(s_ucal, UCAL_HOUR_OF_DAY, &ec);
126         if (n)
127                 *n = ucal_get(s_ucal, UCAL_MINUTE, &ec);
128         if (s)
129                 *s = ucal_get(s_ucal, UCAL_SECOND, &ec);
130
131         if (CALENDAR_SYSTEM_EAST_ASIAN_LUNISOLAR == event->system_type)
132                 ucal_close(s_ucal);
133 }
134
135 static int _cal_db_instance_parse_byint(char *byint, int *by, int *len)
136 {
137         if (NULL == byint || '\0' == *byint)
138                 return CALENDAR_ERROR_NONE;
139
140         char **t = NULL;
141         t = g_strsplit_set(byint, " ,", -1);
142         RETVM_IF(NULL == t, CALENDAR_ERROR_OUT_OF_MEMORY, "g_strsplit_set() Fail");
143
144         int length = g_strv_length(t);
145         int i;
146         int index = 0;
147         for (i = 0 ; i < length; i++) {
148                 if (NULL == t[i] || 0 == strlen(t[i])) continue;
149                 by[index] = atoi(t[i]);
150                 index++;
151         }
152         g_strfreev(t);
153         if (len) *len = index;
154         return CALENDAR_ERROR_NONE;
155 }
156
157 static void __set_time_to_ucal(int calendar_system_type, UCalendar *ucal, calendar_time_s *t)
158 {
159         RET_IF(NULL == ucal);
160         RET_IF(NULL == t);
161
162         UErrorCode ec = U_ZERO_ERROR;
163
164         int y = 0, m = 0, d = 0;
165         int h = 0, n = 0, s = 0;
166         struct tm tm = {0};
167         switch (t->type) {
168         case CALENDAR_TIME_UTIME:
169                 ucal_setMillis(ucal, sec2ms(t->time.utime), &ec);
170                 break;
171
172         case CALENDAR_TIME_LOCALTIME:
173                 switch (calendar_system_type) {
174                 case CALENDAR_SYSTEM_EAST_ASIAN_LUNISOLAR:
175                         tm.tm_year = t->time.date.year - 1900;
176                         tm.tm_mon = t->time.date.month -1;
177                         tm.tm_mday = t->time.date.mday;
178                         tm.tm_hour = t->time.date.hour;
179                         tm.tm_min = t->time.date.minute;
180                         tm.tm_sec = t->time.date.second;
181                         ucal_setMillis(ucal, sec2ms(timegm(&tm)), &ec);
182
183                         y = ucal_get(ucal, UCAL_EXTENDED_YEAR, &ec) - CAL_LUNAR_CALENDAR_BASE_YEAR;
184                         m = ucal_get(ucal, UCAL_MONTH, &ec) + 1;
185                         d = ucal_get(ucal, UCAL_DATE, &ec);
186                         h = ucal_get(ucal, UCAL_HOUR_OF_DAY, &ec);
187                         n = ucal_get(ucal, UCAL_MINUTE, &ec);
188                         s = ucal_get(ucal, UCAL_SECOND, &ec);
189                         ucal_setDateTime(ucal, y, m - 1, d, h, n, s, &ec);
190                         ucal_set(ucal, UCAL_EXTENDED_YEAR, y + CAL_LUNAR_CALENDAR_BASE_YEAR);
191                         break;
192
193                 default:
194                         ucal_setDateTime(ucal, t->time.date.year,
195                                         t->time.date.month -1,
196                                         t->time.date.mday,
197                                         t->time.date.hour,
198                                         t->time.date.minute,
199                                         t->time.date.second, &ec);
200                         break;
201                 }
202                 break;
203         }
204 }
205
206 static int __get_exdate_list(UCalendar *ucal, cal_event_s *event, GList **list)
207 {
208         RETV_IF(NULL == ucal, CALENDAR_ERROR_INVALID_PARAMETER);
209         RETV_IF(NULL == event, CALENDAR_ERROR_INVALID_PARAMETER);
210
211         if (NULL == event->exdate || '\0' == *(event->exdate))
212                 return CALENDAR_ERROR_NONE;
213
214         char **t = NULL;
215         t = g_strsplit_set(event->exdate, " ,", -1);
216         RETVM_IF(NULL == t, CALENDAR_ERROR_OUT_OF_MEMORY, "g_strsplit_set() Fail");;
217
218         DBG("[%s]", event->exdate);
219         int len = 0;
220         len = g_strv_length(t);
221         DBG("exdate len (%d)", len);
222
223         int i;
224         for (i = 0; i < len; i++) {
225                 char *p = t[i];
226                 if (NULL == p)
227                         continue;
228
229                 int y = 0, m = 0, d = 0;
230                 int h = 0, n = 0, s = 0;
231                 long long int lli = 0;
232                 UCalendar *ucal2 = NULL;
233                 UErrorCode ec = U_ZERO_ERROR;
234                 switch (strlen(p)) {
235                 case 8:
236                         DBG("ALLDAY instance");
237                         sscanf(p, CAL_DATETIME_FORMAT_YYYYMMDD, &y, &m, &d);
238
239                         ucal2 = ucal_clone(ucal, &ec);
240                         ucal_setDateTime(ucal2, y, m - 1, d, 0, 0, 0, &ec);
241                         lli = ms2sec(ucal_getMillis(ucal2, &ec));
242                         ucal_close(ucal2);
243                         break;
244
245                 case 15:
246                         DBG("ALLDAY instance");
247                         sscanf(p, CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSS, &y, &m, &d, &h, &n, &s);
248
249                         ucal2 = ucal_clone(ucal, &ec);
250                         ucal_setDateTime(ucal2, y, m - 1, d, h, n, s, &ec);
251                         lli = ms2sec(ucal_getMillis(ucal2, &ec));
252                         ucal_close(ucal2);
253                         break;
254
255                 case 16:
256                         DBG("NORMAL instance");
257                         sscanf(p, CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSSZ, &y, &m, &d, &h, &n, &s);
258                         lli = cal_time_convert_itol(NULL, y, m, d, h, n, s);
259                         break;
260                 }
261                 DBG("%lld", lli);
262
263                 long long int *lli_p = calloc(1, sizeof(long long int));
264                 if (NULL == lli_p)
265                         break;
266
267                 *lli_p = lli;
268
269                 *list = g_list_append(*list, lli_p);
270         }
271         g_strfreev(t);
272
273         return CALENDAR_ERROR_NONE;
274 }
275
276 static int _cal_db_instance_update_exdate_mod(int original_event_id, char *recurrence_id)
277 {
278         int ret = 0;
279         int i, j;
280         char **t = NULL;
281         char *p = NULL;
282         char query[CAL_DB_SQL_MAX_LEN] = {0};
283
284         if (original_event_id < 1 || NULL == recurrence_id) {
285                 DBG("Nothing to update exdate mod");
286                 return CALENDAR_ERROR_NONE;
287         }
288
289         DBG("recurrence_id[%s]", recurrence_id);
290         t = g_strsplit_set(recurrence_id, " ,", -1);
291         RETVM_IF(NULL == t, CALENDAR_ERROR_OUT_OF_MEMORY, "g_strsplit_set() Fail");;
292
293         for (i = 0; t[i]; i++) {
294                 p = t[i];
295
296                 /* remove space */
297                 j = 0;
298                 while (p[j] == ' ')
299                         j++;
300
301                 p = t[i] + j;
302                 DBG("%d[%s]", i + 1, p);
303
304                 int y = 0, m = 0, d = 0;
305                 int h = 0, n = 0, s = 0;
306                 char buf[CAL_STR_SHORT_LEN32] = {0};
307                 switch (strlen(p)) {
308                 case 8:
309                         DBG("ALLDAY instance");
310                         sscanf(p, CAL_DATETIME_FORMAT_YYYYMMDD, &y, &m, &d);
311                         snprintf(buf, sizeof(buf), "%04d-%02d-%02dT%02d:%02d:%02d", y, m, d, 0, 0, 0);
312                         snprintf(query, sizeof(query),
313                                         "DELETE FROM %s "
314                                         "WHERE event_id = %d AND dtstart_datetime = '%s' ",
315                                         CAL_TABLE_ALLDAY_INSTANCE,
316                                         original_event_id, buf);
317                         break;
318
319                 case 15:
320                         DBG("ALLDAY instance");
321                         sscanf(p, CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSS, &y, &m, &d, &h, &n, &s);
322                         snprintf(buf, sizeof(buf), "%04d-%02d-%02dT%02d:%02d:%02d", y, m, d, h, n, s);
323                         snprintf(query, sizeof(query),
324                                         "DELETE FROM %s "
325                                         "WHERE event_id = %d AND dtstart_datetime = '%s' ",
326                                         CAL_TABLE_ALLDAY_INSTANCE,
327                                         original_event_id, buf);
328                         break;
329
330                 case 16:
331                         DBG("NORMAL instance");
332                         sscanf(p, CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSSZ, &y, &m, &d, &h, &n, &s);
333                         snprintf(query, sizeof(query), "DELETE FROM %s WHERE event_id=%d AND dtstart_utime=%lld ",
334                                         CAL_TABLE_NORMAL_INSTANCE, original_event_id, cal_time_convert_itol(NULL, y, m, d, h, n, s));
335                         DBG("(%lld)", cal_time_convert_itol(NULL, y, m, d, h, n, s));
336                         break;
337                 }
338                 ret = cal_db_util_query_exec(query);
339                 if (CALENDAR_ERROR_NONE != ret) {
340                         ERR("cal_db_util_query_exec() Fail(%d)", ret);
341                         SECURE("[%s]", query);
342                         g_strfreev(t);
343                         return ret;
344                 }
345         }
346         g_strfreev(t);
347         return CALENDAR_ERROR_NONE;
348 }
349
350 static inline int __cal_db_instance_has_after(calendar_time_s *t1, calendar_time_s *t2)
351 {
352         if (t1->type == CALENDAR_TIME_UTIME)
353                 return t1->time.utime < t2->time.utime ? 0 : 1;
354
355         DBG("%d %d %d /%d %d %d", t1->time.date.year, t1->time.date.month, t1->time.date.mday,
356                         t2->time.date.year, t2->time.date.month, t2->time.date.mday);
357
358         if (t1->time.date.year == t2->time.date.year) {
359                 if (t1->time.date.month == t2->time.date.month)
360                         return t1->time.date.mday < t2->time.date.mday ? 0 : 1;
361
362                 return t1->time.date.month < t2->time.date.month ? 0 : 1;
363         }
364         return t1->time.date.year < t2->time.date.year ? 0 : 1;
365 }
366
367 static inline int _cal_db_instance_convert_mday(const char *str, int *mday)
368 {
369         int d;
370
371         RETV_IF(!str, CALENDAR_ERROR_INVALID_PARAMETER);
372         RETV_IF(*str, CALENDAR_ERROR_INVALID_PARAMETER);
373
374         d = atoi(str);
375         RETVM_IF(d < 1 || 31 < d, CALENDAR_ERROR_INVALID_PARAMETER, "day(%d)", d);
376
377         DBG("get mday[%s] and convert to int(%d)", str, d);
378         *mday = d;
379         return CALENDAR_ERROR_NONE;
380 }
381
382 static int _cal_db_instance_del_inundant(int event_id, calendar_time_s *st, cal_event_s *event)
383 {
384         int ret = 0;
385         int cnt;
386         char query[CAL_DB_SQL_MAX_LEN];
387
388         if (event->range_type != CALENDAR_RANGE_COUNT)
389                 return CALENDAR_ERROR_NONE;
390
391         cnt = event->count;
392         DBG("get count(%d) and del after this", cnt);
393
394         if (st->type == CALENDAR_TIME_UTIME) {
395                 snprintf(query, sizeof(query), "DELETE FROM %s "
396                                 "WHERE event_id = %d "
397                                 "AND dtstart_utime > (SELECT dtstart_utime FROM %s "
398                                 "WHERE event_id = %d ORDER BY dtstart_utime LIMIT %d, 1) ",
399                                 CAL_TABLE_NORMAL_INSTANCE,
400                                 event_id,
401                                 CAL_TABLE_NORMAL_INSTANCE,
402                                 event_id, cnt -1);
403
404         } else if (st->type == CALENDAR_TIME_LOCALTIME) {
405                 snprintf(query, sizeof(query), "DELETE FROM %s WHERE event_id = %d "
406                                 "AND dtstart_datetime > (SELECT dtstart_datetime FROM %s "
407                                 "WHERE event_id = %d ORDER BY dtstart_datetime LIMIT %d, 1) ",
408                                 CAL_TABLE_ALLDAY_INSTANCE,
409                                 event_id,
410                                 CAL_TABLE_ALLDAY_INSTANCE,
411                                 event_id, cnt -1);
412         }
413
414         ret = cal_db_util_query_exec(query);
415         if (CALENDAR_ERROR_NONE != ret) {
416                 ERR("cal_db_util_query_exec() Fail(%d)", ret);
417                 SECURE("[%s]", query);
418                 return ret;
419         }
420         return CALENDAR_ERROR_NONE;
421 }
422
423 /*
424  *      bit   |7 |6  |5  |4  |3  |2  |1  |0 |
425  *      value |0 |SA |FR |TH |WE |TU |MO |SU|
426  *
427  * UCAL_XXX = bit position + 1
428  * UCAL_SUNDAY = 1
429  * UCAL_MONDAY = 2...
430  */
431 static int __convert_week_to_bits(const char *byday, int *byday_len)
432 {
433         RETV_IF(NULL == byday, -1);
434
435         const char *week_text[7] = {"SU", "MO", "TU", "WE", "TH", "FR", "SA"};
436         int week = 0;
437         int i;
438         int len = 0;
439         for (i = 0; i < 7; i++) {
440                 if (strstr(byday, week_text[i])) {
441                         week |= (0x01 << i);
442                         len++;
443                 }
444         }
445         if (byday_len) *byday_len = len;
446         return week;
447 }
448
449 static int _cal_db_instance_get_duration(UCalendar *ucal, calendar_time_s *st, calendar_time_s *et, long long int *duration)
450 {
451         RETV_IF(NULL == ucal, CALENDAR_ERROR_INVALID_PARAMETER);
452         RETV_IF(NULL == st, CALENDAR_ERROR_INVALID_PARAMETER);
453         RETV_IF(NULL == et, CALENDAR_ERROR_INVALID_PARAMETER);
454
455         long long int _duration = -1;
456         UErrorCode ec = U_ZERO_ERROR;
457         UDate ud;
458
459         switch (st->type) {
460         case CALENDAR_TIME_UTIME:
461                 if (et->time.utime < st->time.utime) {
462                         ERR("check time: end(%lld < start(%lld)", et->time.utime, st->time.utime);
463                         return CALENDAR_ERROR_INVALID_PARAMETER;
464                 }
465                 _duration = et->time.utime - st->time.utime;
466                 break;
467
468         case CALENDAR_TIME_LOCALTIME:
469                 ucal_setDateTime(ucal, et->time.date.year, et->time.date.month -1, et->time.date.mday,
470                                 et->time.date.hour, et->time.date.minute, et->time.date.second, &ec);
471                 ud = ucal_getMillis(ucal, &ec);
472
473                 ucal_setDateTime(ucal, st->time.date.year, st->time.date.month -1, st->time.date.mday,
474                                 st->time.date.hour, st->time.date.minute, st->time.date.second, &ec);
475
476                 _duration = ucal_getFieldDifference(ucal, ud, UCAL_SECOND, &ec);
477                 if (U_FAILURE(ec)) {
478                         ERR("ucal_getFieldDifference() Fail[%s]", u_errorName(ec));
479                         return ec;
480                 }
481                 break;
482         }
483
484         if (duration) *duration = _duration;
485         return CALENDAR_ERROR_NONE;
486 }
487
488 static int _cal_db_instance_insert_record(UCalendar *ucal, long long int duration, cal_event_s *event)
489 {
490         int ret;
491         UErrorCode ec = U_ZERO_ERROR;
492         long long int lli_s = 0;
493         long long int lli_e = 0;
494         int y = 0, m = 0, d = 0;
495         int h = 0, n = 0, s = 0;
496         char buf_s[CAL_STR_MIDDLE_LEN] = {0};
497         char buf_e[CAL_STR_MIDDLE_LEN] = {0};
498
499         RETV_IF(NULL == ucal, CALENDAR_ERROR_INVALID_PARAMETER);
500
501         switch (event->start.type) {
502         case CALENDAR_TIME_UTIME:
503                 lli_s =  ms2sec(ucal_getMillis(ucal, &ec));
504                 lli_e = lli_s + duration;
505                 ret = cal_db_instance_helper_insert_utime_instance(event->index, lli_s, lli_e);
506                 RETVM_IF(CALENDAR_ERROR_NONE != ret, ret, "cal_db_instance_helper_insert_utime_instance() Fail(%d)", ret);
507                 break;
508
509         case CALENDAR_TIME_LOCALTIME:
510                 __get_allday_date(event, ucal, &y, &m, &d, &h, &n, &s);
511                 snprintf(buf_s, sizeof(buf_s), CAL_FORMAT_LOCAL_DATETIME, y, m, d, h, n, s);
512
513                 if (0 < duration) {
514                         UCalendar *ucal2 = NULL;
515                         ucal2 = ucal_clone(ucal, &ec);
516                         ucal_add(ucal2, UCAL_SECOND, duration, &ec);
517                         __get_allday_date(event, ucal2, &y, &m, &d, &h, &n, &s);
518                         ucal_close(ucal2);
519                 }
520                 snprintf(buf_e, sizeof(buf_e), CAL_FORMAT_LOCAL_DATETIME, y, m, d, h, n, s);
521                 ret = cal_db_instance_helper_insert_localtime_instance(event->index, buf_s, buf_e);
522                 RETVM_IF(CALENDAR_ERROR_NONE != ret, ret, "cal_db_instance_allday_insert_record() failed(%d)", ret);
523                 break;
524         }
525         __print_ucal(event->system_type, ucal, NULL, 1);
526         return CALENDAR_ERROR_NONE;
527 }
528
529 static int __convert_wday_to_int(const char *wday)
530 {
531         RETV_IF(NULL == wday, 0);
532
533         const char *week_text[7] = {"SU", "MO", "TU", "WE", "TH", "FR", "SA"};
534         int i;
535         for (i = 0; i < 7; i++) {
536                 if (strstr(wday, week_text[i]))
537                         return i + 1;
538         }
539         return 0;
540 }
541
542 static int __get_until_from_range(cal_event_s *event, calendar_time_s *until)
543 {
544         RETV_IF(NULL == event, CALENDAR_ERROR_INVALID_PARAMETER);
545         RETV_IF(NULL == until, CALENDAR_ERROR_INVALID_PARAMETER);
546
547         long long int range = 0;
548         switch (event->range_type) {
549         case CALENDAR_RANGE_COUNT:
550                 DBG("range count");
551                 break;
552
553         case CALENDAR_RANGE_UNTIL:
554                 DBG("range until");
555                 until->type = event->until.type;
556                 switch (until->type) {
557                 case CALENDAR_TIME_UTIME:
558                         range = cal_time_convert_itol(NULL, CAL_ENDLESS_LIMIT_YEAR,
559                                         CAL_ENDLESS_LIMIT_MONTH, CAL_ENDLESS_LIMIT_MDAY, 0, 0, 0);
560                         if (range < event->until.time.utime) {
561                                 DBG("range max < until time(%lld), so set max(%lld)", event->until.time.utime, range);
562                                 until->time.utime = range;
563                         } else {
564                                 until->time.utime = event->until.time.utime;
565                         }
566                         break;
567
568                 case CALENDAR_TIME_LOCALTIME:
569                         until->time.date.year = CAL_ENDLESS_LIMIT_YEAR < event->until.time.date.year ?
570                                 CAL_ENDLESS_LIMIT_YEAR : event->until.time.date.year;
571                         until->time.date.month = event->until.time.date.month;
572                         until->time.date.mday = event->until.time.date.mday;
573                         until->time.date.hour = event->until.time.date.hour;
574                         until->time.date.minute = event->until.time.date.minute;
575                         until->time.date.second = event->until.time.date.second;
576                         break;
577                 }
578                 break;
579
580         case CALENDAR_RANGE_NONE:
581                 DBG("range none");
582                 until->type = event->until.type;
583                 switch (until->type) {
584                 case CALENDAR_TIME_UTIME:
585                         until->time.utime = cal_time_convert_itol(event->start_tzid,
586                                         CAL_ENDLESS_LIMIT_YEAR,
587                                         CAL_ENDLESS_LIMIT_MONTH,
588                                         CAL_ENDLESS_LIMIT_MDAY,
589                                         0, 0, 0);
590                         break;
591                 case CALENDAR_TIME_LOCALTIME:
592                         until->time.date.year = CAL_ENDLESS_LIMIT_YEAR;
593                         until->time.date.month = CAL_ENDLESS_LIMIT_MONTH;
594                         until->time.date.mday = CAL_ENDLESS_LIMIT_MDAY;
595                         until->time.date.hour = 0;
596                         until->time.date.minute = 0;
597                         until->time.date.second = 0;
598                         break;
599                 }
600                 break;
601         }
602         return CALENDAR_ERROR_NONE;
603 }
604
605 /*
606  * Return true when index meets bysetpos value.
607  * ig. when bysetpos=2 and 3, index 1 returns true(skip), index 2 and 3 returns false(selected).
608  */
609 static bool __check_bysetpos_to_skip(int index, int *bysetpos, int bysetpos_len, int dates_len)
610 {
611         int i;
612         if (0 == bysetpos_len)
613                 return false;
614
615         for (i = 0; i < bysetpos_len; i++) {
616                 if (0 < bysetpos[i]) {
617                         if (bysetpos[i] == (index + 1))
618                                 return false;
619                 } else {
620                         if ((index - dates_len) == bysetpos[i])
621                                 return false;
622                 }
623         }
624         return true;
625 }
626
627 static bool __check_before_dtstart(long long int current_utime, long long int dtstart_utime)
628 {
629         if (current_utime < dtstart_utime) {
630                 DBG("get time(%lld) is earlier than start(%lld), so skip", current_utime, dtstart_utime);
631                 return true;
632         }
633         return false;
634 }
635
636 static bool __check_exdate_to_skip(long long int get_lli, GList **list)
637 {
638         GList *cursor = *list;
639         while (cursor) {
640                 long long int *lli_p = (long long int *)cursor->data;
641                 if (NULL == lli_p) {
642                         cursor = g_list_next(cursor);
643                         continue;
644                 }
645                 long long int lli = *lli_p;
646                 if (lli == get_lli) {
647                         DBG("found exdate(%lld)", get_lli);
648                         free(lli_p);
649                         *list = g_list_delete_link(*list, cursor);
650                         return true;
651                 }
652                 cursor = g_list_next(cursor);
653         }
654         return false;
655 }
656
657 static bool __check_to_stop_loop(long long int current_utime, long long int *last_utime, int loop)
658 {
659         if ((*last_utime == current_utime) || (CAL_ENDLESS_LIMIT_FULL_DAY == loop)) {
660                 DBG("current utime is same as last utime(%lld), so stoppted", current_utime);
661                 return true;
662         }
663         *last_utime = current_utime;
664         return false;
665 }
666
667 static bool __check_out_of_range(long long int current_utime, cal_event_s *event, long long int until_utime, int *count)
668 {
669         RETV_IF(NULL == event, true);
670
671         /* check range */
672         switch (event->range_type) {
673         case CALENDAR_RANGE_UNTIL:
674         case CALENDAR_RANGE_NONE:
675                 if (until_utime < current_utime) {
676                         DBG("(%lld) (%lld)", current_utime, until_utime);
677                         return true;
678                 }
679                 break;
680
681         case CALENDAR_RANGE_COUNT:
682                 (*count)++;
683                 if (event->count < *count) {
684                         DBG("(%d) (%d)", *count, event->count);
685                         return true;
686                 }
687
688                 if (CAL_ENDLESS_LIMIT_UTIME < current_utime) {
689                         /* event count is remained, it should not go over LIMIT */
690                         DBG("stopped because LIMIT UTIME(%lld) < dtstart(%lld)", (long long int)CAL_ENDLESS_LIMIT_UTIME, current_utime);
691                         return true;
692                 }
693                 break;
694         }
695         return false;
696 }
697
698 static bool __check_daily_bymonth_to_skip(UCalendar *ucal, int *bymonth, int bymonth_len, int *log_value)
699 {
700         if (0 == bymonth_len) return false;
701
702         UErrorCode ec = U_ZERO_ERROR;
703         int month = ucal_get(ucal, UCAL_MONTH, &ec) + 1;
704         int i;
705         for (i = 0; i < bymonth_len; i++) {
706                 if (month == bymonth[i])
707                         return false;
708         }
709         if (*log_value != month) {
710                 DBG("Get month(%d) Not in bymonth", month);
711                 *log_value = month;
712         }
713         return true;
714 }
715
716 static int __get_dates_in_month(UCalendar *ucal, int week_bits, int bymonth, int *dates_len)
717 {
718         UErrorCode ec = U_ZERO_ERROR;
719         int len = 0;
720
721         RETV_IF(NULL == ucal, CALENDAR_ERROR_INVALID_PARAMETER);
722
723         int i;
724         for (i = 0; i < 7; i++) {
725                 if (0 == (week_bits & (0x01 << i))) continue;
726                 int wday_int = i + 1;
727
728                 ucal_set(ucal, UCAL_MONTH, bymonth - 1);
729                 ucal_set(ucal, UCAL_DAY_OF_WEEK, wday_int);
730                 ucal_set(ucal, UCAL_DAY_OF_WEEK_IN_MONTH, 1);
731                 int weekno_start = ucal_get(ucal, UCAL_WEEK_OF_YEAR, &ec);
732
733                 ucal_set(ucal, UCAL_MONTH, bymonth - 1);
734                 ucal_set(ucal, UCAL_DAY_OF_WEEK, wday_int);
735                 ucal_set(ucal, UCAL_DAY_OF_WEEK_IN_MONTH, -1);
736                 int weekno_end = ucal_get(ucal, UCAL_WEEK_OF_YEAR, &ec);
737                 if (1 == weekno_end) {
738                         ucal_set(ucal, UCAL_MONTH, bymonth - 1);
739                         ucal_set(ucal, UCAL_DAY_OF_WEEK, wday_int);
740                         ucal_set(ucal, UCAL_DAY_OF_WEEK_IN_MONTH, -1);
741                         ucal_add(ucal, UCAL_DATE, -7, &ec);
742                         weekno_end = ucal_get(ucal, UCAL_WEEK_OF_YEAR, &ec) + 1;
743                 }
744                 int weekno_gap = weekno_end - weekno_start + 1;
745
746                 len += weekno_gap;
747         }
748         if (dates_len) *dates_len = len;
749         return CALENDAR_ERROR_NONE;
750 }
751
752 static int _cal_db_instance_publish_yearly_yday(UCalendar *ucal, cal_event_s *event, long long int duration)
753 {
754         RETV_IF(NULL == ucal, CALENDAR_ERROR_INVALID_PARAMETER);
755         RETV_IF(NULL == event, CALENDAR_ERROR_INVALID_PARAMETER);
756         RETV_IF(NULL == event->byyearday, CALENDAR_ERROR_INVALID_PARAMETER);
757         RETV_IF('\0' == event->byyearday[0], CALENDAR_ERROR_INVALID_PARAMETER);
758
759         UErrorCode ec = U_ZERO_ERROR;
760         calendar_time_s until = {0};
761         __get_until_from_range(event, &until);
762         __set_time_to_ucal(event->system_type, ucal, &until);
763         /* set until before dtstart_utime */
764         long long int until_utime = ms2sec(ucal_getMillis(ucal, &ec));
765
766         int byyearday[CAL_STR_MIDDLE_LEN] = {0};
767         int byyearday_len = 0;
768         _cal_db_instance_parse_byint(event->byyearday, byyearday, &byyearday_len);
769         DBG("byyearday len(%d)", byyearday_len);
770
771         int bysetpos[CAL_STR_MIDDLE_LEN] = {0};
772         int bysetpos_len = 0;
773         _cal_db_instance_parse_byint(event->bysetpos, bysetpos, &bysetpos_len);
774         DBG("bysetpos len(%d)", bysetpos_len);
775
776         GList *list = NULL;
777         __get_exdate_list(ucal, event, &list);
778
779         int loop = 0;
780         int count = 0;
781         bool is_exit = false;
782         long long int last_utime = 0;
783         long long int current_utime = 0;
784         while (false == is_exit) {
785                 calendar_time_s *st = &event->start;
786                 __set_time_to_ucal(event->system_type, ucal, st);
787                 long long int dtstart_utime = ms2sec(ucal_getMillis(ucal, &ec));
788                 ucal_add(ucal, UCAL_YEAR, event->interval * loop, &ec);
789
790                 int i;
791                 for (i = 0; i < byyearday_len; i++) {
792                         ucal_set(ucal, UCAL_DAY_OF_YEAR, byyearday[i]);
793                         if (true == __check_bysetpos_to_skip(i, bysetpos, bysetpos_len, byyearday_len))
794                                 continue;
795
796                         current_utime = ms2sec(ucal_getMillis(ucal, &ec));
797                         if (true == __check_before_dtstart(current_utime, dtstart_utime))
798                                 continue;
799
800                         if (true == __check_exdate_to_skip(current_utime, &list)) {
801                                 count++;
802                                 continue;
803                         }
804                         is_exit = __check_out_of_range(current_utime, event, until_utime, &count);
805                         if (true == is_exit)
806                                 break;
807                         _cal_db_instance_insert_record(ucal, duration, event);
808                 }
809                 if (true == is_exit)
810                         break;
811                 current_utime = ms2sec(ucal_getMillis(ucal, &ec));
812                 is_exit = __check_to_stop_loop(current_utime, &last_utime, loop);
813                 loop++;
814         }
815         if (list)
816                 g_list_free_full(list, free);
817         return CALENDAR_ERROR_NONE;
818 }
819
820 /*
821  * weekno is different num+day
822  * weekno=10, byday=SU, is not always same as 10SU
823  * in 2014, Mar 2nd != Mar 9th
824  */
825 static int _cal_db_instance_publish_yearly_weekno(UCalendar *ucal, cal_event_s *event, long long int duration)
826 {
827         RETV_IF(NULL == ucal, CALENDAR_ERROR_INVALID_PARAMETER);
828         RETV_IF(NULL == event, CALENDAR_ERROR_INVALID_PARAMETER);
829         RETV_IF(NULL == event->byweekno || '\0' == event->byweekno[0], CALENDAR_ERROR_INVALID_PARAMETER);
830
831         UErrorCode ec = U_ZERO_ERROR;
832         calendar_time_s until = {0};
833         __get_until_from_range(event, &until);
834         __set_time_to_ucal(event->system_type, ucal, &until);
835         /* set until before dtstart_utime */
836         long long int until_utime = ms2sec(ucal_getMillis(ucal, &ec));
837
838         /* get byday */
839         int week_bits = 0;
840         int byday_len = 0;
841         if (NULL == event->byday || '\0' == event->byday[0]) {
842                 calendar_time_s *st = &event->start;
843                 __set_time_to_ucal(event->system_type, ucal, st);
844                 int dtstart_wday = ucal_get(ucal, UCAL_DAY_OF_WEEK, &ec);
845                 week_bits |= (0x01 << (dtstart_wday - 1));
846                 byday_len = 1;
847
848         } else {
849                 week_bits = __convert_week_to_bits(event->byday, &byday_len);
850         }
851         DBG("byday_len (%d) week integer(0x%x)", byday_len, week_bits);
852
853         int byweekno[CAL_STR_MIDDLE_LEN] = {0};
854         int byweekno_len = 0;
855         _cal_db_instance_parse_byint(event->byweekno, byweekno, &byweekno_len);
856         DBG("byweekno len(%d)", byweekno_len);
857
858         int bysetpos[CAL_STR_MIDDLE_LEN] = {0};
859         int bysetpos_len = 0;
860         _cal_db_instance_parse_byint(event->bysetpos, bysetpos, &bysetpos_len);
861         DBG("bysetpos len(%d)", bysetpos_len);
862
863         GList *list = NULL;
864         __get_exdate_list(ucal, event, &list);
865
866         int loop = 0;
867         int count = 0;
868         bool is_exit = false;
869         long long int last_utime = 0;
870         long long int current_utime = 0;
871         while (false == is_exit) {
872                 calendar_time_s *st = &event->start;
873                 __set_time_to_ucal(event->system_type, ucal, st);
874                 long long int dtstart_utime = ms2sec(ucal_getMillis(ucal, &ec));
875                 ucal_add(ucal, UCAL_YEAR, (event->interval * loop), &ec);
876                 long long int start_point = sec2ms(ucal_getMillis(ucal, &ec));
877
878                 /* extra_weekno : week-number converting value from iCalendar (RFC2445) to ICU:
879                  * - iCalendar W1 : first week containing at least 4 days of the year
880                  *                 (W0 when contains less than 4 days of the year)
881                  * - ICU W1 : week of 1,Jan
882                  */
883                 int extra_weekno = 0;
884                 ucal_set(ucal, UCAL_MONTH, 0);
885                 ucal_set(ucal, UCAL_DATE, 1);
886                 int wkst = ucal_getAttribute(ucal, UCAL_FIRST_DAY_OF_WEEK);
887                 int first_wday = ucal_get(ucal, UCAL_DAY_OF_WEEK, &ec);
888                 extra_weekno = 3 < ((first_wday+7-wkst)%7) ? 1 : 0;
889
890                 ucal_setMillis(ucal, ms2sec(start_point), &ec); /* set start point */
891
892                 int i;
893                 for (i = 0 ; i < byweekno_len; i++) {
894                         int j;
895                         int week_count = 0;
896                         for (j = 0; j < 7; j++) {
897                                 if (week_bits & (0x01 << j)) {
898                                         week_count++;
899                                         ucal_set(ucal, UCAL_WEEK_OF_YEAR, byweekno[i] + extra_weekno);
900                                         ucal_set(ucal, UCAL_DAY_OF_WEEK, j + 1);
901                                         if (true == __check_bysetpos_to_skip(i + week_count - 1, bysetpos, bysetpos_len, byweekno_len + byday_len - 1))
902                                                 continue;
903
904                                         current_utime = ms2sec(ucal_getMillis(ucal, &ec));
905                                         if (true == __check_before_dtstart(current_utime, dtstart_utime))
906                                                 continue;
907
908                                         if (true == __check_exdate_to_skip(current_utime, &list)) {
909                                                 count++;
910                                                 continue;
911                                         }
912                                         is_exit = __check_out_of_range(current_utime, event, until_utime, &count);
913                                         if (true == is_exit)
914                                                 break;
915                                         _cal_db_instance_insert_record(ucal, duration, event);
916                                 }
917                         }
918                         if (true == is_exit)
919                                 break;
920                 }
921                 if (true == is_exit)
922                         break;
923                 current_utime = ms2sec(ucal_getMillis(ucal, &ec));
924                 is_exit = __check_to_stop_loop(current_utime, &last_utime, loop);
925                 loop++;
926         }
927         if (list)
928                 g_list_free_full(list, free);
929         return CALENDAR_ERROR_NONE;
930 }
931
932 static int _cal_db_instance_publish_yearly_wday(UCalendar *ucal, cal_event_s *event, long long int duration)
933 {
934         RETV_IF(NULL == ucal, CALENDAR_ERROR_INVALID_PARAMETER);
935         RETV_IF(NULL == event, CALENDAR_ERROR_INVALID_PARAMETER);
936
937         UErrorCode ec = U_ZERO_ERROR;
938         calendar_time_s until = {0};
939         __get_until_from_range(event, &until);
940         __set_time_to_ucal(event->system_type, ucal, &until);
941         /* set until before dtstart_utime */
942         long long int until_utime = ms2sec(ucal_getMillis(ucal, &ec));
943
944         /* get bymonth into array */
945         int bymonth[12] = {0};
946         int bymonth_len = 0;
947         bool has_bymonth = true;
948         _cal_db_instance_parse_byint(event->bymonth, bymonth, &bymonth_len);
949         if (0 == bymonth_len) {
950                 has_bymonth = false;
951                 calendar_time_s *st = &event->start;
952                 __set_time_to_ucal(event->system_type, ucal, st);
953                 int month = ucal_get(ucal, UCAL_MONTH, &ec) + 1;
954                 bymonth[0] = month;
955                 bymonth_len = 1;
956         }
957
958         /* get bymonthday into array */
959         int bymonthday[CAL_STR_MIDDLE_LEN] = {0};
960         int bymonthday_len = 0;
961         _cal_db_instance_parse_byint(event->bymonthday, bymonthday, &bymonthday_len);
962         DBG("bymonthday_len(%d)", bymonthday_len);
963
964         char **t = NULL;
965         int byday_len = 0;
966
967         /* if nowday in weekly */
968         if (NULL == event->byday || '\0' == event->byday[0]) {
969                 const char *week_text[7] = {"SU", "MO", "TU", "WE", "TH", "FR", "SA"};
970
971                 calendar_time_s *st = &event->start;
972                 __set_time_to_ucal(event->system_type, ucal, st);
973                 int nth = ucal_get(ucal, UCAL_DAY_OF_WEEK_IN_MONTH, &ec);
974                 int dtstart_wday = ucal_get(ucal, UCAL_DAY_OF_WEEK, &ec);
975                 char buf[CAL_STR_SHORT_LEN32] = {0};
976                 snprintf(buf, sizeof(buf), "%d%s", nth, week_text[dtstart_wday -1]);
977                 DBG("set byday[%s]", buf);
978
979                 t = g_strsplit_set(buf, " ,", -1);
980                 byday_len = 1;
981
982         } else {
983                 t = g_strsplit_set(event->byday, " ,", -1);
984                 byday_len = g_strv_length(t);
985         }
986         DBG("[%s] byday_len(%d)", event->byday, byday_len);
987
988         int bysetpos[CAL_STR_MIDDLE_LEN] = {0};
989         int bysetpos_len = 0;
990         _cal_db_instance_parse_byint(event->bysetpos, bysetpos, &bysetpos_len);
991         DBG("bysetpos len(%d)", bysetpos_len);
992
993         GList *list = NULL;
994         __get_exdate_list(ucal, event, &list);
995
996         int loop = 0;
997         int count = 0;
998         bool is_exit = false;
999         long long int last_utime = 0;
1000         long long int current_utime = 0;
1001         while (false == is_exit) {
1002                 calendar_time_s *st = &event->start;
1003                 __set_time_to_ucal(event->system_type, ucal, st);
1004                 long long int dtstart_utime = ms2sec(ucal_getMillis(ucal, &ec));
1005                 ucal_add(ucal, UCAL_YEAR, event->interval * loop, &ec);
1006                 ucal_setMillis(ucal, ucal_getMillis(ucal, &ec), &ec); /* set start point */
1007
1008                 int i, j, k;
1009                 for (i = 0; i < bymonth_len; i++) {
1010
1011                         if (2 < strlen(t[0])) { /* -3SU, +2SA */
1012                                 for (j = 0; j < byday_len; j++) {
1013                                         if (0 == strlen(t[j])) continue;
1014                                         /* get nth, wday */
1015                                         int nth = 0;
1016                                         char wday[CAL_STR_SHORT_LEN32] = {0};
1017
1018                                         sscanf(t[j], "%d%s", &nth, wday); /* -3SU, +2SA */
1019                                         DBG("nth(%d) wday[%s]", nth, wday);
1020                                         int wday_int = __convert_wday_to_int(wday);
1021
1022                                         /* set nth, wday */
1023                                         if (0 < nth) {
1024                                                 ucal_set(ucal, UCAL_DAY_OF_WEEK, wday_int);
1025                                                 ucal_set(ucal, UCAL_DAY_OF_WEEK_IN_MONTH, 1);
1026                                                 ucal_set(ucal, UCAL_MONTH, false == has_bymonth ? 0 : (bymonth[i] - 1));
1027                                                 ucal_add(ucal, UCAL_WEEK_OF_YEAR, nth - 1, &ec);
1028
1029                                         } else {
1030                                                 ucal_set(ucal, UCAL_DAY_OF_WEEK, wday_int);
1031                                                 ucal_set(ucal, UCAL_MONTH, false == has_bymonth ? 0 : bymonth[i] - 1);
1032                                                 ucal_set(ucal, UCAL_DAY_OF_WEEK_IN_MONTH, nth);
1033                                         }
1034                                         if (true == __check_bysetpos_to_skip(j, bysetpos, bysetpos_len, bymonth_len + byday_len - 1))
1035                                                 continue;
1036
1037                                         current_utime = ms2sec(ucal_getMillis(ucal, &ec));
1038                                         if (true == __check_before_dtstart(current_utime, dtstart_utime))
1039                                                 continue;
1040
1041                                         if (true == __check_exdate_to_skip(current_utime, &list)) {
1042                                                 count++;
1043                                                 continue;
1044                                         }
1045                                         is_exit = __check_out_of_range(current_utime, event, until_utime, &count);
1046                                         if (true == is_exit)
1047                                                 break;
1048                                         _cal_db_instance_insert_record(ucal, duration, event);
1049                                 }
1050
1051                         } else {
1052                                 /* SU, SA: no week num: means all week:1TH,2TH,3TH.., so needs another byevent->system_typex */
1053                                 int week_bits = 0;
1054                                 /* if nowday in weekly */
1055                                 if (NULL == event->byday || '\0' == event->byday[0]) {
1056                                         calendar_time_s *st = &event->start;
1057                                         __set_time_to_ucal(event->system_type, ucal, st);
1058                                         int dtstart_wday = ucal_get(ucal, UCAL_DAY_OF_WEEK, &ec);
1059                                         week_bits |= (0x01 << (dtstart_wday - 1));
1060
1061                                 } else {
1062                                         week_bits = __convert_week_to_bits(event->byday, NULL);
1063                                 }
1064                                 DBG("week integer(0x%x)", week_bits);
1065
1066                                 if (bymonthday_len) { /* bymonthday */
1067                                         for (j = 0; j < bymonthday_len; j++) {
1068                                                 ucal_set(ucal, UCAL_MONTH, bymonth[i] - 1);
1069                                                 ucal_set(ucal, UCAL_DAY_OF_MONTH, bymonthday[j]);
1070                                                 bool is_match_wday = false;
1071                                                 int w = ucal_get(ucal, UCAL_DAY_OF_WEEK, &ec);
1072                                                 for (k = 0; k < 7; k++) { /* check if this is one of wday */
1073                                                         if (week_bits & (0x01 << k)) {
1074                                                                 if ((k + 1) == w) {
1075                                                                         is_match_wday = true;
1076                                                                         break;
1077                                                                 }
1078                                                         }
1079                                                 }
1080                                                 if (false == is_match_wday) {
1081                                                         DBG("get wday(%d) != want wday(%d)", w, k + 1);
1082                                                         continue;
1083                                                 }
1084                                                 if (true == __check_bysetpos_to_skip(j, bysetpos, bysetpos_len, bymonthday_len))
1085                                                         continue;
1086
1087                                                 current_utime = ms2sec(ucal_getMillis(ucal, &ec));
1088                                                 if (true == __check_before_dtstart(current_utime, dtstart_utime))
1089                                                         continue;
1090
1091                                                 if (true == __check_exdate_to_skip(current_utime, &list)) {
1092                                                         count++;
1093                                                         continue;
1094                                                 }
1095                                                 is_exit = __check_out_of_range(current_utime, event, until_utime, &count);
1096                                                 if (true == is_exit)
1097                                                         break;
1098                                                 _cal_db_instance_insert_record(ucal, duration, event);
1099                                         }
1100
1101                                 } else {
1102                                         int year = ucal_get(ucal, UCAL_YEAR, &ec);
1103
1104                                         ucal_set(ucal, UCAL_MONTH, bymonth[i] - 1);
1105                                         ucal_set(ucal, UCAL_DATE, 1);
1106                                         int byday_start = ucal_get(ucal, UCAL_DAY_OF_WEEK, &ec);
1107
1108                                         int dates_len = 0;
1109                                         __get_dates_in_month(ucal, week_bits, bymonth[i], &dates_len);
1110                                         DBG("dates_len (%d)", dates_len);
1111
1112                                         int index = -1;
1113                                         for (j = 0; j < 6; j++) { /* check weekno in month: max 6 */
1114                                                 for (k = 0; k < 7; k++) {
1115                                                         if (0 == (week_bits & (0x01 << ((byday_start -1 +k)%7)))) continue;
1116                                                         index++;
1117
1118                                                         int wday_int = (byday_start -1 +k) %7 + 1;
1119                                                         ucal_set(ucal, UCAL_WEEK_OF_MONTH, (j + 1) + (byday_start -1 +k) / 7);
1120                                                         if (year != ucal_get(ucal, UCAL_YEAR, &ec))
1121                                                                 ucal_set(ucal, UCAL_YEAR, year); /* year is changed from 12/30 */
1122                                                         ucal_set(ucal, UCAL_MONTH, bymonth[i] - 1);
1123                                                         ucal_set(ucal, UCAL_DAY_OF_WEEK, wday_int);
1124
1125                                                         int get_month = ucal_get(ucal, UCAL_MONTH, &ec) + 1;
1126                                                         if (bymonth[i] != get_month) { j = 6; break; }
1127
1128                                                         if (true == __check_bysetpos_to_skip(index, bysetpos, bysetpos_len, dates_len))
1129                                                                 continue;
1130
1131                                                         current_utime = ms2sec(ucal_getMillis(ucal, &ec));
1132                                                         if (true == __check_before_dtstart(current_utime, dtstart_utime))
1133                                                                 continue;
1134
1135                                                         if (true == __check_exdate_to_skip(current_utime, &list)) {
1136                                                                 count++;
1137                                                                 continue;
1138                                                         }
1139                                                         is_exit = __check_out_of_range(current_utime, event, until_utime, &count);
1140                                                         if (true == is_exit)
1141                                                                 break;
1142                                                         _cal_db_instance_insert_record(ucal, duration, event);
1143                                                 }
1144                                                 if (true == is_exit)
1145                                                         break;
1146                                         }
1147                                 }
1148                         }
1149                         if (true == is_exit)
1150                                 break;
1151                 }
1152                 if (true == is_exit)
1153                         break;
1154                 current_utime = ms2sec(ucal_getMillis(ucal, &ec));
1155                 is_exit = __check_to_stop_loop(current_utime, &last_utime, loop);
1156                 loop++;
1157         }
1158         g_strfreev(t);
1159         if (list)
1160                 g_list_free_full(list, free);
1161         return CALENDAR_ERROR_NONE;
1162 }
1163
1164 static int _cal_db_instance_publish_yearly_mday(UCalendar *ucal, cal_event_s *event, long long int duration)
1165 {
1166         RETV_IF(NULL == ucal, CALENDAR_ERROR_INVALID_PARAMETER);
1167         RETV_IF(NULL == event, CALENDAR_ERROR_INVALID_PARAMETER);
1168
1169         UErrorCode ec = U_ZERO_ERROR;
1170         calendar_time_s until = {0};
1171         __get_until_from_range(event, &until);
1172         __set_time_to_ucal(event->system_type, ucal, &until); /* set until before dtstart_utime */
1173         long long int until_utime = ms2sec(ucal_getMillis(ucal, &ec));
1174
1175         /* get bymonth into array */
1176         int bymonth[12] = {0};
1177         int bymonth_len = 0;
1178         _cal_db_instance_parse_byint(event->bymonth, bymonth, &bymonth_len);
1179         if (0 == bymonth_len) {
1180                 calendar_time_s *st = &event->start;
1181                 __set_time_to_ucal(event->system_type, ucal, st);
1182                 int month = ucal_get(ucal, UCAL_MONTH, &ec) + 1;
1183                 bymonth[0] = month;
1184                 bymonth_len = 1;
1185         }
1186         DBG("bymonth_len(%d)", bymonth_len);
1187
1188         /* get bymonthday into array */
1189         int bymonthday[CAL_STR_MIDDLE_LEN] = {0};
1190         int bymonthday_len = 0;
1191         _cal_db_instance_parse_byint(event->bymonthday, bymonthday, &bymonthday_len);
1192         if (0 == bymonthday_len) {
1193                 calendar_time_s *st = &event->start;
1194                 __set_time_to_ucal(event->system_type, ucal, st);
1195                 int dtstart_mday = ucal_get(ucal, UCAL_DATE, &ec);
1196                 bymonthday[0] = dtstart_mday;
1197                 bymonthday_len = 1;
1198         }
1199         DBG("bymonthday len(%d)", bymonthday_len);
1200
1201         int bysetpos[CAL_STR_MIDDLE_LEN] = {0};
1202         int bysetpos_len = 0;
1203         _cal_db_instance_parse_byint(event->bysetpos, bysetpos, &bysetpos_len);
1204         DBG("bysetpos len(%d)", bysetpos_len);
1205
1206         GList *list = NULL;
1207         __get_exdate_list(ucal, event, &list);
1208
1209         int loop = 0;
1210         int count = 0;
1211         bool is_exit = false;
1212         long long int last_utime = 0;
1213         long long int current_utime = 0;
1214         while (false == is_exit) {
1215                 calendar_time_s *st = &event->start;
1216                 __set_time_to_ucal(event->system_type, ucal, st);
1217                 long long int dtstart_utime = ms2sec(ucal_getMillis(ucal, &ec));
1218                 ucal_add(ucal, UCAL_YEAR, event->interval *loop, &ec);
1219                 ucal_setMillis(ucal, ucal_getMillis(ucal, &ec), &ec); /* set start point */
1220
1221                 int i, j;
1222                 for (j = 0; j < bymonth_len; j++) {
1223                         for (i = 0 ; i < bymonthday_len; i++) {
1224                                 if (0 < bymonthday[i]) {
1225                                         ucal_set(ucal, UCAL_MONTH, bymonth[j] - 1);
1226                                         ucal_set(ucal, UCAL_DATE, bymonthday[i]);
1227                                         int get_mday = ucal_get(ucal, UCAL_DATE, &ec);
1228                                         if (get_mday != bymonthday[i]) {
1229                                                 DBG("bymonthday(%d) but get (%d) from icu", bymonthday[i], get_mday);
1230                                                 continue;
1231                                         }
1232                                 } else if (bymonthday[i] < 0) {
1233                                         ucal_set(ucal, UCAL_MONTH, bymonth[j] - 1);
1234                                         ucal_set(ucal, UCAL_DATE, 1);
1235                                         ucal_add(ucal, UCAL_MONTH, 1, &ec);
1236                                         ucal_add(ucal, UCAL_DAY_OF_YEAR, bymonthday[i], &ec);
1237
1238                                 } else { /* 0 is invalid */
1239                                         DBG("Invalid bymonthday(%d)", bymonthday[i]);
1240                                         continue;
1241                                 }
1242                                 if (true == __check_bysetpos_to_skip(i, bysetpos, bysetpos_len, bymonthday_len)) {
1243                                         DBG("no bysetpos");
1244                                         continue;
1245                                 }
1246                                 current_utime = ms2sec(ucal_getMillis(ucal, &ec));
1247                                 if (true == __check_before_dtstart(current_utime, dtstart_utime))
1248                                         continue;
1249
1250                                 if (true == __check_exdate_to_skip(current_utime, &list)) {
1251                                         count++;
1252                                         continue;
1253                                 }
1254                                 is_exit = __check_out_of_range(current_utime, event, until_utime, &count);
1255                                 if (true == is_exit)
1256                                         break;
1257                                 _cal_db_instance_insert_record(ucal, duration, event);
1258                         }
1259                 }
1260                 if (true == is_exit)
1261                         break;
1262                 current_utime = ms2sec(ucal_getMillis(ucal, &ec));
1263                 is_exit = __check_to_stop_loop(current_utime, &last_utime, loop);
1264                 loop++;
1265         }
1266         if (list)
1267                 g_list_free_full(list, free);
1268         return CALENDAR_ERROR_NONE;
1269 }
1270
1271 static int _cal_db_instance_publish_record_yearly(UCalendar *ucal, cal_event_s *event, long long int duration)
1272 {
1273         RETV_IF(NULL == ucal, CALENDAR_ERROR_INVALID_PARAMETER);
1274         RETV_IF(NULL == event, CALENDAR_ERROR_INVALID_PARAMETER);
1275
1276         if (event->byyearday && 0 < strlen(event->byyearday)) {
1277                 _cal_db_instance_publish_yearly_yday(ucal, event, duration);
1278         } else if (event->byweekno && 0 < strlen(event->byweekno)) {
1279                 _cal_db_instance_publish_yearly_weekno(ucal, event, duration);
1280         } else {
1281                 if (event->byday && *event->byday)
1282                         _cal_db_instance_publish_yearly_wday(ucal, event, duration);
1283                 else
1284                         _cal_db_instance_publish_yearly_mday(ucal, event, duration);
1285         }
1286         return CALENDAR_ERROR_NONE;
1287 }
1288
1289 static int _cal_db_instance_publish_monthly_wday(UCalendar *ucal, cal_event_s *event, long long int duration)
1290 {
1291         RETV_IF(NULL == ucal, CALENDAR_ERROR_INVALID_PARAMETER);
1292         RETV_IF(NULL == event, CALENDAR_ERROR_INVALID_PARAMETER);
1293
1294         UErrorCode ec = U_ZERO_ERROR;
1295         calendar_time_s until = {0};
1296         __get_until_from_range(event, &until);
1297         __set_time_to_ucal(event->system_type, ucal, &until); /* set until before dtstart_utime */
1298         long long int until_utime = ms2sec(ucal_getMillis(ucal, &ec));
1299
1300         /* get bymonthday into array */
1301         int bymonthday[CAL_STR_MIDDLE_LEN] = {0};
1302         int bymonthday_len = 0;
1303         _cal_db_instance_parse_byint(event->bymonthday, bymonthday, &bymonthday_len);
1304
1305         char **t = NULL;
1306         int byday_len = 0;
1307
1308         /* if nowday in weekly */
1309         if (NULL == event->byday || '\0' == event->byday[0]) {
1310                 const char *week_text[7] = {"SU", "MO", "TU", "WE", "TH", "FR", "SA"};
1311
1312                 calendar_time_s *st = &event->start;
1313                 __set_time_to_ucal(event->system_type, ucal, st);
1314                 int week_nth = ucal_get(ucal, UCAL_DAY_OF_WEEK_IN_MONTH, &ec);
1315                 int dtstart_wday = ucal_get(ucal, UCAL_DAY_OF_WEEK, &ec);
1316                 char buf[CAL_STR_SHORT_LEN32] = {0};
1317                 snprintf(buf, sizeof(buf), "%d%s", week_nth, week_text[dtstart_wday -1]);
1318                 DBG("set byday[%s]", buf);
1319
1320                 t = g_strsplit_set(buf, " ,", -1);
1321                 byday_len = 1;
1322
1323         } else {
1324                 t = g_strsplit_set(event->byday, " ,", -1);
1325                 byday_len = g_strv_length(t);
1326         }
1327         DBG("[%s] byday_len(%d)", event->byday, byday_len);
1328
1329         int bysetpos[CAL_STR_MIDDLE_LEN] = {0};
1330         int bysetpos_len = 0;
1331         _cal_db_instance_parse_byint(event->bysetpos, bysetpos, &bysetpos_len);
1332         DBG("bysetpos len(%d)", bysetpos_len);
1333
1334         GList *list = NULL;
1335         __get_exdate_list(ucal, event, &list);
1336
1337         int loop = 0;
1338         int count = 0;
1339         bool is_exit = false;
1340         long long int last_utime = 0;
1341         long long int current_utime = 0;
1342         while (false == is_exit) {
1343                 calendar_time_s *st = &event->start;
1344                 __set_time_to_ucal(event->system_type, ucal, st);
1345                 long long int dtstart_utime = ms2sec(ucal_getMillis(ucal, &ec));
1346                 ucal_add(ucal, UCAL_MONTH, event->interval * loop, &ec);
1347                 ucal_setMillis(ucal, ucal_getMillis(ucal, &ec), &ec); /* set start point */
1348
1349                 int i, j, k;
1350                 if (2 < strlen(t[0])) { /* -3SU, +2SA */
1351                         for (i = 0; i < byday_len; i++) {
1352                                 if (0 == strlen(t[i]))
1353                                         continue;
1354                                 /* get nth, wday */
1355                                 int nth = 0;
1356                                 char wday[CAL_STR_SHORT_LEN32] = {0};
1357
1358                                 sscanf(t[i], "%d%s", &nth, wday); /* -3SU, +2SA */
1359                                 DBG("nth(%d) wday[%s]", nth, wday);
1360                                 int wday_int = __convert_wday_to_int(wday);
1361
1362                                 /* set nth, wday */
1363                                 if (0 < nth) {
1364                                         if (4 < nth) {
1365                                                 ucal_set(ucal, UCAL_DAY_OF_WEEK, wday_int);
1366                                                 ucal_set(ucal, UCAL_DAY_OF_WEEK_IN_MONTH, -1);
1367
1368                                         } else {
1369                                                 ucal_set(ucal, UCAL_DAY_OF_WEEK, wday_int);
1370                                                 ucal_set(ucal, UCAL_DAY_OF_WEEK_IN_MONTH, 1);
1371                                                 ucal_add(ucal, UCAL_WEEK_OF_YEAR, nth - 1, &ec);
1372                                         }
1373                                 } else {
1374                                         ucal_set(ucal, UCAL_DAY_OF_WEEK, wday_int);
1375                                         ucal_set(ucal, UCAL_DAY_OF_WEEK_IN_MONTH, nth);
1376                                 }
1377                                 if (true == __check_bysetpos_to_skip(i, bysetpos, bysetpos_len, byday_len))
1378                                         continue;
1379
1380                                 current_utime = ms2sec(ucal_getMillis(ucal, &ec));
1381                                 if (true == __check_before_dtstart(current_utime, dtstart_utime))
1382                                         continue;
1383
1384                                 if (true == __check_exdate_to_skip(current_utime, &list)) {
1385                                         count++;
1386                                         continue;
1387                                 }
1388                                 is_exit = __check_out_of_range(current_utime, event, until_utime, &count);
1389                                 if (true == is_exit)
1390                                         break;
1391                                 _cal_db_instance_insert_record(ucal, duration, event);
1392                         }
1393
1394                 } else { /* SU, SA: no week num: means all week:1TH,2TH,3TH.., so needs another byevent->system_type */
1395                         int week_bits = 0;
1396                         /* if nowday in weekly */
1397                         if (NULL == event->byday || '\0' == event->byday[0]) {
1398                                 calendar_time_s *st = &event->start;
1399                                 __set_time_to_ucal(event->system_type, ucal, st);
1400                                 int dtstart_wday = ucal_get(ucal, UCAL_DAY_OF_WEEK, &ec);
1401                                 week_bits |= (0x01 << (dtstart_wday - 1));
1402
1403                         } else {
1404                                 week_bits = __convert_week_to_bits(event->byday, NULL);
1405                         }
1406                         DBG("week integer(0x%x)", week_bits);
1407
1408                         if (bymonthday_len) { /* bymonthday */
1409                                 for (j = 0; j < bymonthday_len; j++) {
1410                                         ucal_set(ucal, UCAL_DATE, bymonthday[j]);
1411                                         bool is_match_wday = false;
1412                                         int w = ucal_get(ucal, UCAL_DAY_OF_WEEK, &ec);
1413                                         for (k = 0; k < 7; k++) { /* check if this is one of wday */
1414                                                 if (week_bits & (0x01 << k)) {
1415                                                         if ((k + 1) == w) {
1416                                                                 is_match_wday = true;
1417                                                                 break;
1418                                                         }
1419                                                 }
1420                                         }
1421                                         if (false == is_match_wday) {
1422                                                 DBG("get wday(%d) != want wday(%d)", w, k + 1);
1423                                                 continue;
1424                                         }
1425                                         if (true == __check_bysetpos_to_skip(j, bysetpos, bysetpos_len, bymonthday_len))
1426                                                 continue;
1427
1428                                         current_utime = ms2sec(ucal_getMillis(ucal, &ec));
1429                                         if (true == __check_before_dtstart(current_utime, dtstart_utime))
1430                                                 continue;
1431
1432                                         if (true == __check_exdate_to_skip(current_utime, &list)) {
1433                                                 count++;
1434                                                 continue;
1435                                         }
1436                                         is_exit = __check_out_of_range(current_utime, event, until_utime, &count);
1437                                         if (true == is_exit)
1438                                                 break;
1439                                         _cal_db_instance_insert_record(ucal, duration, event);
1440                                 }
1441
1442                         } else {
1443                                 int year = ucal_get(ucal, UCAL_YEAR, &ec);
1444                                 int month = ucal_get(ucal, UCAL_MONTH, &ec) + 1;
1445
1446                                 ucal_set(ucal, UCAL_MONTH, month - 1);
1447                                 ucal_set(ucal, UCAL_DATE, 1);
1448                                 int byday_start = ucal_get(ucal, UCAL_DAY_OF_WEEK, &ec);
1449
1450                                 int dates_len = 0;
1451                                 __get_dates_in_month(ucal, week_bits, month, &dates_len);
1452                                 DBG("month(%d) dates_len (%d)", month, dates_len);
1453
1454                                 int index = -1;
1455                                 for (j = 0; j < 6; j++) { /* check weekno in month: max 6 */
1456                                         for (k = 0; k < 7; k++) {
1457                                                 if (0 == (week_bits & (0x01 << ((byday_start -1 +k)%7)))) continue;
1458                                                 index++;
1459
1460                                                 int wday_int = (byday_start -1 +k) %7 + 1;
1461                                                 ucal_set(ucal, UCAL_WEEK_OF_MONTH, (j + 1) + (byday_start -1 +k) / 7);
1462                                                 if (year != ucal_get(ucal, UCAL_YEAR, &ec)) ucal_set(ucal, UCAL_YEAR, year);
1463                                                 ucal_set(ucal, UCAL_MONTH, month - 1);
1464                                                 ucal_set(ucal, UCAL_DAY_OF_WEEK, wday_int);
1465
1466                                                 int get_month = ucal_get(ucal, UCAL_MONTH, &ec) + 1;
1467                                                 if (month != get_month) { j = 6; break; }
1468
1469                                                 if (true == __check_bysetpos_to_skip(index, bysetpos, bysetpos_len, dates_len))
1470                                                         continue;
1471
1472                                                 current_utime = ms2sec(ucal_getMillis(ucal, &ec));
1473                                                 if (true == __check_before_dtstart(current_utime, dtstart_utime))
1474                                                         continue;
1475
1476                                                 if (true == __check_exdate_to_skip(current_utime, &list)) {
1477                                                         count++;
1478                                                         continue;
1479                                                 }
1480                                                 is_exit = __check_out_of_range(current_utime, event, until_utime, &count);
1481                                                 if (true == is_exit)
1482                                                         break;
1483                                                 _cal_db_instance_insert_record(ucal, duration, event);
1484                                         }
1485                                         if (true == is_exit)
1486                                                 break;
1487                                 }
1488                         }
1489                 }
1490                 if (true == is_exit)
1491                         break;
1492                 current_utime = ms2sec(ucal_getMillis(ucal, &ec));
1493                 is_exit = __check_to_stop_loop(current_utime, &last_utime, loop);
1494                 loop++;
1495         }
1496         g_strfreev(t);
1497         if (list)
1498                 g_list_free_full(list, free);
1499         return CALENDAR_ERROR_NONE;
1500 }
1501
1502 static int _cal_db_instance_publish_monthly_mday(UCalendar *ucal, cal_event_s *event, long long int duration)
1503 {
1504         RETV_IF(NULL == ucal, CALENDAR_ERROR_INVALID_PARAMETER);
1505         RETV_IF(NULL == event, CALENDAR_ERROR_INVALID_PARAMETER);
1506
1507         UErrorCode ec = U_ZERO_ERROR;
1508         calendar_time_s until = {0};
1509         __get_until_from_range(event, &until);
1510         __set_time_to_ucal(event->system_type, ucal, &until); /* set until before dtstart_utime */
1511         long long int until_utime = ms2sec(ucal_getMillis(ucal, &ec));
1512
1513         /* get bymonthday into array */
1514         int bymonthday[CAL_STR_MIDDLE_LEN] = {0};
1515         int bymonthday_len = 0;
1516         _cal_db_instance_parse_byint(event->bymonthday, bymonthday, &bymonthday_len);
1517         if (0 == bymonthday_len) {
1518                 calendar_time_s *st = &event->start;
1519                 __set_time_to_ucal(event->system_type, ucal, st);
1520                 int dtstart_mday = ucal_get(ucal, UCAL_DATE, &ec);
1521                 bymonthday[0] = dtstart_mday;
1522                 bymonthday_len = 1;
1523         }
1524         DBG("bymonthday_len(%d) [%s]", bymonthday_len, event->bymonthday);
1525
1526         int bysetpos[CAL_STR_MIDDLE_LEN] = {0};
1527         int bysetpos_len = 0;
1528         _cal_db_instance_parse_byint(event->bysetpos, bysetpos, &bysetpos_len);
1529         DBG("bysetpos_len(%d)", bysetpos_len);
1530
1531         GList *list = NULL;
1532         __get_exdate_list(ucal, event, &list);
1533
1534         int loop = 0;
1535         int count = 0;
1536         bool is_exit = false;
1537         long long int last_utime = 0;
1538         long long int current_utime = 0;
1539         while (false == is_exit) {
1540                 calendar_time_s *st = &event->start;
1541                 __set_time_to_ucal(event->system_type, ucal, st);
1542                 long long int dtstart_utime = ms2sec(ucal_getMillis(ucal, &ec));
1543                 ucal_add(ucal, UCAL_MONTH, event->interval * loop, &ec);
1544                 ucal_setMillis(ucal, ucal_getMillis(ucal, &ec), &ec); /* set start point */
1545
1546                 int i;
1547                 for (i = 0 ; i < bymonthday_len; i++) {
1548                         if (0 < bymonthday[i]) {
1549                                 ucal_set(ucal, UCAL_MONTH, ucal_get(ucal, UCAL_MONTH, &ec));
1550                                 ucal_set(ucal, UCAL_DATE, bymonthday[i]);
1551                                 int get_mday = ucal_get(ucal, UCAL_DATE, &ec);
1552                                 if (get_mday != bymonthday[i]) {
1553                                         DBG("bymonthday(%d) but get (%d) from icu", bymonthday[i], get_mday);
1554                                         continue;
1555                                 }
1556                         } else if (bymonthday[i] < 0) {
1557                                 ucal_set(ucal, UCAL_DATE, 1);
1558                                 ucal_add(ucal, UCAL_MONTH, 1, &ec);
1559                                 ucal_add(ucal, UCAL_DAY_OF_YEAR, bymonthday[i], &ec);
1560
1561                         } else { /* 0 is invalid */
1562                                 DBG("Invalid bymonthday(%d)", bymonthday[i]);
1563                                 continue;
1564                         }
1565                         if (true == __check_bysetpos_to_skip(i, bysetpos, bysetpos_len, bymonthday_len))
1566                                 continue;
1567
1568                         current_utime = ms2sec(ucal_getMillis(ucal, &ec));
1569                         if (true == __check_before_dtstart(current_utime, dtstart_utime))
1570                                 continue;
1571
1572                         if (true == __check_exdate_to_skip(current_utime, &list)) {
1573                                 count++;
1574                                 continue;
1575                         }
1576                         is_exit = __check_out_of_range(current_utime, event, until_utime, &count);
1577                         if (true == is_exit)
1578                                 break;
1579                         _cal_db_instance_insert_record(ucal, duration, event);
1580                 }
1581                 if (true == is_exit)
1582                         break;
1583                 current_utime = ms2sec(ucal_getMillis(ucal, &ec));
1584                 is_exit = __check_to_stop_loop(current_utime, &last_utime, loop);
1585                 loop++;
1586         }
1587         if (list)
1588                 g_list_free_full(list, free);
1589         return CALENDAR_ERROR_NONE;
1590 }
1591
1592 static int _cal_db_instance_publish_record_monthly(UCalendar *ucal, cal_event_s *event, long long int duration)
1593 {
1594         RETV_IF(NULL == ucal, CALENDAR_ERROR_INVALID_PARAMETER);
1595         RETV_IF(NULL == event, CALENDAR_ERROR_INVALID_PARAMETER);
1596
1597         if (event->byday && 0 < strlen(event->byday))
1598                 _cal_db_instance_publish_monthly_wday(ucal, event, duration);
1599         else
1600                 _cal_db_instance_publish_monthly_mday(ucal, event, duration);
1601
1602         return CALENDAR_ERROR_NONE;
1603 }
1604
1605 static int _cal_db_instance_publish_weekly_wday(UCalendar *ucal, cal_event_s *event, long long int duration)
1606 {
1607         RETV_IF(NULL == ucal, CALENDAR_ERROR_INVALID_PARAMETER);
1608         RETV_IF(NULL == event, CALENDAR_ERROR_INVALID_PARAMETER);
1609
1610         UErrorCode ec = U_ZERO_ERROR;
1611         calendar_time_s until = {0};
1612         __get_until_from_range(event, &until);
1613         __set_time_to_ucal(event->system_type, ucal, &until); /* set until before dtstart_utime */
1614         long long int until_utime = ms2sec(ucal_getMillis(ucal, &ec));
1615
1616         int week_bits = 0;
1617         int byday_len = 0;
1618         /* if nowday in weekly */
1619         if (NULL == event->byday || '\0' == event->byday[0]) {
1620                 calendar_time_s *st = &event->start;
1621                 __set_time_to_ucal(event->system_type, ucal, st);
1622                 int dtstart_wday = ucal_get(ucal, UCAL_DAY_OF_WEEK, &ec);
1623                 week_bits |= (0x01 << (dtstart_wday - 1));
1624
1625         } else {
1626                 week_bits = __convert_week_to_bits(event->byday, &byday_len);
1627         }
1628         DBG("week integer(0x%x)", week_bits);
1629
1630         int bysetpos[CAL_STR_MIDDLE_LEN] = {0};
1631         int bysetpos_len = 0;
1632         _cal_db_instance_parse_byint(event->bysetpos, bysetpos, &bysetpos_len);
1633         DBG("bysetpos len(%d)", bysetpos_len);
1634
1635         GList *list = NULL;
1636         __get_exdate_list(ucal, event, &list);
1637
1638         int byday_start = ucal_getAttribute(ucal, UCAL_FIRST_DAY_OF_WEEK);
1639         DBG("get first day of week(%d)", byday_start);
1640
1641         int loop = 0;
1642         int count = 0;
1643         bool is_exit = false;
1644         long long int last_utime = 0;
1645         long long int current_utime = 0;
1646         while (false == is_exit) {
1647                 calendar_time_s *st = &event->start;
1648                 __set_time_to_ucal(event->system_type, ucal, st);
1649                 long long int dtstart_utime = ms2sec(ucal_getMillis(ucal, &ec));
1650                 ucal_add(ucal, UCAL_WEEK_OF_YEAR, event->interval *loop, &ec);
1651                 ucal_setMillis(ucal, ucal_getMillis(ucal, &ec), &ec); /* set start point */
1652
1653                 int i;
1654                 int index = -1;
1655                 for (i = 0; i < 7; i++) {
1656                         if (0 == (week_bits & (0x01 << ((byday_start -1 +i)%7))))
1657                                 continue;
1658                         index++;
1659
1660                         int wday_int = (byday_start -1 +i) %7 + 1;
1661                         ucal_set(ucal, UCAL_DAY_OF_WEEK, wday_int);
1662
1663                         if (true == __check_bysetpos_to_skip(index, bysetpos, bysetpos_len, byday_len))
1664                                 continue;
1665
1666                         current_utime = ms2sec(ucal_getMillis(ucal, &ec));
1667                         if (true == __check_before_dtstart(current_utime, dtstart_utime))
1668                                 continue;
1669
1670                         if (true == __check_exdate_to_skip(current_utime, &list)) {
1671                                 count++;
1672                                 continue;
1673                         }
1674                         is_exit = __check_out_of_range(current_utime, event, until_utime, &count);
1675                         if (true == is_exit)
1676                                 break;
1677                         _cal_db_instance_insert_record(ucal, duration, event);
1678                 }
1679                 if (true == is_exit)
1680                         break;
1681                 current_utime = ms2sec(ucal_getMillis(ucal, &ec));
1682                 is_exit = __check_to_stop_loop(current_utime, &last_utime, loop);
1683                 loop++;
1684         }
1685         if (list)
1686                 g_list_free_full(list, free);
1687         return CALENDAR_ERROR_NONE;
1688 }
1689
1690 static int _cal_db_instance_publish_record_weekly(UCalendar *ucal, cal_event_s *event, long long int duration)
1691 {
1692         RETV_IF(NULL == ucal, CALENDAR_ERROR_INVALID_PARAMETER);
1693         RETV_IF(NULL == event, CALENDAR_ERROR_INVALID_PARAMETER);
1694
1695         _cal_db_instance_publish_weekly_wday(ucal, event, duration);
1696         return CALENDAR_ERROR_NONE;
1697 }
1698
1699 static int _cal_db_instance_publish_daily_mday(UCalendar *ucal, cal_event_s *event, long long int duration)
1700 {
1701         RETV_IF(NULL == ucal, CALENDAR_ERROR_INVALID_PARAMETER);
1702         RETV_IF(NULL == event, CALENDAR_ERROR_INVALID_PARAMETER);
1703
1704         UErrorCode ec = U_ZERO_ERROR;
1705         calendar_time_s until = {0};
1706         __get_until_from_range(event, &until);
1707         __set_time_to_ucal(event->system_type, ucal, &until); /* set until before dtstart_utime */
1708         long long int until_utime = ms2sec(ucal_getMillis(ucal, &ec));
1709
1710         /* get bymonth into array */
1711         int bymonth[12] = {0};
1712         int bymonth_len = 0;
1713         _cal_db_instance_parse_byint(event->bymonth, bymonth, &bymonth_len);
1714
1715         GList *list = NULL;
1716         __get_exdate_list(ucal, event, &list);
1717
1718         calendar_time_s *st = &event->start;
1719         __set_time_to_ucal(event->system_type, ucal, st);
1720         long long int dtstart_utime = ms2sec(ucal_getMillis(ucal, &ec));
1721         DBG("(%lld)", ms2sec(ucal_getMillis(ucal, &ec)));
1722
1723         int loop = 0;
1724         int count = 0;
1725         bool is_exit = false;
1726         long long int last_utime = 0;
1727         long long int current_utime = 0;
1728         int log_value = 0;
1729         while (false == is_exit) {
1730                 if (loop) ucal_add(ucal, UCAL_DAY_OF_YEAR, event->interval, &ec);
1731
1732                 if (true == __check_daily_bymonth_to_skip(ucal, bymonth, bymonth_len, &log_value)) {
1733                         if (0 == loop) loop = 1;
1734                         continue;
1735                 }
1736                 current_utime = ms2sec(ucal_getMillis(ucal, &ec));
1737                 if (true == __check_before_dtstart(current_utime, dtstart_utime)) {
1738                         if (0 == loop) loop = 1;
1739                         continue;
1740                 }
1741                 if (true == __check_exdate_to_skip(current_utime, &list)) {
1742                         if (0 == loop) loop = 1;
1743                         count++;
1744                         continue;
1745                 }
1746                 is_exit = __check_out_of_range(current_utime, event, until_utime, &count);
1747                 if (true == is_exit) break;
1748                 _cal_db_instance_insert_record(ucal, duration, event);
1749
1750                 current_utime = ms2sec(ucal_getMillis(ucal, &ec));
1751                 is_exit = __check_to_stop_loop(current_utime, &last_utime, loop);
1752                 loop++;
1753         }
1754         if (list)
1755                 g_list_free_full(list, free);
1756         return CALENDAR_ERROR_NONE;
1757 }
1758
1759 static int _cal_db_instance_publish_record_daily(UCalendar *ucal, cal_event_s *event, long long int duration)
1760 {
1761         RETV_IF(NULL == ucal, CALENDAR_ERROR_INVALID_PARAMETER);
1762         RETV_IF(NULL == event, CALENDAR_ERROR_INVALID_PARAMETER);
1763
1764         _cal_db_instance_publish_daily_mday(ucal, event, duration);
1765         return CALENDAR_ERROR_NONE;
1766 }
1767
1768 static int _cal_db_instance_publish_record_once(UCalendar *ucal, cal_event_s *event, long long int duration)
1769 {
1770         RETV_IF(NULL == ucal, CALENDAR_ERROR_INVALID_PARAMETER);
1771         RETV_IF(NULL == event, CALENDAR_ERROR_INVALID_PARAMETER);
1772
1773         calendar_time_s *st = &event->start;
1774         __set_time_to_ucal(event->system_type, ucal, st);
1775         _cal_db_instance_insert_record(ucal, duration, event);
1776         return CALENDAR_ERROR_NONE;
1777 }
1778
1779 static int _cal_db_instance_publish_record_details(UCalendar *ucal, cal_event_s *event)
1780 {
1781         RETV_IF(NULL == ucal, CALENDAR_ERROR_INVALID_PARAMETER);
1782         RETV_IF(NULL == event, CALENDAR_ERROR_INVALID_PARAMETER);
1783
1784         long long int duration = -1;
1785         int exception_freq = 0; /* for exception */
1786
1787         _cal_db_instance_get_duration(ucal, &event->start, &event->end, &duration);
1788         WARN_IF(duration < 0, "Invalid duration (%lld)", duration);
1789
1790         if (0 < event->original_event_id) {
1791                 DBG("this is exception event so publish only one instance");
1792                 exception_freq = event->freq;
1793                 event->freq = CALENDAR_RECURRENCE_NONE;
1794         }
1795
1796         DBG("event interval(%d)", event->interval);
1797         if (event->interval < 1) {
1798                 DBG("Invalid interval, so set 1");
1799                 event->interval = 1;
1800         }
1801
1802         switch (event->freq) {
1803         case CALENDAR_RECURRENCE_YEARLY:
1804                 _cal_db_instance_publish_record_yearly(ucal, event, duration);
1805                 break;
1806
1807         case CALENDAR_RECURRENCE_MONTHLY:
1808                 _cal_db_instance_publish_record_monthly(ucal, event, duration);
1809                 break;
1810
1811         case CALENDAR_RECURRENCE_WEEKLY:
1812                 _cal_db_instance_publish_record_weekly(ucal, event, duration);
1813                 break;
1814
1815         case CALENDAR_RECURRENCE_DAILY:
1816                 _cal_db_instance_publish_record_daily(ucal, event, duration);
1817                 break;
1818
1819         case CALENDAR_RECURRENCE_NONE:
1820         default:
1821                 _cal_db_instance_publish_record_once(ucal, event, duration);
1822                 break;
1823         }
1824
1825         if (0 < event->original_event_id) {
1826                 DBG("return freq for exception event");
1827                 event->freq = exception_freq;
1828         }
1829
1830         return CALENDAR_ERROR_NONE;
1831 }
1832
1833 int cal_db_instance_update_exdate_del(int id, char *exdate)
1834 {
1835         int ret = 0;
1836         char query[CAL_DB_SQL_MAX_LEN] = {0};
1837         char **t = NULL;
1838         char *p = NULL;
1839
1840         if (NULL == exdate || '\0' == *exdate) {
1841                 DBG("Nothing to update exdate del");
1842                 return CALENDAR_ERROR_NONE;
1843         }
1844
1845         DBG("exdate[%s]", exdate);
1846         t = g_strsplit_set(exdate, " ,", -1);
1847         if (NULL == t) {
1848                 ERR("g_strsplit_set() Fail");
1849                 return CALENDAR_ERROR_OUT_OF_MEMORY;
1850         }
1851
1852         int i;
1853         for (i = 0; t[i]; i++) {
1854                 if (NULL == t[i] || '\0' == *t[i]) continue;
1855
1856                 int y = 0, m = 0, d = 0;
1857                 int h = 0, n = 0, s = 0;
1858
1859                 p = t[i];
1860                 DBG("exdate[%s]", p);
1861                 int len = strlen(p);
1862                 switch (len) {
1863                 case 8: /* 20141212 */
1864                         DBG("ALLDAY instance");
1865                         sscanf(p, CAL_DATETIME_FORMAT_YYYYMMDD, &y, &m, &d);
1866                         snprintf(query, sizeof(query), "DELETE FROM %s "
1867                                         "WHERE event_id = %d AND dtstart_datetime = '%04d-%02d-%02dT%02d:%02d:%02d' ",
1868                                         CAL_TABLE_ALLDAY_INSTANCE, id, y, m, d, h, n, s);
1869                         break;
1870
1871                 case 15: /* 20141212T000000 */
1872                         sscanf(p, CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSS, &y, &m, &d, &h, &n, &s);
1873                         snprintf(query, sizeof(query), "DELETE FROM %s "
1874                                         "WHERE event_id = %d AND dtstart_datetime = '%04d-%02d-%02dT%02d:%02d:%02d' ",
1875                                         CAL_TABLE_ALLDAY_INSTANCE, id, y, m, d, h, n, s);
1876                         DBG("localtime instance");
1877                         break;
1878
1879                 case 16: /* 20141212T000000Z */
1880                         sscanf(p, CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSSZ, &y, &m, &d, &h, &n, &s);
1881                         snprintf(query, sizeof(query), "DELETE FROM %s "
1882                                         "WHERE event_id = %d AND dtstart_utime = %lld ",
1883                                         CAL_TABLE_NORMAL_INSTANCE, id, cal_time_convert_itol(NULL, y, m, d, h, n, s));
1884                         DBG("normal instance (%lld)", cal_time_convert_itol(NULL, y, m, d, h, n, s));
1885                         break;
1886                 }
1887
1888                 ret = cal_db_util_query_exec(query);
1889                 if (CALENDAR_ERROR_NONE != ret) {
1890                         ERR("cal_db_util_query_exec() Fail(%d)", ret);
1891                         SECURE("[%s]", query);
1892                         g_strfreev(t);
1893                         return ret;
1894                 }
1895         }
1896         g_strfreev(t);
1897         return CALENDAR_ERROR_NONE;
1898 }
1899
1900 int cal_db_instance_publish_record(calendar_record_h record)
1901 {
1902         RETV_IF(NULL == record, CALENDAR_ERROR_INVALID_PARAMETER);
1903
1904         cal_event_s *event = NULL;
1905         event = (cal_event_s *)(record);
1906
1907         char *tzid = NULL;
1908         int offset = 0;
1909         int sign = 0;
1910         char buf[CAL_STR_SHORT_LEN32] = {0};
1911         switch (event->start.type) {
1912         case CALENDAR_TIME_UTIME:
1913                 if (NULL == event->start_tzid) {
1914                         tzid = NULL;
1915                         break;
1916                 }
1917                 if (true == cal_time_is_available_tzid(event->start_tzid)) {
1918                         tzid = event->start_tzid;
1919                         break;
1920                 }
1921                 cal_db_timezone_get_offset(event->calendar_id, event->start_tzid, &offset);
1922                 if (0 == offset) {
1923                         tzid = NULL;
1924                         break;
1925                 }
1926                 DBG("offset(%d)", offset);
1927                 sign = offset < 0 ? -1 : 1;
1928                 offset /= 60;
1929                 offset *= sign;
1930                 snprintf(buf, sizeof(buf), "Etc/GMT%c%d", sign < 0 ? '-' : '+', offset);
1931                 tzid = buf;
1932                 DBG("set tzid[%s]", buf);
1933                 break;
1934
1935         case CALENDAR_TIME_LOCALTIME:
1936                 tzid = NULL;
1937                 break;
1938         }
1939
1940         UCalendar *ucal = cal_time_open_ucal(event->system_type, tzid, event->wkst);
1941
1942         _cal_db_instance_publish_record_details(ucal, event);
1943         _cal_db_instance_del_inundant(event->index, &event->start, event);
1944         _cal_db_instance_update_exdate_mod(event->original_event_id, event->recurrence_id);
1945
1946         ucal_close(ucal);
1947
1948         return CALENDAR_ERROR_NONE;
1949 }
1950
1951 int cal_db_instance_get_now(long long int *current)
1952 {
1953         *current = ms2sec(ucal_getNow());
1954         return CALENDAR_ERROR_NONE;
1955 }
1956
1957 int cal_db_instance_discard_record(int index)
1958 {
1959         char query[CAL_DB_SQL_MAX_LEN] = {0};
1960         int ret = 0;
1961
1962         DBG("delete normal");
1963         snprintf(query, sizeof(query), "DELETE FROM %s WHERE event_id = %d ",
1964                         CAL_TABLE_NORMAL_INSTANCE, index);
1965
1966         ret = cal_db_util_query_exec(query);
1967         if (CALENDAR_ERROR_NONE != ret) {
1968                 ERR("cal_db_util_query_exec() Fail(%d)", ret);
1969                 SECURE("[%s]", query);
1970                 return ret;
1971         }
1972
1973         DBG("delete allday");
1974         snprintf(query, sizeof(query), "DELETE FROM %s WHERE event_id = %d ",
1975                         CAL_TABLE_ALLDAY_INSTANCE, index);
1976
1977         ret = cal_db_util_query_exec(query);
1978         if (CALENDAR_ERROR_NONE != ret) {
1979                 ERR("cal_db_util_query_exec() Fail(%d)", ret);
1980                 SECURE("[%s]", query);
1981                 return ret;
1982         }
1983         return CALENDAR_ERROR_NONE;
1984 }
1985