Resolved Native API Reference issues for calendar-service
[platform/core/pim/calendar-service.git] / common / cal_vcalendar_make.c
1 /*
2  * Calendar Service
3  *
4  * Copyright (c) 2012 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <stdlib.h>
21 #include <sys/types.h>
22 #include <unistd.h>
23
24 #include "calendar_list.h"
25 #include "calendar_db.h"
26
27 #include "cal_internal.h"
28 #include "cal_typedef.h"
29 #include "cal_record.h"
30 #include "cal_view.h"
31 #include "cal_time.h"
32
33 #include "cal_vcalendar.h"
34 #include "cal_vcalendar_make.h"
35 #include "cal_utils.h"
36
37 enum {
38         VCAL_VER_1 = 1,
39         VCAL_VER_2 = 2,
40 };
41
42 typedef enum {
43         EVENT_ATTENDEE_REQ_PARTICIPANT_ROLE = 0,
44         EVENT_ATTENDEE_OPT_PARTICIPANT_ROLE,
45         EVENT_ATTENDEE_NON_PARTICIPANT_ROLE,
46         EVENT_ATTENDEE_CHAIR_ROLE,
47 } cal_event_attendee_role_type_t;
48
49 typedef enum {
50         EVENT_ATTENDEE_NEEDS_ACTION_AT_STATUS = 0,
51         EVENT_ATTENDEE_ACCEPTED_AT_STATUS,
52         EVENT_ATTENDEE_DECLINED_AT_STATUS,
53         EVENT_ATTENDEE_TENTATIVE_AT_STATUS,
54         EVENT_ATTENDEE_DELEGATED_AT_STATUS,
55         EVENT_ATTENDEE_COMPLETED_AT_STATUS,
56         EVENT_ATTENDEE_IN_PROCESS_AT_STATUS
57 } cal_event_attendee_status_type_t;
58
59
60 static const char *_att_role[] = {
61         [EVENT_ATTENDEE_REQ_PARTICIPANT_ROLE] = "REQ-PARTICIPANT",
62         [EVENT_ATTENDEE_OPT_PARTICIPANT_ROLE] = "OPT-PARTICIPANT",
63         [EVENT_ATTENDEE_NON_PARTICIPANT_ROLE] = "NON-PARTICIPANT",
64         [EVENT_ATTENDEE_CHAIR_ROLE] = "CHAIR",
65 };
66
67 static const char *_att_st[] = {
68         [EVENT_ATTENDEE_NEEDS_ACTION_AT_STATUS] = "NEEDS-ACTION",
69         [EVENT_ATTENDEE_ACCEPTED_AT_STATUS] = "ACCEPTED",
70         [EVENT_ATTENDEE_DECLINED_AT_STATUS] = "DECLINED",
71         [EVENT_ATTENDEE_TENTATIVE_AT_STATUS] = "TENTATIVE",
72         [EVENT_ATTENDEE_DELEGATED_AT_STATUS] = "DELEGATED",
73         [EVENT_ATTENDEE_COMPLETED_AT_STATUS] = "COMPLETED",
74         [EVENT_ATTENDEE_IN_PROCESS_AT_STATUS] = "IN-PROCESS",
75 };
76
77 #define _strlen(s) (((s) && *(s)) ? strlen(s) : 0)
78
79 static inline int _cal_vcalendar_make_alloc(cal_make_s *b, int n)
80 {
81         b->data = realloc(b->data, b->size + n);
82
83         RETVM_IF(!b->data, CALENDAR_ERROR_OUT_OF_MEMORY, "realloc() Fail");
84         b->size += n;
85
86         return CALENDAR_ERROR_NONE;
87 }
88
89 cal_make_s *cal_vcalendar_make_new(void)
90 {
91         cal_make_s *b;
92
93         b = calloc(1, sizeof(cal_make_s));
94         if (!b)
95                 return NULL;
96
97         b->data = calloc(1, sizeof(char));
98         if (!b->data) {
99                 free(b);
100                 return NULL;
101         }
102
103         *b->data = '\0';
104         b->size = 1;
105
106         return b;
107 }
108
109 static inline int _cal_vcalendar_make_folding(cal_make_s *b)
110 {
111         int ret;
112         ret = _cal_vcalendar_make_alloc(b, _strlen(b->lbuf) + 3);
113         RETV_IF(CALENDAR_ERROR_NONE != ret, ret);
114
115         strncat(b->data, b->lbuf, b->size - _strlen(b->data) - 1);
116         strncat(b->data, "\r\n ", b->size - _strlen(b->data) - 1);
117         *b->lbuf = '\0';
118         return CALENDAR_ERROR_NONE;
119 }
120
121 static inline int _cal_vcalendar_make_set_str(cal_make_s *b, const char *s)
122 {
123         int remain_lbuf;
124         int remain_str;
125         int k;
126         int ret;
127
128         remain_lbuf = sizeof(b->lbuf) - _strlen(b->lbuf);
129         remain_str = _strlen(s);
130
131         k = 0;
132         while (remain_lbuf - 1 < remain_str) {
133                 strncat(b->lbuf, s + k, remain_lbuf - 1);
134                 k += remain_lbuf - 1;
135                 remain_str -= remain_lbuf - 1;
136                 ret = _cal_vcalendar_make_folding(b);
137                 RETV_IF(CALENDAR_ERROR_NONE != ret, ret);
138                 remain_lbuf = sizeof(b->lbuf);
139         }
140
141         strncat(b->lbuf, s + k, remain_lbuf - 1);
142         return CALENDAR_ERROR_NONE;
143 }
144
145 static inline int _cal_vcalendar_make_flush(cal_make_s *b)
146 {
147         int ret;
148         ret = _cal_vcalendar_make_alloc(b, _strlen(b->lbuf) + 2);
149         RETV_IF(CALENDAR_ERROR_NONE != ret, ret);
150
151         strncat(b->data, b->lbuf, b->size - _strlen(b->data) - 1);
152         strncat(b->data, "\r\n", b->size - _strlen(b->data) - 1);
153         *b->lbuf = '\0';
154         return CALENDAR_ERROR_NONE;
155 }
156
157 static int _cal_vcalendar_make_printf(cal_make_s *b, const char *s1, const char *s2)
158 {
159         int ret;
160
161         if (s1) {
162                 ret = _cal_vcalendar_make_set_str(b, s1);
163                 RETV_IF(CALENDAR_ERROR_NONE != ret, ret);
164         }
165
166         if (s2) {
167                 ret = _cal_vcalendar_make_set_str(b, s2);
168                 RETV_IF(CALENDAR_ERROR_NONE != ret, ret);
169         }
170
171         return _cal_vcalendar_make_flush(b);
172 }
173
174 char* cal_vcalendar_make_get_data(cal_make_s *b)
175 {
176         if (!b || !b->data)
177                 return NULL;
178         return cal_strdup(b->data);
179 }
180
181 void cal_vcalendar_make_free(cal_make_s **b)
182 {
183         if (!b || !*b)
184                 return;
185
186         if ((*b)->data)
187                 free((*b)->data);
188
189         free(*b);
190         b = NULL;
191 }
192
193 static int  _cal_vcalendar_make_time(cal_make_s *b, char *tzid, calendar_time_s *t, const char *prop)
194 {
195         RETV_IF(NULL == b, CALENDAR_ERROR_INVALID_PARAMETER);
196         RETV_IF(NULL == t, CALENDAR_ERROR_INVALID_PARAMETER);
197
198         if (CALENDAR_TIME_UTIME == t->type && CALENDAR_TODO_NO_START_DATE == t->time.utime) {
199                 DBG("No start date");
200                 return CALENDAR_ERROR_NONE;
201         }
202
203         char buf[CAL_STR_MIDDLE_LEN] = {0};
204         int y = 0, m = 0, d = 0;
205         int h = 0, n = 0, s = 0;
206         switch (b->version) {
207         case VCAL_VER_1:
208                 switch (t->type) {
209                 case CALENDAR_TIME_UTIME:
210                         cal_time_get_local_datetime(NULL, t->time.utime, &y, &m, &d, &h, &n, &s);
211                         snprintf(buf, sizeof(buf), ":"CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSSZ, y, m, d, h, n, s);
212                         break;
213                 case CALENDAR_TIME_LOCALTIME:
214                         snprintf(buf, sizeof(buf), ":"CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSS,
215                                         t->time.date.year, t->time.date.month, t->time.date.mday,
216                                         t->time.date.hour, t->time.date.minute, t->time.date.second);
217                         break;
218                 }
219                 break;
220         case VCAL_VER_2:
221                 switch (t->type) {
222                 case CALENDAR_TIME_UTIME:
223                         if (NULL == tzid || '\0' == *tzid) {
224                                 cal_time_get_local_datetime(NULL, t->time.utime, &y, &m, &d, &h, &n, &s);
225                                 snprintf(buf, sizeof(buf), ":"CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSSZ, y, m, d, h, n, s);
226                         } else {
227                                 cal_time_get_local_datetime(tzid, t->time.utime, &y, &m, &d, &h, &n, &s);
228                                 snprintf(buf, sizeof(buf), ";TZID=%s:"CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSS, tzid, y, m, d, h, n, s);
229                         }
230                         break;
231                 case CALENDAR_TIME_LOCALTIME:
232                         snprintf(buf, sizeof(buf), ":"CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSS,
233                                         t->time.date.year, t->time.date.month, t->time.date.mday,
234                                         t->time.date.hour, t->time.date.minute, t->time.date.second);
235                         break;
236                 }
237                 break;
238         }
239         _cal_vcalendar_make_printf(b, prop, buf);
240         return CALENDAR_ERROR_NONE;
241 }
242
243 static void __encode_escaped_char(char *p, char **r)
244 {
245         RET_IF(NULL == p);
246         RET_IF('\0' == *p);
247
248         int len = strlen(p) * 2;
249         char *q = calloc(len, sizeof(char));
250         RETM_IF(NULL == q, "calloc() Fail");
251         *r = q;
252
253         DBG("Before [%s]", p);
254         while ('\0' != *p) {
255                 if ('\r' == *p && '\n' == *(p + 1))
256                         break;
257                 switch (*p) {
258                 case '\n':
259                         *q = '\\';
260                         q++;
261                         *q = 'n';
262                         break;
263                 case ';':
264                         *q = '\\';
265                         q++;
266                         *q = ';';
267                         break;
268                 case ',':
269                         *q = '\\';
270                         q++;
271                         *q = ',';
272                         break;
273                 case '\\':
274                         *q = '\\';
275                         q++;
276                         *q = '\\';
277                         break;
278                 default:
279                         *q = *p;
280                         break;
281                 }
282                 q++;
283                 p++;
284         }
285         *q = '\0';
286         DBG("After [%s]", *r);
287 }
288
289 static const char* vl_tick(calendar_alarm_time_unit_type_e unit, int tick)
290 {
291         static char buf[CAL_STR_SHORT_LEN32] = {0};
292
293         int i = 0;
294         if (0 < tick) {
295                 *buf = '-';
296                 i++;
297
298         } else {
299                 tick = -tick;
300         }
301
302         switch (unit) {
303         case CALENDAR_ALARM_TIME_UNIT_WEEK:
304                 snprintf(buf + i, sizeof(buf) - i, "P%dW", tick);
305                 break;
306         case CALENDAR_ALARM_TIME_UNIT_DAY:
307                 snprintf(buf + i, sizeof(buf) - i, "P%dD", tick);
308                 break;
309         case CALENDAR_ALARM_TIME_UNIT_HOUR:
310                 snprintf(buf + i, sizeof(buf) - i, "PT%dH", tick);
311                 break;
312         case CALENDAR_ALARM_TIME_UNIT_MINUTE:
313                 snprintf(buf + i, sizeof(buf) - i, "PT%dM", tick);
314                 break;
315         default:
316                 buf[0] = '\0';
317         }
318
319         return buf;
320 }
321
322 int _cal_vcalendar_make_audio(cal_make_s *b, calendar_record_h alarm)
323 {
324         RETV_IF(NULL == b, CALENDAR_ERROR_INVALID_PARAMETER);
325         RETV_IF(NULL == alarm, CALENDAR_ERROR_INVALID_PARAMETER);
326
327         int ret = 0;
328         int unit = 0;
329         ret = calendar_record_get_int(alarm, _calendar_alarm.tick_unit, &unit);
330         RETVM_IF(CALENDAR_ERROR_NONE != ret, ret, "failed to get unit");
331
332         if (CALENDAR_ALARM_TIME_UNIT_SPECIFIC == unit) {
333                 calendar_time_s at = {0};
334                 ret = calendar_record_get_caltime(alarm, _calendar_alarm.alarm_time, &at);
335                 WARN_IF(CALENDAR_ERROR_NONE != ret, "failed to get alarm_time");
336
337                 if (CALENDAR_TIME_UTIME == at.type) {
338                         char *datetime = cal_time_convert_ltos(NULL, at.time.utime, 0);
339                         _cal_vcalendar_make_printf(b, "TRIGGER;VALUE=DATE-TIME:", datetime);
340                         free(datetime);
341
342                 } else {
343                         char datetime[CAL_STR_SHORT_LEN32] = {0};
344                         snprintf(datetime, sizeof(datetime), CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSS,
345                                         at.time.date.year, at.time.date.month, at.time.date.mday,
346                                         at.time.date.hour, at.time.date.minute, at.time.date.second);
347                         _cal_vcalendar_make_printf(b, "TRIGGER;VALUE=DATE-TIME:", datetime);
348                 }
349
350         } else {
351                 int tick = 0;
352                 ret = calendar_record_get_int(alarm, _calendar_alarm.tick, &tick);
353                 WARN_IF(CALENDAR_ERROR_NONE != ret, "failed to get tick");
354
355                 _cal_vcalendar_make_printf(b, "TRIGGER:", vl_tick(unit, tick));
356         }
357         return CALENDAR_ERROR_NONE;
358 }
359
360 /* alarm in ver1.0
361  * aalarm: runTime, snoozeTime, repeatCount, audioContent (AALARM;TYPE=WAVE;VALUE=URL:19960415T235959; ; ; file:///mmedia/taps.wav)
362  * dalarm: runTime, snoozeTime, repeatCount, displayString
363  * malarm: runTime, snoozeTime, repeatCount, addressString, noteString
364  * palarm: runTime, snoozeTime, repeatCount, procedureName
365  */
366 static void _cal_vcalendar_make_aalarm(cal_make_s *b, calendar_record_h record, calendar_record_h alarm)
367 {
368         RETM_IF(NULL == b, "b is NULL");
369         RETM_IF(NULL == record, "record is NULL");
370         RETM_IF(NULL == alarm, "alarm is NULL");
371
372         int ret = CALENDAR_ERROR_NONE;
373
374         /* set alarm */
375         int unit = 0;
376         ret = calendar_record_get_int(alarm, _calendar_alarm.tick_unit, &unit);
377         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
378
379         char datetime[CAL_STR_SHORT_LEN32] = {0};
380         if (CALENDAR_ALARM_TIME_UNIT_SPECIFIC == unit) {
381                 calendar_time_s at = {0};
382                 ret = calendar_record_get_caltime(alarm, _calendar_alarm.alarm_time, &at);
383                 WARN_IF(CALENDAR_ERROR_NONE != ret, "failed to get alarm_time");
384
385                 if (CALENDAR_TIME_UTIME == at.type) {
386                         char *buf = cal_time_convert_ltos(NULL, at.time.utime, 0);
387                         snprintf(datetime, sizeof(datetime), "%s;;;", buf);
388                         free(buf);
389
390                 } else {
391                         snprintf(datetime, sizeof(datetime), CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSS";;;",
392                                         at.time.date.year, at.time.date.month, at.time.date.mday,
393                                         at.time.date.hour, at.time.date.minute, at.time.date.second);
394                 }
395
396         } else {
397                 /* has tick, unit */
398                 int tick = 0;
399                 ret = calendar_record_get_int(alarm, _calendar_alarm.tick, &tick);
400                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
401
402                 char *uri = NULL;
403                 ret = calendar_record_get_uri_p(record, &uri);
404                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_uri_p() failed(%d)", ret);
405
406                 calendar_time_s st = {0};
407                 if (CAL_STRING_EQUAL == strncmp(uri, _calendar_event._uri, strlen(_calendar_event._uri))) {
408                         ret = calendar_record_get_caltime(record, _calendar_event.start_time, &st);
409                         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_caltime() Fail(%d)", ret);
410
411                 } else if (CAL_STRING_EQUAL == strncmp(uri, _calendar_todo._uri, strlen(_calendar_todo._uri))) {
412                         ret = calendar_record_get_caltime(record, _calendar_todo.due_time, &st);
413                         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_caltime() Fail(%d)", ret);
414                 }
415
416                 if (CALENDAR_TIME_UTIME == st.type) {
417                         long long int lli = st.time.utime - (tick * unit);
418                         char *buf = cal_time_convert_ltos(NULL, lli, 0);
419                         snprintf(datetime, sizeof(datetime), "%s;;;", buf);
420                         free(buf);
421                         DBG("aalarm: [%s] = (%lld) - (tick(%d) * unit(%d))", datetime, st.time.utime, tick, unit);
422
423                 } else {
424                         struct tm tm = {0};
425                         tm.tm_year = st.time.date.year - 1900;
426                         tm.tm_mon = st.time.date.month - 1;
427                         tm.tm_mday = st.time.date.mday;
428                         tm.tm_hour = st.time.date.hour;
429                         tm.tm_min = st.time.date.minute;
430                         tm.tm_sec = st.time.date.second;
431                         time_t tt = mktime(&tm);
432                         tt -= (tick * unit);
433                         localtime_r(&tt, &tm);
434
435                         snprintf(datetime, sizeof(datetime), CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSS,
436                                         tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
437                                         tm.tm_hour, tm.tm_min, tm.tm_sec);
438
439                         DBG("aalarm: [%s]", datetime);
440                 }
441         }
442         _cal_vcalendar_make_printf(b, "AALARM:", datetime);
443 }
444
445 static void _cal_vcalendar_make_alarm(cal_make_s *b, calendar_record_h alarm)
446 {
447         RET_IF(NULL == b);
448         RET_IF(NULL == alarm);
449
450         int ret;
451
452         /* TODO : No action type is defined */
453         ret = _cal_vcalendar_make_printf(b, "BEGIN:VALARM", NULL);
454         RETM_IF(CALENDAR_ERROR_NONE != ret, "_cal_vcalendar_make_printf() Fail(%d)", ret);
455
456         ret = _cal_vcalendar_make_audio(b, alarm);
457         RETM_IF(CALENDAR_ERROR_NONE != ret, "_cal_vcalendar_make_audio() Fail(%d)", ret);
458
459         int action = 0;
460         ret = calendar_record_get_int(alarm, _calendar_alarm.action, &action);
461         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
462         switch (action) {
463         default:
464         case CALENDAR_ALARM_ACTION_AUDIO:
465                 ret = _cal_vcalendar_make_printf(b, "ACTION:", "AUDIO");
466                 break;
467         case CALENDAR_ALARM_ACTION_DISPLAY:
468                 ret = _cal_vcalendar_make_printf(b, "ACTION:", "DISPLAY");
469                 break;
470         case CALENDAR_ALARM_ACTION_EMAIL:
471                 ret = _cal_vcalendar_make_printf(b, "ACTION:", "EMAIL");
472                 break;
473         }
474         RETM_IF(CALENDAR_ERROR_NONE != ret, "_cal_vcalendar_make_printf() Fail(%d)", ret);
475
476         char *summary = NULL;
477         ret = calendar_record_get_str_p(alarm, _calendar_alarm.summary, &summary);
478         if (summary && *summary) {
479                 ret = _cal_vcalendar_make_printf(b, "SUMMARY:", summary);
480                 RETM_IF(CALENDAR_ERROR_NONE != ret, "_cal_vcalendar_make_printf() Fail(%d)", ret);
481         }
482
483         char *description = NULL;
484         ret = calendar_record_get_str_p(alarm, _calendar_alarm.description, &description);
485         if (description && *description) {
486                 ret = _cal_vcalendar_make_printf(b, "DESCRIPTION:", description);
487                 RETM_IF(CALENDAR_ERROR_NONE != ret, "_cal_vcalendar_make_printf() Fail(%d)", ret);
488         }
489
490         _cal_vcalendar_make_printf(b, "END:VALARM", NULL);
491 }
492
493 int _cal_vcalendar_make_rrule_append_mday(char *buf, int buf_len, char *mday)
494 {
495         int ret = 0;
496
497         RETV_IF(NULL == buf, 0);
498         RETV_IF(NULL == mday, 0);
499
500         char **t = NULL;
501         t = g_strsplit_set(mday, " ,", -1);
502         if (!t) {
503                 /* LCOV_EXCL_START */
504                 ERR("g_strsplit_set() Fail");
505                 g_strfreev(t);
506                 return 0;
507                 /* LCOV_EXCL_STOP */
508         }
509         int len = strlen(buf);
510         int tlen = g_strv_length(t);
511         int i;
512         for (i = 0; i < tlen; i++) {
513                 if (*t[i] == '\0')
514                         continue;
515
516                 int num = atoi(t[i]);
517                 ret += snprintf(buf +len +ret, buf_len -len -ret, "%d%s",
518                                 num < 0 ? (-1 * num) : num, num < 0 ? "- " : " ");
519         }
520         g_strfreev(t);
521
522         return ret;
523 }
524
525 static void _cal_vcalendar_make_rrule_append_setpos(calendar_record_h record, char *buf, int buf_len)
526 {
527         RET_IF(NULL == buf);
528
529         int ret = CALENDAR_ERROR_NONE;
530         char *bysetpos = NULL;
531
532         ret = calendar_record_get_str_p(record, _calendar_event.bysetpos, &bysetpos);
533         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() failed(%d)", ret);
534
535         int blen = strlen(buf);
536         if (bysetpos && '\0' != bysetpos[0]) {
537                 /* in ver1.0, "3, 5, -4" -> "3+ 5+ 4-" */
538                 char **t = NULL;
539                 t = g_strsplit_set(bysetpos, " ,", -1);
540
541                 int len = g_strv_length(t);
542
543                 int i;
544                 for (i = 0; i < len; i++) {
545                         if (*t[i] == '\0') continue;
546
547                         int setpos = atoi(t[i]);
548                         DBG("%d", setpos);
549
550                         if (setpos == 0) {
551                                 DBG("Invalid setpos(0)");
552                                 continue;
553                         }
554                         blen += snprintf(buf +blen, buf_len -blen, "%d%s ", setpos * (setpos < 0 ? -1 : 1), setpos < 0 ? "-" : "+");
555                 }
556                 g_strfreev(t);
557         } else {
558                 /* in ver2.0, 3TH should be changed to setpos:3, byday:TH */
559                 char *byday = NULL;
560                 ret = calendar_record_get_str_p(record, _calendar_event.byday, &byday);
561                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
562                 if (NULL == byday || '\0' == byday[0]) {
563                         blen += snprintf(buf +blen, buf_len -blen, "%s", "1+ ");
564                         return;
565                 }
566
567                 int len = strlen(byday);
568
569                 bool is_working = true;
570                 bool is_extracted = false;
571                 int i = 0;
572                 int digit = 0;
573                 int sign = 0;
574                 while (i <= len) {
575                         /* extract -1, 1 from 1SU,-1SU */
576                         if ('1' <= byday[i] && byday[i] <= '9') {
577                                 is_working = false;
578                                 digit++;
579                         } else if ('+' == byday[i]) {
580                                 is_working = false;
581                                 sign = 1;
582                         } else if ('-' == byday[i]) {
583                                 is_working = false;
584                                 sign = -1;
585                         } else {
586                                 if (false == is_working) {
587                                         is_extracted = true;
588                                         is_working = true;
589                                         char num[CAL_STR_SHORT_LEN32] = {0};
590                                         snprintf(num, digit +1, "%s", byday +i -digit);
591                                         if (NULL == strstr(buf, num))
592                                                 blen += snprintf(buf +blen, buf_len -blen, "%s%c ", num, (-1 == sign) ? '-' : '+');
593
594                                         digit = 0;
595                                         sign = 0;
596                                 }
597                         }
598                         i++;
599                 }
600                 if (false == is_extracted) {
601                         blen += snprintf(buf +blen, buf_len -blen, "%s", "1+ ");
602                         return;
603                 }
604         }
605 }
606
607 /*
608  * 2WE 3FR in ver2.0 is not converted to ver1.0
609  * because three is no +2 WE +3 FR.
610  */
611 void _cal_vcalendar_make_rrule_append_text_wday(int rrule_type, char *buf, int buf_len, char *wday)
612 {
613         RET_IF(NULL == buf);
614
615         int i, j;
616         int length = 0;
617         char **t = NULL;
618         char *p = NULL;
619
620         int len = strlen(buf);
621         t = g_strsplit_set(wday, " ,", -1);
622         if (!t) {
623                 /* LCOV_EXCL_START */
624                 ERR("g_strsplit_set() Fail");
625                 g_strfreev(t);
626                 return;
627                 /* LCOV_EXCL_STOP */
628         }
629         length = g_strv_length(t);
630
631         for (i = 0; i < length; i++) {
632                 if (*t[i] == '\0')
633                         continue;
634
635                 p = t[i];
636                 /* del space */
637                 while (*p == ' ')
638                         p++;
639
640                 /* get number length */
641                 j = 0;
642                 while (p[j] == '+' || p[j] == '-' || ('1' <= p[j] && p[j] <= '9'))
643                         j++;
644
645                 /* already appended */
646                 if (strstr(buf, p +j))
647                         continue;
648
649                 len += snprintf(buf +len, buf_len -len, "%s ", p +j);
650         }
651         g_strfreev(t);
652
653         return;
654 }
655
656 void _cal_vcalendar_make_rrule_append_wkst(char *buf, int buf_len, calendar_record_h record)
657 {
658         const char wday[7][3] = {"SU", "MO", "TU", "WE", "TH", "FR", "SA"};
659         int wkst = 0;
660         calendar_record_get_int(record, _calendar_event.wkst, &wkst);
661         if (wkst < CALENDAR_SUNDAY || CALENDAR_SATURDAY < wkst)
662                 return;
663
664         DBG("wkst(%d) [%s]", wkst, wday[wkst - 1]);
665         int len = strlen(buf);
666         snprintf(buf +len, buf_len -len, "WKST=%s ", wday[wkst - 1]);
667 }
668
669 int _cal_vcalendar_make_rrule_append_wday(int rrule_type, char *buf, int buf_len, char *wday)
670 {
671         RETV_IF(NULL == buf, CALENDAR_ERROR_INVALID_PARAMETER);
672
673         int i, j;
674         int num = 0, num_past;
675         int length = 0;
676         char **t = NULL;
677         char *p = NULL;
678         char buf_temp[8] = {0};
679
680         RETV_IF(NULL == buf, CALENDAR_ERROR_INVALID_PARAMETER);
681         RETV_IF(NULL == wday, CALENDAR_ERROR_INVALID_PARAMETER);
682
683         int len = strlen(buf);
684
685         num_past = 0;
686         t = g_strsplit_set(wday, " ,", -1);
687         if (!t) {
688                 /* LCOV_EXCL_START */
689                 ERR("g_strsplit_set() Fail");
690                 g_strfreev(t);
691                 return CALENDAR_ERROR_OUT_OF_MEMORY;
692                 /* LCOV_EXCL_STOP */
693         }
694         length = g_strv_length(t);
695         DBG("len(%d)", length);
696
697         for (i = 0; i < length; i++) {
698                 if (*t[i] == '\0') continue;
699
700                 p = t[i];
701
702                 /* get number */
703                 j = 0;
704                 while (p[j] == '+' || p[j] == '-' || ('1' <= p[j] && p[j] <= '9'))
705                         j++;
706
707                 if (0 < j) {
708                         if (CALENDAR_RECURRENCE_WEEKLY == rrule_type) {
709                                 num_past = num;
710                         } else {
711                                 if (*p == '-') {
712                                         snprintf(buf_temp, j + 1, "%s", p + 1);
713                                         num = atoi(buf_temp);
714                                         if (0 == i) {
715                                                 num_past = num;
716                                                 len += snprintf(buf +len, buf_len -len, "%s- ", buf_temp);
717                                         }
718                                 } else {
719                                         snprintf(buf_temp, j + 1, "%s", p);
720                                         num = atoi(buf_temp);
721                                         if (0 == i) {
722                                                 num_past = num;
723                                                 len += snprintf(buf +len, buf_len -len, "%s+ ", buf_temp);
724                                         }
725                                 }
726                         }
727                         if (num_past == num)
728                                 len += snprintf(buf +len, buf_len -len, "%s ", p +j);
729                         else
730                                 ERR("Out of 1.0 spec");
731
732                         DBG("%d num(%d) val[%s]", i, num, p + j);
733                 } else {
734                         len += snprintf(buf +len, buf_len -len, "%s ", p);
735                 }
736                 DBG("[%s]", buf);
737         }
738         g_strfreev(t);
739
740         return CALENDAR_ERROR_NONE;
741 }
742
743 static void __make_begin(cal_make_s *b, calendar_record_h record)
744 {
745         RET_IF(NULL == b);
746         RET_IF(NULL == record);
747
748         int ret = 0;
749         switch (b->type) {
750         case CALENDAR_BOOK_TYPE_EVENT:
751                 ret = _cal_vcalendar_make_printf(b, "BEGIN:VEVENT", NULL);
752                 RETM_IF(CALENDAR_ERROR_NONE != ret, "_cal_vcalendar_make_printf() Fail(%d)", ret);
753                 break;
754         case CALENDAR_BOOK_TYPE_TODO:
755                 ret = _cal_vcalendar_make_printf(b, "BEGIN:VTODO", NULL);
756                 RETM_IF(CALENDAR_ERROR_NONE != ret, "_cal_vcalendar_make_printf() Fail(%d)", ret);
757                 break;
758         }
759 }
760
761 static void __make_dtstart(cal_make_s *b, calendar_record_h record)
762 {
763         RET_IF(NULL == b);
764         RET_IF(NULL == record);
765
766         int ret = 0;
767         char *tzid = NULL;
768         calendar_time_s ct = {0};
769         switch (b->type) {
770         case CALENDAR_BOOK_TYPE_EVENT:
771                 ret = calendar_record_get_str_p(record, _calendar_event.start_tzid, &tzid);
772                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
773                 ret = calendar_record_get_caltime(record, _calendar_event.start_time, &ct);
774                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_caltime() Fail(%d)", ret);
775                 break;
776         case CALENDAR_BOOK_TYPE_TODO:
777                 ret = calendar_record_get_str_p(record, _calendar_todo.start_tzid, &tzid);
778                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
779                 ret = calendar_record_get_caltime(record, _calendar_todo.start_time, &ct);
780                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_caltime() Fail(%d)", ret);
781                 break;
782         }
783         _cal_vcalendar_make_time(b, tzid, &ct, "DTSTART");
784 }
785
786 static void __make_dtend(cal_make_s *b, calendar_record_h record)
787 {
788         RET_IF(NULL == b);
789         RET_IF(NULL == record);
790
791         int ret = 0;
792         char *tzid = NULL;
793         calendar_time_s ct = {0};
794         switch (b->type) {
795         case CALENDAR_BOOK_TYPE_EVENT:
796                 ret = calendar_record_get_str_p(record, _calendar_event.end_tzid, &tzid);
797                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
798                 ret = calendar_record_get_caltime(record, _calendar_event.end_time, &ct);
799                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_caltime() Fail(%d)", ret);
800                 _cal_vcalendar_make_time(b, tzid, &ct, "DTEND");
801                 break;
802         case CALENDAR_BOOK_TYPE_TODO:
803                 ret = calendar_record_get_str_p(record, _calendar_todo.due_tzid, &tzid);
804                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
805                 ret = calendar_record_get_caltime(record, _calendar_todo.due_time, &ct);
806                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_caltime() Fail(%d)", ret);
807                 _cal_vcalendar_make_time(b, tzid, &ct, "DUE");
808                 break;
809         }
810 }
811
812 static void __make_sensitivity(cal_make_s *b, calendar_record_h record)
813 {
814         RET_IF(NULL == b);
815         RET_IF(NULL == record);
816
817         int ret = 0;
818         int value = 0;
819         switch (b->type) {
820         case CALENDAR_BOOK_TYPE_EVENT:
821                 ret = calendar_record_get_int(record, _calendar_event.sensitivity, &value);
822                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
823                 break;
824         case CALENDAR_BOOK_TYPE_TODO:
825                 ret = calendar_record_get_int(record, _calendar_todo.sensitivity, &value);
826                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
827                 break;
828         }
829         char *sensitivity = NULL;
830         switch (value) {
831         case CALENDAR_SENSITIVITY_PUBLIC:
832                 sensitivity = "PUBLIC";
833                 break;
834         case CALENDAR_SENSITIVITY_PRIVATE:
835                 sensitivity = "PRIVATE";
836                 break;
837         case CALENDAR_SENSITIVITY_CONFIDENTIAL:
838                 sensitivity = "CONFIDENTIAL";
839                 break;
840         default:
841                 /* LCOV_EXCL_START */
842                 ERR("Invalid sensitivity(%d)", value);
843                 return;
844                 /* LCOV_EXCL_STOP */
845         }
846         _cal_vcalendar_make_printf(b, "CLASS:", sensitivity);
847 }
848
849 int _cal_vcalendar_make_rrule_append_until(char *buf, int buf_len, calendar_record_h record)
850 {
851         int ret;
852         int range_type = 0;
853         int count;
854         char *until_str = NULL;
855         calendar_time_s caltime;
856
857         ret = calendar_record_get_int(record, _calendar_event.range_type, &range_type);
858         if (CALENDAR_ERROR_NONE != ret) {
859                 /* LCOV_EXCL_START */
860                 ERR("calendar_record_get_int() Fail");
861                 return ret;
862                 /* LCOV_EXCL_STOP */
863         }
864
865         int len = strlen(buf);
866         switch (range_type) {
867         case CALENDAR_RANGE_COUNT:
868                 ret = calendar_record_get_int(record, _calendar_event.count, &count);
869                 if (CALENDAR_ERROR_NONE != ret) {
870                         /* LCOV_EXCL_START */
871                         ERR("calendar_record_get_int() Fail");
872                         return ret;
873                         /* LCOV_EXCL_STOP */
874                 }
875                 snprintf(buf +len, buf_len -len, "#%d", count);
876                 break;
877
878         case CALENDAR_RANGE_UNTIL:
879                 memset(&caltime, 0x0, sizeof(calendar_time_s));
880
881                 ret = calendar_record_get_caltime(record, _calendar_event.until_time, &caltime);
882                 if (CALENDAR_ERROR_NONE != ret) {
883                         /* LCOV_EXCL_START */
884                         ERR("calendar_record_get_caltime() Fail");
885                         return ret;
886                         /* LCOV_EXCL_STOP */
887                 }
888                 switch (caltime.type) {
889                 case CALENDAR_TIME_UTIME:
890                         until_str = cal_time_convert_ltos(NULL, caltime.time.utime, 0);
891                         snprintf(buf +len, buf_len -len, "%s", until_str);
892                         CAL_FREE(until_str);
893                         break;
894
895                 case CALENDAR_TIME_LOCALTIME:
896                         snprintf(buf +len, buf_len -len, CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSS,
897                                         caltime.time.date.year, caltime.time.date.month, caltime.time.date.mday,
898                                         caltime.time.date.hour, caltime.time.date.minute, caltime.time.date.second);
899                         break;
900                 }
901                 break;
902
903         case CALENDAR_RANGE_NONE:
904                 snprintf(buf +len, buf_len -len, "%s", "#0");
905                 break;
906         }
907         return CALENDAR_ERROR_NONE;
908 }
909 static void __make_rrule_ver1_default(calendar_record_h record, int freq, int interval, char *buf, int buf_size)
910 {
911         RET_IF(NULL == record);
912
913         int ret = 0;
914         calendar_time_s caltime = {0};
915         ret = calendar_record_get_caltime(record, _calendar_event.start_time, &caltime);
916         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_caltime() Fail(%d)", ret);
917
918         switch (freq) {
919         case CALENDAR_RECURRENCE_YEARLY:
920                 snprintf(buf, buf_size, "YD%d ", interval);
921                 break;
922         case CALENDAR_RECURRENCE_MONTHLY:
923                 snprintf(buf, buf_size, "MD%d ", interval);
924                 break;
925         }
926
927         char *tzid = NULL;
928         int d = 0;
929         switch (caltime.type) {
930         case CALENDAR_TIME_UTIME:
931                 calendar_record_get_str_p(record, _calendar_event.start_tzid, &tzid);
932                 cal_time_get_local_datetime(tzid, caltime.time.utime, NULL, NULL, &d, NULL, NULL, NULL);
933                 break;
934         case CALENDAR_TIME_LOCALTIME:
935                 d = caltime.time.date.mday;
936                 break;
937         }
938         char mday[CAL_STR_SHORT_LEN32] = {0};
939         snprintf(mday, sizeof(mday), "%d", d);
940         _cal_vcalendar_make_rrule_append_mday(buf, buf_size, mday);
941 }
942
943 static void __make_rrule_ver1(cal_make_s *b, calendar_record_h record)
944 {
945         RET_IF(NULL == b);
946         RET_IF(NULL == record);
947
948         int ret = 0;
949         char buf[CAL_STR_MIDDLE_LEN] = {0};
950
951         int freq = 0;
952         ret = calendar_record_get_int(record, _calendar_event.freq, &freq);
953         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
954
955         int interval = 1;
956         ret = calendar_record_get_int(record, _calendar_event.interval, &interval);
957         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
958         interval = 0 < interval ? interval : 1;
959
960         char *byyearday = NULL;
961         ret = calendar_record_get_str_p(record, _calendar_event.byyearday, &byyearday);
962         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
963
964         char *bymonth = NULL;
965         ret = calendar_record_get_str_p(record, _calendar_event.bymonth, &bymonth);
966         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
967
968         char *byday = NULL;
969         ret = calendar_record_get_str_p(record, _calendar_event.byday, &byday);
970         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
971
972         char *bymonthday = NULL;
973         ret = calendar_record_get_str_p(record, _calendar_event.bymonthday, &bymonthday);
974         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
975
976         int len = 0;
977         switch (freq) {
978         case CALENDAR_RECURRENCE_YEARLY:
979                 if (bymonth && *bymonth) {
980                         DBG("bymonth[%s]", bymonth);
981                         len += snprintf(buf +len, sizeof(buf) -len, "YM%d ", interval);
982                         len += _cal_vcalendar_make_rrule_append_mday(buf, sizeof(buf), bymonth);
983
984                         if (byday && *byday) {
985                                 DBG("byday");
986                                 /* ex> YM1 6 MP1 1+ TH */
987                                 len += snprintf(buf +len, sizeof(buf) -len, "MP%d ", interval);
988                                 _cal_vcalendar_make_rrule_append_setpos(record, buf, sizeof(buf));
989                                 _cal_vcalendar_make_rrule_append_text_wday(CALENDAR_RECURRENCE_MONTHLY, buf, sizeof(buf), byday);
990                         } else if (bymonthday && *bymonthday) {
991                                 DBG("bymonthday");
992                                 /* ex> YM1 2 MD 1 */
993                                 len += snprintf(buf +len, sizeof(buf) -len, "MD%d ", interval);
994                                 _cal_vcalendar_make_rrule_append_mday(buf, sizeof(buf), bymonthday);
995                         } else {
996                                 ERR("Out of scope");
997                                 __make_rrule_ver1_default(record, freq, interval, buf, sizeof(buf));
998                         }
999                 } else if (byyearday && *byyearday) {
1000                         DBG("byyearday");
1001                         snprintf(buf, sizeof(buf), "YD%d ", interval);
1002                         _cal_vcalendar_make_rrule_append_mday(buf, sizeof(buf), byyearday);
1003                 } else {
1004                         ERR("Out of scope");
1005                         __make_rrule_ver1_default(record, freq, interval, buf, sizeof(buf));
1006                 }
1007                 break;
1008
1009         case CALENDAR_RECURRENCE_MONTHLY:
1010                 if (byday && *byday) {
1011                         DBG("byday");
1012                         snprintf(buf, sizeof(buf), "MP%d ", interval);
1013                         _cal_vcalendar_make_rrule_append_setpos(record, buf, sizeof(buf));
1014                         _cal_vcalendar_make_rrule_append_text_wday(CALENDAR_RECURRENCE_MONTHLY, buf, sizeof(buf), byday);
1015                 } else if (bymonthday && *bymonthday) {
1016                         DBG("bymonthday");
1017                         snprintf(buf, sizeof(buf), "MD%d ", interval);
1018                         _cal_vcalendar_make_rrule_append_mday(buf, sizeof(buf), bymonthday);
1019                 } else {
1020                         ERR("Out of scope, so set as bymonthday");
1021                         __make_rrule_ver1_default(record, freq, interval, buf, sizeof(buf));
1022                 }
1023                 break;
1024
1025         case CALENDAR_RECURRENCE_WEEKLY:
1026                 snprintf(buf, sizeof(buf), "W%d ", interval);
1027                 _cal_vcalendar_make_rrule_append_wday(CALENDAR_RECURRENCE_WEEKLY, buf, sizeof(buf), byday);
1028                 break;
1029
1030         case CALENDAR_RECURRENCE_DAILY:
1031                 snprintf(buf, sizeof(buf), "D%d ", interval);
1032                 break;
1033
1034         default:
1035                 /* LCOV_EXCL_START */
1036                 ERR("Out of scope");
1037                 break;
1038                 /* LCOV_EXCL_STOP */
1039         }
1040
1041         if (*buf) {
1042                 _cal_vcalendar_make_rrule_append_wkst(buf, sizeof(buf), record);
1043                 _cal_vcalendar_make_rrule_append_until(buf, sizeof(buf), record);
1044                 _cal_vcalendar_make_printf(b, "RRULE:", buf);
1045         }
1046 }
1047
1048 static void __make_rrule_ver2(cal_make_s *b, calendar_record_h record)
1049 {
1050         RET_IF(NULL == b);
1051         RET_IF(NULL == record);
1052
1053         int ret = 0;
1054         char *text = NULL;
1055         char tmp[CAL_STR_SHORT_LEN32] = {0};
1056         calendar_time_s caltime = {0};
1057
1058         int freq = 0;
1059         ret = calendar_record_get_int(record, _calendar_event.freq, &freq);
1060         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
1061
1062         switch (freq) {
1063         case CALENDAR_RECURRENCE_DAILY:
1064                 _cal_vcalendar_make_set_str(b, "RRULE:FREQ=DAILY");
1065                 break;
1066         case CALENDAR_RECURRENCE_WEEKLY:
1067                 _cal_vcalendar_make_set_str(b, "RRULE:FREQ=WEEKLY");
1068                 break;
1069         case CALENDAR_RECURRENCE_MONTHLY:
1070                 _cal_vcalendar_make_set_str(b, "RRULE:FREQ=MONTHLY");
1071                 break;
1072         case CALENDAR_RECURRENCE_YEARLY:
1073                 _cal_vcalendar_make_set_str(b, "RRULE:FREQ=YEARLY");
1074                 break;
1075         default:
1076                 return;
1077         }
1078
1079         int interval = 1;
1080         ret = calendar_record_get_int(record, _calendar_event.interval, &interval);
1081         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
1082         interval = 0 < interval ? interval : 1;
1083         snprintf(tmp, sizeof(tmp), ";INTERVAL=%d", interval);
1084         _cal_vcalendar_make_set_str(b, tmp);
1085
1086         ret = calendar_record_get_str_p(record, _calendar_event.bysecond, &text);
1087         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1088         if (text && *text) {
1089                 DBG("BYSECOND= [%s]", text);
1090                 _cal_vcalendar_make_set_str(b, ";BYSECOND=");
1091                 _cal_vcalendar_make_set_str(b, text);
1092                 text = NULL;
1093         }
1094
1095         ret = calendar_record_get_str_p(record, _calendar_event.byminute, &text);
1096         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1097         if (text && *text) {
1098                 DBG("BYMINUTE= [%s]", text);
1099                 _cal_vcalendar_make_set_str(b, ";BYMINUTE=");
1100                 _cal_vcalendar_make_set_str(b, text);
1101                 text = NULL;
1102         }
1103
1104         ret = calendar_record_get_str_p(record, _calendar_event.byhour, &text);
1105         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1106         if (text && *text) {
1107                 DBG("BYHOUR= [%s]", text);
1108                 _cal_vcalendar_make_set_str(b, ";BYHOUR=");
1109                 _cal_vcalendar_make_set_str(b, text);
1110                 text = NULL;
1111         }
1112
1113         ret = calendar_record_get_str_p(record, _calendar_event.byday, &text);
1114         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1115         if (text && *text) {
1116                 DBG("BYDAY= [%s]", text);
1117                 _cal_vcalendar_make_set_str(b, ";BYDAY=");
1118                 _cal_vcalendar_make_set_str(b, text);
1119                 text = NULL;
1120         }
1121
1122         ret = calendar_record_get_str_p(record, _calendar_event.bymonthday, &text);
1123         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1124         if (text && *text) {
1125                 DBG("BYMONTHDAY= [%s]", text);
1126                 _cal_vcalendar_make_set_str(b, ";BYMONTHDAY=");
1127                 _cal_vcalendar_make_set_str(b, text);
1128                 text = NULL;
1129         }
1130
1131         ret = calendar_record_get_str_p(record, _calendar_event.byyearday, &text);
1132         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1133         if (text && *text) {
1134                 DBG("BYYEARDAY= [%s]", text);
1135                 _cal_vcalendar_make_set_str(b, ";BYYEARDAY=");
1136                 _cal_vcalendar_make_set_str(b, text);
1137                 text = NULL;
1138         }
1139
1140         ret = calendar_record_get_str_p(record, _calendar_event.byweekno, &text);
1141         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1142         if (text && *text) {
1143                 DBG("BYWEEKNO= [%s]", text);
1144                 _cal_vcalendar_make_set_str(b, ";BYWEEKNO=");
1145                 _cal_vcalendar_make_set_str(b, text);
1146                 text = NULL;
1147         }
1148
1149         ret = calendar_record_get_str_p(record, _calendar_event.bymonth, &text);
1150         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1151         if (text && *text) {
1152                 DBG("BYMONTH= [%s]", text);
1153                 _cal_vcalendar_make_set_str(b, ";BYMONTH=");
1154                 _cal_vcalendar_make_set_str(b, text);
1155                 text = NULL;
1156         }
1157
1158         ret = calendar_record_get_str_p(record, _calendar_event.bysetpos, &text);
1159         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1160         if (text && *text) {
1161                 DBG("BYSETPOS= [%s]", text);
1162                 _cal_vcalendar_make_set_str(b, ";BYSETPOS=");
1163                 _cal_vcalendar_make_set_str(b, text);
1164                 text = NULL;
1165         }
1166
1167         int wkst = 0;
1168         ret = calendar_record_get_int(record, _calendar_event.wkst, &wkst);
1169         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
1170         if (CALENDAR_SUNDAY <= wkst && wkst <= CALENDAR_SATURDAY) {
1171                 _cal_vcalendar_make_set_str(b, ";WKST=");
1172                 switch (wkst) {
1173                 case CALENDAR_SUNDAY:
1174                         _cal_vcalendar_make_set_str(b, "SU");
1175                         break;
1176                 case CALENDAR_MONDAY:
1177                         _cal_vcalendar_make_set_str(b, "MO");
1178                         break;
1179                 case CALENDAR_TUESDAY:
1180                         _cal_vcalendar_make_set_str(b, "TU");
1181                         break;
1182                 case CALENDAR_WEDNESDAY:
1183                         _cal_vcalendar_make_set_str(b, "WE");
1184                         break;
1185                 case CALENDAR_THURSDAY:
1186                         _cal_vcalendar_make_set_str(b, "TH");
1187                         break;
1188                 case CALENDAR_FRIDAY:
1189                         _cal_vcalendar_make_set_str(b, "FR");
1190                         break;
1191                 case CALENDAR_SATURDAY:
1192                         _cal_vcalendar_make_set_str(b, "SA");
1193                         break;
1194                 }
1195         }
1196
1197         int range_type = 0;
1198         int count = 0;
1199         ret = calendar_record_get_int(record, _calendar_event.range_type, &range_type);
1200         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
1201         switch (range_type) {
1202         case CALENDAR_RANGE_COUNT:
1203                 ret = calendar_record_get_int(record, _calendar_event.count, &count);
1204                 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
1205                 snprintf(tmp, sizeof(tmp), ";COUNT=%d", count);
1206                 _cal_vcalendar_make_set_str(b, tmp);
1207                 DBG("count [%s]", tmp);
1208                 break;
1209
1210         case CALENDAR_RANGE_UNTIL:
1211                 ret = calendar_record_get_caltime(record, _calendar_event.until_time, &caltime);
1212                 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_caltime() Fail(%d)", ret);
1213
1214                 if (caltime.type == CALENDAR_TIME_UTIME) {
1215                         char *tmp_tzid = NULL;
1216                         tmp_tzid = cal_time_convert_ltos(NULL, caltime.time.utime, 0);
1217                         if (tmp_tzid) {
1218                                 snprintf(tmp, sizeof(tmp), ";UNTIL=%s", tmp_tzid);
1219                                 CAL_FREE(tmp_tzid);
1220                         }
1221                 } else {
1222                         snprintf(tmp, sizeof(tmp), ";UNTIL="CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSSZ,
1223                                         caltime.time.date.year,
1224                                         caltime.time.date.month,
1225                                         caltime.time.date.mday,
1226                                         caltime.time.date.hour,
1227                                         caltime.time.date.minute,
1228                                         caltime.time.date.second);
1229                 }
1230                 _cal_vcalendar_make_set_str(b, tmp);
1231                 DBG("until [%s]", tmp);
1232                 break;
1233
1234         case CALENDAR_RANGE_NONE:
1235                 DBG("No range");
1236                 break;
1237         }
1238         _cal_vcalendar_make_flush(b);
1239 }
1240
1241 static void __make_rrule(cal_make_s *b, calendar_record_h record)
1242 {
1243         RET_IF(NULL == b);
1244         RET_IF(NULL == record);
1245
1246         switch (b->type) {
1247         case CALENDAR_BOOK_TYPE_EVENT:
1248                 switch (b->version) {
1249                 case VCAL_VER_1:
1250                         __make_rrule_ver1(b, record);
1251                         break;
1252                 case VCAL_VER_2:
1253                         __make_rrule_ver2(b, record);
1254                         break;
1255                 }
1256                 break;
1257         case CALENDAR_BOOK_TYPE_TODO:
1258                 /* LCOV_EXCL_START */
1259                 ERR("No rrule in todo");
1260                 return;
1261                 /* LCOV_EXCL_STOP */
1262         }
1263 }
1264
1265 int _cal_vcalendar_make_attendee(cal_make_s *b, calendar_record_h attendee)
1266 {
1267         int ret;
1268
1269         RETV_IF(NULL == attendee, CALENDAR_ERROR_INVALID_PARAMETER);
1270
1271         ret = _cal_vcalendar_make_set_str(b, "ATTENDEE");
1272         RETV_IF(CALENDAR_ERROR_NONE != ret, ret);
1273
1274         int cutype = 0;
1275         ret = calendar_record_get_int(attendee, _calendar_attendee.cutype, &cutype);
1276         ret = _cal_vcalendar_make_set_str(b, ";CUTYPE=");
1277         switch (cutype) {
1278         case CALENDAR_ATTENDEE_CUTYPE_INDIVIDUAL:
1279                 ret = _cal_vcalendar_make_set_str(b, "INDIVIDUAL");
1280                 break;
1281         case CALENDAR_ATTENDEE_CUTYPE_GROUP:
1282                 ret = _cal_vcalendar_make_set_str(b, "GROUP");
1283                 break;
1284         case CALENDAR_ATTENDEE_CUTYPE_RESOURCE:
1285                 ret = _cal_vcalendar_make_set_str(b, "RESOURCE");
1286                 break;
1287         case CALENDAR_ATTENDEE_CUTYPE_ROOM:
1288                 ret = _cal_vcalendar_make_set_str(b, "ROOM");
1289                 break;
1290         case CALENDAR_ATTENDEE_CUTYPE_UNKNOWN:
1291                 ret = _cal_vcalendar_make_set_str(b, "UNKNOWN");
1292                 break;
1293         }
1294         RETV_IF(CALENDAR_ERROR_NONE != ret, ret);
1295
1296         char *member = NULL;
1297         ret = calendar_record_get_str_p(attendee, _calendar_attendee.member, &member);
1298         if (member && *member) {
1299                 ret = _cal_vcalendar_make_set_str(b, ";MEMBER=");
1300                 ret = _cal_vcalendar_make_set_str(b, member);
1301                 RETV_IF(CALENDAR_ERROR_NONE != ret, ret);
1302         }
1303
1304         int role = 0;
1305         ret = calendar_record_get_int(attendee, _calendar_attendee.role, &role);
1306         {
1307                 ret = _cal_vcalendar_make_set_str(b, ";ROLE=");
1308                 ret = _cal_vcalendar_make_set_str(b, _att_role[role]);
1309                 RETV_IF(CALENDAR_ERROR_NONE != ret, ret);
1310         }
1311
1312         int status = 0;
1313         ret = calendar_record_get_int(attendee, _calendar_attendee.status, &status);
1314         {
1315                 ret = _cal_vcalendar_make_set_str(b, ";PARTSTAT=");
1316                 ret = _cal_vcalendar_make_set_str(b, _att_st[status]);
1317                 RETV_IF(CALENDAR_ERROR_NONE != ret, ret);
1318         }
1319
1320         int rsvp = 0;
1321         ret = calendar_record_get_int(attendee, _calendar_attendee.rsvp, &rsvp);
1322         {
1323                 ret = _cal_vcalendar_make_set_str(b, ";RSVP=");
1324                 ret = _cal_vcalendar_make_set_str(b, rsvp ? "TRUE" : "FALSE");
1325                 RETV_IF(CALENDAR_ERROR_NONE != ret, ret);
1326         }
1327
1328         char *delegatee_uri = NULL;
1329         ret = calendar_record_get_str_p(attendee, _calendar_attendee.delegatee_uri, &delegatee_uri);
1330         if (delegatee_uri && *delegatee_uri) {
1331                 ret = _cal_vcalendar_make_set_str(b, ";DELEGATED-TO=");
1332                 ret = _cal_vcalendar_make_set_str(b, delegatee_uri);
1333                 RETV_IF(CALENDAR_ERROR_NONE != ret, ret);
1334         }
1335
1336         char *delegator_uri = NULL;
1337         ret = calendar_record_get_str_p(attendee, _calendar_attendee.delegator_uri, &delegator_uri);
1338         if (delegator_uri && *delegator_uri) {
1339                 ret = _cal_vcalendar_make_set_str(b, ";DELEGATED-FROM=");
1340                 ret = _cal_vcalendar_make_set_str(b, delegator_uri);
1341                 RETV_IF(CALENDAR_ERROR_NONE != ret, ret);
1342         }
1343
1344         /* TODO : No 'sentby' member in cal_participant_info_t */
1345
1346         char *name = NULL;
1347         ret = calendar_record_get_str_p(attendee, _calendar_attendee.name, &name);
1348         if (name && *name) {
1349                 ret = _cal_vcalendar_make_set_str(b, ";CN=");
1350                 ret = _cal_vcalendar_make_set_str(b, name);
1351                 RETV_IF(CALENDAR_ERROR_NONE != ret, ret);
1352         }
1353
1354         char *email = NULL;
1355         ret = calendar_record_get_str_p(attendee, _calendar_attendee.email, &email);
1356         if (email && *email) {
1357                 ret = _cal_vcalendar_make_set_str(b, ":mailto:");
1358                 ret = _cal_vcalendar_make_set_str(b, email);
1359                 RETV_IF(CALENDAR_ERROR_NONE != ret, ret);
1360         }
1361
1362         _cal_vcalendar_make_flush(b);
1363         return CALENDAR_ERROR_NONE;
1364 }
1365
1366 static void __make_attendee(cal_make_s *b, calendar_record_h record)
1367 {
1368         RET_IF(NULL == b);
1369         RET_IF(NULL == record);
1370
1371         int ret = 0;
1372         unsigned int count = 0;
1373         int i;
1374         switch (b->type) {
1375         case CALENDAR_BOOK_TYPE_EVENT:
1376                 ret = calendar_record_get_child_record_count(record, _calendar_event.calendar_attendee, &count);
1377                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_child_record_count() Fail(%d)", ret);
1378                 for (i = 0; i < count; i++) {
1379                         calendar_record_h child = NULL;
1380                         ret = calendar_record_get_child_record_at_p(record, _calendar_event.calendar_attendee, i, &child);
1381                         ret = _cal_vcalendar_make_attendee(b, child);
1382                 }
1383                 break;
1384         case CALENDAR_BOOK_TYPE_TODO:
1385                 ret = calendar_record_get_child_record_count(record, _calendar_todo.calendar_attendee, &count);
1386                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_child_record_count() Fail(%d)", ret);
1387                 for (i = 0; i < count; i++) {
1388                         calendar_record_h child = NULL;
1389                         ret = calendar_record_get_child_record_at_p(record, _calendar_todo.calendar_attendee, i, &child);
1390                         ret = _cal_vcalendar_make_attendee(b, child);
1391                 }
1392                 break;
1393         }
1394 }
1395
1396 static void __make_alarm_ver1(cal_make_s *b, calendar_record_h record)
1397 {
1398         /* In ver 1.0, only first alarm will be dealt with. */
1399         RET_IF(NULL == b);
1400         RET_IF(NULL == record);
1401
1402         int ret = 0;
1403         unsigned int count = 0;
1404         int i;
1405         switch (b->type) {
1406         case CALENDAR_BOOK_TYPE_EVENT:
1407                 ret = calendar_record_get_child_record_count(record, _calendar_event.calendar_alarm, &count);
1408                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_child_record_count() Fail(%d)", ret);
1409                 for (i = 0; i < count; i++) {
1410                         calendar_record_h child = NULL;
1411                         ret = calendar_record_get_child_record_at_p(record, _calendar_event.calendar_alarm, i, &child);
1412                         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_child_record_at_p() Fail(%d)", ret);
1413
1414                         _cal_vcalendar_make_aalarm(b, record, child);
1415                 }
1416                 break;
1417         case CALENDAR_BOOK_TYPE_TODO:
1418                 ret = calendar_record_get_child_record_count(record, _calendar_todo.calendar_alarm, &count);
1419                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_child_record_count() Fail(%d)", ret);
1420                 for (i = 0; i < count; i++) {
1421                         calendar_record_h child = NULL;
1422                         ret = calendar_record_get_child_record_at_p(record, _calendar_todo.calendar_alarm, i, &child);
1423                         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_child_record_at_p() Fail(%d)", ret);
1424
1425                         _cal_vcalendar_make_aalarm(b, record, child);
1426                 }
1427                 break;
1428         }
1429 }
1430
1431 static void __make_alarm_ver2(cal_make_s *b, calendar_record_h record)
1432 {
1433         RET_IF(NULL == b);
1434         RET_IF(NULL == record);
1435
1436         int ret = 0;
1437         unsigned int count = 0;
1438         int i;
1439         switch (b->type) {
1440         case CALENDAR_BOOK_TYPE_EVENT:
1441                 ret = calendar_record_get_child_record_count(record, _calendar_event.calendar_alarm, &count);
1442                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_child_record_count() Fail(%d)", ret);
1443                 for (i = 0; i < count; i++) {
1444                         calendar_record_h child = NULL;
1445                         ret = calendar_record_get_child_record_at_p(record, _calendar_event.calendar_alarm, i, &child);
1446                         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_child_record_at_p() Fail(%d)", ret);
1447
1448                         _cal_vcalendar_make_alarm(b, child);
1449                 }
1450                 break;
1451         case CALENDAR_BOOK_TYPE_TODO:
1452                 ret = calendar_record_get_child_record_count(record, _calendar_todo.calendar_alarm, &count);
1453                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_child_record_count() Fail(%d)", ret);
1454                 for (i = 0; i < count; i++) {
1455                         calendar_record_h child = NULL;
1456                         ret = calendar_record_get_child_record_at_p(record, _calendar_todo.calendar_alarm, i, &child);
1457                         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_child_record_at_p() Fail(%d)", ret);
1458
1459                         _cal_vcalendar_make_alarm(b, child);
1460                 }
1461                 break;
1462         }
1463 }
1464
1465 static void __make_alarm(cal_make_s *b, calendar_record_h record)
1466 {
1467         RET_IF(NULL == b);
1468         RET_IF(NULL == record);
1469
1470         switch (b->type) {
1471         case CALENDAR_BOOK_TYPE_EVENT:
1472                 switch (b->version) {
1473                 case VCAL_VER_1:
1474                         __make_alarm_ver1(b, record);
1475                         break;
1476                 case VCAL_VER_2:
1477                         __make_alarm_ver2(b, record);
1478                         break;
1479                 }
1480                 break;
1481         case CALENDAR_BOOK_TYPE_TODO:
1482                 /* LCOV_EXCL_START */
1483                 ERR("No rrule in todo");
1484                 return;
1485                 /* LCOV_EXCL_STOP */
1486         }
1487
1488 }
1489 static void __make_created_time(cal_make_s *b, calendar_record_h record)
1490 {
1491         RET_IF(NULL == b);
1492         RET_IF(NULL == record);
1493
1494         int ret = 0;
1495         long long int value = 0;
1496         switch (b->type) {
1497         case CALENDAR_BOOK_TYPE_EVENT:
1498                 ret = calendar_record_get_lli(record, _calendar_event.created_time, &value);
1499                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_lli() Fail(%d)", ret);
1500                 break;
1501         case CALENDAR_BOOK_TYPE_TODO:
1502                 ret = calendar_record_get_lli(record, _calendar_todo.created_time, &value);
1503                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_lli() Fail(%d)", ret);
1504                 break;
1505         }
1506         int y = 0, m = 0, d = 0;
1507         int h = 0, n = 0, s = 0;
1508         cal_time_get_local_datetime(NULL, value, &y, &m, &d, &h, &n, &s);
1509         char buf[CAL_STR_MIDDLE_LEN] = {0};
1510         snprintf(buf, sizeof(buf), CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSSZ, y, m, d, h, n, s);
1511
1512         switch (b->version) {
1513         case VCAL_VER_1:
1514                 _cal_vcalendar_make_printf(b, "DCREATED:", buf);
1515                 break;
1516         case VCAL_VER_2:
1517                 _cal_vcalendar_make_printf(b, "CREATED:", buf);
1518                 break;
1519         }
1520 }
1521
1522 static void __make_summary(cal_make_s *b, calendar_record_h record)
1523 {
1524         RET_IF(NULL == b);
1525         RET_IF(NULL == record);
1526
1527         int ret = 0;
1528         char *value = NULL;
1529         switch (b->type) {
1530         case CALENDAR_BOOK_TYPE_EVENT:
1531                 ret = calendar_record_get_str_p(record, _calendar_event.summary, &value);
1532                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1533                 break;
1534         case CALENDAR_BOOK_TYPE_TODO:
1535                 ret = calendar_record_get_str_p(record, _calendar_todo.summary, &value);
1536                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1537                 break;
1538         }
1539         if (value && *value) {
1540                 char *summary = NULL;
1541                 __encode_escaped_char(value, &summary);
1542                 _cal_vcalendar_make_printf(b, "SUMMARY:", summary);
1543                 free(summary);
1544         }
1545 }
1546
1547 static void __make_description(cal_make_s *b, calendar_record_h record)
1548 {
1549         RET_IF(NULL == b);
1550         RET_IF(NULL == record);
1551
1552         int ret = 0;
1553         char *value = NULL;
1554         switch (b->type) {
1555         case CALENDAR_BOOK_TYPE_EVENT:
1556                 ret = calendar_record_get_str_p(record, _calendar_event.description, &value);
1557                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1558                 break;
1559         case CALENDAR_BOOK_TYPE_TODO:
1560                 ret = calendar_record_get_str_p(record, _calendar_todo.description, &value);
1561                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1562                 break;
1563         }
1564         if (value && *value) {
1565                 char *description = NULL;
1566                 __encode_escaped_char(value, &description);
1567                 _cal_vcalendar_make_printf(b, "DESCRIPTION:", description);
1568                 free(description);
1569         }
1570 }
1571
1572 static void __make_location(cal_make_s *b, calendar_record_h record)
1573 {
1574         RET_IF(NULL == b);
1575         RET_IF(NULL == record);
1576
1577         int ret = 0;
1578         char *value = NULL;
1579         switch (b->type) {
1580         case CALENDAR_BOOK_TYPE_EVENT:
1581                 ret = calendar_record_get_str_p(record, _calendar_event.location, &value);
1582                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1583                 break;
1584         case CALENDAR_BOOK_TYPE_TODO:
1585                 ret = calendar_record_get_str_p(record, _calendar_todo.location, &value);
1586                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1587                 break;
1588         }
1589         if (value && *value) {
1590                 char *location = NULL;
1591                 __encode_escaped_char(value, &location);
1592                 _cal_vcalendar_make_printf(b, "LOCATION:", location);
1593                 free(location);
1594         }
1595 }
1596
1597 static void __make_organizer(cal_make_s *b, calendar_record_h record)
1598 {
1599         RET_IF(NULL == b);
1600         RET_IF(NULL == record);
1601
1602         /* Invalid component in ver 1 */
1603         if (VCAL_VER_1 == b->version)
1604                 return;
1605
1606         int ret = 0;
1607         char *name = NULL;
1608         char *email = NULL;
1609         switch (b->type) {
1610         case CALENDAR_BOOK_TYPE_EVENT:
1611                 ret = calendar_record_get_str_p(record, _calendar_event.organizer_name, &name);
1612                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1613                 ret = calendar_record_get_str_p(record, _calendar_event.organizer_email, &email);
1614                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1615                 break;
1616         case CALENDAR_BOOK_TYPE_TODO:
1617                 ret = calendar_record_get_str_p(record, _calendar_todo.organizer_name, &name);
1618                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1619                 ret = calendar_record_get_str_p(record, _calendar_todo.organizer_email, &email);
1620                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1621                 break;
1622         }
1623         if ((NULL == name || '\0' == *name) && (NULL == email || '\0' == *email))
1624                 return;
1625
1626         char buf[CAL_STR_MIDDLE_LEN] = {0};
1627         snprintf(buf, sizeof(buf), "ORGANIZER%s%s%s%s",
1628                         (name && *name) ? ";CN=" : "",
1629                         (name && *name) ? name : "",
1630                         (email && *email) ? ":MAILTO:" : "",
1631                         (email && *email) ? email : "");
1632
1633         _cal_vcalendar_make_printf(b, buf, NULL);
1634 }
1635
1636 static void __make_last_modified(cal_make_s *b, calendar_record_h record)
1637 {
1638         RET_IF(NULL == b);
1639         RET_IF(NULL == record);
1640
1641         /* kies want to skip */
1642         if (VCAL_VER_1 == b->version) {
1643                 DBG("skip in ver1.0");
1644                 return;
1645         }
1646
1647         int ret = 0;
1648         long long int value = 0;
1649         switch (b->type) {
1650         case CALENDAR_BOOK_TYPE_EVENT:
1651                 ret = calendar_record_get_lli(record, _calendar_event.last_modified_time, &value);
1652                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_lli() Fail(%d)", ret);
1653                 break;
1654         case CALENDAR_BOOK_TYPE_TODO:
1655                 ret = calendar_record_get_lli(record, _calendar_todo.last_modified_time, &value);
1656                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_lli() Fail(%d)", ret);
1657                 break;
1658         }
1659
1660         int y = 0, m = 0, d = 0;
1661         int h = 0, n = 0, s = 0;
1662         cal_time_get_local_datetime(NULL, value, &y, &m, &d, &h, &n, &s);
1663
1664         char buf[CAL_STR_MIDDLE_LEN] = {0};
1665         snprintf(buf, sizeof(buf), CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSSZ, y, m, d, h, n, s);
1666         _cal_vcalendar_make_printf(b, "LAST-MODIFIED:", buf);
1667 }
1668
1669 static void __make_status(cal_make_s *b, calendar_record_h record)
1670 {
1671         RET_IF(NULL == b);
1672         RET_IF(NULL == record);
1673
1674         int ret = 0;
1675         int value = 0;
1676         char *status = NULL;
1677         switch (b->type) {
1678         case CALENDAR_BOOK_TYPE_EVENT:
1679                 ret = calendar_record_get_int(record, _calendar_event.event_status, &value);
1680                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
1681                 switch (value) {
1682                 case CALENDAR_EVENT_STATUS_NONE:
1683                         DBG("None status");
1684                         break;
1685                 case CALENDAR_EVENT_STATUS_TENTATIVE:
1686                         status = "TENTATIVE";
1687                         break;
1688                 case CALENDAR_EVENT_STATUS_CONFIRMED:
1689                         status = "CONFIRMED";
1690                         break;
1691                 case CALENDAR_EVENT_STATUS_CANCELLED:
1692                         status = "CANCELLED";
1693                         break;
1694                 }
1695                 break;
1696         case CALENDAR_BOOK_TYPE_TODO:
1697                 ret = calendar_record_get_int(record, _calendar_todo.todo_status, &value);
1698                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
1699                 switch (value) {
1700                 case CALENDAR_TODO_STATUS_NONE:
1701                         DBG("None status");
1702                         break;
1703                 case CALENDAR_TODO_STATUS_NEEDS_ACTION:
1704                         status = (VCAL_VER_1 == b->version) ? "NEEDS ACTION" : "NEEDS-ACTION";
1705                         break;
1706                 case CALENDAR_TODO_STATUS_COMPLETED:
1707                         status = "COMPLETED";
1708                         break;
1709                 case CALENDAR_TODO_STATUS_IN_PROCESS:
1710                         status = (VCAL_VER_1 == b->version) ? NULL : "IN-PROCESS";
1711                         break;
1712                 case CALENDAR_TODO_STATUS_CANCELED:
1713                         status = (VCAL_VER_1 == b->version) ? NULL : "CANCELLED";
1714                         break;
1715                 }
1716                 break;
1717         }
1718         if (status && *status)
1719                 _cal_vcalendar_make_printf(b, "STATUS:", status);
1720 }
1721
1722 static void __make_completed(cal_make_s *b, calendar_record_h record)
1723 {
1724         RET_IF(NULL == b);
1725         RET_IF(NULL == record);
1726
1727         /* Invalid component in event */
1728         if (CALENDAR_BOOK_TYPE_EVENT == b->type)
1729                 return;
1730
1731         int ret = 0;
1732         long long int value = 0;
1733         ret = calendar_record_get_lli(record, _calendar_todo.completed_time, &value);
1734         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
1735
1736         int y = 0, m = 0, d = 0;
1737         int h = 0, n = 0, s = 0;
1738         cal_time_get_local_datetime(NULL, value, &y, &m, &d, &h, &n, &s);
1739         char buf[CAL_STR_MIDDLE_LEN] = {0};
1740         snprintf(buf, sizeof(buf), CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSSZ, y, m, d, h, n, s);
1741         _cal_vcalendar_make_printf(b, "COMPLETED", buf);
1742 }
1743
1744 static void __make_priority(cal_make_s *b, calendar_record_h record)
1745 {
1746         RET_IF(NULL == b);
1747         RET_IF(NULL == record);
1748
1749         int ret = 0;
1750         int value = 0;
1751         switch (b->type) {
1752         case CALENDAR_BOOK_TYPE_EVENT:
1753                 ret = calendar_record_get_int(record, _calendar_event.priority, &value);
1754                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
1755                 break;
1756         case CALENDAR_BOOK_TYPE_TODO:
1757                 ret = calendar_record_get_int(record, _calendar_todo.priority, &value);
1758                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
1759                 break;
1760         }
1761         int priority = 0;
1762         switch (b->version) {
1763         case VCAL_VER_1:
1764                 switch (value) {
1765                 case CALENDAR_EVENT_PRIORITY_HIGH:
1766                         priority = 2;
1767                         break;
1768                 case CALENDAR_EVENT_PRIORITY_NORMAL:
1769                         priority = 1;
1770                         break;
1771                 case CALENDAR_EVENT_PRIORITY_LOW:
1772                         priority = 0;
1773                         break;
1774                 default:
1775                         priority = 0;
1776                         break;
1777                 }
1778                 break;
1779         case VCAL_VER_2:
1780                 switch (value) {
1781                 case CALENDAR_EVENT_PRIORITY_HIGH:
1782                         /* in version 2.0, one out of 1 ~ 4 */
1783                         priority = 3;
1784                         break;
1785                 case CALENDAR_EVENT_PRIORITY_NORMAL:
1786                         priority = 5;
1787                         break;
1788                 case CALENDAR_EVENT_PRIORITY_LOW:
1789                         /* in version 2, one out of 6 ~ 9. */
1790                         priority = 7;
1791                         break;
1792                 default:
1793                         priority = 0;
1794                         break;
1795                 }
1796                 break;
1797         }
1798         char buf[CAL_STR_MIDDLE_LEN] = {0};
1799         snprintf(buf, sizeof(buf), "PRIORITY:%d", priority);
1800         _cal_vcalendar_make_printf(b, buf, NULL);
1801 }
1802
1803 static void __make_dtstamp(cal_make_s *b, calendar_record_h record)
1804 {
1805         RET_IF(NULL == b);
1806         RET_IF(NULL == record);
1807
1808         /* Not support in ver 1 */
1809         if (VCAL_VER_1 == b->version)
1810                 return;
1811
1812         long long int t = cal_time_get_now();
1813         int y = 0, m = 0, d = 0;
1814         int h = 0, n = 0, s = 0;
1815         cal_time_get_local_datetime(NULL, t, &y, &m, &d, &h, &n, &s);
1816         char buf[CAL_STR_MIDDLE_LEN] = {0};
1817         snprintf(buf, sizeof(buf), CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSSZ, y, m, d, h, n, s);
1818         _cal_vcalendar_make_printf(b, "DTSTAMP:", buf);
1819 }
1820
1821 static void __make_categories(cal_make_s *b, calendar_record_h record)
1822 {
1823         RET_IF(NULL == b);
1824         RET_IF(NULL == record);
1825
1826         int ret = 0;
1827         char *value = NULL;
1828         switch (b->type) {
1829         case CALENDAR_BOOK_TYPE_EVENT:
1830                 ret = calendar_record_get_str_p(record, _calendar_event.categories, &value);
1831                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1832                 break;
1833         case CALENDAR_BOOK_TYPE_TODO:
1834                 ret = calendar_record_get_str_p(record, _calendar_todo.categories, &value);
1835                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1836                 break;
1837         }
1838         if (value && *value)
1839                 _cal_vcalendar_make_printf(b, "CATEGORIES:", value);
1840 }
1841
1842 static void __make_exdate(cal_make_s *b, calendar_record_h record)
1843 {
1844         RET_IF(NULL == b);
1845         RET_IF(NULL == record);
1846
1847         int ret = 0;
1848         char *value = NULL;
1849         switch (b->type) {
1850         case CALENDAR_BOOK_TYPE_EVENT:
1851                 ret = calendar_record_get_str_p(record, _calendar_event.exdate, &value);
1852                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1853                 break;
1854         case CALENDAR_BOOK_TYPE_TODO:
1855                 /* LCOV_EXCL_START */
1856                 ERR("Not support exdate in TODO");
1857                 break;
1858                 /* LCOV_EXCL_STOP */
1859         }
1860         if (value && *value)
1861                 _cal_vcalendar_make_printf(b, "EXDATE:", value);
1862 }
1863
1864 static void _cal_vcalendar_make_child_extended(cal_make_s *b, calendar_record_h child, bool *has_lunar)
1865 {
1866         RET_IF(NULL == b);
1867         RET_IF(NULL == child);
1868
1869         int ret = 0;;
1870         char *key = NULL;
1871         char *value = NULL;
1872
1873         ret = calendar_record_get_str_p(child, _calendar_extended_property.key, &key);
1874         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1875         if (NULL == key || '\0' == *key || (0 != strncmp(key, "X-", strlen("X-")))) {
1876                 DBG("Not extended for vcalendar[%s]", key);
1877                 return;
1878         }
1879
1880         ret = calendar_record_get_str_p(child, _calendar_extended_property.value, &value);
1881         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1882
1883         /* check lunar: will handle next */
1884         if (has_lunar) {
1885                 if ((CAL_STRING_EQUAL == strncmp(key, "X-LUNAR", strlen("X-LUNAR")) && !strncmp(value, ":SET", strlen(":SET"))) ||
1886                                 (CAL_STRING_EQUAL == strncmp(key, "X-LUNAR:", strlen("X-LUNAR:")) && !strncmp(value, "SET", strlen("SET")))) {
1887                         *has_lunar = true;
1888                         return;
1889                 }
1890         }
1891
1892         ret = _cal_vcalendar_make_printf(b, key, value);
1893         RETM_IF(CALENDAR_ERROR_NONE != ret, "_cal_vcalendar_make_printf() Fail(%d)", ret);
1894 }
1895
1896 static void __make_extended(cal_make_s *b, calendar_record_h record)
1897 {
1898         RET_IF(NULL == b);
1899         RET_IF(NULL == record);
1900
1901         int ret = 0;
1902         unsigned int count = 0;
1903         int i;
1904         bool has_lunar = false;
1905         int calendar_system_type = 0;
1906         switch (b->type) {
1907         case CALENDAR_BOOK_TYPE_EVENT:
1908                 ret = calendar_record_get_child_record_count(record, _calendar_event.extended, &count);
1909                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_child_record_count() Fail(%d)", ret);
1910                 for (i = 0; i < count; i++) {
1911                         calendar_record_h child = NULL;
1912                         ret = calendar_record_get_child_record_at_p(record, _calendar_event.extended, i, &child);
1913                         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_child_record_at_p() Fail(%d)", ret);
1914
1915                         _cal_vcalendar_make_child_extended(b, child, &has_lunar);
1916                 }
1917
1918                 /* lunar */
1919                 ret = calendar_record_get_int(record, _calendar_event.calendar_system_type, &calendar_system_type);
1920                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
1921
1922                 if (true == has_lunar || CALENDAR_SYSTEM_EAST_ASIAN_LUNISOLAR == calendar_system_type)
1923                         _cal_vcalendar_make_printf(b, "X-LUNAR:SET", NULL);
1924                 break;
1925         case CALENDAR_BOOK_TYPE_TODO:
1926                 ret = calendar_record_get_child_record_count(record, _calendar_todo.extended, &count);
1927                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_child_record_count() Fail(%d)", ret);
1928                 for (i = 0; i < count; i++) {
1929                         calendar_record_h child = NULL;
1930                         ret = calendar_record_get_child_record_at_p(record, _calendar_todo.extended, i, &child);
1931                         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_child_record_at_p() Fail(%d)", ret);
1932
1933                         _cal_vcalendar_make_child_extended(b, child, NULL);
1934                 }
1935                 break;
1936         }
1937 }
1938
1939 static void __make_end(cal_make_s *b, calendar_record_h record)
1940 {
1941         RET_IF(NULL == b);
1942         RET_IF(NULL == record);
1943
1944         int ret = 0;
1945         switch (b->type) {
1946         case CALENDAR_BOOK_TYPE_EVENT:
1947                 ret = _cal_vcalendar_make_printf(b, "END:VEVENT", NULL);
1948                 RETM_IF(CALENDAR_ERROR_NONE != ret, "_cal_vcalendar_make_printf() Fail(%d)", ret);
1949                 break;
1950         case CALENDAR_BOOK_TYPE_TODO:
1951                 ret = _cal_vcalendar_make_printf(b, "END:VTODO", NULL);
1952                 RETM_IF(CALENDAR_ERROR_NONE != ret, "_cal_vcalendar_make_printf() Fail(%d)", ret);
1953                 break;
1954         }
1955 }
1956
1957 static void _cal_vcalendar_make_schedule(cal_make_s *b, calendar_record_h record)
1958 {
1959         RET_IF(NULL == b);
1960         RET_IF(NULL == record);
1961
1962         __make_begin(b, record);
1963         __make_summary(b, record);
1964         __make_dtstart(b, record);
1965         __make_dtend(b, record);
1966         __make_rrule(b, record); /* only event */
1967         __make_sensitivity(b, record);
1968         __make_created_time(b, record);
1969         __make_description(b, record);
1970         __make_location(b, record);
1971         __make_organizer(b, record);
1972         __make_last_modified(b, record);
1973         __make_status(b, record);
1974         __make_completed(b, record); /* only todo */
1975         __make_priority(b, record);
1976         __make_dtstamp(b, record);
1977         __make_categories(b, record);
1978         __make_exdate(b, record); /* only event */
1979         __make_attendee(b, record);
1980         __make_alarm(b, record);
1981         __make_extended(b, record);
1982         __make_end(b, record);
1983
1984 }
1985
1986 static void __append_header(cal_make_s *b)
1987 {
1988         RET_IF(NULL == b);
1989
1990         int ret = 0;
1991
1992         ret = _cal_vcalendar_make_printf(b, "BEGIN:VCALENDAR", NULL);
1993         RETM_IF(CALENDAR_ERROR_NONE != ret, "_cal_vcalendar_make_printf() Fail(%d)", ret);
1994
1995         ret = _cal_vcalendar_make_printf(b, "PRODID:vCal ID Default", NULL);
1996         RETM_IF(CALENDAR_ERROR_NONE != ret, "_cal_vcalendar_make_printf() Fail(%d)", ret);
1997
1998         char buf[CAL_STR_SHORT_LEN32] = {0};
1999         snprintf(buf, sizeof(buf), "VERSION:%d.0", b->version);
2000         ret = _cal_vcalendar_make_printf(b, buf, NULL);
2001         RETM_IF(CALENDAR_ERROR_NONE != ret, "_cal_vcalendar_make_printf() Fail(%d)", ret);
2002 }
2003
2004 static void __make_footer(cal_make_s *b)
2005 {
2006         int ret = 0;
2007         RET_IF(NULL == b);
2008
2009         ret = _cal_vcalendar_make_printf(b, "END:VCALENDAR", NULL);
2010         RETM_IF(CALENDAR_ERROR_NONE != ret, "_cal_vcalendar_make_printf() Fail(%d)", ret);
2011 }
2012
2013 static void __make_tz(cal_make_s *b, char *tzid, long long int created)
2014 {
2015         int ret = 0;
2016
2017         RET_IF(NULL == b);
2018         RET_IF(NULL == tzid);
2019         RET_IF('\0' == *tzid);
2020
2021         time_t zone = 0;
2022         time_t dst = 0;
2023         cal_time_get_tz_offset(tzid, &zone, &dst);
2024         DBG("offset zone(%ld), dst (%ld)", zone, dst);
2025
2026         bool in_dst = cal_time_in_dst(tzid, created);
2027         dst = in_dst ? dst : 0; /* dst in TZ is depending on created time */
2028         DBG("tzid[%s] created time(%lld) in_dst(%d)", tzid, created, in_dst);
2029
2030         int h = (zone / 3600) + (dst / 3600);
2031         int m = (zone % 3600) / 60 + (dst % 3600) / 60;
2032
2033         char buf[CAL_STR_SHORT_LEN32] = {0};
2034         snprintf(buf, sizeof(buf), "TZ:%s%02d:%02d",
2035                         h == 0 ? "" : (h < 0 ? "-" : "+"),
2036                         h < 0 ? (-1 * h) : h, m < 0 ? (-1 * m) : m);
2037
2038         ret = _cal_vcalendar_make_printf(b, buf, NULL);
2039         RETM_IF(CALENDAR_ERROR_NONE != ret, "_cal_vcalendar_make_printf() Fail");
2040         DBG("append tzid[%s]", buf);
2041 }
2042
2043 static void __devide_vcalendar_with_header(cal_make_s *b, calendar_record_h record)
2044 {
2045         RET_IF(NULL == b);
2046         RET_IF(NULL == record);
2047
2048         if (2 == b->version)
2049                 return;
2050
2051         int ret = 0;
2052         char *uri = NULL;
2053         ret = calendar_record_get_uri_p(record, &uri);
2054         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_uri_p() Fail(%d)", ret);
2055
2056         char *tzid = NULL;
2057         long long int created = 0;
2058
2059         switch (b->type) {
2060         case CALENDAR_BOOK_TYPE_EVENT:
2061                 ret = calendar_record_get_str_p(record, _calendar_event.start_tzid, &tzid);
2062                 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
2063                 ret = calendar_record_get_lli(record, _calendar_event.created_time, &created);
2064                 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_lli() Fail(%d)", ret);
2065                 break;
2066         case CALENDAR_BOOK_TYPE_TODO:
2067                 ret = calendar_record_get_str_p(record, _calendar_todo.due_tzid, &tzid);
2068                 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
2069                 ret = calendar_record_get_lli(record, _calendar_todo.created_time, &created);
2070                 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_lli() Fail(%d)", ret);
2071                 break;
2072         }
2073
2074         if (NULL == tzid || '\0' == *tzid) {
2075                 DBG("No tzid");
2076                 return;
2077         }
2078
2079         if (NULL == b->timezone_tzid || '\0' == *b->timezone_tzid) {
2080                 /* new start of vcalendar */
2081                 __make_tz(b, tzid, created);
2082                 b->timezone_tzid = strdup(tzid);
2083         } else {
2084                 /* not first vcalendar */
2085                 if (0 != strncmp(b->timezone_tzid, tzid, strlen(tzid))) {
2086                         /* different tzid */
2087                         __make_footer(b);
2088                         __append_header(b);
2089                         __make_tz(b, tzid, created);
2090                         if (b->timezone_tzid)
2091                                 free(b->timezone_tzid);
2092                         b->timezone_tzid = strdup(tzid);
2093                 } else {
2094                         DBG("same as before, skip");
2095                 }
2096         }
2097 }
2098 static int __make_vcalendar(cal_make_s *b, calendar_list_h list)
2099 {
2100         RETV_IF(NULL == b, CALENDAR_ERROR_INVALID_PARAMETER);
2101         RETV_IF(NULL == list, CALENDAR_ERROR_INVALID_PARAMETER);
2102
2103         bool valid_count = 0;
2104         int ret = CALENDAR_ERROR_NONE;
2105         calendar_record_h record = NULL;
2106
2107         __append_header(b);
2108
2109         ret = calendar_list_first(list);
2110         RETVM_IF(CALENDAR_ERROR_NONE != ret, ret, "calendar_list_first() Fail");
2111         do {
2112                 ret = calendar_list_get_current_record_p(list, &record);
2113                 if (CALENDAR_ERROR_NONE != ret) break;
2114
2115                 char *uri = NULL;
2116                 ret = calendar_record_get_uri_p(record, &uri);
2117                 DBG("uri[%s]", uri);
2118
2119                 if (CAL_STRING_EQUAL == strcmp(uri, _calendar_event._uri)) {
2120                         valid_count++;
2121                         b->type = CALENDAR_BOOK_TYPE_EVENT;
2122                         __devide_vcalendar_with_header(b, record);
2123                         _cal_vcalendar_make_schedule(b, record);
2124
2125                 } else if (CAL_STRING_EQUAL == strcmp(uri, _calendar_todo._uri)) {
2126                         valid_count++;
2127                         b->type = CALENDAR_BOOK_TYPE_TODO;
2128                         __devide_vcalendar_with_header(b, record);
2129                         _cal_vcalendar_make_schedule(b, record);
2130
2131                 } else if (CAL_STRING_EQUAL == strcmp(uri, _calendar_extended_property._uri)) {
2132                         cal_extended_s *extended = (cal_extended_s *)record;
2133                         if (CAL_STRING_EQUAL == strncmp(extended->key, "VERSION", strlen("VERSION"))) continue;
2134
2135                         ret = _cal_vcalendar_make_printf(b, extended->key, extended->value);
2136                         if (CALENDAR_ERROR_NONE != ret) break;
2137
2138                         DBG("extended key[%s] value[%s]", extended->key, extended->value);
2139
2140                 } else if (CAL_STRING_EQUAL == strcmp(uri, _calendar_timezone._uri)) {
2141                         DBG("Not support timezone");
2142
2143                 } else if (CAL_STRING_EQUAL == strcmp(uri, _calendar_book._uri)) {
2144                         DBG("Not support calendar");
2145
2146                 } else {
2147                         DBG("Unable to understand uri[%s]", uri);
2148                 }
2149
2150         } while (CALENDAR_ERROR_NO_DATA != calendar_list_next(list));
2151
2152         if (0 == valid_count) {
2153                 DBG("There is no valid records");
2154                 return CALENDAR_ERROR_INVALID_PARAMETER;
2155         }
2156
2157         __make_footer(b);
2158
2159         return CALENDAR_ERROR_NONE;
2160 }
2161
2162 int cal_vcalendar_make_vcalendar(cal_make_s *b, calendar_list_h list)
2163 {
2164         RETV_IF(NULL == list, CALENDAR_ERROR_INVALID_PARAMETER);
2165
2166         int ret = CALENDAR_ERROR_NONE;
2167         calendar_record_h record = NULL;
2168
2169         int version = 2; /* set default as ver 2.0 */
2170
2171         ret = calendar_list_first(list);
2172         RETVM_IF(CALENDAR_ERROR_NONE != ret, ret, "calendar_list_first() Fail");
2173         do {
2174                 ret = calendar_list_get_current_record_p(list, &record);
2175                 if (CALENDAR_ERROR_NONE != ret) break;
2176
2177                 char *uri = NULL;
2178                 ret = calendar_record_get_uri_p(record, &uri);
2179                 if (CALENDAR_ERROR_NONE != ret) break;
2180
2181                 if (CAL_STRING_EQUAL == strcmp(uri, _calendar_extended_property._uri)) {
2182                         cal_extended_s *extended = (cal_extended_s *)record;
2183                         if (CAL_STRING_EQUAL == strncmp(extended->key, "VERSION", strlen("VERSION"))) {
2184                                 version = strstr(extended->value, "1.0") ? 1 : 2;
2185                                 break;
2186                         }
2187                 }
2188         } while (CALENDAR_ERROR_NO_DATA != calendar_list_next(list));
2189         b->version = version;
2190         DBG("make as version(%d)", version);
2191
2192         return __make_vcalendar(b, list);
2193 }