[CalendarServer-changes] [3542] CalendarServer/branches/users/cdaboo/normalize-cuaddr-3531/ twistedcaldav

source_changes at macosforge.org source_changes at macosforge.org
Wed Dec 17 19:39:03 PST 2008


Revision: 3542
          http://trac.macosforge.org/projects/calendarserver/changeset/3542
Author:   cdaboo at apple.com
Date:     2008-12-17 19:39:03 -0800 (Wed, 17 Dec 2008)
Log Message:
-----------
Normalize cuaddrs to urn:uuid form as data is written by the client.

Modified Paths:
--------------
    CalendarServer/branches/users/cdaboo/normalize-cuaddr-3531/twistedcaldav/method/put_common.py
    CalendarServer/branches/users/cdaboo/normalize-cuaddr-3531/twistedcaldav/method/report_common.py
    CalendarServer/branches/users/cdaboo/normalize-cuaddr-3531/twistedcaldav/resource.py

Modified: CalendarServer/branches/users/cdaboo/normalize-cuaddr-3531/twistedcaldav/method/put_common.py
===================================================================
--- CalendarServer/branches/users/cdaboo/normalize-cuaddr-3531/twistedcaldav/method/put_common.py	2008-12-17 18:46:25 UTC (rev 3541)
+++ CalendarServer/branches/users/cdaboo/normalize-cuaddr-3531/twistedcaldav/method/put_common.py	2008-12-18 03:39:03 UTC (rev 3542)
@@ -332,6 +332,10 @@
                     log.err(message)
                     raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "valid-calendar-object-resource")))
 
+                # Normalize the calendar user addresses once we know we have valid
+                # calendar data
+                self.destination.iCalendarAddressDoNormalization(self.calendar)
+
                 # Must have a valid UID at this point
                 self.uid = self.calendar.resourceUID()
             else:

Modified: CalendarServer/branches/users/cdaboo/normalize-cuaddr-3531/twistedcaldav/method/report_common.py
===================================================================
--- CalendarServer/branches/users/cdaboo/normalize-cuaddr-3531/twistedcaldav/method/report_common.py	2008-12-17 18:46:25 UTC (rev 3541)
+++ CalendarServer/branches/users/cdaboo/normalize-cuaddr-3531/twistedcaldav/method/report_common.py	2008-12-18 03:39:03 UTC (rev 3542)
@@ -138,7 +138,7 @@
     Return all (non-hidden) properties for the specified resource.
     @param request: the L{IRequest} for the current request.
     @param prop: the L{PropertyContainer} element for the properties of interest.
-    @param resource: the L{CalDAVFile} for the targetted resource.
+    @param resource: the L{CalDAVFile} for the targeted resource.
     @param calendar: the L{Component} for the calendar for the resource. This may be None
         if the calendar has not already been read in, in which case the resource
         will be used to get the calendar if needed.
@@ -160,7 +160,7 @@
     Return property names for all properties on the specified resource.
     @param request: the L{IRequest} for the current request.
     @param prop: the L{PropertyContainer} element for the properties of interest.
-    @param resource: the L{CalDAVFile} for the targetted resource.
+    @param resource: the L{CalDAVFile} for the targeted resource.
     @param calendar: the L{Component} for the calendar for the resource. This may be None
         if the calendar has not already been read in, in which case the resource
         will be used to get the calendar if needed.
@@ -185,7 +185,7 @@
     Return the specified properties on the specified resource.
     @param request: the L{IRequest} for the current request.
     @param prop: the L{PropertyContainer} element for the properties of interest.
-    @param resource: the L{CalDAVFile} for the targetted resource.
+    @param resource: the L{CalDAVFile} for the targeted resource.
     @param calendar: the L{Component} for the calendar for the resource. This may be None
         if the calendar has not already been read in, in which case the resource
         will be used to get the calendar if needed.
@@ -226,7 +226,7 @@
     Return the specified properties on the specified resource.
     @param request: the L{IRequest} for the current request.
     @param props: a list of property elements or qname tuples for the properties of interest.
