1 #include "../pith/headers.h"
2 #include "../pith/mailpart.h"
3 #include "../pith/store.h"
4 #include "../pith/ical.h"
6 typedef struct ical_iana_comp_s
{
7 char *comp
; /* component name */
8 size_t len
; /* size of component name (strlen(x->comp)) */
9 int pos
; /* position of this component in comp array */
10 void *(*parse
)(char **); /* parser */
11 void (*give
)(void **); /* free memory */
14 typedef struct ical_iana_prop_s
{
15 char *prop
; /* component PROPerty name */
16 size_t len
; /* size of component name (strlen(x->prop)) */
17 int pos
; /* location of this component in the prop array */
18 void *(*parse
)(); /* parser */
19 void (*give
)(void **); /* free memory */
22 int ical_january_first(int); /* args: year */
23 void ical_adjust_date(struct tm
*, VTIMEZONE_S
*);
25 void ical_initialize(void);
27 int ical_non_ascii_valid(unsigned char);
28 char *ical_unfold_line(char *);
29 ICLINE_S
*ical_parse_line(char **, char *);
31 ICLINE_S
*ical_cline_cpy(ICLINE_S
*);
32 ICAL_PARAMETER_S
*ical_parameter_cpy(ICAL_PARAMETER_S
*param
);
34 char *ical_get_value(char **);
35 unsigned char *ical_decode(char *, unsigned short);
38 void *ical_parse_vcalendar(char **);
39 void *ical_parse_vevent(char **);
40 void *ical_parse_vtodo(char **);
41 void *ical_parse_vjournal(char **);
42 void *ical_parse_vfreebusy(char **);
43 void *ical_parse_vtimezone(char **);
44 void *ical_parse_valarm(char **);
45 void *ical_parse_timezone(char **);
46 ICAL_S
*ical_parse_unknown_comp(char **, int);
47 ICAL_S
*ical_parse_generic_comp(char **, int);
50 void ical_free_vevent(void **);
51 void ical_free_vtodo(void **);
52 void ical_free_vjournal(void **);
53 void ical_free_vfreebusy(void **);
54 void ical_free_vtimezone(void **);
55 void ical_free_timezone(void **);
56 void ical_free_valarm(void **);
57 void ical_free_unknown_comp(ICAL_S
**);
59 /* parse properties */
60 void *ical_cline_from_token(void *, char **, char *);
61 void *ical_gencline_from_token(void *, char **, char *);
63 void *ical_parse_rrule(void *, char **, char *);
64 void *ical_parse_time(void *, char **, char *);
65 void *ical_parse_offset(void *, char **, char *);
67 void *ical_parse_freq(void *, char *);
68 void *ical_parse_until(void *, char *);
69 void *ical_parse_count(void *, char *);
70 void *ical_parse_interval(void *, char *);
71 void *ical_parse_weekday_list(void *, char *);
72 void *ical_parse_number_list(void *, char *);
74 int ical_get_number_value(char *, int, int);
75 void ical_set_date(ICLINE_S
*, VTIMEZONE_S
*);
76 void ical_set_date_vevent(void *, void *);
79 void ical_free_prop(void ***, ICAL_PROP_S
*, int);
80 void ical_free_cline(void **);
81 void ical_free_param(ICAL_PARAMETER_S
**);
82 void ical_free_gencline(void **);
83 void ical_free_rrule(void **);
84 void ical_fs_give(void **);
85 void ical_free_weekday_list(void **);
87 /* utility functions */
88 void ical_date_time (char *, size_t, struct tm
*);
89 char *ical_get_tzid(ICAL_PARAMETER_S
*);
92 struct tm day_zero
; /* date for january 1, 1601 */
93 int month_len
[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
95 #define UTF8_COMPLETE (1)
99 unsigned long ical_buf_len
;
102 /* parsing structures */
104 /* this is the list of V-components to a Calendar from RFC 5545 */
105 ICAL_COMP_S ical_comp
[] = {
106 {"VCALENDAR", 9, VCalendar
, ical_parse_vcalendar
, ical_free_vcalendar
},
107 {"VTIMEZONE", 9, VTimeZone
, ical_parse_vtimezone
, ical_free_vtimezone
},
108 {"VEVENT", 6, VEvent
, ical_parse_vevent
, ical_free_vevent
},
109 {"VTODO", 5, VTodo
, ical_parse_vtodo
, ical_free_vtodo
},
110 {"VJOURNAL", 8, VJournal
, ical_parse_vjournal
, ical_free_vjournal
},
111 {"VALARM", 6, VAlarm
, ical_parse_valarm
, ical_free_valarm
},
112 {"VFREEBUSY", 9, VFreeBusy
, ical_parse_vfreebusy
, ical_free_vfreebusy
},
113 {NULL
, 0, VUnknown
, NULL
, 0}
116 /* array for properties */
117 ICAL_PROP_S rrule_prop
[] = {
118 {"FREQ", 4, RRFreq
, ical_parse_freq
, ical_fs_give
},
119 {"UNTIL", 5, RRUntil
, ical_parse_until
, ical_fs_give
},
120 {"COUNT", 5, RRCount
, ical_parse_count
, ical_fs_give
},
121 {"INTERVAL", 8, RRInterval
, ical_parse_interval
, ical_fs_give
},
122 {"BYSECOND", 8, RRBysecond
, ical_parse_number_list
, ical_free_weekday_list
},
123 {"BYMINUTE", 8, RRByminute
, ical_parse_number_list
, ical_free_weekday_list
},
124 {"BYHOUR", 6, RRByhour
, ical_parse_number_list
, ical_free_weekday_list
},
125 {"BYDAY", 5, RRByday
, ical_parse_weekday_list
,ical_free_weekday_list
},
126 {"BYWEEKNO", 8, RRByweekno
, 0, 0},
127 {"BYMONTH", 7, RRBymonth
, ical_parse_number_list
, ical_free_weekday_list
},
128 {"BYSETPOS", 8, RRBysetpos
, 0, 0},
129 {"BYWKST", 6, RRWkst
, 0, 0},
131 10, RRBymonthday
, 0, 0},
132 {"BYYEARDAY", 9, RRByyearday
, 0, 0},
133 {NULL
, 0, RRUnknown
, 0, 0}
136 ICAL_PROP_S event_prop
[] = {
137 {"DTSTAMP", 7, EvDtstamp
, ical_cline_from_token
, ical_free_cline
},
138 {"UID", 3, EvUid
, ical_cline_from_token
, ical_free_cline
},
139 {"DTSTART", 7, EvDtstart
, ical_cline_from_token
, ical_free_cline
},
140 {"CLASS", 5, EvClass
, ical_cline_from_token
, ical_free_cline
},
141 {"CREATED", 7, EvCreated
, ical_cline_from_token
, ical_free_cline
},
142 {"DESCRIPTION", 11, EvDescription
, ical_cline_from_token
, ical_free_cline
},
143 {"GEO", 3, EvGeo
, ical_cline_from_token
, ical_free_cline
},
144 {"LASTMOD", 7, EvLastMod
, ical_cline_from_token
, ical_free_cline
},
145 {"LOCATION", 8, EvLocation
, ical_cline_from_token
, ical_free_cline
},
146 {"ORGANIZER", 9, EvOrganizer
, ical_cline_from_token
, ical_free_cline
},
147 {"PRIORITY", 8, EvPriority
, ical_cline_from_token
, ical_free_cline
},
148 {"SEQUENCE", 8, EvSequence
, ical_cline_from_token
, ical_free_cline
},
149 {"STATUS", 6, EvStatus
, ical_cline_from_token
, ical_free_cline
},
150 {"SUMMARY", 7, EvSummary
, ical_cline_from_token
, ical_free_cline
},
151 {"TRANSP", 6, EvTransp
, ical_cline_from_token
, ical_free_cline
},
152 {"URL", 3, EvUrl
, ical_cline_from_token
, ical_free_cline
},
153 {"RECURRENCE-ID", 13, EvRecurrence
, ical_cline_from_token
, ical_free_cline
},
154 {"RRULE", 5, EvRrule
, ical_parse_rrule
, ical_free_rrule
},
155 {"DTEND", 5, EvDtend
, ical_cline_from_token
, ical_free_cline
},
156 {"DURATION", 8, EvDuration
, ical_cline_from_token
, ical_free_cline
},
157 {"ATTACH", 6, EvAttach
, ical_gencline_from_token
, ical_free_gencline
},
158 {"ATTENDEE", 8, EvAttendee
, ical_gencline_from_token
, ical_free_gencline
},
159 {"CATEGORIES", 10, EvCategories
, ical_gencline_from_token
, ical_free_gencline
},
160 {"COMMENT", 7, EvComment
, ical_gencline_from_token
, ical_free_gencline
},
161 {"CONTACT", 7, EvContact
, ical_gencline_from_token
, ical_free_gencline
},
162 {"EXDATE", 6, EvExdate
, ical_gencline_from_token
, ical_free_gencline
},
163 {"RSTATUS", 7, EvRstatus
, ical_gencline_from_token
, ical_free_gencline
},
164 {"RELATED", 7, EvRelated
, ical_gencline_from_token
, ical_free_gencline
},
165 {"RESOURCES", 9, EvResources
, ical_gencline_from_token
, ical_free_gencline
},
166 {"RDATE", 5, EvRdate
, ical_gencline_from_token
, ical_free_gencline
},
167 {NULL
, 0, EvUnknown
, 0, 0}
170 ICAL_PROP_S tz_comp
[] = {
171 {"TZID", 4, TZCid
, ical_cline_from_token
, ical_free_cline
},
172 {"LAST-MODIFIED", 13, TZCLastMod
, ical_cline_from_token
, ical_free_cline
},
173 {"TZURL", 5, TZCUrl
, ical_cline_from_token
, ical_free_cline
},
174 {NULL
, 0, TZCUnknown
, 0, 0}
177 ICAL_PROP_S tz_prop
[] = {
178 {"DTSTART", 7, TZPDtstart
, ical_parse_time
, ical_fs_give
},
179 {"TZOFFSETTO", 10, TZPOffsetto
, ical_parse_offset
, ical_fs_give
},
180 {"TZOFFSETFROM", 12, TZPOffsetfrom
, ical_parse_offset
, ical_fs_give
},
181 {"RRULE", 5, TZPRrule
, ical_parse_rrule
, ical_free_rrule
},
182 {"COMMENT", 7, TZPComment
, ical_gencline_from_token
, ical_free_gencline
},
183 {"RDATE", 5, TZPRdate
, ical_gencline_from_token
, ical_free_gencline
},
184 {"TZNAME", 6, TZPTzname
, ical_gencline_from_token
, ical_free_gencline
},
185 {NULL
, 0, TZPUnknown
, 0, 0}
188 ICAL_PROP_S alarm_prop
[] = {
189 {"ACTION", 6, AlAction
, ical_cline_from_token
, ical_free_cline
},
190 {"TRIGGER", 7, AlTrigger
, ical_cline_from_token
, ical_free_cline
},
191 {"DURATION", 8, AlDuration
, ical_cline_from_token
, ical_free_cline
},
192 {"REPEAT", 6, AlRepeat
, ical_cline_from_token
, ical_free_cline
},
193 {"DESCRIPTION", 11, AlDescription
, ical_cline_from_token
, ical_free_cline
},
194 {"SUMMARY", 7, AlSummary
, ical_cline_from_token
, ical_free_cline
},
195 {"ATTACH", 6, AlAttach
, ical_gencline_from_token
, ical_free_gencline
},
196 {"ATTENDEE", 8, AlAttendee
, ical_gencline_from_token
, ical_free_gencline
},
197 {NULL
, 0, AlUnknown
, 0, 0}
200 /* some useful macros for character analysis */
202 #define ical_wspace(X) \
203 ((X) == ' ' || (X) == '\t')
205 #define ical_name_allowed_char(X) \
206 (((X) >= 'A' && (X) <= 'Z') || \
207 ((X) >= 'a' && (X) <= 'z') || \
210 #define ical_control(X) \
211 (((X) >= 0x00 && (X) <= 0x08) || \
212 ((X) >= 0x0A && (X) <= 0x1F) || \
215 #define ical_safe_char(X) \
216 (ical_non_ascii_valid(X) \
219 || ((X) >= 0x23 && (X) <= 0x2B) \
220 || ((X) >= 0x2D && (X) <= 0x39) \
221 || ((X) >= 0x3C && (X) <= 0x7E))
223 #define ical_qsafe_char(X) \
224 (ical_non_ascii_valid((X)) \
227 || ((X) >= 0x23 && (X) <= 0x7E))
229 #define ical_value_char(X) \
230 (ical_non_ascii_valid(X) \
232 || ((X) >= 0x21 && (X) <= 0x7E))
234 /* Finally, here begins the code. */
237 ical_decode(char *text
, unsigned short encoding
)
240 unsigned long callen
;
242 if(encoding
== ENCQUOTEDPRINTABLE
){
243 t
= rfc822_qprint ((unsigned char *) text
,strlen(text
),&callen
);
245 tlen
= strlen(text
) + 1;
246 strncpy(text
, (char *) t
, tlen
);
247 text
[tlen
- 1] = '\0';
248 fs_give((void **) &t
);
251 return (unsigned char *) text
;
257 -1 - if an error occurred
258 Args: a pointer to the text. If there is an error, the text is not modified.
261 ical_remove_escapes(char **textp
)
268 if(textp
== NULL
) return 0;
270 t
= cpystr(*textp
); /* work on a copy of the text */
271 tlen
= strlen(*textp
) + 1; /* and record its size */
272 /* the variable text below points to the beginning of the filtered text */
273 for (text
= s
= t
, escaped
= 0; rv
== 0 && *s
!= '\0'; s
++){
274 if(*s
== '\\' && escaped
== 0){
297 *t
= '\0'; /* tie off filtered text */
298 t
= text
; /* reset t to the beginning */
300 strncpy(*textp
, t
, tlen
); /* overwrite given text with filtered text */
301 (*textp
)[tlen
- 1] = '\0';
303 fs_give((void **) &t
);
308 ical_debug(char *fcn
, char *text
)
311 strncpy(piece
, text
, 49);
312 piece
[sizeof(piece
)-1] = '\0';
313 dprint((2, "%s: %s\n", fcn
, piece
));
317 *** FREE MEMORY FUNCTIONS
321 ical_free_param(ICAL_PARAMETER_S
**param
)
323 if(param
== NULL
|| *param
== NULL
)
326 if((*param
)->name
) fs_give((void **) &(*param
)->name
);
327 if((*param
)->value
) fs_give((void **) &(*param
)->value
);
328 if((*param
)->next
) ical_free_param(&(*param
)->next
);
329 fs_give((void **)param
);
333 ical_free_cline(void **icv
)
335 ICLINE_S
**ic
= (ICLINE_S
**) icv
;
337 if(ic
== NULL
|| *ic
== NULL
)
340 if((*ic
)->token
) fs_give((void **) &(*ic
)->token
);
341 if((*ic
)->param
) ical_free_param(&(*ic
)->param
);
342 if((*ic
)->value
) fs_give((void **) &(*ic
)->value
);
347 ical_free_gencline(void **giclpv
)
349 GEN_ICLINE_S
**giclp
= (GEN_ICLINE_S
**) giclpv
;
351 if(giclp
== NULL
|| *giclp
== NULL
) return;
353 if((*giclp
)->cline
) ical_free_cline((void **) &(*giclp
)->cline
);
354 if((*giclp
)->next
) ical_free_gencline((void **) &(*giclp
)->next
);
355 fs_give((void **)giclp
);
359 ical_free_vcalendar(void **vcalpv
)
361 VCALENDAR_S
**vcalp
= (VCALENDAR_S
**)vcalpv
;
363 if(vcalp
== NULL
|| *vcalp
== NULL
) return;
365 if((*vcalp
)->prodid
) ical_free_cline((void **) &(*vcalp
)->prodid
);
366 if((*vcalp
)->version
) ical_free_cline((void **) &(*vcalp
)->version
);
367 if((*vcalp
)->calscale
) ical_free_cline((void **) &(*vcalp
)->calscale
);
368 if((*vcalp
)->method
) ical_free_cline((void **) &(*vcalp
)->method
);
369 if((*vcalp
)->uk_prop
) ical_free_gencline((void **) &(*vcalp
)->uk_prop
);
372 for(i
= 0; i
< VUnknown
; i
++)
373 if((*vcalp
)->comp
[i
]) (ical_comp
[i
].give
)(&(*vcalp
)->comp
[i
]);
374 fs_give((void **) &(*vcalp
)->comp
);
376 if((*vcalp
)->uk_comp
) ical_free_unknown_comp(&(*vcalp
)->uk_comp
);
381 ical_free_vevent(void **veventpv
)
383 VEVENT_S
**veventp
= (VEVENT_S
**) veventpv
;
385 if(veventp
== NULL
|| *veventp
== NULL
) return;
387 ical_free_prop(&(*veventp
)->prop
, event_prop
, EvUnknown
);
388 if((*veventp
)->uk_prop
) ical_free_gencline((void **) &(*veventp
)->uk_prop
);
389 if((*veventp
)->valarm
) ical_free_valarm((void **) &(*veventp
)->valarm
);
390 if((*veventp
)->next
) ical_free_vevent((void **) &(*veventp
)->next
);
395 ical_fs_give(void **x
)
397 if(x
!= NULL
&& *x
!= NULL
)
402 ical_free_rrule(void **rrulepv
)
404 RRULE_S
**rrulep
= (RRULE_S
**) rrulepv
;
406 if(rrulep
&& *rrulep
){
407 ical_free_prop(&(*rrulep
)->prop
, rrule_prop
, RRUnknown
);
408 ical_free_param(&(*rrulep
)->param
);
414 ical_free_weekday_list(void **wkdylv
)
416 BYWKDY_S
**wkdyl
= (BYWKDY_S
**) wkdylv
;
418 if(wkdyl
== NULL
) return;
421 ical_free_weekday_list((void **) &(*wkdyl
)->next
);
428 ical_free_vtodo(void **vtodopv
)
433 ical_free_vjournal(void **vjournalpv
)
438 ical_free_vfreebusy(void **vfbpv
)
443 ical_free_prop(void ***propv
, ICAL_PROP_S
*aux_comp
, int max
)
447 if(propv
== NULL
|| *propv
== NULL
) return;
449 for(i
= 0; i
< max
; i
++)
451 for(j
= 0; aux_comp
[j
].prop
!= NULL
&& aux_comp
[j
].pos
!= i
; j
++);
452 if(aux_comp
[j
].give
) (aux_comp
[j
].give
)(&(*propv
)[i
]);
454 fs_give((void **) propv
);
459 ical_free_vtimezone(void **vtzpv
)
461 VTIMEZONE_S
**vtzp
= (VTIMEZONE_S
**) vtzpv
;
464 if(vtzp
== NULL
|| *vtzp
== NULL
) return;
466 ical_free_prop(&(*vtzp
)->prop
, tz_comp
, TZCUnknown
);
467 if((*vtzp
)->uk_prop
) ical_free_gencline((void **) &(*vtzp
)->uk_prop
);
468 if((*vtzp
)->standardc
) ical_free_timezone((void **) &(*vtzp
)->standardc
);
469 if((*vtzp
)->daylightc
) ical_free_timezone((void **) &(*vtzp
)->daylightc
);
474 ical_free_timezone(void **tzpv
)
476 ICAL_TZPROP_S
**tzp
= (ICAL_TZPROP_S
**) tzpv
;
478 if(tzp
== NULL
|| *tzp
== NULL
) return;
480 ical_free_prop(&(*tzp
)->prop
, tz_prop
, TZPUnknown
);
481 if((*tzp
)->uk_prop
) ical_free_gencline((void **) &(*tzp
)->uk_prop
);
482 if((*tzp
)->next
) ical_free_timezone((void **) &(*tzp
)->next
);
487 ical_free_valarm(void **valarmpv
)
489 VALARM_S
**valarmp
= (VALARM_S
**) valarmpv
;
492 if(valarmp
== NULL
|| *valarmp
== NULL
) return;
494 ical_free_prop(&(*valarmp
)->prop
, alarm_prop
, AlUnknown
);
495 if((*valarmp
)->uk_prop
) ical_free_gencline((void **) &(*valarmp
)->uk_prop
);
496 if((*valarmp
)->next
) ical_free_timezone((void **) &(*valarmp
)->next
);
501 ical_free_unknown_comp(ICAL_S
**icalp
)
504 if(icalp
== NULL
|| *icalp
== NULL
) return;
505 for(i
= 0; ical_comp
[i
].comp
&& strucmp((*icalp
)->comp
,ical_comp
[i
].comp
); i
++);
506 if(ical_comp
[i
].give
)
507 (ical_comp
[i
].give
)(&(*icalp
)->value
);
509 ical_free_gencline((void **) &(*icalp
)->value
);
510 fs_give((void **)&(*icalp
)->comp
);
511 ical_free_unknown_comp(&(*icalp
)->next
);
512 ical_free_unknown_comp(&(*icalp
)->branch
);
513 fs_give((void **)icalp
);
517 ical_unfold_line(char *line
)
524 for(i
= 0, j
= 0; line
[j
] != '\0';)
526 case '\r': if(line
[j
+1] == '\n' && ical_wspace(line
[j
+2])){
527 j
+= 3; /* get past white space */
530 case '\n': if(ical_wspace(line
[j
+1])){
531 j
+= 2; /* get past white space */
534 default : line
[i
++] = line
[j
++];
541 ical_get_parameter(char **line
)
543 ICAL_PARAMETER_S
*param
= NULL
;
546 if(line
== NULL
|| *line
== NULL
)
549 for(s
= *line
; s
&& *s
&& ical_name_allowed_char(*s
) ; s
++);
555 param
= fs_get(sizeof(ICAL_PARAMETER_S
));
556 memset((void *)param
, 0, sizeof(ICAL_PARAMETER_S
));
558 param
->name
= cpystr(*line
);
560 *line
= s
+1; /* step over '=' */
561 quoted
= **line
== '"' ? 1 : 0;
563 for(s
= ++*line
; s
&& *s
&& ical_qsafe_char((unsigned char) *s
); s
++);
564 if(*s
!= '"'){ /* error, do not parse this line */
565 ical_free_param(¶m
);
566 *line
= strchr(s
, ':'); /* reset line to closest ':' */
571 for(s
= *line
; s
&& *s
&& (ical_safe_char((unsigned char) *s
)); s
++);
574 param
->value
= cpystr(*line
);
575 *s
= c
; /* restore character */
576 *line
= quoted
? s
+ 1 : s
;
580 param
->next
= ical_get_parameter(line
);
587 ical_get_value(char **line
)
591 if(line
== NULL
|| *line
== NULL
)
594 for (s
= *line
; *s
&& ical_value_char((unsigned char) *s
); s
++);
603 s
= strchr(*line
, '\r');
611 ical_parameter_cpy(ICAL_PARAMETER_S
*param
)
613 ICAL_PARAMETER_S
*rv
;
615 if(param
== NULL
) return NULL
;
617 rv
= fs_get(sizeof(ICAL_PARAMETER_S
));
618 memset((void *)rv
, 0, sizeof(ICAL_PARAMETER_S
));
620 if(param
->name
) rv
->name
= cpystr(param
->name
);
621 if(param
->value
) rv
->value
= cpystr(param
->value
);
622 if(param
->next
) rv
->next
= ical_parameter_cpy(param
->next
);
628 ical_cline_cpy(ICLINE_S
*icl
)
635 rv
= fs_get(sizeof(ICLINE_S
));
636 memset((void *)rv
, 0, sizeof(ICLINE_S
));
638 if(icl
->token
) rv
->token
= cpystr(icl
->token
);
639 if(icl
->param
) rv
->param
= ical_parameter_cpy(icl
->param
);
640 if(icl
->value
) rv
->value
= cpystr(icl
->value
);
645 /* Given a \r\n-ending line (called *text), isolate the occurrence
646 * of the token in that line.
647 * Return the token, and modify the pointer to *text to point to the
648 * end of the token. Modify sep to contain the character following
650 * ical-line = token ':'/';' rest of the line\r\n
651 * on error return null, and set *text to the next line, if possible.
654 ical_isolate_token(char **text
, char *sep
)
658 for(t
= s
= *text
; *t
&& ical_name_allowed_char(*s
); s
++);
659 /* only followed by parameter or value */
660 if(*s
== ':' || *s
== ';'){
662 *s
= '\0'; /* isolate token at pointer s */
665 else{ /* bad data - bail out of here */
667 if(*s
== '\0' || (s
= strstr(s
, "\r\n")) == NULL
)
669 else /* move to next line */
677 ical_parse_text(char *text
)
680 VCALENDAR_S
*vcal
= NULL
;
682 ical_debug("ical_parse_text", text
);
685 text
= ical_unfold_line(text
);
686 for(s
= text
; s
&& *s
!= '\0'; s
++){
687 if(*s
!= 'B' && *s
!= 'b')
689 if(!struncmp(s
+1, "EGIN:VCALENDAR\r\n", 16)){
690 s
+= 17; /* 17 = strlen("BEGIN:VCALENDAR\r\n") */
691 vcal
= (VCALENDAR_S
*) ical_parse_vcalendar(&s
);
699 ical_parse_time(void *ic_datep
, char **text
, char *token
)
704 datep
= fs_get(sizeof(struct tm
));
705 icl
= ical_parse_line(text
, token
);
706 ical_parse_date(icl
->value
, datep
);
707 ical_free_cline((void **) &icl
);
708 ic_datep
= (void *) datep
;
714 ical_parse_interval(void *longvp
, char *value
)
717 unsigned long *longp
;
719 longp
= fs_get(sizeof(unsigned long));
720 *longp
= atoi(value
);
721 longvp
= (void *) longp
;
728 ical_parse_offset(void *offsetv
, char **text
, char *token
)
734 offset
= fs_get(sizeof(int));
736 icl
= ical_parse_line(text
, token
);
738 if(*icl
->value
== '+' || *icl
->value
== '-')
739 value
= icl
->value
+ 1;
743 h
= ical_get_number_value(value
, 0, 2);
744 m
= ical_get_number_value(value
, 2, 4);
746 *offset
= 60*(60*h
+ m
);
747 if(*icl
->value
== '-')
750 ical_free_cline((void **) &icl
);
751 offsetv
= (void *) offset
;
756 /* This function processes the information in *text, and returns
757 * a pointer to the information in iclp, but only if iclp is NULL
758 * otherwise, it simply returns the current value and advances the
760 * Call this function as follows
761 * rv = (cast here *) ical_cline_from_token((void *)rv, &text, token);
764 ical_cline_from_token(void *iclp
, char **text
, char *token
)
768 ical_debug("ical_cline_from_token", *text
);
770 icl
= ical_parse_line(text
, token
);
773 ical_free_cline((void **)&icl
);
781 ical_gencline_from_token(void *giclv
, char **text
, char *token
)
783 GEN_ICLINE_S
*gicl
= NULL
;
785 if(!struncmp(*text
, token
, strlen(token
))){
786 gicl
= fs_get(sizeof(GEN_ICLINE_S
));
787 memset((void *) gicl
, 0, sizeof(GEN_ICLINE_S
));
788 gicl
->cline
= ical_parse_line(text
, token
);
789 // gicl->line = (ICLINE_S *) ical_cline_from_token((void *) gicl->cline, text, token);
790 gicl
->next
= (GEN_ICLINE_S
*) ical_gencline_from_token((void *) gicl
->next
, text
, token
);
794 ical_free_gencline((void **) &gicl
);
796 giclv
= (void *) gicl
;
802 *** PARSE COMPONENT FUNCTIONS
806 ical_parse_vcalendar(char **text
)
813 dprint((9, "ical_parse_vcalendar:\n"));
814 ical_debug("ical_parse_vcalendar", *text
);
816 vcal
= fs_get(sizeof(VCALENDAR_S
));
817 memset((void *) vcal
, 0, sizeof(VCALENDAR_S
));
819 /* s must always point the the beginning of a line */
820 for(s
= *text
; s
&& *s
!= '\0';){
822 s
= ical_isolate_token(&t
, &c
);
829 *t
= c
; /* restore character */
830 if(s
){ /* figure out the token */
831 int ukn
= 0; /* unknown token */
835 case 'b': if(!struncmp(s
+1, "EGIN", 4)){
836 s
+= 6; /* 6 = strlen("BEGIN:") */
837 for(i
= 0; ical_comp
[i
].comp
838 && (struncmp(s
, ical_comp
[i
].comp
, ical_comp
[i
].len
)
839 || struncmp(s
+ ical_comp
[i
].len
, "\r\n", 2)); i
++);
841 if(ical_comp
[i
].parse
){
842 s
+= ical_comp
[i
].len
+ 2;
843 v
= (ical_comp
[i
].parse
)(&s
);
844 if(vcal
->comp
== NULL
){
845 vcal
->comp
= fs_get((VUnknown
+1)*sizeof(void *));
846 memset((void *) vcal
->comp
, 0, (VUnknown
+1)*sizeof(void *));
849 if(vcal
->comp
[ical_comp
[i
].pos
] == NULL
)
850 vcal
->comp
[ical_comp
[i
].pos
] = v
;
852 if((vcal
->method
&& vcal
->method
->value
853 && strucmp(vcal
->method
->value
, "PUBLISH"))
854 || struncmp(ical_comp
[i
].comp
, "VEVENT", 6))
855 (ical_comp
[i
].give
)(&v
);
857 VEVENT_S
*vevent
= (VEVENT_S
*) vcal
->comp
[VEvent
];
858 for(; vevent
&& vevent
->next
; vevent
= vevent
->next
);
863 v
= (void *) ical_parse_unknown_comp(&s
, 0);
864 if(vcal
->uk_comp
== NULL
)
865 vcal
->uk_comp
= (ICAL_S
*) v
;
868 for(ic
= vcal
->uk_comp
; ic
&& ic
->branch
; ic
= ic
->branch
);
869 ic
->branch
= (ICAL_S
*) v
;
876 case 'c': if(!struncmp(s
+1, "ALSCALE", 7)){
877 v
= (void *) vcal
->calscale
;
878 v
= ical_cline_from_token(v
, &s
, "CALSCALE");
879 vcal
->calscale
= (ICLINE_S
*) v
;
885 case 'e': if(!struncmp(s
+1, "ND", 2)){
887 s
+= 4; /* 4 = strlen("END:") */
888 if(!struncmp(s
, "VCALENDAR\r\n", 11)){
889 *text
= s
+ 11; /* 11 = strlen("VCALENDAR\r\n") */
890 return (void *) vcal
;
892 // else ukn++; FIX THIS, this is not quite right
897 case 'm': if(!struncmp(s
+1, "ETHOD", 5)){
898 v
= (void *) vcal
->method
;
899 v
= ical_cline_from_token(v
, &s
, "METHOD");
900 vcal
->method
= (ICLINE_S
*) v
;
906 case 'p': if(!struncmp(s
+1, "RODID", 5)){
907 v
= (void *) vcal
->prodid
;
908 v
= ical_cline_from_token(v
, &s
, "PRODID");
909 vcal
->prodid
= (ICLINE_S
*) v
;
915 case 'v': if(!struncmp(s
+1, "ERSION", 6)){
916 v
= (void *) vcal
->version
;
917 v
= ical_cline_from_token(v
, &s
, "VERSION");
918 vcal
->version
= (ICLINE_S
*) v
;
924 } /* end of switch(*s) */
926 if(ical_buf_len
< t
- s
){
927 fs_resize((void **)&ical_buf
, t
-s
+1);
933 if(vcal
->uk_prop
== NULL
){
934 vcal
->uk_prop
= fs_get(sizeof(GEN_ICLINE_S
));
935 memset((void *)vcal
->uk_prop
, 0, sizeof(GEN_ICLINE_S
));
936 vcal
->uk_prop
->cline
= ical_parse_line(&s
, ical_buf
);
940 for (gcl
= vcal
->uk_prop
; gcl
&& gcl
->next
; gcl
= gcl
->next
);
941 gcl
->next
= fs_get(sizeof(GEN_ICLINE_S
));
942 memset((void *)gcl
->next
, 0, sizeof(GEN_ICLINE_S
));
943 gcl
->next
->cline
= ical_parse_line(&s
, ical_buf
);
951 /* ok, we have parsed the vcalendar, now parse some special properties */
952 /* start by parsing dates */
953 ical_set_date_vevent(vcal
->comp
[VEvent
], vcal
->comp
[VTimeZone
]);
954 return (void *) vcal
;
958 ical_parse_vevent(char **text
)
964 ical_debug("ical_parse_vevent", *text
);
965 vevent
= fs_get(sizeof(VEVENT_S
));
966 memset((void *)vevent
, 0, sizeof(VEVENT_S
));
968 /* s must always point the the beginning of a line */
969 for(s
= *text
; s
&& *s
!= '\0';){
971 s
= ical_isolate_token(&t
, &c
);
977 *t
= c
; /* restore separator */
979 if(s
){ /* figure out the token */
980 int ukn
= 0; /* unknown token */
981 if(!struncmp(s
, "BEGIN", 5)){
982 s
+= 6; /* 6 = strlen("BEGIN:") */
983 if(!struncmp(s
, "VALARM\r\n", 8)){
984 s
+= 8; /* 8 = strlen("VALARM\r\n"); */
985 if(vevent
->valarm
== NULL
)
986 vevent
->valarm
= ical_parse_valarm(&s
);
989 for(valrm
= vevent
->valarm
; valrm
&& valrm
->next
;
990 valrm
= valrm
->next
);
991 valrm
->next
= ical_parse_valarm(&s
);
994 ICAL_S
*uk_comp
= ical_parse_unknown_comp(&s
, 0);
995 ical_free_unknown_comp(&uk_comp
);
997 } else if(!struncmp(s
, "END", t
-s
-1)){
998 s
+= 4; /* 4 = strlen("END:") */
999 if(!struncmp(s
, "VEVENT\r\n",8)){
1000 *text
= s
+ 8; /* 8 = strlen("VCALENDAR\r\n") */
1001 return (void *) vevent
;
1003 } else{ Event_prop i
;
1004 for(i
= 0; i
< EvUnknown
; i
++)
1005 if(!struncmp(s
, event_prop
[i
].prop
, t
-s
))
1007 if(event_prop
[i
].parse
){
1009 if(vevent
->prop
== NULL
){
1010 vevent
->prop
= fs_get((EvUnknown
+1)*sizeof(void *));
1011 memset((void *)vevent
->prop
, 0, (EvUnknown
+1)*sizeof(void *));
1013 v
= vevent
->prop
[event_prop
[i
].pos
];
1014 v
= (event_prop
[i
].parse
)(v
, &s
, event_prop
[i
].prop
);
1015 vevent
->prop
[event_prop
[i
].pos
] = v
;
1022 if(ical_buf_len
< t
- s
){
1023 fs_resize((void **)&ical_buf
, t
-s
+1);
1027 strcpy(ical_buf
, s
);
1029 if(vevent
->uk_prop
== NULL
){
1030 vevent
->uk_prop
= fs_get(sizeof(GEN_ICLINE_S
));
1031 memset((void *)vevent
->uk_prop
, 0, sizeof(GEN_ICLINE_S
));
1032 vevent
->uk_prop
->cline
= ical_parse_line(&s
, ical_buf
);
1036 for (gcl
= vevent
->uk_prop
; gcl
&& gcl
->next
; gcl
= gcl
->next
);
1037 gcl
->next
= fs_get(sizeof(GEN_ICLINE_S
));
1038 memset((void *)gcl
->next
, 0, sizeof(GEN_ICLINE_S
));
1039 gcl
->next
->cline
= ical_parse_line(&s
, ical_buf
);
1042 } /* end of if(s) */
1046 return (void *) vevent
;
1050 ical_parse_vtimezone(char **text
)
1057 ical_debug("ical_parse_vtimezone", *text
);
1058 vtz
= fs_get(sizeof(VTIMEZONE_S
));
1059 memset((void *)vtz
, 0, sizeof(VTIMEZONE_S
));
1061 /* s must always point the the beginning of a line */
1062 for(s
= *text
; s
&& *s
!= '\0';){
1064 s
= ical_isolate_token(&t
, &c
);
1070 *t
= c
; /* restore separator */
1072 if(s
){ /* figure out the token */
1073 int ukn
= 0; /* unknown token */
1074 if(!struncmp(s
, "BEGIN", 5)){
1075 s
+= 6; /* 6 = strlen("BEGIN:") */
1076 if(!struncmp(s
, "STANDARD\r\n", 10)){
1077 s
+= 10; /* 10 = strlen("STANDARD\r\n"); */
1078 v
= ical_parse_timezone(&s
);
1079 if(vtz
->standardc
== NULL
)
1080 vtz
->standardc
= (ICAL_TZPROP_S
*) v
;
1083 for(dl
= vtz
->standardc
; dl
&& dl
->next
; dl
= dl
->next
);
1084 dl
->next
= (ICAL_TZPROP_S
*) v
;
1086 } else if(!struncmp(s
, "DAYLIGHT\r\n", 10)){
1087 s
+= 10; /* 10 = strlen("DAYLIGHT\r\n"); */
1088 v
= ical_parse_timezone(&s
);
1089 if(vtz
->daylightc
== NULL
)
1090 vtz
->daylightc
= (ICAL_TZPROP_S
*) v
;
1093 for(dl
= vtz
->daylightc
; dl
&& dl
->next
; dl
= dl
->next
);
1094 dl
->next
= (ICAL_TZPROP_S
*) v
;
1097 ICAL_S
*uk_comp
= ical_parse_unknown_comp(&s
, 0);
1098 ical_free_unknown_comp(&uk_comp
);
1100 } else if(!struncmp(s
, "END", t
-s
-1)){
1101 s
+= 4; /* 4 = strlen("END:") */
1102 if(!struncmp(s
, "VTIMEZONE\r\n",11)){
1103 *text
= s
+ 11; /* 11 = strlen("VTIMEZONE\r\n") */
1104 return (void *) vtz
;
1107 for(i
= 0; i
< TZCUnknown
; i
++)
1108 if(!struncmp(s
, tz_comp
[i
].prop
, t
-s
))
1110 if(tz_comp
[i
].parse
){
1112 if(vtz
->prop
== NULL
){
1113 vtz
->prop
= fs_get(TZCUnknown
*sizeof(void *));
1114 memset((void *)vtz
->prop
, 0, TZCUnknown
*sizeof(void *));
1116 v
= vtz
->prop
[tz_comp
[i
].pos
];
1117 v
= (tz_comp
[i
].parse
)(v
, &s
, tz_comp
[i
].prop
);
1118 vtz
->prop
[tz_comp
[i
].pos
] = v
;
1125 if(ical_buf_len
< t
- s
){
1126 fs_resize((void **)&ical_buf
, t
-s
+1);
1130 strcpy(ical_buf
, s
);
1132 if(vtz
->uk_prop
== NULL
){
1133 vtz
->uk_prop
= fs_get(sizeof(GEN_ICLINE_S
));
1134 memset((void *)vtz
->uk_prop
, 0, sizeof(GEN_ICLINE_S
));
1135 vtz
->uk_prop
->cline
= ical_parse_line(&s
, ical_buf
);
1139 for (gcl
= vtz
->uk_prop
; gcl
&& gcl
->next
; gcl
= gcl
->next
);
1140 gcl
->next
= fs_get(sizeof(GEN_ICLINE_S
));
1141 memset((void *)gcl
->next
, 0, sizeof(GEN_ICLINE_S
));
1142 gcl
->next
->cline
= ical_parse_line(&s
, ical_buf
);
1145 } /* end of if(s) */
1149 return (void *) vtz
;
1153 ical_parse_timezone(char **text
)
1157 ICAL_TZPROP_S
*tzprop
;
1159 ical_debug("ical_parse_timezone", *text
);
1160 tzprop
= fs_get(sizeof(ICAL_TZPROP_S
));
1161 memset((void *)tzprop
, 0, sizeof(ICAL_TZPROP_S
));
1163 /* s must always point the the beginning of a line */
1164 for(s
= *text
; s
&& *s
!= '\0';){
1166 s
= ical_isolate_token(&t
, &c
);
1172 *t
= c
; /* restore separator */
1174 if(s
){ /* figure out the token */
1175 int ukn
= 0; /* unknown token */
1176 if(!struncmp(s
, "BEGIN", 5)){
1178 s
+= 6; /* 6 = strlen("BEGIN:") */
1179 uk_comp
= ical_parse_unknown_comp(&s
, 0);
1180 ical_free_unknown_comp(&uk_comp
);
1181 } else if(!struncmp(s
, "END", t
-s
-1)){
1182 s
+= 4; /* 4 = strlen("END:") */
1183 if(!struncmp(s
, "STANDARD\r\n", 10)
1184 || !struncmp(s
, "DAYLIGHT\r\n", 10)){
1185 *text
= s
+ 10; /* 10 = strlen("STANDARD\r\n") */
1186 return (void *) tzprop
;
1189 for(i
= 0; i
< TZPUnknown
; i
++)
1190 if(!struncmp(s
, tz_prop
[i
].prop
, t
-s
))
1192 if(tz_prop
[i
].parse
){
1194 if(tzprop
->prop
== NULL
){
1195 tzprop
->prop
= fs_get(TZPUnknown
*sizeof(void *));
1196 memset((void *)tzprop
->prop
, 0, TZPUnknown
*sizeof(void *));
1198 v
= tzprop
->prop
[tz_prop
[i
].pos
];
1199 v
= (tz_prop
[i
].parse
)(v
, &s
, tz_prop
[i
].prop
);
1200 tzprop
->prop
[tz_prop
[i
].pos
] = v
;
1207 if(ical_buf_len
< t
- s
){
1208 fs_resize((void **)&ical_buf
, t
-s
+1);
1212 strcpy(ical_buf
, s
);
1214 if(tzprop
->uk_prop
== NULL
){
1215 tzprop
->uk_prop
= fs_get(sizeof(GEN_ICLINE_S
));
1216 memset((void *)tzprop
->uk_prop
, 0, sizeof(GEN_ICLINE_S
));
1217 tzprop
->uk_prop
->cline
= ical_parse_line(&s
, ical_buf
);
1221 for (gcl
= tzprop
->uk_prop
; gcl
&& gcl
->next
; gcl
= gcl
->next
);
1222 gcl
->next
= fs_get(sizeof(GEN_ICLINE_S
));
1223 memset((void *)gcl
->next
, 0, sizeof(GEN_ICLINE_S
));
1224 gcl
->next
->cline
= ical_parse_line(&s
, ical_buf
);
1227 } /* end of if(s) */
1231 return (void *) tzprop
;
1235 ical_parse_valarm(char **text
)
1241 ical_debug("ical_parse_valarm", *text
);
1242 valarm
= fs_get(sizeof(VALARM_S
));
1243 memset((void *)valarm
, 0, sizeof(VALARM_S
));
1245 /* s must always point the the beginning of a line */
1246 for(s
= *text
; s
&& *s
!= '\0';){
1248 s
= ical_isolate_token(&t
, &c
);
1254 *t
= c
; /* restore separator */
1256 if(s
){ /* figure out the token */
1257 int ukn
= 0; /* unknown token */
1258 if(!struncmp(s
, "BEGIN", 5)){
1260 s
+= 6; /* 6 = strlen("BEGIN:") */
1261 uk_comp
= ical_parse_unknown_comp(&s
, 0);
1262 ical_free_unknown_comp(&uk_comp
);
1263 } else if(!struncmp(s
, "END", t
-s
-1)){
1264 s
+= 4; /* 4 = strlen("END:") */
1265 if(!struncmp(s
, "VALARM\r\n", 8)){
1266 *text
= s
+ 8; /* 8 = strlen("VALARM\r\n") */
1267 return (void *) valarm
;
1269 } else{ Alarm_prop i
;
1270 for(i
= 0; i
< AlUnknown
; i
++)
1271 if(!struncmp(s
, alarm_prop
[i
].prop
, t
-s
))
1273 if(alarm_prop
[i
].parse
){
1275 if(valarm
->prop
== NULL
){
1276 valarm
->prop
= fs_get((AlUnknown
+1)*sizeof(void *));
1277 memset((void *)valarm
->prop
, 0, (AlUnknown
+1)*sizeof(void *));
1279 v
= valarm
->prop
[alarm_prop
[i
].pos
];
1280 v
= (alarm_prop
[i
].parse
)(v
, &s
, alarm_prop
[i
].prop
);
1281 valarm
->prop
[alarm_prop
[i
].pos
] = v
;
1288 if(ical_buf_len
< t
- s
){
1289 fs_resize((void **)&ical_buf
, t
-s
+1);
1293 strcpy(ical_buf
, s
);
1295 if(valarm
->uk_prop
== NULL
){
1296 valarm
->uk_prop
= fs_get(sizeof(GEN_ICLINE_S
));
1297 memset((void *)valarm
->uk_prop
, 0, sizeof(GEN_ICLINE_S
));
1298 valarm
->uk_prop
->cline
= ical_parse_line(&s
, ical_buf
);
1302 for (gcl
= valarm
->uk_prop
; gcl
&& gcl
->next
; gcl
= gcl
->next
);
1303 gcl
->next
= fs_get(sizeof(GEN_ICLINE_S
));
1304 memset((void *)gcl
->next
, 0, sizeof(GEN_ICLINE_S
));
1305 gcl
->next
->cline
= ical_parse_line(&s
, ical_buf
);
1308 } /* end of if(s) */
1312 return (void *) valarm
;
1316 ical_parse_vtodo(char **text
)
1322 ical_parse_vjournal(char **text
)
1328 ical_parse_vfreebusy(char **text
)
1334 ical_parse_generic_comp(char **text
, int level
)
1339 GEN_ICLINE_S
*gcl
= NULL
;
1342 ical_debug("ical_parse_generic_comp", *text
);
1343 ical
= fs_get(sizeof(ICAL_S
));
1344 memset((void *)ical
, 0, sizeof(ICAL_S
));
1346 ical
->comp
= ical_get_value(text
);
1347 token
= fs_get(strlen(ical
->comp
) + 2 + 1);
1348 sprintf(token
, "%s\r\n", ical
->comp
); /* this is allocated memory */
1350 /* s must always point the the beginning of a line */
1351 for(s
= *text
; s
&& *s
!= '\0';){
1353 s
= ical_isolate_token(&t
, &c
);
1360 *t
= c
; /* restore character */
1361 if(s
){ /* figure out the token */
1362 int ukn
= 0; /* unknown token */
1365 case 'b': if(!struncmp(s
+1, "EGIN", 4)){
1366 s
+= 6; /* 6 = strlen("BEGIN:") */
1367 if(ical
->next
== NULL
)
1368 ical
->next
= ical_parse_unknown_comp(&s
, level
+1);
1373 for(i
= 0, b
= ical
; i
<= level
&& b
&& b
->next
; b
= b
->next
, i
++);
1374 if(b
->branch
== NULL
)
1375 b
->branch
= ical_parse_unknown_comp(&s
, level
+1);
1377 for(; b
&& b
->branch
; b
= b
->branch
);
1378 b
->branch
= ical_parse_unknown_comp(&s
, level
+1);
1385 case 'e': if(!struncmp(s
+1, "ND", 2)){
1387 s
+= 4; /* 4 = strlen("END:") */
1388 if(!struncmp(s
, token
, strlen(token
))){
1389 *text
= s
+ strlen(token
);
1390 ical
->value
= (void *) gcl
;
1398 } /* end of switch(*s) */
1400 if(ical_buf_len
< t
- s
){
1401 fs_resize((void **)&ical_buf
, t
-s
+1);
1405 strcpy(ical_buf
, s
);
1408 gcl
= fs_get(sizeof(GEN_ICLINE_S
));
1409 memset((void *)gcl
, 0, sizeof(GEN_ICLINE_S
));
1410 gcl
->cline
= ical_parse_line(&s
, ical_buf
);
1413 GEN_ICLINE_S
*gencl
;
1414 for (gencl
= gcl
; gencl
&& gencl
->next
; gencl
= gencl
->next
);
1415 gencl
->next
= fs_get(sizeof(GEN_ICLINE_S
));
1416 memset((void *)gencl
->next
, 0, sizeof(GEN_ICLINE_S
));
1417 gencl
->next
->cline
= ical_parse_line(&s
, ical_buf
);
1420 } /* end of if(s) */
1423 ical
->value
= (void *) gcl
;
1429 ical_parse_unknown_comp(char **text
, int level
)
1434 ical_debug("ical_parse_unknown_comp", *text
);
1435 for(i
= 0; ical_comp
[i
].comp
1436 && (struncmp(*text
, ical_comp
[i
].comp
, ical_comp
[i
].len
)
1437 || struncmp(*text
+ ical_comp
[i
].len
, "\r\n", 2)); i
++);
1439 if(ical_comp
[i
].parse
){
1440 *text
+= ical_comp
[i
].len
+ 2;
1441 ical
= fs_get(sizeof(ICAL_S
));
1442 memset((void *)ical
, 0, sizeof(ICAL_S
));
1443 ical
->comp
= cpystr(ical_comp
[i
].comp
);
1444 ical
->value
= (ical_comp
[i
].parse
)(text
);
1446 ical
= ical_parse_generic_comp(text
, level
);
1452 ical_parse_line(char **text
, char *name
)
1457 ic
= fs_get(sizeof(ICLINE_S
));
1458 memset((void *)ic
, 0, sizeof(ICLINE_S
));
1460 ic
->token
= cpystr(name
);
1464 ic
->param
= ical_get_parameter(&s
);
1468 ic
->value
= ical_get_value(&s
);
1476 *** PARSE PROPERTY FUNCTIONS
1480 ical_parse_freq(void *fvalp
, char *text
)
1484 fval
= fs_get(sizeof(Freq_value
));
1488 if(text
== NULL
) return fvalp
;
1490 if(!strucmp(text
, "SECONDLY")) *fval
= FSecondly
;
1491 else if(!strucmp(text
, "MINUTELY")) *fval
= FMinutely
;
1492 else if(!strucmp(text
, "HOURLY")) *fval
= FHourly
;
1493 else if(!strucmp(text
, "DAILY")) *fval
= FDaily
;
1494 else if(!strucmp(text
, "WEEKLY")) *fval
= FWeekly
;
1495 else if(!strucmp(text
, "MONTHLY")) *fval
= FMonthly
;
1496 else if(!strucmp(text
, "YEARLY")) *fval
= FYearly
;
1498 fvalp
= (void *) fval
;
1504 ical_parse_until(void *Tmp
, char *text
)
1509 Tm
= fs_get(sizeof(struct tm
));
1510 ical_parse_date(text
, Tm
);
1518 ical_parse_count(void *countp
, char *text
)
1523 count
= fs_get(sizeof(int));
1524 *count
= atoi(text
);
1525 countp
= (void *) count
;
1532 ical_parse_weekday_list(void *bywkdyp
, char *wklist
)
1534 BYWKDY_S
*bywkdy
, *w
;
1540 bywkdyp
= (void *) bywkdy
;
1542 if(wklist
== NULL
) return bywkdyp
;
1545 for(t
= s
= wklist
; done
== 0; s
++){
1546 if(*s
!= ',' && *s
!= '\0')
1551 else /* c == '\0' */
1555 for(w
= bywkdy
; w
&& w
->next
; w
= w
->next
);
1556 w
= fs_get(sizeof(BYWKDY_S
));
1557 memset((void *)w
, 0, sizeof(BYWKDY_S
));
1558 if(!strucmp(t
+len
-2, "SU")) w
->wd
= Sunday
;
1559 else if(!strucmp(t
+len
-2, "MO")) w
->wd
= Monday
;
1560 else if(!strucmp(t
+len
-2, "TU")) w
->wd
= Tuesday
;
1561 else if(!strucmp(t
+len
-2, "WE")) w
->wd
= Wednesday
;
1562 else if(!strucmp(t
+len
-2, "TH")) w
->wd
= Thursday
;
1563 else if(!strucmp(t
+len
-2, "FR")) w
->wd
= Friday
;
1564 else if(!strucmp(t
+len
-2, "SA")) w
->wd
= Saturday
;
1565 // t[len - 2] = '\0';
1567 w
->value
= strtoul(t
, &t
, 10);
1577 ical_free_weekday_list((void **)&bywkdy
);
1579 bywkdyp
= (void *) bywkdy
;
1585 ical_parse_number_list(void *bynop
, char *nolist
)
1592 bynop
= (void *) byno
;
1594 if(nolist
== NULL
) return bynop
;
1596 for(t
= s
= nolist
; done
== 0; s
++){
1597 if(*s
!= ',' && *s
!= '\0')
1602 else /* c == '\0' */
1605 for(n
= byno
; n
&& n
->next
; n
= n
->next
);
1606 n
= fs_get(sizeof(BYWKDY_S
));
1607 memset((void *)n
, 0, sizeof(BYWKDY_S
));
1608 n
->value
= strtoul(t
, &t
, 10);
1617 ical_free_weekday_list((void **)&byno
);
1619 bynop
= (void *) byno
;
1625 ical_parse_rrule(void *rrulep
, char **text
, char *token
)
1630 ICAL_PARAMETER_S
*param
, *p
;
1633 if(text
== NULL
|| *text
== NULL
|| struncmp(*text
, "RRULE", 5))
1636 rrule
= fs_get(sizeof(RRULE_S
));
1637 memset((void *) rrule
, 0, sizeof(RRULE_S
));
1639 /* recurring rules are special. First, we parse the icline that contains it */
1640 icl
= ical_parse_line(text
, token
);
1642 /* now we copy the parameters that it contains */
1643 rrule
->param
= ical_parameter_cpy(icl
->param
);
1645 /* then we parse icl->value as if it was a parameter */
1647 param
= ical_get_parameter(&s
);
1649 /* now we check which values were given, and fill the prop array */
1650 rrule
->prop
= fs_get((RRUnknown
+1)*sizeof(void *));
1651 memset((void *) rrule
->prop
, 0, (RRUnknown
+1)*sizeof(void *));
1653 for(p
= param
; p
!= NULL
; p
= p
->next
){
1654 for(i
= 0; rrule_prop
[i
].prop
!= NULL
&& strucmp(p
->name
, rrule_prop
[i
].prop
); i
++);
1655 if(rrule_prop
[i
].parse
){
1656 void *v
= rrule
->prop
[rrule_prop
[i
].pos
];
1657 v
= (rrule_prop
[i
].parse
)(v
, p
->value
);
1658 rrule
->prop
[rrule_prop
[i
].pos
] = v
;
1661 rrule
->prop
[RRUnknown
] = NULL
;
1663 ical_free_param(¶m
);
1664 ical_free_cline((void **)&icl
);
1667 ical_free_rrule((void **)&rrule
);
1669 rrulep
= (void *) rrule
;
1674 /*** UTF-8 for ICAL ***/
1677 ical_non_ascii_valid(unsigned char c
)
1679 static unsigned char icu
[6];
1680 static int utf8_len
= 0;
1681 static int utf8_type
= 0;
1685 utf8_type
= (c
>= 0xF0 && c
<= 0xF4)
1686 ? 4 : (c
>= 0xE0 && c
<= 0xEF)
1687 ? 3 : (c
>= 0xC2 && c
<= 0xDF)
1693 icu
[utf8_len
++] = c
; /* count it */
1698 else if(utf8_len
== 2){
1699 rv
= (icu
[0] >= 0xC2 && icu
[0] <= 0xDF)
1700 && (icu
[1] >= 0x80 && icu
[1] <= 0xBF) ? UTF8_COMPLETE
: 0;
1703 } else if (utf8_type
== 3){
1708 rv
= (icu
[1] >= 0xA0 && icu
[1] <= 0xBF)
1709 && (icu
[2] >= 0x80 && icu
[2] <= 0xBF) ? UTF8_COMPLETE
: 0;
1710 else if(icu
[0] >= 0xE1 && icu
[0] <= 0xEC)
1711 rv
= (icu
[1] >= 0x80 && icu
[1] <= 0xBF)
1712 && (icu
[2] >= 0x80 && icu
[2] <= 0xBF) ? UTF8_COMPLETE
: 0;
1713 else if(icu
[0] == 0xED)
1714 rv
= (icu
[1] >= 0x80 && icu
[1] <= 0x9F)
1715 && (icu
[2] >= 0x80 && icu
[2] <= 0xBF) ? UTF8_COMPLETE
: 0;
1716 else if(icu
[0] >= 0xE1 && icu
[0] <= 0xEC)
1717 rv
= (icu
[1] >= 0x80 && icu
[1] <= 0xBF)
1718 && (icu
[2] >= 0x80 && icu
[2] <= 0xBF) ? UTF8_COMPLETE
: 0;
1721 } else if (utf8_type
== 4){
1726 rv
= (icu
[1] >= 0x90 && icu
[1] <= 0xBF)
1727 && (icu
[2] >= 0x80 && icu
[2] <= 0xBF)
1728 && (icu
[3] >= 0x80 && icu
[3] <= 0xBF) ? UTF8_COMPLETE
: 0;
1729 else if(icu
[0] >= 0xF1 && icu
[0] <= 0xF3)
1730 rv
= (icu
[1] >= 0x80 && icu
[1] <= 0xBF)
1731 && (icu
[2] >= 0x80 && icu
[2] <= 0xBF)
1732 && (icu
[3] >= 0x80 && icu
[3] <= 0xBF) ? UTF8_COMPLETE
: 0;
1733 else if(icu
[0] == 0xF4)
1734 rv
= (icu
[1] >= 0x80 && icu
[1] <= 0x8F)
1735 && (icu
[2] >= 0x80 && icu
[2] <= 0xBF)
1736 && (icu
[3] >= 0x80 && icu
[3] <= 0xBF) ? UTF8_COMPLETE
: 0;
1744 ical_get_number_value(char *value
, int beg_pos
, int end_pos
)
1750 value
[end_pos
] = '\0';
1751 rv
= strtoul(value
+ beg_pos
, &err
, 10);
1752 if(err
!= NULL
&& *err
!= '\0') return -1;
1758 ical_free_duration(ICAL_DURATION_S
**ic_d
)
1760 if(ic_d
== NULL
|| *ic_d
== NULL
)
1763 if((*ic_d
)->next
) ical_free_duration(&(*ic_d
)->next
);
1764 fs_give((void **)ic_d
);
1767 /* returns 0 if no error, -1 if some error */
1769 ical_parse_duration(char *value
, ICAL_DURATION_S
*ic_d
)
1771 int i
, j
= 0, rv
= 0;
1773 if(value
== NULL
|| ic_d
== NULL
) return -1;
1775 memset((void *)ic_d
, 0, sizeof(ICAL_DURATION_S
));
1777 if(value
[i
= 0] == '-'){
1780 } else if(value
[i
] == '+')
1783 if(value
[i
++] == 'P'){
1784 for(j
= i
; value
[j
] != '\0' && value
[j
] != ','; j
++){
1785 if(!isdigit(value
[j
]))
1787 case 'W': ic_d
->weeks
= ical_get_number_value(value
, i
, j
-1);
1790 case 'D': ic_d
->days
= ical_get_number_value(value
, i
, j
-1);
1793 case 'H': ic_d
->hours
= ical_get_number_value(value
, i
, j
-1);
1796 case 'M': ic_d
->minutes
= ical_get_number_value(value
, i
, j
-1);
1799 case 'S': ic_d
->seconds
= ical_get_number_value(value
, i
, j
-1);
1802 case 'T': i
= j
+ 1;
1812 if(value
[j
++] == ','){
1813 ICAL_DURATION_S next
;
1814 rv
= ical_parse_duration(value
+j
, &next
);
1821 /* return -1 if any error,
1822 0 if value has the DATE-TIME form
1823 1 if value has the DATE form only
1824 2 if value has the DATE-TIME form and is in GMT.
1827 ical_parse_date(char *value
, struct tm
*t
)
1833 if(t
== NULL
) return rv
;
1834 memset((void *)&Tm
, 0, sizeof(struct tm
));
1836 if(value
== NULL
) return rv
;
1838 rv
= 0; /* assume DATE-TIME format */
1839 /* a simple check for the format of the string */
1840 for(i
= 0; isdigit(value
[i
]); i
++);
1841 if (i
== 8 && value
[i
] == '\0')
1844 if (i
!= 8 || value
[i
++] != 'T') return -1;
1846 for(; isdigit(value
[i
]); i
++);
1847 if(i
!= 15 || (value
[i
] != '\0' && (value
[i
] != 'Z' || value
[i
+1] != '\0')))
1849 if(i
== 15 && value
[i
] == 'Z')
1853 Tm
.tm_year
= ical_get_number_value(value
, 0, 4) - 1900;
1854 Tm
.tm_mon
= ical_get_number_value(value
, 4, 6) - 1;
1855 Tm
.tm_mday
= ical_get_number_value(value
, 6, 8);
1857 Tm
.tm_hour
= ical_get_number_value(value
, 9, 11);
1858 Tm
.tm_min
= ical_get_number_value(value
, 11, 13);
1859 Tm
.tm_sec
= ical_get_number_value(value
, 13, 15);
1860 Tm
.tm_isdst
= ICAL_DST_UNKNOWN
;
1866 return (t
->tm_mon
> 11 || t
->tm_mon
< 0
1867 || t
->tm_mday
> 31 || t
->tm_mday
< 0
1868 || t
->tm_hour
> 23 || t
->tm_hour
< 0
1869 || t
->tm_min
> 59 || t
->tm_min
< 0
1870 || t
->tm_sec
> 60 || t
->tm_sec
< 0)
1875 ical_set_date(ICLINE_S
*icl
, VTIMEZONE_S
*vtz
)
1877 int date_form
; /* date forms from section 3.3.4 in RFC 5545 */
1878 ICAL_PARAMETER_S
*param
;
1883 if(icl
== NULL
) return;
1885 for(param
= icl
->param
; param
!= NULL
; param
= param
->next
)
1886 if(!strucmp(param
->name
, "TZID"))
1890 date_form
= 3; /* local time with timezone */
1891 else if(icl
->value
[strlen(icl
->value
)-1] == 'Z')
1892 date_form
= 2; /* utc time */
1893 else date_form
= 1; /* local time */
1895 ical_parse_date(icl
->value
, &ic_date
);
1896 ic_date
.tm_wday
= ical_day_of_week(ic_date
); /* find out day of the week */
1900 case 2: ical_adjust_date(&ic_date
, vtz
);
1903 default: alpine_panic ("Impossible date_form");
1908 ical_std_or_daylight(struct tm
*date
, VTIMEZONE_S
*vtz
)
1910 struct tm standard
, daylight
;
1911 ICLINE_S
*tzid
= (ICLINE_S
*) vtz
->prop
[TZCid
];
1913 // standard = daylight;
1920 /* adjusts time to given time zone */
1922 ical_adjust_date(struct tm
*date
, VTIMEZONE_S
*vtz
)
1924 char *tzname
= NULL
;
1926 ICAL_TZPROP_S
*cur_std_day
;
1932 if((icl
= (ICLINE_S
*)vtz
->prop
[TZCid
]) != NULL
)
1933 tzname
= cpystr(icl
->value
);
1936 cur_std_day
= ical_std_or_daylight(date
, vtz
);
1940 ical_set_date_vevent(void *veventv
, void *vtzv
)
1942 VEVENT_S
*vevent
= (VEVENT_S
*) veventv
;
1943 VTIMEZONE_S
*vtz
= (VTIMEZONE_S
*) vtzv
;
1946 ical_set_date(vevent
->prop
[EvDtstamp
], vtz
);
1947 ical_set_date(vevent
->prop
[EvDtstart
], vtz
);
1948 ical_set_date(vevent
->prop
[EvDtend
], vtz
);
1952 #define LEAP_YEAR(X) ((((X) % 4 == 0) \
1953 && (((X) % 100 != 0) || ((X) % 400 == 0))) \
1956 #define CAL_OFFSET(X) (((X) == 1752) ? 5 : (LEAP_YEAR((X)) ? 2 : 1))
1958 /* given a year, after day_zero, return the day
1959 * of the week of the first of january of that year. On error,
1960 * return a negative number.
1961 * Assumption: day_zero is the date of january 1, of some year.
1964 ical_january_first(int year
)
1966 int i
, january_first
;
1968 if(year
< day_zero
.tm_year
) return -1; /* not supported */
1971 january_first
= day_zero
.tm_wday
;
1972 for(i
= 1900 + day_zero
.tm_year
+ 1; i
<= year
; i
++)
1973 january_first
+= CAL_OFFSET(i
-1);
1975 return january_first
% 7;
1978 /* given a month, week day, and year, return all days of the month
1979 * that have that day as the week day. For example, return all
1980 * sundays in november 2012.
1983 ical_day_from_week(int month
, Weekday day
, int year
)
1990 fday
= ical_first_of_month(month
, year
);
1991 year
+= 1900; /* restore year */
1992 if(year
== 1752 && month
== 8){
1995 for(nday
= 1, wday
= (Weekday
) fday
; wday
!= day
; wday
= (wday
+1) % 7, nday
++)
1997 rv
= fs_get(6*sizeof(int));
1998 memset((void *) rv
, 0, 6*sizeof(int));
1999 for(i
= 0; nday
<= month_len
[month
]; i
++){
2003 if(LEAP_YEAR(year
) && month
== 1 && nday
== 29)
2011 /* given a month and a year, return the weekday of the first of the
2012 * month in that year.
2013 * return value: on error -1, otherwise the day of the week.
2016 ical_first_of_month(int month
, int year
)
2020 if((d
= ical_january_first(year
)) < 0)
2024 for(i
= 0; i
< month
; i
++)
2027 if(LEAP_YEAR(year
) && month
>= 2)
2030 if(year
== 1752 && month
>= 9)
2036 /* given a day, month and year, return the weekday of that day
2037 * return value: on error -1, otherwise the day of the week.
2040 ical_day_of_week(struct tm date
)
2044 if((d
= ical_first_of_month(date
.tm_mon
, date
.tm_year
)) < 0)
2047 d
+= date
.tm_mday
- 1;
2049 if(date
.tm_year
+ 1900 == 1752){
2050 if(date
.tm_mday
> 2 && date
.tm_mday
< 14)
2052 if(date
.tm_mday
>= 14)
2059 /* given an initial date dtstart, and a recurring rule, rrule,
2060 * adjust the date to the first date on the same year, when
2061 * the rule actually starts
2064 adjust_date_rrule(struct tm
*dtstart
, RRULE_S
*rrule
)
2068 memset((void *) &t
, 0, sizeof(struct tm
));
2069 t
.tm_year
= dtstart
->tm_year
; /* same year */
2070 if(rrule
->prop
[RRFreq
]){
2072 if(rrule
->prop
[RRCount
]){
2074 else if(rrule
->prop
[RRInterval
]){
2076 if(rrule
->prop
[RRBysecond
]){
2077 BYWKDY_S
*sec
= (BYWKDY_S
*) rrule
->prop
[RRBysecond
], *seco
;
2078 for (seco
= sec
; seco
!= NULL
; seco
= seco
->next
)
2079 if(seco
== sec
) t
.tm_sec
= seco
->value
;
2080 else if (seco
->value
< t
.tm_sec
)
2081 t
.tm_sec
= seco
->value
;
2083 if (rrule
->prop
[RRByminute
]){
2084 BYWKDY_S
*sec
= (BYWKDY_S
*) rrule
->prop
[RRByminute
], *seco
;
2085 for (seco
= sec
; seco
!= NULL
; seco
= seco
->next
)
2086 if(seco
== sec
) t
.tm_min
= seco
->value
;
2087 else if (seco
->value
< t
.tm_sec
)
2088 t
.tm_min
= seco
->value
;
2090 if (rrule
->prop
[RRByhour
]){
2091 BYWKDY_S
*sec
= (BYWKDY_S
*) rrule
->prop
[RRByhour
], *seco
;
2092 for (seco
= sec
; seco
!= NULL
; seco
= seco
->next
)
2093 if(seco
== sec
) t
.tm_hour
= seco
->value
;
2094 else if (seco
->value
< t
.tm_sec
)
2095 t
.tm_hour
= seco
->value
;
2097 if (rrule
->prop
[RRByday
]){
2099 if (rrule
->prop
[RRByweekno
]){
2101 if (rrule
->prop
[RRBymonthday
]){
2103 if (rrule
->prop
[RRByyearday
]){
2105 if (rrule
->prop
[RRByweekno
]){
2107 if (rrule
->prop
[RRBymonth
]){
2108 BYWKDY_S
*m
= (BYWKDY_S
*) rrule
->prop
[RRBymonth
], *mo
;
2109 for (mo
= m
; mo
!= NULL
; mo
= mo
->next
)
2110 if(mo
== m
) t
.tm_mon
= mo
->value
- 1;
2111 else if (mo
->value
- 1 < t
.tm_mon
)
2112 t
.tm_mon
= mo
->value
- 1;
2114 if (rrule
->prop
[RRBysetpos
]){
2116 if (rrule
->prop
[RRWkst
]){
2122 ical_initialize(void)
2124 static int inited
= 0;
2129 ical_buf_len
= 1024;
2130 ical_buf
= fs_get(ical_buf_len
+1);
2132 memset((void *) &day_zero
, 0, sizeof(struct tm
));
2133 day_zero
.tm_year
= 1601 - 1900;
2134 day_zero
.tm_mday
= 1;
2135 day_zero
.tm_wday
= 4;
2140 /* At this time, we are going to print the date in 24 hour format
2141 * if there is no string for AM or PM, but we use AM or PM when available.
2142 * We plan to make this user configurable, but not today...
2145 ical_date_time (char *tmp
, size_t len
, struct tm
*ic_datep
)
2147 /* test of the AM/PM string is available */
2148 our_strftime(tmp
, len
, "%p", ic_datep
);
2151 our_strftime(tmp
, len
, "%a %x %I:%M %p", ic_datep
);
2153 our_strftime(tmp
, len
, "%a %x %H:%M", ic_datep
);
2156 /* If the icline has a TZID parameter, return its value, otherwise, return
2157 * NULL. Returned value freed by caller.
2160 ical_get_tzid(ICAL_PARAMETER_S
*param
)
2167 if(strucmp(param
->name
, "TZID") == 0)
2168 tzid
= cpystr(param
->value
);
2170 tzid
= ical_get_tzid(param
->next
);
2175 /* we create a summary of the event, and pass that back as
2179 ical_vevent_summary(VCALENDAR_S
*vcal
)
2181 VEVENT_SUMMARY_S
*rv
, *vsummary
= NULL
;
2188 if(vcal
== NULL
) return NULL
;
2190 method
= vcal
->method
;
2192 vevent
= (VEVENT_S
*) vcal
->comp
[VEvent
];
2193 if(vevent
== NULL
|| vevent
->prop
== NULL
)
2196 for(vevent
= (VEVENT_S
*) vcal
->comp
[VEvent
];
2197 vevent
!= NULL
&& vevent
->prop
!= NULL
;
2198 vevent
= vevent
->next
, rv
= rv
->next
){
2200 rv
= fs_get(sizeof(VEVENT_SUMMARY_S
));
2201 memset((void *) rv
, 0, sizeof(VEVENT_SUMMARY_S
));
2203 if(method
!= NULL
&& !strucmp(method
->value
, "CANCEL"))
2206 if((icl
= (ICLINE_S
*) vevent
->prop
[EvPriority
]) != NULL
)
2207 rv
->priority
= atoi(icl
->value
);
2209 if((icl
= (ICLINE_S
*) vevent
->prop
[EvSummary
]) != NULL
){
2210 rv
->summary
= cpystr(icl
->value
? icl
->value
: _("No Summary"));
2211 ical_remove_escapes(&rv
->summary
);
2214 if((icl
= (ICLINE_S
*) vevent
->prop
[EvClass
]) != NULL
)
2215 rv
->class = cpystr(icl
->value
? icl
->value
: _("PUBLIC"));
2217 rv
->class = cpystr(_("PUBLIC"));
2219 if((icl
= (ICLINE_S
*) vevent
->prop
[EvOrganizer
]) != NULL
){
2220 char *cn
, *sender
, *address
;
2221 ICAL_PARAMETER_S
*param
;
2223 cn
= sender
= address
= NULL
;
2224 for(param
= icl
->param
; param
!= NULL
; param
= param
->next
)
2225 if(!strucmp(param
->name
, "CN"))
2227 else if(!strucmp(param
->name
, "SENT-BY"))
2228 sender
= param
->value
;
2231 if(!struncmp(sender
, "MAILTO:", 7))
2233 utf8_snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, "<%s>", sender
);
2234 rv
->sender
= cpystr(tmp_20k_buf
);
2237 if((address
= icl
->value
) != NULL
){
2238 if(!struncmp(address
, "MAILTO:", 7))
2240 utf8_snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, "%s%s<%s>",
2241 cn
? cn
: "", cn
? " " : "",
2242 address
? address
: _("Unknown address"));
2243 rv
->organizer
= cpystr(tmp_20k_buf
);
2245 } /* end of if(organizer) */
2247 if((icl
= (ICLINE_S
*) vevent
->prop
[EvLocation
]) != NULL
){
2248 rv
->location
= cpystr(icl
->value
? icl
->value
: _("Location undisclosed"));
2249 ical_remove_escapes(&rv
->location
);
2252 if((icl
= (ICLINE_S
*) vevent
->prop
[EvDtstart
]) != NULL
){
2254 char tmp
[200], *tzid
;
2255 int icd
; /* ical date return value */
2257 memset((void *)&ic_date
, 0, sizeof(struct tm
));
2258 icd
= ical_parse_date(icl
->value
, &ic_date
);
2259 tzid
= ical_get_tzid(icl
->param
);
2261 ic_date
.tm_wday
= ical_day_of_week(ic_date
);
2263 case 0: /* DATE-TIME */
2264 ical_date_time(tmp
, sizeof(tmp
), &ic_date
);
2267 our_strftime(tmp
, sizeof(tmp
), "%a %x", &ic_date
);
2269 case 2: /* DATE-TIME in GMT, Bug: add adjust to time zone */
2270 our_strftime(tmp
, sizeof(tmp
), "%a %x %I:%M %p", &ic_date
);
2272 default: alpine_panic("Unhandled ical date format");
2277 strncpy(tmp
, _("Error while parsing event date"), sizeof(tmp
));
2278 tmp
[sizeof(tmp
) - 1] = '\0';
2281 if(icl
->value
== NULL
)
2282 rv
->evstart
= cpystr(_("Unknown Start Date"));
2284 size_t len
= strlen(tmp
) + 1;
2287 len
+= strlen(tzid
) + 3; /* 3 = strlen(" ()") */
2289 rv
->evstart
= fs_get(len
*sizeof(char));
2290 snprintf(rv
->evstart
, len
, "%s%s%s%s", tmp
,
2291 tzid
!= NULL
? " (" : "",
2292 tzid
!= NULL
? tzid
: "",
2293 tzid
!= NULL
? ")" : "");
2294 rv
->evstart
[len
-1] = '\0';
2297 fs_give((void **)&tzid
);
2298 } /* end of if dtstart */
2300 if((icl
= (ICLINE_S
*) vevent
->prop
[EvDuration
]) != NULL
){
2302 ICAL_DURATION_S ic_d
, icd2
;
2303 if(ical_parse_duration(icl
->value
, &ic_d
) == 0){
2304 char tmp
[MAILTMPLEN
+1];
2306 for(i
= 1, icd2
= ic_d
; icd2
.next
!= NULL
; icd2
= *icd2
.next
, i
++);
2307 rv
->duration
= fs_get((i
+1)*sizeof(char *));
2314 utf8_snprintf(tmp
+strlen(tmp
), MAILTMPLEN
- strlen(tmp
),
2315 "%d %s ", ic_d
.weeks
, ic_d
.weeks
== 1 ? _("week") : _("weeks"));
2317 utf8_snprintf(tmp
+strlen(tmp
), MAILTMPLEN
- strlen(tmp
),
2318 "%d %s ", ic_d
.days
, ic_d
.days
== 1 ? _("day") : _("days"));
2320 utf8_snprintf(tmp
+strlen(tmp
), MAILTMPLEN
- strlen(tmp
),
2321 "%d %s ", ic_d
.hours
, ic_d
.hours
== 1 ? _("hour") : _("hours"));
2322 if(ic_d
.minutes
> 0)
2323 utf8_snprintf(tmp
+strlen(tmp
), MAILTMPLEN
- strlen(tmp
),
2324 "%d %s ", ic_d
.minutes
, ic_d
.minutes
== 1 ? _("minute") : _("minutes"));
2325 if(ic_d
.seconds
> 0)
2326 utf8_snprintf(tmp
+strlen(tmp
), MAILTMPLEN
- strlen(tmp
),
2327 "%d %s ", ic_d
.seconds
, ic_d
.seconds
== 1 ? _("second") : _("seconds"));
2329 tmp
[MAILTMPLEN
] = '\0';
2330 rv
->duration
[i
++] = cpystr(tmp
);
2332 if(ic_d
.next
!= NULL
)
2336 } while (done
== 0);
2337 rv
->duration
[i
] = NULL
;
2339 } /* end of DURATION */
2340 else if((icl
= (ICLINE_S
*) vevent
->prop
[EvDtend
]) != NULL
){
2342 char tmp
[200], *tzid
;
2345 memset((void *)&ic_date
, 0, sizeof(struct tm
));
2346 icd
= ical_parse_date(icl
->value
, &ic_date
);
2347 tzid
= ical_get_tzid(icl
->param
);
2349 ic_date
.tm_wday
= ical_day_of_week(ic_date
);
2351 case 0: /* DATE-TIME */
2352 ical_date_time(tmp
, sizeof(tmp
), &ic_date
);
2355 our_strftime(tmp
, sizeof(tmp
), "%a %x", &ic_date
);
2357 case 2: /* DATE-TIME in GMT, Bug: add adjust to time zone */
2358 our_strftime(tmp
, sizeof(tmp
), "%a %x %I:%M %p", &ic_date
);
2360 default: alpine_panic("Unhandled ical date format");
2365 strncpy(tmp
, _("Error while parsing event date"), sizeof(tmp
));
2366 tmp
[sizeof(tmp
) - 1] = '\0';
2369 if(icl
->value
== NULL
)
2370 rv
->evend
= cpystr(_("Unknown End Date"));
2372 size_t len
= strlen(tmp
) + 1;
2375 len
+= strlen(tzid
) + 3; /* 3 = strlen(" ()") */
2377 rv
->evend
= fs_get(len
*sizeof(char));
2378 snprintf(rv
->evend
, len
, "%s%s%s%s", tmp
,
2379 tzid
!= NULL
? " (" : "",
2380 tzid
!= NULL
? tzid
: "",
2381 tzid
!= NULL
? ")" : "");
2382 rv
->evend
[len
-1] = '\0';
2385 fs_give((void **)&tzid
);
2386 } /* end of if dtend */
2388 if((icl
= (ICLINE_S
*) vevent
->prop
[EvDtstamp
]) != NULL
){
2390 char tmp
[200], *tzid
;
2393 memset((void *)&ic_date
, 0, sizeof(struct tm
));
2394 icd
= ical_parse_date(icl
->value
, &ic_date
);
2395 tzid
= ical_get_tzid(icl
->param
);
2397 ic_date
.tm_wday
= ical_day_of_week(ic_date
);
2399 case 0: /* DATE-TIME */
2400 ical_date_time(tmp
, sizeof(tmp
), &ic_date
);
2403 our_strftime(tmp
, sizeof(tmp
), "%a %x", &ic_date
);
2405 case 2: /* DATE-TIME in GMT, Bug: add adjust to time zone */
2406 our_strftime(tmp
, sizeof(tmp
), "%a %x %I:%M %p", &ic_date
);
2408 default: alpine_panic("Unhandled ical date format");
2413 strncpy(tmp
, _("Error while parsing event date"), sizeof(tmp
));
2414 tmp
[sizeof(tmp
) - 1] = '\0';
2416 if(icl
->value
== NULL
)
2417 rv
->dtstamp
= cpystr(_("Unknown when event was scheduled"));
2419 size_t len
= strlen(tmp
) + 1;
2422 len
+= strlen(tzid
) + 3; /* 3 = strlen(" ()") */
2424 rv
->dtstamp
= fs_get(len
*sizeof(char));
2425 snprintf(rv
->dtstamp
, len
, "%s%s%s%s", tmp
,
2426 tzid
!= NULL
? " (" : "",
2427 tzid
!= NULL
? tzid
: "",
2428 tzid
!= NULL
? ")" : "");
2429 rv
->dtstamp
[len
-1] = '\0';
2431 } /* end of if dtstamp */
2433 if((gicl
= (GEN_ICLINE_S
*) vevent
->prop
[EvAttendee
]) != NULL
){
2436 for(nattendees
= 0; gicl
!= NULL
; gicl
= gicl
->next
, nattendees
++);
2437 rv
->attendee
= fs_get((nattendees
+1)*sizeof(char *));
2439 gicl
= (GEN_ICLINE_S
*) vevent
->prop
[EvAttendee
];
2440 for(i
= 0; gicl
!= NULL
; gicl
= gicl
->next
, i
++){
2441 char *role
, *partstat
, *rsvp
;
2443 ICAL_PARAMETER_S
*param
;
2446 role
= partstat
= rsvp
= cn
= mailto
= NULL
;
2447 for(param
= icl
->param
; param
!= NULL
; param
= param
->next
){
2448 if(!strucmp(param
->name
, "ROLE")){
2449 if(!strucmp(param
->value
, "REQ-PARTICIPANT"))
2450 role
= _("[Required]");
2451 else if(!strucmp(param
->value
, "OPT-PARTICIPANT"))
2452 role
= _("[Optional]");
2453 else if(!strucmp(param
->value
, "NON-PARTICIPANT"))
2454 role
= _("[Informed]");
2455 else if(!strucmp(param
->value
, "CHAIR"))
2456 role
= _("[ Chair ]");
2458 role
= param
->value
;
2460 else if(!strucmp(param
->name
, "PARTSTAT")){
2461 if(!strucmp(param
->value
, "NEEDS-ACTION"))
2462 partstat
= _("[Need-Reply]");
2463 else if(!strucmp(param
->value
, "ACCEPTED"))
2464 partstat
= _("[ Accepted ]");
2465 else if(!strucmp(param
->value
, "DECLINED"))
2466 partstat
= _("[ Declined ]");
2467 else if(!strucmp(param
->value
, "TENTATIVE"))
2468 partstat
= _("[ Tentative]");
2469 else if(!strucmp(param
->value
, "DELEGATED"))
2470 partstat
= _("[ Delegated]");
2472 partstat
= param
->value
;
2474 else if(!strucmp(param
->name
, "RSVP"))
2475 rsvp
= param
->value
;
2476 else if(!strucmp(param
->name
, "CN"))
2479 if(icl
->value
&& !struncmp(icl
->value
, "MAILTO:", strlen("MAILTO:")))
2480 mailto
= icl
->value
+ 7; /* 7 = strlen("MAILTO:") */
2481 if(!strucmp(cn
, mailto
))
2483 utf8_snprintf(tmp_20k_buf
, SIZEOF_20KBUF
, "%s%s%s%s%s%s<%s>",
2484 role
&& *role
? role
: "",
2485 role
&& *role
? " " : "",
2486 partstat
? partstat
: _("[Unknown Reply]"),
2488 cn
&& *cn
? cn
: "",
2489 cn
&& *cn
? " " : "",
2490 mailto
? mailto
: _("Unknown address"));
2491 rv
->attendee
[i
] = cpystr(tmp_20k_buf
);
2493 rv
->attendee
[i
] = NULL
;
2494 } /* end of ATTENDEES */
2496 if((icl
= (ICLINE_S
*) vevent
->prop
[EvDescription
]) != NULL
){
2497 char *s
, *t
, *u
, *v
;
2500 if(icl
->value
== NULL
){
2501 free_vevent_summary(&rv
);
2505 v
= cpystr(icl
->value
); /* process a copy of icl->value */
2507 for(i
= 1, escaped
= 0, s
= v
; s
&& *s
; s
++){
2508 if(*s
== '\\' && escaped
== 0){ escaped
= 1; continue; }
2510 if(!(*s
== '\\' || *s
== ',' || *s
== 'n' || *s
== 'N' || *s
== ';')){
2511 free_vevent_summary(&rv
);
2512 fs_give((void **)&v
);
2518 if(*s
== ',') i
++; /* a non-scaped comma is a new value for text */
2521 rv
->description
= fs_get((i
+1)*sizeof(unsigned char *));
2523 for (s
= t
= u
= v
, escaped
= 0; *t
!= '\0'; t
++){
2524 if(*t
== '\\' && escaped
== 0){ escaped
= 1; continue; }
2536 default: free_vevent_summary(&rv
);
2537 fs_give((void **)&v
);
2545 rv
->description
[i
++] = cpystr(ical_decode(s
, vcal
->encoding
));
2551 rv
->description
[i
++] = cpystr(ical_decode(s
, vcal
->encoding
));
2552 rv
->description
[i
] = NULL
;
2553 fs_give((void **)&v
);
2554 } /* end of if(description) */
2555 /* last instruction of the loop */
2556 if(vsummary
== NULL
)
2559 VEVENT_SUMMARY_S
*vesy
;
2560 for(vesy
= vsummary
; vesy
&& vesy
->next
; vesy
= vesy
->next
);
2563 } /* end of "for" loop */
2568 free_vevent_summary(VEVENT_SUMMARY_S
**vesy
)
2571 if(vesy
== NULL
|| *vesy
== NULL
) return;
2573 if((*vesy
)->class) fs_give((void **)&(*vesy
)->class);
2574 if((*vesy
)->summary
) fs_give((void **)&(*vesy
)->summary
);
2575 if((*vesy
)->sender
) fs_give((void **)&(*vesy
)->sender
);
2576 if((*vesy
)->organizer
) fs_give((void **)&(*vesy
)->organizer
);
2577 if((*vesy
)->location
) fs_give((void **)&(*vesy
)->location
);
2578 if((*vesy
)->evstart
) fs_give((void **)&(*vesy
)->evstart
);
2579 if((*vesy
)->evend
) fs_give((void **)&(*vesy
)->evend
);
2580 if((*vesy
)->dtstamp
) fs_give((void **)&(*vesy
)->dtstamp
);
2581 if((*vesy
)->duration
){
2582 for(i
= 0; (*vesy
)->duration
[i
] != NULL
; i
++)
2583 fs_give((void **) &(*vesy
)->duration
[i
]);
2584 fs_give((void **) (*vesy
)->duration
);
2586 if((*vesy
)->attendee
){
2587 for(i
= 0; (*vesy
)->attendee
[i
] != NULL
; i
++)
2588 fs_give((void **) &(*vesy
)->attendee
[i
]);
2589 fs_give((void **) &(*vesy
)->attendee
);
2591 if((*vesy
)->description
){
2592 for(i
= 0; (*vesy
)->description
[i
] != NULL
; i
++)
2593 fs_give((void **) &(*vesy
)->description
[i
]);
2594 fs_give((void **) &(*vesy
)->description
);
2596 if((*vesy
)->next
) free_vevent_summary(&(*vesy
)->next
);
2597 fs_give((void **) vesy
);
2604 fs_give((void **)&ical_buf
);