1 #include "../pith/headers.h"
2 #include "../pith/mailpart.h"
3 #include "../pith/store.h"
4 #include "../pith/ical.h"
9 #endif /* STANDALONE */
11 typedef struct ical_iana_comp_s
{
12 char *comp
; /* component name */
13 size_t len
; /* size of component name (strlen(x->comp)) */
14 int pos
; /* position of this component in comp array */
15 void *(*parse
)(char **); /* parser */
16 void (*give
)(void **); /* free memory */
19 typedef struct ical_iana_prop_s
{
20 char *prop
; /* component name */
21 size_t len
; /* size of component name (strlen(x->comp)) */
22 int pos
; /* location of this component in the prop array */
23 void (*parse
)(); /* parser */
24 void (*give
)(void **); /* free memory */
27 int ical_january_first(int); /* args: year */
28 void ical_adjust_date(struct tm
*, VTIMEZONE_S
*);
30 void ical_initialize(void);
32 int ical_non_ascii_valid(unsigned char);
33 char *ical_unfold_line(char *);
34 ICLINE_S
*ical_parse_line(char **, char *);
36 ICLINE_S
*ical_cline_cpy(ICLINE_S
*);
37 ICAL_PARAMETER_S
*ical_parameter_cpy(ICAL_PARAMETER_S
*param
);
39 char *ical_get_value(char **);
42 void *ical_parse_vcalendar(char **);
43 void *ical_parse_vevent(char **);
44 void *ical_parse_vtodo(char **);
45 void *ical_parse_vjournal(char **);
46 void *ical_parse_vfreebusy(char **);
47 void *ical_parse_vtimezone(char **);
48 void *ical_parse_valarm(char **);
49 void *ical_parse_timezone(char **);
50 ICAL_S
*ical_parse_unknown_comp(char **, int);
51 ICAL_S
*ical_parse_generic_comp(char **, int);
54 void ical_free_vevent(void **);
55 void ical_free_vtodo(void **);
56 void ical_free_vjournal(void **);
57 void ical_free_vfreebusy(void **);
58 void ical_free_vtimezone(void **);
59 void ical_free_timezone(void **);
60 void ical_free_valarm(void **);
61 void ical_free_unknown_comp(ICAL_S
**);
63 /* parse properties */
64 void ical_cline_from_token(void **, char **, char *);
65 void ical_gencline_from_token(void **, char **, char *);
67 void ical_parse_rrule(RRULE_S
**, char **);
68 void ical_parse_time(struct tm
*, char **, char *);
69 void ical_parse_offset(int *, char **, char *);
71 void ical_parse_freq(Freq_value
*, char *);
72 void ical_parse_weekday_list(BYWKDY_S
**, char *);
73 void ical_parse_number_list(BYWKDY_S
**, char *);
74 void ical_parse_interval(unsigned long *, char *);
76 int ical_get_number_value(char *, int, int);
77 void ical_set_date(ICLINE_S
*, VTIMEZONE_S
*);
78 void ical_set_date_vevent(void *, void *);
81 void ical_free_prop(void **, ICAL_PROP_S
*);
82 void ical_free_null(void **);
83 void ical_free_cline(void **);
84 void ical_free_param(ICAL_PARAMETER_S
**);
85 void ical_free_gencline(void **);
86 void ical_free_rrule(void **);
87 void ical_free_weekday_list(void **);
90 struct tm day_zero
; /* date for january 1, 1601 */
91 int month_len
[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
93 #define UTF8_COMPLETE (1)
97 unsigned long ical_buf_len
;
100 /* parsing structures */
102 /* this is the list of V-components to a Calendar from RFC 5545 */
103 ICAL_COMP_S ical_comp
[] = {
104 {"VCALENDAR", 9, VCalendar
, ical_parse_vcalendar
, ical_free_vcalendar
},
105 {"VTIMEZONE", 9, VTimeZone
, ical_parse_vtimezone
, ical_free_vtimezone
},
106 {"VEVENT", 6, VEvent
, ical_parse_vevent
, ical_free_vevent
},
107 {"VTODO", 5, VTodo
, ical_parse_vtodo
, ical_free_vtodo
},
108 {"VJOURNAL", 8, VJournal
, ical_parse_vjournal
, ical_free_vjournal
},
109 {"VALARM", 6, VAlarm
, ical_parse_valarm
, ical_free_valarm
},
110 {"VFREEBUSY", 9, VFreeBusy
, ical_parse_vfreebusy
, ical_free_vfreebusy
},
111 {NULL
, 0, VUnknown
, NULL
, 0}
114 /* array for properties */
115 ICAL_PROP_S rrule_prop
[] = {
116 {"FREQ", 4, RRFreq
, ical_parse_freq
, ical_free_null
},
117 {"UNTIL", 5, RRUntil
, ical_parse_freq
, 0},
118 {"COUNT", 5, RRCount
, ical_cline_from_token
, ical_free_cline
},
119 {"INTERVAL", 8, RRInterval
, ical_parse_interval
, ical_free_null
},
120 {"BYSECOND", 8, RRBysecond
, ical_parse_number_list
, ical_free_weekday_list
},
121 {"BYMINUTE", 8, RRByminute
, ical_parse_number_list
, ical_free_weekday_list
},
122 {"BYHOUR", 6, RRByhour
, ical_parse_number_list
, ical_free_weekday_list
},
123 {"BYDAY", 5, RRByday
, ical_parse_weekday_list
,ical_free_weekday_list
},
124 {"BYWEEKNO", 8, RRByweekno
, 0, 0},
125 {"BYMONTH", 7, RRBymonth
, ical_parse_number_list
, ical_free_weekday_list
},
126 {"BYSETPOS", 8, RRBysetpos
, 0, 0},
127 {"BYWKST", 6, RRWkst
, 0, 0},
129 10, RRBymonthday
, 0, 0},
130 {"BYYEARDAY", 9, RRByyearday
, 0, 0},
131 {NULL
, 0, RRUnknown
, 0, 0}
134 ICAL_PROP_S event_prop
[] = {
135 {"DTSTAMP", 7, EvDtstamp
, ical_cline_from_token
, ical_free_cline
},
136 {"UID", 3, EvUid
, ical_cline_from_token
, ical_free_cline
},
137 {"DTSTART", 7, EvDtstart
, ical_cline_from_token
, ical_free_cline
},
138 {"CLASS", 5, EvClass
, ical_cline_from_token
, ical_free_cline
},
139 {"CREATED", 7, EvCreated
, ical_cline_from_token
, ical_free_cline
},
140 {"DESCRIPTION", 11, EvDescription
, ical_cline_from_token
, ical_free_cline
},
141 {"GEO", 3, EvGeo
, ical_cline_from_token
, ical_free_cline
},
142 {"LASTMOD", 7, EvLastMod
, ical_cline_from_token
, ical_free_cline
},
143 {"LOCATION", 8, EvLocation
, ical_cline_from_token
, ical_free_cline
},
144 {"ORGANIZER", 9, EvOrganizer
, ical_cline_from_token
, ical_free_cline
},
145 {"PRIORITY", 8, EvPriority
, ical_cline_from_token
, ical_free_cline
},
146 {"SEQUENCE", 8, EvSequence
, ical_cline_from_token
, ical_free_cline
},
147 {"STATUS", 6, EvStatus
, ical_cline_from_token
, ical_free_cline
},
148 {"SUMMARY", 7, EvSummary
, ical_cline_from_token
, ical_free_cline
},
149 {"TRANSP", 6, EvTransp
, ical_cline_from_token
, ical_free_cline
},
150 {"URL", 3, EvUrl
, ical_cline_from_token
, ical_free_cline
},
151 {"RECURRENCE-ID", 13, EvRecurrence
, ical_cline_from_token
, ical_free_cline
},
152 {"RRULE", 5, EvRrule
, ical_parse_rrule
, ical_free_rrule
},
153 {"DTEND", 5, EvDtend
, ical_cline_from_token
, ical_free_cline
},
154 {"DURATION", 8, EvDuration
, ical_cline_from_token
, ical_free_cline
},
155 {"ATTACH", 6, EvAttach
, ical_gencline_from_token
, ical_free_gencline
},
156 {"ATTENDEE", 8, EvAttendee
, ical_gencline_from_token
, ical_free_gencline
},
157 {"CATEGORIES", 10, EvCategories
, ical_gencline_from_token
, ical_free_gencline
},
158 {"COMMENT", 7, EvComment
, ical_gencline_from_token
, ical_free_gencline
},
159 {"CONTACT", 7, EvContact
, ical_gencline_from_token
, ical_free_gencline
},
160 {"EXDATE", 6, EvExdate
, ical_gencline_from_token
, ical_free_gencline
},
161 {"RSTATUS", 7, EvRstatus
, ical_gencline_from_token
, ical_free_gencline
},
162 {"RELATED", 7, EvRelated
, ical_gencline_from_token
, ical_free_gencline
},
163 {"RESOURCES", 9, EvResources
, ical_gencline_from_token
, ical_free_gencline
},
164 {"RDATE", 5, EvRdate
, ical_gencline_from_token
, ical_free_gencline
},
165 {NULL
, 0, EvUnknown
, 0, 0}
168 ICAL_PROP_S tz_comp
[] = {
169 {"TZID", 4, TZCid
, ical_cline_from_token
, ical_free_cline
},
170 {"LAST-MODIFIED", 13, TZCLastMod
, ical_cline_from_token
, ical_free_cline
},
171 {"TZURL", 5, TZCUrl
, ical_cline_from_token
, ical_free_cline
},
172 {NULL
, 0, TZCUnknown
, 0, 0}
175 ICAL_PROP_S tz_prop
[] = {
176 {"DTSTART", 7, TZPDtstart
, ical_parse_time
, 0},
177 {"TZOFFSETTO", 10, TZPOffsetto
, ical_parse_offset
, 0},
178 {"TZOFFSETFROM", 12, TZPOffsetfrom
, ical_parse_offset
, 0},
179 {"RRULE", 5, TZPRrule
, ical_parse_rrule
, ical_free_rrule
},
180 {"COMMENT", 7, TZPComment
, ical_gencline_from_token
, ical_free_gencline
},
181 {"RDATE", 5, TZPRdate
, ical_gencline_from_token
, ical_free_gencline
},
182 {"TZNAME", 6, TZPTzname
, ical_gencline_from_token
, ical_free_gencline
},
183 {NULL
, 0, TZPUnknown
, 0, 0}
186 ICAL_PROP_S alarm_prop
[] = {
187 {"ACTION", 6, AlAction
, ical_cline_from_token
, ical_free_cline
},
188 {"TRIGGER", 7, AlTrigger
, ical_cline_from_token
, ical_free_cline
},
189 {"DURATION", 8, AlDuration
, ical_cline_from_token
, ical_free_cline
},
190 {"REPEAT", 6, AlRepeat
, ical_cline_from_token
, ical_free_cline
},
191 {"DESCRIPTION", 11, AlDescription
, ical_cline_from_token
, ical_free_cline
},
192 {"SUMMARY", 7, AlSummary
, ical_cline_from_token
, ical_free_cline
},
193 {"ATTACH", 6, AlAttach
, ical_gencline_from_token
, ical_free_gencline
},
194 {"ATTENDEE", 8, AlAttendee
, ical_gencline_from_token
, ical_free_gencline
},
195 {NULL
, 0, AlUnknown
, 0, 0}
198 /* some useful macros for character analysis */
200 #define ical_wspace(X) \
201 ((X) == ' ' || (X) == '\t')
203 #define ical_name_allowed_char(X) \
204 (((X) >= 'A' && (X) <= 'Z') || \
205 ((X) >= 'a' && (X) <= 'z') || \
208 #define ical_control(X) \
209 (((X) >= 0x00 && (X) <= 0x08) || \
210 ((X) >= 0x0A && (X) <= 0x1F) || \
213 #define ical_safe_char(X) \
214 (ical_non_ascii_valid(X) \
217 || ((X) >= 0x23 && (X) <= 0x2B) \
218 || ((X) >= 0x2D && (X) <= 0x39) \
219 || ((X) >= 0x3C && (X) <= 0x7E))
221 #define ical_qsafe_char(X) \
222 (ical_non_ascii_valid((X)) \
225 || ((X) >= 0x23 && (X) <= 0x7E))
227 #define ical_value_char(X) \
228 (ical_non_ascii_valid(X) \
230 || ((X) >= 0x21 && (X) <= 0x7E))
232 /* Finally, here begins the code. */
234 void ical_debug(char *fcn
, char *text
)
237 strncpy(piece
, text
, 49);
238 dprint((9, "%s: %s", fcn
, piece
));
242 *** FREE MEMORY FUNCTIONS
246 ical_free_param(ICAL_PARAMETER_S
**param
)
248 if(param
== NULL
|| *param
== NULL
)
251 if((*param
)->name
) fs_give((void **) &(*param
)->name
);
252 if((*param
)->value
) fs_give((void **) &(*param
)->value
);
253 if((*param
)->next
) ical_free_param(&(*param
)->next
);
254 fs_give((void **)param
);
258 ical_free_null(void **n
)
260 if(n
!= NULL
) *n
= NULL
;
264 ical_free_cline(void **icv
)
266 ICLINE_S
**ic
= (ICLINE_S
**) icv
;
268 if(ic
== NULL
|| *ic
== NULL
)
271 if((*ic
)->token
) fs_give((void **) &(*ic
)->token
);
272 if((*ic
)->param
) ical_free_param(&(*ic
)->param
);
273 if((*ic
)->value
) fs_give((void **) &(*ic
)->value
);
278 ical_free_gencline(void **giclpv
)
280 GEN_ICLINE_S
**giclp
= (GEN_ICLINE_S
**) giclpv
;
282 if(giclp
== NULL
|| *giclp
== NULL
) return;
284 if((*giclp
)->cline
) ical_free_cline((void **) &(*giclp
)->cline
);
285 if((*giclp
)->next
) ical_free_gencline((void **) &(*giclp
)->next
);
289 ical_free_vcalendar(void **vcalpv
)
291 VCALENDAR_S
**vcalp
= (VCALENDAR_S
**)vcalpv
;
293 if(vcalp
== NULL
|| *vcalp
== NULL
) return;
295 if((*vcalp
)->prodid
) ical_free_cline((void **) &(*vcalp
)->prodid
);
296 if((*vcalp
)->version
) ical_free_cline((void **) &(*vcalp
)->version
);
297 if((*vcalp
)->calscale
) ical_free_cline((void **) &(*vcalp
)->calscale
);
298 if((*vcalp
)->method
) ical_free_cline((void **) &(*vcalp
)->method
);
299 if((*vcalp
)->uk_prop
) ical_free_gencline((void **) &(*vcalp
)->uk_prop
);
302 for(i
= 0; i
< VUnknown
; i
++)
303 if((*vcalp
)->comp
[i
]) (ical_comp
[i
].give
)(&(*vcalp
)->comp
[i
]);
304 fs_give((*vcalp
)->comp
);
306 if((*vcalp
)->uk_comp
) ical_free_unknown_comp(&(*vcalp
)->uk_comp
);
311 ical_free_vevent(void **veventpv
)
313 VEVENT_S
**veventp
= (VEVENT_S
**) veventpv
;
315 if(veventp
== NULL
|| *veventp
== NULL
) return;
317 ical_free_prop((*veventp
)->prop
, event_prop
);
318 if((*veventp
)->uk_prop
) ical_free_gencline((void **) &(*veventp
)->uk_prop
);
319 if((*veventp
)->valarm
) ical_free_valarm((void **) &(*veventp
)->valarm
);
324 ical_free_rrule(void **rrulepv
)
326 RRULE_S
**rrulep
= (RRULE_S
**) rrulepv
;
328 if(rrulep
&& *rrulep
){
329 ical_free_prop((*rrulep
)->prop
, rrule_prop
);
330 ical_free_param(&(*rrulep
)->param
);
336 ical_free_weekday_list(void **wkdylv
)
338 BYWKDY_S
**wkdyl
= (BYWKDY_S
**) wkdylv
;
340 if(wkdyl
== NULL
) return;
343 ical_free_weekday_list((void **) &(*wkdyl
)->next
);
350 ical_free_vtodo(void **vtodopv
)
355 ical_free_vjournal(void **vjournalpv
)
360 ical_free_vfreebusy(void **vfbpv
)
365 ical_free_prop(void **propv
, ICAL_PROP_S
*aux_comp
)
369 if(propv
== NULL
) return;
371 for(i
= 0; aux_comp
[i
].prop
!= NULL
; i
++)
373 for(j
= 0; aux_comp
[j
].prop
!= NULL
&& aux_comp
[j
].pos
!= i
; j
++);
374 if(aux_comp
[j
].give
) (aux_comp
[j
].give
)(&propv
[i
]);
381 ical_free_vtimezone(void **vtzpv
)
383 VTIMEZONE_S
**vtzp
= (VTIMEZONE_S
**) vtzpv
;
386 if(vtzp
== NULL
|| *vtzp
== NULL
) return;
388 ical_free_prop((*vtzp
)->prop
, tz_comp
);
390 if((*vtzp
)->uk_prop
) ical_free_gencline((void **) &(*vtzp
)->uk_prop
);
391 if((*vtzp
)->standardc
) ical_free_timezone((void **) &(*vtzp
)->standardc
);
392 if((*vtzp
)->daylightc
) ical_free_timezone((void **) &(*vtzp
)->daylightc
);
397 ical_free_timezone(void **tzpv
)
399 ICAL_TZPROP_S
**tzp
= (ICAL_TZPROP_S
**) tzpv
;
401 if(tzp
== NULL
|| *tzp
== NULL
) return;
403 ical_free_prop((*tzp
)->prop
, tz_prop
);
404 if((*tzp
)->uk_prop
) ical_free_gencline((void **) &(*tzp
)->uk_prop
);
405 if((*tzp
)->next
) ical_free_timezone((void **) &(*tzp
)->next
);
409 void ical_free_valarm(void **valarmpv
)
414 ical_free_unknown_comp(ICAL_S
**icalp
)
417 if(icalp
== NULL
|| *icalp
== NULL
) return;
418 for(i
= 0; ical_comp
[i
].comp
&& strucmp((*icalp
)->comp
,ical_comp
[i
].comp
); i
++);
419 if(ical_comp
[i
].give
)
420 (ical_comp
[i
].give
)(&(*icalp
)->value
);
422 ical_free_gencline((void **) &(*icalp
)->value
);
423 fs_give((void **)&(*icalp
)->comp
);
424 ical_free_unknown_comp(&(*icalp
)->next
);
425 ical_free_unknown_comp(&(*icalp
)->branch
);
426 fs_give((void **)icalp
);
429 char *ical_unfold_line(char *line
)
436 for(i
= 0, j
= 0; line
[j
] != '\0';)
438 case '\r': if(line
[j
+1] == '\n' && ical_wspace(line
[j
+2])){
439 j
+= 3; /* get past white space */
442 default : line
[i
++] = line
[j
++];
449 ical_get_parameter(char **line
)
451 ICAL_PARAMETER_S
*param
= NULL
;
454 if(line
== NULL
|| *line
== NULL
)
457 for(s
= *line
; s
&& *s
&& ical_name_allowed_char(*s
) ; s
++);
463 param
= fs_get(sizeof(ICAL_PARAMETER_S
));
464 memset((void *)param
, 0, sizeof(ICAL_PARAMETER_S
));
466 param
->name
= cpystr(*line
);
468 *line
= s
+1; /* step over '=' */
469 quoted
= **line
== '"' ? 1 : 0;
471 for(s
= ++*line
; s
&& *s
&& ical_qsafe_char((unsigned char) *s
); s
++);
472 if(*s
!= '"'){ /* error, do not parse this line */
473 ical_free_param(¶m
);
474 *line
= strchr(s
, ':'); /* reset line to closest ':' */
479 for(s
= *line
; s
&& *s
&& (ical_safe_char((unsigned char) *s
)); s
++);
482 param
->value
= cpystr(*line
);
483 *s
= c
; /* restore character */
484 *line
= quoted
? s
+ 1 : s
;
488 param
->next
= ical_get_parameter(line
);
494 char *ical_get_value(char **line
)
498 if(line
== NULL
|| *line
== NULL
)
501 for (s
= *line
; *s
&& ical_value_char((unsigned char) *s
); s
++);
512 ical_parameter_cpy(ICAL_PARAMETER_S
*param
)
514 ICAL_PARAMETER_S
*rv
;
516 if(param
== NULL
) return NULL
;
518 rv
= fs_get(sizeof(ICAL_PARAMETER_S
));
519 memset((void *)rv
, 0, sizeof(ICAL_PARAMETER_S
));
521 if(param
->name
) rv
->name
= cpystr(param
->name
);
522 if(param
->value
) rv
->value
= cpystr(param
->value
);
523 if(param
->next
) rv
->next
= ical_parameter_cpy(param
->next
);
529 ical_cline_cpy(ICLINE_S
*icl
)
536 rv
= fs_get(sizeof(ICLINE_S
));
537 memset((void *)rv
, 0, sizeof(ICLINE_S
));
539 if(icl
->token
) rv
->token
= cpystr(icl
->token
);
540 if(icl
->param
) rv
->param
= ical_parameter_cpy(icl
->param
);
541 if(icl
->value
) rv
->value
= cpystr(icl
->value
);
546 /* Given a \r\n-ending line (called *text), isolate the ocurrence
547 * of the token in that line.
548 * Return the token, and modify the pointer to *text to point to the
549 * end of the token. Modify sep to contain the character following
551 * ical-line = token ':'/';' rest of the line\r\n
552 * on error return null, and set *text to the next line, if possible.
555 ical_isolate_token(char **text
, char *sep
)
559 for(t
= s
= *text
; *t
&& ical_name_allowed_char(*s
); s
++);
560 /* only followed by parameter or value */
561 if(*s
== ':' || *s
== ';'){
563 *s
= '\0'; /* isolate token at pointer s */
566 else{ /* bad data - bail out of here */
568 if(*s
== '\0' || (s
= strstr(s
, "\r\n")) == NULL
)
570 else /* move to next line */
578 ical_parse_text(char *text
)
581 VCALENDAR_S
*vcal
= NULL
;
583 ical_debug("ical_parse_text", text
);
586 text
= ical_unfold_line(text
);
587 for(s
= text
; s
&& *s
!= '\0'; s
++){
588 if(*s
!= 'B' && *s
!= 'b')
590 if(!struncmp(s
+1, "EGIN:VCALENDAR\r\n", 16)){
591 s
+= 17; /* 17 = strlen("BEGIN:VCALENDAR\r\n") */
592 vcal
= (VCALENDAR_S
*) ical_parse_vcalendar(&s
);
600 ical_parse_time(struct tm
*ic_date
, char **text
, char *token
)
604 icl
= ical_parse_line(text
, token
);
605 ical_parse_date(icl
->value
, ic_date
);
606 ical_free_cline((void **) &icl
);
610 ical_parse_interval(unsigned long *longv
, char *value
)
612 *longv
= atoi(value
);
617 ical_parse_offset(int *offsetv
, char **text
, char *token
)
623 icl
= ical_parse_line(text
, token
);
625 if(*icl
->value
== '+' || *icl
->value
== '-')
626 value
= icl
->value
+ 1;
630 h
= ical_get_number_value(value
, 0, 2);
631 m
= ical_get_number_value(value
, 2, 4);
633 offset
= 60*(60*h
+ m
);
634 if(*icl
->value
== '-')
638 ical_free_cline((void **) &icl
);
642 ical_cline_from_token(void **iclv
, char **text
, char *token
)
644 ICLINE_S
**icl
= (ICLINE_S
**)iclv
;
647 *icl
= ical_parse_line(text
, token
);
649 ICLINE_S
*ic
= ical_parse_line(text
, token
);
650 ical_free_cline((void **)&ic
);
655 ical_gencline_from_token(void **giclv
, char **text
, char *token
)
659 if(!struncmp(*text
, token
, strlen(token
))){
660 gicl
= fs_get(sizeof(GEN_ICLINE_S
));
661 memset((void *) gicl
, 0, sizeof(GEN_ICLINE_S
));
662 ical_cline_from_token((void **) &gicl
->cline
, text
, token
);
663 ical_gencline_from_token((void **) &gicl
->next
, text
, token
);
664 *giclv
= (void *) gicl
;
669 *** PARSE COMPONENT FUNCTIONS
673 ical_parse_vcalendar(char **text
)
680 dprint((9, "ical_parse_vcalendar:\n"));
681 ical_debug("ical_parse_vcalendar", *text
);
683 vcal
= fs_get(sizeof(VCALENDAR_S
));
684 memset((void *)vcal
, 0, sizeof(VCALENDAR_S
));
686 /* s must always point the the beginning of a line */
687 for(s
= *text
; s
&& *s
!= '\0';){
689 s
= ical_isolate_token(&t
, &c
);
696 *t
= c
; /* restore character */
697 if(s
){ /* figure out the token */
698 int ukn
= 0; /* unknown token */
702 case 'b': if(!struncmp(s
+1, "EGIN", 4)){
703 s
+= 6; /* 6 = strlen("BEGIN:") */
704 for(i
= 0; ical_comp
[i
].comp
705 && (struncmp(s
, ical_comp
[i
].comp
, ical_comp
[i
].len
)
706 || struncmp(s
+ ical_comp
[i
].len
, "\r\n", 2)); i
++);
708 if(ical_comp
[i
].parse
){
709 s
+= ical_comp
[i
].len
+ 2;
710 v
= (ical_comp
[i
].parse
)(&s
);
711 if(vcal
->comp
== NULL
){
712 vcal
->comp
= fs_get(VUnknown
*sizeof(void *));
713 memset((void *) vcal
->comp
, 0, VUnknown
*sizeof(void *));
716 if(vcal
->comp
[ical_comp
[i
].pos
] == NULL
)
717 vcal
->comp
[ical_comp
[i
].pos
] = v
;
719 (ical_comp
[i
].give
)(&v
);
721 v
= (void *) ical_parse_unknown_comp(&s
, 0);
722 if(vcal
->uk_comp
== NULL
)
723 vcal
->uk_comp
= (ICAL_S
*) v
;
726 for(ic
= vcal
->uk_comp
; ic
&& ic
->branch
; ic
= ic
->branch
);
727 ic
->branch
= (ICAL_S
*) v
;
734 case 'c': if(!struncmp(s
+1, "ALSCALE", 7))
735 ical_cline_from_token((void **) &vcal
->calscale
, &s
, "CALSCALE");
740 case 'e': if(!struncmp(s
+1, "ND", 2)){
742 s
+= 4; /* 4 = strlen("END:") */
743 if(!struncmp(s
, "VCALENDAR\r\n", 11)){
744 *text
= s
+ 11; /* 11 = strlen("VCALENDAR\r\n") */
745 return (void *) vcal
;
747 // else ukn++; FIX THIS, this is not quite right
752 case 'm': if(!struncmp(s
+1, "ETHOD", 5))
753 ical_cline_from_token((void **) &vcal
->method
, &s
, "METHOD");
758 case 'p': if(!struncmp(s
+1, "RODID", 5))
759 ical_cline_from_token((void **) &vcal
->prodid
, &s
, "PRODID");
764 case 'v': if(!struncmp(s
+1, "ERSION", 6)){
765 ical_cline_from_token((void **) &vcal
->version
, &s
, "VERSION");
771 } /* end of switch(*s) */
773 if(ical_buf_len
< t
- s
){
774 fs_resize((void **)&ical_buf
, t
-s
+1);
780 if(vcal
->uk_prop
== NULL
){
781 vcal
->uk_prop
= fs_get(sizeof(GEN_ICLINE_S
));
782 memset((void *)vcal
->uk_prop
, 0, sizeof(GEN_ICLINE_S
));
783 vcal
->uk_prop
->cline
= ical_parse_line(&s
, ical_buf
);
787 for (gcl
= vcal
->uk_prop
; gcl
&& gcl
->next
; gcl
= gcl
->next
);
788 gcl
->next
= fs_get(sizeof(GEN_ICLINE_S
));
789 memset((void *)gcl
->next
, 0, sizeof(GEN_ICLINE_S
));
790 gcl
->next
->cline
= ical_parse_line(&s
, ical_buf
);
798 /* ok, we have parsed the vcalendar, now parse some special properties */
799 /* start by parsing dates */
800 ical_set_date_vevent(vcal
->comp
[VEvent
], vcal
->comp
[VTimeZone
]);
801 return (void *) vcal
;
805 ical_parse_vevent(char **text
)
811 ical_debug("ical_parse_vevent", *text
);
812 vevent
= fs_get(sizeof(VEVENT_S
));
813 memset((void *)vevent
, 0, sizeof(VEVENT_S
));
815 /* s must always point the the beginning of a line */
816 for(s
= *text
; s
&& *s
!= '\0';){
818 s
= ical_isolate_token(&t
, &c
);
824 *t
= c
; /* restore separator */
826 if(s
){ /* figure out the token */
827 int ukn
= 0; /* unknown token */
828 if(!struncmp(s
, "BEGIN", 5)){
829 s
+= 6; /* 6 = strlen("BEGIN:") */
830 if(!struncmp(s
, "VALARM\r\n", 8)){
831 s
+= 8; /* 8 = strlen("VALARM\r\n"); */
832 if(vevent
->valarm
== NULL
)
833 vevent
->valarm
= ical_parse_valarm(&s
);
836 for(valrm
= vevent
->valarm
; valrm
&& valrm
->next
;
837 valrm
= valrm
->next
);
838 valrm
->next
= ical_parse_valarm(&s
);
841 ICAL_S
*uk_comp
= ical_parse_unknown_comp(&s
, 0);
842 ical_free_unknown_comp(&uk_comp
);
844 } else if(!struncmp(s
, "END", t
-s
-1)){
845 s
+= 4; /* 4 = strlen("END:") */
846 if(!struncmp(s
, "VEVENT\r\n",8)){
847 *text
= s
+ 8; /* 8 = strlen("VCALENDAR\r\n") */
848 return (void *) vevent
;
850 } else{ Event_prop i
;
851 for(i
= 0; i
< EvUnknown
; i
++)
852 if(!struncmp(s
, event_prop
[i
].prop
, t
-s
))
854 if(event_prop
[i
].parse
){
855 if(vevent
->prop
== NULL
){
856 vevent
->prop
= fs_get(EvUnknown
*sizeof(void *));
857 memset((void *)vevent
->prop
, 0, EvUnknown
*sizeof(void *));
859 (event_prop
[i
].parse
)(&vevent
->prop
[event_prop
[i
].pos
], &s
, event_prop
[i
].prop
);
866 if(ical_buf_len
< t
- s
){
867 fs_resize((void **)&ical_buf
, t
-s
+1);
873 if(vevent
->uk_prop
== NULL
){
874 vevent
->uk_prop
= fs_get(sizeof(GEN_ICLINE_S
));
875 memset((void *)vevent
->uk_prop
, 0, sizeof(GEN_ICLINE_S
));
876 vevent
->uk_prop
->cline
= ical_parse_line(&s
, ical_buf
);
880 for (gcl
= vevent
->uk_prop
; gcl
&& gcl
->next
; gcl
= gcl
->next
);
881 gcl
->next
= fs_get(sizeof(GEN_ICLINE_S
));
882 memset((void *)gcl
->next
, 0, sizeof(GEN_ICLINE_S
));
883 gcl
->next
->cline
= ical_parse_line(&s
, ical_buf
);
890 return (void *) vevent
;
894 ical_parse_vtimezone(char **text
)
901 ical_debug("ical_parse_vtimezone", *text
);
902 vtz
= fs_get(sizeof(VTIMEZONE_S
));
903 memset((void *)vtz
, 0, sizeof(VTIMEZONE_S
));
905 /* s must always point the the beginning of a line */
906 for(s
= *text
; s
&& *s
!= '\0';){
908 s
= ical_isolate_token(&t
, &c
);
914 *t
= c
; /* restore separator */
916 if(s
){ /* figure out the token */
917 int ukn
= 0; /* unknown token */
918 if(!struncmp(s
, "BEGIN", 5)){
919 s
+= 6; /* 6 = strlen("BEGIN:") */
920 if(!struncmp(s
, "STANDARD\r\n", 10)){
921 s
+= 10; /* 10 = strlen("STANDARD\r\n"); */
922 v
= ical_parse_timezone(&s
);
923 if(vtz
->standardc
== NULL
)
924 vtz
->standardc
= (ICAL_TZPROP_S
*) v
;
927 for(dl
= vtz
->standardc
; dl
&& dl
->next
; dl
= dl
->next
);
928 dl
->next
= (ICAL_TZPROP_S
*) v
;
930 } else if(!struncmp(s
, "DAYLIGHT\r\n", 10)){
931 s
+= 10; /* 10 = strlen("DAYLIGHT\r\n"); */
932 v
= ical_parse_timezone(&s
);
933 if(vtz
->daylightc
== NULL
)
934 vtz
->daylightc
= (ICAL_TZPROP_S
*) v
;
937 for(dl
= vtz
->daylightc
; dl
&& dl
->next
; dl
= dl
->next
);
938 dl
->next
= (ICAL_TZPROP_S
*) v
;
941 ICAL_S
*uk_comp
= ical_parse_unknown_comp(&s
, 0);
942 ical_free_unknown_comp(&uk_comp
);
944 } else if(!struncmp(s
, "END", t
-s
-1)){
945 s
+= 4; /* 4 = strlen("END:") */
946 if(!struncmp(s
, "VTIMEZONE\r\n",11)){
947 *text
= s
+ 11; /* 11 = strlen("VTIMEZONE\r\n") */
951 for(i
= 0; i
< TZCUnknown
; i
++)
952 if(!struncmp(s
, tz_comp
[i
].prop
, t
-s
))
954 if(tz_comp
[i
].parse
){
955 if(vtz
->prop
== NULL
){
956 vtz
->prop
= fs_get(TZCUnknown
*sizeof(void *));
957 memset((void *)vtz
->prop
, 0, TZCUnknown
*sizeof(void *));
959 (tz_comp
[i
].parse
)(&vtz
->prop
[tz_comp
[i
].pos
], &s
, tz_comp
[i
].prop
);
966 if(ical_buf_len
< t
- s
){
967 fs_resize((void **)&ical_buf
, t
-s
+1);
973 if(vtz
->uk_prop
== NULL
){
974 vtz
->uk_prop
= fs_get(sizeof(GEN_ICLINE_S
));
975 memset((void *)vtz
->uk_prop
, 0, sizeof(GEN_ICLINE_S
));
976 vtz
->uk_prop
->cline
= ical_parse_line(&s
, ical_buf
);
980 for (gcl
= vtz
->uk_prop
; gcl
&& gcl
->next
; gcl
= gcl
->next
);
981 gcl
->next
= fs_get(sizeof(GEN_ICLINE_S
));
982 memset((void *)gcl
->next
, 0, sizeof(GEN_ICLINE_S
));
983 gcl
->next
->cline
= ical_parse_line(&s
, ical_buf
);
994 ical_parse_timezone(char **text
)
998 ICAL_TZPROP_S
*tzprop
;
1000 ical_debug("ical_parse_timezone", *text
);
1001 tzprop
= fs_get(sizeof(ICAL_TZPROP_S
));
1002 memset((void *)tzprop
, 0, sizeof(ICAL_TZPROP_S
));
1004 /* s must always point the the beginning of a line */
1005 for(s
= *text
; s
&& *s
!= '\0';){
1007 s
= ical_isolate_token(&t
, &c
);
1013 *t
= c
; /* restore separator */
1015 if(s
){ /* figure out the token */
1016 int ukn
= 0; /* unknown token */
1017 if(!struncmp(s
, "BEGIN", 5)){
1018 s
+= 6; /* 6 = strlen("BEGIN:") */
1019 ICAL_S
*uk_comp
= ical_parse_unknown_comp(&s
, 0);
1020 ical_free_unknown_comp(&uk_comp
);
1021 } else if(!struncmp(s
, "END", t
-s
-1)){
1022 s
+= 4; /* 4 = strlen("END:") */
1023 if(!struncmp(s
, "STANDARD\r\n", 10)
1024 || !struncmp(s
, "DAYLIGHT\r\n", 10)){
1025 *text
= s
+ 10; /* 10 = strlen("STANDARD\r\n") */
1026 return (void *) tzprop
;
1029 for(i
= 0; i
< TZPUnknown
; i
++)
1030 if(!struncmp(s
, tz_prop
[i
].prop
, t
-s
))
1032 if(tz_prop
[i
].parse
){
1033 if(tzprop
->prop
== NULL
){
1034 tzprop
->prop
= fs_get(TZPUnknown
*sizeof(void *));
1035 memset((void *)tzprop
->prop
, 0, TZPUnknown
*sizeof(void *));
1037 (tz_prop
[i
].parse
)(&tzprop
->prop
[tz_prop
[i
].pos
], &s
, tz_prop
[i
].prop
);
1044 if(ical_buf_len
< t
- s
){
1045 fs_resize((void **)&ical_buf
, t
-s
+1);
1049 strcpy(ical_buf
, s
);
1051 if(tzprop
->uk_prop
== NULL
){
1052 tzprop
->uk_prop
= fs_get(sizeof(GEN_ICLINE_S
));
1053 memset((void *)tzprop
->uk_prop
, 0, sizeof(GEN_ICLINE_S
));
1054 tzprop
->uk_prop
->cline
= ical_parse_line(&s
, ical_buf
);
1058 for (gcl
= tzprop
->uk_prop
; gcl
&& gcl
->next
; gcl
= gcl
->next
);
1059 gcl
->next
= fs_get(sizeof(GEN_ICLINE_S
));
1060 memset((void *)gcl
->next
, 0, sizeof(GEN_ICLINE_S
));
1061 gcl
->next
->cline
= ical_parse_line(&s
, ical_buf
);
1064 } /* end of if(s) */
1068 return (void *) tzprop
;
1072 ical_parse_valarm(char **text
)
1078 ical_debug("ical_parse_valarm", *text
);
1079 valarm
= fs_get(sizeof(VALARM_S
));
1080 memset((void *)valarm
, 0, sizeof(VALARM_S
));
1082 /* s must always point the the beginning of a line */
1083 for(s
= *text
; s
&& *s
!= '\0';){
1085 s
= ical_isolate_token(&t
, &c
);
1091 *t
= c
; /* restore separator */
1093 if(s
){ /* figure out the token */
1094 int ukn
= 0; /* unknown token */
1095 if(!struncmp(s
, "BEGIN", 5)){
1096 s
+= 6; /* 6 = strlen("BEGIN:") */
1097 ICAL_S
*uk_comp
= ical_parse_unknown_comp(&s
, 0);
1098 ical_free_unknown_comp(&uk_comp
);
1099 } else if(!struncmp(s
, "END", t
-s
-1)){
1100 s
+= 4; /* 4 = strlen("END:") */
1101 if(!struncmp(s
, "ALARM\r\n", 7)){
1102 *text
= s
+ 7; /* 7 = strlen("ALARM\r\n") */
1103 return (void *) valarm
;
1105 } else{ Alarm_prop i
;
1106 for(i
= 0; i
< AlUnknown
; i
++)
1107 if(!struncmp(s
, alarm_prop
[i
].prop
, t
-s
))
1109 if(alarm_prop
[i
].parse
){
1110 if(valarm
->prop
== NULL
){
1111 valarm
->prop
= fs_get(AlUnknown
*sizeof(void *));
1112 memset((void *)valarm
->prop
, 0, AlUnknown
*sizeof(void *));
1114 (alarm_prop
[i
].parse
)(&valarm
->prop
[alarm_prop
[i
].pos
], &s
, alarm_prop
[i
].prop
);
1121 if(ical_buf_len
< t
- s
){
1122 fs_resize((void **)&ical_buf
, t
-s
+1);
1126 strcpy(ical_buf
, s
);
1128 if(valarm
->uk_prop
== NULL
){
1129 valarm
->uk_prop
= fs_get(sizeof(GEN_ICLINE_S
));
1130 memset((void *)valarm
->uk_prop
, 0, sizeof(GEN_ICLINE_S
));
1131 valarm
->uk_prop
->cline
= ical_parse_line(&s
, ical_buf
);
1135 for (gcl
= valarm
->uk_prop
; gcl
&& gcl
->next
; gcl
= gcl
->next
);
1136 gcl
->next
= fs_get(sizeof(GEN_ICLINE_S
));
1137 memset((void *)gcl
->next
, 0, sizeof(GEN_ICLINE_S
));
1138 gcl
->next
->cline
= ical_parse_line(&s
, ical_buf
);
1141 } /* end of if(s) */
1145 return (void *) valarm
;
1149 ical_parse_vtodo(char **text
)
1155 ical_parse_vjournal(char **text
)
1161 ical_parse_vfreebusy(char **text
)
1167 ical_parse_generic_comp(char **text
, int level
)
1172 GEN_ICLINE_S
*gcl
= NULL
;
1175 ical_debug("ical_parse_generic_comp", *text
);
1176 ical
= fs_get(sizeof(ICAL_S
));
1177 memset((void *)ical
, 0, sizeof(ICAL_S
));
1179 ical
->comp
= ical_get_value(text
);
1180 token
= fs_get(strlen(ical
->comp
) + 2 + 1);
1181 sprintf(token
, "%s\r\n", ical
->comp
); /* this is allocated memory */
1183 /* s must always point the the beginning of a line */
1184 for(s
= *text
; s
&& *s
!= '\0';){
1186 s
= ical_isolate_token(&t
, &c
);
1193 *t
= c
; /* restore character */
1194 if(s
){ /* figure out the token */
1195 int ukn
= 0; /* unknown token */
1198 case 'b': if(!struncmp(s
+1, "EGIN", 4)){
1199 s
+= 6; /* 6 = strlen("BEGIN:") */
1200 if(ical
->next
== NULL
)
1201 ical
->next
= ical_parse_unknown_comp(&s
, level
+1);
1206 for(i
= 0, b
= ical
; i
<= level
&& b
&& b
->next
; b
= b
->next
, i
++);
1207 if(b
->branch
== NULL
)
1208 b
->branch
= ical_parse_unknown_comp(&s
, level
+1);
1210 for(; b
&& b
->branch
; b
= b
->branch
);
1211 b
->branch
= ical_parse_unknown_comp(&s
, level
+1);
1218 case 'e': if(!struncmp(s
+1, "ND", 2)){
1220 s
+= 4; /* 4 = strlen("END:") */
1221 if(!struncmp(s
, token
, strlen(token
))){
1222 *text
= s
+ strlen(token
);
1223 ical
->value
= (void *) gcl
;
1231 } /* end of switch(*s) */
1233 if(ical_buf_len
< t
- s
){
1234 fs_resize((void **)&ical_buf
, t
-s
+1);
1238 strcpy(ical_buf
, s
);
1241 gcl
= fs_get(sizeof(GEN_ICLINE_S
));
1242 memset((void *)gcl
, 0, sizeof(GEN_ICLINE_S
));
1243 gcl
->cline
= ical_parse_line(&s
, ical_buf
);
1246 GEN_ICLINE_S
*gencl
;
1247 for (gencl
= gcl
; gencl
&& gencl
->next
; gencl
= gencl
->next
);
1248 gencl
->next
= fs_get(sizeof(GEN_ICLINE_S
));
1249 memset((void *)gencl
->next
, 0, sizeof(GEN_ICLINE_S
));
1250 gencl
->next
->cline
= ical_parse_line(&s
, ical_buf
);
1253 } /* end of if(s) */
1256 ical
->value
= (void *) gcl
;
1262 ical_parse_unknown_comp(char **text
, int level
)
1267 ical_debug("ical_parse_unknown_comp", *text
);
1268 for(i
= 0; ical_comp
[i
].comp
1269 && (struncmp(*text
, ical_comp
[i
].comp
, ical_comp
[i
].len
)
1270 || struncmp(*text
+ ical_comp
[i
].len
, "\r\n", 2)); i
++);
1272 if(ical_comp
[i
].parse
){
1273 *text
+= ical_comp
[i
].len
+ 2;
1274 ical
= fs_get(sizeof(ICAL_S
));
1275 memset((void *)ical
, 0, sizeof(ICAL_S
));
1276 ical
->comp
= cpystr(ical_comp
[i
].comp
);
1277 ical
->value
= (ical_comp
[i
].parse
)(text
);
1279 ical
= ical_parse_generic_comp(text
, level
);
1285 ical_parse_line(char **text
, char *name
)
1290 ic
= fs_get(sizeof(ICLINE_S
));
1291 memset((void *)ic
, 0, sizeof(ICLINE_S
));
1293 ic
->token
= cpystr(name
);
1297 ic
->param
= ical_get_parameter(&s
);
1301 ic
->value
= ical_get_value(&s
);
1309 *** PARSE PROPERTY FUNCTIONS
1313 ical_parse_freq(Freq_value
*fval
, char *text
)
1315 if(fval
== NULL
) return;
1319 if(text
== NULL
) return;
1321 if(!strucmp(text
, "SECONDLY")) *fval
= FSecondly
;
1322 else if(!strucmp(text
, "MINUTELY")) *fval
= FMinutely
;
1323 else if(!strucmp(text
, "HOURLY")) *fval
= FHourly
;
1324 else if(!strucmp(text
, "DAILY")) *fval
= FDaily
;
1325 else if(!strucmp(text
, "WEEKLY")) *fval
= FWeekly
;
1326 else if(!strucmp(text
, "MONTHLY")) *fval
= FMonthly
;
1327 else if(!strucmp(text
, "YEARLY")) *fval
= FYearly
;
1331 ical_parse_weekday_list(BYWKDY_S
**bywkdyp
, char *wklist
)
1333 BYWKDY_S
*bywkdy
, *w
;
1338 if(bywkdyp
== NULL
) return;
1339 *bywkdyp
= bywkdy
= NULL
;
1340 if(wklist
== NULL
) return;
1342 for(t
= s
= wklist
; done
== 0; s
++){
1343 if(*s
!= ',' && *s
!= '\0')
1348 else /* c == '\0' */
1352 for(w
= bywkdy
; w
&& w
->next
; w
= w
->next
);
1353 w
= fs_get(sizeof(BYWKDY_S
));
1354 memset((void *)w
, 0, sizeof(BYWKDY_S
));
1355 if(!strucmp(t
+len
-2, "SU")) w
->wd
= Sunday
;
1356 else if(!strucmp(t
+len
-2, "MO")) w
->wd
= Monday
;
1357 else if(!strucmp(t
+len
-2, "TU")) w
->wd
= Tuesday
;
1358 else if(!strucmp(t
+len
-2, "WE")) w
->wd
= Wednesday
;
1359 else if(!strucmp(t
+len
-2, "TH")) w
->wd
= Thursday
;
1360 else if(!strucmp(t
+len
-2, "FR")) w
->wd
= Friday
;
1361 else if(!strucmp(t
+len
-2, "SA")) w
->wd
= Saturday
;
1362 // t[len - 2] = '\0';
1364 w
->value
= strtoul(t
, &t
, 10);
1374 ical_free_weekday_list((void **)&bywkdy
);
1380 ical_parse_number_list(BYWKDY_S
**bynop
, char *nolist
)
1386 if(bynop
== NULL
) return;
1387 *bynop
= byno
= NULL
;
1388 if(nolist
== NULL
) return;
1390 for(t
= s
= nolist
; done
== 0; s
++){
1391 if(*s
!= ',' && *s
!= '\0')
1396 else /* c == '\0' */
1399 for(n
= byno
; n
&& n
->next
; n
= n
->next
);
1400 n
= fs_get(sizeof(BYWKDY_S
));
1401 memset((void *)n
, 0, sizeof(BYWKDY_S
));
1402 n
->value
= strtoul(t
, &t
, 10);
1411 ical_free_weekday_list((void **)&byno
);
1417 ical_parse_rrule(RRULE_S
**rrulep
, char **text
)
1422 ICAL_PARAMETER_S
*param
, *p
;
1426 || text
== NULL
|| *text
== NULL
|| struncmp(*text
, "RRULE", 5)) return;
1427 rrule
= fs_get(sizeof(RRULE_S
));
1428 memset((void *) rrule
, 0, sizeof(RRULE_S
));
1430 /* recurring rules are special. First, we parse the icline that contains it */
1431 icl
= ical_parse_line(text
, "RRULE");
1433 /* now we copy the parameters that it contains */
1434 rrule
->param
= ical_parameter_cpy(icl
->param
);
1436 /* then we parse icl->value as if it was a parameter */
1438 param
= ical_get_parameter(&s
);
1440 /* now we check which values were given, and fill the prop array */
1441 rrule
->prop
= fs_get(RRUnknown
*sizeof(void *));
1442 memset((void *) rrule
->prop
, 0, RRUnknown
*sizeof(void *));
1444 for(p
= param
; p
!= NULL
; p
= p
->next
){
1445 for(i
= 0; rrule_prop
[i
].prop
!= NULL
&& strucmp(p
->name
, rrule_prop
[i
].prop
); i
++);
1446 if(rrule_prop
[i
].parse
)
1447 (rrule_prop
[i
].parse
)(&rrule
->prop
[rrule_prop
[i
].pos
], p
->value
);
1450 ical_free_param(¶m
);
1451 ical_free_cline((void **)&icl
);
1453 ical_free_rrule((void **)&rrule
);
1458 /*** UTF-8 for ICAL ***/
1461 ical_non_ascii_valid(unsigned char c
)
1464 static int utf8_len
= 0;
1465 static int utf8_type
= 0;
1469 utf8_type
= (c
>= 0xF0 && c
<= 0xF4)
1470 ? 4 : (c
>= 0xE0 && c
<= 0xEF)
1471 ? 3 : (c
>= 0xC2 && c
<= 0xDF)
1477 icu
[utf8_len
++] = c
; /* count it */
1482 else if(utf8_len
== 2){
1483 rv
= (icu
[0] >= 0xC2 && icu
[0] <= 0xDF)
1484 && (icu
[1] >= 0x80 && icu
[1] <= 0xBF) ? UTF8_COMPLETE
: 0;
1487 } else if (utf8_type
== 3){
1492 rv
= (icu
[1] >= 0xA0 && icu
[1] <= 0xBF)
1493 && (icu
[2] >= 0x80 && icu
[2] <= 0xBF) ? UTF8_COMPLETE
: 0;
1494 else if(icu
[0] >= 0xE1 && icu
[0] <= 0xEC)
1495 rv
= (icu
[1] >= 0x80 && icu
[1] <= 0xBF)
1496 && (icu
[2] >= 0x80 && icu
[2] <= 0xBF) ? UTF8_COMPLETE
: 0;
1497 else if(icu
[0] == 0xED)
1498 rv
= (icu
[1] >= 0x80 && icu
[1] <= 0x9F)
1499 && (icu
[2] >= 0x80 && icu
[2] <= 0xBF) ? UTF8_COMPLETE
: 0;
1500 else if(icu
[0] >= 0xE1 && icu
[0] <= 0xEC)
1501 rv
= (icu
[1] >= 0x80 && icu
[1] <= 0xBF)
1502 && (icu
[2] >= 0x80 && icu
[2] <= 0xBF) ? UTF8_COMPLETE
: 0;
1505 } else if (utf8_type
== 4){
1510 rv
= (icu
[1] >= 0x90 && icu
[1] <= 0xBF)
1511 && (icu
[2] >= 0x80 && icu
[2] <= 0xBF)
1512 && (icu
[3] >= 0x80 && icu
[3] <= 0xBF) ? UTF8_COMPLETE
: 0;
1513 else if(icu
[0] >= 0xF1 && icu
[0] <= 0xF3)
1514 rv
= (icu
[1] >= 0x80 && icu
[1] <= 0xBF)
1515 && (icu
[2] >= 0x80 && icu
[2] <= 0xBF)
1516 && (icu
[3] >= 0x80 && icu
[3] <= 0xBF) ? UTF8_COMPLETE
: 0;
1517 else if(icu
[0] == 0xF4)
1518 rv
= (icu
[1] >= 0x80 && icu
[1] <= 0x8F)
1519 && (icu
[2] >= 0x80 && icu
[2] <= 0xBF)
1520 && (icu
[3] >= 0x80 && icu
[3] <= 0xBF) ? UTF8_COMPLETE
: 0;
1528 ical_get_number_value(char *value
, int beg_pos
, int end_pos
)
1534 value
[end_pos
] = '\0';
1535 rv
= strtoul(value
+ beg_pos
, &err
, 10);
1536 if(err
!= NULL
&& *err
!= '\0') return -1;
1542 ical_free_duration(ICAL_DURATION_S
**ic_d
)
1544 if(ic_d
== NULL
|| *ic_d
== NULL
)
1547 if((*ic_d
)->next
) ical_free_duration(&(*ic_d
)->next
);
1548 fs_give((void **)ic_d
);
1551 /* returns 0 if no error, -1 if some error */
1553 ical_parse_duration(char *value
, ICAL_DURATION_S
*ic_d
)
1557 if(value
== NULL
|| ic_d
== NULL
) return -1;
1559 memset((void *)ic_d
, 0, sizeof(ICAL_DURATION_S
));
1561 if(value
[i
= 0] == '-'){
1564 } else if(value
[i
] == '+')
1567 if(value
[i
++] == 'P'){
1568 for(j
= i
; value
[j
] != '\0' && value
[j
] != ','; j
++){
1569 if(!isdigit(value
[j
]))
1571 case 'W': ic_d
->weeks
= ical_get_number_value(value
, i
, j
-1);
1574 case 'D': ic_d
->days
= ical_get_number_value(value
, i
, j
-1);
1577 case 'H': ic_d
->hours
= ical_get_number_value(value
, i
, j
-1);
1580 case 'M': ic_d
->minutes
= ical_get_number_value(value
, i
, j
-1);
1583 case 'S': ic_d
->seconds
= ical_get_number_value(value
, i
, j
-1);
1586 case 'T': i
= j
+ 1;
1596 if(value
[j
++] == ','){
1597 ICAL_DURATION_S next
;
1598 rv
= ical_parse_duration(value
+j
, &next
);
1605 /* return -1 if any error, 0 if no error */
1607 ical_parse_date(char *value
, struct tm
*t
)
1612 if(t
== NULL
) return -1;
1613 memset((void *)&Tm
, 0, sizeof(struct tm
));
1615 if(value
== NULL
) return -1;
1617 /* a simple check for the format of the string */
1618 for(i
= 0; isdigit(value
[i
]); i
++);
1619 if (i
!= 8 || value
[i
++] != 'T') return -1;
1620 for(; isdigit(value
[i
]); i
++);
1621 if(i
!= 15 || (value
[i
] != '\0' && (value
[i
] != 'Z' || value
[i
+1] != '\0')))
1624 Tm
.tm_year
= ical_get_number_value(value
, 0, 4) - 1900;
1625 Tm
.tm_mon
= ical_get_number_value(value
, 4, 6) - 1;
1626 Tm
.tm_mday
= ical_get_number_value(value
, 6, 8);
1627 Tm
.tm_hour
= ical_get_number_value(value
, 9, 11);
1628 Tm
.tm_min
= ical_get_number_value(value
, 11, 13);
1629 Tm
.tm_sec
= ical_get_number_value(value
, 13, 15);
1632 return (t
->tm_mon
> 11 || t
->tm_mon
< 0
1633 || t
->tm_mday
> 31 || t
->tm_mday
< 0
1634 || t
->tm_hour
> 23 || t
->tm_hour
< 0
1635 || t
->tm_min
> 59 || t
->tm_min
< 0
1636 || t
->tm_sec
> 60 || t
->tm_sec
< 0)
1641 ical_set_date(ICLINE_S
*icl
, VTIMEZONE_S
*vtz
)
1643 int date_form
; /* date forms from section 3.3.4 in RFC 5545 */
1644 ICAL_PARAMETER_S
*param
;
1649 if(icl
== NULL
) return;
1651 for(param
= icl
->param
; param
!= NULL
; param
= param
->next
)
1652 if(!strucmp(param
->name
, "TZID"))
1656 date_form
= 3; /* local time with timezone */
1657 else if(icl
->value
[strlen(icl
->value
)-1] == 'Z')
1658 date_form
= 2; /* utc time */
1659 else date_form
= 1; /* local time */
1661 ical_parse_date(icl
->value
, &ic_date
);
1662 ic_date
.tm_wday
= ical_day_of_week(ic_date
); /* find out day of the week */
1666 case 2: ical_adjust_date(&ic_date
, vtz
);
1669 default: alpine_panic ("Impossible date_form");
1674 ical_std_or_daylight(struct tm
*date
, VTIMEZONE_S
*vtz
)
1676 struct tm standard
, daylight
;
1683 /* adjusts time to given time zone */
1685 ical_adjust_date(struct tm
*date
, VTIMEZONE_S
*vtz
)
1687 char *tzname
= NULL
;
1689 ICAL_TZPROP_S
*cur_std_day
;
1695 if((icl
= (ICLINE_S
*)vtz
->prop
[TZCid
]) != NULL
)
1696 tzname
= cpystr(icl
->value
);
1699 //+++ cur_std_day = ical_std_or_daylight(date, vtz);
1703 ical_set_date_vevent(void *veventv
, void *vtzv
)
1705 VEVENT_S
*vevent
= (VEVENT_S
*) veventv
;
1706 VTIMEZONE_S
*vtz
= (VTIMEZONE_S
*) vtzv
;
1709 ical_set_date(vevent
->prop
[EvDtstamp
], vtz
);
1710 ical_set_date(vevent
->prop
[EvDtstart
], vtz
);
1711 ical_set_date(vevent
->prop
[EvDtend
], vtz
);
1715 #define LEAP_YEAR(X) ((((X) % 4 == 0) \
1716 && (((X) % 100 != 0) || ((X) % 400 == 0))) \
1719 #define CAL_OFFSET(X) (((X) == 1752) ? 5 : (LEAP_YEAR((X)) ? 2 : 1))
1721 /* given a year, after day_zero, return the day
1722 * of the week of the first of january of that year. On error,
1723 * return a negative number.
1724 * Assumption: day_zero is the date of january 1, of some year.
1727 ical_january_first(int year
)
1729 int i
, january_first
;
1731 if(year
< day_zero
.tm_year
) return -1; /* not supported */
1734 january_first
= day_zero
.tm_wday
;
1735 for(i
= 1900 + day_zero
.tm_year
+ 1; i
<= year
; i
++)
1736 january_first
+= CAL_OFFSET(i
-1);
1738 return january_first
% 7;
1741 /* given a month, week day, and year, return all days of the month
1742 * that have that day as the week day. For example, return all
1743 * sundays in november 2012.
1746 ical_day_from_week(int month
, Weekday day
, int year
)
1753 fday
= ical_first_of_month(month
, year
);
1754 year
+= 1900; /* restore year */
1755 if(year
== 1752 && month
== 8){
1758 for(nday
= 1, wday
= (Weekday
) fday
; wday
!= day
; wday
= (wday
+1) % 7, nday
++)
1760 rv
= fs_get(6*sizeof(int));
1761 memset((void *)&rv
, 0, 6*sizeof(int));
1762 for(i
= 0; nday
<= month_len
[month
]; i
++){
1766 if(LEAP_YEAR(year
) && month
== 1 && nday
== 29)
1774 /* given a month and a year, return the weekday of the first of the
1775 * month in that year.
1776 * return value: on error -1, otherwise the day of the week.
1779 ical_first_of_month(int month
, int year
)
1783 if((d
= ical_january_first(year
)) < 0)
1787 for(i
= 0; i
< month
; i
++)
1790 if(LEAP_YEAR(year
) && month
>= 2)
1793 if(year
== 1752 && month
>= 9)
1799 /* given a day, month and year, return the weekday of that day
1800 * return value: on error -1, otherwise the day of the week.
1802 int ical_day_of_week(struct tm date
)
1806 if((d
= ical_first_of_month(date
.tm_mon
, date
.tm_year
)) < 0)
1809 d
+= date
.tm_mday
- 1;
1811 if(date
.tm_year
+ 1900 == 1752){
1812 if(date
.tm_mday
> 2 && date
.tm_mday
< 14)
1814 if(date
.tm_mday
>= 14)
1821 /* given an initial date dtstart, and a recurring rule, rrule,
1822 * adjust the date to the first date on the same year, when
1823 * the rule actually starts
1826 adjust_date_rrule(struct tm
*dtstart
, RRULE_S
*rrule
)
1830 memset((void *) &t
, 0, sizeof(struct tm
));
1831 t
.tm_year
= dtstart
->tm_year
; /* same year */
1832 if(rrule
->prop
[RRFreq
]){
1834 if(rrule
->prop
[RRCount
]){
1836 else if(rrule
->prop
[RRInterval
]){
1838 if(rrule
->prop
[RRBysecond
]){
1839 BYWKDY_S
*sec
= (BYWKDY_S
*) rrule
->prop
[RRBysecond
], *seco
;
1840 for (seco
= sec
; seco
!= NULL
; seco
= seco
->next
)
1841 if(seco
== sec
) t
.tm_sec
= seco
->value
;
1842 else if (seco
->value
< t
.tm_sec
)
1843 t
.tm_sec
= seco
->value
;
1845 if (rrule
->prop
[RRByminute
]){
1846 BYWKDY_S
*sec
= (BYWKDY_S
*) rrule
->prop
[RRByminute
], *seco
;
1847 for (seco
= sec
; seco
!= NULL
; seco
= seco
->next
)
1848 if(seco
== sec
) t
.tm_min
= seco
->value
;
1849 else if (seco
->value
< t
.tm_sec
)
1850 t
.tm_min
= seco
->value
;
1852 if (rrule
->prop
[RRByhour
]){
1853 BYWKDY_S
*sec
= (BYWKDY_S
*) rrule
->prop
[RRByhour
], *seco
;
1854 for (seco
= sec
; seco
!= NULL
; seco
= seco
->next
)
1855 if(seco
== sec
) t
.tm_hour
= seco
->value
;
1856 else if (seco
->value
< t
.tm_sec
)
1857 t
.tm_hour
= seco
->value
;
1859 if (rrule
->prop
[RRByday
]){
1861 if (rrule
->prop
[RRByweekno
]){
1863 if (rrule
->prop
[RRBymonthday
]){
1865 if (rrule
->prop
[RRByyearday
]){
1867 if (rrule
->prop
[RRByweekno
]){
1869 if (rrule
->prop
[RRBymonth
]){
1870 BYWKDY_S
*m
= (BYWKDY_S
*) rrule
->prop
[RRBymonth
], *mo
;
1871 for (mo
= m
; mo
!= NULL
; mo
= mo
->next
)
1872 if(mo
== m
) t
.tm_mon
= mo
->value
- 1;
1873 else if (mo
->value
- 1 < t
.tm_mon
)
1874 t
.tm_mon
= mo
->value
- 1;
1876 if (rrule
->prop
[RRBysetpos
]){
1878 if (rrule
->prop
[RRWkst
]){
1883 ical_initialize(void)
1885 ical_buf_len
= 1024;
1886 ical_buf
= fs_get(ical_buf_len
+1);
1888 memset((void *) &day_zero
, 0, sizeof(struct tm
));
1889 day_zero
.tm_year
= 1601 - 1900;
1890 day_zero
.tm_mday
= 1;
1891 day_zero
.tm_wday
= 4;
1894 /* we create a summary of the event, and pass that back as
1898 ical_vevent_summary(VCALENDAR_S
*vcal
)
1900 VEVENT_SUMMARY_S
*rv
;
1906 if(vcal
== NULL
) return NULL
;
1908 method
= vcal
->method
;
1909 vevent
= (VEVENT_S
*) vcal
->comp
[VEvent
];
1911 if(vevent
== NULL
|| vevent
->prop
== NULL
)
1914 rv
= fs_get(sizeof(VEVENT_SUMMARY_S
));
1915 memset((void *) rv
, 0, sizeof(VEVENT_SUMMARY_S
));
1917 if(method
!= NULL
&& !strucmp(method
->value
, "CANCEL"))
1920 if((icl
= (ICLINE_S
*) vevent
->prop
[EvPriority
]) != NULL
)
1921 rv
->priority
= atoi(icl
->value
);
1923 if((icl
= (ICLINE_S
*) vevent
->prop
[EvSummary
]) != NULL
)
1924 rv
->summary
= cpystr(icl
->value
? icl
->value
: _("No Summary"));
1926 if((icl
= (ICLINE_S
*) vevent
->prop
[EvClass
]) != NULL
)
1927 rv
->class = cpystr(icl
->value
? icl
->value
: _("PUBLIC"));
1929 rv
->class = cpystr(_("PUBLIC"));
1931 if((icl
= (ICLINE_S
*) vevent
->prop
[EvOrganizer
]) != NULL
){
1932 char *cn
, *sender
, *address
;
1933 ICAL_PARAMETER_S
*param
;
1935 cn
= sender
= address
= NULL
;
1936 for(param
= icl
->param
; param
!= NULL
; param
= param
->next
)
1937 if(!strucmp(param
->name
, "CN"))
1939 else if(!strucmp(param
->name
, "SENT-BY"))
1940 sender
= param
->value
;
1943 if(!struncmp(sender
, "MAILTO:", 7))
1945 utf8_snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, "<%s>", sender
);
1946 rv
->sender
= cpystr(tmp_20k_buf
);
1949 if((address
= icl
->value
) != NULL
){
1950 if(!struncmp(address
, "MAILTO:", 7))
1952 utf8_snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, "%s%s<%s>",
1953 cn
? cn
: "", cn
? " " : "",
1954 address
? address
: _("Unknown address"));
1955 rv
->organizer
= cpystr(tmp_20k_buf
);
1957 } /* end of if(organizer) */
1959 if((icl
= (ICLINE_S
*) vevent
->prop
[EvLocation
]) != NULL
)
1960 rv
->location
= cpystr(icl
->value
? icl
->value
: _("Location undisclosed"));
1962 if((icl
= (ICLINE_S
*) vevent
->prop
[EvDtstart
]) != NULL
){
1965 memset((void *)&ic_date
, 0, sizeof(struct tm
));
1966 ical_parse_date(icl
->value
, &ic_date
);
1967 ic_date
.tm_wday
= ical_day_of_week(ic_date
);
1968 our_strftime(tmp
, sizeof(tmp
), "%a %x %I:%M %p", &ic_date
);
1969 rv
->evstart
= cpystr(icl
->value
? tmp
: _("Unknown Start Date"));
1970 } /* end of if dtstart */
1972 if((icl
= (ICLINE_S
*) vevent
->prop
[EvDuration
]) != NULL
){
1974 ICAL_DURATION_S ic_d
, icd2
;
1975 if(ical_parse_duration(icl
->value
, &ic_d
) == 0){
1976 char tmp
[MAILTMPLEN
+1];
1978 for(i
= 1, icd2
= ic_d
; icd2
.next
!= NULL
; icd2
= *icd2
.next
, i
++);
1979 rv
->duration
= fs_get((i
+1)*sizeof(char *));
1986 utf8_snprintf(tmp
+strlen(tmp
), MAILTMPLEN
- strlen(tmp
),
1987 "%d %s ", ic_d
.weeks
, ic_d
.weeks
== 1 ? _("week") : _("weeks"));
1989 utf8_snprintf(tmp
+strlen(tmp
), MAILTMPLEN
- strlen(tmp
),
1990 "%d %s ", ic_d
.days
, ic_d
.days
== 1 ? _("day") : _("days"));
1992 utf8_snprintf(tmp
+strlen(tmp
), MAILTMPLEN
- strlen(tmp
),
1993 "%d %s ", ic_d
.hours
, ic_d
.hours
== 1 ? _("hour") : _("hours"));
1994 if(ic_d
.minutes
> 0)
1995 utf8_snprintf(tmp
+strlen(tmp
), MAILTMPLEN
- strlen(tmp
),
1996 "%d %s ", ic_d
.minutes
, ic_d
.minutes
== 1 ? _("minute") : _("minutes"));
1997 if(ic_d
.seconds
> 0)
1998 utf8_snprintf(tmp
+strlen(tmp
), MAILTMPLEN
- strlen(tmp
),
1999 "%d %s ", ic_d
.seconds
, ic_d
.seconds
== 1 ? _("second") : _("seconds"));
2001 tmp
[MAILTMPLEN
] = '\0';
2002 rv
->duration
[i
++] = cpystr(tmp
);
2004 if(ic_d
.next
!= NULL
)
2008 } while (done
== 0);
2009 rv
->duration
[i
] = NULL
;
2011 } /* end of DURATION */
2012 else if((icl
= (ICLINE_S
*) vevent
->prop
[EvDtend
]) != NULL
){
2016 memset((void *)&ic_date
, 0, sizeof(struct tm
));
2017 ical_parse_date(icl
->value
, &ic_date
);
2018 ic_date
.tm_wday
= ical_day_of_week(ic_date
);
2019 our_strftime(tmp
, sizeof(tmp
), "%a %x %I:%M %p", &ic_date
);
2020 rv
->evend
= cpystr(icl
->value
? tmp
: _("Unknown End Date"));
2021 } /* end of if dtend */
2023 if((gicl
= (GEN_ICLINE_S
*) vevent
->prop
[EvAttendee
]) != NULL
){
2026 for(nattendees
= 0; gicl
!= NULL
; gicl
= gicl
->next
, nattendees
++);
2027 rv
->attendee
= fs_get((nattendees
+1)*sizeof(char *));
2029 gicl
= (GEN_ICLINE_S
*) vevent
->prop
[EvAttendee
];
2030 for(i
= 0; gicl
!= NULL
; gicl
= gicl
->next
, i
++){
2031 char *role
, *partstat
, *rsvp
;
2033 ICAL_PARAMETER_S
*param
;
2036 role
= partstat
= rsvp
= cn
= mailto
= NULL
;
2037 for(param
= icl
->param
; param
!= NULL
; param
= param
->next
){
2038 if(!strucmp(param
->name
, "ROLE")){
2039 if(!strucmp(param
->value
, "REQ-PARTICIPANT"))
2040 role
= _("[Required]");
2041 else if(!strucmp(param
->value
, "OPT-PARTICIPANT"))
2042 role
= _("[Optional]");
2043 else if(!strucmp(param
->value
, "NON-PARTICIPANT"))
2044 role
= _("[Informed]");
2045 else if(!strucmp(param
->value
, "CHAIR"))
2046 role
= _("[ Chair ]");
2048 role
= param
->value
;
2050 else if(!strucmp(param
->name
, "PARTSTAT")){
2051 if(!strucmp(param
->value
, "NEEDS-ACTION"))
2052 partstat
= _("[Need-Reply]");
2053 else if(!strucmp(param
->value
, "ACCEPTED"))
2054 partstat
= _("[ Accepted ]");
2055 else if(!strucmp(param
->value
, "DECLINED"))
2056 partstat
= _("[ Declined ]");
2057 else if(!strucmp(param
->value
, "TENTATIVE"))
2058 partstat
= _("[ Tentative]");
2059 else if(!strucmp(param
->value
, "DELEGATED"))
2060 partstat
= _("[ Delegated]");
2062 partstat
= param
->value
;
2064 else if(!strucmp(param
->name
, "RSVP"))
2065 rsvp
= param
->value
;
2066 else if(!strucmp(param
->name
, "CN"))
2069 if(icl
->value
&& !struncmp(icl
->value
, "MAILTO:", strlen("MAILTO:")))
2070 mailto
= icl
->value
+ 7; /* 7 = strlen("MAILTO:") */
2071 if(!strucmp(cn
, mailto
))
2073 utf8_snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, "%s%s%s%s%s%s<%s>",
2074 role
&& *role
? role
: "",
2075 role
&& *role
? " " : "",
2076 partstat
? partstat
: _("[Unknown Reply]"),
2077 partstat
? " " : "",
2078 cn
&& *cn
? cn
: "",
2079 cn
&& *cn
? " " : "",
2080 mailto
? mailto
: _("Unknown address"));
2081 rv
->attendee
[i
] = cpystr(tmp_20k_buf
);
2083 rv
->attendee
[i
] = NULL
;
2084 } /* end of ATTENDEES */
2086 if((icl
= (ICLINE_S
*) vevent
->prop
[EvDescription
]) != NULL
){
2087 char *s
, *t
, *u
, *v
;
2090 if(icl
->value
== NULL
){
2091 free_vevent_summary(&rv
);
2095 v
= cpystr(icl
->value
); /* process a copy of icl->value */
2097 for(i
= 1, escaped
= 0, s
= v
; s
&& *s
; s
++){
2098 if(*s
== '\\'){ escaped
= 1; continue; }
2100 if(!(*s
== '\\' || *s
== ',' || *s
== 'n' || *s
== 'N' || *s
== ';')){
2101 free_vevent_summary(&rv
);
2102 fs_give((void **)&v
);
2108 if(*s
== ',') i
++; /* a non-scaped comma is a new value for text */
2111 rv
->description
= fs_get((i
+1)*sizeof(char *));
2113 for (s
= t
= u
= v
, escaped
= 0; *t
!= '\0'; t
++){
2114 if(*t
== '\\'){ escaped
= 1; continue; }
2126 default: free_vevent_summary(&rv
);
2127 fs_give((void **)&v
);
2135 rv
->description
[i
++] = cpystr(s
);
2141 rv
->description
[i
++] = cpystr(s
);
2142 rv
->description
[i
] = NULL
;
2143 fs_give((void **)&v
);
2144 } /* end of if(description) */
2150 free_vevent_summary(VEVENT_SUMMARY_S
**vesy
)
2153 if(vesy
== NULL
|| *vesy
== NULL
) return;
2155 if((*vesy
)->class) fs_give((void **)&(*vesy
)->class);
2156 if((*vesy
)->summary
) fs_give((void **)&(*vesy
)->summary
);
2157 if((*vesy
)->sender
) fs_give((void **)&(*vesy
)->sender
);
2158 if((*vesy
)->organizer
) fs_give((void **)&(*vesy
)->organizer
);
2159 if((*vesy
)->location
) fs_give((void **)&(*vesy
)->location
);
2160 if((*vesy
)->evstart
) fs_give((void **)&(*vesy
)->evstart
);
2161 if((*vesy
)->evend
) fs_give((void **)&(*vesy
)->evend
);
2162 if((*vesy
)->duration
){
2163 for(i
= 0; (*vesy
)->duration
[i
] != NULL
; i
++)
2164 fs_give((void **) &(*vesy
)->duration
[i
]);
2165 fs_give((void **) (*vesy
)->duration
);
2167 if((*vesy
)->attendee
){
2168 for(i
= 0; (*vesy
)->attendee
[i
] != NULL
; i
++)
2169 fs_give((void **) &(*vesy
)->attendee
[i
]);
2170 fs_give((void **) (*vesy
)->attendee
);
2172 if((*vesy
)->description
){
2173 for(i
= 0; (*vesy
)->description
[i
] != NULL
; i
++)
2174 fs_give((void **) &(*vesy
)->description
[i
]);
2175 fs_give((void **) (*vesy
)->description
);
2177 fs_give((void **) vesy
);
2181 void ical_print_line(ICLINE_S icl
)
2183 ICAL_PARAMETER_S
*p
;
2184 printf("token=%s, ", icl
.token
);
2185 for(p
= icl
.param
; p
!= NULL
; p
= p
->next
){
2186 if(p
->name
) printf("param->name=%s, ", p
->name
);
2187 if(p
->value
) printf("param->value=%s, ", p
->value
);
2189 printf("value=%s", icl
.value
);
2193 #define CRLFCOUNT 100
2195 char *lf2crlf(char *text
)
2200 if(text
== NULL
|| *text
== '\0')
2206 for(i
= 0, s
= text
; *s
;){
2209 fs_resize((void *)&rv
, len
);
2216 fs_give((void **)&text
);
2222 int main (int argc
, char *argv
[])
2228 fprintf(stderr
, "Only give one argument: File name to read\n");
2232 if(readfile(argv
[1], &text
, NULL
) < 0){
2233 fprintf(stderr
, "Can not read %s succesfully\n", argv
[1]);
2237 text
= lf2crlf(text
);
2238 vcal
= ical_parse_text(text
);
2240 ical_free_vcalendar((void **)&vcal
);
2245 #endif /* STANDALONE */