[CalendarServer-changes] [5467] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Sat Apr 10 13:08:47 PDT 2010


Revision: 5467
          http://trac.macosforge.org/projects/calendarserver/changeset/5467
Author:   cdaboo at apple.com
Date:     2010-04-10 13:08:46 -0700 (Sat, 10 Apr 2010)
Log Message:
-----------
Add-member support. Required making liveProperties a function.

Modified Paths:
--------------
    CalendarServer/trunk/twext/web2/dav/element/extensions.py
    CalendarServer/trunk/twext/web2/dav/resource.py
    CalendarServer/trunk/twext/web2/dav/test/test_prop.py
    CalendarServer/trunk/twistedcaldav/directory/addressbook.py
    CalendarServer/trunk/twistedcaldav/directory/opendirectorybacker.py
    CalendarServer/trunk/twistedcaldav/directory/principal.py
    CalendarServer/trunk/twistedcaldav/extensions.py
    CalendarServer/trunk/twistedcaldav/method/__init__.py
    CalendarServer/trunk/twistedcaldav/query/test/test_calendarquery.py
    CalendarServer/trunk/twistedcaldav/resource.py
    CalendarServer/trunk/twistedcaldav/schedule.py
    CalendarServer/trunk/twistedcaldav/sharing.py
    CalendarServer/trunk/twistedcaldav/static.py
    CalendarServer/trunk/twistedcaldav/stdconfig.py
    CalendarServer/trunk/txcaldav/resource.py

Added Paths:
-----------
    CalendarServer/trunk/twistedcaldav/method/post.py

Modified: CalendarServer/trunk/twext/web2/dav/element/extensions.py
===================================================================
--- CalendarServer/trunk/twext/web2/dav/element/extensions.py	2010-04-10 20:07:06 UTC (rev 5466)
+++ CalendarServer/trunk/twext/web2/dav/element/extensions.py	2010-04-10 20:08:46 UTC (rev 5467)
@@ -31,6 +31,7 @@
 __all__ = [
     "CurrentUserPrincipal",
     "ErrorDescription",
+    "AddMember",
     "SyncCollection",
     "SyncToken",
 ]
@@ -58,6 +59,17 @@
     name = "error-description"
     protected = True
 
