# HG changeset patch # User Paul Boddie # Date 1441313497 -7200 # Node ID f88aabfdb8294500515b6ad490d6d75df8b72a76 # Parent cd46f5585f36f15eb6f204a3e7e8ab71e34eb393 Relaxed DTSTAMP tests in the outgoing handler so that Claws Mail responses can be processed. diff -r cd46f5585f36 -r f88aabfdb829 imiptools/client.py --- a/imiptools/client.py Thu Sep 03 21:50:57 2015 +0200 +++ b/imiptools/client.py Thu Sep 03 22:51:37 2015 +0200 @@ -380,11 +380,14 @@ return can_schedule(freebusy, periods, self.uid, self.recurrenceid) - def have_new_object(self, obj=None): + def have_new_object(self, obj=None, strict=True): """ Return whether the current object is new to the current user (or if the - given 'obj' is new). + given 'obj' is new). If 'strict' is specified and is a false value, the + DTSTAMP test will be ignored. This is useful in handling responses from + attendees from clients (like Claws Mail) that erase time information + from DTSTAMP and make it invalid. """ obj = obj or self.get_stored_object_version() @@ -398,37 +401,10 @@ # If the request refers to an older version of the object, ignore # it. - return is_new_object(sequence, self.sequence, dtstamp, self.dtstamp, - self.is_partstat_updated(obj)) + return is_new_object(sequence, self.sequence, dtstamp, self.dtstamp, not strict) return True - def is_partstat_updated(self, obj): - - """ - Return whether the participant status has been updated in the current - object in comparison to the given 'obj'. - - NOTE: Some clients like Claws Mail erase time information from DTSTAMP - NOTE: and make it invalid. Thus, such attendance information may also be - NOTE: incorporated into any new object assessment. - """ - - old_attendees = uri_dict(obj.get_value_map("ATTENDEE")) - new_attendees = uri_dict(self.obj.get_value_map("ATTENDEE")) - - for attendee, attr in old_attendees.items(): - old_partstat = attr.get("PARTSTAT") - new_attr = new_attendees.get(attendee) - new_partstat = new_attr and new_attr.get("PARTSTAT") - - if old_partstat == "NEEDS-ACTION" and new_partstat and \ - new_partstat != old_partstat: - - return True - - return False - def possibly_recurring_indefinitely(self): "Return whether the object recurs indefinitely." diff -r cd46f5585f36 -r f88aabfdb829 imiptools/data.py --- a/imiptools/data.py Thu Sep 03 21:50:57 2015 +0200 +++ b/imiptools/data.py Thu Sep 03 22:51:37 2015 +0200 @@ -706,11 +706,11 @@ # Operations on structure data. -def is_new_object(old_sequence, new_sequence, old_dtstamp, new_dtstamp, partstat_set): +def is_new_object(old_sequence, new_sequence, old_dtstamp, new_dtstamp, ignore_dtstamp): """ Return for the given 'old_sequence' and 'new_sequence', 'old_dtstamp' and - 'new_dtstamp', and the 'partstat_set' indication, whether the object + 'new_dtstamp', and the 'ignore_dtstamp' indication, whether the object providing the new information is really newer than the object providing the old information. """ @@ -726,7 +726,7 @@ is_same_sequence and is_old_dtstamp ) - return is_same_sequence and partstat_set or not is_old_sequence + return is_same_sequence and ignore_dtstamp or not is_old_sequence def get_periods(obj, tzid, end=None, inclusive=False): diff -r cd46f5585f36 -r f88aabfdb829 imiptools/handlers/person_outgoing.py --- a/imiptools/handlers/person_outgoing.py Thu Sep 03 21:50:57 2015 +0200 +++ b/imiptools/handlers/person_outgoing.py Thu Sep 03 22:51:37 2015 +0200 @@ -47,9 +47,10 @@ self.set_identity(from_organiser) - # Check for event using UID. + # Check for a new event, tolerating not-strictly-new events if the + # attendee is responding. - if not self.have_new_object(): + if not self.have_new_object(strict=from_organiser): return False # Update the object.