-    @param resource: the L{CalDAVFile} for the targetted resource.
+    @param resource: the L{CalDAVFile} for the targeted resource.
     @param calendar: the L{Component} for the calendar for the resource. This may be None
         if the calendar has not already been read in, in which case the resource
         will be used to get the calendar if needed.
@@ -298,9 +298,9 @@
     @param matchtotal:  the running total for the number of matches.
     @param excludeuid:  a C{str} containing a UID value to exclude any components with that
         UID from contributing to free-busy.
-    @param organizer:   a C{str} containing the value of the ORGANIZER proeprty in the VFREEBUSY request.
+    @param organizer:   a C{str} containing the value of the ORGANIZER property in the VFREEBUSY request.
         This is used in conjunction with the UID value to process exclusions.
-    @param same_calendar_user:   a C{bool} indicating whether the calendar user requesting tyhe free-busy information
+    @param same_calendar_user:   a C{bool} indicating whether the calendar user requesting the free-busy information
         is the same as the calendar user being targeted.
     @param servertoserver:       a C{bool} indicating whether we are doing a local or remote lookup request.
     """
@@ -313,6 +313,10 @@
         except AccessDeniedError:
             returnValue(matchtotal)
 
+    # May need organizer principal
+    organizer_principal = calresource.principalForCalendarUserAddress(organizer) if organizer else None
+    organizer_uid = organizer_principal.principalUID() if organizer_principal else ""
+
     #
     # What we do is a fake calendar-query for VEVENT/VFREEBUSYs in the specified time-range.
     # We then take those results and merge them into one VFREEBUSY component
@@ -339,7 +343,7 @@
         tz = None
     tzinfo = filter.settimezone(tz)
 
-    # Do some optimisation of access control calculation by determining any inherited ACLs outside of
+    # Do some optimization of access control calculation by determining any inherited ACLs outside of
     # the child resource loop and supply those to the checkPrivileges on each child.
     filteredaces = (yield calresource.inheritedACEsforChildren(request))
 
@@ -363,8 +367,8 @@
         calendar = calresource.iCalendar(name)
         
         # The calendar may come back as None if the resource is being changed, or was deleted
-        # between our initial index query and getting here. For now we will ignore this errror, but in
-        # the longer term we need to simplement some form of locking, perhaps.
+        # between our initial index query and getting here. For now we will ignore this error, but in
+        # the longer term we need to implement some form of locking, perhaps.
         if calendar is None:
             log.err("Calendar %s is missing from calendar collection %r" % (name, calresource))
             continue
@@ -373,18 +377,22 @@
         if excludeuid:
             # See if we have a UID match
             if (excludeuid == uid):
+                test_organizer = calendar.getOrganizer()
+                test_principal = calresource.principalForCalendarUserAddress(test_organizer)
+                test_uid = test_principal.principalUID() if test_principal else ""
+
                 # Check that ORGANIZER's match (security requirement)
-                if (organizer is None) or (organizer == calendar.getOrganizer()):
+                if (organizer is None) or (organizer_uid == test_uid):
                     continue
                 # Check for no ORGANIZER and check by same calendar user
-                elif (calendar.getOrganizer() is None) and same_calendar_user:
+                elif (test_organizer is None) and same_calendar_user:
                     continue
 
         if filter.match(calendar, None):
             # Check size of results is within limit
             matchtotal += 1
             if matchtotal > max_number_of_matches:
-                raise NumberOfMatchesWithinLimits(max_number_of_results)
+                raise NumberOfMatchesWithinLimits(max_number_of_matches)
 
             if calendar.mainType() == "VEVENT":
                 processEventFreeBusy(calendar, fbinfo, timerange, tzinfo)
@@ -486,7 +494,7 @@
             if fbtype == "FREE":
                 continue
             
-            # Look at each period in the propert
+            # Look at each period in the property
             assert isinstance(fb.value(), list), "FREEBUSY property does not contain a list of values: %r" % (fb,)
             for period in fb.value():
                 # Clip period for this instance
@@ -555,7 +563,7 @@
             uid = component.propertyValue("UID")
             uidmap.setdefault(uid, []).append(component)
             
-    # Then we expand each uid set seperately
+    # Then we expand each uid set separately
     for componentSet in uidmap.itervalues():
         instances = InstanceList()
         instances.expandTimeRanges(componentSet, timerange.end)

Modified: CalendarServer/branches/users/cdaboo/normalize-cuaddr-3531/twistedcaldav/resource.py
===================================================================
--- CalendarServer/branches/users/cdaboo/normalize-cuaddr-3531/twistedcaldav/resource.py	2008-12-17 18:46:25 UTC (rev 3541)
+++ CalendarServer/branches/users/cdaboo/normalize-cuaddr-3531/twistedcaldav/resource.py	2008-12-18 03:39:03 UTC (rev 3542)
@@ -59,8 +59,10 @@
 from twistedcaldav.ical import allowedComponents
 from twistedcaldav.ical import Component as iComponent
 from twistedcaldav.log import LoggingMixIn
+from twistedcaldav.scheduling.cuaddress import normalizeCUAddr
 
 from urlparse import urlsplit
+import itertools
 
 if twistedcaldav.__version__:
     serverVersion = twisted.web2.server.VERSION + " TwistedCalDAV/" + twistedcaldav.__version__
@@ -627,6 +629,73 @@
         """
         return caldavxml.CalendarData.fromCalendar(self.iCalendar(name))
 