+class AddMember (WebDAVElement):
+    """
+    A property on a collection to allow for "anonymous" creation of resources.
+    (draft-reschke-webdav-post)
+    """
+    name = "add-member"
+    hidden = True
+    protected = True
+
+    allowed_children = { (dav_namespace, "href"): (0, 1) }
+
 class SyncCollection (WebDAVElement):
     """
     DAV report used to retrieve specific calendar component items via their

Modified: CalendarServer/trunk/twext/web2/dav/resource.py
===================================================================
--- CalendarServer/trunk/twext/web2/dav/resource.py	2010-04-10 20:07:06 UTC (rev 5466)
+++ CalendarServer/trunk/twext/web2/dav/resource.py	2010-04-10 20:08:46 UTC (rev 5467)
@@ -129,31 +129,33 @@
     # meaningful if you are using ACL semantics (ie. Unix-like) which
     # use them.  This (generic) class does not.
 
-    liveProperties = (
-        (dav_namespace, "resourcetype"              ),
-        (dav_namespace, "getetag"                   ),
-        (dav_namespace, "getcontenttype"            ),
-        (dav_namespace, "getcontentlength"          ),
-        (dav_namespace, "getlastmodified"           ),
-        (dav_namespace, "creationdate"              ),
-        (dav_namespace, "displayname"               ),
-        (dav_namespace, "supportedlock"             ),
-        (dav_namespace, "supported-report-set"      ), # RFC 3253, section 3.1.5
-       #(dav_namespace, "owner"                     ), # RFC 3744, section 5.1
-       #(dav_namespace, "group"                     ), # RFC 3744, section 5.2
-        (dav_namespace, "supported-privilege-set"   ), # RFC 3744, section 5.3
-        (dav_namespace, "current-user-privilege-set"), # RFC 3744, section 5.4
-        (dav_namespace, "current-user-principal"    ), # draft-sanchez-webdav-current-principal
-        (dav_namespace, "acl"                       ), # RFC 3744, section 5.5
-        (dav_namespace, "acl-restrictions"          ), # RFC 3744, section 5.6
-        (dav_namespace, "inherited-acl-set"         ), # RFC 3744, section 5.7
-        (dav_namespace, "principal-collection-set"  ), # RFC 3744, section 5.8
-        (dav_namespace, "quota-available-bytes"     ), # RFC 4331, section 3
-        (dav_namespace, "quota-used-bytes"          ), # RFC 4331, section 4
+    def liveProperties(self):
+    
+        return (
+            (dav_namespace, "resourcetype"              ),
+            (dav_namespace, "getetag"                   ),
+            (dav_namespace, "getcontenttype"            ),
+            (dav_namespace, "getcontentlength"          ),
+            (dav_namespace, "getlastmodified"           ),
+            (dav_namespace, "creationdate"              ),
+            (dav_namespace, "displayname"               ),
+            (dav_namespace, "supportedlock"             ),
+            (dav_namespace, "supported-report-set"      ), # RFC 3253, section 3.1.5
+           #(dav_namespace, "owner"                     ), # RFC 3744, section 5.1
+           #(dav_namespace, "group"                     ), # RFC 3744, section 5.2
+            (dav_namespace, "supported-privilege-set"   ), # RFC 3744, section 5.3
+            (dav_namespace, "current-user-privilege-set"), # RFC 3744, section 5.4
+            (dav_namespace, "current-user-principal"    ), # draft-sanchez-webdav-current-principal
+            (dav_namespace, "acl"                       ), # RFC 3744, section 5.5
+            (dav_namespace, "acl-restrictions"          ), # RFC 3744, section 5.6
+            (dav_namespace, "inherited-acl-set"         ), # RFC 3744, section 5.7
+            (dav_namespace, "principal-collection-set"  ), # RFC 3744, section 5.8
+            (dav_namespace, "quota-available-bytes"     ), # RFC 4331, section 3
+            (dav_namespace, "quota-used-bytes"          ), # RFC 4331, section 4
+    
+            (twisted_dav_namespace, "resource-class"),
+        )
 
-        (twisted_dav_namespace, "resource-class"),
-    )
-
     def deadProperties(self):
         """
         Provides internal access to the WebDAV dead property store.
@@ -198,7 +200,7 @@
                 return d
         
         return succeed(
-            qname in self.liveProperties or
+            qname in self.liveProperties() or
             self.deadProperties().contains(qname)
         )
 
@@ -427,7 +429,7 @@
                 qname = property.qname()
                 sname = property.sname()
 
