4 * Copyright (c) 2012 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 #include "calendar_list.h"
24 #include "cal_internal.h"
25 #include "cal_typedef.h"
26 #include "cal_record.h"
29 #include "cal_vcalendar.h"
30 #include "cal_vcalendar_parse.h"
31 #include "cal_utils.h"
41 char *timezone_tzid; /* TZ(ver1) VTIMEZONE(ver2) */
42 char *datetime_tzid; /* in vevent, vtodo as param: TZID=US-Eastern */
44 int type; /* event, todo */
57 VCAL_RECURRENCE_YEARLY_BYYEARDAY,
58 VCAL_RECURRENCE_YEARLY_BYWEEKLY,
59 VCAL_RECURRENCE_YEARLY_BYMONTH,
60 VCAL_RECURRENCE_YEARLY_BYMONTHDAY,
61 VCAL_RECURRENCE_YEARLY_BYDAY,
62 VCAL_RECURRENCE_MONTHLY_BYMONTHDAY,
63 VCAL_RECURRENCE_MONTHLY_BYDAY,
64 VCAL_RECURRENCE_WEEKLY,
65 VCAL_RECURRENCE_DAILY,
74 VCAL_DATETIME_LENGTH_YYYYMMDD = 8,
75 VCAL_DATETIME_LENGTH_YYYYMMDDTHHMMSS = 15,
76 VCAL_DATETIME_LENGTH_YYYYMMDDTHHMMSSZ = 16,
81 VCAL_COMPONENT_VEVENT,
83 VCAL_COMPONENT_VJOURNAL,
84 VCAL_COMPONENT_VFREEBUSY,
85 VCAL_COMPONENT_VTIMEZONE,
91 VCAL_PROPERTY_VERSION,
99 VCAL_COMPONENT_PROPERTY_NONE,
100 VCAL_COMPONENT_PROPERTY_DTSTAMP,
101 VCAL_COMPONENT_PROPERTY_UID,
102 VCAL_COMPONENT_PROPERTY_RECURRENCE_ID,
103 VCAL_COMPONENT_PROPERTY_DTSTART,
104 VCAL_COMPONENT_PROPERTY_CREATED, /* for ver 2: created */
105 VCAL_COMPONENT_PROPERTY_DCREATED, /* for ver 1: created */
106 VCAL_COMPONENT_PROPERTY_DESCRIPTION,
107 VCAL_COMPONENT_PROPERTY_LAST_MODIFIED,
108 VCAL_COMPONENT_PROPERTY_LOCATION,
109 VCAL_COMPONENT_PROPERTY_PRIORITY,
110 VCAL_COMPONENT_PROPERTY_STATUS,
111 VCAL_COMPONENT_PROPERTY_SUMMARY,
112 VCAL_COMPONENT_PROPERTY_RRULE,
113 VCAL_COMPONENT_PROPERTY_DTEND,
114 VCAL_COMPONENT_PROPERTY_DUE,
115 VCAL_COMPONENT_PROPERTY_ATTENDEE,
116 VCAL_COMPONENT_PROPERTY_CATEGORIES,
117 VCAL_COMPONENT_PROPERTY_DALARM, /* for ver 1: display alarm */
118 VCAL_COMPONENT_PROPERTY_MALARM, /* for ver 1: mail alarm */
119 VCAL_COMPONENT_PROPERTY_AALARM, /* for ver 1: audio alarm */
120 VCAL_COMPONENT_PROPERTY_EXDATE,
121 VCAL_COMPONENT_PROPERTY_X_ALLDAY,
122 VCAL_COMPONENT_PROPERTY_X_LUNAR,
123 VCAL_COMPONENT_PROPERTY_BEGIN,
124 VCAL_COMPONENT_PROPERTY_END,
125 VCAL_COMPONENT_PROPERTY_EXTENDED,
126 VCAL_COMPONENT_PROPERTY_MAX,
130 VCAL_COMPONENT_PROPERTY_VALARM_NONE,
131 VCAL_COMPONENT_PROPERTY_VALARM_ACTION,
132 VCAL_COMPONENT_PROPERTY_VALARM_TRIGGER,
133 VCAL_COMPONENT_PROPERTY_VALARM_REPEAT,
134 VCAL_COMPONENT_PROPERTY_VALARM_ATTACH,
135 VCAL_COMPONENT_PROPERTY_VALARM_DESCRIPTION,
136 VCAL_COMPONENT_PROPERTY_VALARM_SUMMARY,
137 VCAL_COMPONENT_PROPERTY_VALARM_DURATION,
138 VCAL_COMPONENT_PROPERTY_VALARM_END,
139 VCAL_COMPONENT_PROPERTY_VALARM_MAX,
144 VCAL_ENCODING_BASE64,
145 VCAL_ENCODING_QUOTED_PRINTABLE,
153 VCAL_CHARSET_ISO_8859_1,
154 VCAL_CHARSET_UTF_MAX,
158 VCAL_COMPONENT_PROPERTY_VTIMEZONE_NONE,
159 VCAL_COMPONENT_PROPERTY_VTIMEZONE_DTSTART,
160 VCAL_COMPONENT_PROPERTY_VTIMEZONE_TZOFFSETFROM,
161 VCAL_COMPONENT_PROPERTY_VTIMEZONE_TZOFFSETTO,
162 VCAL_COMPONENT_PROPERTY_VTIMEZONE_TZNAME,
163 VCAL_COMPONENT_PROPERTY_VTIMEZONE_RDATE,
164 VCAL_COMPONENT_PROPERTY_VTIMEZONE_END,
165 VCAL_COMPONENT_PROPERTY_VTIMEZONE_MAX,
169 VCAL_VER_10_DALARM_NONE = 0,
170 VCAL_VER_10_DALARM_RUN_TIME,
171 VCAL_VER_10_DALARM_SNOOZE_TIME,
172 VCAL_VER_10_DALARM_REPEAT_COUNT,
173 VCAL_VER_10_DALARM_DISPLAY_STRING,
177 VCAL_VER_10_MALARM_NONE = 0,
178 VCAL_VER_10_MALARM_RUN_TIME,
179 VCAL_VER_10_MALARM_SNOOZE_TIME,
180 VCAL_VER_10_MALARM_REPEAT_COUNT,
181 VCAL_VER_10_MALARM_ADDRESS_STRING,
182 VCAL_VER_10_MALARM_NOTE_STRING,
186 VCAL_VER_10_AALARM_NONE = 0,
187 VCAL_VER_10_AALARM_RUN_TIME,
188 VCAL_VER_10_AALARM_SNOOZE_TIME,
189 VCAL_VER_10_AALARM_REPEAT_COUNT,
190 VCAL_VER_10_AALARM_AUDIO_CONTENT,
193 static const char *vcal_component[VCAL_COMPONENT_MAX] = {0};
194 static void __init_component(void)
196 if (NULL == *vcal_component) {
197 vcal_component[VCAL_COMPONENT_VEVENT] = "VEVENT";
198 vcal_component[VCAL_COMPONENT_VTODO] = "VTODO";
199 vcal_component[VCAL_COMPONENT_VJOURNAL] = "VJOURNAL";
200 vcal_component[VCAL_COMPONENT_VFREEBUSY] = "VFREEBUSY";
201 vcal_component[VCAL_COMPONENT_VTIMEZONE] = "VTIMEZONE";
205 static const char *vcal_property[VCAL_PROPERTY_MAX] = {0};
206 static void __init_property(void)
208 if (NULL == *vcal_property) {
209 vcal_property[VCAL_PROPERTY_VERSION] = "VERSION";
210 vcal_property[VCAL_PROPERTY_TZ] = "TZ";
211 vcal_property[VCAL_PROPERTY_BEGIN] = "BEGIN";
212 vcal_property[VCAL_PROPERTY_END] = "END";
216 static const char *component_property[VCAL_COMPONENT_PROPERTY_MAX] = {0};
217 static void __init_component_property(void)
219 if (NULL == *component_property) {
220 component_property[VCAL_COMPONENT_PROPERTY_DTSTAMP] = "DTSTAMP";
221 component_property[VCAL_COMPONENT_PROPERTY_UID] = "UID";
222 component_property[VCAL_COMPONENT_PROPERTY_RECURRENCE_ID] = "RECURRENCE-ID";
223 component_property[VCAL_COMPONENT_PROPERTY_DTSTART] = "DTSTART";
224 component_property[VCAL_COMPONENT_PROPERTY_CREATED] = "CREATED"; /* for ver 2: created */
225 component_property[VCAL_COMPONENT_PROPERTY_DCREATED] = "DCREATED"; /* for ver 1: created */
226 component_property[VCAL_COMPONENT_PROPERTY_DESCRIPTION] = "DESCRIPTION";
227 component_property[VCAL_COMPONENT_PROPERTY_LAST_MODIFIED] = "LAST-MODIFIED";
228 component_property[VCAL_COMPONENT_PROPERTY_LOCATION] = "LOCATION";
229 component_property[VCAL_COMPONENT_PROPERTY_PRIORITY] = "PRIORITY";
230 component_property[VCAL_COMPONENT_PROPERTY_STATUS] = "STATUS";
231 component_property[VCAL_COMPONENT_PROPERTY_SUMMARY] = "SUMMARY";
232 component_property[VCAL_COMPONENT_PROPERTY_RRULE] = "RRULE";
233 component_property[VCAL_COMPONENT_PROPERTY_DTEND] = "DTEND";
234 component_property[VCAL_COMPONENT_PROPERTY_DUE] = "DUE";
235 component_property[VCAL_COMPONENT_PROPERTY_ATTENDEE] = "ATTENDEE";
236 component_property[VCAL_COMPONENT_PROPERTY_CATEGORIES] = "CATEGORIES";
237 component_property[VCAL_COMPONENT_PROPERTY_DALARM] = "DALARM";
238 component_property[VCAL_COMPONENT_PROPERTY_MALARM] = "MALARM";
239 component_property[VCAL_COMPONENT_PROPERTY_AALARM] = "AALARM";
240 component_property[VCAL_COMPONENT_PROPERTY_EXDATE] = "EXDATE";
241 component_property[VCAL_COMPONENT_PROPERTY_X_ALLDAY] = "X-ALLDAY";
242 component_property[VCAL_COMPONENT_PROPERTY_X_LUNAR] = "X-LUNAR";
243 component_property[VCAL_COMPONENT_PROPERTY_BEGIN] = "BEGIN"; /* start alarm component */
244 component_property[VCAL_COMPONENT_PROPERTY_END] = "END"; /* exit record component */
245 component_property[VCAL_COMPONENT_PROPERTY_EXTENDED] = "X-";
249 static const char *component_property_valarm[VCAL_COMPONENT_PROPERTY_VALARM_MAX] = {0};
250 static void __init_component_property_valarm(void)
252 if (NULL == *component_property_valarm) {
253 component_property_valarm[VCAL_COMPONENT_PROPERTY_VALARM_ACTION] = "ACTION";
254 component_property_valarm[VCAL_COMPONENT_PROPERTY_VALARM_TRIGGER] = "TRIGGER";
255 component_property_valarm[VCAL_COMPONENT_PROPERTY_VALARM_REPEAT] = "REPEAT";
256 component_property_valarm[VCAL_COMPONENT_PROPERTY_VALARM_ATTACH] = "ATTACH";
257 component_property_valarm[VCAL_COMPONENT_PROPERTY_VALARM_DESCRIPTION] = "DESCRIPTION";
258 component_property_valarm[VCAL_COMPONENT_PROPERTY_VALARM_SUMMARY] = "SUMMARY";
259 component_property_valarm[VCAL_COMPONENT_PROPERTY_VALARM_DURATION] = "DURATION";
260 component_property_valarm[VCAL_COMPONENT_PROPERTY_VALARM_END] = "END";
264 static const char *component_property_vtimezone[VCAL_COMPONENT_PROPERTY_VTIMEZONE_MAX] = {0};
265 static void __init_component_property_vtimezone(void)
267 if (NULL == *component_property_vtimezone) {
268 component_property_vtimezone[VCAL_COMPONENT_PROPERTY_VTIMEZONE_DTSTART] = "DTSTART";
269 component_property_vtimezone[VCAL_COMPONENT_PROPERTY_VTIMEZONE_TZOFFSETFROM] = "TZOFFSETFROM";
270 component_property_vtimezone[VCAL_COMPONENT_PROPERTY_VTIMEZONE_TZOFFSETTO] = "TZOFFSETTO";
271 component_property_vtimezone[VCAL_COMPONENT_PROPERTY_VTIMEZONE_TZNAME] = "TZNAME";
272 component_property_vtimezone[VCAL_COMPONENT_PROPERTY_VTIMEZONE_RDATE] = "RDATE";
273 component_property_vtimezone[VCAL_COMPONENT_PROPERTY_VTIMEZONE_END] = "END";
277 static inline void __print_cursor(char *cursor, int line)
281 for (i = 0; i < 5; i++) {
282 if (VCAL_CR == *(cursor + i) || VCAL_LF == *(cursor + i)) break;
283 DBG("[%c]", *(cursor + i));
287 static inline void __free_user_data(struct user_data *ud)
290 if (ud->timezone_tzid) free(ud->timezone_tzid);
291 if (ud->datetime_tzid) free(ud->datetime_tzid);
296 static inline char* __remove_empty_line(char *src)
299 if ('\n' != *src && '\r' != *src)
306 static inline char* __remove_invalid_space(char *src)
325 static inline char* __crlf(char *p)
327 RETV_IF(NULL == p, NULL);
328 while (VCAL_LF != *p) {
337 static bool __check_has_rrule(char *stream)
339 RETV_IF(NULL == stream, false);
342 char *cursor = stream;
344 if (*(cursor++) == VCAL_LF) {
345 if (*(cursor++) == 'R' &&
346 *(cursor++) == 'R' &&
347 *(cursor++) == 'U' &&
348 *(cursor++) == 'L' &&
349 *(cursor++) == 'E' &&
350 *(cursor++) == ':') {
352 } else if (*(cursor-1) == 'E' &&
353 *(cursor++) == 'N' &&
354 *(cursor++) == 'D' &&
355 *(cursor++) == ':' &&
356 *(cursor++) == 'V' &&
357 *(cursor++) == 'E' &&
358 *(cursor++) == 'V' &&
359 *(cursor++) == 'E' &&
360 *(cursor++) == 'N' &&
361 *(cursor++) == 'T') {
369 static int _sub_caltime(struct user_data *ud, calendar_time_s *s, calendar_time_s *a, int *diff)
371 RETV_IF(NULL == s, CALENDAR_ERROR_INVALID_PARAMETER);
372 RETV_IF(NULL == a, CALENDAR_ERROR_INVALID_PARAMETER);
373 RETV_IF(NULL == diff, CALENDAR_ERROR_INVALID_PARAMETER);
375 if (s->type != a->type) {
376 WARN("This is strange. start type(%d) alarm type(%d)", s->type, a->type);
378 if (ud->timezone_tzid)
379 tz = ud->timezone_tzid;
380 else if (ud->datetime_tzid)
381 tz = ud->datetime_tzid;
385 long long int lli = 0;
386 if (CALENDAR_TIME_LOCALTIME == s->type) {
387 lli = cal_time_convert_itol(tz, s->time.date.year, s->time.date.month,
388 s->time.date.mday, s->time.date.hour, s->time.date.minute,
389 s->time.date.second);
390 *diff = lli - a->time.utime;
391 DBG("Convert start localtime with tz[%s] and get(%lld)", tz, lli);
393 lli = cal_time_convert_itol(tz, a->time.date.year, a->time.date.month,
394 a->time.date.mday, a->time.date.hour, a->time.date.minute,
395 a->time.date.second);
396 *diff = s->time.utime - lli;
397 DBG("Convert alarm localtime with tz[%s] and get(%lld)", tz, lli);
399 return CALENDAR_ERROR_NONE;
402 case CALENDAR_TIME_UTIME:
403 *diff = s->time.utime - a->time.utime;
405 case CALENDAR_TIME_LOCALTIME:
406 *diff = cal_time_convert_itol(NULL, s->time.date.year, s->time.date.month,
407 s->time.date.mday, s->time.date.hour, s->time.date.minute, s->time.date.second) -
408 cal_time_convert_itol(NULL, a->time.date.year, a->time.date.month,
409 a->time.date.mday, a->time.date.hour, a->time.date.minute, a->time.date.second);
412 return CALENDAR_ERROR_NONE;
415 static void _get_tick_unit(int t, int *tick, int *unit)
420 if (0 == (t % CALENDAR_ALARM_TIME_UNIT_WEEK)) {
421 *tick = t / CALENDAR_ALARM_TIME_UNIT_WEEK;
422 *unit = CALENDAR_ALARM_TIME_UNIT_WEEK;
423 } else if (0 == (t % CALENDAR_ALARM_TIME_UNIT_DAY)) {
424 *tick = t / CALENDAR_ALARM_TIME_UNIT_DAY;
425 *unit = CALENDAR_ALARM_TIME_UNIT_DAY;
426 } else if (0 == (t % CALENDAR_ALARM_TIME_UNIT_HOUR)) {
427 *tick = t / CALENDAR_ALARM_TIME_UNIT_HOUR;
428 *unit = CALENDAR_ALARM_TIME_UNIT_HOUR;
429 } else if (0 == (t % CALENDAR_ALARM_TIME_UNIT_MINUTE)) {
430 *tick = t / CALENDAR_ALARM_TIME_UNIT_MINUTE;
431 *unit = CALENDAR_ALARM_TIME_UNIT_MINUTE;
434 *unit = CALENDAR_ALARM_TIME_UNIT_SPECIFIC;
436 DBG("tick(%d), unit(%d)", *tick, *unit);
439 static char* __get_value(char *cursor, char **value)
441 RETV_IF(NULL == cursor, NULL);
442 RETV_IF(NULL == value, NULL);
444 /* offset: length until ';' or ':' */
446 while (':' != *(cursor + offset) && ';' != *(cursor + offset))
450 while (VCAL_LF != *(cursor + offset + i)) {
451 if ('\0' == *(cursor + offset + i))
457 char *p = calloc(i + 1, sizeof(char));
458 RETVM_IF(NULL == p, NULL, "calloc() Fail");
460 if (VCAL_CR == *(cursor + offset + i -1))
461 memcpy(p, cursor + offset, i -1);
463 memcpy(p, cursor + offset, i);
466 DBG("offset(%d) len(%d) value[%s]", offset, i, *value);
468 return cursor + offset + i +1;
471 static char* __check_word(char *src, const char *word)
473 RETV_IF(NULL == src, NULL);
475 src = __remove_empty_line(src);
476 src = __remove_invalid_space(src);
478 while (*src == *word) {
482 if ('\0' == *src || '\0' == *word)
493 * Change '-' to '/' as icu format to be recognized in icu library.
494 * ig. US-Easten -> US/Eastern
496 static inline void __adjust_tzid(char *p)
500 DBG("Before [%s]", p);
503 if ('-' == *(p +i)) {
504 if ('1' <= *(p +i +1) && *(p +i +1) <= '9')
511 DBG("After [%s]", p);
514 static void __unfolding(char *p)
523 if (VCAL_LF == *(p +1) && ' ' == *(p +2)) /* ver1.0:out of spec, but allowed exceptional case */
525 else if (VCAL_CR == *(p +1) && VCAL_LF == *(p +2) && ' ' == *(p +3)) /* ver1.0:in spec case */
527 else if (VCAL_CR == *(p +1) && VCAL_LF == *(p +2)) /* galaxy wants this format */
533 if (' ' == *(p + 1)) /* ver2.0:out of spec, but allowed exceptional case */
535 else if ('\t' == *(p + 1)) /* ver2.0:out of spec, but allowed exceptional case */
541 if ('\n' == *(p + 1) && ' ' == *(p + 2)) /* ver2.0:in spec case */
543 else if ('\n' == *(p + 1) && '\t' == *(p + 2)) /* ver2.0:out of spec, but allowed exceptional case */
555 static void __decode_escaped_char(char *p)
562 if ('\\' == *p && *(p +1)) {
591 static void __decode_base64(char *p)
596 DBG("Before [%s]", p);
599 buf = g_base64_decode(p, &size);
604 if (strlen(p) < size) {
605 /* LCOV_EXCL_START */
611 snprintf(p, size + 1, "%s%c", buf, '\0');
613 DBG("After [%s]", p);
616 static char __decode_hexa(char *p)
619 char decoded[2] = {0x00, 0x00};
621 for (i = 0; i < 2; i++) {
624 decoded[i] = p[i] - '0';
627 decoded[i] = p[i] - 'a' + 10;
630 decoded[i] = p[i] - 'A' + 10;
634 return (char)((decoded[0] << 4) + decoded[1]);
637 static void __decode_quoted_printable(char *p)
645 DBG("Before[%s]", p);
648 if (p[i+1] == 0x09 || p[i+1] == 0x20) {
650 } else if (p[i+1] == '\r' || p[i+1] == '\n') {
653 if (p[i+1] == '0' && tolower(p[i+2]) == 'd' &&
654 p[i+3] == '=' && p[i+4] == '0' && tolower(p[i+5]) == 'a') {
659 ch = __decode_hexa(p +i +1);
675 static char* __decode_iso8859_1_to_utf8(char *p)
677 RETV_IF(NULL == p, NULL);
682 DBG("Before [%s]", p);
687 out_p = realloc(p, len);
689 /* LCOV_EXCL_START */
690 ERR("realloc() Fail");
695 /* check enough space */
696 for (src = dst = out_p; *src; src++, dst++) {
703 *dst-- = 0x80 | (*src & 0x3f);
704 *dst-- = 0xc0 | (*((unsigned char *)src--) >> 6);
709 DBG("After [%s]", out_p);
713 static char* __decode_charset(char *p)
716 t = g_strsplit(p, ":", 2);
717 RETVM_IF(NULL == t, NULL, "g_strsplit() Fail");
719 if ('\0' == *t[0]) { /* no param */
721 return cal_strdup(p + 1);
725 s = g_strsplit(t[0], ";", -1);
727 /* LCOV_EXCL_START */
728 ERR("g_strsplit() Fail");
733 int count_param = g_strv_length(s);
734 DBG("count_param(%d)", count_param);
736 int charset = VCAL_CHARSET_NONE;
737 int encoding = VCAL_ENCODING_NONE;
740 for (i = 0; i < count_param; i++) {
741 if (NULL == s[i] || '\0' == *s[i])
744 if (CAL_STRING_EQUAL == strncmp(s[i], "CHARSET=", strlen("CHARSET="))) {
745 int key_len = strlen("CHARSET=");
746 if (CAL_STRING_EQUAL == strcmp(s[i] + key_len, "UTF-8"))
747 charset = VCAL_CHARSET_UTF_8;
748 else if (CAL_STRING_EQUAL == strcmp(s[i] + key_len, "ISO-8859-1"))
749 charset = VCAL_CHARSET_ISO_8859_1;
751 WARN("Not support charset[%s]", s[i] + key_len);
752 } else if (CAL_STRING_EQUAL == strncmp(s[i], "ENCODING=", strlen("ENCODING="))) {
753 int key_len = strlen("ENCODING=");
754 if (CAL_STRING_EQUAL == strcmp(s[i] + key_len, "BASE64"))
755 encoding = VCAL_ENCODING_BASE64;
756 else if (CAL_STRING_EQUAL == strcmp(s[i] + key_len, "QUOTED-PRINTABLE"))
757 encoding = VCAL_ENCODING_QUOTED_PRINTABLE;
759 WARN("Not support encoding[%s]", s[i] + key_len);
767 char *ret_str = strdup(t[1]);
771 case VCAL_ENCODING_BASE64:
772 __decode_base64(ret_str);
774 case VCAL_ENCODING_QUOTED_PRINTABLE:
775 __decode_quoted_printable(ret_str);
780 case VCAL_CHARSET_UTF_8:
782 case VCAL_CHARSET_ISO_8859_1:
783 ret_str = __decode_iso8859_1_to_utf8(ret_str);
790 static char* __decode_datetime(char *p, struct user_data *ud)
793 t = g_strsplit(p, ":", -1);
794 RETVM_IF(NULL == t, NULL, "g_strsplit() Fail");
796 if ('\0' == *t[0]) { /* no param */
800 int count = g_strv_length(t);
801 int len_param = strlen(t[count -1]);
802 *(p + strlen(p) - len_param -1) = '\0';
807 s = g_strsplit(p, ";", -1);
809 /* LCOV_EXCL_START */
810 ERR("g_strsplit() Fail");
815 int count_param = g_strv_length(s);
816 DBG("count_param(%d)", count_param);
818 for (i = 0; i < count_param; i++) {
819 if (NULL == s[i] || '\0' == *s[i])
822 if (CAL_STRING_EQUAL != strncmp(s[i], "TZID=", strlen("TZID=")))
825 if (ud->datetime_tzid)
829 tzid = strdup(s[i] + strlen("TZID="));
831 /* LCOV_EXCL_START */
832 ERR("strdup() Fail");
837 DBG("modified tzid[%s]", tzid);
839 if (true == cal_time_is_available_tzid(tzid)) {
841 ud->datetime_tzid = tzid;
846 if (ud->timezone_tzid && *ud->timezone_tzid) {
847 ud->datetime_tzid = strdup(ud->timezone_tzid);
848 if (NULL == ud->datetime_tzid) {
849 /* LCOV_EXCL_START */
850 ERR("strdup() Fail");
854 DBG("set datetime_tzid[%s] as timezone_tzid", ud->datetime_tzid);
856 /* LCOV_EXCL_START */
865 DBG("(%d) (%d) [%s]", strlen(p), len_param, p + strlen(p) +1);
866 return p + strlen(p) +1;
869 static void __decode_duration(char *cursor, int len, int *tick, int *unit)
871 RET_IF(NULL == cursor);
872 RET_IF('\0' == *cursor);
873 RET_IF(NULL == tick);
874 RET_IF(NULL == unit);
881 for (i = 0; i < len; i++) {
882 switch (*(cursor + i)) {
905 u = CALENDAR_ALARM_TIME_UNIT_WEEK;
906 snprintf(buf, digit + 1, "%s", cursor + i - digit);
908 DBG("[%s] (%d)", buf, t);
912 u = CALENDAR_ALARM_TIME_UNIT_DAY;
913 snprintf(buf, digit + 1, "%s", cursor + i - digit);
915 DBG("[%s] (%d)", buf, t);
919 u = CALENDAR_ALARM_TIME_UNIT_HOUR;
920 snprintf(buf, digit + 1, "%s", cursor + i - digit);
922 DBG("[%s] (%d)", buf, t);
926 u = CALENDAR_ALARM_TIME_UNIT_MINUTE;
927 snprintf(buf, digit + 1, "%s", cursor + i - digit);
929 DBG("[%s] (%d)", buf, t);
933 u = CALENDAR_ALARM_TIME_UNIT_SPECIFIC;
934 snprintf(buf, digit + 1, "%s", cursor + i - digit);
936 DBG("[%s] (%d)", buf, t);
940 /* LCOV_EXCL_START */
941 ERR("Invalid value");
948 _get_tick_unit(t, tick, unit);
951 static bool __is_digit(char *p)
954 if ((*p < '0' || '9' < *p) && '+' != *p && '-' != *p)
961 static char* __get_index(char *cursor, const char **array, int len, int *index)
963 RETV_IF(NULL == index, NULL);
967 for (i = 1; i < len; i++) {
968 new = __check_word(cursor, array[i]);
977 DBG("index(%d) [%s]", i, array[i]);
978 return cursor + strlen(array[i]);
981 static void __get_version(char *value, int *version)
985 RET_IF(NULL == value);
986 RET_IF(NULL == version);
988 if (CAL_STRING_EQUAL == strncmp(value, ":1.0", strlen(":1.0")))
993 DBG("version(%d)", *version);
996 static int _get_caltime(char *p, calendar_time_s *caltime, struct user_data *ud)
998 RETV_IF(NULL == p, CALENDAR_ERROR_INVALID_PARAMETER);
999 RETV_IF('\0' == *p, CALENDAR_ERROR_INVALID_PARAMETER);
1000 RETV_IF(NULL == caltime, CALENDAR_ERROR_INVALID_PARAMETER);
1001 RETV_IF(NULL == ud, CALENDAR_ERROR_INVALID_PARAMETER);
1003 int ret = CALENDAR_ERROR_NONE;
1005 switch (strlen(p)) {
1006 case VCAL_DATETIME_LENGTH_YYYYMMDD:
1007 caltime->type = CALENDAR_TIME_LOCALTIME;
1008 sscanf(p, CAL_DATETIME_FORMAT_YYYYMMDD,
1009 &(caltime->time.date.year), &(caltime->time.date.month), &(caltime->time.date.mday));
1010 caltime->time.date.hour = 0;
1011 caltime->time.date.minute = 0;
1012 caltime->time.date.second = 0;
1013 DBG(CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSS,
1014 caltime->time.date.year, caltime->time.date.month, caltime->time.date.mday,
1015 caltime->time.date.hour, caltime->time.date.minute, caltime->time.date.second);
1017 case VCAL_DATETIME_LENGTH_YYYYMMDDTHHMMSS:
1018 sscanf(p, CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSS,
1019 &(caltime->time.date.year), &(caltime->time.date.month), &(caltime->time.date.mday),
1020 &(caltime->time.date.hour), &(caltime->time.date.minute), &(caltime->time.date.second));
1022 if (VCAL_VER_1 == ud->version) {
1023 caltime->type = CALENDAR_TIME_LOCALTIME;
1025 if (NULL == ud->datetime_tzid || '\0' == *ud->datetime_tzid) {
1026 if (NULL == ud->timezone_tzid || '\0' == *ud->timezone_tzid) {
1027 /* Without tzid is localtime */
1028 caltime->type = CALENDAR_TIME_LOCALTIME;
1029 DBG(CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSS,
1030 caltime->time.date.year, caltime->time.date.month, caltime->time.date.mday,
1031 caltime->time.date.hour, caltime->time.date.minute, caltime->time.date.second);
1033 /* No 'Z' with tzid means utime */
1034 caltime->type = CALENDAR_TIME_UTIME;
1035 caltime->time.utime = cal_time_convert_itol(ud->timezone_tzid,
1036 caltime->time.date.year, caltime->time.date.month, caltime->time.date.mday,
1037 caltime->time.date.hour, caltime->time.date.minute, caltime->time.date.second);
1038 DBG("timezone_tzid[%s] (%lld)", ud->timezone_tzid, caltime->time.utime);
1041 /* No 'Z' with tzid means utime */
1042 caltime->type = CALENDAR_TIME_UTIME;
1043 caltime->time.utime = cal_time_convert_itol(ud->datetime_tzid,
1044 caltime->time.date.year, caltime->time.date.month, caltime->time.date.mday,
1045 caltime->time.date.hour, caltime->time.date.minute, caltime->time.date.second);
1046 DBG("datetime_tzid[%s] (%lld)", ud->datetime_tzid, caltime->time.utime);
1050 case VCAL_DATETIME_LENGTH_YYYYMMDDTHHMMSSZ:
1051 if (ud->is_allday) {
1052 caltime->type = CALENDAR_TIME_LOCALTIME;
1053 sscanf(p, CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSSZ,
1054 &(caltime->time.date.year), &(caltime->time.date.month), &(caltime->time.date.mday),
1055 &(caltime->time.date.hour), &(caltime->time.date.minute), &(caltime->time.date.second));
1056 caltime->time.date.hour = 0;
1057 caltime->time.date.minute = 0;
1058 caltime->time.date.second = 0;
1059 DBG(CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSS,
1060 caltime->time.date.year, caltime->time.date.month, caltime->time.date.mday,
1061 caltime->time.date.hour, caltime->time.date.minute, caltime->time.date.second);
1063 caltime->type = CALENDAR_TIME_UTIME;
1064 caltime->time.utime = cal_time_convert_lli(p);
1065 DBG("(%lld)", caltime->time.utime);
1069 /* LCOV_EXCL_START */
1070 ERR("Invalid time format[%s]", p);
1071 ret = CALENDAR_ERROR_INVALID_PARAMETER;
1073 /* LCOV_EXCL_STOP */
1085 static void __parse_tz(const char *tz, int *h, int *m)
1089 char **t = g_strsplit(tz, ":", -1);
1090 RETM_IF(NULL == t, "g_strsplit() is NULL");
1095 else if ('+' == *t[0])
1100 if (0 == strlen(t[0])) {
1101 /* LCOV_EXCL_START */
1105 /* LCOV_EXCL_STOP */
1110 snprintf(buf, strlen(t[0]), "%s", t[0] + 1);
1113 snprintf(buf, strlen(t[0]) + 1, "%s", t[0]);
1115 if (h) *h = sign * atoi(buf);
1117 if (1 == g_strv_length(t)) {
1123 snprintf(buf, strlen(t[1]) + 1, "%s", t[1]);
1124 if (m) *m = atoi(buf);
1129 static void __get_tz(char *value, char **tz)
1131 RET_IF(NULL == value);
1135 __parse_tz(value +1, &h, &m); /* +1 to skip ':' */
1137 char buf[CAL_STR_SHORT_LEN32] = {0};
1139 snprintf(buf, sizeof(buf), "Etc/GMT%c%d", h < 0 ? '+' : '-', h);
1141 cal_time_get_registered_tzid_with_offset(h * 3600 + m * 60, buf, sizeof(buf));
1143 DBG("set tzid [%s]", buf);
1148 static void __work_component_property_dtstamp(char *value, calendar_record_h record, struct user_data *ud)
1153 static void __work_component_property_uid(char *value, calendar_record_h record, struct user_data *ud)
1155 RET_IF(NULL == value);
1156 RET_IF('\0' == *value);
1157 RET_IF(NULL == record);
1161 char *s = __decode_charset(value);
1162 __decode_escaped_char(s);
1164 case CALENDAR_BOOK_TYPE_EVENT:
1165 ret = cal_record_set_str(record, _calendar_event.uid, s);
1166 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
1168 case CALENDAR_BOOK_TYPE_TODO:
1169 ret = cal_record_set_str(record, _calendar_todo.uid, s);
1170 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
1176 static void __work_component_property_recurrence_id(char *value, calendar_record_h record, struct user_data *ud)
1178 RET_IF(NULL == value);
1179 RET_IF('\0' == *value);
1180 RET_IF(NULL == record);
1185 case CALENDAR_BOOK_TYPE_EVENT:
1186 ret = cal_record_set_str(record, _calendar_event.recurrence_id, value +1);
1187 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
1189 case CALENDAR_BOOK_TYPE_TODO:
1190 DBG("Not supported in todo");
1195 static void __work_component_property_dtstart(char *value, calendar_record_h record, struct user_data *ud)
1197 RET_IF(NULL == value);
1198 RET_IF('\0' == *value);
1199 RET_IF(NULL == record);
1204 value = __decode_datetime(value, ud);
1205 calendar_time_s dtstart = {0};
1206 ret = _get_caltime(value, &dtstart, ud);
1207 if (CALENDAR_ERROR_NONE != ret) {
1208 /* LCOV_EXCL_START */
1209 ERR("_get_caltime() Fail(%d)", ret);
1211 /* LCOV_EXCL_STOP */
1215 tzid = ud->datetime_tzid ? ud->datetime_tzid : (ud->timezone_tzid ? ud->timezone_tzid : NULL);
1218 case CALENDAR_BOOK_TYPE_EVENT:
1219 if (tzid && *tzid) {
1220 ret = cal_record_set_str(record, _calendar_event.start_tzid, tzid);
1221 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
1223 ret = cal_record_set_caltime(record, _calendar_event.start_time, dtstart);
1224 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_caltime() Fail(%d)", ret);
1226 case CALENDAR_BOOK_TYPE_TODO:
1227 if (tzid && *tzid) {
1228 ret = cal_record_set_str(record, _calendar_todo.start_tzid, tzid);
1229 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
1231 ret = cal_record_set_caltime(record, _calendar_todo.start_time, dtstart);
1232 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_caltime() Fail(%d)", ret);
1236 /* check if dtend is earlier than dtstart. */
1237 if (CALENDAR_BOOK_TYPE_TODO == ud->type) /* skip in todo */
1240 calendar_time_s dtend = {0};
1241 ret = calendar_record_get_caltime(record, _calendar_event.end_time, &dtend);
1242 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_caltime() Fail(%d)", ret);
1244 if (0 == dtend.time.utime) /* not set yet */
1248 _sub_caltime(ud, &dtstart, &dtend, &diff);
1249 if (diff <= 0) /* proper data */
1252 WARN("dtend < dtstart so set end time to start");
1256 static void __work_component_property_created(char *value, calendar_record_h record, struct user_data *ud)
1258 RET_IF(NULL == value);
1259 RET_IF('\0' == *value);
1260 RET_IF(NULL == record);
1265 case CALENDAR_BOOK_TYPE_EVENT:
1266 ret = cal_record_set_lli(record, _calendar_event.created_time, cal_time_convert_lli(value));
1267 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_lli() Fail(%d)", ret);
1270 case CALENDAR_BOOK_TYPE_TODO:
1271 ret = cal_record_set_lli(record, _calendar_todo.created_time, cal_time_convert_lli(value));
1272 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_lli() Fail(%d)", ret);
1277 static void __work_component_property_description(char *value, calendar_record_h record, struct user_data *ud)
1279 RET_IF(NULL == value);
1280 RET_IF('\0' == *value);
1281 RET_IF(NULL == record);
1285 char *s = __decode_charset(value);
1286 __decode_escaped_char(s);
1288 case CALENDAR_BOOK_TYPE_EVENT:
1289 ret = cal_record_set_str(record, _calendar_event.description, s);
1290 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
1292 case CALENDAR_BOOK_TYPE_TODO:
1293 ret = cal_record_set_str(record, _calendar_todo.description, s);
1294 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
1300 static void __work_component_property_last_modified(char *value, calendar_record_h record, struct user_data *ud)
1302 RET_IF(NULL == value);
1303 RET_IF('\0' == *value);
1304 RET_IF(NULL == record);
1309 case CALENDAR_BOOK_TYPE_EVENT:
1310 ret = cal_record_set_lli(record, _calendar_event.last_modified_time, cal_time_convert_lli(value));
1311 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_lli() Fail(%d)", ret);
1313 case CALENDAR_BOOK_TYPE_TODO:
1314 ret = cal_record_set_lli(record, _calendar_todo.last_modified_time, cal_time_convert_lli(value));
1315 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_lli() Fail(%d)", ret);
1320 static void __work_component_property_location(char *value, calendar_record_h record, struct user_data *ud)
1322 RET_IF(NULL == value);
1323 RET_IF('\0' == *value);
1324 RET_IF(NULL == record);
1328 char *s = __decode_charset(value);
1329 __decode_escaped_char(s);
1331 case CALENDAR_BOOK_TYPE_EVENT:
1332 ret = cal_record_set_str(record, _calendar_event.location, s);
1333 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
1335 case CALENDAR_BOOK_TYPE_TODO:
1336 ret = cal_record_set_str(record, _calendar_todo.location, s);
1337 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
1343 static int __decode_priority(char *value, struct user_data *ud)
1345 int original_priority = atoi(value);
1346 int modified_priority = 0;
1348 switch (ud->version) {
1350 switch (original_priority) {
1352 modified_priority = CALENDAR_TODO_PRIORITY_LOW;
1355 modified_priority = CALENDAR_TODO_PRIORITY_NORMAL;
1358 modified_priority = CALENDAR_TODO_PRIORITY_HIGH;
1361 DBG("Unable to parse [%s]", value);
1362 modified_priority = CALENDAR_TODO_PRIORITY_NONE;
1369 switch (original_priority) {
1371 modified_priority = CALENDAR_TODO_PRIORITY_HIGH;
1374 modified_priority = CALENDAR_TODO_PRIORITY_NORMAL;
1377 modified_priority = CALENDAR_TODO_PRIORITY_LOW;
1380 DBG("Unable to parse [%s]", value);
1381 modified_priority = CALENDAR_TODO_PRIORITY_NONE;
1386 DBG("convert priority(%d) -> (%d)", original_priority, modified_priority);
1387 return modified_priority;
1390 static void __work_component_property_priority(char *value, calendar_record_h record, struct user_data *ud)
1392 RET_IF(NULL == value);
1393 RET_IF('\0' == *value);
1394 RET_IF(NULL == record);
1396 RETM_IF(*value < '0' || '9' < *value, "out of range[%s]", value);
1399 int modified_priority = __decode_priority(value, ud);
1401 case CALENDAR_BOOK_TYPE_EVENT:
1402 ret = cal_record_set_int(record, _calendar_event.priority, modified_priority);
1403 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
1405 case CALENDAR_BOOK_TYPE_TODO:
1406 ret = cal_record_set_int(record, _calendar_todo.priority, modified_priority);
1407 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
1412 static void __work_component_property_status(char *value, calendar_record_h record, struct user_data *ud)
1414 RET_IF(NULL == value);
1415 RET_IF('\0' == *value);
1416 RET_IF(NULL == record);
1422 case CALENDAR_BOOK_TYPE_EVENT:
1423 if (CAL_STRING_EQUAL == strncmp(value, ":TENTATIVE", strlen(":TENTATIVE")))
1424 status = CALENDAR_EVENT_STATUS_TENTATIVE;
1425 else if (CAL_STRING_EQUAL == strncmp(value, ":CONFIRMED", strlen(":CONFIRMED")))
1426 status = CALENDAR_EVENT_STATUS_CONFIRMED;
1427 else if (CAL_STRING_EQUAL == strncmp(value, ":CANCELLED", strlen(":CANCELLED")))
1428 status = CALENDAR_EVENT_STATUS_CANCELLED;
1430 status = CALENDAR_EVENT_STATUS_NONE;
1432 ret = cal_record_set_int(record, _calendar_event.event_status, status);
1433 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
1435 case CALENDAR_BOOK_TYPE_TODO:
1436 if (CAL_STRING_EQUAL == strncmp(value, ":NEEDS-ACTION", strlen(":NEEDS-ACTION")))
1437 status = CALENDAR_TODO_STATUS_NEEDS_ACTION;
1438 else if (CAL_STRING_EQUAL == strncmp(value, ":NEEDS ACTION", strlen(":NEEDS ACTION")))
1439 status = CALENDAR_TODO_STATUS_NEEDS_ACTION;
1440 else if (CAL_STRING_EQUAL == strncmp(value, ":COMPLETED", strlen(":COMPLETED")))
1441 status = CALENDAR_TODO_STATUS_COMPLETED;
1442 else if (CAL_STRING_EQUAL == strncmp(value, ":IN-PROCESS", strlen(":IN-PROCESS")))
1443 status = CALENDAR_TODO_STATUS_IN_PROCESS;
1444 else if (CAL_STRING_EQUAL == strncmp(value, ":CANCELLED", strlen(":CANCELLED")))
1445 status = CALENDAR_TODO_STATUS_CANCELED;
1447 status = CALENDAR_TODO_STATUS_NONE;
1449 ret = cal_record_set_int(record, _calendar_todo.todo_status, status);
1450 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
1455 static void __work_component_property_summary(char *value, calendar_record_h record, struct user_data *ud)
1457 RET_IF(NULL == value);
1458 RET_IF('\0' == *value);
1459 RET_IF(NULL == record);
1463 char *s = __decode_charset(value);
1464 __decode_escaped_char(s);
1466 case CALENDAR_BOOK_TYPE_EVENT:
1467 ret = cal_record_set_str(record, _calendar_event.summary, s);
1468 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
1470 case CALENDAR_BOOK_TYPE_TODO:
1471 ret = cal_record_set_str(record, _calendar_todo.summary, s);
1472 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
1478 static bool __is_wday_string(char *p)
1480 RETV_IF(NULL == p, false);
1481 RETV_IF('0' == *p, false);
1483 if ('S' == *p && 'U' == *(p +1))
1485 else if ('M' == *p && 'O' == *(p +1))
1487 else if ('T' == *p && 'U' == *(p +1))
1489 else if ('W' == *p && 'E' == *(p +1))
1491 else if ('T' == *p && 'H' == *(p +1))
1493 else if ('F' == *p && 'R' == *(p +1))
1495 else if ('S' == *p && 'A' == *(p +1))
1502 static int __get_frequency(char *p)
1504 if ('Y' == *p && 'M' == *(p +1))
1505 return VCAL_RECURRENCE_YEARLY_BYMONTH;
1506 else if ('Y' == *p && 'D' == *(p +1))
1507 return VCAL_RECURRENCE_YEARLY_BYYEARDAY;
1508 else if ('M' == *p && 'P' == *(p +1))
1509 return VCAL_RECURRENCE_MONTHLY_BYDAY;
1510 else if ('M' == *p && 'D' == *(p +1))
1511 return VCAL_RECURRENCE_MONTHLY_BYMONTHDAY;
1512 else if ('W' == *p && 'E' != *(p +1)) /* check 'E' for WE(Wednesday) */
1513 return VCAL_RECURRENCE_WEEKLY;
1515 return VCAL_RECURRENCE_DAILY;
1517 return VCAL_RECURRENCE_NONE;
1520 static void __set_bystr(int freq_mode, calendar_record_h record, char *bystr)
1522 RET_IF(NULL == record);
1523 RET_IF(NULL == bystr);
1524 RET_IF('\0' == *bystr);
1526 DBG("bystr[%s]", bystr);
1527 bystr[strlen(bystr) -1] = '\0'; /* to remove ',' */
1529 switch (freq_mode) {
1530 case VCAL_RECURRENCE_YEARLY_BYMONTH:
1531 ret = cal_record_set_str(record, _calendar_event.bymonth, bystr);
1532 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
1534 case VCAL_RECURRENCE_YEARLY_BYYEARDAY:
1535 ret = cal_record_set_str(record, _calendar_event.byyearday, bystr);
1536 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
1538 case VCAL_RECURRENCE_MONTHLY_BYMONTHDAY:
1539 ret = cal_record_set_str(record, _calendar_event.bymonthday, bystr);
1540 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
1542 case VCAL_RECURRENCE_MONTHLY_BYDAY:
1543 ret = cal_record_set_str(record, _calendar_event.byday, bystr);
1544 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
1546 case VCAL_RECURRENCE_WEEKLY:
1547 ret = cal_record_set_str(record, _calendar_event.byday, bystr);
1548 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
1550 case VCAL_RECURRENCE_DAILY:
1556 * Yearly |bymonth |YM1 6 7 #10
1557 * |YM1 1 6 12 #5 MP1 1+ MO 1- FR
1558 * Yearly |byyearday |YD3 1 100 200 #10
1559 * Monthly|byposition|MP2 1+ SU 1- SU #10
1560 * Monthly|byday |MD1 1 1- #10
1561 * Weekly | |W2 MO WE FR 19941224T000000Z
1564 static void __work_component_property_rrule_ver_1(char *value, calendar_record_h record, struct user_data *ud)
1568 RET_IF(NULL == value);
1569 RET_IF('\0' == *value);
1570 RET_IF(NULL == record);
1575 t = g_strsplit_set(value, ": ", -1);
1576 RETM_IF(NULL == t, "g_strsplit_set() Fail");
1579 int len = g_strv_length(t);
1583 bool has_by = false;
1585 char bystr[CAL_STR_MIDDLE_LEN] = {0};
1592 for (i = 0; i < len; i++) {
1593 if (NULL == t[i] || '\0' == *t[i])
1598 if (true == __is_wday_string(t[i])) {
1602 for (j = 0; j < week_index; j++)
1603 len_str += snprintf(bystr + len_str, sizeof(bystr) - len_str, "%d%s,", week[j], t[i]);
1606 len_str += snprintf(bystr + len_str, sizeof(bystr) - len_str, "%s,", t[i]);
1608 DBG("[%s] week_index(%d)", bystr, week_index);
1609 } else if ('L' == *t[i] && 'D' == *(t[i] +1)) { /* last day */
1611 len_str += snprintf(bystr + len_str, sizeof(bystr) - len_str, "%s,", "-1");
1613 } else if ('W' == *t[i] && 'K' == *(t[i] +1) && 'S' == *(t[i] +2) && 'T' == *(t[i] +3)) { /* +4 is '=' */
1614 if ('S' == *(t[i] +5) && 'U' == *(t[i] +6))
1615 ret = cal_record_set_int(record, _calendar_event.wkst, CALENDAR_SUNDAY);
1616 else if ('M' == *(t[i] +5))
1617 ret = cal_record_set_int(record, _calendar_event.wkst, CALENDAR_MONDAY);
1618 else if ('T' == *(t[i] +5) && 'U' == *(t[i] +6))
1619 ret = cal_record_set_int(record, _calendar_event.wkst, CALENDAR_TUESDAY);
1620 else if ('W' == *(t[i] +5))
1621 ret = cal_record_set_int(record, _calendar_event.wkst, CALENDAR_WEDNESDAY);
1622 else if ('T' == *(t[i] +5) && 'H' == *(t[i] +6))
1623 ret = cal_record_set_int(record, _calendar_event.wkst, CALENDAR_THURSDAY);
1624 else if ('F' == *(t[i] +5))
1625 ret = cal_record_set_int(record, _calendar_event.wkst, CALENDAR_FRIDAY);
1626 else if ('S' == *(t[i] +5) && 'A' == *(t[i] +6))
1627 ret = cal_record_set_int(record, _calendar_event.wkst, CALENDAR_SATURDAY);
1629 ERR("Invalid parameter[%s]", t[i]);
1631 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
1632 } else if (true == __is_digit(t[i])) {
1635 bool exit_loop = false;
1638 switch (freq_mode) {
1639 case VCAL_RECURRENCE_MONTHLY_BYDAY:
1640 case VCAL_RECURRENCE_WEEKLY:
1644 while (t[i] + j && *(t[i] +j)) {
1645 switch (*(t[i] +j)) {
1657 if (true == exit_loop) break;
1660 snprintf(buf, j +1, "%s", t[i]);
1661 week[week_index] = atoi(buf) * sign;
1666 while (t[i] + j && *(t[i] +j)) {
1667 switch (*(t[i] +j)) {
1679 if (true == exit_loop) break;
1682 snprintf(buf, j +1, "%s", t[i]);
1683 len_str += snprintf(bystr + len_str, sizeof(bystr) - len_str, "%d,", (atoi(buf) * sign));
1687 if (true == has_by) {
1688 __set_bystr(freq_mode, record, bystr);
1690 memset(bystr, 0x0, strlen(bystr));
1694 if (VCAL_RECURRENCE_NONE != (freq_mode = __get_frequency(t[i]))) {
1695 if (0 == frequency) {
1697 switch (freq_mode) {
1698 case VCAL_RECURRENCE_YEARLY_BYMONTH:
1699 frequency = CALENDAR_RECURRENCE_YEARLY;
1700 interval = ('\0' == *(t[i] +2)) ? 1 : atoi(t[i] +2);
1702 case VCAL_RECURRENCE_YEARLY_BYYEARDAY:
1703 frequency = CALENDAR_RECURRENCE_YEARLY;
1704 interval = ('\0' == *(t[i] +2)) ? 1 : atoi(t[i] +2);
1706 case VCAL_RECURRENCE_MONTHLY_BYDAY:
1707 frequency = CALENDAR_RECURRENCE_MONTHLY;
1708 interval = ('\0' == *(t[i] +2)) ? 1 : atoi(t[i] +2);
1710 case VCAL_RECURRENCE_MONTHLY_BYMONTHDAY:
1711 frequency = CALENDAR_RECURRENCE_MONTHLY;
1712 interval = ('\0' == *(t[i] +2)) ? 1 : atoi(t[i] +2);
1714 case VCAL_RECURRENCE_WEEKLY:
1715 frequency = CALENDAR_RECURRENCE_WEEKLY;
1716 interval = ('\0' == *(t[i] +1)) ? 1 : atoi(t[i] +1);
1718 case VCAL_RECURRENCE_DAILY:
1719 frequency = CALENDAR_RECURRENCE_DAILY;
1720 interval = ('\0' == *(t[i] +1)) ? 1 : atoi(t[i] +1);
1723 ret = cal_record_set_int(record, _calendar_event.freq, frequency);
1724 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
1725 ret = cal_record_set_int(record, _calendar_event.interval, interval);
1726 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
1727 DBG("frequency[%d] interval(%d)", frequency, interval);
1730 if ('0' <= *t[i] && *t[i] <= '9' && strlen("YYYYMMDDTHHMMSS") <= strlen(t[i])) {
1732 calendar_time_s caltime = {0};
1733 _get_caltime(t[i], &caltime, ud);
1734 ret = cal_record_set_int(record, _calendar_event.range_type, CALENDAR_RANGE_UNTIL);
1735 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
1736 ret = cal_record_set_caltime(record, _calendar_event.until_time, caltime);
1737 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_caltime() Fail(%d)", ret);
1739 } else if ('#' == *t[i]) {
1741 if (true == __is_digit(t[i] +1)) {
1742 if (0 == atoi(t[i] +1)) {
1744 ret = cal_record_set_int(record, _calendar_event.range_type, CALENDAR_RANGE_NONE);
1745 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
1747 DBG("count (%d)", atoi(t[i] +1));
1748 ret = cal_record_set_int(record, _calendar_event.range_type, CALENDAR_RANGE_COUNT);
1749 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
1750 ret = cal_record_set_int(record, _calendar_event.count, atoi(t[i] +1));
1751 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
1754 ERR("Unable to parse count[%s]", t[i]);
1763 __set_bystr(freq_mode, record, bystr);
1768 static void __work_component_property_rrule_ver_2(char *value, calendar_record_h record, struct user_data *ud)
1773 RET_IF(NULL == value);
1774 RET_IF('\0' == *value);
1775 RET_IF(NULL == record);
1778 t = g_strsplit_set(value, ";:", -1);
1779 RETM_IF(NULL == t, "g_strsplit_set() Fail");
1781 ret = cal_record_set_int(record, _calendar_event.range_type, CALENDAR_RANGE_NONE);
1782 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
1784 int len = g_strv_length(t);
1786 for (i = 0; i < len; i++) {
1787 if (NULL == t[i] || '\0' == *t[i]) continue;
1789 if (CAL_STRING_EQUAL == strncmp(t[i], "FREQ=", strlen("FREQ="))) {
1791 if (CAL_STRING_EQUAL == strncmp(t[i] + strlen("FREQ"), "=YEARLY", strlen("=YEARLY")))
1792 frequency = CALENDAR_RECURRENCE_YEARLY;
1793 else if (CAL_STRING_EQUAL == strncmp(t[i] + strlen("FREQ"), "=MONTHLY", strlen("=MONTHLY")))
1794 frequency = CALENDAR_RECURRENCE_MONTHLY;
1795 else if (CAL_STRING_EQUAL == strncmp(t[i] + strlen("FREQ"), "=WEEKLY", strlen("=WEEKLY")))
1796 frequency = CALENDAR_RECURRENCE_WEEKLY;
1797 else if (CAL_STRING_EQUAL == strncmp(t[i] + strlen("FREQ"), "=DAILY", strlen("=DAILY")))
1798 frequency = CALENDAR_RECURRENCE_DAILY;
1800 frequency = CALENDAR_RECURRENCE_NONE;
1802 DBG("frequency(%d) [%s]", frequency, t[i] + strlen("FREQ") + 1);
1803 ret = cal_record_set_int(record, _calendar_event.freq, frequency);
1804 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
1806 } else if (CAL_STRING_EQUAL == strncmp(t[i], "UNTIL=", strlen("UNTIL="))) {
1807 calendar_time_s caltime = {0};
1808 _get_caltime(t[i] + strlen("UNTIL="), &caltime, ud);
1809 ret = cal_record_set_caltime(record, _calendar_event.until_time, caltime);
1810 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_caltime() Fail(%d)", ret);
1811 ret = cal_record_set_int(record, _calendar_event.range_type, CALENDAR_RANGE_UNTIL);
1812 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
1813 } else if (CAL_STRING_EQUAL == strncmp(t[i], "COUNT=", strlen("COUNT="))) {
1814 int count = atoi(t[i] + strlen("COUNT="));
1815 if (count < 1) count = 1;
1816 ret = cal_record_set_int(record, _calendar_event.count, count);
1817 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
1818 ret = cal_record_set_int(record, _calendar_event.range_type, CALENDAR_RANGE_COUNT);
1819 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
1820 } else if (CAL_STRING_EQUAL == strncmp(t[i], "INTERVAL=", strlen("INTERVAL="))) {
1821 int interval = atoi(t[i] + strlen("INTERVAL="));
1822 if (interval < 1) interval = 1;
1823 ret = cal_record_set_int(record, _calendar_event.interval, interval);
1824 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
1825 } else if (CAL_STRING_EQUAL == strncmp(t[i], "BYYEARDAY=", strlen("BYYEARDAY="))) {
1826 ret = cal_record_set_str(record, _calendar_event.byyearday, t[i] + strlen("BYYEARDAY="));
1827 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
1828 } else if (CAL_STRING_EQUAL == strncmp(t[i], "BYWEEKNO=", strlen("BYWEEKNO="))) {
1829 ret = cal_record_set_str(record, _calendar_event.byweekno, t[i] + strlen("BYWEEKNO="));
1830 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
1831 } else if (CAL_STRING_EQUAL == strncmp(t[i], "BYMONTH=", strlen("BYMONTH="))) {
1832 ret = cal_record_set_str(record, _calendar_event.bymonth, t[i] + strlen("BYMONTH="));
1833 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
1834 } else if (CAL_STRING_EQUAL == strncmp(t[i], "BYMONTHDAY=", strlen("BYMONTHDAY="))) {
1835 ret = cal_record_set_str(record, _calendar_event.bymonthday, t[i] + strlen("BYMONTHDAY="));
1836 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
1837 } else if (CAL_STRING_EQUAL == strncmp(t[i], "BYDAY=", strlen("BYDAY="))) {
1838 ret = cal_record_set_str(record, _calendar_event.byday, t[i] + strlen("BYDAY="));
1839 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
1840 } else if (CAL_STRING_EQUAL == strncmp(t[i], "BYSETPOS=", strlen("BYSETPOS="))) {
1841 ret = cal_record_set_str(record, _calendar_event.bysetpos, t[i] + strlen("BYSETPOS="));
1842 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
1843 } else if (CAL_STRING_EQUAL == strncmp(t[i], "WKST=", strlen("WKST="))) {
1844 if (CAL_STRING_EQUAL == strncmp(t[i] + strlen("WKST="), "SU", strlen("SU")))
1845 ret = cal_record_set_int(record, _calendar_event.wkst, CALENDAR_SUNDAY);
1846 else if (CAL_STRING_EQUAL == strncmp(t[i] + strlen("WKST="), "MO", strlen("MO")))
1847 ret = cal_record_set_int(record, _calendar_event.wkst, CALENDAR_MONDAY);
1848 else if (CAL_STRING_EQUAL == strncmp(t[i] + strlen("WKST="), "TU", strlen("TU")))
1849 ret = cal_record_set_int(record, _calendar_event.wkst, CALENDAR_TUESDAY);
1850 else if (CAL_STRING_EQUAL == strncmp(t[i] + strlen("WKST="), "WE", strlen("WE")))
1851 ret = cal_record_set_int(record, _calendar_event.wkst, CALENDAR_WEDNESDAY);
1852 else if (CAL_STRING_EQUAL == strncmp(t[i] + strlen("WKST="), "TH", strlen("TH")))
1853 ret = cal_record_set_int(record, _calendar_event.wkst, CALENDAR_THURSDAY);
1854 else if (CAL_STRING_EQUAL == strncmp(t[i] + strlen("WKST="), "FR", strlen("FR")))
1855 ret = cal_record_set_int(record, _calendar_event.wkst, CALENDAR_FRIDAY);
1856 else if (CAL_STRING_EQUAL == strncmp(t[i] + strlen("WKST="), "SA", strlen("SA")))
1857 ret = cal_record_set_int(record, _calendar_event.wkst, CALENDAR_SATURDAY);
1859 DBG("Unable to parse[%s]", t[i]);
1861 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
1863 DBG("Unable to parse[%s]", t[i]);
1870 static void __work_component_property_rrule(char *value, calendar_record_h record, struct user_data *ud)
1874 RET_IF(NULL == value);
1875 RET_IF('\0' == *value);
1876 RET_IF(NULL == record);
1879 int version = ud->version;
1880 /* check if this field has different version content */
1881 if (CAL_STRING_EQUAL == strncmp(value, ":FREQ=", strlen(":FREQ=")))
1882 version = VCAL_VER_2;
1884 version = VCAL_VER_1;
1887 case CALENDAR_BOOK_TYPE_EVENT:
1890 __work_component_property_rrule_ver_1(value, record, ud);
1893 __work_component_property_rrule_ver_2(value, record, ud);
1897 case CALENDAR_BOOK_TYPE_TODO:
1898 DBG("Not support rrule in todo");
1903 static void __work_component_property_dtend(char *value, calendar_record_h record, struct user_data *ud)
1905 RET_IF(NULL == value);
1906 RET_IF('\0' == *value);
1907 RET_IF(NULL == record);
1912 value = __decode_datetime(value, ud);
1913 calendar_time_s dtend = {0};
1914 ret = _get_caltime(value, &dtend, ud);
1915 if (CALENDAR_ERROR_NONE != ret) {
1916 /* LCOV_EXCL_START */
1917 ERR("_get_caltime() Fail(%d)", ret);
1919 /* LCOV_EXCL_STOP */
1923 tzid = ud->datetime_tzid ? ud->datetime_tzid : (ud->timezone_tzid ? ud->timezone_tzid : NULL);
1925 /* check if dtend is earlier than dtstart. */
1927 if (CALENDAR_BOOK_TYPE_TODO == ud->type) /* skip in todo */
1930 calendar_time_s dtstart = {0};
1931 ret = calendar_record_get_caltime(record, _calendar_event.start_time, &dtstart);
1932 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_caltime() Fail(%d)", ret);
1934 if (0 == dtstart.time.utime) /* not set yet */
1938 _sub_caltime(ud, &dtstart, &dtend, &diff);
1939 if (diff <= 0) /* proper data */
1942 WARN("dtend < dtstart so set end time to start");
1947 case CALENDAR_BOOK_TYPE_EVENT:
1948 if (tzid && *tzid) {
1949 ret = cal_record_set_str(record, _calendar_event.end_tzid, tzid);
1950 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
1952 ret = cal_record_set_caltime(record, _calendar_event.end_time, dtend);
1953 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_caltime() Fail(%d)", ret);
1955 case CALENDAR_BOOK_TYPE_TODO:
1956 if (tzid && *tzid) {
1957 ret = cal_record_set_str(record, _calendar_todo.due_tzid, tzid);
1958 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
1960 ret = cal_record_set_caltime(record, _calendar_todo.due_time, dtend);
1961 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_caltime() Fail(%d)", ret);
1966 static void __work_component_property_attendee_mailto(calendar_record_h attendee, char *value)
1968 RET_IF(NULL == value);
1969 RET_IF('\0' == *value);
1970 RET_IF(NULL == attendee);
1973 char *mailto = NULL;
1974 ret = calendar_record_get_str(attendee, _calendar_attendee.email, &mailto);
1975 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str() Fail");
1979 ret = cal_record_set_str(attendee, _calendar_attendee.email, value);
1980 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail");
1982 static void __work_component_property_attendee_cutype(calendar_record_h attendee, char *value)
1986 RET_IF(NULL == value);
1987 RET_IF('\0' == *value);
1988 RET_IF(NULL == attendee);
1990 const char *prop = NULL;
1991 if (CAL_STRING_EQUAL == strncmp(value, "INDIVIDUAL", strlen("INDIVIDUAL"))) {
1992 ret = cal_record_set_int(attendee, _calendar_attendee.cutype, CALENDAR_ATTENDEE_CUTYPE_INDIVIDUAL);
1993 if (strlen(value) > strlen("INDIVIDUAL"))
1994 prop = "INDIVIDUAL";
1996 } else if (CAL_STRING_EQUAL == strncmp(value, "GROUP", strlen("GROUP"))) {
1997 ret = cal_record_set_int(attendee, _calendar_attendee.cutype, CALENDAR_ATTENDEE_CUTYPE_GROUP);
1998 if (strlen(value) > strlen("GROUP"))
2001 } else if (CAL_STRING_EQUAL == strncmp(value, "RESOURCE", strlen("RESOURCE"))) {
2002 ret = cal_record_set_int(attendee, _calendar_attendee.cutype, CALENDAR_ATTENDEE_CUTYPE_RESOURCE);
2003 if (strlen(value) > strlen("RESOURCE"))
2006 } else if (CAL_STRING_EQUAL == strncmp(value, "ROOM", strlen("ROOM"))) {
2007 ret = cal_record_set_int(attendee, _calendar_attendee.cutype, CALENDAR_ATTENDEE_CUTYPE_ROOM);
2008 if (strlen(value) > strlen("ROOM"))
2011 } else if (CAL_STRING_EQUAL == strncmp(value, "UNKNOWN", strlen("UNKNOWN"))) {
2012 ret = cal_record_set_int(attendee, _calendar_attendee.cutype, CALENDAR_ATTENDEE_CUTYPE_UNKNOWN);
2013 if (strlen(value) > strlen("UNKNOWN"))
2017 /* LCOV_EXCL_START */
2018 ERR("Invalid value[%s]", value);
2019 /* LCOV_EXCL_STOP */
2021 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
2024 if (prop && CAL_STRING_EQUAL == strncmp(value + strlen(prop), ":MAILTO", strlen(":MAILTO")))
2025 __work_component_property_attendee_mailto(attendee, value + strlen(prop) + strlen(":MAILTO") +1);
2027 static void __work_component_property_attendee_member(calendar_record_h attendee, char *value)
2029 RET_IF(NULL == value);
2030 RET_IF('\0' == *value);
2031 RET_IF(NULL == attendee);
2033 int ret = cal_record_set_str(attendee, _calendar_attendee.member, value);
2034 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
2036 static void __work_component_property_attendee_role(calendar_record_h attendee, char *value)
2040 RET_IF(NULL == value);
2041 RET_IF('\0' == *value);
2042 RET_IF(NULL == attendee);
2044 const char *prop = NULL;
2045 if (CAL_STRING_EQUAL == strncmp(value, "REQ-PARTICIPANT", strlen("REQ-PARTICIPANT"))) {
2046 ret = cal_record_set_int(attendee, _calendar_attendee.cutype, CALENDAR_ATTENDEE_ROLE_REQ_PARTICIPANT);
2047 if (strlen(value) > strlen("REQ-PARTICIPANT"))
2048 prop = "REQ-PARTICIPANT";
2049 } else if (CAL_STRING_EQUAL == strncmp(value, "OPT-PARTICIPANT", strlen("OPT-PARTICIPANT"))) {
2050 ret = cal_record_set_int(attendee, _calendar_attendee.cutype, CALENDAR_ATTENDEE_ROLE_OPT_PARTICIPANT);
2051 if (strlen(value) > strlen("OPT-PARTICIPANT"))
2052 prop = "OPT-PARTICIPANT";
2053 } else if (CAL_STRING_EQUAL == strncmp(value, "NON-PARTICIPANT", strlen("NON-PARTICIPANT"))) {
2054 ret = cal_record_set_int(attendee, _calendar_attendee.cutype, CALENDAR_ATTENDEE_ROLE_NON_PARTICIPANT);
2055 if (strlen(value) > strlen("NON-PARTICIPANT"))
2056 prop = "NON-PARTICIPANT";
2057 } else if (CAL_STRING_EQUAL == strncmp(value, "CHAIR", strlen("CHAIR"))) {
2058 ret = cal_record_set_int(attendee, _calendar_attendee.cutype, CALENDAR_ATTENDEE_ROLE_CHAIR);
2059 if (strlen(value) > strlen("CHAIR"))
2062 /* LCOV_EXCL_START */
2063 ERR("Invalid value[%s]", value);
2064 /* LCOV_EXCL_STOP */
2066 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
2069 if (prop && CAL_STRING_EQUAL == strncmp(value + strlen(prop), ":MAILTO", strlen(":MAILTO")))
2070 __work_component_property_attendee_mailto(attendee, value + strlen(prop) + strlen(":MAILTO") +1);
2072 static void __work_component_property_attendee_partstat(calendar_record_h attendee, char *value)
2076 RET_IF(NULL == value);
2077 RET_IF('\0' == *value);
2078 RET_IF(NULL == attendee);
2080 const char *prop = NULL;
2081 if (CAL_STRING_EQUAL == strncmp(value, "NEEDS-ACTION", strlen("NEEDS-ACTION"))) {
2082 ret = cal_record_set_int(attendee, _calendar_attendee.cutype, CALENDAR_ATTENDEE_STATUS_PENDING);
2083 if (strlen(value) > strlen("NEEDS-ACTION"))
2084 prop = "NEEDS-ACTION";
2086 } else if (CAL_STRING_EQUAL == strncmp(value, "ACCEPTED", strlen("ACCEPTED"))) {
2087 ret = cal_record_set_int(attendee, _calendar_attendee.cutype, CALENDAR_ATTENDEE_STATUS_ACCEPTED);
2088 if (strlen(value) > strlen("ACCEPTED"))
2091 } else if (CAL_STRING_EQUAL == strncmp(value, "DECLINED", strlen("DECLINED"))) {
2092 ret = cal_record_set_int(attendee, _calendar_attendee.cutype, CALENDAR_ATTENDEE_STATUS_DECLINED);
2093 if (strlen(value) > strlen("DECLINED"))
2096 } else if (CAL_STRING_EQUAL == strncmp(value, "TENTATIVE", strlen("TENTATIVE"))) {
2097 ret = cal_record_set_int(attendee, _calendar_attendee.cutype, CALENDAR_ATTENDEE_STATUS_TENTATIVE);
2098 if (strlen(value) > strlen("TENTATIVE"))
2101 } else if (CAL_STRING_EQUAL == strncmp(value, "DELEGATED", strlen("DELEGATED"))) {
2102 ret = cal_record_set_int(attendee, _calendar_attendee.cutype, CALENDAR_ATTENDEE_STATUS_DELEGATED);
2103 if (strlen(value) > strlen("DELEGATED"))
2106 } else if (CAL_STRING_EQUAL == strncmp(value, "COMPLETED", strlen("COMPLETED"))) {
2107 ret = cal_record_set_int(attendee, _calendar_attendee.cutype, CALENDAR_ATTENDEE_STATUS_COMPLETED);
2108 if (strlen(value) > strlen("COMPLETED"))
2111 } else if (CAL_STRING_EQUAL == strncmp(value, "IN-PROCESS", strlen("IN-PROCESS"))) {
2112 ret = cal_record_set_int(attendee, _calendar_attendee.cutype, CALENDAR_ATTENDEE_STATUS_IN_PROCESS);
2113 if (strlen(value) > strlen("IN-PROCESS"))
2114 prop = "IN-PROCESS";
2117 /* LCOV_EXCL_START */
2118 ERR("Invalid value[%s]", value);
2119 /* LCOV_EXCL_STOP */
2121 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
2124 if (prop && CAL_STRING_EQUAL == strncmp(value + strlen(prop), ":MAILTO", strlen(":MAILTO")))
2125 __work_component_property_attendee_mailto(attendee, value + strlen(prop) + strlen(":MAILTO") +1);
2127 static void __work_component_property_attendee_rsvp(calendar_record_h attendee, char *value)
2129 RET_IF(NULL == value);
2130 RET_IF('\0' == *value);
2131 RET_IF(NULL == attendee);
2134 if (CAL_STRING_EQUAL == strncmp(value, "TRUE", strlen("TRUE")))
2135 ret = cal_record_set_int(attendee, _calendar_attendee.rsvp, 1);
2137 ret = cal_record_set_int(attendee, _calendar_attendee.rsvp, 0);
2139 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
2141 static void __work_component_property_attendee_delegated_to(calendar_record_h attendee, char *value)
2143 RET_IF(NULL == value);
2144 RET_IF('\0' == *value);
2145 RET_IF(NULL == attendee);
2148 ret = cal_record_set_str(attendee, _calendar_attendee.delegatee_uri, value);
2149 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail");
2151 static void __work_component_property_attendee_delegated_from(calendar_record_h attendee, char *value)
2153 RET_IF(NULL == value);
2154 RET_IF('\0' == *value);
2155 RET_IF(NULL == attendee);
2158 ret = cal_record_set_str(attendee, _calendar_attendee.delegator_uri, value);
2159 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail");
2161 static void __work_component_property_attendee_sent_by(calendar_record_h attendee, char *value)
2165 static void __work_component_property_attendee_cn(calendar_record_h attendee, char *value)
2167 RET_IF(NULL == value);
2168 RET_IF('\0' == *value);
2169 RET_IF(NULL == attendee);
2172 ret = cal_record_set_str(attendee, _calendar_attendee.name, value);
2173 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail");
2175 static void __work_component_property_attendee_dir(calendar_record_h attendee, char *value)
2182 * ATTENDEE;ROLE=REQ-PARTICIPANT;DELEGATED-FROM="MAILTO:bob@host.com";PARTSTAT=ACCEPTED;CN=Jane Doe:MAILTO:jdoe@host1.com
2183 * ATTENDEE;CN=John Smith;DIR="ldap://host.com:6666/o=eDABC%20Industries,c=3DUS??(cn=3DBJim%20Dolittle)":MAILTO:jimdo@host1.com
2184 * ATTENDEE;RSVP=TRUE;ROLE=REQ-PARTICIPANT;CUTYPE=GROUP:MAILTO:employee-A@host.com
2185 * ATTENDEE;CN=MAILTO:MAILTO:MAILTO@host.com
2187 static void __work_component_property_attendee(char *value, calendar_record_h record, struct user_data *ud)
2189 RET_IF(NULL == value);
2190 RET_IF('\0' == *value);
2191 RET_IF(NULL == record);
2195 calendar_record_h attendee = NULL;
2196 ret = calendar_record_create(_calendar_attendee._uri, &attendee);
2197 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_create() Fail(%d)", ret);
2200 t = g_strsplit(value, ";", -1);
2201 RETM_IF(NULL == t, "g_strsplit() Fail");
2203 int len = g_strv_length(t);
2205 for (i = 0; i < len; i++) {
2206 if (NULL == t[i] || '\0' == *t[i]) continue;
2208 if (CAL_STRING_EQUAL == strncmp(t[i], "CUTYPE", strlen("CUTYPE")))
2209 __work_component_property_attendee_cutype(attendee, t[i] + strlen("CUTYPE") +1);
2210 else if (CAL_STRING_EQUAL == strncmp(t[i], "MEMBER", strlen("MEMBER")))
2211 __work_component_property_attendee_member(attendee, t[i] + strlen("MEMBER") +1);
2212 else if (CAL_STRING_EQUAL == strncmp(t[i], "ROLE", strlen("ROLE")))
2213 __work_component_property_attendee_role(attendee, t[i] + strlen("ROLE") +1);
2214 else if (CAL_STRING_EQUAL == strncmp(t[i], "PARTSTAT", strlen("PARTSTAT")))
2215 __work_component_property_attendee_partstat(attendee, t[i] + strlen("PARTSTAT") +1);
2216 else if (CAL_STRING_EQUAL == strncmp(t[i], "RSVP", strlen("RSVP")))
2217 __work_component_property_attendee_rsvp(attendee, t[i] + strlen("RSVP") +1);
2218 else if (CAL_STRING_EQUAL == strncmp(t[i], "DELEGATED-TO", strlen("DELEGATED-TO")))
2219 __work_component_property_attendee_delegated_to(attendee, t[i] + strlen("DELEGATED-TO") +1);
2220 else if (CAL_STRING_EQUAL == strncmp(t[i], "DELEGATED-FROM", strlen("DELEGATED-FROM")))
2221 __work_component_property_attendee_delegated_from(attendee, t[i] + strlen("DELEGATED-FROM") +1);
2222 else if (CAL_STRING_EQUAL == strncmp(t[i], "SENT_BY", strlen("SENT_BY")))
2223 __work_component_property_attendee_sent_by(attendee, t[i] + strlen("SENT_BY") +1);
2224 else if (CAL_STRING_EQUAL == strncmp(t[i], "CN", strlen("CN")))
2225 __work_component_property_attendee_cn(attendee, t[i] + strlen("CN") +1);
2226 else if (CAL_STRING_EQUAL == strncmp(t[i], "DIR", strlen("DIR")))
2227 __work_component_property_attendee_dir(attendee, t[i] + strlen("DIR") +1);
2228 else if (CAL_STRING_EQUAL == strncmp(t[i], ":MAILTO", strlen(":MAILTO")))
2229 __work_component_property_attendee_mailto(attendee, t[i] + strlen(":MAILTO") +1);
2231 ERR("Invalid value[%s]", t[i]);
2237 case CALENDAR_BOOK_TYPE_EVENT:
2238 ret = calendar_record_add_child_record(record, _calendar_event.calendar_attendee, attendee);
2239 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_add_child_record() Fail(%d)", ret);
2241 case CALENDAR_BOOK_TYPE_TODO:
2242 ret = calendar_record_add_child_record(record, _calendar_event.calendar_attendee, attendee);
2243 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_add_child_record() Fail(%d)", ret);
2248 static void __work_component_property_categories(char *value, calendar_record_h record, struct user_data *ud)
2250 RET_IF(NULL == value);
2251 RET_IF('\0' == *value);
2252 RET_IF(NULL == record);
2256 char *s = __decode_charset(value);
2257 __decode_escaped_char(s);
2259 case CALENDAR_BOOK_TYPE_EVENT:
2260 ret = cal_record_set_str(record, _calendar_event.categories, s);
2261 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
2263 case CALENDAR_BOOK_TYPE_TODO:
2264 ret = cal_record_set_str(record, _calendar_todo.categories, s);
2265 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
2271 static void _set_alarm_tick_unit(calendar_record_h alarm, calendar_time_s alarm_time, int diff)
2275 RET_IF(NULL == alarm);
2278 DBG("set specific alarm");
2279 ret = cal_record_set_caltime(alarm, _calendar_alarm.alarm_time, alarm_time);
2280 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_caltime() Fail(%d)", ret);
2281 ret = cal_record_set_int(alarm, _calendar_alarm.tick_unit, CALENDAR_ALARM_TIME_UNIT_SPECIFIC);
2282 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
2283 } else if (0 == diff) {
2284 DBG("set alarm in start time");
2285 ret = cal_record_set_int(alarm, _calendar_alarm.tick, 0);
2286 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
2287 ret = cal_record_set_int(alarm, _calendar_alarm.tick_unit, CALENDAR_ALARM_TIME_UNIT_HOUR);
2288 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
2292 _get_tick_unit(diff, &tick, &unit);
2293 ret = cal_record_set_int(alarm, _calendar_alarm.tick, tick);
2294 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
2295 ret = cal_record_set_int(alarm, _calendar_alarm.tick_unit, unit);
2296 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
2302 * dalarmparts = 0*3(strnosemi ";") strnosemi; runTime, snoozeTime, repeatCount, displayString
2303 * DALARM:19960415T235000;PT5M;2;Your Taxes Are Due !!!
2305 static void __work_component_property_dalarm(char *value, calendar_record_h record, struct user_data *ud)
2307 RET_IF(NULL == value);
2308 RET_IF('\0' == *value);
2309 RET_IF(NULL == record);
2314 t = g_strsplit_set(value, ";:", -1);
2315 RETM_IF(NULL == t, "g_strsplit_set() Fail");
2317 calendar_record_h alarm = NULL;
2318 ret = calendar_record_create(_calendar_alarm._uri, &alarm);
2319 if (CALENDAR_ERROR_NONE != ret) {
2320 /* LCOV_EXCL_START */
2321 ERR("calendar_record_create() Fail(%d)", ret);
2324 /* LCOV_EXCL_STOP */
2326 ret = cal_record_set_int(alarm, _calendar_alarm.action, CALENDAR_ALARM_ACTION_DISPLAY);
2327 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
2329 int len = g_strv_length(t);
2331 int index = VCAL_VER_10_DALARM_NONE;
2332 for (i = 0; i < len; i++) {
2335 if (NULL == t[i] || '\0' == *t[i])
2338 if ('0' <= *t[i] && *t[i] <= '9' && strlen("PTM") < strlen(t[i])) {
2340 index = VCAL_VER_10_DALARM_RUN_TIME;
2341 calendar_time_s alarm_time = {0};
2342 ret = _get_caltime(t[i], &alarm_time, ud);
2343 if (CALENDAR_ERROR_NONE != ret) {
2344 /* LCOV_EXCL_START */
2345 ERR("_get_caltime() Fail(%d)", ret);
2346 index = VCAL_VER_10_AALARM_NONE;
2348 /* LCOV_EXCL_STOP */
2351 if (true == ud->has_rrule) {
2352 calendar_time_s start_time = {0};
2353 ret = calendar_record_get_caltime(record, _calendar_event.start_time, &start_time);
2356 ret = _sub_caltime(ud, &start_time, &alarm_time, &diff);
2357 if (CALENDAR_ERROR_NONE != ret) {
2358 /* LCOV_EXCL_START */
2359 ERR("_sub_caltime() Fail(%d)", ret);
2360 index = VCAL_VER_10_DALARM_NONE;
2362 /* LCOV_EXCL_STOP */
2364 _set_alarm_tick_unit(alarm, alarm_time, diff);
2367 _set_alarm_tick_unit(alarm, alarm_time, -1); /* -1 goes to specific time */
2369 } else if (VCAL_VER_10_DALARM_DISPLAY_STRING == index) { /* displayString */
2370 DBG("displayString [%s]", t[i]);
2371 ret = cal_record_set_str(alarm, _calendar_alarm.summary, t[i]);
2372 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
2379 if (VCAL_VER_10_DALARM_NONE == index) {
2381 calendar_record_destroy(alarm, true);
2387 case VCALENDAR_TYPE_VEVENT:
2388 ret = calendar_record_add_child_record(record, _calendar_event.calendar_alarm, alarm);
2389 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_add_child_record() Fail(%d)", ret);
2391 case VCALENDAR_TYPE_VTODO:
2392 ret = calendar_record_add_child_record(record, _calendar_todo.calendar_alarm, alarm);
2393 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_add_child_record() Fail(%d)", ret);
2401 * malarmparts = 0*4(strnosemi ";") strnosemi; runTime, snoozeTime, repeatCount, addressString, noteString
2403 static void __work_component_property_malarm(char *value, calendar_record_h record, struct user_data *ud)
2405 /* diff with aalarm: action */
2406 RET_IF(NULL == value);
2407 RET_IF('\0' == *value);
2408 RET_IF(NULL == record);
2413 t = g_strsplit_set(value, ";:", -1);
2414 RETM_IF(NULL == t, "g_strsplit_set() Fail");
2416 calendar_record_h alarm = NULL;
2417 ret = calendar_record_create(_calendar_alarm._uri, &alarm);
2418 if (CALENDAR_ERROR_NONE != ret) {
2419 /* LCOV_EXCL_START */
2420 ERR("calendar_record_create() Fail(%d)", ret);
2423 /* LCOV_EXCL_STOP */
2425 ret = cal_record_set_int(alarm, _calendar_alarm.action, CALENDAR_ALARM_ACTION_EMAIL);
2426 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
2428 int len = g_strv_length(t);
2430 int index = VCAL_VER_10_MALARM_NONE;
2431 for (i = 0; i < len; i++) {
2434 if (NULL == t[i] || '\0' == *t[i])
2437 if ('0' <= *t[i] && *t[i] <= '9' && strlen("PTM") < strlen(t[i])) {
2439 index = VCAL_VER_10_MALARM_RUN_TIME;
2440 calendar_time_s alarm_time = {0};
2441 ret = _get_caltime(t[i], &alarm_time, ud);
2442 if (CALENDAR_ERROR_NONE != ret) {
2443 /* LCOV_EXCL_START */
2444 ERR("_get_caltime() Fail(%d)", ret);
2445 index = VCAL_VER_10_AALARM_NONE;
2447 /* LCOV_EXCL_STOP */
2450 if (true == ud->has_rrule) {
2451 calendar_time_s start_time = {0};
2452 ret = calendar_record_get_caltime(record, _calendar_event.start_time, &start_time);
2453 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_caltime() Fail(%d)", ret);
2456 ret = _sub_caltime(ud, &start_time, &alarm_time, &diff);
2457 if (CALENDAR_ERROR_NONE != ret) {
2458 /* LCOV_EXCL_START */
2459 ERR("_sub_caltime() Fail(%d)", ret);
2460 index = VCAL_VER_10_MALARM_NONE;
2462 /* LCOV_EXCL_STOP */
2464 _set_alarm_tick_unit(alarm, alarm_time, diff);
2467 _set_alarm_tick_unit(alarm, alarm_time, -1); /* -1 goes to specific time */
2469 } else if (VCAL_VER_10_MALARM_ADDRESS_STRING == index) { /* addressString */
2470 DBG("addressString [%s]", t[i]);
2471 ret = cal_record_set_str(alarm, _calendar_alarm.attach, t[i]);
2472 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
2474 } else if (VCAL_VER_10_MALARM_NOTE_STRING == index) { /* noteString */
2475 DBG("noteString [%s]", t[i]);
2476 ret = cal_record_set_str(alarm, _calendar_alarm.description, t[i]);
2477 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
2484 if (VCAL_VER_10_MALARM_NONE == index) {
2486 calendar_record_destroy(alarm, true);
2492 case VCALENDAR_TYPE_VEVENT:
2493 ret = calendar_record_add_child_record(record, _calendar_event.calendar_alarm, alarm);
2494 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_add_child_record() Fail(%d)", ret);
2496 case VCALENDAR_TYPE_VTODO:
2497 ret = calendar_record_add_child_record(record, _calendar_todo.calendar_alarm, alarm);
2498 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_add_child_record() Fail(%d)", ret);
2505 * aalarmparts = 0*3(strnosemi ";") strnosemi; runTime, snoozeTime, repeatCount, audioContent
2506 * AALARM;TYPE=WAVE;VALUE=URL:19960415T235959; ; ; file:///mmedia/taps.wav
2507 * AALARM;TYPE=WAVE;VALUE=CONTENT-ID:19960903T060000;PT15M;4;<jsmith.part2.=960901T083000.xyzMail@host1.com>
2509 static void __work_component_property_aalarm(char *value, calendar_record_h record, struct user_data *ud)
2513 RET_IF(NULL == value);
2514 RET_IF('\0' == *value);
2515 RET_IF(NULL == record);
2520 t = g_strsplit_set(value, ";:", -1);
2521 RETM_IF(NULL == t, "g_strsplit_set() Fail");
2523 calendar_record_h alarm = NULL;
2524 ret = calendar_record_create(_calendar_alarm._uri, &alarm);
2525 if (CALENDAR_ERROR_NONE != ret) {
2526 /* LCOV_EXCL_START */
2527 ERR("calendar_record_create() Fail(%d)", ret);
2530 /* LCOV_EXCL_STOP */
2532 ret = cal_record_set_int(alarm, _calendar_alarm.action, CALENDAR_ALARM_ACTION_AUDIO);
2533 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
2535 int len = g_strv_length(t);
2537 int index = VCAL_VER_10_AALARM_NONE;
2538 for (i = 0; i < len; i++) {
2541 if (NULL == t[i] || '\0' == *t[i])
2544 if ('0' <= *t[i] && *t[i] <= '9' && strlen("PTM") < strlen(t[i])) {
2546 index = VCAL_VER_10_AALARM_RUN_TIME;
2547 calendar_time_s alarm_time = {0};
2548 ret = _get_caltime(t[i], &alarm_time, ud);
2549 if (CALENDAR_ERROR_NONE != ret) {
2550 /* LCOV_EXCL_START */
2551 ERR("_get_caltime() Fail(%d)", ret);
2552 index = VCAL_VER_10_AALARM_NONE;
2554 /* LCOV_EXCL_STOP */
2557 if (true == ud->has_rrule) {
2558 calendar_time_s start_time = {0};
2559 ret = calendar_record_get_caltime(record, _calendar_event.start_time, &start_time);
2562 ret = _sub_caltime(ud, &start_time, &alarm_time, &diff);
2563 if (CALENDAR_ERROR_NONE != ret) {
2564 /* LCOV_EXCL_START */
2565 ERR("_sub_caltime() Fail(%d)", ret);
2566 index = VCAL_VER_10_AALARM_NONE;
2568 /* LCOV_EXCL_STOP */
2570 _set_alarm_tick_unit(alarm, alarm_time, diff);
2573 _set_alarm_tick_unit(alarm, alarm_time, -1); /* -1 goes to specific time */
2575 } else if (VCAL_VER_10_AALARM_AUDIO_CONTENT == index) {
2577 DBG("Content [%s]", t[i]);
2578 ret = cal_record_set_str(alarm, _calendar_alarm.attach, t[i]);
2579 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
2585 if (VCAL_VER_10_AALARM_NONE == index) {
2587 calendar_record_destroy(alarm, true);
2593 case VCALENDAR_TYPE_VEVENT:
2594 ret = calendar_record_add_child_record(record, _calendar_event.calendar_alarm, alarm);
2595 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_add_child_record() Fail(%d)", ret);
2597 case VCALENDAR_TYPE_VTODO:
2598 ret = calendar_record_add_child_record(record, _calendar_todo.calendar_alarm, alarm);
2599 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_add_child_record() Fail(%d)", ret);
2605 static void __work_component_property_exdate(char *value, calendar_record_h record, struct user_data *ud)
2607 RET_IF(NULL == value);
2608 RET_IF('\0' == *value);
2609 RET_IF(NULL == record);
2614 case CALENDAR_BOOK_TYPE_EVENT:
2615 ret = cal_record_set_str(record, _calendar_event.exdate, value + 1);
2616 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
2618 case CALENDAR_BOOK_TYPE_TODO:
2619 /* LCOV_EXCL_START */
2620 ERR("No exdate in todo");
2622 /* LCOV_EXCL_STOP */
2626 static void __work_component_property_x_allday(char *value, calendar_record_h record, struct user_data *ud)
2628 RET_IF(NULL == value);
2629 RET_IF('\0' == *value);
2630 RET_IF(NULL == record);
2634 if (CAL_STRING_EQUAL == strncmp(value, ":SET", strlen(":SET"))) {
2635 DBG("x-allday: set");
2636 ud->is_allday = true;
2638 calendar_time_s caltime = {0};
2640 case CALENDAR_BOOK_TYPE_EVENT:
2641 ret = calendar_record_get_caltime(record, _calendar_event.start_time, &caltime);
2642 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_caltime() Fail");
2643 if (CALENDAR_TIME_LOCALTIME == caltime.type) {
2644 caltime.time.date.hour = 0;
2645 caltime.time.date.minute = 0;
2646 caltime.time.date.second = 0;
2647 ret = cal_record_set_caltime(record, _calendar_event.start_time, caltime);
2648 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_caltime() Fail");
2650 ret = calendar_record_get_caltime(record, _calendar_event.end_time, &caltime);
2651 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_caltime() Fail");
2652 if (CALENDAR_TIME_LOCALTIME == caltime.type) {
2653 caltime.time.date.hour = 0;
2654 caltime.time.date.minute = 0;
2655 caltime.time.date.second = 0;
2656 ret = cal_record_set_caltime(record, _calendar_event.end_time, caltime);
2657 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_caltime() Fail");
2659 ret = calendar_record_get_caltime(record, _calendar_event.until_time, &caltime);
2660 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_caltime() Fail");
2661 if (CALENDAR_TIME_LOCALTIME == caltime.type) {
2662 caltime.time.date.hour = 0;
2663 caltime.time.date.minute = 0;
2664 caltime.time.date.second = 0;
2665 ret = cal_record_set_caltime(record, _calendar_event.until_time, caltime);
2666 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_caltime() Fail");
2669 case CALENDAR_BOOK_TYPE_TODO:
2670 ret = calendar_record_get_caltime(record, _calendar_todo.start_time, &caltime);
2671 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_caltime() Fail");
2672 if (CALENDAR_TIME_LOCALTIME == caltime.type) {
2673 caltime.time.date.hour = 0;
2674 caltime.time.date.minute = 0;
2675 caltime.time.date.second = 0;
2676 ret = cal_record_set_caltime(record, _calendar_todo.start_time, caltime);
2677 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_caltime() Fail");
2679 ret = calendar_record_get_caltime(record, _calendar_todo.due_time, &caltime);
2680 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_caltime() Fail");
2681 if (CALENDAR_TIME_LOCALTIME == caltime.type) {
2682 caltime.time.date.hour = 0;
2683 caltime.time.date.minute = 0;
2684 caltime.time.date.second = 0;
2685 ret = cal_record_set_caltime(record, _calendar_todo.due_time, caltime);
2686 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_caltime() Fail");
2693 static void __work_component_property_x_lunar(char *value, calendar_record_h record, struct user_data *ud)
2695 RET_IF(NULL == value);
2696 RET_IF('\0' == *value);
2697 RET_IF(NULL == record);
2701 if (CAL_STRING_EQUAL == strncmp(value, ":SET", strlen(":SET"))) {
2702 DBG("x-lunar: set");
2704 case CALENDAR_BOOK_TYPE_EVENT:
2705 ret = cal_record_set_int(record, _calendar_event.calendar_system_type, CALENDAR_SYSTEM_EAST_ASIAN_LUNISOLAR);
2706 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
2708 case CALENDAR_BOOK_TYPE_TODO:
2709 DBG("Not supported lunar in todo");
2715 static void __work_component_property_valarm_action(char *value, calendar_record_h alarm, struct user_data *ud)
2717 RET_IF(NULL == value);
2718 RET_IF('\0' == *value);
2719 RET_IF(NULL == alarm);
2721 const char *prop[CALENDAR_ALARM_ACTION_MAX] = {":AUDIO", ":DISPLAY", ":EMAIL"};
2725 for (i = 0; i < CALENDAR_ALARM_ACTION_MAX; i++) {
2726 if (CAL_STRING_EQUAL == strncmp(value, prop[i], strlen(prop[i]))) {
2727 ret = cal_record_set_int(alarm, _calendar_alarm.action, i);
2728 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
2734 static void __work_component_property_valarm_trigger(char *value, calendar_record_h record, calendar_record_h alarm, struct user_data *ud)
2738 RET_IF(NULL == value);
2739 RET_IF('\0' == *value);
2740 RET_IF(NULL == alarm);
2745 t = g_strsplit_set(value, ";:", -1);
2746 RETM_IF(NULL == t, "g_strsplit_set() Fail");
2748 int related = VCAL_RELATED_NONE;
2749 int len = g_strv_length(t);
2751 for (i = 0; i < len; i++) {
2752 if (NULL == t[i] || '\0' == *t[i]) continue;
2754 if (CAL_STRING_EQUAL == strncmp(t[i], "RELATED", strlen("RELATED"))) {
2755 if (CAL_STRING_EQUAL == strncmp(t[i] + strlen("RELATED"), "=START", strlen("=START")))
2756 related = VCAL_RELATED_START;
2757 else if (CAL_STRING_EQUAL == strncmp(t[i] + strlen("RELATED"), "=END", strlen("=END")))
2758 related = VCAL_RELATED_END;
2760 ERR("Invalid related:[%s]", t[i]);
2761 } else if (CAL_STRING_EQUAL == strncmp(t[i], "VALUE", strlen("VALUE"))) {
2764 if ('0' <= *t[i] && *t[i] <= '9' && strlen("YYYYDDMM") <= strlen(t[i])) {
2765 calendar_time_s caltime = {0};
2766 _get_caltime(t[i], &caltime, ud);
2767 ret = cal_record_set_caltime(alarm, _calendar_alarm.alarm_time, caltime);
2768 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_caltime() Fail(%d)", ret);
2769 ret = cal_record_set_int(alarm, _calendar_alarm.tick_unit, CALENDAR_ALARM_TIME_UNIT_SPECIFIC);
2770 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
2774 __decode_duration(t[i], strlen(t[i]), &tick, &unit);
2775 if (CALENDAR_ALARM_TIME_UNIT_SPECIFIC == unit || 0 < tick) {
2776 if (CALENDAR_ALARM_TIME_UNIT_SPECIFIC == unit)
2777 DBG("alarm tick is second, changed as specific.");
2779 DBG("alarm is set after start/end time(%d).", tick);
2781 calendar_time_s caltime = {0};
2782 if (VCAL_RELATED_NONE == related) {
2784 case CALENDAR_BOOK_TYPE_EVENT:
2785 related = VCAL_RELATED_START;
2787 case CALENDAR_BOOK_TYPE_TODO:
2788 related = VCAL_RELATED_END;
2793 case VCAL_RELATED_START:
2794 ret = calendar_record_get_caltime(record, _calendar_event.start_time, &caltime);
2795 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_caltime() Fail(%d)", ret);
2797 case VCAL_RELATED_END:
2798 ret = calendar_record_get_caltime(record, _calendar_event.end_time, &caltime);
2799 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_caltime() Fail(%d)", ret);
2802 cal_time_modify_caltime(&caltime, tick * unit);
2803 ret = cal_record_set_caltime(alarm, _calendar_alarm.alarm_time, caltime);
2804 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_caltime() Fail(%d)", ret);
2805 ret = cal_record_set_int(alarm, _calendar_alarm.tick_unit, CALENDAR_ALARM_TIME_UNIT_SPECIFIC);
2806 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
2808 ret = cal_record_set_int(alarm, _calendar_alarm.tick, (-1 * tick));
2809 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
2810 ret = cal_record_set_int(alarm, _calendar_alarm.tick_unit, unit);
2811 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
2820 static void __work_component_property_valarm_repeat(char *value, calendar_record_h alarm, struct user_data *ud)
2825 static void __work_component_property_valarm_attach(char *value, calendar_record_h alarm, struct user_data *ud)
2827 RET_IF(NULL == value);
2828 RET_IF('\0' == *value);
2829 RET_IF(NULL == alarm);
2831 int ret = cal_record_set_str(alarm, _calendar_alarm.attach, value + 1);
2832 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
2835 static void __work_component_property_valarm_description(char *value, calendar_record_h alarm, struct user_data *ud)
2837 RET_IF(NULL == value);
2838 RET_IF('\0' == *value);
2839 RET_IF(NULL == alarm);
2841 int ret = cal_record_set_str(alarm, _calendar_alarm.description, value + 1);
2842 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
2845 static void __work_component_property_valarm_summary(char *value, calendar_record_h alarm, struct user_data *ud)
2847 RET_IF(NULL == value);
2848 RET_IF('\0' == *value);
2849 RET_IF(NULL == alarm);
2851 int ret = cal_record_set_str(alarm, _calendar_alarm.summary, value);
2852 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
2855 static void __work_component_property_valarm_duration(char *value, calendar_record_h alarm, struct user_data *ud)
2860 static char* __work_component_property_begin(char *cursor, calendar_record_h record, struct user_data *ud)
2864 RETV_IF(NULL == cursor, NULL);
2865 RETV_IF(NULL == record, NULL);
2866 RETV_IF(NULL == ud, NULL);
2868 if (0 != strncmp(cursor, ":VALARM", strlen(":VALARM"))) {
2869 DBG("this is not valarm");
2870 return __crlf(cursor);
2873 __init_component_property_valarm();
2876 calendar_record_h alarm = NULL;
2877 ret = calendar_record_create(_calendar_alarm._uri, &alarm);
2878 RETVM_IF(CALENDAR_ERROR_NONE != ret, NULL, "calendar_record_create() Fail(%d)", ret);
2880 cursor = __crlf(cursor); /* crlf: BEGIN:VALARM */
2881 bool exit_loop = false;
2884 cursor = __get_index(cursor, component_property_valarm, VCAL_COMPONENT_PROPERTY_VALARM_MAX, &index);
2888 case VCAL_COMPONENT_PROPERTY_VALARM_ACTION:
2889 cursor = __get_value(cursor, &value);
2890 __work_component_property_valarm_action(value, alarm, ud);
2895 case VCAL_COMPONENT_PROPERTY_VALARM_TRIGGER:
2896 cursor = __get_value(cursor, &value);
2897 __work_component_property_valarm_trigger(value, record, alarm, ud);
2902 case VCAL_COMPONENT_PROPERTY_VALARM_REPEAT:
2903 cursor = __get_value(cursor, &value);
2904 __work_component_property_valarm_repeat(value, alarm, ud);
2909 case VCAL_COMPONENT_PROPERTY_VALARM_ATTACH:
2910 cursor = __get_value(cursor, &value);
2911 __work_component_property_valarm_attach(value, alarm, ud);
2916 case VCAL_COMPONENT_PROPERTY_VALARM_DESCRIPTION:
2917 cursor = __get_value(cursor, &value);
2918 __work_component_property_valarm_description(value, alarm, ud);
2923 case VCAL_COMPONENT_PROPERTY_VALARM_SUMMARY:
2924 cursor = __get_value(cursor, &value);
2925 __work_component_property_valarm_summary(value, alarm, ud);
2930 case VCAL_COMPONENT_PROPERTY_VALARM_DURATION:
2931 cursor = __get_value(cursor, &value);
2932 __work_component_property_valarm_duration(value, alarm, ud);
2937 case VCAL_COMPONENT_PROPERTY_VALARM_END:
2943 /* LCOV_EXCL_START */
2944 ERR("Invalid index(%d)", index);
2945 cursor = __crlf(cursor);
2947 /* LCOV_EXCL_STOP */
2950 if (true == exit_loop) break;
2954 case VCALENDAR_TYPE_VEVENT:
2955 ret = calendar_record_add_child_record(record, _calendar_event.calendar_alarm, alarm);
2957 case VCALENDAR_TYPE_VTODO:
2958 ret = calendar_record_add_child_record(record, _calendar_todo.calendar_alarm, alarm);
2961 RETVM_IF(CALENDAR_ERROR_NONE != ret, NULL, "calendar_record_add_child_record() Fail(%d)", ret);
2965 static char* __work_component_vevent(char *cursor, calendar_record_h record, struct user_data *ud)
2967 RETV_IF(NULL == cursor, NULL);
2968 RETV_IF(NULL == record, NULL);
2970 bool exit_loop = false;
2973 cursor = __get_index(cursor, component_property, VCAL_COMPONENT_PROPERTY_MAX, &index);
2977 case VCAL_COMPONENT_PROPERTY_DTSTAMP:
2978 cursor = __get_value(cursor, &value);
2979 __work_component_property_dtstamp(value, record, ud);
2983 case VCAL_COMPONENT_PROPERTY_UID:
2984 cursor = __get_value(cursor, &value);
2985 __work_component_property_uid(value, record, ud);
2989 case VCAL_COMPONENT_PROPERTY_RECURRENCE_ID:
2990 cursor = __get_value(cursor, &value);
2991 __work_component_property_recurrence_id(value, record, ud);
2995 case VCAL_COMPONENT_PROPERTY_DTSTART:
2996 cursor = __get_value(cursor, &value);
2997 __work_component_property_dtstart(value, record, ud);
3001 case VCAL_COMPONENT_PROPERTY_CREATED:
3002 cursor = __get_value(cursor, &value);
3003 __work_component_property_created(value, record, ud);
3007 case VCAL_COMPONENT_PROPERTY_DCREATED:
3008 cursor = __get_value(cursor, &value);
3009 __work_component_property_created(value, record, ud);
3013 case VCAL_COMPONENT_PROPERTY_DESCRIPTION:
3014 cursor = __get_value(cursor, &value);
3015 __work_component_property_description(value, record, ud);
3019 case VCAL_COMPONENT_PROPERTY_LAST_MODIFIED:
3020 cursor = __get_value(cursor, &value);
3021 __work_component_property_last_modified(value, record, ud);
3025 case VCAL_COMPONENT_PROPERTY_LOCATION:
3026 cursor = __get_value(cursor, &value);
3027 __work_component_property_location(value, record, ud);
3031 case VCAL_COMPONENT_PROPERTY_PRIORITY:
3032 cursor = __get_value(cursor, &value);
3033 __work_component_property_priority(value + 1, record, ud);
3037 case VCAL_COMPONENT_PROPERTY_STATUS:
3038 cursor = __get_value(cursor, &value);
3039 __work_component_property_status(value, record, ud);
3043 case VCAL_COMPONENT_PROPERTY_SUMMARY:
3044 cursor = __get_value(cursor, &value);
3045 __work_component_property_summary(value, record, ud);
3049 case VCAL_COMPONENT_PROPERTY_RRULE:
3050 cursor = __get_value(cursor, &value);
3051 __work_component_property_rrule(value, record, ud);
3055 case VCAL_COMPONENT_PROPERTY_DTEND:
3056 if (CAL_STRING_EQUAL != strcmp(((cal_record_s*)(record))->view_uri, _calendar_event._uri))
3058 cursor = __get_value(cursor, &value);
3059 __work_component_property_dtend(value, record, ud);
3063 case VCAL_COMPONENT_PROPERTY_DUE:
3064 if (CAL_STRING_EQUAL != strcmp(((cal_record_s*)(record))->view_uri, _calendar_todo._uri))
3066 cursor = __get_value(cursor, &value);
3067 __work_component_property_dtend(value, record, ud);
3071 case VCAL_COMPONENT_PROPERTY_ATTENDEE:
3072 cursor = __get_value(cursor, &value);
3073 __work_component_property_attendee(value, record, ud);
3077 case VCAL_COMPONENT_PROPERTY_CATEGORIES:
3078 cursor = __get_value(cursor, &value);
3079 __work_component_property_categories(value, record, ud);
3083 case VCAL_COMPONENT_PROPERTY_DALARM:
3084 cursor = __get_value(cursor, &value);
3085 __work_component_property_dalarm(value, record, ud);
3089 case VCAL_COMPONENT_PROPERTY_MALARM:
3090 cursor = __get_value(cursor, &value);
3091 __work_component_property_malarm(value, record, ud);
3095 case VCAL_COMPONENT_PROPERTY_AALARM:
3096 cursor = __get_value(cursor, &value);
3097 __work_component_property_aalarm(value, record, ud);
3101 case VCAL_COMPONENT_PROPERTY_EXDATE:
3102 cursor = __get_value(cursor, &value);
3103 __work_component_property_exdate(value, record, ud);
3107 case VCAL_COMPONENT_PROPERTY_X_ALLDAY:
3108 cursor = __get_value(cursor, &value);
3109 __work_component_property_x_allday(value, record, ud);
3113 case VCAL_COMPONENT_PROPERTY_X_LUNAR:
3114 cursor = __get_value(cursor, &value);
3115 __work_component_property_x_lunar(value, record, ud);
3119 case VCAL_COMPONENT_PROPERTY_BEGIN:
3120 cursor = __work_component_property_begin(cursor, record, ud);
3122 cursor = __crlf(cursor);
3124 case VCAL_COMPONENT_PROPERTY_END:
3126 cursor = __crlf(cursor);
3129 case VCAL_COMPONENT_PROPERTY_EXTENDED:
3130 cursor = __get_value(cursor, &value);
3135 cursor = __crlf(cursor);
3138 if (true == exit_loop) break;
3143 static char* __work_component_vjournal(char *cursor, calendar_record_h record, struct user_data *ud)
3145 RETV_IF(NULL == cursor, NULL);
3147 DBG("Not supported vjournal");
3149 bool exit_loop = false;
3152 cursor = __get_index(cursor, component_property, VCAL_COMPONENT_PROPERTY_MAX, &index);
3154 case VCAL_COMPONENT_PROPERTY_END:
3156 cursor = __crlf(cursor);
3161 cursor = __crlf(cursor);
3164 if (true == exit_loop) break;
3169 static char* __work_component_vfreebusy(char *cursor, calendar_record_h record, struct user_data *ud)
3171 RETV_IF(NULL == cursor, NULL);
3173 DBG("Not supported vfreebusy");
3175 bool exit_loop = false;
3178 cursor = __get_index(cursor, component_property, VCAL_COMPONENT_PROPERTY_MAX, &index);
3180 case VCAL_COMPONENT_PROPERTY_END:
3182 cursor = __crlf(cursor);
3187 cursor = __crlf(cursor);
3190 if (true == exit_loop) break;
3195 static void __work_component_property_vtimezone_standard_dtstart(char *value, calendar_record_h record, struct user_data *ud)
3199 RET_IF(NULL == value);
3200 RET_IF('\0' == *value);
3201 RET_IF(NULL == record);
3204 int y = 0, m = 0, d = 0;
3205 int h = 0, n = 0, s = 0;
3206 sscanf(value +1, CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSS, &y, &m, &d, &h, &n, &s);
3207 ret = cal_record_set_int(record, _calendar_timezone.standard_start_month, m);
3208 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
3209 ret = cal_record_set_int(record, _calendar_timezone.standard_start_hour, h);
3210 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
3212 long long int t = cal_time_convert_lli(value +1);
3213 int nth = 0, wday = 0;
3214 cal_time_get_nth_wday(t, &nth, &wday);
3215 ret = cal_record_set_int(record, _calendar_timezone.standard_start_position_of_week, nth);
3216 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
3217 ret = cal_record_set_int(record, _calendar_timezone.standard_start_day, wday);
3218 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
3220 static void __work_component_property_vtimezone_standard_tzoffsetfrom(char *value, calendar_record_h record, struct user_data *ud)
3224 static void __work_component_property_vtimezone_standard_tzoffsetto(char *value, calendar_record_h record, struct user_data *ud)
3228 RET_IF(NULL == value);
3229 RET_IF('\0' == *value);
3230 RET_IF(NULL == record);
3234 sscanf(value, "%c%02d%02d", &c, &h, &m);
3236 int offset = h * 60 + m;
3237 if ('-' == c) offset *= -1;
3240 ret = cal_record_set_int(record, _calendar_timezone.standard_bias, offset);
3241 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
3242 ret = cal_record_set_int(record, _calendar_timezone.tz_offset_from_gmt, offset);
3243 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
3245 if (NULL == ud->timezone_tzid || '\0' == *ud->timezone_tzid) {
3246 char buf[CAL_STR_SHORT_LEN32] = {0};
3247 snprintf(buf, sizeof(buf), "Etc/GMT%c%d", offset < 0 ? '+' : '-', h);
3248 ud->timezone_tzid = strdup(buf);
3249 __adjust_tzid(ud->timezone_tzid);
3250 DBG("timezone_tzid[%s]", ud->timezone_tzid);
3253 static void __work_component_property_vtimezone_standard_tzname(char *value, calendar_record_h record, struct user_data *ud)
3255 RET_IF(NULL == value);
3256 RET_IF('\0' == *value);
3257 RET_IF(NULL == record);
3259 int ret = cal_record_set_str(record, _calendar_timezone.standard_name, value);
3260 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
3262 static void __work_component_property_vtimezone_standard_rdate(char *value, calendar_record_h record, struct user_data *ud)
3266 static char* __work_component_vtimezone_standard(char *cursor, calendar_record_h record, struct user_data *ud)
3270 RETV_IF(NULL == cursor, __crlf(cursor));
3271 RETV_IF('\0' == *cursor, __crlf(cursor));
3272 RETV_IF(NULL == record, __crlf(cursor));
3274 cursor = __crlf(cursor);
3275 bool exit_loop = false;
3278 cursor = __get_index(cursor, component_property_vtimezone, VCAL_COMPONENT_PROPERTY_VTIMEZONE_MAX, &index);
3282 case VCAL_COMPONENT_PROPERTY_VTIMEZONE_DTSTART:
3283 cursor = __get_value(cursor, &value);
3284 __work_component_property_vtimezone_standard_dtstart(value +1, record, ud);
3288 case VCAL_COMPONENT_PROPERTY_VTIMEZONE_TZOFFSETFROM:
3289 cursor = __get_value(cursor, &value);
3290 __work_component_property_vtimezone_standard_tzoffsetfrom(value, record, ud);
3294 case VCAL_COMPONENT_PROPERTY_VTIMEZONE_TZOFFSETTO:
3295 cursor = __get_value(cursor, &value);
3296 __work_component_property_vtimezone_standard_tzoffsetto(value +1, record, ud);
3300 case VCAL_COMPONENT_PROPERTY_VTIMEZONE_TZNAME:
3301 cursor = __get_value(cursor, &value);
3302 __work_component_property_vtimezone_standard_tzname(value +1, record, ud);
3306 case VCAL_COMPONENT_PROPERTY_VTIMEZONE_RDATE:
3307 cursor = __get_value(cursor, &value);
3308 __work_component_property_vtimezone_standard_rdate(value, record, ud);
3312 case VCAL_COMPONENT_PROPERTY_VTIMEZONE_END:
3313 cursor = __crlf(cursor);
3317 cursor = __crlf(cursor);
3320 if (true == exit_loop) break;
3325 static void __work_component_property_vtimezone_daylight_dtstart(char *value, calendar_record_h record, struct user_data *ud)
3327 RET_IF(NULL == value);
3328 RET_IF('\0' == *value);
3329 RET_IF(NULL == record);
3332 int y = 0, m = 0, d = 0;
3333 int h = 0, n = 0, s = 0;
3334 sscanf(value +1, CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSS, &y, &m, &d, &h, &n, &s);
3335 ret = cal_record_set_int(record, _calendar_timezone.day_light_start_month, m);
3336 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
3337 ret = cal_record_set_int(record, _calendar_timezone.day_light_start_hour, h);
3338 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
3340 long long int t = cal_time_convert_lli(value +1);
3341 int nth = 0, wday = 0;
3342 cal_time_get_nth_wday(t, &nth, &wday);
3343 ret = cal_record_set_int(record, _calendar_timezone.day_light_start_position_of_week, nth);
3344 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
3345 ret = cal_record_set_int(record, _calendar_timezone.day_light_start_day, wday);
3346 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
3348 static void __work_component_property_vtimezone_daylight_tzoffsetfrom(char *value, calendar_record_h record, struct user_data *ud)
3352 static void __work_component_property_vtimezone_daylight_tzoffsetto(char *value, calendar_record_h record, struct user_data *ud)
3354 RET_IF(NULL == value);
3355 RET_IF('\0' == *value);
3356 RET_IF(NULL == record);
3360 sscanf(value, "%c%02d%02d", &c, &h, &m);
3362 int offset = h * 60 + m;
3363 if ('-' == c) offset *= -1;
3365 int ret = cal_record_set_int(record, _calendar_timezone.day_light_bias, offset);
3366 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_int() Fail(%d)", ret);
3368 static void __work_component_property_vtimezone_daylight_tzname(char *value, calendar_record_h record, struct user_data *ud)
3370 RET_IF(NULL == value);
3371 RET_IF('\0' == *value);
3372 RET_IF(NULL == record);
3374 int ret = cal_record_set_str(record, _calendar_timezone.day_light_name, value);
3375 WARN_IF(CALENDAR_ERROR_NONE != ret, "cal_record_set_str() Fail(%d)", ret);
3377 static void __work_component_property_vtimezone_daylight_rdate(char *value, calendar_record_h record, struct user_data *ud)
3381 static char* __work_component_vtimezone_daylight(char *cursor, calendar_record_h record, struct user_data *ud)
3383 RETV_IF(NULL == cursor, __crlf(cursor));
3384 RETV_IF('\0' == *cursor, __crlf(cursor));
3385 RETV_IF(NULL == record, __crlf(cursor));
3387 cursor = __crlf(cursor);
3388 bool exit_loop = false;
3391 cursor = __get_index(cursor, component_property_vtimezone, VCAL_COMPONENT_PROPERTY_VTIMEZONE_MAX, &index);
3395 case VCAL_COMPONENT_PROPERTY_VTIMEZONE_DTSTART:
3396 cursor = __get_value(cursor, &value);
3397 __work_component_property_vtimezone_daylight_dtstart(value +1, record, ud);
3401 case VCAL_COMPONENT_PROPERTY_VTIMEZONE_TZOFFSETFROM:
3402 cursor = __get_value(cursor, &value);
3403 __work_component_property_vtimezone_daylight_tzoffsetfrom(value, record, ud);
3407 case VCAL_COMPONENT_PROPERTY_VTIMEZONE_TZOFFSETTO:
3408 cursor = __get_value(cursor, &value);
3409 __work_component_property_vtimezone_daylight_tzoffsetto(value +1, record, ud);
3413 case VCAL_COMPONENT_PROPERTY_VTIMEZONE_TZNAME:
3414 cursor = __get_value(cursor, &value);
3415 __work_component_property_vtimezone_daylight_tzname(value +1, record, ud);
3419 case VCAL_COMPONENT_PROPERTY_VTIMEZONE_RDATE:
3420 cursor = __get_value(cursor, &value);
3421 __work_component_property_vtimezone_daylight_rdate(value, record, ud);
3425 case VCAL_COMPONENT_PROPERTY_VTIMEZONE_END:
3426 cursor = __crlf(cursor);
3430 cursor = __crlf(cursor);
3433 if (true == exit_loop) break;
3438 static char* __work_component_vtimezone(char *cursor, calendar_record_h record, struct user_data *ud)
3442 RETV_IF(NULL == cursor, NULL);
3443 RETV_IF(NULL == record, NULL);
3445 __init_component_property_vtimezone();
3448 if (CAL_STRING_EQUAL == strncmp(cursor, "TZID:", strlen("TZID:"))) {
3449 char *p = cursor + strlen("TZID");
3450 if (NULL == p || '\0' == *p) {
3451 /* LCOV_EXCL_START */
3452 ERR("Inavlid tzid");
3453 cursor = __crlf(cursor);
3455 /* LCOV_EXCL_STOP */
3457 if (ud->timezone_tzid) {
3458 free(ud->timezone_tzid);
3459 ud->timezone_tzid = NULL;
3462 cursor = __get_value(p, &value);
3463 __adjust_tzid(value);
3464 DBG("tzid[%s]", value +1);
3465 if (true == cal_time_is_available_tzid(value +1))
3466 ud->timezone_tzid = strdup(value +1);
3468 DBG("Invalid tzid string[%s]", value +1);
3471 } else if (CAL_STRING_EQUAL == strncmp(cursor, "BEGIN:STANDARD", strlen("BEGIN:STANDARD"))) {
3472 cursor = __work_component_vtimezone_standard(cursor, record, ud);
3473 } else if (CAL_STRING_EQUAL == strncmp(cursor, "BEGIN:DAYLIGHT", strlen("BEGIN:DAYLIGHT"))) {
3474 cursor = __work_component_vtimezone_daylight(cursor, record, ud);
3475 } else if (CAL_STRING_EQUAL == strncmp(cursor, "END", strlen("END"))) {
3476 cursor = __crlf(cursor);
3479 DBG("Unable to parse");
3480 __print_cursor(cursor, __LINE__);
3481 cursor = __crlf(cursor);
3487 static char* __work_property_begin(char *cursor, calendar_record_h *out_record, struct user_data *ud)
3490 RETV_IF(NULL == cursor, NULL);
3491 RETV_IF('\0' == *cursor, NULL);
3492 RETV_IF(NULL == out_record, NULL);
3493 RETV_IF(NULL == ud, NULL);
3497 cursor = __get_index(cursor +1, vcal_component, VCAL_COMPONENT_MAX, &index);
3498 cursor = __crlf(cursor);
3499 calendar_record_h record = NULL;
3501 case VCAL_COMPONENT_VEVENT:
3502 ret = calendar_record_create(_calendar_event._uri, &record);
3503 RETVM_IF(CALENDAR_ERROR_NONE != ret, NULL, "calendar_record_create() Fail(%d)", ret);
3504 ud->type = CALENDAR_BOOK_TYPE_EVENT;
3505 ud->has_rrule = __check_has_rrule(cursor);
3506 cursor = __work_component_vevent(cursor, record, ud);
3509 case VCAL_COMPONENT_VTODO:
3510 ret = calendar_record_create(_calendar_todo._uri, &record);
3511 RETVM_IF(CALENDAR_ERROR_NONE != ret, NULL, "calendar_record_create() Fail(%d)", ret);
3512 ud->type = CALENDAR_BOOK_TYPE_TODO;
3513 ud->has_rrule = __check_has_rrule(cursor);
3514 cursor = __work_component_vevent(cursor, record, ud); /* same as event */
3517 case VCAL_COMPONENT_VJOURNAL:
3518 cursor = __work_component_vjournal(cursor, record, ud);
3521 case VCAL_COMPONENT_VFREEBUSY:
3522 cursor = __work_component_vfreebusy(cursor, record, ud);
3525 case VCAL_COMPONENT_VTIMEZONE:
3526 ret = calendar_record_create(_calendar_timezone._uri, &record);
3527 RETVM_IF(CALENDAR_ERROR_NONE != ret, NULL, "calendar_record_create() Fail(%d)", ret);
3528 cursor = __work_component_vtimezone(cursor, record, ud);
3531 *out_record = record;
3535 int cal_vcalendar_parse_vcalendar_object(char *stream, calendar_list_h list, vcalendar_foreach_s *foreach_data)
3539 RETV_IF(NULL == stream, CALENDAR_ERROR_INVALID_PARAMETER);
3540 RETV_IF(NULL == list, CALENDAR_ERROR_INVALID_PARAMETER);
3544 __init_component_property();
3545 __unfolding(stream);
3547 struct user_data *ud = calloc(1, sizeof(struct user_data));
3548 RETVM_IF(NULL == ud, CALENDAR_ERROR_OUT_OF_MEMORY, "calloc() Fail");
3549 ud->version = VCAL_VER_2; /* default */
3551 calendar_record_h record = NULL;
3554 bool exit_loop = false;
3555 char *cursor = (char *)stream;
3559 cursor = __get_index(cursor, vcal_property, VCAL_PROPERTY_MAX, &index);
3561 case VCAL_PROPERTY_VERSION:
3562 cursor = __get_value(cursor, &value);
3563 __get_version(value, &ud->version);
3568 case VCAL_PROPERTY_TZ:
3569 if (ud->timezone_tzid)
3571 cursor = __get_value(cursor, &value);
3572 __get_tz(value + 1, &ud->timezone_tzid);
3573 __adjust_tzid(ud->timezone_tzid);
3574 DBG("timezone_tzid[%s]", ud->timezone_tzid);
3579 case VCAL_PROPERTY_BEGIN: /* BEGIN:VEVENT */
3580 cursor = __work_property_begin(cursor, &record, ud);
3581 calendar_list_add(list, record);
3584 foreach_data->ret = foreach_data->callback(record, foreach_data->user_data);
3585 if (false == foreach_data->ret)
3590 case VCAL_PROPERTY_END: /* END:VCALENDAR */
3591 DBG("exit VCALENDAR");
3592 /* fini vcalendar */
3597 DBG("skip invalid property, index(%d)", index);
3598 cursor = __crlf(cursor);
3601 if (true == exit_loop)
3605 DBG("count(%d)", count);
3608 free(ud->timezone_tzid);
3611 return CALENDAR_ERROR_NONE;