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 **);
40 char *ical_decode(char *, unsigned short);
43 void *ical_parse_vcalendar(char **);
44 void *ical_parse_vevent(char **);
45 void *ical_parse_vtodo(char **);
46 void *ical_parse_vjournal(char **);
47 void *ical_parse_vfreebusy(char **);
48 void *ical_parse_vtimezone(char **);
49 void *ical_parse_valarm(char **);
50 void *ical_parse_timezone(char **);
51 ICAL_S
*ical_parse_unknown_comp(char **, int);
52 ICAL_S
*ical_parse_generic_comp(char **, int);
55 void ical_free_vevent(void **);
56 void ical_free_vtodo(void **);
57 void ical_free_vjournal(void **);
58 void ical_free_vfreebusy(void **);
59 void ical_free_vtimezone(void **);
60 void ical_free_timezone(void **);
61 void ical_free_valarm(void **);
62 void ical_free_unknown_comp(ICAL_S
**);
64 /* parse properties */
65 void ical_cline_from_token(void **, char **, char *);
66 void ical_gencline_from_token(void **, char **, char *);
68 void ical_parse_rrule(RRULE_S
**, char **);
69 void ical_parse_time(struct tm
*, char **, char *);
70 void ical_parse_offset(int *, char **, char *);
72 void ical_parse_freq(Freq_value
*, char *);
73 void ical_parse_weekday_list(BYWKDY_S
**, char *);
74 void ical_parse_number_list(BYWKDY_S
**, char *);
75 void ical_parse_interval(unsigned long *, char *);
77 int ical_get_number_value(char *, int, int);
78 void ical_set_date(ICLINE_S
*, VTIMEZONE_S
*);
79 void ical_set_date_vevent(void *, void *);
82 void ical_free_prop(void **, ICAL_PROP_S
*);
83 void ical_free_null(void **);
84 void ical_free_cline(void **);
85 void ical_free_param(ICAL_PARAMETER_S
**);
86 void ical_free_gencline(void **);
87 void ical_free_rrule(void **);
88 void ical_free_weekday_list(void **);
91 struct tm day_zero
; /* date for january 1, 1601 */
92 int month_len
[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
94 #define UTF8_COMPLETE (1)
98 unsigned long ical_buf_len
;
101 /* parsing structures */
103 /* this is the list of V-components to a Calendar from RFC 5545 */
104 ICAL_COMP_S ical_comp
[] = {
105 {"VCALENDAR", 9, VCalendar
, ical_parse_vcalendar
, ical_free_vcalendar
},
106 {"VTIMEZONE", 9, VTimeZone
, ical_parse_vtimezone
, ical_free_vtimezone
},
107 {"VEVENT", 6, VEvent
, ical_parse_vevent
, ical_free_vevent
},
108 {"VTODO", 5, VTodo
, ical_parse_vtodo
, ical_free_vtodo
},
109 {"VJOURNAL", 8, VJournal
, ical_parse_vjournal
, ical_free_vjournal
},
110 {"VALARM", 6, VAlarm
, ical_parse_valarm
, ical_free_valarm
},
111 {"VFREEBUSY", 9, VFreeBusy
, ical_parse_vfreebusy
, ical_free_vfreebusy
},
112 {NULL
, 0, VUnknown
, NULL
, 0}
115 /* array for properties */
116 ICAL_PROP_S rrule_prop
[] = {
117 {"FREQ", 4, RRFreq
, ical_parse_freq
, ical_free_null
},
118 {"UNTIL", 5, RRUntil
, ical_parse_freq
, 0},
119 {"COUNT", 5, RRCount
, ical_cline_from_token
, ical_free_cline
},
120 {"INTERVAL", 8, RRInterval
, ical_parse_interval
, ical_free_null
},
121 {"BYSECOND", 8, RRBysecond
, ical_parse_number_list
, ical_free_weekday_list
},
122 {"BYMINUTE", 8, RRByminute
, ical_parse_number_list
, ical_free_weekday_list
},
123 {"BYHOUR", 6, RRByhour
, ical_parse_number_list
, ical_free_weekday_list
},
124 {"BYDAY", 5, RRByday
, ical_parse_weekday_list
,ical_free_weekday_list
},
125 {"BYWEEKNO", 8, RRByweekno
, 0, 0},
126 {"BYMONTH", 7, RRBymonth
, ical_parse_number_list
, ical_free_weekday_list
},
127 {"BYSETPOS", 8, RRBysetpos
, 0, 0},
128 {"BYWKST", 6, RRWkst
, 0, 0},
130 10, RRBymonthday
, 0, 0},
131 {"BYYEARDAY", 9, RRByyearday
, 0, 0},
132 {NULL
, 0, RRUnknown
, 0, 0}
135 ICAL_PROP_S event_prop
[] = {
136 {"DTSTAMP", 7, EvDtstamp
, ical_cline_from_token
, ical_free_cline
},
137 {"UID", 3, EvUid
, ical_cline_from_token
, ical_free_cline
},
138 {"DTSTART", 7, EvDtstart
, ical_cline_from_token
, ical_free_cline
},
139 {"CLASS", 5, EvClass
, ical_cline_from_token
, ical_free_cline
},
140 {"CREATED", 7, EvCreated
, ical_cline_from_token
, ical_free_cline
},
141 {"DESCRIPTION", 11, EvDescription
, ical_cline_from_token
, ical_free_cline
},
142 {"GEO", 3, EvGeo
, ical_cline_from_token
, ical_free_cline
},
143 {"LASTMOD", 7, EvLastMod
, ical_cline_from_token
, ical_free_cline
},
144 {"LOCATION", 8, EvLocation
, ical_cline_from_token
, ical_free_cline
},
145 {"ORGANIZER", 9, EvOrganizer
, ical_cline_from_token
, ical_free_cline
},
146 {"PRIORITY", 8, EvPriority
, ical_cline_from_token
, ical_free_cline
},
147 {"SEQUENCE", 8, EvSequence
, ical_cline_from_token
, ical_free_cline
},
148 {"STATUS", 6, EvStatus
, ical_cline_from_token
, ical_free_cline
},
149 {"SUMMARY", 7, EvSummary
, ical_cline_from_token
, ical_free_cline
},
150 {"TRANSP", 6, EvTransp
, ical_cline_from_token
, ical_free_cline
},
151 {"URL", 3, EvUrl
, ical_cline_from_token
, ical_free_cline
},
152 {"RECURRENCE-ID", 13, EvRecurrence
, ical_cline_from_token
, ical_free_cline
},
153 {"RRULE", 5, EvRrule
, ical_parse_rrule
, ical_free_rrule
},
154 {"DTEND", 5, EvDtend
, ical_cline_from_token
, ical_free_cline
},
155 {"DURATION", 8, EvDuration
, ical_cline_from_token
, ical_free_cline
},
156 {"ATTACH", 6, EvAttach
, ical_gencline_from_token
, ical_free_gencline
},
157 {"ATTENDEE", 8, EvAttendee
, ical_gencline_from_token
, ical_free_gencline
},
158 {"CATEGORIES", 10, EvCategories
, ical_gencline_from_token
, ical_free_gencline
},
159 {"COMMENT", 7, EvComment
, ical_gencline_from_token
, ical_free_gencline
},
160 {"CONTACT", 7, EvContact
, ical_gencline_from_token
, ical_free_gencline
},
161 {"EXDATE", 6, EvExdate
, ical_gencline_from_token
, ical_free_gencline
},
162 {"RSTATUS", 7, EvRstatus
, ical_gencline_from_token
, ical_free_gencline
},
163 {"RELATED", 7, EvRelated
, ical_gencline_from_token
, ical_free_gencline
},
164 {"RESOURCES", 9, EvResources
, ical_gencline_from_token
, ical_free_gencline
},
165 {"RDATE", 5, EvRdate
, ical_gencline_from_token
, ical_free_gencline
},
166 {NULL
, 0, EvUnknown
, 0, 0}
169 ICAL_PROP_S tz_comp
[] = {
170 {"TZID", 4, TZCid
, ical_cline_from_token
, ical_free_cline
},
171 {"LAST-MODIFIED", 13, TZCLastMod
, ical_cline_from_token
, ical_free_cline
},
172 {"TZURL", 5, TZCUrl
, ical_cline_from_token
, ical_free_cline
},
173 {NULL
, 0, TZCUnknown
, 0, 0}
176 ICAL_PROP_S tz_prop
[] = {
177 {"DTSTART", 7, TZPDtstart
, ical_parse_time
, 0},
178 {"TZOFFSETTO", 10, TZPOffsetto
, ical_parse_offset
, 0},
179 {"TZOFFSETFROM", 12, TZPOffsetfrom
, ical_parse_offset
, 0},
180 {"RRULE", 5, TZPRrule
, ical_parse_rrule
, ical_free_rrule
},
181 {"COMMENT", 7, TZPComment
, ical_gencline_from_token
, ical_free_gencline
},
182 {"RDATE", 5, TZPRdate
, ical_gencline_from_token
, ical_free_gencline
},
183 {"TZNAME", 6, TZPTzname
, ical_gencline_from_token
, ical_free_gencline
},
184 {NULL
, 0, TZPUnknown
, 0, 0}
187 ICAL_PROP_S alarm_prop
[] = {
188 {"ACTION", 6, AlAction
, ical_cline_from_token
, ical_free_cline
},
189 {"TRIGGER", 7, AlTrigger
, ical_cline_from_token
, ical_free_cline
},
190 {"DURATION", 8, AlDuration
, ical_cline_from_token
, ical_free_cline
},
191 {"REPEAT", 6, AlRepeat
, ical_cline_from_token
, ical_free_cline
},
192 {"DESCRIPTION", 11, AlDescription
, ical_cline_from_token
, ical_free_cline
},
193 {"SUMMARY", 7, AlSummary
, ical_cline_from_token
, ical_free_cline
},
194 {"ATTACH", 6, AlAttach
, ical_gencline_from_token
, ical_free_gencline
},
195 {"ATTENDEE", 8, AlAttendee
, ical_gencline_from_token
, ical_free_gencline
},
196 {NULL
, 0, AlUnknown
, 0, 0}
199 /* some useful macros for character analysis */
201 #define ical_wspace(X) \
202 ((X) == ' ' || (X) == '\t')
204 #define ical_name_allowed_char(X) \
205 (((X) >= 'A' && (X) <= 'Z') || \
206 ((X) >= 'a' && (X) <= 'z') || \
209 #define ical_control(X) \
210 (((X) >= 0x00 && (X) <= 0x08) || \
211 ((X) >= 0x0A && (X) <= 0x1F) || \
214 #define ical_safe_char(X) \
215 (ical_non_ascii_valid(X) \
218 || ((X) >= 0x23 && (X) <= 0x2B) \
219 || ((X) >= 0x2D && (X) <= 0x39) \
220 || ((X) >= 0x3C && (X) <= 0x7E))
222 #define ical_qsafe_char(X) \
223 (ical_non_ascii_valid((X)) \
226 || ((X) >= 0x23 && (X) <= 0x7E))
228 #define ical_value_char(X) \
229 (ical_non_ascii_valid(X) \
231 || ((X) >= 0x21 && (X) <= 0x7E))
233 /* Finally, here begins the code. */
236 ical_decode(char *text
, unsigned short encoding
)
239 unsigned long callen
;
240 if(encoding
== ENCQUOTEDPRINTABLE
){
241 t
= rfc822_qprint ((unsigned char *) text
,strlen(text
),&callen
);
243 strncpy(text
, t
, strlen(t
));
244 fs_give((void **) &t
);
253 -1 - if an error occured
254 Args: a pointer to the text. If there is an error, the text is not modified.
257 ical_remove_escapes(char **textp
)
263 if(textp
== NULL
) return 0;
265 t
= cpystr(*textp
); /* work on a copy of the text */
266 /* the variable text below points to the beginning of the filtered text */
267 for (text
= s
= t
, escaped
= 0; rv
== 0 && *s
!= '\0'; s
++){
268 if(*s
== '\\' && escaped
== 0){
291 *t
= '\0'; /* tie off filtered text */
292 t
= text
; /* reset t to the beginning */
294 fs_give((void **) &t
);
296 strncpy(*textp
, t
, strlen(t
)); /* overwrite given text with filtered text */
297 (*textp
)[strlen(t
)] = '\0';
302 void ical_debug(char *fcn
, char *text
)
305 strncpy(piece
, text
, 49);
306 dprint((9, "%s: %s", fcn
, piece
));
310 *** FREE MEMORY FUNCTIONS
314 ical_free_param(ICAL_PARAMETER_S
**param
)
316 if(param
== NULL
|| *param
== NULL
)
319 if((*param
)->name
) fs_give((void **) &(*param
)->name
);
320 if((*param
)->value
) fs_give((void **) &(*param
)->value
);
321 if((*param
)->next
) ical_free_param(&(*param
)->next
);
322 fs_give((void **)param
);
326 ical_free_null(void **n
)
328 if(n
!= NULL
) *n
= NULL
;
332 ical_free_cline(void **icv
)
334 ICLINE_S
**ic
= (ICLINE_S
**) icv
;
336 if(ic
== NULL
|| *ic
== NULL
)
339 if((*ic
)->token
) fs_give((void **) &(*ic
)->token
);
340 if((*ic
)->param
) ical_free_param(&(*ic
)->param
);
341 if((*ic
)->value
) fs_give((void **) &(*ic
)->value
);
346 ical_free_gencline(void **giclpv
)
348 GEN_ICLINE_S
**giclp
= (GEN_ICLINE_S
**) giclpv
;
350 if(giclp
== NULL
|| *giclp
== NULL
) return;
352 if((*giclp
)->cline
) ical_free_cline((void **) &(*giclp
)->cline
);
353 if((*giclp
)->next
) ical_free_gencline((void **) &(*giclp
)->next
);
357 ical_free_vcalendar(void **vcalpv
)
359 VCALENDAR_S
**vcalp
= (VCALENDAR_S
**)vcalpv
;
361 if(vcalp
== NULL
|| *vcalp
== NULL
) return;
363 if((*vcalp
)->prodid
) ical_free_cline((void **) &(*vcalp
)->prodid
);
364 if((*vcalp
)->version
) ical_free_cline((void **) &(*vcalp
)->version
);
365 if((*vcalp
)->calscale
) ical_free_cline((void **) &(*vcalp
)->calscale
);
366 if((*vcalp
)->method
) ical_free_cline((void **) &(*vcalp
)->method
);
367 if((*vcalp
)->uk_prop
) ical_free_gencline((void **) &(*vcalp
)->uk_prop
);
370 for(i
= 0; i
< VUnknown
; i
++)
371 if((*vcalp
)->comp
[i
]) (ical_comp
[i
].give
)(&(*vcalp
)->comp
[i
]);
372 fs_give((*vcalp
)->comp
);
374 if((*vcalp
)->uk_comp
) ical_free_unknown_comp(&(*vcalp
)->uk_comp
);
379 ical_free_vevent(void **veventpv
)
381 VEVENT_S
**veventp
= (VEVENT_S
**) veventpv
;
383 if(veventp
== NULL
|| *veventp
== NULL
) return;
385 ical_free_prop((*veventp
)->prop
, event_prop
);
386 if((*veventp
)->uk_prop
) ical_free_gencline((void **) &(*veventp
)->uk_prop
);
387 if((*veventp
)->valarm
) ical_free_valarm((void **) &(*veventp
)->valarm
);
392 ical_free_rrule(void **rrulepv
)
394 RRULE_S
**rrulep
= (RRULE_S
**) rrulepv
;
396 if(rrulep
&& *rrulep
){
397 ical_free_prop((*rrulep
)->prop
, rrule_prop
);
398 ical_free_param(&(*rrulep
)->param
);
404 ical_free_weekday_list(void **wkdylv
)
406 BYWKDY_S
**wkdyl
= (BYWKDY_S
**) wkdylv
;
408 if(wkdyl
== NULL
) return;
411 ical_free_weekday_list((void **) &(*wkdyl
)->next
);
418 ical_free_vtodo(void **vtodopv
)
423 ical_free_vjournal(void **vjournalpv
)
428 ical_free_vfreebusy(void **vfbpv
)
433 ical_free_prop(void **propv
, ICAL_PROP_S
*aux_comp
)
437 if(propv
== NULL
) return;
439 for(i
= 0; aux_comp
[i
].prop
!= NULL
; i
++)
441 for(j
= 0; aux_comp
[j
].prop
!= NULL
&& aux_comp
[j
].pos
!= i
; j
++);
442 if(aux_comp
[j
].give
) (aux_comp
[j
].give
)(&propv
[i
]);
449 ical_free_vtimezone(void **vtzpv
)
451 VTIMEZONE_S
**vtzp
= (VTIMEZONE_S
**) vtzpv
;
454 if(vtzp
== NULL
|| *vtzp
== NULL
) return;
456 ical_free_prop((*vtzp
)->prop
, tz_comp
);
458 if((*vtzp
)->uk_prop
) ical_free_gencline((void **) &(*vtzp
)->uk_prop
);
459 if((*vtzp
)->standardc
) ical_free_timezone((void **) &(*vtzp
)->standardc
);
460 if((*vtzp
)->daylightc
) ical_free_timezone((void **) &(*vtzp
)->daylightc
);
465 ical_free_timezone(void **tzpv
)
467 ICAL_TZPROP_S
**tzp
= (ICAL_TZPROP_S
**) tzpv
;
469 if(tzp
== NULL
|| *tzp
== NULL
) return;
471 ical_free_prop((*tzp
)->prop
, tz_prop
);
472 if((*tzp
)->uk_prop
) ical_free_gencline((void **) &(*tzp
)->uk_prop
);
473 if((*tzp
)->next
) ical_free_timezone((void **) &(*tzp
)->next
);
477 void ical_free_valarm(void **valarmpv
)
482 ical_free_unknown_comp(ICAL_S
**icalp
)
485 if(icalp
== NULL
|| *icalp
== NULL
) return;
486 for(i
= 0; ical_comp
[i
].comp
&& strucmp((*icalp
)->comp
,ical_comp
[i
].comp
); i
++);
487 if(ical_comp
[i
].give
)
488 (ical_comp
[i
].give
)(&(*icalp
)->value
);
490 ical_free_gencline((void **) &(*icalp
)->value
);
491 fs_give((void **)&(*icalp
)->comp
);
492 ical_free_unknown_comp(&(*icalp
)->next
);
493 ical_free_unknown_comp(&(*icalp
)->branch
);
494 fs_give((void **)icalp
);
497 char *ical_unfold_line(char *line
)
504 for(i
= 0, j
= 0; line
[j
] != '\0';)
506 case '\r': if(line
[j
+1] == '\n' && ical_wspace(line
[j
+2])){
507 j
+= 3; /* get past white space */
510 default : line
[i
++] = line
[j
++];
517 ical_get_parameter(char **line
)
519 ICAL_PARAMETER_S
*param
= NULL
;
522 if(line
== NULL
|| *line
== NULL
)
525 for(s
= *line
; s
&& *s
&& ical_name_allowed_char(*s
) ; s
++);
531 param
= fs_get(sizeof(ICAL_PARAMETER_S
));
532 memset((void *)param
, 0, sizeof(ICAL_PARAMETER_S
));
534 param
->name
= cpystr(*line
);
536 *line
= s
+1; /* step over '=' */
537 quoted
= **line
== '"' ? 1 : 0;
539 for(s
= ++*line
; s
&& *s
&& ical_qsafe_char((unsigned char) *s
); s
++);
540 if(*s
!= '"'){ /* error, do not parse this line */
541 ical_free_param(¶m
);
542 *line
= strchr(s
, ':'); /* reset line to closest ':' */
547 for(s
= *line
; s
&& *s
&& (ical_safe_char((unsigned char) *s
)); s
++);
550 param
->value
= cpystr(*line
);
551 *s
= c
; /* restore character */
552 *line
= quoted
? s
+ 1 : s
;
556 param
->next
= ical_get_parameter(line
);
562 char *ical_get_value(char **line
)
566 if(line
== NULL
|| *line
== NULL
)
569 for (s
= *line
; *s
&& ical_value_char((unsigned char) *s
); s
++);
578 s
= strchr(*line
, '\r');
586 ical_parameter_cpy(ICAL_PARAMETER_S
*param
)
588 ICAL_PARAMETER_S
*rv
;
590 if(param
== NULL
) return NULL
;
592 rv
= fs_get(sizeof(ICAL_PARAMETER_S
));
593 memset((void *)rv
, 0, sizeof(ICAL_PARAMETER_S
));
595 if(param
->name
) rv
->name
= cpystr(param
->name
);
596 if(param
->value
) rv
->value
= cpystr(param
->value
);
597 if(param
->next
) rv
->next
= ical_parameter_cpy(param
->next
);
603 ical_cline_cpy(ICLINE_S
*icl
)
610 rv
= fs_get(sizeof(ICLINE_S
));
611 memset((void *)rv
, 0, sizeof(ICLINE_S
));
613 if(icl
->token
) rv
->token
= cpystr(icl
->token
);
614 if(icl
->param
) rv
->param
= ical_parameter_cpy(icl
->param
);
615 if(icl
->value
) rv
->value
= cpystr(icl
->value
);
620 /* Given a \r\n-ending line (called *text), isolate the ocurrence
621 * of the token in that line.
622 * Return the token, and modify the pointer to *text to point to the
623 * end of the token. Modify sep to contain the character following
625 * ical-line = token ':'/';' rest of the line\r\n
626 * on error return null, and set *text to the next line, if possible.
629 ical_isolate_token(char **text
, char *sep
)
633 for(t
= s
= *text
; *t
&& ical_name_allowed_char(*s
); s
++);
634 /* only followed by parameter or value */
635 if(*s
== ':' || *s
== ';'){
637 *s
= '\0'; /* isolate token at pointer s */
640 else{ /* bad data - bail out of here */
642 if(*s
== '\0' || (s
= strstr(s
, "\r\n")) == NULL
)
644 else /* move to next line */
652 ical_parse_text(char *text
)
655 VCALENDAR_S
*vcal
= NULL
;
657 ical_debug("ical_parse_text", text
);
660 text
= ical_unfold_line(text
);
661 for(s
= text
; s
&& *s
!= '\0'; s
++){
662 if(*s
!= 'B' && *s
!= 'b')
664 if(!struncmp(s
+1, "EGIN:VCALENDAR\r\n", 16)){
665 s
+= 17; /* 17 = strlen("BEGIN:VCALENDAR\r\n") */
666 vcal
= (VCALENDAR_S
*) ical_parse_vcalendar(&s
);
674 ical_parse_time(struct tm
*ic_date
, char **text
, char *token
)
678 icl
= ical_parse_line(text
, token
);
679 ical_parse_date(icl
->value
, ic_date
);
680 ical_free_cline((void **) &icl
);
684 ical_parse_interval(unsigned long *longv
, char *value
)
686 *longv
= atoi(value
);
691 ical_parse_offset(int *offsetv
, char **text
, char *token
)
697 icl
= ical_parse_line(text
, token
);
699 if(*icl
->value
== '+' || *icl
->value
== '-')
700 value
= icl
->value
+ 1;
704 h
= ical_get_number_value(value
, 0, 2);
705 m
= ical_get_number_value(value
, 2, 4);
707 offset
= 60*(60*h
+ m
);
708 if(*icl
->value
== '-')
712 ical_free_cline((void **) &icl
);
716 ical_cline_from_token(void **iclv
, char **text
, char *token
)
718 ICLINE_S
**icl
= (ICLINE_S
**)iclv
;
721 *icl
= ical_parse_line(text
, token
);
723 ICLINE_S
*ic
= ical_parse_line(text
, token
);
724 ical_free_cline((void **)&ic
);
729 ical_gencline_from_token(void **giclv
, char **text
, char *token
)
733 if(!struncmp(*text
, token
, strlen(token
))){
734 gicl
= fs_get(sizeof(GEN_ICLINE_S
));
735 memset((void *) gicl
, 0, sizeof(GEN_ICLINE_S
));
736 ical_cline_from_token((void **) &gicl
->cline
, text
, token
);
737 ical_gencline_from_token((void **) &gicl
->next
, text
, token
);
738 *giclv
= (void *) gicl
;
743 *** PARSE COMPONENT FUNCTIONS
747 ical_parse_vcalendar(char **text
)
754 dprint((9, "ical_parse_vcalendar:\n"));
755 ical_debug("ical_parse_vcalendar", *text
);
757 vcal
= fs_get(sizeof(VCALENDAR_S
));
758 memset((void *)vcal
, 0, sizeof(VCALENDAR_S
));
760 /* s must always point the the beginning of a line */
761 for(s
= *text
; s
&& *s
!= '\0';){
763 s
= ical_isolate_token(&t
, &c
);
770 *t
= c
; /* restore character */
771 if(s
){ /* figure out the token */
772 int ukn
= 0; /* unknown token */
776 case 'b': if(!struncmp(s
+1, "EGIN", 4)){
777 s
+= 6; /* 6 = strlen("BEGIN:") */
778 for(i
= 0; ical_comp
[i
].comp
779 && (struncmp(s
, ical_comp
[i
].comp
, ical_comp
[i
].len
)
780 || struncmp(s
+ ical_comp
[i
].len
, "\r\n", 2)); i
++);
782 if(ical_comp
[i
].parse
){
783 s
+= ical_comp
[i
].len
+ 2;
784 v
= (ical_comp
[i
].parse
)(&s
);
785 if(vcal
->comp
== NULL
){
786 vcal
->comp
= fs_get(VUnknown
*sizeof(void *));
787 memset((void *) vcal
->comp
, 0, VUnknown
*sizeof(void *));
790 if(vcal
->comp
[ical_comp
[i
].pos
] == NULL
)
791 vcal
->comp
[ical_comp
[i
].pos
] = v
;
793 (ical_comp
[i
].give
)(&v
);
795 v
= (void *) ical_parse_unknown_comp(&s
, 0);
796 if(vcal
->uk_comp
== NULL
)
797 vcal
->uk_comp
= (ICAL_S
*) v
;
800 for(ic
= vcal
->uk_comp
; ic
&& ic
->branch
; ic
= ic
->branch
);
801 ic
->branch
= (ICAL_S
*) v
;
808 case 'c': if(!struncmp(s
+1, "ALSCALE", 7))
809 ical_cline_from_token((void **) &vcal
->calscale
, &s
, "CALSCALE");
814 case 'e': if(!struncmp(s
+1, "ND", 2)){
816 s
+= 4; /* 4 = strlen("END:") */
817 if(!struncmp(s
, "VCALENDAR\r\n", 11)){
818 *text
= s
+ 11; /* 11 = strlen("VCALENDAR\r\n") */
819 return (void *) vcal
;
821 // else ukn++; FIX THIS, this is not quite right
826 case 'm': if(!struncmp(s
+1, "ETHOD", 5))
827 ical_cline_from_token((void **) &vcal
->method
, &s
, "METHOD");
832 case 'p': if(!struncmp(s
+1, "RODID", 5))
833 ical_cline_from_token((void **) &vcal
->prodid
, &s
, "PRODID");
838 case 'v': if(!struncmp(s
+1, "ERSION", 6)){
839 ical_cline_from_token((void **) &vcal
->version
, &s
, "VERSION");
845 } /* end of switch(*s) */
847 if(ical_buf_len
< t
- s
){
848 fs_resize((void **)&ical_buf
, t
-s
+1);
854 if(vcal
->uk_prop
== NULL
){
855 vcal
->uk_prop
= fs_get(sizeof(GEN_ICLINE_S
));
856 memset((void *)vcal
->uk_prop
, 0, sizeof(GEN_ICLINE_S
));
857 vcal
->uk_prop
->cline
= ical_parse_line(&s
, ical_buf
);
861 for (gcl
= vcal
->uk_prop
; gcl
&& gcl
->next
; gcl
= gcl
->next
);
862 gcl
->next
= fs_get(sizeof(GEN_ICLINE_S
));
863 memset((void *)gcl
->next
, 0, sizeof(GEN_ICLINE_S
));
864 gcl
->next
->cline
= ical_parse_line(&s
, ical_buf
);
872 /* ok, we have parsed the vcalendar, now parse some special properties */
873 /* start by parsing dates */
874 ical_set_date_vevent(vcal
->comp
[VEvent
], vcal
->comp
[VTimeZone
]);
875 return (void *) vcal
;
879 ical_parse_vevent(char **text
)
885 ical_debug("ical_parse_vevent", *text
);
886 vevent
= fs_get(sizeof(VEVENT_S
));
887 memset((void *)vevent
, 0, sizeof(VEVENT_S
));
889 /* s must always point the the beginning of a line */
890 for(s
= *text
; s
&& *s
!= '\0';){
892 s
= ical_isolate_token(&t
, &c
);
898 *t
= c
; /* restore separator */
900 if(s
){ /* figure out the token */
901 int ukn
= 0; /* unknown token */
902 if(!struncmp(s
, "BEGIN", 5)){
903 s
+= 6; /* 6 = strlen("BEGIN:") */
904 if(!struncmp(s
, "VALARM\r\n", 8)){
905 s
+= 8; /* 8 = strlen("VALARM\r\n"); */
906 if(vevent
->valarm
== NULL
)
907 vevent
->valarm
= ical_parse_valarm(&s
);
910 for(valrm
= vevent
->valarm
; valrm
&& valrm
->next
;
911 valrm
= valrm
->next
);
912 valrm
->next
= ical_parse_valarm(&s
);
915 ICAL_S
*uk_comp
= ical_parse_unknown_comp(&s
, 0);
916 ical_free_unknown_comp(&uk_comp
);
918 } else if(!struncmp(s
, "END", t
-s
-1)){
919 s
+= 4; /* 4 = strlen("END:") */
920 if(!struncmp(s
, "VEVENT\r\n",8)){
921 *text
= s
+ 8; /* 8 = strlen("VCALENDAR\r\n") */
922 return (void *) vevent
;
924 } else{ Event_prop i
;
925 for(i
= 0; i
< EvUnknown
; i
++)
926 if(!struncmp(s
, event_prop
[i
].prop
, t
-s
))
928 if(event_prop
[i
].parse
){
929 if(vevent
->prop
== NULL
){
930 vevent
->prop
= fs_get(EvUnknown
*sizeof(void *));
931 memset((void *)vevent
->prop
, 0, EvUnknown
*sizeof(void *));
933 (event_prop
[i
].parse
)(&vevent
->prop
[event_prop
[i
].pos
], &s
, event_prop
[i
].prop
);
940 if(ical_buf_len
< t
- s
){
941 fs_resize((void **)&ical_buf
, t
-s
+1);
947 if(vevent
->uk_prop
== NULL
){
948 vevent
->uk_prop
= fs_get(sizeof(GEN_ICLINE_S
));
949 memset((void *)vevent
->uk_prop
, 0, sizeof(GEN_ICLINE_S
));
950 vevent
->uk_prop
->cline
= ical_parse_line(&s
, ical_buf
);
954 for (gcl
= vevent
->uk_prop
; gcl
&& gcl
->next
; gcl
= gcl
->next
);
955 gcl
->next
= fs_get(sizeof(GEN_ICLINE_S
));
956 memset((void *)gcl
->next
, 0, sizeof(GEN_ICLINE_S
));
957 gcl
->next
->cline
= ical_parse_line(&s
, ical_buf
);
964 return (void *) vevent
;
968 ical_parse_vtimezone(char **text
)
975 ical_debug("ical_parse_vtimezone", *text
);
976 vtz
= fs_get(sizeof(VTIMEZONE_S
));
977 memset((void *)vtz
, 0, sizeof(VTIMEZONE_S
));
979 /* s must always point the the beginning of a line */
980 for(s
= *text
; s
&& *s
!= '\0';){
982 s
= ical_isolate_token(&t
, &c
);
988 *t
= c
; /* restore separator */
990 if(s
){ /* figure out the token */
991 int ukn
= 0; /* unknown token */
992 if(!struncmp(s
, "BEGIN", 5)){
993 s
+= 6; /* 6 = strlen("BEGIN:") */
994 if(!struncmp(s
, "STANDARD\r\n", 10)){
995 s
+= 10; /* 10 = strlen("STANDARD\r\n"); */
996 v
= ical_parse_timezone(&s
);
997 if(vtz
->standardc
== NULL
)
998 vtz
->standardc
= (ICAL_TZPROP_S
*) v
;
1001 for(dl
= vtz
->standardc
; dl
&& dl
->next
; dl
= dl
->next
);
1002 dl
->next
= (ICAL_TZPROP_S
*) v
;
1004 } else if(!struncmp(s
, "DAYLIGHT\r\n", 10)){
1005 s
+= 10; /* 10 = strlen("DAYLIGHT\r\n"); */
1006 v
= ical_parse_timezone(&s
);
1007 if(vtz
->daylightc
== NULL
)
1008 vtz
->daylightc
= (ICAL_TZPROP_S
*) v
;
1011 for(dl
= vtz
->daylightc
; dl
&& dl
->next
; dl
= dl
->next
);
1012 dl
->next
= (ICAL_TZPROP_S
*) v
;
1015 ICAL_S
*uk_comp
= ical_parse_unknown_comp(&s
, 0);
1016 ical_free_unknown_comp(&uk_comp
);
1018 } else if(!struncmp(s
, "END", t
-s
-1)){
1019 s
+= 4; /* 4 = strlen("END:") */
1020 if(!struncmp(s
, "VTIMEZONE\r\n",11)){
1021 *text
= s
+ 11; /* 11 = strlen("VTIMEZONE\r\n") */
1022 return (void *) vtz
;
1025 for(i
= 0; i
< TZCUnknown
; i
++)
1026 if(!struncmp(s
, tz_comp
[i
].prop
, t
-s
))
1028 if(tz_comp
[i
].parse
){
1029 if(vtz
->prop
== NULL
){
1030 vtz
->prop
= fs_get(TZCUnknown
*sizeof(void *));
1031 memset((void *)vtz
->prop
, 0, TZCUnknown
*sizeof(void *));
1033 (tz_comp
[i
].parse
)(&vtz
->prop
[tz_comp
[i
].pos
], &s
, tz_comp
[i
].prop
);
1040 if(ical_buf_len
< t
- s
){
1041 fs_resize((void **)&ical_buf
, t
-s
+1);
1045 strcpy(ical_buf
, s
);
1047 if(vtz
->uk_prop
== NULL
){
1048 vtz
->uk_prop
= fs_get(sizeof(GEN_ICLINE_S
));
1049 memset((void *)vtz
->uk_prop
, 0, sizeof(GEN_ICLINE_S
));
1050 vtz
->uk_prop
->cline
= ical_parse_line(&s
, ical_buf
);
1054 for (gcl
= vtz
->uk_prop
; gcl
&& gcl
->next
; gcl
= gcl
->next
);
1055 gcl
->next
= fs_get(sizeof(GEN_ICLINE_S
));
1056 memset((void *)gcl
->next
, 0, sizeof(GEN_ICLINE_S
));
1057 gcl
->next
->cline
= ical_parse_line(&s
, ical_buf
);
1060 } /* end of if(s) */
1064 return (void *) vtz
;
1068 ical_parse_timezone(char **text
)
1072 ICAL_TZPROP_S
*tzprop
;
1074 ical_debug("ical_parse_timezone", *text
);
1075 tzprop
= fs_get(sizeof(ICAL_TZPROP_S
));
1076 memset((void *)tzprop
, 0, sizeof(ICAL_TZPROP_S
));
1078 /* s must always point the the beginning of a line */
1079 for(s
= *text
; s
&& *s
!= '\0';){
1081 s
= ical_isolate_token(&t
, &c
);
1087 *t
= c
; /* restore separator */
1089 if(s
){ /* figure out the token */
1090 int ukn
= 0; /* unknown token */
1091 if(!struncmp(s
, "BEGIN", 5)){
1092 s
+= 6; /* 6 = strlen("BEGIN:") */
1093 ICAL_S
*uk_comp
= ical_parse_unknown_comp(&s
, 0);
1094 ical_free_unknown_comp(&uk_comp
);
1095 } else if(!struncmp(s
, "END", t
-s
-1)){
1096 s
+= 4; /* 4 = strlen("END:") */
1097 if(!struncmp(s
, "STANDARD\r\n", 10)
1098 || !struncmp(s
, "DAYLIGHT\r\n", 10)){
1099 *text
= s
+ 10; /* 10 = strlen("STANDARD\r\n") */
1100 return (void *) tzprop
;
1103 for(i
= 0; i
< TZPUnknown
; i
++)
1104 if(!struncmp(s
, tz_prop
[i
].prop
, t
-s
))
1106 if(tz_prop
[i
].parse
){
1107 if(tzprop
->prop
== NULL
){
1108 tzprop
->prop
= fs_get(TZPUnknown
*sizeof(void *));
1109 memset((void *)tzprop
->prop
, 0, TZPUnknown
*sizeof(void *));
1111 (tz_prop
[i
].parse
)(&tzprop
->prop
[tz_prop
[i
].pos
], &s
, tz_prop
[i
].prop
);
1118 if(ical_buf_len
< t
- s
){
1119 fs_resize((void **)&ical_buf
, t
-s
+1);
1123 strcpy(ical_buf
, s
);
1125 if(tzprop
->uk_prop
== NULL
){
1126 tzprop
->uk_prop
= fs_get(sizeof(GEN_ICLINE_S
));
1127 memset((void *)tzprop
->uk_prop
, 0, sizeof(GEN_ICLINE_S
));
1128 tzprop
->uk_prop
->cline
= ical_parse_line(&s
, ical_buf
);
1132 for (gcl
= tzprop
->uk_prop
; gcl
&& gcl
->next
; gcl
= gcl
->next
);
1133 gcl
->next
= fs_get(sizeof(GEN_ICLINE_S
));
1134 memset((void *)gcl
->next
, 0, sizeof(GEN_ICLINE_S
));
1135 gcl
->next
->cline
= ical_parse_line(&s
, ical_buf
);
1138 } /* end of if(s) */
1142 return (void *) tzprop
;
1146 ical_parse_valarm(char **text
)
1152 ical_debug("ical_parse_valarm", *text
);
1153 valarm
= fs_get(sizeof(VALARM_S
));
1154 memset((void *)valarm
, 0, sizeof(VALARM_S
));
1156 /* s must always point the the beginning of a line */
1157 for(s
= *text
; s
&& *s
!= '\0';){
1159 s
= ical_isolate_token(&t
, &c
);
1165 *t
= c
; /* restore separator */
1167 if(s
){ /* figure out the token */
1168 int ukn
= 0; /* unknown token */
1169 if(!struncmp(s
, "BEGIN", 5)){
1170 s
+= 6; /* 6 = strlen("BEGIN:") */
1171 ICAL_S
*uk_comp
= ical_parse_unknown_comp(&s
, 0);
1172 ical_free_unknown_comp(&uk_comp
);
1173 } else if(!struncmp(s
, "END", t
-s
-1)){
1174 s
+= 4; /* 4 = strlen("END:") */
1175 if(!struncmp(s
, "ALARM\r\n", 7)){
1176 *text
= s
+ 7; /* 7 = strlen("ALARM\r\n") */
1177 return (void *) valarm
;
1179 } else{ Alarm_prop i
;
1180 for(i
= 0; i
< AlUnknown
; i
++)
1181 if(!struncmp(s
, alarm_prop
[i
].prop
, t
-s
))
1183 if(alarm_prop
[i
].parse
){
1184 if(valarm
->prop
== NULL
){
1185 valarm
->prop
= fs_get(AlUnknown
*sizeof(void *));
1186 memset((void *)valarm
->prop
, 0, AlUnknown
*sizeof(void *));
1188 (alarm_prop
[i
].parse
)(&valarm
->prop
[alarm_prop
[i
].pos
], &s
, alarm_prop
[i
].prop
);
1195 if(ical_buf_len
< t
- s
){
1196 fs_resize((void **)&ical_buf
, t
-s
+1);
1200 strcpy(ical_buf
, s
);
1202 if(valarm
->uk_prop
== NULL
){
1203 valarm
->uk_prop
= fs_get(sizeof(GEN_ICLINE_S
));
1204 memset((void *)valarm
->uk_prop
, 0, sizeof(GEN_ICLINE_S
));
1205 valarm
->uk_prop
->cline
= ical_parse_line(&s
, ical_buf
);
1209 for (gcl
= valarm
->uk_prop
; gcl
&& gcl
->next
; gcl
= gcl
->next
);
1210 gcl
->next
= fs_get(sizeof(GEN_ICLINE_S
));
1211 memset((void *)gcl
->next
, 0, sizeof(GEN_ICLINE_S
));
1212 gcl
->next
->cline
= ical_parse_line(&s
, ical_buf
);
1215 } /* end of if(s) */
1219 return (void *) valarm
;
1223 ical_parse_vtodo(char **text
)
1229 ical_parse_vjournal(char **text
)
1235 ical_parse_vfreebusy(char **text
)
1241 ical_parse_generic_comp(char **text
, int level
)
1246 GEN_ICLINE_S
*gcl
= NULL
;
1249 ical_debug("ical_parse_generic_comp", *text
);
1250 ical
= fs_get(sizeof(ICAL_S
));
1251 memset((void *)ical
, 0, sizeof(ICAL_S
));
1253 ical
->comp
= ical_get_value(text
);
1254 token
= fs_get(strlen(ical
->comp
) + 2 + 1);
1255 sprintf(token
, "%s\r\n", ical
->comp
); /* this is allocated memory */
1257 /* s must always point the the beginning of a line */
1258 for(s
= *text
; s
&& *s
!= '\0';){
1260 s
= ical_isolate_token(&t
, &c
);
1267 *t
= c
; /* restore character */
1268 if(s
){ /* figure out the token */
1269 int ukn
= 0; /* unknown token */
1272 case 'b': if(!struncmp(s
+1, "EGIN", 4)){
1273 s
+= 6; /* 6 = strlen("BEGIN:") */
1274 if(ical
->next
== NULL
)
1275 ical
->next
= ical_parse_unknown_comp(&s
, level
+1);
1280 for(i
= 0, b
= ical
; i
<= level
&& b
&& b
->next
; b
= b
->next
, i
++);
1281 if(b
->branch
== NULL
)
1282 b
->branch
= ical_parse_unknown_comp(&s
, level
+1);
1284 for(; b
&& b
->branch
; b
= b
->branch
);
1285 b
->branch
= ical_parse_unknown_comp(&s
, level
+1);
1292 case 'e': if(!struncmp(s
+1, "ND", 2)){
1294 s
+= 4; /* 4 = strlen("END:") */
1295 if(!struncmp(s
, token
, strlen(token
))){
1296 *text
= s
+ strlen(token
);
1297 ical
->value
= (void *) gcl
;
1305 } /* end of switch(*s) */
1307 if(ical_buf_len
< t
- s
){
1308 fs_resize((void **)&ical_buf
, t
-s
+1);
1312 strcpy(ical_buf
, s
);
1315 gcl
= fs_get(sizeof(GEN_ICLINE_S
));
1316 memset((void *)gcl
, 0, sizeof(GEN_ICLINE_S
));
1317 gcl
->cline
= ical_parse_line(&s
, ical_buf
);
1320 GEN_ICLINE_S
*gencl
;
1321 for (gencl
= gcl
; gencl
&& gencl
->next
; gencl
= gencl
->next
);
1322 gencl
->next
= fs_get(sizeof(GEN_ICLINE_S
));
1323 memset((void *)gencl
->next
, 0, sizeof(GEN_ICLINE_S
));
1324 gencl
->next
->cline
= ical_parse_line(&s
, ical_buf
);
1327 } /* end of if(s) */
1330 ical
->value
= (void *) gcl
;
1336 ical_parse_unknown_comp(char **text
, int level
)
1341 ical_debug("ical_parse_unknown_comp", *text
);
1342 for(i
= 0; ical_comp
[i
].comp
1343 && (struncmp(*text
, ical_comp
[i
].comp
, ical_comp
[i
].len
)
1344 || struncmp(*text
+ ical_comp
[i
].len
, "\r\n", 2)); i
++);
1346 if(ical_comp
[i
].parse
){
1347 *text
+= ical_comp
[i
].len
+ 2;
1348 ical
= fs_get(sizeof(ICAL_S
));
1349 memset((void *)ical
, 0, sizeof(ICAL_S
));
1350 ical
->comp
= cpystr(ical_comp
[i
].comp
);
1351 ical
->value
= (ical_comp
[i
].parse
)(text
);
1353 ical
= ical_parse_generic_comp(text
, level
);
1359 ical_parse_line(char **text
, char *name
)
1364 ic
= fs_get(sizeof(ICLINE_S
));
1365 memset((void *)ic
, 0, sizeof(ICLINE_S
));
1367 ic
->token
= cpystr(name
);
1371 ic
->param
= ical_get_parameter(&s
);
1375 ic
->value
= ical_get_value(&s
);
1383 *** PARSE PROPERTY FUNCTIONS
1387 ical_parse_freq(Freq_value
*fval
, char *text
)
1389 if(fval
== NULL
) return;
1393 if(text
== NULL
) return;
1395 if(!strucmp(text
, "SECONDLY")) *fval
= FSecondly
;
1396 else if(!strucmp(text
, "MINUTELY")) *fval
= FMinutely
;
1397 else if(!strucmp(text
, "HOURLY")) *fval
= FHourly
;
1398 else if(!strucmp(text
, "DAILY")) *fval
= FDaily
;
1399 else if(!strucmp(text
, "WEEKLY")) *fval
= FWeekly
;
1400 else if(!strucmp(text
, "MONTHLY")) *fval
= FMonthly
;
1401 else if(!strucmp(text
, "YEARLY")) *fval
= FYearly
;
1405 ical_parse_weekday_list(BYWKDY_S
**bywkdyp
, char *wklist
)
1407 BYWKDY_S
*bywkdy
, *w
;
1412 if(bywkdyp
== NULL
) return;
1413 *bywkdyp
= bywkdy
= NULL
;
1414 if(wklist
== NULL
) return;
1416 for(t
= s
= wklist
; done
== 0; s
++){
1417 if(*s
!= ',' && *s
!= '\0')
1422 else /* c == '\0' */
1426 for(w
= bywkdy
; w
&& w
->next
; w
= w
->next
);
1427 w
= fs_get(sizeof(BYWKDY_S
));
1428 memset((void *)w
, 0, sizeof(BYWKDY_S
));
1429 if(!strucmp(t
+len
-2, "SU")) w
->wd
= Sunday
;
1430 else if(!strucmp(t
+len
-2, "MO")) w
->wd
= Monday
;
1431 else if(!strucmp(t
+len
-2, "TU")) w
->wd
= Tuesday
;
1432 else if(!strucmp(t
+len
-2, "WE")) w
->wd
= Wednesday
;
1433 else if(!strucmp(t
+len
-2, "TH")) w
->wd
= Thursday
;
1434 else if(!strucmp(t
+len
-2, "FR")) w
->wd
= Friday
;
1435 else if(!strucmp(t
+len
-2, "SA")) w
->wd
= Saturday
;
1436 // t[len - 2] = '\0';
1438 w
->value
= strtoul(t
, &t
, 10);
1448 ical_free_weekday_list((void **)&bywkdy
);
1454 ical_parse_number_list(BYWKDY_S
**bynop
, char *nolist
)
1460 if(bynop
== NULL
) return;
1461 *bynop
= byno
= NULL
;
1462 if(nolist
== NULL
) return;
1464 for(t
= s
= nolist
; done
== 0; s
++){
1465 if(*s
!= ',' && *s
!= '\0')
1470 else /* c == '\0' */
1473 for(n
= byno
; n
&& n
->next
; n
= n
->next
);
1474 n
= fs_get(sizeof(BYWKDY_S
));
1475 memset((void *)n
, 0, sizeof(BYWKDY_S
));
1476 n
->value
= strtoul(t
, &t
, 10);
1485 ical_free_weekday_list((void **)&byno
);
1491 ical_parse_rrule(RRULE_S
**rrulep
, char **text
)
1496 ICAL_PARAMETER_S
*param
, *p
;
1500 || text
== NULL
|| *text
== NULL
|| struncmp(*text
, "RRULE", 5)) return;
1501 rrule
= fs_get(sizeof(RRULE_S
));
1502 memset((void *) rrule
, 0, sizeof(RRULE_S
));
1504 /* recurring rules are special. First, we parse the icline that contains it */
1505 icl
= ical_parse_line(text
, "RRULE");
1507 /* now we copy the parameters that it contains */
1508 rrule
->param
= ical_parameter_cpy(icl
->param
);
1510 /* then we parse icl->value as if it was a parameter */
1512 param
= ical_get_parameter(&s
);
1514 /* now we check which values were given, and fill the prop array */
1515 rrule
->prop
= fs_get(RRUnknown
*sizeof(void *));
1516 memset((void *) rrule
->prop
, 0, RRUnknown
*sizeof(void *));
1518 for(p
= param
; p
!= NULL
; p
= p
->next
){
1519 for(i
= 0; rrule_prop
[i
].prop
!= NULL
&& strucmp(p
->name
, rrule_prop
[i
].prop
); i
++);
1520 if(rrule_prop
[i
].parse
)
1521 (rrule_prop
[i
].parse
)(&rrule
->prop
[rrule_prop
[i
].pos
], p
->value
);
1524 ical_free_param(¶m
);
1525 ical_free_cline((void **)&icl
);
1527 ical_free_rrule((void **)&rrule
);
1532 /*** UTF-8 for ICAL ***/
1535 ical_non_ascii_valid(unsigned char c
)
1538 static int utf8_len
= 0;
1539 static int utf8_type
= 0;
1543 utf8_type
= (c
>= 0xF0 && c
<= 0xF4)
1544 ? 4 : (c
>= 0xE0 && c
<= 0xEF)
1545 ? 3 : (c
>= 0xC2 && c
<= 0xDF)
1551 icu
[utf8_len
++] = c
; /* count it */
1556 else if(utf8_len
== 2){
1557 rv
= (icu
[0] >= 0xC2 && icu
[0] <= 0xDF)
1558 && (icu
[1] >= 0x80 && icu
[1] <= 0xBF) ? UTF8_COMPLETE
: 0;
1561 } else if (utf8_type
== 3){
1566 rv
= (icu
[1] >= 0xA0 && icu
[1] <= 0xBF)
1567 && (icu
[2] >= 0x80 && icu
[2] <= 0xBF) ? UTF8_COMPLETE
: 0;
1568 else if(icu
[0] >= 0xE1 && icu
[0] <= 0xEC)
1569 rv
= (icu
[1] >= 0x80 && icu
[1] <= 0xBF)
1570 && (icu
[2] >= 0x80 && icu
[2] <= 0xBF) ? UTF8_COMPLETE
: 0;
1571 else if(icu
[0] == 0xED)
1572 rv
= (icu
[1] >= 0x80 && icu
[1] <= 0x9F)
1573 && (icu
[2] >= 0x80 && icu
[2] <= 0xBF) ? UTF8_COMPLETE
: 0;
1574 else if(icu
[0] >= 0xE1 && icu
[0] <= 0xEC)
1575 rv
= (icu
[1] >= 0x80 && icu
[1] <= 0xBF)
1576 && (icu
[2] >= 0x80 && icu
[2] <= 0xBF) ? UTF8_COMPLETE
: 0;
1579 } else if (utf8_type
== 4){
1584 rv
= (icu
[1] >= 0x90 && icu
[1] <= 0xBF)
1585 && (icu
[2] >= 0x80 && icu
[2] <= 0xBF)
1586 && (icu
[3] >= 0x80 && icu
[3] <= 0xBF) ? UTF8_COMPLETE
: 0;
1587 else if(icu
[0] >= 0xF1 && icu
[0] <= 0xF3)
1588 rv
= (icu
[1] >= 0x80 && icu
[1] <= 0xBF)
1589 && (icu
[2] >= 0x80 && icu
[2] <= 0xBF)
1590 && (icu
[3] >= 0x80 && icu
[3] <= 0xBF) ? UTF8_COMPLETE
: 0;
1591 else if(icu
[0] == 0xF4)
1592 rv
= (icu
[1] >= 0x80 && icu
[1] <= 0x8F)
1593 && (icu
[2] >= 0x80 && icu
[2] <= 0xBF)
1594 && (icu
[3] >= 0x80 && icu
[3] <= 0xBF) ? UTF8_COMPLETE
: 0;
1602 ical_get_number_value(char *value
, int beg_pos
, int end_pos
)
1608 value
[end_pos
] = '\0';
1609 rv
= strtoul(value
+ beg_pos
, &err
, 10);
1610 if(err
!= NULL
&& *err
!= '\0') return -1;
1616 ical_free_duration(ICAL_DURATION_S
**ic_d
)
1618 if(ic_d
== NULL
|| *ic_d
== NULL
)
1621 if((*ic_d
)->next
) ical_free_duration(&(*ic_d
)->next
);
1622 fs_give((void **)ic_d
);
1625 /* returns 0 if no error, -1 if some error */
1627 ical_parse_duration(char *value
, ICAL_DURATION_S
*ic_d
)
1631 if(value
== NULL
|| ic_d
== NULL
) return -1;
1633 memset((void *)ic_d
, 0, sizeof(ICAL_DURATION_S
));
1635 if(value
[i
= 0] == '-'){
1638 } else if(value
[i
] == '+')
1641 if(value
[i
++] == 'P'){
1642 for(j
= i
; value
[j
] != '\0' && value
[j
] != ','; j
++){
1643 if(!isdigit(value
[j
]))
1645 case 'W': ic_d
->weeks
= ical_get_number_value(value
, i
, j
-1);
1648 case 'D': ic_d
->days
= ical_get_number_value(value
, i
, j
-1);
1651 case 'H': ic_d
->hours
= ical_get_number_value(value
, i
, j
-1);
1654 case 'M': ic_d
->minutes
= ical_get_number_value(value
, i
, j
-1);
1657 case 'S': ic_d
->seconds
= ical_get_number_value(value
, i
, j
-1);
1660 case 'T': i
= j
+ 1;
1670 if(value
[j
++] == ','){
1671 ICAL_DURATION_S next
;
1672 rv
= ical_parse_duration(value
+j
, &next
);
1679 /* return -1 if any error,
1680 0 if value has the DATE-TIME form
1681 1 if value has the DATE form only
1684 ical_parse_date(char *value
, struct tm
*t
)
1690 if(t
== NULL
) return rv
;
1691 memset((void *)&Tm
, 0, sizeof(struct tm
));
1693 if(value
== NULL
) return rv
;
1695 rv
= 0; /* assume DATE-TIME format */
1696 /* a simple check for the format of the string */
1697 for(i
= 0; isdigit(value
[i
]); i
++);
1698 if (i
== 8 && value
[i
] == '\0')
1701 if (i
!= 8 || value
[i
++] != 'T') return -1;
1703 for(; isdigit(value
[i
]); i
++);
1704 if(i
!= 15 || (value
[i
] != '\0' && (value
[i
] != 'Z' || value
[i
+1] != '\0')))
1708 Tm
.tm_year
= ical_get_number_value(value
, 0, 4) - 1900;
1709 Tm
.tm_mon
= ical_get_number_value(value
, 4, 6) - 1;
1710 Tm
.tm_mday
= ical_get_number_value(value
, 6, 8);
1712 Tm
.tm_hour
= ical_get_number_value(value
, 9, 11);
1713 Tm
.tm_min
= ical_get_number_value(value
, 11, 13);
1714 Tm
.tm_sec
= ical_get_number_value(value
, 13, 15);
1718 return (t
->tm_mon
> 11 || t
->tm_mon
< 0
1719 || t
->tm_mday
> 31 || t
->tm_mday
< 0
1720 || t
->tm_hour
> 23 || t
->tm_hour
< 0
1721 || t
->tm_min
> 59 || t
->tm_min
< 0
1722 || t
->tm_sec
> 60 || t
->tm_sec
< 0)
1727 ical_set_date(ICLINE_S
*icl
, VTIMEZONE_S
*vtz
)
1729 int date_form
; /* date forms from section 3.3.4 in RFC 5545 */
1730 ICAL_PARAMETER_S
*param
;
1735 if(icl
== NULL
) return;
1737 for(param
= icl
->param
; param
!= NULL
; param
= param
->next
)
1738 if(!strucmp(param
->name
, "TZID"))
1742 date_form
= 3; /* local time with timezone */
1743 else if(icl
->value
[strlen(icl
->value
)-1] == 'Z')
1744 date_form
= 2; /* utc time */
1745 else date_form
= 1; /* local time */
1747 ical_parse_date(icl
->value
, &ic_date
);
1748 ic_date
.tm_wday
= ical_day_of_week(ic_date
); /* find out day of the week */
1752 case 2: ical_adjust_date(&ic_date
, vtz
);
1755 default: alpine_panic ("Impossible date_form");
1760 ical_std_or_daylight(struct tm
*date
, VTIMEZONE_S
*vtz
)
1762 struct tm standard
, daylight
;
1769 /* adjusts time to given time zone */
1771 ical_adjust_date(struct tm
*date
, VTIMEZONE_S
*vtz
)
1773 char *tzname
= NULL
;
1775 ICAL_TZPROP_S
*cur_std_day
;
1781 if((icl
= (ICLINE_S
*)vtz
->prop
[TZCid
]) != NULL
)
1782 tzname
= cpystr(icl
->value
);
1785 //+++ cur_std_day = ical_std_or_daylight(date, vtz);
1789 ical_set_date_vevent(void *veventv
, void *vtzv
)
1791 VEVENT_S
*vevent
= (VEVENT_S
*) veventv
;
1792 VTIMEZONE_S
*vtz
= (VTIMEZONE_S
*) vtzv
;
1795 ical_set_date(vevent
->prop
[EvDtstamp
], vtz
);
1796 ical_set_date(vevent
->prop
[EvDtstart
], vtz
);
1797 ical_set_date(vevent
->prop
[EvDtend
], vtz
);
1801 #define LEAP_YEAR(X) ((((X) % 4 == 0) \
1802 && (((X) % 100 != 0) || ((X) % 400 == 0))) \
1805 #define CAL_OFFSET(X) (((X) == 1752) ? 5 : (LEAP_YEAR((X)) ? 2 : 1))
1807 /* given a year, after day_zero, return the day
1808 * of the week of the first of january of that year. On error,
1809 * return a negative number.
1810 * Assumption: day_zero is the date of january 1, of some year.
1813 ical_january_first(int year
)
1815 int i
, january_first
;
1817 if(year
< day_zero
.tm_year
) return -1; /* not supported */
1820 january_first
= day_zero
.tm_wday
;
1821 for(i
= 1900 + day_zero
.tm_year
+ 1; i
<= year
; i
++)
1822 january_first
+= CAL_OFFSET(i
-1);
1824 return january_first
% 7;
1827 /* given a month, week day, and year, return all days of the month
1828 * that have that day as the week day. For example, return all
1829 * sundays in november 2012.
1832 ical_day_from_week(int month
, Weekday day
, int year
)
1839 fday
= ical_first_of_month(month
, year
);
1840 year
+= 1900; /* restore year */
1841 if(year
== 1752 && month
== 8){
1844 for(nday
= 1, wday
= (Weekday
) fday
; wday
!= day
; wday
= (wday
+1) % 7, nday
++)
1846 rv
= fs_get(6*sizeof(int));
1847 memset((void *)&rv
, 0, 6*sizeof(int));
1848 for(i
= 0; nday
<= month_len
[month
]; i
++){
1852 if(LEAP_YEAR(year
) && month
== 1 && nday
== 29)
1860 /* given a month and a year, return the weekday of the first of the
1861 * month in that year.
1862 * return value: on error -1, otherwise the day of the week.
1865 ical_first_of_month(int month
, int year
)
1869 if((d
= ical_january_first(year
)) < 0)
1873 for(i
= 0; i
< month
; i
++)
1876 if(LEAP_YEAR(year
) && month
>= 2)
1879 if(year
== 1752 && month
>= 9)
1885 /* given a day, month and year, return the weekday of that day
1886 * return value: on error -1, otherwise the day of the week.
1888 int ical_day_of_week(struct tm date
)
1892 if((d
= ical_first_of_month(date
.tm_mon
, date
.tm_year
)) < 0)
1895 d
+= date
.tm_mday
- 1;
1897 if(date
.tm_year
+ 1900 == 1752){
1898 if(date
.tm_mday
> 2 && date
.tm_mday
< 14)
1900 if(date
.tm_mday
>= 14)
1907 /* given an initial date dtstart, and a recurring rule, rrule,
1908 * adjust the date to the first date on the same year, when
1909 * the rule actually starts
1912 adjust_date_rrule(struct tm
*dtstart
, RRULE_S
*rrule
)
1916 memset((void *) &t
, 0, sizeof(struct tm
));
1917 t
.tm_year
= dtstart
->tm_year
; /* same year */
1918 if(rrule
->prop
[RRFreq
]){
1920 if(rrule
->prop
[RRCount
]){
1922 else if(rrule
->prop
[RRInterval
]){
1924 if(rrule
->prop
[RRBysecond
]){
1925 BYWKDY_S
*sec
= (BYWKDY_S
*) rrule
->prop
[RRBysecond
], *seco
;
1926 for (seco
= sec
; seco
!= NULL
; seco
= seco
->next
)
1927 if(seco
== sec
) t
.tm_sec
= seco
->value
;
1928 else if (seco
->value
< t
.tm_sec
)
1929 t
.tm_sec
= seco
->value
;
1931 if (rrule
->prop
[RRByminute
]){
1932 BYWKDY_S
*sec
= (BYWKDY_S
*) rrule
->prop
[RRByminute
], *seco
;
1933 for (seco
= sec
; seco
!= NULL
; seco
= seco
->next
)
1934 if(seco
== sec
) t
.tm_min
= seco
->value
;
1935 else if (seco
->value
< t
.tm_sec
)
1936 t
.tm_min
= seco
->value
;
1938 if (rrule
->prop
[RRByhour
]){
1939 BYWKDY_S
*sec
= (BYWKDY_S
*) rrule
->prop
[RRByhour
], *seco
;
1940 for (seco
= sec
; seco
!= NULL
; seco
= seco
->next
)
1941 if(seco
== sec
) t
.tm_hour
= seco
->value
;
1942 else if (seco
->value
< t
.tm_sec
)
1943 t
.tm_hour
= seco
->value
;
1945 if (rrule
->prop
[RRByday
]){
1947 if (rrule
->prop
[RRByweekno
]){
1949 if (rrule
->prop
[RRBymonthday
]){
1951 if (rrule
->prop
[RRByyearday
]){
1953 if (rrule
->prop
[RRByweekno
]){
1955 if (rrule
->prop
[RRBymonth
]){
1956 BYWKDY_S
*m
= (BYWKDY_S
*) rrule
->prop
[RRBymonth
], *mo
;
1957 for (mo
= m
; mo
!= NULL
; mo
= mo
->next
)
1958 if(mo
== m
) t
.tm_mon
= mo
->value
- 1;
1959 else if (mo
->value
- 1 < t
.tm_mon
)
1960 t
.tm_mon
= mo
->value
- 1;
1962 if (rrule
->prop
[RRBysetpos
]){
1964 if (rrule
->prop
[RRWkst
]){
1969 ical_initialize(void)
1971 ical_buf_len
= 1024;
1972 ical_buf
= fs_get(ical_buf_len
+1);
1974 memset((void *) &day_zero
, 0, sizeof(struct tm
));
1975 day_zero
.tm_year
= 1601 - 1900;
1976 day_zero
.tm_mday
= 1;
1977 day_zero
.tm_wday
= 4;
1980 /* we create a summary of the event, and pass that back as
1984 ical_vevent_summary(VCALENDAR_S
*vcal
)
1986 VEVENT_SUMMARY_S
*rv
;
1993 if(vcal
== NULL
) return NULL
;
1995 method
= vcal
->method
;
1996 vevent
= (VEVENT_S
*) vcal
->comp
[VEvent
];
1998 if(vevent
== NULL
|| vevent
->prop
== NULL
)
2001 rv
= fs_get(sizeof(VEVENT_SUMMARY_S
));
2002 memset((void *) rv
, 0, sizeof(VEVENT_SUMMARY_S
));
2004 if(method
!= NULL
&& !strucmp(method
->value
, "CANCEL"))
2007 if((icl
= (ICLINE_S
*) vevent
->prop
[EvPriority
]) != NULL
)
2008 rv
->priority
= atoi(icl
->value
);
2010 if((icl
= (ICLINE_S
*) vevent
->prop
[EvSummary
]) != NULL
)
2011 rv
->summary
= cpystr(icl
->value
? icl
->value
: _("No Summary"));
2013 if((icl
= (ICLINE_S
*) vevent
->prop
[EvClass
]) != NULL
)
2014 rv
->class = cpystr(icl
->value
? icl
->value
: _("PUBLIC"));
2016 rv
->class = cpystr(_("PUBLIC"));
2018 if((icl
= (ICLINE_S
*) vevent
->prop
[EvOrganizer
]) != NULL
){
2019 char *cn
, *sender
, *address
;
2020 ICAL_PARAMETER_S
*param
;
2022 cn
= sender
= address
= NULL
;
2023 for(param
= icl
->param
; param
!= NULL
; param
= param
->next
)
2024 if(!strucmp(param
->name
, "CN"))
2026 else if(!strucmp(param
->name
, "SENT-BY"))
2027 sender
= param
->value
;
2030 if(!struncmp(sender
, "MAILTO:", 7))
2032 utf8_snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, "<%s>", sender
);
2033 rv
->sender
= cpystr(tmp_20k_buf
);
2036 if((address
= icl
->value
) != NULL
){
2037 if(!struncmp(address
, "MAILTO:", 7))
2039 utf8_snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, "%s%s<%s>",
2040 cn
? cn
: "", cn
? " " : "",
2041 address
? address
: _("Unknown address"));
2042 rv
->organizer
= cpystr(tmp_20k_buf
);
2044 } /* end of if(organizer) */
2046 if((icl
= (ICLINE_S
*) vevent
->prop
[EvLocation
]) != NULL
)
2047 rv
->location
= cpystr(icl
->value
? icl
->value
: _("Location undisclosed"));
2049 if((icl
= (ICLINE_S
*) vevent
->prop
[EvDtstart
]) != NULL
){
2052 int icd
; /* ical date return value */
2054 memset((void *)&ic_date
, 0, sizeof(struct tm
));
2055 icd
= ical_parse_date(icl
->value
, &ic_date
);
2057 ic_date
.tm_wday
= ical_day_of_week(ic_date
);
2059 case 0: /* DATE-TIME */
2060 our_strftime(tmp
, sizeof(tmp
), "%a %x %I:%M %p", &ic_date
);
2063 our_strftime(tmp
, sizeof(tmp
), "%a %x", &ic_date
);
2065 default: alpine_panic("Unhandled ical date format");
2070 strncpy(tmp
, _("Error while parsing event date"), sizeof(tmp
));
2071 tmp
[sizeof(tmp
) - 1] = '\0';
2073 rv
->evstart
= cpystr(icl
->value
? tmp
: _("Unknown Start Date"));
2074 } /* end of if dtstart */
2076 if((icl
= (ICLINE_S
*) vevent
->prop
[EvDuration
]) != NULL
){
2078 ICAL_DURATION_S ic_d
, icd2
;
2079 if(ical_parse_duration(icl
->value
, &ic_d
) == 0){
2080 char tmp
[MAILTMPLEN
+1];
2082 for(i
= 1, icd2
= ic_d
; icd2
.next
!= NULL
; icd2
= *icd2
.next
, i
++);
2083 rv
->duration
= fs_get((i
+1)*sizeof(char *));
2090 utf8_snprintf(tmp
+strlen(tmp
), MAILTMPLEN
- strlen(tmp
),
2091 "%d %s ", ic_d
.weeks
, ic_d
.weeks
== 1 ? _("week") : _("weeks"));
2093 utf8_snprintf(tmp
+strlen(tmp
), MAILTMPLEN
- strlen(tmp
),
2094 "%d %s ", ic_d
.days
, ic_d
.days
== 1 ? _("day") : _("days"));
2096 utf8_snprintf(tmp
+strlen(tmp
), MAILTMPLEN
- strlen(tmp
),
2097 "%d %s ", ic_d
.hours
, ic_d
.hours
== 1 ? _("hour") : _("hours"));
2098 if(ic_d
.minutes
> 0)
2099 utf8_snprintf(tmp
+strlen(tmp
), MAILTMPLEN
- strlen(tmp
),
2100 "%d %s ", ic_d
.minutes
, ic_d
.minutes
== 1 ? _("minute") : _("minutes"));
2101 if(ic_d
.seconds
> 0)
2102 utf8_snprintf(tmp
+strlen(tmp
), MAILTMPLEN
- strlen(tmp
),
2103 "%d %s ", ic_d
.seconds
, ic_d
.seconds
== 1 ? _("second") : _("seconds"));
2105 tmp
[MAILTMPLEN
] = '\0';
2106 rv
->duration
[i
++] = cpystr(tmp
);
2108 if(ic_d
.next
!= NULL
)
2112 } while (done
== 0);
2113 rv
->duration
[i
] = NULL
;
2115 } /* end of DURATION */
2116 else if((icl
= (ICLINE_S
*) vevent
->prop
[EvDtend
]) != NULL
){
2121 memset((void *)&ic_date
, 0, sizeof(struct tm
));
2122 icd
= ical_parse_date(icl
->value
, &ic_date
);
2124 ic_date
.tm_wday
= ical_day_of_week(ic_date
);
2126 case 0: /* DATE-TIME */
2127 our_strftime(tmp
, sizeof(tmp
), "%a %x %I:%M %p", &ic_date
);
2130 our_strftime(tmp
, sizeof(tmp
), "%a %x", &ic_date
);
2132 default: alpine_panic("Unhandled ical date format");
2137 strncpy(tmp
, _("Error while parsing event date"), sizeof(tmp
));
2138 tmp
[sizeof(tmp
) - 1] = '\0';
2140 rv
->evend
= cpystr(icl
->value
? tmp
: _("Unknown End Date"));
2141 } /* end of if dtend */
2143 if((gicl
= (GEN_ICLINE_S
*) vevent
->prop
[EvAttendee
]) != NULL
){
2146 for(nattendees
= 0; gicl
!= NULL
; gicl
= gicl
->next
, nattendees
++);
2147 rv
->attendee
= fs_get((nattendees
+1)*sizeof(char *));
2149 gicl
= (GEN_ICLINE_S
*) vevent
->prop
[EvAttendee
];
2150 for(i
= 0; gicl
!= NULL
; gicl
= gicl
->next
, i
++){
2151 char *role
, *partstat
, *rsvp
;
2153 ICAL_PARAMETER_S
*param
;
2156 role
= partstat
= rsvp
= cn
= mailto
= NULL
;
2157 for(param
= icl
->param
; param
!= NULL
; param
= param
->next
){
2158 if(!strucmp(param
->name
, "ROLE")){
2159 if(!strucmp(param
->value
, "REQ-PARTICIPANT"))
2160 role
= _("[Required]");
2161 else if(!strucmp(param
->value
, "OPT-PARTICIPANT"))
2162 role
= _("[Optional]");
2163 else if(!strucmp(param
->value
, "NON-PARTICIPANT"))
2164 role
= _("[Informed]");
2165 else if(!strucmp(param
->value
, "CHAIR"))
2166 role
= _("[ Chair ]");
2168 role
= param
->value
;
2170 else if(!strucmp(param
->name
, "PARTSTAT")){
2171 if(!strucmp(param
->value
, "NEEDS-ACTION"))
2172 partstat
= _("[Need-Reply]");
2173 else if(!strucmp(param
->value
, "ACCEPTED"))
2174 partstat
= _("[ Accepted ]");
2175 else if(!strucmp(param
->value
, "DECLINED"))
2176 partstat
= _("[ Declined ]");
2177 else if(!strucmp(param
->value
, "TENTATIVE"))
2178 partstat
= _("[ Tentative]");
2179 else if(!strucmp(param
->value
, "DELEGATED"))
2180 partstat
= _("[ Delegated]");
2182 partstat
= param
->value
;
2184 else if(!strucmp(param
->name
, "RSVP"))
2185 rsvp
= param
->value
;
2186 else if(!strucmp(param
->name
, "CN"))
2189 if(icl
->value
&& !struncmp(icl
->value
, "MAILTO:", strlen("MAILTO:")))
2190 mailto
= icl
->value
+ 7; /* 7 = strlen("MAILTO:") */
2191 if(!strucmp(cn
, mailto
))
2193 utf8_snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, "%s%s%s%s%s%s<%s>",
2194 role
&& *role
? role
: "",
2195 role
&& *role
? " " : "",
2196 partstat
? partstat
: _("[Unknown Reply]"),
2198 cn
&& *cn
? cn
: "",
2199 cn
&& *cn
? " " : "",
2200 mailto
? mailto
: _("Unknown address"));
2201 rv
->attendee
[i
] = cpystr(tmp_20k_buf
);
2203 rv
->attendee
[i
] = NULL
;
2204 } /* end of ATTENDEES */
2206 if((icl
= (ICLINE_S
*) vevent
->prop
[EvDescription
]) != NULL
){
2207 char *s
, *t
, *u
, *v
;
2210 if(icl
->value
== NULL
){
2211 free_vevent_summary(&rv
);
2215 v
= cpystr(icl
->value
); /* process a copy of icl->value */
2217 for(i
= 1, escaped
= 0, s
= v
; s
&& *s
; s
++){
2218 if(*s
== '\\' && escaped
== 0){ escaped
= 1; continue; }
2220 if(!(*s
== '\\' || *s
== ',' || *s
== 'n' || *s
== 'N' || *s
== ';')){
2221 free_vevent_summary(&rv
);
2222 fs_give((void **)&v
);
2228 if(*s
== ',') i
++; /* a non-scaped comma is a new value for text */
2231 rv
->description
= fs_get((i
+1)*sizeof(char *));
2233 for (s
= t
= u
= v
, escaped
= 0; *t
!= '\0'; t
++){
2234 if(*t
== '\\' && escaped
== 0){ escaped
= 1; continue; }
2246 default: free_vevent_summary(&rv
);
2247 fs_give((void **)&v
);
2255 rv
->description
[i
++] = cpystr(ical_decode(s
, vcal
->encoding
));
2261 rv
->description
[i
++] = cpystr(ical_decode(s
, vcal
->encoding
));
2262 rv
->description
[i
] = NULL
;
2263 fs_give((void **)&v
);
2264 } /* end of if(description) */
2270 free_vevent_summary(VEVENT_SUMMARY_S
**vesy
)
2273 if(vesy
== NULL
|| *vesy
== NULL
) return;
2275 if((*vesy
)->class) fs_give((void **)&(*vesy
)->class);
2276 if((*vesy
)->summary
) fs_give((void **)&(*vesy
)->summary
);
2277 if((*vesy
)->sender
) fs_give((void **)&(*vesy
)->sender
);
2278 if((*vesy
)->organizer
) fs_give((void **)&(*vesy
)->organizer
);
2279 if((*vesy
)->location
) fs_give((void **)&(*vesy
)->location
);
2280 if((*vesy
)->evstart
) fs_give((void **)&(*vesy
)->evstart
);
2281 if((*vesy
)->evend
) fs_give((void **)&(*vesy
)->evend
);
2282 if((*vesy
)->duration
){
2283 for(i
= 0; (*vesy
)->duration
[i
] != NULL
; i
++)
2284 fs_give((void **) &(*vesy
)->duration
[i
]);
2285 fs_give((void **) (*vesy
)->duration
);
2287 if((*vesy
)->attendee
){
2288 for(i
= 0; (*vesy
)->attendee
[i
] != NULL
; i
++)
2289 fs_give((void **) &(*vesy
)->attendee
[i
]);
2290 fs_give((void **) (*vesy
)->attendee
);
2292 if((*vesy
)->description
){
2293 for(i
= 0; (*vesy
)->description
[i
] != NULL
; i
++)
2294 fs_give((void **) &(*vesy
)->description
[i
]);
2295 fs_give((void **) (*vesy
)->description
);
2297 fs_give((void **) vesy
);
2301 void ical_print_line(ICLINE_S icl
)
2303 ICAL_PARAMETER_S
*p
;
2304 printf("token=%s, ", icl
.token
);
2305 for(p
= icl
.param
; p
!= NULL
; p
= p
->next
){
2306 if(p
->name
) printf("param->name=%s, ", p
->name
);
2307 if(p
->value
) printf("param->value=%s, ", p
->value
);
2309 printf("value=%s", icl
.value
);
2313 #define CRLFCOUNT 100
2315 char *lf2crlf(char *text
)
2320 if(text
== NULL
|| *text
== '\0')
2326 for(i
= 0, s
= text
; *s
;){
2329 fs_resize((void *)&rv
, len
);
2336 fs_give((void **)&text
);
2342 int main (int argc
, char *argv
[])
2348 fprintf(stderr
, "Only give one argument: File name to read\n");
2352 if(readfile(argv
[1], &text
, NULL
) < 0){
2353 fprintf(stderr
, "Can not read %s succesfully\n", argv
[1]);
2357 text
= lf2crlf(text
);
2358 vcal
= ical_parse_text(text
);
2360 ical_free_vcalendar((void **)&vcal
);
2365 #endif /* STANDALONE */