-            if qname in self.liveProperties:
+            if qname in self.liveProperties():
                 raise HTTPError(StatusResponse(
                     responsecode.FORBIDDEN,
                     "Live property %s cannot be deleted." % (sname,)
@@ -449,7 +451,7 @@
         """
         See L{IDAVResource.listProperties}.
         """
-        qnames = set(self.liveProperties)
+        qnames = set(self.liveProperties())
 
         # Add dynamic live properties that exist
         dynamicLiveProperties = (
@@ -2288,12 +2290,14 @@
     # WebDAV
     ##
 
-    liveProperties = DAVResource.liveProperties + (
-        (dav_namespace, "alternate-URI-set"),
-        (dav_namespace, "principal-URL"    ),
-        (dav_namespace, "group-member-set" ),
-        (dav_namespace, "group-membership" ),
-    )
+    def liveProperties(self):
+        
+        return super(DAVPrincipalResource, self).liveProperties() + (
+            (dav_namespace, "alternate-URI-set"),
+            (dav_namespace, "principal-URL"    ),
+            (dav_namespace, "group-member-set" ),
+            (dav_namespace, "group-membership" ),
+        )
 
     def davComplianceClasses(self):
         return ("1", "access-control",)

Modified: CalendarServer/trunk/twext/web2/dav/test/test_prop.py
===================================================================
--- CalendarServer/trunk/twext/web2/dav/test/test_prop.py	2010-04-10 20:07:06 UTC (rev 5466)
+++ CalendarServer/trunk/twext/web2/dav/test/test_prop.py	2010-04-10 20:08:46 UTC (rev 5467)
@@ -47,7 +47,7 @@
     """
 
     def liveProperties(self):
-        return [lookupElement(qname)() for qname in self.resource_class.liveProperties if (qname[0] == dav_namespace) and qname not in dynamicLiveProperties]
+        return [lookupElement(qname)() for qname in self.site.resource.liveProperties() if (qname[0] == dav_namespace) and qname not in dynamicLiveProperties]
 
     def test_PROPFIND_basic(self):
         """

Modified: CalendarServer/trunk/twistedcaldav/directory/addressbook.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/addressbook.py	2010-04-10 20:07:06 UTC (rev 5466)
+++ CalendarServer/trunk/twistedcaldav/directory/addressbook.py	2010-04-10 20:08:46 UTC (rev 5467)
@@ -298,6 +298,8 @@
         ##
         #return joinURL(self.parent.parent.getChild(self.record.recordType).url(), self.record.shortName)
 
+    def canonicalURL(self, request):
+        return succeed(self.url())
     ##
     # DAV
     ##

Modified: CalendarServer/trunk/twistedcaldav/directory/opendirectorybacker.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/opendirectorybacker.py	2010-04-10 20:07:06 UTC (rev 5466)
+++ CalendarServer/trunk/twistedcaldav/directory/opendirectorybacker.py	2010-04-10 20:08:46 UTC (rev 5467)
@@ -2025,7 +2025,7 @@
 
     def listProperties(self, request):
         #print("VCardResource.listProperties()")
-        qnames = set(self.liveProperties)
+        qnames = set(self.liveProperties())
 
         # Add dynamic live properties that exist
         dynamicLiveProperties = (

Modified: CalendarServer/trunk/twistedcaldav/directory/principal.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/directory/principal.py	2010-04-10 20:07:06 UTC (rev 5466)
+++ CalendarServer/trunk/twistedcaldav/directory/principal.py	2010-04-10 20:08:46 UTC (rev 5467)
@@ -514,11 +514,13 @@
     Directory principal resource.
     """
 
-    liveProperties = tuple(DAVPrincipalResource.liveProperties) + (
-        (calendarserver_namespace, "first-name"       ),
-        (calendarserver_namespace, "last-name"        ),
-        (calendarserver_namespace, "email-address-set"),
-    )
+    def liveProperties(self):
+        
+        return super(DirectoryPrincipalResource, self).liveProperties() + (
+            (calendarserver_namespace, "first-name"       ),
+            (calendarserver_namespace, "last-name"        ),
+            (calendarserver_namespace, "email-address-set"),
+        )
 
     def __init__(self, parent, record):
         """
@@ -821,16 +823,9 @@
     Directory calendar principal resource.
     """
 
-    @property
     def liveProperties(self):
-        # This needs to be a dynamic property because CalendarPrincipalResource
-        # liveProperties changes on the fly (drop box enabling)
-        return (
-            tuple(DirectoryPrincipalResource.liveProperties) +
-            tuple(CalendarPrincipalResource.liveProperties)
-        )
+        return DirectoryPrincipalResource.liveProperties(self) + CalendarPrincipalResource.liveProperties(self)
 
-
     @inlineCallbacks
     def readProperty(self, property, request):
         # Ouch, multiple inheritance.

Modified: CalendarServer/trunk/twistedcaldav/extensions.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/extensions.py	2010-04-10 20:07:06 UTC (rev 5466)
+++ CalendarServer/trunk/twistedcaldav/extensions.py	2010-04-10 20:08:46 UTC (rev 5467)
@@ -453,11 +453,12 @@
     Extended L{twext.web2.dav.static.DAVFile} implementation.
     """
 
-    liveProperties = tuple(SuperDAVPrincipalResource.liveProperties) + (
-        (calendarserver_namespace, "expanded-group-member-set"),
-        (calendarserver_namespace, "expanded-group-membership"),
-        (calendarserver_namespace, "record-type"),
-    )
+    def liveProperties(self):
+        return super(DAVPrincipalResource, self).liveProperties() + (
+            (calendarserver_namespace, "expanded-group-member-set"),
+            (calendarserver_namespace, "expanded-group-membership"),
+            (calendarserver_namespace, "record-type"),
+        )
 
     http_REPORT = http_REPORT
 

Modified: CalendarServer/trunk/twistedcaldav/method/__init__.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/method/__init__.py	2010-04-10 20:07:06 UTC (rev 5466)
+++ CalendarServer/trunk/twistedcaldav/method/__init__.py	2010-04-10 20:08:46 UTC (rev 5467)
@@ -27,6 +27,7 @@
     "get",
     "mkcalendar",
     "mkcol",
+    "post",
     "propfind",
     "put",
     "report",

Added: CalendarServer/trunk/twistedcaldav/method/post.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/method/post.py	                        (rev 0)
+++ CalendarServer/trunk/twistedcaldav/method/post.py	2010-04-10 20:08:46 UTC (rev 5467)
@@ -0,0 +1,169 @@
+##
+# Copyright (c) 2005-2007 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from hashlib import md5
+
+from twext.web2.dav.http import ErrorResponse
+from twext.web2.dav.util import allDataFromStream, joinURL
+from twext.web2.filter.location import addLocation
+from twext.web2.http import HTTPError, StatusResponse
+
+from twistedcaldav.caldavxml import caldav_namespace
+from twistedcaldav.carddavxml import carddav_namespace
+from twistedcaldav.method.put_addressbook_common import StoreAddressObjectResource
+from twistedcaldav.method.put_common import StoreCalendarObjectResource
+
+import time
+
+"""
+CalDAV POST method.
+"""
+
+__all__ = ["http_POST"]
+
+from twisted.internet.defer import inlineCallbacks, returnValue
+from twisted.web2 import responsecode
+
+from twistedcaldav.config import config
+
+ at inlineCallbacks
+def http_POST(self, request):
+
+    # POST can support many different APIs
+    
+    # First look at query params
+    if request.params:
+        if request.params == "add-member":
+            if config.EnableAddMember:
+                result = (yield POST_handler_add_member(self, request))
+                returnValue(result)
+
+    else:
+        # Content-type handlers
+        contentType = request.headers.getHeader("content-type")
+        if contentType:
+            if hasattr(self, "POST_handler_content_type"):
+                result = (yield self.POST_handler_content_type(request, (contentType.mediaType, contentType.mediaSubtype)))
+                returnValue(result)
+
+    returnValue(responsecode.FORBIDDEN)
+
+ at inlineCallbacks
+def POST_handler_add_member(self, request):
+
+    # Handle ;add-member
+    if self.isCalendarCollection():
+        
+        parentURL = request.path
+        parent = self
+
+        # Content-type check
+        content_type = request.headers.getHeader("content-type")
+        if content_type is not None and (content_type.mediaType, content_type.mediaSubtype) != ("text", "calendar"):
+            self.log_error("MIME type %s not allowed in calendar collection" % (content_type,))
+            raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "supported-calendar-data")))
+            
+        # Read the calendar component from the stream
+        try:
+            calendardata = (yield allDataFromStream(request.stream))
+            if not hasattr(request, "extendedLogItems"):
+                request.extendedLogItems = {}
+            request.extendedLogItems["cl"] = str(len(calendardata)) if calendardata else "0"
+
+            # We must have some data at this point
+            if calendardata is None:
+                # Use correct DAV:error response
+                raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, "valid-calendar-data"), description="No calendar data"))
+
+            # Create a new name if one was not provided
+            name =  md5(str(calendardata) + str(time.time()) + self.fp.path).hexdigest() + ".ics"
+        
+            # Get a resource for the new item
+            newchildURL = joinURL(parentURL, name)
+            newchild = (yield request.locateResource(newchildURL))
+
+            storer = StoreCalendarObjectResource(
+                request = request,
+                destination = newchild,
+                destination_uri = newchildURL,
+                destinationcal = True,
+                destinationparent = parent,
+                calendar = calendardata,
+            )
+            result = (yield storer.run())
+
+            # May need to add a location header
+            addLocation(request, request.unparseURL(path=newchildURL, params=""))
+
+            returnValue(result)
+
+        except ValueError, e:
+            self.log_error("Error while handling (calendar) POST: %s" % (e,))
+            raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, str(e)))
+
+    elif self.isAddressBookCollection():
+        
+        parentURL = request.path
+        parent = self
+
+        # Content-type check
+        content_type = request.headers.getHeader("content-type")
+        if content_type is not None and (content_type.mediaType, content_type.mediaSubtype) != ("text", "vcard"):
+            self.log_error("MIME type %s not allowed in address book collection" % (content_type,))
+            raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (carddav_namespace, "supported-address-data")))
+            
+        # Read the calendar component from the stream
+        try:
+            vcarddata = (yield allDataFromStream(request.stream))
+            if not hasattr(request, "extendedLogItems"):
+                request.extendedLogItems = {}
+            request.extendedLogItems["cl"] = str(len(vcarddata)) if vcarddata else "0"
+
+            # We must have some data at this point
+            if vcarddata is None:
+                # Use correct DAV:error response
+                raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (carddav_namespace, "valid-address-data"), description="No address data"))
+
+            # Create a new name if one was not provided
+            name =  md5(str(vcarddata) + str(time.time()) + self.fp.path).hexdigest() + ".vcf"
+        
+            # Get a resource for the new item
+            newchildURL = joinURL(parentURL, name)
+            newchild = (yield request.locateResource(newchildURL))
+
+            storer = StoreAddressObjectResource(
+                request = request,
+                sourceadbk = False,
+                destination = newchild,
+                destination_uri = newchildURL,
+                destinationadbk = True,
+                destinationparent = parent,
+                vcard = vcarddata,
+            )
+            result = (yield storer.run())
+
+            # May need to add a location header
+            addLocation(request, request.unparseURL(path=newchildURL, params=""))
+
+            returnValue(result)
+
+        except ValueError, e:
+            self.log_error("Error while handling (calendar) POST: %s" % (e,))
+            raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, str(e)))
+
+    # Default behavior
+    returnValue(responsecode.FORBIDDEN)
+

