53113cc2b985bf5de6f8feb7fee46047fcbeac54
[framework/pim/calendar-service.git] / common / cal_vcalendar_parse.c
1 /*
2  * Calendar Service
3  *
4  * Copyright (c) 2012 - 2013 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 <ctype.h>
22
23 #include "calendar_list.h"
24
25 #include "cal_internal.h"
26 #include "cal_typedef.h"
27 #include "cal_record.h"
28 #include "cal_view.h"
29 #include "cal_time.h"
30
31 #include "cal_vcalendar.h"
32 #include "cal_vcalendar_parse.h"
33
34 enum {
35         ENCODE_NONE = 0x0,
36         ENCODE_BASE64,
37         ENCODE_QUOTED_PRINTABLE,
38         ENCODE_MAX,
39 };
40
41 struct _prop_func {
42         char *prop;
43         int (*func)(int *val, void *data);
44 };
45
46 struct _vcalendar_func {
47         char *prop;
48         int (*func)(int ver, calendar_list_h list, calendar_record_h event, void *data);
49 };
50
51 struct _record_func {
52         char *prop;
53         int (*func)(calendar_record_h record, void *data);
54 };
55
56 char *_cal_vcalendar_parse_vcalendar(calendar_list_h *list_sch, void *data);
57 char *_cal_vcalendar_parse_vevent(int ver, calendar_list_h *list_sch, void *data);
58 char *_cal_vcalendar_parse_vtodo(int ver, calendar_list_h *list_sch, void *data);
59 char *_cal_vcalendar_parse_valarm(int type, calendar_record_h record, void *data);
60
61 enum {
62         VCAL_PRODID = 0x0,
63         VCAL_VERSION,
64 //      VCAL_CALSCALE,
65 //      VCAL_METHOD,
66         VCAL_MAX,
67 };
68
69 static int __cal_vcalendar_parse_prodid(int *val, void *data);
70 static int __cal_vcalendar_parse_version(int *val, void *data);
71
72 struct _prop_func _basic_funcs[VCAL_MAX] =
73 {
74         {"PRODID", __cal_vcalendar_parse_prodid },
75         {"VERSION", __cal_vcalendar_parse_version }//,
76 //      {"CALSCALE", __cal_vcalendar_parse_calscale },
77 //      {"METHOD", __cal_vcalendar_parse_method }
78 };
79
80 static int __cal_vcalendar_parse_dtstamp(int ver, calendar_list_h list, calendar_record_h event, void *data);
81 static int __cal_vcalendar_parse_uid(int type, calendar_list_h list, calendar_record_h record, void *data);
82 static int __cal_vcalendar_parse_dtstart(int ver, calendar_list_h list, calendar_record_h event, void *data);
83 static int __cal_vcalendar_parse_created(int ver, calendar_list_h list, calendar_record_h event, void *data);
84 static int __cal_vcalendar_parse_description(int ver, calendar_list_h list, calendar_record_h event, void *data);
85 static int __cal_vcalendar_parse_last_mod(int ver, calendar_list_h list, calendar_record_h event, void *data);
86 static int __cal_vcalendar_parse_location(int ver, calendar_list_h list, calendar_record_h event, void *data);
87 static int __cal_vcalendar_parse_priority(int ver, calendar_list_h list, calendar_record_h event, void *data);
88 static int __cal_vcalendar_parse_status(int ver, calendar_list_h list, calendar_record_h event, void *data);
89 static int __cal_vcalendar_parse_summary(int ver, calendar_list_h list, calendar_record_h event, void *data);
90 static int __cal_vcalendar_parse_rrule(int ver, calendar_list_h list, calendar_record_h event, void *data);
91 static int __cal_vcalendar_parse_dtend(int ver, calendar_list_h list, calendar_record_h event, void *data);
92
93 static int __cal_vcalendar_parse_completed(int ver, calendar_list_h list, calendar_record_h event, void *data);
94 static int __cal_vcalendar_parse_percent(int ver, calendar_list_h list, calendar_record_h event, void *data);
95
96 enum {
97         ATTENDEE_CUTYPE = 0x0,
98         ATTENDEE_MEMBER,
99         ATTENDEE_ROLE,
100         ATTENDEE_PARTSTAT,
101         ATTENDEE_RSVP,
102         ATTENDEE_DELTO,
103         ATTENDEE_DELFROM,
104         ATTENDEE_SENTBY,
105         ATTENDEE_CN,
106         ATTENDEE_DIR,
107         ATTENDEE_MAX,
108 };
109
110 static int __cal_vcalendar_parse_attendee_cutype(calendar_record_h event, void *data);
111 static int __cal_vcalendar_parse_attendee_member(calendar_record_h event, void *data);
112 static int __cal_vcalendar_parse_attendee_role(calendar_record_h event, void *data);
113 static int __cal_vcalendar_parse_attendee_partstat(calendar_record_h event, void *data);
114 static int __cal_vcalendar_parse_attendee_rsvp(calendar_record_h event, void *data);
115 static int __cal_vcalendar_parse_attendee_delto(calendar_record_h event, void *data);
116 static int __cal_vcalendar_parse_attendee_delfrom(calendar_record_h event, void *data);
117 static int __cal_vcalendar_parse_attendee_sentby(calendar_record_h event, void *data);
118 static int __cal_vcalendar_parse_attendee_cn(calendar_record_h event, void *data);
119 static int __cal_vcalendar_parse_attendee_dir(calendar_record_h event, void *data);
120
121 struct _record_func _attendee_funcs[ATTENDEE_MAX] =
122 {
123         { "CUTYPE=", __cal_vcalendar_parse_attendee_cutype },
124         { "MEMBER=", __cal_vcalendar_parse_attendee_member },
125         { "ROLE=", __cal_vcalendar_parse_attendee_role },
126         { "PARTSTAT=", __cal_vcalendar_parse_attendee_partstat },
127         { "RSVP=", __cal_vcalendar_parse_attendee_rsvp },
128         { "DELTO=", __cal_vcalendar_parse_attendee_delto },
129         { "DELFROM=", __cal_vcalendar_parse_attendee_delfrom },
130         { "SENTBY=", __cal_vcalendar_parse_attendee_sentby },
131         { "CN=", __cal_vcalendar_parse_attendee_cn },
132         { "DIR=", __cal_vcalendar_parse_attendee_dir }
133 };
134
135 static int __cal_vcalendar_parse_attendee(int ver, calendar_list_h list, calendar_record_h event, void *data);
136 static int __cal_vcalendar_parse_categories(int ver, calendar_list_h list, calendar_record_h event, void *data);
137 static int __cal_vcalendar_parse_aalarm(int ver, calendar_list_h list, calendar_record_h event, void *data);
138
139 enum {
140         VEVE_DTSTAMP = 0x0,
141         VEVE_UID,
142         VEVE_DTSTART,
143         VEVE_CREATED,
144         VEVE_DESCRIPTION,
145         VEVE_LAST_MOD,
146         VEVE_LOCATION,
147         VEVE_PRIORITY,
148         VEVE_STATUS,
149         VEVE_SUMMARY,
150         VEVE_RRULE,
151         VEVE_DTEND,
152         VEVE_DUE,
153         VEVE_ATTENDEE,
154         VEVE_CATEGORIES,
155         VEVE_AALARM,    /* for ver 1.0 */
156         VEVE_MAX,
157 };
158
159 struct _vcalendar_func _vevent_funcs[VEVE_MAX] =
160 {
161         { "DTSTAMP", __cal_vcalendar_parse_dtstamp },
162         { "UID", __cal_vcalendar_parse_uid },
163         { "DTSTART", __cal_vcalendar_parse_dtstart },
164         { "CREATED", __cal_vcalendar_parse_created },
165         { "DESCRIPTION", __cal_vcalendar_parse_description },
166         { "LAST-MOD", __cal_vcalendar_parse_last_mod },
167         { "LOCATION", __cal_vcalendar_parse_location },
168         { "PRIORITY", __cal_vcalendar_parse_priority },
169         { "STATUS", __cal_vcalendar_parse_status },
170         { "SUMMARY", __cal_vcalendar_parse_summary },
171         { "RRULE", __cal_vcalendar_parse_rrule },
172         { "DTEND", __cal_vcalendar_parse_dtend },
173         { "DUE", __cal_vcalendar_parse_dtend },
174         { "ATTENDEE", __cal_vcalendar_parse_attendee },
175         { "CATEGORIES", __cal_vcalendar_parse_categories },
176         { "AALARM", __cal_vcalendar_parse_aalarm },
177 };
178
179 static int __cal_vcalendar_parse_action(calendar_record_h alarm, void *data);
180 static int __cal_vcalendar_parse_trigger(calendar_record_h alarm, void *data);
181 static int __cal_vcalendar_parse_repeat(calendar_record_h alarm, void *data);
182 static int __cal_vcalendar_parse_duration_alarm(calendar_record_h alarm, void *data);
183 static int __cal_vcalendar_parse_attach_alarm(calendar_record_h alarm, void *data);
184 static int __cal_vcalendar_parse_summary_alarm(calendar_record_h alarm, void *data);
185
186 enum {
187         VALA_ACTION = 0x0,
188         VALA_TRIGGER,
189         VALA_REPEAT,
190         VALA_DURATION,
191         VALA_ATTACH,
192 //      VALA_DESCRIPTION,
193         VALA_SUMMARY,
194 //      VALA_ATTENDEE,
195         VALA_MAX,
196 };
197
198 struct _record_func _valarm_funcs[VALA_MAX] =
199 {
200         { "ACTION", __cal_vcalendar_parse_action },
201         { "TRIGGER", __cal_vcalendar_parse_trigger },
202         { "REPEAT", __cal_vcalendar_parse_repeat },
203         { "DURATION", __cal_vcalendar_parse_duration_alarm },
204         { "ATTACH", __cal_vcalendar_parse_attach_alarm },
205 //      { "DESCRIPTION", __cal_vcalendar_parse_description },
206         { "SUMMARY", __cal_vcalendar_parse_summary_alarm },
207 //      { "ATTENDEE", __cal_vcalendar_parse_attendee },
208 };
209
210 enum {
211         VTODO_DTSTAMP = 0x0,
212         VTODO_UID,
213 //      VTODO_CLASS,
214         VTODO_COMPLETED,
215         VTODO_CREATED,
216         VTODO_DESCRIPTION,
217         VTODO_DTSTART,
218 //      VTODO_GEO,
219         VTODO_LAST_MOD,
220         VTODO_LOCATION,
221 //      VTODO_ORGANIZER,
222         VTODO_PERCENT,
223         VTODO_PRIORITY,
224 //      VTODO_RECURID,
225 //      VTODO_SEQ,
226         VTODO_STATUS,
227         VTODO_SUMMARY,
228 //      VTODO_URL,
229 //      VTODO_RRULE,
230         VTODO_DUE,
231 //      VTODO_DURATION,
232 //      VTODO_ATTACH,
233 //      VTODO_ATTENDEE,
234 //      VTODO_CATEGORIES,
235 //      VTODO_COMMENT,
236 //      VTODO_CONTACT,
237 //      VTODO_EXDATE,
238 //      VTODO_RSTATUS,
239 //      VTODO_RELATED,
240 //      VTODO_RESOURCES,
241 //      VTODO_RDATE,
242 //      VTODO_X_PROP,
243 //      VTODO_IANA_PROP,
244         VTODO_AALARM,   /* for ver 1.0 */
245         VTODO_MAX,
246 };
247
248 struct _vcalendar_func _vtodo_funcs[VTODO_MAX] =
249 {
250         { "DTSTAMP", __cal_vcalendar_parse_dtstamp },
251         { "UID", __cal_vcalendar_parse_uid },
252         { "COMPLETED", __cal_vcalendar_parse_completed },
253         { "CREATED", __cal_vcalendar_parse_created },
254         { "DESCRIPTION", __cal_vcalendar_parse_description },
255         { "DTSTART", __cal_vcalendar_parse_dtstart },
256         { "LAST-MOD", __cal_vcalendar_parse_last_mod },
257         { "LOCATION", __cal_vcalendar_parse_location },
258         { "PERCENT", __cal_vcalendar_parse_percent },
259         { "PRIORITY", __cal_vcalendar_parse_priority },
260         { "STATUS", __cal_vcalendar_parse_status },
261         { "SUMMARY", __cal_vcalendar_parse_summary },
262         { "DUE", __cal_vcalendar_parse_dtend },
263         { "AALARM", __cal_vcalendar_parse_aalarm },
264 };
265
266 static int __cal_vcalendar_parse_freq(calendar_record_h event, void *data);
267 static int __cal_vcalendar_parse_until(calendar_record_h event, void *data);
268 static int __cal_vcalendar_parse_count(calendar_record_h event, void *data);
269 static int __cal_vcalendar_parse_interval(calendar_record_h event, void *data);
270 static int __cal_vcalendar_parse_bysecond(calendar_record_h event, void *data);
271 static int __cal_vcalendar_parse_byminute(calendar_record_h event, void *data);
272 static int __cal_vcalendar_parse_byhour(calendar_record_h event, void *data);
273 static int __cal_vcalendar_parse_byday(calendar_record_h event, void *data);
274 static int __cal_vcalendar_parse_bymonthday(calendar_record_h event, void *data);
275 static int __cal_vcalendar_parse_byyearday(calendar_record_h event, void *data);
276 static int __cal_vcalendar_parse_byweekno(calendar_record_h event, void *data);
277 static int __cal_vcalendar_parse_bymonth(calendar_record_h event, void *data);
278 static int __cal_vcalendar_parse_bysetpos(calendar_record_h event, void *data);
279 static int __cal_vcalendar_parse_wkst(calendar_record_h event, void *data);
280
281 enum {
282         RRULE_FREQ = 0x0,
283         RRULE_UNTIL,
284         RRULE_COUNT,
285         RRULE_INTERVAL,
286         RRULE_BYSECOND,
287         RRULE_BYMINUTE,
288         RRULE_BYHOUR,
289         RRULE_BYDAY,
290         RRULE_BYMONTHDAY,
291         RRULE_BYYEARDAY,
292         RRULE_BYWEEKNO,
293         RRULE_BYMONTH,
294         RRULE_BYSETPOS,
295         RRULE_WKST,
296         RRULE_MAX,
297 };
298
299 struct _record_func _rrule_funcs[RRULE_MAX] =
300 {
301         { "FREQ=", __cal_vcalendar_parse_freq },
302         { "UNTIL=", __cal_vcalendar_parse_until },
303         { "COUNT=", __cal_vcalendar_parse_count },
304         { "INTERVAL=", __cal_vcalendar_parse_interval },
305         { "BYSECOND=", __cal_vcalendar_parse_bysecond },
306         { "BYMINUTE=", __cal_vcalendar_parse_byminute },
307         { "BYHOUR=", __cal_vcalendar_parse_byhour },
308         { "BYDAY=", __cal_vcalendar_parse_byday },
309         { "BYMONTHDAY=", __cal_vcalendar_parse_bymonthday },
310         { "BYYEARDAY=", __cal_vcalendar_parse_byyearday },
311         { "BYWEEKNO=", __cal_vcalendar_parse_byweekno },
312         { "BYMONTH=", __cal_vcalendar_parse_bymonth },
313         { "BYSETPOS=", __cal_vcalendar_parse_bysetpos },
314         { "WKST=", __cal_vcalendar_parse_wkst }
315 };
316
317 static int __cal_vcalendar_parse_trig_related(calendar_record_h event, void *data);
318 static int __cal_vcalendar_parse_trig_value(calendar_record_h event, void *data);
319
320 enum {
321         TRIG_RELATED = 0x0,
322         TRIG_VALUE,
323         TRIG_MAX,
324 };
325
326 struct _record_func _trig_funcs[TRIG_MAX] =
327 {
328         { "RELATED=", __cal_vcalendar_parse_trig_related },
329         { "VALUE=", __cal_vcalendar_parse_trig_value }
330 };
331
332 static int __cal_vcalendar_parse_charset(int *val, void *data);
333 static int __cal_vcalendar_parse_encoding(int *val, void *data);
334
335
336 enum {
337         TEXT_CHARSET = 0x0,
338         TEXT_ENCODING,
339         TEXT_MAX,
340 };
341
342 struct _prop_func _optional_funcs[TEXT_MAX] =
343 {
344         { "CHARSET=", __cal_vcalendar_parse_charset },
345         { "ENCODING=", __cal_vcalendar_parse_encoding },
346 };
347
348 //util //////////////////////////////////////////////////////////////////////
349
350
351 char *_cal_vcalendar_parse_remove_space(char *src)
352 {
353         while (*src) {
354                 if ('\n' != *src && '\r' != *src) {
355                         break;
356                 }
357                 src++;
358         }
359         return src;
360 }
361
362 static char __cal_vcalendar_parse_decode_hexa(char *p)
363 {
364         int i;
365         char decoded[2] = {0x00, 0x00};
366
367         for (i = 0; i < 2; i++) {
368                 switch (p[i]) {
369                 case '0' ... '9':
370                         decoded[i] = p[i] - '0';
371                         break;
372                 case 'a' ... 'f':
373                         decoded[i] = p[i] - 'a' + 10;
374                         break;
375                 case 'A' ... 'F':
376                         decoded[i] = p[i] - 'A' + 10;
377                         break;
378                 }
379         }
380
381         return (char)((decoded[0] << 4) + decoded[1]);
382 }
383
384 static int __cal_vcalendar_parse_decode_quoted_printable(char *p, int *len)
385 {
386         int i = 0, j = 0;
387         char ch;
388
389         while (p[i]) {
390                 if (p[i] == '=') {
391                         if (p[i+1] == 0x09 || p[i+1] == 0x20) {
392                                 i +=3;
393
394                         } else if (p[i+1] == '\r' || p[i+1] == '\n') {
395                                 i +=3;
396
397                         } else {
398                                 if (p[i+1] == '0' && tolower(p[i+2]) == 'd' &&
399                                                 p[i+3] == '=' && p[i+4] == '0' && tolower(p[i+5]) == 'a') {
400                                         p[j] = '\n';
401                                         j++;
402                                         i += 6;
403                                 } else {
404                                         ch = __cal_vcalendar_parse_decode_hexa(&p[i+1]);
405                                         p[j] = ch;
406                                         j++;
407                                         i += 3;
408                                 }
409                         }
410                 } else {
411                         p[j] = p[i];
412                         j++;
413                         i++;
414                 }
415         }
416         p[j] = '\0';
417         *len = i;
418         return CALENDAR_ERROR_NONE;
419 }
420
421 ////////////////////////////////////////////////////////////////////////
422
423 int _cal_vcalendar_parse_unfolding(char *stream)
424 {
425         char *p;
426
427         retv_if(stream == NULL, CALENDAR_ERROR_INVALID_PARAMETER);
428
429         p = stream;
430         while (*stream) {
431                 if ('=' == *stream && '\r' == *(stream + 1) && '\n' == *(stream + 2))
432                 {
433                         stream += 3;
434                 }
435                 else if ('\n' == *stream && ' ' == *(stream + 1))
436                 {
437                         stream += 2;
438                         p--;
439                 }
440                 else if ('\0' == *stream)
441                 {
442                         DBG("break\n");
443                         break;
444                 }
445                 *p = *stream;
446                 p++;
447                 stream++;
448
449         }
450         return CALENDAR_ERROR_NONE;
451 }
452
453 char *_cal_vcalendar_parse_read_line(char *stream, char **prop, char **cont)
454 {
455         int i;
456         char *p, *q;
457         int out;
458
459         /* skip space */
460         p = stream;
461         q = p;
462         out = 0;
463         while (*p) {
464                 switch (*p) {
465                 case ' ':
466                         break;
467                 default:
468                         out = 1;
469                         break;
470                 }
471                 if (out == 1) {
472                         break;
473                 }
474                 p++;
475         }
476
477         i = 0;
478         out = 0;
479         q = p;
480         while (*p) {
481                 switch (*p) {
482                 case ';':
483                 case ':':
484                         out = 1;
485                         break;
486                 default:
487                         i++;
488                         break;
489                 }
490                 if (out == 1) {
491                         i++;
492                         break;
493                 }
494                 p++;
495         }
496
497         if (0 < i) {
498                 *prop = calloc(1, i);
499                 snprintf(*prop, i, "%s", q);
500         } else {
501                 *prop = NULL;
502                 *cont = NULL;
503                 return NULL;
504         }
505
506         i = 0;
507         out = 0;
508         q = p;
509
510         while (*p) {
511                 switch (*p) {
512                 case '\r':
513                         if ('\n' == *(p + 1)) {
514                                 out = 1;
515                         }
516                         break;
517                 case '\0':
518                         break;
519                 default:
520                         i++;
521                         break;
522                 }
523                 if (out == 1) {
524                         i++;
525                         break;
526                 }
527                 p++;
528         }
529
530         if (0 < i) {
531                 *cont = calloc(1, i);
532                 snprintf(*cont, i, "%s", q);
533                 p += 2;
534         } else {
535                 *prop = NULL;
536                 *cont = NULL;
537                 return NULL;
538         }
539
540         DBG("%s][%s\n", *prop, *cont);
541         return p;
542 }
543
544 // start parse func ////////////////////////////////////////////////////
545 /* vcalendar */////////////////////////////////////////////////
546
547 static int __cal_vcalendar_parse_prodid(int *val, void *data)
548 {
549         return CALENDAR_ERROR_NONE;
550 }
551
552 static int __cal_vcalendar_parse_version(int *val, void *data)
553 {
554         char *p = (char *)data;
555
556         p++;
557         if (!strncmp(p, "1.0", strlen("1.0")))
558         {
559                 DBG("version 1.0");
560         }
561         else if (!strncmp(p, "2.0", strlen("2.0")))
562         {
563                 DBG("version 2.0");
564         }
565         else
566         {
567                 DBG("Invald version");
568         }
569
570         return CALENDAR_ERROR_NONE;
571 }
572
573 /* vevnt */////////////////////////////////////////////////
574 static int __cal_vcalendar_parse_dtstamp(int ver, calendar_list_h list, calendar_record_h event, void *data)
575 {
576         return CALENDAR_ERROR_NONE;
577 }
578
579 static int __cal_vcalendar_parse_uid(int type, calendar_list_h list, calendar_record_h record, void *data)
580 {
581         int ret;
582         char *p = (char *)data;
583
584         p++;
585
586         switch (type)
587         {
588         case CALENDAR_BOOK_TYPE_EVENT:
589                 ret = _cal_record_set_str(record, _calendar_event.uid, p);
590                 break;
591         case CALENDAR_BOOK_TYPE_TODO:
592                 ret = _cal_record_set_str(record, _calendar_todo.uid, p);
593                 break;
594         }
595         return CALENDAR_ERROR_NONE;
596 }
597
598 static int __cal_vcalendar_parse_get_tzid_from_list(calendar_list_h list, const char *tzid, calendar_record_h *timezone)
599 {
600         GList *l = NULL;
601
602         if (list == NULL || tzid == NULL)
603         {
604                 return -1;
605         }
606
607         cal_list_s *cal_list = (cal_list_s *)list;
608         l = g_list_first(cal_list->record);
609
610         while (l)
611         {
612                 char *uri = NULL;
613                 calendar_record_h record = (calendar_record_h)l->data;
614                 calendar_record_get_uri_p(record, &uri);
615                 if (strncmp(uri, _calendar_timezone._uri, strlen(_calendar_timezone._uri)))
616                 {
617                         l = g_list_next(l);
618                         continue;
619                 }
620
621                 cal_timezone_s *tz = (cal_timezone_s *)record;
622                 if (!strncmp(tz->standard_name, tzid, strlen(tzid)))
623                 {
624                         DBG("Found same tzid[%s] in the list", tzid);
625                         *timezone = record;
626                         break;
627                 }
628
629                 l = g_list_next(l);
630         }
631
632         return CALENDAR_ERROR_NONE;
633 }
634
635 static int __cal_vcalendar_parse_dtstart(int type, calendar_list_h list, calendar_record_h record, void *data)
636 {
637         int ret;
638         char *p = (char *)data;
639         int k = 0, j;
640         char *tzid = NULL; // free after appling
641         char buf[64] = {0, };
642         calendar_time_s start = {0};
643
644         p++;
645
646         int is_quot = 0;
647         if (!strncmp(p, "TZID=", strlen("TZID="))) {
648                 k = 0;
649                 j = strlen("TZID=");
650                 while ((p[j] != ':' && p[j] != ';' && p[j] != '\n' && p[j] != '\0') || is_quot == 1) {
651                         if (p[j] == '\"' && is_quot == 0)
652                         {
653                                 is_quot = 1;
654                                 j++;
655                         }
656                         else if (p[j] == '\"' && is_quot == 1)
657                         {
658                                 is_quot = 0;
659                                 j++;
660                                 break;
661                         }
662                         else
663                         {
664                         }
665
666                         buf[k] = p[j];
667                         k++;
668                         j++;
669                 }
670                 if (p[j] != '\0') {
671                         buf[k] = '\0';
672                 }
673                 p += j;
674                 p++;
675         } else {
676                 snprintf(buf, sizeof(buf), "%s", CAL_TZID_GMT);
677         }
678         tzid = strdup(buf);
679         DBG("tzid[%s]", tzid);
680         DBG("next[%s]", p);
681
682         if (!strncmp(p, "VALUE=", strlen("VALUE="))) {
683                 k = 0;
684                 j = strlen("VALUE=");
685                 while (p[j] != ':' && p[j] != ';' && p[j] != '\n' && p[j] != '\0') {
686                         buf[k] = p[j];
687                         k++;
688                         j++;
689                 }
690                 if (p[j] != '\0') {
691                         buf[k] = '\0';
692                 }
693                 p += j;
694                 p++;
695         }
696
697         int y, mon, d, h, min, s;
698         char t, z;
699
700         if (!strncmp(buf, "DATE", strlen("DATE"))){
701                 DBG("value is date");
702                 start.type = CALENDAR_TIME_LOCALTIME;
703
704                 sscanf(p, "%4d%2d%2d", &y, &mon, &d);
705                 start.time.date.year = y;
706                 start.time.date.month = mon;
707                 start.time.date.mday = d;
708
709         } else {
710                 DBG("value is utime");
711                 start.type = CALENDAR_TIME_UTIME;
712
713                 sscanf(p, "%4d%2d%2d%c%2d%2d%2d%c", &y, &mon, &d, &t, &h, &min, &s, &z);
714
715                 if (strlen(p) != strlen("YYYYMMDDTHHMMSS"))
716                 {
717                         start.time.utime = _cal_time_convert_itol(NULL, y, mon, d, h, min, s);
718                 }
719                 else
720                 {
721                         char *like_tzid = NULL;
722                         if (_cal_time_is_registered_tzid(tzid))
723                         {
724                                 start.time.utime = _cal_time_convert_itol(tzid, y, mon, d, h, min, s);
725                         }
726                         else
727                         {
728                                 calendar_record_h timezone = NULL;
729                                 // try get timezone info from the list
730                                 __cal_vcalendar_parse_get_tzid_from_list(list, tzid, &timezone);
731                                 if (timezone)
732                                 {
733                                         DBG("Found from the list");
734                                         _cal_time_get_like_tzid(tzid, timezone, &like_tzid);
735                                         start.time.utime = _cal_time_convert_itol(like_tzid, y, mon, d, h, min, s);
736                                         DBG("[%s]", like_tzid);
737                                         CAL_FREE(like_tzid);
738                                         like_tzid = NULL;
739                                 }
740                                 else
741                                 {
742                                         DBG("Nowhere to find");
743                                         start.time.utime = _cal_time_convert_itol(tzid, y, mon, d, h, min, s);
744                                 }
745                         }
746                 }
747         }
748
749         switch (type)
750         {
751         case CALENDAR_BOOK_TYPE_EVENT:
752                 ret = _cal_record_set_str(record, _calendar_event.start_tzid, tzid);
753                 ret = _cal_record_set_caltime(record, _calendar_event.start_time, start);
754                 break;
755         case CALENDAR_BOOK_TYPE_TODO:
756                 ret = _cal_record_set_str(record, _calendar_todo.start_tzid, tzid);
757                 ret = _cal_record_set_caltime(record, _calendar_todo.start_time, start);
758                 break;
759         }
760         if (tzid) free(tzid);
761
762         return CALENDAR_ERROR_NONE;
763 }
764
765 static int __cal_vcalendar_parse_created(int type, calendar_list_h list, calendar_record_h record, void *data)
766 {
767         int ret;
768         char *p = (char *)data;
769
770         p++;
771         switch (type)
772         {
773         case CALENDAR_BOOK_TYPE_EVENT:
774                 ret = _cal_record_set_lli(record, _calendar_event.created_time,
775                                 _cal_time_convert_stol(NULL, p));
776                 break;
777         case CALENDAR_BOOK_TYPE_TODO:
778                 ret = _cal_record_set_lli(record, _calendar_todo.created_time,
779                                 _cal_time_convert_stol(NULL, p));
780                 break;
781         }
782
783         return CALENDAR_ERROR_NONE;
784 }
785
786 static int __work_description_switch(int me, int mode, char *buf, int *charset, int *encoding)
787 {
788         switch (mode) {
789         case 1:
790         case 2:
791                 if (!strncmp(buf, "CHARSET=UTF-8", strlen("CHARSET=UTF-8"))) {
792                         DBG("CHARSET=UTF-8");
793                         *charset = 1;
794
795                 } else if (!strncmp(buf, "CHARSET=UTF-16",
796                                         strlen("CHARSET=UTF-16"))) {
797                         DBG("CHARSET=UTF-16");
798                         *charset = 1;
799
800                 } else if (!strncmp(buf, "ENCODING=BASE64",
801                                         strlen("ENCODING=BASE64"))) {
802                         DBG("ENCODE_BASE64");
803                         *encoding = ENCODE_BASE64;
804
805                 } else if (!strncmp(buf, "ENCODING=QUOTED-PRINTABLE",
806                                         strlen("ENCODING=QUOTED-PRINTABLE"))) {
807                         DBG("ENCODE_QUOTED_PRINTABLE");
808                         *encoding = ENCODE_QUOTED_PRINTABLE;
809
810                 } else {
811
812                 }
813                 mode = 0;
814                 break;
815         default:
816                 mode = me;
817                 break;
818         }
819         return mode;
820 }
821
822 static int __cal_vcalendar_parse_description(int type, calendar_list_h list, calendar_record_h record, void *data)
823 {
824         int i, j;
825         int ret;
826         int len;
827         int out;
828         int mode;
829         int charset, encoding;
830         char buf[64] = {0};
831         char *p = (char *)data;
832
833         i = j = 0;
834         out = 0;
835         mode = 0;
836         charset = encoding = 0;
837         while (p[i] != '\0') {
838                 switch (p[i]) {
839                 case ':':
840                         mode = 1;
841                         out = 1;
842                         break;
843
844                 case ';':
845                         buf[j] = '\0';
846                         mode = __work_description_switch(2, mode, buf, &charset, &encoding);
847                         j = 0;
848                         break;
849
850                 default:
851                         buf[j] = p[i];
852                         j++;
853                         break;
854                 }
855                 i++;
856
857                 if (out) {
858                         DBG("out");
859                         break;
860                 }
861         }
862         __work_description_switch(0, mode, buf, &charset, &encoding);
863
864         DBG("charset(%d) encoding(%d)", charset, encoding);
865         if (encoding) {
866                 __cal_vcalendar_parse_decode_quoted_printable(p+i, &len);
867         }
868
869         switch (type)
870         {
871         case CALENDAR_BOOK_TYPE_EVENT:
872                 ret = _cal_record_set_str(record, _calendar_event.description, p + i);
873                 break;
874         case CALENDAR_BOOK_TYPE_TODO:
875                 ret = _cal_record_set_str(record, _calendar_todo.description, p + i);
876                 break;
877         }
878
879         return CALENDAR_ERROR_NONE;
880 }
881
882 static int __cal_vcalendar_parse_last_mod(int type, calendar_list_h list, calendar_record_h record, void *data)
883 {
884         int ret;
885         char *p = (char *)data;
886
887         p++;
888
889         switch (type)
890         {
891         case CALENDAR_BOOK_TYPE_EVENT:
892                 ret = _cal_record_set_lli(record, _calendar_event.last_modified_time,
893                                 _cal_time_convert_stol(NULL, p));
894                 break;
895         case CALENDAR_BOOK_TYPE_TODO:
896                 ret = _cal_record_set_lli(record, _calendar_todo.last_modified_time,
897                                 _cal_time_convert_stol(NULL, p));
898                 break;
899         }
900         return CALENDAR_ERROR_NONE;
901 }
902
903 inline void __cal_vcalendar_parse_get_optional(char *p, int *encoding)
904 {
905         int i;
906
907         for (i = 0; i < TEXT_MAX; i++) {
908                 if (!strncmp(p, _optional_funcs[i].prop, strlen(_optional_funcs[i].prop))) {
909                         int j = 0;
910                         char buf[64] = {0, };
911                         p += strlen(_optional_funcs[i].prop);
912                         while (p[j] != ':' && p[j] != ';' && p[j] != '\n' && p[j] != '\0') {
913                                 buf[j] = p[j];
914                                 j++;
915                         }
916                         if (p[j] != '\0') {
917                                 buf[j] = '\0';
918                         }
919
920                         p += j;
921                         _optional_funcs[i].func(encoding, buf);
922                         break;
923                 } else {
924
925                 }
926         }
927 }
928
929 static int __cal_vcalendar_parse_location(int type, calendar_list_h list, calendar_record_h record, void *data)
930 {
931         int i, j;
932         int ret;
933         int len;
934         int out;
935         int mode;
936         int charset, encoding;
937         char buf[64] = {0};
938         char *p = (char *)data;
939
940         i = j = 0;
941         out = 0;
942         mode = 0;
943         charset = encoding = 0;
944         while (p[i] != '\0') {
945                 switch (p[i]) {
946                 case ':':
947                         mode = 1;
948                         out = 1;
949                         break;
950
951                 case ';':
952                         buf[j] = '\0';
953                         mode = __work_description_switch(2, mode, buf, &charset, &encoding);
954                         j = 0;
955                         break;
956
957                 default:
958                         buf[j] = p[i];
959                         j++;
960                         break;
961                 }
962                 i++;
963
964                 if (out) {
965                         DBG("out");
966                         break;
967                 }
968         }
969         __work_description_switch(0, mode, buf, &charset, &encoding);
970
971         DBG("charset(%d) encoding(%d)", charset, encoding);
972         if (encoding) {
973                 __cal_vcalendar_parse_decode_quoted_printable(p+i, &len);
974         }
975
976         switch (type)
977         {
978         case CALENDAR_BOOK_TYPE_EVENT:
979                 ret = _cal_record_set_str(record, _calendar_event.location, p + i);
980                 break;
981         case CALENDAR_BOOK_TYPE_TODO:
982                 ret = _cal_record_set_str(record, _calendar_todo.location, p + i);
983                 break;
984         }
985
986         return CALENDAR_ERROR_NONE;
987 }
988
989 static int __cal_vcalendar_parse_priority(int type, calendar_list_h list, calendar_record_h record, void *data)
990 {
991         int ret;
992         char *p = (char *)data;
993
994         p++;
995         if (p[0] < '0' || p[0] > '9') {
996                 DBG("warning check range\n");
997                 return -1;
998         }
999
1000         switch (type)
1001         {
1002         case CALENDAR_BOOK_TYPE_EVENT:
1003                 ret = _cal_record_set_int(record, _calendar_event.priority, atoi(p));
1004                 break;
1005         case CALENDAR_BOOK_TYPE_TODO:
1006                 ret = _cal_record_set_int(record, _calendar_todo.priority, atoi(p));
1007                 break;
1008         }
1009         return CALENDAR_ERROR_NONE;
1010 }
1011
1012 static int __cal_vcalendar_parse_status(int type, calendar_list_h list, calendar_record_h record, void *data)
1013 {
1014         int ret;
1015         int status;
1016         char *p = (char *)data;
1017
1018         p++;
1019
1020         switch (type)
1021         {
1022         case CALENDAR_BOOK_TYPE_EVENT:
1023                 if (!strncmp(p, "TENTATIVE", strlen("TENTATIVE")))
1024                 {
1025                         status = CALENDAR_EVENT_STATUS_TENTATIVE;
1026                 }
1027                 else if (!strncmp(p, "CONFIRMED", strlen("CONFIRMED")))
1028                 {
1029                         status = CALENDAR_EVENT_STATUS_CONFIRMED;
1030                 }
1031                 else if (!strncmp(p, "CANCELLED", strlen("CANCELLED")))
1032                 {
1033                         status = CALENDAR_EVENT_STATUS_CANCELLED;
1034                 }
1035                 else
1036                 {
1037                         status = CALENDAR_EVENT_STATUS_NONE;
1038                 }
1039                 ret = _cal_record_set_int(record, _calendar_event.event_status, status);
1040
1041                 break;
1042
1043         case CALENDAR_BOOK_TYPE_TODO:
1044                 if (!strncmp(p, "NEEDS-ACTION", strlen("NEEDS-ACTION"))) // for ver2.0
1045                 {
1046                         status = CALENDAR_TODO_STATUS_NEEDS_ACTION;
1047                 }
1048                 else if (!strncmp(p, "NEEDS ACTION", strlen("NEEDS ACTION"))) // for ver1.0
1049                 {
1050                         status = CALENDAR_TODO_STATUS_NEEDS_ACTION;
1051                 }
1052                 else if (!strncmp(p, "COMPLETED", strlen("COMPLETED")))
1053                 {
1054                         status = CALENDAR_TODO_STATUS_COMPLETED;
1055                 }
1056                 else if (!strncmp(p, "IN-PROCESS", strlen("IN-PROCESS")))
1057                 {
1058                         status = CALENDAR_TODO_STATUS_IN_PROCESS;
1059                 }
1060                 else if (!strncmp(p, "CANCELLED", strlen("CANCELLED")))
1061                 {
1062                         status = CALENDAR_TODO_STATUS_CANCELED;
1063                 }
1064                 else
1065                 {
1066                         status = CALENDAR_TODO_STATUS_NONE;
1067                 }
1068                 ret = _cal_record_set_int(record, _calendar_todo.todo_status, status);
1069
1070                 break;
1071         }
1072
1073         return CALENDAR_ERROR_NONE;
1074 }
1075
1076 static int __cal_vcalendar_parse_summary(int type, calendar_list_h list, calendar_record_h record, void *data)
1077 {
1078         int ret;
1079         int i, j;
1080         int len;
1081         int out;
1082         int mode;
1083         int charset, encoding;
1084         char buf[64] = {0};
1085         char *p = (char *)data;
1086
1087         i = j = 0;
1088         out = 0;
1089         mode = 0;
1090         charset = encoding = 0;
1091         while (p[i] != '\0') {
1092                 switch (p[i]) {
1093                 case ':':
1094                         mode = 1;
1095                         out = 1;
1096                         break;
1097
1098                 case ';':
1099                         buf[j] = '\0';
1100                         mode = __work_description_switch(2, mode, buf, &charset, &encoding);
1101                         j = 0;
1102                         break;
1103
1104                 default:
1105                         buf[j] = p[i];
1106                         j++;
1107                         break;
1108                 }
1109                 i++;
1110
1111                 if (out) {
1112                         break;
1113                 }
1114         }
1115         __work_description_switch(0, mode, buf, &charset, &encoding);
1116
1117         DBG("charset(%d) encoding(%d)", charset, encoding);
1118         if (encoding) {
1119                 __cal_vcalendar_parse_decode_quoted_printable(p+i, &len);
1120         }
1121
1122         switch (type)
1123         {
1124         case CALENDAR_BOOK_TYPE_EVENT:
1125                 ret = _cal_record_set_str(record, _calendar_event.summary, p + i);
1126                 break;
1127         case CALENDAR_BOOK_TYPE_TODO:
1128                 ret = _cal_record_set_str(record, _calendar_todo.summary, p + i);
1129                 break;
1130         }
1131
1132         DBG("summary(%s)\n", p + i);
1133         return CALENDAR_ERROR_NONE;
1134 }
1135
1136 static int __cal_vcalendar_parse_rrule(int ver, calendar_list_h list, calendar_record_h event, void *data)
1137 {
1138         int ret;
1139         int i, j, k;
1140         int mode;
1141         int version = 0;
1142         char buf[64] = {0};
1143         char *tzid;
1144         char *p = (char *)data;
1145
1146         i = j = 0;
1147         mode = 0;
1148
1149         if (strstr(p, "FREQ=")) {
1150                 DBG("This is version 2");
1151                 version = 2;
1152         } else {
1153                 DBG("This is version 1");
1154                 version = 1;
1155         }
1156
1157         if (version == 2) {
1158                 i = j = 0;
1159                 ret = _cal_record_set_int(event, _calendar_event.interval, 1);
1160                 /* this is for ver 2 */
1161                 while (p[i] != '\0') {
1162                         DBG("[%c](%d)", p[i], i);
1163                         switch (p[i]) {
1164                         case ':':
1165                         case ';':
1166                                 buf[j] = '\0';
1167                                 if (strlen(buf) < 1) {
1168                                         break;
1169                                 }
1170
1171                                 for (k = 0; k < RRULE_MAX; k++) {
1172                                         if (!strncmp(buf, _rrule_funcs[k].prop, strlen(_rrule_funcs[k].prop))) {
1173                                                 _rrule_funcs[k].func(event, buf + strlen(_rrule_funcs[k].prop));
1174                                                 break;
1175                                         }
1176                                 }
1177                                 j = 0;
1178                                 break;
1179
1180                         default:
1181                                 buf[j] = p[i];
1182                                 j++;
1183                                 break;
1184                         }
1185                         i++;
1186                 }
1187
1188                 buf[j] = '\0';
1189                 for (i = 0; i < RRULE_MAX; i++) {
1190                         if (!strncmp(buf, _rrule_funcs[i].prop, strlen(_rrule_funcs[i].prop))) {
1191                                 version = 2;
1192                                 _rrule_funcs[i].func(event, buf + strlen(_rrule_funcs[i].prop));
1193                                 break;
1194                         }
1195                 }
1196                 return CALENDAR_ERROR_NONE;
1197         }
1198
1199         /* this is for ver 1 */
1200         int freq = 0;
1201         int interval;
1202         char by[64] = {0};
1203         char _by[64] = {0};
1204         char date[8] = {0};
1205         int tmp;
1206         int is_wday = 0;
1207         int y, mon, d, h, min, s;
1208         char t, z;
1209         calendar_time_s stime;
1210         i = 0;
1211         mode = 0;
1212         interval = 0;
1213
1214         ret = calendar_record_get_str(event, _calendar_event.start_tzid, &tzid);
1215         ret = calendar_record_get_caltime(event, _calendar_event.start_time, &stime);
1216
1217         while (p[i] != '\0') {
1218                 switch (p[i]) {
1219                 case ':':
1220                 case ' ':
1221                         if (mode == 0) {
1222                                 DBG("in mode 1");
1223                                 mode = 1;
1224
1225                         } else if (mode == 1) {
1226                                 DBG("in mode 2");
1227                                 mode = 2;
1228                                 buf[j] = '\0';
1229                                 if (buf[0] == 'D') {
1230                                         freq = CALENDAR_RECURRENCE_DAILY;
1231
1232                                 } else if (buf[0] == 'W') {
1233                                         freq = CALENDAR_RECURRENCE_WEEKLY;
1234
1235                                 } else if (buf[0] == 'M') {
1236                                         freq = CALENDAR_RECURRENCE_MONTHLY;
1237
1238                                 } else if (buf[0] == 'Y') {
1239                                         freq = CALENDAR_RECURRENCE_YEARLY;
1240
1241                                 } else {
1242                                         freq = CALENDAR_RECURRENCE_NONE;
1243
1244                                 }
1245                                 ret = _cal_record_set_int(event, _calendar_event.freq, freq);
1246
1247                                 if (buf[1] >= '1' && buf[1] <= '9') {
1248                                         interval = atoi(&buf[1]);
1249                                 } else {
1250                                         interval = atoi(&buf[2]);
1251                                 }
1252                                 DBG("interval(%d)", interval);
1253                                 ret = _cal_record_set_int(event, _calendar_event.interval, interval);
1254                                 memset(buf, 0x0, sizeof(buf));
1255
1256                         } else {
1257                                 mode = 3;
1258                                 DBG("in mode 3");
1259                                 DBG("remained buf[%s]", buf);
1260
1261
1262                                 DBG("len(%d)", strlen(by));
1263                                 if (strlen(by) < 1) {
1264                                         DBG("ret(%d)", atoi(buf));
1265                                         if (buf[0] >= '1' && buf[0] <= '9') {
1266                                                 DBG("Set digit");
1267                                                 is_wday = 0;
1268                                         } else {
1269                                                 DBG("Set wday [%s]", buf);
1270                                                 is_wday = 1;
1271                                         }
1272                                         DBG("1[%s][%s]", by, buf);
1273                                         snprintf(_by, sizeof(by), "%s", buf);
1274
1275                                 } else {
1276                                         DBG("2[%s][%s]", by, buf);
1277                                         snprintf(_by, sizeof(by), "%s %s", by, buf);
1278                                 }
1279                                 memcpy(by, _by, sizeof(_by));
1280
1281
1282                                 buf[j] = '\0';
1283                                 DBG("end statement[%s]", buf);
1284                                 DBG("freq(%d}", freq);
1285                                 switch (freq) {
1286                                 case CALENDAR_RECURRENCE_YEARLY:
1287                                         ret = _cal_record_set_str(event, _calendar_event.bymonth, by);
1288                                         _cal_time_ltoi(tzid, stime.time.utime, NULL, NULL, &tmp);
1289                                         snprintf(date, sizeof(date), "%d", tmp);
1290                                         ret = _cal_record_set_str(event, _calendar_event.bymonthday, date);
1291                                         break;
1292
1293                                 case CALENDAR_RECURRENCE_MONTHLY:
1294                                         _cal_time_ltoi(tzid, stime.time.utime, NULL, &tmp, NULL);
1295                                         snprintf(date, sizeof(date), "%d", tmp);
1296                                         ret = _cal_record_set_str(event, _calendar_event.bymonth, date);
1297
1298                                         if (is_wday) {
1299                                                 ret = _cal_record_set_str(event, _calendar_event.byday, by);
1300                                         } else {
1301                                                 ret = _cal_record_set_str(event, _calendar_event.bymonthday, by);
1302                                         }
1303                                         break;
1304
1305                                 case CALENDAR_RECURRENCE_WEEKLY:
1306                                         DBG("set weekly[%s]", by);
1307                                         ret = _cal_record_set_str(event, _calendar_event.byday, by);
1308                                         break;
1309
1310                                 case CALENDAR_RECURRENCE_DAILY:
1311                                         DBG("set daily[%s]", by);
1312                                         ret = _cal_record_set_str(event, _calendar_event.byday, by);
1313                                         break;
1314                                 default:
1315                                         DBG("Nothing to set");
1316                                         break;
1317                                 }
1318                         }
1319                         j = 0;
1320                         memset(buf, 0x0, sizeof(buf));
1321                         break;
1322
1323                 default:
1324                         buf[j] = p[i];
1325                         j++;
1326                         break;
1327                 }
1328                 i++;
1329         }
1330
1331         DBG("freq(%d) interval(%d) by[%s]", freq, interval, by);
1332
1333         i = 0;
1334         DBG("buf[%s]", buf);
1335         calendar_time_s caltime = {0};
1336         if (buf[i] == '#') {
1337                 if (buf[i + 1] == '0')
1338                 {
1339                         DBG("count 0 and means endless");
1340                         ret = _cal_record_set_int(event, _calendar_event.range_type,
1341                                         CALENDAR_RANGE_NONE);
1342                 }
1343                 else
1344                 {
1345                         DBG("until count [%s]", &buf[i+1]);
1346                         ret = _cal_record_set_int(event, _calendar_event.range_type,
1347                                         CALENDAR_RANGE_COUNT);
1348                         ret = _cal_record_set_int(event, _calendar_event.count,
1349                                         atoi(&buf[i+1]));
1350                 }
1351
1352         } else {
1353                 ret = _cal_record_set_int(event, _calendar_event.range_type,
1354                                 CALENDAR_RANGE_UNTIL);
1355                 DBG("untiltime[%s]", &buf[i]);
1356                 sscanf(&buf[i], "%4d%2d%2d%c%2d%2d%2d%c",
1357                                 &y, &mon, &d, &t, &h, &min, &s, &z);
1358                 caltime.type = CALENDAR_TIME_UTIME;
1359                 caltime.time.utime = _cal_time_convert_itol(tzid, y, mon, d, h, min, s);
1360                 ret = _cal_record_set_caltime(event, _calendar_event.until_time, caltime);
1361         }
1362
1363         CAL_FREE(tzid);
1364
1365         return CALENDAR_ERROR_NONE;
1366 }
1367
1368 static int __cal_vcalendar_parse_dtend(int type, calendar_list_h list, calendar_record_h record, void *data)
1369 {
1370         int ret;
1371         char *p = (char *)data;
1372         int k = 0, j;
1373         char buf[64] = {0, };
1374         char *tzid = NULL;
1375         calendar_time_s end;
1376
1377         p++;
1378
1379         int is_quot = 0;
1380         if (!strncmp(p, "TZID=", strlen("TZID="))) {
1381                 k = 0;
1382                 j = strlen("TZID=");
1383                 while ((p[j] != ':' && p[j] != ';' && p[j] != '\n' && p[j] != '\0') || is_quot == 1) {
1384
1385                         if (p[j] == '\"' && is_quot == 0)
1386                         {
1387                                 is_quot = 1;
1388                                 j++; // remove double quotation
1389                         }
1390                         else if (p[j] == '\"' && is_quot == 1)
1391                         {
1392                                 is_quot = 0;
1393                                 j++;
1394                                 break;
1395                         }
1396                         else
1397                         {
1398                         }
1399
1400                         buf[k] = p[j];
1401                         k++;
1402                         j++;
1403                 }
1404                 if (p[j] != '\0') {
1405                         buf[k] = '\0';
1406                 }
1407                 p += j;
1408                 p++;
1409         } else {
1410                 snprintf(buf, sizeof(buf), "%s", CAL_TZID_GMT);
1411         }
1412         tzid = strdup(buf);
1413
1414         if (!strncmp(p, "VALUE=", strlen("VALUE="))) {
1415                 k = 0;
1416                 j = strlen("VALUE=");
1417                 while (p[j] != ':' && p[j] != ';' && p[j] != '\n' && p[j] != '\0') {
1418                         buf[k] = p[j];
1419                         k++;
1420                         j++;
1421                 }
1422                 if (p[j] != '\0') {
1423                         buf[k] = '\0';
1424                 }
1425                 p += j;
1426                 p++;
1427         }
1428
1429         int y, mon, d, h, min, s;
1430         char t, z;
1431
1432         if (!strncmp(buf, "DATE", strlen("DATE"))){
1433                 end.type = CALENDAR_TIME_LOCALTIME;
1434
1435                 sscanf(p, "%4d%2d%2d", &y, &mon, &d);
1436                 end.time.date.year = y;
1437                 end.time.date.month = mon;
1438                 end.time.date.mday = d;
1439
1440         } else {
1441                 end.type = CALENDAR_TIME_UTIME;
1442
1443                 sscanf(p, "%4d%2d%2d%c%2d%2d%2d%c", &y, &mon, &d, &t, &h, &min, &s, &z);
1444
1445                 if (strlen(p) != strlen("YYYYMMDDTHHMMSS"))
1446                 {
1447                         end.time.utime = _cal_time_convert_itol(NULL, y, mon, d, h, min, s);
1448                 }
1449                 else
1450                 {
1451                         char *like_tzid = NULL;
1452                         if (_cal_time_is_registered_tzid(tzid))
1453                         {
1454                                 end.time.utime = _cal_time_convert_itol(tzid, y, mon, d, h, min, s);
1455                         }
1456                         else
1457                         {
1458                                 calendar_record_h timezone = NULL;
1459                                 // try get timezone info from the list
1460                                 __cal_vcalendar_parse_get_tzid_from_list(list, tzid, &timezone);
1461                                 if (timezone)
1462                                 {
1463                                         DBG("Found from the list");
1464                                         _cal_time_get_like_tzid(tzid, timezone, &like_tzid);
1465                                         end.time.utime = _cal_time_convert_itol(like_tzid, y, mon, d, h, min, s);
1466                                         DBG("[%s]", like_tzid);
1467                                         CAL_FREE(like_tzid);
1468                                         like_tzid = NULL;
1469                                 }
1470                                 else
1471                                 {
1472                                         DBG("Nowhere to find");
1473                                         end.time.utime = _cal_time_convert_itol(tzid, y, mon, d, h, min, s);
1474                                 }
1475                         }
1476                 }
1477         }
1478         switch (type)
1479         {
1480         case CALENDAR_BOOK_TYPE_EVENT:
1481                 ret = _cal_record_set_str(record, _calendar_event.end_tzid, tzid);
1482                 ret = _cal_record_set_caltime(record, _calendar_event.end_time, end);
1483                 break;
1484         case CALENDAR_BOOK_TYPE_TODO:
1485                 ret = _cal_record_set_str(record, _calendar_todo.due_tzid, tzid);
1486                 ret = _cal_record_set_caltime(record, _calendar_todo.due_time, end);
1487                 break;
1488         }
1489         CAL_FREE(tzid);
1490
1491         return CALENDAR_ERROR_NONE;
1492 }
1493
1494 static int __cal_vcalendar_parse_completed(int ver, calendar_list_h list, calendar_record_h event, void *data)
1495 {
1496         return CALENDAR_ERROR_NONE;
1497 }
1498
1499 static int __cal_vcalendar_parse_percent(int ver, calendar_list_h list, calendar_record_h event, void *data)
1500 {
1501         return CALENDAR_ERROR_NONE;
1502 }
1503
1504 /////////////////////////////////////////////////////////////////
1505 static int __cal_vcalendar_parse_attendee_cutype(calendar_record_h attendee, void *data)
1506 {
1507         return CALENDAR_ERROR_NONE;
1508 }
1509
1510 static int __cal_vcalendar_parse_attendee_member(calendar_record_h attendee, void *data)
1511 {
1512         return CALENDAR_ERROR_NONE;
1513 }
1514
1515 static int __cal_vcalendar_parse_attendee_role(calendar_record_h attendee, void *data)
1516 {
1517         return CALENDAR_ERROR_NONE;
1518 }
1519
1520 static int __cal_vcalendar_parse_attendee_partstat(calendar_record_h attendee, void *data)
1521 {
1522         return CALENDAR_ERROR_NONE;
1523 }
1524
1525 static int __cal_vcalendar_parse_attendee_rsvp(calendar_record_h attendee, void *data)
1526 {
1527         return CALENDAR_ERROR_NONE;
1528 }
1529
1530 static int __cal_vcalendar_parse_attendee_delto(calendar_record_h attendee, void *data)
1531 {
1532         return CALENDAR_ERROR_NONE;
1533 }
1534
1535 static int __cal_vcalendar_parse_attendee_delfrom(calendar_record_h attendee, void *data)
1536 {
1537         return CALENDAR_ERROR_NONE;
1538 }
1539
1540 static int __cal_vcalendar_parse_attendee_sentby(calendar_record_h attendee, void *data)
1541 {
1542         return CALENDAR_ERROR_NONE;
1543 }
1544
1545 static int __cal_vcalendar_parse_attendee_cn(calendar_record_h attendee, void *data)
1546 {
1547         int ret;
1548         int i = 0;
1549         char *text = NULL;
1550         char *p = (char *)data;
1551
1552         while (*p != ':' && *p != '\n' && *p != '\r' && *p != '\0') {
1553                 i++;
1554                 p++;
1555         }
1556
1557         text = calloc(i + 1, sizeof(char));
1558         if (text == NULL) {
1559                 ERR("Failed to calloc");
1560                 return -1;
1561         }
1562         snprintf(text, i + 1, "%s", (char *)data);
1563
1564         ret = _cal_record_set_str(attendee, _calendar_attendee.name, text);
1565         DBG("cn[%s]", text);
1566         if (text) free(text);
1567
1568         return CALENDAR_ERROR_NONE;
1569 }
1570
1571 static int __cal_vcalendar_parse_attendee_dir(calendar_record_h attendee, void *data)
1572 {
1573         return CALENDAR_ERROR_NONE;
1574 }
1575
1576 int _work_attendee_mailto(calendar_record_h attendee, char *buf)
1577 {
1578         return CALENDAR_ERROR_NONE;
1579 }
1580
1581 int _work_attendee_property(calendar_record_h attendee, char *buf)
1582 {
1583         int i;
1584         int len_all, len_prop;
1585
1586         for (i = 0; i < ATTENDEE_MAX; i++) {
1587                 if (!strncmp(buf, _attendee_funcs[i].prop, strlen(_attendee_funcs[i].prop))) {
1588                         len_all = strlen(buf);
1589                         len_prop = strlen(_attendee_funcs[i].prop);
1590                         snprintf(buf, len_all - len_prop + 1, "%s", &buf[len_prop]);
1591                         _attendee_funcs[i].func(attendee, buf);
1592                         break;
1593                 }
1594         }
1595         return CALENDAR_ERROR_NONE;
1596 }
1597
1598 static int __cal_vcalendar_parse_attendee(int ver, calendar_list_h list, calendar_record_h event, void *data)
1599 {
1600         int ret;
1601         int i, j;
1602         char *p = (char *)data;
1603         calendar_record_h attendee;
1604
1605         ret = calendar_record_create(_calendar_attendee._uri, &attendee);
1606
1607         ret = calendar_record_add_child_record(event, _calendar_event.calendar_attendee, attendee);
1608
1609         i = 0;
1610         j = 0;
1611         int mode = 0;
1612         char buf[64] = {0};
1613
1614         while (p[i] != '\0') {
1615                 switch (p[i]) {
1616                 case ':':
1617                         /* work mail to */
1618                         if (mode) {
1619                                 buf[j] = '\0';
1620                                 _work_attendee_mailto(attendee, buf);
1621                                 mode = 0;
1622                         } else {
1623                                 mode = 1;
1624                         }
1625                         j = 0;
1626                         break;
1627
1628                 case ';':
1629                         /* work property */
1630                         if (mode) {
1631                                 buf[j] = '\0';
1632                                 _work_attendee_property(attendee, buf);
1633                                 mode = 0;
1634                         } else {
1635                                 mode = 2;
1636                         }
1637                         j = 0;
1638                         break;
1639
1640                 default:
1641                         buf[j] = p[i];
1642                         j++;
1643                         break;
1644                 }
1645                 i++;
1646         }
1647
1648         switch (mode) {
1649         case 1:
1650                 buf[j] = '\0';
1651                 _work_attendee_mailto(attendee, buf);
1652                 break;
1653         case 2:
1654                 buf[j] = '\0';
1655                 _work_attendee_property(attendee, buf);
1656                 break;
1657         default:
1658                 break;
1659         }
1660
1661         return CALENDAR_ERROR_NONE;
1662 }
1663
1664
1665 static int __cal_vcalendar_parse_categories(int ver, calendar_list_h list, calendar_record_h event, void *data)
1666 {
1667         char *p = (char *)data;
1668         int encoding = 0;
1669
1670         while (*p != '\n' && *p != '\r' && *p != '\0') {
1671                 if ( *p == ':') {
1672                         p++;
1673                         if (encoding == ENCODE_BASE64) {
1674                                 gsize len;
1675                                 _cal_record_set_str(event, _calendar_event.categories,
1676                                                 (char *)g_base64_decode(p, &len));
1677
1678                         } else if (encoding == ENCODE_QUOTED_PRINTABLE) {
1679                                 int len;
1680                                 __cal_vcalendar_parse_decode_quoted_printable(p, &len);
1681                                 _cal_record_set_str(event, _calendar_event.categories, p);
1682
1683                         } else {
1684                                 _cal_record_set_str(event, _calendar_event.categories, p);
1685                         }
1686                         break;
1687
1688                 } else if (*p == ';') {
1689                         p++;
1690                         __cal_vcalendar_parse_get_optional(p, &encoding);
1691
1692                 } else {
1693                         p++;
1694                 }
1695         }
1696         DBG("ver(%d)categories(%s)\n", ver, p);
1697
1698         return CALENDAR_ERROR_NONE;
1699 }
1700
1701 /*
1702    For ver 1.0 aalarm
1703    alarmparts   = 0*3(strnosemi ";") strnosemi
1704    ; runTime, snoozeTime, repeatCount, audioContent
1705 */
1706 enum {
1707         __AALARM_INVALID = 0,
1708         __AALARM_RUNTIME,
1709         __AALARM_TYPE,
1710         __AALARM_VALUE,
1711         __AALARM_SNOOZETIME,
1712         __AALARM_REPEATCOUNT,
1713         __AALARM_AUDIOCONTENT,
1714 };
1715 static int __cal_vcalendar_parse_aalarm(int ver, calendar_list_h list, calendar_record_h record, void *data)
1716 {
1717         int ret;
1718         int i = 0, j = 0;
1719         int part = 0;
1720         int y, mon, d, h, min, s;
1721         char t, z;
1722         char buf[64] = {0};
1723         char *p = (char *)data;
1724
1725         while (p[i] != '\0')
1726         {
1727                 // select part
1728                 switch (p[i])
1729                 {
1730                 case ':':
1731                         i++;
1732                         part = __AALARM_RUNTIME;
1733                         break;
1734
1735                 case ';':
1736                         i++;
1737                         if (!strncmp(p, "TYPE=", strlen("TYPE=")))
1738                         {
1739                                 part = __AALARM_TYPE;
1740                         }
1741                         else if (!strncmp(p, "VALUE=", strlen("VALUE=")))
1742                         {
1743                                 part = __AALARM_VALUE;
1744                         }
1745                         else if (p[i] == 'P')
1746                         {
1747                                 part = __AALARM_SNOOZETIME; // Period
1748                         }
1749                         else if (p[i] >= '0' && p[i] < '9')
1750                         {
1751                                 part = __AALARM_REPEATCOUNT; // repeatCount
1752                         }
1753                         else
1754                         {
1755                                 part = __AALARM_AUDIOCONTENT;
1756                         }
1757                         break;
1758
1759                 default:
1760                         ERR("Error");
1761                         i++;
1762                         break;
1763                 }
1764
1765                 // extract value
1766                 j = 0;
1767                 while (p[i] != '\0' && p[i] != ':' && p[i] != ';')
1768                 {
1769                         buf[j] = p[i];
1770                         j++;
1771                         i++;
1772                 }
1773                 buf[j] = '\0';
1774
1775                 DBG("part(%d) value[%s]", part, buf);
1776                 // work part
1777                 switch (part)
1778                 {
1779                 case __AALARM_INVALID:
1780                         break;
1781
1782                 case __AALARM_RUNTIME:
1783                         y = mon = d = h = min = s = 0;
1784                         sscanf(buf, "%04d%02d%02d%c%02d%02d%02d%c", &y, &mon, &d, &t, &h, &min, &s, &z);
1785                         DBG("%d %d %d %d %d %d", y, mon, d, h, min, s);
1786                         break;
1787
1788                 case __AALARM_TYPE:
1789                         break;
1790
1791                 case __AALARM_VALUE:
1792                         break;
1793
1794                 case __AALARM_SNOOZETIME:
1795                         break;
1796
1797                 case __AALARM_REPEATCOUNT:
1798                         break;
1799
1800                 case __AALARM_AUDIOCONTENT:
1801                         break;
1802
1803                 }
1804         }
1805
1806         char *tzid = NULL;
1807         long long int run_utime = 0;
1808         int diff = 0;
1809         int tick = 0, unit = 0;
1810         calendar_record_h alarm = NULL;
1811         calendar_time_s caltime = {0};
1812         switch (ver)
1813         {
1814         case VCALENDAR_TYPE_VEVENT:
1815                 ret = calendar_record_get_caltime(record, _calendar_event.start_time, &caltime);
1816                 if (z != 'Z')
1817                 {
1818                         ret = calendar_record_get_str_p(record, _calendar_event.start_tzid, &tzid);
1819                         run_utime = _cal_time_convert_itol(tzid, y, mon, d, h, min, s);
1820                         if (tzid) free(tzid);
1821                 }
1822                 else
1823                 {
1824                         run_utime = _cal_time_convert_itol(NULL, y, mon, d, h, min, s);
1825                 }
1826
1827                 switch (caltime.type)
1828                 {
1829                 case CALENDAR_TIME_UTIME:
1830                         diff = (int)(caltime.time.utime - run_utime);
1831                         DBG("diff(%d) = (%lld) - (%lld)", diff, caltime.time.utime, run_utime);
1832
1833                         if (diff / (60 * 60 * 24 * 7) > 0)
1834                         {
1835                                 unit = CALENDAR_ALARM_TIME_UNIT_WEEK;
1836                                 tick = diff /(60 * 60 * 24 * 7);
1837                         }
1838                         else if (diff / (60 * 60 * 24 ) > 0)
1839                         {
1840                                 unit = CALENDAR_ALARM_TIME_UNIT_DAY;
1841                                 tick = diff /(60 * 60 * 24);
1842                         }
1843                         else if (diff / (60 * 60) > 0)
1844                         {
1845                                 unit = CALENDAR_ALARM_TIME_UNIT_HOUR;
1846                                 tick = diff / (60 * 60);
1847                         }
1848                         else
1849                         {
1850                                 unit = CALENDAR_ALARM_TIME_UNIT_MINUTE;
1851                                 tick = diff / 60;
1852                         }
1853                         break;
1854
1855                 case CALENDAR_TIME_LOCALTIME:
1856                         break;
1857                 }
1858
1859                 ret = calendar_record_create(_calendar_alarm._uri, &alarm);
1860                 if (CALENDAR_ERROR_NONE != ret)
1861                 {
1862                         ERR("calendar_record_create() failed");
1863                         return ret;
1864                 }
1865                 calendar_record_set_int(alarm, _calendar_alarm.tick, tick);
1866                 calendar_record_set_int(alarm, _calendar_alarm.tick_unit, unit);
1867                 calendar_record_add_child_record(record, _calendar_event.calendar_alarm, alarm);
1868                 break;
1869
1870         case VCALENDAR_TYPE_VTODO:
1871                 ret = calendar_record_get_caltime(record, _calendar_todo.due_time, &caltime);
1872                 if (z != 'Z')
1873                 {
1874                         ret = calendar_record_get_str_p(record, _calendar_todo.due_tzid, &tzid);
1875                         run_utime = _cal_time_convert_itol(tzid, y, mon, d, h, min, s);
1876                         if (tzid) free(tzid);
1877                 }
1878                 else
1879                 {
1880                         run_utime = _cal_time_convert_itol(NULL, y, mon, d, h, min, s);
1881                 }
1882
1883                 switch (caltime.type)
1884                 {
1885                 case CALENDAR_TIME_UTIME:
1886                         diff = (int)(caltime.time.utime - run_utime);
1887
1888                         if (diff / (60 * 60 * 24 * 7) > 0)
1889                         {
1890                                 unit = CALENDAR_ALARM_TIME_UNIT_WEEK;
1891                                 tick = diff /(60 * 60 * 24 * 7);
1892                         }
1893                         else if (diff / (60 * 60 * 24 ) > 0)
1894                         {
1895                                 unit = CALENDAR_ALARM_TIME_UNIT_DAY;
1896                                 tick = diff /(60 * 60 * 24);
1897                         }
1898                         else if (diff / (60 * 60) > 0)
1899                         {
1900                                 unit = CALENDAR_ALARM_TIME_UNIT_HOUR;
1901                                 tick = diff / (60 * 60);
1902                         }
1903                         else
1904                         {
1905                                 unit = CALENDAR_ALARM_TIME_UNIT_MINUTE;
1906                                 tick = diff / 60;
1907                         }
1908                         break;
1909
1910                         break;
1911                 case CALENDAR_TIME_LOCALTIME:
1912                         break;
1913                 }
1914                 ret = calendar_record_create(_calendar_alarm._uri, &alarm);
1915                 if (CALENDAR_ERROR_NONE != ret)
1916                 {
1917                         ERR("calendar_record_create() failed");
1918                         return ret;
1919                 }
1920                 calendar_record_set_int(alarm, _calendar_alarm.tick, tick);
1921                 calendar_record_set_int(alarm, _calendar_alarm.tick_unit, unit);
1922                 calendar_record_add_child_record(record, _calendar_todo.calendar_alarm, alarm);
1923                 break;
1924         }
1925
1926         return CALENDAR_ERROR_NONE;
1927 }
1928 /* end */
1929
1930
1931 enum {
1932         WEEKNAME2_SA = 0x0,
1933         WEEKNAME2_FR,
1934         WEEKNAME2_TH,
1935         WEEKNAME2_WE,
1936         WEEKNAME2_TU,
1937         WEEKNAME2_MO,
1938         WEEKNAME2_SU,
1939         WEEKNAME2_MAX,
1940 };
1941 const char weekname2[WEEKNAME2_MAX][3] = {"SA", "FR", "TH", "WE", "TU", "MO", "SU"};
1942
1943 //alarm////////////////////////////////////////////////////////////
1944 static int __cal_vcalendar_parse_action(calendar_record_h alarm, void *data)
1945 {
1946         return CALENDAR_ERROR_NONE;
1947 }
1948
1949 static char *__cal_vcalendar_parse_extract_duration(char *p, int *dur_t, char *dur)
1950 {
1951         char du = '0';
1952         char buf[8] = {0, };
1953         int i = 0, c, d = 1;
1954         int t = 0;
1955
1956         DBG("%s", p);
1957         while (*p != '\0' && *p != '\n') {
1958                 switch (*p) {
1959                 case '+':
1960                         d = 1;
1961                         break;
1962                 case '-':
1963                         d = -1;
1964                         break;
1965                 case 'P':
1966                         i = 0;
1967                         break;
1968                 case 'T':
1969                         break;
1970                 case 'W':
1971                         du = 'W';
1972                         c = atoi(buf);
1973                         t += c * 7 * 24 * 60 * 60;
1974                         memset(buf, 0x0, sizeof(buf));
1975                         i = 0;
1976                         break;
1977                 case 'D':
1978                         du = 'D';
1979                         c = atoi(buf);
1980                         t += c * 24 * 60 * 60;
1981                         memset(buf, 0x0, sizeof(buf));
1982                         i = 0;
1983                         break;
1984                 case 'H':
1985                         du = 'H';
1986                         c = atoi(buf);
1987                         t += c * 60 * 60;
1988                         memset(buf, 0x0, sizeof(buf));
1989                         i = 0;
1990                         break;
1991                 case 'M':
1992                         du = 'M';
1993                         c = atoi(buf);
1994                         t += c * 60;
1995                         memset(buf, 0x0, sizeof(buf));
1996                         i = 0;
1997                         break;
1998                 case 'S':
1999                         du = 'S';
2000                         c = atoi(buf);
2001                         t += c;
2002                         memset(buf, 0x0, sizeof(buf));
2003                         i = 0;
2004                         break;
2005                 default:
2006                         buf[i] = *p;
2007                         i++;
2008                         break;
2009
2010                 }
2011                 p++;
2012         }
2013         t *= d;
2014         *dur_t = t;
2015
2016         if (dur) {
2017                 *dur = du;
2018         }
2019
2020         return p;
2021 }
2022
2023 static int __cal_vcalendar_parse_trigger_time(calendar_record_h alarm, char *p)
2024 {
2025         char t = 0, z;
2026         int y, mon, d, h, min, s;
2027         int tick, unit;
2028         cal_alarm_s *_alarm = (cal_alarm_s *)alarm;
2029
2030         if (NULL == alarm || NULL == p)
2031         {
2032                 ERR("Invalid parameter");
2033                 return CALENDAR_ERROR_INVALID_PARAMETER;
2034         }
2035
2036         sscanf(p, "%4d%2d%2d%c%2d%2d%2d%c", &y, &mon, &d, &t, &h, &min, &s, &z);
2037
2038         tick = _alarm->remind_tick;
2039         unit = _alarm->remind_tick_unit;
2040         switch (unit)
2041         {
2042         case CALENDAR_ALARM_TIME_UNIT_WEEK:
2043                 mon += tick;
2044                 break;
2045         case CALENDAR_ALARM_TIME_UNIT_DAY:
2046                 d += tick;
2047                 break;
2048         case CALENDAR_ALARM_TIME_UNIT_HOUR:
2049                 h += tick;
2050                 break;
2051         case CALENDAR_ALARM_TIME_UNIT_MINUTE:
2052                 min += tick;
2053                 break;
2054         case CALENDAR_ALARM_TIME_UNIT_SPECIFIC:
2055         default:
2056                 break;
2057         }
2058
2059         if (t == 0)
2060         {
2061                 int datetime = y *10000 + mon *100 + d;
2062                 _cal_record_set_lli(alarm, _calendar_alarm.time, datetime);
2063                 DBG("DATE(%d)", datetime);
2064         }
2065         else
2066         {
2067                 long long int lli = _cal_time_convert_itol(NULL, y, mon, d, h, min, s);
2068                 _cal_record_set_lli(alarm, _calendar_alarm.time, lli);
2069                 DBG("DATE-TIME(%lld)", lli);
2070         }
2071         return CALENDAR_ERROR_NONE;
2072 }
2073
2074 static int __cal_vcalendar_parse_duration_alarm(calendar_record_h alarm, void *data)
2075 {
2076         int ret = CALENDAR_ERROR_NONE;
2077         char *p = (char *)data;
2078         char dur;
2079         int dur_t;
2080         int tick, unit;
2081
2082         p++;
2083
2084         __cal_vcalendar_parse_extract_duration(p, &dur_t, &dur);
2085         switch (dur) {
2086         case 'W':
2087                 tick = dur_t/(7 *24 *60 *60);
2088                 unit = CALENDAR_ALARM_TIME_UNIT_WEEK;
2089                 break;
2090         case 'D':
2091                 tick = dur_t/(24 *60 *60);
2092                 unit = CALENDAR_ALARM_TIME_UNIT_DAY;
2093                 break;
2094         case 'H':
2095                 tick = dur_t/(60 *60);
2096                 unit = CALENDAR_ALARM_TIME_UNIT_HOUR;
2097                 break;
2098         case 'M':
2099                 tick = dur_t/(60);
2100                 unit = CALENDAR_ALARM_TIME_UNIT_MINUTE;
2101                 break;
2102         default:
2103                 tick = 1;
2104                 unit = CALENDAR_ALARM_NONE;;
2105                 break;
2106         }
2107
2108         ret = _cal_record_set_int(alarm, _calendar_alarm.tick, tick);
2109         ret = _cal_record_set_int(alarm, _calendar_alarm.tick_unit, unit);
2110         DBG("tick(%d) unit(%d)", tick, unit);
2111
2112         return ret;
2113 }
2114
2115 static int __cal_vcalendar_parse_trigger(calendar_record_h alarm, void *data)
2116 {
2117         int i = 0, out = 0;
2118         char *p = (char *)data;
2119
2120         p++;
2121
2122         // default unit
2123         _cal_record_set_int(alarm, _calendar_alarm.tick_unit, CALENDAR_ALARM_TIME_UNIT_SPECIFIC);
2124
2125         while (*p != '\n' && *p != '\r' && *p != '\0') {
2126
2127                 for (i = 0; i < TRIG_MAX; i++) {
2128                         if (!strncmp(p, _trig_funcs[i].prop, strlen(_trig_funcs[i].prop))) {
2129                                 out = 1;
2130                                 int j = 0;
2131                                 char buf[64] = {0, };
2132                                 p += strlen(_trig_funcs[i].prop);
2133                                 while (p[j] != ';' && p[j] != '\n' && p[j] != '\0') {
2134                                         buf[j] = p[j];
2135                                         j++;
2136                                 }
2137                                 if (p[j] != '\0') {
2138                                         buf[j] = '\0';
2139                                 }
2140
2141                                 p += j;
2142                                 _trig_funcs[i].func(alarm, buf);
2143                                 break;
2144                         }
2145                 }
2146                 if (out == 1) {
2147                         break;
2148                 }
2149
2150                 if (*p >= '1'  && *p <= '9')
2151                 {
2152                         __cal_vcalendar_parse_trigger_time(alarm, p);
2153                 }
2154                 else
2155                 {
2156                         __cal_vcalendar_parse_duration_alarm(alarm, p);
2157                 }
2158                 break;
2159         }
2160         return CALENDAR_ERROR_NONE;
2161 }
2162
2163 static int __cal_vcalendar_parse_repeat(calendar_record_h alarm, void *data)
2164 {
2165         return CALENDAR_ERROR_NONE;
2166 }
2167
2168 static int __cal_vcalendar_parse_attach_alarm(calendar_record_h alarm, void *data)
2169 {
2170         return CALENDAR_ERROR_NONE;
2171 }
2172
2173 static int __cal_vcalendar_parse_summary_alarm(calendar_record_h alarm, void *data)
2174 {
2175         int ret;
2176         char *p = (char *)data;
2177
2178         p++;
2179
2180         ret = _cal_record_set_str(alarm, _calendar_alarm.description, p);
2181         DBG("alarm description[%s]", p);
2182         return CALENDAR_ERROR_NONE;
2183 }
2184
2185
2186 //rrule////////////////////////////////////////////////////////////
2187 static int __cal_vcalendar_parse_freq(calendar_record_h event, void *data)
2188 {
2189         int ret;
2190         int freq = -1;
2191         char *p = (char *)data;
2192
2193         DBG("%s\n", (char *)data);
2194         if (!strncmp(p, "YEARLY", strlen("YEARLY"))) {
2195                 freq = CALENDAR_RECURRENCE_YEARLY;
2196
2197         } else if (!strncmp(p, "MONTHLY", strlen("MONTHLY"))) {
2198                 freq = CALENDAR_RECURRENCE_MONTHLY;
2199
2200         } else if (!strncmp(p, "WEEKLY", strlen("WEEKLY"))) {
2201                 freq = CALENDAR_RECURRENCE_WEEKLY;
2202
2203         } else if (!strncmp(p, "DAILY", strlen("DAILY"))) {
2204                 freq = CALENDAR_RECURRENCE_DAILY;
2205
2206         } else if (!strncmp(p, "HOURLY", strlen("HOURLY"))) {
2207                 freq = CALENDAR_RECURRENCE_NONE;
2208
2209         } else if (!strncmp(p, "MINUTELY", strlen("MINUTELY"))) {
2210                 freq = CALENDAR_RECURRENCE_NONE;
2211
2212         } else if (!strncmp(p, "SECONDLY", strlen("SECONDLY"))) {
2213                 freq = CALENDAR_RECURRENCE_NONE;
2214
2215         } else {
2216                 freq = CALENDAR_RECURRENCE_NONE;
2217
2218         }
2219         ret = _cal_record_set_int(event, _calendar_event.freq, freq);
2220         return CALENDAR_ERROR_NONE;
2221 }
2222
2223 static int __cal_vcalendar_parse_until(calendar_record_h event, void *data)
2224 {
2225         int ret;
2226         calendar_time_s stime;
2227         calendar_time_s until;
2228         int y, mon, d, h, min, s;
2229         char *tzid;
2230         char t, z;
2231         char *p = (char *)data;
2232
2233         /* until value type has the same value as the dtstart */
2234         ret = _cal_record_set_int(event, _calendar_event.range_type, CALENDAR_RANGE_UNTIL);
2235
2236         ret = calendar_record_get_str(event, _calendar_event.start_tzid, &tzid);
2237         ret = calendar_record_get_caltime(event, _calendar_event.start_time, &stime);
2238         until.type = stime.type;
2239
2240         switch (stime.type)
2241         {
2242         case CALENDAR_TIME_UTIME:
2243                 until.time.utime = _cal_time_convert_stol(tzid, p);
2244                 break;
2245
2246         case CALENDAR_TIME_LOCALTIME:
2247                 sscanf(p, "%4d%2d%2d%c%2d%2d%2d%c", &y, &mon, &d, &t, &h, &min, &s, &z);
2248                 until.time.date.year = y;
2249                 until.time.date.month = mon;
2250                 until.time.date.mday = d;
2251
2252                 break;
2253         }
2254         ret = _cal_record_set_caltime(event, _calendar_event.until_time, until);
2255         CAL_FREE(tzid);
2256
2257         return CALENDAR_ERROR_NONE;
2258 }
2259
2260 static int __cal_vcalendar_parse_count(calendar_record_h event, void *data)
2261 {
2262         int ret;
2263         int c;
2264         char *p = (char *)data;
2265
2266         DBG("%s\n", (char *)data);
2267         ret = _cal_record_set_int(event, _calendar_event.range_type, CALENDAR_RANGE_COUNT);
2268         c = atoi(p);
2269         ret = _cal_record_set_int(event, _calendar_event.count, c < 0 ? 0 : c);
2270         return ret;
2271 }
2272
2273 static int __cal_vcalendar_parse_interval(calendar_record_h event, void *data)
2274 {
2275         DBG("%s\n", (char *)data);
2276         int c;
2277         char *p = (char *)data;
2278
2279         c = atoi(p);
2280         return _cal_record_set_int(event, _calendar_event.interval, c < 0 ? 0 : c);
2281 }
2282
2283 static int __cal_vcalendar_parse_bysecond(calendar_record_h event, void *data)
2284 {
2285         DBG("%s\n", (char *)data);
2286         return _cal_record_set_str(event, _calendar_event.bysecond, (char *)data);
2287 }
2288
2289 static int __cal_vcalendar_parse_byminute(calendar_record_h event, void *data)
2290 {
2291         DBG("%s\n", (char *)data);
2292         return _cal_record_set_str(event, _calendar_event.byminute, (char *)data);
2293 }
2294
2295 static int __cal_vcalendar_parse_byhour(calendar_record_h event, void *data)
2296 {
2297         DBG("%s\n", (char *)data);
2298         return _cal_record_set_str(event, _calendar_event.byhour, (char *)data);
2299 }
2300
2301 static int __cal_vcalendar_parse_byday(calendar_record_h event, void *data)
2302 {
2303         DBG("%s\n", (char *)data);
2304         return _cal_record_set_str(event, _calendar_event.byday, (char *)data);
2305 }
2306
2307 static int __cal_vcalendar_parse_bymonthday(calendar_record_h event, void *data)
2308 {
2309         DBG("%s\n", (char *)data);
2310         return _cal_record_set_str(event, _calendar_event.bymonthday, (char *)data);
2311 }
2312
2313 static int __cal_vcalendar_parse_byyearday(calendar_record_h event, void *data)
2314 {
2315         DBG("%s\n", (char *)data);
2316         return _cal_record_set_str(event, _calendar_event.byyearday, (char *)data);
2317 }
2318
2319 static int __cal_vcalendar_parse_byweekno(calendar_record_h event, void *data)
2320 {
2321         DBG("%s\n", (char *)data);
2322         return _cal_record_set_str(event, _calendar_event.byweekno, (char *)data);
2323 }
2324
2325 static int __cal_vcalendar_parse_bymonth(calendar_record_h event, void *data)
2326 {
2327         DBG("%s\n", (char *)data);
2328         return _cal_record_set_str(event, _calendar_event.bymonth, (char *)data);
2329 }
2330
2331 static int __cal_vcalendar_parse_bysetpos(calendar_record_h event, void *data)
2332 {
2333         DBG("%s\n", (char *)data);
2334         return _cal_record_set_str(event, _calendar_event.bysetpos, (char *)data);
2335 }
2336
2337 static int __cal_vcalendar_parse_wkst(calendar_record_h event, void *data)
2338 {
2339         DBG("%s\n", (char *)data);
2340         int wkst;
2341         char *p = (char *)data;
2342
2343         if (!strncmp(p, "SU", strlen("SU"))) {
2344                 wkst = CALENDAR_SUNDAY;
2345
2346         } else if (!strncmp(p, "MO", strlen("MO"))) {
2347                 wkst = CALENDAR_MONDAY;
2348
2349         } else if (!strncmp(p, "TU", strlen("TU"))) {
2350                 wkst = CALENDAR_TUESDAY;
2351
2352         } else if (!strncmp(p, "WE", strlen("WE"))) {
2353                 wkst = CALENDAR_WEDNESDAY;
2354
2355         } else if (!strncmp(p, "TH", strlen("TH"))) {
2356                 wkst = CALENDAR_THURSDAY;
2357
2358         } else if (!strncmp(p, "FR", strlen("FR"))) {
2359                 wkst = CALENDAR_FRIDAY;
2360
2361         } else if (!strncmp(p, "SA", strlen("SA"))) {
2362                 wkst = CALENDAR_SATURDAY;
2363
2364         } else {
2365                 wkst = -1;
2366         }
2367         return _cal_record_set_int(event, _calendar_event.wkst, wkst);
2368 }
2369
2370 static int __get_tick_unit(char *p, int *tick, int *unit)
2371 {
2372         int d, c, i = 0; /* direct, const, i */
2373         int t, u; /* tick, unit */
2374         char buf[8] = {0};
2375
2376         t = 0;
2377         c = 0;
2378         u = CAL_SCH_TIME_UNIT_OFF;
2379         while (*p != '\0' && *p != '\n') {
2380                 switch (*p) {
2381                 case '+':
2382                         d = 1;
2383                         break;
2384                 case '-':
2385                         d = -1;
2386                         break;
2387                 case 'P':
2388                         i = 0;
2389                         break;
2390                 case 'T':
2391                         break;
2392                 case 'W':
2393                         c = atoi(buf);
2394                         DBG("W tick(%d)", c);
2395                         if (c == 0) break;
2396                         u = CALENDAR_ALARM_TIME_UNIT_WEEK;
2397                         t += c;
2398                         i = 0;
2399                         break;
2400                 case 'D':
2401                         c = atoi(buf);
2402                         DBG("D tick(%d)", c);
2403                         if (c == 0) break;
2404                         u = CALENDAR_ALARM_TIME_UNIT_DAY;
2405                         t += c;
2406                         i = 0;
2407                         break;
2408                 case 'H':
2409                         c = atoi(buf);
2410                         DBG("H tick(%d)", c);
2411                         if (c == 0) break;
2412                         u = CALENDAR_ALARM_TIME_UNIT_HOUR;
2413                         t += c;
2414                         i = 0;
2415                         break;
2416                 case 'M':
2417                         c = atoi(buf);
2418                         DBG("M tick(%d)", c);
2419                         if (c == 0) break;
2420                         u = CALENDAR_ALARM_TIME_UNIT_MINUTE;
2421                         t += c;
2422                         i = 0;
2423                         break;
2424                 case 'S':
2425                         i = 0;
2426                         break;
2427                 default:
2428                         buf[i] = *p;
2429                         i++;
2430                         break;
2431                 }
2432                 p++;
2433         }
2434         if (t != c) {
2435                 u = CALENDAR_ALARM_TIME_UNIT_SPECIFIC;
2436         }
2437         *tick = t;
2438         *unit = u;
2439         DBG("get tic(%d) unit(%d)", t, u);
2440
2441         return CALENDAR_ERROR_NONE;
2442 }
2443
2444 static int __cal_vcalendar_parse_trig_related(calendar_record_h alarm, void *data)
2445 {
2446         DBG("%s\n", (char *)data);
2447
2448         int tick = 0, unit;
2449         char *p = (char *)data;
2450
2451         if (p == NULL) {
2452                 return -1;
2453         }
2454
2455         if (!strncmp(p, "START", strlen("START") + 1)) {
2456                 p += strlen("START") + 1;
2457                 DBG("related start and value[%s]", p);
2458
2459         } else if (!strncmp(p, "END", strlen("END") +1)) {
2460                 p += strlen("END") + 1;
2461                 DBG("related end and value[%s]", p);
2462
2463         } else {
2464                 DBG("no related and value[%s]", p);
2465
2466         }
2467         __get_tick_unit(p, &tick, &unit);
2468         _cal_record_set_int(alarm, _calendar_alarm.tick, tick);
2469         _cal_record_set_int(alarm, _calendar_alarm.tick_unit, unit);
2470
2471         return CALENDAR_ERROR_NONE;
2472 }
2473
2474 long long int _get_utime_from_datetime(char *tzid, char *p)
2475 {
2476         int y, mon, d, h, min, s;
2477         int len;
2478         char t, z;
2479         if (p == NULL) {
2480                 return -1;
2481         }
2482         len = strlen(p);
2483         if (len < strlen("YYYYMMDDTHHMMSS")) {
2484                 return -1;
2485         }
2486
2487         sscanf(p, "%04d%02d%02d%c%02d%02d%02d%c",
2488                         &y, &mon, &d, &t, &h, &min, &s, &z);
2489
2490         return _cal_time_convert_itol(tzid, y, mon, d, h, min, s);
2491 }
2492
2493 static int __cal_vcalendar_parse_trig_value(calendar_record_h alarm, void *data)
2494 {
2495         DBG("%s\n", (char *)data);
2496
2497         int ret;
2498         char *p = (char *)data;
2499
2500         if (!strncmp(p, "DATE-TIME", strlen("DATE-TIME") + 1)) {
2501                 p += strlen("DATE-TIME") + 1;
2502                 ret = _cal_record_set_int(alarm, _calendar_alarm.tick_unit, CALENDAR_ALARM_TIME_UNIT_SPECIFIC);
2503                 ret = _cal_record_set_lli(alarm, _calendar_alarm.time, _cal_time_convert_stol(NULL, p));
2504         } else {
2505
2506         }
2507         return CALENDAR_ERROR_NONE;
2508 }
2509
2510 static int __cal_vcalendar_parse_charset(int *val, void *data)
2511 {
2512         DBG("%s\n", (char *)data);
2513         return CALENDAR_ERROR_NONE;
2514 }
2515
2516 static int __cal_vcalendar_parse_encoding(int *val, void *data)
2517 {
2518         char *p = (char *)data;
2519         *val = 0;
2520
2521         if (!strncmp(p, "BASE64", strlen("BASE64"))) {
2522                 DBG("ENCODE_BASE64");
2523                 *val = ENCODE_BASE64;
2524
2525         } else if (!strncmp(p, "QUOTED-PRINTABLE", strlen("QUOTED-PRINTABLE"))){
2526                 DBG("ENCODE_QUOTED_PRINTABLE");
2527                 *val = ENCODE_QUOTED_PRINTABLE;
2528
2529         }
2530         return CALENDAR_ERROR_NONE;
2531 }
2532
2533 // end parse func////////////////////////////////////////////////////////////////
2534
2535 char *_cal_vcalendar_parse_vevent(int ver, calendar_list_h *list_sch, void *data)
2536 {
2537         DBG("[%s]", __func__);
2538         int i;
2539         int ret;
2540         char *prop = NULL, *cont = NULL;
2541         char *cursor = (char *)data;
2542         calendar_record_h event = NULL;
2543
2544         ret = calendar_record_create(_calendar_event._uri, &event);
2545         if (CALENDAR_ERROR_NONE != ret)
2546         {
2547                 ERR("calendar_record_create() failed");
2548                 return NULL;
2549         }
2550
2551         while ((cursor = _cal_vcalendar_parse_read_line(cursor, &prop, &cont))) {
2552                 if (!strncmp(cont + 1, "VALARM", strlen("VALARM"))) {
2553                         if (!strncmp(cont + 1, "VALARM", strlen("VALARM"))) {
2554                                 cursor = _cal_vcalendar_parse_valarm(VCALENDAR_TYPE_VEVENT, event, cursor);
2555                         } else {
2556                                 break;
2557                         }
2558
2559                 } else if (!strncmp(prop, "END", strlen("END"))) {
2560                         break;
2561
2562                 } else {
2563                         for (i = 0; i < VEVE_MAX; i++) {
2564                                 if (!strncmp(prop, _vevent_funcs[i].prop, strlen(_vevent_funcs[i].prop))) {
2565                                         _vevent_funcs[i].func(ver, *list_sch, event, cont);
2566                                         break;
2567                                 }
2568                         }
2569                 }
2570
2571                 CAL_FREE(prop);
2572                 CAL_FREE(cont);
2573         }
2574
2575         CAL_FREE(prop);
2576         CAL_FREE(cont);
2577
2578         DBG("event add to the list");
2579         ret = calendar_list_add(*list_sch, event);
2580
2581         return cursor;
2582 }
2583
2584 char *_cal_vcalendar_parse_vtodo(int type, calendar_list_h *list_sch, void *data)
2585 {
2586         int i;
2587         int ret;
2588         char *prop = NULL, *cont = NULL;
2589         char *cursor = (char *)data;
2590         calendar_record_h todo = NULL;
2591
2592         ret = calendar_record_create(_calendar_todo._uri, &todo);
2593         if (CALENDAR_ERROR_NONE != ret)
2594         {
2595                 ERR("calendar_record_create() failed");
2596                 return NULL;
2597         }
2598
2599         /* do until meet BEGIN */
2600         while ((cursor = _cal_vcalendar_parse_read_line(cursor, &prop, &cont))) {
2601                 if (!strncmp(prop, "BEGIN", strlen("BEGIN"))) {
2602
2603                         if (!strncmp(cont + 1, "VALARM", strlen("VALARM"))) {
2604                                 cursor = _cal_vcalendar_parse_valarm(VCALENDAR_TYPE_VTODO, todo, cursor);
2605                         } else {
2606                                 break;
2607                         }
2608
2609                 } else if (!strncmp(prop, "END", strlen("END"))) {
2610                         break;
2611
2612                 } else {
2613                         for (i = 0; i < VTODO_MAX; i++) {
2614                                 if (!strncmp(prop, _vtodo_funcs[i].prop, strlen(_vtodo_funcs[i].prop))) {
2615                                         _vtodo_funcs[i].func(type, *list_sch, todo, cont);
2616                                         break;
2617                                 }
2618                         }
2619                 }
2620
2621                 CAL_FREE(prop);
2622                 CAL_FREE(cont);
2623         }
2624
2625         CAL_FREE(prop);
2626         CAL_FREE(cont);
2627
2628         ret = calendar_list_add(*list_sch, todo);
2629
2630         return cursor;
2631 }
2632
2633 char *_cal_vcalendar_parse_valarm(int type, calendar_record_h record, void *data)
2634 {
2635         int ret;
2636         int i;
2637         char *prop = NULL, *cont = NULL;
2638         char *cursor = (char *)data;
2639         calendar_record_h alarm = NULL;
2640
2641         ret = calendar_record_create(_calendar_alarm._uri, &alarm);
2642
2643         while ((cursor = _cal_vcalendar_parse_read_line(cursor, &prop, &cont))) {
2644                 if (!strncmp(prop, "BEGIN", strlen("BEGIN"))) {
2645                         break;
2646
2647                 } else if (!strncmp(prop, "END", strlen("END"))) {
2648                         break;
2649
2650                 }
2651
2652                 for (i = 0; i < VALA_MAX; i++) {
2653                         if (!strncmp(prop, _valarm_funcs[i].prop, strlen(_valarm_funcs[i].prop))) {
2654                                 _valarm_funcs[i].func(alarm, cont);
2655                                 break;
2656                         }
2657                 }
2658                 CAL_FREE(prop);
2659                 CAL_FREE(cont);
2660         }
2661
2662         switch (type) {
2663         case VCALENDAR_TYPE_VEVENT:
2664                 ret = calendar_record_add_child_record(record, _calendar_event.calendar_alarm, alarm);
2665                 break;
2666         case VCALENDAR_TYPE_VTODO:
2667                 ret = calendar_record_add_child_record(record, _calendar_todo.calendar_alarm, alarm);
2668                 break;
2669         }
2670
2671         CAL_FREE(prop);
2672         CAL_FREE(cont);
2673
2674         return cursor;
2675 }
2676
2677 /*
2678  * parse vtimezone
2679  */
2680 enum {
2681         VTIMEZONE_STD_DTSTART = 0x0,
2682         VTIMEZONE_STD_TZOFFSETFROM,
2683         VTIMEZONE_STD_TZOFFSETTO,
2684         VTIMEZONE_STD_MAX,
2685 };
2686
2687 static int __cal_vcalendar_parse_vtimezone_std_dtstart(calendar_record_h timezone, void *data)
2688 {
2689         int y, mon, d, h, min, s;
2690         int nth = 0, wday = 0;
2691         long long int utime;
2692         char t, z;
2693         char *p = (char *)data;
2694
2695         if (NULL == timezone)
2696         {
2697                 ERR("Invalid parameter");
2698                 return CALENDAR_ERROR_INVALID_PARAMETER;
2699         }
2700
2701         sscanf(p +1, "%04d%02d%02d%c%02d%02d%02d%c", &y, &mon, &d, &t, &h, &min, &s, &z);
2702         utime = _cal_time_convert_itol(NULL, y, mon, d, h, min, s);
2703         _cal_time_ltoi2(NULL, utime, &nth, &wday);
2704         DBG("timezone dtstart(%04d-%02d-%02d %02d:%02d:%02d", y, mon, d, h, min, s);
2705         DBG("timezone day of week(%d/%d)", nth, wday);
2706         _cal_record_set_int(timezone, _calendar_timezone.standard_start_month, mon);
2707         _cal_record_set_int(timezone, _calendar_timezone.standard_start_position_of_week, nth);
2708         _cal_record_set_int(timezone, _calendar_timezone.standard_start_day, wday);
2709         _cal_record_set_int(timezone, _calendar_timezone.standard_start_hour, h);
2710         return CALENDAR_ERROR_NONE;
2711 }
2712
2713 static int __cal_vcalendar_parse_vtimezone_std_tzoffsetfrom(calendar_record_h timezone, void *data)
2714 {
2715         return 0;
2716 }
2717
2718 static int __cal_vcalendar_parse_vtimezone_std_tzoffsetto(calendar_record_h timezone, void *data)
2719 {
2720         int h, m;
2721         char *p = (char *)data;
2722         char c;
2723         cal_timezone_s *tz = (cal_timezone_s *)timezone;
2724
2725         if (NULL == timezone)
2726         {
2727                 ERR("Invalid parameter");
2728                 return CALENDAR_ERROR_INVALID_PARAMETER;
2729         }
2730
2731         sscanf(p +1, "%c%02d%02d", &c, &h, &m);
2732         DBG("timezone standard offsetto(%c)(%02d)(%02d)", c, h, m);
2733         if (c == '-')
2734         {
2735                 h *= -1;
2736         }
2737         if (tz->day_light_bias)
2738         {
2739                 // this means daylight is set before gmt offset
2740                 _cal_record_set_int(timezone, _calendar_timezone.day_light_bias,
2741                                 tz->day_light_bias - (h * 60 + m));
2742         }
2743         _cal_record_set_int(timezone, _calendar_timezone.tz_offset_from_gmt, h * 60 + m);
2744         return CALENDAR_ERROR_NONE;
2745 }
2746
2747 struct _record_func _vtimezone_std[VTIMEZONE_STD_MAX] =
2748 {
2749         {"DTSTART", __cal_vcalendar_parse_vtimezone_std_dtstart },
2750         {"TZOFFSETFROM", __cal_vcalendar_parse_vtimezone_std_tzoffsetfrom },
2751         {"TZOFFSETTO", __cal_vcalendar_parse_vtimezone_std_tzoffsetto }
2752 };
2753
2754 char *_cal_vcalendar_parse_standard(calendar_record_h timezone, void *data)
2755 {
2756         DBG("[%s]", __func__);
2757         int i;
2758         char *prop = NULL, *cont = NULL;
2759         char *cursor = (char *)data;
2760
2761         while ((cursor = _cal_vcalendar_parse_read_line(cursor, &prop, &cont))) {
2762                 if (!strncmp(prop, "END", strlen("END"))) {
2763                         break;
2764                 }
2765
2766                 for (i = 0; i < VTIMEZONE_STD_MAX; i++)
2767                 {
2768                         if (!strncmp(prop, _vtimezone_std[i].prop, strlen(_vtimezone_std[i].prop))) {
2769                                 _vtimezone_std[i].func(timezone, cont);
2770                                 break;
2771                         }
2772                 }
2773
2774                 CAL_FREE(prop);
2775                 CAL_FREE(cont);
2776         }
2777
2778         CAL_FREE(prop);
2779         CAL_FREE(cont);
2780
2781         return cursor;
2782 }
2783
2784 enum {
2785         VTIMEZONE_DST_DTSTART = 0x0,
2786         VTIMEZONE_DST_TZOFFSETFROM,
2787         VTIMEZONE_DST_TZOFFSETTO,
2788         VTIMEZONE_DST_MAX,
2789 };
2790
2791 static int __cal_vcalendar_parse_vtimezone_dst_dtstart(calendar_record_h timezone, void *data)
2792 {
2793         int y, mon, d, h, min, s;
2794         int nth = 0, wday = 0;
2795         long long int utime;
2796         char t, z;
2797         char *p = (char *)data;
2798
2799         if (NULL == timezone)
2800         {
2801                 ERR("Invalid parameter");
2802                 return CALENDAR_ERROR_INVALID_PARAMETER;
2803         }
2804
2805         sscanf(p +1, "%04d%02d%02d%c%02d%02d%02d%c", &y, &mon, &d, &t, &h, &min, &s, &z);
2806         utime = _cal_time_convert_itol(NULL, y, mon, d, h, min, s);
2807         _cal_time_ltoi2(NULL, utime, &nth, &wday);
2808         DBG("timezone daylight(%04d-%02d-%02d %02d:%02d:%02d", y, mon, d, h, min, s);
2809         DBG("timezone daylight day of week(%dth/%d)", nth, wday);
2810         _cal_record_set_int(timezone, _calendar_timezone.day_light_start_month, mon);
2811         _cal_record_set_int(timezone, _calendar_timezone.day_light_start_position_of_week, nth);
2812         _cal_record_set_int(timezone, _calendar_timezone.day_light_start_day, wday);
2813         _cal_record_set_int(timezone, _calendar_timezone.day_light_start_hour, h);
2814         return CALENDAR_ERROR_NONE;
2815 }
2816
2817 static int __cal_vcalendar_parse_vtimezone_dst_tzoffsetfrom(calendar_record_h timezone, void *data)
2818 {
2819         return 0;
2820 }
2821
2822 static int __cal_vcalendar_parse_vtimezone_dst_tzoffsetto(calendar_record_h timezone, void *data)
2823 {
2824         int h, m;
2825         char *p = (char *)data;
2826         char c;
2827         cal_timezone_s *tz = (cal_timezone_s *)timezone;
2828
2829         if (NULL == timezone)
2830         {
2831                 ERR("Invalid parameter");
2832                 return CALENDAR_ERROR_INVALID_PARAMETER;
2833         }
2834
2835         sscanf(p +1, "%c%02d%02d", &c, &h, &m);
2836         DBG("timezone offsetto(%c)(%02d)(%02d)", c, h, m);
2837         if (c == '-')
2838         {
2839                 h *= -1;
2840         }
2841         _cal_record_set_int(timezone, _calendar_timezone.day_light_bias,
2842                         (h * 60 + m) - tz->tz_offset_from_gmt);
2843         return CALENDAR_ERROR_NONE;
2844 }
2845
2846 struct _record_func _vtimezone_dst[VTIMEZONE_STD_MAX] =
2847 {
2848         {"DTSTART", __cal_vcalendar_parse_vtimezone_dst_dtstart },
2849         {"TZOFFSETFROM", __cal_vcalendar_parse_vtimezone_dst_tzoffsetfrom },
2850         {"TZOFFSETTO", __cal_vcalendar_parse_vtimezone_dst_tzoffsetto }
2851 };
2852
2853 char *_cal_vcalendar_parse_daylight(calendar_record_h timezone, void *data)
2854 {
2855         DBG("[%s]", __func__);
2856         int i;
2857         char *prop = NULL, *cont = NULL;
2858         char *cursor = (char *)data;
2859
2860         while ((cursor = _cal_vcalendar_parse_read_line(cursor, &prop, &cont))) {
2861                 if (!strncmp(prop, "END", strlen("END"))) {
2862                         break;
2863                 }
2864
2865                 for (i = 0; i < VTIMEZONE_DST_MAX; i++)
2866                 {
2867                         if (!strncmp(prop, _vtimezone_dst[i].prop, strlen(_vtimezone_dst[i].prop))) {
2868                                 _vtimezone_dst[i].func(timezone, cont);
2869                                 break;
2870                         }
2871                 }
2872
2873                 CAL_FREE(prop);
2874                 CAL_FREE(cont);
2875         }
2876
2877         CAL_FREE(prop);
2878         CAL_FREE(cont);
2879
2880         return cursor;
2881 }
2882
2883 char *_cal_vcalendar_parse_vtimezone(int ver, calendar_list_h *list_sch, void *data)
2884 {
2885         int ret = CALENDAR_ERROR_NONE;
2886         char *prop = NULL, *cont = NULL;
2887         char *cursor = (char *)data;
2888         calendar_record_h timezone = NULL;
2889
2890         ret = calendar_record_create(_calendar_timezone._uri, &timezone);
2891         if (CALENDAR_ERROR_NONE != ret)
2892         {
2893                 ERR("calendar_record_create() failed");
2894                 return NULL;
2895         }
2896
2897         while ((cursor = _cal_vcalendar_parse_read_line(cursor, &prop, &cont)))
2898         {
2899                 if (!strncmp(prop, "TZID", strlen("TZID")))
2900                 {
2901                         _cal_record_set_str(timezone, _calendar_timezone.standard_name, cont +1);
2902                         _cal_record_set_str(timezone, _calendar_timezone.day_light_name, cont +1);
2903                         DBG("name[%s]", cont +1);
2904                 }
2905                 else if (!strncmp(prop, "BEGIN", strlen("BEGIN")))
2906                 {
2907                         if (!strncmp(cont + 1, "STANDARD", strlen("STANDARD")))
2908                         {
2909                                 cursor = _cal_vcalendar_parse_standard(timezone, cursor);
2910                         }
2911                         else if (!strncmp(cont + 1, "DAYLIGHT", strlen("DAYLIGHT")))
2912                         {
2913                                 cursor = _cal_vcalendar_parse_daylight(timezone, cursor);
2914                         }
2915                         else
2916                         {
2917                                 DBG("Error");
2918                         }
2919                 }
2920                 else if (!strncmp(prop, "END", strlen("END")))
2921                 {
2922                         if (!strncmp(cont + 1, "VTIMEZONE", strlen("VTIMEZONE")))
2923                         {
2924                                 break;
2925                         }
2926                         else
2927                         {
2928                                 DBG("Error");
2929                         }
2930                 }
2931                 else
2932                 {
2933                                 DBG("Error");
2934                 }
2935                 CAL_FREE(prop);
2936                 CAL_FREE(cont);
2937         }
2938
2939         CAL_FREE(prop);
2940         CAL_FREE(cont);
2941
2942         DBG("add timezone to the list");
2943         calendar_list_add(*list_sch, timezone);
2944
2945         return cursor;
2946 }
2947
2948 /*
2949  * parses vcalendar and appends record to the list.
2950  */
2951 char *_cal_vcalendar_parse_vcalendar(calendar_list_h *list, void *data)
2952 {
2953         DBG("[%s]", __func__);
2954         int ret = CALENDAR_ERROR_NONE;
2955         char *prop = NULL, *cont = NULL;
2956         char *cursor = (char *)data;
2957         char *p = cursor;
2958         calendar_list_h l = NULL;
2959
2960         if (NULL == list)
2961         {
2962                 ERR("Invalid parameter: list is NULL");
2963                 return NULL;
2964         }
2965
2966         ret = calendar_list_create(&l);
2967         if (CALENDAR_ERROR_NONE != ret)
2968         {
2969                 ERR("calendar_list_create() failed");
2970                 return NULL;
2971         }
2972
2973         while ((cursor = _cal_vcalendar_parse_read_line(cursor, &prop, &cont))) {
2974                 if (prop == NULL || cont == NULL)
2975                 {
2976                         ERR("Failed to parse");
2977                         break;
2978                 }
2979                 if (!strncmp(prop, "BEGIN", strlen("BEGIN"))) {
2980                         CAL_FREE(prop);
2981                         CAL_FREE(cont);
2982                         break;
2983                 }
2984
2985                 if (!strncmp(prop, "PRODID", strlen("PRODID"))) {
2986                         _basic_funcs[VCAL_PRODID].func(NULL, cont);
2987
2988                 } else if (!strncmp(prop, "VERSION", strlen("VERSION"))) {
2989                         _basic_funcs[VCAL_VERSION].func(NULL, cont);
2990
2991                 } else {
2992
2993                 }
2994
2995                 CAL_FREE(prop);
2996                 CAL_FREE(cont);
2997                 p = cursor;
2998         }
2999
3000         cursor = p;
3001         while ((cursor = _cal_vcalendar_parse_read_line(cursor, &prop, &cont))) {
3002                 if (prop == NULL || cont == NULL)
3003                 {
3004                         ERR("Failed to parse");
3005                         break;
3006                 }
3007                 if (!strncmp(prop, "BEGIN", strlen("BEGIN"))) {
3008
3009                         if (!strncmp(cont + 1, "VEVENT", strlen("VEVENT"))) {
3010                                 cursor = _cal_vcalendar_parse_vevent(CALENDAR_BOOK_TYPE_EVENT, &l, cursor);
3011
3012                         } else if (!strncmp(cont + 1, "VTODO", strlen("VTODO"))) {
3013                                 cursor = _cal_vcalendar_parse_vtodo(CALENDAR_BOOK_TYPE_TODO, &l, cursor);
3014
3015                         } else if (!strncmp(cont + 1, "VTIMEZONE", strlen("VTIMEZONE"))) {
3016                                 cursor = _cal_vcalendar_parse_vtimezone(CALENDAR_BOOK_TYPE_NONE, &l, cursor);
3017 /*
3018                         } else if (!strncmp(cont + 1, "VFREEBUSY", strlen("VFREEBUSY"))) {
3019 */
3020                         } else {
3021
3022                         }
3023
3024                 } else if (!strncmp(prop, "END:VCALENDAR", strlen("END:VCALENDAR"))) {
3025                         CAL_FREE(prop);
3026                         CAL_FREE(cont);
3027                         break;
3028                 }
3029
3030                 CAL_FREE(prop);
3031                 CAL_FREE(cont);
3032         }
3033         CAL_FREE(prop);
3034         CAL_FREE(cont);
3035
3036         *list = l;
3037
3038         return cursor;
3039 }
3040