+    def iCalendarAddressDoNormalization(self, ical):
+        """
+        Normalize calendar user addresses in the supplied iCalendar object into their
+        urn:uuid form where possible. Also reset CN= property and add X-CALENDARSERVER-EMAIL property.
+
+        @param ical: calendar object to normalize.
+        @type ical: L{Component}
+        """
+        
+        def normalizeCalendarUserAddress(prop):
+            """
+            Do the ORGANIZER/ATTENDEE property normalization.
+
+            @param prop: organizer/attendee property
+            @type prop: L{Property}
+            """
+            
+            # Check that we have a principal for this calendar user address - if not we
+            # cannot do anything with it
+            cuaddr = normalizeCUAddr(prop.value())
+            principal = self.principalForCalendarUserAddress(cuaddr)
+            if principal is None:
+                return
+
+            # Always re-write value to urn:uuid
+            prop.setValue("urn:uuid:%s" % (principal.record.guid,))
+
+            # Always re-write the CN parameter
+            if principal.record.fullName:
+                prop.params()["CN"] = [principal.record.fullName,]
+            else:
+                try:
+                    del prop.params()["CN"]
+                except KeyError:
+                    pass
+
+            # Re-write the X-CALENDARSERVER-EMAIL if its value no longer matches
+            oldemail = prop.params().get("X-CALENDARSERVER-EMAIL", (None,))[0]
+            if oldemail:
+                oldemail = "mailto:%s" % (oldemail,)
+            if oldemail is None or oldemail not in principal.record.calendarUserAddresses:
+                if cuaddr.startswith("mailto:") and cuaddr in principal.record.calendarUserAddresses:
+                    email = cuaddr[7:]
+                else:
+                    for addr in principal.record.calendarUserAddresses:
+                        if addr.startswith("mailto:"):
+                            email = addr[7:]
+                            break
+                    else:
+                        email = None
+                        
+                if email:
+                    prop.params()["X-CALENDARSERVER-EMAIL"] = [email,]
+                else:
+                    try:
+                        del prop.params()["X-CALENDARSERVER-EMAIL"]
+                    except KeyError:
+                        pass
+
+        for component in ical.subcomponents():
+            if component.name() != "VTIMEZONE":
+                for prop in itertools.chain(
+                    component.properties("ORGANIZER"),
+                    component.properties("ATTENDEE")
+                ):
+                    normalizeCalendarUserAddress(prop)
+
     def principalForCalendarUserAddress(self, address):
         for principalCollection in self.principalCollections():
             principal = principalCollection.principalForCalendarUserAddress(address)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20081217/75326068/attachment-0001.html>


More information about the calendarserver-changes mailing list