Modified: CalendarServer/trunk/twistedcaldav/query/test/test_calendarquery.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/query/test/test_calendarquery.py	2010-04-10 20:07:06 UTC (rev 5466)
+++ CalendarServer/trunk/twistedcaldav/query/test/test_calendarquery.py	2010-04-10 20:08:46 UTC (rev 5467)
@@ -16,7 +16,6 @@
 
 from twistedcaldav import caldavxml
 from twistedcaldav.query import queryfilter
-from twistedcaldav.query.calendarquery import sqlcalendarquery
 import datetime
 import twistedcaldav.test.util
 
@@ -94,6 +93,4 @@
     
         Eastern  = USTimeZone(-5, "Eastern",  "EST", "EDT")
         filter.child.settzinfo(Eastern)
-        
-        print sqlcalendarquery(filter)
         
\ No newline at end of file

Modified: CalendarServer/trunk/twistedcaldav/resource.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/resource.py	2010-04-10 20:07:06 UTC (rev 5466)
+++ CalendarServer/trunk/twistedcaldav/resource.py	2010-04-10 20:08:46 UTC (rev 5467)
@@ -159,24 +159,28 @@
     # WebDAV
     ##
 
-    liveProperties = DAVResource.liveProperties + (
-        davxml.Owner.qname(),               # Private Events needs this but it is also OK to return empty
-        caldavxml.SupportedCalendarComponentSet.qname(),
-        caldavxml.SupportedCalendarData.qname(),
-    )
+    def liveProperties(self):
+        baseProperties = (
+            davxml.Owner.qname(),               # Private Events needs this but it is also OK to return empty
+            caldavxml.SupportedCalendarComponentSet.qname(),
+            caldavxml.SupportedCalendarData.qname(),
+        )
+        
+        if config.EnableAddMember and (self.isCalendarCollection() or self.isAddressBookCollection()):
+            baseProperties += (davxml.AddMember.qname(),)
+            
+        if config.Sharing.Enabled:
+            if config.Sharing.Calendars.Enabled and self.isCalendarCollection():
+                baseProperties += (customxml.Invite.qname(),)
+            elif config.Sharing.AddressBooks.Enabled and self.isAddressBookCollection():
+                baseProperties += (customxml.Invite.qname(),)
+                
+        return super(CalDAVResource, self).liveProperties() + baseProperties
 
     supportedCalendarComponentSet = caldavxml.SupportedCalendarComponentSet(
         *[caldavxml.CalendarComponent(name=item) for item in allowedComponents]
     )
 
