From 1a8645d8b85f46d34ff24f1f7bdc69bfd32282d4 Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Mon, 11 Dec 2000 22:07:10 +0000 Subject: Initial revision svn path=/trunk/; revision=6915 --- libical/src/libicalss/icalclassify.c | 701 +++++++++++++++++++++++++++++++++++ 1 file changed, 701 insertions(+) create mode 100644 libical/src/libicalss/icalclassify.c (limited to 'libical/src/libicalss/icalclassify.c') diff --git a/libical/src/libicalss/icalclassify.c b/libical/src/libicalss/icalclassify.c new file mode 100644 index 0000000000..e0ee710544 --- /dev/null +++ b/libical/src/libicalss/icalclassify.c @@ -0,0 +1,701 @@ +/* -*- Mode: C -*- + ====================================================================== + FILE: icalclassify.c + CREATOR: ebusboom 23 aug 2000 + + $Id$ + $Locker$ + + (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org + + This program is free software; you can redistribute it and/or modify + it under the terms of either: + + The LGPL as published by the Free Software Foundation, version + 2.1, available at: http://www.fsf.org/copyleft/lesser.html + + Or: + + The Mozilla Public License Version 1.0. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + + ======================================================================*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "ical.h" +#include "icalclassify.h" +#include "icalmemory.h" +#include /* For tolower() */ +#include /* for index() */ +#include /* for malloc and free */ + + + +struct icalclassify_parts { + icalcomponent *c; + icalproperty_method method; + char* organizer; + icalparameter_partstat reply_partstat; + char* reply_attendee; + char* uid; + int sequence; + struct icaltimetype dtstamp; + struct icaltimetype recurrence_id; +}; + + +char* icalclassify_lowercase(const char* str) +{ + char* p = 0; + char* new = icalmemory_strdup(str); + + if(str ==0){ + return 0; + } + + for(p = new; *p!=0; p++){ + *p = tolower(*p); + } + + return new; +} + +/* Return a set of components that intersect in time with comp. For +component X and Y to intersect: + X.DTSTART < Y.DTEND && X.DTEND > Y.DTSTART +*/ + + +icalcomponent* icalclassify_find_overlaps(icalset* set, icalcomponent* comp) +{ + icalcomponent *return_set; + icalcomponent *c; + struct icaltime_span span,compspan; + + icalerror_clear_errno(); + compspan = icalcomponent_get_span(comp); + + if(icalerrno != ICAL_NO_ERROR){ + return 0; + } + + + return_set = icalcomponent_new(ICAL_XROOT_COMPONENT); + + for(c = icalset_get_first_component(set); + c != 0; + c = icalset_get_next_component(set)){ + + icalerror_clear_errno(); + + span = icalcomponent_get_span(c); + + if(icalerrno != ICAL_NO_ERROR){ + continue; + } + + if (compspan.start < span.end && + compspan.end > span.start){ + + icalcomponent *clone = icalcomponent_new_clone(c); + + icalcomponent_add_component(return_set,clone); + } + } + + if(icalcomponent_count_components(return_set,ICAL_ANY_COMPONENT) !=0){ + return return_set; + } else { + icalcomponent_free(return_set); + return 0; + } +} + + + +icalparameter_partstat icalclassify_find_attendee(icalcomponent *c, + const char* attendee) +{ + icalproperty *p; + char* lattendee = icalclassify_lowercase(attendee); + char* upn = index(lattendee,':'); + icalcomponent *inner = icalcomponent_get_first_real_component(c); + + for(p = icalcomponent_get_first_property(inner,ICAL_ATTENDEE_PROPERTY); + p != 0; + p = icalcomponent_get_next_property(inner,ICAL_ATTENDEE_PROPERTY)) + { + const char* this_attendee + = icalclassify_lowercase(icalproperty_get_attendee(p)); + char* this_upn = index(this_attendee,':'); + + if(strcmp(this_upn,upn)==0){ + + icalparameter *param = icalproperty_get_first_parameter(p, + ICAL_PARTSTAT_PARAMETER); + if (param != 0){ + free(lattendee); + free((void*)this_attendee); + return icalparameter_get_partstat(param); + } + + } + + } + + free(lattendee); + return ICAL_PARTSTAT_NONE; + +} + +void icalssutil_free_parts(struct icalclassify_parts *parts) +{ + if(parts == 0){ + return; + } + + if(parts->organizer != 0){ + free(parts->organizer); + } + + if(parts->uid != 0){ + free(parts->uid); + } + + if(parts->reply_attendee){ + free(parts->reply_attendee); + } +} + +void icalssutil_get_parts(icalcomponent* c, + struct icalclassify_parts* parts) +{ + icalproperty *p; + icalcomponent *inner; + + memset(parts,0,sizeof(struct icalclassify_parts)); + + parts->method = ICAL_METHOD_NONE; + parts->sequence = 0; + parts->reply_partstat = ICAL_PARTSTAT_NONE; + + if(c == 0){ + return; + } + + parts->c = c; + + p = icalcomponent_get_first_property(c,ICAL_METHOD_PROPERTY); + if(p!=0){ + parts->method = icalproperty_get_method(p); + } + + inner = icalcomponent_get_first_real_component(c); + + p = icalcomponent_get_first_property(inner,ICAL_ORGANIZER_PROPERTY); + if(p!=0){ + parts->organizer = strdup(icalproperty_get_organizer(p)); + } + + p = icalcomponent_get_first_property(inner,ICAL_SEQUENCE_PROPERTY); + if(p!=0){ + parts->sequence = icalproperty_get_sequence(p); + } + + p = icalcomponent_get_first_property(inner,ICAL_UID_PROPERTY); + if(p!=0){ + parts->uid = strdup(icalproperty_get_uid(p)); + } + + p = icalcomponent_get_first_property(inner,ICAL_RECURRENCEID_PROPERTY); + if(p!=0){ + parts->recurrence_id = icalproperty_get_recurrenceid(p); + } + + p = icalcomponent_get_first_property(inner,ICAL_DTSTAMP_PROPERTY); + if(p!=0){ + parts->dtstamp = icalproperty_get_dtstamp(p); + } + + if(parts->method==ICAL_METHOD_REPLY){ + icalparameter *param; + p = icalcomponent_get_first_property(inner,ICAL_ATTENDEE_PROPERTY); + + if(p!=0){ + + param = icalproperty_get_first_parameter(p,ICAL_PARTSTAT_PARAMETER); + + if(param != 0){ + parts->reply_partstat = + icalparameter_get_partstat(param); + } + + parts->reply_attendee = strdup(icalproperty_get_attendee(p)); + } + + } + + +} + + +int icalssutil_is_rescheduled(icalcomponent* a,icalcomponent* b) +{ + icalproperty *p1,*p2; + icalcomponent *i1,*i2; + int i; + + icalproperty_kind kind_array[] = { + ICAL_DTSTART_PROPERTY, + ICAL_DTEND_PROPERTY, + ICAL_DURATION_PROPERTY, + ICAL_DUE_PROPERTY, + ICAL_RRULE_PROPERTY, + ICAL_RDATE_PROPERTY, + ICAL_EXRULE_PROPERTY, + ICAL_EXDATE_PROPERTY, + ICAL_NO_PROPERTY + }; + + i1 = icalcomponent_get_first_real_component(a); + i2 = icalcomponent_get_first_real_component(b); + + for(i =0; kind_array[i] != ICAL_NO_PROPERTY; i++){ + p1 = icalcomponent_get_first_property(i1,kind_array[i]); + p2 = icalcomponent_get_first_property(i2,kind_array[i]); + + if( (p1!=0)^(p1!=0) ){ + /* Return true if the property exists in one component and not + the other */ + return 1; + } + + if(p1 && strcmp(icalproperty_as_ical_string(p1), + icalproperty_as_ical_string(p2)) != 0){ + return 1; + } + } + + return 0; + +} + +#define icalclassify_pre \ + int rtrn =0; + +#define icalclassify_post \ + return rtrn; + + +int icalclassify_publish_new(struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalclassify_pre; + + if(comp->method == ICAL_METHOD_PUBLISH && + match == 0){ + rtrn = 1; + } + + icalclassify_post; + +} + +int icalclassify_publish_update(struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalclassify_pre; + + if(comp->method == ICAL_METHOD_PUBLISH && + match !=0 ){ + rtrn = 1; + } + + icalclassify_post; + +} + +int icalclassify_publish_freebusy(struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalclassify_pre; + + if(comp->method == ICAL_METHOD_PUBLISH && + match == 0){ + rtrn = 1; + } + + icalclassify_post; + +} + + +int icalclassify_request_new(struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + /* Method is REQUEST, and there is no match */ + + icalclassify_pre + + if(match->c==0 && comp->method == ICAL_METHOD_REQUEST){ + rtrn = 1; + } + + icalclassify_post + +} + +int icalclassify_request_update( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + /* REQUEST method, Higher SEQUENCE than match, and all + time-related properties are unchanged */ + + icalclassify_pre + + if (match != 0 && + comp->sequence >= match->sequence && + !icalssutil_is_rescheduled(comp->c,match->c)){ + rtrn = 1; + } + + icalclassify_post + +} + +int icalclassify_request_reschedule( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + /* REQUEST method, Higher SEQUENCE than match, and one or more + time-related properties are changed */ + icalclassify_pre + + if (match->c != 0 && + comp->sequence > match->sequence && + icalssutil_is_rescheduled(comp->c,match->c)){ + rtrn = 1; + } + + icalclassify_post + +} + +int icalclassify_request_delegate( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalclassify_pre + + if (match->c != 0 && + comp->sequence > match->sequence && + icalssutil_is_rescheduled(comp->c,match->c)){ + rtrn = 1; + } + + icalclassify_post + +} + +int icalclassify_request_new_organizer( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + /* Organizer has changed between match and component */ + icalclassify_pre + + icalclassify_post + +} + +int icalclassify_request_status( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalclassify_pre + icalclassify_post +} + +int icalclassify_request_forward( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalclassify_pre + icalclassify_post +} + +int icalclassify_request_freebusy( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalclassify_pre + icalclassify_post +} + +int icalclassify_reply_accept( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalparameter_partstat partstat; + icalclassify_pre; + + partstat = icalclassify_find_attendee(match->c,comp->reply_attendee); + + if(partstat != ICAL_PARTSTAT_NONE && + comp->reply_partstat == ICAL_PARTSTAT_ACCEPTED){ + rtrn = 1; + } + + icalclassify_post +} +int icalclassify_reply_decline( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalparameter_partstat partstat; + icalclassify_pre; + + + partstat = icalclassify_find_attendee(match->c,comp->reply_attendee); + + if(partstat != ICAL_PARTSTAT_NONE && + comp->reply_partstat == ICAL_PARTSTAT_DECLINED){ + rtrn = 1; + } + icalclassify_post +} +int icalclassify_reply_crasher_accept( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalparameter_partstat partstat; + icalclassify_pre; + + + partstat = icalclassify_find_attendee(match->c,comp->reply_attendee); + + if(partstat == ICAL_PARTSTAT_NONE && + comp->reply_partstat == ICAL_PARTSTAT_ACCEPTED){ + rtrn = 1; + } + icalclassify_post +} +int icalclassify_reply_crasher_decline( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalparameter_partstat partstat; + icalclassify_pre; + + + partstat = icalclassify_find_attendee(match->c,comp->reply_attendee); + + if(partstat == ICAL_PARTSTAT_NONE && + comp->reply_partstat == ICAL_PARTSTAT_DECLINED){ + rtrn = 1; + } + icalclassify_post +} +int icalclassify_add_instance( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalclassify_pre + if(comp->method == ICAL_METHOD_ADD){ + rtrn = 1; + } + icalclassify_post +} +int icalclassify_cancel_event( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalclassify_pre + if(comp->method == ICAL_METHOD_CANCEL){ + rtrn = 1; + } + icalclassify_post +} +int icalclassify_cancel_instance( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalclassify_pre + if(comp->method == ICAL_METHOD_CANCEL){ + rtrn = 1; + } + icalclassify_post +} +int icalclassify_cancel_all( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalclassify_pre + if(comp->method == ICAL_METHOD_CANCEL){ + rtrn = 1; + } + icalclassify_post +} +int icalclassify_refesh( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalclassify_pre + if(comp->method == ICAL_METHOD_REFRESH){ + rtrn = 1; + } + icalclassify_post +} +int icalclassify_counter( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalclassify_pre + if(comp->method == ICAL_METHOD_COUNTER){ + rtrn = 1; + } + icalclassify_post +} +int icalclassify_delinecounter( + struct icalclassify_parts *comp, + struct icalclassify_parts *match, + const char* user) +{ + icalclassify_pre + + if(comp->method == ICAL_METHOD_DECLINECOUNTER){ + rtrn = 1; + } + + icalclassify_post +} + +struct icalclassify_map { + icalproperty_method method; + int (*fn)(struct icalclassify_parts *comp,struct icalclassify_parts *match, const char* user); + ical_class class; +} icalclassify_map[] = +{ {ICAL_METHOD_PUBLISH,icalclassify_publish_new,ICAL_PUBLISH_NEW_CLASS}, + {ICAL_METHOD_PUBLISH,icalclassify_publish_update,ICAL_PUBLISH_UPDATE_CLASS}, + {ICAL_METHOD_PUBLISH,icalclassify_publish_freebusy,ICAL_PUBLISH_FREEBUSY_CLASS}, + {ICAL_METHOD_REQUEST,icalclassify_request_new,ICAL_REQUEST_NEW_CLASS}, + {ICAL_METHOD_REQUEST,icalclassify_request_update,ICAL_REQUEST_UPDATE_CLASS}, + {ICAL_METHOD_REQUEST,icalclassify_request_reschedule,ICAL_REQUEST_RESCHEDULE_CLASS}, + {ICAL_METHOD_REQUEST,icalclassify_request_delegate,ICAL_REQUEST_DELEGATE_CLASS}, + {ICAL_METHOD_REQUEST,icalclassify_request_new_organizer,ICAL_REQUEST_NEW_ORGANIZER_CLASS}, + {ICAL_METHOD_REQUEST,icalclassify_request_forward,ICAL_REQUEST_FORWARD_CLASS}, + {ICAL_METHOD_REQUEST,icalclassify_request_status,ICAL_REQUEST_STATUS_CLASS}, + {ICAL_METHOD_REQUEST,icalclassify_request_freebusy,ICAL_REQUEST_FREEBUSY_CLASS}, + + {ICAL_METHOD_REPLY,icalclassify_reply_accept,ICAL_REPLY_ACCEPT_CLASS}, + {ICAL_METHOD_REPLY,icalclassify_reply_decline,ICAL_REPLY_DECLINE_CLASS}, + {ICAL_METHOD_REPLY,icalclassify_reply_crasher_accept,ICAL_REPLY_CRASHER_ACCEPT_CLASS}, + {ICAL_METHOD_REPLY,icalclassify_reply_crasher_decline,ICAL_REPLY_CRASHER_DECLINE_CLASS}, + + {ICAL_METHOD_ADD,icalclassify_add_instance,ICAL_ADD_INSTANCE_CLASS}, + + {ICAL_METHOD_CANCEL,icalclassify_cancel_event,ICAL_CANCEL_EVENT_CLASS}, + {ICAL_METHOD_CANCEL,icalclassify_cancel_instance,ICAL_CANCEL_INSTANCE_CLASS}, + {ICAL_METHOD_CANCEL,icalclassify_cancel_all,ICAL_CANCEL_ALL_CLASS}, + + {ICAL_METHOD_REFRESH,icalclassify_refesh,ICAL_REFRESH_CLASS}, + {ICAL_METHOD_COUNTER,icalclassify_counter,ICAL_COUNTER_CLASS}, + {ICAL_METHOD_DECLINECOUNTER,icalclassify_delinecounter,ICAL_DECLINECOUNTER_CLASS}, + {ICAL_METHOD_NONE,0,ICAL_NO_CLASS} +}; + + +ical_class icalclassify(icalcomponent* c,icalcomponent* match, + const char* user) +{ + icalcomponent *inner; + icalproperty *p; + icalproperty_method method; + ical_class class = ICAL_UNKNOWN_CLASS; + + int i; + + struct icalclassify_parts comp_parts; + struct icalclassify_parts match_parts; + + inner = icalcomponent_get_first_real_component(c); + + if (inner == 0) { + return ICAL_NO_CLASS; + } + + icalssutil_get_parts(c,&comp_parts); + icalssutil_get_parts(match,&match_parts); + + /* Determine if the incoming component is obsoleted by the match */ + if(match != 0 && ( + comp_parts.method == ICAL_METHOD_REQUEST + )){ + assert ( ! ((comp_parts.dtstamp.is_utc==1)^ + (match_parts.dtstamp.is_utc==1))); + + if( comp_parts.sequence0) + { + /* comp has a smaller sequence and a later DTSTAMP */ + return ICAL_MISSEQUENCED_CLASS; + } + + if( (comp_parts.sequence