summaryrefslogtreecommitdiffabout
path: root/libical/src/libical/icalrestriction.c.in
Unidiff
Diffstat (limited to 'libical/src/libical/icalrestriction.c.in') (more/less context) (ignore whitespace changes)
-rw-r--r--libical/src/libical/icalrestriction.c.in447
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
24in machine generated code below */
25
26struct icalrestriction_property_record;
27
28typedef char* (*restriction_func)(struct icalrestriction_property_record* rec,icalcomponent* comp,icalproperty* prop);
29
30
31typedef 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
40typedef 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
48icalrestriction_property_record*
49icalrestriction_get_property_restriction(icalproperty_method method,
50 icalcomponent_kind component,
51 icalproperty_kind property);
52icalrestriction_component_record*
53icalrestriction_get_component_restriction(icalproperty_method method,
54 icalcomponent_kind component,
55 icalcomponent_kind subcomponent);
56
57icalrestriction_component_record icalrestriction_component_records[];
58icalrestriction_property_record icalrestriction_property_records[];
59
60icalrestriction_property_record null_prop_record = {ICAL_METHOD_NONE,ICAL_NO_COMPONENT,ICAL_NO_PROPERTY,ICAL_RESTRICTION_UNKNOWN,0};
61icalrestriction_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
70char 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
82char 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
95int
96icalrestriction_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
113char* 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
132char* 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}
149char* 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}
163char* 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
181char* 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
199char* 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}
210char* icalrestriction_must_be_recurring(icalrestriction_property_record *rec,
211 icalcomponent* comp,
212 icalproperty* prop){
213 /* Hack */
214 return 0;
215}
216char* 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}
228char* 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}
239char* icalrestriction_must_if_tz_ref(icalrestriction_property_record *rec,
240 icalcomponent* comp,
241 icalproperty* prop){
242
243 /* Hack */
244 return 0;
245}
246char* 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}
258char* 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
267int 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
353int 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
404icalrestriction_property_record*
405icalrestriction_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
426icalrestriction_component_record*
427icalrestriction_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