-    @classmethod
-    def enableSharing(clz, enable):
-        qname = (calendarserver_namespace, "invite" )
-        if enable and qname not in clz.liveProperties:
-            clz.liveProperties += (qname,)
-        elif not enable and qname in clz.liveProperties:
-            clz.liveProperties = tuple([p for p in clz.liveProperties if p != qname])
-
     def isShadowableProperty(self, qname):
         """
         Shadowable properties are ones on shared resources where a "default" exists until
@@ -191,7 +195,7 @@
         """
         A global property is one that is the same for all users.
         """
-        if qname in self.liveProperties:
+        if qname in self.liveProperties():
             if qname in (
                 davxml.DisplayName.qname(),
                 customxml.Invite.qname(),
@@ -283,6 +287,12 @@
             owner = (yield self.owner(request))
             returnValue(davxml.Owner(owner))
 
+        elif qname == davxml.AddMember.qname() and config.EnableAddMember and (
+            self.isCalendarCollection() or self.isAddressBookCollection()
+        ):
+            url = (yield self.canonicalURL(request))
+            returnValue(davxml.AddMember(davxml.HRef.fromString(url + "/;add-member")))
+
         elif qname == caldavxml.SupportedCalendarComponentSet.qname():
             # CalDAV-access-09, section 5.2.3
             if self.hasDeadProperty(qname):
@@ -1058,40 +1068,32 @@
     """
     implements(ICalendarPrincipalResource)
 
