bb9312083ba7384cda0b2400721a2d47d67944f9
[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                 ERR("g_strsplit_set() Fail");
504                 g_strfreev(t);
505                 return 0;
506         }
507         int len = strlen(buf);
508         int tlen = g_strv_length(t);
509         int i;
510         for (i = 0; i < tlen; i++) {
511                 if (*t[i] == '\0')
512                         continue;
513
514                 int num = atoi(t[i]);
515                 ret += snprintf(buf +len +ret, buf_len -len -ret, "%d%s",
516                                 num < 0 ? (-1 * num) : num, num < 0 ? "- " : " ");
517         }
518         g_strfreev(t);
519
520         return ret;
521 }
522
523 static void _cal_vcalendar_make_rrule_append_setpos(calendar_record_h record, char *buf, int buf_len)
524 {
525         RET_IF(NULL == buf);
526
527         int ret = CALENDAR_ERROR_NONE;
528         char *bysetpos = NULL;
529
530         ret = calendar_record_get_str_p(record, _calendar_event.bysetpos, &bysetpos);
531         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() failed(%d)", ret);
532
533         int blen = strlen(buf);
534         if (bysetpos && '\0' != bysetpos[0]) {
535                 /* in ver1.0, "3, 5, -4" -> "3+ 5+ 4-" */
536                 char **t = NULL;
537                 t = g_strsplit_set(bysetpos, " ,", -1);
538
539                 int len = g_strv_length(t);
540
541                 int i;
542                 for (i = 0; i < len; i++) {
543                         if (*t[i] == '\0') continue;
544
545                         int setpos = atoi(t[i]);
546                         DBG("%d", setpos);
547
548                         if (setpos == 0) {
549                                 DBG("Invalid setpos(0)");
550                                 continue;
551                         }
552                         blen += snprintf(buf +blen, buf_len -blen, "%d%s ", setpos * (setpos < 0 ? -1 : 1), setpos < 0 ? "-" : "+");
553                 }
554                 g_strfreev(t);
555         } else {
556                 /* in ver2.0, 3TH should be changed to setpos:3, byday:TH */
557                 char *byday = NULL;
558                 ret = calendar_record_get_str_p(record, _calendar_event.byday, &byday);
559                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
560                 if (NULL == byday || '\0' == byday[0]) {
561                         blen += snprintf(buf +blen, buf_len -blen, "%s", "1+ ");
562                         return;
563                 }
564
565                 int len = strlen(byday);
566
567                 bool is_working = true;
568                 bool is_extracted = false;
569                 int i = 0;
570                 int digit = 0;
571                 int sign = 0;
572                 while (i <= len) {
573                         /* extract -1, 1 from 1SU,-1SU */
574                         if ('1' <= byday[i] && byday[i] <= '9') {
575                                 is_working = false;
576                                 digit++;
577                         } else if ('+' == byday[i]) {
578                                 is_working = false;
579                                 sign = 1;
580                         } else if ('-' == byday[i]) {
581                                 is_working = false;
582                                 sign = -1;
583                         } else {
584                                 if (false == is_working) {
585                                         is_extracted = true;
586                                         is_working = true;
587                                         char num[CAL_STR_SHORT_LEN32] = {0};
588                                         snprintf(num, digit +1, "%s", byday +i -digit);
589                                         if (NULL == strstr(buf, num))
590                                                 blen += snprintf(buf +blen, buf_len -blen, "%s%c ", num, (-1 == sign) ? '-' : '+');
591
592                                         digit = 0;
593                                         sign = 0;
594                                 }
595                         }
596                         i++;
597                 }
598                 if (false == is_extracted) {
599                         blen += snprintf(buf +blen, buf_len -blen, "%s", "1+ ");
600                         return;
601                 }
602         }
603 }
604
605 /*
606  * 2WE 3FR in ver2.0 is not converted to ver1.0
607  * because three is no +2 WE +3 FR.
608  */
609 void _cal_vcalendar_make_rrule_append_text_wday(int rrule_type, char *buf, int buf_len, char *wday)
610 {
611         RET_IF(NULL == buf);
612
613         int i, j;
614         int length = 0;
615         char **t = NULL;
616         char *p = NULL;
617
618         int len = strlen(buf);
619         t = g_strsplit_set(wday, " ,", -1);
620         if (!t) {
621                 ERR("g_strsplit_set() Fail");
622                 g_strfreev(t);
623                 return;
624         }
625         length = g_strv_length(t);
626
627         for (i = 0; i < length; i++) {
628                 if (*t[i] == '\0')
629                         continue;
630
631                 p = t[i];
632                 /* del space */
633                 while (*p == ' ')
634                         p++;
635
636                 /* get number length */
637                 j = 0;
638                 while (p[j] == '+' || p[j] == '-' || ('1' <= p[j] && p[j] <= '9'))
639                         j++;
640
641                 /* already appended */
642                 if (strstr(buf, p +j))
643                         continue;
644
645                 len += snprintf(buf +len, buf_len -len, "%s ", p +j);
646         }
647         g_strfreev(t);
648
649         return;
650 }
651
652 void _cal_vcalendar_make_rrule_append_wkst(char *buf, int buf_len, calendar_record_h record)
653 {
654         const char wday[7][3] = {"SU", "MO", "TU", "WE", "TH", "FR", "SA"};
655         int wkst = 0;
656         calendar_record_get_int(record, _calendar_event.wkst, &wkst);
657         if (wkst < CALENDAR_SUNDAY || CALENDAR_SATURDAY < wkst)
658                 return;
659
660         DBG("wkst(%d) [%s]", wkst, wday[wkst - 1]);
661         int len = strlen(buf);
662         snprintf(buf +len, buf_len -len, "WKST=%s ", wday[wkst - 1]);
663 }
664
665 int _cal_vcalendar_make_rrule_append_wday(int rrule_type, char *buf, int buf_len, char *wday)
666 {
667         RETV_IF(NULL == buf, CALENDAR_ERROR_INVALID_PARAMETER);
668
669         int i, j;
670         int num = 0, num_past;
671         int length = 0;
672         char **t = NULL;
673         char *p = NULL;
674         char buf_temp[8] = {0};
675
676         RETV_IF(NULL == buf, CALENDAR_ERROR_INVALID_PARAMETER);
677         RETV_IF(NULL == wday, CALENDAR_ERROR_INVALID_PARAMETER);
678
679         int len = strlen(buf);
680
681         num_past = 0;
682         t = g_strsplit_set(wday, " ,", -1);
683         if (!t) {
684                 ERR("g_strsplit_set() Fail");
685                 g_strfreev(t);
686                 return CALENDAR_ERROR_OUT_OF_MEMORY;
687         }
688         length = g_strv_length(t);
689         DBG("len(%d)", length);
690
691         for (i = 0; i < length; i++) {
692                 if (*t[i] == '\0') continue;
693
694                 p = t[i];
695
696                 /* get number */
697                 j = 0;
698                 while (p[j] == '+' || p[j] == '-' || ('1' <= p[j] && p[j] <= '9'))
699                         j++;
700
701                 if (0 < j) {
702                         if (CALENDAR_RECURRENCE_WEEKLY == rrule_type) {
703                                 num_past = num;
704                         } else {
705                                 if (*p == '-') {
706                                         snprintf(buf_temp, j + 1, "%s", p + 1);
707                                         num = atoi(buf_temp);
708                                         if (0 == i) {
709                                                 num_past = num;
710                                                 len += snprintf(buf +len, buf_len -len, "%s- ", buf_temp);
711                                         }
712                                 } else {
713                                         snprintf(buf_temp, j + 1, "%s", p);
714                                         num = atoi(buf_temp);
715                                         if (0 == i) {
716                                                 num_past = num;
717                                                 len += snprintf(buf +len, buf_len -len, "%s+ ", buf_temp);
718                                         }
719                                 }
720                         }
721                         if (num_past == num)
722                                 len += snprintf(buf +len, buf_len -len, "%s ", p +j);
723                          else
724                                 ERR("Out of 1.0 spec");
725
726                         DBG("%d num(%d) val[%s]", i, num, p + j);
727                 } else {
728                         len += snprintf(buf +len, buf_len -len, "%s ", p);
729                 }
730                 DBG("[%s]", buf);
731         }
732         g_strfreev(t);
733
734         return CALENDAR_ERROR_NONE;
735 }
736
737 static void __make_begin(cal_make_s *b, calendar_record_h record)
738 {
739         RET_IF(NULL == b);
740         RET_IF(NULL == record);
741
742         int ret = 0;
743         switch (b->type) {
744         case CALENDAR_BOOK_TYPE_EVENT:
745                 ret = _cal_vcalendar_make_printf(b, "BEGIN:VEVENT", NULL);
746                 RETM_IF(CALENDAR_ERROR_NONE != ret, "_cal_vcalendar_make_printf() Fail(%d)", ret);
747                 break;
748         case CALENDAR_BOOK_TYPE_TODO:
749                 ret = _cal_vcalendar_make_printf(b, "BEGIN:VTODO", NULL);
750                 RETM_IF(CALENDAR_ERROR_NONE != ret, "_cal_vcalendar_make_printf() Fail(%d)", ret);
751                 break;
752         }
753 }
754
755 static void __make_dtstart(cal_make_s *b, calendar_record_h record)
756 {
757         RET_IF(NULL == b);
758         RET_IF(NULL == record);
759
760         int ret = 0;
761         char *tzid = NULL;
762         calendar_time_s ct = {0};
763         switch (b->type) {
764         case CALENDAR_BOOK_TYPE_EVENT:
765                 ret = calendar_record_get_str_p(record, _calendar_event.start_tzid, &tzid);
766                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
767                 ret = calendar_record_get_caltime(record, _calendar_event.start_time, &ct);
768                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_caltime() Fail(%d)", ret);
769                 break;
770         case CALENDAR_BOOK_TYPE_TODO:
771                 ret = calendar_record_get_str_p(record, _calendar_todo.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_todo.start_time, &ct);
774                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_caltime() Fail(%d)", ret);
775                 break;
776         }
777         _cal_vcalendar_make_time(b, tzid, &ct, "DTSTART");
778 }
779
780 static void __make_dtend(cal_make_s *b, calendar_record_h record)
781 {
782         RET_IF(NULL == b);
783         RET_IF(NULL == record);
784
785         int ret = 0;
786         char *tzid = NULL;
787         calendar_time_s ct = {0};
788         switch (b->type) {
789         case CALENDAR_BOOK_TYPE_EVENT:
790                 ret = calendar_record_get_str_p(record, _calendar_event.end_tzid, &tzid);
791                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
792                 ret = calendar_record_get_caltime(record, _calendar_event.end_time, &ct);
793                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_caltime() Fail(%d)", ret);
794                 _cal_vcalendar_make_time(b, tzid, &ct, "DTEND");
795                 break;
796         case CALENDAR_BOOK_TYPE_TODO:
797                 ret = calendar_record_get_str_p(record, _calendar_todo.due_tzid, &tzid);
798                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
799                 ret = calendar_record_get_caltime(record, _calendar_todo.due_time, &ct);
800                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_caltime() Fail(%d)", ret);
801                 _cal_vcalendar_make_time(b, tzid, &ct, "DUE");
802                 break;
803         }
804 }
805
806 static void __make_sensitivity(cal_make_s *b, calendar_record_h record)
807 {
808         RET_IF(NULL == b);
809         RET_IF(NULL == record);
810
811         int ret = 0;
812         int value = 0;
813         switch (b->type) {
814         case CALENDAR_BOOK_TYPE_EVENT:
815                 ret = calendar_record_get_int(record, _calendar_event.sensitivity, &value);
816                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
817                 break;
818         case CALENDAR_BOOK_TYPE_TODO:
819                 ret = calendar_record_get_int(record, _calendar_todo.sensitivity, &value);
820                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
821                 break;
822         }
823         char *sensitivity = NULL;
824         switch (value) {
825         case CALENDAR_SENSITIVITY_PUBLIC:
826                 sensitivity = "PUBLIC";
827                 break;
828         case CALENDAR_SENSITIVITY_PRIVATE:
829                 sensitivity = "PRIVATE";
830                 break;
831         case CALENDAR_SENSITIVITY_CONFIDENTIAL:
832                 sensitivity = "CONFIDENTIAL";
833                 break;
834         default:
835                 ERR("Invalid sensitivity(%d)", value);
836                 return;
837         }
838         _cal_vcalendar_make_printf(b, "CLASS:", sensitivity);
839 }
840
841 int _cal_vcalendar_make_rrule_append_until(char *buf, int buf_len, calendar_record_h record)
842 {
843         int ret;
844         int range_type = 0;
845         int count;
846         char *until_str = NULL;
847         calendar_time_s caltime;
848
849         ret = calendar_record_get_int(record, _calendar_event.range_type, &range_type);
850         if (CALENDAR_ERROR_NONE != ret) {
851                 ERR("calendar_record_get_int() Fail");
852                 return ret;
853         }
854
855         int len = strlen(buf);
856         switch (range_type) {
857         case CALENDAR_RANGE_COUNT:
858                 ret = calendar_record_get_int(record, _calendar_event.count, &count);
859                 if (CALENDAR_ERROR_NONE != ret) {
860                         ERR("calendar_record_get_int() Fail");
861                         return ret;
862                 }
863                 snprintf(buf +len, buf_len -len, "#%d", count);
864                 break;
865
866         case CALENDAR_RANGE_UNTIL:
867                 memset(&caltime, 0x0, sizeof(calendar_time_s));
868
869                 ret = calendar_record_get_caltime(record, _calendar_event.until_time, &caltime);
870                 if (CALENDAR_ERROR_NONE != ret) {
871                         ERR("calendar_record_get_caltime() Fail");
872                         return ret;
873                 }
874                 switch (caltime.type) {
875                 case CALENDAR_TIME_UTIME:
876                         until_str = cal_time_convert_ltos(NULL, caltime.time.utime, 0);
877                         snprintf(buf +len, buf_len -len, "%s", until_str);
878                         CAL_FREE(until_str);
879                         break;
880
881                 case CALENDAR_TIME_LOCALTIME:
882                         snprintf(buf +len, buf_len -len, CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSS,
883                                         caltime.time.date.year, caltime.time.date.month, caltime.time.date.mday,
884                                         caltime.time.date.hour, caltime.time.date.minute, caltime.time.date.second);
885                         break;
886                 }
887                 break;
888
889         case CALENDAR_RANGE_NONE:
890                 snprintf(buf +len, buf_len -len, "%s", "#0");
891                 break;
892         }
893         return CALENDAR_ERROR_NONE;
894 }
895 static void __make_rrule_ver1_default(calendar_record_h record, int freq, int interval, char *buf, int buf_size)
896 {
897         RET_IF(NULL == record);
898
899         int ret = 0;
900         calendar_time_s caltime = {0};
901         ret = calendar_record_get_caltime(record, _calendar_event.start_time, &caltime);
902         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_caltime() Fail(%d)", ret);
903
904         switch (freq) {
905         case CALENDAR_RECURRENCE_YEARLY:
906                 snprintf(buf, buf_size, "YD%d ", interval);
907                 break;
908         case CALENDAR_RECURRENCE_MONTHLY:
909                 snprintf(buf, buf_size, "MD%d ", interval);
910                 break;
911         }
912
913         char *tzid = NULL;
914         int d = 0;
915         switch (caltime.type) {
916         case CALENDAR_TIME_UTIME:
917                 calendar_record_get_str_p(record, _calendar_event.start_tzid, &tzid);
918                 cal_time_get_local_datetime(tzid, caltime.time.utime, NULL, NULL, &d, NULL, NULL, NULL);
919                 break;
920         case CALENDAR_TIME_LOCALTIME:
921                 d = caltime.time.date.mday;
922                 break;
923         }
924         char mday[CAL_STR_SHORT_LEN32] = {0};
925         snprintf(mday, sizeof(mday), "%d", d);
926         _cal_vcalendar_make_rrule_append_mday(buf, buf_size, mday);
927 }
928
929 static void __make_rrule_ver1(cal_make_s *b, calendar_record_h record)
930 {
931         RET_IF(NULL == b);
932         RET_IF(NULL == record);
933
934         int ret = 0;
935         char buf[CAL_STR_MIDDLE_LEN] = {0};
936
937         int freq = 0;
938         ret = calendar_record_get_int(record, _calendar_event.freq, &freq);
939         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
940
941         int interval = 1;
942         ret = calendar_record_get_int(record, _calendar_event.interval, &interval);
943         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
944         interval = 0 < interval ? interval : 1;
945
946         char *byyearday = NULL;
947         ret = calendar_record_get_str_p(record, _calendar_event.byyearday, &byyearday);
948         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
949
950         char *bymonth = NULL;
951         ret = calendar_record_get_str_p(record, _calendar_event.bymonth, &bymonth);
952         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
953
954         char *byday = NULL;
955         ret = calendar_record_get_str_p(record, _calendar_event.byday, &byday);
956         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
957
958         char *bymonthday = NULL;
959         ret = calendar_record_get_str_p(record, _calendar_event.bymonthday, &bymonthday);
960         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
961
962         int len = 0;
963         switch (freq) {
964         case CALENDAR_RECURRENCE_YEARLY:
965                 if (bymonth && *bymonth) {
966                         DBG("bymonth[%s]", bymonth);
967                         len += snprintf(buf +len, sizeof(buf) -len, "YM%d ", interval);
968                         len += _cal_vcalendar_make_rrule_append_mday(buf, sizeof(buf), bymonth);
969
970                         if (byday && *byday) {
971                                 DBG("byday");
972                                 /* ex> YM1 6 MP1 1+ TH */
973                                 len += snprintf(buf +len, sizeof(buf) -len, "MP%d ", interval);
974                                 _cal_vcalendar_make_rrule_append_setpos(record, buf, sizeof(buf));
975                                 _cal_vcalendar_make_rrule_append_text_wday(CALENDAR_RECURRENCE_MONTHLY, buf, sizeof(buf), byday);
976                         } else if (bymonthday && *bymonthday) {
977                                 DBG("bymonthday");
978                                 /* ex> YM1 2 MD 1 */
979                                 len += snprintf(buf +len, sizeof(buf) -len, "MD%d ", interval);
980                                 _cal_vcalendar_make_rrule_append_mday(buf, sizeof(buf), bymonthday);
981                         } else {
982                                 ERR("Out of scope");
983                                 __make_rrule_ver1_default(record, freq, interval, buf, sizeof(buf));
984                         }
985                 } else if (byyearday && *byyearday) {
986                         DBG("byyearday");
987                         snprintf(buf, sizeof(buf), "YD%d ", interval);
988                         _cal_vcalendar_make_rrule_append_mday(buf, sizeof(buf), byyearday);
989                 } else {
990                         ERR("Out of scope");
991                         __make_rrule_ver1_default(record, freq, interval, buf, sizeof(buf));
992                 }
993                 break;
994
995         case CALENDAR_RECURRENCE_MONTHLY:
996                 if (byday && *byday) {
997                         DBG("byday");
998                         snprintf(buf, sizeof(buf), "MP%d ", interval);
999                         _cal_vcalendar_make_rrule_append_setpos(record, buf, sizeof(buf));
1000                         _cal_vcalendar_make_rrule_append_text_wday(CALENDAR_RECURRENCE_MONTHLY, buf, sizeof(buf), byday);
1001                 } else if (bymonthday && *bymonthday) {
1002                         DBG("bymonthday");
1003                         snprintf(buf, sizeof(buf), "MD%d ", interval);
1004                         _cal_vcalendar_make_rrule_append_mday(buf, sizeof(buf), bymonthday);
1005                 } else {
1006                         ERR("Out of scope, so set as bymonthday");
1007                         __make_rrule_ver1_default(record, freq, interval, buf, sizeof(buf));
1008                 }
1009                 break;
1010
1011         case CALENDAR_RECURRENCE_WEEKLY:
1012                 snprintf(buf, sizeof(buf), "W%d ", interval);
1013                 _cal_vcalendar_make_rrule_append_wday(CALENDAR_RECURRENCE_WEEKLY, buf, sizeof(buf), byday);
1014                 break;
1015
1016         case CALENDAR_RECURRENCE_DAILY:
1017                 snprintf(buf, sizeof(buf), "D%d ", interval);
1018                 break;
1019
1020         default:
1021                 ERR("Out of scope");
1022                 break;
1023         }
1024
1025         if (*buf) {
1026                 _cal_vcalendar_make_rrule_append_wkst(buf, sizeof(buf), record);
1027                 _cal_vcalendar_make_rrule_append_until(buf, sizeof(buf), record);
1028                 _cal_vcalendar_make_printf(b, "RRULE:", buf);
1029         }
1030 }
1031
1032 static void __make_rrule_ver2(cal_make_s *b, calendar_record_h record)
1033 {
1034         RET_IF(NULL == b);
1035         RET_IF(NULL == record);
1036
1037         int ret = 0;
1038         char *text = NULL;
1039         char tmp[CAL_STR_SHORT_LEN32] = {0};
1040         calendar_time_s caltime = {0};
1041
1042         int freq = 0;
1043         ret = calendar_record_get_int(record, _calendar_event.freq, &freq);
1044         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
1045
1046         switch (freq) {
1047         case CALENDAR_RECURRENCE_DAILY:
1048                 _cal_vcalendar_make_set_str(b, "RRULE:FREQ=DAILY");
1049                 break;
1050         case CALENDAR_RECURRENCE_WEEKLY:
1051                 _cal_vcalendar_make_set_str(b, "RRULE:FREQ=WEEKLY");
1052                 break;
1053         case CALENDAR_RECURRENCE_MONTHLY:
1054                 _cal_vcalendar_make_set_str(b, "RRULE:FREQ=MONTHLY");
1055                 break;
1056         case CALENDAR_RECURRENCE_YEARLY:
1057                 _cal_vcalendar_make_set_str(b, "RRULE:FREQ=YEARLY");
1058                 break;
1059         default:
1060                 return;
1061         }
1062
1063         int interval = 1;
1064         ret = calendar_record_get_int(record, _calendar_event.interval, &interval);
1065         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
1066         interval = 0 < interval ? interval : 1;
1067         snprintf(tmp, sizeof(tmp), ";INTERVAL=%d", interval);
1068         _cal_vcalendar_make_set_str(b, tmp);
1069
1070         ret = calendar_record_get_str_p(record, _calendar_event.bysecond, &text);
1071         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1072         if (text && *text) {
1073                 DBG("BYSECOND= [%s]", text);
1074                 _cal_vcalendar_make_set_str(b, ";BYSECOND=");
1075                 _cal_vcalendar_make_set_str(b, text);
1076                 text = NULL;
1077         }
1078
1079         ret = calendar_record_get_str_p(record, _calendar_event.byminute, &text);
1080         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1081         if (text && *text) {
1082                 DBG("BYMINUTE= [%s]", text);
1083                 _cal_vcalendar_make_set_str(b, ";BYMINUTE=");
1084                 _cal_vcalendar_make_set_str(b, text);
1085                 text = NULL;
1086         }
1087
1088         ret = calendar_record_get_str_p(record, _calendar_event.byhour, &text);
1089         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1090         if (text && *text) {
1091                 DBG("BYHOUR= [%s]", text);
1092                 _cal_vcalendar_make_set_str(b, ";BYHOUR=");
1093                 _cal_vcalendar_make_set_str(b, text);
1094                 text = NULL;
1095         }
1096
1097         ret = calendar_record_get_str_p(record, _calendar_event.byday, &text);
1098         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1099         if (text && *text) {
1100                 DBG("BYDAY= [%s]", text);
1101                 _cal_vcalendar_make_set_str(b, ";BYDAY=");
1102                 _cal_vcalendar_make_set_str(b, text);
1103                 text = NULL;
1104         }
1105
1106         ret = calendar_record_get_str_p(record, _calendar_event.bymonthday, &text);
1107         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1108         if (text && *text) {
1109                 DBG("BYMONTHDAY= [%s]", text);
1110                 _cal_vcalendar_make_set_str(b, ";BYMONTHDAY=");
1111                 _cal_vcalendar_make_set_str(b, text);
1112                 text = NULL;
1113         }
1114
1115         ret = calendar_record_get_str_p(record, _calendar_event.byyearday, &text);
1116         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1117         if (text && *text) {
1118                 DBG("BYYEARDAY= [%s]", text);
1119                 _cal_vcalendar_make_set_str(b, ";BYYEARDAY=");
1120                 _cal_vcalendar_make_set_str(b, text);
1121                 text = NULL;
1122         }
1123
1124         ret = calendar_record_get_str_p(record, _calendar_event.byweekno, &text);
1125         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1126         if (text && *text) {
1127                 DBG("BYWEEKNO= [%s]", text);
1128                 _cal_vcalendar_make_set_str(b, ";BYWEEKNO=");
1129                 _cal_vcalendar_make_set_str(b, text);
1130                 text = NULL;
1131         }
1132
1133         ret = calendar_record_get_str_p(record, _calendar_event.bymonth, &text);
1134         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1135         if (text && *text) {
1136                 DBG("BYMONTH= [%s]", text);
1137                 _cal_vcalendar_make_set_str(b, ";BYMONTH=");
1138                 _cal_vcalendar_make_set_str(b, text);
1139                 text = NULL;
1140         }
1141
1142         ret = calendar_record_get_str_p(record, _calendar_event.bysetpos, &text);
1143         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1144         if (text && *text) {
1145                 DBG("BYSETPOS= [%s]", text);
1146                 _cal_vcalendar_make_set_str(b, ";BYSETPOS=");
1147                 _cal_vcalendar_make_set_str(b, text);
1148                 text = NULL;
1149         }
1150
1151         int wkst = 0;
1152         ret = calendar_record_get_int(record, _calendar_event.wkst, &wkst);
1153         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
1154         if (CALENDAR_SUNDAY <= wkst && wkst <= CALENDAR_SATURDAY) {
1155                 _cal_vcalendar_make_set_str(b, ";WKST=");
1156                 switch (wkst) {
1157                 case CALENDAR_SUNDAY:
1158                         _cal_vcalendar_make_set_str(b, "SU");
1159                         break;
1160                 case CALENDAR_MONDAY:
1161                         _cal_vcalendar_make_set_str(b, "MO");
1162                         break;
1163                 case CALENDAR_TUESDAY:
1164                         _cal_vcalendar_make_set_str(b, "TU");
1165                         break;
1166                 case CALENDAR_WEDNESDAY:
1167                         _cal_vcalendar_make_set_str(b, "WE");
1168                         break;
1169                 case CALENDAR_THURSDAY:
1170                         _cal_vcalendar_make_set_str(b, "TH");
1171                         break;
1172                 case CALENDAR_FRIDAY:
1173                         _cal_vcalendar_make_set_str(b, "FR");
1174                         break;
1175                 case CALENDAR_SATURDAY:
1176                         _cal_vcalendar_make_set_str(b, "SA");
1177                         break;
1178                 }
1179         }
1180
1181         int range_type = 0;
1182         int count = 0;
1183         ret = calendar_record_get_int(record, _calendar_event.range_type, &range_type);
1184         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
1185         switch (range_type) {
1186         case CALENDAR_RANGE_COUNT:
1187                 ret = calendar_record_get_int(record, _calendar_event.count, &count);
1188                 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
1189                 snprintf(tmp, sizeof(tmp), ";COUNT=%d", count);
1190                 _cal_vcalendar_make_set_str(b, tmp);
1191                 DBG("count [%s]", tmp);
1192                 break;
1193
1194         case CALENDAR_RANGE_UNTIL:
1195                 ret = calendar_record_get_caltime(record, _calendar_event.until_time, &caltime);
1196                 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_caltime() Fail(%d)", ret);
1197
1198                 if (caltime.type == CALENDAR_TIME_UTIME) {
1199                         char *tmp_tzid = NULL;
1200                         tmp_tzid = cal_time_convert_ltos(NULL, caltime.time.utime, 0);
1201                         if (tmp_tzid) {
1202                                 snprintf(tmp, sizeof(tmp), ";UNTIL=%s", tmp_tzid);
1203                                 CAL_FREE(tmp_tzid);
1204                         }
1205                 } else {
1206                         snprintf(tmp, sizeof(tmp), ";UNTIL="CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSSZ,
1207                                         caltime.time.date.year,
1208                                         caltime.time.date.month,
1209                                         caltime.time.date.mday,
1210                                         caltime.time.date.hour,
1211                                         caltime.time.date.minute,
1212                                         caltime.time.date.second);
1213                 }
1214                 _cal_vcalendar_make_set_str(b, tmp);
1215                 DBG("until [%s]", tmp);
1216                 break;
1217
1218         case CALENDAR_RANGE_NONE:
1219                 DBG("No range");
1220                 break;
1221         }
1222         _cal_vcalendar_make_flush(b);
1223 }
1224
1225 static void __make_rrule(cal_make_s *b, calendar_record_h record)
1226 {
1227         RET_IF(NULL == b);
1228         RET_IF(NULL == record);
1229
1230         switch (b->type) {
1231         case CALENDAR_BOOK_TYPE_EVENT:
1232                 switch (b->version) {
1233                 case VCAL_VER_1:
1234                         __make_rrule_ver1(b, record);
1235                         break;
1236                 case VCAL_VER_2:
1237                         __make_rrule_ver2(b, record);
1238                         break;
1239                 }
1240                 break;
1241         case CALENDAR_BOOK_TYPE_TODO:
1242                 ERR("No rrule in todo");
1243                 return;
1244         }
1245 }
1246
1247 int _cal_vcalendar_make_attendee(cal_make_s *b, calendar_record_h attendee)
1248 {
1249         int ret;
1250
1251         RETV_IF(NULL == attendee, CALENDAR_ERROR_INVALID_PARAMETER);
1252
1253         ret = _cal_vcalendar_make_set_str(b, "ATTENDEE");
1254         RETV_IF(CALENDAR_ERROR_NONE != ret, ret);
1255
1256         int cutype = 0;
1257         ret = calendar_record_get_int(attendee, _calendar_attendee.cutype, &cutype);
1258         ret = _cal_vcalendar_make_set_str(b, ";CUTYPE=");
1259         switch (cutype) {
1260         case CALENDAR_ATTENDEE_CUTYPE_INDIVIDUAL:
1261                 ret = _cal_vcalendar_make_set_str(b, "INDIVIDUAL");
1262                 break;
1263         case CALENDAR_ATTENDEE_CUTYPE_GROUP:
1264                 ret = _cal_vcalendar_make_set_str(b, "GROUP");
1265                 break;
1266         case CALENDAR_ATTENDEE_CUTYPE_RESOURCE:
1267                 ret = _cal_vcalendar_make_set_str(b, "RESOURCE");
1268                 break;
1269         case CALENDAR_ATTENDEE_CUTYPE_ROOM:
1270                 ret = _cal_vcalendar_make_set_str(b, "ROOM");
1271                 break;
1272         case CALENDAR_ATTENDEE_CUTYPE_UNKNOWN:
1273                 ret = _cal_vcalendar_make_set_str(b, "UNKNOWN");
1274                 break;
1275         }
1276         RETV_IF(CALENDAR_ERROR_NONE != ret, ret);
1277
1278         char *member = NULL;
1279         ret = calendar_record_get_str_p(attendee, _calendar_attendee.member, &member);
1280         if (member && *member) {
1281                 ret = _cal_vcalendar_make_set_str(b, ";MEMBER=");
1282                 ret = _cal_vcalendar_make_set_str(b, member);
1283                 RETV_IF(CALENDAR_ERROR_NONE != ret, ret);
1284         }
1285
1286         int role = 0;
1287         ret = calendar_record_get_int(attendee, _calendar_attendee.role, &role);
1288         {
1289                 ret = _cal_vcalendar_make_set_str(b, ";ROLE=");
1290                 ret = _cal_vcalendar_make_set_str(b, _att_role[role]);
1291                 RETV_IF(CALENDAR_ERROR_NONE != ret, ret);
1292         }
1293
1294         int status = 0;
1295         ret = calendar_record_get_int(attendee, _calendar_attendee.status, &status);
1296         {
1297                 ret = _cal_vcalendar_make_set_str(b, ";PARTSTAT=");
1298                 ret = _cal_vcalendar_make_set_str(b, _att_st[status]);
1299                 RETV_IF(CALENDAR_ERROR_NONE != ret, ret);
1300         }
1301
1302         int rsvp = 0;
1303         ret = calendar_record_get_int(attendee, _calendar_attendee.rsvp, &rsvp);
1304         {
1305                 ret = _cal_vcalendar_make_set_str(b, ";RSVP=");
1306                 ret = _cal_vcalendar_make_set_str(b, rsvp ? "TRUE" : "FALSE");
1307                 RETV_IF(CALENDAR_ERROR_NONE != ret, ret);
1308         }
1309
1310         char *delegatee_uri = NULL;
1311         ret = calendar_record_get_str_p(attendee, _calendar_attendee.delegatee_uri, &delegatee_uri);
1312         if (delegatee_uri && *delegatee_uri) {
1313                 ret = _cal_vcalendar_make_set_str(b, ";DELEGATED-TO=");
1314                 ret = _cal_vcalendar_make_set_str(b, delegatee_uri);
1315                 RETV_IF(CALENDAR_ERROR_NONE != ret, ret);
1316         }
1317
1318         char *delegator_uri = NULL;
1319         ret = calendar_record_get_str_p(attendee, _calendar_attendee.delegator_uri, &delegator_uri);
1320         if (delegator_uri && *delegator_uri) {
1321                 ret = _cal_vcalendar_make_set_str(b, ";DELEGATED-FROM=");
1322                 ret = _cal_vcalendar_make_set_str(b, delegator_uri);
1323                 RETV_IF(CALENDAR_ERROR_NONE != ret, ret);
1324         }
1325
1326         /* TODO : No 'sentby' member in cal_participant_info_t */
1327
1328         char *name = NULL;
1329         ret = calendar_record_get_str_p(attendee, _calendar_attendee.name, &name);
1330         if (name && *name) {
1331                 ret = _cal_vcalendar_make_set_str(b, ";CN=");
1332                 ret = _cal_vcalendar_make_set_str(b, name);
1333                 RETV_IF(CALENDAR_ERROR_NONE != ret, ret);
1334         }
1335
1336         char *email = NULL;
1337         ret = calendar_record_get_str_p(attendee, _calendar_attendee.email, &email);
1338         if (email && *email) {
1339                 ret = _cal_vcalendar_make_set_str(b, ":mailto:");
1340                 ret = _cal_vcalendar_make_set_str(b, email);
1341                 RETV_IF(CALENDAR_ERROR_NONE != ret, ret);
1342         }
1343
1344         _cal_vcalendar_make_flush(b);
1345         return CALENDAR_ERROR_NONE;
1346 }
1347
1348 static void __make_attendee(cal_make_s *b, calendar_record_h record)
1349 {
1350         RET_IF(NULL == b);
1351         RET_IF(NULL == record);
1352
1353         int ret = 0;
1354         unsigned int count = 0;
1355         int i;
1356         switch (b->type) {
1357         case CALENDAR_BOOK_TYPE_EVENT:
1358                 ret = calendar_record_get_child_record_count(record, _calendar_event.calendar_attendee, &count);
1359                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_child_record_count() Fail(%d)", ret);
1360                 for (i = 0; i < count; i++) {
1361                         calendar_record_h child = NULL;
1362                         ret = calendar_record_get_child_record_at_p(record, _calendar_event.calendar_attendee, i, &child);
1363                         ret = _cal_vcalendar_make_attendee(b, child);
1364                 }
1365                 break;
1366         case CALENDAR_BOOK_TYPE_TODO:
1367                 ret = calendar_record_get_child_record_count(record, _calendar_todo.calendar_attendee, &count);
1368                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_child_record_count() Fail(%d)", ret);
1369                 for (i = 0; i < count; i++) {
1370                         calendar_record_h child = NULL;
1371                         ret = calendar_record_get_child_record_at_p(record, _calendar_todo.calendar_attendee, i, &child);
1372                         ret = _cal_vcalendar_make_attendee(b, child);
1373                 }
1374                 break;
1375         }
1376 }
1377
1378 static void __make_alarm_ver1(cal_make_s *b, calendar_record_h record)
1379 {
1380         /* In ver 1.0, only first alarm will be dealt with. */
1381         RET_IF(NULL == b);
1382         RET_IF(NULL == record);
1383
1384         int ret = 0;
1385         unsigned int count = 0;
1386         int i;
1387         switch (b->type) {
1388         case CALENDAR_BOOK_TYPE_EVENT:
1389                 ret = calendar_record_get_child_record_count(record, _calendar_event.calendar_alarm, &count);
1390                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_child_record_count() Fail(%d)", ret);
1391                 for (i = 0; i < count; i++) {
1392                         calendar_record_h child = NULL;
1393                         ret = calendar_record_get_child_record_at_p(record, _calendar_event.calendar_alarm, i, &child);
1394                         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_child_record_at_p() Fail(%d)", ret);
1395
1396                         _cal_vcalendar_make_aalarm(b, record, child);
1397                 }
1398                 break;
1399         case CALENDAR_BOOK_TYPE_TODO:
1400                 ret = calendar_record_get_child_record_count(record, _calendar_todo.calendar_alarm, &count);
1401                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_child_record_count() Fail(%d)", ret);
1402                 for (i = 0; i < count; i++) {
1403                         calendar_record_h child = NULL;
1404                         ret = calendar_record_get_child_record_at_p(record, _calendar_todo.calendar_alarm, i, &child);
1405                         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_child_record_at_p() Fail(%d)", ret);
1406
1407                         _cal_vcalendar_make_aalarm(b, record, child);
1408                 }
1409                 break;
1410         }
1411 }
1412
1413 static void __make_alarm_ver2(cal_make_s *b, calendar_record_h record)
1414 {
1415         RET_IF(NULL == b);
1416         RET_IF(NULL == record);
1417
1418         int ret = 0;
1419         unsigned int count = 0;
1420         int i;
1421         switch (b->type) {
1422         case CALENDAR_BOOK_TYPE_EVENT:
1423                 ret = calendar_record_get_child_record_count(record, _calendar_event.calendar_alarm, &count);
1424                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_child_record_count() Fail(%d)", ret);
1425                 for (i = 0; i < count; i++) {
1426                         calendar_record_h child = NULL;
1427                         ret = calendar_record_get_child_record_at_p(record, _calendar_event.calendar_alarm, i, &child);
1428                         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_child_record_at_p() Fail(%d)", ret);
1429
1430                         _cal_vcalendar_make_alarm(b, child);
1431                 }
1432                 break;
1433         case CALENDAR_BOOK_TYPE_TODO:
1434                 ret = calendar_record_get_child_record_count(record, _calendar_todo.calendar_alarm, &count);
1435                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_child_record_count() Fail(%d)", ret);
1436                 for (i = 0; i < count; i++) {
1437                         calendar_record_h child = NULL;
1438                         ret = calendar_record_get_child_record_at_p(record, _calendar_todo.calendar_alarm, i, &child);
1439                         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_child_record_at_p() Fail(%d)", ret);
1440
1441                         _cal_vcalendar_make_alarm(b, child);
1442                 }
1443                 break;
1444         }
1445 }
1446
1447 static void __make_alarm(cal_make_s *b, calendar_record_h record)
1448 {
1449         RET_IF(NULL == b);
1450         RET_IF(NULL == record);
1451
1452         switch (b->type) {
1453         case CALENDAR_BOOK_TYPE_EVENT:
1454                 switch (b->version) {
1455                 case VCAL_VER_1:
1456                         __make_alarm_ver1(b, record);
1457                         break;
1458                 case VCAL_VER_2:
1459                         __make_alarm_ver2(b, record);
1460                         break;
1461                 }
1462                 break;
1463         case CALENDAR_BOOK_TYPE_TODO:
1464                 ERR("No rrule in todo");
1465                 return;
1466         }
1467
1468 }
1469 static void __make_created_time(cal_make_s *b, calendar_record_h record)
1470 {
1471         RET_IF(NULL == b);
1472         RET_IF(NULL == record);
1473
1474         int ret = 0;
1475         long long int value = 0;
1476         switch (b->type) {
1477         case CALENDAR_BOOK_TYPE_EVENT:
1478                 ret = calendar_record_get_lli(record, _calendar_event.created_time, &value);
1479                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_lli() Fail(%d)", ret);
1480                 break;
1481         case CALENDAR_BOOK_TYPE_TODO:
1482                 ret = calendar_record_get_lli(record, _calendar_todo.created_time, &value);
1483                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_lli() Fail(%d)", ret);
1484                 break;
1485         }
1486         int y = 0, m = 0, d = 0;
1487         int h = 0, n = 0, s = 0;
1488         cal_time_get_local_datetime(NULL, value, &y, &m, &d, &h, &n, &s);
1489         char buf[CAL_STR_MIDDLE_LEN] = {0};
1490         snprintf(buf, sizeof(buf), CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSSZ, y, m, d, h, n, s);
1491
1492         switch (b->version) {
1493         case VCAL_VER_1:
1494                 _cal_vcalendar_make_printf(b, "DCREATED:", buf);
1495                 break;
1496         case VCAL_VER_2:
1497                 _cal_vcalendar_make_printf(b, "CREATED:", buf);
1498                 break;
1499         }
1500 }
1501
1502 static void __make_summary(cal_make_s *b, calendar_record_h record)
1503 {
1504         RET_IF(NULL == b);
1505         RET_IF(NULL == record);
1506
1507         int ret = 0;
1508         char *value = NULL;
1509         switch (b->type) {
1510         case CALENDAR_BOOK_TYPE_EVENT:
1511                 ret = calendar_record_get_str_p(record, _calendar_event.summary, &value);
1512                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1513                 break;
1514         case CALENDAR_BOOK_TYPE_TODO:
1515                 ret = calendar_record_get_str_p(record, _calendar_todo.summary, &value);
1516                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1517                 break;
1518         }
1519         if (value && *value) {
1520                 char *summary = NULL;
1521                 __encode_escaped_char(value, &summary);
1522                 _cal_vcalendar_make_printf(b, "SUMMARY:", summary);
1523                 free(summary);
1524         }
1525 }
1526
1527 static void __make_description(cal_make_s *b, calendar_record_h record)
1528 {
1529         RET_IF(NULL == b);
1530         RET_IF(NULL == record);
1531
1532         int ret = 0;
1533         char *value = NULL;
1534         switch (b->type) {
1535         case CALENDAR_BOOK_TYPE_EVENT:
1536                 ret = calendar_record_get_str_p(record, _calendar_event.description, &value);
1537                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1538                 break;
1539         case CALENDAR_BOOK_TYPE_TODO:
1540                 ret = calendar_record_get_str_p(record, _calendar_todo.description, &value);
1541                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1542                 break;
1543         }
1544         if (value && *value) {
1545                 char *description = NULL;
1546                 __encode_escaped_char(value, &description);
1547                 _cal_vcalendar_make_printf(b, "DESCRIPTION:", description);
1548                 free(description);
1549         }
1550 }
1551
1552 static void __make_location(cal_make_s *b, calendar_record_h record)
1553 {
1554         RET_IF(NULL == b);
1555         RET_IF(NULL == record);
1556
1557         int ret = 0;
1558         char *value = NULL;
1559         switch (b->type) {
1560         case CALENDAR_BOOK_TYPE_EVENT:
1561                 ret = calendar_record_get_str_p(record, _calendar_event.location, &value);
1562                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1563                 break;
1564         case CALENDAR_BOOK_TYPE_TODO:
1565                 ret = calendar_record_get_str_p(record, _calendar_todo.location, &value);
1566                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1567                 break;
1568         }
1569         if (value && *value) {
1570                 char *location = NULL;
1571                 __encode_escaped_char(value, &location);
1572                 _cal_vcalendar_make_printf(b, "LOCATION:", location);
1573                 free(location);
1574         }
1575 }
1576
1577 static void __make_organizer(cal_make_s *b, calendar_record_h record)
1578 {
1579         RET_IF(NULL == b);
1580         RET_IF(NULL == record);
1581
1582         /* Invalid component in ver 1 */
1583         if (VCAL_VER_1 == b->version)
1584                 return;
1585
1586         int ret = 0;
1587         char *name = NULL;
1588         char *email = NULL;
1589         switch (b->type) {
1590         case CALENDAR_BOOK_TYPE_EVENT:
1591                 ret = calendar_record_get_str_p(record, _calendar_event.organizer_name, &name);
1592                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1593                 ret = calendar_record_get_str_p(record, _calendar_event.organizer_email, &email);
1594                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1595                 break;
1596         case CALENDAR_BOOK_TYPE_TODO:
1597                 ret = calendar_record_get_str_p(record, _calendar_todo.organizer_name, &name);
1598                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1599                 ret = calendar_record_get_str_p(record, _calendar_todo.organizer_email, &email);
1600                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1601                 break;
1602         }
1603         if ((NULL == name || '\0' == *name) && (NULL == email || '\0' == *email))
1604                 return;
1605
1606         char buf[CAL_STR_MIDDLE_LEN] = {0};
1607         snprintf(buf, sizeof(buf), "ORGANIZER%s%s%s%s",
1608                         (name && *name) ? ";CN=" : "",
1609                         (name && *name) ? name : "",
1610                         (email && *email) ? ":MAILTO:" : "",
1611                         (email && *email) ? email : "");
1612
1613         _cal_vcalendar_make_printf(b, buf, NULL);
1614 }
1615
1616 static void __make_last_modified(cal_make_s *b, calendar_record_h record)
1617 {
1618         RET_IF(NULL == b);
1619         RET_IF(NULL == record);
1620
1621         /* kies want to skip */
1622         if (VCAL_VER_1 == b->version) {
1623                 DBG("skip in ver1.0");
1624                 return;
1625         }
1626
1627         int ret = 0;
1628         long long int value = 0;
1629         switch (b->type) {
1630         case CALENDAR_BOOK_TYPE_EVENT:
1631                 ret = calendar_record_get_lli(record, _calendar_event.last_modified_time, &value);
1632                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_lli() Fail(%d)", ret);
1633                 break;
1634         case CALENDAR_BOOK_TYPE_TODO:
1635                 ret = calendar_record_get_lli(record, _calendar_todo.last_modified_time, &value);
1636                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_lli() Fail(%d)", ret);
1637                 break;
1638         }
1639
1640         int y = 0, m = 0, d = 0;
1641         int h = 0, n = 0, s = 0;
1642         cal_time_get_local_datetime(NULL, value, &y, &m, &d, &h, &n, &s);
1643
1644         char buf[CAL_STR_MIDDLE_LEN] = {0};
1645         snprintf(buf, sizeof(buf), CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSSZ, y, m, d, h, n, s);
1646         _cal_vcalendar_make_printf(b, "LAST-MODIFIED:", buf);
1647 }
1648
1649 static void __make_status(cal_make_s *b, calendar_record_h record)
1650 {
1651         RET_IF(NULL == b);
1652         RET_IF(NULL == record);
1653
1654         int ret = 0;
1655         int value = 0;
1656         char *status = NULL;
1657         switch (b->type) {
1658         case CALENDAR_BOOK_TYPE_EVENT:
1659                 ret = calendar_record_get_int(record, _calendar_event.event_status, &value);
1660                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
1661                 switch (value) {
1662                 case CALENDAR_EVENT_STATUS_NONE:
1663                         DBG("None status");
1664                         break;
1665                 case CALENDAR_EVENT_STATUS_TENTATIVE:
1666                         status = "TENTATIVE";
1667                         break;
1668                 case CALENDAR_EVENT_STATUS_CONFIRMED:
1669                         status = "CONFIRMED";
1670                         break;
1671                 case CALENDAR_EVENT_STATUS_CANCELLED:
1672                         status = "CANCELLED";
1673                         break;
1674                 }
1675                 break;
1676         case CALENDAR_BOOK_TYPE_TODO:
1677                 ret = calendar_record_get_int(record, _calendar_todo.todo_status, &value);
1678                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
1679                 switch (value) {
1680                 case CALENDAR_TODO_STATUS_NONE:
1681                         DBG("None status");
1682                         break;
1683                 case CALENDAR_TODO_STATUS_NEEDS_ACTION:
1684                         status = (VCAL_VER_1 == b->version) ? "NEEDS ACTION" : "NEEDS-ACTION";
1685                         break;
1686                 case CALENDAR_TODO_STATUS_COMPLETED:
1687                         status = "COMPLETED";
1688                         break;
1689                 case CALENDAR_TODO_STATUS_IN_PROCESS:
1690                         status = (VCAL_VER_1 == b->version) ? NULL : "IN-PROCESS";
1691                         break;
1692                 case CALENDAR_TODO_STATUS_CANCELED:
1693                         status = (VCAL_VER_1 == b->version) ? NULL : "CANCELLED";
1694                         break;
1695                 }
1696                 break;
1697         }
1698         if (status && *status)
1699                 _cal_vcalendar_make_printf(b, "STATUS:", status);
1700 }
1701
1702 static void __make_completed(cal_make_s *b, calendar_record_h record)
1703 {
1704         RET_IF(NULL == b);
1705         RET_IF(NULL == record);
1706
1707         /* Invalid component in event */
1708         if (CALENDAR_BOOK_TYPE_EVENT == b->type)
1709                 return;
1710
1711         int ret = 0;
1712         long long int value = 0;
1713         ret = calendar_record_get_lli(record, _calendar_todo.completed_time, &value);
1714         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
1715
1716         int y = 0, m = 0, d = 0;
1717         int h = 0, n = 0, s = 0;
1718         cal_time_get_local_datetime(NULL, value, &y, &m, &d, &h, &n, &s);
1719         char buf[CAL_STR_MIDDLE_LEN] = {0};
1720         snprintf(buf, sizeof(buf), CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSSZ, y, m, d, h, n, s);
1721         _cal_vcalendar_make_printf(b, "COMPLETED", buf);
1722 }
1723
1724 static void __make_priority(cal_make_s *b, calendar_record_h record)
1725 {
1726         RET_IF(NULL == b);
1727         RET_IF(NULL == record);
1728
1729         int ret = 0;
1730         int value = 0;
1731         switch (b->type) {
1732         case CALENDAR_BOOK_TYPE_EVENT:
1733                 ret = calendar_record_get_int(record, _calendar_event.priority, &value);
1734                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
1735                 break;
1736         case CALENDAR_BOOK_TYPE_TODO:
1737                 ret = calendar_record_get_int(record, _calendar_todo.priority, &value);
1738                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
1739                 break;
1740         }
1741         int priority = 0;
1742         switch (b->version) {
1743         case VCAL_VER_1:
1744                 switch (value) {
1745                 case CALENDAR_EVENT_PRIORITY_HIGH:
1746                         priority = 2;
1747                         break;
1748                 case CALENDAR_EVENT_PRIORITY_NORMAL:
1749                         priority = 1;
1750                         break;
1751                 case CALENDAR_EVENT_PRIORITY_LOW:
1752                         priority = 0;
1753                         break;
1754                 default:
1755                         priority = 0;
1756                         break;
1757                 }
1758                 break;
1759         case VCAL_VER_2:
1760                 switch (value) {
1761                 case CALENDAR_EVENT_PRIORITY_HIGH:
1762                         /* in version 2.0, one out of 1 ~ 4 */
1763                         priority = 3;
1764                         break;
1765                 case CALENDAR_EVENT_PRIORITY_NORMAL:
1766                         priority = 5;
1767                         break;
1768                 case CALENDAR_EVENT_PRIORITY_LOW:
1769                         /* in version 2, one out of 6 ~ 9. */
1770                         priority = 7;
1771                         break;
1772                 default:
1773                         priority = 0;
1774                         break;
1775                 }
1776                 break;
1777         }
1778         char buf[CAL_STR_MIDDLE_LEN] = {0};
1779         snprintf(buf, sizeof(buf), "PRIORITY:%d", priority);
1780         _cal_vcalendar_make_printf(b, buf, NULL);
1781 }
1782
1783 static void __make_dtstamp(cal_make_s *b, calendar_record_h record)
1784 {
1785         RET_IF(NULL == b);
1786         RET_IF(NULL == record);
1787
1788         /* Not support in ver 1 */
1789         if (VCAL_VER_1 == b->version)
1790                 return;
1791
1792         long long int t = cal_time_get_now();
1793         int y = 0, m = 0, d = 0;
1794         int h = 0, n = 0, s = 0;
1795         cal_time_get_local_datetime(NULL, t, &y, &m, &d, &h, &n, &s);
1796         char buf[CAL_STR_MIDDLE_LEN] = {0};
1797         snprintf(buf, sizeof(buf), CAL_DATETIME_FORMAT_YYYYMMDDTHHMMSSZ, y, m, d, h, n, s);
1798         _cal_vcalendar_make_printf(b, "DTSTAMP:", buf);
1799 }
1800
1801 static void __make_categories(cal_make_s *b, calendar_record_h record)
1802 {
1803         RET_IF(NULL == b);
1804         RET_IF(NULL == record);
1805
1806         int ret = 0;
1807         char *value = NULL;
1808         switch (b->type) {
1809         case CALENDAR_BOOK_TYPE_EVENT:
1810                 ret = calendar_record_get_str_p(record, _calendar_event.categories, &value);
1811                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1812                 break;
1813         case CALENDAR_BOOK_TYPE_TODO:
1814                 ret = calendar_record_get_str_p(record, _calendar_todo.categories, &value);
1815                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1816                 break;
1817         }
1818         if (value && *value)
1819                 _cal_vcalendar_make_printf(b, "CATEGORIES:", value);
1820 }
1821
1822 static void __make_exdate(cal_make_s *b, calendar_record_h record)
1823 {
1824         RET_IF(NULL == b);
1825         RET_IF(NULL == record);
1826
1827         int ret = 0;
1828         char *value = NULL;
1829         switch (b->type) {
1830         case CALENDAR_BOOK_TYPE_EVENT:
1831                 ret = calendar_record_get_str_p(record, _calendar_event.exdate, &value);
1832                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1833                 break;
1834         case CALENDAR_BOOK_TYPE_TODO:
1835                 ERR("Not support exdate in TODO");
1836                 break;
1837         }
1838         if (value && *value)
1839                 _cal_vcalendar_make_printf(b, "EXDATE:", value);
1840 }
1841
1842 static void _cal_vcalendar_make_child_extended(cal_make_s *b, calendar_record_h child, bool *has_lunar)
1843 {
1844         RET_IF(NULL == b);
1845         RET_IF(NULL == child);
1846
1847         int ret = 0;;
1848         char *key = NULL;
1849         char *value = NULL;
1850
1851         ret = calendar_record_get_str_p(child, _calendar_extended_property.key, &key);
1852         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1853         if (NULL == key || '\0' == *key || (0 != strncmp(key, "X-", strlen("X-")))) {
1854                 DBG("Not extended for vcalendar[%s]", key);
1855                 return;
1856         }
1857
1858         ret = calendar_record_get_str_p(child, _calendar_extended_property.value, &value);
1859         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
1860
1861         /* check lunar: will handle next */
1862         if (has_lunar) {
1863                 if ((CAL_STRING_EQUAL == strncmp(key, "X-LUNAR", strlen("X-LUNAR")) && !strncmp(value, ":SET", strlen(":SET"))) ||
1864                                 (CAL_STRING_EQUAL == strncmp(key, "X-LUNAR:", strlen("X-LUNAR:")) && !strncmp(value, "SET", strlen("SET")))) {
1865                         *has_lunar = true;
1866                         return;
1867                 }
1868         }
1869
1870         ret = _cal_vcalendar_make_printf(b, key, value);
1871         RETM_IF(CALENDAR_ERROR_NONE != ret, "_cal_vcalendar_make_printf() Fail(%d)", ret);
1872 }
1873
1874 static void __make_extended(cal_make_s *b, calendar_record_h record)
1875 {
1876         RET_IF(NULL == b);
1877         RET_IF(NULL == record);
1878
1879         int ret = 0;
1880         unsigned int count = 0;
1881         int i;
1882         bool has_lunar = false;
1883         int calendar_system_type = 0;
1884         switch (b->type) {
1885         case CALENDAR_BOOK_TYPE_EVENT:
1886                 ret = calendar_record_get_child_record_count(record, _calendar_event.extended, &count);
1887                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_child_record_count() Fail(%d)", ret);
1888                 for (i = 0; i < count; i++) {
1889                         calendar_record_h child = NULL;
1890                         ret = calendar_record_get_child_record_at_p(record, _calendar_event.extended, i, &child);
1891                         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_child_record_at_p() Fail(%d)", ret);
1892
1893                         _cal_vcalendar_make_child_extended(b, child, &has_lunar);
1894                 }
1895
1896                 /* lunar */
1897                 ret = calendar_record_get_int(record, _calendar_event.calendar_system_type, &calendar_system_type);
1898                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_int() Fail(%d)", ret);
1899
1900                 if (true == has_lunar || CALENDAR_SYSTEM_EAST_ASIAN_LUNISOLAR == calendar_system_type)
1901                         _cal_vcalendar_make_printf(b, "X-LUNAR:SET", NULL);
1902                 break;
1903         case CALENDAR_BOOK_TYPE_TODO:
1904                 ret = calendar_record_get_child_record_count(record, _calendar_todo.extended, &count);
1905                 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_child_record_count() Fail(%d)", ret);
1906                 for (i = 0; i < count; i++) {
1907                         calendar_record_h child = NULL;
1908                         ret = calendar_record_get_child_record_at_p(record, _calendar_todo.extended, i, &child);
1909                         WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_child_record_at_p() Fail(%d)", ret);
1910
1911                         _cal_vcalendar_make_child_extended(b, child, NULL);
1912                 }
1913                 break;
1914         }
1915 }
1916
1917 static void __make_end(cal_make_s *b, calendar_record_h record)
1918 {
1919         RET_IF(NULL == b);
1920         RET_IF(NULL == record);
1921
1922         int ret = 0;
1923         switch (b->type) {
1924         case CALENDAR_BOOK_TYPE_EVENT:
1925                 ret = _cal_vcalendar_make_printf(b, "END:VEVENT", NULL);
1926                 RETM_IF(CALENDAR_ERROR_NONE != ret, "_cal_vcalendar_make_printf() Fail(%d)", ret);
1927                 break;
1928         case CALENDAR_BOOK_TYPE_TODO:
1929                 ret = _cal_vcalendar_make_printf(b, "END:VTODO", NULL);
1930                 RETM_IF(CALENDAR_ERROR_NONE != ret, "_cal_vcalendar_make_printf() Fail(%d)", ret);
1931                 break;
1932         }
1933 }
1934
1935 static void _cal_vcalendar_make_schedule(cal_make_s *b, calendar_record_h record)
1936 {
1937         RET_IF(NULL == b);
1938         RET_IF(NULL == record);
1939
1940         __make_begin(b, record);
1941         __make_summary(b, record);
1942         __make_dtstart(b, record);
1943         __make_dtend(b, record);
1944         __make_rrule(b, record); /* only event */
1945         __make_sensitivity(b, record);
1946         __make_created_time(b, record);
1947         __make_description(b, record);
1948         __make_location(b, record);
1949         __make_organizer(b, record);
1950         __make_last_modified(b, record);
1951         __make_status(b, record);
1952         __make_completed(b, record); /* only todo */
1953         __make_priority(b, record);
1954         __make_dtstamp(b, record);
1955         __make_categories(b, record);
1956         __make_exdate(b, record); /* only event */
1957         __make_attendee(b, record);
1958         __make_alarm(b, record);
1959         __make_extended(b, record);
1960         __make_end(b, record);
1961
1962 }
1963
1964 static void __append_header(cal_make_s *b)
1965 {
1966         RET_IF(NULL == b);
1967
1968         int ret = 0;
1969
1970         ret = _cal_vcalendar_make_printf(b, "BEGIN:VCALENDAR", NULL);
1971         RETM_IF(CALENDAR_ERROR_NONE != ret, "_cal_vcalendar_make_printf() Fail(%d)", ret);
1972
1973         ret = _cal_vcalendar_make_printf(b, "PRODID:vCal ID Default", NULL);
1974         RETM_IF(CALENDAR_ERROR_NONE != ret, "_cal_vcalendar_make_printf() Fail(%d)", ret);
1975
1976         char buf[CAL_STR_SHORT_LEN32] = {0};
1977         snprintf(buf, sizeof(buf), "VERSION:%d.0", b->version);
1978         ret = _cal_vcalendar_make_printf(b, buf, NULL);
1979         RETM_IF(CALENDAR_ERROR_NONE != ret, "_cal_vcalendar_make_printf() Fail(%d)", ret);
1980 }
1981
1982 static void __make_footer(cal_make_s *b)
1983 {
1984         int ret = 0;
1985         RET_IF(NULL == b);
1986
1987         ret = _cal_vcalendar_make_printf(b, "END:VCALENDAR", NULL);
1988         RETM_IF(CALENDAR_ERROR_NONE != ret, "_cal_vcalendar_make_printf() Fail(%d)", ret);
1989 }
1990
1991 static void __make_tz(cal_make_s *b, char *tzid, long long int created)
1992 {
1993         int ret = 0;
1994
1995         RET_IF(NULL == b);
1996         RET_IF(NULL == tzid);
1997         RET_IF('\0' == *tzid);
1998
1999         time_t zone = 0;
2000         time_t dst = 0;
2001         cal_time_get_tz_offset(tzid, &zone, &dst);
2002         DBG("offset zone(%ld), dst (%ld)", zone, dst);
2003
2004         bool in_dst = cal_time_in_dst(tzid, created);
2005         dst = in_dst ? dst : 0; /* dst in TZ is depending on created time */
2006         DBG("tzid[%s] created time(%lld) in_dst(%d)", tzid, created, in_dst);
2007
2008         int h = (zone / 3600) + (dst / 3600);
2009         int m = (zone % 3600) / 60 + (dst % 3600) / 60;
2010
2011         char buf[CAL_STR_SHORT_LEN32] = {0};
2012         snprintf(buf, sizeof(buf), "TZ:%s%02d:%02d",
2013                         h == 0 ? "" : (h < 0 ? "-" : "+"),
2014                         h < 0 ? (-1 * h) : h, m < 0 ? (-1 * m) : m);
2015
2016         ret = _cal_vcalendar_make_printf(b, buf, NULL);
2017         RETM_IF(CALENDAR_ERROR_NONE != ret, "_cal_vcalendar_make_printf() Fail");
2018         DBG("append tzid[%s]", buf);
2019 }
2020
2021 static void __devide_vcalendar_with_header(cal_make_s *b, calendar_record_h record)
2022 {
2023         RET_IF(NULL == b);
2024         RET_IF(NULL == record);
2025
2026         if (2 == b->version)
2027                 return;
2028
2029         int ret = 0;
2030         char *uri = NULL;
2031         ret = calendar_record_get_uri_p(record, &uri);
2032         RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_uri_p() Fail(%d)", ret);
2033
2034         char *tzid = NULL;
2035         long long int created = 0;
2036
2037         switch (b->type) {
2038         case CALENDAR_BOOK_TYPE_EVENT:
2039                 ret = calendar_record_get_str_p(record, _calendar_event.start_tzid, &tzid);
2040                 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
2041                 ret = calendar_record_get_lli(record, _calendar_event.created_time, &created);
2042                 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_lli() Fail(%d)", ret);
2043                 break;
2044         case CALENDAR_BOOK_TYPE_TODO:
2045                 ret = calendar_record_get_str_p(record, _calendar_todo.due_tzid, &tzid);
2046                 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_str_p() Fail(%d)", ret);
2047                 ret = calendar_record_get_lli(record, _calendar_todo.created_time, &created);
2048                 WARN_IF(CALENDAR_ERROR_NONE != ret, "calendar_record_get_lli() Fail(%d)", ret);
2049                 break;
2050         }
2051
2052         if (NULL == tzid || '\0' == *tzid) {
2053                 DBG("No tzid");
2054                 return;
2055         }
2056
2057         if (NULL == b->timezone_tzid || '\0' == *b->timezone_tzid) {
2058                 /* new start of vcalendar */
2059                 __make_tz(b, tzid, created);
2060                 b->timezone_tzid = strdup(tzid);
2061         } else {
2062                 /* not first vcalendar */
2063                 if (0 != strncmp(b->timezone_tzid, tzid, strlen(tzid))) {
2064                         /* different tzid */
2065                         __make_footer(b);
2066                         __append_header(b);
2067                         __make_tz(b, tzid, created);
2068                         if (b->timezone_tzid)
2069                                 free(b->timezone_tzid);
2070                         b->timezone_tzid = strdup(tzid);
2071                 } else {
2072                         DBG("same as before, skip");
2073                 }
2074         }
2075 }
2076 static int __make_vcalendar(cal_make_s *b, calendar_list_h list)
2077 {
2078         RETV_IF(NULL == b, CALENDAR_ERROR_INVALID_PARAMETER);
2079         RETV_IF(NULL == list, CALENDAR_ERROR_INVALID_PARAMETER);
2080
2081         int ret = CALENDAR_ERROR_NONE;
2082         calendar_record_h record = NULL;
2083
2084         __append_header(b);
2085
2086         ret = calendar_list_first(list);
2087         RETVM_IF(CALENDAR_ERROR_NONE != ret, ret, "calendar_list_first() Fail");
2088         do {
2089                 ret = calendar_list_get_current_record_p(list, &record);
2090                 if (CALENDAR_ERROR_NONE != ret) break;
2091
2092                 char *uri = NULL;
2093                 ret = calendar_record_get_uri_p(record, &uri);
2094                 DBG("uri[%s]", uri);
2095
2096                 if (CAL_STRING_EQUAL == strcmp(uri, _calendar_event._uri)) {
2097                         b->type = CALENDAR_BOOK_TYPE_EVENT;
2098                         __devide_vcalendar_with_header(b, record);
2099                         _cal_vcalendar_make_schedule(b, record);
2100
2101                 } else if (CAL_STRING_EQUAL == strcmp(uri, _calendar_todo._uri)) {
2102                         b->type = CALENDAR_BOOK_TYPE_TODO;
2103                         __devide_vcalendar_with_header(b, record);
2104                         _cal_vcalendar_make_schedule(b, record);
2105
2106                 } else if (CAL_STRING_EQUAL == strcmp(uri, _calendar_extended_property._uri)) {
2107                         cal_extended_s *extended = (cal_extended_s *)record;
2108                         if (CAL_STRING_EQUAL == strncmp(extended->key, "VERSION", strlen("VERSION"))) continue;
2109
2110                         ret = _cal_vcalendar_make_printf(b, extended->key, extended->value);
2111                         if (CALENDAR_ERROR_NONE != ret) break;
2112
2113                         DBG("extended key[%s] value[%s]", extended->key, extended->value);
2114
2115                 } else if (CAL_STRING_EQUAL == strcmp(uri, _calendar_timezone._uri)) {
2116                         DBG("Not support timezone");
2117
2118                 } else if (CAL_STRING_EQUAL == strcmp(uri, _calendar_book._uri)) {
2119                         DBG("Not support calendar");
2120
2121                 } else {
2122                         DBG("Unable to understand uri[%s]", uri);
2123                 }
2124
2125         } while (CALENDAR_ERROR_NO_DATA != calendar_list_next(list));
2126         __make_footer(b);
2127
2128         return CALENDAR_ERROR_NONE;
2129 }
2130
2131 int cal_vcalendar_make_vcalendar(cal_make_s *b, calendar_list_h list)
2132 {
2133         RETV_IF(NULL == list, CALENDAR_ERROR_INVALID_PARAMETER);
2134
2135         int ret = CALENDAR_ERROR_NONE;
2136         calendar_record_h record = NULL;
2137
2138         int version = 2; /* set default as ver 2.0 */
2139
2140         ret = calendar_list_first(list);
2141         RETVM_IF(CALENDAR_ERROR_NONE != ret, ret, "calendar_list_first() Fail");
2142         do {
2143                 ret = calendar_list_get_current_record_p(list, &record);
2144                 if (CALENDAR_ERROR_NONE != ret) break;
2145
2146                 char *uri = NULL;
2147                 ret = calendar_record_get_uri_p(record, &uri);
2148
2149                 if (CAL_STRING_EQUAL == strcmp(uri, _calendar_extended_property._uri)) {
2150                         cal_extended_s *extended = (cal_extended_s *)record;
2151                         if (CAL_STRING_EQUAL == strncmp(extended->key, "VERSION", strlen("VERSION"))) {
2152                                 version = strstr(extended->value, "1.0") ? 1 : 2;
2153                                 break;
2154                         }
2155                 }
2156         } while (CALENDAR_ERROR_NO_DATA != calendar_list_next(list));
2157         b->version = version;
2158         DBG("make as version(%d)", version);
2159
2160         __make_vcalendar(b, list);
2161         return CALENDAR_ERROR_NONE;
2162 }