<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[5467] CalendarServer/trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.macosforge.org/projects/calendarserver/changeset/5467">5467</a></dd>
<dt>Author</dt> <dd>cdaboo@apple.com</dd>
<dt>Date</dt> <dd>2010-04-10 13:08:46 -0700 (Sat, 10 Apr 2010)</dd>
</dl>

<h3>Log Message</h3>
<pre>Add-member support. Required making liveProperties a function.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#CalendarServertrunktwextweb2davelementextensionspy">CalendarServer/trunk/twext/web2/dav/element/extensions.py</a></li>
<li><a href="#CalendarServertrunktwextweb2davresourcepy">CalendarServer/trunk/twext/web2/dav/resource.py</a></li>
<li><a href="#CalendarServertrunktwextweb2davtesttest_proppy">CalendarServer/trunk/twext/web2/dav/test/test_prop.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavdirectoryaddressbookpy">CalendarServer/trunk/twistedcaldav/directory/addressbook.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavdirectoryopendirectorybackerpy">CalendarServer/trunk/twistedcaldav/directory/opendirectorybacker.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavdirectoryprincipalpy">CalendarServer/trunk/twistedcaldav/directory/principal.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavextensionspy">CalendarServer/trunk/twistedcaldav/extensions.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavmethod__init__py">CalendarServer/trunk/twistedcaldav/method/__init__.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavquerytesttest_calendarquerypy">CalendarServer/trunk/twistedcaldav/query/test/test_calendarquery.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavresourcepy">CalendarServer/trunk/twistedcaldav/resource.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavschedulepy">CalendarServer/trunk/twistedcaldav/schedule.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavsharingpy">CalendarServer/trunk/twistedcaldav/sharing.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavstaticpy">CalendarServer/trunk/twistedcaldav/static.py</a></li>
<li><a href="#CalendarServertrunktwistedcaldavstdconfigpy">CalendarServer/trunk/twistedcaldav/stdconfig.py</a></li>
<li><a href="#CalendarServertrunktxcaldavresourcepy">CalendarServer/trunk/txcaldav/resource.py</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#CalendarServertrunktwistedcaldavmethodpostpy">CalendarServer/trunk/twistedcaldav/method/post.py</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="CalendarServertrunktwextweb2davelementextensionspy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twext/web2/dav/element/extensions.py (5466 => 5467)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> __all__ = [
</span><span class="cx">     &quot;CurrentUserPrincipal&quot;,
</span><span class="cx">     &quot;ErrorDescription&quot;,
</span><ins>+    &quot;AddMember&quot;,
</ins><span class="cx">     &quot;SyncCollection&quot;,
</span><span class="cx">     &quot;SyncToken&quot;,
</span><span class="cx"> ]
</span><span class="lines">@@ -58,6 +59,17 @@
</span><span class="cx">     name = &quot;error-description&quot;
</span><span class="cx">     protected = True
</span><span class="cx"> 
</span><ins>+class AddMember (WebDAVElement):
+    &quot;&quot;&quot;
+    A property on a collection to allow for &quot;anonymous&quot; creation of resources.
+    (draft-reschke-webdav-post)
+    &quot;&quot;&quot;
+    name = &quot;add-member&quot;
+    hidden = True
+    protected = True
+
+    allowed_children = { (dav_namespace, &quot;href&quot;): (0, 1) }
+
</ins><span class="cx"> class SyncCollection (WebDAVElement):
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     DAV report used to retrieve specific calendar component items via their
</span></span></pre></div>
<a id="CalendarServertrunktwextweb2davresourcepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twext/web2/dav/resource.py (5466 => 5467)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -129,31 +129,33 @@
</span><span class="cx">     # meaningful if you are using ACL semantics (ie. Unix-like) which
</span><span class="cx">     # use them.  This (generic) class does not.
</span><span class="cx"> 
</span><del>-    liveProperties = (
-        (dav_namespace, &quot;resourcetype&quot;              ),
-        (dav_namespace, &quot;getetag&quot;                   ),
-        (dav_namespace, &quot;getcontenttype&quot;            ),
-        (dav_namespace, &quot;getcontentlength&quot;          ),
-        (dav_namespace, &quot;getlastmodified&quot;           ),
-        (dav_namespace, &quot;creationdate&quot;              ),
-        (dav_namespace, &quot;displayname&quot;               ),
-        (dav_namespace, &quot;supportedlock&quot;             ),
-        (dav_namespace, &quot;supported-report-set&quot;      ), # RFC 3253, section 3.1.5
-       #(dav_namespace, &quot;owner&quot;                     ), # RFC 3744, section 5.1
-       #(dav_namespace, &quot;group&quot;                     ), # RFC 3744, section 5.2
-        (dav_namespace, &quot;supported-privilege-set&quot;   ), # RFC 3744, section 5.3
-        (dav_namespace, &quot;current-user-privilege-set&quot;), # RFC 3744, section 5.4
-        (dav_namespace, &quot;current-user-principal&quot;    ), # draft-sanchez-webdav-current-principal
-        (dav_namespace, &quot;acl&quot;                       ), # RFC 3744, section 5.5
-        (dav_namespace, &quot;acl-restrictions&quot;          ), # RFC 3744, section 5.6
-        (dav_namespace, &quot;inherited-acl-set&quot;         ), # RFC 3744, section 5.7
-        (dav_namespace, &quot;principal-collection-set&quot;  ), # RFC 3744, section 5.8
-        (dav_namespace, &quot;quota-available-bytes&quot;     ), # RFC 4331, section 3
-        (dav_namespace, &quot;quota-used-bytes&quot;          ), # RFC 4331, section 4
</del><ins>+    def liveProperties(self):
+    
+        return (
+            (dav_namespace, &quot;resourcetype&quot;              ),
+            (dav_namespace, &quot;getetag&quot;                   ),
+            (dav_namespace, &quot;getcontenttype&quot;            ),
+            (dav_namespace, &quot;getcontentlength&quot;          ),
+            (dav_namespace, &quot;getlastmodified&quot;           ),
+            (dav_namespace, &quot;creationdate&quot;              ),
+            (dav_namespace, &quot;displayname&quot;               ),
+            (dav_namespace, &quot;supportedlock&quot;             ),
+            (dav_namespace, &quot;supported-report-set&quot;      ), # RFC 3253, section 3.1.5
+           #(dav_namespace, &quot;owner&quot;                     ), # RFC 3744, section 5.1
+           #(dav_namespace, &quot;group&quot;                     ), # RFC 3744, section 5.2
+            (dav_namespace, &quot;supported-privilege-set&quot;   ), # RFC 3744, section 5.3
+            (dav_namespace, &quot;current-user-privilege-set&quot;), # RFC 3744, section 5.4
+            (dav_namespace, &quot;current-user-principal&quot;    ), # draft-sanchez-webdav-current-principal
+            (dav_namespace, &quot;acl&quot;                       ), # RFC 3744, section 5.5
+            (dav_namespace, &quot;acl-restrictions&quot;          ), # RFC 3744, section 5.6
+            (dav_namespace, &quot;inherited-acl-set&quot;         ), # RFC 3744, section 5.7
+            (dav_namespace, &quot;principal-collection-set&quot;  ), # RFC 3744, section 5.8
+            (dav_namespace, &quot;quota-available-bytes&quot;     ), # RFC 4331, section 3
+            (dav_namespace, &quot;quota-used-bytes&quot;          ), # RFC 4331, section 4
+    
+            (twisted_dav_namespace, &quot;resource-class&quot;),
+        )
</ins><span class="cx"> 
</span><del>-        (twisted_dav_namespace, &quot;resource-class&quot;),
-    )
-
</del><span class="cx">     def deadProperties(self):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Provides internal access to the WebDAV dead property store.
</span><span class="lines">@@ -198,7 +200,7 @@
</span><span class="cx">                 return d
</span><span class="cx">         
</span><span class="cx">         return succeed(
</span><del>-            qname in self.liveProperties or
</del><ins>+            qname in self.liveProperties() or
</ins><span class="cx">             self.deadProperties().contains(qname)
</span><span class="cx">         )
</span><span class="cx"> 
</span><span class="lines">@@ -427,7 +429,7 @@
</span><span class="cx">                 qname = property.qname()
</span><span class="cx">                 sname = property.sname()
</span><span class="cx"> 
</span><del>-            if qname in self.liveProperties:
</del><ins>+            if qname in self.liveProperties():
</ins><span class="cx">                 raise HTTPError(StatusResponse(
</span><span class="cx">                     responsecode.FORBIDDEN,
</span><span class="cx">                     &quot;Live property %s cannot be deleted.&quot; % (sname,)
</span><span class="lines">@@ -449,7 +451,7 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         See L{IDAVResource.listProperties}.
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        qnames = set(self.liveProperties)
</del><ins>+        qnames = set(self.liveProperties())
</ins><span class="cx"> 
</span><span class="cx">         # Add dynamic live properties that exist
</span><span class="cx">         dynamicLiveProperties = (
</span><span class="lines">@@ -2288,12 +2290,14 @@
</span><span class="cx">     # WebDAV
</span><span class="cx">     ##
</span><span class="cx"> 
</span><del>-    liveProperties = DAVResource.liveProperties + (
-        (dav_namespace, &quot;alternate-URI-set&quot;),
-        (dav_namespace, &quot;principal-URL&quot;    ),
-        (dav_namespace, &quot;group-member-set&quot; ),
-        (dav_namespace, &quot;group-membership&quot; ),
-    )
</del><ins>+    def liveProperties(self):
+        
+        return super(DAVPrincipalResource, self).liveProperties() + (
+            (dav_namespace, &quot;alternate-URI-set&quot;),
+            (dav_namespace, &quot;principal-URL&quot;    ),
+            (dav_namespace, &quot;group-member-set&quot; ),
+            (dav_namespace, &quot;group-membership&quot; ),
+        )
</ins><span class="cx"> 
</span><span class="cx">     def davComplianceClasses(self):
</span><span class="cx">         return (&quot;1&quot;, &quot;access-control&quot;,)
</span></span></pre></div>
<a id="CalendarServertrunktwextweb2davtesttest_proppy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twext/web2/dav/test/test_prop.py (5466 => 5467)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -47,7 +47,7 @@
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx"> 
</span><span class="cx">     def liveProperties(self):
</span><del>-        return [lookupElement(qname)() for qname in self.resource_class.liveProperties if (qname[0] == dav_namespace) and qname not in dynamicLiveProperties]
</del><ins>+        return [lookupElement(qname)() for qname in self.site.resource.liveProperties() if (qname[0] == dav_namespace) and qname not in dynamicLiveProperties]
</ins><span class="cx"> 
</span><span class="cx">     def test_PROPFIND_basic(self):
</span><span class="cx">         &quot;&quot;&quot;
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavdirectoryaddressbookpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/directory/addressbook.py (5466 => 5467)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -298,6 +298,8 @@
</span><span class="cx">         ##
</span><span class="cx">         #return joinURL(self.parent.parent.getChild(self.record.recordType).url(), self.record.shortName)
</span><span class="cx"> 
</span><ins>+    def canonicalURL(self, request):
+        return succeed(self.url())
</ins><span class="cx">     ##
</span><span class="cx">     # DAV
</span><span class="cx">     ##
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavdirectoryopendirectorybackerpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/directory/opendirectorybacker.py (5466 => 5467)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -2025,7 +2025,7 @@
</span><span class="cx"> 
</span><span class="cx">     def listProperties(self, request):
</span><span class="cx">         #print(&quot;VCardResource.listProperties()&quot;)
</span><del>-        qnames = set(self.liveProperties)
</del><ins>+        qnames = set(self.liveProperties())
</ins><span class="cx"> 
</span><span class="cx">         # Add dynamic live properties that exist
</span><span class="cx">         dynamicLiveProperties = (
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavdirectoryprincipalpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/directory/principal.py (5466 => 5467)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -514,11 +514,13 @@
</span><span class="cx">     Directory principal resource.
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-    liveProperties = tuple(DAVPrincipalResource.liveProperties) + (
-        (calendarserver_namespace, &quot;first-name&quot;       ),
-        (calendarserver_namespace, &quot;last-name&quot;        ),
-        (calendarserver_namespace, &quot;email-address-set&quot;),
-    )
</del><ins>+    def liveProperties(self):
+        
+        return super(DirectoryPrincipalResource, self).liveProperties() + (
+            (calendarserver_namespace, &quot;first-name&quot;       ),
+            (calendarserver_namespace, &quot;last-name&quot;        ),
+            (calendarserver_namespace, &quot;email-address-set&quot;),
+        )
</ins><span class="cx"> 
</span><span class="cx">     def __init__(self, parent, record):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -821,16 +823,9 @@
</span><span class="cx">     Directory calendar principal resource.
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-    @property
</del><span class="cx">     def liveProperties(self):
</span><del>-        # This needs to be a dynamic property because CalendarPrincipalResource
-        # liveProperties changes on the fly (drop box enabling)
-        return (
-            tuple(DirectoryPrincipalResource.liveProperties) +
-            tuple(CalendarPrincipalResource.liveProperties)
-        )
</del><ins>+        return DirectoryPrincipalResource.liveProperties(self) + CalendarPrincipalResource.liveProperties(self)
</ins><span class="cx"> 
</span><del>-
</del><span class="cx">     @inlineCallbacks
</span><span class="cx">     def readProperty(self, property, request):
</span><span class="cx">         # Ouch, multiple inheritance.
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavextensionspy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/extensions.py (5466 => 5467)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -453,11 +453,12 @@
</span><span class="cx">     Extended L{twext.web2.dav.static.DAVFile} implementation.
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-    liveProperties = tuple(SuperDAVPrincipalResource.liveProperties) + (
-        (calendarserver_namespace, &quot;expanded-group-member-set&quot;),
-        (calendarserver_namespace, &quot;expanded-group-membership&quot;),
-        (calendarserver_namespace, &quot;record-type&quot;),
-    )
</del><ins>+    def liveProperties(self):
+        return super(DAVPrincipalResource, self).liveProperties() + (
+            (calendarserver_namespace, &quot;expanded-group-member-set&quot;),
+            (calendarserver_namespace, &quot;expanded-group-membership&quot;),
+            (calendarserver_namespace, &quot;record-type&quot;),
+        )
</ins><span class="cx"> 
</span><span class="cx">     http_REPORT = http_REPORT
</span><span class="cx"> 
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavmethod__init__py"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/method/__init__.py (5466 => 5467)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx">     &quot;get&quot;,
</span><span class="cx">     &quot;mkcalendar&quot;,
</span><span class="cx">     &quot;mkcol&quot;,
</span><ins>+    &quot;post&quot;,
</ins><span class="cx">     &quot;propfind&quot;,
</span><span class="cx">     &quot;put&quot;,
</span><span class="cx">     &quot;report&quot;,
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavmethodpostpy"></a>
<div class="addfile"><h4>Added: CalendarServer/trunk/twistedcaldav/method/post.py (0 => 5467)</h4>
<pre class="diff"><span>
<span class="info">--- CalendarServer/trunk/twistedcaldav/method/post.py                                (rev 0)
+++ CalendarServer/trunk/twistedcaldav/method/post.py        2010-04-10 20:08:46 UTC (rev 5467)
</span><span class="lines">@@ -0,0 +1,169 @@
</span><ins>+##
+# Copyright (c) 2005-2007 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
+# 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 &quot;AS IS&quot; 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
+
+&quot;&quot;&quot;
+CalDAV POST method.
+&quot;&quot;&quot;
+
+__all__ = [&quot;http_POST&quot;]
+
+from twisted.internet.defer import inlineCallbacks, returnValue
+from twisted.web2 import responsecode
+
+from twistedcaldav.config import config
+
+@inlineCallbacks
+def http_POST(self, request):
+
+    # POST can support many different APIs
+    
+    # First look at query params
+    if request.params:
+        if request.params == &quot;add-member&quot;:
+            if config.EnableAddMember:
+                result = (yield POST_handler_add_member(self, request))
+                returnValue(result)
+
+    else:
+        # Content-type handlers
+        contentType = request.headers.getHeader(&quot;content-type&quot;)
+        if contentType:
+            if hasattr(self, &quot;POST_handler_content_type&quot;):
+                result = (yield self.POST_handler_content_type(request, (contentType.mediaType, contentType.mediaSubtype)))
+                returnValue(result)
+
+    returnValue(responsecode.FORBIDDEN)
+
+@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(&quot;content-type&quot;)
+        if content_type is not None and (content_type.mediaType, content_type.mediaSubtype) != (&quot;text&quot;, &quot;calendar&quot;):
+            self.log_error(&quot;MIME type %s not allowed in calendar collection&quot; % (content_type,))
+            raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, &quot;supported-calendar-data&quot;)))
+            
+        # Read the calendar component from the stream
+        try:
+            calendardata = (yield allDataFromStream(request.stream))
+            if not hasattr(request, &quot;extendedLogItems&quot;):
+                request.extendedLogItems = {}
+            request.extendedLogItems[&quot;cl&quot;] = str(len(calendardata)) if calendardata else &quot;0&quot;
+
+            # We must have some data at this point
+            if calendardata is None:
+                # Use correct DAV:error response
+                raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (caldav_namespace, &quot;valid-calendar-data&quot;), description=&quot;No calendar data&quot;))
+
+            # Create a new name if one was not provided
+            name =  md5(str(calendardata) + str(time.time()) + self.fp.path).hexdigest() + &quot;.ics&quot;
+        
+            # 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=&quot;&quot;))
+
+            returnValue(result)
+
+        except ValueError, e:
+            self.log_error(&quot;Error while handling (calendar) POST: %s&quot; % (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(&quot;content-type&quot;)
+        if content_type is not None and (content_type.mediaType, content_type.mediaSubtype) != (&quot;text&quot;, &quot;vcard&quot;):
+            self.log_error(&quot;MIME type %s not allowed in address book collection&quot; % (content_type,))
+            raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (carddav_namespace, &quot;supported-address-data&quot;)))
+            
+        # Read the calendar component from the stream
+        try:
+            vcarddata = (yield allDataFromStream(request.stream))
+            if not hasattr(request, &quot;extendedLogItems&quot;):
+                request.extendedLogItems = {}
+            request.extendedLogItems[&quot;cl&quot;] = str(len(vcarddata)) if vcarddata else &quot;0&quot;
+
+            # We must have some data at this point
+            if vcarddata is None:
+                # Use correct DAV:error response
+                raise HTTPError(ErrorResponse(responsecode.FORBIDDEN, (carddav_namespace, &quot;valid-address-data&quot;), description=&quot;No address data&quot;))
+
+            # Create a new name if one was not provided
+            name =  md5(str(vcarddata) + str(time.time()) + self.fp.path).hexdigest() + &quot;.vcf&quot;
+        
+            # 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=&quot;&quot;))
+
+            returnValue(result)
+
+        except ValueError, e:
+            self.log_error(&quot;Error while handling (calendar) POST: %s&quot; % (e,))
+            raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, str(e)))
+
+    # Default behavior
+    returnValue(responsecode.FORBIDDEN)
+
</ins></span></pre></div>
<a id="CalendarServertrunktwistedcaldavquerytesttest_calendarquerypy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/query/test/test_calendarquery.py (5466 => 5467)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -16,7 +16,6 @@
</span><span class="cx"> 
</span><span class="cx"> from twistedcaldav import caldavxml
</span><span class="cx"> from twistedcaldav.query import queryfilter
</span><del>-from twistedcaldav.query.calendarquery import sqlcalendarquery
</del><span class="cx"> import datetime
</span><span class="cx"> import twistedcaldav.test.util
</span><span class="cx"> 
</span><span class="lines">@@ -94,6 +93,4 @@
</span><span class="cx">     
</span><span class="cx">         Eastern  = USTimeZone(-5, &quot;Eastern&quot;,  &quot;EST&quot;, &quot;EDT&quot;)
</span><span class="cx">         filter.child.settzinfo(Eastern)
</span><del>-        
-        print sqlcalendarquery(filter)
</del><span class="cx">         
</span><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavresourcepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/resource.py (5466 => 5467)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -159,24 +159,28 @@
</span><span class="cx">     # WebDAV
</span><span class="cx">     ##
</span><span class="cx"> 
</span><del>-    liveProperties = DAVResource.liveProperties + (
-        davxml.Owner.qname(),               # Private Events needs this but it is also OK to return empty
-        caldavxml.SupportedCalendarComponentSet.qname(),
-        caldavxml.SupportedCalendarData.qname(),
-    )
</del><ins>+    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
</ins><span class="cx"> 
</span><span class="cx">     supportedCalendarComponentSet = caldavxml.SupportedCalendarComponentSet(
</span><span class="cx">         *[caldavxml.CalendarComponent(name=item) for item in allowedComponents]
</span><span class="cx">     )
</span><span class="cx"> 
</span><del>-    @classmethod
-    def enableSharing(clz, enable):
-        qname = (calendarserver_namespace, &quot;invite&quot; )
-        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])
-
</del><span class="cx">     def isShadowableProperty(self, qname):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         Shadowable properties are ones on shared resources where a &quot;default&quot; exists until
</span><span class="lines">@@ -191,7 +195,7 @@
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="cx">         A global property is one that is the same for all users.
</span><span class="cx">         &quot;&quot;&quot;
</span><del>-        if qname in self.liveProperties:
</del><ins>+        if qname in self.liveProperties():
</ins><span class="cx">             if qname in (
</span><span class="cx">                 davxml.DisplayName.qname(),
</span><span class="cx">                 customxml.Invite.qname(),
</span><span class="lines">@@ -283,6 +287,12 @@
</span><span class="cx">             owner = (yield self.owner(request))
</span><span class="cx">             returnValue(davxml.Owner(owner))
</span><span class="cx"> 
</span><ins>+        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 + &quot;/;add-member&quot;)))
+
</ins><span class="cx">         elif qname == caldavxml.SupportedCalendarComponentSet.qname():
</span><span class="cx">             # CalDAV-access-09, section 5.2.3
</span><span class="cx">             if self.hasDeadProperty(qname):
</span><span class="lines">@@ -1058,40 +1068,32 @@
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     implements(ICalendarPrincipalResource)
</span><span class="cx"> 
</span><del>-    liveProperties = tuple(DAVPrincipalResource.liveProperties) + (
-        (caldav_namespace, &quot;calendar-home-set&quot;        ),
-        (caldav_namespace, &quot;calendar-user-address-set&quot;),
-        (caldav_namespace, &quot;schedule-inbox-URL&quot;       ),
-        (caldav_namespace, &quot;schedule-outbox-URL&quot;      ),
-        (caldav_namespace, &quot;calendar-user-type&quot;       ),
-        (calendarserver_namespace, &quot;calendar-proxy-read-for&quot;  ),
-        (calendarserver_namespace, &quot;calendar-proxy-write-for&quot; ),
-        (calendarserver_namespace, &quot;auto-schedule&quot; ),
-    )
</del><ins>+    def liveProperties(self):
+        
+        baseProperties = ()
+        
+        if config.EnableCalDAV:
+            baseProperties += (
+                (caldav_namespace, &quot;calendar-home-set&quot;        ),
+                (caldav_namespace, &quot;calendar-user-address-set&quot;),
+                (caldav_namespace, &quot;schedule-inbox-URL&quot;       ),
+                (caldav_namespace, &quot;schedule-outbox-URL&quot;      ),
+                (caldav_namespace, &quot;calendar-user-type&quot;       ),
+                (calendarserver_namespace, &quot;calendar-proxy-read-for&quot;  ),
+                (calendarserver_namespace, &quot;calendar-proxy-write-for&quot; ),
+                (calendarserver_namespace, &quot;auto-schedule&quot; ),
+            )
+        
+        if config.EnableCardDAV:
+            baseProperties += (carddavxml.AddressBookHomeSet.qname(),)
</ins><span class="cx"> 
</span><del>-    @classmethod
-    def enableDropBox(clz, enable):
-        qname = (calendarserver_namespace, &quot;dropbox-home-URL&quot; )
-        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])
</del><ins>+        if config.EnableDropBox:
+            baseProperties += (customxml.DropBoxHomeURL.qname(),)
</ins><span class="cx"> 
</span><del>-    @classmethod
-    def enableSharing(clz, enable):
-        qname = (calendarserver_namespace, &quot;notification-URL&quot; )
-        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])
</del><ins>+        if config.Sharing.Enabled:
+            baseProperties += (customxml.NotificationURL.qname(),)
</ins><span class="cx"> 
</span><del>-    @classmethod
-    def enableAddressBooks(clz, enable):
-        qname = (carddav_namespace, &quot;addressbook-home-set&quot; )
-        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])
</del><ins>+        return super(CalendarPrincipalResource, self).liveProperties() + baseProperties
</ins><span class="cx"> 
</span><span class="cx">     def isCollection(self):
</span><span class="cx">         return True
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavschedulepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/schedule.py (5466 => 5467)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -82,10 +82,12 @@
</span><span class="cx">     Extends L{DAVResource} to provide CalDAV functionality.
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx"> 
</span><del>-    liveProperties = CalendarSchedulingCollectionResource.liveProperties + (
-        (caldav_namespace, &quot;calendar-free-busy-set&quot;),
-        (caldav_namespace, &quot;schedule-default-calendar-URL&quot;),
-    )
</del><ins>+    def liveProperties(self):
+        
+        return super(ScheduleInboxResource, self).liveProperties() + (
+            (caldav_namespace, &quot;calendar-free-busy-set&quot;),
+            (caldav_namespace, &quot;schedule-default-calendar-URL&quot;),
+        )
</ins><span class="cx"> 
</span><span class="cx">     def resourceType(self, request):
</span><span class="cx">         return succeed(davxml.ResourceType.scheduleInbox)
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavsharingpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/sharing.py (5466 => 5467)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -610,18 +610,16 @@
</span><span class="cx">         d.addCallback(self.xmlPOSTNoAuth, request)
</span><span class="cx">         return d
</span><span class="cx">     
</span><del>-    def http_POST(self, request):
</del><ins>+    def POST_handler_content_type(self, request, contentType):
</ins><span class="cx">         if self.isCollection():
</span><del>-            contentType = request.headers.getHeader(&quot;content-type&quot;)
</del><span class="cx">             if contentType:
</span><del>-                contentType = (contentType.mediaType, contentType.mediaSubtype)
</del><span class="cx">                 if contentType in self._postHandlers:
</span><span class="cx">                     return self._postHandlers[contentType](self, request)
</span><span class="cx">                 else:
</span><span class="cx">                     self.log_info(&quot;Get a POST of an unsupported content type on a collection type: %s&quot; % (contentType,))
</span><span class="cx">             else:
</span><span class="cx">                 self.log_info(&quot;Get a POST with no content type on a collection&quot;)
</span><del>-        return responsecode.FORBIDDEN
</del><ins>+        return succeed(responsecode.FORBIDDEN)
</ins><span class="cx"> 
</span><span class="cx">     _postHandlers = {
</span><span class="cx">         (&quot;application&quot;, &quot;xml&quot;) : xmlPOSTAuth,
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavstaticpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/static.py (5466 => 5467)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -929,11 +929,13 @@
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Calendar home collection resource.
</span><span class="cx">     &quot;&quot;&quot;
</span><del>-    liveProperties = CalDAVFile.liveProperties + (
-        (customxml.calendarserver_namespace, &quot;xmpp-uri&quot;),
-        (customxml.calendarserver_namespace, &quot;xmpp-heartbeat-uri&quot;),
-        (customxml.calendarserver_namespace, &quot;xmpp-server&quot;),
-    )
</del><ins>+    def liveProperties(self):
+        
+        return super(CalendarHomeFile, self).liveProperties() + (
+            (customxml.calendarserver_namespace, &quot;xmpp-uri&quot;),
+            (customxml.calendarserver_namespace, &quot;xmpp-heartbeat-uri&quot;),
+            (customxml.calendarserver_namespace, &quot;xmpp-server&quot;),
+        )
</ins><span class="cx"> 
</span><span class="cx">     def __init__(self, path, parent, record):
</span><span class="cx">         &quot;&quot;&quot;
</span><span class="lines">@@ -1493,9 +1495,11 @@
</span><span class="cx">     &quot;&quot;&quot;
</span><span class="cx">     Address book home collection resource.
</span><span class="cx">     &quot;&quot;&quot;
</span><del>-    liveProperties = CalDAVFile.liveProperties + (
-        (customxml.calendarserver_namespace, &quot;xmpp-uri&quot;),
-    )
</del><ins>+    
+    def liveProperties(self):
+        return super(AddressBookHomeFile, self).liveProperties() + (
+            (customxml.calendarserver_namespace, &quot;xmpp-uri&quot;),
+        )
</ins><span class="cx"> 
</span><span class="cx">     def __init__(self, path, parent, record):
</span><span class="cx">         &quot;&quot;&quot;
</span></span></pre></div>
<a id="CalendarServertrunktwistedcaldavstdconfigpy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/twistedcaldav/stdconfig.py (5466 => 5467)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -331,6 +331,7 @@
</span><span class="cx">     #
</span><span class="cx">     # Standard (or draft) WebDAV extensions
</span><span class="cx">     #
</span><ins>+    &quot;EnableAddMember&quot;         : True,  # POST ;add-member extension
</ins><span class="cx">     &quot;EnableSyncReport&quot;        : True,  # REPORT collection-sync
</span><span class="cx">     &quot;EnableWellKnown&quot;         : True,  # /.well-known resource
</span><span class="cx"> 
</span><span class="lines">@@ -676,15 +677,6 @@
</span><span class="cx">                 del configDict.DirectoryService.params[param]
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-def _updateAddressBook(configDict):
-    #
-    # FIXME: Use the config object instead of doing this here
-    #
-    from twistedcaldav.resource import CalendarPrincipalResource
-    CalendarPrincipalResource.enableAddressBooks(configDict.EnableCardDAV)
-
-
-
</del><span class="cx"> def _preUpdateDirectoryAddressBookBackingDirectoryService(configDict, items):
</span><span class="cx">     #
</span><span class="cx">     # Special handling for directory address book configs
</span><span class="lines">@@ -809,13 +801,6 @@
</span><span class="cx">     except re.error, e:
</span><span class="cx">         raise ConfigurationError(&quot;Invalid regular expression in RejectClients: %s&quot; % (e,))
</span><span class="cx"> 
</span><del>-def _updateDropBox(configDict):
-    #
-    # FIXME: Use the config object instead of doing this here
-    #
-    from twistedcaldav.resource import CalendarPrincipalResource
-    CalendarPrincipalResource.enableDropBox(configDict.EnableDropBox)
-
</del><span class="cx"> def _updateLogLevels(configDict):
</span><span class="cx">     clearLogLevels()
</span><span class="cx"> 
</span><span class="lines">@@ -923,14 +908,6 @@
</span><span class="cx">                     log.info(&quot;iMIP %s password not found in keychain&quot; %
</span><span class="cx">                         (direction,))
</span><span class="cx"> 
</span><del>-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)
-
</del><span class="cx"> def _updatePartitions(configDict):
</span><span class="cx">     if configDict.Partitioning.Enabled:
</span><span class="cx">         partitions.setSelfPartition(configDict.Partitioning.ServerPartitionID)
</span><span class="lines">@@ -969,17 +946,14 @@
</span><span class="cx">     )
</span><span class="cx"> POST_UPDATE_HOOKS = (
</span><span class="cx">     _updateHostName,
</span><del>-    _updateAddressBook,
</del><span class="cx">     _postUpdateDirectoryService,
</span><span class="cx">     _postUpdateAugmentService,
</span><span class="cx">     _postUpdateProxyDBService,
</span><span class="cx">     _updateACLs,
</span><span class="cx">     _updateRejectClients,
</span><del>-    _updateDropBox,
</del><span class="cx">     _updateLogLevels,
</span><span class="cx">     _updateNotifications,
</span><span class="cx">     _updateScheduling,
</span><del>-    _updateSharing,
</del><span class="cx">     _updatePartitions,
</span><span class="cx">     _updateCompliance,
</span><span class="cx">     )
</span></span></pre></div>
<a id="CalendarServertrunktxcaldavresourcepy"></a>
<div class="modfile"><h4>Modified: CalendarServer/trunk/txcaldav/resource.py (5466 => 5467)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -118,11 +118,13 @@
</span><span class="cx">     # WebDAV
</span><span class="cx">     #
</span><span class="cx"> 
</span><del>-    liveProperties = DAVResource.liveProperties + (
-        (dav_namespace,    &quot;owner&quot;),               # Private Events needs this but it is also OK to return empty
-        (caldav_namespace, &quot;supported-calendar-component-set&quot;),
-        (caldav_namespace, &quot;supported-calendar-data&quot;         ),
-    )
</del><ins>+    def liveProperties(self):
+        
+        return super(CalendarCollectionResource, self).liveProperties() + (
+            (dav_namespace,    &quot;owner&quot;),               # Private Events needs this but it is also OK to return empty
+            (caldav_namespace, &quot;supported-calendar-component-set&quot;),
+            (caldav_namespace, &quot;supported-calendar-data&quot;         ),
+        )
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>