-    liveProperties = tuple(DAVPrincipalResource.liveProperties) + (
-        (caldav_namespace, "calendar-home-set"        ),
-        (caldav_namespace, "calendar-user-address-set"),
-        (caldav_namespace, "schedule-inbox-URL"       ),
-        (caldav_namespace, "schedule-outbox-URL"      ),
-        (caldav_namespace, "calendar-user-type"       ),
-        (calendarserver_namespace, "calendar-proxy-read-for"  ),
-        (calendarserver_namespace, "calendar-proxy-write-for" ),
-        (calendarserver_namespace, "auto-schedule" ),
-    )
+    def liveProperties(self):
+        
+        baseProperties = ()
+        
+        if config.EnableCalDAV:
+            baseProperties += (
+                (caldav_namespace, "calendar-home-set"        ),
+                (caldav_namespace, "calendar-user-address-set"),
+                (caldav_namespace, "schedule-inbox-URL"       ),
+                (caldav_namespace, "schedule-outbox-URL"      ),
+                (caldav_namespace, "calendar-user-type"       ),
+                (calendarserver_namespace, "calendar-proxy-read-for"  ),
+                (calendarserver_namespace, "calendar-proxy-write-for" ),
+                (calendarserver_namespace, "auto-schedule" ),
+            )
+        
+        if config.EnableCardDAV:
+            baseProperties += (carddavxml.AddressBookHomeSet.qname(),)
 
-    @classmethod
-    def enableDropBox(clz, enable):
-        qname = (calendarserver_namespace, "dropbox-home-URL" )
-        if enable and qname not in clz.liveProperties:
-            clz.liveProperties += (qname,)
-        elif not enable and qname in clz.liveProperties:
-            clz.liveProperties = tuple([p for p in clz.liveProperties if p != qname])
+        if config.EnableDropBox:
+            baseProperties += (customxml.DropBoxHomeURL.qname(),)
 
