[CalendarServer-changes] [3601] CalendarServer/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Tue Jan 20 13:02:18 PST 2009
Revision: 3601
http://trac.macosforge.org/projects/calendarserver/changeset/3601
Author: cdaboo at apple.com
Date: 2009-01-20 13:02:18 -0800 (Tue, 20 Jan 2009)
Log Message:
-----------
Make sure entirely cancelled event written by ATTENDEE is ignored rather than generating a 403.
Modified Paths:
--------------
CalendarServer/trunk/run
CalendarServer/trunk/twistedcaldav/ical.py
CalendarServer/trunk/twistedcaldav/scheduling/icaldiff.py
CalendarServer/trunk/twistedcaldav/scheduling/implicit.py
CalendarServer/trunk/twistedcaldav/scheduling/test/test_icaldiff.py
Modified: CalendarServer/trunk/run
===================================================================
--- CalendarServer/trunk/run 2009-01-20 21:01:01 UTC (rev 3600)
+++ CalendarServer/trunk/run 2009-01-20 21:02:18 UTC (rev 3601)
@@ -692,7 +692,7 @@
caldavtester="${top}/CalDAVTester";
-svn_get "CalDAVTester" "${caldavtester}" "${svn_uri_base}/CalDAVTester/trunk" 3587;
+svn_get "CalDAVTester" "${caldavtester}" "${svn_uri_base}/CalDAVTester/trunk" 3600;
#
# Calendar Server
Modified: CalendarServer/trunk/twistedcaldav/ical.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/ical.py 2009-01-20 21:01:01 UTC (rev 3600)
+++ CalendarServer/trunk/twistedcaldav/ical.py 2009-01-20 21:02:18 UTC (rev 3601)
@@ -1724,6 +1724,14 @@
self.removeProperty(duration)
self.addProperty(Property("DTEND", newdtend))
+ exdates = self.properties("EXDATE")
+ for exdate in exdates:
+ exdate.setValue([normalizeToUTC(value) for value in exdate.value()])
+ try:
+ del exdate.params()["TZID"]
+ except KeyError:
+ pass
+
rid = self.getProperty("RECURRENCE-ID")
if rid is not None:
rid.setValue(normalizeToUTC(rid.value()))
Modified: CalendarServer/trunk/twistedcaldav/scheduling/icaldiff.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/scheduling/icaldiff.py 2009-01-20 21:01:01 UTC (rev 3600)
+++ CalendarServer/trunk/twistedcaldav/scheduling/icaldiff.py 2009-01-20 21:02:18 UTC (rev 3601)
@@ -14,7 +14,7 @@
# limitations under the License.
##
-from twistedcaldav.ical import Component
+from twistedcaldav.ical import Component, Property
from twistedcaldav.log import Logger
from twistedcaldav.scheduling.cuaddress import normalizeCUAddr
from twistedcaldav.scheduling.itip import iTipGenerator
@@ -239,19 +239,19 @@
self.calendar2 = duplicateAndNormalize(self.calendar2)
if self.calendar1 == self.calendar2:
- return True, True
+ return True, True, ()
# Need to look at each component and do special comparisons
# Make sure the same VCALENDAR properties match
if not self._checkVCALENDARProperties():
self._logDiffError("attendeeDiff: VCALENDAR properties do not match")
- return False, False
+ return False, False, ()
# Make sure the same VTIMEZONE components appear
if not self._compareVTIMEZONEs():
self._logDiffError("attendeeDiff: VTIMEZONEs do not match")
- return False, False
+ return False, False, ()
# Compare each component instance from the new calendar with each derived
# component instance from the old one
@@ -377,37 +377,56 @@
map2 = mapComponents(self.calendar2)
set2 = set(map2.keys())
+ # Ugly case: if an Attendee has a STATUS:CANCELLED meeting and the ORGANIZER does not,
+ # we may need to remove an EXDATE for the cancelled instance from the ORGANIZER's
+ # master instance to ensure that matches
+ cancelled_rids = []
+ master2 = self.calendar2.masterComponent()
+ for key in set2 - set1:
+ component2 = map2[key]
+ if component2.propertyValue("STATUS") == "CANCELLED":
+ rid = component2.getRecurrenceIDUTC()
+ cancelled_rids.append(rid)
+ if master2:
+ master2.addProperty(Property("EXDATE", [rid,]))
+
# All the components in calendar1 must be in calendar2
result = set1 - set2
if result:
log.debug("Missing components from first calendar: %s" % (result,))
- return False, False
+ return False, False, ()
# Now verify that each component in set1 matches what is in set2
attendee_unchanged = True
for key, value in map1.iteritems():
component1 = value
component2 = map2[key]
-
+
nomismatch, no_attendee_change = self._testComponents(component1, component2)
if not nomismatch:
- return False, False
+ return False, False, ()
attendee_unchanged &= no_attendee_change
# Now verify that each additional component in set2 matches a derived component in set1
for key in set2 - set1:
+
+ # First check if the attendee's copy is cancelled
+ component2 = map2[key]
+ if component2.propertyValue("STATUS") == "CANCELLED":
+ continue
+
+ # Now derive the organizer's expected instance and compare
component1 = self.calendar1.deriveInstance(key[2])
if component1 is None:
log.debug("_compareComponents: Could not derive instance: %s" % (key[2],))
- return False, False
- component2 = map2[key]
+ return False, False, ()
nomismatch, no_attendee_change = self._testComponents(component1, component2)
if not nomismatch:
- return False, False
+ return False, False, ()
attendee_unchanged &= no_attendee_change
- return True, attendee_unchanged
+ return True, attendee_unchanged, tuple(cancelled_rids)
def _testComponents(self, comp1, comp2):
Modified: CalendarServer/trunk/twistedcaldav/scheduling/implicit.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/scheduling/implicit.py 2009-01-20 21:01:01 UTC (rev 3600)
+++ CalendarServer/trunk/twistedcaldav/scheduling/implicit.py 2009-01-20 21:02:18 UTC (rev 3601)
@@ -662,13 +662,39 @@
self.oldcalendar = None
# Determine whether the current change is allowed
- if self.isAttendeeChangeInsignificant():
+ change_allowed, no_itip, cancelled_rids = self.isAttendeeChangeInsignificant()
+
+ if not change_allowed:
+ if self.calendar.hasPropertyValueInAllComponents(Property("STATUS", "CANCELLED")):
+ log.debug("Attendee '%s' is creating CANCELLED event for mismatched UID: '%s' - removing entire event" % (self.attendee, self.uid,))
+ self.return_status = ImplicitScheduler.STATUS_ORPHANED_CANCELLED_EVENT
+ returnValue(None)
+ else:
+ log.error("Attendee '%s' is not allowed to make an unauthorized change to an organized event: UID:%s" % (self.attendeePrincipal, self.uid,))
+ raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "valid-attendee-change")))
+
+ # Remove orphaned attendee cancelled events
+ if cancelled_rids:
+ log.debug("Attendee '%s' is creating CANCELLED overridden instances for UID: '%s' - removing instances" % (self.attendee, self.uid,))
+ master = self.calendar.masterComponent()
+ for rid in cancelled_rids:
+ self.calendar.removeComponent(self.calendar.overriddenComponent(rid))
+ if master:
+ master.addProperty(Property("EXDATE", [rid,]))
+
+ # If no components left, make sure we delete the orphaned event
+ if self.calendar.mainType() is None:
+ log.debug("Attendee '%s' CANCELLED all instances of UID: '%s' - removing entire event" % (self.attendee, self.uid,))
+ self.return_status = ImplicitScheduler.STATUS_ORPHANED_CANCELLED_EVENT
+ returnValue(None)
+
+ if no_itip:
log.debug("Implicit - attendee '%s' is updating UID: '%s' but change is not significant" % (self.attendee, self.uid))
returnValue(None)
elif isinstance(self.organizerAddress, LocalCalendarUser):
# Check to see whether all instances are CANCELLED
if self.calendar.hasPropertyValueInAllComponents(Property("STATUS", "CANCELLED")):
- log.debug("Attendee '%s' is creating CANCELLED event for UID: '%s' - missing organizer copy" % (self.attendee, self.uid,))
+ log.debug("Attendee '%s' is creating CANCELLED event for missing UID: '%s' - removing entire event" % (self.attendee, self.uid,))
self.return_status = ImplicitScheduler.STATUS_ORPHANED_CANCELLED_EVENT
returnValue(None)
else:
@@ -732,12 +758,9 @@
oldcalendar = self.organizer_calendar
oldcalendar.attendeesView((self.attendee,))
differ = iCalDiff(oldcalendar, self.calendar, self.do_smart_merge)
- change_allowed, no_itip = differ.attendeeDiff(self.attendee)
- if not change_allowed:
- log.error("Attendee '%s' is not allowed to make an unauthorized change to an organized event: UID:%s" % (self.attendeePrincipal, self.uid,))
- raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "valid-attendee-change")))
+ change_allowed, no_itip, cancelled_rids = differ.attendeeDiff(self.attendee)
- return no_itip
+ return change_allowed, no_itip, cancelled_rids
def scheduleWithOrganizer(self):
Modified: CalendarServer/trunk/twistedcaldav/scheduling/test/test_icaldiff.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/scheduling/test/test_icaldiff.py 2009-01-20 21:01:01 UTC (rev 3600)
+++ CalendarServer/trunk/twistedcaldav/scheduling/test/test_icaldiff.py 2009-01-20 21:02:18 UTC (rev 3601)
@@ -506,7 +506,7 @@
END:VCALENDAR
""",
"mailto:user2 at example.com",
- (True, True,)
+ (True, True, (),)
),
(
"#1.2 Simple component, PARTSTAT change",
@@ -537,7 +537,7 @@
END:VCALENDAR
""",
"mailto:user2 at example.com",
- (True, False,)
+ (True, False, (),)
),
(
"#1.3 Simple component, bad change",
@@ -568,7 +568,7 @@
END:VCALENDAR
""",
"mailto:user2 at example.com",
- (False, False,)
+ (False, False, (),)
),
(
"#1.4 Simple component, valarm change",
@@ -609,7 +609,7 @@
END:VCALENDAR
""",
"mailto:user2 at example.com",
- (True, True,)
+ (True, True, (),)
),
(
"#1.5 Simple component, vcalendar props change ok",
@@ -651,7 +651,7 @@
END:VCALENDAR
""",
"mailto:user2 at example.com",
- (True, True,)
+ (True, True, (),)
),
(
"#1.6 Simple component, vcalendar props change bad",
@@ -693,7 +693,7 @@
END:VCALENDAR
""",
"mailto:user2 at example.com",
- (True, True,)
+ (True, True, (),)
),
(
"#1.7 Simple component, vtimezone no change",
@@ -760,7 +760,7 @@
END:VCALENDAR
""",
"mailto:user2 at example.com",
- (True, True,)
+ (True, True, (),)
),
(
"#1.8 Simple component, vtimezone bad change",
@@ -827,7 +827,7 @@
END:VCALENDAR
""",
"mailto:user2 at example.com",
- (False, False,)
+ (False, False, (),)
),
)
@@ -885,7 +885,7 @@
END:VCALENDAR
""",
"mailto:user2 at example.com",
- (True, True,)
+ (True, True, (),)
),
(
"#1.2 Complex component, alarm change",
@@ -944,7 +944,7 @@
END:VCALENDAR
""",
"mailto:user2 at example.com",
- (True, True,)
+ (True, True, (),)
),
(
"#1.3 Complex component, missing override",
@@ -985,7 +985,7 @@
END:VCALENDAR
""",
"mailto:user2 at example.com",
- (False, False,)
+ (False, False, (),)
),
(
"#1.4 Complex component, additional override no change ok",
@@ -1043,7 +1043,7 @@
END:VCALENDAR
""",
"mailto:user2 at example.com",
- (True, True,)
+ (True, True, (),)
),
(
"#1.5 Complex component, additional override change ok",
@@ -1101,7 +1101,7 @@
END:VCALENDAR
""",
"mailto:user2 at example.com",
- (True, False,)
+ (True, False, (),)
),
(
"#1.6 Complex component, additional override bad",
@@ -1159,7 +1159,7 @@
END:VCALENDAR
""",
"mailto:user2 at example.com",
- (False, False,)
+ (False, False, (),)
),
)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20090120/3f6a3b09/attachment-0001.html>
More information about the calendarserver-changes
mailing list