[CalendarServer-changes] [8463] CalDAVClientLibrary/trunk/caldavclientlibrary
source_changes at macosforge.org
source_changes at macosforge.org
Thu Dec 15 19:42:39 PST 2011
Revision: 8463
http://trac.macosforge.org/projects/calendarserver/changeset/8463
Author: cdaboo at apple.com
Date: 2011-12-15 19:42:39 -0800 (Thu, 15 Dec 2011)
Log Message:
-----------
Fix principal discovery. Add some new commands, including sync report.
Modified Paths:
--------------
CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/__init__.py
CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/cat.py
CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/principal.py
CalDAVClientLibrary/trunk/caldavclientlibrary/browser/shell.py
CalDAVClientLibrary/trunk/caldavclientlibrary/client/clientsession.py
CalDAVClientLibrary/trunk/caldavclientlibrary/client/principal.py
CalDAVClientLibrary/trunk/caldavclientlibrary/protocol/caldav/multiget.py
CalDAVClientLibrary/trunk/caldavclientlibrary/protocol/webdav/definitions/davxml.py
CalDAVClientLibrary/trunk/caldavclientlibrary/protocol/webdav/propfindparser.py
CalDAVClientLibrary/trunk/caldavclientlibrary/protocol/webdav/report.py
Added Paths:
-----------
CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/addressbooks.py
CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/calendars.py
CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/sync.py
CalDAVClientLibrary/trunk/caldavclientlibrary/client/addressbook.py
CalDAVClientLibrary/trunk/caldavclientlibrary/protocol/webdav/synccollection.py
Modified: CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/__init__.py
===================================================================
--- CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/__init__.py 2011-12-16 00:20:51 UTC (rev 8462)
+++ CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/__init__.py 2011-12-16 03:42:39 UTC (rev 8463)
@@ -16,8 +16,10 @@
__all__ = [
"acl",
+ "addressbooks",
"cat",
"cd",
+ "calendars",
"help",
"history",
"import",
@@ -35,6 +37,7 @@
"quota",
"rm",
"server",
+ "sync",
"user",
"whoami",
]
Added: CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/addressbooks.py
===================================================================
--- CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/addressbooks.py (rev 0)
+++ CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/addressbooks.py 2011-12-16 03:42:39 UTC (rev 8463)
@@ -0,0 +1,67 @@
+##
+# Copyright (c) 2007-2011 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from caldavclientlibrary.browser.command import Command, CommandError
+from caldavclientlibrary.browser.command import WrongOptions
+from caldavclientlibrary.protocol.url import URL
+import getopt
+import shlex
+
+class Cmd(Command):
+
+ def __init__(self):
+ super(Command, self).__init__()
+ self.cmds = ("addressbooks",)
+
+ def execute(self, name, options):
+ opts, args = getopt.getopt(shlex.split(options), '')
+ if len(opts) != 0:
+ print self.usage(name)
+ raise WrongOptions
+
+ if len(args) > 1:
+ print "Wrong number of arguments: %d" % (len(args),)
+ print self.usage(name)
+ raise WrongOptions
+ ppath = URL(url=args[0]) if args else None
+ principal = self.shell.account.getPrincipal(ppath)
+ if principal is None:
+ print "No principal found for %s" % (ppath if ppath else "current principal")
+ raise CommandError
+
+ homeset = principal.adbkhomeset
+ if not homeset:
+ print "No address book home set found for %s" % (principal.principalPath,)
+ raise CommandError
+
+ newpath = homeset[0].path
+ result = self.shell.setWD(newpath)
+
+ if not result:
+ print "%s: No such directory" % (newpath,)
+
+ return result
+
+ def complete(self, text):
+ return self.shell.wdcomplete(text)
+
+ def usage(self, name):
+ return """Usage: %s [PRINCIPAL]
+PRINCIPAL is a principal-URL.
+""" % (name,)
+
+ def helpDescription(self):
+ return "Change working directory to address book home for current or specified principal."
Added: CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/calendars.py
===================================================================
--- CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/calendars.py (rev 0)
+++ CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/calendars.py 2011-12-16 03:42:39 UTC (rev 8463)
@@ -0,0 +1,67 @@
+##
+# Copyright (c) 2007-2011 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from caldavclientlibrary.browser.command import Command, CommandError
+from caldavclientlibrary.browser.command import WrongOptions
+from caldavclientlibrary.protocol.url import URL
+import getopt
+import shlex
+
+class Cmd(Command):
+
+ def __init__(self):
+ super(Command, self).__init__()
+ self.cmds = ("calendars",)
+
+ def execute(self, name, options):
+ opts, args = getopt.getopt(shlex.split(options), '')
+ if len(opts) != 0:
+ print self.usage(name)
+ raise WrongOptions
+
+ if len(args) > 1:
+ print "Wrong number of arguments: %d" % (len(args),)
+ print self.usage(name)
+ raise WrongOptions
+ ppath = URL(url=args[0]) if args else None
+ principal = self.shell.account.getPrincipal(ppath)
+ if principal is None:
+ print "No principal found for %s" % (ppath if ppath else "current principal")
+ raise CommandError
+
+ homeset = principal.homeset
+ if not homeset:
+ print "No calendar home set found for %s" % (principal.principalPath,)
+ raise CommandError
+
+ newpath = homeset[0].path
+ result = self.shell.setWD(newpath)
+
+ if not result:
+ print "%s: No such directory" % (newpath,)
+
+ return result
+
+ def complete(self, text):
+ return self.shell.wdcomplete(text)
+
+ def usage(self, name):
+ return """Usage: %s [PRINCIPAL]
+PRINCIPAL is a principal-URL.
+""" % (name,)
+
+ def helpDescription(self):
+ return "Change working directory to calendar home for current or specified principal."
Modified: CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/cat.py
===================================================================
--- CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/cat.py 2011-12-16 00:20:51 UTC (rev 8462)
+++ CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/cat.py 2011-12-16 03:42:39 UTC (rev 8463)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2007-2010 Apple Inc. All rights reserved.
+# Copyright (c) 2007-2011 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.
@@ -25,7 +25,7 @@
def __init__(self):
super(Command, self).__init__()
- self.cmds = ("cat",)
+ self.cmds = ("cat", "more",)
def execute(self, name, options):
opts, args = getopt.getopt(shlex.split(options), '')
Modified: CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/principal.py
===================================================================
--- CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/principal.py 2011-12-16 00:20:51 UTC (rev 8462)
+++ CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/principal.py 2011-12-16 03:42:39 UTC (rev 8463)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2007-2010 Apple Inc. All rights reserved.
+# Copyright (c) 2007-2011 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.
@@ -69,6 +69,7 @@
Outbox URL : %s
Inbox URL : %s
Calendar Addresses: %s
+ Address Book Homes: %s
""" % (
principal.principalPath,
principal.getSmartDisplayName(),
@@ -80,11 +81,14 @@
principal.outboxURL,
principal.inboxURL,
utils.printList(principal.cuaddrs),
+ utils.printList(principal.adbkhomeset),
),
if print_proxies:
utils.printProxyPrincipals(self.shell.account, principal, True, True, resolve, False, refresh)
+ print ""
+
return True
def usage(self, name):
@@ -98,4 +102,4 @@
""" % (name,)
def helpDescription(self):
- return "Displays the current server login id."
+ return "Get details on principals."
Added: CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/sync.py
===================================================================
--- CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/sync.py (rev 0)
+++ CalDAVClientLibrary/trunk/caldavclientlibrary/browser/commands/sync.py 2011-12-16 03:42:39 UTC (rev 8463)
@@ -0,0 +1,86 @@
+##
+# Copyright (c) 2007-2011 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from caldavclientlibrary.browser.command import Command
+from caldavclientlibrary.browser.command import WrongOptions
+from caldavclientlibrary.protocol.url import URL
+import os
+import getopt
+import shlex
+
+synctokens = {}
+
+class Cmd(Command):
+
+ def __init__(self):
+ super(Command, self).__init__()
+ self.cmds = ("sync",)
+
+ def execute(self, name, options):
+
+ force = False
+
+ opts, args = getopt.getopt(shlex.split(options), 'f')
+
+ for name, _ignore_value in opts:
+
+ if name == "-f":
+ force = True
+ else:
+ print "Unknown option: %s" % (name,)
+ print self.usage(name)
+ raise WrongOptions
+
+ if len(args) > 1:
+ print "Wrong number of arguments: %d" % (len(args),)
+ print self.usage(name)
+ raise WrongOptions
+ elif args:
+ path = args[0]
+ if not path.startswith("/"):
+ path = os.path.join(self.shell.wd, path)
+ else:
+ path = self.shell.wd
+ if not path.endswith("/"):
+ path += "/"
+ resource = URL(url=path)
+ synctoken = synctokens.get(path, "") if not force else ""
+ newsyctoken, changed, removed, other = self.shell.account.session.syncCollection(resource, synctoken)
+ synctokens[path] = newsyctoken
+
+ for item in changed:
+ print "Changed: %s" % (item,)
+ for item in removed:
+ print "Removed: %s" % (item,)
+ for item in other:
+ print "Error: %s" % (item,)
+ print ""
+
+ return True
+
+ def complete(self, text):
+ return self.shell.wdcomplete(text)
+
+ def usage(self, name):
+ return """Usage: %s [OPTIONS] [PATH]
+PATH is a relative or absolute path.
+
+Options:
+-f force full sync
+""" % (name,)
+
+ def helpDescription(self):
+ return "Sync the contents of a directory."
Modified: CalDAVClientLibrary/trunk/caldavclientlibrary/browser/shell.py
===================================================================
--- CalDAVClientLibrary/trunk/caldavclientlibrary/browser/shell.py 2011-12-16 00:20:51 UTC (rev 8462)
+++ CalDAVClientLibrary/trunk/caldavclientlibrary/browser/shell.py 2011-12-16 03:42:39 UTC (rev 8463)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2007-2010 Apple Inc. All rights reserved.
+# Copyright (c) 2007-2011 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.
@@ -40,8 +40,7 @@
# Create the account
ssl = server.startswith("https://")
server = server[8:] if ssl else server[7:]
- paths = path
- self.account = CalDAVAccount(server, ssl=ssl, user=self.user, pswd=self.pswd, root=paths, principal=paths, logging=logging)
+ self.account = CalDAVAccount(server, ssl=ssl, user=self.user, pswd=self.pswd, root=path, principal=None, logging=logging)
atexit.register(self.saveHistory)
Added: CalDAVClientLibrary/trunk/caldavclientlibrary/client/addressbook.py
===================================================================
--- CalDAVClientLibrary/trunk/caldavclientlibrary/client/addressbook.py (rev 0)
+++ CalDAVClientLibrary/trunk/caldavclientlibrary/client/addressbook.py 2011-12-16 03:42:39 UTC (rev 8463)
@@ -0,0 +1,65 @@
+##
+# Copyright (c) 2006-2011 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from caldavclientlibrary.protocol.carddav.definitions import carddavxml
+from caldavclientlibrary.protocol.url import URL
+from caldavclientlibrary.protocol.webdav.definitions import davxml
+
+class AddressBook(object):
+
+ def __init__(self, path=None, session=None):
+ self.path = path
+ if not path.endswith("/"):
+ self.path += "/"
+ self.session = session
+ self.displayname = None
+ self.description = None
+
+ def __str__(self):
+ return "AddressBook: %s" % (self.path,)
+
+ def __repr__(self):
+ return "AddressBook: %s" % (self.path,)
+
+ def exists(self):
+ return self.session.testResource(URL(url=self.path))
+
+ def readAddressBook(self):
+ pass
+ def writeAddressBook(self, adbk):
+ pass
+
+ def readComponent(self, name=None, uid=None):
+ pass
+ def writeComponent(self, component, name=None):
+ pass
+
+ def getDisplayName(self):
+ if self.displayname is None and self.session:
+ self._getProperties()
+ return self.displayname
+
+ def getDescription(self):
+ if self.description is None and self.session:
+ self._getProperties()
+ return self.description
+
+ def _getProperties(self):
+ assert(self.session is not None)
+
+ results, _ignore_bad = self.session.getProperties(URL(url=self.path), (davxml.displayname, carddavxml.addressbook_description,))
+ self.displayname = results.get(davxml.displayname, "")
+ self.description = results.get(carddavxml.addressbook_description, "")
Modified: CalDAVClientLibrary/trunk/caldavclientlibrary/client/clientsession.py
===================================================================
--- CalDAVClientLibrary/trunk/caldavclientlibrary/client/clientsession.py 2011-12-16 00:20:51 UTC (rev 8462)
+++ CalDAVClientLibrary/trunk/caldavclientlibrary/client/clientsession.py 2011-12-16 03:42:39 UTC (rev 8463)
@@ -20,6 +20,8 @@
from caldavclientlibrary.protocol.carddav.makeaddressbook import MakeAddressBook
from caldavclientlibrary.protocol.http.authentication.basic import Basic
from caldavclientlibrary.protocol.http.authentication.digest import Digest
+from caldavclientlibrary.protocol.webdav.synccollection import SyncCollection
+from caldavclientlibrary.protocol.http.util import parseStatusLine
try:
from caldavclientlibrary.protocol.http.authentication.gssapi import Kerberos
except ImportError:
@@ -65,7 +67,7 @@
# Paths
self.rootPath = URL(url=root)
- self.principalPath = URL(url=principal)
+ self.principalPath = URL(url=principal) if principal else None
self._initCalDAVState()
@@ -77,6 +79,13 @@
def _discoverPrincipal(self):
+ current = self.getCurrentPrincipalResource(self.rootPath)
+ if current:
+ self.principalPath = current
+ if self.log:
+ self.log.write("Found current principal path: %s\n" % (self.principalPath.absoluteURL(),))
+ return
+
hrefs = self.getHrefListProperty(self.rootPath, davxml.principal_collection_set)
if not hrefs:
return
@@ -88,7 +97,7 @@
if results:
self.principalPath = results[0]
if self.log:
- self.log.write("Found principal path: %s" % (self.principalPath.absoluteURL(),))
+ self.log.write("Found principal path: %s\n" % (self.principalPath.absoluteURL(),))
return
def setUserPswd(self, user, pswd):
@@ -318,7 +327,7 @@
results = ()
# Create WebDAV principal-match
- request = PrincipalMatch(self, rurl.realtiveURL(), (davxml.principal_URL,))
+ request = PrincipalMatch(self, rurl.relativeURL(), (davxml.principal_URL,))
result = ResponseDataString()
request.setOutput(result)
@@ -336,7 +345,7 @@
# Get child element name (decode URL)
name = URL(url=item.getResource(), decode=True)
- results += (name.path,)
+ results += (name,)
else:
self.handleHTTPError(request)
@@ -362,6 +371,14 @@
return None
+ # Do current-user-principal property on the passed in url
+ def getCurrentPrincipalResource(self, rurl):
+
+ assert(isinstance(rurl, URL))
+
+ hrefs = self.getHrefListProperty(rurl, davxml.current_user_principal)
+ return hrefs[0] if hrefs else None
+
def setProperties(self, rurl, props):
assert(isinstance(rurl, URL))
@@ -477,6 +494,53 @@
if request.getStatusCode() not in (statuscodes.OK, statuscodes.Created, statuscodes.NoContent):
self.handleHTTPError(request)
+ def syncCollection(self, rurl, synctoken, props=()):
+
+ assert(isinstance(rurl, URL))
+
+ newsynctoken = ""
+ changed = set()
+ removed = set()
+ other = set()
+
+ # Create WebDAV sync REPORT
+ request = SyncCollection(self, rurl.relativeURL(), headers.Depth1, synctoken, props)
+ result = ResponseDataString()
+ request.setOutput(result)
+
+ # Process it
+ self.runSession(request)
+
+ # If its a 207 we want to parse the XML
+ if request.getStatusCode() == statuscodes.MultiStatus:
+
+ parser = PropFindParser()
+ parser.parseData(result.getData())
+
+ # Look at each propfind result
+ for item in parser.getResults().itervalues():
+
+ # Get child element name (decode URL)
+ name = URL(url=item.getResource(), decode=True)
+ status = parseStatusLine(item.status)
+ if status == 404:
+ removed.add(name)
+ elif status / 100 != 2:
+ other.add(name)
+ else:
+ changed.add(name)
+
+ # Get the new token
+ for node in parser.getOthers():
+ if node.tag == davxml.sync_token:
+ newsynctoken = node.text
+ break
+
+ else:
+ self.handleHTTPError(request)
+
+ return (newsynctoken, changed, removed, other,)
+
def deleteResource(self, rurl):
assert(isinstance(rurl, URL))
Modified: CalDAVClientLibrary/trunk/caldavclientlibrary/client/principal.py
===================================================================
--- CalDAVClientLibrary/trunk/caldavclientlibrary/client/principal.py 2011-12-16 00:20:51 UTC (rev 8462)
+++ CalDAVClientLibrary/trunk/caldavclientlibrary/client/principal.py 2011-12-16 03:42:39 UTC (rev 8463)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2007-2009 Apple Inc. All rights reserved.
+# Copyright (c) 2007-2011 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.
@@ -14,11 +14,13 @@
# limitations under the License.
##
+from caldavclientlibrary.client.addressbook import AddressBook
+from caldavclientlibrary.client.calendar import Calendar
from caldavclientlibrary.protocol.caldav.definitions import caldavxml
-from caldavclientlibrary.client.calendar import Calendar
+from caldavclientlibrary.protocol.caldav.definitions import headers
+from caldavclientlibrary.protocol.carddav.definitions import carddavxml
from caldavclientlibrary.protocol.url import URL
from caldavclientlibrary.protocol.webdav.definitions import davxml
-from caldavclientlibrary.protocol.caldav.definitions import headers
class PrincipalCache(object):
@@ -63,6 +65,7 @@
Outbox URL : %s
Inbox URL : %s
Calendar Addresses: %s
+ Address Book Homes: %s
""" % (
self.principalPath,
self.displayname,
@@ -73,7 +76,8 @@
self.homeset,
self.outboxURL,
self.inboxURL,
- self.cuaddrs
+ self.cuaddrs,
+ self.adbkhomeset,
)
def _initFields(self):
@@ -88,6 +92,7 @@
self.outboxURL = ""
self.inboxURL = ""
self.cuaddrs = ()
+ self.adbkhomeset = ()
self.proxyFor = None
self.proxyreadURL = ""
@@ -111,6 +116,7 @@
caldavxml.schedule_outbox_URL,
caldavxml.schedule_inbox_URL,
caldavxml.calendar_user_address_set,
+ carddavxml.addressbook_home_set,
),
)
if results:
@@ -133,6 +139,7 @@
self.outboxURL = results.get(caldavxml.schedule_outbox_URL, None)
self.inboxURL = results.get(caldavxml.schedule_inbox_URL, None)
self.cuaddrs = make_tuple(results.get(caldavxml.calendar_user_address_set, None))
+ self.adbkhomeset = make_tuple(results.get(carddavxml.addressbook_home_set, None))
# Get proxy resource details if proxy support is available
if self.session.hasDAVVersion(headers.calendar_proxy) and not self.proxyFor:
@@ -227,3 +234,17 @@
self.session.setProperties(self.proxywriteURL, ((davxml.group_member_set, principals),))
+ def listAddressBooks(self, root=None):
+ adbks = []
+ home = self.adbkhomeset[0]
+ if not home.path.endswith("/"):
+ home.path += "/"
+
+ results = self.session.getPropertiesOnHierarchy(home, (davxml.resourcetype,))
+ for path, items in results.iteritems():
+ if davxml.resourcetype in items:
+ rtype = items[davxml.resourcetype]
+ if rtype.find(str(davxml.collection)) is not None and rtype.find(str(carddavxml.addressbook)) is not None:
+ adbks.append(AddressBook(path=path, session=self.session))
+ return adbks
+
Modified: CalDAVClientLibrary/trunk/caldavclientlibrary/protocol/caldav/multiget.py
===================================================================
--- CalDAVClientLibrary/trunk/caldavclientlibrary/protocol/caldav/multiget.py 2011-12-16 00:20:51 UTC (rev 8462)
+++ CalDAVClientLibrary/trunk/caldavclientlibrary/protocol/caldav/multiget.py 2011-12-16 03:42:39 UTC (rev 8463)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2007-2008 Apple Inc. All rights reserved.
+# Copyright (c) 2007-2011 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.
@@ -14,14 +14,14 @@
# limitations under the License.
##
-from caldavclientlibrary.protocol.webdav.report import Report
from StringIO import StringIO
-from caldavclientlibrary.protocol.http.data.string import RequestDataString
from caldavclientlibrary.protocol.caldav.definitions import caldavxml
+from caldavclientlibrary.protocol.http.data.string import RequestDataString
+from caldavclientlibrary.protocol.utils.xmlhelpers import BetterElementTree
+from caldavclientlibrary.protocol.webdav.definitions import davxml
+from caldavclientlibrary.protocol.webdav.report import Report
from xml.etree.ElementTree import Element
from xml.etree.ElementTree import SubElement
-from caldavclientlibrary.protocol.webdav.definitions import davxml
-from caldavclientlibrary.protocol.utils.xmlhelpers import BetterElementTree
class Multiget(Report):
@@ -29,14 +29,12 @@
super(Multiget, self).__init__(session, url)
self.props = props
self.hrefs = hrefs
- pass
def initRequestData(self):
- if self.displayname or self.description or self.timezone:
- # Write XML info to a string
- os = StringIO()
- self.generateXML(os)
- self.request_data = RequestDataString(os.getvalue(), "text/xml charset=utf-8")
+ # Write XML info to a string
+ os = StringIO()
+ self.generateXML(os)
+ self.request_data = RequestDataString(os.getvalue(), "text/xml charset=utf-8")
def generateXML(self, os):
# Structure of document is:
Modified: CalDAVClientLibrary/trunk/caldavclientlibrary/protocol/webdav/definitions/davxml.py
===================================================================
--- CalDAVClientLibrary/trunk/caldavclientlibrary/protocol/webdav/definitions/davxml.py 2011-12-16 00:20:51 UTC (rev 8462)
+++ CalDAVClientLibrary/trunk/caldavclientlibrary/protocol/webdav/definitions/davxml.py 2011-12-16 03:42:39 UTC (rev 8463)
@@ -94,3 +94,6 @@
mkcol = QName(DAVNamespace, "mkcol")
mkcol_response = QName(DAVNamespace, "mkcol-response")
+
+sync_collection = QName(DAVNamespace, "sync-collection")
+sync_token = QName(DAVNamespace, "sync-token")
Modified: CalDAVClientLibrary/trunk/caldavclientlibrary/protocol/webdav/propfindparser.py
===================================================================
--- CalDAVClientLibrary/trunk/caldavclientlibrary/protocol/webdav/propfindparser.py 2011-12-16 00:20:51 UTC (rev 8462)
+++ CalDAVClientLibrary/trunk/caldavclientlibrary/protocol/webdav/propfindparser.py 2011-12-16 03:42:39 UTC (rev 8463)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2007-2010 Apple Inc. All rights reserved.
+# Copyright (c) 2007-2011 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.
@@ -67,14 +67,19 @@
def __init__(self):
self.results = {}
+ self.others = set()
def getResults(self):
return self.results
+ def getOthers(self):
+ return self.others
+
# Parse the response element down to the properties
def parseResponse(self, response):
# Verify that the node is the correct element <DAV:response>
if response.tag != davxml.response:
+ self.others.add(response)
return
# Node is the right type, so iterate over all child response nodes and process each one
Modified: CalDAVClientLibrary/trunk/caldavclientlibrary/protocol/webdav/report.py
===================================================================
--- CalDAVClientLibrary/trunk/caldavclientlibrary/protocol/webdav/report.py 2011-12-16 00:20:51 UTC (rev 8462)
+++ CalDAVClientLibrary/trunk/caldavclientlibrary/protocol/webdav/report.py 2011-12-16 03:42:39 UTC (rev 8463)
@@ -1,5 +1,5 @@
##
-# Copyright (c) 2007-2008 Apple Inc. All rights reserved.
+# Copyright (c) 2007-2011 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.
@@ -22,5 +22,5 @@
def __init__(self, session, url):
super(Report, self).__init__(session, methods.REPORT, url)
- def _setOutput(self, response_data):
+ def setOutput(self, response_data):
self.response_data = response_data;
Added: CalDAVClientLibrary/trunk/caldavclientlibrary/protocol/webdav/synccollection.py
===================================================================
--- CalDAVClientLibrary/trunk/caldavclientlibrary/protocol/webdav/synccollection.py (rev 0)
+++ CalDAVClientLibrary/trunk/caldavclientlibrary/protocol/webdav/synccollection.py 2011-12-16 03:42:39 UTC (rev 8463)
@@ -0,0 +1,77 @@
+##
+# Copyright (c) 2007-2011 Apple Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##
+
+from StringIO import StringIO
+from caldavclientlibrary.protocol.http.data.string import RequestDataString
+from caldavclientlibrary.protocol.utils.xmlhelpers import BetterElementTree
+from caldavclientlibrary.protocol.webdav.definitions import davxml, headers
+from caldavclientlibrary.protocol.webdav.report import Report
+from xml.etree.ElementTree import Element
+from xml.etree.ElementTree import SubElement
+
+class SyncCollection(Report):
+
+ def __init__(self, session, url, depth, synctoken, props=()):
+ assert(depth in (headers.Depth0, headers.Depth1, headers.DepthInfinity))
+
+ super(SyncCollection, self).__init__(session, url)
+ self.depth = depth
+ self.synctoken = synctoken
+ self.props = props
+
+ self.initRequestData()
+
+ def initRequestData(self):
+ # Write XML info to a string
+ os = StringIO()
+ self.generateXML(os)
+ self.request_data = RequestDataString(os.getvalue(), "text/xml charset=utf-8")
+
+ def addHeaders(self, hdrs):
+ # Do default
+ super(SyncCollection, self).addHeaders(hdrs)
+
+ # Add depth header
+ hdrs.append((headers.Depth, self.depth))
+
+ def generateXML(self, os):
+ # Structure of document is:
+ #
+ # <DAV:sync-collection>
+ # <DAV:sync-token>xxx</DAV:sync-token>
+ # <DAV:prop>
+ # <<names of each property as elements>>
+ # </DAV:prop>
+ # </DAV:sync-collection>
+
+ # <DAV:sync-collection> element
+ synccollection = Element(davxml.sync_collection)
+
+ # Add sync-token element
+ SubElement(synccollection, davxml.sync_token).text = self.synctoken
+
+ if self.props:
+ # <DAV:prop> element
+ prop = SubElement(synccollection, davxml.prop)
+
+ # Now add each property
+ for propname in self.props:
+ # Add property element taking namespace into account
+ SubElement(prop, propname)
+
+ # Now we have the complete document, so write it out (no indentation)
+ xmldoc = BetterElementTree(synccollection)
+ xmldoc.writeUTF8(os)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20111215/55083a8c/attachment-0001.html>
More information about the calendarserver-changes
mailing list