-    @classmethod
-    def enableSharing(clz, enable):
-        qname = (calendarserver_namespace, "notification-URL" )
-        if enable and qname not in clz.liveProperties:
-            clz.liveProperties += (qname,)
-        elif not enable and qname in clz.liveProperties:
-            clz.liveProperties = tuple([p for p in clz.liveProperties if p != qname])
+        if config.Sharing.Enabled:
+            baseProperties += (customxml.NotificationURL.qname(),)
 
-    @classmethod
-    def enableAddressBooks(clz, enable):
-        qname = (carddav_namespace, "addressbook-home-set" )
-        if enable and qname not in clz.liveProperties:
-            clz.liveProperties += (qname,)
-        elif not enable and qname in clz.liveProperties:
-            clz.liveProperties = tuple([p for p in clz.liveProperties if p != qname])
+        return super(CalendarPrincipalResource, self).liveProperties() + baseProperties
 
     def isCollection(self):
         return True

Modified: CalendarServer/trunk/twistedcaldav/schedule.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/schedule.py	2010-04-10 20:07:06 UTC (rev 5466)
+++ CalendarServer/trunk/twistedcaldav/schedule.py	2010-04-10 20:08:46 UTC (rev 5467)
@@ -82,10 +82,12 @@
     Extends L{DAVResource} to provide CalDAV functionality.
     """
 
-    liveProperties = CalendarSchedulingCollectionResource.liveProperties + (
-        (caldav_namespace, "calendar-free-busy-set"),
-        (caldav_namespace, "schedule-default-calendar-URL"),
-    )
+    def liveProperties(self):
+        
+        return super(ScheduleInboxResource, self).liveProperties() + (
+            (caldav_namespace, "calendar-free-busy-set"),
+            (caldav_namespace, "schedule-default-calendar-URL"),
+        )
 
     def resourceType(self, request):
         return succeed(davxml.ResourceType.scheduleInbox)

Modified: CalendarServer/trunk/twistedcaldav/sharing.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/sharing.py	2010-04-10 20:07:06 UTC (rev 5466)
+++ CalendarServer/trunk/twistedcaldav/sharing.py	2010-04-10 20:08:46 UTC (rev 5467)
@@ -610,18 +610,16 @@
         d.addCallback(self.xmlPOSTNoAuth, request)
         return d
     
-    def http_POST(self, request):
+    def POST_handler_content_type(self, request, contentType):
         if self.isCollection():
-            contentType = request.headers.getHeader("content-type")
             if contentType:
-                contentType = (contentType.mediaType, contentType.mediaSubtype)
                 if contentType in self._postHandlers:
                     return self._postHandlers[contentType](self, request)
                 else:
                     self.log_info("Get a POST of an unsupported content type on a collection type: %s" % (contentType,))
             else:
                 self.log_info("Get a POST with no content type on a collection")
-        return responsecode.FORBIDDEN
+        return succeed(responsecode.FORBIDDEN)
 
     _postHandlers = {
         ("application", "xml") : xmlPOSTAuth,

Modified: CalendarServer/trunk/twistedcaldav/static.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/static.py	2010-04-10 20:07:06 UTC (rev 5466)
+++ CalendarServer/trunk/twistedcaldav/static.py	2010-04-10 20:08:46 UTC (rev 5467)
@@ -929,11 +929,13 @@
     """
     Calendar home collection resource.
     """
-    liveProperties = CalDAVFile.liveProperties + (
-        (customxml.calendarserver_namespace, "xmpp-uri"),
-        (customxml.calendarserver_namespace, "xmpp-heartbeat-uri"),
-        (customxml.calendarserver_namespace, "xmpp-server"),
-    )
+    def liveProperties(self):
+        
+        return super(CalendarHomeFile, self).liveProperties() + (
+            (customxml.calendarserver_namespace, "xmpp-uri"),
+            (customxml.calendarserver_namespace, "xmpp-heartbeat-uri"),
+            (customxml.calendarserver_namespace, "xmpp-server"),
+        )
 
     def __init__(self, path, parent, record):
         """
@@ -1493,9 +1495,11 @@
     """
     Address book home collection resource.
     """
