Revision: 2097 http://trac.macosforge.org/projects/calendarserver/changeset/2097 Author: cdaboo@apple.com Date: 2008-01-10 12:23:26 -0800 (Thu, 10 Jan 2008) Log Message: ----------- Query match access restrictions. Modified Paths: -------------- CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/caldavxml.py CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/ical.py CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/method/report_calquery.py Modified: CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/caldavxml.py =================================================================== --- CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/caldavxml.py 2008-01-08 21:32:58 UTC (rev 2096) +++ CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/caldavxml.py 2008-01-10 20:23:26 UTC (rev 2097) @@ -191,7 +191,7 @@ self.filter_name = self.filter_name.encode("utf-8") self.defined = not self.qualifier or (self.qualifier.qname() != (caldav_namespace, "is-not-defined")) - def match(self, item): + def match(self, item, access=None): """ Returns True if the given calendar item (either a component, property or parameter value) matches this filter, False otherwise. @@ -201,11 +201,11 @@ # be negated by the caller if not self.defined: return True - if self.qualifier and not self.qualifier.match(item): return False + if self.qualifier and not self.qualifier.match(item, access): return False if len(self.filters) > 0: for filter in self.filters: - if filter._match(item): + if filter._match(item, access): return True return False else: @@ -893,12 +893,16 @@ allowed_children = { (caldav_namespace, "comp-filter"): (1, 1) } - def match(self, component): + def match(self, component, access): """ Returns True if the given calendar component matches this filter, False otherwise. """ + # We only care about certain access restrictions. + if access not in (iComponent.ACCESS_CONFIDENTIAL, iComponent.ACCESS_RESTRICTED): + access = None + # We need to prepare ourselves for a time-range query by pre-calculating # the set of instances up to the latest time-range limit. That way we can # avoid having to do some form of recurrence expansion for each query sub-part. @@ -910,7 +914,7 @@ self.children[0].setInstances(instances) # <filter> contains exactly one <comp-filter> - return self.children[0].match(component) + return self.children[0].match(component, access) def valid(self): """ @@ -962,7 +966,7 @@ } allowed_attributes = { "name": True } - def match(self, item): + def match(self, item, access): """ Returns True if the given calendar item (which is a component) matches this filter, False otherwise. @@ -978,20 +982,26 @@ if len(self.filters) > 0: for filter in self.filters: - if filter._match(item): + if filter._match(item, access): return True return False else: return True - def _match(self, component): + def _match(self, component, access): # At least one subcomponent must match (or is-not-defined is set) for subcomponent in component.subcomponents(): + # If access restrictions are in force, restrict matching to specific components only. + # In particular do not match VALARM. + if access and subcomponent.name() not in ("VEVENT", "VTODO", "VJOURNAL", "VFREEBUSY", "VTIMEZONE",): + continue + + # Try to match the component name if isinstance(self.filter_name, str): if subcomponent.name() != self.filter_name: continue else: if subcomponent.name() not in self.filter_name: continue - if self.match(subcomponent): break + if self.match(subcomponent, access): break else: return not self.defined return self.defined @@ -1117,10 +1127,22 @@ } allowed_attributes = { "name": True } - def _match(self, component): + def _match(self, component, access): + # When access restriction is in force, we need to only allow matches against the properties + # allowed by the access restriction level. + if access: + allowedProperties = iComponent.confidentialPropertiesMap.get(component.name(), None) + if allowedProperties and access == iComponent.ACCESS_RESTRICTED: + allowedProperties += iComponent.extraRestrictedProperties + else: + allowedProperties = None + # At least one property must match (or is-not-defined is set) for property in component.properties(): - if property.name() == self.filter_name and self.match(property): break + # Apply access restrictions, if any. + if allowedProperties is not None and property.name() not in allowedProperties: + continue + if property.name() == self.filter_name and self.match(property, access): break else: return not self.defined return self.defined @@ -1173,7 +1195,7 @@ } allowed_attributes = { "name": True } - def _match(self, property): + def _match(self, property, access): # We have to deal with the problem that the 'Native' form of a property # will be missing the TZID parameter due to the conversion performed. Converting # to non-native for the entire calendar object causes problems elsewhere, so its @@ -1186,7 +1208,7 @@ # At least one property must match (or is-not-defined is set) result = not self.defined for parameterName in property.params().keys(): - if parameterName == self.filter_name and self.match(property.params()[parameterName]): + if parameterName == self.filter_name and self.match(property.params()[parameterName], access): result = self.defined break @@ -1200,7 +1222,7 @@ """ name = "is-defined" - def match(self, component): + def match(self, component, access): return component is not None class IsNotDefined (CalDAVEmptyElement): @@ -1210,7 +1232,7 @@ """ name = "is-not-defined" - def match(self, component): + def match(self, component, access): # Oddly, this needs always to return True so that it appears there is # a match - but we then "negate" the result if is-not-defined is set. # Actually this method should never be called as we special case the @@ -1265,7 +1287,7 @@ else: self.negate = False - def match(self, item): + def match(self, item, access): """ Match the text for the item. If the item is a property, then match the property value, @@ -1356,7 +1378,7 @@ # No other tests return True - def match(self, property): + def match(self, property, access): """ NB This is only called when doing a time-range match on a property. """ Modified: CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/ical.py =================================================================== --- CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/ical.py 2008-01-08 21:32:58 UTC (rev 2096) +++ CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/ical.py 2008-01-10 20:23:26 UTC (rev 2097) @@ -175,6 +175,16 @@ "RESTRICTED" : ACCESS_RESTRICTED, } + confidentialPropertiesMap = { + "VCALENDAR": ("PRODID", "VERSION", "CALSCALE", ACCESS_PROPERTY), + "VEVENT": ("UID", "RECURRENCE-ID", "SEQUENCE", "DTSTAMP", "STATUS", "TRANSP", "DTSTART", "DTEND", "DURATION", "RRULE", "RDATE", "EXRULE", "EXDATE", ), + "VTODO": ("UID", "RECURRENCE-ID", "SEQUENCE", "DTSTAMP", "STATUS", "DTSTART", "COMPLETED", "DUE", "DURATION", "RRULE", "RDATE", "EXRULE", "EXDATE", ), + "VJOURNAL": ("UID", "RECURRENCE-ID", "SEQUENCE", "DTSTAMP", "STATUS", "DTSTART", "RRULE", "RDATE", "EXRULE", "EXDATE", ), + "VFREEBUSY": ("UID", "DTSTAMP", "DTSTART", "DTEND", "DURATION", "FREEBUSY", ), + "VTIMEZONE": None, + } + extraRestrictedProperties = ("SUMMARY", "LOCATION",) + @classmethod def fromString(clazz, string): """ Modified: CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/method/report_calquery.py =================================================================== --- CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/method/report_calquery.py 2008-01-08 21:32:58 UTC (rev 2096) +++ CalendarServer/branches/users/cdaboo/private_events-2081/twistedcaldav/method/report_calquery.py 2008-01-10 20:23:26 UTC (rev 2097) @@ -31,6 +31,7 @@ from twisted.web2.http import HTTPError, StatusResponse from twistedcaldav.caldavxml import caldav_namespace +from twistedcaldav.customxml import TwistedCalendarAccessProperty from twistedcaldav.method import report_common import urllib @@ -113,7 +114,16 @@ @param calendar: the L{Component} calendar read from the resource. """ - if query_ok or filter.match(calendar): + # Handle private events access restrictions + if not isowner: + try: + access = resource.readDeadProperty(TwistedCalendarAccessProperty) + except HTTPError: + access = None + else: + access = None + + if query_ok or filter.match(calendar, access): # Check size of results is within limit matchcount[0] += 1 if matchcount[0] > max_number_of_results:
participants (1)
-
source_changes@macosforge.org