Diffstat (limited to 'libical/src/libical/icalrestriction.c.in') (more/less context) (ignore whitespace changes)
-rw-r--r-- | libical/src/libical/icalrestriction.c.in | 447 |
1 files changed, 447 insertions, 0 deletions
diff --git a/libical/src/libical/icalrestriction.c.in b/libical/src/libical/icalrestriction.c.in new file mode 100644 index 0000000..4544425 --- a/dev/null +++ b/libical/src/libical/icalrestriction.c.in | |||
@@ -0,0 +1,447 @@ | |||
1 | /* -*- Mode: C -*- */ | ||
2 | /* ====================================================================== | ||
3 | File: icalrestriction.c | ||
4 | |||
5 | (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org | ||
6 | ======================================================================*/ | ||
7 | /*#line 7 "icalrestriction.c.in"*/ | ||
8 | |||
9 | #ifdef HAVE_CONFIG_H | ||
10 | #include <config.h> | ||
11 | #endif | ||
12 | |||
13 | #include "icalrestriction.h" | ||
14 | #include "icalenums.h" | ||
15 | #include "icalerror.h" | ||
16 | |||
17 | #include <assert.h> | ||
18 | #include <stdio.h> /* For snprintf */ | ||
19 | |||
20 | #define TMP_BUF_SIZE 1024 | ||
21 | |||
22 | |||
23 | /* Define the structs for the restrictions. these data are filled out | ||
24 | in machine generated code below */ | ||
25 | |||
26 | struct icalrestriction_property_record; | ||
27 | |||
28 | typedef char* (*restriction_func)(struct icalrestriction_property_record* rec,icalcomponent* comp,icalproperty* prop); | ||
29 | |||
30 | |||
31 | typedef struct icalrestriction_property_record { | ||
32 | icalproperty_method method; | ||
33 | icalcomponent_kind component; | ||
34 | icalproperty_kind property; | ||
35 | icalrestriction_kind restriction; | ||
36 | restriction_func function; | ||
37 | } icalrestriction_property_record; | ||
38 | |||
39 | |||
40 | typedef struct icalrestriction_component_record { | ||
41 | icalproperty_method method; | ||
42 | icalcomponent_kind component; | ||
43 | icalcomponent_kind subcomponent; | ||
44 | icalrestriction_kind restriction; | ||
45 | restriction_func function; | ||
46 | } icalrestriction_component_record; | ||
47 | |||
48 | icalrestriction_property_record* | ||
49 | icalrestriction_get_property_restriction(icalproperty_method method, | ||
50 | icalcomponent_kind component, | ||
51 | icalproperty_kind property); | ||
52 | icalrestriction_component_record* | ||
53 | icalrestriction_get_component_restriction(icalproperty_method method, | ||
54 | icalcomponent_kind component, | ||
55 | icalcomponent_kind subcomponent); | ||
56 | |||
57 | icalrestriction_component_record icalrestriction_component_records[]; | ||
58 | icalrestriction_property_record icalrestriction_property_records[]; | ||
59 | |||
60 | icalrestriction_property_record null_prop_record = {ICAL_METHOD_NONE,ICAL_NO_COMPONENT,ICAL_NO_PROPERTY,ICAL_RESTRICTION_UNKNOWN,0}; | ||
61 | icalrestriction_component_record null_comp_record = {ICAL_METHOD_NONE,ICAL_NO_COMPONENT,ICAL_NO_COMPONENT,ICAL_RESTRICTION_UNKNOWN,0}; | ||
62 | |||
63 | |||
64 | /* The each row gives the result of comparing a restriction against a | ||
65 | count. The columns in each row represent 0,1,2+. '-1' indicates | ||
66 | 'invalid, 'don't care' or 'needs more analysis' So, for | ||
67 | ICAL_RESTRICTION_ONE, if there is 1 of a property with that | ||
68 | restriction, it passes, but if there are 0 or 2+, it fails. */ | ||
69 | |||
70 | char compare_map[ICAL_RESTRICTION_UNKNOWN+1][3] = { | ||
71 | { 1, 1, 1},/*ICAL_RESTRICTION_NONE*/ | ||
72 | { 1, 0, 0},/*ICAL_RESTRICTION_ZERO*/ | ||
73 | { 0, 1, 0},/*ICAL_RESTRICTION_ONE*/ | ||
74 | { 1, 1, 1},/*ICAL_RESTRICTION_ZEROPLUS*/ | ||
75 | { 0, 1, 1},/*ICAL_RESTRICTION_ONEPLUS*/ | ||
76 | { 1, 1, 0},/*ICAL_RESTRICTION_ZEROORONE*/ | ||
77 | { 1, 1, 0},/*ICAL_RESTRICTION_ONEEXCLUSIVE*/ | ||
78 | { 1, 1, 0},/*ICAL_RESTRICTION_ONEMUTUAL*/ | ||
79 | { 1, 1, 1} /*ICAL_RESTRICTION_UNKNOWN*/ | ||
80 | }; | ||
81 | |||
82 | char restr_string_map[ICAL_RESTRICTION_UNKNOWN+1][60] = { | ||
83 | "unknown number",/*ICAL_RESTRICTION_NONE*/ | ||
84 | "0",/*ICAL_RESTRICTION_ZERO*/ | ||
85 | "1",/*ICAL_RESTRICTION_ONE*/ | ||
86 | "zero or more",/*ICAL_RESTRICTION_ZEROPLUS*/ | ||
87 | "one or more" ,/*ICAL_RESTRICTION_ONEPLUS*/ | ||
88 | "zero or one",/*ICAL_RESTRICTION_ZEROORONE*/ | ||
89 | "zero or one, exclusive with another property",/*ICAL_RESTRICTION_ONEEXCLUSIVE*/ | ||
90 | "zero or one, mutual with another property",/*ICAL_RESTRICTION_ONEMUTUAL*/ | ||
91 | "unknown number" /*ICAL_RESTRICTION_UNKNOWN*/ | ||
92 | }; | ||
93 | |||
94 | |||
95 | int | ||
96 | icalrestriction_compare(icalrestriction_kind restr, int count){ | ||
97 | |||
98 | if ( restr < ICAL_RESTRICTION_NONE || restr > ICAL_RESTRICTION_UNKNOWN | ||
99 | || count < 0){ | ||
100 | return -1; | ||
101 | } | ||
102 | |||
103 | if (count > 2) { | ||
104 | count = 2; | ||
105 | } | ||
106 | |||
107 | return compare_map[restr][count]; | ||
108 | |||
109 | } | ||
110 | |||
111 | /* Special case routines */ | ||
112 | |||
113 | char* icalrestriction_may_be_draft_final_canceled( | ||
114 | icalrestriction_property_record *rec, | ||
115 | icalcomponent* comp, | ||
116 | icalproperty* prop) | ||
117 | { | ||
118 | |||
119 | icalproperty_status stat = icalproperty_get_status(prop); | ||
120 | |||
121 | if( !( stat == ICAL_STATUS_DRAFT || | ||
122 | stat == ICAL_STATUS_FINAL || | ||
123 | stat == ICAL_STATUS_CANCELLED )){ | ||
124 | |||
125 | return "Failed iTIP restrictions for STATUS property. Value must be one of DRAFT, FINAL, or CANCELED"; | ||
126 | |||
127 | } | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | char* icalrestriction_may_be_comp_need_process( | ||
133 | icalrestriction_property_record *rec, | ||
134 | icalcomponent* comp, | ||
135 | icalproperty* prop) | ||
136 | { | ||
137 | icalproperty_status stat = icalproperty_get_status(prop); | ||
138 | |||
139 | if( !( stat == ICAL_STATUS_COMPLETED || | ||
140 | stat == ICAL_STATUS_NEEDSACTION || | ||
141 | stat == ICAL_STATUS_INPROCESS )){ | ||
142 | |||
143 | return "Failed iTIP restrictions for STATUS property. Value must be one of COMPLETED, NEEDS-ACTION or IN-PROCESS"; | ||
144 | |||
145 | } | ||
146 | |||
147 | return 0; | ||
148 | } | ||
149 | char* icalrestriction_may_be_tent_conf(icalrestriction_property_record *rec, | ||
150 | icalcomponent* comp, | ||
151 | icalproperty* prop){ | ||
152 | icalproperty_status stat = icalproperty_get_status(prop); | ||
153 | |||
154 | if( !( stat == ICAL_STATUS_TENTATIVE || | ||
155 | stat == ICAL_STATUS_CONFIRMED )){ | ||
156 | |||
157 | return "Failed iTIP restrictions for STATUS property. Value must be one of TENTATIVE or CONFIRMED"; | ||
158 | |||
159 | } | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | char* icalrestriction_may_be_tent_conf_cancel( | ||
164 | icalrestriction_property_record *rec, | ||
165 | icalcomponent* comp, | ||
166 | icalproperty* prop) | ||
167 | { | ||
168 | icalproperty_status stat = icalproperty_get_status(prop); | ||
169 | |||
170 | if( !( stat == ICAL_STATUS_TENTATIVE || | ||
171 | stat == ICAL_STATUS_CONFIRMED || | ||
172 | stat == ICAL_STATUS_CANCELLED )){ | ||
173 | |||
174 | return "Failed iTIP restrictions for STATUS property. Value must be one of TENTATIVE, CONFIRMED or CANCELED"; | ||
175 | |||
176 | } | ||
177 | |||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | char* icalrestriction_must_be_cancel_if_present( | ||
182 | icalrestriction_property_record *rec, | ||
183 | icalcomponent* comp, | ||
184 | icalproperty* prop) | ||
185 | { | ||
186 | /* This routine will not be called if prop == 0 */ | ||
187 | icalproperty_status stat = icalproperty_get_status(prop); | ||
188 | |||
189 | if( stat != ICAL_STATUS_CANCELLED) | ||
190 | { | ||
191 | return "Failed iTIP restrictions for STATUS property. Value must be CANCELLED"; | ||
192 | |||
193 | } | ||
194 | |||
195 | |||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | char* icalrestriction_must_be_canceled_no_attendee( | ||
200 | icalrestriction_property_record *rec, | ||
201 | icalcomponent* comp, | ||
202 | icalproperty* prop) | ||
203 | { | ||
204 | |||
205 | /* Hack. see rfc2446, 3.2.5 CANCEL for porperty STATUS. I don't | ||
206 | understand the note */ | ||
207 | |||
208 | return 0; | ||
209 | } | ||
210 | char* icalrestriction_must_be_recurring(icalrestriction_property_record *rec, | ||
211 | icalcomponent* comp, | ||
212 | icalproperty* prop){ | ||
213 | /* Hack */ | ||
214 | return 0; | ||
215 | } | ||
216 | char* icalrestriction_must_have_duration(icalrestriction_property_record *rec, | ||
217 | icalcomponent* comp, | ||
218 | icalproperty* prop){ | ||
219 | |||
220 | if( !icalcomponent_get_first_property(comp,ICAL_DURATION_PROPERTY)){ | ||
221 | |||
222 | return "Failed iTIP restrictions for STATUS property. This component must have a DURATION property"; | ||
223 | |||
224 | } | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | char* icalrestriction_must_have_repeat(icalrestriction_property_record *rec, | ||
229 | icalcomponent* comp, | ||
230 | icalproperty* prop){ | ||
231 | if( !icalcomponent_get_first_property(comp,ICAL_REPEAT_PROPERTY)){ | ||
232 | |||
233 | return "Failed iTIP restrictions for STATUS property. This component must have a REPEAT property"; | ||
234 | |||
235 | } | ||
236 | |||
237 | return 0; | ||
238 | } | ||
239 | char* icalrestriction_must_if_tz_ref(icalrestriction_property_record *rec, | ||
240 | icalcomponent* comp, | ||
241 | icalproperty* prop){ | ||
242 | |||
243 | /* Hack */ | ||
244 | return 0; | ||
245 | } | ||
246 | char* icalrestriction_no_dtend(icalrestriction_property_record *rec, | ||
247 | icalcomponent* comp, | ||
248 | icalproperty* prop){ | ||
249 | |||
250 | if( !icalcomponent_get_first_property(comp,ICAL_DTEND_PROPERTY)){ | ||
251 | |||
252 | return "Failed iTIP restrictions for STATUS property. The component must not have both DURATION and DTEND"; | ||
253 | |||
254 | } | ||
255 | |||
256 | return 0; | ||
257 | } | ||
258 | char* icalrestriction_no_duration(icalrestriction_property_record *rec, | ||
259 | icalcomponent* comp, | ||
260 | icalproperty* prop){ | ||
261 | |||
262 | /* _no_dtend takes care of this one */ | ||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | |||
267 | int icalrestriction_check_component(icalproperty_method method, | ||
268 | icalcomponent* comp) | ||
269 | { | ||
270 | icalproperty_kind kind; | ||
271 | icalcomponent_kind comp_kind; | ||
272 | icalrestriction_kind restr; | ||
273 | icalrestriction_property_record *prop_record; | ||
274 | icalrestriction_component_record *comp_record; | ||
275 | char* funcr = 0; | ||
276 | icalproperty *prop; | ||
277 | |||
278 | int count; | ||
279 | int compare; | ||
280 | int valid = 1; | ||
281 | |||
282 | comp_kind = icalcomponent_isa(comp); | ||
283 | |||
284 | /* Check all of the properties in this component */ | ||
285 | |||
286 | for(kind = ICAL_ANY_PROPERTY+1; kind != ICAL_NO_PROPERTY; kind++){ | ||
287 | count = icalcomponent_count_properties(comp, kind); | ||
288 | |||
289 | prop_record = icalrestriction_get_property_restriction(method, | ||
290 | comp_kind, | ||
291 | kind); | ||
292 | |||
293 | restr = prop_record->restriction; | ||
294 | |||
295 | if(restr == ICAL_RESTRICTION_ONEEXCLUSIVE || | ||
296 | restr == ICAL_RESTRICTION_ONEMUTUAL) { | ||
297 | |||
298 | /* First treat is as a 0/1 restriction */ | ||
299 | restr = ICAL_RESTRICTION_ZEROORONE; | ||
300 | compare = icalrestriction_compare(restr,count); | ||
301 | |||
302 | } else { | ||
303 | |||
304 | compare = icalrestriction_compare(restr,count); | ||
305 | } | ||
306 | |||
307 | assert(compare != -1); | ||
308 | |||
309 | if (compare == 0){ | ||
310 | char temp[TMP_BUF_SIZE]; | ||
311 | |||
312 | snprintf(temp, TMP_BUF_SIZE,"Failed iTIP restrictions for %s property. Expected %s instances of the property and got %d", | ||
313 | icalenum_property_kind_to_string(kind), | ||
314 | restr_string_map[restr], count); | ||
315 | |||
316 | icalcomponent_add_property | ||
317 | (comp, | ||
318 | icalproperty_vanew_xlicerror( | ||
319 | temp, | ||
320 | icalparameter_new_xlicerrortype(ICAL_XLICERRORTYPE_INVALIDITIP), | ||
321 | 0)); | ||
322 | } | ||
323 | |||
324 | |||
325 | prop = icalcomponent_get_first_property(comp, kind); | ||
326 | |||
327 | if (prop != 0 && prop_record->function !=0 ){ | ||
328 | funcr = prop_record->function(prop_record,comp,prop); | ||
329 | } | ||
330 | |||
331 | if(funcr !=0){ | ||
332 | icalcomponent_add_property | ||
333 | (comp, | ||
334 | icalproperty_vanew_xlicerror( | ||
335 | funcr, | ||
336 | icalparameter_new_xlicerrortype( | ||
337 | ICAL_XLICERRORTYPE_INVALIDITIP), | ||
338 | 0)); | ||
339 | |||
340 | compare = 0; | ||
341 | } | ||
342 | |||
343 | valid = valid && compare; | ||
344 | } | ||
345 | |||
346 | |||
347 | |||
348 | return valid; | ||
349 | |||
350 | |||
351 | } | ||
352 | |||
353 | int icalrestriction_check(icalcomponent* outer_comp) | ||
354 | { | ||
355 | icalcomponent_kind comp_kind; | ||
356 | icalproperty_method method; | ||
357 | icalcomponent* inner_comp; | ||
358 | icalproperty *method_prop; | ||
359 | int valid; | ||
360 | |||
361 | icalerror_check_arg_rz( (outer_comp!=0), "outer comp"); | ||
362 | |||
363 | |||
364 | /* Get the Method value from the outer component */ | ||
365 | |||
366 | comp_kind = icalcomponent_isa(outer_comp); | ||
367 | |||
368 | if (comp_kind != ICAL_VCALENDAR_COMPONENT){ | ||
369 | icalerror_set_errno(ICAL_BADARG_ERROR); | ||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | method_prop = icalcomponent_get_first_property(outer_comp, | ||
374 | ICAL_METHOD_PROPERTY); | ||
375 | |||
376 | if (method_prop == 0){ | ||
377 | method = ICAL_METHOD_NONE; | ||
378 | } else { | ||
379 | method = icalproperty_get_method(method_prop); | ||
380 | } | ||
381 | |||
382 | |||
383 | /* Check the VCALENDAR wrapper */ | ||
384 | valid = icalrestriction_check_component(ICAL_METHOD_NONE,outer_comp); | ||
385 | |||
386 | |||
387 | /* Now check the inner components */ | ||
388 | |||
389 | for(inner_comp= icalcomponent_get_first_component(outer_comp, | ||
390 | ICAL_ANY_COMPONENT); | ||
391 | inner_comp != 0; | ||
392 | inner_comp= icalcomponent_get_next_component(outer_comp, | ||
393 | ICAL_ANY_COMPONENT)){ | ||
394 | |||
395 | valid = valid && icalrestriction_check_component(method,inner_comp); | ||
396 | |||
397 | } | ||
398 | |||
399 | |||
400 | return valid; | ||
401 | |||
402 | } | ||
403 | |||
404 | icalrestriction_property_record* | ||
405 | icalrestriction_get_property_restriction(icalproperty_method method, | ||
406 | icalcomponent_kind component, | ||
407 | icalproperty_kind property) | ||
408 | { | ||
409 | int i; | ||
410 | |||
411 | for(i = 0; | ||
412 | icalrestriction_property_records[i].restriction != ICAL_RESTRICTION_NONE; | ||
413 | i++){ | ||
414 | |||
415 | if (method == icalrestriction_property_records[i].method && | ||
416 | component == icalrestriction_property_records[i].component && | ||
417 | property == icalrestriction_property_records[i].property ){ | ||
418 | return &icalrestriction_property_records[i]; | ||
419 | } | ||
420 | } | ||
421 | |||
422 | return &null_prop_record; | ||
423 | } | ||
424 | |||
425 | |||
426 | icalrestriction_component_record* | ||
427 | icalrestriction_get_component_restriction(icalproperty_method method, | ||
428 | icalcomponent_kind component, | ||
429 | icalcomponent_kind subcomponent) | ||
430 | { | ||
431 | |||
432 | int i; | ||
433 | |||
434 | for(i = 0; | ||
435 | icalrestriction_component_records[i].restriction != ICAL_RESTRICTION_NONE; | ||
436 | i++){ | ||
437 | |||
438 | if (method == icalrestriction_component_records[i].method && | ||
439 | component == icalrestriction_component_records[i].component && | ||
440 | subcomponent == icalrestriction_component_records[i].subcomponent ){ | ||
441 | return &icalrestriction_component_records[i]; | ||
442 | } | ||
443 | } | ||
444 | |||
445 | return &null_comp_record; | ||
446 | } | ||
447 | |||