[CalendarServer-changes] [8921] CalendarServer/branches/users/gaya/ldapdirectorybacker

source_changes at macosforge.org source_changes at macosforge.org
Wed Mar 21 17:41:39 PDT 2012


Revision: 8921
          http://trac.macosforge.org/projects/calendarserver/changeset/8921
Author:   gaya at apple.com
Date:     2012-03-21 17:41:39 -0700 (Wed, 21 Mar 2012)
Log Message:
-----------
sync with TOT

Modified Paths:
--------------
    CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/accesslog.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/provision/root.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/provision/test/test_root.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/push/applepush.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/calverify.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/dbinspect.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/export.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/gateway.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/principals.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/purge.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/shell/cmd.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/shell/terminal.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/shell/vfs.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/webadmin/resource.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/webadmin/test/test_resource.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/webcal/resource.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/contrib/migration/calendarmigrator.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/contrib/migration/calendarpromotion.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/contrib/migration/test/test_migrator.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/contrib/tools/protocolanalysis.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/doc/Extensions/caldav-notifications.txt
    CalendarServer/branches/users/gaya/ldapdirectorybacker/doc/Extensions/caldav-notifications.xml
    CalendarServer/branches/users/gaya/ldapdirectorybacker/pyflakes
    CalendarServer/branches/users/gaya/ldapdirectorybacker/support/build.sh
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/__init__.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/auth.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/http.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/acl.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/copymove.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/delete.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/get.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/mkcol.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/prop_common.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/propfind.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/proppatch.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/put.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/put_common.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/report.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/report_acl_principal_prop_set.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/report_expand.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/report_principal_match.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/report_principal_property_search.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/report_principal_search_property_set.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/resource.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_acl.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_prop.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_quota.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_report.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_resource.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_static.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_xattrprops.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/util.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/util.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/xattrprops.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/__init__.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/caldavxml.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/carddavxml.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/customxml.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/calendaruserproxy.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/ldapdirectory.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/opendirectorybacker.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/principal.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/test/test_calendar.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/test/test_guidchange.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/test/test_principal.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/test/test_proxyprincipalmembers.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/wiki.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directorybackedaddressbook.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/dropbox.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/extensions.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/freebusyurl.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/linkresource.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/mail.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/copymove.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/copymove_contact.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/delete.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/get.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/mkcalendar.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/mkcol.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/propfind.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/put_addressbook_common.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/put_common.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/report.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/report_addressbook_query.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/report_calendar_query.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/report_common.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/report_freebusy.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/report_multiget_common.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/report_sync_collection.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/mkcolxml.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/notifications.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/resource.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/schedule.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/scheduling/caldav.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/scheduling/implicit.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/scheduling/scheduler.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/sharing.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/simpleresource.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/stdconfig.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/storebridge.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_addressbookmultiget.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_addressbookquery.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_cache.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_calendarquery.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_extensions.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_mkcalendar.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_multiget.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_props.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_resource.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_schedule.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_sharing.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_upgrade.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_wrapping.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/util.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/timezoneservice.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/timezonestdservice.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/timezonexml.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/upgrade.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/base/datastore/file.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/base/propertystore/base.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/base/propertystore/sql.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/base/propertystore/test/base.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/base/propertystore/test/test_appledouble.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/base/propertystore/test/test_xattr.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/base/propertystore/xattr.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/caldav/datastore/file.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/caldav/datastore/sql.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/caldav/datastore/test/common.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/caldav/datastore/test/test_sql.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/caldav/datastore/test/test_util.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/caldav/datastore/util.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/caldav/resource.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/carddav/datastore/file.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/carddav/datastore/sql.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/carddav/datastore/test/common.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/carddav/datastore/test/test_sql.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/carddav/resource.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/common/datastore/file.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/common/datastore/sql.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/common/datastore/test/test_sql.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/common/datastore/upgrade/sql/upgrades/upgrade_from_1_to_2.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/common/inotifications.py

Added Paths:
-----------
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/__init__.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/base.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/draft_sync.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/element.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/extensions.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/parser.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/parser_base.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/parser_sax.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc2518.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc3253.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc3744.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc4331.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc5397.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc5842.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc5995.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/__init__.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/test_base.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/test_xml.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/test_xml_rfc3744.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/xmlext.py

Removed Paths:
-------------
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/davxml.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/element/
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_davxml.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_xml.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_xml_rfc3744.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/__init__.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/base.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/draft_sync.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/element.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/extensions.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/parser.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/parser_base.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/parser_sax.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc2518.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc3253.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc3744.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc4331.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc5397.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc5842.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc5995.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/__init__.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/test_base.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/test_xml.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/test_xml_rfc3744.py
    CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/xmlext.py

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/accesslog.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/accesslog.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/accesslog.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -32,7 +32,7 @@
 from twisted.internet import protocol
 from twisted.protocols import amp
 from twext.web2 import iweb
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.log import BaseCommonAccessLoggingObserver
 from twext.web2.log import LogWrapperResource
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/provision/root.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/provision/root.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/provision/root.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -22,7 +22,7 @@
 from twext.python.log import Logger
 from twext.web2 import responsecode
 from twext.web2.auth.wrapper import UnauthorizedResponse
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.xattrprops import xattrPropertyStore
 from twext.web2.http import HTTPError, StatusResponse, RedirectResponse
 
@@ -105,7 +105,8 @@
         if not config.EnableKeepAlive:
             def addConnectionClose(request, response):
                 response.headers.setHeader("connection", ("close",))
-                request.chanRequest.channel.setReadPersistent(False)
+                if request.chanRequest is not None:
+                    request.chanRequest.channel.setReadPersistent(False)
                 return response
             self.contentFilters.append((addConnectionClose, True))
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/provision/test/test_root.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/provision/test/test_root.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/provision/test/test_root.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -24,7 +24,7 @@
 from twext.web2 import server
 from twext.web2.auth import basic
 from twext.web2.dav import auth
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.http import HTTPError
 from twext.web2.iweb import IResponse
 from twext.web2.test.test_server import SimpleRequest

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/push/applepush.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/push/applepush.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/push/applepush.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -18,7 +18,7 @@
 from twext.python.log import Logger, LoggingMixIn
 from twext.python.log import LoggingMixIn
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.noneprops import NonePropertyStore
 from twext.web2.dav.resource import DAVResource
 from twext.web2.http import Response

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/calverify.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/calverify.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/calverify.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -625,6 +625,8 @@
             calendar = yield self.getCalendar(resid)
             if calendar is None:
                 continue
+            if self.options["verbose"] and self.masterComponent(calendar) is None:
+                print "Missing master for organizer: %s, resid: %s, uid: %s" % (organizer, resid, uid,)
             organizerViewOfAttendees = self.buildAttendeeStates(calendar, self.start, self.end)
             try:
                 del organizerViewOfAttendees[organizer]
@@ -893,6 +895,18 @@
         returnValue(caldata)
 
 
+    def masterComponent(self, calendar):
+        """
+        Return the master iCal component in this calendar.
+        @return: the L{Component} for the master component,
+            or C{None} if there isn't one.
+        """
+        for component in calendar.getComponents(definitions.cICalComponent_VEVENT):
+            if not component.hasProperty("RECURRENCE-ID"):
+                return component
+        
+        return None
+
     def buildAttendeeStates(self, calendar, start, end, attendee_only=None):
         # Expand events into instances in the start/end range
         results = []

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/dbinspect.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/dbinspect.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/dbinspect.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -330,8 +330,49 @@
         ).on(txn))
         returnValue(tuple(rows))
 
+class EventDetails(Cmd):
+    """
+    Base class for common event details commands.
+    """
+    def printEventDetails(self, txn, details):
+        owner, calendar, resource_id, resource, created, modified, data = details
+        shortname = UserNameFromUID(txn, owner)
+        table = tables.Table()
+        table.addRow(("Owner UID:", owner,))
+        table.addRow(("User Name:", shortname,))
+        table.addRow(("Calendar:", calendar,))
+        table.addRow(("Resource Name:", resource))
+        table.addRow(("Resource ID:", resource_id))
+        table.addRow(("Created", created))
+        table.addRow(("Modified", modified))
+        print "\n"
+        table.printTable()
+        print data
+    
+    @inlineCallbacks
+    def getEventData(self, txn, whereClause, whereParams):
+        ch = schema.CALENDAR_HOME
+        cb = schema.CALENDAR_BIND
+        co = schema.CALENDAR_OBJECT
+        rows = (yield Select(
+            [
+                ch.OWNER_UID,
+                cb.CALENDAR_RESOURCE_NAME,
+                co.RESOURCE_ID,
+                co.RESOURCE_NAME,
+                co.CREATED,
+                co.MODIFIED,
+                co.ICALENDAR_TEXT,
+            ],
+            From=ch.join(
+                cb, type="inner", on=(ch.RESOURCE_ID == cb.CALENDAR_HOME_RESOURCE_ID).And(
+                    cb.BIND_MODE == _BIND_MODE_OWN)).join(
+                co, type="inner", on=(cb.CALENDAR_RESOURCE_ID == co.CALENDAR_RESOURCE_ID)),
+            Where=whereClause,
+        ).on(txn, **whereParams))
+        returnValue(tuple(rows))
 
-class Event(Cmd):
+class Event(EventDetails):
     
     _name = "Get Event Data by Resource-ID"
     
@@ -347,35 +388,16 @@
             returnValue(None)
         result = yield self.getData(txn, rid)
         if result:
-            resource, created, modified, data = result
-            table = tables.Table()
-            table.addRow(("Resource Name:", resource))
-            table.addRow(("Resource ID:", rid))
-            table.addRow(("Created", created))
-            table.addRow(("Modified", modified))
-            print "\n"
-            table.printTable()
-            print data
+            self.printEventDetails(txn, result[0])
         else:
             print "Could not find resource"
 
-    @inlineCallbacks
     def getData(self, txn, rid):
         co = schema.CALENDAR_OBJECT
-        rows = (yield Select(
-            [
-                co.RESOURCE_NAME,
-                co.CREATED,
-                co.MODIFIED,
-                co.ICALENDAR_TEXT,
-            ],
-            From=co,
-            Where=(co.RESOURCE_ID == Parameter("ResourceID")),
-        ).on(txn, **{"ResourceID": rid}))
-        returnValue(rows[0] if rows else None)
+        return self.getEventData(txn, (co.RESOURCE_ID == Parameter("RID")), {"RID":rid})
 
 
-class EventsByUID(Cmd):
+class EventsByUID(EventDetails):
     
     _name = "Get Event Data by iCalendar UID"
     
@@ -386,46 +408,17 @@
         uid = raw_input("UID: ")
         rows = yield self.getData(txn, uid)
         if rows:
-            for owner, calendar, resource_id, resource, created, modified, data in rows:
-                shortname = UserNameFromUID(txn, owner)
-                table = tables.Table()
-                table.addRow(("User Name:", shortname,))
-                table.addRow(("Calendar:", calendar,))
-                table.addRow(("Resource Name:", resource))
-                table.addRow(("Resource ID:", resource_id))
-                table.addRow(("Created", created))
-                table.addRow(("Modified", modified))
-                print "\n"
-                table.printTable()
-                print data
+            for result in rows:
+                self.printEventDetails(txn, result)
         else:
             print "Could not find icalendar data"
 
-    @inlineCallbacks
     def getData(self, txn, uid):
-        ch = schema.CALENDAR_HOME
-        cb = schema.CALENDAR_BIND
         co = schema.CALENDAR_OBJECT
-        rows = (yield Select(
-            [
-                ch.OWNER_UID,
-                cb.CALENDAR_RESOURCE_NAME,
-                co.RESOURCE_ID,
-                co.RESOURCE_NAME,
-                co.CREATED,
-                co.MODIFIED,
-                co.ICALENDAR_TEXT,
-            ],
-            From=ch.join(
-                cb, type="inner", on=(ch.RESOURCE_ID == cb.CALENDAR_HOME_RESOURCE_ID).And(
-                    cb.BIND_MODE == _BIND_MODE_OWN)).join(
-                co, type="inner", on=(cb.CALENDAR_RESOURCE_ID == co.CALENDAR_RESOURCE_ID)),
-            Where=(co.ICALENDAR_UID == Parameter("UID")),
-        ).on(txn, **{"UID": uid}))
-        returnValue(tuple(rows))
+        return self.getEventData(txn, (co.ICALENDAR_UID == Parameter("UID")), {"UID":uid})
 
 
-class EventsByName(Cmd):
+class EventsByName(EventDetails):
     
     _name = "Get Event Data by resource name"
     
@@ -436,46 +429,17 @@
         name = raw_input("Resource Name: ")
         rows = yield self.getData(txn, name)
         if rows:
-            for owner, calendar, resource_id, resource, created, modified, data in rows:
-                shortname = UserNameFromUID(txn, owner)
-                table = tables.Table()
-                table.addRow(("User Name:", shortname,))
-                table.addRow(("Calendar:", calendar,))
-                table.addRow(("Resource Name:", resource))
-                table.addRow(("Resource ID:", resource_id))
-                table.addRow(("Created", created))
-                table.addRow(("Modified", modified))
-                print "\n"
-                table.printTable()
-                print data
+            for result in rows:
+                self.printEventDetails(txn, result)
         else:
             print "Could not find icalendar data"
 
-    @inlineCallbacks
     def getData(self, txn, name):
-        ch = schema.CALENDAR_HOME
-        cb = schema.CALENDAR_BIND
         co = schema.CALENDAR_OBJECT
-        rows = (yield Select(
-            [
-                ch.OWNER_UID,
-                cb.CALENDAR_RESOURCE_NAME,
-                co.RESOURCE_ID,
-                co.RESOURCE_NAME,
-                co.CREATED,
-                co.MODIFIED,
-                co.ICALENDAR_TEXT,
-            ],
-            From=ch.join(
-                cb, type="inner", on=(ch.RESOURCE_ID == cb.CALENDAR_HOME_RESOURCE_ID).And(
-                    cb.BIND_MODE == _BIND_MODE_OWN)).join(
-                co, type="inner", on=(cb.CALENDAR_RESOURCE_ID == co.CALENDAR_RESOURCE_ID)),
-            Where=(co.RESOURCE_NAME == Parameter("Name")),
-        ).on(txn, **{"Name": name}))
-        returnValue(tuple(rows))
+        return self.getEventData(txn, (co.RESOURCE_NAME == Parameter("NAME")), {"NAME":name})
 
 
-class EventsByOwner(Cmd):
+class EventsByOwner(EventDetails):
     
     _name = "Get Event Data by Owner UID"
     
@@ -486,46 +450,17 @@
         uid = raw_input("Owner UID: ")
         rows = yield self.getData(txn, uid)
         if rows:
-            for owner, calendar, resource_id, resource, created, modified, data in rows:
-                shortname = UserNameFromUID(txn, owner)
-                table = tables.Table()
-                table.addRow(("User Name:", shortname,))
-                table.addRow(("Calendar:", calendar,))
-                table.addRow(("Resource Name:", resource))
-                table.addRow(("Resource ID:", resource_id))
-                table.addRow(("Created", created))
-                table.addRow(("Modified", modified))
-                print "\n"
-                table.printTable()
-                print data
+            for result in rows:
+                self.printEventDetails(txn, result)
         else:
             print "Could not find icalendar data"
 
-    @inlineCallbacks
     def getData(self, txn, uid):
         ch = schema.CALENDAR_HOME
-        cb = schema.CALENDAR_BIND
-        co = schema.CALENDAR_OBJECT
-        rows = (yield Select(
-            [
-                ch.OWNER_UID,
-                cb.CALENDAR_RESOURCE_NAME,
-                co.RESOURCE_ID,
-                co.RESOURCE_NAME,
-                co.CREATED,
-                co.MODIFIED,
-                co.ICALENDAR_TEXT,
-            ],
-            From=ch.join(
-                cb, type="inner", on=(ch.RESOURCE_ID == cb.CALENDAR_HOME_RESOURCE_ID).And(
-                    cb.BIND_MODE == _BIND_MODE_OWN)).join(
-                co, type="inner", on=(cb.CALENDAR_RESOURCE_ID == co.CALENDAR_RESOURCE_ID)),
-            Where=(ch.OWNER_UID == Parameter("UID")),
-        ).on(txn, **{"UID": uid}))
-        returnValue(tuple(rows))
+        return self.getEventData(txn, (ch.OWNER_UID == Parameter("UID")), {"UID":uid})
 
 
-class EventsByOwnerCalendar(Cmd):
+class EventsByOwnerCalendar(EventDetails):
     
     _name = "Get Event Data by Owner UID and calendar name"
     
@@ -537,46 +472,56 @@
         name = raw_input("Calendar resource name: ")
         rows = yield self.getData(txn, uid, name)
         if rows:
-            for owner, calendar, resource_id, resource, created, modified, data in rows:
-                shortname = UserNameFromUID(txn, owner)
-                table = tables.Table()
-                table.addRow(("User Name:", shortname,))
-                table.addRow(("Calendar:", calendar,))
-                table.addRow(("Resource Name:", resource))
-                table.addRow(("Resource ID:", resource_id))
-                table.addRow(("Created", created))
-                table.addRow(("Modified", modified))
-                print "\n"
-                table.printTable()
-                print data
+            for result in rows:
+                self.printEventDetails(txn, result)
         else:
             print "Could not find icalendar data"
 
-    @inlineCallbacks
     def getData(self, txn, uid, name):
         ch = schema.CALENDAR_HOME
         cb = schema.CALENDAR_BIND
+        return self.getEventData(txn, (ch.OWNER_UID == Parameter("UID")).And(cb.CALENDAR_RESOURCE_NAME == Parameter("NAME")), {"UID": uid, "NAME": name})
+
+
+class EventsByPath(EventDetails):
+    
+    _name = "Get Event Data by HTTP Path"
+    
+    @inlineCallbacks
+    def doIt(self, txn):
+        
+        
+        path = raw_input("Path: ")
+        pathbits = path.split("/")
+        if len(pathbits) != 6:
+            print "Not a valid calendar object resource path"
+            returnValue(None)
+        homeName = pathbits[3]
+        calendarName = pathbits[4]
+        resourceName = pathbits[5]
+        rows = yield self.getData(txn, homeName, calendarName, resourceName)
+        if rows:
+            for result in rows:
+                self.printEventDetails(txn, result)
+        else:
+            print "Could not find icalendar data"
+
+    def getData(self, txn, homeName, calendarName, resourceName):
+        ch = schema.CALENDAR_HOME
+        cb = schema.CALENDAR_BIND
         co = schema.CALENDAR_OBJECT
-        rows = (yield Select(
-            [
-                ch.OWNER_UID,
-                cb.CALENDAR_RESOURCE_NAME,
-                co.RESOURCE_ID,
-                co.RESOURCE_NAME,
-                co.CREATED,
-                co.MODIFIED,
-                co.ICALENDAR_TEXT,
-            ],
-            From=ch.join(
-                cb, type="inner", on=(ch.RESOURCE_ID == cb.CALENDAR_HOME_RESOURCE_ID).And(
-                    cb.BIND_MODE == _BIND_MODE_OWN)).join(
-                co, type="inner", on=(cb.CALENDAR_RESOURCE_ID == co.CALENDAR_RESOURCE_ID)),
-            Where=((ch.OWNER_UID == Parameter("UID")).And(cb.CALENDAR_RESOURCE_NAME == Parameter("NAME"))),
-        ).on(txn, **{"UID": uid, "NAME": name}))
-        returnValue(tuple(rows))
+        return self.getEventData(
+            txn,
+            (
+                ch.OWNER_UID == Parameter("HOME")).And(
+                cb.CALENDAR_RESOURCE_NAME == Parameter("CALENDAR")).And(
+                co.RESOURCE_NAME == Parameter("RESOURCE")
+            ),
+            {"HOME": homeName, "CALENDAR": calendarName, "RESOURCE": resourceName}
+        )
 
 
-class EventsByContent(Cmd):
+class EventsByContent(EventDetails):
     
     _name = "Get Event Data by Searching its Text Data"
     
@@ -587,43 +532,14 @@
         uid = raw_input("Search for: ")
         rows = yield self.getData(txn, uid)
         if rows:
-            for owner, calendar, resource_id, resource, created, modified, data in rows:
-                shortname = UserNameFromUID(txn, owner)
-                table = tables.Table()
-                table.addRow(("User Name:", shortname,))
-                table.addRow(("Calendar:", calendar,))
-                table.addRow(("Resource Name:", resource))
-                table.addRow(("Resource ID:", resource_id))
-                table.addRow(("Created", created))
-                table.addRow(("Modified", modified))
-                print "\n"
-                table.printTable()
-                print data
+            for result in rows:
+                self.printEventDetails(txn, result)
         else:
             print "Could not find icalendar data"
 
-    @inlineCallbacks
     def getData(self, txn, text):
-        ch = schema.CALENDAR_HOME
-        cb = schema.CALENDAR_BIND
         co = schema.CALENDAR_OBJECT
-        rows = (yield Select(
-            [
-                ch.OWNER_UID,
-                cb.CALENDAR_RESOURCE_NAME,
-                co.RESOURCE_ID,
-                co.RESOURCE_NAME,
-                co.CREATED,
-                co.MODIFIED,
-                co.ICALENDAR_TEXT,
-            ],
-            From=ch.join(
-                cb, type="inner", on=(ch.RESOURCE_ID == cb.CALENDAR_HOME_RESOURCE_ID).And(
-                    cb.BIND_MODE == _BIND_MODE_OWN)).join(
-                co, type="inner", on=(cb.CALENDAR_RESOURCE_ID == co.CALENDAR_RESOURCE_ID)),
-            Where=(co.ICALENDAR_TEXT.Contains(Parameter("Text"))),
-        ).on(txn, **{"Text": text}))
-        returnValue(tuple(rows))
+        return self.getEventData(txn, (co.ICALENDAR_TEXT.Contains(Parameter("TEXT"))), {"TEXT":text})
 
 
 class EventsInTimerange(Cmd):
@@ -811,6 +727,7 @@
         self.registerCommand(EventsByName)
         self.registerCommand(EventsByOwner)
         self.registerCommand(EventsByOwnerCalendar)
+        self.registerCommand(EventsByPath)
         self.registerCommand(EventsByContent)
         self.registerCommand(EventsInTimerange)
         self.doDBInspect()

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/export.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/export.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/export.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -243,7 +243,7 @@
         """
         directory = exportService.directoryService()
         record = directory.recordWithShortName(self.recordType, self.shortName)
-        return record.guid
+        return record.uid
 
 
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/gateway.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/gateway.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/gateway.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -30,7 +30,7 @@
 from twisted.python.util import switchUID
 from twistedcaldav.config import config, ConfigurationError
 from twistedcaldav.directory.directory import DirectoryError
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 
 from calendarserver.tools.util import loadConfig, getDirectory, setupMemcached, checkDirectory
 from calendarserver.tools.principals import (

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/principals.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/principals.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/principals.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -27,12 +27,13 @@
 from twisted.python.util import switchUID
 from twisted.internet import reactor
 from twisted.internet.defer import inlineCallbacks, returnValue
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 
 from twext.python.log import clearLogLevels
 from twext.python.log import StandardIOObserver
-from twext.web2.dav.davxml import sname2qname, qname2sname
 
+from txdav.xml.base import decodeXMLName, encodeXMLName
+
 from twistedcaldav.config import config, ConfigurationError
 from twistedcaldav.directory.directory import UnknownRecordTypeError, DirectoryError
 
@@ -160,7 +161,7 @@
 
         elif opt in ("", "--read-property"):
             try:
-                qname = sname2qname(arg)
+                qname = decodeXMLName(arg)
             except ValueError, e:
                 abort(e)
             principalActions.append((action_readProperty, qname))
@@ -511,7 +512,7 @@
 @inlineCallbacks
 def action_readProperty(resource, qname):
     property = (yield resource.readProperty(qname, None))
-    print "%r on %s:" % (qname2sname(qname), resource)
+    print "%r on %s:" % (encodeXMLName(*qname), resource)
     print ""
     print property.toxml()
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/purge.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/purge.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/purge.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -29,7 +29,7 @@
 from twisted.internet.defer import inlineCallbacks, returnValue
 
 from twext.python.log import Logger
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.responsecode import NO_CONTENT
 
 from twistedcaldav import caldavxml

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/shell/cmd.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/shell/cmd.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/shell/cmd.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -425,3 +425,35 @@
         raise NotImplementedError("")
 
     cmd_sql.hidden = "Not implemented."
+
+
+    def cmd_log(self, tokens):
+        """
+        Enable logging.
+
+        usage: log [file]
+        """
+        if hasattr(self, "_logFile"):
+            self.terminal.write("Already logging to file: %s\n" % (self._logFile,))
+            return
+
+        if tokens:
+            fileName = tokens.pop(0)
+        else:
+            fileName = "/tmp/shell.log"
+
+        if tokens:
+            raise UnknownArguments(tokens)
+
+        from twisted.python.log import startLogging
+        try:
+            f = open(fileName, "w")
+        except (IOError, OSError), e:
+            self.terminal.write("Unable to open file %s: %s\n" % (fileName, e))
+            return
+
+        startLogging(f)
+
+        self._logFile = fileName
+
+    cmd_log.hidden = "Debug tool"

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/shell/terminal.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/shell/terminal.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/shell/terminal.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -95,12 +95,6 @@
         """
         Start the service.
         """
-        # For debugging
-        if True:
-            from twisted.python.log import startLogging
-            f = open("/tmp/shell.log", "w")
-            startLogging(f)
-
         super(ShellService, self).startService()
 
         # Set up the terminal for interactive action

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/shell/vfs.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/shell/vfs.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/tools/shell/vfs.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -242,6 +242,9 @@
     def __init__(self, service, path, uid, record=None):
         Folder.__init__(self, service, path)
 
+        if record is None:
+            record = self.service.directory.recordWithUID(uid)
+
         if record is not None:
             assert uid == record.uid
 
@@ -304,6 +307,7 @@
     def list(self):
         return Folder.list(self)
 
+    @inlineCallbacks
     def describe(self):
         result = []
         result.append("Principal home for UID: %s\n" % (self.uid,))
@@ -355,12 +359,55 @@
                 rows.append((group.uid, group.shortNames[0], group.fullName))
 
             if rows:
+                def sortKey(row):
+                    return (row[1], row[2])
                 result.append("Group Memberships:")
-                result.append(tableString(rows, header=("UID", "Short Name", "Full Name")))
+                result.append(tableString(
+                    sorted(rows, key=sortKey),
+                    header=("UID", "Short Name", "Full Name")
+                ))
 
-        return "\n".join(result)
+            #
+            # Proxy for...
+            #
 
+            # FIXME: This logic should be in the DirectoryRecord.
 
+            def meAndMyGroups(record=self.record, groups=set((self.record,))):
+                for group in record.groups():
+                    groups.add(group)
+                    meAndMyGroups(group, groups)
+                return groups
+                
+            # FIXME: This module global is really gross.
+            from twistedcaldav.directory.calendaruserproxy import ProxyDBService
+
+            rows = []
+            proxyInfoSeen = set()
+            for record in meAndMyGroups():
+                proxyUIDs = (yield ProxyDBService.getMemberships(record.uid))
+
+                for proxyUID in proxyUIDs:
+                    # These are of the form: F153A05B-FF27-4B6C-BD6D-D1239D0082B0#calendar-proxy-read
+                    # I don't know how to get DirectoryRecord objects for the proxyUID here, so, let's cheat for now.
+                    proxyUID, proxyType = proxyUID.split("#")
+                    if (proxyUID, proxyType) not in proxyInfoSeen:
+                        proxyRecord = self.service.directory.recordWithUID(proxyUID)
+                        rows.append((proxyUID, proxyRecord.recordType, proxyRecord.shortNames[0], proxyRecord.fullName, proxyType))
+                        proxyInfoSeen.add((proxyUID, proxyType))
+
+            if rows:
+                def sortKey(row):
+                    return (row[1], row[2], row[4])
+                result.append("Proxy Access:")
+                result.append(tableString(
+                    sorted(rows, key=sortKey),
+                    header=("UID", "Record Type", "Short Name", "Full Name", "Access")
+                ))
+
+        returnValue("\n".join(result))
+
+
 class CalendarHomeFolder(Folder):
     """
     Calendar home folder.
@@ -519,7 +566,7 @@
         rows = []
 
         rows.append(("UID", self.uid))
-        rows.append(("Type", self.componentType))
+        rows.append(("Component Type", self.componentType))
         rows.append(("Summary", self.summary))
         
         organizer = self.mainComponent.getProperty("ORGANIZER")

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/webadmin/resource.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/webadmin/resource.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/webadmin/resource.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -43,7 +43,7 @@
 from zope.interface.declarations import implements
 from twext.web2.stream import MemoryStream
 from twext.web2.http import HTTPError
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 
 from twisted.web.iweb import ITemplateLoader
 from twisted.web.template import (

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/webadmin/test/test_resource.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/webadmin/test/test_resource.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/webadmin/test/test_resource.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -33,12 +33,12 @@
 from twisted.internet.defer import returnValue
 from calendarserver.webadmin.resource import WebAdminResource
 
-from twext.web2.dav.element.rfc3744 import GroupMemberSet
-from twext.web2.dav.element.rfc2518 import DisplayName
+from txdav.xml.rfc3744 import GroupMemberSet
+from txdav.xml.rfc2518 import DisplayName
 
 from twext.web2.http import HTTPError
 from twext.web2.responsecode import CONFLICT
-from twext.web2.dav.element.rfc2518 import HRef
+from txdav.xml.rfc2518 import HRef
 from twistedcaldav.directory.directory import DirectoryRecord
 
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/webcal/resource.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/webcal/resource.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/calendarserver/webcal/resource.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -32,7 +32,7 @@
 from twext.web2.http import Response
 from twext.web2.http_headers import MimeType
 from twext.web2.stream import MemoryStream
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.resource import TwistedACLInheritable
 
 from twistedcaldav.config import config

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/contrib/migration/calendarmigrator.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/contrib/migration/calendarmigrator.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/contrib/migration/calendarmigrator.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -42,7 +42,14 @@
 NEW_CONFIG_DIR = "Library/Server/" + NEW_SERVER_DIR + "/Config"
 LOG_DIR = "var/log/caldavd"
 DITTO = "/usr/bin/ditto"
+RESOURCE_MIGRATION_TRIGGER = "trigger_resource_migration"
 
+# For looking up previous run state
+CALDAV_LAUNCHD_KEY = "org.calendarserver.calendarserver"
+CARDDAV_LAUNCHD_KEY = "org.addressbookserver.addressbookserver"
+LAUNCHD_OVERRIDES = "var/db/launchd.db/com.apple.launchd/overrides.plist"
+LAUNCHD_PREFS_DIR = "System/Library/LaunchDaemons"
+SERVER_ADMIN = "%s/usr/sbin/serveradmin" % (SERVER_APP_ROOT,)
 
 # Processed by mergePlist
 specialKeys = """
@@ -108,6 +115,8 @@
 
         if os.path.exists(options.sourceRoot):
 
+            enableCalDAV, enableCardDAV = examineRunState(options)
+
             # Pull values out of previous plists
             (
                 oldServerRootValue,
@@ -143,6 +152,8 @@
                 options,
                 newServerRootValue,
                 newDataRootValue,
+                enableCalDAV,
+                enableCardDAV
             )
 
             # Create log directory
@@ -155,15 +166,121 @@
             # Set ownership
             os.chown(logDir, uid, gid)
 
+            # Trigger migration of locations and resources from OD
+            triggerResourceMigration(newServerRoot)
 
+            setRunState(options, enableCalDAV, enableCardDAV)
+
     else:
         log("ERROR: --sourceRoot and --sourceVersion must be specified")
         sys.exit(1)
 
 
+def examineRunState(options):
+    """
+    Try to determine whether the CalDAV and CardDAV services were running in
+    previous system.
 
-def migrateConfiguration(options, newServerRootValue, newDataRootValue):
+    @return: a tuple of booleans: whether CalDAV was enabled, and whether
+    CardDAV was enabled
     """
+
+    enableCalDAV = None
+    enableCardDAV = None
+
+    try:
+        disabled = isServiceDisabled(options.sourceRoot, CALDAV_LAUNCHD_KEY)
+        enableCalDAV = not disabled
+        log("Calendar service '%s' was previously %s" %
+            (CALDAV_LAUNCHD_KEY, "disabled" if disabled else "enabled"))
+    except ServiceStateError, e:
+        log("Couldn't determine previous state of calendar service '%s': %s" %
+            (CALDAV_LAUNCHD_KEY, e))
+
+    try:
+        disabled = isServiceDisabled(options.sourceRoot, CARDDAV_LAUNCHD_KEY)
+        enableCardDAV = not disabled
+        log("Addressbook service '%s' was previously %s" %
+            (CARDDAV_LAUNCHD_KEY, "disabled" if disabled else "enabled"))
+    except ServiceStateError, e:
+        log("Couldn't determine previous state of addressbook service '%s': %s" %
+            (CARDDAV_LAUNCHD_KEY, e))
+
+    if enableCalDAV:
+        # Check previous plist in case previous system was Lion, since there
+        # is now only one launchd key for both services
+        oldCalDAVPlistPath = os.path.join(options.sourceRoot,
+            CALDAVD_CONFIG_DIR, CALDAVD_PLIST)
+        if os.path.exists(oldCalDAVPlistPath):
+            log("Examining previous caldavd.plist for EnableCalDAV and EnableCardDAV: %s" % (oldCalDAVPlistPath,))
+            oldCalDAVDPlist = readPlist(oldCalDAVPlistPath)
+            if "EnableCalDAV" in oldCalDAVDPlist:
+                enableCalDAV = oldCalDAVDPlist["EnableCalDAV"]
+                log("Based on caldavd.plist, setting EnableCalDAV to %s" % (enableCalDAV,))
+            if "EnableCardDAV" in oldCalDAVDPlist:
+                enableCardDAV = oldCalDAVDPlist["EnableCardDAV"]
+                log("Based on caldavd.plist, setting EnableCardDAV to %s" % (enableCardDAV,))
+
+    # A value of None means we weren't able to determine, so default to off
+    if enableCalDAV is None:
+        enableCalDAV = False
+    if enableCardDAV is None:
+        enableCardDAV = False
+
+    return (enableCalDAV, enableCardDAV)
+
+
+def setRunState(options, enableCalDAV, enableCardDAV):
+    """
+    Use serveradmin to launch the service if needed.
+    """
+
+    if enableCalDAV or enableCardDAV:
+        serviceName = "calendar" if enableCalDAV else "addressbook"
+        log("Starting service via serveradmin start %s" % (serviceName,))
+        ret = subprocess.call([SERVER_ADMIN, "start", serviceName])
+        log("serveradmin exited with %d" % (ret,))
+
+
+def isServiceDisabled(source, service):
+    """
+    Returns whether or not a service is disabled
+
+    @param source: System root to examine
+    @param service: launchd key representing service
+    @return: True if service is disabled, False if enabled
+    """
+
+    overridesPath = os.path.join(source, LAUNCHD_OVERRIDES)
+    if os.path.isfile(overridesPath):
+        overrides = readPlist(overridesPath)
+        try:
+            return overrides[service]['Disabled']
+        except KeyError:
+            # Key is not in the overrides.plist, continue on
+            pass
+
+    prefsPath = os.path.join(source, LAUNCHD_PREFS_DIR, "%s.plist" % service)
+    if os.path.isfile(prefsPath):
+        prefs = readPlist(prefsPath)
+        try:
+            return prefs['Disabled']
+        except KeyError:
+            return False
+
+    raise ServiceStateError("Neither %s nor %s exist" %
+        (overridesPath, prefsPath))
+
+
+class ServiceStateError(Exception):
+    """
+    Could not determine service state
+    """
+
+
+
+def migrateConfiguration(options, newServerRootValue, newDataRootValue, enableCalDAV, enableCardDAV):
+    """
     Copy files/directories/symlinks from previous system's /etc/caldavd
     and /etc/carddavd
 
@@ -247,6 +364,10 @@
     newCalDAVDPlist["DocumentRoot"] = "Documents"
     newCalDAVDPlist["DataRoot"] = newDataRootValue
 
+    newCalDAVDPlist["EnableCalDAV"] = enableCalDAV
+    newCalDAVDPlist["EnableCardDAV"] = enableCardDAV
+
+
     log("Writing %s" % (newConfigFile,))
     writePlist(newCalDAVDPlist, newConfigFile)
 
@@ -278,6 +399,13 @@
             if key in ("requireComputerRecord",):
                 del combined["DirectoryService"]["params"][key]
 
+    # Disable XMPPNotifier now that we're directly talking to APNS
+    try:
+        if caldav["Notifications"]["Services"]["XMPPNotifier"]["Enabled"]:
+            caldav["Notifications"]["Services"]["XMPPNotifier"]["Enabled"] = False
+    except KeyError:
+        pass
+
     # Merge ports
     if not caldav.get("HTTPPort", 0):
         caldav["HTTPPort"] = 8008
@@ -321,7 +449,6 @@
     combined["RedirectHTTPToHTTPS"] = enableSSL
 
 
-
 def log(msg):
     try:
         timestamp = datetime.datetime.now().strftime("%b %d %H:%M:%S")
@@ -579,6 +706,22 @@
     )
 
 
+def triggerResourceMigration(newServerRoot):
+    """
+    Leave a file in the server root to act as a signal that the server
+    should migrate locations and resources from OD when it starts up.
+    """
+    triggerPath = os.path.join(newServerRoot, RESOURCE_MIGRATION_TRIGGER)
+    if not os.path.exists(newServerRoot):
+        log("New server root directory doesn't exist: %s" % (newServerRoot,))
+        return
+
+    if not os.path.exists(triggerPath):
+        # Create an empty trigger file
+        log("Creating resource migration trigger file: %s" % (triggerPath,))
+        open(triggerPath, "w").close()
+
+
 def relativize(parent, child):
     """
     If child is really a child of parent, make child relative to parent.

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/contrib/migration/calendarpromotion.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/contrib/migration/calendarpromotion.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/contrib/migration/calendarpromotion.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -14,10 +14,12 @@
 import shutil
 from pwd import getpwnam
 from grp import getgrnam
+from plistlib import readPlist, writePlist
 
 SRC_CONFIG_DIR = "/Applications/Server.app/Contents/ServerRoot/private/etc/caldavd"
 CALENDAR_SERVER_ROOT = "/Library/Server/Calendar and Contacts"
 DEST_CONFIG_DIR = "%s/Config" % (CALENDAR_SERVER_ROOT,)
+CALDAVD_PLIST = "caldavd.plist"
 USER_NAME = "calendar"
 GROUP_NAME = "calendar"
 LOG_DIR = "/var/log/caldavd"
@@ -34,6 +36,26 @@
         # Already exists
         pass
 
+    plistPath = os.path.join(DEST_CONFIG_DIR, CALDAVD_PLIST)
+    if os.path.exists(plistPath):
+        try:
+            plistData = readPlist(plistPath)
+
+            # Turn off services in case this is a re-promotion
+            plistData["EnableCalDAV"] = False
+            plistData["EnableCardDAV"] = False
+
+            # Disable XMPPNotifier now that we're directly talking to APNS
+            try:
+                if plistData["Notifications"]["Services"]["XMPPNotifier"]["Enabled"]:
+                    plistData["Notifications"]["Services"]["XMPPNotifier"]["Enabled"] = False
+            except KeyError:
+                pass
+
+            writePlist(plistData, plistPath)
+        except Exception, e:
+            print "Unable to disable services in %s: %s" % (plistPath, e)
+
     # Create log directory
     try:
         os.mkdir(LOG_DIR, 0755)

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/contrib/migration/test/test_migrator.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/contrib/migration/test/test_migrator.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/contrib/migration/test/test_migrator.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011 Apple Inc. All rights reserved.
+# Copyright (c) 2012 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.
@@ -407,6 +407,43 @@
         self.assertEquals(newCombined, expected)
 
 
+    def test_disableXMPPNotifier(self):
+
+        # Ensure XMPPNotifier is disabled
+
+        oldCalDAV = {
+            "Notifications": {
+                "Services" : {
+                    "XMPPNotifier" : {
+                        "Enabled" : True,
+                    },
+                },
+            },
+        }
+        oldCardDAV = { }
+        expected = {
+            "Notifications": {
+                "Services" : {
+                    "XMPPNotifier" : {
+                        "Enabled" : False,
+                    },
+                },
+            },
+            "BindHTTPPorts": [8008, 8800],
+            "BindSSLPorts": [8443, 8843],
+            "EnableSSL" : False,
+            "HTTPPort": 8008,
+            "RedirectHTTPToHTTPS": False,
+            "SSLAuthorityChain": "",
+            "SSLCertificate": "",
+            "SSLPort": 8443,
+            "SSLPrivateKey": "",
+        }
+        newCombined = { }
+        mergePlist(oldCalDAV, oldCardDAV, newCombined)
+        self.assertEquals(newCombined, expected)
+
+
     def test_examinePreviousSystem(self):
         """
         Set up a virtual system in various configurations, then ensure the

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/contrib/tools/protocolanalysis.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/contrib/tools/protocolanalysis.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/contrib/tools/protocolanalysis.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -909,76 +909,77 @@
                 others.add(segments[3])
 
 
-    def printAll(self, doTabs):
+    def printAll(self, doTabs, summary):
 
         self.printInfo(doTabs)
         
         print "Load Analysis"
-        self.printHourlyTotals(doTabs)
+        self.printHourlyTotals(doTabs, summary)
         
-        print "Client Analysis"
-        self.printClientTotals(doTabs)
-        
-        print "Protocol Analysis Count"
-        self.printHourlyByXXXDetails(self.hourlyByMethodCount, doTabs)
-        
-        print "Protocol Analysis Average Response Time (ms)"
-        self.printHourlyByXXXDetails(self.averagedHourlyByMethodTime, doTabs, showAverages=True)
-        
-        print "Status Code Analysis"
-        self.printHourlyByXXXDetails(self.hourlyByStatus, doTabs)
-        
-        print "Protocol Analysis by Status"
-        self.printXXXMethodDetails(self.statusByMethodCount, doTabs, False)
-        
-        print "Cache Analysis"
-        self.printHourlyCacheDetails(doTabs)
-        
-        if len(self.hourlyPropfindByResponseCount):
-            print "PROPFIND Calendar response count distribution"
-            self.printHourlyByXXXDetails(self.hourlyPropfindByResponseCount, doTabs)
-        
-        if len(self.averagedHourlyByRecipientCount):
-            print "Average Recipient Counts"
-            self.printHourlyByXXXDetails(self.averagedHourlyByRecipientCount, doTabs, showTotals=False)
+        if not summary:
+            print "Client Analysis"
+            self.printClientTotals(doTabs)
             
-        print "Queue Depth vs Response Time"
-        self.printQueueDepthResponseTime(doTabs)
-        
-        print "Instance Count Distribution"
-        self.printInstanceCount(doTabs)
+            print "Protocol Analysis Count"
+            self.printHourlyByXXXDetails(self.hourlyByMethodCount, doTabs)
+            
+            print "Protocol Analysis Average Response Time (ms)"
+            self.printHourlyByXXXDetails(self.averagedHourlyByMethodTime, doTabs, showAverages=True)
+            
+            print "Status Code Analysis"
+            self.printHourlyByXXXDetails(self.hourlyByStatus, doTabs)
+            
+            print "Protocol Analysis by Status"
+            self.printXXXMethodDetails(self.statusByMethodCount, doTabs, False)
+            
+            print "Cache Analysis"
+            self.printHourlyCacheDetails(doTabs)
+            
+            if len(self.hourlyPropfindByResponseCount):
+                print "PROPFIND Calendar response count distribution"
+                self.printHourlyByXXXDetails(self.hourlyPropfindByResponseCount, doTabs)
+            
+            if len(self.averagedHourlyByRecipientCount):
+                print "Average Recipient Counts"
+                self.printHourlyByXXXDetails(self.averagedHourlyByRecipientCount, doTabs, showTotals=False)
+                
+            print "Queue Depth vs Response Time"
+            self.printQueueDepthResponseTime(doTabs)
+            
+            print "Instance Count Distribution"
+            self.printInstanceCount(doTabs)
+    
+            print "Protocol Analysis by Client"
+            self.printXXXMethodDetails(self.clientIDByMethodCount, doTabs)
+            
+            if len(self.requestSizeByBucket):
+                print "Request size distribution"
+                self.printHourlyByXXXDetails(self.requestSizeByBucket, doTabs)
+            
+            if len(self.responseSizeByBucket):
+                print "Response size distribution (excluding GET Dropbox)"
+                self.printHourlyByXXXDetails(self.responseSizeByBucket, doTabs)
+            
+            if len(self.averageResponseCountByMethod):
+                print "Average response count by method"
+                self.printResponseCounts(doTabs)
+            
+            if len(self.requestTimeByBucket):
+                print "Response time distribution"
+                self.printHourlyByXXXDetails(self.requestTimeByBucket, doTabs)
+            
+            print "URI Counts"
+            self.printURICounts(doTabs)
+    
+            #print "User Interaction Counts"
+            #self.printUserInteractionCounts(doTabs)
+    
+            #print "User Weights (top 100)"
+            #self.printUserWeights(doTabs)
+    
+            #print "User Response times"
+            #self.printUserResponseTimes(doTabs)
 
-        print "Protocol Analysis by Client"
-        self.printXXXMethodDetails(self.clientIDByMethodCount, doTabs)
-        
-        if len(self.requestSizeByBucket):
-            print "Request size distribution"
-            self.printHourlyByXXXDetails(self.requestSizeByBucket, doTabs)
-        
-        if len(self.responseSizeByBucket):
-            print "Response size distribution (excluding GET Dropbox)"
-            self.printHourlyByXXXDetails(self.responseSizeByBucket, doTabs)
-        
-        if len(self.averageResponseCountByMethod):
-            print "Average response count by method"
-            self.printResponseCounts(doTabs)
-        
-        if len(self.requestTimeByBucket):
-            print "Response time distribution"
-            self.printHourlyByXXXDetails(self.requestTimeByBucket, doTabs)
-        
-        print "URI Counts"
-        self.printURICounts(doTabs)
-
-        #print "User Interaction Counts"
-        #self.printUserInteractionCounts(doTabs)
-
-        #print "User Weights (top 100)"
-        #self.printUserWeights(doTabs)
-
-        #print "User Response times"
-        #self.printUserResponseTimes(doTabs)
-
     def printInfo(self, doTabs):
         
         table = tables.Table()
@@ -1008,19 +1009,33 @@
         # Clip to select hour range
         return "%02d:%02d (%02d:%02d)" % (localhour, minute, utchour, minute,)
         
-    def printHourlyTotals(self, doTabs):
+    def printHourlyTotals(self, doTabs, summary):
         
         table = tables.Table()
-        table.addHeader(("Local (UTC)", "Total",    "Av. Requests", "Av. Queue", "Max. Queue", "Av. Response",))
-        table.addHeader(("",            "Requests", "Per Second",   "Depth",     "Depth (# queues)",      "Time(ms)",))
-        table.setDefaultColumnFormats((
-            tables.Table.ColumnFormat("%s", tables.Table.ColumnFormat.CENTER_JUSTIFY), 
-            tables.Table.ColumnFormat("%d", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
-            tables.Table.ColumnFormat("%.1f", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
-            tables.Table.ColumnFormat("%d", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
-            tables.Table.ColumnFormat("%d (%2d)", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
-            tables.Table.ColumnFormat("%.1f", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
-        ))
+        table.addHeader(
+            ("Local (UTC)", "Total",    "Av. Requests", "Av. Response",) if summary else
+            ("Local (UTC)", "Total",    "Av. Requests", "Av. Queue", "Max. Queue", "Av. Response",)
+        )
+        table.addHeader(
+            ("",            "Requests", "Per Second",   "Time(ms)",) if summary else
+            ("",            "Requests", "Per Second",   "Depth",     "Depth (# queues)",      "Time(ms)",)
+        )
+        table.setDefaultColumnFormats(
+            (
+                tables.Table.ColumnFormat("%s", tables.Table.ColumnFormat.CENTER_JUSTIFY), 
+                tables.Table.ColumnFormat("%d", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
+                tables.Table.ColumnFormat("%.1f", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
+                tables.Table.ColumnFormat("%.1f", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
+            ) if summary else
+            (
+                tables.Table.ColumnFormat("%s", tables.Table.ColumnFormat.CENTER_JUSTIFY), 
+                tables.Table.ColumnFormat("%d", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
+                tables.Table.ColumnFormat("%.1f", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
+                tables.Table.ColumnFormat("%d", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
+                tables.Table.ColumnFormat("%d (%2d)", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
+                tables.Table.ColumnFormat("%.1f", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
+            )
+        )
     
         totalRequests = 0
         totalDepth = 0
@@ -1034,34 +1049,58 @@
             countRequests, _ignore503, countDepth, maxDepth, countTime = value
             maxDepthAll = max(maxDepth.values()) if maxDepth.values() else 0
             maxDepthCount = list(maxDepth.values()).count(maxDepthAll)
-            table.addRow((
-                hour,
-                countRequests,
-                (1.0 * countRequests) / self.resolutionMinutes / 60,
-                safePercent(countDepth, countRequests, 1),
-                (maxDepthAll, maxDepthCount,),
-                safePercent(countTime, countRequests, 1.0),
-            ))
+            table.addRow(
+                (
+                    hour,
+                    countRequests,
+                    (1.0 * countRequests) / self.resolutionMinutes / 60,
+                    safePercent(countTime, countRequests, 1.0),
+                ) if summary else
+                (
+                    hour,
+                    countRequests,
+                    (1.0 * countRequests) / self.resolutionMinutes / 60,
+                    safePercent(countDepth, countRequests, 1),
+                    (maxDepthAll, maxDepthCount,),
+                    safePercent(countTime, countRequests, 1.0),
+                )
+            )
             totalRequests += countRequests
             totalDepth += countDepth
             totalMaxDepth = max(totalMaxDepth, maxDepthAll)
             totalTime += countTime
     
-        table.addFooter((
-            "Total:",
-            totalRequests,
-            (1.0 * totalRequests) / self.timeBucketCount / self.resolutionMinutes / 60,
-            safePercent(totalDepth, totalRequests, 1),
-            totalMaxDepth,
-            safePercent(totalTime, totalRequests, 1.0),
-        ), columnFormats=(
-            tables.Table.ColumnFormat("%s"), 
-            tables.Table.ColumnFormat("%d", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
-            tables.Table.ColumnFormat("%.1f", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
-            tables.Table.ColumnFormat("%d", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
-            tables.Table.ColumnFormat("%d     ", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
-            tables.Table.ColumnFormat("%.1f", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
-        ))
+        table.addFooter(
+            (
+                "Total:",
+                totalRequests,
+                (1.0 * totalRequests) / self.timeBucketCount / self.resolutionMinutes / 60,
+                safePercent(totalTime, totalRequests, 1.0),
+            ) if summary else
+            (
+                "Total:",
+                totalRequests,
+                (1.0 * totalRequests) / self.timeBucketCount / self.resolutionMinutes / 60,
+                safePercent(totalDepth, totalRequests, 1),
+                totalMaxDepth,
+                safePercent(totalTime, totalRequests, 1.0),
+            ),
+            columnFormats=
+            (
+                tables.Table.ColumnFormat("%s"), 
+                tables.Table.ColumnFormat("%d", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
+                tables.Table.ColumnFormat("%.1f", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
+                tables.Table.ColumnFormat("%.1f", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
+            ) if summary else
+            (
+                tables.Table.ColumnFormat("%s"), 
+                tables.Table.ColumnFormat("%d", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
+                tables.Table.ColumnFormat("%.1f", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
+                tables.Table.ColumnFormat("%d", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
+                tables.Table.ColumnFormat("%d     ", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
+                tables.Table.ColumnFormat("%.1f", tables.Table.ColumnFormat.RIGHT_JUSTIFY),
+            )
+        )
     
         table.printTabDelimitedData() if doTabs else table.printTable()
         print ""
@@ -1790,6 +1829,7 @@
     --user        User to analyze
     --client      Client to analyze
     --tabs        Generate tab-delimited output rather than table
+    --summary     Print the Load Analysis summary only
     --repeat      Parse the file and then allow more data to be parsed
     --diff        Compare two or more files
 
@@ -1814,6 +1854,7 @@
         diffMode = False
         doTabDelimited = False
         repeat = False
+        summary = False
         resolution = 60
         startHour = 0
         endHour = startHour + 23
@@ -1821,7 +1862,7 @@
         filterByUser = None
         filterByClient = None
 
-        options, args = getopt.getopt(sys.argv[1:], "h", ["diff", "hours=", "utcoffset=", "resolution=", "repeat", "tabs", "user=", "client=", ])
+        options, args = getopt.getopt(sys.argv[1:], "h", ["diff", "hours=", "utcoffset=", "resolution=", "repeat", "summary", "tabs", "user=", "client=", ])
 
         for option, value in options:
             if option == "-h":
@@ -1830,6 +1871,8 @@
                 diffMode = True
             elif option == "--repeat":
                 repeat = True
+            elif option == "--summary":
+                summary = True
             elif option == "--tabs":
                 doTabDelimited = True
             elif option == "--hours":
@@ -1885,9 +1928,9 @@
             ctr[-1] = analyzers[-1].analyzeLogFile(arg, ctr[-1])
 
         if diffMode and len(analyzers) > 1:
-            Differ(analyzers).printAll(doTabDelimited)
+            Differ(analyzers).printAll(doTabDelimited, summary)
         else:
-            analyzers[-1].printAll(doTabDelimited)
+            analyzers[-1].printAll(doTabDelimited, summary)
             
             if repeat:
                 while True:
@@ -1896,7 +1939,7 @@
                         break
                     print "\n\n\n"
                     analyzers[0].analyzeLogFile(arg, ctr[0])
-                    analyzers[0].printAll(doTabDelimited)
+                    analyzers[0].printAll(doTabDelimited, summary)
                 
     except Exception, e:
         print traceback.print_exc()

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/doc/Extensions/caldav-notifications.txt
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/doc/Extensions/caldav-notifications.txt	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/doc/Extensions/caldav-notifications.txt	2012-03-22 00:41:39 UTC (rev 8921)
@@ -3,7 +3,7 @@
 
 Calendar Server Extension                                       C. Daboo
                                                               Apple Inc.
-                                                           March 6, 2012
+                                                          March 19, 2012
 
 
                   CalDAV: Calendar User Notifications
@@ -78,27 +78,27 @@
        5.2.1.  CS:quotastatus Element Definition  . . . . . . . . . .  9
      5.3.  Resource Changes Notification  . . . . . . . . . . . . . . 10
        5.3.1.  CS:resource-change Element Definition  . . . . . . . . 11
-       5.3.2.  CS:calendar-changes Element Definition . . . . . . . . 14
-         5.3.2.1.  Handling Recurrences in CS:calendar-changes  . . . 16
-       5.3.3.  CS:deleted-details Element Definition  . . . . . . . . 17
-       5.3.4.  CS:notify-changes Property . . . . . . . . . . . . . . 19
-   6.  Security Considerations  . . . . . . . . . . . . . . . . . . . 19
-   7.  IANA Considerations  . . . . . . . . . . . . . . . . . . . . . 20
-   8.  Acknowledgments  . . . . . . . . . . . . . . . . . . . . . . . 20
-   9.  References . . . . . . . . . . . . . . . . . . . . . . . . . . 20
-     9.1.  Normative References . . . . . . . . . . . . . . . . . . . 20
-     9.2.  Informative References . . . . . . . . . . . . . . . . . . 20
-   Appendix A.  Examples  . . . . . . . . . . . . . . . . . . . . . . 20
-     A.1.  Resource Created . . . . . . . . . . . . . . . . . . . . . 20
-     A.2.  Resource Updated - Property Change . . . . . . . . . . . . 21
-     A.3.  Resource Updated - Parameter Change  . . . . . . . . . . . 22
-     A.4.  Resource Updated - Multiple Instances Change . . . . . . . 22
-     A.5.  Resource Updated - Multiple User Change  . . . . . . . . . 23
-     A.6.  Resource Deleted . . . . . . . . . . . . . . . . . . . . . 24
-     A.7.  Collection Created . . . . . . . . . . . . . . . . . . . . 25
-     A.8.  Collection Updated . . . . . . . . . . . . . . . . . . . . 25
-     A.9.  Collection Deleted . . . . . . . . . . . . . . . . . . . . 26
-   Author's Address . . . . . . . . . . . . . . . . . . . . . . . . . 26
+       5.3.2.  CS:calendar-changes Element Definition . . . . . . . . 15
+         5.3.2.1.  Handling Recurrences in CS:calendar-changes  . . . 17
+       5.3.3.  CS:deleted-details Element Definition  . . . . . . . . 18
+       5.3.4.  CS:notify-changes Property . . . . . . . . . . . . . . 20
+   6.  Security Considerations  . . . . . . . . . . . . . . . . . . . 20
+   7.  IANA Considerations  . . . . . . . . . . . . . . . . . . . . . 21
+   8.  Acknowledgments  . . . . . . . . . . . . . . . . . . . . . . . 21
+   9.  References . . . . . . . . . . . . . . . . . . . . . . . . . . 21
+     9.1.  Normative References . . . . . . . . . . . . . . . . . . . 21
+     9.2.  Informative References . . . . . . . . . . . . . . . . . . 21
+   Appendix A.  Examples  . . . . . . . . . . . . . . . . . . . . . . 21
+     A.1.  Resource Created . . . . . . . . . . . . . . . . . . . . . 21
+     A.2.  Resource Updated - Property Change . . . . . . . . . . . . 22
+     A.3.  Resource Updated - Parameter Change  . . . . . . . . . . . 23
+     A.4.  Resource Updated - Multiple Instances Change . . . . . . . 23
+     A.5.  Resource Updated - Multiple User Change  . . . . . . . . . 24
+     A.6.  Resource Deleted . . . . . . . . . . . . . . . . . . . . . 25
+     A.7.  Collection Created . . . . . . . . . . . . . . . . . . . . 26
+     A.8.  Collection Updated . . . . . . . . . . . . . . . . . . . . 26
+     A.9.  Collection Deleted . . . . . . . . . . . . . . . . . . . . 27
+   Author's Address . . . . . . . . . . . . . . . . . . . . . . . . . 27
 
 
 
@@ -594,21 +594,21 @@
       collection.
 
       When used for a calendar object resource change, it can contain
-      CS:created, CS:updated, CS:deleted elements each of which
-      indicates a created, updated or deleted resource, respectively.
-      The DAV:href element within those three elements, contain the URI
-      of the changed resource, optional information about who changed
-      the resource and when that change was made (the CS:changed-by
-      element), and information specific to the nature of the change.
-      Servers SHOULD coalesce resource change notifications for the same
-      resource into a single notification resource.  Servers MAY
-      coalesce resource change notifications to multiple resources into
-      a single notification resource.  The CS:updated element optionally
+      one of the CS:created, or CS:deleted elements, or multiple CS:
+      updated elements, which indicate a created, deleted or updated
+      resource, respectively.  The DAV:href element within those
+      elements, contains the URI of the changed resource, optional
+      information about who changed the resource and when that change
+      was made (the CS:changed-by element), and information specific to
+      the nature of the change.  Servers SHOULD coalesce resource change
+      notifications for the same resource into a single notification
+      resource where possible.  The CS:updated element optionally
       contains CS:content and/or DAV:prop elements to indicate a change
       to the body of the resource or resource WebDAV properties,
       respectively.  The DAV:prop element MAY contain a list of property
       elements to indicate which properties changed.  The CS:updated
       element can also contain zero or more CS:calendar-changes elements
+      to list details of the changes.  If no CS:calendar-changes element
 
 
 
@@ -617,7 +617,6 @@
                         CalDAV User Notifications             March 2012
 
 
-      to list details of the changes.  If no CS:calendar-changes element
       is present, the specific details are not provided, and clients
       will need to assume that some set of changes occurred, but the
       server is unwilling to disclose the full details.  The CS:deleted
@@ -635,7 +634,46 @@
 
    Definition:
 
-   <!ELEMENT resource-change ((created*, updated*, deleted*) |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Daboo                                                          [Page 12]
+
+                        CalDAV User Notifications             March 2012
+
+
+   <!ELEMENT resource-change (created | updated+ | deleted |
                               collection-changes)>
      <!ELEMENT created (DAV:href, changed-by?, ANY)>
      <!ELEMENT updated (DAV:href, changed-by?, content?,
@@ -643,13 +681,15 @@
        <!ELEMENT content EMPTY>
      <!ELEMENT deleted (DAV:href, changed-by?, deleted-details)>
 
-     <!ELEMENT changed-by (first-name, last-name,
+     <!ELEMENT changed-by (common-name | (first-name, last-name),
                            dtstamp?, DAV:href)>
+       <!ELEMENT common-name CDATA>
        <!ELEMENT first-name CDATA>
        <!ELEMENT last-name CDATA>
      <!-- CS:changed-by indicates who made the change that caused the
           notification. CS:first-name and CS:last-name are the first
-          and last names of the corresponding user. CS:dtstamp is the
+          and last names of the corresponding user. or the
+          CS:common-name is the overall display name. CS:dtstamp is the
           time in UTC when the change was made. The DAV:href element
           is the principal URI or email address of the user who made
           the change. -->
@@ -665,22 +705,30 @@
        <!ELEMENT child-deleted CDATA>
        <!-- Each of the three elements above MUST contain a positive,
             non-zero integer value indicate the total number of changes
+            being reported for the collection. -->
 
+   Example:  This is an example of the body of a notification resource
+      for changes where one resource has been created:
 
 
-Daboo                                                          [Page 12]
+
+
+
+
+
+
+
+
+
+
+
+
+
+Daboo                                                          [Page 13]
 
                         CalDAV User Notifications             March 2012
 
 
-            being reported for the collection. -->
-
-   Example:  This is an example of the body of a notification resource
-      for changes where one resource has been created, two updated, and
-      one deleted.  One of the updated resources elements contains
-      additional information indicating which recurrence instances in
-      the iCalendar data were changed:
-
    <?xml version="1.0" encoding="UTF-8"?>
    <CS:notification xmlns:D="DAV:"
                     xmlns:CS="http://calendarserver.org/ns/">
@@ -689,11 +737,24 @@
        <CS:created>
          <D:href>http://example.com/cyrus/calendar/new.ics</D:href>
          <CS:changed-by>
-           <CS:first-name>Cyrus</CS:first-name>
-           <CS:last-name>Daboo</CS:last-name>
+           <CS:common-name>Cyrus Daboo</CS:common-name>
            <D:href>/principals/cyrusdaboo</D:href>
          </CS:changed-by>
        </CS:created>
+     </CS:resource-change>
+   </CS:notification>
+
+   Example:  This is an example of the body of a notification resource
+      for changes where a resource has been updated twice.  One of the
+      updated resources elements contains additional information
+      indicating which recurrence instances in the iCalendar data were
+      changed:
+
+   <?xml version="1.0" encoding="UTF-8"?>
+   <CS:notification xmlns:D="DAV:"
+                    xmlns:CS="http://calendarserver.org/ns/">
+     <CS:dtstamp>2011-12-09T11:51:14-05:00</CS:dtstamp>
+     <CS:resource-change>
        <CS:updated>
          <D:href>http://example.com/cyrus/calendar/event.ics</D:href>
          <CS:changed-by>
@@ -703,13 +764,35 @@
          </CS:changed-by>
        </CS:updated>
        <CS:updated>
-         <D:href>http://example.com/cyrus/calendar/todo.ics</D:href>
+         <D:href>http://example.com/cyrus/calendar/event.ics</D:href>
          <CS:changed-by>
            <CS:first-name>Eleanor</CS:first-name>
            <CS:last-name>Daboo</CS:last-name>
            <D:href>mailto:eleanor at example.com</D:href>
          </CS:changed-by>
        </CS:updated>
+     </CS:resource-change>
+   </CS:notification>
+
+
+
+
+
+
+
+Daboo                                                          [Page 14]
+
+                        CalDAV User Notifications             March 2012
+
+
+   Example:  This is an example of the body of a notification resource
+      for changes where one resource has been deleted:
+
+   <?xml version="1.0" encoding="UTF-8"?>
+   <CS:notification xmlns:D="DAV:"
+                    xmlns:CS="http://calendarserver.org/ns/">
+     <CS:dtstamp>2011-12-09T11:51:14-05:00</CS:dtstamp>
+     <CS:resource-change>
        <CS:deleted>
          <D:href>http://example.com/cyrus/calendar/old.ics</D:href>
          <CS:changed-by>
@@ -721,15 +804,7 @@
      </CS:resource-change>
    </CS:notification>
 
-
-
-
-Daboo                                                          [Page 13]
-
-                        CalDAV User Notifications             March 2012
-
-
-   Example:  This example is the same as the previous one, except that
+   Example:  This example is the same as the previous three, except that
       all the individual resource changes have been coalesced into a
       single notification about changes to the parent calendar
       collection:
@@ -758,6 +833,14 @@
       have changed, or provides details of deleted calendar object
       resources.
 
+
+
+
+Daboo                                                          [Page 15]
+
+                        CalDAV User Notifications             March 2012
+
+
    Description:  This XML element is used in a CS:updated element to
       describe how a calendar object resource changed, or in a CS:
       deleted element to provide details of a deleted resource.  It can
@@ -769,22 +852,6 @@
 
    Definition:
 
-
-
-
-
-
-
-
-
-
-
-
-Daboo                                                          [Page 14]
-
-                        CalDAV User Notifications             March 2012
-
-
    <!ELEMENT calendar-changes (recurrence+) >
 
      <!ELEMENT recurrence
@@ -820,6 +887,16 @@
       the master component in a recurring component, was changed and
       that the change was to the "SUMMARY" iCalendar property.
 
+
+
+
+
+
+Daboo                                                          [Page 16]
+
+                        CalDAV User Notifications             March 2012
+
+
    <CS:calendar-changes xmlns:CS="http://calendarserver.org/ns/">
      <CS:recurrence>
        <CS:master/>
@@ -833,14 +910,6 @@
       component was changed and that the change was to the "DTSTART"
       iCalendar property.
 
-
-
-
-Daboo                                                          [Page 15]
-
-                        CalDAV User Notifications             March 2012
-
-
    <CS:calendar-changes xmlns:CS="http://calendarserver.org/ns/">
      <CS:recurrence>
        <CS:recurrenceid>20111215T160000Z</CS:recurrenceid>
@@ -874,6 +943,16 @@
       the added component.  A CS:changes element will be present.  There
       will not be any CS:added or CS:removed elements.
 
+
+
+
+
+
+Daboo                                                          [Page 17]
+
+                        CalDAV User Notifications             March 2012
+
+
    Master exists, override removed  In this case, a CS:recurrence
       element will be present, containing a CS:recurrence-id element
       with a value equal to the RECURRENCE-ID property value (in UTC) of
@@ -889,14 +968,6 @@
       will not be any CS:added or CS:changes element.  There will also
       be a CS:master element present, with an appropriate CS:changes
       element, likely covering a change to "RRULE" or addition of
-
-
-
-Daboo                                                          [Page 16]
-
-                        CalDAV User Notifications             March 2012
-
-
       "EXDATE" properties.
 
    Master does not exist, override added  In this case, a CS:recurrence
@@ -930,29 +1001,19 @@
       describe useful information about a deleted resource or
       collection, so clients can provide a meaningful notification
       message to users.  This element has two variants: one for deletion
-      of a calendar object resource, the other for deletion of a
-      calendar collection.
 
-   Definition:
 
 
+Daboo                                                          [Page 18]
+
+                        CalDAV User Notifications             March 2012
 
 
+      of a calendar object resource, the other for deletion of a
+      calendar collection.
 
+   Definition:
 
-
-
-
-
-
-
-
-
-Daboo                                                          [Page 17]
-
-                        CalDAV User Notifications             March 2012
-
-
    <!ELEMENT deleted-details ((deleted-component,
                                deleted-summary,
                                deleted-next-instance?,
@@ -997,18 +1058,17 @@
      >20120505T120000</CS:deleted-next-instance>
    </CS:deleted-details>
 
-   Example:  This example indicates deletion of a calendar.
 
-   <CS:deleted-details xmlns:CS="http://calendarserver.org/ns/">
-     <CS:deleted-displayname>Holidays</CS:deleted-displayname>
 
-
-
-Daboo                                                          [Page 18]
+Daboo                                                          [Page 19]
 
                         CalDAV User Notifications             March 2012
 
 
+   Example:  This example indicates deletion of a calendar.
+
+   <CS:deleted-details xmlns:CS="http://calendarserver.org/ns/">
+     <CS:deleted-displayname>Holidays</CS:deleted-displayname>
    </CS:deleted-details>
 
 5.3.4.  CS:notify-changes Property
@@ -1054,17 +1114,16 @@
    limits are placed on the number and frequency of such user generated
    notifications.
 
-   TBD: More?
 
 
+Daboo                                                          [Page 20]
+
+                        CalDAV User Notifications             March 2012
 
 
+   TBD: More?
 
-Daboo                                                          [Page 19]
-
-                        CalDAV User Notifications             March 2012
 
-
 7.  IANA Considerations
 
    This document does not require any actions on the part of IANA.
@@ -1113,10 +1172,7 @@
 
 
 
-
-
-
-Daboo                                                          [Page 20]
+Daboo                                                          [Page 21]
 
                         CalDAV User Notifications             March 2012
 
@@ -1172,7 +1228,7 @@
 
 
 
-Daboo                                                          [Page 21]
+Daboo                                                          [Page 22]
 
                         CalDAV User Notifications             March 2012
 
@@ -1228,7 +1284,7 @@
 
 
 
-Daboo                                                          [Page 22]
+Daboo                                                          [Page 23]
 
                         CalDAV User Notifications             March 2012
 
@@ -1284,7 +1340,7 @@
 
 
 
-Daboo                                                          [Page 23]
+Daboo                                                          [Page 24]
 
                         CalDAV User Notifications             March 2012
 
@@ -1340,7 +1396,7 @@
 
 
 
-Daboo                                                          [Page 24]
+Daboo                                                          [Page 25]
 
                         CalDAV User Notifications             March 2012
 
@@ -1396,7 +1452,7 @@
 
 
 
-Daboo                                                          [Page 25]
+Daboo                                                          [Page 26]
 
                         CalDAV User Notifications             March 2012
 
@@ -1452,7 +1508,7 @@
 
 
 
-Daboo                                                          [Page 26]
+Daboo                                                          [Page 27]
 
                         CalDAV User Notifications             March 2012
 
@@ -1508,5 +1564,5 @@
 
 
 
-Daboo                                                          [Page 27]
+Daboo                                                          [Page 28]
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/doc/Extensions/caldav-notifications.xml
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/doc/Extensions/caldav-notifications.xml	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/doc/Extensions/caldav-notifications.xml	2012-03-22 00:41:39 UTC (rev 8921)
@@ -318,12 +318,12 @@
                         <t hangText="Namespace:">http://calendarserver.org/ns/</t>
                         <t hangText="Purpose:">Indicates that resources have been created, updated or deleted.</t>
                         <t hangText="Description:">This XML element is used in a CS:notification element to describe a resource change notification. It can describe a change directly to a calendar object resource or to a calendar collection.</t>
-                        <t>When used for a calendar object resource change, it can contain CS:created, CS:updated, CS:deleted elements each of which indicates a created, updated or deleted resource, respectively. The DAV:href element within those three elements, contain the URI of the changed resource, optional information about who changed the resource and when that change was made (the CS:changed-by element), and information specific to the nature of the change. Servers SHOULD coalesce resource change notifications for the same resource into a single notification resource. Servers MAY coalesce resource change notifications to multiple resources into a single notification resource. The CS:updated element optionally contains CS:content and/or DAV:prop elements to indicate a change to the body of the resource or resource WebDAV properties, respectively. The DAV:prop element MAY contain a list of property elements to indicate which properties changed. The CS:updated element can also contain zero or more CS:calendar-changes elements to list details of the changes. If no CS:calendar-changes element is present, the specific details are not provided, and clients will need to assume that some set of changes occurred, but the server is unwilling to disclose the full details. The CS:deleted element can also contain zero or more CS:deleted-details elements to list details of the deleted resource.</t>
+                        <t>When used for a calendar object resource change, it can contain one of the CS:created, or CS:deleted elements, or multiple CS:updated elements, which indicate a created, deleted or updated resource, respectively. The DAV:href element within those elements, contains the URI of the changed resource, optional information about who changed the resource and when that change was made (the CS:changed-by element), and information specific to the nature of the change. Servers SHOULD coalesce resource change notifications for the same resource into a single notification resource where possible. The CS:updated element optionally contains CS:content and/or DAV:prop elements to indicate a change to the body of the resource or resource WebDAV properties, respectively. The DAV:prop element MAY contain a list of property elements to indicate which properties changed. The CS:updated element can also contain zero or more CS:calendar-changes elements to list details of the changes. If no CS:calendar-changes element is present, the specific details are not provided, and clients will need to assume that some set of changes occurred, but the server is unwilling to disclose the full details. The CS:deleted element can also contain zero or more CS:deleted-details elements to list details of the deleted resource.</t>
                         <t>When used for a calendar collection change, it can contain a CS:collection-changes element. The DAV:href element within that element, contains the URI of the changed calendar collection. The DAV:prop element indicates a change to WebDAV properties on the calendar collection resource. The CS:child-created, CS:child-updated, and CS:child-deleted elements each contain a positive integer value indicating how many child resources were added, updated or deleted in the collection, respectively.</t>
                         <t hangText="Definition:">
                           <figure>
                             <artwork><![CDATA[
-<!ELEMENT resource-change ((created*, updated*, deleted*) |
+<!ELEMENT resource-change (created | updated+ | deleted |
                            collection-changes)>
   <!ELEMENT created (DAV:href, changed-by?, ANY)>
   <!ELEMENT updated (DAV:href, changed-by?, content?,
@@ -331,13 +331,15 @@
     <!ELEMENT content EMPTY>
   <!ELEMENT deleted (DAV:href, changed-by?, deleted-details)>
 
-  <!ELEMENT changed-by (first-name, last-name,
+  <!ELEMENT changed-by (common-name | (first-name, last-name),
                         dtstamp?, DAV:href)>
+    <!ELEMENT common-name CDATA>
     <!ELEMENT first-name CDATA>
     <!ELEMENT last-name CDATA>
   <!-- CS:changed-by indicates who made the change that caused the
        notification. CS:first-name and CS:last-name are the first
-       and last names of the corresponding user. CS:dtstamp is the
+       and last names of the corresponding user. or the
+       CS:common-name is the overall display name. CS:dtstamp is the
        time in UTC when the change was made. The DAV:href element
        is the principal URI or email address of the user who made
        the change. -->
@@ -356,7 +358,7 @@
          being reported for the collection. -->]]></artwork>
                           </figure>
                         </t>
-                        <t hangText="Example:">This is an example of the body of a notification resource for changes where one resource has been created, two updated, and one deleted. One of the updated resources elements contains additional information indicating which recurrence instances in the iCalendar data were changed:
+                        <t hangText="Example:">This is an example of the body of a notification resource for changes where one resource has been created:
                           <figure>
                             <artwork><![CDATA[
 <?xml version="1.0" encoding="UTF-8"?>
@@ -367,11 +369,22 @@
     <CS:created>
       <D:href>http://example.com/cyrus/calendar/new.ics</D:href>
       <CS:changed-by>
-        <CS:first-name>Cyrus</CS:first-name>
-        <CS:last-name>Daboo</CS:last-name>
+        <CS:common-name>Cyrus Daboo</CS:common-name>
         <D:href>/principals/cyrusdaboo</D:href>
       </CS:changed-by>
     </CS:created>
+  </CS:resource-change>
+</CS:notification>]]></artwork>
+                          </figure>
+                        </t>
+                        <t hangText="Example:">This is an example of the body of a notification resource for changes where a resource has been updated twice. One of the updated resources elements contains additional information indicating which recurrence instances in the iCalendar data were changed:
+                          <figure>
+                            <artwork><![CDATA[
+<?xml version="1.0" encoding="UTF-8"?>
+<CS:notification xmlns:D="DAV:"
+                 xmlns:CS="http://calendarserver.org/ns/">
+  <CS:dtstamp>2011-12-09T11:51:14-05:00</CS:dtstamp>
+  <CS:resource-change>
     <CS:updated>
       <D:href>http://example.com/cyrus/calendar/event.ics</D:href>
       <CS:changed-by>
@@ -381,13 +394,25 @@
       </CS:changed-by>
     </CS:updated>
     <CS:updated>
-      <D:href>http://example.com/cyrus/calendar/todo.ics</D:href>
+      <D:href>http://example.com/cyrus/calendar/event.ics</D:href>
       <CS:changed-by>
         <CS:first-name>Eleanor</CS:first-name>
         <CS:last-name>Daboo</CS:last-name>
         <D:href>mailto:eleanor at example.com</D:href>
       </CS:changed-by>
     </CS:updated>
+  </CS:resource-change>
+</CS:notification>]]></artwork>
+                          </figure>
+                        </t>
+                        <t hangText="Example:">This is an example of the body of a notification resource for changes where one resource has been deleted:
+                          <figure>
+                            <artwork><![CDATA[
+<?xml version="1.0" encoding="UTF-8"?>
+<CS:notification xmlns:D="DAV:"
+                 xmlns:CS="http://calendarserver.org/ns/">
+  <CS:dtstamp>2011-12-09T11:51:14-05:00</CS:dtstamp>
+  <CS:resource-change>
     <CS:deleted>
       <D:href>http://example.com/cyrus/calendar/old.ics</D:href>
       <CS:changed-by>
@@ -400,7 +425,7 @@
 </CS:notification>]]></artwork>
                           </figure>
                         </t>
-                        <t hangText="Example:">This example is the same as the previous one, except that all the individual resource changes have been coalesced into a single notification about changes to the parent calendar collection:
+                        <t hangText="Example:">This example is the same as the previous three, except that all the individual resource changes have been coalesced into a single notification about changes to the parent calendar collection:
                           <figure>
                             <artwork><![CDATA[
 <?xml version="1.0" encoding="UTF-8"?>

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/pyflakes
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/pyflakes	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/pyflakes	2012-03-22 00:41:39 UTC (rev 8921)
@@ -4,7 +4,7 @@
 set -u
 
 wd="$(cd "$(dirname "$0")" && pwd)";
-flakes="$(cd "${wd}/../pyflakes-0.4.0" && pwd)";
+flakes="$(cd "${wd}/../pyflakes-0.5.0" && pwd)";
 
 export PYTHONPATH="${flakes}:${PYTHONPATH:-}";
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/support/build.sh
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/support/build.sh	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/support/build.sh	2012-03-22 00:41:39 UTC (rev 8921)
@@ -672,12 +672,6 @@
     "Zope Interface" "zope.interface" "${zi}" \
     "http://www.zope.org/Products/ZopeInterface/${zv}/${zi}.tar.gz";
 
-  local pv="0.8.4";
-  local px="PyXML-${pv}";
-  py_dependency -v "${pv}" -m "1f7655050cebbb664db976405fdba209" \
-    "PyXML" "xml.dom.ext" "${px}" \
-    "http://${sf}/project/pyxml/pyxml/${pv}/${px}.tar.gz";
-
   local po="pyOpenSSL-0.13";
   py_dependency -v 0.13 -m "767bca18a71178ca353dff9e10941929" \
     "PyOpenSSL" "OpenSSL" "${po}" \

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/__init__.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/__init__.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -51,6 +51,3 @@
     "util",
     "xattrprops",
 ]
-
-from twext.web2.dav import davxml
-

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/auth.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/auth.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/auth.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -1,9 +1,24 @@
-from zope.interface import implements, Interface
-from twisted.internet import defer
-from twisted.cred import checkers, error, portal
-from twext.web2.resource import WrapperResource
-from twext.web2.dav import davxml
-from twext.web2.dav.davxml import twisted_private_namespace
+##
+# Copyright (c) 2005-2012 Apple Computer, Inc. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+##
 
 __all__ = [
     "IPrincipal",
@@ -13,6 +28,14 @@
     "AuthenticationWrapper",
 ]
 
+from zope.interface import implements, Interface
+from twisted.internet import defer
+from twisted.cred import checkers, error, portal
+from twext.web2.resource import WrapperResource
+from txdav.xml.element import twisted_private_namespace, registerElement
+from txdav.xml.element import WebDAVTextElement, Principal, HRef
+
+
 class AuthenticationWrapper(WrapperResource):
     def __init__(self, resource, portal, credentialFactories, loginInterfaces):
         """
@@ -47,7 +70,7 @@
 
     def requestAvatar(self, avatarId, mind, *interfaces):
         if IPrincipal in interfaces:
-            return IPrincipal, davxml.Principal(davxml.HRef(avatarId[0])), davxml.Principal(davxml.HRef(avatarId[1]))
+            return IPrincipal, Principal(HRef(avatarId[0])), Principal(HRef(avatarId[1]))
         
         raise NotImplementedError("Only IPrincipal interface is supported")
 
@@ -108,8 +131,8 @@
 # Utilities
 ##
 
-class TwistedPasswordProperty (davxml.WebDAVTextElement):
+class TwistedPasswordProperty (WebDAVTextElement):
     namespace = twisted_private_namespace
     name = "password"
 
-davxml.registerElement(TwistedPasswordProperty)
+registerElement(TwistedPasswordProperty)

Deleted: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/davxml.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/davxml.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/davxml.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -1,120 +0,0 @@
-
-##
-# Copyright (c) 2005-2010 Apple Computer, Inc. All rights reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-# 
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-# 
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
-# DRI: Wilfredo Sanchez, wsanchez at apple.com
-##
-
-"""
-WebDAV XML Support.
-
-This module provides XML utilities for use with WebDAV.
-
-This API is considered private to static.py and is therefore subject to
-change.
-
-See RFC 2518: http://www.ietf.org/rfc/rfc2518.txt (WebDAV)
-See RFC 3253: http://www.ietf.org/rfc/rfc3253.txt (WebDAV + Versioning)
-See RFC 3744: http://www.ietf.org/rfc/rfc3744.txt (WebDAV ACLs)
-"""
-
-#
-# Import all XML element definitions
-#
-
-from twext.web2.dav.element.base    import *
-from twext.web2.dav.element.parser  import *
-from twext.web2.dav.element.util    import *
-from twext.web2.dav.element.rfc2518 import *
-from twext.web2.dav.element.rfc3253 import *
-from twext.web2.dav.element.rfc3744 import *
-from twext.web2.dav.element.rfc4331 import *
-from twext.web2.dav.element.rfc5842 import *
-from twext.web2.dav.element.extensions import *
-
-#
-# Register all XML elements with the parser
-#
-
-from twext.web2.dav.element import base as b
-from twext.web2.dav.element import parser as p
-from twext.web2.dav.element import util as u
-from twext.web2.dav.element import rfc2518 as r1
-from twext.web2.dav.element import rfc3253 as r2
-from twext.web2.dav.element import rfc3744 as r3
-from twext.web2.dav.element import rfc4331 as r4
-from twext.web2.dav.element import rfc5842 as r5
-from twext.web2.dav.element import extensions as e
-
-__all__ = (
-    registerElements(b) +
-    registerElements(p) +
-    registerElements(u) +
-    registerElements(r1) +
-    registerElements(r2) +
-    registerElements(r3) +
-    registerElements(r4) +
-    registerElements(r5) +
-    registerElements(e) +
-    [
-        "sname2qname",
-        "qname2sname",
-    ]
-)
-
-
-def sname2qname(sname):
-    """
-    Convert an sname into a qname.
-
-    That is, parse a property name string (eg: C{"{DAV:}displayname"})
-    into a tuple (eg: C{("DAV:", "displayname")}).
-
-    @raise ValueError is input is not valid. Note, however, that this
-    function does not attempt to fully validate C{sname}.
-    """
-    def raiseIf(condition):
-        if condition:
-            raise ValueError("Invalid sname: %s" % (sname,))
-
-    raiseIf(not sname.startswith("{"))
-
-    try:
-        i = sname.index("}")
-    except ValueError:
-        raiseIf(True)
-
-    namespace = sname[1:i]
-    name = sname [i+1:]
-
-    raiseIf("{" in namespace or not name)
-
-    return namespace, name
-
-def qname2sname(qname):
-    """
-    Convert a qname into an sname.
-    """
-    try:
-        return "{%s}%s" % qname
-    except TypeError:
-        raise ValueError("Invalid qname: %r" % (qname,))
-

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/http.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/http.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/http.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -47,15 +47,15 @@
 from twext.web2.iweb import IResponse
 from twext.web2.http import Response, HTTPError, StatusResponse
 from twext.web2.http_headers import MimeType
-from twext.web2.dav import davxml
 from twext.web2.dav.util import joinURL
+from txdav.xml import element
 
 log = Logger()
 
 
 class ErrorResponse(Response):
     """
-    A L{Response} object which contains a status code and a L{davxml.Error}
+    A L{Response} object which contains a status code and a L{element.Error}
     element.
     Renders itself as a DAV:error XML document.
     """
@@ -65,7 +65,7 @@
     def __init__(self, code, error, description=None):
         """
         @param code: a response code.
-        @param error: an L{davxml.WebDAVElement} identifying the error, or a
+        @param error: an L{WebDAVElement} identifying the error, or a
             tuple C{(namespace, name)} with which to create an empty element
             denoting the error.  (The latter is useful in the case of
             preconditions ans postconditions, not all of which have defined
@@ -75,15 +75,15 @@
         """
         if type(error) is tuple:
             xml_namespace, xml_name = error
-            error = davxml.WebDAVUnknownElement()
+            error = element.WebDAVUnknownElement()
             error.namespace = xml_namespace
             error.name = xml_name
 
         self.description = description
         if self.description:
-            output = davxml.Error(error, davxml.ErrorDescription(self.description)).toxml()
+            output = element.Error(error, element.ErrorDescription(self.description)).toxml()
         else:
-            output = davxml.Error(error).toxml()
+            output = element.Error(error).toxml()
 
         Response.__init__(self, code=code, stream=output)
 
@@ -114,10 +114,10 @@
                 uri = joinURL(base_uri, subpath)
 
             for p in privileges:
-                denials.append(davxml.Resource(davxml.HRef(uri), 
-                                               davxml.Privilege(p)))
+                denials.append(element.Resource(element.HRef(uri), 
+                                               element.Privilege(p)))
 
-        super(NeedPrivilegesResponse, self).__init__(responsecode.FORBIDDEN, davxml.NeedPrivileges(*denials))
+        super(NeedPrivilegesResponse, self).__init__(responsecode.FORBIDDEN, element.NeedPrivileges(*denials))
 
 class MultiStatusResponse (Response):
     """
@@ -126,10 +126,10 @@
     """
     def __init__(self, xml_responses):
         """
-        @param xml_responses: an interable of davxml.Response objects.
+        @param xml_responses: an interable of element.Response objects.
         """
         Response.__init__(self, code=responsecode.MULTI_STATUS,
-                          stream=davxml.MultiStatus(*xml_responses).toxml())
+                          stream=element.MultiStatus(*xml_responses).toxml())
 
         self.headers.setHeader("content-type", MimeType("text", "xml"))
 
@@ -181,13 +181,13 @@
         uri = path[self.path_basename_len:]
 
         children = []
-        children.append(davxml.HRef(uri))
-        children.append(davxml.Status.fromResponseCode(code))
+        children.append(element.HRef(uri))
+        children.append(element.Status.fromResponseCode(code))
         if error is not None:
             children.append(error)
         if message is not None:
-            children.append(davxml.ResponseDescription(message))
-        self.responses.append(davxml.StatusResponse(*children))
+            children.append(element.ResponseDescription(message))
+        self.responses.append(element.StatusResponse(*children))
 
     def response(self):
         """
@@ -237,19 +237,19 @@
 
         if len(property.children) > 0:
             # Re-instantiate as empty element.
-            property = property.emptyCopy()
+            property = element.WebDAVUnknownElement.withName(property.namespace, property.name)
 
         if code > 400: # Error codes only
             log.err("Error during %s for %s: %s" % (self.method, property, message))
 
         children = []
-        children.append(davxml.PropertyContainer(property))
-        children.append(davxml.Status.fromResponseCode(code))
+        children.append(element.PropertyContainer(property))
+        children.append(element.Status.fromResponseCode(code))
         if error is not None:
             children.append(error)
         if message is not None:
-            children.append(davxml.ResponseDescription(message))
-        self.propstats.append(davxml.PropertyStatus(*children))
+            children.append(element.ResponseDescription(message))
+        self.propstats.append(element.PropertyStatus(*children))
 
     def error(self):
         """
@@ -260,32 +260,32 @@
             changed_status = False
             newchildren = []
             for child in propstat.children:
-                if isinstance(child, davxml.Status) and (child.code / 100 == 2):
+                if isinstance(child, element.Status) and (child.code / 100 == 2):
                     # Change the code
-                    newchildren.append(davxml.Status.fromResponseCode(responsecode.FAILED_DEPENDENCY))
+                    newchildren.append(element.Status.fromResponseCode(responsecode.FAILED_DEPENDENCY))
                     changed_status = True
-                elif changed_status and isinstance(child, davxml.ResponseDescription):
-                    newchildren.append(davxml.ResponseDescription(responsecode.RESPONSES[responsecode.FAILED_DEPENDENCY]))
+                elif changed_status and isinstance(child, element.ResponseDescription):
+                    newchildren.append(element.ResponseDescription(responsecode.RESPONSES[responsecode.FAILED_DEPENDENCY]))
                 else:
                     newchildren.append(child)
-            self.propstats[index] = davxml.PropertyStatus(*newchildren)
+            self.propstats[index] = element.PropertyStatus(*newchildren)
 
     def response(self):
         """
         Generate a response from the responses contained in the queue or, if
         there are no such responses, return the C{success_response} provided to
         L{__init__}.
-        @return: a L{davxml.PropertyStatusResponse}.
+        @return: a L{element.PropertyStatusResponse}.
         """
         if self.propstats:
-            return davxml.PropertyStatusResponse(
-                davxml.HRef(self.uri),
+            return element.PropertyStatusResponse(
+                element.HRef(self.uri),
                 *self.propstats
             )
         else:
-            return davxml.StatusResponse(
-                davxml.HRef(self.uri),
-                davxml.Status.fromResponseCode(self.success_response)
+            return element.StatusResponse(
+                element.HRef(self.uri),
+                element.Status.fromResponseCode(self.success_response)
             )
 
 ##
@@ -331,7 +331,7 @@
 
 def errorForFailure(failure):
     if failure.check(HTTPError) and isinstance(failure.value.response, ErrorResponse):
-        return davxml.Error(failure.value.response.error)
+        return element.Error(failure.value.response.error)
     else:
         return None
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/acl.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/acl.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/acl.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -34,7 +34,7 @@
 from twext.python.log import Logger
 from twext.web2 import responsecode
 from twext.web2.http import StatusResponse, HTTPError
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.http import ErrorResponse
 from twext.web2.dav.util import davXMLFromStream
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/copymove.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/copymove.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/copymove.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -36,7 +36,7 @@
 from twext.web2.dav.fileop import move
 from twext.web2.http import HTTPError, StatusResponse
 from twext.web2.filter.location import addLocation
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.idav import IDAVResource
 from twext.web2.dav.method import put_common
 from twext.web2.dav.util import parentForURL

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/delete.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/delete.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/delete.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -34,7 +34,7 @@
 from twext.python.log import Logger
 from twext.web2 import responsecode
 from twext.web2.http import HTTPError
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.method.delete_common import deleteResource
 from twext.web2.dav.util import parentForURL
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/get.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/get.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/get.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -31,7 +31,7 @@
 
 import twext
 
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.util import parentForURL
 
 def http_OPTIONS(self, request):

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/mkcol.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/mkcol.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/mkcol.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -34,7 +34,7 @@
 from twext.python.log import Logger
 from twext.web2 import responsecode
 from twext.web2.http import HTTPError, StatusResponse
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.fileop import mkcollection
 from twext.web2.dav.util import noDataFromStream, parentForURL
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/prop_common.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/prop_common.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/prop_common.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -13,8 +13,7 @@
 
 from twext.python.log import Logger
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
-from twext.web2.dav.element.base import WebDAVElement
+from txdav.xml import element
 from twext.web2.dav.http import statusForFailure
 from twext.web2.dav.method.propfind import propertyName
 
@@ -33,20 +32,20 @@
         for status in properties_by_status:
             properties = properties_by_status[status]
             if properties:
-                xml_status = davxml.Status.fromResponseCode(status)
-                xml_container = davxml.PropertyContainer(*properties)
-                xml_propstat = davxml.PropertyStatus(xml_container, xml_status)
+                xml_status = element.Status.fromResponseCode(status)
+                xml_container = element.PropertyContainer(*properties)
+                xml_propstat = element.PropertyStatus(xml_container, xml_status)
 
                 propstats.append(xml_propstat)
 
         if propstats:
-            responses.append(davxml.PropertyStatusResponse(href, *propstats))
+            responses.append(element.PropertyStatusResponse(href, *propstats))
 
     else:
         responses.append(
-            davxml.StatusResponse(
+            element.StatusResponse(
                 href,
-                davxml.Status.fromResponseCode(responsecode.OK),
+                element.Status.fromResponseCode(responsecode.OK),
             )
         )
 
@@ -77,7 +76,7 @@
     }
     
     for property in props:
-        if isinstance(property, WebDAVElement):
+        if isinstance(property, element.WebDAVElement):
             qname = property.qname()
         else:
             qname = property

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/propfind.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/propfind.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/propfind.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -39,7 +39,7 @@
 from twext.web2.http import HTTPError
 from twext.web2 import responsecode
 from twext.web2.http import StatusResponse
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.http import MultiStatusResponse, statusForFailure,\
     ErrorResponse
 from twext.web2.dav.util import normalizeURL, davXMLFromStream

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/proppatch.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/proppatch.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/proppatch.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -35,7 +35,7 @@
 from twext.python.log import Logger
 from twext.web2 import responsecode
 from twext.web2.http import HTTPError, StatusResponse
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.http import MultiStatusResponse, PropertyStatusResponseQueue
 from twext.web2.dav.util import davXMLFromStream
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/put.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/put.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/put.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -34,7 +34,7 @@
 from twext.python.log import Logger
 from twext.web2 import responsecode
 from twext.web2.http import HTTPError, StatusResponse
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.method import put_common
 from twext.web2.dav.util import parentForURL
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/put_common.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/put_common.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/put_common.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -28,8 +28,8 @@
 from twisted.python import failure, log
 from twext.python.filepath import CachingFilePath as FilePath
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
-from twext.web2.dav.element.base import dav_namespace
+from txdav.xml import element as davxml
+from txdav.xml.base import dav_namespace
 from twext.web2.dav.fileop import copy, delete, put
 from twext.web2.dav.http import ErrorResponse
 from twext.web2.dav.resource import TwistedGETContentMD5

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/report.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/report.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/report.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -40,10 +40,10 @@
 from twext.python.log import Logger
 from twext.web2 import responsecode
 from twext.web2.http import HTTPError, StatusResponse
-from twext.web2.dav import davxml
-from twext.web2.dav.element.parser import lookupElement
 from twext.web2.dav.http import ErrorResponse
 from twext.web2.dav.util import davXMLFromStream
+from txdav.xml import element as davxml
+from txdav.xml.element import lookupElement
 
 log = Logger()
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/report_acl_principal_prop_set.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/report_acl_principal_prop_set.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/report_acl_principal_prop_set.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -34,7 +34,7 @@
 from twext.python.log import Logger
 from twext.web2 import responsecode
 from twext.web2.http import HTTPError, StatusResponse
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.http import ErrorResponse
 from twext.web2.dav.http import MultiStatusResponse
 from twext.web2.dav.method import prop_common

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/report_expand.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/report_expand.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/report_expand.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -32,8 +32,8 @@
 
 from twext.python.log import Logger
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
-from twext.web2.dav.davxml import dav_namespace
+from txdav.xml import element
+from txdav.xml.element import dav_namespace
 from twext.web2.dav.http import statusForFailure, MultiStatusResponse
 from twext.web2.dav.method import prop_common
 from twext.web2.dav.method.propfind import propertyName
@@ -52,9 +52,9 @@
     TODO: for simplicity we will only support one level of expansion.
     """
     # Verify root element
-    if not isinstance(expand_property, davxml.ExpandProperty):
+    if not isinstance(expand_property, element.ExpandProperty):
         raise ValueError("%s expected as root element, not %s."
-                         % (davxml.ExpandProperty.sname(), expand_property.sname()))
+                         % (element.ExpandProperty.sname(), expand_property.sname()))
 
     # Only handle Depth: 0
     depth = request.headers.getHeader("depth", "0")
@@ -102,27 +102,27 @@
             prop = (yield self.readProperty(qname, request))
             
             # Form the PROPFIND-style DAV:prop element we need later
-            props_to_return = davxml.PropertyContainer(*properties[qname])
+            props_to_return = element.PropertyContainer(*properties[qname])
 
             # Now dereference any HRefs
             responses = []
             for href in prop.children:
-                if isinstance(href, davxml.HRef):
+                if isinstance(href, element.HRef):
                     
                     # Locate the Href resource and its parent
                     resource_uri = str(href)
                     child = (yield request.locateResource(resource_uri))
     
                     if not child or not child.exists():
-                        responses.append(davxml.StatusResponse(href, davxml.Status.fromResponseCode(responsecode.NOT_FOUND)))
+                        responses.append(element.StatusResponse(href, element.Status.fromResponseCode(responsecode.NOT_FOUND)))
                         continue
                     parent = (yield request.locateResource(parentForURL(resource_uri)))
     
                     # Check privileges on parent - must have at least DAV:read
                     try:
-                        yield parent.checkPrivileges(request, (davxml.Read(),))
+                        yield parent.checkPrivileges(request, (element.Read(),))
                     except AccessDeniedError:
-                        responses.append(davxml.StatusResponse(href, davxml.Status.fromResponseCode(responsecode.FORBIDDEN)))
+                        responses.append(element.StatusResponse(href, element.Status.fromResponseCode(responsecode.FORBIDDEN)))
                         continue
                     
                     # Cache the last parent's inherited aces for checkPrivileges optimization
@@ -135,9 +135,9 @@
 
                     # Check privileges - must have at least DAV:read
                     try:
-                        yield child.checkPrivileges(request, (davxml.Read(),), inherited_aces=filteredaces)
+                        yield child.checkPrivileges(request, (element.Read(),), inherited_aces=filteredaces)
                     except AccessDeniedError:
-                        responses.append(davxml.StatusResponse(href, davxml.Status.fromResponseCode(responsecode.FORBIDDEN)))
+                        responses.append(element.StatusResponse(href, element.Status.fromResponseCode(responsecode.FORBIDDEN)))
                         continue
             
                     # Now retrieve all the requested properties on the HRef resource
@@ -163,11 +163,11 @@
 
     # Build the overall response
     propstats = [
-        davxml.PropertyStatus(
-            davxml.PropertyContainer(*properties_by_status[status]),
-            davxml.Status.fromResponseCode(status)
+        element.PropertyStatus(
+            element.PropertyContainer(*properties_by_status[status]),
+            element.Status.fromResponseCode(status)
         )
         for status in properties_by_status if properties_by_status[status]
     ]
 
-    returnValue(MultiStatusResponse((davxml.PropertyStatusResponse(davxml.HRef(request.uri), *propstats),)))
+    returnValue(MultiStatusResponse((element.PropertyStatusResponse(element.HRef(request.uri), *propstats),)))

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/report_principal_match.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/report_principal_match.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/report_principal_match.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -35,8 +35,8 @@
 from twext.python.log import Logger
 from twext.web2 import responsecode
 from twext.web2.http import StatusResponse, HTTPError
-from twext.web2.dav import davxml
-from twext.web2.dav.davxml import dav_namespace
+from txdav.xml import element
+from txdav.xml.element import dav_namespace
 from twext.web2.dav.http import ErrorResponse, MultiStatusResponse
 from twext.web2.dav.method import prop_common
 from twext.web2.dav.method.report import NumberOfMatchesWithinLimits
@@ -51,9 +51,9 @@
     Generate a principal-match REPORT. (RFC 3744, section 9.3)
     """
     # Verify root element
-    if not isinstance(principal_match, davxml.PrincipalMatch):
+    if not isinstance(principal_match, element.PrincipalMatch):
         raise ValueError("%s expected as root element, not %s."
-                         % (davxml.PrincipalMatch.sname(), principal_match.sname()))
+                         % (element.PrincipalMatch.sname(), principal_match.sname()))
 
     # Only handle Depth: 0
     depth = request.headers.getHeader("depth", "0")
@@ -130,7 +130,7 @@
                         d = waitForDeferred(prop_common.responseForHref(
                             request,
                             responses,
-                            davxml.HRef.fromString(uri),
+                            element.HRef.fromString(uri),
                             principal,
                             propertiesForResource,
                             propElement
@@ -147,7 +147,7 @@
         
             children = []
             d = waitForDeferred(self.findChildren("infinity", request, lambda x, y: children.append((x,y)),
-                                                  privileges=(davxml.Read(),), inherited_aces=filteredaces))
+                                                  privileges=(element.Read(),), inherited_aces=filteredaces))
             yield d
             d.getResult()
 
@@ -159,7 +159,7 @@
                     prop = prop.getResult()
                     if prop: prop.removeWhitespaceNodes()
 
-                    if prop and len(prop.children) == 1 and isinstance(prop.children[0], davxml.HRef):
+                    if prop and len(prop.children) == 1 and isinstance(prop.children[0], element.HRef):
                         # Find principal associated with this property and test it
                         principal = waitForDeferred(request.locateResource(str(prop.children[0])))
                         yield principal
@@ -178,7 +178,7 @@
                                 d = waitForDeferred(prop_common.responseForHref(
                                     request,
                                     responses,
-                                    davxml.HRef.fromString(uri),
+                                    element.HRef.fromString(uri),
                                     child,
                                     propertiesForResource,
                                     propElement
@@ -194,7 +194,7 @@
         log.err("Too many matching components in principal-match report")
         raise HTTPError(ErrorResponse(
             responsecode.FORBIDDEN,
-            davxml.NumberOfMatchesWithinLimits()
+            element.NumberOfMatchesWithinLimits()
         ))
 
     yield MultiStatusResponse(responses)

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/report_principal_property_search.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/report_principal_property_search.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/report_principal_property_search.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -34,8 +34,9 @@
 from twext.python.log import Logger
 from twext.web2 import responsecode
 from twext.web2.http import HTTPError, StatusResponse
-from twext.web2.dav import davxml
-from twext.web2.dav.davxml import dav_namespace
+from txdav.xml.base import PCDATAElement
+from txdav.xml import element
+from txdav.xml.element import dav_namespace
 from twext.web2.dav.http import ErrorResponse, MultiStatusResponse
 from twext.web2.dav.method import prop_common
 from twext.web2.dav.method.report import NumberOfMatchesWithinLimits
@@ -51,9 +52,9 @@
     """
 
     # Verify root element
-    if not isinstance(principal_property_search, davxml.PrincipalPropertySearch):
+    if not isinstance(principal_property_search, element.PrincipalPropertySearch):
         raise ValueError("%s expected as root element, not %s."
-                         % (davxml.PrincipalPropertySearch.sname(), principal_property_search.sname()))
+                         % (element.PrincipalPropertySearch.sname(), principal_property_search.sname()))
 
     # Only handle Depth: 0
     depth = request.headers.getHeader("depth", "0")
@@ -73,9 +74,9 @@
         elif child.qname() == (dav_namespace, "apply-to-principal-collection-set"):
             applyTo = True
         elif child.qname() == (dav_namespace, "property-search"):
-            props = child.childOfType(davxml.PropertyContainer)
+            props = child.childOfType(element.PropertyContainer)
             props.removeWhitespaceNodes()
-            match = child.childOfType(davxml.Match)
+            match = child.childOfType(element.Match)
             propertySearches.append((props.children, str(match).lower()))
     
     def nodeMatch(node, match):
@@ -88,7 +89,7 @@
         """
         node.removeWhitespaceNodes()
         for child in node.children:
-            if isinstance(child, davxml.PCDATAElement):
+            if isinstance(child, PCDATAElement):
                 comp = str(child).lower()
                 if comp.find(match) != -1:
                     return True
@@ -152,7 +153,7 @@
 
             children = []
             d = waitForDeferred(resource.findChildren("infinity", request, lambda x, y: children.append((x,y)),
-                                                      privileges=(davxml.Read(),), inherited_aces=filteredaces))
+                                                      privileges=(element.Read(),), inherited_aces=filteredaces))
             yield d
             d.getResult()
 
@@ -170,7 +171,7 @@
                         d = waitForDeferred(prop_common.responseForHref(
                             request,
                             responses,
-                            davxml.HRef.fromString(uri),
+                            element.HRef.fromString(uri),
                             child,
                             propertiesForResource,
                             propElement
@@ -182,7 +183,7 @@
         log.err("Too many matching components in prinicpal-property-search report")
         raise HTTPError(ErrorResponse(
             responsecode.FORBIDDEN,
-            davxml.NumberOfMatchesWithinLimits()
+            element.NumberOfMatchesWithinLimits()
         ))
 
     yield MultiStatusResponse(responses)

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/report_principal_search_property_set.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/report_principal_search_property_set.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/method/report_principal_search_property_set.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -33,7 +33,7 @@
 
 from twext.python.log import Logger
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.http import HTTPError, Response, StatusResponse
 from twext.web2.stream import MemoryStream
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/resource.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/resource.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/resource.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -65,15 +65,18 @@
 from twext.web2.server import NoURLForResourceError
 from twext.web2.static import MetaDataMixin, StaticRenderMixin
 from twext.web2.auth.wrapper import UnauthorizedResponse
-from twext.web2.dav import davxml
-from twext.web2.dav.davxml import dav_namespace, lookupElement
-from twext.web2.dav.davxml import twisted_dav_namespace, twisted_private_namespace
 from twext.web2.dav.idav import IDAVResource, IDAVPrincipalResource, IDAVPrincipalCollectionResource
 from twext.web2.dav.http import NeedPrivilegesResponse
 from twext.web2.dav.noneprops import NonePropertyStore
 from twext.web2.dav.util import unimplemented, parentForURL, joinURL
 from twext.web2.dav.auth import PrincipalCredentials
+from txdav.xml import element
+from txdav.xml.element import WebDAVElement, WebDAVEmptyElement, WebDAVTextElement
+from txdav.xml.element import dav_namespace
+from txdav.xml.element import twisted_dav_namespace, twisted_private_namespace
+from txdav.xml.element import registerElement, lookupElement
 
+
 log = Logger()
 
 
@@ -173,8 +176,8 @@
         @return: a dict-like object from which one can read and to
             which one can write dead properties.  Keys are qname
             tuples (i.e. C{(namespace, name)}) as returned by
-            L{davxml.WebDAVElement.qname()} and values are
-            L{davxml.WebDAVElement} instances.
+            L{WebDAVElement.qname()} and values are
+            L{WebDAVElement} instances.
         """
         if not hasattr(self, "_dead_properties"):
             self._dead_properties = NonePropertyStore(self)
@@ -187,7 +190,7 @@
         if type(property) is tuple:
             qname = property
         else:
-            qname = property.qname()
+            qname = (property.namespace, property.name)
 
         if qname[0] == twisted_private_namespace:
             return succeed(False)
@@ -227,20 +230,20 @@
                     if self.deadProperties().contains(qname):
                         returnValue(self.deadProperties().get(qname))
                     if self.isCollection():
-                        returnValue(davxml.ResourceType.collection) #@UndefinedVariable
-                    returnValue(davxml.ResourceType.empty) #@UndefinedVariable
+                        returnValue(element.ResourceType.collection) #@UndefinedVariable
+                    returnValue(element.ResourceType.empty) #@UndefinedVariable
 
                 if name == "getetag":
                     etag = (yield self.etag())
                     if etag is None:
                         returnValue(None)
-                    returnValue(davxml.GETETag(etag.generate()))
+                    returnValue(element.GETETag(etag.generate()))
 
                 if name == "getcontenttype":
                     mimeType = self.contentType()
                     if mimeType is None:
                         returnValue(None)
-                    returnValue(davxml.GETContentType(generateContentType(mimeType)))
+                    returnValue(element.GETContentType(generateContentType(mimeType)))
 
                 if name == "getcontentlength":
                     length = self.contentLength()
@@ -248,43 +251,43 @@
                         # TODO: really we should "render" the resource and 
                         # determine its size from that but for now we just 
                         # return an empty element.
-                        returnValue(davxml.GETContentLength(""))
+                        returnValue(element.GETContentLength(""))
                     else:
-                        returnValue(davxml.GETContentLength(str(length)))
+                        returnValue(element.GETContentLength(str(length)))
 
                 if name == "getlastmodified":
                     lastModified = self.lastModified()
                     if lastModified is None:
                         returnValue(None)
-                    returnValue(davxml.GETLastModified.fromDate(lastModified))
+                    returnValue(element.GETLastModified.fromDate(lastModified))
 
                 if name == "creationdate":
                     creationDate = self.creationDate()
                     if creationDate is None:
                         returnValue(None)
-                    returnValue(davxml.CreationDate.fromDate(creationDate))
+                    returnValue(element.CreationDate.fromDate(creationDate))
 
                 if name == "displayname":
                     displayName = self.displayName()
                     if displayName is None:
                         returnValue(None)
-                    returnValue(davxml.DisplayName(displayName))
+                    returnValue(element.DisplayName(displayName))
 
                 if name == "supportedlock":
-                    returnValue(davxml.SupportedLock(
-                        davxml.LockEntry(
-                            davxml.LockScope.exclusive, #@UndefinedVariable
-                            davxml.LockType.write #@UndefinedVariable
+                    returnValue(element.SupportedLock(
+                        element.LockEntry(
+                            element.LockScope.exclusive, #@UndefinedVariable
+                            element.LockType.write #@UndefinedVariable
                         ),
-                        davxml.LockEntry(
-                            davxml.LockScope.shared, #@UndefinedVariable
-                            davxml.LockType.write #@UndefinedVariable
+                        element.LockEntry(
+                            element.LockScope.shared, #@UndefinedVariable
+                            element.LockType.write #@UndefinedVariable
                         ),
                     ))
 
                 if name == "supported-report-set":
-                    returnValue(davxml.SupportedReportSet(*[
-                        davxml.SupportedReport(report,)
+                    returnValue(element.SupportedReportSet(*[
+                        element.SupportedReport(report,)
                         for report in self.supportedReports()
                     ]))
 
@@ -292,14 +295,14 @@
                     returnValue((yield self.supportedPrivileges(request)))
 
                 if name == "acl-restrictions":
-                    returnValue(davxml.ACLRestrictions())
+                    returnValue(element.ACLRestrictions())
 
                 if name == "inherited-acl-set":
-                    returnValue(davxml.InheritedACLSet(*self.inheritedACLSet()))
+                    returnValue(element.InheritedACLSet(*self.inheritedACLSet()))
 
                 if name == "principal-collection-set":
-                    returnValue(davxml.PrincipalCollectionSet(*[
-                        davxml.HRef(
+                    returnValue(element.PrincipalCollectionSet(*[
+                        element.HRef(
                             principalCollection.principalCollectionURL()
                         )
                         for principalCollection in self.principalCollections()
@@ -322,9 +325,9 @@
                     @inlineCallbacks
                     def callback():
                         privs = yield self.currentPrivileges(request)
-                        returnValue(davxml.CurrentUserPrivilegeSet(*privs))
+                        returnValue(element.CurrentUserPrivilegeSet(*privs))
                     returnValue((yield ifAllowed(
-                        (davxml.ReadCurrentUserPrivilegeSet(),),
+                        (element.ReadCurrentUserPrivilegeSet(),),
                         callback
                     )))
 
@@ -333,14 +336,14 @@
                     def callback():
                         acl = yield self.accessControlList(request)
                         if acl is None:
-                            acl = davxml.ACL()
+                            acl = element.ACL()
                         returnValue(acl)
                     returnValue(
-                        (yield ifAllowed((davxml.ReadACL(),), callback))
+                        (yield ifAllowed((element.ReadACL(),), callback))
                     )
 
                 if name == "current-user-principal":
-                    returnValue(davxml.CurrentUserPrincipal(
+                    returnValue(element.CurrentUserPrincipal(
                         self.currentPrincipal(request).children[0]
                     ))
 
@@ -352,7 +355,7 @@
                             "Property %s does not exist." % (sname,)
                         ))
                     else:
-                        returnValue(davxml.QuotaAvailableBytes(str(qvalue[0])))
+                        returnValue(element.QuotaAvailableBytes(str(qvalue[0])))
 
                 if name == "quota-used-bytes":
                     qvalue = yield self.quota(request)
@@ -362,7 +365,7 @@
                             "Property %s does not exist." % (sname,)
                         ))
                     else:
-                        returnValue(davxml.QuotaUsedBytes(str(qvalue[1])))
+                        returnValue(element.QuotaUsedBytes(str(qvalue[1])))
 
             elif namespace == twisted_dav_namespace:
                 if name == "resource-class":
@@ -383,7 +386,7 @@
         """
         See L{IDAVResource.writeProperty}.
         """
-        assert isinstance(property, davxml.WebDAVElement), (
+        assert isinstance(property, WebDAVElement), (
             "Not a property: %r" % (property,)
         )
 
@@ -545,17 +548,17 @@
     # to override the values of some HTTP metadata.
     #
     def contentType(self):
-        if self.hasDeadProperty((davxml.dav_namespace, "getcontenttype")):
+        if self.hasDeadProperty((element.dav_namespace, "getcontenttype")):
             return self.readDeadProperty(
-                (davxml.dav_namespace, "getcontenttype")
+                (element.dav_namespace, "getcontenttype")
             ).mimeType()
         else:
             return super(DAVPropertyMixIn, self).contentType()
 
     def displayName(self):
-        if self.hasDeadProperty((davxml.dav_namespace, "displayname")):
+        if self.hasDeadProperty((element.dav_namespace, "displayname")):
             return str(self.readDeadProperty(
-                (davxml.dav_namespace, "displayname")
+                (element.dav_namespace, "displayname")
             ))
         else:
             return super(DAVPropertyMixIn, self).displayName()
@@ -806,7 +809,7 @@
         for ace in acl.children:
             for privilege in tuple(pending):
                 if not self.matchPrivilege(
-                    davxml.Privilege(privilege), ace.privileges, privyset
+                    element.Privilege(privilege), ace.privileges, privyset
                 ):
                     continue
 
@@ -861,7 +864,7 @@
 
         aces.extend(inherited_aces)
 
-        acl = davxml.ACL(*aces)
+        acl = element.ACL(*aces)
 
         return acl
     
@@ -873,10 +876,10 @@
         expand-property.
         """
         result = []
-        result.append(davxml.Report(davxml.ACLPrincipalPropSet(),))
-        result.append(davxml.Report(davxml.PrincipalMatch(),))
-        result.append(davxml.Report(davxml.PrincipalPropertySearch(),))
-        result.append(davxml.Report(davxml.ExpandProperty(),))
+        result.append(element.Report(element.ACLPrincipalPropSet(),))
+        result.append(element.Report(element.PrincipalMatch(),))
+        result.append(element.Report(element.PrincipalPropertySearch(),))
+        result.append(element.Report(element.ExpandProperty(),))
         return result
 
     ##
@@ -906,7 +909,7 @@
             def translateError(response):
                 return Failure(HTTPError(response))
 
-            if request.authnUser == davxml.Principal(davxml.Unauthenticated()):
+            if request.authnUser == element.Principal(element.Unauthenticated()):
                 return UnauthorizedResponse.makeResponse(
                     request.credentialFactories,
                     request.remoteAddr).addCallback(translateError)
@@ -932,7 +935,7 @@
         necessary authentication metadata.
 
         If the request was not thusly prepared, both C{authzUser} and
-        C{authnUser} will be L{davxml.Unauthenticated}.
+        C{authnUser} will be L{element.Unauthenticated}.
 
         @param request: the request which may contain authentication
             information and a reference to a portal to authenticate
@@ -948,8 +951,8 @@
         if not (hasattr(request, 'portal') and
                 hasattr(request, 'credentialFactories') and
                 hasattr(request, 'loginInterfaces')):
-            request.authnUser = davxml.Principal(davxml.Unauthenticated())
-            request.authzUser = davxml.Principal(davxml.Unauthenticated())
+            request.authnUser = element.Principal(element.Unauthenticated())
+            request.authzUser = element.Principal(element.Unauthenticated())
             return succeed((request.authnUser, request.authzUser))
 
         authHeader = request.headers.getHeader('authorization')
@@ -1020,8 +1023,8 @@
                 # This request has already been authenticated via the wiki
                 return succeed((request.authnUser, request.authzUser))
 
-            request.authnUser = davxml.Principal(davxml.Unauthenticated())
-            request.authzUser = davxml.Principal(davxml.Unauthenticated())
+            request.authnUser = element.Principal(element.Unauthenticated())
+            request.authzUser = element.Principal(element.Unauthenticated())
             return succeed((request.authnUser, request.authzUser))
 
     ##
@@ -1050,7 +1053,7 @@
 
     def defaultRootAccessControlList(self):
         """
-        @return: the L{davxml.ACL} element containing the default
+        @return: the L{element.ACL} element containing the default
             access control list for this resource.
         """
         #
@@ -1062,14 +1065,14 @@
 
     def defaultAccessControlList(self):
         """
-        @return: the L{davxml.ACL} element containing the default
+        @return: the L{element.ACL} element containing the default
             access control list for this resource.
         """
         #
         # The default behaviour is no ACL; we should inherit from the parent
         # collection.
         #
-        return davxml.ACL()
+        return element.ACL()
 
     def setAccessControlList(self, acl):
         """
@@ -1091,7 +1094,7 @@
         entry. This is the behaviour required by the C{ACL}
         request. (RFC 3744, section 8.1).
 
-        @param new_acl:  an L{davxml.ACL} element
+        @param new_acl:  an L{element.ACL} element
         @param request: the request being processed.
         @return: a tuple of the C{DAV:error} precondition element if
             an error occurred, C{None} otherwise.
@@ -1132,14 +1135,14 @@
             and recurse into any DAV:SupportedPrivilege's
             """
             for item in sp.children:
-                if isinstance(item, davxml.Privilege):
+                if isinstance(item, element.Privilege):
                     supported.append(item.children[0])
-                elif isinstance(item, davxml.SupportedPrivilege):
+                elif isinstance(item, element.SupportedPrivilege):
                     addSupportedPrivilege(item)
 
         supportedPrivs = (yield self.supportedPrivileges(request))
         for item in supportedPrivs.children:
-            assert isinstance(item, davxml.SupportedPrivilege), (
+            assert isinstance(item, element.SupportedPrivilege), (
                 "Not a SupportedPrivilege: %r" % (item,)
             )
             addSupportedPrivilege(item)
@@ -1155,7 +1158,7 @@
                                 "on resource %r"
                                 % (old_ace, self))
                         returnValue((
-                            davxml.dav_namespace,
+                            element.dav_namespace,
                             "no-protected-ace-conflict"
                         ))
 
@@ -1176,7 +1179,7 @@
                     #    log.err("Attempt to overwrite inherited ace %r "
                     #            "on resource %r" % (old_ace, self))
                     #    returnValue((
-                    #        davxml.dav_namespace,
+                    #        element.dav_namespace,
                     #        "no-inherited-ace-conflict"
                     #    ))
 
@@ -1185,7 +1188,7 @@
                 log.err("Attempt to set grant ace %r after deny ace "
                         "on resource %r"
                         % (ace, self))
-                returnValue((davxml.dav_namespace, "deny-before-grant"))
+                returnValue((element.dav_namespace, "deny-before-grant"))
             got_deny = not ace.allow
 
             # Step 4: ignore as this server has no abstract privileges
@@ -1198,19 +1201,19 @@
                             "in ace %r on resource %r"
                             % (privilege.children[0], ace, self))
                     returnValue((
-                        davxml.dav_namespace,
+                        element.dav_namespace,
                         "not-supported-privilege"
                     ))
 
             if ace.protected:
                 log.err("Attempt to create protected ace %r on resource %r"
                         % (ace, self))
-                returnValue((davxml.dav_namespace, "no-ace-conflict"))
+                returnValue((element.dav_namespace, "no-ace-conflict"))
 
             if ace.inherited:
                 log.err("Attempt to create inherited ace %r on resource %r"
                         % (ace, self))
-                returnValue((davxml.dav_namespace, "no-ace-conflict"))
+                returnValue((element.dav_namespace, "no-ace-conflict"))
 
             # Step 6
             valid = (yield self.validPrincipal(ace.principal, request))
@@ -1219,7 +1222,7 @@
                 log.err("Attempt to use unrecognized principal %r "
                         "in ace %r on resource %r"
                         % (ace.principal, ace, self))
-                returnValue((davxml.dav_namespace, "recognized-principal"))
+                returnValue((element.dav_namespace, "recognized-principal"))
 
         # Step 8 & 9
         #
@@ -1256,7 +1259,7 @@
         command.
         @param new_aces: C{list} of L{ACE} for ACL being set.
         """
-        return self.setAccessControlList(davxml.ACL(*new_aces))
+        return self.setAccessControlList(element.ACL(*new_aces))
 
 
     def matchPrivilege(self, privilege, ace_privileges, supportedPrivileges):
@@ -1280,15 +1283,15 @@
         (RFC 3744, section 5.5)
 
         @param request: the request being processed.
-        @param privileges: an iterable of L{davxml.WebDAVElement}
+        @param privileges: an iterable of L{WebDAVElement}
             elements denoting access control privileges.
         @param recurse: C{True} if a recursive check on all child
             resources of this resource should be performed as well,
             C{False} otherwise.
-        @param principal: the L{davxml.Principal} to check privileges
+        @param principal: the L{element.Principal} to check privileges
             for.  If C{None}, it is deduced from C{request} by calling
             L{currentPrincipal}.
-        @param inherited_aces: a list of L{davxml.ACE}s corresponding
+        @param inherited_aces: a list of L{element.ACE}s corresponding
             to the pre-computed inheritable aces from the parent
             resource hierarchy.
         @return: a L{Deferred} that callbacks with C{None} or errbacks
@@ -1333,7 +1336,7 @@
             for ace in acl.children:
                 for privilege in tuple(pending):
                     if not self.matchPrivilege(
-                        davxml.Privilege(privilege),
+                        element.Privilege(privilege),
                         ace.privileges, supportedPrivs
                     ):
                         continue
@@ -1424,7 +1427,7 @@
             return url
 
         try:
-            acl = self.readDeadProperty(davxml.ACL)
+            acl = self.readDeadProperty(element.ACL)
         except HTTPError, e:
             assert e.response.code == responsecode.NOT_FOUND, (
                 "Expected %s response from readDeadProperty() exception, "
@@ -1474,9 +1477,9 @@
                                 children = list(ace.children)
                                 children.remove(TwistedACLInheritable())
                                 children.append(
-                                    davxml.Inherited(davxml.HRef(parentURL))
+                                    element.Inherited(element.HRef(parentURL))
                                 )
-                                aces.append(davxml.ACE(*children))
+                                aces.append(element.ACE(*children))
             else:
                 aces.extend(inherited_aces)
 
@@ -1485,14 +1488,14 @@
             # inheritance.
             if not expanding:
                 aces = [
-                    davxml.ACE(*[
+                    element.ACE(*[
                         c for c in ace.children
                         if c != TwistedACLInheritable()
                     ])
                     for ace in aces
                 ]
 
-            acl = davxml.ACL(*aces)
+            acl = element.ACL(*aces)
 
         returnValue(acl)
 
@@ -1526,11 +1529,11 @@
                     children = list(ace.children)
                     children.remove(TwistedACLInheritable())
                     children.append(
-                        davxml.Inherited(
-                            davxml.HRef(request.urlForResource(self))
+                        element.Inherited(
+                            element.HRef(request.urlForResource(self))
                         )
                     )
-                    aces.append(davxml.ACE(*children))
+                    aces.append(element.ACE(*children))
             return aces
 
         d = self.accessControlList(request, inheritance=True, expanding=True)
@@ -1539,7 +1542,7 @@
 
     def inheritedACLSet(self):
         """
-        @return: a sequence of L{davxml.HRef}s from which ACLs are
+        @return: a sequence of L{element.HRef}s from which ACLs are
         inherited.
 
         This implementation returns an empty set.
@@ -1627,12 +1630,12 @@
         principal2 = principal2.children[0]
 
         if type(principal1) == type(principal2):
-            if isinstance(principal1, davxml.Property):
+            if isinstance(principal1, element.Property):
                 return (
                     type(principal1.children[0]) ==
                     type(principal2.children[0])
                 )
-            elif isinstance(principal1, davxml.HRef):
+            elif isinstance(principal1, element.HRef):
                 return (
                     str(principal1.children[0]) ==
                     str(principal2.children[0])
@@ -1648,7 +1651,7 @@
         by principal2.
 
         @param principal1: a L{Principal} to test. C{principal1} must
-            contain a L{davxml.HRef} or L{davxml.Unauthenticated}
+            contain a L{element.HRef} or L{element.Unauthenticated}
             element.
         @param principal2: a L{Principal} to test.
         @param request: the request being processed.
@@ -1670,27 +1673,27 @@
             return succeed(match)
 
         def doMatch():
-            if isinstance(principal2, davxml.All):
+            if isinstance(principal2, element.All):
                 return succeed(True)
 
-            elif isinstance(principal2, davxml.Authenticated):
-                if isinstance(principal1, davxml.Unauthenticated):
+            elif isinstance(principal2, element.Authenticated):
+                if isinstance(principal1, element.Unauthenticated):
                     return succeed(False)
-                elif isinstance(principal1, davxml.All):
+                elif isinstance(principal1, element.All):
                     return succeed(False)
                 else:
                     return succeed(True)
 
-            elif isinstance(principal2, davxml.Unauthenticated):
-                if isinstance(principal1, davxml.Unauthenticated):
+            elif isinstance(principal2, element.Unauthenticated):
+                if isinstance(principal1, element.Unauthenticated):
                     return succeed(True)
                 else:
                     return succeed(False)
 
-            elif isinstance(principal1, davxml.Unauthenticated):
+            elif isinstance(principal1, element.Unauthenticated):
                 return succeed(False)
 
-            assert isinstance(principal1, davxml.HRef), (
+            assert isinstance(principal1, element.HRef), (
                 "Not an HRef: %r" % (principal1,)
             )
 
@@ -1765,7 +1768,7 @@
             #
             real_principal = ace_principal.children[0]
 
-            if isinstance(real_principal, davxml.Property):
+            if isinstance(real_principal, element.Property):
                 # See comments in matchPrincipal().  We probably need
                 # some common code.
                 log.err("Encountered a property principal (%s), "
@@ -1773,7 +1776,7 @@
                         % (real_principal,))
                 return False
 
-            if isinstance(real_principal, davxml.HRef):
+            if isinstance(real_principal, element.HRef):
                 return self.validHrefPrincipal(real_principal, request)
 
             return True
@@ -1809,27 +1812,27 @@
 
     def resolvePrincipal(self, principal, request):
         """
-        Resolves a L{davxml.Principal} element into a L{davxml.HRef}
+        Resolves a L{element.Principal} element into a L{element.HRef}
         element if possible.  Specifically, the given C{principal}'s
         contained element is resolved.
 
-        L{davxml.Property} is resolved to the URI in the contained
+        L{element.Property} is resolved to the URI in the contained
         property.
 
-        L{davxml.Self} is resolved to the URI of this resource.
+        L{element.Self} is resolved to the URI of this resource.
 
-        L{davxml.HRef} elements are returned as-is.
+        L{element.HRef} elements are returned as-is.
 
         All other principals, including meta-principals
-        (eg. L{davxml.All}), resolve to C{None}.
+        (eg. L{element.All}), resolve to C{None}.
 
-        @param principal: the L{davxml.Principal} child element to
+        @param principal: the L{element.Principal} child element to
         resolve.
         @param request: the request being processed.
-        @return: a deferred L{davxml.HRef} element or C{None}.
+        @return: a deferred L{element.HRef} element or C{None}.
         """
 
-        if isinstance(principal, davxml.Property):
+        if isinstance(principal, element.Property):
             # NotImplementedError("Property principals are not implemented.")
             #
             # We can't raise here without potentially crippling the
@@ -1860,7 +1863,7 @@
                     )
                     return None
 
-                if not isinstance(principal, davxml.Principal):
+                if not isinstance(principal, element.Principal):
                     log.err("Non-principal value in property {%s}%s "
                             "referenced by property principal."
                             % (namespace, name))
@@ -1878,22 +1881,22 @@
             d.addCallback(gotPrincipal)
             return d
 
-        elif isinstance(principal, davxml.Self):
+        elif isinstance(principal, element.Self):
             try:
                 self = IDAVPrincipalResource(self)
             except TypeError:
                 log.err("DAV:self ACE is set on non-principal resource %r"
                         % (self,))
                 return succeed(None)
-            principal = davxml.HRef(self.principalURL())
+            principal = element.HRef(self.principalURL())
 
-        if isinstance(principal, davxml.HRef):
+        if isinstance(principal, element.HRef):
             return succeed(principal)
 
         assert isinstance(principal, (
-            davxml.All,
-            davxml.Authenticated,
-            davxml.Unauthenticated
+            element.All,
+            element.Authenticated,
+            element.Unauthenticated
         )), "Not a meta-principal: %r" % (principal,)
 
         return succeed(None)
@@ -1956,7 +1959,7 @@
     
     def principalSearchPropertySet(self):
         """
-        @return: a L{davxml.PrincipalSearchPropertySet} element describing the
+        @return: a L{element.PrincipalSearchPropertySet} element describing the
         principal properties that can be searched on this principal collection,
         or C{None} if this is not a principal collection.
         
@@ -2320,19 +2323,19 @@
 
             if namespace == dav_namespace:
                 if name == "alternate-URI-set":
-                    return davxml.AlternateURISet(*[
-                        davxml.HRef(u) for u in self.alternateURIs()
+                    return element.AlternateURISet(*[
+                        element.HRef(u) for u in self.alternateURIs()
                     ])
 
                 if name == "principal-URL":
-                    return davxml.PrincipalURL(
-                        davxml.HRef(self.principalURL())
+                    return element.PrincipalURL(
+                        element.HRef(self.principalURL())
                     )
 
                 if name == "group-member-set":
                     def callback(members):
-                        return davxml.GroupMemberSet(*[
-                            davxml.HRef(p.principalURL())
+                        return element.GroupMemberSet(*[
+                            element.HRef(p.principalURL())
                             for p in members
                         ])
                     
@@ -2342,8 +2345,8 @@
 
                 if name == "group-membership":
                     def callback(memberships):
-                        return davxml.GroupMembership(*[
-                            davxml.HRef(g.principalURL())
+                        return element.GroupMembership(*[
+                            element.HRef(g.principalURL())
                             for g in memberships
                         ])
                     
@@ -2353,12 +2356,12 @@
 
                 if name == "resourcetype":
                     if self.isCollection():
-                        return davxml.ResourceType(
-                            davxml.Collection(),
-                            davxml.Principal()
+                        return element.ResourceType(
+                            element.Collection(),
+                            element.Principal()
                         )
                     else:
-                        return davxml.ResourceType(davxml.Principal())
+                        return element.ResourceType(element.Principal())
 
             return super(DAVPrincipalResource, self).readProperty(
                 qname, request
@@ -2511,7 +2514,7 @@
     else:
         return True
 
-class TwistedACLInheritable (davxml.WebDAVEmptyElement):
+class TwistedACLInheritable (WebDAVEmptyElement):
     """
     When set on an ACE, this indicates that the ACE privileges should
     be inherited by all child resources within the resource with this
@@ -2520,20 +2523,20 @@
     namespace = twisted_dav_namespace
     name = "inheritable"
 
-davxml.registerElement(TwistedACLInheritable)
-davxml.ACE.allowed_children[(twisted_dav_namespace, "inheritable")] = (0, 1)
+registerElement(TwistedACLInheritable)
+element.ACE.allowed_children[(twisted_dav_namespace, "inheritable")] = (0, 1)
 
-class TwistedGETContentMD5 (davxml.WebDAVTextElement):
+class TwistedGETContentMD5 (WebDAVTextElement):
     """
     MD5 hash of the resource content.
     """
     namespace = twisted_dav_namespace
     name = "getcontentmd5"
 
-davxml.registerElement(TwistedGETContentMD5)
+registerElement(TwistedGETContentMD5)
 
 
-class TwistedQuotaRootProperty (davxml.WebDAVTextElement):
+class TwistedQuotaRootProperty (WebDAVTextElement):
     """
     When set on a collection, this property indicates that the
     collection has a quota limit for the size of all resources stored
@@ -2544,9 +2547,9 @@
     namespace = twisted_private_namespace
     name = "quota-root"
 
-davxml.registerElement(TwistedQuotaRootProperty)
+registerElement(TwistedQuotaRootProperty)
 
-class TwistedQuotaUsedProperty (davxml.WebDAVTextElement):
+class TwistedQuotaUsedProperty (WebDAVTextElement):
     """
     When set on a collection, this property contains the cached
     running total of the size of all resources stored in the
@@ -2556,30 +2559,30 @@
     namespace = twisted_private_namespace
     name = "quota-used"
 
-davxml.registerElement(TwistedQuotaUsedProperty)
+registerElement(TwistedQuotaUsedProperty)
 
-allACL = davxml.ACL(
-    davxml.ACE(
-        davxml.Principal(davxml.All()),
-        davxml.Grant(davxml.Privilege(davxml.All())),
-        davxml.Protected(),
+allACL = element.ACL(
+    element.ACE(
+        element.Principal(element.All()),
+        element.Grant(element.Privilege(element.All())),
+        element.Protected(),
         TwistedACLInheritable()
     )
 )
 
-readonlyACL = davxml.ACL(
-    davxml.ACE(
-        davxml.Principal(davxml.All()),
-        davxml.Grant(davxml.Privilege(davxml.Read())),
-        davxml.Protected(),
+readonlyACL = element.ACL(
+    element.ACE(
+        element.Principal(element.All()),
+        element.Grant(element.Privilege(element.Read())),
+        element.Protected(),
         TwistedACLInheritable()
     )
 )
 
-allPrivilegeSet = davxml.SupportedPrivilegeSet(
-    davxml.SupportedPrivilege(
-        davxml.Privilege(davxml.All()),
-        davxml.Description("all privileges", **{"xml:lang": "en"})
+allPrivilegeSet = element.SupportedPrivilegeSet(
+    element.SupportedPrivilege(
+        element.Privilege(element.All()),
+        element.Description("all privileges", **{"xml:lang": "en"})
     )
 )
 
@@ -2587,79 +2590,79 @@
 # This is one possible graph of the "standard" privileges documented
 # in 3744, section 3.
 #
-davPrivilegeSet = davxml.SupportedPrivilegeSet(
-    davxml.SupportedPrivilege(
-        davxml.Privilege(davxml.All()),
-        davxml.Description(
+davPrivilegeSet = element.SupportedPrivilegeSet(
+    element.SupportedPrivilege(
+        element.Privilege(element.All()),
+        element.Description(
             "all privileges",
             **{"xml:lang": "en"}
         ),
-        davxml.SupportedPrivilege(
-            davxml.Privilege(davxml.Read()),
-            davxml.Description(
+        element.SupportedPrivilege(
+            element.Privilege(element.Read()),
+            element.Description(
                 "read resource",
                 **{"xml:lang": "en"}
             ),
         ),
-        davxml.SupportedPrivilege(
-            davxml.Privilege(davxml.Write()),
-            davxml.Description(
+        element.SupportedPrivilege(
+            element.Privilege(element.Write()),
+            element.Description(
                 "write resource",
                 **{"xml:lang": "en"}
             ),
-            davxml.SupportedPrivilege(
-                davxml.Privilege(davxml.WriteProperties()),
-                davxml.Description(
+            element.SupportedPrivilege(
+                element.Privilege(element.WriteProperties()),
+                element.Description(
                     "write resource properties",
                     **{"xml:lang": "en"}
                 ),
             ),
-            davxml.SupportedPrivilege(
-                davxml.Privilege(davxml.WriteContent()),
-                davxml.Description(
+            element.SupportedPrivilege(
+                element.Privilege(element.WriteContent()),
+                element.Description(
                     "write resource content",
                     **{"xml:lang": "en"}
                 ),
             ),
-            davxml.SupportedPrivilege(
-                davxml.Privilege(davxml.Bind()),
-                davxml.Description(
+            element.SupportedPrivilege(
+                element.Privilege(element.Bind()),
+                element.Description(
                     "add child resource",
                     **{"xml:lang": "en"}
                 ),
             ),
-            davxml.SupportedPrivilege(
-                davxml.Privilege(davxml.Unbind()),
-                davxml.Description(
+            element.SupportedPrivilege(
+                element.Privilege(element.Unbind()),
+                element.Description(
                     "remove child resource",
                     **{"xml:lang": "en"}
                 ),
             ),
         ),
-        davxml.SupportedPrivilege(
-            davxml.Privilege(davxml.Unlock()),
-            davxml.Description(
+        element.SupportedPrivilege(
+            element.Privilege(element.Unlock()),
+            element.Description(
                 "unlock resource without ownership of lock",
                 **{"xml:lang": "en"}
             ),
         ),
-        davxml.SupportedPrivilege(
-            davxml.Privilege(davxml.ReadACL()),
-            davxml.Description(
+        element.SupportedPrivilege(
+            element.Privilege(element.ReadACL()),
+            element.Description(
                 "read resource access control list",
                 **{"xml:lang": "en"}
             ),
         ),
-        davxml.SupportedPrivilege(
-            davxml.Privilege(davxml.WriteACL()),
-            davxml.Description(
+        element.SupportedPrivilege(
+            element.Privilege(element.WriteACL()),
+            element.Description(
                 "write resource access control list",
                 **{"xml:lang": "en"}
             ),
         ),
-        davxml.SupportedPrivilege(
-            davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
-            davxml.Description(
+        element.SupportedPrivilege(
+            element.Privilege(element.ReadCurrentUserPrivilegeSet()),
+            element.Description(
                 "read privileges for current principal",
                 **{"xml:lang": "en"}
             ),
@@ -2667,10 +2670,10 @@
     ),
 )
 
-unauthenticatedPrincipal = davxml.Principal(davxml.Unauthenticated())
+unauthenticatedPrincipal = element.Principal(element.Unauthenticated())
 
 
-class ResourceClass (davxml.WebDAVTextElement):
+class ResourceClass (WebDAVTextElement):
     namespace = twisted_dav_namespace
     name = "resource-class"
     hidden = False

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_acl.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_acl.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_acl.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -29,18 +29,18 @@
 from twext.web2 import responsecode
 from twext.web2.auth import basic
 from twext.web2.stream import MemoryStream
-from twext.web2.dav import davxml
-
 from twext.web2.dav.util import davXMLFromStream
 from twext.web2.dav.auth import TwistedPasswordProperty, IPrincipal, DavRealm, TwistedPropertyChecker, AuthenticationWrapper
 from twext.web2.dav.fileop import rmdir
-
-import twext.web2.dav.test.util
 from twext.web2.test.test_server import SimpleRequest
 from twext.web2.dav.test.util import Site, serialize
 from twext.web2.dav.test.test_resource import \
     TestDAVPrincipalResource, TestPrincipalsCollection
 
+from txdav.xml import element
+
+import twext.web2.dav.test.util
+
 class ACL(twext.web2.dav.test.util.TestCase):
     """
     RFC 3744 (WebDAV ACL) tests.
@@ -75,14 +75,14 @@
             loginInterfaces
         ))
 
-        rootResource.setAccessControlList(self.grant(davxml.All()))
+        rootResource.setAccessControlList(self.grant(element.All()))
 
         for name, acl in (
             ("none"       , self.grant()),
-            ("read"       , self.grant(davxml.Read())),
-            ("read-write" , self.grant(davxml.Read(), davxml.Write())),
-            ("unlock"     , self.grant(davxml.Unlock())),
-            ("all"        , self.grant(davxml.All())),
+            ("read"       , self.grant(element.Read())),
+            ("read-write" , self.grant(element.Read(), element.Write())),
+            ("unlock"     , self.grant(element.Unlock())),
+            ("all"        , self.grant(element.All())),
         ):
             filename = os.path.join(docroot, name)
             if not os.path.isfile(filename):
@@ -92,8 +92,8 @@
 
         for name, acl in (
             ("nobind" , self.grant()),
-            ("bind"   , self.grant(davxml.Bind())),
-            ("unbind" , self.grant(davxml.Bind(), davxml.Unbind())),
+            ("bind"   , self.grant(element.Bind())),
+            ("unbind" , self.grant(element.Bind(), element.Unbind())),
         ):
             dirname = os.path.join(docroot, name)
             if not os.path.isdir(dirname):
@@ -131,15 +131,15 @@
                 src_resource = self.resource_class(src_path)
                 src_resource.setAccessControlList({
                     "nobind": self.grant(),
-                    "bind"  : self.grant(davxml.Bind()),
-                    "unbind": self.grant(davxml.Bind(), davxml.Unbind())
+                    "bind"  : self.grant(element.Bind()),
+                    "unbind": self.grant(element.Bind(), element.Unbind())
                 }[src])
                 for name, acl in (
                     ("none"       , self.grant()),
-                    ("read"       , self.grant(davxml.Read())),
-                    ("read-write" , self.grant(davxml.Read(), davxml.Write())),
-                    ("unlock"     , self.grant(davxml.Unlock())),
-                    ("all"        , self.grant(davxml.All())),
+                    ("read"       , self.grant(element.Read())),
+                    ("read-write" , self.grant(element.Read(), element.Write())),
+                    ("unlock"     , self.grant(element.Unlock())),
+                    ("all"        , self.grant(element.All())),
                 ):
                     filename = os.path.join(src_path, name)
                     if not os.path.isfile(filename):
@@ -318,7 +318,7 @@
 
                 request = SimpleRequest(self.site, "PROPPATCH", "/" + name)
                 request.stream = MemoryStream(
-                    davxml.WebDAVDocument(davxml.PropertyUpdate()).toxml()
+                    element.WebDAVDocument(element.PropertyUpdate()).toxml()
                 )
                 _add_auth_header(request)
 
@@ -354,7 +354,7 @@
 
                     request = SimpleRequest(self.site, method, "/" + name)
                     if method == "REPORT":
-                        request.stream = MemoryStream(davxml.PrincipalPropertySearch().toxml())
+                        request.stream = MemoryStream(element.PrincipalPropertySearch().toxml())
 
                     _add_auth_header(request)
 

Deleted: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_davxml.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_davxml.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_davxml.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -1,55 +0,0 @@
-
-##
-# Copyright (c) 2005-2010 Apple Computer, Inc. All rights reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-# 
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-# 
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
-# DRI: Wilfredo Sanchez, wsanchez at apple.com
-##
-
-from twext.web2.dav.davxml import *
-
-from twistedcaldav.test.util import TestCase
-
-class XML(TestCase):
-    def test_sname2qname(self):
-        # Empty name
-        self.assertRaises(ValueError, sname2qname, "") 
-        self.assertRaises(ValueError, sname2qname, "{}")
-        self.assertRaises(ValueError, sname2qname, "{x}")
-
-        # Weird bracket cases
-        self.assertRaises(ValueError, sname2qname, "{")
-        self.assertRaises(ValueError, sname2qname, "x{")
-        self.assertRaises(ValueError, sname2qname, "{x")
-        self.assertRaises(ValueError, sname2qname, "}")
-        self.assertRaises(ValueError, sname2qname, "x}")
-        self.assertRaises(ValueError, sname2qname, "}x")  
-        self.assertRaises(ValueError, sname2qname, "{{}")
-        self.assertRaises(ValueError, sname2qname, "{{}}")
-        self.assertRaises(ValueError, sname2qname, "x{}")
-
-        # Empty namespace is OK
-        self.assertEquals(sname2qname("{}x"), ("", "x"))
-
-        # Normal case
-        self.assertEquals(sname2qname("{namespace}name"), ("namespace", "name"))
-
-    def test_qname2sname(self):
-        self.assertEquals(qname2sname(("namespace", "name")), "{namespace}name")

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_prop.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_prop.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_prop.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -26,11 +26,13 @@
 from twext.web2.iweb import IResponse
 from twext.web2.stream import MemoryStream
 from twext.web2 import http_headers
-from twext.web2.dav import davxml
-from twext.web2.dav.davxml import dav_namespace, lookupElement
 from twext.web2.dav.util import davXMLFromStream
 from twext.web2.test.test_server import SimpleRequest
 from twext.web2.dav.test.util import serialize
+
+from txdav.xml import element as davxml
+from txdav.xml.element import dav_namespace, lookupElement
+
 import twext.web2.dav.test.util
 
 # Remove dynamic live properties that exist

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_quota.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_quota.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_quota.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -29,7 +29,7 @@
 import twext.web2.dav.test.util
 from twext.web2.test.test_server import SimpleRequest
 from twext.web2.dav.test.util import Site
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 import os
 
 class QuotaBase(twext.web2.dav.test.util.TestCase):

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_report.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_report.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_report.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -28,7 +28,7 @@
 
 import twext.web2.dav.test.util
 from twext.web2.test.test_server import SimpleRequest
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 
 class REPORT(twext.web2.dav.test.util.TestCase):
     """

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_resource.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_resource.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_resource.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -28,7 +28,7 @@
 from twext.web2.http import HTTPError
 from twext.web2.auth import basic
 from twext.web2.server import Site
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.resource import DAVResource, AccessDeniedError, \
     DAVPrincipalResource, DAVPrincipalCollectionResource, davPrivilegeSet
 from twext.web2.dav.auth import TwistedPasswordProperty, DavRealm, TwistedPropertyChecker, IPrincipal, AuthenticationWrapper

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_static.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_static.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_static.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -23,7 +23,7 @@
 ##
 
 from twext.web2.dav.test import util
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.stream import readStream
 from twext.web2.test.test_server import SimpleRequest
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_xattrprops.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_xattrprops.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_xattrprops.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -15,7 +15,7 @@
 from twext.web2.responsecode import FORBIDDEN
 from twext.web2.http import HTTPError
 from twext.web2.dav.static import DAVFile
-from twext.web2.dav.davxml import Depth, WebDAVDocument
+from txdav.xml.element import Depth, WebDAVDocument
 
 try:
     from twext.web2.dav.xattrprops import xattrPropertyStore

Deleted: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_xml.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_xml.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_xml.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -1,105 +0,0 @@
-# Copyright (c) 2009 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-##
-# Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-##
-
-"""
-Tests for L{twext.web2.dav.davxml}.
-"""
-
-from twisted.trial.unittest import TestCase
-from twext.web2.dav.davxml import WebDAVDocument, WebDAVUnknownElement
-from twext.web2.dav.davxml import Response, HRef, MultiStatus, Status
-from twext.web2.dav.davxml import CurrentUserPrincipal
-
-
-class WebDAVElementTestsMixin:
-    """
-    Mixin for L{TestCase}s which test a L{WebDAVElement} subclass.
-    """
-    def test_fromString(self):
-        """
-        The XML representation of L{WebDAVDocument} can be parsed into a
-        L{WebDAVDocument} instance using L{WebDAVDocument.fromString}.
-        """
-        doc = WebDAVDocument.fromString(self.serialized)
-        self.assertEquals(doc, WebDAVDocument(self.element))
-
-
-    def test_toxml(self):
-        """
-        L{WebDAVDocument.toxml} returns a C{str} giving the XML representation
-        of the L{WebDAVDocument} instance.
-        """
-        document = WebDAVDocument(self.element)
-        self.assertEquals(
-            document,
-            WebDAVDocument.fromString(document.toxml()))
-
-
-
-class MultiStatusTests(WebDAVElementTestsMixin, TestCase):
-    """
-    Tests for L{MultiStatus}
-    """
-    serialized = (
-        '<?xml version="1.0" encoding="utf-8" ?>'
-        '<D:multistatus xmlns:D="DAV:">'
-        '  <D:response>'
-        '    <D:href>http://webdav.sb.aol.com/webdav/secret</D:href>'
-        '    <D:status>HTTP/1.1 403 Forbidden</D:status>'
-        '  </D:response>'
-        '</D:multistatus>')
-
-    element = MultiStatus(
-        Response(
-            HRef("http://webdav.sb.aol.com/webdav/secret"),
-            Status("HTTP/1.1 403 Forbidden")))
-
-
-
-class WebDAVUnknownElementTests(WebDAVElementTestsMixin, TestCase):
-    """
-    Tests for L{WebDAVUnknownElement}.
-    """
-    serialized = (
-        '<?xml version="1.0" encoding="utf-8" ?>'
-        '<T:foo xmlns:T="http://twistedmatrix.com/"/>')
-
-    element = WebDAVUnknownElement()
-    element.namespace = "http://twistedmatrix.com/"
-    element.name = "foo"
-
-
-
-class CurrentUserPrincipalTests(WebDAVElementTestsMixin, TestCase):
-    """
-    Tests for L{CurrentUserPrincipal}.
-    """
-    serialized = (
-        '<?xml version="1.0" encoding="utf-8" ?>'
-        '<D:current-user-principal xmlns:D="DAV:">'
-        '  <D:href>foo</D:href>'
-        '</D:current-user-principal>')
-
-    element = CurrentUserPrincipal(HRef("foo"))

Deleted: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_xml_rfc3744.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_xml_rfc3744.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/test_xml_rfc3744.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -1,59 +0,0 @@
-##
-# Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-# 
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-# 
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
-# DRI: Wilfredo Sanchez, wsanchez at apple.com
-##
-
-from twisted.trial import unittest
-from twext.web2.dav import davxml
-from twext.web2.dav.resource import davPrivilegeSet
-
-class XML_3744(unittest.TestCase):
-    """
-    RFC 3744 (WebDAV ACL) XML tests.
-    """
-    def test_Privilege_isAggregateOf(self):
-        """
-        Privilege.isAggregateOf()
-        """
-        for a, b in (
-            (davxml.All(), davxml.Write()),
-            (davxml.All(), davxml.ReadACL()),
-            (davxml.Write(), davxml.WriteProperties()),
-            (davxml.Write(), davxml.WriteContent()),
-            (davxml.Write(), davxml.Bind()),
-            (davxml.Write(), davxml.Unbind()),
-        ):
-            pa = davxml.Privilege(a)
-            pb = davxml.Privilege(b)
-
-            self.failUnless(pa.isAggregateOf(pb, davPrivilegeSet), "%s contains %s" % (a.sname(), b.sname()))
-            self.failIf(pb.isAggregateOf(pa, davPrivilegeSet), "%s does not contain %s" % (b.sname(), a.sname()))
-
-        for a, b in (
-            (davxml.Unlock(), davxml.Write()),
-            (davxml.Unlock(), davxml.WriteACL()),
-            (davxml.ReadCurrentUserPrivilegeSet(), davxml.WriteProperties()),
-        ):
-            pa = davxml.Privilege(a)
-            pb = davxml.Privilege(b)
-
-            self.failIf(pb.isAggregateOf(pa, davPrivilegeSet), "%s does not contain %s" % (b.sname(), a.sname()))

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/util.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/util.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/test/util.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -34,11 +34,10 @@
 from twext.python.log import Logger
 from twext.web2.http import HTTPError, StatusResponse
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
-
 from twext.web2.dav.resource import TwistedACLInheritable
 from twext.web2.dav.static import DAVFile
 from twext.web2.dav.util import joinURL
+from txdav.xml import element
 
 log = Logger()
 
@@ -61,7 +60,7 @@
                 "No such property: {%s}%s" % qname
             ))
 
-        doc = davxml.WebDAVDocument.fromString(property)
+        doc = element.WebDAVDocument.fromString(property)
         return doc.root_element
 
     def set(self, property):
@@ -100,10 +99,10 @@
     resource_class = TestFile
 
     def grant(*privileges):
-        return davxml.ACL(*[
-            davxml.ACE(
-                davxml.Grant(davxml.Privilege(privilege)),
-                davxml.Principal(davxml.All())
+        return element.ACL(*[
+            element.ACE(
+                element.Grant(element.Privilege(privilege)),
+                element.Principal(element.All())
             )
             for privilege in privileges
         ])
@@ -111,10 +110,10 @@
     grant = staticmethod(grant)
 
     def grantInherit(*privileges):
-        return davxml.ACL(*[
-            davxml.ACE(
-                davxml.Grant(davxml.Privilege(privilege)),
-                davxml.Principal(davxml.All()),
+        return element.ACL(*[
+            element.ACE(
+                element.Grant(element.Privilege(privilege)),
+                element.Principal(element.All()),
                 TwistedACLInheritable()
             )
             for privilege in privileges
@@ -126,7 +125,7 @@
         docroot = self.mktemp()
         os.mkdir(docroot)
         rootresource = self.resource_class(docroot)
-        rootresource.setAccessControlList(self.grantInherit(davxml.All()))
+        rootresource.setAccessControlList(self.grantInherit(element.All()))
 
         dirnames = (
             os.path.join(docroot, "dir1"),                          # 0
@@ -173,7 +172,7 @@
     def _getSite(self):
         if not hasattr(self, "_site"):
             rootresource = self.resource_class(self.docroot)
-            rootresource.setAccessControlList(self.grantInherit(davxml.All()))
+            rootresource.setAccessControlList(self.grantInherit(element.All()))
             self._site = Site(rootresource)
         return self._site
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/util.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/util.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/util.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -50,7 +50,7 @@
 
 from twext.python.log import Logger
 from twext.web2.stream import readStream
-from twext.web2.dav import davxml
+from txdav.xml.parser import WebDAVDocument
 
 log = Logger()
 
@@ -79,7 +79,7 @@
 
     def parse(xml):
         try:
-            doc = davxml.WebDAVDocument.fromString(xml)
+            doc = WebDAVDocument.fromString(xml)
             doc.root_element.validate()
             return doc
         except ValueError:

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/xattrprops.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/xattrprops.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twext/web2/dav/xattrprops.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -52,8 +52,8 @@
 from twisted.python.log import err
 from twext.web2 import responsecode
 from twext.web2.http import HTTPError, StatusResponse
-from twext.web2.dav import davxml
 from twext.web2.dav.http import statusForFailure
+from txdav.xml.parser import WebDAVDocument
 
 # RFC 2518 Section 12.13.1 says that removal of non-existing property
 # is not an error.  python-xattr on Linux fails with ENODATA in this
@@ -170,7 +170,7 @@
             legacy = True
 
         try:
-            doc = davxml.WebDAVDocument.fromString(data)
+            doc = WebDAVDocument.fromString(data)
         except ValueError:
             try:
                 doc = unpickle(data)

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/__init__.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/__init__.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/__init__.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -33,16 +33,12 @@
 # Register additional WebDAV XML elements
 #
 
-import twext.web2.dav.davxml
 import twistedcaldav.caldavxml
 import twistedcaldav.carddavxml
 import twistedcaldav.mkcolxml
 import twistedcaldav.customxml
 
-twext.web2.dav.davxml.registerElements(twistedcaldav.caldavxml)
-twext.web2.dav.davxml.registerElements(twistedcaldav.customxml)
-twext.web2.dav.davxml.registerElements(twistedcaldav.carddavxml)
-twext.web2.dav.davxml.registerElements(twistedcaldav.mkcolxml)
+twistedcaldav # Shhh.. pyflakes
 
 #
 # DefaultHTTPHandler

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/caldavxml.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/caldavxml.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/caldavxml.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -27,7 +27,10 @@
 
 from pycalendar.datetime import PyCalendarDateTime
 
-from twext.web2.dav import davxml
+from txdav.xml.element import registerElement, dav_namespace
+from txdav.xml.element import WebDAVElement, PCDATAElement
+from txdav.xml.element import WebDAVEmptyElement, WebDAVTextElement
+from txdav.xml.element import ResourceType, Collection
 
 from twext.python.log import Logger
 
@@ -61,24 +64,28 @@
     "calendar-query-extended",
 )
 
-class CalDAVElement (davxml.WebDAVElement):
+
+class CalDAVElement (WebDAVElement):
     """
     CalDAV XML element.
     """
     namespace = caldav_namespace
 
-class CalDAVEmptyElement (davxml.WebDAVEmptyElement):
+
+class CalDAVEmptyElement (WebDAVEmptyElement):
     """
     CalDAV element with no contents.
     """
     namespace = caldav_namespace
 
-class CalDAVTextElement (davxml.WebDAVTextElement):
+
+class CalDAVTextElement (WebDAVTextElement):
     """
     CalDAV element containing PCDATA.
     """
     namespace = caldav_namespace
 
+
 class CalDAVTimeRangeElement (CalDAVEmptyElement):
     """
     CalDAV element containing a time range.
@@ -121,11 +128,11 @@
         # No other tests
         return True
 
+
 class CalDAVTimeZoneElement (CalDAVTextElement):
     """
     CalDAV element containing iCalendar data with a single VTIMEZONE component.
     """
-
     def calendar(self):
         """
         Returns a calendar component derived from this element, which contains
@@ -160,6 +167,8 @@
 
         return found
         
+
+ at registerElement
 class CalendarHomeSet (CalDAVElement):
     """
     The calendar collections URLs for this principal's calendar user.
@@ -168,8 +177,10 @@
     name = "calendar-home-set"
     hidden = True
 
-    allowed_children = { (davxml.dav_namespace, "href"): (0, None) }
+    allowed_children = { (dav_namespace, "href"): (0, None) }
 
+
+ at registerElement
 class CalendarDescription (CalDAVTextElement):
     """
     Provides a human-readable description of what this calendar collection
@@ -180,6 +191,8 @@
     hidden = True
     # May be protected; but we'll let the client set this if they like.
 
+
+ at registerElement
 class CalendarTimeZone (CalDAVTimeZoneElement):
     """
     Specifies a time zone on a calendar collection.
@@ -188,6 +201,8 @@
     name = "calendar-timezone"
     hidden = True
 
+
+ at registerElement
 class SupportedCalendarComponentSets (CalDAVElement):
     """
     Indicates what set of calendar components the server is willing to allow
@@ -200,6 +215,8 @@
 
     allowed_children = { (caldav_namespace, "supported-calendar-component-set"): (0, None) }
 
+
+ at registerElement
 class SupportedCalendarComponentSet (CalDAVElement):
     """
     Indicates what set of calendar components are allowed in a collection.
@@ -211,6 +228,8 @@
 
     allowed_children = { (caldav_namespace, "comp"): (0, None) }
 
+
+ at registerElement
 class SupportedCalendarData (CalDAVElement):
     """
     Specifies restrictions on a calendar collection.
@@ -222,6 +241,8 @@
 
     allowed_children = { (caldav_namespace, "calendar-data"): (0, None) }
 
+
+ at registerElement
 class MaxResourceSize (CalDAVTextElement):
     """
     Specifies restrictions on a calendar collection.
@@ -231,6 +252,8 @@
     hidden = True
     protected = True
 
+
+ at registerElement
 class MinDateTime (CalDAVTextElement):
     """
     Specifies restrictions on a calendar collection.
@@ -240,6 +263,8 @@
     hidden = True
     protected = True
 
+
+ at registerElement
 class MaxDateTime (CalDAVTextElement):
     """
     Specifies restrictions on a calendar collection.
@@ -249,6 +274,8 @@
     hidden = True
     protected = True
 
+
+ at registerElement
 class MaxInstances (CalDAVTextElement):
     """
     Specifies restrictions on a calendar collection.
@@ -258,6 +285,8 @@
     hidden = True
     protected = True
 
+
+ at registerElement
 class MaxAttendeesPerInstance (CalDAVTextElement):
     """
     Specifies restrictions on a calendar collection.
@@ -267,6 +296,8 @@
     hidden = True
     protected = True
 
+
+ at registerElement
 class Calendar (CalDAVEmptyElement):
     """
     Denotes a calendar collection.
@@ -274,6 +305,8 @@
     """
     name = "calendar"
 
+
+ at registerElement
 class MakeCalendar (CalDAVElement):
     """
     Top-level element for request body in MKCALENDAR.
@@ -281,10 +314,12 @@
     """
     name = "mkcalendar"
 
-    allowed_children = { (davxml.dav_namespace, "set"): (0, 1) }
+    allowed_children = { (dav_namespace, "set"): (0, 1) }
 
     child_types = { "WebDAVUnknownElement": (0, None) }
 
+
+ at registerElement
 class MakeCalendarResponse (CalDAVElement):
     """
     Top-level element for response body in MKCALENDAR.
@@ -292,8 +327,10 @@
     """
     name = "mkcalendar-response"
 
-    allowed_children = { davxml.WebDAVElement: (0, None) }
+    allowed_children = { WebDAVElement: (0, None) }
 
+
+ at registerElement
 class CalendarQuery (CalDAVElement):
     """
     Defines a report for querying calendar data.
@@ -302,11 +339,11 @@
     name = "calendar-query"
 
     allowed_children = {
-        (davxml.dav_namespace, "allprop" ): (0, None),
-        (davxml.dav_namespace, "propname"): (0, None),
-        (davxml.dav_namespace, "prop"    ): (0, None),
-        (caldav_namespace,     "timezone"): (0, 1),
-        (caldav_namespace,     "filter"  ): (0, 1), # Actually (1, 1) unless element is empty
+        (dav_namespace,    "allprop" ): (0, None),
+        (dav_namespace,    "propname"): (0, None),
+        (dav_namespace,    "prop"    ): (0, None),
+        (caldav_namespace, "timezone"): (0, 1),
+        (caldav_namespace, "filter"  ): (0, 1), # Actually (1, 1) unless element is empty
     }
 
     def __init__(self, *children, **attributes):
@@ -320,9 +357,9 @@
             qname = child.qname()
 
             if qname in (
-                (davxml.dav_namespace, "allprop" ),
-                (davxml.dav_namespace, "propname"),
-                (davxml.dav_namespace, "prop"    ),
+                (dav_namespace, "allprop" ),
+                (dav_namespace, "propname"),
+                (dav_namespace, "prop"    ),
             ):
                 if props is not None:
                     raise ValueError("Only one of CalDAV:allprop, CalDAV:propname, CalDAV:prop allowed")
@@ -345,6 +382,8 @@
         self.filter = filter
         self.timezone = timezone
 
+
+ at registerElement
 class CalendarData (CalDAVElement):
     """
     Defines which parts of a calendar component object should be returned by a
@@ -358,7 +397,7 @@
         (caldav_namespace, "expand"               ): (0, 1),
         (caldav_namespace, "limit-recurrence-set" ): (0, 1),
         (caldav_namespace, "limit-freebusy-set"   ): (0, 1),
-        davxml.PCDATAElement: (0, None),
+        PCDATAElement: (0, None),
     }
     allowed_attributes = {
         "content-type": False,
@@ -370,10 +409,10 @@
         if isinstance(calendar, str):
             if not calendar:
                 raise ValueError("Missing calendar data")
-            return clazz(davxml.PCDATAElement(calendar))
+            return clazz(PCDATAElement(calendar))
         elif isinstance(calendar, iComponent):
             assert calendar.name() == "VCALENDAR", "Not a calendar: %r" % (calendar,)
-            return clazz(davxml.PCDATAElement(calendar.getTextWithTimezones(includeTimezones=not config.EnableTimezonesByReference)))
+            return clazz(PCDATAElement(calendar.getTextWithTimezones(includeTimezones=not config.EnableTimezonesByReference)))
         else:
             raise ValueError("Not a calendar: %s" % (calendar,))
 
@@ -404,7 +443,7 @@
             elif qname == (caldav_namespace, "limit-freebusy-set"):
                 freebusy_set = child
 
-            elif isinstance(child, davxml.PCDATAElement):
+            elif isinstance(child, PCDATAElement):
                 if data is None:
                     data = child
                 else:
@@ -469,7 +508,7 @@
         Returns the calendar data derived from this element.
         """
         for data in self.children:
-            if not isinstance(data, davxml.PCDATAElement):
+            if not isinstance(data, PCDATAElement):
                 return None
             else:
                 # We guaranteed in __init__() that there is only one child...
@@ -479,6 +518,8 @@
 
     textData = calendarData
 
+
+ at registerElement
 class CalendarComponent (CalDAVElement):
     """
     Defines which component types to return.
@@ -581,6 +622,8 @@
 
         return result
 
+
+ at registerElement
 class AllComponents (CalDAVEmptyElement):
     """
     Specifies that all components shall be returned.
@@ -588,6 +631,8 @@
     """
     name = "allcomp"
 
+
+ at registerElement
 class AllProperties (CalDAVEmptyElement):
     """
     Specifies that all properties shall be returned.
@@ -595,6 +640,8 @@
     """
     name = "allprop"
 
+
+ at registerElement
 class Property (CalDAVEmptyElement):
     """
     Defines a property to return in a response.
@@ -623,6 +670,8 @@
         else:
             self.novalue = False
 
+
+ at registerElement
 class Expand (CalDAVTimeRangeElement):
     """
     Specifies that the server should expand recurring components into separate
@@ -631,6 +680,8 @@
     """
     name = "expand"
 
+
+ at registerElement
 class LimitRecurrenceSet (CalDAVTimeRangeElement):
     """
     Specifies a time range to limit the set of recurrence instances returned by
@@ -639,6 +690,8 @@
     """
     name = "limit-recurrence-set"
 
+
+ at registerElement
 class LimitFreeBusySet (CalDAVTimeRangeElement):
     """
     Specifies a time range to limit the set of FREEBUSY properties returned by
@@ -647,6 +700,8 @@
     """
     name = "limit-freebusy-set"
 
+
+ at registerElement
 class Filter (CalDAVElement):
     """
     Determines which matching components are returned.
@@ -656,6 +711,8 @@
 
     allowed_children = { (caldav_namespace, "comp-filter"): (1, 1) }
 
+
+ at registerElement
 class ComponentFilter (CalDAVElement):
     """
     Limits a search to only the chosen component types.
@@ -674,6 +731,8 @@
         "test": False,
     }
 
+
+ at registerElement
 class PropertyFilter (CalDAVElement):
     """
     Limits a search to specific properties.
@@ -692,6 +751,8 @@
         "test": False,
     }
 
+
+ at registerElement
 class ParameterFilter (CalDAVElement):
     """
     Limits a search to specific parameters.
@@ -705,6 +766,8 @@
     }
     allowed_attributes = { "name": True }
 
+
+ at registerElement
 class IsNotDefined (CalDAVEmptyElement):
     """
     Specifies that the named iCalendar item does not exist.
@@ -712,6 +775,8 @@
     """
     name = "is-not-defined"
 
+
+ at registerElement
 class TextMatch (CalDAVTextElement):
     """
     Specifies a substring match on a property or parameter value.
@@ -726,11 +791,11 @@
             caseless = "no"
 
         if type(string) is str:
-            return clazz(davxml.PCDATAElement(string), caseless=caseless)
+            return clazz(PCDATAElement(string), caseless=caseless)
         elif type(string) is unicode:
-            return clazz(davxml.PCDATAElement(string.encode("utf-8")), caseless=caseless)
+            return clazz(PCDATAElement(string.encode("utf-8")), caseless=caseless)
         else:
-            return clazz(davxml.PCDATAElement(str(string)), caseless=caseless)
+            return clazz(PCDATAElement(str(string)), caseless=caseless)
 
     fromString = classmethod(fromString)
 
@@ -740,6 +805,8 @@
         "match-type": False,
     }
 
+
+ at registerElement
 class TimeZone (CalDAVTimeZoneElement):
     """
     Specifies a time zone component.
@@ -747,6 +814,8 @@
     """
     name = "timezone"
 
+
+ at registerElement
 class TimeRange (CalDAVTimeRangeElement):
     """
     Specifies a time for testing components against.
@@ -754,6 +823,8 @@
     """
     name = "time-range"
 
+
+ at registerElement
 class CalendarMultiGet (CalDAVElement):
     """
     CalDAV report used to retrieve specific calendar component items via their
@@ -765,10 +836,10 @@
     # To allow for an empty element in a supported-report-set property we need
     # to relax the child restrictions
     allowed_children = {
-        (davxml.dav_namespace, "allprop" ): (0, 1),
-        (davxml.dav_namespace, "propname"): (0, 1),
-        (davxml.dav_namespace, "prop"    ): (0, 1),
-        (davxml.dav_namespace, "href"    ): (0, None),    # Actually ought to be (1, None)
+        (dav_namespace, "allprop" ): (0, 1),
+        (dav_namespace, "propname"): (0, 1),
+        (dav_namespace, "prop"    ): (0, 1),
+        (dav_namespace, "href"    ): (0, None),    # Actually ought to be (1, None)
     }
 
     def __init__(self, *children, **attributes):
@@ -781,20 +852,22 @@
             qname = child.qname()
 
             if qname in (
-                (davxml.dav_namespace, "allprop" ),
-                (davxml.dav_namespace, "propname"),
-                (davxml.dav_namespace, "prop"    ),
+                (dav_namespace, "allprop" ),
+                (dav_namespace, "propname"),
+                (dav_namespace, "prop"    ),
             ):
                 if property is not None:
                     raise ValueError("Only one of DAV:allprop, DAV:propname, DAV:prop allowed")
                 property = child
 
-            elif qname == (davxml.dav_namespace, "href"):
+            elif qname == (dav_namespace, "href"):
                 resources.append(child)
 
         self.property  = property
         self.resources = resources
 
+
+ at registerElement
 class FreeBusyQuery (CalDAVElement):
     """
     CalDAV report used to generate a VFREEBUSY to determine busy time over a
@@ -824,6 +897,8 @@
 
         self.timerange  = timerange
 
+
+ at registerElement
 class ReadFreeBusy(CalDAVEmptyElement):
     """
     Privilege which allows the free busy report to be executed.
@@ -831,6 +906,8 @@
     """
     name = "read-free-busy"
     
+
+ at registerElement
 class NoUIDConflict(CalDAVElement):
     """
     CalDAV precondition used to indicate a UID conflict during PUT/COPY/MOVE.
@@ -838,8 +915,10 @@
     """
     name = "no-uid-conflict"
 
-    allowed_children = { (davxml.dav_namespace, "href"): (1, 1) }
+    allowed_children = { (dav_namespace, "href"): (1, 1) }
     
+
+ at registerElement
 class SupportedFilter(CalDAVElement):
     """
     CalDAV precondition used to indicate an unsupported component type in a
@@ -858,6 +937,7 @@
 # CalDAV Schedule objects
 ##
 
+ at registerElement
 class CalendarUserAddressSet (CalDAVElement):
     """
     The list of calendar user addresses for this principal's calendar user.
@@ -866,8 +946,10 @@
     name = "calendar-user-address-set"
     hidden = True
 
-    allowed_children = { (davxml.dav_namespace, "href"): (0, None) }
+    allowed_children = { (dav_namespace, "href"): (0, None) }
 
+
+ at registerElement
 class CalendarFreeBusySet (CalDAVElement):
     """
     The list of calendar URIs that contribute to free-busy for this principal's calendar user.
@@ -877,8 +959,10 @@
     name = "calendar-free-busy-set"
     hidden = True
 
-    allowed_children = { (davxml.dav_namespace, "href"): (0, None) }
+    allowed_children = { (dav_namespace, "href"): (0, None) }
 
+
+ at registerElement
 class ScheduleCalendarTransp (CalDAVElement):
     """
     Indicates whether a calendar should be used for freebusy lookups.
@@ -890,26 +974,34 @@
         (caldav_namespace,     "transparent" ): (0, 1),
     }
 
+
+ at registerElement
 class Opaque (CalDAVEmptyElement):
     """
     Indicates that a calendar is used in freebusy lookups.
     """
     name = "opaque"
 
+
+ at registerElement
 class Transparent (CalDAVEmptyElement):
     """
     Indicates that a calendar is not used in freebusy lookups.
     """
     name = "transparent"
 
+
+ at registerElement
 class ScheduleDefaultCalendarURL (CalDAVElement):
     """
     A single href indicating which calendar is the default for scheduling.
     """
     name = "schedule-default-calendar-URL"
 
-    allowed_children = { (davxml.dav_namespace, "href"): (0, 1) }
+    allowed_children = { (dav_namespace, "href"): (0, 1) }
 
+
+ at registerElement
 class ScheduleInboxURL (CalDAVElement):
     """
     A principal property to indicate the schedule INBOX for the principal.
@@ -919,8 +1011,10 @@
     hidden = True
     protected = True
 
-    allowed_children = { (davxml.dav_namespace, "href"): (0, 1) }
+    allowed_children = { (dav_namespace, "href"): (0, 1) }
 
+
+ at registerElement
 class ScheduleOutboxURL (CalDAVElement):
     """
     A principal property to indicate the schedule OUTBOX for the principal.
@@ -930,8 +1024,10 @@
     hidden = True
     protected = True
 
-    allowed_children = { (davxml.dav_namespace, "href"): (0, 1) }
+    allowed_children = { (dav_namespace, "href"): (0, 1) }
 
+
+ at registerElement
 class Originator (CalDAVElement):
     """
     A property on resources in schedule Inbox and Outbox indicating the Originator used
@@ -942,8 +1038,10 @@
     hidden = True
     protected = True
 
-    allowed_children = { (davxml.dav_namespace, "href"): (0, 1) } # NB Minimum is zero because this is a property name
+    allowed_children = { (dav_namespace, "href"): (0, 1) } # NB Minimum is zero because this is a property name
 
+
+ at registerElement
 class Recipient (CalDAVElement):
     """
     A property on resources in schedule Inbox indicating the Recipients targeted
@@ -957,8 +1055,10 @@
     hidden = True
     protected = True
 
-    allowed_children = { (davxml.dav_namespace, "href"): (0, None) } # NB Minimum is zero because this is a property name
+    allowed_children = { (dav_namespace, "href"): (0, None) } # NB Minimum is zero because this is a property name
 
+
+ at registerElement
 class ScheduleTag (CalDAVTextElement):
     """
     Property on scheduling resources.
@@ -968,6 +1068,8 @@
     hidden = True
     protected = True
 
+
+ at registerElement
 class ScheduleInbox (CalDAVEmptyElement):
     """
     Denotes the resource type of a calendar schedule Inbox.
@@ -975,6 +1077,8 @@
     """
     name = "schedule-inbox"
 
+
+ at registerElement
 class ScheduleOutbox (CalDAVEmptyElement):
     """
     Denotes the resource type of a calendar schedule Outbox.
@@ -982,6 +1086,8 @@
     """
     name = "schedule-outbox"
 
+
+ at registerElement
 class ScheduleResponse (CalDAVElement):
     """
     The set of responses for a SCHEDULE method operation.
@@ -991,6 +1097,8 @@
 
     allowed_children = { (caldav_namespace, "response"): (0, None) }
 
+
+ at registerElement
 class Response (CalDAVElement):
     """
     A response to an iTIP request against a specific recipient.
@@ -999,13 +1107,15 @@
     name = "response"
 
     allowed_children = {
-        (caldav_namespace,     "recipient"          ): (1, 1),
-        (caldav_namespace,     "request-status"     ): (1, 1),
-        (caldav_namespace,     "calendar-data"      ): (0, 1),
-        (davxml.dav_namespace, "error"              ): (0, 1),        # 2518bis
-        (davxml.dav_namespace, "responsedescription"): (0, 1)
+        (caldav_namespace, "recipient"          ): (1, 1),
+        (caldav_namespace, "request-status"     ): (1, 1),
+        (caldav_namespace, "calendar-data"      ): (0, 1),
+        (dav_namespace,    "error"              ): (0, 1),  # 2518bis
+        (dav_namespace,    "responsedescription"): (0, 1)
     }
 
+
+ at registerElement
 class RequestStatus (CalDAVTextElement):
     """
     The iTIP REQUEST-STATUS value for the iTIP operation.
@@ -1013,6 +1123,8 @@
     """
     name = "request-status"
 
+
+ at registerElement
 class Schedule (CalDAVEmptyElement):
     """
     Privilege which allows the SCHEDULE method to be executed.
@@ -1020,6 +1132,8 @@
     """
     name = "schedule"
     
+
+ at registerElement
 class ScheduleDeliver (CalDAVEmptyElement):
     """
     Privilege which controls scheduling messages going into the Inbox.
@@ -1027,6 +1141,8 @@
     """
     name = "schedule-deliver"
     
+
+ at registerElement
 class ScheduleSend (CalDAVEmptyElement):
     """
     Privilege which controls the ability to send scheduling messages.
@@ -1034,6 +1150,8 @@
     """
     name = "schedule-send"
     
+
+ at registerElement
 class CalendarUserType (CalDAVTextElement):
     """
     The CALDAV:calendar-user-type property from section 9.2.4 of caldav-sched-05
@@ -1041,6 +1159,7 @@
     name = "calendar-user-type"
     protected = True
 
+
 ##
 # draft-daboo-valarm-extensions
 ##
@@ -1049,6 +1168,7 @@
     "calendar-default-alarms",
 )
 
+
 class DefaultAlarmBase (CalDAVTextElement):
     """
     Common behavior for default alarm properties.
@@ -1089,10 +1209,10 @@
         
         return True
 
+
+ at registerElement
 class DefaultAlarmVEventDateTime (DefaultAlarmBase):
-
     name = "default-alarm-vevent-datetime"
-
     calendartxt = """
 BEGIN:VCALENDAR
 VERSION:2.0
@@ -1107,10 +1227,10 @@
 END:VCALENDAR
 """
     
+
+ at registerElement
 class DefaultAlarmVEventDate (DefaultAlarmBase):
-
     name = "default-alarm-vevent-date"
-
     calendartxt = """
 BEGIN:VCALENDAR
 VERSION:2.0
@@ -1125,11 +1245,10 @@
 END:VCALENDAR
 """
     
+
+ at registerElement
 class DefaultAlarmVToDoDateTime (DefaultAlarmBase):
-
     name = "default-alarm-vtodo-datetime"
-    
-
     calendartxt = """
 BEGIN:VCALENDAR
 VERSION:2.0
@@ -1143,10 +1262,10 @@
 END:VCALENDAR
 """
 
+
+ at registerElement
 class DefaultAlarmVToDoDate (DefaultAlarmBase):
-
     name = "default-alarm-vtodo-date"
-    
     calendartxt = """
 BEGIN:VCALENDAR
 VERSION:2.0
@@ -1160,12 +1279,14 @@
 END:VCALENDAR
 """
 
+
 ##
-# Extensions to davxml.ResourceType
+# Extensions to ResourceType
 ##
 
 def _isCalendar(self): return bool(self.childrenOfType(Calendar))
-davxml.ResourceType.isCalendar = _isCalendar
-davxml.ResourceType.calendar = davxml.ResourceType(davxml.Collection(), Calendar())
-davxml.ResourceType.scheduleInbox = davxml.ResourceType(davxml.Collection(), ScheduleInbox())
-davxml.ResourceType.scheduleOutbox = davxml.ResourceType(davxml.Collection(), ScheduleOutbox())
+ResourceType.isCalendar = _isCalendar
+
+ResourceType.calendar       = ResourceType(Collection(), Calendar())
+ResourceType.scheduleInbox  = ResourceType(Collection(), ScheduleInbox())
+ResourceType.scheduleOutbox = ResourceType(Collection(), ScheduleOutbox())

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/carddavxml.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/carddavxml.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/carddavxml.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -25,7 +25,11 @@
 See draft spec: 
 """
 
-from twext.web2.dav import davxml
+from txdav.xml.element import registerElement, dav_namespace
+from txdav.xml.element import WebDAVElement, PCDATAElement
+from txdav.xml.element import WebDAVEmptyElement, WebDAVTextElement
+from txdav.xml.element import ResourceType, Collection
+
 from twistedcaldav.vcard import Component
 
 ##
@@ -38,24 +42,29 @@
     "addressbook",
 )
 
-class CardDAVElement (davxml.WebDAVElement):
+
+class CardDAVElement (WebDAVElement):
     """
     CardDAV XML element.
     """
     namespace = carddav_namespace
 
-class CardDAVEmptyElement (davxml.WebDAVEmptyElement):
+
+class CardDAVEmptyElement (WebDAVEmptyElement):
     """
     CardDAV element with no contents.
     """
     namespace = carddav_namespace
 
-class CardDAVTextElement (davxml.WebDAVTextElement):
+
+class CardDAVTextElement (WebDAVTextElement):
     """
     CardDAV element containing PCDATA.
     """
     namespace = carddav_namespace
 
+
+ at registerElement
 class AddressBookHomeSet (CardDAVElement):
     """
     The address book collections URLs for this principal.
@@ -64,8 +73,10 @@
     name = "addressbook-home-set"
     hidden = True
 
-    allowed_children = { (davxml.dav_namespace, "href"): (0, None) }
+    allowed_children = { (dav_namespace, "href"): (0, None) }
 
+
+ at registerElement
 class AddressBookDescription (CardDAVTextElement):
     """
     Provides a human-readable description of what this address book collection
@@ -76,6 +87,8 @@
     hidden = True
     # May be protected; but we'll let the client set this if they like.
 
+
+ at registerElement
 class SupportedAddressData (CardDAVElement):
     """
     Specifies restrictions on an address book collection.
@@ -87,6 +100,8 @@
 
     allowed_children = { (carddav_namespace, "address-data-type"): (0, None) }
 
+
+ at registerElement
 class MaxResourceSize (CardDAVTextElement):
     """
     Specifies restrictions on an address book collection.
@@ -96,6 +111,8 @@
     hidden = True
     protected = True
 
+
+ at registerElement
 class AddressBook (CardDAVEmptyElement):
     """
     Denotes an address book collection.
@@ -103,6 +120,8 @@
     """
     name = "addressbook"
 
+
+ at registerElement
 class AddressBookQuery (CardDAVElement):
     """
     Defines a report for querying address book data.
@@ -111,11 +130,11 @@
     name = "addressbook-query"
 
     allowed_children = {
-        (davxml.dav_namespace, "allprop" ): (0, None),
-        (davxml.dav_namespace, "propname"): (0, None),
-        (davxml.dav_namespace, "prop"    ): (0, None),
-        (carddav_namespace,    "filter"  ): (0, 1), # Actually (1, 1) unless element is empty
-        (carddav_namespace,    "limit"    ): (0, None),
+        (dav_namespace,     "allprop" ): (0, None),
+        (dav_namespace,     "propname"): (0, None),
+        (dav_namespace,     "prop"    ): (0, None),
+        (carddav_namespace, "filter"  ): (0, 1), # Actually (1, 1) unless element is empty
+        (carddav_namespace, "limit"    ): (0, None),
     }
 
     def __init__(self, *children, **attributes):
@@ -129,9 +148,9 @@
             qname = child.qname()
 
             if qname in (
-                (davxml.dav_namespace, "allprop" ),
-                (davxml.dav_namespace, "propname"),
-                (davxml.dav_namespace, "prop"    ),
+                (dav_namespace, "allprop" ),
+                (dav_namespace, "propname"),
+                (dav_namespace, "prop"    ),
             ):
                 if props is not None:
                     raise ValueError("Only one of CardDAV:allprop, CardDAV:propname, CardDAV:prop allowed")
@@ -155,6 +174,8 @@
         self.filter = filter
         self.limit = limit
 
+
+ at registerElement
 class AddressDataType (CardDAVEmptyElement):
     """
     Defines which parts of a address component object should be returned by a
@@ -168,6 +189,8 @@
         "version"     : False,
     }
 
+
+ at registerElement
 class AddressData (CardDAVElement):
     """
     Defines which parts of a address component object should be returned by a
@@ -178,8 +201,8 @@
 
     allowed_children = {
         (carddav_namespace, "allprop"): (0, 1),
-        (carddav_namespace, "prop"): (0, None),
-        davxml.PCDATAElement:        (0, None),
+        (carddav_namespace, "prop"   ): (0, None),
+        PCDATAElement                 : (0, None),
     }
     allowed_attributes = {
         "content-type": False,
@@ -189,7 +212,7 @@
     @classmethod
     def fromAddress(clazz, address):
         assert address.name() == "VCARD", "Not a vCard: %r" % (address,)
-        return clazz(davxml.PCDATAElement(str(address)))
+        return clazz(PCDATAElement(str(address)))
 
     @classmethod
     def fromAddressData(clazz, addressdata):
@@ -198,7 +221,7 @@
         @param addressdata: a string of valid address data.
         @return: a L{Addressata} element.
         """
-        return clazz(davxml.PCDATAElement(addressdata))
+        return clazz(PCDATAElement(addressdata))
 
     fromTextData = fromAddressData
 
@@ -227,7 +250,7 @@
                     else:
                         raise ValueError("CardDAV:allprop and CardDAV:prop may not be combined")
 
-            elif isinstance(child, davxml.PCDATAElement):
+            elif isinstance(child, PCDATAElement):
                 if data is None:
                     data = child
                 else:
@@ -289,7 +312,7 @@
         Returns an address component derived from this element.
         """
         for data in self.children:
-            if not isinstance(data, davxml.PCDATAElement):
+            if not isinstance(data, PCDATAElement):
                 return None
             else:
                 # We guaranteed in __init__() that there is only one child...
@@ -299,6 +322,8 @@
 
     textData = addressData
 
+
+ at registerElement
 class AllProperties (CardDAVEmptyElement):
     """
     Specifies that all properties shall be returned.
@@ -306,6 +331,8 @@
     """
     name = "allprop"
 
+
+ at registerElement
 class Property (CardDAVEmptyElement):
     """
     Defines a property to return in a response.
@@ -334,6 +361,8 @@
         else:
             self.novalue = False
 
+
+ at registerElement
 class Filter (CardDAVElement):
     """
     Determines which matching components are returned.
@@ -344,6 +373,8 @@
     allowed_children = { (carddav_namespace, "prop-filter"): (0, None) }
     allowed_attributes = { "test": False }
         
+
+ at registerElement
 class PropertyFilter (CardDAVElement):
     """
     Limits a search to specific properties.
@@ -361,6 +392,8 @@
         "test": False,
     }
 
+
+ at registerElement
 class ParameterFilter (CardDAVElement):
     """
     Limits a search to specific parameters.
@@ -374,7 +407,9 @@
     }
     allowed_attributes = { "name": True }
 
-class Limit (davxml.WebDAVElement):
+
+ at registerElement
+class Limit (WebDAVElement):
     """
     Client supplied limit for reports.
     """
@@ -384,7 +419,9 @@
         (carddav_namespace, "nresults" )  : (1, 1),
     }
 
-class NResults (davxml.WebDAVTextElement):
+
+ at registerElement
+class NResults (WebDAVTextElement):
     """
     Number of results limit.
     """
@@ -392,6 +429,8 @@
     name = "nresults"
 
 
+
+ at registerElement
 class IsNotDefined (CardDAVEmptyElement):
     """
     Specifies that the named vCard item does not exist.
@@ -399,6 +438,8 @@
     """
     name = "is-not-defined"
 
+
+ at registerElement
 class TextMatch (CardDAVTextElement):
     """
     Specifies a substring match on a property or parameter value.
@@ -408,11 +449,11 @@
 
     def fromString(clazz, string): #@NoSelf
         if type(string) is str:
-            return clazz(davxml.PCDATAElement(string))
+            return clazz(PCDATAElement(string))
         elif type(string) is unicode:
-            return clazz(davxml.PCDATAElement(string.encode("utf-8")))
+            return clazz(PCDATAElement(string.encode("utf-8")))
         else:
-            return clazz(davxml.PCDATAElement(str(string)))
+            return clazz(PCDATAElement(str(string)))
 
     fromString = classmethod(fromString)
 
@@ -422,6 +463,8 @@
         "match-type": False
     }
 
+
+ at registerElement
 class AddressBookMultiGet (CardDAVElement):
     """
     CardDAV report used to retrieve specific vCard items via their URIs.
@@ -432,10 +475,10 @@
     # To allow for an empty element in a supported-report-set property we need
     # to relax the child restrictions
     allowed_children = {
-        (davxml.dav_namespace, "allprop" ): (0, 1),
-        (davxml.dav_namespace, "propname"): (0, 1),
-        (davxml.dav_namespace, "prop"    ): (0, 1),
-        (davxml.dav_namespace, "href"    ): (0, None),    # Actually ought to be (1, None)
+        (dav_namespace, "allprop" ): (0, 1),
+        (dav_namespace, "propname"): (0, 1),
+        (dav_namespace, "prop"    ): (0, 1),
+        (dav_namespace, "href"    ): (0, None),    # Actually ought to be (1, None)
     }
 
     def __init__(self, *children, **attributes):
@@ -448,20 +491,22 @@
             qname = child.qname()
 
             if qname in (
-                (davxml.dav_namespace, "allprop" ),
-                (davxml.dav_namespace, "propname"),
-                (davxml.dav_namespace, "prop"    ),
+                (dav_namespace, "allprop" ),
+                (dav_namespace, "propname"),
+                (dav_namespace, "prop"    ),
             ):
                 if property is not None:
                     raise ValueError("Only one of DAV:allprop, DAV:propname, DAV:prop allowed")
                 property = child
 
-            elif qname == (davxml.dav_namespace, "href"):
+            elif qname == (dav_namespace, "href"):
                 resources.append(child)
 
         self.property  = property
         self.resources = resources
 
+
+ at registerElement
 class NoUIDConflict(CardDAVElement):
     """
     CardDAV precondition used to indicate a UID conflict during PUT/COPY/MOVE.
@@ -469,8 +514,10 @@
     """
     name = "no-uid-conflict"
 
-    allowed_children = { (davxml.dav_namespace, "href"): (1, 1) }
+    allowed_children = { (dav_namespace, "href"): (1, 1) }
     
+
+ at registerElement
 class SupportedFilter(CardDAVElement):
     """
     CardDAV precondition used to indicate an unsupported component type in a
@@ -484,6 +531,8 @@
         (carddav_namespace, "param-filter"): (0, None)
     }
     
+
+ at registerElement
 class DirectoryGateway(CardDAVElement):
     """
     CardDAV property on a principal to indicate where the directory gateway resource is.
@@ -492,27 +541,32 @@
     hidden = True
     protected = True
 
-    allowed_children = { (davxml.dav_namespace, "href"): (0, None) }
+    allowed_children = { (dav_namespace, "href"): (0, None) }
     
+
+ at registerElement
 class Directory(CardDAVEmptyElement):
     """
     CardDAV property on a principal to indicate where the directory resource is.
     """
     name = "directory"
     
+
+ at registerElement
 class DefaultAddressBookURL (CardDAVElement):
     """
     A single href indicating which addressbook is the default.
     """
     name = "default-addressbook-URL"
 
-    allowed_children = { (davxml.dav_namespace, "href"): (0, 1) }
+    allowed_children = { (dav_namespace, "href"): (0, 1) }
 
 ##
-# Extensions to davxml.ResourceType
+# Extensions to ResourceType
 ##
 
 def _isAddressBook(self): return bool(self.childrenOfType(AddressBook))
-davxml.ResourceType.isAddressBook = _isAddressBook
-davxml.ResourceType.addressbook = davxml.ResourceType(davxml.Collection(), AddressBook())
-davxml.ResourceType.directory = davxml.ResourceType(davxml.Collection(), AddressBook(), Directory())
+ResourceType.isAddressBook = _isAddressBook
+
+ResourceType.addressbook = ResourceType(Collection(), AddressBook())
+ResourceType.directory   = ResourceType(Collection(), AddressBook(), Directory())

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/customxml.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/customxml.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/customxml.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -23,16 +23,19 @@
 change.
 """
 
-from twext.web2.dav.davxml import dav_namespace
-from twext.web2.dav.davxml import twisted_dav_namespace
-from twext.web2.dav.element.base import twisted_private_namespace
-from twext.web2.dav import davxml
+from txdav.xml.element import registerElement, dav_namespace
+from txdav.xml.element import twisted_dav_namespace, twisted_private_namespace
+from txdav.xml.element import WebDAVElement, PCDATAElement
+from txdav.xml.element import WebDAVEmptyElement, WebDAVTextElement
+from txdav.xml.element import PrincipalPropertySearch, Match
+from txdav.xml.element import ResourceType, Collection, Principal
 
 from twistedcaldav import caldavxml, carddavxml
 from twistedcaldav.ical import Component as iComponent
 
 from pycalendar.datetime import PyCalendarDateTime
 
+
 calendarserver_namespace = "http://calendarserver.org/ns/"
 
 calendarserver_proxy_compliance = (
@@ -60,7 +63,9 @@
     "calendarserver-sharing-no-scheduling",
 )
 
-class TwistedCalendarSupportedComponents (davxml.WebDAVTextElement):
+
+ at registerElement
+class TwistedCalendarSupportedComponents (WebDAVTextElement):
     """
     Contains the calendar supported components list.
     """
@@ -71,7 +76,9 @@
     def getValue(self):
         return str(self)
 
-class TwistedCalendarAccessProperty (davxml.WebDAVTextElement):
+
+ at registerElement
+class TwistedCalendarAccessProperty (WebDAVTextElement):
     """
     Contains the calendar access level (private events) for the resource.
     """
@@ -82,7 +89,9 @@
     def getValue(self):
         return str(self)
 
-class TwistedSchedulingObjectResource (davxml.WebDAVTextElement):
+
+ at registerElement
+class TwistedSchedulingObjectResource (WebDAVTextElement):
     """
     Indicates that the resource is a scheduling object resource.    
     """
@@ -90,7 +99,9 @@
     name = "scheduling-object-resource"
     hidden = True
 
-class TwistedScheduleMatchETags(davxml.WebDAVElement):
+
+ at registerElement
+class TwistedScheduleMatchETags(WebDAVElement):
     """
     List of ETags that can be used for a "weak" If-Match comparison.    
     """
@@ -100,7 +111,9 @@
 
     allowed_children = { (dav_namespace, "getetag"): (0, None) }
 
-class TwistedCalendarHasPrivateCommentsProperty (davxml.WebDAVEmptyElement):
+
+ at registerElement
+class TwistedCalendarHasPrivateCommentsProperty (WebDAVEmptyElement):
     """
     Indicates that a calendar resource has private comments.
     
@@ -112,7 +125,9 @@
     name = "calendar-has-private-comments"
     hidden = True
 
-class CalendarProxyRead (davxml.WebDAVEmptyElement):
+
+ at registerElement
+class CalendarProxyRead (WebDAVEmptyElement):
     """
     A read-only calendar user proxy principal resource.
     (Apple Extension to CalDAV)
@@ -120,7 +135,9 @@
     namespace = calendarserver_namespace
     name = "calendar-proxy-read"
 
-class CalendarProxyWrite (davxml.WebDAVEmptyElement):
+
+ at registerElement
+class CalendarProxyWrite (WebDAVEmptyElement):
     """
     A read-write calendar user proxy principal resource.
     (Apple Extension to CalDAV)
@@ -128,7 +145,9 @@
     namespace = calendarserver_namespace
     name = "calendar-proxy-write"
 
-class CalendarProxyReadFor (davxml.WebDAVElement):
+
+ at registerElement
+class CalendarProxyReadFor (WebDAVElement):
     """
     List of principals granting read-only proxy status.
     (Apple Extension to CalDAV)
@@ -140,7 +159,9 @@
 
     allowed_children = { (dav_namespace, "href"): (0, None) }
 
-class CalendarProxyWriteFor (davxml.WebDAVElement):
+
+ at registerElement
+class CalendarProxyWriteFor (WebDAVElement):
     """
     List of principals granting read-write proxy status.
     (Apple Extension to CalDAV)
@@ -152,7 +173,9 @@
 
     allowed_children = { (dav_namespace, "href"): (0, None) }
 
-class DropBoxHome (davxml.WebDAVEmptyElement):
+
+ at registerElement
+class DropBoxHome (WebDAVEmptyElement):
     """
     Denotes a drop box home collection (a collection that will contain drop boxes).
     (Apple Extension to CalDAV)
@@ -160,7 +183,9 @@
     namespace = calendarserver_namespace
     name = "dropbox-home"
 
-class DropBox (davxml.WebDAVEmptyElement):
+
+ at registerElement
+class DropBox (WebDAVEmptyElement):
     """
     Denotes a drop box collection.
     (Apple Extension to CalDAV)
@@ -168,7 +193,9 @@
     namespace = calendarserver_namespace
     name = "dropbox"
 
-class DropBoxHomeURL (davxml.WebDAVElement):
+
+ at registerElement
+class DropBoxHomeURL (WebDAVElement):
     """
     A principal property to indicate the location of the drop box home.
     (Apple Extension to CalDAV)
@@ -178,9 +205,11 @@
     hidden = True
     protected = True
 
-    allowed_children = { (davxml.dav_namespace, "href"): (0, 1) }
+    allowed_children = { (dav_namespace, "href"): (0, 1) }
 
-class GETCTag (davxml.WebDAVTextElement):
+
+ at registerElement
+class GETCTag (WebDAVTextElement):
     """
     Contains the calendar collection entity tag.
     """
@@ -188,7 +217,9 @@
     name = "getctag"
     protected = True
 
-class CalendarAvailability (davxml.WebDAVTextElement):
+
+ at registerElement
+class CalendarAvailability (WebDAVTextElement):
     """
     Contains the calendar availability property.
     """
@@ -232,7 +263,9 @@
 
         return found
 
-class MaxCollections (davxml.WebDAVTextElement):
+
+ at registerElement
+class MaxCollections (WebDAVTextElement):
     """
     Maximum number of child collections in a home collection
     """
@@ -241,7 +274,9 @@
     hidden = True
     protected = True
 
-class MaxResources (davxml.WebDAVTextElement):
+
+ at registerElement
+class MaxResources (WebDAVTextElement):
     """
     Maximum number of child resources in a collection
     """
@@ -250,7 +285,9 @@
     hidden = True
     protected = True
 
-class Timezones (davxml.WebDAVEmptyElement):
+
+ at registerElement
+class Timezones (WebDAVEmptyElement):
     """
     Denotes a timezone service resource.
     (Apple Extension to CalDAV)
@@ -258,7 +295,9 @@
     namespace = calendarserver_namespace
     name = "timezones"
 
-class TZIDs (davxml.WebDAVElement):
+
+ at registerElement
+class TZIDs (WebDAVElement):
     """
     Wraps a list of timezone ids.
     """
@@ -266,14 +305,18 @@
     name = "tzids"
     allowed_children = { (calendarserver_namespace, "tzid" ): (0, None) }
 
-class TZID (davxml.WebDAVTextElement):
+
+ at registerElement
+class TZID (WebDAVTextElement):
     """
     A timezone id.
     """
     namespace = calendarserver_namespace
     name = "tzid"
 
-class TZData (davxml.WebDAVElement):
+
+ at registerElement
+class TZData (WebDAVElement):
     """
     Wraps a list of timezone observances.
     """
@@ -281,7 +324,9 @@
     name = "tzdata"
     allowed_children = { (calendarserver_namespace, "observance" ): (0, None) }
 
-class Observance (davxml.WebDAVElement):
+
+ at registerElement
+class Observance (WebDAVElement):
     """
     A timezone observance.
     """
@@ -292,21 +337,27 @@
         (calendarserver_namespace, "utc-offset" ): (1, 1),
     }
 
-class Onset (davxml.WebDAVTextElement):
+
+ at registerElement
+class Onset (WebDAVTextElement):
     """
     The onset date-time for a DST transition.
     """
     namespace = calendarserver_namespace
     name = "onset"
 
-class UTCOffset (davxml.WebDAVTextElement):
+
+ at registerElement
+class UTCOffset (WebDAVTextElement):
     """
     A UTC offset value for a timezone observance.
     """
     namespace = calendarserver_namespace
     name = "utc-offset"
 
-class PubSubPushTransportsProperty (davxml.WebDAVTextElement):
+
+ at registerElement
+class PubSubPushTransportsProperty (WebDAVTextElement):
     """
     A calendar property describing the available push notification transports
     available.
@@ -319,7 +370,9 @@
         (calendarserver_namespace, "transport") : (0, 1),
     }
 
-class PubSubTransportProperty (davxml.WebDAVTextElement):
+
+ at registerElement
+class PubSubTransportProperty (WebDAVTextElement):
     namespace = calendarserver_namespace
     name = "transport"
     protected = True
@@ -335,32 +388,42 @@
         (calendarserver_namespace, "xmpp-uri") : (1, 1),
     }
 
-class PubSubSubscriptionProperty (davxml.WebDAVTextElement):
+
+ at registerElement
+class PubSubSubscriptionProperty (WebDAVTextElement):
     namespace = calendarserver_namespace
     name = "subscription-url"
     protected = True
     hidden = True
-    allowed_children = { (davxml.dav_namespace, "href"): (0, 1) }
+    allowed_children = { (dav_namespace, "href"): (0, 1) }
 
-class PubSubAPSBundleIDProperty (davxml.WebDAVTextElement):
+
+ at registerElement
+class PubSubAPSBundleIDProperty (WebDAVTextElement):
     namespace = calendarserver_namespace
     name = "apsbundleid"
     protected = True
     hidden = True
 
-class PubSubAPSEnvironmentProperty (davxml.WebDAVTextElement):
+
+ at registerElement
+class PubSubAPSEnvironmentProperty (WebDAVTextElement):
     namespace = calendarserver_namespace
     name = "env"
     protected = True
     hidden = True
 
-class PubSubXMPPPushKeyProperty (davxml.WebDAVTextElement):
+
+ at registerElement
+class PubSubXMPPPushKeyProperty (WebDAVTextElement):
     namespace = calendarserver_namespace
     name = "pushkey"
     protected = True
     hidden = True
 
-class PubSubXMPPURIProperty (davxml.WebDAVTextElement):
+
+ at registerElement
+class PubSubXMPPURIProperty (WebDAVTextElement):
     """
     A calendar home property to indicate the pubsub XMPP URI to subscribe to
     for notifications.
@@ -370,7 +433,9 @@
     protected = True
     hidden = True
 
-class PubSubHeartbeatProperty (davxml.WebDAVElement):
+
+ at registerElement
+class PubSubHeartbeatProperty (WebDAVElement):
     """
     A calendar home property to indicate the pubsub XMPP URI to subscribe to
     for server heartbeats.
@@ -384,19 +449,25 @@
         (calendarserver_namespace, "xmpp-heartbeat-minutes" ) : (1, 1),
     }
 
-class PubSubHeartbeatURIProperty (davxml.WebDAVTextElement):
+
+ at registerElement
+class PubSubHeartbeatURIProperty (WebDAVTextElement):
     namespace = calendarserver_namespace
     name = "xmpp-heartbeat-uri"
     protected = True
     hidden = True
 
-class PubSubHeartbeatMinutesProperty (davxml.WebDAVTextElement):
+
+ at registerElement
+class PubSubHeartbeatMinutesProperty (WebDAVTextElement):
     namespace = calendarserver_namespace
     name = "xmpp-heartbeat-minutes"
     protected = True
     hidden = True
 
-class PubSubXMPPServerProperty (davxml.WebDAVTextElement):
+
+ at registerElement
+class PubSubXMPPServerProperty (WebDAVTextElement):
     """
     A calendar home property to indicate the pubsub XMPP hostname to
     contact for notifications.
@@ -406,14 +477,17 @@
     protected = True
     hidden = True
 
-davxml.PrincipalPropertySearch.allowed_children[(calendarserver_namespace, "limit")] = (0, 1)
-davxml.PrincipalPropertySearch.allowed_attributes["type"] = False
-davxml.Match.allowed_attributes = {
+
+PrincipalPropertySearch.allowed_children[(calendarserver_namespace, "limit")] = (0, 1)
+PrincipalPropertySearch.allowed_attributes["type"] = False
+Match.allowed_attributes = {
     "caseless": False,
     "match-type": False,
 }
 
-class Limit (davxml.WebDAVElement):
+
+ at registerElement
+class Limit (WebDAVElement):
     """
     Client supplied limit for reports.
     """
@@ -423,14 +497,18 @@
         (calendarserver_namespace, "nresults" )  : (1, 1),
     }
 
-class NResults (davxml.WebDAVTextElement):
+
+ at registerElement
+class NResults (WebDAVTextElement):
     """
     Number of results limit.
     """
     namespace = calendarserver_namespace
     name = "nresults"
 
-class FirstNameProperty (davxml.WebDAVTextElement):
+
+ at registerElement
+class FirstNameProperty (WebDAVTextElement):
     """
     A property representing first name of a principal
     """
@@ -439,7 +517,9 @@
     protected = True
     hidden = True
 
-class LastNameProperty (davxml.WebDAVTextElement):
+
+ at registerElement
+class LastNameProperty (WebDAVTextElement):
     """
     A property representing last name of a principal
     """
@@ -448,7 +528,9 @@
     protected = True
     hidden = True
 
-class EmailAddressProperty (davxml.WebDAVTextElement):
+
+ at registerElement
+class EmailAddressProperty (WebDAVTextElement):
     """
     A property representing email address of a principal
     """
@@ -457,7 +539,9 @@
     protected = True
     hidden = True
 
-class EmailAddressSet (davxml.WebDAVElement):
+
+ at registerElement
+class EmailAddressSet (WebDAVElement):
     """
     The list of email addresses of a principal
     """
@@ -467,7 +551,9 @@
 
     allowed_children = { (calendarserver_namespace, "email-address"): (0, None) }
 
-class ExpandedGroupMemberSet (davxml.WebDAVElement):
+
+ at registerElement
+class ExpandedGroupMemberSet (WebDAVElement):
     """
     The expanded list of members of a (group) principal
     """
@@ -478,7 +564,9 @@
 
     allowed_children = { (dav_namespace, "href"): (0, None) }
 
-class ExpandedGroupMembership (davxml.WebDAVElement):
+
+ at registerElement
+class ExpandedGroupMembership (WebDAVElement):
     """
     The expanded list of groups a principal is a member of
     """
@@ -489,7 +577,9 @@
 
     allowed_children = { (dav_namespace, "href"): (0, None) }
 
-class IScheduleInbox (davxml.WebDAVEmptyElement):
+
+ at registerElement
+class IScheduleInbox (WebDAVEmptyElement):
     """
     Denotes the resourcetype of a iSchedule Inbox.
     (CalDAV-s2s-xx, section x.x.x)
@@ -497,7 +587,9 @@
     namespace = calendarserver_namespace
     name = "ischedule-inbox"
 
-class FreeBusyURL (davxml.WebDAVEmptyElement):
+
+ at registerElement
+class FreeBusyURL (WebDAVEmptyElement):
     """
     Denotes the resourcetype of a free-busy URL resource.
     (CalDAV-s2s-xx, section x.x.x)
@@ -505,7 +597,9 @@
     namespace = calendarserver_namespace
     name = "free-busy-url"
 
-class ScheduleChanges (davxml.WebDAVElement):
+
+ at registerElement
+class ScheduleChanges (WebDAVElement):
     """
     Change indicator for a scheduling message.
     """
@@ -518,16 +612,20 @@
         (calendarserver_namespace, "action" )      : (0, 1), # Have to allow 0 as element is empty in PROPFIND requests
     }
 
-class ScheduleDefaultTasksURL (davxml.WebDAVElement):
+
+ at registerElement
+class ScheduleDefaultTasksURL (WebDAVElement):
     """
     A single href indicating which calendar is the default for VTODO scheduling.
     """
     namespace = calendarserver_namespace
     name = "schedule-default-tasks-URL"
 
-    allowed_children = { (davxml.dav_namespace, "href"): (0, 1) }
+    allowed_children = { (dav_namespace, "href"): (0, 1) }
 
-class DTStamp (davxml.WebDAVTextElement):
+
+ at registerElement
+class DTStamp (WebDAVTextElement):
     """
     A UTC timestamp in iCal format.
     """
@@ -536,9 +634,11 @@
 
     def __init__(self, *children):
         super(DTStamp, self).__init__(children)
-        self.children = (davxml.PCDATAElement(PyCalendarDateTime.getNowUTC().getText()),)
+        self.children = (PCDATAElement(PyCalendarDateTime.getNowUTC().getText()),)
 
-class Action (davxml.WebDAVElement):
+
+ at registerElement
+class Action (WebDAVElement):
     """
     A UTC timestamp in iCal format.
     """
@@ -551,14 +651,18 @@
         (calendarserver_namespace, "reply" )  : (0, 1),
     }
 
-class Create (davxml.WebDAVEmptyElement):
+
+ at registerElement
+class Create (WebDAVEmptyElement):
     """
     Event created.
     """
     namespace = calendarserver_namespace
     name = "create"
 
-class Update (davxml.WebDAVElement):
+
+ at registerElement
+class Update (WebDAVElement):
     """
     Event updated.
     """
@@ -568,7 +672,9 @@
         (calendarserver_namespace, "recurrence" ) : (1, None),
     }
 
-class Cancel (davxml.WebDAVElement):
+
+ at registerElement
+class Cancel (WebDAVElement):
     """
     Event cancelled.
     """
@@ -578,7 +684,9 @@
         (calendarserver_namespace, "recurrence" ) : (0, 1),
     }
 
-class Reply (davxml.WebDAVElement):
+
+ at registerElement
+class Reply (WebDAVElement):
     """
     Event replied to.
     """
@@ -589,7 +697,9 @@
         (calendarserver_namespace, "recurrence" )      : (1, None),
     }
 
-class Recurrence (davxml.WebDAVElement):
+
+ at registerElement
+class Recurrence (WebDAVElement):
     """
     Changes to an event.
     """
@@ -601,21 +711,27 @@
         (calendarserver_namespace, "changes" )      : (0, 1),
     }
 
-class Master (davxml.WebDAVEmptyElement):
+
+ at registerElement
+class Master (WebDAVEmptyElement):
     """
     Master instance changed.
     """
     namespace = calendarserver_namespace
     name = "master"
 
-class RecurrenceID (davxml.WebDAVTextElement):
+
+ at registerElement
+class RecurrenceID (WebDAVTextElement):
     """
     A recurrence instance changed.
     """
     namespace = calendarserver_namespace
     name = "recurrenceid"
 
-class Changes (davxml.WebDAVElement):
+
+ at registerElement
+class Changes (WebDAVElement):
     """
     Changes to an event.
     """
@@ -625,7 +741,9 @@
         (calendarserver_namespace, "changed-property" )  : (0, None),
     }
 
-class ChangedProperty (davxml.WebDAVElement):
+
+ at registerElement
+class ChangedProperty (WebDAVElement):
     """
     Changes to a property.
     """
@@ -640,7 +758,9 @@
         "name" : True,
     }
 
-class ChangedParameter (davxml.WebDAVEmptyElement):
+
+ at registerElement
+class ChangedParameter (WebDAVEmptyElement):
     """
     Changes to a parameter.
     """
@@ -651,14 +771,18 @@
         "name" : True,
     }
 
-class Attendee (davxml.WebDAVTextElement):
+
+ at registerElement
+class Attendee (WebDAVTextElement):
     """
     An attendee calendar user address.
     """
     namespace = calendarserver_namespace
     name = "attendee"
 
-class RecordType (davxml.WebDAVTextElement):
+
+ at registerElement
+class RecordType (WebDAVTextElement):
     """
     Exposes the type of a record
     """
@@ -667,68 +791,88 @@
     protected = True
     hidden = True
 
-class AutoSchedule (davxml.WebDAVTextElement):
+
+ at registerElement
+class AutoSchedule (WebDAVTextElement):
     """
     Whether the principal automatically accepts invitations
     """
     namespace = calendarserver_namespace
     name = "auto-schedule"
 
-class AutoScheduleMode (davxml.WebDAVTextElement):
+
+ at registerElement
+class AutoScheduleMode (WebDAVTextElement):
     """
     The principal's auto-schedule mode
     """
     namespace = calendarserver_namespace
     name = "auto-schedule-mode"
 
+
 ##
 # Sharing
 ##
 
-class ReadAccess (davxml.WebDAVEmptyElement):
+ at registerElement
+class ReadAccess (WebDAVEmptyElement):
     """
     Denotes read and update attendee partstat on a shared calendar.
     """
     namespace = calendarserver_namespace
     name = "read"
 
-class ReadWriteAccess (davxml.WebDAVEmptyElement):
+
+ at registerElement
+class ReadWriteAccess (WebDAVEmptyElement):
     """
     Denotes read and write access on a shared calendar.
     """
     namespace = calendarserver_namespace
     name = "read-write"
 
-class UID (davxml.WebDAVTextElement):
+
+ at registerElement
+class UID (WebDAVTextElement):
     namespace = calendarserver_namespace
     name = "uid"
 
-class InReplyTo (davxml.WebDAVTextElement):
+
+ at registerElement
+class InReplyTo (WebDAVTextElement):
     namespace = calendarserver_namespace
     name = "in-reply-to"
 
-class SharedOwner (davxml.WebDAVEmptyElement):
+
+ at registerElement
+class SharedOwner (WebDAVEmptyElement):
     """
     Denotes a shared collection.
     """
     namespace = calendarserver_namespace
     name = "shared-owner"
 
-class Shared (davxml.WebDAVEmptyElement):
+
+ at registerElement
+class Shared (WebDAVEmptyElement):
     """
     Denotes a shared collection.
     """
     namespace = calendarserver_namespace
     name = "shared"
 
-class Subscribed (davxml.WebDAVEmptyElement):
+
+ at registerElement
+class Subscribed (WebDAVEmptyElement):
     """
     Denotes a subscribed calendar collection.
     """
     namespace = calendarserver_namespace
     name = "subscribed"
 
-class SharedURL (davxml.WebDAVTextElement):
+
+ at registerElement
+class SharedURL (WebDAVTextElement):
     """
     The source url for a shared calendar.
     """
@@ -737,7 +881,9 @@
     protected = True
     hidden = True
 
-class SharedAs (davxml.WebDAVElement):
+
+ at registerElement
+class SharedAs (WebDAVElement):
     """
     The url for a shared calendar.
     """
@@ -748,21 +894,27 @@
         (dav_namespace, "href")    : (1, 1),
     }
 
-class SharedAcceptEmailNotification (davxml.WebDAVTextElement):
+
+ at registerElement
+class SharedAcceptEmailNotification (WebDAVTextElement):
     """
     The accept email flag for a shared calendar.
     """
     namespace = calendarserver_namespace
     name = "shared-accept-email-notification"
 
-class Birthday (davxml.WebDAVEmptyElement):
+
+ at registerElement
+class Birthday (WebDAVEmptyElement):
     """
     Denotes a birthday calendar collection.
     """
     namespace = calendarserver_namespace
     name = "birthday"
 
-class AllowedSharingModes (davxml.WebDAVElement):
+
+ at registerElement
+class AllowedSharingModes (WebDAVElement):
     namespace = calendarserver_namespace
     name = "allowed-sharing-modes"
     protected = True
@@ -773,15 +925,21 @@
         (calendarserver_namespace, "can-be-published") : (0, 1),
     }
 
-class CanBeShared (davxml.WebDAVEmptyElement):
+
+ at registerElement
+class CanBeShared (WebDAVEmptyElement):
     namespace = calendarserver_namespace
     name = "can-be-shared"
 
-class CanBePublished (davxml.WebDAVEmptyElement):
+
+ at registerElement
+class CanBePublished (WebDAVEmptyElement):
     namespace = calendarserver_namespace
     name = "can-be-published"
 
-class InviteShare (davxml.WebDAVElement):
+
+ at registerElement
+class InviteShare (WebDAVElement):
     namespace = calendarserver_namespace
     name = "share"
 
@@ -790,7 +948,9 @@
         (calendarserver_namespace, "remove") : (0, None),
     }
 
-class InviteSet (davxml.WebDAVElement):
+
+ at registerElement
+class InviteSet (WebDAVElement):
     namespace = calendarserver_namespace
     name = "set"
 
@@ -803,7 +963,9 @@
         (calendarserver_namespace, "read-write-schedule") : (0, 1),
     }
 
-class InviteRemove (davxml.WebDAVElement):
+
+ at registerElement
+class InviteRemove (WebDAVElement):
     namespace = calendarserver_namespace
     name = "remove"
 
@@ -814,7 +976,9 @@
         (calendarserver_namespace, "read-write-schedule") : (0, 1),
     }
 
-class InviteUser (davxml.WebDAVElement):
+
+ at registerElement
+class InviteUser (WebDAVElement):
     namespace = calendarserver_namespace
     name = "user"
 
@@ -831,7 +995,9 @@
         (calendarserver_namespace, "summary")           : (0, 1),
     }
 
-class InviteAccess (davxml.WebDAVElement):
+
+ at registerElement
+class InviteAccess (WebDAVElement):
     namespace = calendarserver_namespace
     name = "access"
 
@@ -841,7 +1007,9 @@
         (calendarserver_namespace, "read-write-schedule") : (0, 1),
     }
 
-class Invite (davxml.WebDAVElement):
+
+ at registerElement
+class Invite (WebDAVElement):
     namespace = calendarserver_namespace
     name = "invite"
 
@@ -849,31 +1017,45 @@
         (calendarserver_namespace, "user") : (0, None),
     }
 
-class InviteSummary (davxml.WebDAVTextElement):
+
+ at registerElement
+class InviteSummary (WebDAVTextElement):
     namespace = calendarserver_namespace
     name = "summary"
 
-class InviteStatusNoResponse (davxml.WebDAVEmptyElement):
+
+ at registerElement
+class InviteStatusNoResponse (WebDAVEmptyElement):
     namespace = calendarserver_namespace
     name = "invite-noresponse"
 
-class InviteStatusDeleted (davxml.WebDAVEmptyElement):
+
+ at registerElement
+class InviteStatusDeleted (WebDAVEmptyElement):
     namespace = calendarserver_namespace
     name = "invite-deleted"
 
-class InviteStatusAccepted (davxml.WebDAVEmptyElement):
+
+ at registerElement
+class InviteStatusAccepted (WebDAVEmptyElement):
     namespace = calendarserver_namespace
     name = "invite-accepted"
 
-class InviteStatusDeclined (davxml.WebDAVEmptyElement):
+
+ at registerElement
+class InviteStatusDeclined (WebDAVEmptyElement):
     namespace = calendarserver_namespace
     name = "invite-declined"
 
-class InviteStatusInvalid (davxml.WebDAVEmptyElement):
+
+ at registerElement
+class InviteStatusInvalid (WebDAVEmptyElement):
     namespace = calendarserver_namespace
     name = "invite-invalid"
 
-class HostURL (davxml.WebDAVElement):
+
+ at registerElement
+class HostURL (WebDAVElement):
     """
     The source for a shared calendar
     """
@@ -884,7 +1066,9 @@
         (dav_namespace, "href") : (0, None)
     }
 
-class Organizer (davxml.WebDAVElement):
+
+ at registerElement
+class Organizer (WebDAVElement):
     """
     The organizer for a shared calendar
     """
@@ -896,14 +1080,18 @@
         (calendarserver_namespace, "common-name")  : (0, 1)
     }
 
-class CommonName (davxml.WebDAVTextElement):
+
+ at registerElement
+class CommonName (WebDAVTextElement):
     """
     Common name for Sharer or Sharee
     """
     namespace = calendarserver_namespace
     name = "common-name"
 
-class InviteNotification (davxml.WebDAVElement):
+
+ at registerElement
+class InviteNotification (WebDAVElement):
     namespace = calendarserver_namespace
     name = "invite-notification"
 
@@ -924,7 +1112,9 @@
         "shared-type" : True,
     }
 
-class InviteReply (davxml.WebDAVElement):
+
+ at registerElement
+class InviteReply (WebDAVElement):
     namespace = calendarserver_namespace
     name = "invite-reply"
 
@@ -937,7 +1127,9 @@
         (calendarserver_namespace, "summary")         : (0, 1),
     }
 
-class ResourceUpdateNotification (davxml.WebDAVElement):
+
+ at registerElement
+class ResourceUpdateNotification (WebDAVElement):
     namespace = calendarserver_namespace
     name = "resource-update-notification"
 
@@ -949,19 +1141,27 @@
         (calendarserver_namespace, "resource-deleted-notification") : (0, 1),
     }
 
-class ResourceUpdateAdded(davxml.WebDAVEmptyElement):
+
+ at registerElement
+class ResourceUpdateAdded(WebDAVEmptyElement):
     namespace = calendarserver_namespace
     name = "resource-added-notification"
 
-class ResourceUpdateUpdated(davxml.WebDAVEmptyElement):
+
+ at registerElement
+class ResourceUpdateUpdated(WebDAVEmptyElement):
     namespace = calendarserver_namespace
     name = "resource-updated-notification"
 
-class ResourceUpdateDeleted(davxml.WebDAVEmptyElement):
+
+ at registerElement
+class ResourceUpdateDeleted(WebDAVEmptyElement):
     namespace = calendarserver_namespace
     name = "resource-deleted-notification"
 
-class SharedCalendarUpdateNotification (davxml.WebDAVElement):
+
+ at registerElement
+class SharedCalendarUpdateNotification (WebDAVElement):
     namespace = calendarserver_namespace
     name = "shared-update-notification"
 
@@ -977,7 +1177,8 @@
 # Notifications
 ##
 
-class Notification (davxml.WebDAVElement):
+ at registerElement
+class Notification (WebDAVElement):
     """
     Denotes a notification collection, or a notification message.
     """
@@ -992,7 +1193,9 @@
         (calendarserver_namespace, "shared-update-notification")    : (0, None),
     }
 
-class NotificationURL (davxml.WebDAVElement):
+
+ at registerElement
+class NotificationURL (WebDAVElement):
     """
     A principal property to indicate the notification collection for the principal.
     """
@@ -1005,7 +1208,9 @@
         (dav_namespace, "href") : (0, 1)
     }
 
-class NotificationType (davxml.WebDAVElement):
+
+ at registerElement
+class NotificationType (WebDAVElement):
     """
     A property to indicate what type of notification the resource represents.
     """
@@ -1019,16 +1224,20 @@
         (calendarserver_namespace, "invite-reply")          : (0, None),
     }
 
-class Link (davxml.WebDAVEmptyElement):
+
+ at registerElement
+class Link (WebDAVEmptyElement):
     """
     Denotes a linked resource.
     """
     namespace = calendarserver_namespace
     name = "link"
 
+
 mm_namespace = "http://me.com/_namespace/"
 
-class Multiput (davxml.WebDAVElement):
+ at registerElement
+class Multiput (WebDAVElement):
     namespace = mm_namespace
     name = "multiput"
 
@@ -1036,32 +1245,40 @@
         (mm_namespace, "resource")   : (1, None),
     }
 
-class Resource (davxml.WebDAVElement):
+
+ at registerElement
+class Resource (WebDAVElement):
     namespace = mm_namespace
     name = "resource"
 
     allowed_children = {
-        (davxml,       "href")     : (0, 1),
-        (mm_namespace, "if-match") : (0, 1),
-        (davxml,       "set")      : (0, 1),
-        (davxml,       "remove")   : (0, 1),
-        (mm_namespace, "delete")   : (0, 1),
+        (dav_namespace, "href")     : (0, 1),
+        (mm_namespace,  "if-match") : (0, 1),
+        (dav_namespace, "set")      : (0, 1),
+        (dav_namespace, "remove")   : (0, 1),
+        (mm_namespace,  "delete")   : (0, 1),
     }
 
-class IfMatch (davxml.WebDAVElement):
+
+ at registerElement
+class IfMatch (WebDAVElement):
     namespace = mm_namespace
     name = "if-match"
 
     allowed_children = {
-        (davxml, "getetag")   : (1, 1),
+        (dav_namespace, "getetag")   : (1, 1),
     }
 
-class Delete (davxml.WebDAVEmptyElement):
+
+ at registerElement
+class Delete (WebDAVEmptyElement):
     namespace = mm_namespace
     name = "delete"
 
 
-class BulkRequests (davxml.WebDAVElement):
+
+ at registerElement
+class BulkRequests (WebDAVElement):
     namespace = mm_namespace
     name = "bulk-requests"
     hidden = True
@@ -1072,7 +1289,9 @@
         (mm_namespace, "crud")     : (0, 1),
     }
 
-class Simple (davxml.WebDAVElement):
+
+ at registerElement
+class Simple (WebDAVElement):
     namespace = mm_namespace
     name = "simple"
     hidden = True
@@ -1083,7 +1302,9 @@
         (mm_namespace, "max-bytes")       : (1, 1),
     }
 
-class CRUD (davxml.WebDAVElement):
+
+ at registerElement
+class CRUD (WebDAVElement):
     namespace = mm_namespace
     name = "crud"
     hidden = True
@@ -1094,11 +1315,15 @@
         (mm_namespace, "max-bytes")       : (1, 1),
     }
 
-class MaxBulkResources (davxml.WebDAVTextElement):
+
+ at registerElement
+class MaxBulkResources (WebDAVTextElement):
     namespace = mm_namespace
     name = "max-resources"
 
-class MaxBulkBytes (davxml.WebDAVTextElement):
+
+ at registerElement
+class MaxBulkBytes (WebDAVTextElement):
     namespace = mm_namespace
     name = "max-bytes"
 
@@ -1107,23 +1332,31 @@
 # Client properties we might care about
 #
 
-class CalendarColor(davxml.WebDAVTextElement):
+ at registerElement
+class CalendarColor(WebDAVTextElement):
     namespace = "http://apple.com/ns/ical/"
     name = "calendar-color"
 
 ##
-# Extensions to davxml.ResourceType
+# Extensions to ResourceType
 ##
 
-davxml.ResourceType.dropboxhome = davxml.ResourceType(davxml.Collection(), DropBoxHome())
-davxml.ResourceType.dropbox = davxml.ResourceType(davxml.Collection(), DropBox())
-davxml.ResourceType.calendarproxyread = davxml.ResourceType(davxml.Principal(), davxml.Collection(), CalendarProxyRead())
-davxml.ResourceType.calendarproxywrite = davxml.ResourceType(davxml.Principal(), davxml.Collection(), CalendarProxyWrite())
-davxml.ResourceType.timezones = davxml.ResourceType(Timezones())
-davxml.ResourceType.ischeduleinbox = davxml.ResourceType(IScheduleInbox())
-davxml.ResourceType.freebusyurl = davxml.ResourceType(FreeBusyURL())
-davxml.ResourceType.notification = davxml.ResourceType(davxml.Collection(), Notification())
-davxml.ResourceType.sharedownercalendar = davxml.ResourceType(davxml.Collection(), caldavxml.Calendar(), SharedOwner())
-davxml.ResourceType.sharedcalendar = davxml.ResourceType(davxml.Collection(), caldavxml.Calendar(), Shared())
-davxml.ResourceType.sharedaddressbook = davxml.ResourceType(davxml.Collection(), carddavxml.AddressBook(), Shared())
-davxml.ResourceType.link = davxml.ResourceType(Link())
+ResourceType.dropboxhome = ResourceType(Collection(), DropBoxHome())
+ResourceType.dropbox     = ResourceType(Collection(), DropBox())
+
+ResourceType.calendarproxyread  = ResourceType(Principal(), Collection(), CalendarProxyRead())
+ResourceType.calendarproxywrite = ResourceType(Principal(), Collection(), CalendarProxyWrite())
+
+ResourceType.timezones = ResourceType(Timezones())
+
+ResourceType.ischeduleinbox = ResourceType(IScheduleInbox())
+
+ResourceType.freebusyurl = ResourceType(FreeBusyURL())
+
+ResourceType.notification = ResourceType(Collection(), Notification())
+
+ResourceType.sharedownercalendar = ResourceType(Collection(), caldavxml.Calendar(),     SharedOwner())
+ResourceType.sharedcalendar      = ResourceType(Collection(), caldavxml.Calendar(),     Shared())
+ResourceType.sharedaddressbook   = ResourceType(Collection(), carddavxml.AddressBook(), Shared())
+
+ResourceType.link = ResourceType(Link())

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/calendaruserproxy.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/calendaruserproxy.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/calendaruserproxy.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -33,8 +33,8 @@
 from twisted.internet.defer import succeed, inlineCallbacks, returnValue
 from twext.web2 import responsecode
 from twext.web2.http import HTTPError, StatusResponse
-from twext.web2.dav import davxml
-from twext.web2.dav.element.base import dav_namespace
+from txdav.xml import element as davxml
+from txdav.xml.base import dav_namespace
 from twext.web2.dav.util import joinURL
 from twext.web2.dav.noneprops import NonePropertyStore
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/ldapdirectory.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/ldapdirectory.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/ldapdirectory.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -1338,8 +1338,9 @@
                 dn = normalizeDNstr(dn)
                 shortName = self.service._getUniqueLdapAttribute(attrs, "cn")
                 self.log_debug("%s is a member of %s" % (self._memberId, shortName))
-                groups.append(self.service.recordWithShortName(recordType,
-                    shortName))
+                record = self.service.recordWithShortName(recordType, shortName)
+                if record is not None:
+                    groups.append(record)
         except ldap.PROTOCOL_ERROR, e:
             self.log_warn(str(e))
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/opendirectorybacker.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/opendirectorybacker.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/opendirectorybacker.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -40,8 +40,8 @@
 from socket import getfqdn
 
 from twisted.internet.defer import inlineCallbacks, returnValue, deferredGenerator, succeed
-from twext.web2.dav import davxml
-from twext.web2.dav.element.base import twisted_dav_namespace, dav_namespace, parse_date, twisted_private_namespace
+from txdav.xml import element as davxml
+from txdav.xml.base import twisted_dav_namespace, dav_namespace, parse_date, twisted_private_namespace
 from twext.web2.dav.resource import DAVPropertyMixIn
 from twext.web2.dav.util import joinURL
 from twext.web2.http_headers import MimeType, generateContentType, ETag

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/principal.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/principal.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/principal.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -40,7 +40,7 @@
 from twext.web2.auth.digest import DigestedCredentials
 from twext.web2 import responsecode
 from twext.web2.http import HTTPError
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.util import joinURL
 from twext.web2.dav.noneprops import NonePropertyStore
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/test/test_calendar.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/test/test_calendar.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/test/test_calendar.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -15,7 +15,7 @@
 ##
 
 from twisted.internet.defer import inlineCallbacks
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 
 from twistedcaldav import caldavxml
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/test/test_guidchange.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/test/test_guidchange.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/test/test_guidchange.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -15,7 +15,7 @@
 ##
 from twistedcaldav.directory.directory import DirectoryService
 
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.resource import AccessDeniedError
 from twext.web2.test.test_server import SimpleRequest
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/test/test_principal.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/test/test_principal.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/test/test_principal.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -18,7 +18,7 @@
 
 from twisted.cred.credentials import UsernamePassword
 from twisted.internet.defer import inlineCallbacks
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.fileop import rmdir
 from twext.web2.dav.resource import AccessDeniedError
 from twext.web2.http import HTTPError

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/test/test_proxyprincipalmembers.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/test/test_proxyprincipalmembers.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/test/test_proxyprincipalmembers.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -15,7 +15,7 @@
 ##
 
 from twisted.internet.defer import DeferredList, inlineCallbacks, succeed
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 
 from twistedcaldav.directory.directory import DirectoryService
 from twistedcaldav.test.util import xmlFile, augmentsFile, proxiesFile

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/wiki.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/wiki.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/wiki.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -24,7 +24,7 @@
 ]
 
 from twisted.internet.defer import inlineCallbacks, returnValue
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twisted.web.xmlrpc import Proxy, Fault
 from twext.web2.http import HTTPError, StatusResponse
 from twext.web2.auth.wrapper import UnauthorizedResponse

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directorybackedaddressbook.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directorybackedaddressbook.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directorybackedaddressbook.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -24,8 +24,7 @@
 
 from twext.python.log import Logger
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
-from twext.web2.dav.element.extensions import SyncCollection
+from txdav.xml import element as davxml
 from twext.web2.dav.resource import TwistedACLInheritable
 from twext.web2.http import HTTPError, StatusResponse
 
@@ -125,7 +124,7 @@
         result = super(DirectoryBackedAddressBookResource, self).supportedReports()
         if config.EnableSyncReport:
             # Not supported on the directory backed address book
-            result.remove(davxml.Report(SyncCollection(),))
+            result.remove(davxml.Report(davxml.SyncCollection(),))
         return result
 
     def resourceType(self):

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/dropbox.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/dropbox.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/dropbox.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -25,7 +25,7 @@
 
 from twext.python.log import Logger
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.http import ErrorResponse
 from twext.web2.dav.resource import DAVResource, TwistedACLInheritable
 from twext.web2.dav.util import joinURL

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/extensions.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/extensions.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/extensions.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -47,9 +47,9 @@
 from twext.web2.http_headers import MimeType
 from twext.web2.stream import FileStream
 from twext.web2.static import MetaDataMixin, StaticRenderMixin
-from twext.web2.dav import davxml
+from txdav.xml import element
+from txdav.xml.element import dav_namespace
 from twext.web2.dav.auth import PrincipalCredentials
-from twext.web2.dav.davxml import dav_namespace
 from twext.web2.dav.http import MultiStatusResponse
 from twext.web2.dav.idav import IDAVPrincipalResource
 from twext.web2.dav.static import DAVFile as SuperDAVFile
@@ -102,8 +102,8 @@
             hasattr(request, "credentialFactories") and
             hasattr(request, "loginInterfaces")
         ):
-            request.authnUser = davxml.Principal(davxml.Unauthenticated())
-            request.authzUser = davxml.Principal(davxml.Unauthenticated())
+            request.authnUser = element.Principal(element.Unauthenticated())
+            request.authzUser = element.Principal(element.Unauthenticated())
             returnValue((request.authnUser, request.authzUser,))
 
         authHeader = request.headers.getHeader("authorization")
@@ -155,8 +155,8 @@
                 # This request has already been authenticated via the wiki
                 returnValue((request.authnUser, request.authzUser))
 
-            request.authnUser = davxml.Principal(davxml.Unauthenticated())
-            request.authzUser = davxml.Principal(davxml.Unauthenticated())
+            request.authnUser = element.Principal(element.Unauthenticated())
+            request.authzUser = element.Principal(element.Unauthenticated())
             returnValue((request.authnUser, request.authzUser,))
 
     def principalsForAuthID(self, request, creds):
@@ -290,8 +290,8 @@
         searching.
         """
         # Verify root element
-        if not isinstance(principal_property_search, davxml.PrincipalPropertySearch):
-            msg = "%s expected as root element, not %s." % (davxml.PrincipalPropertySearch.sname(), principal_property_search.sname())
+        if not isinstance(principal_property_search, element.PrincipalPropertySearch):
+            msg = "%s expected as root element, not %s." % (element.PrincipalPropertySearch.sname(), principal_property_search.sname())
             log.warn(msg)
             raise HTTPError(StatusResponse(responsecode.BAD_REQUEST, msg))
 
@@ -334,10 +334,10 @@
                 applyTo = True
 
             elif child.qname() == (dav_namespace, "property-search"):
-                props = child.childOfType(davxml.PropertyContainer)
+                props = child.childOfType(element.PropertyContainer)
                 props.removeWhitespaceNodes()
 
-                match = child.childOfType(davxml.Match)
+                match = child.childOfType(element.Match)
                 caseless = match.attributes.get("caseless", "yes")
                 if caseless not in ("yes", "no"):
                     msg = "Bad XML: unknown value for caseless attribute: %s" % (caseless,)
@@ -434,7 +434,7 @@
             yield prop_common.responseForHref(
                 request,
                 responses,
-                davxml.HRef.fromString(url),
+                element.HRef.fromString(url),
                 resource,
                 propertiesForResource,
                 propElement
@@ -444,13 +444,13 @@
             if resultsWereLimited[0] == "server":
                 log.err("Too many matching resources in "
                         "principal-property-search report")
-            responses.append(davxml.StatusResponse(
-                davxml.HRef.fromString(request.uri),
-                davxml.Status.fromResponseCode(
+            responses.append(element.StatusResponse(
+                element.HRef.fromString(request.uri),
+                element.Status.fromResponseCode(
                     responsecode.INSUFFICIENT_STORAGE_SPACE
                 ),
-                davxml.Error(davxml.NumberOfMatchesWithinLimits()),
-                davxml.ResponseDescription("Results limited by %s at %d"
+                element.Error(element.NumberOfMatchesWithinLimits()),
+                element.ResponseDescription("Results limited by %s at %d"
                                            % resultsWereLimited),
             ))
         returnValue(MultiStatusResponse(responses))
@@ -714,7 +714,7 @@
         # Allow live property to be overridden by dead property
         if self.deadProperties().contains((dav_namespace, "resourcetype")):
             return self.deadProperties().get((dav_namespace, "resourcetype"))
-        return davxml.ResourceType(davxml.Collection()) if self.isCollection() else davxml.ResourceType()
+        return element.ResourceType(element.Collection()) if self.isCollection() else element.ResourceType()
 
     def contentType(self):
         return MimeType("httpd", "unix-directory") if self.isCollection() else None
@@ -842,13 +842,13 @@
             if name == "expanded-group-member-set":
                 principals = (yield self.expandedGroupMembers())
                 returnValue(customxml.ExpandedGroupMemberSet(
-                    *[davxml.HRef(p.principalURL()) for p in principals]
+                    *[element.HRef(p.principalURL()) for p in principals]
                 ))
 
             elif name == "expanded-group-membership":
                 principals = (yield self.expandedGroupMemberships())
                 returnValue(customxml.ExpandedGroupMembership(
-                    *[davxml.HRef(p.principalURL()) for p in principals]
+                    *[element.HRef(p.principalURL()) for p in principals]
                 ))
 
             elif name == "record-type":
@@ -882,9 +882,9 @@
         if self.deadProperties().contains((dav_namespace, "resourcetype")):
             return self.deadProperties().get((dav_namespace, "resourcetype"))
         if self.isCollection():
-            return davxml.ResourceType(davxml.Principal(), davxml.Collection())
+            return element.ResourceType(element.Principal(), element.Collection())
         else:
-            return davxml.ResourceType(davxml.Principal())
+            return element.ResourceType(element.Principal())
 
 
 
@@ -899,8 +899,8 @@
         if self.deadProperties().contains((dav_namespace, "resourcetype")):
             return self.deadProperties().get((dav_namespace, "resourcetype"))
         if self.isCollection():
-            return davxml.ResourceType.collection #@UndefinedVariable
-        return davxml.ResourceType.empty #@UndefinedVariable
+            return element.ResourceType.collection #@UndefinedVariable
+        return element.ResourceType.empty #@UndefinedVariable
 
     def render(self, request):
         if not self.fp.exists():

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/freebusyurl.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/freebusyurl.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/freebusyurl.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -26,7 +26,7 @@
 
 from twext.python.log import Logger
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.http import ErrorResponse
 from twext.web2.dav.util import joinURL
 from twext.web2.http import HTTPError

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/linkresource.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/linkresource.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/linkresource.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -17,7 +17,7 @@
 
 from twext.python.log import LoggingMixIn
 from twext.web2 import responsecode, server, http
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.http import HTTPError, StatusResponse
 from twext.web2.resource import WrapperResource
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/mail.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/mail.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/mail.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -55,7 +55,7 @@
 
 from twext.web2 import server, responsecode
 from twext.web2.channel.http import HTTPFactory
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.noneprops import NonePropertyStore
 from twext.web2.http import Response, HTTPError
 from twext.web2.http_headers import MimeType

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/copymove.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/copymove.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/copymove.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -25,7 +25,7 @@
 from twisted.internet.defer import inlineCallbacks, returnValue
 from twext.web2 import responsecode
 from twext.web2.filter.location import addLocation
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.http import ErrorResponse
 from twext.web2.dav.util import parentForURL
 from twext.web2.http import StatusResponse, HTTPError

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/copymove_contact.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/copymove_contact.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/copymove_contact.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -25,7 +25,7 @@
 from twisted.internet.defer import inlineCallbacks, returnValue
 from twext.web2 import responsecode
 from twext.web2.filter.location import addLocation
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.http import ErrorResponse
 from twext.web2.dav.util import parentForURL
 from twext.web2.http import StatusResponse, HTTPError

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/delete.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/delete.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/delete.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -24,7 +24,7 @@
 
 from twisted.internet.defer import inlineCallbacks, returnValue
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.util import parentForURL
 from twext.web2.http import HTTPError
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/get.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/get.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/get.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -22,7 +22,7 @@
 
 from twisted.internet.defer import inlineCallbacks, returnValue
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.http import ErrorResponse
 from twext.web2.dav.util import parentForURL
 from twext.web2.http import HTTPError

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/mkcalendar.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/mkcalendar.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/mkcalendar.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -24,7 +24,7 @@
 from twisted.internet.defer import inlineCallbacks, returnValue
 from twisted.python.failure import Failure
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.http import MultiStatusResponse, PropertyStatusResponseQueue
 from twext.web2.dav.util import davXMLFromStream
 from twext.web2.dav.util import parentForURL

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/mkcol.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/mkcol.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/mkcol.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -26,7 +26,7 @@
 
 from twext.python.log import Logger
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.http import Response
 from twext.web2.dav.http import ErrorResponse, PropertyStatusResponseQueue
 from twext.web2.dav.util import davXMLFromStream

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/propfind.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/propfind.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/propfind.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -32,7 +32,7 @@
 from twext.web2.http import HTTPError
 from twext.web2 import responsecode
 from twext.web2.http import StatusResponse
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.http import MultiStatusResponse, statusForFailure,\
     ErrorResponse
 from twext.web2.dav.util import normalizeURL, davXMLFromStream

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/put_addressbook_common.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/put_addressbook_common.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/put_addressbook_common.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -29,7 +29,7 @@
 from twisted.internet.defer import Deferred, inlineCallbacks
 from twisted.internet.defer import returnValue
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.http import ErrorResponse
 from twext.web2.dav.util import joinURL, parentForURL
 from twext.web2.http import HTTPError

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/put_common.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/put_common.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/put_common.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -32,7 +32,7 @@
 
 from twext.web2.dav.util import joinURL, parentForURL
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 
 from twext.web2.http import HTTPError
 from twext.web2.http import StatusResponse

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/report.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/report.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/report.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -31,9 +31,9 @@
 from twisted.internet.defer import inlineCallbacks, returnValue
 from twext.web2 import responsecode
 from twext.web2.http import HTTPError, StatusResponse
-from twext.web2.dav import davxml
-from twext.web2.dav.element.parser import lookupElement
 from twext.web2.dav.util import davXMLFromStream
+from txdav.xml import element as davxml
+from txdav.xml.element import lookupElement
 
 from twext.python.log import Logger
 from twext.web2.dav.http import ErrorResponse

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/report_addressbook_query.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/report_addressbook_query.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/report_addressbook_query.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -27,7 +27,7 @@
 
 from twext.python.log import Logger
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.http import ErrorResponse, MultiStatusResponse
 from twext.web2.dav.method.report import NumberOfMatchesWithinLimits
 from twext.web2.dav.util import joinURL

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/report_calendar_query.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/report_calendar_query.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/report_calendar_query.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -26,7 +26,7 @@
 from twisted.internet.defer import inlineCallbacks, returnValue,\
     maybeDeferred
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.http import MultiStatusResponse
 from twext.web2.dav.method.report import NumberOfMatchesWithinLimits
 from twext.web2.dav.util import joinURL

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/report_common.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/report_common.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/report_common.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -39,8 +39,8 @@
 from twisted.internet.defer import inlineCallbacks, returnValue, maybeDeferred
 from twisted.python.failure import Failure
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
-from twext.web2.dav.element.base import WebDAVElement
+
+from txdav.xml import element
 from twext.web2.dav.http import statusForFailure
 from twext.web2.dav.method.propfind import propertyName
 from twext.web2.dav.method.report import NumberOfMatchesWithinLimits
@@ -183,14 +183,14 @@
         for status in properties_by_status:
             properties = properties_by_status[status]
             if properties:
-                xml_status = davxml.Status.fromResponseCode(status)
-                xml_container = davxml.PropertyContainer(*properties)
-                xml_propstat = davxml.PropertyStatus(xml_container, xml_status)
+                xml_status = element.Status.fromResponseCode(status)
+                xml_container = element.PropertyContainer(*properties)
+                xml_propstat = element.PropertyStatus(xml_container, xml_status)
 
                 propstats.append(xml_propstat)
 
         if propstats:
-            responses.append(davxml.PropertyStatusResponse(href, *propstats))
+            responses.append(element.PropertyStatusResponse(href, *propstats))
 
     d = propertiesForResource(request, propertyreq, resource, calendar, timezone, vcard, isowner)
     d.addCallback(_defer)
@@ -354,7 +354,7 @@
             properties_by_status[responsecode.OK].append(propvalue)
             continue
     
-        if isinstance(property, WebDAVElement):
+        if isinstance(property, element.WebDAVElement):
             qname = property.qname()
         else:
             qname = property

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/report_freebusy.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/report_freebusy.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/report_freebusy.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -25,7 +25,7 @@
 
 from twisted.internet.defer import inlineCallbacks, returnValue
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.method.report import NumberOfMatchesWithinLimits
 from twext.web2.http import HTTPError, Response, StatusResponse
 from twext.web2.http_headers import MimeType

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/report_multiget_common.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/report_multiget_common.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/report_multiget_common.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -24,8 +24,8 @@
 
 from twext.python.log import Logger
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
-from twext.web2.dav.element.base import dav_namespace
+from txdav.xml import element as davxml
+from txdav.xml.base import dav_namespace
 from twext.web2.dav.http import ErrorResponse, MultiStatusResponse
 from twext.web2.dav.resource import AccessDeniedError
 from twext.web2.dav.util import joinURL

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/report_sync_collection.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/report_sync_collection.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/method/report_sync_collection.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -20,16 +20,13 @@
 
 __all__ = ["report_DAV__sync_collection"]
 
-from twext.python.log import Logger
-from twext.web2.dav.davxml import SyncToken
-from twext.web2.dav.http import ErrorResponse
-
 from twisted.internet.defer import inlineCallbacks, returnValue
 from twisted.python.failure import Failure
+
+from twext.python.log import Logger
+from txdav.xml import element
+from twext.web2.dav.http import ErrorResponse
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
-from twext.web2.dav.element.base import WebDAVElement
-from twext.web2.dav.element.extensions import SyncCollection
 from twext.web2.dav.http import MultiStatusResponse, statusForFailure
 from twext.web2.dav.method.prop_common import responseForHref
 from twext.web2.dav.method.propfind import propertyName
@@ -51,11 +48,11 @@
     """
     
     # These resource support the report
-    if not config.EnableSyncReport or davxml.Report(SyncCollection(),) not in self.supportedReports():
+    if not config.EnableSyncReport or element.Report(element.SyncCollection(),) not in self.supportedReports():
         log.err("sync-collection report is only allowed on calendar/inbox/addressbook/notification collection resources %s" % (self,))
         raise HTTPError(ErrorResponse(
             responsecode.FORBIDDEN,
-            davxml.SupportedReport(),
+            element.SupportedReport(),
             "Report not supported on this resource",
         ))
    
@@ -92,7 +89,7 @@
         }
         
         for property in props:
-            if isinstance(property, WebDAVElement):
+            if isinstance(property, element.WebDAVElement):
                 qname = property.qname()
             else:
                 qname = property
@@ -132,12 +129,12 @@
             lambda x, y: ok_resources.append((x, y)),
             lambda x, y: forbidden_resources.append((x, y)),
             changed,
-            (davxml.Read(),),
+            (element.Read(),),
             inherited_aces=filteredaces
         )
 
     for child, child_uri in ok_resources:
-        href = davxml.HRef.fromString(child_uri)
+        href = element.HRef.fromString(child_uri)
         try:
             yield responseForHref(
                 request,
@@ -155,7 +152,7 @@
             log.err("Missing resource during sync: %s" % (href,))
 
     for child, child_uri in forbidden_resources:
-        href = davxml.HRef.fromString(child_uri)
+        href = element.HRef.fromString(child_uri)
         try:
             yield responseForHref(
                 request,
@@ -173,17 +170,17 @@
             log.err("Missing resource during sync: %s" % (href,))
 
     for name in removed:
-        href = davxml.HRef.fromString(joinURL(request.uri, name))
-        responses.append(davxml.StatusResponse(davxml.HRef.fromString(href), davxml.Status.fromResponseCode(responsecode.NOT_FOUND)))
+        href = element.HRef.fromString(joinURL(request.uri, name))
+        responses.append(element.StatusResponse(element.HRef.fromString(href), element.Status.fromResponseCode(responsecode.NOT_FOUND)))
     
     for name in notallowed:
-        href = davxml.HRef.fromString(joinURL(request.uri, name))
-        responses.append(davxml.StatusResponse(davxml.HRef.fromString(href), davxml.Status.fromResponseCode(responsecode.NOT_ALLOWED)))
+        href = element.HRef.fromString(joinURL(request.uri, name))
+        responses.append(element.StatusResponse(element.HRef.fromString(href), element.Status.fromResponseCode(responsecode.NOT_ALLOWED)))
     
     if not hasattr(request, "extendedLogItems"):
         request.extendedLogItems = {}
     request.extendedLogItems["responses"] = len(responses)
 
-    responses.append(SyncToken.fromString(newtoken))
+    responses.append(element.SyncToken.fromString(newtoken))
 
     returnValue(MultiStatusResponse(responses))

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/mkcolxml.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/mkcolxml.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/mkcolxml.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -25,7 +25,8 @@
 See RFC 5689.
 """
 
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
+from txdav.xml.element import registerElement
 
 ##
 # Extended MKCOL objects
@@ -35,6 +36,8 @@
     "extended-mkcol",
 )
 
+
+ at registerElement
 class MakeCollection (davxml.WebDAVElement):
     """
     Top-level element for request body in MKCOL.
@@ -46,6 +49,8 @@
 
     child_types = { "WebDAVUnknownElement": (0, None) }
 
+
+ at registerElement
 class MakeCollectionResponse (davxml.WebDAVElement):
     """
     Top-level element for response body in MKCOL.

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/notifications.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/notifications.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/notifications.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -25,7 +25,7 @@
 
 from twext.python.log import Logger, LoggingMixIn
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 
 from twisted.internet.defer import succeed, inlineCallbacks, returnValue,\
     maybeDeferred

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/resource.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/resource.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/resource.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -37,23 +37,23 @@
 
 from zope.interface import implements
 
-from twext.python.log import LoggingMixIn
-from twext.web2.dav.davxml import SyncCollection
-from twext.web2.dav.http import ErrorResponse
-
 from twisted.internet.defer import succeed, maybeDeferred, fail
 from twisted.internet.defer import inlineCallbacks, returnValue
 
+from twext.python.log import LoggingMixIn
+
+from txdav.xml import element
+from txdav.xml.element import dav_namespace
+
 from twext.web2 import responsecode, http, http_headers
-from twext.web2.dav import davxml
 from twext.web2.dav.auth import AuthenticationWrapper as SuperAuthenticationWrapper
-from twext.web2.dav.davxml import dav_namespace
 from twext.web2.dav.idav import IDAVPrincipalCollectionResource
 from twext.web2.dav.resource import AccessDeniedError, DAVPrincipalCollectionResource,\
     davPrivilegeSet
 from twext.web2.dav.resource import TwistedACLInheritable
 from twext.web2.dav.util import joinURL, parentForURL, normalizeURL
 from twext.web2.http import HTTPError, RedirectResponse, StatusResponse, Response
+from twext.web2.dav.http import ErrorResponse
 from twext.web2.http_headers import MimeType, ETag
 from twext.web2.stream import MemoryStream
 
@@ -146,37 +146,37 @@
 
     top_supported_privileges = []
 
-    for supported_privilege in davPrivilegeSet.childrenOfType(davxml.SupportedPrivilege):
-        all_privilege = supported_privilege.childOfType(davxml.Privilege)
-        if isinstance(all_privilege.children[0], davxml.All):
-            all_description = supported_privilege.childOfType(davxml.Description)
+    for supported_privilege in davPrivilegeSet.childrenOfType(element.SupportedPrivilege):
+        all_privilege = supported_privilege.childOfType(element.Privilege)
+        if isinstance(all_privilege.children[0], element.All):
+            all_description = supported_privilege.childOfType(element.Description)
             all_supported_privileges = []
-            for all_supported_privilege in supported_privilege.childrenOfType(davxml.SupportedPrivilege):
-                read_privilege = all_supported_privilege.childOfType(davxml.Privilege)
-                if isinstance(read_privilege.children[0], davxml.Read):
-                    read_description = all_supported_privilege.childOfType(davxml.Description)
-                    read_supported_privileges = list(all_supported_privilege.childrenOfType(davxml.SupportedPrivilege))
+            for all_supported_privilege in supported_privilege.childrenOfType(element.SupportedPrivilege):
+                read_privilege = all_supported_privilege.childOfType(element.Privilege)
+                if isinstance(read_privilege.children[0], element.Read):
+                    read_description = all_supported_privilege.childOfType(element.Description)
+                    read_supported_privileges = list(all_supported_privilege.childrenOfType(element.SupportedPrivilege))
                     read_supported_privileges.append(
-                        davxml.SupportedPrivilege(
-                            davxml.Privilege(caldavxml.ReadFreeBusy()),
-                            davxml.Description("allow free busy report query", **{"xml:lang": "en"}),
+                        element.SupportedPrivilege(
+                            element.Privilege(caldavxml.ReadFreeBusy()),
+                            element.Description("allow free busy report query", **{"xml:lang": "en"}),
                         )
                     )
                     all_supported_privileges.append(
-                        davxml.SupportedPrivilege(read_privilege, read_description, *read_supported_privileges)
+                        element.SupportedPrivilege(read_privilege, read_description, *read_supported_privileges)
                     )
                     edited = True
                 else:
                     all_supported_privileges.append(all_supported_privilege)
             top_supported_privileges.append(
-                davxml.SupportedPrivilege(all_privilege, all_description, *all_supported_privileges)
+                element.SupportedPrivilege(all_privilege, all_description, *all_supported_privileges)
             )
         else:
             top_supported_privileges.append(supported_privilege)
 
     assert edited, "Structure of davPrivilegeSet changed in a way that I don't know how to extend for calendarPrivilegeSet"
 
-    return davxml.SupportedPrivilegeSet(*top_supported_privileges)
+    return element.SupportedPrivilegeSet(*top_supported_privileges)
 
 calendarPrivilegeSet = _calendarPrivilegeSet()
 
@@ -381,7 +381,7 @@
 
     def liveProperties(self):
         baseProperties = (
-            davxml.Owner.qname(),               # Private Events needs this but it is also OK to return empty
+            element.Owner.qname(),               # Private Events needs this but it is also OK to return empty
         )
         
         if self.isPseudoCalendarCollection():
@@ -405,7 +405,7 @@
 
         if self.isCalendarCollection():
             baseProperties += (
-                davxml.ResourceID.qname(),
+                element.ResourceID.qname(),
                 
                 # These are "live" properties in the sense of WebDAV, however "live" for twext actually means
                 # ones that are also always present, but the default alarm properties are allowed to be absent
@@ -420,7 +420,7 @@
 
         if self.isAddressBookCollection():
             baseProperties += (
-                davxml.ResourceID.qname(),
+                element.ResourceID.qname(),
                 carddavxml.SupportedAddressData.qname(),
                 customxml.GETCTag.qname(),
                 customxml.PubSubXMPPPushKeyProperty.qname(),
@@ -435,11 +435,11 @@
                 caldavxml.ScheduleTag.qname(),
             )
             
-        if config.EnableSyncReport and (davxml.Report(SyncCollection(),) in self.supportedReports()):
-            baseProperties += (davxml.SyncToken.qname(),)
+        if config.EnableSyncReport and (element.Report(element.SyncCollection(),) in self.supportedReports()):
+            baseProperties += (element.SyncToken.qname(),)
             
         if config.EnableAddMember and (self.isCalendarCollection() or self.isAddressBookCollection()):
-            baseProperties += (davxml.AddMember.qname(),)
+            baseProperties += (element.AddMember.qname(),)
             
         if config.Sharing.Enabled:
             if config.Sharing.Calendars.Enabled and self.isCalendarCollection():
@@ -474,7 +474,7 @@
         """
         if qname in self.liveProperties():
             if qname in (
-                davxml.DisplayName.qname(),
+                element.DisplayName.qname(),
                 customxml.Invite.qname(),
             ):
                 return False
@@ -598,31 +598,31 @@
     @inlineCallbacks
     def _readGlobalProperty(self, qname, property, request):
 
-        if qname == davxml.Owner.qname():
+        if qname == element.Owner.qname():
             owner = (yield self.owner(request))
-            returnValue(davxml.Owner(owner))
+            returnValue(element.Owner(owner))
 
-        elif qname == davxml.ResourceType.qname():
+        elif qname == element.ResourceType.qname():
             returnValue(self.resourceType())
 
-        elif qname == davxml.ResourceID.qname():
-            returnValue(davxml.ResourceID(davxml.HRef.fromString(self.resourceID())))
+        elif qname == element.ResourceID.qname():
+            returnValue(element.ResourceID(element.HRef.fromString(self.resourceID())))
 
         elif qname == customxml.GETCTag.qname() and (
             self.isPseudoCalendarCollection() or self.isAddressBookCollection()
         ):
             returnValue(customxml.GETCTag.fromString((yield self.getInternalSyncToken())))
 
-        elif qname == davxml.SyncToken.qname() and config.EnableSyncReport and (
-            davxml.Report(SyncCollection(),) in self.supportedReports()
+        elif qname == element.SyncToken.qname() and config.EnableSyncReport and (
+            element.Report(element.SyncCollection(),) in self.supportedReports()
         ):
-            returnValue(davxml.SyncToken.fromString((yield self.getSyncToken())))
+            returnValue(element.SyncToken.fromString((yield self.getSyncToken())))
 
-        elif qname == davxml.AddMember.qname() and config.EnableAddMember and (
+        elif qname == element.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")))
+            returnValue(element.AddMember(element.HRef.fromString(url + "/;add-member")))
 
         elif qname == caldavxml.SupportedCalendarComponentSet.qname() and self.isPseudoCalendarCollection():
             returnValue(self.getSupportedComponentSet())
@@ -707,7 +707,7 @@
             isvirt = self.isVirtualShare()
             
             if isvirt:
-                returnValue(customxml.SharedURL(davxml.HRef.fromString(self._share.hosturl)))
+                returnValue(customxml.SharedURL(element.HRef.fromString(self._share.hosturl)))
             else:
                 returnValue(None)
 
@@ -716,7 +716,7 @@
 
     @inlineCallbacks
     def writeProperty(self, property, request):
-        assert isinstance(property, davxml.WebDAVElement), (
+        assert isinstance(property, element.WebDAVElement), (
             "%r is not a WebDAVElement instance" % (property,)
         )
         
@@ -805,7 +805,7 @@
 
         yield self._preProcessWriteProperty(property, request)
 
-        if property.qname() == davxml.ResourceType.qname():
+        if property.qname() == element.ResourceType.qname():
             if self.isCalendarCollection() or self.isAddressBookCollection():
                 sawShare = [child for child in property.children if child.qname() == (calendarserver_namespace, "shared-owner")]
                 if sawShare:
@@ -823,7 +823,7 @@
                 # Check if adding or removing share
                 shared = (yield self.isShared(request))
                 for child in property.children:
-                    if child.qname() == davxml.Collection.qname():
+                    if child.qname() == element.Collection.qname():
                         break
                 else:
                     raise HTTPError(StatusResponse(
@@ -893,37 +893,37 @@
                 if self.accessMode == Component.ACCESS_PRIVATE:
                     newacls.extend(config.AdminACEs)
                     newacls.extend(config.ReadACEs)
-                    newacls.append(davxml.ACE(
-                        davxml.Invert(
-                            davxml.Principal(owner),
+                    newacls.append(element.ACE(
+                        element.Invert(
+                            element.Principal(owner),
                         ),
-                        davxml.Deny(
-                            davxml.Privilege(
-                                davxml.Read(),
+                        element.Deny(
+                            element.Privilege(
+                                element.Read(),
                             ),
-                            davxml.Privilege(
-                                davxml.Write(),
+                            element.Privilege(
+                                element.Write(),
                             ),
                         ),
-                        davxml.Protected(),
+                        element.Protected(),
                     ))
                 else:
                     newacls.extend(config.AdminACEs)
                     newacls.extend(config.ReadACEs)
-                    newacls.append(davxml.ACE(
-                        davxml.Invert(
-                            davxml.Principal(owner),
+                    newacls.append(element.ACE(
+                        element.Invert(
+                            element.Principal(owner),
                         ),
-                        davxml.Deny(
-                            davxml.Privilege(
-                                davxml.Write(),
+                        element.Deny(
+                            element.Privilege(
+                                element.Write(),
                             ),
                         ),
-                        davxml.Protected(),
+                        element.Protected(),
                     ))
                 newacls.extend(acls.children)
 
-                acls = davxml.ACL(*newacls)
+                acls = element.ACL(*newacls)
  
         returnValue(acls)
 
@@ -992,7 +992,7 @@
         current = self.currentPrincipal(request)
         if current in config.AllAdminPrincipalObjects:
             returnValue(True)
-        if davxml.Principal((yield self.owner(request))) == current:
+        if element.Principal((yield self.owner(request))) == current:
             returnValue(True)
         returnValue(False)
 
@@ -1002,7 +1002,7 @@
     ##
 
     def displayName(self):
-        if self.isAddressBookCollection() and not self.hasDeadProperty((davxml.dav_namespace, "displayname")):
+        if self.isAddressBookCollection() and not self.hasDeadProperty((dav_namespace, "displayname")):
             return None
         
         if 'record' in dir(self):
@@ -1022,10 +1022,10 @@
         return None
 
     def resourceID(self):
-        if not self.hasDeadProperty(davxml.ResourceID.qname()):
+        if not self.hasDeadProperty(element.ResourceID.qname()):
             uuidval = uuid.uuid4()
-            self.writeDeadProperty(davxml.ResourceID(davxml.HRef.fromString(uuidval.urn)))
-        return str(self.readDeadProperty(davxml.ResourceID.qname()).children[0])
+            self.writeDeadProperty(element.ResourceID(element.HRef.fromString(uuidval.urn)))
+        return str(self.readDeadProperty(element.ResourceID.qname()).children[0])
 
     ##
     # CalDAV
@@ -1140,7 +1140,7 @@
             
             # Adjust the default calendar setting if necessary
             if defaultCalendarType is not None:
-                yield inbox.writeProperty(defaultCalendarType(davxml.HRef(destination_path)), request)               
+                yield inbox.writeProperty(defaultCalendarType(element.HRef(destination_path)), request)               
 
     def isCalendarOpaque(self):
         
@@ -1219,7 +1219,7 @@
             principal = (yield self.resourceOwnerPrincipal(request))
             home = (yield principal.addressBookHome(request))
             (_ignore_scheme, _ignore_host, destination_path, _ignore_query, _ignore_fragment) = urlsplit(normalizeURL(destination_uri))
-            yield home.writeProperty(carddavxml.DefaultAddressBookURL(davxml.HRef(destination_path)), request)               
+            yield home.writeProperty(carddavxml.DefaultAddressBookURL(element.HRef(destination_path)), request)               
 
     @inlineCallbacks
     def isDefaultAddressBook(self, request):
@@ -1265,21 +1265,21 @@
 
     def supportedReports(self):
         result = super(CalDAVResource, self).supportedReports()
-        result.append(davxml.Report(caldavxml.CalendarQuery(),))
-        result.append(davxml.Report(caldavxml.CalendarMultiGet(),))
+        result.append(element.Report(caldavxml.CalendarQuery(),))
+        result.append(element.Report(caldavxml.CalendarMultiGet(),))
         if self.isCollection():
             # Only allowed on collections
-            result.append(davxml.Report(caldavxml.FreeBusyQuery(),))
+            result.append(element.Report(caldavxml.FreeBusyQuery(),))
         if config.EnableCardDAV:
-            result.append(davxml.Report(carddavxml.AddressBookQuery(),))
-            result.append(davxml.Report(carddavxml.AddressBookMultiGet(),))
+            result.append(element.Report(carddavxml.AddressBookQuery(),))
+            result.append(element.Report(carddavxml.AddressBookMultiGet(),))
         if (
             self.isPseudoCalendarCollection() or
             self.isAddressBookCollection() or
             self.isNotificationCollection()
         ) and config.EnableSyncReport:
             # Only allowed on calendar/inbox/addressbook/notification collections
-            result.append(davxml.Report(SyncCollection(),))
+            result.append(element.Report(element.SyncCollection(),))
         return result
 
     def writeNewACEs(self, newaces):
@@ -1300,7 +1300,7 @@
                 if TwistedACLInheritable() not in ace.children:
                     children = list(ace.children)
                     children.append(TwistedACLInheritable())
-                    edited_aces.append(davxml.ACE(*children))
+                    edited_aces.append(element.ACE(*children))
                 else:
                     edited_aces.append(ace)
         else:
@@ -1817,26 +1817,26 @@
         principal-search-property-set report.
         """
         result = super(CalendarPrincipalCollectionResource, self).supportedReports()
-        result.append(davxml.Report(davxml.PrincipalSearchPropertySet(),))
+        result.append(element.Report(element.PrincipalSearchPropertySet(),))
         return result
 
     def principalSearchPropertySet(self):
-        return davxml.PrincipalSearchPropertySet(
-            davxml.PrincipalSearchProperty(
-                davxml.PropertyContainer(
-                    davxml.DisplayName()
+        return element.PrincipalSearchPropertySet(
+            element.PrincipalSearchProperty(
+                element.PropertyContainer(
+                    element.DisplayName()
                 ),
-                davxml.Description(
-                    davxml.PCDATAElement("Display Name"),
+                element.Description(
+                    element.PCDATAElement("Display Name"),
                     **{"xml:lang":"en"}
                 ),
             ),
-            davxml.PrincipalSearchProperty(
-                davxml.PropertyContainer(
+            element.PrincipalSearchProperty(
+                element.PropertyContainer(
                     caldavxml.CalendarUserAddressSet()
                 ),
-                davxml.Description(
-                    davxml.PCDATAElement("Calendar User Addresses"),
+                element.Description(
+                    element.PCDATAElement("Calendar User Addresses"),
                     **{"xml:lang":"en"}
                 ),
             ),
@@ -1904,12 +1904,12 @@
         if namespace == caldav_namespace and self.calendarsEnabled():
             if name == "calendar-home-set":
                 returnValue(caldavxml.CalendarHomeSet(
-                    *[davxml.HRef(url) for url in self.calendarHomeURLs()]
+                    *[element.HRef(url) for url in self.calendarHomeURLs()]
                 ))
 
             elif name == "calendar-user-address-set":
                 returnValue(caldavxml.CalendarUserAddressSet(
-                    *[davxml.HRef(uri) for uri in self.calendarUserAddresses()]
+                    *[element.HRef(uri) for uri in self.calendarUserAddresses()]
                 ))
 
             elif name == "schedule-inbox-URL":
@@ -1917,14 +1917,14 @@
                 if url is None:
                     returnValue(None)
                 else:
-                    returnValue(caldavxml.ScheduleInboxURL(davxml.HRef(url)))
+                    returnValue(caldavxml.ScheduleInboxURL(element.HRef(url)))
 
             elif name == "schedule-outbox-URL":
                 url = self.scheduleOutboxURL()
                 if url is None:
                     returnValue(None)
                 else:
-                    returnValue(caldavxml.ScheduleOutboxURL(davxml.HRef(url)))
+                    returnValue(caldavxml.ScheduleOutboxURL(element.HRef(url)))
 
             elif name == "calendar-user-type":
                 returnValue(caldavxml.CalendarUserType(self.record.getCUType()))
@@ -1935,25 +1935,25 @@
                 if url is None:
                     returnValue(None)
                 else:
-                    returnValue(customxml.DropBoxHomeURL(davxml.HRef(url)))
+                    returnValue(customxml.DropBoxHomeURL(element.HRef(url)))
 
             elif name == "notification-URL" and config.Sharing.Enabled:
                 url = yield self.notificationURL()
                 if url is None:
                     returnValue(None)
                 else:
-                    returnValue(customxml.NotificationURL(davxml.HRef(url)))
+                    returnValue(customxml.NotificationURL(element.HRef(url)))
 
             elif name == "calendar-proxy-read-for" and self.calendarsEnabled():
                 results = (yield self.proxyFor(False))
                 returnValue(customxml.CalendarProxyReadFor(
-                    *[davxml.HRef(principal.principalURL()) for principal in results]
+                    *[element.HRef(principal.principalURL()) for principal in results]
                 ))
 
             elif name == "calendar-proxy-write-for" and self.calendarsEnabled():
                 results = (yield self.proxyFor(True))
                 returnValue(customxml.CalendarProxyWriteFor(
-                    *[davxml.HRef(principal.principalURL()) for principal in results]
+                    *[element.HRef(principal.principalURL()) for principal in results]
                 ))
 
             elif name == "auto-schedule" and self.calendarsEnabled():
@@ -1967,11 +1967,11 @@
         elif namespace == carddav_namespace and self.addressBooksEnabled():
             if name == "addressbook-home-set":
                 returnValue(carddavxml.AddressBookHomeSet(
-                    *[davxml.HRef(url) for url in self.addressBookHomeURLs()]
+                    *[element.HRef(url) for url in self.addressBookHomeURLs()]
                  ))
             elif name == "directory-gateway" and self.directoryAddressBookEnabled():
                 returnValue(carddavxml.DirectoryGateway(
-                    davxml.HRef.fromString(joinURL("/", config.DirectoryAddressBook.name, "/"))
+                    element.HRef.fromString(joinURL("/", config.DirectoryAddressBook.name, "/"))
                 ))
 
         result = (yield super(CalendarPrincipalResource, self).readProperty(property, request))
@@ -2180,7 +2180,7 @@
         result = super(CommonHomeResource, self).supportedReports()
         if config.EnableSyncReport and config.EnableSyncReportHome:
             # Allowed on any home
-            result.append(davxml.Report(SyncCollection(),))
+            result.append(element.Report(element.SyncCollection(),))
         return result
 
     def _mergeSyncTokens(self, hometoken, notificationtoken):
@@ -2313,7 +2313,7 @@
                             children.append(
                                 customxml.PubSubTransportProperty(
                                     customxml.PubSubSubscriptionProperty(
-                                        davxml.HRef(
+                                        element.HRef(
                                             apsConfiguration["SubscriptionURL"]
                                         ),
                                     ),
@@ -2405,7 +2405,7 @@
     ##
 
     def owner(self, request):
-        return succeed(davxml.HRef(self.principalForRecord().principalURL()))
+        return succeed(element.HRef(self.principalForRecord().principalURL()))
 
     def ownerPrincipal(self, request):
         return succeed(self.principalForRecord())
@@ -2419,18 +2419,18 @@
         # Server may be read only
         if config.EnableReadOnlyServer:
             owner_privs = (
-                davxml.Privilege(davxml.Read()),
-                davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
+                element.Privilege(element.Read()),
+                element.Privilege(element.ReadCurrentUserPrivilegeSet()),
             )
         else:
-            owner_privs = (davxml.Privilege(davxml.All()),)
+            owner_privs = (element.Privilege(element.All()),)
 
         aces = (
             # Inheritable access for the resource's associated principal.
-            davxml.ACE(
-                davxml.Principal(davxml.HRef(myPrincipal.principalURL())),
-                davxml.Grant(*owner_privs),
-                davxml.Protected(),
+            element.ACE(
+                element.Principal(element.HRef(myPrincipal.principalURL())),
+                element.Grant(*owner_privs),
+                element.Protected(),
                 TwistedACLInheritable(),
             ),
         )
@@ -2441,7 +2441,7 @@
         # Give all access to config.AdminPrincipals
         aces += config.AdminACEs
         
-        return davxml.ACL(*aces)
+        return element.ACL(*aces)
 
     def accessControlList(self, request, inheritance=True, expanding=False, inherited_aces=None):
         # Permissions here are fixed, and are not subject to inheritance rules, etc.
@@ -2622,24 +2622,24 @@
         # Server may be read only
         if config.EnableReadOnlyServer:
             owner_privs = (
-                davxml.Privilege(davxml.Read()),
-                davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
+                element.Privilege(element.Read()),
+                element.Privilege(element.ReadCurrentUserPrivilegeSet()),
             )
         else:
-            owner_privs = (davxml.Privilege(davxml.All()),)
+            owner_privs = (element.Privilege(element.All()),)
 
         aces = (
             # Inheritable access for the resource's associated principal.
-            davxml.ACE(
-                davxml.Principal(davxml.HRef(myPrincipal.principalURL())),
-                davxml.Grant(*owner_privs),
-                davxml.Protected(),
+            element.ACE(
+                element.Principal(element.HRef(myPrincipal.principalURL())),
+                element.Grant(*owner_privs),
+                element.Protected(),
                 TwistedACLInheritable(),
             ),
             # Inheritable CALDAV:read-free-busy access for authenticated users.
-            davxml.ACE(
-                davxml.Principal(davxml.Authenticated()),
-                davxml.Grant(davxml.Privilege(caldavxml.ReadFreeBusy())),
+            element.ACE(
+                element.Principal(element.Authenticated()),
+                element.Grant(element.Privilege(caldavxml.ReadFreeBusy())),
                 TwistedACLInheritable(),
             ),
         )
@@ -2654,37 +2654,37 @@
             # Server may be read only
             if config.EnableReadOnlyServer:
                 rw_proxy_privs = (
-                    davxml.Privilege(davxml.Read()),
-                    davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
+                    element.Privilege(element.Read()),
+                    element.Privilege(element.ReadCurrentUserPrivilegeSet()),
                 )
             else:
                 rw_proxy_privs = (
-                    davxml.Privilege(davxml.Read()),
-                    davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
-                    davxml.Privilege(davxml.Write()),
+                    element.Privilege(element.Read()),
+                    element.Privilege(element.ReadCurrentUserPrivilegeSet()),
+                    element.Privilege(element.Write()),
                 )
 
             aces += (
                 # DAV:read/DAV:read-current-user-privilege-set access for this principal's calendar-proxy-read users.
-                davxml.ACE(
-                    davxml.Principal(davxml.HRef(joinURL(myPrincipal.principalURL(), "calendar-proxy-read/"))),
-                    davxml.Grant(
-                        davxml.Privilege(davxml.Read()),
-                        davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
+                element.ACE(
+                    element.Principal(element.HRef(joinURL(myPrincipal.principalURL(), "calendar-proxy-read/"))),
+                    element.Grant(
+                        element.Privilege(element.Read()),
+                        element.Privilege(element.ReadCurrentUserPrivilegeSet()),
                     ),
-                    davxml.Protected(),
+                    element.Protected(),
                     TwistedACLInheritable(),
                 ),
                 # DAV:read/DAV:read-current-user-privilege-set/DAV:write access for this principal's calendar-proxy-write users.
-                davxml.ACE(
-                    davxml.Principal(davxml.HRef(joinURL(myPrincipal.principalURL(), "calendar-proxy-write/"))),
-                    davxml.Grant(*rw_proxy_privs),
-                    davxml.Protected(),
+                element.ACE(
+                    element.Principal(element.HRef(joinURL(myPrincipal.principalURL(), "calendar-proxy-write/"))),
+                    element.Grant(*rw_proxy_privs),
+                    element.Protected(),
                     TwistedACLInheritable(),
                 ),
             )
 
-        return davxml.ACL(*aces)
+        return element.ACL(*aces)
 
 
     @inlineCallbacks
@@ -2785,11 +2785,11 @@
 
     @inlineCallbacks
     def writeProperty(self, property, request):
-        assert isinstance(property, davxml.WebDAVElement)
+        assert isinstance(property, element.WebDAVElement)
 
         if property.qname() == carddavxml.DefaultAddressBookURL.qname():
             # Verify that the address book added in the PROPPATCH is valid.
-            property.children = [davxml.HRef(normalizeURL(str(href))) for href in property.children]
+            property.children = [element.HRef(normalizeURL(str(href))) for href in property.children]
             new_adbk = [str(href) for href in property.children]
             adbk = None
             if len(new_adbk) == 1:
@@ -2807,7 +2807,7 @@
                 adbkURI = (yield adbk.canonicalURL(request))
                 if not adbkURI.endswith("/"):
                     adbkURI += "/"
-                property = carddavxml.DefaultAddressBookURL(davxml.HRef(adbkURI))
+                property = carddavxml.DefaultAddressBookURL(element.HRef(adbkURI))
 
         yield super(AddressBookHomeResource, self).writeProperty(property, request)
 
@@ -2875,11 +2875,11 @@
 
         self.writeDeadProperty(
             carddavxml.DefaultAddressBookURL(
-                davxml.HRef(defaultAddressBookURL)
+                element.HRef(defaultAddressBookURL)
             )
         )
         returnValue(carddavxml.DefaultAddressBookURL(
-            davxml.HRef(defaultAddressBookURL))
+            element.HRef(defaultAddressBookURL))
         )
 
     @inlineCallbacks
@@ -2929,35 +2929,35 @@
     """
 
     def resourceType(self):
-        return davxml.ResourceType.sharedaddressbook #@UndefinedVariable
+        return element.ResourceType.sharedaddressbook #@UndefinedVariable
 
     def defaultAccessControlList(self):
 
         aces = (
-            davxml.ACE(
-                davxml.Principal(davxml.Authenticated()),
-                davxml.Grant(
-                    davxml.Privilege(davxml.Read()),
-                    davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
-                    davxml.Privilege(davxml.Write()),
+            element.ACE(
+                element.Principal(element.Authenticated()),
+                element.Grant(
+                    element.Privilege(element.Read()),
+                    element.Privilege(element.ReadCurrentUserPrivilegeSet()),
+                    element.Privilege(element.Write()),
                 ),
-                davxml.Protected(),
+                element.Protected(),
                 TwistedACLInheritable(),
            ),
         )
         
         if config.GlobalAddressBook.EnableAnonymousReadAccess:
             aces += (
-                davxml.ACE(
-                    davxml.Principal(davxml.Unauthenticated()),
-                    davxml.Grant(
-                        davxml.Privilege(davxml.Read()),
+                element.ACE(
+                    element.Principal(element.Unauthenticated()),
+                    element.Grant(
+                        element.Privilege(element.Read()),
                     ),
-                    davxml.Protected(),
+                    element.Protected(),
                     TwistedACLInheritable(),
                ),
             )
-        return davxml.ACL(*aces)
+        return element.ACL(*aces)
 
     def accessControlList(self, request, inheritance=True, expanding=False, inherited_aces=None):
         # Permissions here are fixed, and are not subject to inheritance rules, etc.

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/schedule.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/schedule.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/schedule.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -27,9 +27,8 @@
 
 
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
-from twext.web2.dav.element.extensions import SyncCollection
-from twext.web2.dav.element.rfc2518 import HRef
+from txdav.xml import element as davxml
+from txdav.xml.rfc2518 import HRef
 from twext.web2.dav.http import ErrorResponse, MultiStatusResponse
 from twext.web2.dav.noneprops import NonePropertyStore
 from twext.web2.dav.resource import davPrivilegeSet
@@ -123,7 +122,7 @@
         # free-busy report not allowed
         if config.EnableSyncReport:
             # Only allowed on calendar/inbox/addressbook collections
-            result.append(davxml.Report(SyncCollection(),))
+            result.append(davxml.Report(davxml.SyncCollection(),))
         return result
 
 class ScheduleInboxResource (CalendarSchedulingCollectionResource):

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/scheduling/caldav.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/scheduling/caldav.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/scheduling/caldav.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -27,7 +27,7 @@
 from twisted.internet.defer import inlineCallbacks, returnValue
 from twisted.python.failure import Failure
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.resource import AccessDeniedError
 from twext.web2.dav.util import joinURL
 from twext.web2.http import HTTPError

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/scheduling/implicit.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/scheduling/implicit.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/scheduling/implicit.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -104,6 +104,15 @@
                 "Cannot change scheduling object mode",
             ))
 
+        # Organizer events must have a master component
+        if self.state == "organizer" and self.calendar.masterComponent() is None:
+            raise HTTPError(ErrorResponse(
+                responsecode.FORBIDDEN,
+                (caldav_namespace, "organizer-allowed"),
+                "Organizer cannot schedule without a master component.",
+            ))
+            
+
         returnValue((self.action != "none", new_type == "schedule",))
 
     @inlineCallbacks

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/scheduling/scheduler.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/scheduling/scheduler.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/scheduling/scheduler.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -27,7 +27,7 @@
 from twext.web2 import responsecode
 from twext.web2.http import HTTPError, Response, StatusResponse
 from twext.web2.http_headers import MimeType
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.http import errorForFailure, messageForFailure, statusForFailure
 from twext.web2.dav.http import ErrorResponse
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/sharing.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/sharing.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/sharing.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -26,11 +26,11 @@
 
 from twext.python.log import LoggingMixIn
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
+from twext.web2.http import HTTPError, Response, XMLResponse
 from twext.web2.dav.http import ErrorResponse, MultiStatusResponse
 from twext.web2.dav.resource import TwistedACLInheritable
 from twext.web2.dav.util import allDataFromStream, joinURL
-from twext.web2.http import HTTPError, Response, XMLResponse
+from txdav.xml import element
 
 from twisted.internet.defer import succeed, inlineCallbacks, DeferredList,\
     returnValue
@@ -77,7 +77,7 @@
         
         # Change resourcetype
         rtype = self.resourceType()
-        rtype = davxml.ResourceType(*(rtype.children + (customxml.SharedOwner(),)))
+        rtype = element.ResourceType(*(rtype.children + (customxml.SharedOwner(),)))
         self.writeDeadProperty(rtype)
         
         # Create invites database
@@ -89,7 +89,7 @@
         # Change resource type (note this might be called after deleting a resource
         # so we have to cope with that)
         rtype = self.resourceType()
-        rtype = davxml.ResourceType(*([child for child in rtype.children if child != customxml.SharedOwner()]))
+        rtype = element.ResourceType(*([child for child in rtype.children if child != customxml.SharedOwner()]))
         self.writeDeadProperty(rtype)
         
         # Remove all invitees
@@ -141,11 +141,11 @@
         """
         
         # Need to have at least DAV:read to do this
-        yield self.authorize(request, (davxml.Read(),))
+        yield self.authorize(request, (element.Read(),))
         
         # Find current principal
         authz_principal = self.currentPrincipal(request).children[0]
-        if not isinstance(authz_principal, davxml.HRef):
+        if not isinstance(authz_principal, element.HRef):
             raise HTTPError(ErrorResponse(
                 responsecode.FORBIDDEN,
                 (calendarserver_namespace, "valid-principal"),
@@ -236,13 +236,13 @@
         try:
             superMethod = superObject.resourceType
         except AttributeError:
-            rtype = davxml.ResourceType()
+            rtype = element.ResourceType()
         else:
             rtype = superMethod()
 
         isVirt = self.isVirtualShare()
         if isVirt:
-            rtype = davxml.ResourceType(
+            rtype = element.ResourceType(
                 *(
                     tuple([child for child in rtype.children if child.qname() != customxml.SharedOwner.qname()]) +
                     (customxml.Shared(),)
@@ -299,28 +299,28 @@
                 self._share.shareuid
             )
             if invite is None:
-                returnValue(davxml.ACL())
+                returnValue(element.ACL())
             inviteAccess = invite.access
             
         userprivs = [
         ]
         if inviteAccess in ("read-only", "read-write", "read-write-schedule",):
-            userprivs.append(davxml.Privilege(davxml.Read()))
-            userprivs.append(davxml.Privilege(davxml.ReadACL()))
-            userprivs.append(davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()))
+            userprivs.append(element.Privilege(element.Read()))
+            userprivs.append(element.Privilege(element.ReadACL()))
+            userprivs.append(element.Privilege(element.ReadCurrentUserPrivilegeSet()))
         if inviteAccess in ("read-only",):
-            userprivs.append(davxml.Privilege(davxml.WriteProperties()))
+            userprivs.append(element.Privilege(element.WriteProperties()))
         if inviteAccess in ("read-write", "read-write-schedule",):
-            userprivs.append(davxml.Privilege(davxml.Write()))
+            userprivs.append(element.Privilege(element.Write()))
         proxyprivs = list(userprivs)
-        proxyprivs.remove(davxml.Privilege(davxml.ReadACL()))
+        proxyprivs.remove(element.Privilege(element.ReadACL()))
 
         aces = (
             # Inheritable specific access for the resource's associated principal.
-            davxml.ACE(
-                davxml.Principal(davxml.HRef(self._shareePrincipal.principalURL())),
-                davxml.Grant(*userprivs),
-                davxml.Protected(),
+            element.ACE(
+                element.Principal(element.HRef(self._shareePrincipal.principalURL())),
+                element.Grant(*userprivs),
+                element.Protected(),
                 TwistedACLInheritable(),
             ),
         )
@@ -328,9 +328,9 @@
         if self.isCalendarCollection():
             aces += (
                 # Inheritable CALDAV:read-free-busy access for authenticated users.
-                davxml.ACE(
-                    davxml.Principal(davxml.Authenticated()),
-                    davxml.Grant(davxml.Privilege(caldavxml.ReadFreeBusy())),
+                element.ACE(
+                    element.Principal(element.Authenticated()),
+                    element.Grant(element.Privilege(caldavxml.ReadFreeBusy())),
                     TwistedACLInheritable(),
                 ),
             )
@@ -344,25 +344,25 @@
         if config.EnableProxyPrincipals:
             aces += (
                 # DAV:read/DAV:read-current-user-privilege-set access for this principal's calendar-proxy-read users.
-                davxml.ACE(
-                    davxml.Principal(davxml.HRef(joinURL(self._shareePrincipal.principalURL(), "calendar-proxy-read/"))),
-                    davxml.Grant(
-                        davxml.Privilege(davxml.Read()),
-                        davxml.Privilege(davxml.ReadCurrentUserPrivilegeSet()),
+                element.ACE(
+                    element.Principal(element.HRef(joinURL(self._shareePrincipal.principalURL(), "calendar-proxy-read/"))),
+                    element.Grant(
+                        element.Privilege(element.Read()),
+                        element.Privilege(element.ReadCurrentUserPrivilegeSet()),
                     ),
-                    davxml.Protected(),
+                    element.Protected(),
                     TwistedACLInheritable(),
                 ),
                 # DAV:read/DAV:read-current-user-privilege-set/DAV:write access for this principal's calendar-proxy-write users.
-                davxml.ACE(
-                    davxml.Principal(davxml.HRef(joinURL(self._shareePrincipal.principalURL(), "calendar-proxy-write/"))),
-                    davxml.Grant(*proxyprivs),
-                    davxml.Protected(),
+                element.ACE(
+                    element.Principal(element.HRef(joinURL(self._shareePrincipal.principalURL(), "calendar-proxy-write/"))),
+                    element.Grant(*proxyprivs),
+                    element.Protected(),
                     TwistedACLInheritable(),
                 ),
             )
 
-        returnValue(davxml.ACL(*aces))
+        returnValue(element.ACL(*aces))
 
     def validUserIDForShare(self, userid):
         """
@@ -633,14 +633,14 @@
             customxml.DTStamp.fromString(PyCalendarDateTime.getNowUTC().getText()),
             customxml.InviteNotification(
                 customxml.UID.fromString(record.inviteuid),
-                davxml.HRef.fromString(record.userid),
+                element.HRef.fromString(record.userid),
                 inviteStatusMapToXML[record.state](),
                 customxml.InviteAccess(inviteAccessMapToXML[record.access]()),
                 customxml.HostURL(
-                    davxml.HRef.fromString(hosturl),
+                    element.HRef.fromString(hosturl),
                 ),
                 customxml.Organizer(
-                    davxml.HRef.fromString(owner),
+                    element.HRef.fromString(owner),
                     customxml.CommonName.fromString(ownerCN),
                 ),
                 customxml.InviteSummary.fromString(record.summary),
@@ -666,7 +666,7 @@
 
     @inlineCallbacks
     def _xmlHandleInvite(self, request, docroot):
-        yield self.authorize(request, (davxml.Read(), davxml.Write()))
+        yield self.authorize(request, (element.Read(), element.Write()))
         result = (yield self._handleInvite(request, docroot))
         returnValue(result)
     
@@ -677,7 +677,7 @@
             access = None
             summary = None
             for item in inviteset.children:
-                if isinstance(item, davxml.HRef):
+                if isinstance(item, element.HRef):
                     userid = str(item)
                     continue
                 if isinstance(item, customxml.CommonName):
@@ -709,7 +709,7 @@
             userid = None
             access = []
             for item in inviteremove.children:
-                if isinstance(item, davxml.HRef):
+                if isinstance(item, element.HRef):
                     userid = str(item)
                     continue
                 if isinstance(item, customxml.ReadAccess) or isinstance(item, customxml.ReadWriteAccess):
@@ -785,11 +785,11 @@
             if badusers:
                 xml_responses = []
                 xml_responses.extend([
-                    davxml.StatusResponse(davxml.HRef(userid), davxml.Status.fromResponseCode(ok_code))
+                    element.StatusResponse(element.HRef(userid), element.Status.fromResponseCode(ok_code))
                     for userid in sorted(okusers)
                 ])
                 xml_responses.extend([
-                    davxml.StatusResponse(davxml.HRef(userid), davxml.Status.fromResponseCode(responsecode.FORBIDDEN))
+                    element.StatusResponse(element.HRef(userid), element.Status.fromResponseCode(responsecode.FORBIDDEN))
                     for userid in sorted(badusers)
                 ])
             
@@ -804,7 +804,7 @@
 
     @inlineCallbacks
     def _xmlHandleInviteReply(self, request, docroot):
-        yield self.authorize(request, (davxml.Read(), davxml.Write()))
+        yield self.authorize(request, (element.Read(), element.Write()))
         result = (yield self._handleInviteReply(request, docroot))
         returnValue(result)
     
@@ -817,7 +817,7 @@
         # Need to read the data and get the root element first
         xmldata = (yield allDataFromStream(request.stream))
         try:
-            doc = davxml.WebDAVDocument.fromString(xmldata)
+            doc = element.WebDAVDocument.fromString(xmldata)
         except ValueError, e:
             self.log_error("Error parsing doc (%s) Doc:\n %s" % (str(e), xmldata,))
             raise HTTPError(ErrorResponse(
@@ -889,7 +889,7 @@
         
         return customxml.InviteUser(
             customxml.UID.fromString(self.inviteuid),
-            davxml.HRef.fromString(self.userid),
+            element.HRef.fromString(self.userid),
             customxml.CommonName.fromString(self.name),
             customxml.InviteAccess(inviteAccessMapToXML[self.access]()),
             inviteStatusMapToXML[self.state](),
@@ -1110,7 +1110,7 @@
         # Set per-user displayname or color to whatever was given
         sharedCollection.setVirtualShare(ownerPrincipal, share)
         if displayname:
-            yield sharedCollection.writeProperty(davxml.DisplayName.fromString(displayname), request)
+            yield sharedCollection.writeProperty(element.DisplayName.fromString(displayname), request)
         if color:
             yield sharedCollection.writeProperty(customxml.CalendarColor.fromString(color), request)
 
@@ -1129,7 +1129,7 @@
         returnValue(XMLResponse(
             code = responsecode.OK,
             element = customxml.SharedAs(
-                davxml.HRef.fromString(joinURL(self.url(), share.localname))
+                element.HRef.fromString(joinURL(self.url(), share.localname))
             )
         ))
 
@@ -1219,10 +1219,10 @@
             customxml.InviteReply(
                 *(
                     (
-                        davxml.HRef.fromString(sharee),
+                        element.HRef.fromString(sharee),
                         inviteStatusMapToXML[state](),
                         customxml.HostURL(
-                            davxml.HRef.fromString(hostUrl),
+                            element.HRef.fromString(hostUrl),
                         ),
                         customxml.InReplyTo.fromString(replytoUID),
                     ) + ((customxml.InviteSummary.fromString(displayname),) if displayname is not None else ())
@@ -1248,7 +1248,7 @@
                 summary = str(item)
             elif isinstance(item, customxml.HostURL):
                 for hosturlItem in item.children:
-                    if isinstance(hosturlItem, davxml.HRef):
+                    if isinstance(hosturlItem, element.HRef):
                         hostUrl = str(hosturlItem)
             elif isinstance(item, customxml.InReplyTo):
                 replytoUID = str(item)

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/simpleresource.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/simpleresource.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/simpleresource.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -26,7 +26,7 @@
 ]
 
 from twext.web2 import http
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.noneprops import NonePropertyStore
 
 from twisted.internet.defer import succeed

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/stdconfig.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/stdconfig.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/stdconfig.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -21,7 +21,7 @@
 import os
 import re
 
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.resource import TwistedACLInheritable
 
 from twext.python.plistlib import PlistParser #@UnresolvedImport
@@ -928,7 +928,7 @@
         "UseExternalProxies" : False,
     },
 
-    "EnableKeepAlive": True,
+    "EnableKeepAlive": False,
 
     "EnableResponseCache":  True,
     "ResponseCacheTimeout": 30, # Minutes

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/storebridge.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/storebridge.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/storebridge.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -17,8 +17,8 @@
 
 from twext.python.log import Logger
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
-from twext.web2.dav.element.base import dav_namespace, WebDAVUnknownElement
+from txdav.xml import element as davxml
+from txdav.xml.base import dav_namespace, WebDAVUnknownElement
 from twext.web2.dav.http import ErrorResponse, ResponseQueue, MultiStatusResponse
 from twext.web2.dav.noneprops import NonePropertyStore
 from twext.web2.dav.resource import TwistedACLInheritable, AccessDeniedError
@@ -630,7 +630,7 @@
                         davxml.HRef.fromString(""),
                         davxml.Status.fromResponseCode(code),
                     davxml.Error(
-                        WebDAVUnknownElement.fromQname(*error),
+                        WebDAVUnknownElement.withName(*error),
                         customxml.UID.fromString(component.resourceUID()),
                     ) if error else None,
                     )
@@ -787,7 +787,7 @@
                     davxml.HRef.fromString(""),
                     davxml.Status.fromResponseCode(code),
                     davxml.Error(
-                        WebDAVUnknownElement.fromQname(*error),
+                        WebDAVUnknownElement.withName(*error),
                         customxml.UID.fromString(component.resourceUID()),
                     ) if error else None,
                 )
@@ -845,7 +845,7 @@
                     davxml.HRef.fromString(href),
                     davxml.Status.fromResponseCode(code),
                     davxml.Error(
-                        WebDAVUnknownElement.fromQname(*error),
+                        WebDAVUnknownElement.withName(*error),
                     ) if error else None,
                 )
             )
@@ -896,7 +896,7 @@
                     davxml.HRef.fromString(href),
                     davxml.Status.fromResponseCode(code),
                     davxml.Error(
-                        WebDAVUnknownElement.fromQname(*error),
+                        WebDAVUnknownElement.withName(*error),
                     ) if error else None,
                 )
             )

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_addressbookmultiget.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_addressbookmultiget.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_addressbookmultiget.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -20,7 +20,7 @@
 from twext.web2 import responsecode
 from twext.web2.iweb import IResponse
 from twext.web2.stream import MemoryStream
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.fileop import rmdir
 from twext.web2.dav.util import davXMLFromStream
 from twext.web2.test.test_server import SimpleRequest

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_addressbookquery.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_addressbookquery.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_addressbookquery.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -20,7 +20,7 @@
 from twext.web2 import responsecode
 from twext.web2.iweb import IResponse
 from twext.web2.stream import MemoryStream
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.fileop import rmdir
 from twext.web2.dav.util import davXMLFromStream
 from twext.web2.test.test_server import SimpleRequest

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_cache.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_cache.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_cache.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -20,7 +20,7 @@
 
 from twisted.internet.defer import succeed, maybeDeferred
 
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.util import allDataFromStream
 from twext.web2.stream import MemoryStream
 from twext.web2.http_headers import Headers

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_calendarquery.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_calendarquery.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_calendarquery.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -23,7 +23,7 @@
 from twext.web2 import responsecode
 from twext.web2.iweb import IResponse
 from twext.web2.stream import MemoryStream
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.util import davXMLFromStream
 from twext.web2.test.test_server import SimpleRequest
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_extensions.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_extensions.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_extensions.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -16,8 +16,7 @@
 ##
 
 from twext.python.filepath import CachingFilePath as FilePath
-from twext.web2.dav import davxml
-from twext.web2.dav.element.base import WebDAVElement
+from txdav.xml.element import WebDAVElement, ResourceType
 from twext.web2.http_headers import MimeType
 from twext.web2.static import MetaDataMixin
 
@@ -164,7 +163,7 @@
         def addUnicodeChild(davFile):
             m = MetaDataMixin()
             m.contentType = lambda: MimeType.fromString('text/plain')
-            m.resourceType = lambda: davxml.ResourceType()
+            m.resourceType = lambda: ResourceType()
             m.isCollection = lambda: False
             davFile.putChild(unicodeChildName, m)
         yield self.doDirectoryTest([nonASCIIFilename], addUnicodeChild,

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_mkcalendar.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_mkcalendar.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_mkcalendar.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -21,7 +21,7 @@
 from twext.web2 import responsecode
 from twext.web2.iweb import IResponse
 from twext.web2.stream import MemoryStream
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.fileop import rmdir
 from twext.web2.test.test_server import SimpleRequest
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_multiget.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_multiget.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_multiget.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -20,7 +20,7 @@
 from twext.web2 import responsecode
 from twext.web2.iweb import IResponse
 from twext.web2.stream import MemoryStream
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.util import davXMLFromStream
 from twext.web2.test.test_server import SimpleRequest
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_props.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_props.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_props.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -20,7 +20,7 @@
 
 from twext.web2 import responsecode, http_headers
 from twext.web2.iweb import IResponse
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.util import davXMLFromStream
 from twext.web2.test.test_server import SimpleRequest
 from twistedcaldav import caldavxml
@@ -202,8 +202,8 @@
                 return davXMLFromStream(response.stream).addCallback(got_xml)
 
             query = davxml.PropertyFind(
-                        davxml.AllProperties(),
-                    )
+                davxml.AllProperties(),
+            )
 
             request = SimpleRequest(
                 self.site,

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_resource.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_resource.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_resource.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -14,10 +14,7 @@
 # limitations under the License.
 ##
 
-from twext.web2.dav import davxml
-from twext.web2.dav.davxml import Principal
-from twext.web2.dav.davxml import Unauthenticated
-from twext.web2.dav.element.rfc2518 import HRef
+from txdav.xml.element import HRef, Principal, Unauthenticated
 from twext.web2.http import HTTPError
 from twext.web2.test.test_server import SimpleRequest
 
@@ -273,7 +270,7 @@
         newadbk = yield request.locateResource("/addressbooks/users/wsanchez/newadbk")
         yield newadbk.createAddressBookCollection()
         home.writeDeadProperty(carddavxml.DefaultAddressBookURL(
-            davxml.HRef("/addressbooks/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/newadbk/")
+            HRef("/addressbooks/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/newadbk/")
         ))
         request._newStoreTransaction.commit()
         
@@ -321,7 +318,7 @@
         newadbk = yield request.locateResource("/addressbooks/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/newadbk/")
         yield newadbk.createAddressBookCollection()
         home.writeDeadProperty(carddavxml.DefaultAddressBookURL(
-            davxml.HRef("/addressbooks/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/newadbk/")
+            HRef("/addressbooks/__uids__/6423F94A-6B76-4A3A-815B-D52CFD77935D/newadbk/")
         ))
         try:
             default = yield home.readProperty(carddavxml.DefaultAddressBookURL, request)

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_schedule.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_schedule.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_schedule.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -15,7 +15,7 @@
 ##
 
 from twext.web2 import responsecode, http_headers
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.util import davXMLFromStream
 from twext.web2.http import HTTPError
 from twext.web2.iweb import IResponse

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_sharing.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_sharing.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_sharing.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -16,7 +16,7 @@
 
 
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.http_headers import MimeType
 from twext.web2.iweb import IResource
 from twext.web2.stream import MemoryStream

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_upgrade.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_upgrade.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_upgrade.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -14,9 +14,15 @@
 # limitations under the License.
 ##
 
+import hashlib
+import os, zlib, cPickle
 
+from twisted.python.reflect import namedClass
 from twisted.internet.defer import inlineCallbacks
-from twext.web2.dav import davxml
+
+from txdav.xml.parser import WebDAVDocument
+from txdav.caldav.datastore.index_file import db_basename
+
 from twistedcaldav.config import config
 from twistedcaldav.directory.xmlfile import XMLDirectoryService
 from twistedcaldav.directory.resourceinfo import ResourceInfoDatabase
@@ -28,13 +34,8 @@
 from twistedcaldav.test.util import TestCase
 from calendarserver.tools.util import getDirectory
 
-import hashlib
-import os, zlib, cPickle
-from txdav.caldav.datastore.index_file import db_basename
-from twisted.python.reflect import namedClass
 
 
-
 freeBusyAttr = xattrname(
     "{urn:ietf:params:xml:ns:caldav}calendar-free-busy-set"
 )
@@ -214,7 +215,7 @@
 
         # Pickled XML
         value = "<?xml version='1.0' encoding='UTF-8'?>\r\n<calendar-free-busy-set xmlns='urn:ietf:params:xml:ns:caldav'>\r\n  <href xmlns='DAV:'>/calendars/__uids__/BB05932F-DCE7-4195-9ED4-0896EAFF3B0B/calendar</href>\r\n</calendar-free-busy-set>\r\n"
-        doc = davxml.WebDAVDocument.fromString(value)
+        doc = WebDAVDocument.fromString(value)
         value = cPickle.dumps(doc.root_element)
         self.assertEquals(updateFreeBusySet(value, directory), None)
 
@@ -240,7 +241,7 @@
 
         # Pickled XML
         value = "<?xml version='1.0' encoding='UTF-8'?>\r\n<calendar-free-busy-set xmlns='urn:ietf:params:xml:ns:caldav'>\r\n  <href xmlns='DAV:'>/calendars/users/wsanchez/calendar</href>\r\n</calendar-free-busy-set>\r\n"
-        doc = davxml.WebDAVDocument.fromString(value)
+        doc = WebDAVDocument.fromString(value)
         value = cPickle.dumps(doc.root_element)
         newValue = updateFreeBusySet(value, directory)
         newValue = zlib.decompress(newValue)
@@ -387,7 +388,7 @@
                             "@xattrs" :
                             {
                                 # Pickled XML Doc
-                                freeBusyAttr : cPickle.dumps(davxml.WebDAVDocument.fromString("<?xml version='1.0' encoding='UTF-8'?>\r\n<calendar-free-busy-set xmlns='urn:ietf:params:xml:ns:caldav'>\r\n  <href xmlns='DAV:'>/calendars/users/wsanchez/calendar</href>\r\n</calendar-free-busy-set>\r\n").root_element),
+                                freeBusyAttr : cPickle.dumps(WebDAVDocument.fromString("<?xml version='1.0' encoding='UTF-8'?>\r\n<calendar-free-busy-set xmlns='urn:ietf:params:xml:ns:caldav'>\r\n  <href xmlns='DAV:'>/calendars/users/wsanchez/calendar</href>\r\n</calendar-free-busy-set>\r\n").root_element),
                             },
                         },
                     },
@@ -1705,7 +1706,7 @@
     except zlib.error:
         return False
     try:
-        davxml.WebDAVDocument.fromString(value)
+        WebDAVDocument.fromString(value)
         return True
     except ValueError:
         return False

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_wrapping.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_wrapping.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/test_wrapping.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -24,7 +24,7 @@
 from twext.web2.http_headers import Headers
 from twext.enterprise.ienterprise import AlreadyFinishedError
 
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twistedcaldav.config import config
 
 from twisted.internet.defer import inlineCallbacks, returnValue

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/util.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/util.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/test/util.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -30,7 +30,7 @@
 from twext.python.memcacheclient import ClientFactory
 from twext.python.filepath import CachingFilePath as FilePath
 import twext.web2.dav.test.util
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.http import HTTPError, StatusResponse
 
 from twistedcaldav import memcacher

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/timezoneservice.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/timezoneservice.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/timezoneservice.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -25,7 +25,7 @@
 from twext.web2.dav.http import ErrorResponse
 
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.method.propfind import http_PROPFIND
 from twext.web2.dav.noneprops import NonePropertyStore
 from twext.web2.http import HTTPError

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/timezonestdservice.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/timezonestdservice.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/timezonestdservice.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -27,7 +27,7 @@
 
 from twext.python.log import Logger
 from twext.web2 import responsecode
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.http import ErrorResponse
 from twext.web2.dav.method.propfind import http_PROPFIND
 from twext.web2.dav.noneprops import NonePropertyStore

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/timezonexml.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/timezonexml.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/timezonexml.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -1,5 +1,5 @@
 ##
-# Copyright (c) 2011 Apple Inc. All rights reserved.
+# Copyright (c) 2011-2012 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.
@@ -18,14 +18,18 @@
 This module provides XML definitions for use with Timezone Standard Service.
 """
 
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
+from txdav.xml.element import registerElement
 
+
 ##
 # Timezone Service XML Definitions
 ##
 
 timezone_namespace = "urn:ietf:params:xml:ns:timezone-service"
 
+
+ at registerElement
 class Capabilities (davxml.WebDAVElement):
     namespace = timezone_namespace
     name = "capabilities"
@@ -33,6 +37,8 @@
         (timezone_namespace, "operation"): (0, None),
     }
 
+
+ at registerElement
 class Operation (davxml.WebDAVElement):
     namespace = timezone_namespace
     name = "operation"
@@ -42,14 +48,20 @@
         (timezone_namespace, "accept-parameter"): (0, None),
     }
 
+
+ at registerElement
 class Action (davxml.WebDAVTextElement):
     namespace = timezone_namespace
     name = "action"
 
+
+ at registerElement
 class Description (davxml.WebDAVTextElement):
     namespace = timezone_namespace
     name = "description"
 
+
+ at registerElement
 class AcceptParameter (davxml.WebDAVElement):
     namespace = timezone_namespace
     name = "accept-parameter"
@@ -61,22 +73,32 @@
         (timezone_namespace, "description"): (0, 1),
     }
 
+
+ at registerElement
 class Name (davxml.WebDAVTextElement):
     namespace = timezone_namespace
     name = "name"
 
+
+ at registerElement
 class Required (davxml.WebDAVTextElement):
     namespace = timezone_namespace
     name = "required"
 
+
+ at registerElement
 class Multi (davxml.WebDAVTextElement):
     namespace = timezone_namespace
     name = "multi"
 
+
+ at registerElement
 class Value (davxml.WebDAVTextElement):
     namespace = timezone_namespace
     name = "value"
 
+
+ at registerElement
 class TimezoneList (davxml.WebDAVElement):
     namespace = timezone_namespace
     name = "timezone-list"
@@ -85,10 +107,14 @@
         (timezone_namespace, "summary"): (0, None),
     }
 
+
+ at registerElement
 class Dtstamp (davxml.WebDAVTextElement):
     namespace = timezone_namespace
     name = "dtstamp"
 
+
+ at registerElement
 class Summary (davxml.WebDAVElement):
     namespace = timezone_namespace
     name = "summary"
@@ -100,26 +126,38 @@
         (timezone_namespace, "inactive"): (0, 1),
     }
 
+
+ at registerElement
 class Tzid (davxml.WebDAVTextElement):
     namespace = timezone_namespace
     name = "tzid"
 
+
+ at registerElement
 class LastModified (davxml.WebDAVTextElement):
     namespace = timezone_namespace
     name = "last-modified"
 
+
+ at registerElement
 class LocalName (davxml.WebDAVTextElement):
     namespace = timezone_namespace
     name = "local-name"
 
+
+ at registerElement
 class Alias (davxml.WebDAVTextElement):
     namespace = timezone_namespace
     name = "alias"
 
+
+ at registerElement
 class Inactive (davxml.WebDAVEmptyElement):
     namespace = timezone_namespace
     name = "inactive"
 
+
+ at registerElement
 class Timezones (davxml.WebDAVElement):
     namespace = timezone_namespace
     name = "timezones"
@@ -128,6 +166,8 @@
         (timezone_namespace, "tzdata"): (0, None),
     }
 
+
+ at registerElement
 class Tzdata (davxml.WebDAVElement):
     namespace = timezone_namespace
     name = "tzdata"
@@ -137,10 +177,14 @@
         (timezone_namespace, "observance"): (0, None),
     }
 
+
+ at registerElement
 class Calscale (davxml.WebDAVTextElement):
     namespace = timezone_namespace
     name = "calscale"
 
+
+ at registerElement
 class Observance (davxml.WebDAVElement):
     namespace = timezone_namespace
     name = "observance"
@@ -152,15 +196,20 @@
         (timezone_namespace, "utc-offset-to"): (1, 1),
     }
 
+
+ at registerElement
 class Onset (davxml.WebDAVTextElement):
     namespace = timezone_namespace
     name = "onset"
 
+
+ at registerElement
 class UTCOffsetFrom (davxml.WebDAVTextElement):
     namespace = timezone_namespace
     name = "utc-offset-from"
 
+
+ at registerElement
 class UTCOffsetTo (davxml.WebDAVTextElement):
     namespace = timezone_namespace
     name = "utc-offset-to"
-

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/upgrade.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/upgrade.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/upgrade.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -22,7 +22,7 @@
 from cPickle import loads as unpickle, UnpicklingError
 
 from twext.python.log import Logger
-from twext.web2.dav import davxml
+from txdav.xml import element
 from twext.web2.dav.fileop import rmdir
 
 from twistedcaldav import caldavxml
@@ -814,7 +814,7 @@
         pass
 
     try:
-        doc = davxml.WebDAVDocument.fromString(value)
+        doc = element.WebDAVDocument.fromString(value)
         freeBusySet = doc.root_element
     except ValueError:
         try:
@@ -837,7 +837,7 @@
                 fbset.add(newHref)
 
     if didUpdate:
-        property = caldavxml.CalendarFreeBusySet(*[davxml.HRef(href)
+        property = caldavxml.CalendarFreeBusySet(*[element.HRef(href)
             for href in fbset])
         value = compress(property.toxml())
         return value
@@ -1112,8 +1112,8 @@
                     request = FakeRequest(root, "PUT", None)
                     request.noAttendeeRefresh = True # tell scheduling to skip refresh
                     request.checkedSACL = True
-                    request.authnUser = request.authzUser = davxml.Principal(
-                        davxml.HRef.fromString("/principals/__uids__/%s/" % (uuid,))
+                    request.authnUser = request.authzUser = element.Principal(
+                        element.HRef.fromString("/principals/__uids__/%s/" % (uuid,))
                     )
 
                     # The request may end up with an associated transaction and we must make sure that is

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/base/datastore/file.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/base/datastore/file.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/base/datastore/file.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -25,7 +25,7 @@
 from txdav.idav import IDataStoreObject
 from txdav.base.propertystore.base import PropertyName
 
-from twext.web2.dav.element.rfc2518 import GETContentType
+from txdav.xml.rfc2518 import GETContentType
 from twext.web2.dav.resource import TwistedGETContentMD5
 
 from twisted.python import hashlib

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/base/propertystore/base.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/base/propertystore/base.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/base/propertystore/base.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -24,7 +24,7 @@
 ]
 
 from twext.python.log import LoggingMixIn
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 from twext.web2.dav.resource import TwistedGETContentMD5,\
     TwistedQuotaRootProperty
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/base/propertystore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/base/propertystore/sql.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/base/propertystore/sql.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -29,12 +29,11 @@
 from twext.enterprise.dal.syntax import (
     Select, Parameter, Update, Insert, TableSyntax, Delete)
 
+from txdav.xml.parser import WebDAVDocument
 from txdav.common.datastore.sql_tables import schema
 from txdav.base.propertystore.base import (AbstractPropertyStore,
                                            PropertyName, validKey)
 
-from twext.web2.dav.davxml import WebDAVDocument
-
 from twisted.internet.defer import inlineCallbacks, returnValue
 
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/base/propertystore/test/base.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/base/propertystore/test/base.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/base/propertystore/test/base.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -30,7 +30,7 @@
 from twisted.internet.defer import inlineCallbacks
 from twisted.trial import unittest
 
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 
 from txdav.idav import IPropertyStore
 from txdav.base.propertystore.base import PropertyName

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/base/propertystore/test/test_appledouble.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/base/propertystore/test/test_appledouble.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/base/propertystore/test/test_appledouble.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -29,7 +29,7 @@
 
 from txdav.base.propertystore.base import PropertyName
 from twisted.python.filepath import FilePath
-from twext.web2.dav.element.rfc2518 import GETContentType, HRef, Depth
+from txdav.xml.rfc2518 import GETContentType, HRef, Depth
 
 # This tar file contains a single file, 'f', with 2 xattrs; 'alpha' with
 # contents 'beta', and 'gamma' with contents 'delta'.

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/base/propertystore/test/test_xattr.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/base/propertystore/test/test_xattr.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/base/propertystore/test/test_xattr.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -19,7 +19,7 @@
 """
 
 from twext.python.filepath import CachingFilePath as FilePath
-from twext.web2.dav.element.base import WebDAVTextElement
+from txdav.xml.base import WebDAVTextElement
 from txdav.base.propertystore.base import PropertyName
 from txdav.base.propertystore.test import base
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/base/propertystore/xattr.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/base/propertystore/xattr.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/base/propertystore/xattr.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -32,12 +32,12 @@
 from cPickle import UnpicklingError, loads as unpickle
 from xattr import xattr
 
-from twext.web2.dav.davxml import WebDAVDocument
+from twisted.python.reflect import namedAny
 
+from txdav.xml.parser import WebDAVDocument
 from txdav.base.propertystore.base import AbstractPropertyStore, PropertyName,\
         validKey
 from txdav.idav import PropertyStoreError
-from twisted.python.reflect import namedAny
 
 #
 # RFC 2518 Section 12.13.1 says that removal of non-existing property is not an

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/caldav/datastore/file.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/caldav/datastore/file.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/caldav/datastore/file.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -37,8 +37,8 @@
 from twisted.python.failure import Failure
 
 from twext.python.vcomponent import VComponent
-from twext.web2.dav import davxml
-from twext.web2.dav.element.rfc2518 import ResourceType, GETContentType
+from txdav.xml import element as davxml
+from txdav.xml.rfc2518 import ResourceType, GETContentType
 from twext.web2.dav.resource import TwistedGETContentMD5
 from twext.web2.http_headers import generateContentType, MimeType
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/caldav/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/caldav/datastore/sql.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/caldav/datastore/sql.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -27,7 +27,7 @@
 
 from twext.python.clsprop import classproperty
 from twext.python.vcomponent import VComponent
-from twext.web2.dav.element.rfc2518 import ResourceType
+from txdav.xml.rfc2518 import ResourceType
 from twext.web2.http_headers import MimeType, generateContentType
 
 from twisted.internet.defer import inlineCallbacks, returnValue

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/caldav/datastore/test/common.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/caldav/datastore/test/common.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/caldav/datastore/test/common.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -27,15 +27,12 @@
 from twisted.python import hashlib
 
 from twext.python.clsprop import classproperty
-
-from twext.enterprise.ienterprise import AlreadyFinishedError
-
+from twext.python.vcomponent import VComponent
 from twext.python.filepath import CachingFilePath as FilePath
-from twext.web2.dav import davxml
+from twext.enterprise.ienterprise import AlreadyFinishedError
 from twext.web2.http_headers import MimeType
-from twext.web2.dav.element.base import WebDAVUnknownElement
-from twext.python.vcomponent import VComponent
 
+from txdav.xml.element import WebDAVUnknownElement, ResourceType
 from txdav.idav import IPropertyStore, IDataStore
 from txdav.base.propertystore.base import PropertyName
 from txdav.common.icommondatastore import HomeChildNameAlreadyExistsError, \
@@ -710,9 +707,9 @@
                 yield home.calendarWithName(name)).properties()
             self.assertEquals(
                 calendarProperties[
-                    PropertyName.fromString(davxml.ResourceType.sname())
+                    PropertyName.fromString(ResourceType.sname())
                 ],
-                davxml.ResourceType.calendar #@UndefinedVariable
+                ResourceType.calendar #@UndefinedVariable
             )
         yield checkProperties()
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/caldav/datastore/test/test_sql.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/caldav/datastore/test/test_sql.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/caldav/datastore/test/test_sql.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -27,7 +27,7 @@
 
 from twext.enterprise.dal.syntax import Select, Parameter, Insert
 from twext.python.vcomponent import VComponent
-from twext.web2.dav.element.rfc2518 import GETContentLanguage, ResourceType
+from txdav.xml.rfc2518 import GETContentLanguage, ResourceType
 
 from txdav.base.propertystore.base import PropertyName
 from txdav.caldav.datastore.test.common import CommonTests as CalendarCommonTests,\

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/caldav/datastore/test/test_util.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/caldav/datastore/test/test_util.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/caldav/datastore/test/test_util.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -450,7 +450,7 @@
         """
         yield self.createConflicted()
         from txdav.base.propertystore.base import PropertyName
-        from twext.web2.dav import davxml
+        from txdav.xml import element as davxml
         class StubConflictingElement(davxml.WebDAVTextElement):
             namespace = "http://example.com/ns/stub-conflict"
             name = "conflict"

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/caldav/datastore/util.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/caldav/datastore/util.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/caldav/datastore/util.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -155,8 +155,8 @@
     for calendarObject in (yield inCalendar.calendarObjects()):
         try:
             ctype = yield calendarObject.componentType()
-        except InvalidICalendarDataError, e:
-            log.error("  InvalidICalendarDataError: Failed to migrate calendar object: %s/%s/%s (%s)" % (
+        except Exception, e: # Don't stop for any error
+            log.error("  Failed to migrate calendar object: %s/%s/%s (%s)" % (
                 inCalendar.ownerHome().name(),
                 inCalendar.name(),
                 calendarObject.name(),
@@ -165,6 +165,7 @@
             bad_count += 1
             continue
 
+
         if ctype not in ("VEVENT", "VTODO"):
             log.error("Migration skipping unsupported (%s) calendar object %r"
                       % (ctype, calendarObject))

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/caldav/resource.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/caldav/resource.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/caldav/resource.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -31,7 +31,7 @@
 import urllib
 
 from twext.python.log import LoggingMixIn
-from twext.web2.dav.element.base import dav_namespace
+from txdav.xml.base import dav_namespace
 from twext.web2.http_headers import MimeType
 from twext.web2.http import RedirectResponse, Response
 from twext.web2.stream import MemoryStream

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/carddav/datastore/file.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/carddav/datastore/file.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/carddav/datastore/file.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -29,7 +29,7 @@
 
 from errno import ENOENT
 
-from twext.web2.dav.element.rfc2518 import ResourceType, GETContentType
+from txdav.xml.rfc2518 import ResourceType, GETContentType
 from twext.web2.dav.resource import TwistedGETContentMD5
 from twext.web2.http_headers import MimeType
 

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/carddav/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/carddav/datastore/sql.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/carddav/datastore/sql.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -31,7 +31,7 @@
 from twisted.internet.defer import inlineCallbacks, returnValue
 from twisted.python import hashlib
 
-from twext.web2.dav.element.rfc2518 import ResourceType
+from txdav.xml.rfc2518 import ResourceType
 from twext.web2.http_headers import MimeType
 
 from twistedcaldav import carddavxml, customxml

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/carddav/datastore/test/common.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/carddav/datastore/test/common.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/carddav/datastore/test/common.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -41,8 +41,7 @@
 from twistedcaldav.vcard import Component as VComponent
 
 from twext.python.filepath import CachingFilePath as FilePath
-from twext.web2.dav import davxml
-from twext.web2.dav.element.base import WebDAVUnknownElement
+from txdav.xml.element import WebDAVUnknownElement, ResourceType
 
 
 storePath = FilePath(__file__).parent().child("addressbook_store")
@@ -319,10 +318,10 @@
         self.assertNotIdentical((yield home.addressbookWithName(name)), None)
         def checkProperties():
             addressbookProperties = (yield home.addressbookWithName(name)).properties()
-            addressbookType = davxml.ResourceType.addressbook #@UndefinedVariable
+            addressbookType = ResourceType.addressbook #@UndefinedVariable
             self.assertEquals(
                 addressbookProperties[
-                    PropertyName.fromString(davxml.ResourceType.sname())
+                    PropertyName.fromString(ResourceType.sname())
                 ],
                 addressbookType
             )

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/carddav/datastore/test/test_sql.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/carddav/datastore/test/test_sql.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/carddav/datastore/test/test_sql.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -20,7 +20,7 @@
 """
 
 from twext.enterprise.dal.syntax import Select, Parameter
-from twext.web2.dav.element.rfc2518 import GETContentLanguage, ResourceType
+from txdav.xml.rfc2518 import GETContentLanguage, ResourceType
 
 from twisted.internet.defer import inlineCallbacks, returnValue
 from twisted.trial import unittest

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/carddav/resource.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/carddav/resource.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/carddav/resource.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -26,7 +26,7 @@
 ]
 
 from twext.python.log import LoggingMixIn
-from twext.web2.dav.element.base import dav_namespace
+from txdav.xml.base import dav_namespace
 
 from twistedcaldav.carddavxml import carddav_namespace
 from twistedcaldav.config import config

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/common/datastore/file.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/common/datastore/file.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/common/datastore/file.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -21,8 +21,8 @@
 
 from twext.internet.decorate import memoizedKey
 from twext.python.log import LoggingMixIn
-from twext.web2.dav.element.rfc2518 import ResourceType, GETContentType, HRef
-from twext.web2.dav.element.rfc5842 import ResourceID
+from txdav.xml.rfc2518 import ResourceType, GETContentType, HRef
+from txdav.xml.rfc5842 import ResourceID
 from twext.web2.http_headers import generateContentType, MimeType
 from twext.web2.dav.resource import TwistedGETContentMD5,\
     TwistedQuotaUsedProperty

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/common/datastore/sql.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/common/datastore/sql.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/common/datastore/sql.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -29,8 +29,8 @@
 from zope.interface import implements, directlyProvides
 
 from twext.python.log import Logger, LoggingMixIn
-from twext.web2.dav.element.rfc2518 import ResourceType
-from twext.web2.dav.element.parser import WebDAVDocument
+from txdav.xml.rfc2518 import ResourceType
+from txdav.xml.parser import WebDAVDocument
 from twext.web2.http_headers import MimeType
 
 from twisted.python import hashlib

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/common/datastore/test/test_sql.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/common/datastore/test/test_sql.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/common/datastore/test/test_sql.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -19,7 +19,7 @@
 """
 
 from twext.enterprise.dal.syntax import Select
-from twext.web2.dav import davxml
+from txdav.xml import element as davxml
 
 from twisted.internet.defer import inlineCallbacks
 from twisted.internet.task import Clock

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/common/datastore/upgrade/sql/upgrades/upgrade_from_1_to_2.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/common/datastore/upgrade/sql/upgrades/upgrade_from_1_to_2.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/common/datastore/upgrade/sql/upgrades/upgrade_from_1_to_2.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -16,7 +16,7 @@
 ##
 
 from twext.enterprise.dal.syntax import Update
-from twext.web2.dav.element.parser import WebDAVDocument
+from txdav.xml.parser import WebDAVDocument
 from twisted.internet.defer import inlineCallbacks
 from twistedcaldav import caldavxml
 from txdav.common.datastore.sql_tables import schema

Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/common/inotifications.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/common/inotifications.py	2012-03-22 00:23:24 UTC (rev 8920)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/common/inotifications.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -88,7 +88,7 @@
             C{CS:notificationtype} property.
             
         @type xmltype: an instance of
-            L{twext.web2.dav.element.base.WebDAVElement},
+            L{txdav.xml.base.WebDAVElement},
             most likely a subclass like L{twistedcaldav.customxml.InviteReply},
             L{twistedcaldav.customxml.InviteRemove}, etc.
 


Property changes on: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml
___________________________________________________________________
Added: svn:ignore
   + *.pyc


Deleted: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/__init__.py
===================================================================
--- CalendarServer/trunk/txdav/xml/__init__.py	2012-03-22 00:02:25 UTC (rev 8919)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/__init__.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -1,54 +0,0 @@
-# Copyright (c) 2009 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-##
-# Copyright (c) 2005-2012 Apple Computer, Inc. All rights reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-##
-
-"""
-WebDAV XML support.
-
-This module provides XML utilities for use with WebDAV.
-
-See RFC 2518: http://www.ietf.org/rfc/rfc2518.txt (WebDAV)
-See RFC 3253: http://www.ietf.org/rfc/rfc3253.txt (WebDAV + Versioning)
-See RFC 3744: http://www.ietf.org/rfc/rfc3744.txt (WebDAV ACLs)
-See RFC 4331: http://www.ietf.org/rfc/rfc4331.txt (WebDAV Quota)
-See RFC 5842: http://www.ietf.org/rfc/rfc5842.txt (WebDAV Bind)
-"""
-
-__all__ = [
-    "base",
-    "element",
-    "parser",
-]
-
-import txdav.xml.rfc2518
-import txdav.xml.rfc3253
-import txdav.xml.rfc3744
-import txdav.xml.rfc4331
-import txdav.xml.rfc5842
-import txdav.xml.rfc5397
-import txdav.xml.rfc5995
-import txdav.xml.draft_sync
-import txdav.xml.extensions
-
-txdav # Shhh pyflakes

Copied: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/__init__.py (from rev 8919, CalendarServer/trunk/txdav/xml/__init__.py)
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/__init__.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/__init__.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -0,0 +1,54 @@
+# Copyright (c) 2009 Twisted Matrix Laboratories.
+# See LICENSE for details.
+
+##
+# Copyright (c) 2005-2012 Apple Computer, Inc. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+##
+
+"""
+WebDAV XML support.
+
+This module provides XML utilities for use with WebDAV.
+
+See RFC 2518: http://www.ietf.org/rfc/rfc2518.txt (WebDAV)
+See RFC 3253: http://www.ietf.org/rfc/rfc3253.txt (WebDAV + Versioning)
+See RFC 3744: http://www.ietf.org/rfc/rfc3744.txt (WebDAV ACLs)
+See RFC 4331: http://www.ietf.org/rfc/rfc4331.txt (WebDAV Quota)
+See RFC 5842: http://www.ietf.org/rfc/rfc5842.txt (WebDAV Bind)
+"""
+
+__all__ = [
+    "base",
+    "element",
+    "parser",
+]
+
+import txdav.xml.rfc2518
+import txdav.xml.rfc3253
+import txdav.xml.rfc3744
+import txdav.xml.rfc4331
+import txdav.xml.rfc5842
+import txdav.xml.rfc5397
+import txdav.xml.rfc5995
+import txdav.xml.draft_sync
+import txdav.xml.extensions
+
+txdav # Shhh pyflakes

Deleted: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/base.py
===================================================================
--- CalendarServer/trunk/txdav/xml/base.py	2012-03-22 00:02:25 UTC (rev 8919)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/base.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -1,783 +0,0 @@
-##
-# Copyright (c) 2005-2012 Apple Computer, Inc. All rights reserved.
-# Copyright (c) 2007 Twisted Matrix Laboratories.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-##
-
-"""
-WebDAV XML base classes.
-
-This module provides XML utilities for use with WebDAV.
-
-See RFC 2518: http://www.ietf.org/rfc/rfc2518.txt (WebDAV)
-"""
-
-__all__ = [
-    "dav_namespace",
-    "twisted_dav_namespace",
-    "twisted_private_namespace",
-    "encodeXMLName",
-    "decodeXMLName",
-    "WebDAVElement",
-    "PCDATAElement",
-    "WebDAVOneShotElement",
-    "WebDAVUnknownElement",
-    "WebDAVEmptyElement",
-    "WebDAVTextElement",
-    "WebDAVDateTimeElement",
-    "DateTimeHeaderElement",
-]
-
-import datetime
-import string
-import cStringIO as StringIO
-import re
-
-from twext.python.log import Logger
-from twext.web2.http_headers import parseDateTime
-
-log = Logger()
-
-##
-# Base XML elements
-##
-
-_elements_by_qname = {}
-
-dav_namespace = "DAV:"
-twisted_dav_namespace = "http://twistedmatrix.com/xml_namespace/dav/"
-twisted_private_namespace = twisted_dav_namespace + "private/"
-
-
-def encodeXMLName(namespace, name):
-    """
-    Encodes an XML namespace and name into a UTF-8 string.
-    If namespace is None, returns "name", otherwise, returns
-    "{namespace}name".
-    """
-    if not namespace:
-        sname = name
-    else:
-        sname = u"{%s}%s" % (namespace, name)
-
-    return sname.encode("utf-8")
-
-
-def decodeXMLName(name):
-    """
-    Decodes an XML (namespace, name) pair from an ASCII string as
-    encoded by encodeXMLName().
-    """
-    def invalid():
-        raise ValueError("Invalid encoded name: %r" % (name,))
-
-    if not name:
-        invalid()
-
-    if name[0] is "{":
-        index = name.find("}")
-        if (index is -1 or not len(name) > index):
-            invalid()
-
-        namespace = name[1:index].decode("utf-8")
-        localname = name[index+1:].decode("utf-8")
-
-        if not namespace:
-            namespace = None
-
-        if not localname:
-            invalid()
-
-    else:
-        namespace = None
-        localname = name.decode("utf-8")
-    
-    if "{" in localname or "}" in localname:
-        invalid()
-
-    return (namespace, localname)
-
-
-class WebDAVElement (object):
-    """
-    WebDAV XML element. (RFC 2518, section 12)
-    """
-    namespace          = dav_namespace # Element namespace (class variable)
-    name               = None          # Element name (class variable)
-    allowed_children   = None          # Types & count limits on child elements
-    allowed_attributes = None          # Allowed attribute names
-    hidden             = False         # Don't list in PROPFIND with <allprop>
-    protected          = False         # See RFC 3253 section 1.4.1
-    unregistered       = False         # Subclass of factory; doesn't register
-
-    def __init__(self, *children, **attributes):
-        super(WebDAVElement, self).__init__()
-
-        if self.allowed_children is None:
-            raise NotImplementedError(
-                "WebDAVElement subclass %s is not implemented."
-                % (self.__class__.__name__,)
-            )
-
-        my_children = []
-
-        allowPCDATA = self.allowed_children.has_key(PCDATAElement)
-
-        for child in children:
-            if child is None:
-                continue
-
-            if isinstance(child, (str, unicode)):
-                child = PCDATAElement(child)
-
-            if isinstance(child, PCDATAElement) and not allowPCDATA:
-                continue
-
-            my_children.append(child)
-
-        self.children = tuple(my_children)
-        self.attributes = attributes
-
-    @classmethod
-    def qname(cls):
-        return (cls.namespace, cls.name)
-
-    @classmethod
-    def sname(cls):
-        return encodeXMLName(cls.namespace, cls.name)
-
-    def validate(self):
-        children = self.children
-        attributes = self.attributes
-
-        if self.allowed_children is None:
-            raise NotImplementedError(
-                "WebDAVElement subclass %s is not implemented."
-                % (self.__class__.__name__,)
-            )
-
-        #
-        # Validate that children are of acceptable types
-        #
-        allowed_children = dict([
-            (child_type, list(limits))
-            for child_type, limits
-            in self.allowed_children.items()
-        ])
-
-        my_children = []
-
-        for child in children:
-
-            assert isinstance(child, (WebDAVElement, PCDATAElement)), "Not an element: %r" % (child,)
-            
-            child.validate()
-
-            for allowed, (min, max) in allowed_children.items():
-                if type(allowed) == type and isinstance(child, allowed):
-                    qname = allowed
-                elif child.qname() == allowed:
-                    qname = allowed
-                else:
-                    continue
-
-                if min is not None and min > 0:
-                    min -= 1
-                if max is not None:
-                    assert max > 0, "Too many children of type %s for %s" % (child.sname(), self.sname())
-                    max -= 1
-                allowed_children[qname] = (min, max)
-                my_children.append(child)
-                break
-            else:
-                if not (isinstance(child, PCDATAElement) and child.isWhitespace()):
-                    log.debug(
-                        "Child of type %s is unexpected and therefore ignored in %s element"
-                        % (child.sname(), self.sname())
-                    )
-
-        for qname, (min, max) in allowed_children.items():
-            if min != 0:
-                raise ValueError("Not enough children of type %s for %s"
-                                 % (encodeXMLName(*qname), self.sname()))
-
-        self.children = tuple(my_children)
-
-        #
-        # Validate that attributes have known names
-        #
-        my_attributes = {}
-
-        if self.allowed_attributes:
-            for name in attributes:
-                if name not in self.allowed_attributes:
-                    log.debug("Attribute %s is unexpected in %s element" % (name, self.sname()))
-                my_attributes[name] = attributes[name]
-
-            for name, required in self.allowed_attributes.items():
-                if required and name not in my_attributes:
-                    raise ValueError("Attribute %s is required in %s element"
-                                     % (name, self.sname()))
-
-        else:
-            if not isinstance(self, WebDAVUnknownElement) and attributes:
-                log.debug("Attributes %s are unexpected in %s element"
-                          % (attributes.keys(), self.sname()))
-            my_attributes.update(attributes)
-
-        self.attributes = my_attributes
-
-    def __str__(self):
-        return self.sname()
-
-    def __repr__(self):
-        if hasattr(self, "attributes") and hasattr(self, "children"):
-            return "<%s %r: %r>" % (self.sname(), self.attributes, self.children)
-        else:
-            return "<%s>" % (self.sname())
-
-    def __eq__(self, other):
-        if isinstance(other, WebDAVElement):
-            return (
-                self.name       == other.name       and
-                self.namespace  == other.namespace  and
-                self.attributes == other.attributes and
-                self.children   == other.children
-            )
-        else:
-            return NotImplemented
-
-    def __ne__(self, other):
-        return not self.__eq__(other)
-
-    def __contains__(self, child):
-        return child in self.children
-
-    def writeXML(self, output, pretty=True):
-        output.write("<?xml version='1.0' encoding='UTF-8'?>" + ("\n" if pretty else ""))
-        self._writeToStream(output, "", 0, pretty)
-
-    def _writeToStream(self, output, ns, level, pretty):
-        """
-        Fast XML output.
-
-        @param output: C{stream} to write to.
-        @param ns: C{str} containing the namespace of the enclosing element.
-        @param level: C{int} containing the element nesting level (starts at 0).
-        @param pretty: C{bool} whether to use 'pretty' formatted output or not.
-        """
-        
-        # Do pretty indent
-        if pretty and level:
-            output.write("  " * level)
-        
-        # Check for empty element (one with either no children or a single PCDATA that is itself empty)
-        if (len(self.children) == 0 or
-            (len(self.children) == 1 and isinstance(self.children[0], PCDATAElement) and len(str(self.children[0])) == 0)):
-
-            # Write out any attributes or the namespace if difference from enclosing element.
-            if self.attributes or (ns != self.namespace):
-                output.write("<%s" % (self.name,))
-                for name, value in self.attributes.iteritems():
-                    self._writeAttributeToStream(output, name, value)
-                if ns != self.namespace:
-                    output.write(" xmlns='%s'" % (self.namespace,))
-                output.write("/>")
-            else:
-                output.write("<%s/>" % (self.name,))
-        else:
-            # Write out any attributes or the namespace if difference from enclosing element.
-            if self.attributes or (ns != self.namespace):
-                output.write("<%s" % (self.name,))
-                for name, value in self.attributes.iteritems():
-                    self._writeAttributeToStream(output, name, value)
-                if ns != self.namespace:
-                    output.write(" xmlns='%s'" % (self.namespace,))
-                    ns = self.namespace
-                output.write(">")
-            else:
-                output.write("<%s>" % (self.name,))
-                
-            # Determine nature of children when doing pretty print: we do
-            # not want to insert CRLFs or any other whitespace in PCDATA.
-            hasPCDATA = False
-            for child in self.children:
-                if isinstance(child, PCDATAElement):
-                    hasPCDATA = True
-                    break
-            
-            # Write out the children.
-            if pretty and not hasPCDATA:
-                output.write("\r\n")
-            for child in self.children:
-                child._writeToStream(output, ns, level+1, pretty)
-                
-            # Close the element.
-            if pretty and not hasPCDATA and level:
-                output.write("  " * level)
-            output.write("</%s>" % (self.name,))
-
-        if pretty and level:
-            output.write("\r\n")
-
-    def _writeAttributeToStream(self, output, name, value):
-        
-        # Quote any single quotes. We do not need to be any smarter than this.
-        value = value.replace("'", "'")
-
-        output.write(" %s='%s'" % (name, value,))  
-      
-    def toxml(self, pretty=True):
-        output = StringIO.StringIO()
-        self.writeXML(output, pretty)
-        return str(output.getvalue())
-
-    def element(self, document):
-        element = document.createElementNS(self.namespace, self.name)
-        if hasattr(self, "attributes"):
-            for name, value in self.attributes.items():
-                namespace, name = decodeXMLName(name)
-                attribute = document.createAttributeNS(namespace, name)
-                attribute.nodeValue = value
-                element.setAttributeNodeNS(attribute)
-        return element
-
-    def addToDOM(self, document, parent):
-        element = self.element(document)
-
-        if parent is None:
-            document.appendChild(element)
-        else:
-            parent.appendChild(element)
-
-        for child in self.children:
-            if child:
-                try:
-                    child.addToDOM(document, element)
-                except:
-                    log.err("Unable to add child %r of element %s to DOM" % (child, self))
-                    raise
-
-    def childrenOfType(self, child_type):
-        """
-        Returns a list of children with the same qname as the given type.
-        """
-        if type(child_type) is tuple:
-            qname = child_type
-        else:
-            qname = child_type.qname()
-
-        return [ c for c in self.children if c.qname() == qname ]
-
-    def childOfType(self, child_type):
-        """
-        Returns a child of the given type, if any, or None.
-        Raises ValueError if more than one is found.
-        """
-        found = None
-        for child in self.childrenOfType(child_type):
-            if found:
-                raise ValueError("Multiple %s elements found in %s" % (child_type.sname(), self.toxml()))
-            found = child
-        return found
-
-    def removeWhitespaceNodes(self):
-        """ Removes all of the whitespace-only text decendants of a DOM node. """
-        # prepare the list of text nodes to remove (and recurse when needed)
-        remove_list = []
-        for child in self.children:
-            if isinstance(child, PCDATAElement) and not child.data.strip():
-                # add this text node to the to-be-removed list
-                remove_list.append(child)
-            elif isinstance(child, WebDAVElement):
-                # recurse, it's the simplest way to deal with the subtree
-                child.removeWhitespaceNodes()
-
-        # perform the removals
-        newchildren = []
-        for child in self.children:
-            if child not in remove_list:
-                newchildren.append(child)
-        self.children = tuple(newchildren)
-
-
-class PCDATAElement (object):
-    def __init__(self, data):
-        super(PCDATAElement, self).__init__()
-
-        if data is None:
-            data = ""
-        elif type(data) is unicode:
-            data = data.encode("utf-8")
-        else:
-            assert type(data) is str, ("PCDATA must be a string: %r" % (data,))
-
-        self.data = data
-
-    @classmethod
-    def qname(cls):
-        return (None, "#PCDATA")
-
-    @classmethod
-    def sname(cls):
-        return "#PCDATA"
-
-    def validate(self):
-        pass
-
-    def __str__(self):
-        return str(self.data)
-
-    def __repr__(self):
-        return "<%s: %r>" % (self.__class__.__name__, self.data)
-
-    def __add__(self, other):
-        if isinstance(other, PCDATAElement):
-            return self.__class__(self.data + other.data)
-        else:
-            return self.__class__(self.data + other)
-
-    def __eq__(self, other):
-        if isinstance(other, PCDATAElement):
-            return self.data == other.data
-        elif type(other) in (str, unicode):
-            return self.data == other
-        else:
-            return NotImplemented
-
-    def __ne__(self, other):
-        return not self.__eq__(other)
-
-    def isWhitespace(self):
-        for char in str(self):
-            if char not in string.whitespace:
-                return False
-        return True
-
-    def element(self, document):
-        return document.createTextNode(self.data)
-
-    def addToDOM(self, document, parent):
-        try:
-            parent.appendChild(self.element(document))
-        except TypeError:
-            log.err("Invalid PCDATA: %r" % (self.data,))
-            raise
-
-    def _writeToStream(self, output, ns, level, pretty):
-        # Do escaping/CDATA behavior
-        if "\r" in self.data or "\n" in self.data:
-            # Do CDATA
-            cdata = "<![CDATA[%s]]>" % (self.data.replace("]]>", "]]>"),)
-        else:
-            cdata = self.data
-            if "&" in cdata:
-                cdata = cdata.replace("&", "&")
-            if "<" in cdata:
-                cdata = cdata.replace("<", "<")
-            if ">" in cdata:
-                cdata = cdata.replace(">", ">")
-
-        output.write(cdata)
-
-
-class WebDAVOneShotElement (WebDAVElement):
-    """
-    Element with exactly one WebDAVEmptyElement child and no attributes.
-    """
-    __singletons = {}
-
-    def __new__(clazz, *children):
-        child = None
-        for next in children:
-            if isinstance(next, WebDAVEmptyElement):
-                if child is not None:
-                    raise ValueError("%s must have exactly one child, not %r"
-                                     % (clazz.__name__, children))
-                child = next
-            elif isinstance(next, PCDATAElement):
-                pass
-            else:
-                raise ValueError("%s child is not a WebDAVEmptyElement instance: %s"
-                                 % (clazz.__name__, next))
-
-        if clazz not in WebDAVOneShotElement.__singletons:
-            WebDAVOneShotElement.__singletons[clazz] = {
-                child: WebDAVElement.__new__(clazz)
-            }
-        elif child not in WebDAVOneShotElement.__singletons[clazz]:
-            WebDAVOneShotElement.__singletons[clazz][child] = (
-                WebDAVElement.__new__(clazz)
-            )
-
-        return WebDAVOneShotElement.__singletons[clazz][child]
-
-
-class WebDAVUnknownElement (WebDAVElement):
-    """
-    Placeholder for unknown element tag names.
-    """
-    allowed_children = {
-        WebDAVElement: (0, None),
-        PCDATAElement: (0, None),
-    }
-
-    @classmethod
-    def withName(cls, namespace, name):
-        child = cls()
-        child.namespace = namespace
-        child.name = name
-        return child
-
-    def qname(self):
-        return (self.namespace, self.name)
-
-    def sname(self):
-        return encodeXMLName(self.namespace, self.name)
-
-
-class WebDAVEmptyElement (WebDAVElement):
-    """
-    WebDAV element with no contents.
-    """
-    __singletons = {}
-
-    def __new__(clazz, *args, **kwargs):
-        assert not args
-
-        if kwargs:
-            return WebDAVElement.__new__(clazz)
-        else:
-            if clazz not in WebDAVEmptyElement.__singletons:
-                WebDAVEmptyElement.__singletons[clazz] = (WebDAVElement.__new__(clazz))
-            return WebDAVEmptyElement.__singletons[clazz]
-
-    allowed_children = {}
-    children = ()
-
-    def __hash__(self):
-        """
-        Define a hash method, so that an empty element can serve as dictionary
-        keys. It's mainly useful to define singletons with
-        L{WebDAVOneShotElement}.
-        """
-        return hash((self.name, self.namespace))
-
-
-class WebDAVTextElement (WebDAVElement):
-    """
-    WebDAV element containing PCDATA.
-    """
-    @classmethod
-    def fromString(clazz, string):
-        if string is None:
-            return clazz()
-        elif isinstance(string, (str, unicode)):
-            return clazz(PCDATAElement(string))
-        else:
-            return clazz(PCDATAElement(str(string)))
-
-    allowed_children = { PCDATAElement: (0, None) }
-
-    def __str__(self):
-        return "".join([c.data for c in self.children])
-
-    def __repr__(self):
-        content = str(self)
-        if content:
-            return "<%s: %r>" % (self.sname(), content)
-        else:
-            return "<%s>" % (self.sname(),)
-
-    def __eq__(self, other):
-        if isinstance(other, WebDAVTextElement):
-            return str(self) == str(other)
-        elif type(other) in (str, unicode):
-            return str(self) == other
-        else:
-            return NotImplemented
-
-
-class WebDAVDateTimeElement (WebDAVTextElement):
-    """
-    WebDAV date-time element. (RFC 2518, section 23.2)
-    """
-    @classmethod
-    def fromDate(clazz, date):
-        """
-        date may be a datetime.datetime instance, a POSIX timestamp
-        (integer value, such as returned by time.time()), or an ISO
-        8601-formatted (eg. "2005-06-13T16:14:11Z") date/time string.
-        """
-        def isoformat(date):
-            if date.utcoffset() is None:
-                return date.isoformat() + "Z"
-            else:
-                return date.isoformat()
-
-        if type(date) is int:
-            date = isoformat(datetime.datetime.fromtimestamp(date))
-        elif type(date) is str:
-            pass
-        elif type(date) is unicode:
-            date = date.encode("utf-8")
-        elif isinstance(date, datetime.datetime):
-            date = isoformat(date)
-        else:
-            raise ValueError("Unknown date type: %r" % (date,))
-
-        return clazz(PCDATAElement(date))
-
-    def __init__(self, *children, **attributes):
-        super(WebDAVDateTimeElement, self).__init__(*children, **attributes)
-        self.datetime() # Raise ValueError if the format is wrong
-
-    def __eq__(self, other):
-        if isinstance(other, WebDAVDateTimeElement):
-            return self.datetime() == other.datetime()
-        else:
-            return NotImplemented
-
-    def datetime(self):
-        s = str(self)
-        if not s:
-            return None
-        else:
-            return parse_date(s)
-
-
-class DateTimeHeaderElement (WebDAVTextElement):
-    """
-    WebDAV date-time element for elements that substitute for HTTP
-    headers. (RFC 2068, section 3.3.1)
-    """
-    @classmethod
-    def fromDate(clazz, date):
-        """
-        date may be a datetime.datetime instance, a POSIX timestamp
-        (integer value, such as returned by time.time()), or an RFC
-        2068 Full Date (eg. "Mon, 23 May 2005 04:52:22 GMT") string.
-        """
-        def format(date):
-            #
-            # FIXME: strftime() is subject to localization nonsense; we need to
-            # ensure that we're using the correct localization, or don't use
-            # strftime().
-            #
-            return date.strftime("%a, %d %b %Y %H:%M:%S GMT")
-
-        if type(date) is int:
-            date = format(datetime.datetime.fromtimestamp(date))
-        elif type(date) is str:
-            pass
-        elif type(date) is unicode:
-            date = date.encode("utf-8")
-        elif isinstance(date, datetime.datetime):
-            if date.tzinfo:
-                raise NotImplementedError("I need to normalize to UTC")
-            date = format(date)
-        else:
-            raise ValueError("Unknown date type: %r" % (date,))
-
-        return clazz(PCDATAElement(date))
-
-    def __init__(self, *children, **attributes):
-        super(DateTimeHeaderElement, self).__init__(*children, **attributes)
-        self.datetime() # Raise ValueError if the format is wrong
-
-    def __eq__(self, other):
-        if isinstance(other, WebDAVDateTimeElement):
-            return self.datetime() == other.datetime()
-        else:
-            return NotImplemented
-
-    def datetime(self):
-        s = str(self)
-        if not s:
-            return None
-        else:
-            return parseDateTime(s)
-
-
-##
-# Utilities
-##
-
-class FixedOffset (datetime.tzinfo):
-    """
-    Fixed offset in minutes east from UTC.
-    """
-    def __init__(self, offset, name=None):
-        super(FixedOffset, self).__init__()
-
-        self._offset = datetime.timedelta(minutes=offset)
-        self._name   = name
-
-    def utcoffset(self, dt): return self._offset
-    def tzname   (self, dt): return self._name
-    def dst      (self, dt): return datetime.timedelta(0)
-
-
-_regex_ISO8601Date = re.compile(
-    "^" +
-    "(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})T" +
-    "(?P<hour>\d{2}):(?P<minute>\d{2}):(?P<second>\d{2})(?:.(?P<subsecond>\d+))*" +
-    "(?:Z|(?P<offset_sign>\+|-)(?P<offset_hour>\d{2}):(?P<offset_minute>\d{2}))" +
-    "$"
-)
-
-def parse_date(date):
-    """
-    Parse an ISO 8601 date and return a corresponding datetime.datetime object.
-    """
-    # See http://www.iso.org/iso/en/prods-services/popstds/datesandtime.html
-
-    match = _regex_ISO8601Date.match(date)
-    if match is not None:
-        subsecond = match.group("subsecond")
-        if subsecond is None:
-            subsecond = 0
-        else:
-            subsecond = int(subsecond)
-
-        offset_sign = match.group("offset_sign")
-        if offset_sign is None:
-            offset = FixedOffset(0)
-        else:
-            offset_hour   = int(match.group("offset_hour"  ))
-            offset_minute = int(match.group("offset_minute"))
-
-            delta = (offset_hour * 60) + offset_minute
-
-            if   offset_sign == "+": offset = FixedOffset(0 - delta)
-            elif offset_sign == "-": offset = FixedOffset(0 + delta)
-
-        return datetime.datetime(
-            int(match.group("year"  )),
-            int(match.group("month" )),
-            int(match.group("day"   )),
-            int(match.group("hour"  )),
-            int(match.group("minute")),
-            int(match.group("second")),
-            subsecond,
-            offset
-        )
-    else:
-        raise ValueError("Invalid ISO 8601 date format: %r" % (date,))

Copied: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/base.py (from rev 8919, CalendarServer/trunk/txdav/xml/base.py)
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/base.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/base.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -0,0 +1,783 @@
+##
+# Copyright (c) 2005-2012 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2007 Twisted Matrix Laboratories.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+##
+
+"""
+WebDAV XML base classes.
+
+This module provides XML utilities for use with WebDAV.
+
+See RFC 2518: http://www.ietf.org/rfc/rfc2518.txt (WebDAV)
+"""
+
+__all__ = [
+    "dav_namespace",
+    "twisted_dav_namespace",
+    "twisted_private_namespace",
+    "encodeXMLName",
+    "decodeXMLName",
+    "WebDAVElement",
+    "PCDATAElement",
+    "WebDAVOneShotElement",
+    "WebDAVUnknownElement",
+    "WebDAVEmptyElement",
+    "WebDAVTextElement",
+    "WebDAVDateTimeElement",
+    "DateTimeHeaderElement",
+]
+
+import datetime
+import string
+import cStringIO as StringIO
+import re
+
+from twext.python.log import Logger
+from twext.web2.http_headers import parseDateTime
+
+log = Logger()
+
+##
+# Base XML elements
+##
+
+_elements_by_qname = {}
+
+dav_namespace = "DAV:"
+twisted_dav_namespace = "http://twistedmatrix.com/xml_namespace/dav/"
+twisted_private_namespace = twisted_dav_namespace + "private/"
+
+
+def encodeXMLName(namespace, name):
+    """
+    Encodes an XML namespace and name into a UTF-8 string.
+    If namespace is None, returns "name", otherwise, returns
+    "{namespace}name".
+    """
+    if not namespace:
+        sname = name
+    else:
+        sname = u"{%s}%s" % (namespace, name)
+
+    return sname.encode("utf-8")
+
+
+def decodeXMLName(name):
+    """
+    Decodes an XML (namespace, name) pair from an ASCII string as
+    encoded by encodeXMLName().
+    """
+    def invalid():
+        raise ValueError("Invalid encoded name: %r" % (name,))
+
+    if not name:
+        invalid()
+
+    if name[0] is "{":
+        index = name.find("}")
+        if (index is -1 or not len(name) > index):
+            invalid()
+
+        namespace = name[1:index].decode("utf-8")
+        localname = name[index+1:].decode("utf-8")
+
+        if not namespace:
+            namespace = None
+
+        if not localname:
+            invalid()
+
+    else:
+        namespace = None
+        localname = name.decode("utf-8")
+    
+    if "{" in localname or "}" in localname:
+        invalid()
+
+    return (namespace, localname)
+
+
+class WebDAVElement (object):
+    """
+    WebDAV XML element. (RFC 2518, section 12)
+    """
+    namespace          = dav_namespace # Element namespace (class variable)
+    name               = None          # Element name (class variable)
+    allowed_children   = None          # Types & count limits on child elements
+    allowed_attributes = None          # Allowed attribute names
+    hidden             = False         # Don't list in PROPFIND with <allprop>
+    protected          = False         # See RFC 3253 section 1.4.1
+    unregistered       = False         # Subclass of factory; doesn't register
+
+    def __init__(self, *children, **attributes):
+        super(WebDAVElement, self).__init__()
+
+        if self.allowed_children is None:
+            raise NotImplementedError(
+                "WebDAVElement subclass %s is not implemented."
+                % (self.__class__.__name__,)
+            )
+
+        my_children = []
+
+        allowPCDATA = self.allowed_children.has_key(PCDATAElement)
+
+        for child in children:
+            if child is None:
+                continue
+
+            if isinstance(child, (str, unicode)):
+                child = PCDATAElement(child)
+
+            if isinstance(child, PCDATAElement) and not allowPCDATA:
+                continue
+
+            my_children.append(child)
+
+        self.children = tuple(my_children)
+        self.attributes = attributes
+
+    @classmethod
+    def qname(cls):
+        return (cls.namespace, cls.name)
+
+    @classmethod
+    def sname(cls):
+        return encodeXMLName(cls.namespace, cls.name)
+
+    def validate(self):
+        children = self.children
+        attributes = self.attributes
+
+        if self.allowed_children is None:
+            raise NotImplementedError(
+                "WebDAVElement subclass %s is not implemented."
+                % (self.__class__.__name__,)
+            )
+
+        #
+        # Validate that children are of acceptable types
+        #
+        allowed_children = dict([
+            (child_type, list(limits))
+            for child_type, limits
+            in self.allowed_children.items()
+        ])
+
+        my_children = []
+
+        for child in children:
+
+            assert isinstance(child, (WebDAVElement, PCDATAElement)), "Not an element: %r" % (child,)
+            
+            child.validate()
+
+            for allowed, (min, max) in allowed_children.items():
+                if type(allowed) == type and isinstance(child, allowed):
+                    qname = allowed
+                elif child.qname() == allowed:
+                    qname = allowed
+                else:
+                    continue
+
+                if min is not None and min > 0:
+                    min -= 1
+                if max is not None:
+                    assert max > 0, "Too many children of type %s for %s" % (child.sname(), self.sname())
+                    max -= 1
+                allowed_children[qname] = (min, max)
+                my_children.append(child)
+                break
+            else:
+                if not (isinstance(child, PCDATAElement) and child.isWhitespace()):
+                    log.debug(
+                        "Child of type %s is unexpected and therefore ignored in %s element"
+                        % (child.sname(), self.sname())
+                    )
+
+        for qname, (min, max) in allowed_children.items():
+            if min != 0:
+                raise ValueError("Not enough children of type %s for %s"
+                                 % (encodeXMLName(*qname), self.sname()))
+
+        self.children = tuple(my_children)
+
+        #
+        # Validate that attributes have known names
+        #
+        my_attributes = {}
+
+        if self.allowed_attributes:
+            for name in attributes:
+                if name not in self.allowed_attributes:
+                    log.debug("Attribute %s is unexpected in %s element" % (name, self.sname()))
+                my_attributes[name] = attributes[name]
+
+            for name, required in self.allowed_attributes.items():
+                if required and name not in my_attributes:
+                    raise ValueError("Attribute %s is required in %s element"
+                                     % (name, self.sname()))
+
+        else:
+            if not isinstance(self, WebDAVUnknownElement) and attributes:
+                log.debug("Attributes %s are unexpected in %s element"
+                          % (attributes.keys(), self.sname()))
+            my_attributes.update(attributes)
+
+        self.attributes = my_attributes
+
+    def __str__(self):
+        return self.sname()
+
+    def __repr__(self):
+        if hasattr(self, "attributes") and hasattr(self, "children"):
+            return "<%s %r: %r>" % (self.sname(), self.attributes, self.children)
+        else:
+            return "<%s>" % (self.sname())
+
+    def __eq__(self, other):
+        if isinstance(other, WebDAVElement):
+            return (
+                self.name       == other.name       and
+                self.namespace  == other.namespace  and
+                self.attributes == other.attributes and
+                self.children   == other.children
+            )
+        else:
+            return NotImplemented
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __contains__(self, child):
+        return child in self.children
+
+    def writeXML(self, output, pretty=True):
+        output.write("<?xml version='1.0' encoding='UTF-8'?>" + ("\n" if pretty else ""))
+        self._writeToStream(output, "", 0, pretty)
+
+    def _writeToStream(self, output, ns, level, pretty):
+        """
+        Fast XML output.
+
+        @param output: C{stream} to write to.
+        @param ns: C{str} containing the namespace of the enclosing element.
+        @param level: C{int} containing the element nesting level (starts at 0).
+        @param pretty: C{bool} whether to use 'pretty' formatted output or not.
+        """
+        
+        # Do pretty indent
+        if pretty and level:
+            output.write("  " * level)
+        
+        # Check for empty element (one with either no children or a single PCDATA that is itself empty)
+        if (len(self.children) == 0 or
+            (len(self.children) == 1 and isinstance(self.children[0], PCDATAElement) and len(str(self.children[0])) == 0)):
+
+            # Write out any attributes or the namespace if difference from enclosing element.
+            if self.attributes or (ns != self.namespace):
+                output.write("<%s" % (self.name,))
+                for name, value in self.attributes.iteritems():
+                    self._writeAttributeToStream(output, name, value)
+                if ns != self.namespace:
+                    output.write(" xmlns='%s'" % (self.namespace,))
+                output.write("/>")
+            else:
+                output.write("<%s/>" % (self.name,))
+        else:
+            # Write out any attributes or the namespace if difference from enclosing element.
+            if self.attributes or (ns != self.namespace):
+                output.write("<%s" % (self.name,))
+                for name, value in self.attributes.iteritems():
+                    self._writeAttributeToStream(output, name, value)
+                if ns != self.namespace:
+                    output.write(" xmlns='%s'" % (self.namespace,))
+                    ns = self.namespace
+                output.write(">")
+            else:
+                output.write("<%s>" % (self.name,))
+                
+            # Determine nature of children when doing pretty print: we do
+            # not want to insert CRLFs or any other whitespace in PCDATA.
+            hasPCDATA = False
+            for child in self.children:
+                if isinstance(child, PCDATAElement):
+                    hasPCDATA = True
+                    break
+            
+            # Write out the children.
+            if pretty and not hasPCDATA:
+                output.write("\r\n")
+            for child in self.children:
+                child._writeToStream(output, ns, level+1, pretty)
+                
+            # Close the element.
+            if pretty and not hasPCDATA and level:
+                output.write("  " * level)
+            output.write("</%s>" % (self.name,))
+
+        if pretty and level:
+            output.write("\r\n")
+
+    def _writeAttributeToStream(self, output, name, value):
+        
+        # Quote any single quotes. We do not need to be any smarter than this.
+        value = value.replace("'", "'")
+
+        output.write(" %s='%s'" % (name, value,))  
+      
+    def toxml(self, pretty=True):
+        output = StringIO.StringIO()
+        self.writeXML(output, pretty)
+        return str(output.getvalue())
+
+    def element(self, document):
+        element = document.createElementNS(self.namespace, self.name)
+        if hasattr(self, "attributes"):
+            for name, value in self.attributes.items():
+                namespace, name = decodeXMLName(name)
+                attribute = document.createAttributeNS(namespace, name)
+                attribute.nodeValue = value
+                element.setAttributeNodeNS(attribute)
+        return element
+
+    def addToDOM(self, document, parent):
+        element = self.element(document)
+
+        if parent is None:
+            document.appendChild(element)
+        else:
+            parent.appendChild(element)
+
+        for child in self.children:
+            if child:
+                try:
+                    child.addToDOM(document, element)
+                except:
+                    log.err("Unable to add child %r of element %s to DOM" % (child, self))
+                    raise
+
+    def childrenOfType(self, child_type):
+        """
+        Returns a list of children with the same qname as the given type.
+        """
+        if type(child_type) is tuple:
+            qname = child_type
+        else:
+            qname = child_type.qname()
+
+        return [ c for c in self.children if c.qname() == qname ]
+
+    def childOfType(self, child_type):
+        """
+        Returns a child of the given type, if any, or None.
+        Raises ValueError if more than one is found.
+        """
+        found = None
+        for child in self.childrenOfType(child_type):
+            if found:
+                raise ValueError("Multiple %s elements found in %s" % (child_type.sname(), self.toxml()))
+            found = child
+        return found
+
+    def removeWhitespaceNodes(self):
+        """ Removes all of the whitespace-only text decendants of a DOM node. """
+        # prepare the list of text nodes to remove (and recurse when needed)
+        remove_list = []
+        for child in self.children:
+            if isinstance(child, PCDATAElement) and not child.data.strip():
+                # add this text node to the to-be-removed list
+                remove_list.append(child)
+            elif isinstance(child, WebDAVElement):
+                # recurse, it's the simplest way to deal with the subtree
+                child.removeWhitespaceNodes()
+
+        # perform the removals
+        newchildren = []
+        for child in self.children:
+            if child not in remove_list:
+                newchildren.append(child)
+        self.children = tuple(newchildren)
+
+
+class PCDATAElement (object):
+    def __init__(self, data):
+        super(PCDATAElement, self).__init__()
+
+        if data is None:
+            data = ""
+        elif type(data) is unicode:
+            data = data.encode("utf-8")
+        else:
+            assert type(data) is str, ("PCDATA must be a string: %r" % (data,))
+
+        self.data = data
+
+    @classmethod
+    def qname(cls):
+        return (None, "#PCDATA")
+
+    @classmethod
+    def sname(cls):
+        return "#PCDATA"
+
+    def validate(self):
+        pass
+
+    def __str__(self):
+        return str(self.data)
+
+    def __repr__(self):
+        return "<%s: %r>" % (self.__class__.__name__, self.data)
+
+    def __add__(self, other):
+        if isinstance(other, PCDATAElement):
+            return self.__class__(self.data + other.data)
+        else:
+            return self.__class__(self.data + other)
+
+    def __eq__(self, other):
+        if isinstance(other, PCDATAElement):
+            return self.data == other.data
+        elif type(other) in (str, unicode):
+            return self.data == other
+        else:
+            return NotImplemented
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def isWhitespace(self):
+        for char in str(self):
+            if char not in string.whitespace:
+                return False
+        return True
+
+    def element(self, document):
+        return document.createTextNode(self.data)
+
+    def addToDOM(self, document, parent):
+        try:
+            parent.appendChild(self.element(document))
+        except TypeError:
+            log.err("Invalid PCDATA: %r" % (self.data,))
+            raise
+
+    def _writeToStream(self, output, ns, level, pretty):
+        # Do escaping/CDATA behavior
+        if "\r" in self.data or "\n" in self.data:
+            # Do CDATA
+            cdata = "<![CDATA[%s]]>" % (self.data.replace("]]>", "]]>"),)
+        else:
+            cdata = self.data
+            if "&" in cdata:
+                cdata = cdata.replace("&", "&")
+            if "<" in cdata:
+                cdata = cdata.replace("<", "<")
+            if ">" in cdata:
+                cdata = cdata.replace(">", ">")
+
+        output.write(cdata)
+
+
+class WebDAVOneShotElement (WebDAVElement):
+    """
+    Element with exactly one WebDAVEmptyElement child and no attributes.
+    """
+    __singletons = {}
+
+    def __new__(clazz, *children):
+        child = None
+        for next in children:
+            if isinstance(next, WebDAVEmptyElement):
+                if child is not None:
+                    raise ValueError("%s must have exactly one child, not %r"
+                                     % (clazz.__name__, children))
+                child = next
+            elif isinstance(next, PCDATAElement):
+                pass
+            else:
+                raise ValueError("%s child is not a WebDAVEmptyElement instance: %s"
+                                 % (clazz.__name__, next))
+
+        if clazz not in WebDAVOneShotElement.__singletons:
+            WebDAVOneShotElement.__singletons[clazz] = {
+                child: WebDAVElement.__new__(clazz)
+            }
+        elif child not in WebDAVOneShotElement.__singletons[clazz]:
+            WebDAVOneShotElement.__singletons[clazz][child] = (
+                WebDAVElement.__new__(clazz)
+            )
+
+        return WebDAVOneShotElement.__singletons[clazz][child]
+
+
+class WebDAVUnknownElement (WebDAVElement):
+    """
+    Placeholder for unknown element tag names.
+    """
+    allowed_children = {
+        WebDAVElement: (0, None),
+        PCDATAElement: (0, None),
+    }
+
+    @classmethod
+    def withName(cls, namespace, name):
+        child = cls()
+        child.namespace = namespace
+        child.name = name
+        return child
+
+    def qname(self):
+        return (self.namespace, self.name)
+
+    def sname(self):
+        return encodeXMLName(self.namespace, self.name)
+
+
+class WebDAVEmptyElement (WebDAVElement):
+    """
+    WebDAV element with no contents.
+    """
+    __singletons = {}
+
+    def __new__(clazz, *args, **kwargs):
+        assert not args
+
+        if kwargs:
+            return WebDAVElement.__new__(clazz)
+        else:
+            if clazz not in WebDAVEmptyElement.__singletons:
+                WebDAVEmptyElement.__singletons[clazz] = (WebDAVElement.__new__(clazz))
+            return WebDAVEmptyElement.__singletons[clazz]
+
+    allowed_children = {}
+    children = ()
+
+    def __hash__(self):
+        """
+        Define a hash method, so that an empty element can serve as dictionary
+        keys. It's mainly useful to define singletons with
+        L{WebDAVOneShotElement}.
+        """
+        return hash((self.name, self.namespace))
+
+
+class WebDAVTextElement (WebDAVElement):
+    """
+    WebDAV element containing PCDATA.
+    """
+    @classmethod
+    def fromString(clazz, string):
+        if string is None:
+            return clazz()
+        elif isinstance(string, (str, unicode)):
+            return clazz(PCDATAElement(string))
+        else:
+            return clazz(PCDATAElement(str(string)))
+
+    allowed_children = { PCDATAElement: (0, None) }
+
+    def __str__(self):
+        return "".join([c.data for c in self.children])
+
+    def __repr__(self):
+        content = str(self)
+        if content:
+            return "<%s: %r>" % (self.sname(), content)
+        else:
+            return "<%s>" % (self.sname(),)
+
+    def __eq__(self, other):
+        if isinstance(other, WebDAVTextElement):
+            return str(self) == str(other)
+        elif type(other) in (str, unicode):
+            return str(self) == other
+        else:
+            return NotImplemented
+
+
+class WebDAVDateTimeElement (WebDAVTextElement):
+    """
+    WebDAV date-time element. (RFC 2518, section 23.2)
+    """
+    @classmethod
+    def fromDate(clazz, date):
+        """
+        date may be a datetime.datetime instance, a POSIX timestamp
+        (integer value, such as returned by time.time()), or an ISO
+        8601-formatted (eg. "2005-06-13T16:14:11Z") date/time string.
+        """
+        def isoformat(date):
+            if date.utcoffset() is None:
+                return date.isoformat() + "Z"
+            else:
+                return date.isoformat()
+
+        if type(date) is int:
+            date = isoformat(datetime.datetime.fromtimestamp(date))
+        elif type(date) is str:
+            pass
+        elif type(date) is unicode:
+            date = date.encode("utf-8")
+        elif isinstance(date, datetime.datetime):
+            date = isoformat(date)
+        else:
+            raise ValueError("Unknown date type: %r" % (date,))
+
+        return clazz(PCDATAElement(date))
+
+    def __init__(self, *children, **attributes):
+        super(WebDAVDateTimeElement, self).__init__(*children, **attributes)
+        self.datetime() # Raise ValueError if the format is wrong
+
+    def __eq__(self, other):
+        if isinstance(other, WebDAVDateTimeElement):
+            return self.datetime() == other.datetime()
+        else:
+            return NotImplemented
+
+    def datetime(self):
+        s = str(self)
+        if not s:
+            return None
+        else:
+            return parse_date(s)
+
+
+class DateTimeHeaderElement (WebDAVTextElement):
+    """
+    WebDAV date-time element for elements that substitute for HTTP
+    headers. (RFC 2068, section 3.3.1)
+    """
+    @classmethod
+    def fromDate(clazz, date):
+        """
+        date may be a datetime.datetime instance, a POSIX timestamp
+        (integer value, such as returned by time.time()), or an RFC
+        2068 Full Date (eg. "Mon, 23 May 2005 04:52:22 GMT") string.
+        """
+        def format(date):
+            #
+            # FIXME: strftime() is subject to localization nonsense; we need to
+            # ensure that we're using the correct localization, or don't use
+            # strftime().
+            #
+            return date.strftime("%a, %d %b %Y %H:%M:%S GMT")
+
+        if type(date) is int:
+            date = format(datetime.datetime.fromtimestamp(date))
+        elif type(date) is str:
+            pass
+        elif type(date) is unicode:
+            date = date.encode("utf-8")
+        elif isinstance(date, datetime.datetime):
+            if date.tzinfo:
+                raise NotImplementedError("I need to normalize to UTC")
+            date = format(date)
+        else:
+            raise ValueError("Unknown date type: %r" % (date,))
+
+        return clazz(PCDATAElement(date))
+
+    def __init__(self, *children, **attributes):
+        super(DateTimeHeaderElement, self).__init__(*children, **attributes)
+        self.datetime() # Raise ValueError if the format is wrong
+
+    def __eq__(self, other):
+        if isinstance(other, WebDAVDateTimeElement):
+            return self.datetime() == other.datetime()
+        else:
+            return NotImplemented
+
+    def datetime(self):
+        s = str(self)
+        if not s:
+            return None
+        else:
+            return parseDateTime(s)
+
+
+##
+# Utilities
+##
+
+class FixedOffset (datetime.tzinfo):
+    """
+    Fixed offset in minutes east from UTC.
+    """
+    def __init__(self, offset, name=None):
+        super(FixedOffset, self).__init__()
+
+        self._offset = datetime.timedelta(minutes=offset)
+        self._name   = name
+
+    def utcoffset(self, dt): return self._offset
+    def tzname   (self, dt): return self._name
+    def dst      (self, dt): return datetime.timedelta(0)
+
+
+_regex_ISO8601Date = re.compile(
+    "^" +
+    "(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})T" +
+    "(?P<hour>\d{2}):(?P<minute>\d{2}):(?P<second>\d{2})(?:.(?P<subsecond>\d+))*" +
+    "(?:Z|(?P<offset_sign>\+|-)(?P<offset_hour>\d{2}):(?P<offset_minute>\d{2}))" +
+    "$"
+)
+
+def parse_date(date):
+    """
+    Parse an ISO 8601 date and return a corresponding datetime.datetime object.
+    """
+    # See http://www.iso.org/iso/en/prods-services/popstds/datesandtime.html
+
+    match = _regex_ISO8601Date.match(date)
+    if match is not None:
+        subsecond = match.group("subsecond")
+        if subsecond is None:
+            subsecond = 0
+        else:
+            subsecond = int(subsecond)
+
+        offset_sign = match.group("offset_sign")
+        if offset_sign is None:
+            offset = FixedOffset(0)
+        else:
+            offset_hour   = int(match.group("offset_hour"  ))
+            offset_minute = int(match.group("offset_minute"))
+
+            delta = (offset_hour * 60) + offset_minute
+
+            if   offset_sign == "+": offset = FixedOffset(0 - delta)
+            elif offset_sign == "-": offset = FixedOffset(0 + delta)
+
+        return datetime.datetime(
+            int(match.group("year"  )),
+            int(match.group("month" )),
+            int(match.group("day"   )),
+            int(match.group("hour"  )),
+            int(match.group("minute")),
+            int(match.group("second")),
+            subsecond,
+            offset
+        )
+    else:
+        raise ValueError("Invalid ISO 8601 date format: %r" % (date,))

Deleted: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/draft_sync.py
===================================================================
--- CalendarServer/trunk/txdav/xml/draft_sync.py	2012-03-22 00:02:25 UTC (rev 8919)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/draft_sync.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -1,103 +0,0 @@
-##
-# Copyright (c) 2009-2012 Apple Computer, Inc. All rights reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-# 
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-# 
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-##
-
-"""
-draft-daboo-webdav-sync (Collection Synchronization for WebDAV) XML
-Elements
-
-This module provides XML element definitions for use with WebDAV
-Synchronization.
-
-See draft-daboo-webdav-sync: http://tools.ietf.org/html/draft-daboo-webdav-sync
-
-Last draft referenced: -08
-"""
-
-__all__ = []
-
-
-from txdav.xml.base import WebDAVElement, WebDAVTextElement, dav_namespace
-from txdav.xml.element import registerElement, registerElementClass
-from txdav.xml.rfc2518 import MultiStatus
-
-
- at registerElement
- at registerElementClass
-class SyncCollection (WebDAVElement):
-    """
-    DAV report used to retrieve specific calendar component items via
-    their URIs.
-    """
-    name = "sync-collection"
-
-    # To allow for an empty element in a supported-report-set property we need
-    # to relax the child restrictions
-    allowed_children = {
-        (dav_namespace, "sync-token"): (0, 1), # When used in the REPORT this is required
-        (dav_namespace, "sync-level"): (0, 1), # When used in the REPORT this is required
-        (dav_namespace, "prop"      ): (0, 1),
-    }
-
-    def __init__(self, *children, **attributes):
-        super(SyncCollection, self).__init__(*children, **attributes)
-
-        self.property = None
-        self.sync_token = None
-        self.sync_level = None
-
-        for child in self.children:
-            qname = child.qname()
-
-            if qname == (dav_namespace, "sync-token"):
-                self.sync_token = str(child)
-
-            elif qname == (dav_namespace, "sync-level"):
-                self.sync_level = str(child)
-
-            elif qname == (dav_namespace, "prop"):
-                if self.property is not None:
-                    raise ValueError("Only one of DAV:prop allowed")
-                self.property = child
-
-
- at registerElement
- at registerElementClass
-class SyncToken (WebDAVTextElement):
-    """
-    Synchronization token used in report and as a property.
-    """
-    name = "sync-token"
-    hidden = True
-    protected = True
-
-
- at registerElement
- at registerElementClass
-class SyncLevel (WebDAVTextElement):
-    """
-    Synchronization level used in report.
-    """
-    name = "sync-level"
-
-
-# Extend MultiStatus, to add sync-token
-MultiStatus.allowed_children[(dav_namespace, "sync-token")] = (0, 1)

Copied: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/draft_sync.py (from rev 8919, CalendarServer/trunk/txdav/xml/draft_sync.py)
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/draft_sync.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/draft_sync.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -0,0 +1,103 @@
+##
+# Copyright (c) 2009-2012 Apple Computer, Inc. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+##
+
+"""
+draft-daboo-webdav-sync (Collection Synchronization for WebDAV) XML
+Elements
+
+This module provides XML element definitions for use with WebDAV
+Synchronization.
+
+See draft-daboo-webdav-sync: http://tools.ietf.org/html/draft-daboo-webdav-sync
+
+Last draft referenced: -08
+"""
+
+__all__ = []
+
+
+from txdav.xml.base import WebDAVElement, WebDAVTextElement, dav_namespace
+from txdav.xml.element import registerElement, registerElementClass
+from txdav.xml.rfc2518 import MultiStatus
+
+
+ at registerElement
+ at registerElementClass
+class SyncCollection (WebDAVElement):
+    """
+    DAV report used to retrieve specific calendar component items via
+    their URIs.
+    """
+    name = "sync-collection"
+
+    # To allow for an empty element in a supported-report-set property we need
+    # to relax the child restrictions
+    allowed_children = {
+        (dav_namespace, "sync-token"): (0, 1), # When used in the REPORT this is required
+        (dav_namespace, "sync-level"): (0, 1), # When used in the REPORT this is required
+        (dav_namespace, "prop"      ): (0, 1),
+    }
+
+    def __init__(self, *children, **attributes):
+        super(SyncCollection, self).__init__(*children, **attributes)
+
+        self.property = None
+        self.sync_token = None
+        self.sync_level = None
+
+        for child in self.children:
+            qname = child.qname()
+
+            if qname == (dav_namespace, "sync-token"):
+                self.sync_token = str(child)
+
+            elif qname == (dav_namespace, "sync-level"):
+                self.sync_level = str(child)
+
+            elif qname == (dav_namespace, "prop"):
+                if self.property is not None:
+                    raise ValueError("Only one of DAV:prop allowed")
+                self.property = child
+
+
+ at registerElement
+ at registerElementClass
+class SyncToken (WebDAVTextElement):
+    """
+    Synchronization token used in report and as a property.
+    """
+    name = "sync-token"
+    hidden = True
+    protected = True
+
+
+ at registerElement
+ at registerElementClass
+class SyncLevel (WebDAVTextElement):
+    """
+    Synchronization level used in report.
+    """
+    name = "sync-level"
+
+
+# Extend MultiStatus, to add sync-token
+MultiStatus.allowed_children[(dav_namespace, "sync-token")] = (0, 1)

Deleted: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/element.py
===================================================================
--- CalendarServer/trunk/txdav/xml/element.py	2012-03-22 00:02:25 UTC (rev 8919)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/element.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -1,94 +0,0 @@
-##
-# Copyright (c) 2005-2012 Apple Computer, Inc. All rights reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-# 
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-# 
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-##
-
-"""
-WebDAV XML elements.
-"""
-
-__all__ = [
-    "WebDAVDocument",
-    "dav_namespace",
-    "twisted_dav_namespace",
-    "twisted_private_namespace",
-    "WebDAVElement",
-    "PCDATAElement",
-    "WebDAVOneShotElement",
-    "WebDAVUnknownElement",
-    "WebDAVEmptyElement",
-    "WebDAVTextElement",
-    "WebDAVDateTimeElement",
-    "DateTimeHeaderElement",
-    "registerElement",
-    "registerElementClass",
-    "lookupElement",
-]
-
-from txdav.xml.parser import WebDAVDocument
-from txdav.xml.base import dav_namespace
-from txdav.xml.base import twisted_dav_namespace, twisted_private_namespace
-from txdav.xml.base import WebDAVElement
-from txdav.xml.base import PCDATAElement, WebDAVOneShotElement, WebDAVUnknownElement
-from txdav.xml.base import WebDAVEmptyElement, WebDAVTextElement
-from txdav.xml.base import WebDAVDateTimeElement, DateTimeHeaderElement
-from txdav.xml.base import _elements_by_qname
-
-
-##
-# XML element registration
-##
-
-def registerElement(elementClass):
-    """
-    Register an XML element class with the parser and add to this module's namespace.
-    """
-    assert issubclass(elementClass, WebDAVElement), "Not a WebDAVElement: %s" % (elementClass,)
-    assert elementClass.namespace, "Element has no namespace: %s" % (elementClass,)
-    assert elementClass.name, "Element has no name: %s" % (elementClass,)
-
-    qname = elementClass.namespace, elementClass.name
-    
-    if qname in _elements_by_qname:
-        raise AssertionError(
-            "Attempting to register element %s multiple times: (%r, %r)"
-            % (elementClass.sname(), _elements_by_qname[qname], elementClass)
-        )
-    
-    if not (qname in _elements_by_qname and issubclass(elementClass, _elements_by_qname[qname])):
-        _elements_by_qname[qname] = elementClass
-
-    return elementClass
-
-
-def registerElementClass(elementClass):
-    """
-    Add an XML element class to this module's namespace.
-    """
-    globals()[elementClass.__name__] = elementClass
-    __all__.append(elementClass.__name__)
-    return elementClass
-
-
-def lookupElement(qname):
-    """
-    Return the element class for the element with the given qname.
-    """
-    return _elements_by_qname[qname]

Copied: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/element.py (from rev 8919, CalendarServer/trunk/txdav/xml/element.py)
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/element.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/element.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -0,0 +1,94 @@
+##
+# Copyright (c) 2005-2012 Apple Computer, Inc. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+##
+
+"""
+WebDAV XML elements.
+"""
+
+__all__ = [
+    "WebDAVDocument",
+    "dav_namespace",
+    "twisted_dav_namespace",
+    "twisted_private_namespace",
+    "WebDAVElement",
+    "PCDATAElement",
+    "WebDAVOneShotElement",
+    "WebDAVUnknownElement",
+    "WebDAVEmptyElement",
+    "WebDAVTextElement",
+    "WebDAVDateTimeElement",
+    "DateTimeHeaderElement",
+    "registerElement",
+    "registerElementClass",
+    "lookupElement",
+]
+
+from txdav.xml.parser import WebDAVDocument
+from txdav.xml.base import dav_namespace
+from txdav.xml.base import twisted_dav_namespace, twisted_private_namespace
+from txdav.xml.base import WebDAVElement
+from txdav.xml.base import PCDATAElement, WebDAVOneShotElement, WebDAVUnknownElement
+from txdav.xml.base import WebDAVEmptyElement, WebDAVTextElement
+from txdav.xml.base import WebDAVDateTimeElement, DateTimeHeaderElement
+from txdav.xml.base import _elements_by_qname
+
+
+##
+# XML element registration
+##
+
+def registerElement(elementClass):
+    """
+    Register an XML element class with the parser and add to this module's namespace.
+    """
+    assert issubclass(elementClass, WebDAVElement), "Not a WebDAVElement: %s" % (elementClass,)
+    assert elementClass.namespace, "Element has no namespace: %s" % (elementClass,)
+    assert elementClass.name, "Element has no name: %s" % (elementClass,)
+
+    qname = elementClass.namespace, elementClass.name
+    
+    if qname in _elements_by_qname:
+        raise AssertionError(
+            "Attempting to register element %s multiple times: (%r, %r)"
+            % (elementClass.sname(), _elements_by_qname[qname], elementClass)
+        )
+    
+    if not (qname in _elements_by_qname and issubclass(elementClass, _elements_by_qname[qname])):
+        _elements_by_qname[qname] = elementClass
+
+    return elementClass
+
+
+def registerElementClass(elementClass):
+    """
+    Add an XML element class to this module's namespace.
+    """
+    globals()[elementClass.__name__] = elementClass
+    __all__.append(elementClass.__name__)
+    return elementClass
+
+
+def lookupElement(qname):
+    """
+    Return the element class for the element with the given qname.
+    """
+    return _elements_by_qname[qname]

Deleted: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/extensions.py
===================================================================
--- CalendarServer/trunk/txdav/xml/extensions.py	2012-03-22 00:02:25 UTC (rev 8919)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/extensions.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -1,46 +0,0 @@
-# Copyright (c) 2009 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-##
-# Copyright (c) 2005-2012 Apple Computer, Inc. All rights reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-#
-##
-
-"""
-Implementation of draft-sanchez-webdav-current-principal-02.
-"""
-
-__all__ = []
-
-
-from txdav.xml.base import WebDAVTextElement, twisted_dav_namespace
-from txdav.xml.element import registerElement, registerElementClass
-
-
- at registerElement
- at registerElementClass
-class ErrorDescription(WebDAVTextElement):
-    """
-    The human-readable description of a failed precondition
-    """
-    namespace = twisted_dav_namespace
-    name = "error-description"
-    protected = True

Copied: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/extensions.py (from rev 8919, CalendarServer/trunk/txdav/xml/extensions.py)
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/extensions.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/extensions.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -0,0 +1,46 @@
+# Copyright (c) 2009 Twisted Matrix Laboratories.
+# See LICENSE for details.
+
+##
+# Copyright (c) 2005-2012 Apple Computer, Inc. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+##
+
+"""
+Implementation of draft-sanchez-webdav-current-principal-02.
+"""
+
+__all__ = []
+
+
+from txdav.xml.base import WebDAVTextElement, twisted_dav_namespace
+from txdav.xml.element import registerElement, registerElementClass
+
+
+ at registerElement
+ at registerElementClass
+class ErrorDescription(WebDAVTextElement):
+    """
+    The human-readable description of a failed precondition
+    """
+    namespace = twisted_dav_namespace
+    name = "error-description"
+    protected = True

Deleted: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/parser.py
===================================================================
--- CalendarServer/trunk/txdav/xml/parser.py	2012-03-22 00:02:25 UTC (rev 8919)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/parser.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -1,35 +0,0 @@
-##
-# Copyright (c) 2005-2012 Apple Computer, Inc. All rights reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-# 
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-# 
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-##
-
-"""
-WebDAV XML parsing.
-
-This module provides XML utilities for use with WebDAV.
-
-See RFC 2518: http://www.ietf.org/rfc/rfc2518.txt (WebDAV)
-"""
-
-__all__ = [
-    "WebDAVDocument",
-]
-
-from txdav.xml.parser_sax import WebDAVDocument

Copied: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/parser.py (from rev 8919, CalendarServer/trunk/txdav/xml/parser.py)
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/parser.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/parser.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -0,0 +1,35 @@
+##
+# Copyright (c) 2005-2012 Apple Computer, Inc. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+##
+
+"""
+WebDAV XML parsing.
+
+This module provides XML utilities for use with WebDAV.
+
+See RFC 2518: http://www.ietf.org/rfc/rfc2518.txt (WebDAV)
+"""
+
+__all__ = [
+    "WebDAVDocument",
+]
+
+from txdav.xml.parser_sax import WebDAVDocument

Deleted: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/parser_base.py
===================================================================
--- CalendarServer/trunk/txdav/xml/parser_base.py	2012-03-22 00:02:25 UTC (rev 8919)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/parser_base.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -1,74 +0,0 @@
-##
-# Copyright (c) 2005-2012 Apple Computer, Inc. All rights reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-# 
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-# 
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-##
-
-__all__ = [
-    "AbstractWebDAVDocument",
-]
-
-from cStringIO import StringIO
-
-from txdav.xml.base import WebDAVElement
-
-
-class AbstractWebDAVDocument(object):
-    """
-    WebDAV XML document.
-    """
-    @classmethod
-    def fromStream(cls, source):
-        raise NotImplementedError()
-
-    @classmethod
-    def fromString(cls, source):
-        source = StringIO(source)
-        try:
-            return cls.fromStream(source)
-        finally:
-            source.close()
-
-    def __init__(self, root_element):
-        """
-        root_element must be a WebDAVElement instance.
-        """
-        super(AbstractWebDAVDocument, self).__init__()
-
-        if not isinstance(root_element, WebDAVElement):
-            raise ValueError("Not a WebDAVElement: %r" % (root_element,))
-
-        self.root_element = root_element
-
-    def __str__(self):
-        return self.toxml()
-
-    def __eq__(self, other):
-        if isinstance(other, AbstractWebDAVDocument):
-            return self.root_element == other.root_element
-        else:
-            return NotImplemented
-
-    def writeXML(self, output):
-        raise NotImplementedError()
-
-    def toxml(self):
-        output = StringIO()
-        self.writeXML(output)
-        return output.getvalue()

Copied: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/parser_base.py (from rev 8919, CalendarServer/trunk/txdav/xml/parser_base.py)
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/parser_base.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/parser_base.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -0,0 +1,74 @@
+##
+# Copyright (c) 2005-2012 Apple Computer, Inc. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+##
+
+__all__ = [
+    "AbstractWebDAVDocument",
+]
+
+from cStringIO import StringIO
+
+from txdav.xml.base import WebDAVElement
+
+
+class AbstractWebDAVDocument(object):
+    """
+    WebDAV XML document.
+    """
+    @classmethod
+    def fromStream(cls, source):
+        raise NotImplementedError()
+
+    @classmethod
+    def fromString(cls, source):
+        source = StringIO(source)
+        try:
+            return cls.fromStream(source)
+        finally:
+            source.close()
+
+    def __init__(self, root_element):
+        """
+        root_element must be a WebDAVElement instance.
+        """
+        super(AbstractWebDAVDocument, self).__init__()
+
+        if not isinstance(root_element, WebDAVElement):
+            raise ValueError("Not a WebDAVElement: %r" % (root_element,))
+
+        self.root_element = root_element
+
+    def __str__(self):
+        return self.toxml()
+
+    def __eq__(self, other):
+        if isinstance(other, AbstractWebDAVDocument):
+            return self.root_element == other.root_element
+        else:
+            return NotImplemented
+
+    def writeXML(self, output):
+        raise NotImplementedError()
+
+    def toxml(self):
+        output = StringIO()
+        self.writeXML(output)
+        return output.getvalue()

Deleted: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/parser_sax.py
===================================================================
--- CalendarServer/trunk/txdav/xml/parser_sax.py	2012-03-22 00:02:25 UTC (rev 8919)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/parser_sax.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -1,171 +0,0 @@
-##
-# Copyright (c) 2005-2012 Apple Computer, Inc. All rights reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-# 
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-# 
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-##
-
-__all__ = [
-    "WebDAVDocument",
-]
-
-import xml.dom.minidom
-import xml.sax
-
-from txdav.xml.base import WebDAVUnknownElement, PCDATAElement
-from txdav.xml.base import _elements_by_qname
-from txdav.xml.parser_base import AbstractWebDAVDocument
-from txdav.xml.xmlext import Print as xmlPrint
-
-
-class WebDAVContentHandler (xml.sax.handler.ContentHandler):
-    def setDocumentLocator(self, locator): self.locator = locator
-    locator = None
-
-    def __init__(self):
-        xml.sax.handler.ContentHandler.__init__(self)
-        self._characterBuffer = None
-
-    def location(self):
-        return "line %d, column %d" % (self.locator.getLineNumber(), self.locator.getColumnNumber())
-
-    def startDocument(self):
-        self.stack = [{
-            "name"       : None,
-            "class"      : None,
-            "attributes" : None,
-            "children"   : [],
-        }]
-
-        # Keep a cache of the subclasses we create for unknown XML
-        # elements, so that we don't create multiple classes for the
-        # same element; it's fairly typical for elements to appear
-        # multiple times in a document.
-        self.unknownElementClasses = {}
-
-    def endDocument(self):
-        top = self.stack[-1]
-
-        assert top["name"] is None
-        assert top["class"] is None
-        assert top["attributes"] is None
-        assert len(top["children"]) is 1, "Must have exactly one root element, got %d" % len(top["children"])
-
-        self.dom = WebDAVDocument(top["children"][0])
-        del(self.unknownElementClasses)
-
-    def startElementNS(self, name, qname, attributes):
-        if self._characterBuffer is not None:
-            pcdata = PCDATAElement("".join(self._characterBuffer))
-            self.stack[-1]["children"].append(pcdata)
-            self._characterBuffer = None
-
-        attributes_dict = {}
-
-        if attributes.getLength() is not 0:
-            for attr_name in attributes.getQNames():
-                attributes_dict[attr_name.encode("utf-8")] = attributes.getValueByQName(attr_name)
-
-        tag_namespace, tag_name = name
-
-        if name in _elements_by_qname:
-            element_class = _elements_by_qname[name]
-        elif name in self.unknownElementClasses:
-            element_class = self.unknownElementClasses[name]
-        else:
-            def element_class(*args, **kwargs):
-                element = WebDAVUnknownElement(*args, **kwargs)
-                element.namespace = tag_namespace
-                element.name      = tag_name
-                return element
-            self.unknownElementClasses[name] = element_class
-
-        self.stack.append({
-            "name"       : name,
-            "class"      : element_class,
-            "attributes" : attributes_dict,
-            "children"   : [],
-        })
-
-    def endElementNS(self, name, qname):
-        if self._characterBuffer is not None:
-            pcdata = PCDATAElement("".join(self._characterBuffer))
-            self.stack[-1]["children"].append(pcdata)
-            self._characterBuffer = None
-
-        # Pop the current element from the stack...
-        top = self.stack[-1]
-        del(self.stack[-1])
-
-        assert top["name"] == name, "Last item on stack is %s while closing %s" % (top["name"], name)
-
-        # ...then instantiate the element and add it to the parent's list of
-        # children.
-        try:
-            element = top["class"](*top["children"], **top["attributes"])
-        except ValueError, e:
-            e.args = ("%s at %s" % (e.args[0], self.location()),) + e.args[1:]
-            raise # Re-raises modified e, but preserves traceback
-
-        self.stack[-1]["children"].append(element)
-
-    def characters(self, content):
-        # Stash character data away in a list that we will "".join() when done
-        if self._characterBuffer is None:
-            self._characterBuffer = []
-        self._characterBuffer.append(content)
-
-    def ignorableWhitespace(self, whitespace):
-        self.characters(self, whitespace)
-
-    def startElement(self, name, attributes):
-        raise AssertionError("startElement() should not be called by namespace-aware parser")
-
-    def endElement(self, name):
-        raise AssertionError("endElement() should not be called by namespace-aware parser")
-
-    def processingInstruction(self, target, data):
-        raise AssertionError("processing instructions are not allowed")
-
-    def skippedEntity(self, name):
-        raise AssertionError("skipped entities are not allowed")
-
-
-class WebDAVDocument(AbstractWebDAVDocument):
-    @classmethod
-    def fromStream(cls, source):
-        handler = WebDAVContentHandler()
-        parser  = xml.sax.make_parser()
-
-        parser.setContentHandler(handler)
-        parser.setFeature(xml.sax.handler.feature_namespaces, True)
-
-        try:
-            parser.parse(source)
-        except xml.sax.SAXParseException, e:
-            raise ValueError(e)
-
-        #handler.dom.root_element.validate()
-
-        return handler.dom
-        
-    def writeXML(self, output):
-        document = xml.dom.minidom.Document()
-        self.root_element.addToDOM(document, None)
-        #document.normalize()
-        xmlPrint(document, output)

Copied: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/parser_sax.py (from rev 8919, CalendarServer/trunk/txdav/xml/parser_sax.py)
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/parser_sax.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/parser_sax.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -0,0 +1,171 @@
+##
+# Copyright (c) 2005-2012 Apple Computer, Inc. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+##
+
+__all__ = [
+    "WebDAVDocument",
+]
+
+import xml.dom.minidom
+import xml.sax
+
+from txdav.xml.base import WebDAVUnknownElement, PCDATAElement
+from txdav.xml.base import _elements_by_qname
+from txdav.xml.parser_base import AbstractWebDAVDocument
+from txdav.xml.xmlext import Print as xmlPrint
+
+
+class WebDAVContentHandler (xml.sax.handler.ContentHandler):
+    def setDocumentLocator(self, locator): self.locator = locator
+    locator = None
+
+    def __init__(self):
+        xml.sax.handler.ContentHandler.__init__(self)
+        self._characterBuffer = None
+
+    def location(self):
+        return "line %d, column %d" % (self.locator.getLineNumber(), self.locator.getColumnNumber())
+
+    def startDocument(self):
+        self.stack = [{
+            "name"       : None,
+            "class"      : None,
+            "attributes" : None,
+            "children"   : [],
+        }]
+
+        # Keep a cache of the subclasses we create for unknown XML
+        # elements, so that we don't create multiple classes for the
+        # same element; it's fairly typical for elements to appear
+        # multiple times in a document.
+        self.unknownElementClasses = {}
+
+    def endDocument(self):
+        top = self.stack[-1]
+
+        assert top["name"] is None
+        assert top["class"] is None
+        assert top["attributes"] is None
+        assert len(top["children"]) is 1, "Must have exactly one root element, got %d" % len(top["children"])
+
+        self.dom = WebDAVDocument(top["children"][0])
+        del(self.unknownElementClasses)
+
+    def startElementNS(self, name, qname, attributes):
+        if self._characterBuffer is not None:
+            pcdata = PCDATAElement("".join(self._characterBuffer))
+            self.stack[-1]["children"].append(pcdata)
+            self._characterBuffer = None
+
+        attributes_dict = {}
+
+        if attributes.getLength() is not 0:
+            for attr_name in attributes.getQNames():
+                attributes_dict[attr_name.encode("utf-8")] = attributes.getValueByQName(attr_name)
+
+        tag_namespace, tag_name = name
+
+        if name in _elements_by_qname:
+            element_class = _elements_by_qname[name]
+        elif name in self.unknownElementClasses:
+            element_class = self.unknownElementClasses[name]
+        else:
+            def element_class(*args, **kwargs):
+                element = WebDAVUnknownElement(*args, **kwargs)
+                element.namespace = tag_namespace
+                element.name      = tag_name
+                return element
+            self.unknownElementClasses[name] = element_class
+
+        self.stack.append({
+            "name"       : name,
+            "class"      : element_class,
+            "attributes" : attributes_dict,
+            "children"   : [],
+        })
+
+    def endElementNS(self, name, qname):
+        if self._characterBuffer is not None:
+            pcdata = PCDATAElement("".join(self._characterBuffer))
+            self.stack[-1]["children"].append(pcdata)
+            self._characterBuffer = None
+
+        # Pop the current element from the stack...
+        top = self.stack[-1]
+        del(self.stack[-1])
+
+        assert top["name"] == name, "Last item on stack is %s while closing %s" % (top["name"], name)
+
+        # ...then instantiate the element and add it to the parent's list of
+        # children.
+        try:
+            element = top["class"](*top["children"], **top["attributes"])
+        except ValueError, e:
+            e.args = ("%s at %s" % (e.args[0], self.location()),) + e.args[1:]
+            raise # Re-raises modified e, but preserves traceback
+
+        self.stack[-1]["children"].append(element)
+
+    def characters(self, content):
+        # Stash character data away in a list that we will "".join() when done
+        if self._characterBuffer is None:
+            self._characterBuffer = []
+        self._characterBuffer.append(content)
+
+    def ignorableWhitespace(self, whitespace):
+        self.characters(self, whitespace)
+
+    def startElement(self, name, attributes):
+        raise AssertionError("startElement() should not be called by namespace-aware parser")
+
+    def endElement(self, name):
+        raise AssertionError("endElement() should not be called by namespace-aware parser")
+
+    def processingInstruction(self, target, data):
+        raise AssertionError("processing instructions are not allowed")
+
+    def skippedEntity(self, name):
+        raise AssertionError("skipped entities are not allowed")
+
+
+class WebDAVDocument(AbstractWebDAVDocument):
+    @classmethod
+    def fromStream(cls, source):
+        handler = WebDAVContentHandler()
+        parser  = xml.sax.make_parser()
+
+        parser.setContentHandler(handler)
+        parser.setFeature(xml.sax.handler.feature_namespaces, True)
+
+        try:
+            parser.parse(source)
+        except xml.sax.SAXParseException, e:
+            raise ValueError(e)
+
+        #handler.dom.root_element.validate()
+
+        return handler.dom
+        
+    def writeXML(self, output):
+        document = xml.dom.minidom.Document()
+        self.root_element.addToDOM(document, None)
+        #document.normalize()
+        xmlPrint(document, output)

Deleted: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc2518.py
===================================================================
--- CalendarServer/trunk/txdav/xml/rfc2518.py	2012-03-22 00:02:25 UTC (rev 8919)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc2518.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -1,728 +0,0 @@
-##
-# Copyright (c) 2005-2012 Apple Computer, Inc. All rights reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-# 
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-# 
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-##
-
-# FIXME: RFC 2518 is obsoleted by RFC 5689.  Check for changes.
-
-"""
-RFC 2518 (WebDAV) XML Elements
-
-This module provides XML element definitions for use with WebDAV.
-
-See RFC 2518: http://www.ietf.org/rfc/rfc2518.txt
-"""
-
-__all__ = []
-
-
-from twext.web2 import responsecode
-from twext.web2.http_headers import MimeType
-
-from txdav.xml.base import WebDAVElement, WebDAVTextElement, PCDATAElement
-from txdav.xml.base import WebDAVEmptyElement, WebDAVOneShotElement
-from txdav.xml.base import WebDAVDateTimeElement, DateTimeHeaderElement
-from txdav.xml.element import dav_namespace, registerElement, registerElementClass
-
-
-##
-# Section 12
-##
-
- at registerElement
- at registerElementClass
-class ActiveLock (WebDAVElement):
-    """
-    Describes a lock on a resource. (RFC 2518, section 12.1)
-    """
-    name = "activelock"
-
-    allowed_children = {
-        (dav_namespace, "lockscope"): (1, 1),
-        (dav_namespace, "locktype" ): (1, 1),
-        (dav_namespace, "depth"    ): (1, 1),
-        (dav_namespace, "owner"    ): (0, 1),
-        (dav_namespace, "timeout"  ): (0, 1),
-        (dav_namespace, "locktoken"): (0, 1),
-    }
-
-
- at registerElement
- at registerElementClass
-class Depth (WebDAVTextElement):
-    """
-    The value of the depth header. (RFC 2518, section 12.1.1)
-    """
-    name = "depth"
-
-    def validate(self):
-        super(Depth, self).validate()
-
-        depth = str(self)
-        if depth not in ("0", "1", "infinity"):
-            raise ValueError("Invalid depth: %s" % (depth,))
-
-
- at registerElement
- at registerElementClass
-class LockToken (WebDAVElement):
-    """
-    The lock token associated with a lock. (RFC 2518, section 12.1.2)
-    """
-    name = "locktoken"
-
-    allowed_children = { (dav_namespace, "href"): (1, None) }
-
-
- at registerElement
- at registerElementClass
-class Timeout (WebDAVTextElement):
-    """
-    The timeout associated with a lock. (RFC 2518, section 12.1.3)
-    """
-    name = "timeout"
-
-
- at registerElement
- at registerElementClass
-class Collection (WebDAVEmptyElement):
-    """
-    Identifies the associated resource as a collection. (RFC 2518, section 12.2)
-    """
-    name = "collection"
-
-
- at registerElement
- at registerElementClass
-class HRef (WebDAVTextElement):
-    """
-    Identifies the content of the element as a URI. (RFC 2518, section 12.3)
-    """
-    name = "href"
-
-
- at registerElement
- at registerElementClass
-class Link (WebDAVElement):
-    """
-    Identifies the property as a link and contains the source and
-    destination of that link. (RFC 2518, section 12.4)
-    """
-    name = "link"
-
-    allowed_children = {
-        (dav_namespace, "src"): (1, None),
-        (dav_namespace, "dst"): (1, None),
-    }
-
-
- at registerElement
- at registerElementClass
-class LinkDestination (WebDAVTextElement):
-    """
-    Indicates the destination of a link. (RFC 2518, section 12.4.1)
-    """
-    name = "dst"
-
-
- at registerElement
- at registerElementClass
-class LinkSource (WebDAVTextElement):
-    """
-    Indicates the source of a link. (RFC 2518, section 12.4.2)
-    """
-    name = "src"
-
-
- at registerElement
- at registerElementClass
-class LockEntry (WebDAVElement):
-    """
-    Defines the types of lock that can be used with the
-    resource. (RFC 2518, section 12.5)
-    """
-    name = "lockentry"
-
-    allowed_children = {
-        (dav_namespace, "lockscope"): (1, 1),
-        (dav_namespace, "locktype" ): (1, 1),
-    }
-
-
- at registerElement
- at registerElementClass
-class LockInfo (WebDAVElement):
-    """
-    Used with a LOCK method to specify the type of lock that the
-    client wishes to have created. (RFC 2518, section 12.6)
-    """
-    name = "lockinfo"
-
-    allowed_children = {
-        (dav_namespace, "lockscope"): (1, 1),
-        (dav_namespace, "locktype" ): (1, 1),
-        (dav_namespace, "owner"    ): (0, 1),
-    }
-
-
- at registerElement
- at registerElementClass
-class LockScope (WebDAVOneShotElement):
-    """
-    Specifies whether a lock is an exclusive lock or a shared
-    lock. (RFC 2518, section 12.7)
-    """
-    name = "lockscope"
-
-    allowed_children = {
-        (dav_namespace, "exclusive"): (0, 1),
-        (dav_namespace, "shared"   ): (0, 1),
-    }
-
-
- at registerElement
- at registerElementClass
-class Exclusive (WebDAVEmptyElement):
-    """
-    Indicates an exclusive lock. (RFC 2518, section 12.7.1)
-    """
-    name = "exclusive"
-
-LockScope.exclusive = LockScope(Exclusive())
-
-
- at registerElement
- at registerElementClass
-class Shared (WebDAVEmptyElement):
-    """
-    Indicates a shared lock. (RFC 2518, section 12.7.2)
-    """
-    name = "shared"
-
-LockScope.shared = LockScope(Shared())
-
-
- at registerElement
- at registerElementClass
-class LockType (WebDAVOneShotElement):
-    """
-    Specifies the access type of a lock. (RFC 2518, section 12.8)
-    """
-    name = "locktype"
-
-    allowed_children = { (dav_namespace, "write"): (0, 1) }
-
-
- at registerElement
- at registerElementClass
-class Write (WebDAVEmptyElement):
-    """
-    Indicates a write lock. (RFC 2518, section 12.8.1)
-    Controls methods that lock a resource or modify the content, dead
-    properties, or (in the case of a collection) membership of a resource.
-    (RFC 3744, section 3.2)
-    """
-    name = "write"
-
-LockType.write = LockType(Write())
-
-
- at registerElement
- at registerElementClass
-class MultiStatus (WebDAVElement):
-    """
-    Contains multiple Responses. (RFC 2518, section 12.9)
-    """
-    name = "multistatus"
-
-    allowed_children = {
-        (dav_namespace, "response"           ): (0, None),
-        (dav_namespace, "responsedescription"): (0, 1),
-    }
-
-
- at registerElement
- at registerElementClass
-class Response (WebDAVElement):
-    """
-    Holds a single response describing the effect of a method on a
-    resource and/or its properties. (RFC 2518, section 12.9.1)
-    """
-    name = "response"
-
-    allowed_children = {
-        (dav_namespace, "href"               ): (1, None),
-        (dav_namespace, "status"             ): (1, 1),
-        (dav_namespace, "propstat"           ): (1, None),
-        (dav_namespace, "error"              ): (0, 1),        # 2518bis
-        (dav_namespace, "responsedescription"): (0, 1),
-    }
-
-    def __new__(clazz, *children):
-        if clazz is not Response: return WebDAVElement.__new__(clazz)
-
-        resource_count = 0
-        status_count   = 0
-        propstat_count = 0
-
-        for child in children:
-            if   isinstance(child, HRef          ): resource_count += 1
-            elif isinstance(child, Status        ): status_count   += 1
-            elif isinstance(child, PropertyStatus): propstat_count += 1
-
-        if resource_count < 1:
-            raise ValueError("%s element must have at least one %s."
-                             % (clazz.sname(), HRef.sname()))
-
-        if status_count is 0:
-            if propstat_count is 0:
-                raise ValueError("%s element must have one of %s or %s"
-                                 % (clazz.sname(), Status.sname(), PropertyStatus.sname()))
-
-            if resource_count > 1:
-                raise ValueError("%s element with %s may only have one %s"
-                                 % (clazz.sname(), PropertyStatus.sname(), HRef.sname()))
-
-            return PropertyStatusResponse.__new__(PropertyStatusResponse, *children)
-
-        if status_count > 1:
-            raise ValueError("%s element may only have one %s" % (clazz.sname(), Status.sname()))
-
-        return StatusResponse.__new__(StatusResponse, *children)
-
-
- at registerElementClass
-class StatusResponse (Response):
-    """
-    Specialized derivative of Response for resource status.
-    """
-    unregistered = True
-
-    allowed_children = {
-        (dav_namespace, "href"               ): (1, None),
-        (dav_namespace, "status"             ): (1, 1),
-        (dav_namespace, "error"              ): (0, 1),        # 2518bis
-        (dav_namespace, "responsedescription"): (0, 1),
-    }
-
-
- at registerElementClass
-class PropertyStatusResponse (Response):
-    """
-    Specialized derivative of Response for property status.
-    """
-    unregistered = True
-
-    allowed_children = {
-        (dav_namespace, "href"               ): (1, 1),
-        (dav_namespace, "propstat"           ): (1, None),
-        (dav_namespace, "error"              ): (0, 1),        # 2518bis
-        (dav_namespace, "responsedescription"): (0, 1),
-    }
-
-
- at registerElement
- at registerElementClass
-class PropertyStatus (WebDAVElement):
-    """
-    Groups together a Property and Status element that is associated
-    with a particular DAV:href element. (RFC 2518, section 12.9.1.1)
-    """
-    name = "propstat"
-
-    allowed_children = {
-        (dav_namespace, "prop"               ): (1, 1),
-        (dav_namespace, "status"             ): (1, 1),
-        (dav_namespace, "error"              ): (0, 1),        # 2518bis
-        (dav_namespace, "responsedescription"): (0, 1),
-    }
-
-
- at registerElement
- at registerElementClass
-class Status (WebDAVTextElement):
-    """
-    Holds a single HTTP status line. (RFC 2518, section 12.9.1.2)
-    """
-    name = "status"
-
-    def fromResponseCode(clazz, code):
-        """
-        code must be an integer response code in
-        twext.web2.responsecode.RESPONSES.keys()
-        """
-        if code not in responsecode.RESPONSES:
-            raise ValueError("Invalid response code: %r" % (code,))
-
-        return clazz(PCDATAElement("HTTP/1.1 %d %s" % (code, responsecode.RESPONSES[code])))
-
-    fromResponseCode = classmethod(fromResponseCode)
-
-    def __init__(self, *children, **attributes):
-        super(Status, self).__init__(*children, **attributes)
-
-        status = str(self)
-        if not status.startswith("HTTP/1.1 "):
-            raise ValueError("Invalid WebDAV status: %s" % (status,))
-
-        code = int(status[9:12])
-        if code not in responsecode.RESPONSES:
-            raise ValueError("Invalid status code: %s" % (code,))
-
-        self.code = code
-
-
- at registerElement
- at registerElementClass
-class ResponseDescription (WebDAVTextElement):
-    """
-    Contains a message that can be displayed to the user explaining the nature
-    of the response. (RFC 2518, section 12.9.2)
-    """
-    name = "responsedescription"
-
-
- at registerElement
- at registerElementClass
-class Owner (WebDAVElement):
-    """
-    Property which provides information about the principal taking out a lock.
-    (RFC 2518, section 12.10)
-    Property which identifies a principal as being the owner principal of a
-    resource. (RFC 3744, section 5.1)
-    Note that RFC 2518 allows any content, while RFC 3744 expect zero or one
-    DAV:href element.
-    """
-    name = "owner"
-    hidden = True
-    protected = True # may be protected, per RFC 3744, section 5.1
-
-    allowed_children = { WebDAVElement: (0, None) }
-
-
- at registerElement
- at registerElementClass
-class PropertyContainer (WebDAVElement):
-    """
-    Contains properties related to a resource. (RFC 2518, section 12.11)
-    """
-    name = "prop"
-
-    allowed_children = { WebDAVElement: (0, None) }
-
-
- at registerElement
- at registerElementClass
-class PropertyBehavior (WebDAVElement):
-    """
-    Specifies how properties are handled during a COPY or MOVE. (RFC 2518,
-    section 12.12)
-    """
-    name = "propertybehavior"
-
-    allowed_children = {
-        (dav_namespace, "omit"     ): (0, 1),
-        (dav_namespace, "keepalive"): (0, 1),
-    }
-
-    def __init__(self, *children, **attributes):
-        super(PropertyBehavior, self).__init__(*children, **attributes)
-
-        if len(self.children) != 1:
-            raise ValueError(
-                "Exactly one of DAV:omit, DAV:keepalive required for %s, got: %s"
-                % (self.sname(), self.children)
-            )
-
-        self.behavior = children[0]
-
-
- at registerElement
- at registerElementClass
-class KeepAlive (WebDAVElement):
-    """
-    Specifies requirements for the copying/moving or live properties. (RFC 2518,
-    section 12.12.1)
-    """
-    name = "keepalive"
-
-    allowed_children = {
-        (dav_namespace, "href"): (0, None),
-        PCDATAElement: (0, 1),
-    }
-
-    def validate(self):
-        super(KeepAlive, self).validate()
-
-        type = None
-
-        for child in self.children:
-            if type is None:
-                type = child.qname()
-            elif child.qname() != type:
-                raise ValueError(
-                    "Only one of DAV:href or PCDATA allowed for %s, got: %s"
-                    % (self.sname(), self.children)
-                )
-
-        if type == "#PCDATA":
-            if str(self) != "*":
-                raise ValueError("Invalid keepalive value: %r", (str(self),))
-
-
- at registerElement
- at registerElementClass
-class Omit (WebDAVEmptyElement):
-    """
-    Instructs the server that it should use best effort to copy properties. (RFC
-    2518, section 12.12.2)
-    """
-    name = "omit"
-
-
- at registerElement
- at registerElementClass
-class PropertyUpdate (WebDAVElement):
-    """
-    Contains a request to alter the properties on a resource. (RFC 2518, section
-    12.13)
-    """
-    name = "propertyupdate"
-
-    allowed_children = {
-        (dav_namespace, "remove"): (0, None),
-        (dav_namespace, "set"   ): (0, None),
-    }
-
-
- at registerElement
- at registerElementClass
-class Remove (WebDAVElement):
-    """
-    Lists the DAV properties to be removed from a resource. (RFC 2518, section
-    12.13.1)
-    """
-    name = "remove"
-
-    allowed_children = { (dav_namespace, "prop"): (1, 1) }
-
-
- at registerElement
- at registerElementClass
-class Set (WebDAVElement):
-    """
-    Lists the DAV properties to be set for a resource. (RFC 2518, section
-    12.13.2)
-    """
-    name = "set"
-
-    allowed_children = { (dav_namespace, "prop"): (1, 1) }
-
-
- at registerElement
- at registerElementClass
-class PropertyFind (WebDAVElement):
-    """
-    Specifies the properties to be returned from a PROPFIND
-    method. (RFC 2518, section 12.14)
-    """
-    name = "propfind"
-
-    allowed_children = {
-        (dav_namespace, "allprop" ): (0, 1),
-        (dav_namespace, "propname"): (0, 1),
-        (dav_namespace, "prop"    ): (0, 1),
-    }
-
-    def validate(self):
-        super(PropertyFind, self).validate()
-
-        if len(self.children) != 1:
-            raise ValueError(
-                "Exactly one of DAV:allprop, DAV:propname or DAV:prop is required for %s, got: %r"
-                % (self.sname(), self.children)
-            )
-
-
- at registerElement
- at registerElementClass
-class AllProperties (WebDAVEmptyElement):
-    """
-    Specifies that all property names and values on the resource are
-    to be returned. (RFC 2518, section 12.14.1)
-    """
-    name = "allprop"
-
-
- at registerElement
- at registerElementClass
-class PropertyName (WebDAVEmptyElement):
-    """
-    Specifies that only a list of property names on the resource are
-    to be returned. (RFC 2518, section 12.14.2)
-    """
-    name = "propname"
-
-
-##
-# Section 13
-##
-
- at registerElement
- at registerElementClass
-class CreationDate (WebDAVDateTimeElement):
-    """
-    Records the time and date that the resource was created. (RFC 2518, section
-    13.1)
-    """
-    name = "creationdate"
-    # MAY be protected as per RFC2518bis.  We may make this more flexible later.
-    protected = True
-
-
- at registerElement
- at registerElementClass
-class DisplayName (WebDAVTextElement):
-    """
-    Provides a name for the resource that is suitable for presentation
-    to a user. (RFC 2518, section 13.2)
-    """
-    name = "displayname"
-
-
- at registerElement
- at registerElementClass
-class GETContentLanguage (WebDAVTextElement):
-    """
-    Contains the Content-Language header returned by a GET without
-    accept headers. (RFC 2518, section 13.3)
-    """
-    name = "getcontentlanguage"
-
-
- at registerElement
- at registerElementClass
-class GETContentLength (WebDAVTextElement):
-    """
-    Contains the Content-Length header returned by a GET without
-    accept headers. (RFC 2518, section 13.4)
-    """
-    name = "getcontentlength"
-    protected = True
-
-
- at registerElement
- at registerElementClass
-class GETContentType (WebDAVTextElement):
-    """
-    Contains the Content-Type header returned by a GET without
-    accept headers. (RFC 2518, section 13.5)
-    """
-    name = "getcontenttype"
-
-    def mimeType(self):
-        return MimeType.fromString(str(self))
-
-
- at registerElement
- at registerElementClass
-class GETETag (WebDAVTextElement):
-    """
-    Contains the ETag header returned by a GET without
-    accept headers. (RFC 2518, section 13.6)
-    """
-    name = "getetag"
-    protected = True
-
-
- at registerElement
- at registerElementClass
-class GETLastModified (DateTimeHeaderElement):
-    """
-    Contains the Last-Modified header returned by a GET without accept
-    headers. (RFC 2518, section 13.7)
-    """
-    name = "getlastmodified"
-    protected = True
-
-
- at registerElement
- at registerElementClass
-class LockDiscovery (WebDAVElement):
-    """
-    Describes the active locks on a resource. (RFC 2518, section 13.8)
-    """
-    name = "lockdiscovery"
-    protected = True
-
-    allowed_children = { (dav_namespace, "activelock"): (0, None) }
-
-
- at registerElement
- at registerElementClass
-class ResourceType (WebDAVElement):
-    """
-    Specifies the nature of the resource. (RFC 2518, section 13.9)
-    """
-    name = "resourcetype"
-    protected = True
-
-    allowed_children = { WebDAVElement: (0, None) }
-
-ResourceType.collection = ResourceType(Collection())
-ResourceType.empty      = ResourceType()
-
-
- at registerElement
- at registerElementClass
-class Source (WebDAVElement):
-    """
-    The destination of the source link identifies the resource that
-    contains the unprocessed source of the link's source. (RFC 2518, section
-    13.10)
-    """
-    name = "source"
-
-    allowed_children = { (dav_namespace, "link"): (0, None) }
-
-
- at registerElement
- at registerElementClass
-class SupportedLock (WebDAVElement):
-    """
-    Provides a listing of the lock capabilities supported by the
-    resource. (RFC 2518, section 13.11)
-    """
-    name = "supportedlock"
-    protected = True
-
-    allowed_children = { (dav_namespace, "lockentry"): (0, None) }
-
-
-# FIXME: Add preconditions codes defined in RFC4918
-
-
- at registerElement
- at registerElementClass
-class PropfindFiniteDepth (WebDAVEmptyElement):
-    """
-    Error which indicates Depth:infinity PROPFIND not allowed
-    """
-    name = "propfind-finite-depth"

Copied: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc2518.py (from rev 8919, CalendarServer/trunk/txdav/xml/rfc2518.py)
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc2518.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc2518.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -0,0 +1,728 @@
+##
+# Copyright (c) 2005-2012 Apple Computer, Inc. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+##
+
+# FIXME: RFC 2518 is obsoleted by RFC 5689.  Check for changes.
+
+"""
+RFC 2518 (WebDAV) XML Elements
+
+This module provides XML element definitions for use with WebDAV.
+
+See RFC 2518: http://www.ietf.org/rfc/rfc2518.txt
+"""
+
+__all__ = []
+
+
+from twext.web2 import responsecode
+from twext.web2.http_headers import MimeType
+
+from txdav.xml.base import WebDAVElement, WebDAVTextElement, PCDATAElement
+from txdav.xml.base import WebDAVEmptyElement, WebDAVOneShotElement
+from txdav.xml.base import WebDAVDateTimeElement, DateTimeHeaderElement
+from txdav.xml.element import dav_namespace, registerElement, registerElementClass
+
+
+##
+# Section 12
+##
+
+ at registerElement
+ at registerElementClass
+class ActiveLock (WebDAVElement):
+    """
+    Describes a lock on a resource. (RFC 2518, section 12.1)
+    """
+    name = "activelock"
+
+    allowed_children = {
+        (dav_namespace, "lockscope"): (1, 1),
+        (dav_namespace, "locktype" ): (1, 1),
+        (dav_namespace, "depth"    ): (1, 1),
+        (dav_namespace, "owner"    ): (0, 1),
+        (dav_namespace, "timeout"  ): (0, 1),
+        (dav_namespace, "locktoken"): (0, 1),
+    }
+
+
+ at registerElement
+ at registerElementClass
+class Depth (WebDAVTextElement):
+    """
+    The value of the depth header. (RFC 2518, section 12.1.1)
+    """
+    name = "depth"
+
+    def validate(self):
+        super(Depth, self).validate()
+
+        depth = str(self)
+        if depth not in ("0", "1", "infinity"):
+            raise ValueError("Invalid depth: %s" % (depth,))
+
+
+ at registerElement
+ at registerElementClass
+class LockToken (WebDAVElement):
+    """
+    The lock token associated with a lock. (RFC 2518, section 12.1.2)
+    """
+    name = "locktoken"
+
+    allowed_children = { (dav_namespace, "href"): (1, None) }
+
+
+ at registerElement
+ at registerElementClass
+class Timeout (WebDAVTextElement):
+    """
+    The timeout associated with a lock. (RFC 2518, section 12.1.3)
+    """
+    name = "timeout"
+
+
+ at registerElement
+ at registerElementClass
+class Collection (WebDAVEmptyElement):
+    """
+    Identifies the associated resource as a collection. (RFC 2518, section 12.2)
+    """
+    name = "collection"
+
+
+ at registerElement
+ at registerElementClass
+class HRef (WebDAVTextElement):
+    """
+    Identifies the content of the element as a URI. (RFC 2518, section 12.3)
+    """
+    name = "href"
+
+
+ at registerElement
+ at registerElementClass
+class Link (WebDAVElement):
+    """
+    Identifies the property as a link and contains the source and
+    destination of that link. (RFC 2518, section 12.4)
+    """
+    name = "link"
+
+    allowed_children = {
+        (dav_namespace, "src"): (1, None),
+        (dav_namespace, "dst"): (1, None),
+    }
+
+
+ at registerElement
+ at registerElementClass
+class LinkDestination (WebDAVTextElement):
+    """
+    Indicates the destination of a link. (RFC 2518, section 12.4.1)
+    """
+    name = "dst"
+
+
+ at registerElement
+ at registerElementClass
+class LinkSource (WebDAVTextElement):
+    """
+    Indicates the source of a link. (RFC 2518, section 12.4.2)
+    """
+    name = "src"
+
+
+ at registerElement
+ at registerElementClass
+class LockEntry (WebDAVElement):
+    """
+    Defines the types of lock that can be used with the
+    resource. (RFC 2518, section 12.5)
+    """
+    name = "lockentry"
+
+    allowed_children = {
+        (dav_namespace, "lockscope"): (1, 1),
+        (dav_namespace, "locktype" ): (1, 1),
+    }
+
+
+ at registerElement
+ at registerElementClass
+class LockInfo (WebDAVElement):
+    """
+    Used with a LOCK method to specify the type of lock that the
+    client wishes to have created. (RFC 2518, section 12.6)
+    """
+    name = "lockinfo"
+
+    allowed_children = {
+        (dav_namespace, "lockscope"): (1, 1),
+        (dav_namespace, "locktype" ): (1, 1),
+        (dav_namespace, "owner"    ): (0, 1),
+    }
+
+
+ at registerElement
+ at registerElementClass
+class LockScope (WebDAVOneShotElement):
+    """
+    Specifies whether a lock is an exclusive lock or a shared
+    lock. (RFC 2518, section 12.7)
+    """
+    name = "lockscope"
+
+    allowed_children = {
+        (dav_namespace, "exclusive"): (0, 1),
+        (dav_namespace, "shared"   ): (0, 1),
+    }
+
+
+ at registerElement
+ at registerElementClass
+class Exclusive (WebDAVEmptyElement):
+    """
+    Indicates an exclusive lock. (RFC 2518, section 12.7.1)
+    """
+    name = "exclusive"
+
+LockScope.exclusive = LockScope(Exclusive())
+
+
+ at registerElement
+ at registerElementClass
+class Shared (WebDAVEmptyElement):
+    """
+    Indicates a shared lock. (RFC 2518, section 12.7.2)
+    """
+    name = "shared"
+
+LockScope.shared = LockScope(Shared())
+
+
+ at registerElement
+ at registerElementClass
+class LockType (WebDAVOneShotElement):
+    """
+    Specifies the access type of a lock. (RFC 2518, section 12.8)
+    """
+    name = "locktype"
+
+    allowed_children = { (dav_namespace, "write"): (0, 1) }
+
+
+ at registerElement
+ at registerElementClass
+class Write (WebDAVEmptyElement):
+    """
+    Indicates a write lock. (RFC 2518, section 12.8.1)
+    Controls methods that lock a resource or modify the content, dead
+    properties, or (in the case of a collection) membership of a resource.
+    (RFC 3744, section 3.2)
+    """
+    name = "write"
+
+LockType.write = LockType(Write())
+
+
+ at registerElement
+ at registerElementClass
+class MultiStatus (WebDAVElement):
+    """
+    Contains multiple Responses. (RFC 2518, section 12.9)
+    """
+    name = "multistatus"
+
+    allowed_children = {
+        (dav_namespace, "response"           ): (0, None),
+        (dav_namespace, "responsedescription"): (0, 1),
+    }
+
+
+ at registerElement
+ at registerElementClass
+class Response (WebDAVElement):
+    """
+    Holds a single response describing the effect of a method on a
+    resource and/or its properties. (RFC 2518, section 12.9.1)
+    """
+    name = "response"
+
+    allowed_children = {
+        (dav_namespace, "href"               ): (1, None),
+        (dav_namespace, "status"             ): (1, 1),
+        (dav_namespace, "propstat"           ): (1, None),
+        (dav_namespace, "error"              ): (0, 1),        # 2518bis
+        (dav_namespace, "responsedescription"): (0, 1),
+    }
+
+    def __new__(clazz, *children):
+        if clazz is not Response: return WebDAVElement.__new__(clazz)
+
+        resource_count = 0
+        status_count   = 0
+        propstat_count = 0
+
+        for child in children:
+            if   isinstance(child, HRef          ): resource_count += 1
+            elif isinstance(child, Status        ): status_count   += 1
+            elif isinstance(child, PropertyStatus): propstat_count += 1
+
+        if resource_count < 1:
+            raise ValueError("%s element must have at least one %s."
+                             % (clazz.sname(), HRef.sname()))
+
+        if status_count is 0:
+            if propstat_count is 0:
+                raise ValueError("%s element must have one of %s or %s"
+                                 % (clazz.sname(), Status.sname(), PropertyStatus.sname()))
+
+            if resource_count > 1:
+                raise ValueError("%s element with %s may only have one %s"
+                                 % (clazz.sname(), PropertyStatus.sname(), HRef.sname()))
+
+            return PropertyStatusResponse.__new__(PropertyStatusResponse, *children)
+
+        if status_count > 1:
+            raise ValueError("%s element may only have one %s" % (clazz.sname(), Status.sname()))
+
+        return StatusResponse.__new__(StatusResponse, *children)
+
+
+ at registerElementClass
+class StatusResponse (Response):
+    """
+    Specialized derivative of Response for resource status.
+    """
+    unregistered = True
+
+    allowed_children = {
+        (dav_namespace, "href"               ): (1, None),
+        (dav_namespace, "status"             ): (1, 1),
+        (dav_namespace, "error"              ): (0, 1),        # 2518bis
+        (dav_namespace, "responsedescription"): (0, 1),
+    }
+
+
+ at registerElementClass
+class PropertyStatusResponse (Response):
+    """
+    Specialized derivative of Response for property status.
+    """
+    unregistered = True
+
+    allowed_children = {
+        (dav_namespace, "href"               ): (1, 1),
+        (dav_namespace, "propstat"           ): (1, None),
+        (dav_namespace, "error"              ): (0, 1),        # 2518bis
+        (dav_namespace, "responsedescription"): (0, 1),
+    }
+
+
+ at registerElement
+ at registerElementClass
+class PropertyStatus (WebDAVElement):
+    """
+    Groups together a Property and Status element that is associated
+    with a particular DAV:href element. (RFC 2518, section 12.9.1.1)
+    """
+    name = "propstat"
+
+    allowed_children = {
+        (dav_namespace, "prop"               ): (1, 1),
+        (dav_namespace, "status"             ): (1, 1),
+        (dav_namespace, "error"              ): (0, 1),        # 2518bis
+        (dav_namespace, "responsedescription"): (0, 1),
+    }
+
+
+ at registerElement
+ at registerElementClass
+class Status (WebDAVTextElement):
+    """
+    Holds a single HTTP status line. (RFC 2518, section 12.9.1.2)
+    """
+    name = "status"
+
+    def fromResponseCode(clazz, code):
+        """
+        code must be an integer response code in
+        twext.web2.responsecode.RESPONSES.keys()
+        """
+        if code not in responsecode.RESPONSES:
+            raise ValueError("Invalid response code: %r" % (code,))
+
+        return clazz(PCDATAElement("HTTP/1.1 %d %s" % (code, responsecode.RESPONSES[code])))
+
+    fromResponseCode = classmethod(fromResponseCode)
+
+    def __init__(self, *children, **attributes):
+        super(Status, self).__init__(*children, **attributes)
+
+        status = str(self)
+        if not status.startswith("HTTP/1.1 "):
+            raise ValueError("Invalid WebDAV status: %s" % (status,))
+
+        code = int(status[9:12])
+        if code not in responsecode.RESPONSES:
+            raise ValueError("Invalid status code: %s" % (code,))
+
+        self.code = code
+
+
+ at registerElement
+ at registerElementClass
+class ResponseDescription (WebDAVTextElement):
+    """
+    Contains a message that can be displayed to the user explaining the nature
+    of the response. (RFC 2518, section 12.9.2)
+    """
+    name = "responsedescription"
+
+
+ at registerElement
+ at registerElementClass
+class Owner (WebDAVElement):
+    """
+    Property which provides information about the principal taking out a lock.
+    (RFC 2518, section 12.10)
+    Property which identifies a principal as being the owner principal of a
+    resource. (RFC 3744, section 5.1)
+    Note that RFC 2518 allows any content, while RFC 3744 expect zero or one
+    DAV:href element.
+    """
+    name = "owner"
+    hidden = True
+    protected = True # may be protected, per RFC 3744, section 5.1
+
+    allowed_children = { WebDAVElement: (0, None) }
+
+
+ at registerElement
+ at registerElementClass
+class PropertyContainer (WebDAVElement):
+    """
+    Contains properties related to a resource. (RFC 2518, section 12.11)
+    """
+    name = "prop"
+
+    allowed_children = { WebDAVElement: (0, None) }
+
+
+ at registerElement
+ at registerElementClass
+class PropertyBehavior (WebDAVElement):
+    """
+    Specifies how properties are handled during a COPY or MOVE. (RFC 2518,
+    section 12.12)
+    """
+    name = "propertybehavior"
+
+    allowed_children = {
+        (dav_namespace, "omit"     ): (0, 1),
+        (dav_namespace, "keepalive"): (0, 1),
+    }
+
+    def __init__(self, *children, **attributes):
+        super(PropertyBehavior, self).__init__(*children, **attributes)
+
+        if len(self.children) != 1:
+            raise ValueError(
+                "Exactly one of DAV:omit, DAV:keepalive required for %s, got: %s"
+                % (self.sname(), self.children)
+            )
+
+        self.behavior = children[0]
+
+
+ at registerElement
+ at registerElementClass
+class KeepAlive (WebDAVElement):
+    """
+    Specifies requirements for the copying/moving or live properties. (RFC 2518,
+    section 12.12.1)
+    """
+    name = "keepalive"
+
+    allowed_children = {
+        (dav_namespace, "href"): (0, None),
+        PCDATAElement: (0, 1),
+    }
+
+    def validate(self):
+        super(KeepAlive, self).validate()
+
+        type = None
+
+        for child in self.children:
+            if type is None:
+                type = child.qname()
+            elif child.qname() != type:
+                raise ValueError(
+                    "Only one of DAV:href or PCDATA allowed for %s, got: %s"
+                    % (self.sname(), self.children)
+                )
+
+        if type == "#PCDATA":
+            if str(self) != "*":
+                raise ValueError("Invalid keepalive value: %r", (str(self),))
+
+
+ at registerElement
+ at registerElementClass
+class Omit (WebDAVEmptyElement):
+    """
+    Instructs the server that it should use best effort to copy properties. (RFC
+    2518, section 12.12.2)
+    """
+    name = "omit"
+
+
+ at registerElement
+ at registerElementClass
+class PropertyUpdate (WebDAVElement):
+    """
+    Contains a request to alter the properties on a resource. (RFC 2518, section
+    12.13)
+    """
+    name = "propertyupdate"
+
+    allowed_children = {
+        (dav_namespace, "remove"): (0, None),
+        (dav_namespace, "set"   ): (0, None),
+    }
+
+
+ at registerElement
+ at registerElementClass
+class Remove (WebDAVElement):
+    """
+    Lists the DAV properties to be removed from a resource. (RFC 2518, section
+    12.13.1)
+    """
+    name = "remove"
+
+    allowed_children = { (dav_namespace, "prop"): (1, 1) }
+
+
+ at registerElement
+ at registerElementClass
+class Set (WebDAVElement):
+    """
+    Lists the DAV properties to be set for a resource. (RFC 2518, section
+    12.13.2)
+    """
+    name = "set"
+
+    allowed_children = { (dav_namespace, "prop"): (1, 1) }
+
+
+ at registerElement
+ at registerElementClass
+class PropertyFind (WebDAVElement):
+    """
+    Specifies the properties to be returned from a PROPFIND
+    method. (RFC 2518, section 12.14)
+    """
+    name = "propfind"
+
+    allowed_children = {
+        (dav_namespace, "allprop" ): (0, 1),
+        (dav_namespace, "propname"): (0, 1),
+        (dav_namespace, "prop"    ): (0, 1),
+    }
+
+    def validate(self):
+        super(PropertyFind, self).validate()
+
+        if len(self.children) != 1:
+            raise ValueError(
+                "Exactly one of DAV:allprop, DAV:propname or DAV:prop is required for %s, got: %r"
+                % (self.sname(), self.children)
+            )
+
+
+ at registerElement
+ at registerElementClass
+class AllProperties (WebDAVEmptyElement):
+    """
+    Specifies that all property names and values on the resource are
+    to be returned. (RFC 2518, section 12.14.1)
+    """
+    name = "allprop"
+
+
+ at registerElement
+ at registerElementClass
+class PropertyName (WebDAVEmptyElement):
+    """
+    Specifies that only a list of property names on the resource are
+    to be returned. (RFC 2518, section 12.14.2)
+    """
+    name = "propname"
+
+
+##
+# Section 13
+##
+
+ at registerElement
+ at registerElementClass
+class CreationDate (WebDAVDateTimeElement):
+    """
+    Records the time and date that the resource was created. (RFC 2518, section
+    13.1)
+    """
+    name = "creationdate"
+    # MAY be protected as per RFC2518bis.  We may make this more flexible later.
+    protected = True
+
+
+ at registerElement
+ at registerElementClass
+class DisplayName (WebDAVTextElement):
+    """
+    Provides a name for the resource that is suitable for presentation
+    to a user. (RFC 2518, section 13.2)
+    """
+    name = "displayname"
+
+
+ at registerElement
+ at registerElementClass
+class GETContentLanguage (WebDAVTextElement):
+    """
+    Contains the Content-Language header returned by a GET without
+    accept headers. (RFC 2518, section 13.3)
+    """
+    name = "getcontentlanguage"
+
+
+ at registerElement
+ at registerElementClass
+class GETContentLength (WebDAVTextElement):
+    """
+    Contains the Content-Length header returned by a GET without
+    accept headers. (RFC 2518, section 13.4)
+    """
+    name = "getcontentlength"
+    protected = True
+
+
+ at registerElement
+ at registerElementClass
+class GETContentType (WebDAVTextElement):
+    """
+    Contains the Content-Type header returned by a GET without
+    accept headers. (RFC 2518, section 13.5)
+    """
+    name = "getcontenttype"
+
+    def mimeType(self):
+        return MimeType.fromString(str(self))
+
+
+ at registerElement
+ at registerElementClass
+class GETETag (WebDAVTextElement):
+    """
+    Contains the ETag header returned by a GET without
+    accept headers. (RFC 2518, section 13.6)
+    """
+    name = "getetag"
+    protected = True
+
+
+ at registerElement
+ at registerElementClass
+class GETLastModified (DateTimeHeaderElement):
+    """
+    Contains the Last-Modified header returned by a GET without accept
+    headers. (RFC 2518, section 13.7)
+    """
+    name = "getlastmodified"
+    protected = True
+
+
+ at registerElement
+ at registerElementClass
+class LockDiscovery (WebDAVElement):
+    """
+    Describes the active locks on a resource. (RFC 2518, section 13.8)
+    """
+    name = "lockdiscovery"
+    protected = True
+
+    allowed_children = { (dav_namespace, "activelock"): (0, None) }
+
+
+ at registerElement
+ at registerElementClass
+class ResourceType (WebDAVElement):
+    """
+    Specifies the nature of the resource. (RFC 2518, section 13.9)
+    """
+    name = "resourcetype"
+    protected = True
+
+    allowed_children = { WebDAVElement: (0, None) }
+
+ResourceType.collection = ResourceType(Collection())
+ResourceType.empty      = ResourceType()
+
+
+ at registerElement
+ at registerElementClass
+class Source (WebDAVElement):
+    """
+    The destination of the source link identifies the resource that
+    contains the unprocessed source of the link's source. (RFC 2518, section
+    13.10)
+    """
+    name = "source"
+
+    allowed_children = { (dav_namespace, "link"): (0, None) }
+
+
+ at registerElement
+ at registerElementClass
+class SupportedLock (WebDAVElement):
+    """
+    Provides a listing of the lock capabilities supported by the
+    resource. (RFC 2518, section 13.11)
+    """
+    name = "supportedlock"
+    protected = True
+
+    allowed_children = { (dav_namespace, "lockentry"): (0, None) }
+
+
+# FIXME: Add preconditions codes defined in RFC4918
+
+
+ at registerElement
+ at registerElementClass
+class PropfindFiniteDepth (WebDAVEmptyElement):
+    """
+    Error which indicates Depth:infinity PROPFIND not allowed
+    """
+    name = "propfind-finite-depth"

Deleted: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc3253.py
===================================================================
--- CalendarServer/trunk/txdav/xml/rfc3253.py	2012-03-22 00:02:25 UTC (rev 8919)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc3253.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -1,234 +0,0 @@
-##
-# Copyright (c) 2005-2012 Apple Computer, Inc. All rights reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-# 
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-# 
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-##
-
-"""
-RFC 3253 (Versioning Extensions to WebDAV) XML Elements
-
-This module provides XML element definitions for use with WebDAV.
-
-See RFC 3253: http://www.ietf.org/rfc/rfc3253.txt
-"""
-
-__all__ = []
-
-
-from txdav.xml.base import WebDAVElement, WebDAVTextElement, dav_namespace
-from txdav.xml.element import registerElement, registerElementClass
-
-
-##
-# Section 1
-##
-
- at registerElement
- at registerElementClass
-class Error (WebDAVElement):
-    """
-    Specifies an error condition. (RFC 3253, section 1.6)
-    """
-    # FIXME: RFC 3253 doesn't quite seem to define this element...
-    # FIXME: Move when we update to RFC 2518bis
-    name = "error"
-
-    allowed_children = { WebDAVElement: (0, None) }
-
-
-##
-# Section 3
-##
-
- at registerElement
- at registerElementClass
-class Comment (WebDAVTextElement):
-    """
-    Property used to track a brief comment about a resource that is suitable for
-    presentation to a user. On a version, can be used to indicate why that
-    version was created. (RFC 3253, section 3.1.1)
-    """
-    name = "comment"
-    hidden = True
-
-
- at registerElement
- at registerElementClass
-class CreatorDisplayName (WebDAVTextElement):
-    """
-    Property which contains a description of the creator of the resource that is
-    suitable for presentation to a user. (RFC 3253, section 3.1.2)
-    """
-    name = "creator-displayname"
-    hidden = True
-
-
- at registerElement
- at registerElementClass
-class SupportedMethod (WebDAVElement):
-    """
-    Property which identifies a method that is supported by a resource. A method
-    is supported by a resource if there is some state of that resource for which
-    an application of that method will successfully satisfy all postconditions
-    of that method, including any additional postconditions added by the
-    features supported by that resource. (RFC 3253, section 3.1.3)
-    """
-    name = "supported-method"
-    hidden = True
-
-    allowed_children = { WebDAVElement: (0, None) }
-    allowed_attributes = { "name": True }
-
-
- at registerElement
- at registerElementClass
-class SupportedMethodSet (WebDAVElement):
-    """
-    Property which identifies the methods that are supported by a resource. (RFC
-    3253, section 3.1.3)
-    """
-    name = "supported-method-set"
-    protected = True
-    hidden = True
-
-    allowed_children = { (dav_namespace, "supported-method"): (0, None) }
-
-
- at registerElement
- at registerElementClass
-class SupportedLiveProperty (WebDAVElement):
-    """
-    Property which identifies a live property that is supported by a resource. A
-    live property is supported by a resource if that property has the semantics
-    defined for that property.  The value of this property must identify all
-    live properties defined by this document that are supported by the resource
-    and should identify all live properties that are supported by the resource.
-    (RFC 3253, section 3.1.4)
-    """
-    name = "supported-live-property"
-
-    # FIXME: Where is the name element defined?
-    allowed_children = { (dav_namespace, "name"): (1, 1) }
-
-
- at registerElement
- at registerElementClass
-class SupportedLivePropertySet (WebDAVElement):
-    """
-    Property which identifies the live properties that are supported by a
-    resource. (RFC 3253, section 3.1.4)
-    """
-    name = "supported-live-property-set"
-    hidden = True
-    protected = True
-
-    allowed_children = { (dav_namespace, "supported-live-property"): (0, None) }
-
-
- at registerElement
- at registerElementClass
-class Report (WebDAVElement):
-    """
-    A report. (RFC 3253, section 3.1.5)
-    """
-    # FIXME: Section 3.1.5 is pretty low on information.  Where else do we look?
-    name = "report"
-
-    allowed_children = { WebDAVElement: (0, None) }
-
-
- at registerElement
- at registerElementClass
-class SupportedReport (WebDAVElement):
-    """
-    Identifies a report that is supported by the resource.  (RFC 3253, section
-    3.1.5)
-    """
-    name = "supported-report"
-
-    #
-    # FIXME:
-    #
-    #   RFC 3253, section 3.1.5 defines supported-report as:
-    #
-    #     <!ELEMENT supported-report report>
-    #
-    #   Which means that a report child element is required.  However, section
-    # 3.6 defined a precondition with the same name (DAV:supported-report),
-    # which means that, according to section 1.6.1, this XML must be issued if
-    # the precondition fails:
-    #
-    #     <?xml version="1.0"?>
-    #     <D:error xmlns:D="DAV:">
-    #      <D:supported-report/>
-    #     </D:error>
-    #
-    #   Which is a problem because here we use supported-report with no
-    # children.
-    #
-    #   Absent any better guidance, we'll allow no children for this element for
-    # the time being.
-    #
-    allowed_children = { (dav_namespace, "report"): (0, 1) }
-
-
- at registerElement
- at registerElementClass
-class SupportedReportSet (WebDAVElement):
-    """
-    Property which identifies the reports that are supported by the resource.
-    (RFC 3253, section 3.1.5)
-    """
-    name = "supported-report-set"
-    hidden = True
-    protected = True
-
-    allowed_children = { (dav_namespace, "supported-report"): (0, None) }
-
-
- at registerElement
- at registerElementClass
-class ExpandProperty (WebDAVElement):
-    """
-    Report which provides a mechanism for retrieving in one request the
-    properties from resources identified by DAV:href property values.
-    (RFC 3253, section 3.8)
-    """
-    name = "expand-property"
-
-    allowed_children = { (dav_namespace, "property"): (0, None) }
-
-
- at registerElement
- at registerElementClass
-class Property (WebDAVElement):
-    """
-    Identifies a property by name. (RFC 3253, section 3.8)
-    Principal which matches a user if the value of the identified property of a
-    resource contains at most one DAV:href element, the value of that element
-    identifies a principal, and the user matches that principal. (RFC 3744,
-    section 5.5.1)
-    """
-    name = "property"
-
-    allowed_children = { (dav_namespace, "property"): (0, None) }
-    allowed_attributes = {
-        "name"      : True,
-        "namespace" : False,
-    }

Copied: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc3253.py (from rev 8919, CalendarServer/trunk/txdav/xml/rfc3253.py)
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc3253.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc3253.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -0,0 +1,234 @@
+##
+# Copyright (c) 2005-2012 Apple Computer, Inc. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+##
+
+"""
+RFC 3253 (Versioning Extensions to WebDAV) XML Elements
+
+This module provides XML element definitions for use with WebDAV.
+
+See RFC 3253: http://www.ietf.org/rfc/rfc3253.txt
+"""
+
+__all__ = []
+
+
+from txdav.xml.base import WebDAVElement, WebDAVTextElement, dav_namespace
+from txdav.xml.element import registerElement, registerElementClass
+
+
+##
+# Section 1
+##
+
+ at registerElement
+ at registerElementClass
+class Error (WebDAVElement):
+    """
+    Specifies an error condition. (RFC 3253, section 1.6)
+    """
+    # FIXME: RFC 3253 doesn't quite seem to define this element...
+    # FIXME: Move when we update to RFC 2518bis
+    name = "error"
+
+    allowed_children = { WebDAVElement: (0, None) }
+
+
+##
+# Section 3
+##
+
+ at registerElement
+ at registerElementClass
+class Comment (WebDAVTextElement):
+    """
+    Property used to track a brief comment about a resource that is suitable for
+    presentation to a user. On a version, can be used to indicate why that
+    version was created. (RFC 3253, section 3.1.1)
+    """
+    name = "comment"
+    hidden = True
+
+
+ at registerElement
+ at registerElementClass
+class CreatorDisplayName (WebDAVTextElement):
+    """
+    Property which contains a description of the creator of the resource that is
+    suitable for presentation to a user. (RFC 3253, section 3.1.2)
+    """
+    name = "creator-displayname"
+    hidden = True
+
+
+ at registerElement
+ at registerElementClass
+class SupportedMethod (WebDAVElement):
+    """
+    Property which identifies a method that is supported by a resource. A method
+    is supported by a resource if there is some state of that resource for which
+    an application of that method will successfully satisfy all postconditions
+    of that method, including any additional postconditions added by the
+    features supported by that resource. (RFC 3253, section 3.1.3)
+    """
+    name = "supported-method"
+    hidden = True
+
+    allowed_children = { WebDAVElement: (0, None) }
+    allowed_attributes = { "name": True }
+
+
+ at registerElement
+ at registerElementClass
+class SupportedMethodSet (WebDAVElement):
+    """
+    Property which identifies the methods that are supported by a resource. (RFC
+    3253, section 3.1.3)
+    """
+    name = "supported-method-set"
+    protected = True
+    hidden = True
+
+    allowed_children = { (dav_namespace, "supported-method"): (0, None) }
+
+
+ at registerElement
+ at registerElementClass
+class SupportedLiveProperty (WebDAVElement):
+    """
+    Property which identifies a live property that is supported by a resource. A
+    live property is supported by a resource if that property has the semantics
+    defined for that property.  The value of this property must identify all
+    live properties defined by this document that are supported by the resource
+    and should identify all live properties that are supported by the resource.
+    (RFC 3253, section 3.1.4)
+    """
+    name = "supported-live-property"
+
+    # FIXME: Where is the name element defined?
+    allowed_children = { (dav_namespace, "name"): (1, 1) }
+
+
+ at registerElement
+ at registerElementClass
+class SupportedLivePropertySet (WebDAVElement):
+    """
+    Property which identifies the live properties that are supported by a
+    resource. (RFC 3253, section 3.1.4)
+    """
+    name = "supported-live-property-set"
+    hidden = True
+    protected = True
+
+    allowed_children = { (dav_namespace, "supported-live-property"): (0, None) }
+
+
+ at registerElement
+ at registerElementClass
+class Report (WebDAVElement):
+    """
+    A report. (RFC 3253, section 3.1.5)
+    """
+    # FIXME: Section 3.1.5 is pretty low on information.  Where else do we look?
+    name = "report"
+
+    allowed_children = { WebDAVElement: (0, None) }
+
+
+ at registerElement
+ at registerElementClass
+class SupportedReport (WebDAVElement):
+    """
+    Identifies a report that is supported by the resource.  (RFC 3253, section
+    3.1.5)
+    """
+    name = "supported-report"
+
+    #
+    # FIXME:
+    #
+    #   RFC 3253, section 3.1.5 defines supported-report as:
+    #
+    #     <!ELEMENT supported-report report>
+    #
+    #   Which means that a report child element is required.  However, section
+    # 3.6 defined a precondition with the same name (DAV:supported-report),
+    # which means that, according to section 1.6.1, this XML must be issued if
+    # the precondition fails:
+    #
+    #     <?xml version="1.0"?>
+    #     <D:error xmlns:D="DAV:">
+    #      <D:supported-report/>
+    #     </D:error>
+    #
+    #   Which is a problem because here we use supported-report with no
+    # children.
+    #
+    #   Absent any better guidance, we'll allow no children for this element for
+    # the time being.
+    #
+    allowed_children = { (dav_namespace, "report"): (0, 1) }
+
+
+ at registerElement
+ at registerElementClass
+class SupportedReportSet (WebDAVElement):
+    """
+    Property which identifies the reports that are supported by the resource.
+    (RFC 3253, section 3.1.5)
+    """
+    name = "supported-report-set"
+    hidden = True
+    protected = True
+
+    allowed_children = { (dav_namespace, "supported-report"): (0, None) }
+
+
+ at registerElement
+ at registerElementClass
+class ExpandProperty (WebDAVElement):
+    """
+    Report which provides a mechanism for retrieving in one request the
+    properties from resources identified by DAV:href property values.
+    (RFC 3253, section 3.8)
+    """
+    name = "expand-property"
+
+    allowed_children = { (dav_namespace, "property"): (0, None) }
+
+
+ at registerElement
+ at registerElementClass
+class Property (WebDAVElement):
+    """
+    Identifies a property by name. (RFC 3253, section 3.8)
+    Principal which matches a user if the value of the identified property of a
+    resource contains at most one DAV:href element, the value of that element
+    identifies a principal, and the user matches that principal. (RFC 3744,
+    section 5.5.1)
+    """
+    name = "property"
+
+    allowed_children = { (dav_namespace, "property"): (0, None) }
+    allowed_attributes = {
+        "name"      : True,
+        "namespace" : False,
+    }

Deleted: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc3744.py
===================================================================
--- CalendarServer/trunk/txdav/xml/rfc3744.py	2012-03-22 00:02:25 UTC (rev 8919)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc3744.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -1,932 +0,0 @@
-##
-# Copyright (c) 2005-2012 Apple Computer, Inc. All rights reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-# 
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-# 
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-##
-
-"""
-RFC 3744 (WebDAV Access Control Protocol) XML Elements
-
-This module provides XML element definitions for use with WebDAV.
-
-See RFC 3744: http://www.ietf.org/rfc/rfc3744.txt
-"""
-
-__all__ = []
-
-
-from txdav.xml.base import WebDAVElement, PCDATAElement
-from txdav.xml.base import WebDAVEmptyElement, WebDAVTextElement
-from txdav.xml.element import dav_namespace, registerElement, registerElementClass
-
-
-##
-# Section 3 (Privileges)
-##
-
- at registerElement
- at registerElementClass
-class Read (WebDAVEmptyElement):
-    """
-    Privilege which controls methods that return information about the state
-    of a resource, including the resource's properties. (RFC 3744, section
-    3.1)
-    """
-    name = "read"
-
-
-# For DAV:write element (RFC 3744, section 3.2) see Write class in
-# rfc2518.py.
-
-
- at registerElement
- at registerElementClass
-class WriteProperties (WebDAVEmptyElement):
-    """
-    Privilege which controls methods that modify the dead properties of a
-    resource. (RFC 3744, section 3.3)
-    """
-    name = "write-properties"
-
-
- at registerElement
- at registerElementClass
-class WriteContent (WebDAVEmptyElement):
-    """
-    Privilege which controls methods that modify the content of an existing
-    resource. (RFC 3744, section 3.4)
-    """
-    name = "write-content"
-
-
- at registerElement
- at registerElementClass
-class Unlock (WebDAVEmptyElement):
-    """
-    Privilege which controls the use of the UNLOCK method by a principal other
-    than the lock owner. (RFC 3744, section 3.5)
-    """
-    name = "unlock"
-
-
- at registerElement
- at registerElementClass
-class ReadACL (WebDAVEmptyElement):
-    """
-    Privilege which controls the use of the PROPFIND method to retrieve the
-    DAV:acl property of a resource. (RFC 3744, section 3.6)
-    """
-    name = "read-acl"
-
-
- at registerElement
- at registerElementClass
-class ReadCurrentUserPrivilegeSet (WebDAVEmptyElement):
-    """
-    Privilege which controls the use of the PROPFIND method to retrieve the
-    DAV:current-user-privilege-set property of a resource. (RFC 3744, section
-    3.7)
-    """
-    name = "read-current-user-privilege-set"
-
-
- at registerElement
- at registerElementClass
-class WriteACL (WebDAVEmptyElement):
-    """
-    Privilege which controls the use of the ACL method to modify the DAV:acl
-    property of a resource. (RFC 3744, section 3.8)
-    """
-    name = "write-acl"
-
-
- at registerElement
- at registerElementClass
-class Bind (WebDAVEmptyElement):
-    """
-    Privilege which allows a method to add a new member URL from the a
-    collection resource. (RFC 3744, section 3.9)
-    """
-    name = "bind"
-
-
- at registerElement
- at registerElementClass
-class Unbind (WebDAVEmptyElement):
-    """
-    Privilege which allows a method to remove a member URL from the a collection
-    resource. (RFC 3744, section 3.10)
-    """
-    name = "unbind"
-
-
- at registerElement
- at registerElementClass
-class All (WebDAVEmptyElement):
-    """
-    Aggregate privilege that contains the entire set of privileges that can be
-    applied to a resource. (RFC 3744, section 3.11)
-    Principal which matches all users. (RFC 3744, section 5.5.1)
-    """
-    name = "all"
-
-
-##
-# Section 4 (Principal Properties)
-##
-
- at registerElement
- at registerElementClass
-class Principal (WebDAVElement):
-    """
-    Indicates a principal resource type. (RFC 3744, section 4)
-    Identifies the principal to which an ACE applies. (RFC 3744, section 5.5.1)
-    """
-    name = "principal"
-
-    allowed_children = {
-        (dav_namespace, "href"           ): (0, 1),
-        (dav_namespace, "all"            ): (0, 1),
-        (dav_namespace, "authenticated"  ): (0, 1),
-        (dav_namespace, "unauthenticated"): (0, 1),
-        (dav_namespace, "property"       ): (0, 1),
-        (dav_namespace, "self"           ): (0, 1),
-    }
-
-    def validate(self):
-        super(Principal, self).validate()
-
-        if len(self.children) > 1:
-            raise ValueError(
-                "Exactly one of DAV:href, DAV:all, DAV:authenticated, "
-                "DAV:unauthenticated, DAV:property or DAV:self is required for "
-                "%s, got: %r"
-                % (self.sname(), self.children)
-            )
-
-
- at registerElement
- at registerElementClass
-class AlternateURISet (WebDAVElement):
-    """
-    Property which contains the URIs of network resources with additional
-    descriptive information about the principal. (RFC 3744, section 4.1)
-    """
-    name = "alternate-URI-set"
-    hidden = True
-    protected = True
-
-    allowed_children = { (dav_namespace, "href"): (0, None) }
-
-
- at registerElement
- at registerElementClass
-class PrincipalURL (WebDAVElement):
-    """
-    Property which contains the URL that must be used to identify this principal
-    in an ACL request. (RFC 3744, section 4.2)
-    """
-    name = "principal-URL"
-    hidden = True
-    protected = True
-
-    allowed_children = { (dav_namespace, "href"): (0, 1) }
-
-
- at registerElement
- at registerElementClass
-class GroupMemberSet (WebDAVElement):
-    """
-    Property which identifies the principals that are direct members of a group
-    principal.
-    (RFC 3744, section 4.3)
-    """
-    name = "group-member-set"
-    hidden = True
-
-    allowed_children = { (dav_namespace, "href"): (0, None) }
-
-
- at registerElement
- at registerElementClass
-class GroupMembership (WebDAVElement):
-    """
-    Property which identifies the group principals in which a principal is
-    directly a member. (RFC 3744, section 4.4)
-    """
-    name = "group-membership"
-    hidden = True
-    protected = True
-
-    allowed_children = { (dav_namespace, "href"): (0, None) }
-
-
-##
-# Section 5 (Access Control Properties)
-##
-
-# For DAV:owner element (RFC 3744, section 5.1) see Owner class in
-# rfc2518.py.
-
-
- at registerElement
- at registerElementClass
-class Group (WebDAVElement):
-    """
-    Property which identifies a particular principal as being the group
-    principal of a resource. (RFC 3744, section 5.2)
-    """
-    name = "group"
-    hidden = True
-    protected = True # may be protected, per RFC 3744, section 5.2
-
-    allowed_children = { (dav_namespace, "href"): (0, 1) }
-
-
- at registerElement
- at registerElementClass
-class SupportedPrivilegeSet (WebDAVElement):
-    """
-    Property which identifies the privileges defined for a resource. (RFC 3744,
-    section 5.3)
-    """
-    name = "supported-privilege-set"
-    hidden = True
-    protected = True
-
-    allowed_children = { (dav_namespace, "supported-privilege"): (0, None) }
-
-
- at registerElement
- at registerElementClass
-class SupportedPrivilege (WebDAVElement):
-    """
-    Identifies a privilege defined for a resource. (RFC 3744, section 5.3)
-    """
-    name = "supported-privilege"
-
-    allowed_children = {
-        (dav_namespace, "privilege"          ): (1, 1),
-        (dav_namespace, "abstract"           ): (0, 1),
-        (dav_namespace, "description"        ): (1, 1),
-        (dav_namespace, "supported-privilege"): (0, None),
-    }
-
-
- at registerElement
- at registerElementClass
-class Privilege (WebDAVElement):
-    """
-    Identifies a privilege. (RFC 3744, sections 5.3 and 5.5.1)
-    """
-    name = "privilege"
-
-    allowed_children = { WebDAVElement: (0, None) }
-
-    def isAggregateOf(self, subprivilege, supportedPrivileges):
-        """
-        Check whether this privilege is an aggregate of another.
-        @param subprivilege: a L{Privilege}
-        @param supportedPrivileges: a L{SupportedPrivilegeSet}
-        @return: C{True} is this privilege is an aggregate of C{subprivilege}
-            according to C{supportedPrivileges}.
-        """
-        # DAV: all is an aggregate of all privileges
-        if len(self.children) == 1 and self.children[0].qname() == (dav_namespace, "all"):
-            return True
-
-        def isAggregate(supportedPrivilege):
-            sp = supportedPrivilege.childOfType(Privilege)
-
-            if sp == self:
-                def find(supportedPrivilege):
-                    if supportedPrivilege.childOfType(Privilege) == subprivilege:
-                        return True
-
-                    for child in supportedPrivilege.childrenOfType(SupportedPrivilege):
-                        if find(child):
-                            return True
-                    else:
-                        return False
-
-                return find(supportedPrivilege)
-            else:
-                for child in supportedPrivilege.childrenOfType(SupportedPrivilege):
-                    if isAggregate(child):
-                        return True
-                else:
-                    return False
-
-        for supportedPrivilege in supportedPrivileges.children:
-            if isAggregate(supportedPrivilege):
-                return True
-        else:
-            return False
-
-    def expandAggregate(self, supportedPrivileges):
-        """
-        Expand this privilege into the set of privileges aggregated under it
-        based on the structure of the given supported privileges. If this
-        privilege is not an aggregate, just return it as-is.
-        @param supportedPrivileges: a L{SupportedPrivilegeSet}
-        @return: the list of expanded L{Privileges}
-        """
-
-        # Find ourselves in supported privileges
-        def find(supportedPrivilege):
-            """
-            Find the supportPrivilege which matches this privilege.
-            """
-            if supportedPrivilege.childOfType(Privilege) == self:
-                return supportedPrivilege
-
-            for child in supportedPrivilege.childrenOfType(SupportedPrivilege):
-                result = find(child)
-                if result is not None:
-                    return result
-            else:
-                return None
-
-        for supportedPrivilege in supportedPrivileges.children:
-            result = find(supportedPrivilege)
-            if result is not None:
-                break
-        else:
-            return [self]
-
-        # Now add sub-privileges recursively
-        aggregates = []
-        def add(supportedPrivilege):
-            """
-            Add all sub-privileges to the list.
-            """
-            aggregates.append(supportedPrivilege.childOfType(Privilege))
-            for child in supportedPrivilege.childrenOfType(SupportedPrivilege):
-                add(child)
-        add(result)
-
-        return aggregates
-
-
- at registerElement
- at registerElementClass
-class Abstract (WebDAVElement):
-    """
-    Identifies a privilege as abstract. (RFC 3744, section 5.3)
-    """
-    name = "abstract"
-
-
- at registerElement
- at registerElementClass
-class Description (WebDAVTextElement):
-    """
-    A human-readable description of what privilege controls access to. (RFC
-    3744, sections 5.3 and 9.5)
-    """
-    name = "description"
-    allowed_attributes = { "xml:lang": True }
-
-
- at registerElement
- at registerElementClass
-class CurrentUserPrivilegeSet (WebDAVElement):
-    """
-    Property which contains the exact set of privileges (as computer by the
-    server) granted to the currently authenticated HTTP user. (RFC 3744, section
-    5.4)
-    """
-    name = "current-user-privilege-set"
-    hidden = True
-    protected = True
-
-    allowed_children = { (dav_namespace, "privilege"): (0, None) }
-
-
-# For DAV:privilege element (RFC 3744, section 5.4) see Privilege class above.
-
-
- at registerElement
- at registerElementClass
-class ACL (WebDAVElement):
-    """
-    Property which specifies the list of access control entries which define
-    what privileges are granted to which users for a resource. (RFC 3744,
-    section 5.5)
-    """
-    name = "acl"
-    hidden = True
-    protected = True
-
-    allowed_children = { (dav_namespace, "ace"): (0, None) }
-
-
- at registerElement
- at registerElementClass
-class ACE (WebDAVElement):
-    """
-    Specifies the list of access control entries which define what privileges
-    are granted to which users for a resource. (RFC 3744, section 5.5)
-    """
-    name = "ace"
-
-    allowed_children = {
-        (dav_namespace, "principal"): (0, 1),
-        (dav_namespace, "invert"   ): (0, 1),
-        (dav_namespace, "grant"    ): (0, 1),
-        (dav_namespace, "deny"     ): (0, 1),
-        (dav_namespace, "protected"): (0, 1),
-        (dav_namespace, "inherited"): (0, 1),
-    }
-
-    def __init__(self, *children, **attributes):
-        super(ACE, self).__init__(*children, **attributes)
-
-        self.principal  = None
-        self.invert     = None
-        self.allow      = None
-        self.privileges = None
-        self.inherited  = None
-        self.protected  = False
-
-        my_children = []
-
-        for child in self.children:
-            namespace, name = child.qname()
-
-            if isinstance(child, PCDATAElement):
-                continue
-
-            if (namespace == dav_namespace):
-                if name in ("principal", "invert"):
-                    if self.principal is not None:
-                        raise ValueError(
-                            "Only one of DAV:principal or DAV:invert allowed in %s, got: %s"
-                            % (self.sname(), self.children)
-                        )
-                    if name == "invert":
-                        self.invert    = True
-                        self.principal = child.children[0]
-                    else:
-                        self.invert    = False
-                        self.principal = child
-    
-                elif name in ("grant", "deny"):
-                    if self.allow is not None:
-                        raise ValueError(
-                            "Only one of DAV:grant or DAV:deny allowed in %s, got: %s"
-                            % (self.sname(), self.children)
-                        )
-                    self.allow      = (name == "grant")
-                    self.privileges = child.children
-    
-                elif name == "inherited":
-                    self.inherited = str(child.children[0])
-    
-                elif name == "protected":
-                    self.protected = True
-
-            my_children.append(child)
-
-        self.children = tuple(my_children)
-
-        if self.principal is None:
-            raise ValueError(
-                "One of DAV:principal or DAV:invert is required in %s, got: %s"
-                % (self.sname(), self.children)
-            )
-        assert self.invert is not None
-
-        if self.allow is None:
-            raise ValueError(
-                "One of DAV:grant or DAV:deny is required in %s, got: %s"
-                % (self.sname(), self.children)
-            )
-        assert self.privileges is not None
-
-
-# For DAV:principal element (RFC 3744, section 5.5.1) see Principal
-# class above.
-
-
-# For DAV:all element (RFC 3744, section 5.5.1) see All class above.
-
-
- at registerElement
- at registerElementClass
-class Authenticated (WebDAVEmptyElement):
-    """
-    Principal which matches authenticated users. (RFC 3744, section 5.5.1)
-    """
-    name = "authenticated"
-
-
- at registerElement
- at registerElementClass
-class Unauthenticated (WebDAVEmptyElement):
-    """
-    Principal which matches unauthenticated users. (RFC 3744, section 5.5.1)
-    """
-    name = "unauthenticated"
-
-
-# For DAV:property element (RFC 3744, section 5.5.1) see Property
-# class above.
-
-
- at registerElement
- at registerElementClass
-class Self (WebDAVEmptyElement):
-    """
-    Principal which matches a user if a resource is a principal and the user
-    matches the resource. (RFC 3744, sections 5.5.1 and 9.3)
-    """
-    name = "self"
-
-
- at registerElement
- at registerElementClass
-class Invert (WebDAVElement):
-    """
-    Principal which matches a user if the user does not match the principal
-    contained by this principal. (RFC 3744, section 5.5.1)
-    """
-    name = "invert"
-
-    allowed_children = { (dav_namespace, "principal"): (1, 1) }
-
-
- at registerElement
- at registerElementClass
-class Grant (WebDAVElement):
-    """
-    Grants the contained privileges to a principal. (RFC 3744, section 5.5.2)
-    """
-    name = "grant"
-
-    allowed_children = { (dav_namespace, "privilege"): (1, None) }
-
-
- at registerElement
- at registerElementClass
-class Deny (WebDAVElement):
-    """
-    Denies the contained privileges to a principal. (RFC 3744, section 5.5.2)
-    """
-    name = "deny"
-
-    allowed_children = { (dav_namespace, "privilege"): (1, None) }
-
-
-# For DAV:privilege element (RFC 3744, section 5.5.2) see Privilege
-# class above.
-
-
- at registerElement
- at registerElementClass
-class Protected (WebDAVEmptyElement):
-    """
-    Identifies an ACE as protected. (RFC 3744, section 5.5.3)
-    """
-    name = "protected"
-
-
- at registerElement
- at registerElementClass
-class Inherited (WebDAVElement):
-    """
-    Indicates that an ACE is inherited from the resource indentified by the
-    contained DAV:href element. (RFC 3744, section 5.5.4)
-    """
-    name = "inherited"
-
-    allowed_children = { (dav_namespace, "href"): (1, 1) }
-
-
- at registerElement
- at registerElementClass
-class ACLRestrictions (WebDAVElement):
-    """
-    Property which defines the types of ACLs supported by this server, to avoid
-    clients needlessly getting errors. (RFC 3744, section 5.6)
-    """
-    name = "acl-restrictions"
-    hidden = True
-    protected = True
-
-    allowed_children = {
-        (dav_namespace, "grant-only"        ): (0, 1),
-        (dav_namespace, "no-invert"         ): (0, 1),
-        (dav_namespace, "deny-before-grant" ): (0, 1),
-        (dav_namespace, "required-principal"): (0, 1),
-    }
-
-
- at registerElement
- at registerElementClass
-class GrantOnly (WebDAVEmptyElement):
-    """
-    Indicates that ACEs with deny clauses are not allowed. (RFC 3744, section
-    5.6.1)
-    """
-    name = "grant-only"
-
-
- at registerElement
- at registerElementClass
-class NoInvert (WebDAVEmptyElement):
-    """
-    Indicates that ACEs with the DAV:invert element are not allowed. (RFC 3744,
-    section 5.6.2)
-    """
-    name = "no-invert"
-
-
- at registerElement
- at registerElementClass
-class DenyBeforeGrant (WebDAVEmptyElement):
-    """
-    Indicates that all deny ACEs must precede all grant ACEs. (RFC 3744, section
-    5.6.3)
-    """
-    name = "deny-before-grant"
-
-
- at registerElement
- at registerElementClass
-class RequiredPrincipal (WebDAVElement):
-    """
-    Indicates which principals must have an ACE defined in an ACL. (RFC 3744,
-    section 5.6.4)
-    """
-    name = "required-principal"
-
-    allowed_children = {
-        (dav_namespace, "all"            ): (0, 1),
-        (dav_namespace, "authenticated"  ): (0, 1),
-        (dav_namespace, "unauthenticated"): (0, 1),
-        (dav_namespace, "self"           ): (0, 1),
-        (dav_namespace, "href"           ): (0, None),
-        (dav_namespace, "property"       ): (0, None),
-    }
-
-    def validate(self):
-        super(RequiredPrincipal, self).validate()
-
-        type = None
-
-        for child in self.children:
-            if type is None:
-                type = child.qname()
-            elif child.qname() != type:
-                raise ValueError(
-                    "Only one of DAV:all, DAV:authenticated, DAV:unauthenticated, "
-                    "DAV:self, DAV:href or DAV:property allowed for %s, got: %s"
-                    % (self.sname(), self.children)
-                )
-
-
- at registerElement
- at registerElementClass
-class InheritedACLSet (WebDAVElement):
-    """
-    Property which contains a set of URLs that identify other resources that
-    also control the access to this resource. (RFC 3744, section 5.7)
-    """
-    name = "inherited-acl-set"
-    hidden = True
-    protected = True
-
-    allowed_children = { (dav_namespace, "href"): (0, None) }
-
-
- at registerElement
- at registerElementClass
-class PrincipalCollectionSet (WebDAVElement):
-    """
-    Property which contains a set of URLs that identify the root collections
-    that contain the principals that are available on the server that implements
-    a resource. (RFC 3744, section 5.8)
-    """
-    name = "principal-collection-set"
-    hidden = True
-    protected = True
-
-    allowed_children = { (dav_namespace, "href"): (0, None) }
-
-
-##
-# Section 7 (Access Control and existing methods)
-##
-
- at registerElement
- at registerElementClass
-class NeedPrivileges (WebDAVElement):
-    """
-    Error which indicates insufficient privileges. (RFC 3744, section 7.1.1)
-    """
-    name = "need-privileges"
-
-    allowed_children = { (dav_namespace, "resource"): (0, None) }
-
-
- at registerElement
- at registerElementClass
-class Resource (WebDAVElement):
-    """
-    Identifies which resource had insufficient privileges. (RFC 3744, section
-    7.1.1)
-    """
-    name = "resource"
-
-    allowed_children = {
-        (dav_namespace, "href"     ): (1, 1),
-        (dav_namespace, "privilege"): (1, 1),
-    }
-
-
-##
-# Section 9 (Access Control Reports)
-##
-
- at registerElement
- at registerElementClass
-class ACLPrincipalPropSet (WebDAVElement):
-    """
-    Report which returns, for all principals in the DAV:acl property (of the
-    resource identified by the Request-URI) that are identified by http(s) URLs
-    or by a DAV:property principal, the value of the properties specified in the
-    REPORT request body. (RFC 3744, section 9.2)
-    """
-    name = "acl-principal-prop-set"
-
-    allowed_children = { WebDAVElement: (0, None) }
-
-    def validate(self):
-        super(ACLPrincipalPropSet, self).validate()
-
-        prop = False
-        
-        for child in self.children:
-            if child.qname() == (dav_namespace, "prop"):
-                if prop:
-                    raise ValueError(
-                        "Only one DAV:prop allowed for %s, got: %s"
-                        % (self.sname(), self.children)
-                    )
-                prop = True
-
-
- at registerElement
- at registerElementClass
-class PrincipalMatch (WebDAVElement):
-    """
-    Report used to identify all members (at any depth) of the collection
-    identified by the Request-URI that are principals and that match the current
-    user. (RFC 3744, section 9.3)
-    """
-    name = "principal-match"
-
-    allowed_children = {
-        (dav_namespace, "principal-property"): (0, 1),
-        (dav_namespace, "self"              ): (0, 1),
-        (dav_namespace, "prop"              ): (0, 1),
-    }
-
-    def validate(self):
-        super(PrincipalMatch, self).validate()
-
-        # This element can be empty when uses in supported-report-set
-        if not len(self.children):
-            return
-
-        principalPropertyOrSelf = False
-
-        for child in self.children:
-            namespace, name = child.qname()
-
-            if (namespace == dav_namespace) and name in ("principal-property", "self"):
-                if principalPropertyOrSelf:
-                    raise ValueError(
-                        "Only one of DAV:principal-property or DAV:self allowed in %s, got: %s"
-                        % (self.sname(), self.children)
-                    )
-                principalPropertyOrSelf = True
-
-        if not principalPropertyOrSelf:
-            raise ValueError(
-                "One of DAV:principal-property or DAV:self is required in %s, got: %s"
-                % (self.sname(), self.children)
-            )
-
-
- at registerElement
- at registerElementClass
-class PrincipalProperty (WebDAVElement):
-    """
-    Identifies a property. (RFC 3744, section 9.3)
-    """
-    name = "principal-property"
-
-    allowed_children = { WebDAVElement: (0, None) }
-
-
-# For DAV:self element (RFC 3744, section 9.3) see Self class above.
-
-
- at registerElement
- at registerElementClass
-class PrincipalPropertySearch (WebDAVElement):
-    """
-    Report which performs a search for all principals whose properties contain
-    character data that matches the search criteria specified in the request.
-    (RFC 3744, section 9.4)
-    """
-    name = "principal-property-search"
-
-    allowed_children = {
-        (dav_namespace, "property-search"                  ): (0, None),    # This is required but this element must be empty in supported-report-set
-        (dav_namespace, "prop"                             ): (0, 1),
-        (dav_namespace, "apply-to-principal-collection-set"): (0, 1),
-    }
-    allowed_attributes = { "test": False }
-
-
- at registerElement
- at registerElementClass
-class PropertySearch (WebDAVElement):
-    """
-    Contains a DAV:prop element enumerating the properties to be searched and a
-    DAV:match element, containing the search string. (RFC 3744, section 9.4)
-    """
-    name = "property-search"
-
-    allowed_children = {
-        (dav_namespace, "prop" ): (1, 1),
-        (dav_namespace, "match"): (1, 1),
-    }
-
-
- at registerElement
- at registerElementClass
-class Match (WebDAVTextElement):
-    """
-    Contains a search string. (RFC 3744, section 9.4)
-    """
-    name = "match"
-
-
- at registerElement
- at registerElementClass
-class PrincipalSearchPropertySet (WebDAVElement):
-    """
-    Report which identifies those properties that may be searched using the
-    DAV:principal-property-search report. (RFC 3744, section 9.5)
-    """
-    name = "principal-search-property-set"
-
-    allowed_children = { (dav_namespace, "principal-search-property"): (0, None) }
-
-
- at registerElement
- at registerElementClass
-class PrincipalSearchProperty (WebDAVElement):
-    """
-    Contains exactly one searchable property, and a description of the property.
-    (RFC 3744, section 9.5)
-    """
-    name = "principal-search-property"
-
-    allowed_children = {
-        (dav_namespace, "prop"       ): (1, 1),
-        (dav_namespace, "description"): (1, 1),
-    }
-
-
- at registerElement
- at registerElementClass
-class NumberOfMatchesWithinLimits (WebDAVEmptyElement):
-    """
-    Error which indicates too many results
-    """
-    name = "number-of-matches-within-limits"
-
-
-# For DAV:description element (RFC 3744, section 9.5) see Description
-# class above.

Copied: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc3744.py (from rev 8919, CalendarServer/trunk/txdav/xml/rfc3744.py)
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc3744.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc3744.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -0,0 +1,932 @@
+##
+# Copyright (c) 2005-2012 Apple Computer, Inc. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+##
+
+"""
+RFC 3744 (WebDAV Access Control Protocol) XML Elements
+
+This module provides XML element definitions for use with WebDAV.
+
+See RFC 3744: http://www.ietf.org/rfc/rfc3744.txt
+"""
+
+__all__ = []
+
+
+from txdav.xml.base import WebDAVElement, PCDATAElement
+from txdav.xml.base import WebDAVEmptyElement, WebDAVTextElement
+from txdav.xml.element import dav_namespace, registerElement, registerElementClass
+
+
+##
+# Section 3 (Privileges)
+##
+
+ at registerElement
+ at registerElementClass
+class Read (WebDAVEmptyElement):
+    """
+    Privilege which controls methods that return information about the state
+    of a resource, including the resource's properties. (RFC 3744, section
+    3.1)
+    """
+    name = "read"
+
+
+# For DAV:write element (RFC 3744, section 3.2) see Write class in
+# rfc2518.py.
+
+
+ at registerElement
+ at registerElementClass
+class WriteProperties (WebDAVEmptyElement):
+    """
+    Privilege which controls methods that modify the dead properties of a
+    resource. (RFC 3744, section 3.3)
+    """
+    name = "write-properties"
+
+
+ at registerElement
+ at registerElementClass
+class WriteContent (WebDAVEmptyElement):
+    """
+    Privilege which controls methods that modify the content of an existing
+    resource. (RFC 3744, section 3.4)
+    """
+    name = "write-content"
+
+
+ at registerElement
+ at registerElementClass
+class Unlock (WebDAVEmptyElement):
+    """
+    Privilege which controls the use of the UNLOCK method by a principal other
+    than the lock owner. (RFC 3744, section 3.5)
+    """
+    name = "unlock"
+
+
+ at registerElement
+ at registerElementClass
+class ReadACL (WebDAVEmptyElement):
+    """
+    Privilege which controls the use of the PROPFIND method to retrieve the
+    DAV:acl property of a resource. (RFC 3744, section 3.6)
+    """
+    name = "read-acl"
+
+
+ at registerElement
+ at registerElementClass
+class ReadCurrentUserPrivilegeSet (WebDAVEmptyElement):
+    """
+    Privilege which controls the use of the PROPFIND method to retrieve the
+    DAV:current-user-privilege-set property of a resource. (RFC 3744, section
+    3.7)
+    """
+    name = "read-current-user-privilege-set"
+
+
+ at registerElement
+ at registerElementClass
+class WriteACL (WebDAVEmptyElement):
+    """
+    Privilege which controls the use of the ACL method to modify the DAV:acl
+    property of a resource. (RFC 3744, section 3.8)
+    """
+    name = "write-acl"
+
+
+ at registerElement
+ at registerElementClass
+class Bind (WebDAVEmptyElement):
+    """
+    Privilege which allows a method to add a new member URL from the a
+    collection resource. (RFC 3744, section 3.9)
+    """
+    name = "bind"
+
+
+ at registerElement
+ at registerElementClass
+class Unbind (WebDAVEmptyElement):
+    """
+    Privilege which allows a method to remove a member URL from the a collection
+    resource. (RFC 3744, section 3.10)
+    """
+    name = "unbind"
+
+
+ at registerElement
+ at registerElementClass
+class All (WebDAVEmptyElement):
+    """
+    Aggregate privilege that contains the entire set of privileges that can be
+    applied to a resource. (RFC 3744, section 3.11)
+    Principal which matches all users. (RFC 3744, section 5.5.1)
+    """
+    name = "all"
+
+
+##
+# Section 4 (Principal Properties)
+##
+
+ at registerElement
+ at registerElementClass
+class Principal (WebDAVElement):
+    """
+    Indicates a principal resource type. (RFC 3744, section 4)
+    Identifies the principal to which an ACE applies. (RFC 3744, section 5.5.1)
+    """
+    name = "principal"
+
+    allowed_children = {
+        (dav_namespace, "href"           ): (0, 1),
+        (dav_namespace, "all"            ): (0, 1),
+        (dav_namespace, "authenticated"  ): (0, 1),
+        (dav_namespace, "unauthenticated"): (0, 1),
+        (dav_namespace, "property"       ): (0, 1),
+        (dav_namespace, "self"           ): (0, 1),
+    }
+
+    def validate(self):
+        super(Principal, self).validate()
+
+        if len(self.children) > 1:
+            raise ValueError(
+                "Exactly one of DAV:href, DAV:all, DAV:authenticated, "
+                "DAV:unauthenticated, DAV:property or DAV:self is required for "
+                "%s, got: %r"
+                % (self.sname(), self.children)
+            )
+
+
+ at registerElement
+ at registerElementClass
+class AlternateURISet (WebDAVElement):
+    """
+    Property which contains the URIs of network resources with additional
+    descriptive information about the principal. (RFC 3744, section 4.1)
+    """
+    name = "alternate-URI-set"
+    hidden = True
+    protected = True
+
+    allowed_children = { (dav_namespace, "href"): (0, None) }
+
+
+ at registerElement
+ at registerElementClass
+class PrincipalURL (WebDAVElement):
+    """
+    Property which contains the URL that must be used to identify this principal
+    in an ACL request. (RFC 3744, section 4.2)
+    """
+    name = "principal-URL"
+    hidden = True
+    protected = True
+
+    allowed_children = { (dav_namespace, "href"): (0, 1) }
+
+
+ at registerElement
+ at registerElementClass
+class GroupMemberSet (WebDAVElement):
+    """
+    Property which identifies the principals that are direct members of a group
+    principal.
+    (RFC 3744, section 4.3)
+    """
+    name = "group-member-set"
+    hidden = True
+
+    allowed_children = { (dav_namespace, "href"): (0, None) }
+
+
+ at registerElement
+ at registerElementClass
+class GroupMembership (WebDAVElement):
+    """
+    Property which identifies the group principals in which a principal is
+    directly a member. (RFC 3744, section 4.4)
+    """
+    name = "group-membership"
+    hidden = True
+    protected = True
+
+    allowed_children = { (dav_namespace, "href"): (0, None) }
+
+
+##
+# Section 5 (Access Control Properties)
+##
+
+# For DAV:owner element (RFC 3744, section 5.1) see Owner class in
+# rfc2518.py.
+
+
+ at registerElement
+ at registerElementClass
+class Group (WebDAVElement):
+    """
+    Property which identifies a particular principal as being the group
+    principal of a resource. (RFC 3744, section 5.2)
+    """
+    name = "group"
+    hidden = True
+    protected = True # may be protected, per RFC 3744, section 5.2
+
+    allowed_children = { (dav_namespace, "href"): (0, 1) }
+
+
+ at registerElement
+ at registerElementClass
+class SupportedPrivilegeSet (WebDAVElement):
+    """
+    Property which identifies the privileges defined for a resource. (RFC 3744,
+    section 5.3)
+    """
+    name = "supported-privilege-set"
+    hidden = True
+    protected = True
+
+    allowed_children = { (dav_namespace, "supported-privilege"): (0, None) }
+
+
+ at registerElement
+ at registerElementClass
+class SupportedPrivilege (WebDAVElement):
+    """
+    Identifies a privilege defined for a resource. (RFC 3744, section 5.3)
+    """
+    name = "supported-privilege"
+
+    allowed_children = {
+        (dav_namespace, "privilege"          ): (1, 1),
+        (dav_namespace, "abstract"           ): (0, 1),
+        (dav_namespace, "description"        ): (1, 1),
+        (dav_namespace, "supported-privilege"): (0, None),
+    }
+
+
+ at registerElement
+ at registerElementClass
+class Privilege (WebDAVElement):
+    """
+    Identifies a privilege. (RFC 3744, sections 5.3 and 5.5.1)
+    """
+    name = "privilege"
+
+    allowed_children = { WebDAVElement: (0, None) }
+
+    def isAggregateOf(self, subprivilege, supportedPrivileges):
+        """
+        Check whether this privilege is an aggregate of another.
+        @param subprivilege: a L{Privilege}
+        @param supportedPrivileges: a L{SupportedPrivilegeSet}
+        @return: C{True} is this privilege is an aggregate of C{subprivilege}
+            according to C{supportedPrivileges}.
+        """
+        # DAV: all is an aggregate of all privileges
+        if len(self.children) == 1 and self.children[0].qname() == (dav_namespace, "all"):
+            return True
+
+        def isAggregate(supportedPrivilege):
+            sp = supportedPrivilege.childOfType(Privilege)
+
+            if sp == self:
+                def find(supportedPrivilege):
+                    if supportedPrivilege.childOfType(Privilege) == subprivilege:
+                        return True
+
+                    for child in supportedPrivilege.childrenOfType(SupportedPrivilege):
+                        if find(child):
+                            return True
+                    else:
+                        return False
+
+                return find(supportedPrivilege)
+            else:
+                for child in supportedPrivilege.childrenOfType(SupportedPrivilege):
+                    if isAggregate(child):
+                        return True
+                else:
+                    return False
+
+        for supportedPrivilege in supportedPrivileges.children:
+            if isAggregate(supportedPrivilege):
+                return True
+        else:
+            return False
+
+    def expandAggregate(self, supportedPrivileges):
+        """
+        Expand this privilege into the set of privileges aggregated under it
+        based on the structure of the given supported privileges. If this
+        privilege is not an aggregate, just return it as-is.
+        @param supportedPrivileges: a L{SupportedPrivilegeSet}
+        @return: the list of expanded L{Privileges}
+        """
+
+        # Find ourselves in supported privileges
+        def find(supportedPrivilege):
+            """
+            Find the supportPrivilege which matches this privilege.
+            """
+            if supportedPrivilege.childOfType(Privilege) == self:
+                return supportedPrivilege
+
+            for child in supportedPrivilege.childrenOfType(SupportedPrivilege):
+                result = find(child)
+                if result is not None:
+                    return result
+            else:
+                return None
+
+        for supportedPrivilege in supportedPrivileges.children:
+            result = find(supportedPrivilege)
+            if result is not None:
+                break
+        else:
+            return [self]
+
+        # Now add sub-privileges recursively
+        aggregates = []
+        def add(supportedPrivilege):
+            """
+            Add all sub-privileges to the list.
+            """
+            aggregates.append(supportedPrivilege.childOfType(Privilege))
+            for child in supportedPrivilege.childrenOfType(SupportedPrivilege):
+                add(child)
+        add(result)
+
+        return aggregates
+
+
+ at registerElement
+ at registerElementClass
+class Abstract (WebDAVElement):
+    """
+    Identifies a privilege as abstract. (RFC 3744, section 5.3)
+    """
+    name = "abstract"
+
+
+ at registerElement
+ at registerElementClass
+class Description (WebDAVTextElement):
+    """
+    A human-readable description of what privilege controls access to. (RFC
+    3744, sections 5.3 and 9.5)
+    """
+    name = "description"
+    allowed_attributes = { "xml:lang": True }
+
+
+ at registerElement
+ at registerElementClass
+class CurrentUserPrivilegeSet (WebDAVElement):
+    """
+    Property which contains the exact set of privileges (as computer by the
+    server) granted to the currently authenticated HTTP user. (RFC 3744, section
+    5.4)
+    """
+    name = "current-user-privilege-set"
+    hidden = True
+    protected = True
+
+    allowed_children = { (dav_namespace, "privilege"): (0, None) }
+
+
+# For DAV:privilege element (RFC 3744, section 5.4) see Privilege class above.
+
+
+ at registerElement
+ at registerElementClass
+class ACL (WebDAVElement):
+    """
+    Property which specifies the list of access control entries which define
+    what privileges are granted to which users for a resource. (RFC 3744,
+    section 5.5)
+    """
+    name = "acl"
+    hidden = True
+    protected = True
+
+    allowed_children = { (dav_namespace, "ace"): (0, None) }
+
+
+ at registerElement
+ at registerElementClass
+class ACE (WebDAVElement):
+    """
+    Specifies the list of access control entries which define what privileges
+    are granted to which users for a resource. (RFC 3744, section 5.5)
+    """
+    name = "ace"
+
+    allowed_children = {
+        (dav_namespace, "principal"): (0, 1),
+        (dav_namespace, "invert"   ): (0, 1),
+        (dav_namespace, "grant"    ): (0, 1),
+        (dav_namespace, "deny"     ): (0, 1),
+        (dav_namespace, "protected"): (0, 1),
+        (dav_namespace, "inherited"): (0, 1),
+    }
+
+    def __init__(self, *children, **attributes):
+        super(ACE, self).__init__(*children, **attributes)
+
+        self.principal  = None
+        self.invert     = None
+        self.allow      = None
+        self.privileges = None
+        self.inherited  = None
+        self.protected  = False
+
+        my_children = []
+
+        for child in self.children:
+            namespace, name = child.qname()
+
+            if isinstance(child, PCDATAElement):
+                continue
+
+            if (namespace == dav_namespace):
+                if name in ("principal", "invert"):
+                    if self.principal is not None:
+                        raise ValueError(
+                            "Only one of DAV:principal or DAV:invert allowed in %s, got: %s"
+                            % (self.sname(), self.children)
+                        )
+                    if name == "invert":
+                        self.invert    = True
+                        self.principal = child.children[0]
+                    else:
+                        self.invert    = False
+                        self.principal = child
+    
+                elif name in ("grant", "deny"):
+                    if self.allow is not None:
+                        raise ValueError(
+                            "Only one of DAV:grant or DAV:deny allowed in %s, got: %s"
+                            % (self.sname(), self.children)
+                        )
+                    self.allow      = (name == "grant")
+                    self.privileges = child.children
+    
+                elif name == "inherited":
+                    self.inherited = str(child.children[0])
+    
+                elif name == "protected":
+                    self.protected = True
+
+            my_children.append(child)
+
+        self.children = tuple(my_children)
+
+        if self.principal is None:
+            raise ValueError(
+                "One of DAV:principal or DAV:invert is required in %s, got: %s"
+                % (self.sname(), self.children)
+            )
+        assert self.invert is not None
+
+        if self.allow is None:
+            raise ValueError(
+                "One of DAV:grant or DAV:deny is required in %s, got: %s"
+                % (self.sname(), self.children)
+            )
+        assert self.privileges is not None
+
+
+# For DAV:principal element (RFC 3744, section 5.5.1) see Principal
+# class above.
+
+
+# For DAV:all element (RFC 3744, section 5.5.1) see All class above.
+
+
+ at registerElement
+ at registerElementClass
+class Authenticated (WebDAVEmptyElement):
+    """
+    Principal which matches authenticated users. (RFC 3744, section 5.5.1)
+    """
+    name = "authenticated"
+
+
+ at registerElement
+ at registerElementClass
+class Unauthenticated (WebDAVEmptyElement):
+    """
+    Principal which matches unauthenticated users. (RFC 3744, section 5.5.1)
+    """
+    name = "unauthenticated"
+
+
+# For DAV:property element (RFC 3744, section 5.5.1) see Property
+# class above.
+
+
+ at registerElement
+ at registerElementClass
+class Self (WebDAVEmptyElement):
+    """
+    Principal which matches a user if a resource is a principal and the user
+    matches the resource. (RFC 3744, sections 5.5.1 and 9.3)
+    """
+    name = "self"
+
+
+ at registerElement
+ at registerElementClass
+class Invert (WebDAVElement):
+    """
+    Principal which matches a user if the user does not match the principal
+    contained by this principal. (RFC 3744, section 5.5.1)
+    """
+    name = "invert"
+
+    allowed_children = { (dav_namespace, "principal"): (1, 1) }
+
+
+ at registerElement
+ at registerElementClass
+class Grant (WebDAVElement):
+    """
+    Grants the contained privileges to a principal. (RFC 3744, section 5.5.2)
+    """
+    name = "grant"
+
+    allowed_children = { (dav_namespace, "privilege"): (1, None) }
+
+
+ at registerElement
+ at registerElementClass
+class Deny (WebDAVElement):
+    """
+    Denies the contained privileges to a principal. (RFC 3744, section 5.5.2)
+    """
+    name = "deny"
+
+    allowed_children = { (dav_namespace, "privilege"): (1, None) }
+
+
+# For DAV:privilege element (RFC 3744, section 5.5.2) see Privilege
+# class above.
+
+
+ at registerElement
+ at registerElementClass
+class Protected (WebDAVEmptyElement):
+    """
+    Identifies an ACE as protected. (RFC 3744, section 5.5.3)
+    """
+    name = "protected"
+
+
+ at registerElement
+ at registerElementClass
+class Inherited (WebDAVElement):
+    """
+    Indicates that an ACE is inherited from the resource indentified by the
+    contained DAV:href element. (RFC 3744, section 5.5.4)
+    """
+    name = "inherited"
+
+    allowed_children = { (dav_namespace, "href"): (1, 1) }
+
+
+ at registerElement
+ at registerElementClass
+class ACLRestrictions (WebDAVElement):
+    """
+    Property which defines the types of ACLs supported by this server, to avoid
+    clients needlessly getting errors. (RFC 3744, section 5.6)
+    """
+    name = "acl-restrictions"
+    hidden = True
+    protected = True
+
+    allowed_children = {
+        (dav_namespace, "grant-only"        ): (0, 1),
+        (dav_namespace, "no-invert"         ): (0, 1),
+        (dav_namespace, "deny-before-grant" ): (0, 1),
+        (dav_namespace, "required-principal"): (0, 1),
+    }
+
+
+ at registerElement
+ at registerElementClass
+class GrantOnly (WebDAVEmptyElement):
+    """
+    Indicates that ACEs with deny clauses are not allowed. (RFC 3744, section
+    5.6.1)
+    """
+    name = "grant-only"
+
+
+ at registerElement
+ at registerElementClass
+class NoInvert (WebDAVEmptyElement):
+    """
+    Indicates that ACEs with the DAV:invert element are not allowed. (RFC 3744,
+    section 5.6.2)
+    """
+    name = "no-invert"
+
+
+ at registerElement
+ at registerElementClass
+class DenyBeforeGrant (WebDAVEmptyElement):
+    """
+    Indicates that all deny ACEs must precede all grant ACEs. (RFC 3744, section
+    5.6.3)
+    """
+    name = "deny-before-grant"
+
+
+ at registerElement
+ at registerElementClass
+class RequiredPrincipal (WebDAVElement):
+    """
+    Indicates which principals must have an ACE defined in an ACL. (RFC 3744,
+    section 5.6.4)
+    """
+    name = "required-principal"
+
+    allowed_children = {
+        (dav_namespace, "all"            ): (0, 1),
+        (dav_namespace, "authenticated"  ): (0, 1),
+        (dav_namespace, "unauthenticated"): (0, 1),
+        (dav_namespace, "self"           ): (0, 1),
+        (dav_namespace, "href"           ): (0, None),
+        (dav_namespace, "property"       ): (0, None),
+    }
+
+    def validate(self):
+        super(RequiredPrincipal, self).validate()
+
+        type = None
+
+        for child in self.children:
+            if type is None:
+                type = child.qname()
+            elif child.qname() != type:
+                raise ValueError(
+                    "Only one of DAV:all, DAV:authenticated, DAV:unauthenticated, "
+                    "DAV:self, DAV:href or DAV:property allowed for %s, got: %s"
+                    % (self.sname(), self.children)
+                )
+
+
+ at registerElement
+ at registerElementClass
+class InheritedACLSet (WebDAVElement):
+    """
+    Property which contains a set of URLs that identify other resources that
+    also control the access to this resource. (RFC 3744, section 5.7)
+    """
+    name = "inherited-acl-set"
+    hidden = True
+    protected = True
+
+    allowed_children = { (dav_namespace, "href"): (0, None) }
+
+
+ at registerElement
+ at registerElementClass
+class PrincipalCollectionSet (WebDAVElement):
+    """
+    Property which contains a set of URLs that identify the root collections
+    that contain the principals that are available on the server that implements
+    a resource. (RFC 3744, section 5.8)
+    """
+    name = "principal-collection-set"
+    hidden = True
+    protected = True
+
+    allowed_children = { (dav_namespace, "href"): (0, None) }
+
+
+##
+# Section 7 (Access Control and existing methods)
+##
+
+ at registerElement
+ at registerElementClass
+class NeedPrivileges (WebDAVElement):
+    """
+    Error which indicates insufficient privileges. (RFC 3744, section 7.1.1)
+    """
+    name = "need-privileges"
+
+    allowed_children = { (dav_namespace, "resource"): (0, None) }
+
+
+ at registerElement
+ at registerElementClass
+class Resource (WebDAVElement):
+    """
+    Identifies which resource had insufficient privileges. (RFC 3744, section
+    7.1.1)
+    """
+    name = "resource"
+
+    allowed_children = {
+        (dav_namespace, "href"     ): (1, 1),
+        (dav_namespace, "privilege"): (1, 1),
+    }
+
+
+##
+# Section 9 (Access Control Reports)
+##
+
+ at registerElement
+ at registerElementClass
+class ACLPrincipalPropSet (WebDAVElement):
+    """
+    Report which returns, for all principals in the DAV:acl property (of the
+    resource identified by the Request-URI) that are identified by http(s) URLs
+    or by a DAV:property principal, the value of the properties specified in the
+    REPORT request body. (RFC 3744, section 9.2)
+    """
+    name = "acl-principal-prop-set"
+
+    allowed_children = { WebDAVElement: (0, None) }
+
+    def validate(self):
+        super(ACLPrincipalPropSet, self).validate()
+
+        prop = False
+        
+        for child in self.children:
+            if child.qname() == (dav_namespace, "prop"):
+                if prop:
+                    raise ValueError(
+                        "Only one DAV:prop allowed for %s, got: %s"
+                        % (self.sname(), self.children)
+                    )
+                prop = True
+
+
+ at registerElement
+ at registerElementClass
+class PrincipalMatch (WebDAVElement):
+    """
+    Report used to identify all members (at any depth) of the collection
+    identified by the Request-URI that are principals and that match the current
+    user. (RFC 3744, section 9.3)
+    """
+    name = "principal-match"
+
+    allowed_children = {
+        (dav_namespace, "principal-property"): (0, 1),
+        (dav_namespace, "self"              ): (0, 1),
+        (dav_namespace, "prop"              ): (0, 1),
+    }
+
+    def validate(self):
+        super(PrincipalMatch, self).validate()
+
+        # This element can be empty when uses in supported-report-set
+        if not len(self.children):
+            return
+
+        principalPropertyOrSelf = False
+
+        for child in self.children:
+            namespace, name = child.qname()
+
+            if (namespace == dav_namespace) and name in ("principal-property", "self"):
+                if principalPropertyOrSelf:
+                    raise ValueError(
+                        "Only one of DAV:principal-property or DAV:self allowed in %s, got: %s"
+                        % (self.sname(), self.children)
+                    )
+                principalPropertyOrSelf = True
+
+        if not principalPropertyOrSelf:
+            raise ValueError(
+                "One of DAV:principal-property or DAV:self is required in %s, got: %s"
+                % (self.sname(), self.children)
+            )
+
+
+ at registerElement
+ at registerElementClass
+class PrincipalProperty (WebDAVElement):
+    """
+    Identifies a property. (RFC 3744, section 9.3)
+    """
+    name = "principal-property"
+
+    allowed_children = { WebDAVElement: (0, None) }
+
+
+# For DAV:self element (RFC 3744, section 9.3) see Self class above.
+
+
+ at registerElement
+ at registerElementClass
+class PrincipalPropertySearch (WebDAVElement):
+    """
+    Report which performs a search for all principals whose properties contain
+    character data that matches the search criteria specified in the request.
+    (RFC 3744, section 9.4)
+    """
+    name = "principal-property-search"
+
+    allowed_children = {
+        (dav_namespace, "property-search"                  ): (0, None),    # This is required but this element must be empty in supported-report-set
+        (dav_namespace, "prop"                             ): (0, 1),
+        (dav_namespace, "apply-to-principal-collection-set"): (0, 1),
+    }
+    allowed_attributes = { "test": False }
+
+
+ at registerElement
+ at registerElementClass
+class PropertySearch (WebDAVElement):
+    """
+    Contains a DAV:prop element enumerating the properties to be searched and a
+    DAV:match element, containing the search string. (RFC 3744, section 9.4)
+    """
+    name = "property-search"
+
+    allowed_children = {
+        (dav_namespace, "prop" ): (1, 1),
+        (dav_namespace, "match"): (1, 1),
+    }
+
+
+ at registerElement
+ at registerElementClass
+class Match (WebDAVTextElement):
+    """
+    Contains a search string. (RFC 3744, section 9.4)
+    """
+    name = "match"
+
+
+ at registerElement
+ at registerElementClass
+class PrincipalSearchPropertySet (WebDAVElement):
+    """
+    Report which identifies those properties that may be searched using the
+    DAV:principal-property-search report. (RFC 3744, section 9.5)
+    """
+    name = "principal-search-property-set"
+
+    allowed_children = { (dav_namespace, "principal-search-property"): (0, None) }
+
+
+ at registerElement
+ at registerElementClass
+class PrincipalSearchProperty (WebDAVElement):
+    """
+    Contains exactly one searchable property, and a description of the property.
+    (RFC 3744, section 9.5)
+    """
+    name = "principal-search-property"
+
+    allowed_children = {
+        (dav_namespace, "prop"       ): (1, 1),
+        (dav_namespace, "description"): (1, 1),
+    }
+
+
+ at registerElement
+ at registerElementClass
+class NumberOfMatchesWithinLimits (WebDAVEmptyElement):
+    """
+    Error which indicates too many results
+    """
+    name = "number-of-matches-within-limits"
+
+
+# For DAV:description element (RFC 3744, section 9.5) see Description
+# class above.

Deleted: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc4331.py
===================================================================
--- CalendarServer/trunk/txdav/xml/rfc4331.py	2012-03-22 00:02:25 UTC (rev 8919)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc4331.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -1,63 +0,0 @@
-##
-# Copyright (c) 2005-2007 Apple Inc. All rights reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-# 
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-# 
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-##
-
-"""
-RFC 4331 (Quota and Size Properties for WebDAV Collections) XML Elements
-
-This module provides XML element definitions for use with WebDAV.
-
-See RFC 4331: http://www.ietf.org/rfc/rfc4331.txt
-"""
-
-__all__ = []
-
-
-from txdav.xml.base import WebDAVTextElement
-from txdav.xml.element import registerElement, registerElementClass
-
-
-##
-# Section 3 & 4 (Quota Properties)
-##
-
- at registerElement
- at registerElementClass
-class QuotaAvailableBytes (WebDAVTextElement):
-    """
-    Property which contains the the number of bytes available under the
-    current quota to store data in a collection (RFC 4331, section 3)
-    """
-    name = "quota-available-bytes"
-    hidden = True
-    protected = True
-
-
- at registerElement
- at registerElementClass
-class QuotaUsedBytes (WebDAVTextElement):
-    """
-    Property which contains the the number of bytes used under the
-    current quota to store data in a collection (RFC 4331, section 4)
-    """
-    name = "quota-used-bytes"
-    hidden = True
-    protected = True

Copied: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc4331.py (from rev 8919, CalendarServer/trunk/txdav/xml/rfc4331.py)
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc4331.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc4331.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -0,0 +1,63 @@
+##
+# Copyright (c) 2005-2007 Apple Inc. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+##
+
+"""
+RFC 4331 (Quota and Size Properties for WebDAV Collections) XML Elements
+
+This module provides XML element definitions for use with WebDAV.
+
+See RFC 4331: http://www.ietf.org/rfc/rfc4331.txt
+"""
+
+__all__ = []
+
+
+from txdav.xml.base import WebDAVTextElement
+from txdav.xml.element import registerElement, registerElementClass
+
+
+##
+# Section 3 & 4 (Quota Properties)
+##
+
+ at registerElement
+ at registerElementClass
+class QuotaAvailableBytes (WebDAVTextElement):
+    """
+    Property which contains the the number of bytes available under the
+    current quota to store data in a collection (RFC 4331, section 3)
+    """
+    name = "quota-available-bytes"
+    hidden = True
+    protected = True
+
+
+ at registerElement
+ at registerElementClass
+class QuotaUsedBytes (WebDAVTextElement):
+    """
+    Property which contains the the number of bytes used under the
+    current quota to store data in a collection (RFC 4331, section 4)
+    """
+    name = "quota-used-bytes"
+    hidden = True
+    protected = True

Deleted: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc5397.py
===================================================================
--- CalendarServer/trunk/txdav/xml/rfc5397.py	2012-03-22 00:02:25 UTC (rev 8919)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc5397.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -1,50 +0,0 @@
-##
-# Copyright (c) 2009-2012 Apple Computer, Inc. All rights reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-# 
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-# 
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-##
-
-"""
-RFC 5397 (WebDAV Current Principal Extension) XML Elements
-
-This module provides XML element definitions for use with the
-DAV:current-user-principal property.
-
-See RFC 5397: http://www.ietf.org/rfc/rfc5397.txt
-"""
-
-__all__ = []
-
-
-from txdav.xml.base import WebDAVElement, dav_namespace
-from txdav.xml.element import registerElement, registerElementClass
-
-
- at registerElement
- at registerElementClass
-class CurrentUserPrincipal(WebDAVElement):
-    """
-    Current principal information
-    """
-    name = "current-user-principal"
-
-    allowed_children = {
-        (dav_namespace, "href")            : (0, 1),
-        (dav_namespace, "unauthenticated") : (0, 1),
-    }

Copied: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc5397.py (from rev 8919, CalendarServer/trunk/txdav/xml/rfc5397.py)
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc5397.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc5397.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -0,0 +1,50 @@
+##
+# Copyright (c) 2009-2012 Apple Computer, Inc. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+##
+
+"""
+RFC 5397 (WebDAV Current Principal Extension) XML Elements
+
+This module provides XML element definitions for use with the
+DAV:current-user-principal property.
+
+See RFC 5397: http://www.ietf.org/rfc/rfc5397.txt
+"""
+
+__all__ = []
+
+
+from txdav.xml.base import WebDAVElement, dav_namespace
+from txdav.xml.element import registerElement, registerElementClass
+
+
+ at registerElement
+ at registerElementClass
+class CurrentUserPrincipal(WebDAVElement):
+    """
+    Current principal information
+    """
+    name = "current-user-principal"
+
+    allowed_children = {
+        (dav_namespace, "href")            : (0, 1),
+        (dav_namespace, "unauthenticated") : (0, 1),
+    }

Deleted: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc5842.py
===================================================================
--- CalendarServer/trunk/txdav/xml/rfc5842.py	2012-03-22 00:02:25 UTC (rev 8919)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc5842.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -1,158 +0,0 @@
-##
-# Copyright (c) 2005-2012 Apple Inc. All rights reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-# 
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-# 
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-##
-
-"""
-RFC 5842 (Binding Extensions to WebDAV) XML Elements
-
-This module provides XML element definitions for use with WebDAV.
-
-See RFC 5842: http://www.ietf.org/rfc/rfc5842.txt
-"""
-
-__all__ = []
-
-
-from txdav.xml.base import WebDAVTextElement, WebDAVElement
-from txdav.xml.element import dav_namespace, registerElement, registerElementClass
-
-
- at registerElement
- at registerElementClass
-class ResourceID (WebDAVElement):
-    """
-    Unique identifier for a resource
-    """
-    name = "resource-id"
-    hidden = True
-    protected = True
-
-    allowed_children = { (dav_namespace, "href"): (0, 1) }
-
-
- at registerElement
- at registerElementClass
-class ParentSet (WebDAVElement):
-    """
-    Identifies other bindings to a resource
-    """
-    name = "parent-set"
-    hidden = True
-    protected = True
-
-    allowed_children = { (dav_namespace, "parent"): (0, 1) }
-
-
- at registerElement
- at registerElementClass
-class Parent (WebDAVElement):
-
-    name = "parent"
-
-    allowed_children = {
-        (dav_namespace, "href")    : (1, 1),
-        (dav_namespace, "segment") : (1, 1),
-    }
-
-
- at registerElement
- at registerElementClass
-class Segment (WebDAVTextElement):
-
-    name = "segment"
-
-
-# Problem: DAV:bind is also defined in RFC3744 but with our XML element parsing/mapping behavior
-# we are not allowed to have two class with the same qname(). So we are stuck.
-#
-# FIXME: redefine bind in rfc3744.py (with a note) to allow
-# sub-elements and so that can extend it here.
-
-
-#@registerElement
-#@registerElementClass
-#class BindResponse (WebDAVElement):
-#    """
-#    Response body for a BIND request
-#    """
-#
-#    name = "bind-response"
-#
-#    allowed_children = {
-#        # ANY
-#    }
-#
-#
-#@registerElement
-#@registerElementClass
-#class UnbindRequest (WebDAVElement):
-#    """
-#    Request body for a UNBIND request
-#    """
-#
-#    name = "unbind"
-#
-#    allowed_children = {
-#        (dav_namespace, "segment") : (1, 1),
-#    }
-#
-#
-#@registerElement
-#@registerElementClass
-#class Unbind (WebDAVElement):
-#    """
-#    Response body for a UNBIND request
-#    """
-#
-#    name = "unbind-response"
-#
-#    allowed_children = {
-#        # ANY
-#    }
-#
-#
-#@registerElement
-#@registerElementClass
-#class RebindRequest (WebDAVElement):
-#    """
-#    Request body for a REBIND request
-#    """
-#
-#    name = "rebind"
-#
-#    allowed_children = {
-#        (dav_namespace, "segment") : (1, 1),
-#        (dav_namespace, "href")    : (1, 1),
-#    }
-#
-#
-#@registerElement
-#@registerElementClass
-#class Rebind (WebDAVElement):
-#    """
-#    Response body for a UNBIND request
-#    """
-#
-#    name = "rebind-response"
-#
-#    allowed_children = {
-#        # ANY
-#    }

Copied: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc5842.py (from rev 8919, CalendarServer/trunk/txdav/xml/rfc5842.py)
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc5842.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc5842.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -0,0 +1,158 @@
+##
+# Copyright (c) 2005-2012 Apple Inc. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+##
+
+"""
+RFC 5842 (Binding Extensions to WebDAV) XML Elements
+
+This module provides XML element definitions for use with WebDAV.
+
+See RFC 5842: http://www.ietf.org/rfc/rfc5842.txt
+"""
+
+__all__ = []
+
+
+from txdav.xml.base import WebDAVTextElement, WebDAVElement
+from txdav.xml.element import dav_namespace, registerElement, registerElementClass
+
+
+ at registerElement
+ at registerElementClass
+class ResourceID (WebDAVElement):
+    """
+    Unique identifier for a resource
+    """
+    name = "resource-id"
+    hidden = True
+    protected = True
+
+    allowed_children = { (dav_namespace, "href"): (0, 1) }
+
+
+ at registerElement
+ at registerElementClass
+class ParentSet (WebDAVElement):
+    """
+    Identifies other bindings to a resource
+    """
+    name = "parent-set"
+    hidden = True
+    protected = True
+
+    allowed_children = { (dav_namespace, "parent"): (0, 1) }
+
+
+ at registerElement
+ at registerElementClass
+class Parent (WebDAVElement):
+
+    name = "parent"
+
+    allowed_children = {
+        (dav_namespace, "href")    : (1, 1),
+        (dav_namespace, "segment") : (1, 1),
+    }
+
+
+ at registerElement
+ at registerElementClass
+class Segment (WebDAVTextElement):
+
+    name = "segment"
+
+
+# Problem: DAV:bind is also defined in RFC3744 but with our XML element parsing/mapping behavior
+# we are not allowed to have two class with the same qname(). So we are stuck.
+#
+# FIXME: redefine bind in rfc3744.py (with a note) to allow
+# sub-elements and so that can extend it here.
+
+
+#@registerElement
+#@registerElementClass
+#class BindResponse (WebDAVElement):
+#    """
+#    Response body for a BIND request
+#    """
+#
+#    name = "bind-response"
+#
+#    allowed_children = {
+#        # ANY
+#    }
+#
+#
+#@registerElement
+#@registerElementClass
+#class UnbindRequest (WebDAVElement):
+#    """
+#    Request body for a UNBIND request
+#    """
+#
+#    name = "unbind"
+#
+#    allowed_children = {
+#        (dav_namespace, "segment") : (1, 1),
+#    }
+#
+#
+#@registerElement
+#@registerElementClass
+#class Unbind (WebDAVElement):
+#    """
+#    Response body for a UNBIND request
+#    """
+#
+#    name = "unbind-response"
+#
+#    allowed_children = {
+#        # ANY
+#    }
+#
+#
+#@registerElement
+#@registerElementClass
+#class RebindRequest (WebDAVElement):
+#    """
+#    Request body for a REBIND request
+#    """
+#
+#    name = "rebind"
+#
+#    allowed_children = {
+#        (dav_namespace, "segment") : (1, 1),
+#        (dav_namespace, "href")    : (1, 1),
+#    }
+#
+#
+#@registerElement
+#@registerElementClass
+#class Rebind (WebDAVElement):
+#    """
+#    Response body for a UNBIND request
+#    """
+#
+#    name = "rebind-response"
+#
+#    allowed_children = {
+#        # ANY
+#    }

Deleted: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc5995.py
===================================================================
--- CalendarServer/trunk/txdav/xml/rfc5995.py	2012-03-22 00:02:25 UTC (rev 8919)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc5995.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -1,61 +0,0 @@
-##
-# Copyright (c) 2009-2012 Apple Computer, Inc. All rights reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-# 
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-# 
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-##
-
-"""
-RFC 5995 (Using POST to Add Members to WebDAV Collections) XML
-Elements
-
-This module provides XML element definitions for use with using POST
-to add members to WebDAV collections.
-
-See RFC 5995: http://www.ietf.org/rfc/rfc5995.txt
-"""
-
-__all__ = []
-
-
-from txdav.xml.base import WebDAVElement, dav_namespace
-from txdav.xml.element import registerElement, registerElementClass
-
-
- at registerElement
- at registerElementClass
-class AddMember (WebDAVElement):
-    """
-    A property on a collection to allow for "anonymous" creation of
-    resources.
-    """
-    name = "add-member"
-    hidden = True
-    protected = True
-
-    allowed_children = { (dav_namespace, "href"): (0, 1) }
-
-
- at registerElement
- at registerElementClass
-class AllowClientDefinedURI (WebDAVElement):
-    """
-    Precondition indicating that the server allows clients to specify
-    the last path segment for newly created resources.
-    """
-    name = "allow-client-defined-uri"

Copied: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc5995.py (from rev 8919, CalendarServer/trunk/txdav/xml/rfc5995.py)
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc5995.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/rfc5995.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -0,0 +1,61 @@
+##
+# Copyright (c) 2009-2012 Apple Computer, Inc. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+##
+
+"""
+RFC 5995 (Using POST to Add Members to WebDAV Collections) XML
+Elements
+
+This module provides XML element definitions for use with using POST
+to add members to WebDAV collections.
+
+See RFC 5995: http://www.ietf.org/rfc/rfc5995.txt
+"""
+
+__all__ = []
+
+
+from txdav.xml.base import WebDAVElement, dav_namespace
+from txdav.xml.element import registerElement, registerElementClass
+
+
+ at registerElement
+ at registerElementClass
+class AddMember (WebDAVElement):
+    """
+    A property on a collection to allow for "anonymous" creation of
+    resources.
+    """
+    name = "add-member"
+    hidden = True
+    protected = True
+
+    allowed_children = { (dav_namespace, "href"): (0, 1) }
+
+
+ at registerElement
+ at registerElementClass
+class AllowClientDefinedURI (WebDAVElement):
+    """
+    Precondition indicating that the server allows clients to specify
+    the last path segment for newly created resources.
+    """
+    name = "allow-client-defined-uri"

Deleted: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/__init__.py
===================================================================
--- CalendarServer/trunk/txdav/xml/test/__init__.py	2012-03-22 00:02:25 UTC (rev 8919)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/__init__.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -1,19 +0,0 @@
-##
-# Copyright (c) 2012 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.
-##
-
-"""
-WebDAV XML tests.
-"""

Copied: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/__init__.py (from rev 8919, CalendarServer/trunk/txdav/xml/test/__init__.py)
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/__init__.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/__init__.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -0,0 +1,19 @@
+##
+# Copyright (c) 2012 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.
+##
+
+"""
+WebDAV XML tests.
+"""

Deleted: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/test_base.py
===================================================================
--- CalendarServer/trunk/txdav/xml/test/test_base.py	2012-03-22 00:02:25 UTC (rev 8919)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/test_base.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -1,107 +0,0 @@
-##
-# Copyright (c) 2005-2012 Apple Computer, Inc. All rights reserved.
-# Copyright (c) 2009 Twisted Matrix Laboratories.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-##
-
-"""
-Tests for L{txdav.xml.base}.
-"""
-
-from twisted.trial.unittest import TestCase
-from txdav.xml.base import decodeXMLName, encodeXMLName
-from txdav.xml.base import WebDAVUnknownElement
-from txdav.xml.parser import WebDAVDocument
-
-
-class NameEncodeTests(TestCase):
-    """
-    Name encoding tests.
-    """
-    def test_decodeXMLName(self):
-        # Empty name
-        self.assertRaises(ValueError, decodeXMLName, "") 
-        self.assertRaises(ValueError, decodeXMLName, "{}")
-        self.assertRaises(ValueError, decodeXMLName, "{x}")
-
-        # Weird bracket cases
-        self.assertRaises(ValueError, decodeXMLName, "{")
-        self.assertRaises(ValueError, decodeXMLName, "x{")
-        self.assertRaises(ValueError, decodeXMLName, "{x")
-        self.assertRaises(ValueError, decodeXMLName, "}")
-        self.assertRaises(ValueError, decodeXMLName, "x}")
-        self.assertRaises(ValueError, decodeXMLName, "}x")  
-        self.assertRaises(ValueError, decodeXMLName, "{{}")
-        self.assertRaises(ValueError, decodeXMLName, "{{}}")
-        self.assertRaises(ValueError, decodeXMLName, "x{}")
-
-        # Empty namespace is OK
-        self.assertEquals(decodeXMLName(  "x"), (None, "x"))
-        self.assertEquals(decodeXMLName("{}x"), (None, "x"))
-
-        # Normal case
-        self.assertEquals(decodeXMLName("{namespace}name"), ("namespace", "name"))
-
-    def test_encodeXMLName(self):
-        # No namespace
-        self.assertEquals(encodeXMLName(None, "name"), "name")
-        self.assertEquals(encodeXMLName(""  , "name"), "name")
-
-        # Normal case
-        self.assertEquals(encodeXMLName("namespace", "name"), "{namespace}name")
-
-
-class WebDAVElementTestsMixin:
-    """
-    Mixin for L{TestCase}s which test a L{WebDAVElement} subclass.
-    """
-    def test_fromString(self):
-        """
-        The XML representation of L{WebDAVDocument} can be parsed into a
-        L{WebDAVDocument} instance using L{WebDAVDocument.fromString}.
-        """
-        doc = WebDAVDocument.fromString(self.serialized)
-        self.assertEquals(doc, WebDAVDocument(self.element))
-
-
-    def test_toxml(self):
-        """
-        L{WebDAVDocument.toxml} returns a C{str} giving the XML representation
-        of the L{WebDAVDocument} instance.
-        """
-        document = WebDAVDocument(self.element)
-        self.assertEquals(
-            document,
-            WebDAVDocument.fromString(document.toxml()))
-
-
-class WebDAVUnknownElementTests(WebDAVElementTestsMixin, TestCase):
-    """
-    Tests for L{WebDAVUnknownElement}.
-    """
-    serialized = (
-        """<?xml version="1.0" encoding="utf-8" ?>"""
-        """<T:foo xmlns:T="http://twistedmatrix.com/"/>"""
-    )
-
-    element = WebDAVUnknownElement.withName(
-        "http://twistedmatrix.com/",
-        "foo"
-    )

Copied: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/test_base.py (from rev 8919, CalendarServer/trunk/txdav/xml/test/test_base.py)
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/test_base.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/test_base.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -0,0 +1,107 @@
+##
+# Copyright (c) 2005-2012 Apple Computer, Inc. All rights reserved.
+# Copyright (c) 2009 Twisted Matrix Laboratories.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+##
+
+"""
+Tests for L{txdav.xml.base}.
+"""
+
+from twisted.trial.unittest import TestCase
+from txdav.xml.base import decodeXMLName, encodeXMLName
+from txdav.xml.base import WebDAVUnknownElement
+from txdav.xml.parser import WebDAVDocument
+
+
+class NameEncodeTests(TestCase):
+    """
+    Name encoding tests.
+    """
+    def test_decodeXMLName(self):
+        # Empty name
+        self.assertRaises(ValueError, decodeXMLName, "") 
+        self.assertRaises(ValueError, decodeXMLName, "{}")
+        self.assertRaises(ValueError, decodeXMLName, "{x}")
+
+        # Weird bracket cases
+        self.assertRaises(ValueError, decodeXMLName, "{")
+        self.assertRaises(ValueError, decodeXMLName, "x{")
+        self.assertRaises(ValueError, decodeXMLName, "{x")
+        self.assertRaises(ValueError, decodeXMLName, "}")
+        self.assertRaises(ValueError, decodeXMLName, "x}")
+        self.assertRaises(ValueError, decodeXMLName, "}x")  
+        self.assertRaises(ValueError, decodeXMLName, "{{}")
+        self.assertRaises(ValueError, decodeXMLName, "{{}}")
+        self.assertRaises(ValueError, decodeXMLName, "x{}")
+
+        # Empty namespace is OK
+        self.assertEquals(decodeXMLName(  "x"), (None, "x"))
+        self.assertEquals(decodeXMLName("{}x"), (None, "x"))
+
+        # Normal case
+        self.assertEquals(decodeXMLName("{namespace}name"), ("namespace", "name"))
+
+    def test_encodeXMLName(self):
+        # No namespace
+        self.assertEquals(encodeXMLName(None, "name"), "name")
+        self.assertEquals(encodeXMLName(""  , "name"), "name")
+
+        # Normal case
+        self.assertEquals(encodeXMLName("namespace", "name"), "{namespace}name")
+
+
+class WebDAVElementTestsMixin:
+    """
+    Mixin for L{TestCase}s which test a L{WebDAVElement} subclass.
+    """
+    def test_fromString(self):
+        """
+        The XML representation of L{WebDAVDocument} can be parsed into a
+        L{WebDAVDocument} instance using L{WebDAVDocument.fromString}.
+        """
+        doc = WebDAVDocument.fromString(self.serialized)
+        self.assertEquals(doc, WebDAVDocument(self.element))
+
+
+    def test_toxml(self):
+        """
+        L{WebDAVDocument.toxml} returns a C{str} giving the XML representation
+        of the L{WebDAVDocument} instance.
+        """
+        document = WebDAVDocument(self.element)
+        self.assertEquals(
+            document,
+            WebDAVDocument.fromString(document.toxml()))
+
+
+class WebDAVUnknownElementTests(WebDAVElementTestsMixin, TestCase):
+    """
+    Tests for L{WebDAVUnknownElement}.
+    """
+    serialized = (
+        """<?xml version="1.0" encoding="utf-8" ?>"""
+        """<T:foo xmlns:T="http://twistedmatrix.com/"/>"""
+    )
+
+    element = WebDAVUnknownElement.withName(
+        "http://twistedmatrix.com/",
+        "foo"
+    )

Deleted: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/test_xml.py
===================================================================
--- CalendarServer/trunk/txdav/xml/test/test_xml.py	2012-03-22 00:02:25 UTC (rev 8919)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/test_xml.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -1,68 +0,0 @@
-# Copyright (c) 2009 Twisted Matrix Laboratories.
-# See LICENSE for details.
-
-##
-# Copyright (c) 2005-2012 Apple Computer, Inc. All rights reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-##
-
-"""
-Tests for L{txdav.xml}.
-"""
-
-from twisted.trial.unittest import TestCase
-from txdav.xml.element import Response, HRef, MultiStatus, Status
-from txdav.xml.element import CurrentUserPrincipal
-from txdav.xml.test.test_base import WebDAVElementTestsMixin
-
-
-class MultiStatusTests(WebDAVElementTestsMixin, TestCase):
-    """
-    Tests for L{MultiStatus}
-    """
-    serialized = (
-        """<?xml version="1.0" encoding="utf-8" ?>"""
-        """<D:multistatus xmlns:D="DAV:">"""
-        """  <D:response>"""
-        """    <D:href>http://webdav.sb.aol.com/webdav/secret</D:href>"""
-        """    <D:status>HTTP/1.1 403 Forbidden</D:status>"""
-        """  </D:response>"""
-        """</D:multistatus>"""
-    )
-
-    element = MultiStatus(
-        Response(
-            HRef("http://webdav.sb.aol.com/webdav/secret"),
-            Status("HTTP/1.1 403 Forbidden")),
-        )
-
-
-class CurrentUserPrincipalTests(WebDAVElementTestsMixin, TestCase):
-    """
-    Tests for L{CurrentUserPrincipal}.
-    """
-    serialized = (
-        """<?xml version="1.0" encoding="utf-8" ?>"""
-        """<D:current-user-principal xmlns:D="DAV:">"""
-        """  <D:href>foo</D:href>"""
-        """</D:current-user-principal>"""
-    )
-
-    element = CurrentUserPrincipal(HRef("foo"))

Copied: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/test_xml.py (from rev 8919, CalendarServer/trunk/txdav/xml/test/test_xml.py)
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/test_xml.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/test_xml.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -0,0 +1,68 @@
+# Copyright (c) 2009 Twisted Matrix Laboratories.
+# See LICENSE for details.
+
+##
+# Copyright (c) 2005-2012 Apple Computer, Inc. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+##
+
+"""
+Tests for L{txdav.xml}.
+"""
+
+from twisted.trial.unittest import TestCase
+from txdav.xml.element import Response, HRef, MultiStatus, Status
+from txdav.xml.element import CurrentUserPrincipal
+from txdav.xml.test.test_base import WebDAVElementTestsMixin
+
+
+class MultiStatusTests(WebDAVElementTestsMixin, TestCase):
+    """
+    Tests for L{MultiStatus}
+    """
+    serialized = (
+        """<?xml version="1.0" encoding="utf-8" ?>"""
+        """<D:multistatus xmlns:D="DAV:">"""
+        """  <D:response>"""
+        """    <D:href>http://webdav.sb.aol.com/webdav/secret</D:href>"""
+        """    <D:status>HTTP/1.1 403 Forbidden</D:status>"""
+        """  </D:response>"""
+        """</D:multistatus>"""
+    )
+
+    element = MultiStatus(
+        Response(
+            HRef("http://webdav.sb.aol.com/webdav/secret"),
+            Status("HTTP/1.1 403 Forbidden")),
+        )
+
+
+class CurrentUserPrincipalTests(WebDAVElementTestsMixin, TestCase):
+    """
+    Tests for L{CurrentUserPrincipal}.
+    """
+    serialized = (
+        """<?xml version="1.0" encoding="utf-8" ?>"""
+        """<D:current-user-principal xmlns:D="DAV:">"""
+        """  <D:href>foo</D:href>"""
+        """</D:current-user-principal>"""
+    )
+
+    element = CurrentUserPrincipal(HRef("foo"))

Deleted: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/test_xml_rfc3744.py
===================================================================
--- CalendarServer/trunk/txdav/xml/test/test_xml_rfc3744.py	2012-03-22 00:02:25 UTC (rev 8919)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/test_xml_rfc3744.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -1,68 +0,0 @@
-##
-# Copyright (c) 2005-2012 Apple Computer, Inc. All rights reserved.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-# 
-# The above copyright notice and this permission notice shall be included in all
-# copies or substantial portions of the Software.
-# 
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-# SOFTWARE.
-##
-
-from twisted.trial import unittest
-
-from txdav.xml import element as davxml
-from twext.web2.dav.resource import davPrivilegeSet
-
-
-class XML_3744(unittest.TestCase):
-    """
-    RFC 3744 (WebDAV ACL) XML tests.
-    """
-    def test_Privilege_isAggregateOf(self):
-        """
-        Privilege.isAggregateOf()
-        """
-        for a, b in (
-            (davxml.All(), davxml.Write()),
-            (davxml.All(), davxml.ReadACL()),
-            (davxml.Write(), davxml.WriteProperties()),
-            (davxml.Write(), davxml.WriteContent()),
-            (davxml.Write(), davxml.Bind()),
-            (davxml.Write(), davxml.Unbind()),
-        ):
-            pa = davxml.Privilege(a)
-            pb = davxml.Privilege(b)
-
-            self.failUnless(
-                pa.isAggregateOf(pb, davPrivilegeSet),
-                "%s contains %s" % (a.sname(), b.sname())
-            )
-            self.failIf(
-                pb.isAggregateOf(pa, davPrivilegeSet),
-                "%s does not contain %s" % (b.sname(), a.sname())
-            )
-
-        for a, b in (
-            (davxml.Unlock(), davxml.Write()),
-            (davxml.Unlock(), davxml.WriteACL()),
-            (davxml.ReadCurrentUserPrivilegeSet(), davxml.WriteProperties()),
-        ):
-            pa = davxml.Privilege(a)
-            pb = davxml.Privilege(b)
-
-            self.failIf(
-                pb.isAggregateOf(pa, davPrivilegeSet),
-                "%s does not contain %s" % (b.sname(), a.sname())
-            )

Copied: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/test_xml_rfc3744.py (from rev 8919, CalendarServer/trunk/txdav/xml/test/test_xml_rfc3744.py)
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/test_xml_rfc3744.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/test/test_xml_rfc3744.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -0,0 +1,68 @@
+##
+# Copyright (c) 2005-2012 Apple Computer, Inc. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+##
+
+from twisted.trial import unittest
+
+from txdav.xml import element as davxml
+from twext.web2.dav.resource import davPrivilegeSet
+
+
+class XML_3744(unittest.TestCase):
+    """
+    RFC 3744 (WebDAV ACL) XML tests.
+    """
+    def test_Privilege_isAggregateOf(self):
+        """
+        Privilege.isAggregateOf()
+        """
+        for a, b in (
+            (davxml.All(), davxml.Write()),
+            (davxml.All(), davxml.ReadACL()),
+            (davxml.Write(), davxml.WriteProperties()),
+            (davxml.Write(), davxml.WriteContent()),
+            (davxml.Write(), davxml.Bind()),
+            (davxml.Write(), davxml.Unbind()),
+        ):
+            pa = davxml.Privilege(a)
+            pb = davxml.Privilege(b)
+
+            self.failUnless(
+                pa.isAggregateOf(pb, davPrivilegeSet),
+                "%s contains %s" % (a.sname(), b.sname())
+            )
+            self.failIf(
+                pb.isAggregateOf(pa, davPrivilegeSet),
+                "%s does not contain %s" % (b.sname(), a.sname())
+            )
+
+        for a, b in (
+            (davxml.Unlock(), davxml.Write()),
+            (davxml.Unlock(), davxml.WriteACL()),
+            (davxml.ReadCurrentUserPrivilegeSet(), davxml.WriteProperties()),
+        ):
+            pa = davxml.Privilege(a)
+            pb = davxml.Privilege(b)
+
+            self.failIf(
+                pb.isAggregateOf(pa, davPrivilegeSet),
+                "%s does not contain %s" % (b.sname(), a.sname())
+            )

Deleted: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/xmlext.py
===================================================================
--- CalendarServer/trunk/txdav/xml/xmlext.py	2012-03-22 00:02:25 UTC (rev 8919)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/xmlext.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -1,430 +0,0 @@
-########################################################################
-#
-# File Name:            __init__.py
-#
-#
-"""
-WWW: http://4suite.com/4DOM         e-mail: support at 4suite.com
-
-Copyright (c) 2000 Fourthought Inc, USA.   All Rights Reserved.
-See  http://4suite.com/COPYRIGHT  for license and copyright information
-"""
-
-"""Some Helper functions: 4DOM/PyXML-specific Extensions to the DOM,
-and DOM-related utilities."""
-
-__all__ = [ "Print", "PrettyPrint" ]
-
-import sys,string
-import re
-
-from xml.dom import Node
-from xml.dom import XML_NAMESPACE, XMLNS_NAMESPACE, DOMException
-
-def Print(root, stream=sys.stdout, encoding='UTF-8'):
-    if not hasattr(root, "nodeType"):
-        return
-    nss = SeekNss(root)
-    visitor = PrintVisitor(stream, encoding, nsHints=nss)
-    PrintWalker(visitor, root).run()
-    return
-
-def PrettyPrint(root, stream=sys.stdout, encoding='UTF-8', indent='  ',
-                preserveElements=None):
-    if not hasattr(root, "nodeType"):
-        return
-    nss_hints = SeekNss(root)
-    preserveElements = preserveElements or []
-    owner_doc = root.ownerDocument or root
-    if hasattr(owner_doc, 'getElementsByName'):
-        #We don't want to insert any whitespace into HTML inline elements
-        preserveElements = preserveElements + HTML_4_TRANSITIONAL_INLINE
-    visitor = PrintVisitor(stream, encoding, indent,
-                                   preserveElements, nss_hints)
-    PrintWalker(visitor, root).run()
-    stream.write('\n')
-    return
-
-def GetAllNs(node):
-    #The xml namespace is implicit
-    nss = {'xml': XML_NAMESPACE}
-    if node.nodeType == Node.ATTRIBUTE_NODE and node.ownerElement:
-        return GetAllNs(node.ownerElement)
-    if node.nodeType == Node.ELEMENT_NODE:
-        if node.namespaceURI:
-            nss[node.prefix] = node.namespaceURI
-        for attr in node.attributes.values():
-            if attr.namespaceURI == XMLNS_NAMESPACE:
-                if attr.localName == 'xmlns':
-                    nss[None] = attr.value
-                else:
-                    nss[attr.localName] = attr.value
-            elif attr.namespaceURI:
-                nss[attr.prefix] = attr.namespaceURI
-    if node.parentNode:
-        #Inner NS/Prefix mappings take precedence over outer ones
-        parent_nss = GetAllNs(node.parentNode)
-        parent_nss.update(nss)
-        nss = parent_nss
-    return nss
-
-def SeekNss(node, nss=None):
-    '''traverses the tree to seek an approximate set of defined namespaces'''
-    nss = nss or {}
-    for child in node.childNodes:
-        if child.nodeType == Node.ELEMENT_NODE:
-            if child.namespaceURI:
-                nss[child.prefix] = child.namespaceURI
-            for attr in child.attributes.values():
-                if attr.namespaceURI == XMLNS_NAMESPACE:
-                    if attr.localName == 'xmlns':
-                        nss[None] = attr.value
-                    else:
-                        nss[attr.localName] = attr.value
-                elif attr.namespaceURI:
-                    nss[attr.prefix] = attr.namespaceURI
-            SeekNss(child, nss)
-    return nss
-
-class PrintVisitor:
-    def __init__(self, stream, encoding, indent='', plainElements=None,
-                 nsHints=None, isXhtml=0, force8bit=0):
-        self.stream = stream
-        self.encoding = encoding
-        # Namespaces
-        self._namespaces = [{}]
-        self._nsHints = nsHints or {}
-        # PrettyPrint
-        self._indent = indent
-        self._depth = 0
-        self._inText = 0
-        self._plainElements = plainElements or []
-        # HTML support
-        self._html = None
-        self._isXhtml = isXhtml
-        self.force8bit = force8bit
-        return
-
-    def _write(self, text):
-        if self.force8bit:
-            obj = strobj_to_utf8str(text, self.encoding)
-        else:
-            obj = utf8_to_code(text, self.encoding)
-        self.stream.write(obj)
-        return
-
-    def _tryIndent(self):
-        if not self._inText and self._indent:
-            self._write('\n' + self._indent*self._depth)
-        return
-
-    def visit(self, node):
-        if self._html is None:
-            # Set HTMLDocument flag here for speed
-            self._html = hasattr(node.ownerDocument, 'getElementsByName')
-
-        nodeType = node.nodeType
-        if node.nodeType == Node.ELEMENT_NODE:
-            return self.visitElement(node)
-
-        elif node.nodeType == Node.ATTRIBUTE_NODE:
-            return self.visitAttr(node)
-
-        elif node.nodeType == Node.TEXT_NODE:
-            return self.visitText(node)
-
-        elif node.nodeType == Node.CDATA_SECTION_NODE:
-            return self.visitCDATASection(node)
-
-        elif node.nodeType == Node.ENTITY_REFERENCE_NODE:
-            return self.visitEntityReference(node)
-
-        elif node.nodeType == Node.ENTITY_NODE:
-            return self.visitEntity(node)
-
-        elif node.nodeType == Node.PROCESSING_INSTRUCTION_NODE:
-            return self.visitProcessingInstruction(node)
-
-        elif node.nodeType == Node.COMMENT_NODE:
-            return self.visitComment(node)
-
-        elif node.nodeType == Node.DOCUMENT_NODE:
-            return self.visitDocument(node)
-
-        elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
-            return self.visitDocumentType(node)
-
-        elif node.nodeType == Node.DOCUMENT_FRAGMENT_NODE:
-            return self.visitDocumentFragment(node)
-
-        elif node.nodeType == Node.NOTATION_NODE:
-            return self.visitNotation(node)
-
-        # It has a node type, but we don't know how to handle it
-        raise Exception("Unknown node type: %s" % repr(node))
-
-    def visitNodeList(self, node, exclude=None):
-        for curr in node:
-            curr is not exclude and self.visit(curr)
-        return
-
-    def visitNamedNodeMap(self, node):
-        for item in node.values():
-            self.visit(item)
-        return
-
-    def visitAttr(self, node):
-        if node.namespaceURI == XMLNS_NAMESPACE:
-            # Skip namespace declarations
-            return
-        self._write(' ' + node.name)
-        value = node.value
-        if value or not self._html:
-            text = TranslateCdata(value, self.encoding)
-            text, delimiter = TranslateCdataAttr(text)
-            self.stream.write("=%s%s%s" % (delimiter, text, delimiter))
-        return
-
-    def visitProlog(self):
-        self._write("<?xml version='1.0' encoding='%s'?>" % (
-            self.encoding or 'utf-8'
-            ))
-        self._inText = 0
-        return
-
-    def visitDocument(self, node):
-        not self._html and self.visitProlog()
-        node.doctype and self.visitDocumentType(node.doctype)
-        self.visitNodeList(node.childNodes, exclude=node.doctype)
-        return
-
-    def visitDocumentFragment(self, node):
-        self.visitNodeList(node.childNodes)
-        return
-
-    def visitElement(self, node):
-        self._namespaces.append(self._namespaces[-1].copy())
-        inline = node.tagName in self._plainElements
-        not inline and self._tryIndent()
-        self._write('<%s' % node.tagName)
-        if self._isXhtml or not self._html:
-            namespaces = ''
-            if self._isXhtml:
-                nss = {'xml': XML_NAMESPACE, None: XHTML_NAMESPACE}
-            else:
-                nss = GetAllNs(node)
-            if self._nsHints:
-                self._nsHints.update(nss)
-                nss = self._nsHints
-                self._nsHints = {}
-            del nss['xml']
-            for prefix in nss.keys():
-                if not self._namespaces[-1].has_key(prefix) or self._namespaces[-1][prefix] != nss[prefix]:
-                    nsuri, delimiter = TranslateCdataAttr(nss[prefix])
-                    if prefix:
-                        xmlns = " xmlns:%s=%s%s%s" % (prefix, delimiter,nsuri,delimiter)
-                    else:
-                        xmlns = " xmlns=%s%s%s" % (delimiter,nsuri,delimiter)
-                    namespaces = namespaces + xmlns
-
-                self._namespaces[-1][prefix] = nss[prefix]
-            self._write(namespaces)
-        for attr in node.attributes.values():
-            self.visitAttr(attr)
-        if len(node.childNodes):
-            self._write('>')
-            self._depth = self._depth + 1
-            self.visitNodeList(node.childNodes)
-            self._depth = self._depth - 1
-            if not self._html or (node.tagName not in HTML_FORBIDDEN_END):
-                not (self._inText and inline) and self._tryIndent()
-                self._write('</%s>' % node.tagName)
-        elif not self._html:
-            self._write('/>')
-        elif node.tagName not in HTML_FORBIDDEN_END:
-            self._write('></%s>' % node.tagName)
-        else:
-            self._write('>')
-        del self._namespaces[-1]
-        self._inText = 0
-        return
-
-    def visitText(self, node):
-        text = node.data
-        if self._indent:
-            text = string.strip(text) and text
-        if text:
-            if self._html:
-                text = TranslateHtmlCdata(text, self.encoding)
-            else:
-                text = TranslateCdata(text, self.encoding)
-            self.stream.write(text)
-            self._inText = 1
-        return
-
-    def visitDocumentType(self, doctype):
-        if not doctype.systemId and not doctype.publicId: return
-        self._tryIndent()
-        self._write('<!DOCTYPE %s' % doctype.name)
-        if doctype.systemId and '"' in doctype.systemId:
-            system = "'%s'" % doctype.systemId
-        else:
-            system = '"%s"' % doctype.systemId
-        if doctype.publicId and '"' in doctype.publicId:
-            # We should probably throw an error
-            # Valid characters:  <space> | <newline> | <linefeed> |
-            #                    [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]
-            public = "'%s'" % doctype.publicId
-        else:
-            public = '"%s"' % doctype.publicId
-        if doctype.publicId and doctype.systemId:
-            self._write(' PUBLIC %s %s' % (public, system))
-        elif doctype.systemId:
-            self._write(' SYSTEM %s' % system)
-        if doctype.entities or doctype.notations:
-            self._write(' [')
-            self._depth = self._depth + 1
-            self.visitNamedNodeMap(doctype.entities)
-            self.visitNamedNodeMap(doctype.notations)
-            self._depth = self._depth - 1
-            self._tryIndent()
-            self._write(']>')
-        else:
-            self._write('>')
-        self._inText = 0
-        return
-
-    def visitEntity(self, node):
-        """Visited from a NamedNodeMap in DocumentType"""
-        self._tryIndent()
-        self._write('<!ENTITY %s' % (node.nodeName))
-        node.publicId and self._write(' PUBLIC %s' % node.publicId)
-        node.systemId and self._write(' SYSTEM %s' % node.systemId)
-        node.notationName and self._write(' NDATA %s' % node.notationName)
-        self._write('>')
-        return
-
-    def visitNotation(self, node):
-        """Visited from a NamedNodeMap in DocumentType"""
-        self._tryIndent()
-        self._write('<!NOTATION %s' % node.nodeName)
-        node.publicId and self._write(' PUBLIC %s' % node.publicId)
-        node.systemId and self._write(' SYSTEM %s' % node.systemId)
-        self._write('>')
-        return
-
-    def visitCDATASection(self, node):
-        self._tryIndent()
-        self._write('<![CDATA[%s]]>' % (node.data))
-        self._inText = 0
-        return
-
-    def visitComment(self, node):
-        self._tryIndent()
-        self._write('<!--%s-->' % (node.data))
-        self._inText = 0
-        return
-
-    def visitEntityReference(self, node):
-        self._write('&%s;' % node.nodeName)
-        self._inText = 1
-        return
-
-    def visitProcessingInstruction(self, node):
-        self._tryIndent()
-        self._write('<?%s %s?>' % (node.target, node.data))
-        self._inText = 0
-        return
-
-class PrintWalker:
-    def __init__(self, visitor, startNode):
-        self.visitor = visitor
-        self.start_node = startNode
-        return
-
-    def step(self):
-        """There is really no step to printing.  It prints the whole thing"""
-        self.visitor.visit(self.start_node)
-        return
-
-    def run(self):
-        return self.step()
-
-ILLEGAL_LOW_CHARS = '[\x01-\x08\x0B-\x0C\x0E-\x1F]'
-SURROGATE_BLOCK = '[\xF0-\xF7][\x80-\xBF][\x80-\xBF][\x80-\xBF]'
-ILLEGAL_HIGH_CHARS = '\xEF\xBF[\xBE\xBF]'
-#Note: Prolly fuzzy on this, but it looks as if characters from the surrogate block are allowed if in scalar form, which is encoded in UTF8 the same was as in surrogate block form
-XML_ILLEGAL_CHAR_PATTERN = re.compile('%s|%s'%(ILLEGAL_LOW_CHARS, ILLEGAL_HIGH_CHARS))
-
-g_utf8TwoBytePattern = re.compile('([\xC0-\xC3])([\x80-\xBF])')
-g_cdataCharPattern = re.compile('[&<]|]]>')
-g_charToEntity = {
-        '&': '&',
-        '<': '<',
-        ']]>': ']]>',
-        }
-
-# Slightly modified to not use types.Unicode
-import codecs
-def utf8_to_code(text, encoding):
-    encoder = codecs.lookup(encoding)[0] # encode,decode,reader,writer
-    if type(text) is not unicode:
-        text = unicode(text, "utf-8")
-    return encoder(text)[0] # result,size
-def strobj_to_utf8str(text, encoding):
-    if string.upper(encoding) not in ["UTF-8", "ISO-8859-1", "LATIN-1"]:
-        raise ValueError("Invalid encoding: %s"%encoding)
-    encoder = codecs.lookup(encoding)[0] # encode,decode,reader,writer
-    if type(text) is not unicode:
-        text = unicode(text, "utf-8")
-    #FIXME
-    return str(encoder(text)[0])
-
-def TranslateCdataAttr(characters):
-    '''Handles normalization and some intelligence about quoting'''
-    if not characters:
-        return '', "'"
-    if "'" in characters:
-        delimiter = '"'
-        new_chars = re.sub('"', '"', characters)
-    else:
-        delimiter = "'"
-        new_chars = re.sub("'", ''', characters)
-    #FIXME: There's more to normalization
-    #Convert attribute new-lines to character entity
-    # characters is possibly shorter than new_chars (no entities)
-    if "\n" in characters:
-        new_chars = re.sub('\n', '
', new_chars)
-    return new_chars, delimiter
-
-#Note: Unicode object only for now
-def TranslateCdata(characters, encoding='UTF-8', prev_chars='', markupSafe=0,
-                   charsetHandler=utf8_to_code):
-    """
-    charsetHandler is a function that takes a string or unicode object as the
-    first argument, representing the string to be procesed, and an encoding
-    specifier as the second argument.  It must return a string or unicode
-    object
-    """
-    if not characters:
-        return ''
-    if not markupSafe:
-        if g_cdataCharPattern.search(characters):
-            new_string = g_cdataCharPattern.subn(
-                lambda m, d=g_charToEntity: d[m.group()],
-                characters)[0]
-        else:
-            new_string = characters
-        if prev_chars[-2:] == ']]' and characters[0] == '>':
-            new_string = '>' + new_string[1:]
-    else:
-        new_string = characters
-    #Note: use decimal char entity rep because some browsers are broken
-    #FIXME: This will bomb for high characters.  Should, for instance, detect
-    #The UTF-8 for 0xFFFE and put out &#xFFFE;
-    if XML_ILLEGAL_CHAR_PATTERN.search(new_string):
-        new_string = XML_ILLEGAL_CHAR_PATTERN.subn(
-            lambda m: '&#%i;' % ord(m.group()),
-            new_string)[0]
-    new_string = charsetHandler(new_string, encoding)
-    return new_string

Copied: CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/xmlext.py (from rev 8919, CalendarServer/trunk/txdav/xml/xmlext.py)
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/xmlext.py	                        (rev 0)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/txdav/xml/xmlext.py	2012-03-22 00:41:39 UTC (rev 8921)
@@ -0,0 +1,430 @@
+########################################################################
+#
+# File Name:            __init__.py
+#
+#
+"""
+WWW: http://4suite.com/4DOM         e-mail: support at 4suite.com
+
+Copyright (c) 2000 Fourthought Inc, USA.   All Rights Reserved.
+See  http://4suite.com/COPYRIGHT  for license and copyright information
+"""
+
+"""Some Helper functions: 4DOM/PyXML-specific Extensions to the DOM,
+and DOM-related utilities."""
+
+__all__ = [ "Print", "PrettyPrint" ]
+
+import sys,string
+import re
+
+from xml.dom import Node
+from xml.dom import XML_NAMESPACE, XMLNS_NAMESPACE, DOMException
+
+def Print(root, stream=sys.stdout, encoding='UTF-8'):
+    if not hasattr(root, "nodeType"):
+        return
+    nss = SeekNss(root)
+    visitor = PrintVisitor(stream, encoding, nsHints=nss)
+    PrintWalker(visitor, root).run()
+    return
+
+def PrettyPrint(root, stream=sys.stdout, encoding='UTF-8', indent='  ',
+                preserveElements=None):
+    if not hasattr(root, "nodeType"):
+        return
+    nss_hints = SeekNss(root)
+    preserveElements = preserveElements or []
+    owner_doc = root.ownerDocument or root
+    if hasattr(owner_doc, 'getElementsByName'):
+        #We don't want to insert any whitespace into HTML inline elements
+        preserveElements = preserveElements + HTML_4_TRANSITIONAL_INLINE
+    visitor = PrintVisitor(stream, encoding, indent,
+                                   preserveElements, nss_hints)
+    PrintWalker(visitor, root).run()
+    stream.write('\n')
+    return
+
+def GetAllNs(node):
+    #The xml namespace is implicit
+    nss = {'xml': XML_NAMESPACE}
+    if node.nodeType == Node.ATTRIBUTE_NODE and node.ownerElement:
+        return GetAllNs(node.ownerElement)
+    if node.nodeType == Node.ELEMENT_NODE:
+        if node.namespaceURI:
+            nss[node.prefix] = node.namespaceURI
+        for attr in node.attributes.values():
+            if attr.namespaceURI == XMLNS_NAMESPACE:
+                if attr.localName == 'xmlns':
+                    nss[None] = attr.value
+                else:
+                    nss[attr.localName] = attr.value
+            elif attr.namespaceURI:
+                nss[attr.prefix] = attr.namespaceURI
+    if node.parentNode:
+        #Inner NS/Prefix mappings take precedence over outer ones
+        parent_nss = GetAllNs(node.parentNode)
+        parent_nss.update(nss)
+        nss = parent_nss
+    return nss
+
+def SeekNss(node, nss=None):
+    '''traverses the tree to seek an approximate set of defined namespaces'''
+    nss = nss or {}
+    for child in node.childNodes:
+        if child.nodeType == Node.ELEMENT_NODE:
+            if child.namespaceURI:
+                nss[child.prefix] = child.namespaceURI
+            for attr in child.attributes.values():
+                if attr.namespaceURI == XMLNS_NAMESPACE:
+                    if attr.localName == 'xmlns':
+                        nss[None] = attr.value
+                    else:
+                        nss[attr.localName] = attr.value
+                elif attr.namespaceURI:
+                    nss[attr.prefix] = attr.namespaceURI
+            SeekNss(child, nss)
+    return nss
+
+class PrintVisitor:
+    def __init__(self, stream, encoding, indent='', plainElements=None,
+                 nsHints=None, isXhtml=0, force8bit=0):
+        self.stream = stream
+        self.encoding = encoding
+        # Namespaces
+        self._namespaces = [{}]
+        self._nsHints = nsHints or {}
+        # PrettyPrint
+        self._indent = indent
+        self._depth = 0
+        self._inText = 0
+        self._plainElements = plainElements or []
+        # HTML support
+        self._html = None
+        self._isXhtml = isXhtml
+        self.force8bit = force8bit
+        return
+
+    def _write(self, text):
+        if self.force8bit:
+            obj = strobj_to_utf8str(text, self.encoding)
+        else:
+            obj = utf8_to_code(text, self.encoding)
+        self.stream.write(obj)
+        return
+
+    def _tryIndent(self):
+        if not self._inText and self._indent:
+            self._write('\n' + self._indent*self._depth)
+        return
+
+    def visit(self, node):
+        if self._html is None:
+            # Set HTMLDocument flag here for speed
+            self._html = hasattr(node.ownerDocument, 'getElementsByName')
+
+        nodeType = node.nodeType
+        if node.nodeType == Node.ELEMENT_NODE:
+            return self.visitElement(node)
+
+        elif node.nodeType == Node.ATTRIBUTE_NODE:
+            return self.visitAttr(node)
+
+        elif node.nodeType == Node.TEXT_NODE:
+            return self.visitText(node)
+
+        elif node.nodeType == Node.CDATA_SECTION_NODE:
+            return self.visitCDATASection(node)
+
+        elif node.nodeType == Node.ENTITY_REFERENCE_NODE:
+            return self.visitEntityReference(node)
+
+        elif node.nodeType == Node.ENTITY_NODE:
+            return self.visitEntity(node)
+
+        elif node.nodeType == Node.PROCESSING_INSTRUCTION_NODE:
+            return self.visitProcessingInstruction(node)
+
+        elif node.nodeType == Node.COMMENT_NODE:
+            return self.visitComment(node)
+
+        elif node.nodeType == Node.DOCUMENT_NODE:
+            return self.visitDocument(node)
+
+        elif node.nodeType == Node.DOCUMENT_TYPE_NODE:
+            return self.visitDocumentType(node)
+
+        elif node.nodeType == Node.DOCUMENT_FRAGMENT_NODE:
+            return self.visitDocumentFragment(node)
+
+        elif node.nodeType == Node.NOTATION_NODE:
+            return self.visitNotation(node)
+
+        # It has a node type, but we don't know how to handle it
+        raise Exception("Unknown node type: %s" % repr(node))
+
+    def visitNodeList(self, node, exclude=None):
+        for curr in node:
+            curr is not exclude and self.visit(curr)
+        return
+
+    def visitNamedNodeMap(self, node):
+        for item in node.values():
+            self.visit(item)
+        return
+
+    def visitAttr(self, node):
+        if node.namespaceURI == XMLNS_NAMESPACE:
+            # Skip namespace declarations
+            return
+        self._write(' ' + node.name)
+        value = node.value
+        if value or not self._html:
+            text = TranslateCdata(value, self.encoding)
+            text, delimiter = TranslateCdataAttr(text)
+            self.stream.write("=%s%s%s" % (delimiter, text, delimiter))
+        return
+
+    def visitProlog(self):
+        self._write("<?xml version='1.0' encoding='%s'?>" % (
+            self.encoding or 'utf-8'
+            ))
+        self._inText = 0
+        return
+
+    def visitDocument(self, node):
+        not self._html and self.visitProlog()
+        node.doctype and self.visitDocumentType(node.doctype)
+        self.visitNodeList(node.childNodes, exclude=node.doctype)
+        return
+
+    def visitDocumentFragment(self, node):
+        self.visitNodeList(node.childNodes)
+        return
+
+    def visitElement(self, node):
+        self._namespaces.append(self._namespaces[-1].copy())
+        inline = node.tagName in self._plainElements
+        not inline and self._tryIndent()
+        self._write('<%s' % node.tagName)
+        if self._isXhtml or not self._html:
+            namespaces = ''
+            if self._isXhtml:
+                nss = {'xml': XML_NAMESPACE, None: XHTML_NAMESPACE}
+            else:
+                nss = GetAllNs(node)
+            if self._nsHints:
+                self._nsHints.update(nss)
+                nss = self._nsHints
+                self._nsHints = {}
+            del nss['xml']
+            for prefix in nss.keys():
+                if not self._namespaces[-1].has_key(prefix) or self._namespaces[-1][prefix] != nss[prefix]:
+                    nsuri, delimiter = TranslateCdataAttr(nss[prefix])
+                    if prefix:
+                        xmlns = " xmlns:%s=%s%s%s" % (prefix, delimiter,nsuri,delimiter)
+                    else:
+                        xmlns = " xmlns=%s%s%s" % (delimiter,nsuri,delimiter)
+                    namespaces = namespaces + xmlns
+
+                self._namespaces[-1][prefix] = nss[prefix]
+            self._write(namespaces)
+        for attr in node.attributes.values():
+            self.visitAttr(attr)
+        if len(node.childNodes):
+            self._write('>')
+            self._depth = self._depth + 1
+            self.visitNodeList(node.childNodes)
+            self._depth = self._depth - 1
+            if not self._html or (node.tagName not in HTML_FORBIDDEN_END):
+                not (self._inText and inline) and self._tryIndent()
+                self._write('</%s>' % node.tagName)
+        elif not self._html:
+            self._write('/>')
+        elif node.tagName not in HTML_FORBIDDEN_END:
+            self._write('></%s>' % node.tagName)
+        else:
+            self._write('>')
+        del self._namespaces[-1]
+        self._inText = 0
+        return
+
+    def visitText(self, node):
+        text = node.data
+        if self._indent:
+            text = string.strip(text) and text
+        if text:
+            if self._html:
+                text = TranslateHtmlCdata(text, self.encoding)
+            else:
+                text = TranslateCdata(text, self.encoding)
+            self.stream.write(text)
+            self._inText = 1
+        return
+
+    def visitDocumentType(self, doctype):
+        if not doctype.systemId and not doctype.publicId: return
+        self._tryIndent()
+        self._write('<!DOCTYPE %s' % doctype.name)
+        if doctype.systemId and '"' in doctype.systemId:
+            system = "'%s'" % doctype.systemId
+        else:
+            system = '"%s"' % doctype.systemId
+        if doctype.publicId and '"' in doctype.publicId:
+            # We should probably throw an error
+            # Valid characters:  <space> | <newline> | <linefeed> |
+            #                    [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]
+            public = "'%s'" % doctype.publicId
+        else:
+            public = '"%s"' % doctype.publicId
+        if doctype.publicId and doctype.systemId:
+            self._write(' PUBLIC %s %s' % (public, system))
+        elif doctype.systemId:
+            self._write(' SYSTEM %s' % system)
+        if doctype.entities or doctype.notations:
+            self._write(' [')
+            self._depth = self._depth + 1
+            self.visitNamedNodeMap(doctype.entities)
+            self.visitNamedNodeMap(doctype.notations)
+            self._depth = self._depth - 1
+            self._tryIndent()
+            self._write(']>')
+        else:
+            self._write('>')
+        self._inText = 0
+        return
+
+    def visitEntity(self, node):
+        """Visited from a NamedNodeMap in DocumentType"""
+        self._tryIndent()
+        self._write('<!ENTITY %s' % (node.nodeName))
+        node.publicId and self._write(' PUBLIC %s' % node.publicId)
+        node.systemId and self._write(' SYSTEM %s' % node.systemId)
+        node.notationName and self._write(' NDATA %s' % node.notationName)
+        self._write('>')
+        return
+
+    def visitNotation(self, node):
+        """Visited from a NamedNodeMap in DocumentType"""
+        self._tryIndent()
+        self._write('<!NOTATION %s' % node.nodeName)
+        node.publicId and self._write(' PUBLIC %s' % node.publicId)
+        node.systemId and self._write(' SYSTEM %s' % node.systemId)
+        self._write('>')
+        return
+
+    def visitCDATASection(self, node):
+        self._tryIndent()
+        self._write('<![CDATA[%s]]>' % (node.data))
+        self._inText = 0
+        return
+
+    def visitComment(self, node):
+        self._tryIndent()
+        self._write('<!--%s-->' % (node.data))
+        self._inText = 0
+        return
+
+    def visitEntityReference(self, node):
+        self._write('&%s;' % node.nodeName)
+        self._inText = 1
+        return
+
+    def visitProcessingInstruction(self, node):
+        self._tryIndent()
+        self._write('<?%s %s?>' % (node.target, node.data))
+        self._inText = 0
+        return
+
+class PrintWalker:
+    def __init__(self, visitor, startNode):
+        self.visitor = visitor
+        self.start_node = startNode
+        return
+
+    def step(self):
+        """There is really no step to printing.  It prints the whole thing"""
+        self.visitor.visit(self.start_node)
+        return
+
+    def run(self):
+        return self.step()
+
+ILLEGAL_LOW_CHARS = '[\x01-\x08\x0B-\x0C\x0E-\x1F]'
+SURROGATE_BLOCK = '[\xF0-\xF7][\x80-\xBF][\x80-\xBF][\x80-\xBF]'
+ILLEGAL_HIGH_CHARS = '\xEF\xBF[\xBE\xBF]'
+#Note: Prolly fuzzy on this, but it looks as if characters from the surrogate block are allowed if in scalar form, which is encoded in UTF8 the same was as in surrogate block form
+XML_ILLEGAL_CHAR_PATTERN = re.compile('%s|%s'%(ILLEGAL_LOW_CHARS, ILLEGAL_HIGH_CHARS))
+
+g_utf8TwoBytePattern = re.compile('([\xC0-\xC3])([\x80-\xBF])')
+g_cdataCharPattern = re.compile('[&<]|]]>')
+g_charToEntity = {
+        '&': '&',
+        '<': '<',
+        ']]>': ']]>',
+        }
+
+# Slightly modified to not use types.Unicode
+import codecs
+def utf8_to_code(text, encoding):
+    encoder = codecs.lookup(encoding)[0] # encode,decode,reader,writer
+    if type(text) is not unicode:
+        text = unicode(text, "utf-8")
+    return encoder(text)[0] # result,size
+def strobj_to_utf8str(text, encoding):
+    if string.upper(encoding) not in ["UTF-8", "ISO-8859-1", "LATIN-1"]:
+        raise ValueError("Invalid encoding: %s"%encoding)
+    encoder = codecs.lookup(encoding)[0] # encode,decode,reader,writer
+    if type(text) is not unicode:
+        text = unicode(text, "utf-8")
+    #FIXME
+    return str(encoder(text)[0])
+
+def TranslateCdataAttr(characters):
+    '''Handles normalization and some intelligence about quoting'''
+    if not characters:
+        return '', "'"
+    if "'" in characters:
+        delimiter = '"'
+        new_chars = re.sub('"', '"', characters)
+    else:
+        delimiter = "'"
+        new_chars = re.sub("'", ''', characters)
+    #FIXME: There's more to normalization
+    #Convert attribute new-lines to character entity
+    # characters is possibly shorter than new_chars (no entities)
+    if "\n" in characters:
+        new_chars = re.sub('\n', '
', new_chars)
+    return new_chars, delimiter
+
+#Note: Unicode object only for now
+def TranslateCdata(characters, encoding='UTF-8', prev_chars='', markupSafe=0,
+                   charsetHandler=utf8_to_code):
+    """
+    charsetHandler is a function that takes a string or unicode object as the
+    first argument, representing the string to be procesed, and an encoding
+    specifier as the second argument.  It must return a string or unicode
+    object
+    """
+    if not characters:
+        return ''
+    if not markupSafe:
+        if g_cdataCharPattern.search(characters):
+            new_string = g_cdataCharPattern.subn(
+                lambda m, d=g_charToEntity: d[m.group()],
+                characters)[0]
+        else:
+            new_string = characters
+        if prev_chars[-2:] == ']]' and characters[0] == '>':
+            new_string = '>' + new_string[1:]
+    else:
+        new_string = characters
+    #Note: use decimal char entity rep because some browsers are broken
+    #FIXME: This will bomb for high characters.  Should, for instance, detect
+    #The UTF-8 for 0xFFFE and put out &#xFFFE;
+    if XML_ILLEGAL_CHAR_PATTERN.search(new_string):
+        new_string = XML_ILLEGAL_CHAR_PATTERN.subn(
+            lambda m: '&#%i;' % ord(m.group()),
+            new_string)[0]
+    new_string = charsetHandler(new_string, encoding)
+    return new_string
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20120321/4587869a/attachment-0001.html>


More information about the calendarserver-changes mailing list