-    liveProperties = CalDAVFile.liveProperties + (
-        (customxml.calendarserver_namespace, "xmpp-uri"),
-    )
+    
+    def liveProperties(self):
+        return super(AddressBookHomeFile, self).liveProperties() + (
+            (customxml.calendarserver_namespace, "xmpp-uri"),
+        )
 
     def __init__(self, path, parent, record):
         """

Modified: CalendarServer/trunk/twistedcaldav/stdconfig.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/stdconfig.py	2010-04-10 20:07:06 UTC (rev 5466)
+++ CalendarServer/trunk/twistedcaldav/stdconfig.py	2010-04-10 20:08:46 UTC (rev 5467)
@@ -331,6 +331,7 @@
     #
     # Standard (or draft) WebDAV extensions
     #
+    "EnableAddMember"         : True,  # POST ;add-member extension
     "EnableSyncReport"        : True,  # REPORT collection-sync
     "EnableWellKnown"         : True,  # /.well-known resource
 
@@ -676,15 +677,6 @@
                 del configDict.DirectoryService.params[param]
 
 
-def _updateAddressBook(configDict):
-    #
-    # FIXME: Use the config object instead of doing this here
-    #
-    from twistedcaldav.resource import CalendarPrincipalResource
-    CalendarPrincipalResource.enableAddressBooks(configDict.EnableCardDAV)
-
-
-
 def _preUpdateDirectoryAddressBookBackingDirectoryService(configDict, items):
     #
     # Special handling for directory address book configs
@@ -809,13 +801,6 @@
     except re.error, e:
         raise ConfigurationError("Invalid regular expression in RejectClients: %s" % (e,))
 
-def _updateDropBox(configDict):
-    #
-    # FIXME: Use the config object instead of doing this here
-    #
-    from twistedcaldav.resource import CalendarPrincipalResource
-    CalendarPrincipalResource.enableDropBox(configDict.EnableDropBox)
-
 def _updateLogLevels(configDict):
     clearLogLevels()
 
@@ -923,14 +908,6 @@
                     log.info("iMIP %s password not found in keychain" %
                         (direction,))
 
-def _updateSharing(configDict):
-    #
-    # FIXME: Use the config object instead of doing this here
-    #
-    from twistedcaldav.resource import CalDAVResource, CalendarPrincipalResource
-    CalDAVResource.enableSharing(configDict.Sharing.Enabled)
-    CalendarPrincipalResource.enableSharing(configDict.Sharing.Enabled)
-
 def _updatePartitions(configDict):
     if configDict.Partitioning.Enabled:
         partitions.setSelfPartition(configDict.Partitioning.ServerPartitionID)
@@ -969,17 +946,14 @@
     )
 POST_UPDATE_HOOKS = (
     _updateHostName,
-    _updateAddressBook,
     _postUpdateDirectoryService,
     _postUpdateAugmentService,
     _postUpdateProxyDBService,
     _updateACLs,
     _updateRejectClients,
-    _updateDropBox,
     _updateLogLevels,
     _updateNotifications,
     _updateScheduling,
-    _updateSharing,
     _updatePartitions,
     _updateCompliance,
     )

Modified: CalendarServer/trunk/txcaldav/resource.py
===================================================================
--- CalendarServer/trunk/txcaldav/resource.py	2010-04-10 20:07:06 UTC (rev 5466)
+++ CalendarServer/trunk/txcaldav/resource.py	2010-04-10 20:08:46 UTC (rev 5467)
@@ -118,11 +118,13 @@
     # WebDAV
     #
 
-    liveProperties = DAVResource.liveProperties + (
-        (dav_namespace,    "owner"),               # Private Events needs this but it is also OK to return empty
-        (caldav_namespace, "supported-calendar-component-set"),
-        (caldav_namespace, "supported-calendar-data"         ),
-    )
+    def liveProperties(self):
+        
+        return super(CalendarCollectionResource, self).liveProperties() + (
+            (dav_namespace,    "owner"),               # Private Events needs this but it is also OK to return empty
+            (caldav_namespace, "supported-calendar-component-set"),
+            (caldav_namespace, "supported-calendar-data"         ),
+        )
 
 
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20100410/57540191/attachment-0001.html>


More information about the calendarserver-changes mailing list