[CalendarServer-changes] [5105] CalendarServer/branches/users/glyph/use-system-twisted
source_changes at macosforge.org
source_changes at macosforge.org
Fri Feb 12 14:49:11 PST 2010
Revision: 5105
http://trac.macosforge.org/projects/calendarserver/changeset/5105
Author: glyph at apple.com
Date: 2010-02-12 14:49:09 -0800 (Fri, 12 Feb 2010)
Log Message:
-----------
Integrate changes from trunk.
Modified Paths:
--------------
CalendarServer/branches/users/glyph/use-system-twisted/bin/calendarserver_load_augmentdb
CalendarServer/branches/users/glyph/use-system-twisted/bin/calendarserver_make_partition
CalendarServer/branches/users/glyph/use-system-twisted/bin/calendarserver_manage_augments
CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tap/caldav.py
CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tools/gateway.py
CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tools/loadaugmentdb.py
CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tools/manageaugments.py
CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tools/managepostgres.py
CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tools/principals.py
CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tools/test/gateway/augments.xml
CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tools/test/test_gateway.py
CalendarServer/branches/users/glyph/use-system-twisted/conf/auth/augments-default.xml
CalendarServer/branches/users/glyph/use-system-twisted/conf/auth/augments-test.xml
CalendarServer/branches/users/glyph/use-system-twisted/conf/auth/augments.dtd
CalendarServer/branches/users/glyph/use-system-twisted/conf/caldavd-apple.plist
CalendarServer/branches/users/glyph/use-system-twisted/setup.py
CalendarServer/branches/users/glyph/use-system-twisted/support/Makefile.Apple
CalendarServer/branches/users/glyph/use-system-twisted/support/submit
CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/database.py
CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/aggregate.py
CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/augment.py
CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/cachingdirectory.py
CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/calendaruserproxy.py
CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/directory.py
CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/augments-test-default.xml
CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/augments-test.xml
CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/augments.xml
CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/modify/augments.xml
CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/resources/augments.xml
CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/test_augment.py
CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/test_cachedirectory.py
CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/test_modify.py
CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/test_xmlfile.py
CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/xmlaccountsparser.py
CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/xmlaugmentsparser.py
CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/xmlfile.py
CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/mail.py
Added Paths:
-----------
CalendarServer/branches/users/glyph/use-system-twisted/bin/calendarserver_manage_postgres
CalendarServer/branches/users/glyph/use-system-twisted/conf/servertoserver.xml
CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/xmlutil.py
Property Changed:
----------------
CalendarServer/branches/users/glyph/use-system-twisted/
Property changes on: CalendarServer/branches/users/glyph/use-system-twisted
___________________________________________________________________
Modified: svn:mergeinfo
- /CalendarServer/branches/config-separation:4379-4443
/CalendarServer/branches/egg-info-351:4589-4625
/CalendarServer/branches/users/cdaboo/directory-cache-on-demand-3627:3628-3644
/CalendarServer/branches/users/cdaboo/partition-4464:4465-4957
/CalendarServer/branches/users/glyph/contacts-server-merge:4971-5080
/CalendarServer/branches/users/sagen/locations-resources:5032-5051
/CalendarServer/branches/users/sagen/locations-resources-2:5052-5061
/CalendarServer/branches/users/sagen/resource-delegates-4038:4040-4067
/CalendarServer/branches/users/sagen/resource-delegates-4066:4068-4075
+ /CalendarServer/branches/config-separation:4379-4443
/CalendarServer/branches/egg-info-351:4589-4625
/CalendarServer/branches/users/cdaboo/directory-cache-on-demand-3627:3628-3644
/CalendarServer/branches/users/cdaboo/partition-4464:4465-4957
/CalendarServer/branches/users/glyph/contacts-server-merge:4971-5080
/CalendarServer/branches/users/sagen/locations-resources:5032-5051
/CalendarServer/branches/users/sagen/locations-resources-2:5052-5061
/CalendarServer/branches/users/sagen/resource-delegates-4038:4040-4067
/CalendarServer/branches/users/sagen/resource-delegates-4066:4068-4075
/CalendarServer/branches/users/sagen/resources-2:5084-5093
/CalendarServer/trunk:5084-5104
Modified: CalendarServer/branches/users/glyph/use-system-twisted/bin/calendarserver_load_augmentdb
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/bin/calendarserver_load_augmentdb 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/bin/calendarserver_load_augmentdb 2010-02-12 22:49:09 UTC (rev 5105)
@@ -32,6 +32,8 @@
child = Popen((run, "-p"), stdout=PIPE)
path, stderr = child.communicate()
+ path = path.rstrip("\n")
+
if child.wait() == 0:
sys.path[0:0] = path.split(":")
Modified: CalendarServer/branches/users/glyph/use-system-twisted/bin/calendarserver_make_partition
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/bin/calendarserver_make_partition 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/bin/calendarserver_make_partition 2010-02-12 22:49:09 UTC (rev 5105)
@@ -32,6 +32,8 @@
child = Popen((run, "-p"), stdout=PIPE)
path, stderr = child.communicate()
+ path = path.rstrip("\n")
+
if child.wait() == 0:
sys.path[0:0] = path.split(":")
Modified: CalendarServer/branches/users/glyph/use-system-twisted/bin/calendarserver_manage_augments
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/bin/calendarserver_manage_augments 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/bin/calendarserver_manage_augments 2010-02-12 22:49:09 UTC (rev 5105)
@@ -20,6 +20,7 @@
#PYTHONPATH
if __name__ == "__main__":
+
if "PYTHONPATH" in globals():
sys.path.insert(0, PYTHONPATH)
else:
@@ -30,8 +31,10 @@
run = join(home, "run")
child = Popen((run, "-p"), stdout=PIPE)
- path, stderr = child.communicate()
+ path, _ignore_stderr = child.communicate()
+ path = path.rstrip("\n")
+
if child.wait() == 0:
sys.path[0:0] = path.split(":")
Copied: CalendarServer/branches/users/glyph/use-system-twisted/bin/calendarserver_manage_postgres (from rev 5104, CalendarServer/trunk/bin/calendarserver_manage_postgres)
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/bin/calendarserver_manage_postgres (rev 0)
+++ CalendarServer/branches/users/glyph/use-system-twisted/bin/calendarserver_manage_postgres 2010-02-12 22:49:09 UTC (rev 5105)
@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+##
+# Copyright (c) 2010 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.
+##
+
+import sys
+
+#PYTHONPATH
+
+if __name__ == "__main__":
+
+ if "PYTHONPATH" in globals():
+ sys.path.insert(0, PYTHONPATH)
+ else:
+ from os.path import dirname, abspath, join
+ from subprocess import Popen, PIPE
+
+ home = dirname(dirname(abspath(__file__)))
+ run = join(home, "run")
+
+ child = Popen((run, "-p"), stdout=PIPE)
+ path, _ignore_stderr = child.communicate()
+
+ path = path.rstrip("\n")
+
+ if child.wait() == 0:
+ sys.path[0:0] = path.split(":")
+
+ from calendarserver.tools.managepostgres import main
+ main()
Modified: CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tap/caldav.py
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tap/caldav.py 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tap/caldav.py 2010-02-12 22:49:09 UTC (rev 5105)
@@ -647,14 +647,9 @@
credentialFactories.append(credFactory)
- # Set up a digest credential factory for use on the /inbox iMIP
+ # Set up a basic credential factory for use on the /inbox iMIP
# injection resource
- schemeConfig = config.Authentication.Digest
- digestCredentialFactory = QopDigestCredentialFactory(
- schemeConfig["Algorithm"],
- schemeConfig["Qop"],
- realm,
- )
+ inboxCredentialFactory = BasicCredentialFactory(realm)
#
# Setup Resource hierarchy
@@ -728,7 +723,7 @@
% (self.imipResourceClass,))
# The authenticationWrapper below will be configured to always
- # allow digest auth on /inbox
+ # allow basic auth on /inbox
root.putChild("inbox", self.imipResourceClass(root))
#
@@ -772,7 +767,7 @@
credentialFactories,
(auth.IPrincipal,),
overrides = {
- "/inbox" : (digestCredentialFactory,),
+ "/inbox" : (inboxCredentialFactory,),
}
)
Modified: CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tools/gateway.py
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tools/gateway.py 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tools/gateway.py 2010-02-12 22:49:09 UTC (rev 5105)
@@ -93,11 +93,13 @@
try:
config.directory = getDirectory()
except DirectoryError, e:
- abort(e)
+ respondWithError(str(e))
+ return
setupMemcached(config)
setupNotifications(config)
except ConfigurationError, e:
- abort(e)
+ respondWithError(e)
+ return
#
# Read commands from stdin
@@ -106,7 +108,8 @@
try:
plist = plistlib.readPlistFromString(rawInput)
except xml.parsers.expat.ExpatError, e:
- abort(str(e))
+ respondWithError(str(e))
+ return
# If the plist is an array, each element of the array is a separate
# command dictionary.
@@ -116,7 +119,8 @@
commands = [plist]
runner = Runner(config.directory, commands)
- runner.validate()
+ if not runner.validate():
+ return
#
# Start the reactor
@@ -125,6 +129,24 @@
reactor.run()
+attrMap = {
+ 'GeneratedUID' : { 'attr' : 'guid', },
+ 'RealName' : { 'attr' : 'fullName', },
+ 'RecordName' : { 'attr' : 'shortNames', },
+ 'Comment' : { 'extras' : True, 'attr' : 'comment', },
+ 'Description' : { 'extras' : True, 'attr' : 'description', },
+ 'Type' : { 'extras' : True, 'attr' : 'type', },
+ 'Capacity' : { 'extras' : True, 'attr' : 'capacity', },
+ 'Building' : { 'extras' : True, 'attr' : 'building', },
+ 'Floor' : { 'extras' : True, 'attr' : 'floor', },
+ 'Street' : { 'extras' : True, 'attr' : 'street', },
+ 'City' : { 'extras' : True, 'attr' : 'city', },
+ 'State' : { 'extras' : True, 'attr' : 'state', },
+ 'ZIP' : { 'extras' : True, 'attr' : 'zip', },
+ 'Country' : { 'extras' : True, 'attr' : 'country', },
+ 'Phone' : { 'extras' : True, 'attr' : 'phone', },
+}
+
class Runner(object):
def __init__(self, directory, commands):
@@ -135,24 +157,33 @@
# Make sure commands are valid
for command in self.commands:
if not command.has_key('command'):
- abort("'command' missing from plist")
+ respondWithError("'command' missing from plist")
+ return False
commandName = command['command']
methodName = "command_%s" % (commandName,)
if not hasattr(self, methodName):
- abort("Unknown command '%s'" % (commandName,))
+ respondWithError("Unknown command '%s'" % (commandName,))
+ return False
+ return True
@inlineCallbacks
def run(self):
- for command in self.commands:
- commandName = command['command']
- methodName = "command_%s" % (commandName,)
- if hasattr(self, methodName):
- (yield getattr(self, methodName)(command))
- else:
- abort("Unknown command '%s'" % (commandName,))
+ try:
+ for command in self.commands:
+ commandName = command['command']
+ methodName = "command_%s" % (commandName,)
+ if hasattr(self, methodName):
+ (yield getattr(self, methodName)(command))
+ else:
+ respondWithError("Unknown command '%s'" % (commandName,))
- reactor.stop()
+ except Exception, e:
+ respondWithError("Command failed: '%s'" % (str(e),))
+ raise
+ finally:
+ reactor.stop()
+
# Locations
def command_getLocationList(self, command):
@@ -160,18 +191,53 @@
def command_createLocation(self, command):
+ kwargs = {}
+ for key, info in attrMap.iteritems():
+ if command.has_key(key):
+ kwargs[info['attr']] = command[key]
try:
- self.dir.createRecord("locations", guid=command['GeneratedUID'],
- shortNames=command['RecordName'], fullName=command['RealName'])
+ self.dir.createRecord("locations", **kwargs)
except DirectoryError, e:
- abort(str(e))
+ respondWithError(str(e))
+ return
respondWithRecordsOfType(self.dir, command, "locations")
+ def command_getLocationAttributes(self, command):
+ guid = command['GeneratedUID']
+ record = self.dir.recordWithGUID(guid)
+ recordDict = recordToDict(record)
+ # principal = principalForPrincipalID(guid, directory=self.dir)
+ # recordDict['AutoSchedule'] = principal.getAutoSchedule()
+ respond(command, recordDict)
+
+ def command_setLocationAttributes(self, command):
+
+ kwargs = {}
+ for key, info in attrMap.iteritems():
+ if command.has_key(key):
+ kwargs[info['attr']] = command[key]
+ try:
+ self.dir.updateRecord("locations", **kwargs)
+ except DirectoryError, e:
+ respondWithError(str(e))
+ return
+
+ # principal = principalForPrincipalID(command['GeneratedUID'],
+ # directory=self.dir)
+ # principal.setAutoSchedule(command.get('AutoSchedule', False))
+
+ self.command_getLocationAttributes(command)
+
def command_deleteLocation(self, command):
+ kwargs = {}
+ for key, info in attrMap.iteritems():
+ if command.has_key(key):
+ kwargs[info['attr']] = command[key]
try:
- self.dir.destroyRecord("locations", guid=command['GeneratedUID'])
+ self.dir.destroyRecord("locations", **kwargs)
except DirectoryError, e:
- abort(str(e))
+ respondWithError(str(e))
+ return
respondWithRecordsOfType(self.dir, command, "locations")
# Resources
@@ -180,18 +246,53 @@
respondWithRecordsOfType(self.dir, command, "resources")
def command_createResource(self, command):
+ kwargs = {}
+ for key, info in attrMap.iteritems():
+ if command.has_key(key):
+ kwargs[info['attr']] = command[key]
try:
- self.dir.createRecord("resources", guid=command['GeneratedUID'],
- shortNames=command['RecordName'], fullName=command['RealName'])
+ self.dir.createRecord("resources", **kwargs)
except DirectoryError, e:
- abort(str(e))
+ respondWithError(str(e))
+ return
respondWithRecordsOfType(self.dir, command, "resources")
+ def command_getResourceAttributes(self, command):
+ guid = command['GeneratedUID']
+ record = self.dir.recordWithGUID(guid)
+ recordDict = recordToDict(record)
+ # principal = principalForPrincipalID(guid, directory=self.dir)
+ # recordDict['AutoSchedule'] = principal.getAutoSchedule()
+ respond(command, recordDict)
+
+ def command_setResourceAttributes(self, command):
+
+ kwargs = {}
+ for key, info in attrMap.iteritems():
+ if command.has_key(key):
+ kwargs[info['attr']] = command[key]
+ try:
+ self.dir.updateRecord("resources", **kwargs)
+ except DirectoryError, e:
+ respondWithError(str(e))
+ return
+
+ # principal = principalForPrincipalID(command['GeneratedUID'],
+ # directory=self.dir)
+ # principal.setAutoSchedule(command.get('AutoSchedule', False))
+
+ self.command_getResourceAttributes(command)
+
def command_deleteResource(self, command):
+ kwargs = {}
+ for key, info in attrMap.iteritems():
+ if command.has_key(key):
+ kwargs[info['attr']] = command[key]
try:
- self.dir.destroyRecord("resources", guid=command['GeneratedUID'])
+ self.dir.destroyRecord("resources", **kwargs)
except DirectoryError, e:
- abort(str(e))
+ respondWithError(str(e))
+ return
respondWithRecordsOfType(self.dir, command, "resources")
# Proxies
@@ -199,16 +300,28 @@
@inlineCallbacks
def command_listWriteProxies(self, command):
principal = principalForPrincipalID(command['Principal'], directory=self.dir)
+ if principal is None:
+ respondWithError("Principal not found: %s" % (command['Principal'],))
+ return
(yield respondWithProxies(self.dir, command, principal, "write"))
@inlineCallbacks
def command_addWriteProxy(self, command):
- principal = principalForPrincipalID(command['Principal'], directory=self.dir)
+ principal = principalForPrincipalID(command['Principal'],
+ directory=self.dir)
+ if principal is None:
+ respondWithError("Principal not found: %s" % (command['Principal'],))
+ return
+
proxy = principalForPrincipalID(command['Proxy'], directory=self.dir)
+ if proxy is None:
+ respondWithError("Proxy not found: %s" % (command['Proxy'],))
+ return
try:
(yield addProxy(principal, "write", proxy))
except ProxyError, e:
- abort(str(e))
+ respondWithError(str(e))
+ return
except ProxyWarning, e:
pass
(yield respondWithProxies(self.dir, command, principal, "write"))
@@ -216,11 +329,18 @@
@inlineCallbacks
def command_removeWriteProxy(self, command):
principal = principalForPrincipalID(command['Principal'], directory=self.dir)
+ if principal is None:
+ respondWithError("Principal not found: %s" % (command['Principal'],))
+ return
proxy = principalForPrincipalID(command['Proxy'], directory=self.dir)
+ if proxy is None:
+ respondWithError("Proxy not found: %s" % (command['Proxy'],))
+ return
try:
(yield removeProxy(principal, proxy, proxyTypes=("write",)))
except ProxyError, e:
- abort(str(e))
+ respondWithError(str(e))
+ return
except ProxyWarning, e:
pass
(yield respondWithProxies(self.dir, command, principal, "write"))
@@ -228,16 +348,26 @@
@inlineCallbacks
def command_listReadProxies(self, command):
principal = principalForPrincipalID(command['Principal'], directory=self.dir)
+ if principal is None:
+ respondWithError("Principal not found: %s" % (command['Principal'],))
+ return
(yield respondWithProxies(self.dir, command, principal, "read"))
@inlineCallbacks
def command_addReadProxy(self, command):
principal = principalForPrincipalID(command['Principal'], directory=self.dir)
+ if principal is None:
+ respondWithError("Principal not found: %s" % (command['Principal'],))
+ return
proxy = principalForPrincipalID(command['Proxy'], directory=self.dir)
+ if proxy is None:
+ respondWithError("Proxy not found: %s" % (command['Proxy'],))
+ return
try:
(yield addProxy(principal, "read", proxy))
except ProxyError, e:
- abort(str(e))
+ respondWithError(str(e))
+ return
except ProxyWarning, e:
pass
(yield respondWithProxies(self.dir, command, principal, "read"))
@@ -245,11 +375,18 @@
@inlineCallbacks
def command_removeReadProxy(self, command):
principal = principalForPrincipalID(command['Principal'], directory=self.dir)
+ if principal is None:
+ respondWithError("Principal not found: %s" % (command['Principal'],))
+ return
proxy = principalForPrincipalID(command['Proxy'], directory=self.dir)
+ if proxy is None:
+ respondWithError("Proxy not found: %s" % (command['Proxy'],))
+ return
try:
(yield removeProxy(principal, proxy, proxyTypes=("read",)))
except ProxyError, e:
- abort(str(e))
+ respondWithError(str(e))
+ return
except ProxyWarning, e:
pass
(yield respondWithProxies(self.dir, command, principal, "read"))
@@ -271,27 +408,38 @@
})
+def recordToDict(record):
+ recordDict = {}
+ for key, info in attrMap.iteritems():
+ try:
+ if info.get('extras', False):
+ value = record.extras[info['attr']]
+ else:
+ value = getattr(record, info['attr'])
+ recordDict[key] = value
+ except KeyError:
+ pass
+ return recordDict
+
def respondWithRecordsOfType(directory, command, recordType):
result = []
for record in directory.listRecords(recordType):
- result.append( {
- 'GeneratedUID' : record.guid,
- 'RecordName' : [n for n in record.shortNames],
- 'RealName' : record.fullName,
- 'AutoSchedule' : record.autoSchedule,
- } )
+ recordDict = recordToDict(record)
+ result.append(recordDict)
respond(command, result)
def respond(command, result):
sys.stdout.write(plistlib.writePlistToString( { 'command' : command['command'], 'result' : result } ) )
-def abort(msg, status=1):
+def respondWithError(msg, status=1):
sys.stdout.write(plistlib.writePlistToString( { 'error' : msg, } ) )
+ """
try:
reactor.stop()
except RuntimeError:
pass
sys.exit(status)
+ """
if __name__ == "__main__":
main()
Modified: CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tools/loadaugmentdb.py
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tools/loadaugmentdb.py 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tools/loadaugmentdb.py 2010-02-12 22:49:09 UTC (rev 5105)
@@ -160,23 +160,30 @@
def run(dbxml):
try:
- guids = set((yield augment.AugmentService.getAllGUIDs()))
+ uids = set((yield augment.AugmentService.getAllUIDs()))
added = 0
updated = 0
removed = 0
if dbxml:
+ add_records = list()
+ modify_records = list()
for record in dbxml.db.values():
- yield augment.AugmentService.addAugmentRecord(record, record.guid in guids)
- if record.guid in guids:
- updated += 1
+ if record.uid in uids:
+ modify_records.append(record)
else:
- added += 1
- for guid in guids.difference(dbxml.db.keys()):
- yield augment.AugmentService.removeAugmentRecord(guid)
- removed += 1
+ add_records.append(record)
+ yield augment.AugmentService.addAugmentRecords(add_records, False)
+ added = len(add_records)
+
+ yield augment.AugmentService.addAugmentRecords(modify_records, True)
+ updated = len(modify_records)
+
+ remove_uids = uids.difference(dbxml.db.keys())
+ yield augment.AugmentService.removeAugmentRecords(remove_uids)
+ removed = len(remove_uids)
else:
yield augment.AugmentService.clean()
- removed = len(guids)
+ removed = len(uids)
print "Changes:"
print " Added: %d" % (added,)
Modified: CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tools/manageaugments.py
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tools/manageaugments.py 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tools/manageaugments.py 2010-02-12 22:49:09 UTC (rev 5105)
@@ -15,145 +15,26 @@
# limitations under the License.
##
+from calendarserver.tools.loadaugmentdb import StandardIOObserver
+from calendarserver.tools.util import loadConfig, getDirectory,\
+ autoDisableMemcached
+from grp import getgrnam
from optparse import OptionParser
-from twistedcaldav.directory import xmlaugmentsparser
-from xml.etree.ElementTree import ElementTree, tostring, SubElement
-from xml.parsers.expat import ExpatError
-import sys
+from pwd import getpwnam
+from twext.log import setLogLevelForNamespace
+from twisted.internet import reactor
+from twisted.python.util import switchUID
+from twistedcaldav.config import config, ConfigurationError
+from twistedcaldav.directory import augment
+from twistedcaldav.directory.augment import AugmentRecord
import os
+import sys
+from twisted.internet.defer import inlineCallbacks
def error(s):
print s
sys.exit(1)
-def readXML(xmlfile):
-
- # Read in XML
- try:
- tree = ElementTree(file=xmlfile)
- except ExpatError, e:
- error("Unable to parse file '%s' because: %s" % (xmlfile, e,))
-
- # Verify that top-level element is correct
- augments_node = tree.getroot()
- if augments_node.tag != xmlaugmentsparser.ELEMENT_AUGMENTS:
- error("Ignoring file '%s' because it is not a augments file" % (xmlfile,))
-
- return augments_node
-
-def writeXML(xmlfile, root):
-
- data = """<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE augments SYSTEM "augments.dtd">
-
-""" + tostring(root)
-
- with open(xmlfile, "w") as f:
- f.write(data)
-
-def addSubElement(parent, tag, text=None, indent=0):
-
- child = SubElement(parent, tag)
- child.text = text
- child.tail = "\n" + " " * indent
- return child
-
-def changeSubElementText(parent, tag, text):
-
- child = parent.find(tag)
- child.text = text
-
-def doAdd(xmlfile, guid, host, enable_calendar, auto_schedule):
-
- augments_node = readXML(xmlfile)
-
- # Make sure GUID is not already present
- for child in augments_node.getchildren():
-
- if child.tag != xmlaugmentsparser.ELEMENT_RECORD:
- error("Unknown augment type: '%s' in augment file: '%s'" % (child.tag, xmlfile,))
-
- for node in child.getchildren():
-
- if node.tag == xmlaugmentsparser.ELEMENT_GUID and node.text == guid:
- error("Cannot add guid '%s' because it already exists in augment file: '%s'" % (guid, xmlfile,))
-
- # Create new record
- if len(augments_node.getchildren()):
- augments_node.getchildren()[-1].tail = "\n "
- record = addSubElement(augments_node, xmlaugmentsparser.ELEMENT_RECORD, "\n ")
- addSubElement(record, xmlaugmentsparser.ELEMENT_GUID, guid, 4)
- addSubElement(record, xmlaugmentsparser.ELEMENT_ENABLE, "true", 4)
- addSubElement(record, xmlaugmentsparser.ELEMENT_HOSTEDAT, host, 4)
- addSubElement(record, xmlaugmentsparser.ELEMENT_ENABLECALENDAR, "true" if enable_calendar else "false", 4)
- addSubElement(record, xmlaugmentsparser.ELEMENT_AUTOSCHEDULE, "true" if auto_schedule else "false", 2)
-
- # Modify xmlfile
- writeXML(xmlfile, augments_node)
- print "Added guid '%s' in augment file: '%s'" % (guid, xmlfile,)
-
-def doModify(xmlfile, guid, host, enable_calendar, auto_schedule):
-
- augments_node = readXML(xmlfile)
-
- # Make sure GUID is present
- for child in augments_node.getchildren():
-
- if child.tag != xmlaugmentsparser.ELEMENT_RECORD:
- error("Unknown augment type: '%s' in augment file: '%s'" % (child.tag, xmlfile,))
-
- for node in child.getchildren():
-
- if node.tag == xmlaugmentsparser.ELEMENT_GUID and node.text == guid:
- break
- else:
- continue
- break
- else:
- error("Cannot modify guid '%s' because it does not exist in augment file: '%s'" % (guid, xmlfile,))
-
- # Modify record
- if host is not None:
- child.find(xmlaugmentsparser.ELEMENT_HOSTEDAT).text = host
- child.find(xmlaugmentsparser.ELEMENT_ENABLECALENDAR).text = "true" if enable_calendar else "false"
- child.find(xmlaugmentsparser.ELEMENT_AUTOSCHEDULE).text = "true" if auto_schedule else "false"
-
- # Modify xmlfile
- writeXML(xmlfile, augments_node)
- print "Modified guid '%s' in augment file: '%s'" % (guid, xmlfile,)
-
-def doRemove(xmlfile, guid):
-
- augments_node = readXML(xmlfile)
-
- # Make sure GUID is present
- for child in augments_node.getchildren():
-
- if child.tag != xmlaugmentsparser.ELEMENT_RECORD:
- error("Unknown augment type: '%s' in augment file: '%s'" % (child.tag, xmlfile,))
-
- for node in child.getchildren():
-
- if node.tag == xmlaugmentsparser.ELEMENT_GUID and node.text == guid:
- break
- else:
- continue
- augments_node.remove(child)
- break
- else:
- error("Cannot remove guid '%s' because it does not exist in augment file: '%s'" % (guid, xmlfile,))
-
- # Modify xmlfile
- writeXML(xmlfile, augments_node)
- print "Removed guid '%s' from augment file: '%s'" % (guid, xmlfile,)
-
-def doPrint(xmlfile):
-
- # Read in XML
- augments_node = readXML(xmlfile)
-
- print tostring(augments_node)
-
def main():
usage = "%prog [options] ACTION"
@@ -163,7 +44,6 @@
add: add a user record
modify: modify a user record
remove: remove a user record
- print: print all user records
"""
description = "Tool to manipulate CalendarServer augments XML file"
version = "%prog v1.0"
@@ -171,47 +51,97 @@
parser.epilog = epilog
parser.format_epilog = lambda _:epilog
- parser.add_option("-f", "--file", dest="xmlfilename",
- help="XML augment file to manipulate", metavar="FILE")
- parser.add_option("-g", "--guid", dest="guid",
- help="OD GUID to manipulate", metavar="GUID")
- parser.add_option("-i", "--guidfile", dest="guidfile",
- help="File containing a list of GUIDs to manipulate", metavar="GUIDFILE")
+ parser.add_option("-f", "--file", dest="configfilename",
+ help="caldavd.plist defining Augment Service", metavar="FILE")
+ parser.add_option("-u", "--uid", dest="uid",
+ help="OD GUID to manipulate", metavar="UID")
+ parser.add_option("-i", "--uidfile", dest="uidfile",
+ help="File containing a list of GUIDs to manipulate", metavar="UIDFILE")
parser.add_option("-n", "--node", dest="node",
- help="Partition node to assign to GUID", metavar="NODE")
+ help="Partition node to assign to UID", metavar="NODE")
parser.add_option("-c", "--enable-calendar", action="store_true", dest="enable_calendar",
- default=True, help="Enable calendaring for this GUID: %default")
- parser.add_option("-a", "--auto-schedule", action="store_true", dest="auto_schedule",
- default=False, help="Enable auto-schedule for this GUID: %default")
+ default=True, help="Enable calendaring for this UID: %default")
+ parser.add_option("-a", "--enable-addressbooks", action="store_true", dest="enable_addressbook",
+ default=True, help="Enable calendaring for this UID: %default")
+ parser.add_option("-s", "--auto-schedule", action="store_true", dest="auto_schedule",
+ default=False, help="Enable auto-schedule for this UID: %default")
(options, args) = parser.parse_args()
if len(args) != 1:
parser.error("incorrect number of arguments")
- guids = []
- if options.guid:
- guids.append(options.guid)
- elif options.guidfile:
- if not os.path.exists(options.guidfile):
- parser.error("File containing list of GUIDs does not exist")
- with open(options.guidfile) as f:
- for line in f:
- guids.append(line[:-1])
-
- if args[0] == "add":
- if not options.node:
- parser.error("Partition node must be specified when adding")
- for guid in guids:
- doAdd(options.xmlfilename, guid, options.node, options.enable_calendar, options.auto_schedule)
- elif args[0] == "modify":
- for guid in guids:
- doModify(options.xmlfilename, guid, options.node, options.enable_calendar, options.auto_schedule)
- elif args[0] == "remove":
- for guid in guids:
- doRemove(options.xmlfilename, guid)
- elif args[0] == "print":
- doPrint(options.xmlfilename)
+ observer = StandardIOObserver()
+ observer.start()
+ #
+ # Get configuration
+ #
+ try:
+ loadConfig(options.configfilename)
+ setLogLevelForNamespace(None, "warn")
+
+ # Shed privileges
+ if config.UserName and config.GroupName and os.getuid() == 0:
+ uid = getpwnam(config.UserName).pw_uid
+ gid = getgrnam(config.GroupName).gr_gid
+ switchUID(uid, uid, gid)
+
+ os.umask(config.umask)
+
+ config.directory = getDirectory()
+ autoDisableMemcached(config)
+ except ConfigurationError, e:
+ usage("Unable to start: %s" % (e,))
+
+ #
+ # Start the reactor
+ #
+ reactor.callLater(0, run, parser, options, args)
+ reactor.run()
+
+def makeRecord(uid, options):
+ return AugmentRecord(
+ uid = uid,
+ enabled = True,
+ hostedAt = options.node,
+ enabledForCalendaring = options.enable_calendar,
+ enabledForAddressBooks = options.enable_addressbook,
+ autoSchedule = options.auto_schedule,
+ )
+
+ at inlineCallbacks
+def run(parser, options, args):
+
+ try:
+ uids = []
+ if options.uid:
+ uids.append(options.uid)
+ elif options.uidfile:
+ if not os.path.exists(options.uidfile):
+ parser.error("File containing list of UIDs does not exist")
+ with open(options.uidfile) as f:
+ for line in f:
+ uids.append(line[:-1])
+
+ if args[0] == "add":
+ if not options.node:
+ parser.error("Partition node must be specified when adding")
+ yield augment.AugmentService.addAugmentRecords([makeRecord(uid, options) for uid in uids], False)
+ for uid in uids:
+ print "Added uid '%s' to augment database" % (uid,)
+ elif args[0] == "modify":
+ yield augment.AugmentService.addAugmentRecords([makeRecord(uid, options) for uid in uids], True)
+ for uid in uids:
+ print "Modified uid '%s' in augment database" % (uid,)
+ elif args[0] == "remove":
+ yield augment.AugmentService.removeAugmentRecords(uids)
+ for uid in uids:
+ print "Removed uid '%s' from augment database" % (uid,)
+ else:
+ parser.error("Unknown argument")
+ finally:
+ reactor.stop()
+
if __name__ == '__main__':
main()
Modified: CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tools/managepostgres.py
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tools/managepostgres.py 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tools/managepostgres.py 2010-02-12 22:49:09 UTC (rev 5105)
@@ -69,9 +69,9 @@
def doClean(basedir):
- cmd("rm -rf %s/data" % (basedir, basedir,))
+ cmd("rm -rf %s/data" % (basedir,))
-if __name__ == '__main__':
+def main():
usage = "%prog [options] ACTION"
epilog = """
@@ -93,7 +93,7 @@
parser.add_option("-v", "--verbose", action="store_true", dest="verbose",
default=True, help="Use debug logging for PostgreSQL")
parser.add_option("-d", "--base-dir", dest="basedir",
- default="%s/../postgresql-8.4.1/_root" % (os.getcwd(),), help="Base directory for PostgreSQL install")
+ default="%s/../postgresql-8.4.2/_root" % (os.getcwd(),), help="Base directory for PostgreSQL install")
(options, args) = parser.parse_args()
@@ -112,3 +112,6 @@
doClean(options.basedir)
else:
parser.error("incorrect argument '%s'" % (args[0],))
+
+if __name__ == '__main__':
+ main()
Modified: CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tools/principals.py
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tools/principals.py 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tools/principals.py 2010-02-12 22:49:09 UTC (rev 5105)
@@ -334,7 +334,7 @@
if checkOnly:
return None
- return directory.principalCollection.principalForUID(str(guid))
+ return directory.principalCollection.principalForUID(principalID)
except ValueError:
pass
Modified: CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tools/test/gateway/augments.xml
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tools/test/gateway/augments.xml 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tools/test/gateway/augments.xml 2010-02-12 22:49:09 UTC (rev 5105)
@@ -20,17 +20,17 @@
<augments>
<record>
- <guid>user01</guid>
+ <uid>user01</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
</record>
<record>
- <guid>user02</guid>
+ <uid>user02</uid>
<enable>false</enable>
<enable-calendar>false</enable-calendar>
</record>
<record>
- <guid>location01</guid>
+ <uid>location01</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
</record>
Modified: CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tools/test/test_gateway.py
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tools/test/test_gateway.py 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/calendarserver/tools/test/test_gateway.py 2010-02-12 22:49:09 UTC (rev 5105)
@@ -185,27 +185,81 @@
self.assertEquals(len(results['result']), 10)
@inlineCallbacks
+ def test_getLocationAttributes(self):
+ results = yield self.runCommand(command_createLocation)
+ results = yield self.runCommand(command_getLocationAttributes)
+ self.assertEquals(results['result']['Building'], "Test Building")
+ self.assertEquals(results['result']['City'], "Cupertino")
+ self.assertEquals(results['result']['Capacity'], "40")
+ self.assertEquals(results['result']['Description'], "Test Description")
+ self.assertEquals(results['result']['ZIP'], "95014")
+ self.assertEquals(results['result']['Floor'], "First")
+ self.assertEquals(results['result']['RecordName'], ['createdlocation01'])
+ self.assertEquals(results['result']['State'], "CA")
+ self.assertEquals(results['result']['Street'], "1 Infinite Loop")
+ self.assertEquals(results['result']['RealName'], "Created Location 01")
+ self.assertEquals(results['result']['Comment'], "Test Comment")
+
+ @inlineCallbacks
def test_getResourceList(self):
results = yield self.runCommand(command_getResourceList)
self.assertEquals(len(results['result']), 10)
@inlineCallbacks
+ def test_getResourceAttributes(self):
+ results = yield self.runCommand(command_createResource)
+ results = yield self.runCommand(command_getResourceAttributes)
+ self.assertEquals(results['result']['Comment'], "Test Comment")
+
+ @inlineCallbacks
def test_createLocation(self):
directory = getDirectory()
- record = directory.recordWithUID("createdlocation01")
+ record = directory.recordWithUID("836B1B66-2E9A-4F46-8B1C-3DD6772C20B2")
self.assertEquals(record, None)
yield self.runCommand(command_createLocation)
directory.flushCaches()
- record = directory.recordWithUID("createdlocation01")
+ record = directory.recordWithUID("836B1B66-2E9A-4F46-8B1C-3DD6772C20B2")
self.assertNotEquals(record, None)
+ self.assertEquals(record.extras['comment'], "Test Comment")
+ self.assertEquals(record.extras['building'], "Test Building")
+ self.assertEquals(record.extras['floor'], "First")
+ self.assertEquals(record.extras['capacity'], "40")
+ self.assertEquals(record.extras['street'], "1 Infinite Loop")
+ self.assertEquals(record.extras['city'], "Cupertino")
+ self.assertEquals(record.extras['state'], "CA")
+ self.assertEquals(record.extras['zip'], "95014")
+ self.assertEquals(record.extras['country'], "USA")
+ self.assertEquals(record.extras['phone'], "(408) 555-1212")
+
@inlineCallbacks
- def test_destroyRecord(self):
+ def test_setLocationAttributes(self):
directory = getDirectory()
+ yield self.runCommand(command_createLocation)
+ record = directory.recordWithUID("836B1B66-2E9A-4F46-8B1C-3DD6772C20B2")
+ yield self.runCommand(command_setLocationAttributes)
+ directory.flushCaches()
+ record = directory.recordWithUID("836B1B66-2E9A-4F46-8B1C-3DD6772C20B2")
+
+ self.assertEquals(record.extras['comment'], "Updated Test Comment")
+ self.assertEquals(record.extras['building'], "Updated Test Building")
+ self.assertEquals(record.extras['floor'], "Second")
+ self.assertEquals(record.extras['capacity'], "41")
+ self.assertEquals(record.extras['street'], "2 Infinite Loop")
+ self.assertEquals(record.extras['city'], "Updated Cupertino")
+ self.assertEquals(record.extras['state'], "Updated CA")
+ self.assertEquals(record.extras['zip'], "95015")
+ self.assertEquals(record.extras['country'], "Updated USA")
+ self.assertEquals(record.extras['phone'], "(408) 555-1213")
+
+ @inlineCallbacks
+ def test_destroyLocation(self):
+ directory = getDirectory()
+
record = directory.recordWithUID("location01")
self.assertNotEquals(record, None)
@@ -216,6 +270,46 @@
self.assertEquals(record, None)
@inlineCallbacks
+ def test_createResource(self):
+ directory = getDirectory()
+
+ record = directory.recordWithUID("AF575A61-CFA6-49E1-A0F6-B5662C9D9801")
+ self.assertEquals(record, None)
+
+ yield self.runCommand(command_createResource)
+
+ directory.flushCaches()
+ record = directory.recordWithUID("AF575A61-CFA6-49E1-A0F6-B5662C9D9801")
+ self.assertNotEquals(record, None)
+
+ @inlineCallbacks
+ def test_setResourceAttributes(self):
+ directory = getDirectory()
+
+ yield self.runCommand(command_createResource)
+ record = directory.recordWithUID("AF575A61-CFA6-49E1-A0F6-B5662C9D9801")
+ self.assertEquals(record.fullName, "Laptop 1")
+
+ yield self.runCommand(command_setResourceAttributes)
+
+ directory.flushCaches()
+ record = directory.recordWithUID("AF575A61-CFA6-49E1-A0F6-B5662C9D9801")
+ self.assertEquals(record.fullName, "Updated Laptop 1")
+
+ @inlineCallbacks
+ def test_destroyResource(self):
+ directory = getDirectory()
+
+ record = directory.recordWithUID("resource01")
+ self.assertNotEquals(record, None)
+
+ yield self.runCommand(command_deleteResource)
+
+ directory.flushCaches()
+ record = directory.recordWithUID("resource01")
+ self.assertEquals(record, None)
+
+ @inlineCallbacks
def test_addWriteProxy(self):
results = yield self.runCommand(command_addWriteProxy)
self.assertEquals(len(results['result']['Proxies']), 1)
@@ -228,18 +322,6 @@
-command_deleteLocation = """<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>command</key>
- <string>deleteLocation</string>
- <key>GeneratedUID</key>
- <string>guidoffice3</string>
-</dict>
-</plist>
-"""
-
command_addReadProxy = """<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
@@ -277,17 +359,40 @@
<key>AutoSchedule</key>
<true/>
<key>GeneratedUID</key>
- <string>createdlocation01</string>
+ <string>836B1B66-2E9A-4F46-8B1C-3DD6772C20B2</string>
<key>RealName</key>
<string>Created Location 01</string>
<key>RecordName</key>
<array>
<string>createdlocation01</string>
</array>
+ <key>Comment</key>
+ <string>Test Comment</string>
+ <key>Description</key>
+ <string>Test Description</string>
+ <key>Building</key>
+ <string>Test Building</string>
+ <key>Floor</key>
+ <string>First</string>
+ <key>Capacity</key>
+ <string>40</string>
+ <key>Street</key>
+ <string>1 Infinite Loop</string>
+ <key>City</key>
+ <string>Cupertino</string>
+ <key>State</key>
+ <string>CA</string>
+ <key>ZIP</key>
+ <string>95014</string>
+ <key>Country</key>
+ <string>USA</string>
+ <key>Phone</key>
+ <string>(408) 555-1212</string>
</dict>
</plist>
"""
+
command_createResource = """<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
@@ -297,13 +402,15 @@
<key>AutoSchedule</key>
<true/>
<key>GeneratedUID</key>
- <string>guidlaptop1</string>
+ <string>AF575A61-CFA6-49E1-A0F6-B5662C9D9801</string>
<key>RealName</key>
<string>Laptop 1</string>
<key>RecordName</key>
<array>
<string>laptop1</string>
</array>
+ <key>Comment</key>
+ <string>Test Comment</string>
</dict>
</plist>
"""
@@ -327,7 +434,7 @@
<key>command</key>
<string>deleteResource</string>
<key>GeneratedUID</key>
- <string>guidlaptop1</string>
+ <string>resource01</string>
</dict>
</plist>
"""
@@ -403,3 +510,89 @@
</dict>
</plist>
"""
+
+command_setLocationAttributes = """<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>command</key>
+ <string>setLocationAttributes</string>
+ <key>AutoSchedule</key>
+ <false/>
+ <key>GeneratedUID</key>
+ <string>836B1B66-2E9A-4F46-8B1C-3DD6772C20B2</string>
+ <key>RealName</key>
+ <string>Updated Location 01</string>
+ <key>RecordName</key>
+ <array>
+ <string>createdlocation01</string>
+ </array>
+ <key>Comment</key>
+ <string>Updated Test Comment</string>
+ <key>Description</key>
+ <string>Updated Test Description</string>
+ <key>Building</key>
+ <string>Updated Test Building</string>
+ <key>Floor</key>
+ <string>Second</string>
+ <key>Capacity</key>
+ <string>41</string>
+ <key>Street</key>
+ <string>2 Infinite Loop</string>
+ <key>City</key>
+ <string>Updated Cupertino</string>
+ <key>State</key>
+ <string>Updated CA</string>
+ <key>ZIP</key>
+ <string>95015</string>
+ <key>Country</key>
+ <string>Updated USA</string>
+ <key>Phone</key>
+ <string>(408) 555-1213</string>
+</dict>
+</plist>
+"""
+
+command_getLocationAttributes = """<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>command</key>
+ <string>getLocationAttributes</string>
+ <key>GeneratedUID</key>
+ <string>836B1B66-2E9A-4F46-8B1C-3DD6772C20B2</string>
+</dict>
+</plist>
+"""
+
+command_setResourceAttributes = """<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>command</key>
+ <string>setResourceAttributes</string>
+ <key>AutoSchedule</key>
+ <false/>
+ <key>GeneratedUID</key>
+ <string>AF575A61-CFA6-49E1-A0F6-B5662C9D9801</string>
+ <key>RealName</key>
+ <string>Updated Laptop 1</string>
+ <key>RecordName</key>
+ <array>
+ <string>laptop1</string>
+ </array>
+</dict>
+</plist>
+"""
+
+command_getResourceAttributes = """<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>command</key>
+ <string>getResourceAttributes</string>
+ <key>GeneratedUID</key>
+ <string>AF575A61-CFA6-49E1-A0F6-B5662C9D9801</string>
+</dict>
+</plist>
+"""
Modified: CalendarServer/branches/users/glyph/use-system-twisted/conf/auth/augments-default.xml
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/conf/auth/augments-default.xml 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/conf/auth/augments-default.xml 2010-02-12 22:49:09 UTC (rev 5105)
@@ -20,8 +20,9 @@
<augments>
<record>
- <guid>Default</guid>
+ <uid>Default</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
</record>
</augments>
Modified: CalendarServer/branches/users/glyph/use-system-twisted/conf/auth/augments-test.xml
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/conf/auth/augments-test.xml 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/conf/auth/augments-test.xml 2010-02-12 22:49:09 UTC (rev 5105)
@@ -20,31 +20,31 @@
<augments>
<record>
- <guid>Default</guid>
+ <uid>Default</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
<enable-addressbook>true</enable-addressbook>
</record>
<record repeat="10">
- <guid>location%02d</guid>
+ <uid>location%02d</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
<enable-addressbook>true</enable-addressbook>
<auto-schedule>true</auto-schedule>
</record>
<record repeat="10">
- <guid>resource%02d</guid>
+ <uid>resource%02d</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
<enable-addressbook>true</enable-addressbook>
<auto-schedule>true</auto-schedule>
</record>
<record repeat="4">
- <guid>group%02d</guid>
+ <uid>group%02d</uid>
<enable>true</enable>
</record>
<record>
- <guid>disabledgroup</guid>
+ <uid>disabledgroup</uid>
<enable>false</enable>
</record>
</augments>
Modified: CalendarServer/branches/users/glyph/use-system-twisted/conf/auth/augments.dtd
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/conf/auth/augments.dtd 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/conf/auth/augments.dtd 2010-02-12 22:49:09 UTC (rev 5105)
@@ -16,12 +16,13 @@
<!ELEMENT augments (record*) >
- <!ELEMENT record (guid, enable, hosted-at?, enable-calendar?, auto-schedule?)>
+ <!ELEMENT record (guid, enable, hosted-at?, enable-calendar?, enable-addressbook?, auto-schedule?)>
<!ATTLIST record repeat CDATA "1">
- <!ELEMENT guid (#PCDATA)>
- <!ELEMENT enable (#PCDATA)>
- <!ELEMENT hosted-at (#PCDATA)>
- <!ELEMENT enable-calendar (#PCDATA)>
- <!ELEMENT auto-schedule (#PCDATA)>
+ <!ELEMENT uid (#PCDATA)>
+ <!ELEMENT enable (#PCDATA)>
+ <!ELEMENT hosted-at (#PCDATA)>
+ <!ELEMENT enable-calendar (#PCDATA)>
+ <!ELEMENT enable-addressbook (#PCDATA)>
+ <!ELEMENT auto-schedule (#PCDATA)>
>
Modified: CalendarServer/branches/users/glyph/use-system-twisted/conf/caldavd-apple.plist
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/conf/caldavd-apple.plist 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/conf/caldavd-apple.plist 2010-02-12 22:49:09 UTC (rev 5105)
@@ -149,10 +149,6 @@
<dict>
<key>node</key>
<string>/Search</string>
- <key>restrictEnabledRecords</key>
- <false/>
- <key>restrictToGroup</key>
- <string></string>
<key>cacheTimeout</key>
<integer>30</integer>
</dict>
Copied: CalendarServer/branches/users/glyph/use-system-twisted/conf/servertoserver.xml (from rev 5104, CalendarServer/trunk/conf/servertoserver.xml)
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/conf/servertoserver.xml (rev 0)
+++ CalendarServer/branches/users/glyph/use-system-twisted/conf/servertoserver.xml 2010-02-12 22:49:09 UTC (rev 5105)
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+Copyright (c) 2006-2007 Apple Inc. All rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+ -->
+
+<!DOCTYPE servers SYSTEM "servertoserver.dtd">
+
+<servers>
+ <!--
+ <server>
+ <uri>https://localhost:8543/inbox</uri>
+ <allow-requests-from/>
+ <allow-requests-to/>
+ <domains>
+ <domain>example.org</domain>
+ </domains>
+ <hosts>
+ <host>127.0.0.1</host>
+ </hosts>
+ </server>
+ -->
+</servers>
Modified: CalendarServer/branches/users/glyph/use-system-twisted/setup.py
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/setup.py 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/setup.py 2010-02-12 22:49:09 UTC (rev 5105)
@@ -1,7 +1,7 @@
#!/usr/bin/env python
##
-# Copyright (c) 2006-2009 Apple Inc. All rights reserved.
+# Copyright (c) 2006-2010 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.
@@ -46,9 +46,9 @@
# Options
#
-description = "CardDAV protocol extensions to twext.web2.dav",
+description = "CalDAV/CardDAV protocol extensions to twext.web2.dav",
long_description = """
-Extends twext.web2.dav to implement CardDAV-aware resources and methods.
+Extends twisted.web2.dav to implement CalDAV/CardDAV-aware resources and methods.
"""
classifiers = None
@@ -83,88 +83,91 @@
# Run setup
#
-from distutils.core import setup
+if __name__ == "__main__":
+ from distutils.core import setup
-dist = setup(
- name = "twistedcaldav",
- version = version_string,
- description = description,
- long_description = long_description,
- url = None,
- classifiers = classifiers,
- author = "Apple Inc.",
- author_email = None,
- license = None,
- platforms = [ "all" ],
- packages = find_modules(),
- package_data = {
- "twistedcaldav": [
- "zoneinfo/*.ics",
- "zoneinfo/*/*.ics",
- "zoneinfo/*/*/*.ics",
- "images/*/*.jpg",
- ],
- },
- scripts = [
- "bin/caldavd",
- "bin/calendarserver_export",
- "bin/calendarserver_manage_principals",
- "bin/calendarserver_command_gateway",
- "bin/carddavd",
- ],
- data_files = [ ("caldavd", ["conf/caldavd.plist"]),
- ("carddavd", ["conf/carddavd.plist.default" ])],
- ext_modules = extensions,
- py_modules = ["kqreactor", "memcacheclient"],
-)
+ dist = setup(
+ name = "Calendar and Contacts Server",
+ version = version_string,
+ description = description,
+ long_description = long_description,
+ url = None,
+ classifiers = classifiers,
+ author = "Apple Inc.",
+ author_email = None,
+ license = None,
+ platforms = [ "all" ],
+ packages = find_modules(),
+ package_data = {
+ "twistedcaldav": [
+ "zoneinfo/*.ics",
+ "zoneinfo/*/*.ics",
+ "zoneinfo/*/*/*.ics",
+ "images/*/*.jpg",
+ ],
+ },
+ scripts = [
+ "bin/caldavd",
+ "bin/calendarserver_export",
+ "bin/calendarserver_load_augmentdb",
+ "bin/calendarserver_make_partition",
+ "bin/calendarserver_manage_augments",
+ "bin/calendarserver_manage_principals",
+ "bin/calendarserver_command_gateway",
+ "bin/carddavd",
+ ],
+ data_files = [ ("caldavd", ["conf/caldavd.plist"]),
+ ("carddavd", ["conf/carddavd.plist.default" ])],
+ ext_modules = extensions,
+ py_modules = ["kqreactor", "memcacheclient"],
+ )
-if "install" in dist.commands:
- import os
- install_scripts = dist.command_obj["install"].install_scripts
- install_lib = dist.command_obj["install"].install_lib
- root = dist.command_obj["install"].root
- base = dist.command_obj["install"].install_base
+ if "install" in dist.commands:
+ install_scripts = dist.command_obj["install"].install_scripts
+ install_lib = dist.command_obj["install"].install_lib
+ root = dist.command_obj["install"].root
+ base = dist.command_obj["install"].install_base
- if root:
- install_lib = install_lib[len(root):]
+ if root:
+ install_lib = install_lib[len(root):]
- for script in dist.scripts:
- scriptPath = os.path.join(install_scripts, os.path.basename(script))
+ for script in dist.scripts:
+ scriptPath = os.path.join(install_scripts, os.path.basename(script))
- print "rewriting %s" % (scriptPath,)
+ print "rewriting %s" % (scriptPath,)
- script = []
-
- fileType = None
+ script = []
- for line in file(scriptPath, "r"):
- if not fileType:
- if line.startswith("#!"):
- if "python" in line.lower():
- fileType = "python"
- elif "sh" in line.lower():
- fileType = "sh"
+ fileType = None
- line = line.rstrip("\n")
- if fileType == "sh":
- if line == "#PYTHONPATH":
- script.append('PYTHONPATH="%s:$PYTHONPATH"' % (install_lib,))
- elif line == "#PATH":
- script.append('PATH="%s:$PATH"' % (os.path.join(base, "bin"),))
- else:
- script.append(line)
+ for line in file(scriptPath, "r"):
+ if not fileType:
+ if line.startswith("#!"):
+ if "python" in line.lower():
+ fileType = "python"
+ elif "sh" in line.lower():
+ fileType = "sh"
- elif fileType == "python":
- if line == "#PYTHONPATH":
- script.append('PYTHONPATH="%s"' % (install_lib,))
- elif line == "#PATH":
- script.append('PATH="%s"' % (os.path.join(base, "bin"),))
+ line = line.rstrip("\n")
+ if fileType == "sh":
+ if line == "#PYTHONPATH":
+ script.append('PYTHONPATH="%s:$PYTHONPATH"' % (install_lib,))
+ elif line == "#PATH":
+ script.append('PATH="%s:$PATH"' % (os.path.join(base, "bin"),))
+ else:
+ script.append(line)
+
+ elif fileType == "python":
+ if line == "#PYTHONPATH":
+ script.append('PYTHONPATH="%s"' % (install_lib,))
+ elif line == "#PATH":
+ script.append('PATH="%s"' % (os.path.join(base, "bin"),))
+ else:
+ script.append(line)
+
else:
script.append(line)
- else:
- script.append(line)
-
- newScript = open(scriptPath, "w")
- newScript.write("\n".join(script))
- newScript.close()
+ newScript = open(scriptPath, "w")
+ newScript.write("\n".join(script))
+ newScript.close()
Modified: CalendarServer/branches/users/glyph/use-system-twisted/support/Makefile.Apple
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/support/Makefile.Apple 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/support/Makefile.Apple 2010-02-12 22:49:09 UTC (rev 5105)
@@ -94,14 +94,19 @@
$(_v) rm -f "$(DSTROOT)$(PY_HOME)/lib/python/twisted/python/zshcomp.pyc"
$(_v) rm -f "$(DSTROOT)$(PY_HOME)/lib/python/twisted/python/_twisted_zsh_stub"
$(_v) $(INSTALL_FILE) "$(Sources)/conf/caldavd-apple.plist" "$(DSTROOT)$(ETCDIR)/caldavd/caldavd.plist"
+ $(_v) $(INSTALL_FILE) "$(Sources)/conf/caldavd-partitioning-primary.plist" "$(DSTROOT)$(ETCDIR)/caldavd/caldavd-partitioning-primary.plist"
+ $(_v) $(INSTALL_FILE) "$(Sources)/conf/caldavd-partitioning-secondary.plist" "$(DSTROOT)$(ETCDIR)/caldavd/caldavd-partitioning-secondary.plist"
+ $(_v) $(INSTALL_FILE) "$(Sources)/conf/partitions.plist" "$(DSTROOT)$(ETCDIR)/caldavd/partitions.plist"
+ $(_v) $(INSTALL_FILE) "$(Sources)/conf/servertoserver.xml" "$(DSTROOT)$(ETCDIR)/caldavd/servertoserver.xml"
$(_v) chmod -R ugo+r "$(DSTROOT)$(PY_HOME)"
$(_v) for f in $$(find "$(DSTROOT)$(ETCDIR)" -type f ! -name '*.default'); do cp "$${f}" "$${f}.default"; done
+ $(_v) $(INSTALL_FILE) "$(Sources)/conf/servertoserver.dtd" "$(DSTROOT)$(ETCDIR)/caldavd/servertoserver.dtd"
install::
@echo "Installing manual pages..."
$(_v) $(INSTALL_DIRECTORY) "$(DSTROOT)$(MANDIR)/man8"
$(_v) $(INSTALL_FILE) "$(Sources)/doc/caldavd.8" "$(DSTROOT)$(MANDIR)/man8"
- $(_v) $(INSTALL_FILE) "$(Sources)/doc/carddavd.8" "$(DSTROOT)$(MANDIR)/man8"
+ $(_v) $(INSTALL_FILE) "$(Sources)/doc/carddavd.8" "$(DSTROOT)$(MANDIR)/man8"
$(_v) $(INSTALL_FILE) "$(Sources)/doc/calendarserver_export.8" "$(DSTROOT)$(MANDIR)/man8"
$(_v) $(INSTALL_FILE) "$(Sources)/doc/calendarserver_manage_principals.8" "$(DSTROOT)$(MANDIR)/man8"
$(_v) $(INSTALL_FILE) "$(Sources)/doc/calendarserver_command_gateway.8" "$(DSTROOT)$(MANDIR)/man8"
Modified: CalendarServer/branches/users/glyph/use-system-twisted/support/submit
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/support/submit 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/support/submit 2010-02-12 22:49:09 UTC (rev 5105)
@@ -1,7 +1,7 @@
#!/bin/sh
##
-# Copyright (c) 2005-2009 Apple Inc. All rights reserved.
+# Copyright (c) 2005-2010 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.
@@ -85,7 +85,7 @@
if [ $# != 0 ]; then usage "Unrecognized arguments:" "$@"; fi;
- project="AddressBookServer";
+ project="CalendarServer";
uri="$(svn info "${src}" --xml | sed -n 's|^.*<url>\(.*\)</url>.*$|\1|p')";
revision="$(svnversion "${src}")";
@@ -106,8 +106,7 @@
revision="$(echo "${revision}" | sed 's|M$||g')";
fi;
-# project_version="${project}-$((${version} + ${revision} / 10000 % 100)).$((${revision} / 100 % 100)).$((${revision} % 100))";
- project_version="${project}-${version}"
+ project_version="${project}-$((${version} + ${revision} / 10000 % 100)).$((${revision} / 100 % 100)).$((${revision} % 100))";
#
# Make sure changes are checked in.
@@ -121,13 +120,13 @@
# Do submission
#
-tmp="$(mktemp -d -t AddressBookServer_build)";
+tmp="$(mktemp -d -t CalendarServer_build)";
wc="${tmp}/${project_version}";
if "${build}"; then
echo "";
echo "Copying ${src}...";
- ignores="$(mktemp -t AddressBookServer_ignores)";
+ ignores="$(mktemp -t CalendarServer_ignores)";
svn st --no-ignore | sed -n -e 's|^I......||p' > "${ignores}";
rsync -av --exclude=".svn" --exclude="_trial_temp" --exclude-from="${ignores}" "${src}/" "${wc}";
rm "${ignores}";
@@ -159,7 +158,7 @@
echo "";
echo "Preparing sources for ${project_version}...";
-make SRCROOT="${wc}" -C "${wc}" prep;
+make -C "${wc}" prep;
if "${build}"; then
echo "";
Modified: CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/database.py
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/database.py 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/database.py 2010-02-12 22:49:09 UTC (rev 5105)
@@ -408,6 +408,9 @@
def _test_table(self, name):
raise NotImplementedError
+ def _create_index(self, name, ontable, columns, ifnotexists=False):
+ raise NotImplementedError
+
def _prepare_statement(self, sql):
raise NotImplementedError
@@ -453,6 +456,17 @@
""" % (name,)))
returnValue(result)
+ @inlineCallbacks
+ def _create_index(self, name, ontable, columns, ifnotexists=False):
+
+ statement = "create index %s%s on %s (%s)" % (
+ "if not exists " if ifnotexists else "",
+ name,
+ ontable,
+ ", ".join(columns),
+ )
+ yield self._db_execute(statement)
+
def _prepare_statement(self, sql):
# We are going to use the sqlite syntax of :1, :2 etc for our
# internal statements so we do not need to remap those
@@ -512,6 +526,26 @@
returnValue(result)
@inlineCallbacks
+ def _create_index(self, name, ontable, columns, ifnotexists=False):
+
+ statement = "create index %s on %s (%s)" % (
+ name,
+ ontable,
+ ", ".join(columns),
+ )
+
+ try:
+ yield self._db_execute(statement)
+ except pgdb.DatabaseError:
+
+ if not ifnotexists:
+ raise
+
+ result = (yield self._test_table(name))
+ if not result:
+ raise
+
+ @inlineCallbacks
def _db_init_schema_table(self):
"""
Initialise the underlying database tables.
Modified: CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/aggregate.py
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/aggregate.py 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/aggregate.py 2010-02-12 22:49:09 UTC (rev 5105)
@@ -192,25 +192,26 @@
def createRecord(self, recordType, guid=None, shortNames=(), authIDs=set(),
fullName=None, firstName=None, lastName=None, emailAddresses=set(),
- uid=None, password=None, **kwds):
+ uid=None, password=None, **kwargs):
service = self.serviceForRecordType(recordType)
return service.createRecord(recordType, guid=guid,
shortNames=shortNames, authIDs=authIDs, fullName=fullName,
firstName=firstName, lastName=lastName,
- emailAddresses=emailAddresses, uid=uid, password=password, **kwds)
+ emailAddresses=emailAddresses, uid=uid, password=password, **kwargs)
- def updateRecord(self, recordType, guid, shortNames=(), authIDs=set(),
+ def updateRecord(self, recordType, guid=None, shortNames=(), authIDs=set(),
fullName=None, firstName=None, lastName=None, emailAddresses=set(),
- uid=None, password=None, **kwds):
+ uid=None, password=None, **kwargs):
service = self.serviceForRecordType(recordType)
- return service.updateRecord(recordType, guid, shortNames=shortNames,
+ return service.updateRecord(recordType, guid=guid,
+ shortNames=shortNames,
authIDs=authIDs, fullName=fullName, firstName=firstName,
lastName=lastName, emailAddresses=emailAddresses, uid=uid,
- password=password, **kwds)
+ password=password, **kwargs)
- def destroyRecord(self, recordType, guid):
+ def destroyRecord(self, recordType, guid=None):
service = self.serviceForRecordType(recordType)
- return service.destroyRecord(recordType, guid)
+ return service.destroyRecord(recordType, guid=guid)
class DuplicateRecordTypeError(DirectoryError):
"""
Modified: CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/augment.py
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/augment.py 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/augment.py 2010-02-12 22:49:09 UTC (rev 5105)
@@ -24,6 +24,10 @@
from twistedcaldav.database import AbstractADBAPIDatabase, ADBAPISqliteMixin,\
ADBAPIPostgreSQLMixin
from twistedcaldav.directory.xmlaugmentsparser import XMLAugmentsParser
+import os
+from twistedcaldav.directory import xmlaugmentsparser
+from twistedcaldav.xmlutil import newElementTreeWithRoot, addSubElement,\
+ writeXML, readXML
log = Logger()
@@ -35,14 +39,14 @@
def __init__(
self,
- guid,
+ uid,
enabled=False,
hostedAt="",
enabledForCalendaring=False,
autoSchedule=False,
enabledForAddressBooks=False,
):
- self.guid = guid
+ self.uid = uid
self.enabled = enabled
self.hostedAt = hostedAt
self.enabledForCalendaring = enabledForCalendaring
@@ -58,47 +62,73 @@
pass
@inlineCallbacks
- def getAugmentRecord(self, guid):
+ def getAugmentRecord(self, uid):
"""
- Get an AugmentRecord for the specified GUID or the default.
+ Get an AugmentRecord for the specified UID or the default.
- @param guid: directory GUID to lookup
- @type guid: C{str}
+ @param uid: directory UID to lookup
+ @type uid: C{str}
@return: L{Deferred}
"""
- result = (yield self._lookupAugmentRecord(guid))
+ result = (yield self._lookupAugmentRecord(uid))
if result is None:
if not hasattr(self, "_defaultRecord"):
self._defaultRecord = (yield self._lookupAugmentRecord("Default"))
if self._defaultRecord is not None:
result = copy.deepcopy(self._defaultRecord)
- result.guid = guid
+ result.uid = uid
returnValue(result)
@inlineCallbacks
- def getAllGUIDs(self):
+ def getAllUIDs(self):
"""
- Get all AugmentRecord GUIDs.
+ Get all AugmentRecord UIDs.
@return: L{Deferred}
"""
raise NotImplementedError("Child class must define this.")
- def _lookupAugmentRecord(self, guid):
+ def _lookupAugmentRecord(self, uid):
"""
- Get an AugmentRecord for the specified GUID.
+ Get an AugmentRecord for the specified UID.
- @param guid: directory GUID to lookup
- @type guid: C{str}
+ @param uid: directory UID to lookup
+ @type uid: C{str}
@return: L{Deferred}
"""
raise NotImplementedError("Child class must define this.")
+ def addAugmentRecords(self, records, update=False):
+ """
+ Add an AugmentRecord to the DB.
+
+ @param record: augment records to add
+ @type record: C{list} of L{AugmentRecord}
+ @param update: C{True} if changing an existing record
+ @type update: C{bool}
+
+ @return: L{Deferred}
+ """
+
+ raise NotImplementedError("Child class must define this.")
+
+ def removeAugmentRecords(self, uids):
+ """
+ Remove AugmentRecords with the specified UIDs.
+
+ @param uid: directory UIDs to remove
+ @type uid: C{list} of C{str}
+
+ @return: L{Deferred}
+ """
+
+ raise NotImplementedError("Child class must define this.")
+
def refresh(self):
"""
Refresh any cached data.
@@ -120,6 +150,29 @@
self.lastCached = 0
self.db = {}
+ # Preflight existence of files
+ missing = list()
+ for xmlFile in self.xmlFiles:
+ if not os.path.exists(xmlFile):
+ missing.append(xmlFile)
+
+ # For each missing one create an empty xml file
+ if missing:
+ # If all files are missing, then create one augment file that defaults
+ # to all records being enabled
+ doDefault = (len(missing) == len(self.xmlFiles))
+ for missedFile in missing:
+
+ _ignore_etree, root = newElementTreeWithRoot(xmlaugmentsparser.ELEMENT_AUGMENTS)
+ if doDefault:
+ record = addSubElement(root, xmlaugmentsparser.ELEMENT_RECORD)
+ addSubElement(record, xmlaugmentsparser.ELEMENT_UID, "Default")
+ addSubElement(record, xmlaugmentsparser.ELEMENT_ENABLE, "true")
+ addSubElement(record, xmlaugmentsparser.ELEMENT_ENABLECALENDAR, "true")
+ addSubElement(record, xmlaugmentsparser.ELEMENT_ENABLEADDRESSBOOK, "true")
+ doDefault = False
+ writeXML(missedFile, root)
+
try:
self.db = self._parseXML()
except RuntimeError:
@@ -129,21 +182,21 @@
self.lastCached = time.time()
@inlineCallbacks
- def getAllGUIDs(self):
+ def getAllUIDs(self):
"""
- Get all AugmentRecord GUIDs.
+ Get all AugmentRecord UIDs.
@return: L{Deferred}
"""
return succeed(self.db.keys())
- def _lookupAugmentRecord(self, guid):
+ def _lookupAugmentRecord(self, uid):
"""
- Get an AugmentRecord for the specified GUID.
+ Get an AugmentRecord for the specified UID.
- @param guid: directory GUID to lookup
- @type guid: C{str}
+ @param uid: directory UID to lookup
+ @type uid: C{str}
@return: L{Deferred}
"""
@@ -152,8 +205,117 @@
if self.lastCached + self.cacheTimeout <= time.time():
self.refresh()
- return succeed(self.db.get(guid))
+ return succeed(self.db.get(uid))
+ def addAugmentRecords(self, records, update=False):
+ """
+ Add an AugmentRecord to the DB.
+
+ @param records: augment records to add
+ @type records: C{list} of L{AugmentRecord}
+ @param update: C{True} if changing an existing record
+ @type update: C{bool}
+
+ @return: L{Deferred}
+ """
+
+ if update:
+ # Now look at each file and modify the UIDs
+ for xmlFile in self.xmlFiles:
+ self._doModifyInFile(xmlFile, records)
+ else:
+ # Add to first file in list
+ self._doAddToFile(self.xmlFiles[0], records)
+
+ def _doAddToFile(self, xmlfile, records):
+
+ _ignore_etree, augments_node = readXML(xmlfile)
+
+ # Create new record
+ for record in records:
+ record_node = addSubElement(augments_node, xmlaugmentsparser.ELEMENT_RECORD)
+ addSubElement(record_node, xmlaugmentsparser.ELEMENT_UID, record.uid)
+ addSubElement(record_node, xmlaugmentsparser.ELEMENT_ENABLE, "true" if record.enabled else "false")
+ addSubElement(record_node, xmlaugmentsparser.ELEMENT_HOSTEDAT, record.hostedAt)
+ addSubElement(record_node, xmlaugmentsparser.ELEMENT_ENABLECALENDAR, "true" if record.enabledForCalendaring else "false")
+ addSubElement(record_node, xmlaugmentsparser.ELEMENT_ENABLEADDRESSBOOK, "true" if record.enabledForAddressBooks else "false")
+ addSubElement(record_node, xmlaugmentsparser.ELEMENT_AUTOSCHEDULE, "true" if record.autoSchedule else "false")
+
+ # Modify xmlfile
+ writeXML(xmlfile, augments_node)
+
+ def _doModifyInFile(self, xmlfile, records):
+
+ _ignore_etree, augments_node = readXML(xmlfile)
+
+ # Map uid->record for fast lookup
+ recordMap = dict([(record.uid, record) for record in records])
+
+ # Make sure UID is present
+ changed = False
+ for child in augments_node.getchildren():
+
+ if child.tag != xmlaugmentsparser.ELEMENT_RECORD:
+ continue
+
+ uid = child.find(xmlaugmentsparser.ELEMENT_UID).text
+ if uid in recordMap:
+ # Modify record
+ record = recordMap[uid]
+ child.find(xmlaugmentsparser.ELEMENT_ENABLE).text = "true" if record.enabled else "false"
+ child.find(xmlaugmentsparser.ELEMENT_HOSTEDAT).text = record.hostedAt
+ child.find(xmlaugmentsparser.ELEMENT_ENABLECALENDAR).text = "true" if record.enabledForCalendaring else "false"
+ child.find(xmlaugmentsparser.ELEMENT_ENABLEADDRESSBOOK).text = "true" if record.enabledForAddressBooks else "false"
+ child.find(xmlaugmentsparser.ELEMENT_AUTOSCHEDULE).text = "true" if record.autoSchedule else "false"
+ changed = True
+
+
+ # Modify xmlfile
+ if changed:
+ writeXML(xmlfile, augments_node)
+
+ def removeAugmentRecords(self, uids):
+ """
+ Remove AugmentRecords with the specified UIDs.
+
+ @param uid: directory UID to lookup
+ @type uid: C{list} of C{str}
+
+ @return: L{Deferred}
+ """
+
+ # Remove from cache first
+ removed = set()
+ for uid in uids:
+ if uid in self.db:
+ del self.db[uid]
+ removed.add(uid)
+
+ # Now look at each file and remove the UIDs
+ for xmlFile in self.xmlFiles:
+ self._doRemoveFromFile(xmlFile, removed)
+
+ return succeed(None)
+
+ def _doRemoveFromFile(self, xmlfile, uids):
+
+ _ignore_etree, augments_node = readXML(xmlfile)
+
+ # Remove all UIDs present
+ changed = False
+ for child in tuple(augments_node.getchildren()):
+
+ if child.tag != xmlaugmentsparser.ELEMENT_RECORD:
+ continue
+
+ if child.find(xmlaugmentsparser.ELEMENT_UID).text in uids:
+ augments_node.remove(child)
+ changed = True
+
+ # Modify xmlfile
+ if changed:
+ writeXML(xmlfile, augments_node)
+
def refresh(self):
"""
Refresh any cached data.
@@ -191,81 +353,87 @@
AbstractADBAPIDatabase.__init__(self, dbID, dbapiName, dbapiArgs, True, **kwargs)
@inlineCallbacks
- def getAllGUIDs(self):
+ def getAllUIDs(self):
"""
- Get all AugmentRecord GUIDs.
+ Get all AugmentRecord UIDs.
@return: L{Deferred}
"""
# Query for the record information
- results = (yield self.queryList("select GUID from AUGMENTS", ()))
+ results = (yield self.queryList("select UID from AUGMENTS", ()))
returnValue(results)
@inlineCallbacks
- def _lookupAugmentRecord(self, guid):
+ def _lookupAugmentRecord(self, uid):
"""
- Get an AugmentRecord for the specified GUID.
+ Get an AugmentRecord for the specified UID.
- @param guid: directory GUID to lookup
- @type guid: C{str}
+ @param uid: directory UID to lookup
+ @type uid: C{str}
@return: L{Deferred}
"""
# Query for the record information
- results = (yield self.query("select GUID, ENABLED, PARTITIONID, CALENDARING, AUTOSCHEDULE from AUGMENTS where GUID = :1", (guid,)))
+ results = (yield self.query("select UID, ENABLED, PARTITIONID, CALENDARING, ADDRESSBOOKS, AUTOSCHEDULE from AUGMENTS where UID = :1", (uid,)))
if not results:
returnValue(None)
else:
- guid, enabled, partitionid, enabdledForCalendaring, autoSchedule = results[0]
+ uid, enabled, partitionid, enabledForCalendaring, enabledForAddressBooks, autoSchedule = results[0]
record = AugmentRecord(
- guid = guid,
+ uid = uid,
enabled = enabled == "T",
hostedAt = (yield self._getPartition(partitionid)),
- enabledForCalendaring = enabdledForCalendaring == "T",
+ enabledForCalendaring = enabledForCalendaring == "T",
+ enabledForAddressBooks = enabledForAddressBooks == "T",
autoSchedule = autoSchedule == "T",
)
returnValue(record)
@inlineCallbacks
- def addAugmentRecord(self, record, update=False):
+ def addAugmentRecords(self, records, update=False):
- partitionid = (yield self._getPartitionID(record.hostedAt))
-
- if update:
- yield self.execute(
- """update AUGMENTS set
- (GUID, ENABLED, PARTITIONID, CALENDARING, AUTOSCHEDULE) =
- (:1, :2, :3, :4, :5) where GUID = :6""",
- (
- record.guid,
- "T" if record.enabled else "F",
- partitionid,
- "T" if record.enabledForCalendaring else "F",
- "T" if record.autoSchedule else "F",
- record.guid,
+ for record in records:
+ partitionid = (yield self._getPartitionID(record.hostedAt))
+
+ if update:
+ yield self.execute(
+ """update AUGMENTS set
+ (UID, ENABLED, PARTITIONID, CALENDARING, ADDRESSBOOKS, AUTOSCHEDULE) =
+ (:1, :2, :3, :4, :5, :6) where UID = :7""",
+ (
+ record.uid,
+ "T" if record.enabled else "F",
+ partitionid,
+ "T" if record.enabledForCalendaring else "F",
+ "T" if record.enabledForAddressBooks else "F",
+ "T" if record.autoSchedule else "F",
+ record.uid,
+ )
)
- )
- else:
- yield self.execute(
- """insert into AUGMENTS
- (GUID, ENABLED, PARTITIONID, CALENDARING, AUTOSCHEDULE)
- values (:1, :2, :3, :4, :5)""",
- (
- record.guid,
- "T" if record.enabled else "F",
- partitionid,
- "T" if record.enabledForCalendaring else "F",
- "T" if record.autoSchedule else "F",
+ else:
+ yield self.execute(
+ """insert into AUGMENTS
+ (UID, ENABLED, PARTITIONID, CALENDARING, ADDRESSBOOKS, AUTOSCHEDULE)
+ values (:1, :2, :3, :4, :5, :6)""",
+ (
+ record.uid,
+ "T" if record.enabled else "F",
+ partitionid,
+ "T" if record.enabledForCalendaring else "F",
+ "T" if record.enabledForAddressBooks else "F",
+ "T" if record.autoSchedule else "F",
+ )
)
- )
- def removeAugmentRecord(self, guid):
+ @inlineCallbacks
+ def removeAugmentRecords(self, uids):
- return self.query("delete from AUGMENTS where GUID = :1", (guid,))
+ for uid in uids:
+ yield self.execute("delete from AUGMENTS where UID = :1", (uid,))
@inlineCallbacks
def _getPartitionID(self, hostedat, createIfMissing=True):
@@ -315,20 +483,29 @@
"""
#
- # TESTTYPE table
+ # AUGMENTS table
#
- yield self._create_table("AUGMENTS", (
- ("GUID", "text unique"),
- ("ENABLED", "text(1)"),
- ("PARTITIONID", "text"),
- ("CALENDARING", "text(1)"),
- ("AUTOSCHEDULE", "text(1)"),
- ))
+ yield self._create_table(
+ "AUGMENTS",
+ (
+ ("UID", "text unique"),
+ ("ENABLED", "text(1)"),
+ ("PARTITIONID", "text"),
+ ("CALENDARING", "text(1)"),
+ ("ADDRESSBOOKS", "text(1)"),
+ ("AUTOSCHEDULE", "text(1)"),
+ ),
+ ifnotexists=True,
+ )
- yield self._create_table("PARTITIONS", (
- ("PARTITIONID", "serial"),
- ("HOSTEDAT", "text"),
- ))
+ yield self._create_table(
+ "PARTITIONS",
+ (
+ ("PARTITIONID", "serial"),
+ ("HOSTEDAT", "text"),
+ ),
+ ifnotexists=True,
+ )
@inlineCallbacks
def _db_empty_data_tables(self):
Modified: CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/cachingdirectory.py
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/cachingdirectory.py 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/cachingdirectory.py 2010-02-12 22:49:09 UTC (rev 5105)
@@ -357,12 +357,12 @@
self, service, recordType, guid,
shortNames=(), authIDs=set(),
fullName=None, firstName=None, lastName=None, emailAddresses=set(),
- uid=None,
+ uid=None, **kwargs
):
super(CachingDirectoryRecord, self).__init__(
- service = service,
- recordType = recordType,
- guid = guid,
+ service,
+ recordType,
+ guid,
shortNames = shortNames,
authIDs = authIDs,
fullName = fullName,
@@ -370,6 +370,7 @@
lastName = lastName,
emailAddresses = emailAddresses,
uid = uid,
+ **kwargs
)
self.cachedTime = time.time()
Modified: CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/calendaruserproxy.py
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/calendaruserproxy.py 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/calendaruserproxy.py 2010-02-12 22:49:09 UTC (rev 5105)
@@ -719,15 +719,17 @@
ifnotexists=True,
)
- yield self._db_execute(
- """
- create index if not exists GROUPNAMES on GROUPS (GROUPNAME)
- """
+ yield self._create_index(
+ "GROUPNAMES",
+ "GROUPS",
+ ("GROUPNAME",),
+ ifnotexists=True,
)
- yield self._db_execute(
- """
- create index if not exists MEMBERS on GROUPS (MEMBER)
- """
+ yield self._create_index(
+ "MEMBERS",
+ "GROUPS",
+ ("MEMBER",),
+ ifnotexists=True,
)
@inlineCallbacks
@@ -740,15 +742,17 @@
# Add index if old version is less than "4"
if int(old_version) < 4:
- yield self._db_execute(
- """
- create index if not exists GROUPNAMES on GROUPS (GROUPNAME)
- """
+ yield self._create_index(
+ "GROUPNAMES",
+ "GROUPS",
+ ("GROUPNAME",),
+ ifnotexists=True,
)
- yield self._db_execute(
- """
- create index if not exists MEMBERS on GROUPS (MEMBER)
- """
+ yield self._create_index(
+ "MEMBERS",
+ "GROUPS",
+ ("MEMBER",),
+ ifnotexists=True,
)
def _db_empty_data_tables(self):
Modified: CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/directory.py
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/directory.py 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/directory.py 2010-02-12 22:49:09 UTC (rev 5105)
@@ -299,21 +299,21 @@
def createRecord(self, recordType, guid=None, shortNames=(), authIDs=set(),
fullName=None, firstName=None, lastName=None, emailAddresses=set(),
- uid=None, password=None, **kwds):
+ uid=None, password=None, **kwargs):
"""
Create/persist a directory record based on the given values
"""
raise NotImplementedError("Subclass must implement createRecord")
- def updateRecord(self, recordType, guid, shortNames=(), authIDs=set(),
+ def updateRecord(self, recordType, guid=None, shortNames=(), authIDs=set(),
fullName=None, firstName=None, lastName=None, emailAddresses=set(),
- uid=None, password=None, **kwds):
+ uid=None, password=None, **kwargs):
"""
Update/persist a directory record based on the given values
"""
raise NotImplementedError("Subclass must implement updateRecord")
- def destroyRecord(self, recordType, guid):
+ def destroyRecord(self, recordType, guid=None):
"""
Remove a directory record from the directory
"""
@@ -342,6 +342,7 @@
calendarUserAddresses=set(), autoSchedule=False, enabledForCalendaring=None,
enabledForAddressBooks=None,
uid=None,
+ **kwargs
):
assert service.realmName is not None
assert recordType
@@ -356,23 +357,25 @@
if fullName is None:
fullName = ""
- self.service = service
- self.recordType = recordType
- self.guid = guid
- self.uid = uid
- self.enabled = False
- self.hostedAt = ""
- self.shortNames = shortNames
- self.authIDs = authIDs
- self.fullName = fullName
- self.firstName = firstName
- self.lastName = lastName
- self.emailAddresses = emailAddresses
- self.enabledForCalendaring = enabledForCalendaring
- self.autoSchedule = autoSchedule
+ self.service = service
+ self.recordType = recordType
+ self.guid = guid
+ self.uid = uid
+ self.enabled = False
+ self.hostedAt = ""
+ self.shortNames = shortNames
+ self.authIDs = authIDs
+ self.fullName = fullName
+ self.firstName = firstName
+ self.lastName = lastName
+ self.emailAddresses = emailAddresses
+ self.enabledForCalendaring = enabledForCalendaring
+ self.autoSchedule = autoSchedule
self.enabledForAddressBooks = enabledForAddressBooks
+ self.extras = kwargs
+
def get_calendarUserAddresses(self):
"""
Dynamically construct a calendarUserAddresses attribute which describes
Modified: CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/augments-test-default.xml
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/augments-test-default.xml 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/augments-test-default.xml 2010-02-12 22:49:09 UTC (rev 5105)
@@ -20,45 +20,49 @@
<augments>
<record>
- <guid>Default</guid>
+ <uid>Default</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
<hosted-at>00001</hosted-at>
</record>
<record>
- <guid>D11F03A0-97EA-48AF-9A6C-FAC7F3975766</guid>
+ <uid>D11F03A0-97EA-48AF-9A6C-FAC7F3975766</uid>
<enable>true</enable>
</record>
<record>
- <guid>6423F94A-6B76-4A3A-815B-D52CFD77935D</guid>
+ <uid>6423F94A-6B76-4A3A-815B-D52CFD77935D</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
</record>
<record>
- <guid>5A985493-EE2C-4665-94CF-4DFEA3A89500</guid>
+ <uid>5A985493-EE2C-4665-94CF-4DFEA3A89500</uid>
<enable>false</enable>
</record>
<record>
- <guid>8B4288F6-CC82-491D-8EF9-642EF4F3E7D0</guid>
+ <uid>8B4288F6-CC82-491D-8EF9-642EF4F3E7D0</uid>
<enable>true</enable>
<enable-calendar>false</enable-calendar>
+ <enable-addressbook>false</enable-addressbook>
</record>
<record>
- <guid>5FF60DAD-0BDE-4508-8C77-15F0CA5C8DD1</guid>
+ <uid>5FF60DAD-0BDE-4508-8C77-15F0CA5C8DD1</uid>
<enable>true</enable>
<hosted-at>00001</hosted-at>
</record>
<record>
- <guid>543D28BA-F74F-4D5F-9243-B3E3A61171E5</guid>
+ <uid>543D28BA-F74F-4D5F-9243-B3E3A61171E5</uid>
<enable>true</enable>
<hosted-at>00002</hosted-at>
</record>
<record>
- <guid>6A73326A-F781-47E7-A9F8-AF47364D4152</guid>
+ <uid>6A73326A-F781-47E7-A9F8-AF47364D4152</uid>
<enable>true</enable>
<hosted-at>00002</hosted-at>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
<auto-schedule>true</auto-schedule>
</record>
</augments>
Modified: CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/augments-test.xml
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/augments-test.xml 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/augments-test.xml 2010-02-12 22:49:09 UTC (rev 5105)
@@ -20,39 +20,42 @@
<augments>
<record>
- <guid>D11F03A0-97EA-48AF-9A6C-FAC7F3975766</guid>
+ <uid>D11F03A0-97EA-48AF-9A6C-FAC7F3975766</uid>
<enable>true</enable>
</record>
<record>
- <guid>6423F94A-6B76-4A3A-815B-D52CFD77935D</guid>
+ <uid>6423F94A-6B76-4A3A-815B-D52CFD77935D</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
</record>
<record>
- <guid>5A985493-EE2C-4665-94CF-4DFEA3A89500</guid>
+ <uid>5A985493-EE2C-4665-94CF-4DFEA3A89500</uid>
<enable>false</enable>
</record>
<record>
- <guid>8B4288F6-CC82-491D-8EF9-642EF4F3E7D0</guid>
+ <uid>8B4288F6-CC82-491D-8EF9-642EF4F3E7D0</uid>
<enable>true</enable>
<enable-calendar>false</enable-calendar>
+ <enable-addressbook>false</enable-addressbook>
</record>
<record>
- <guid>5FF60DAD-0BDE-4508-8C77-15F0CA5C8DD1</guid>
+ <uid>5FF60DAD-0BDE-4508-8C77-15F0CA5C8DD1</uid>
<enable>true</enable>
<hosted-at>00001</hosted-at>
</record>
<record>
- <guid>543D28BA-F74F-4D5F-9243-B3E3A61171E5</guid>
+ <uid>543D28BA-F74F-4D5F-9243-B3E3A61171E5</uid>
<enable>true</enable>
<hosted-at>00002</hosted-at>
</record>
<record>
- <guid>6A73326A-F781-47E7-A9F8-AF47364D4152</guid>
+ <uid>6A73326A-F781-47E7-A9F8-AF47364D4152</uid>
<enable>true</enable>
<hosted-at>00002</hosted-at>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
<auto-schedule>true</auto-schedule>
</record>
</augments>
Modified: CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/augments.xml
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/augments.xml 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/augments.xml 2010-02-12 22:49:09 UTC (rev 5105)
@@ -20,109 +20,123 @@
<augments realm="Test">
<record>
- <guid>D11F03A0-97EA-48AF-9A6C-FAC7F3975766</guid>
+ <uid>D11F03A0-97EA-48AF-9A6C-FAC7F3975766</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
</record>
<record>
- <guid>6423F94A-6B76-4A3A-815B-D52CFD77935D</guid>
+ <uid>6423F94A-6B76-4A3A-815B-D52CFD77935D</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
</record>
<record>
- <guid>5A985493-EE2C-4665-94CF-4DFEA3A89500</guid>
+ <uid>5A985493-EE2C-4665-94CF-4DFEA3A89500</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
</record>
<record>
- <guid>8B4288F6-CC82-491D-8EF9-642EF4F3E7D0</guid>
+ <uid>8B4288F6-CC82-491D-8EF9-642EF4F3E7D0</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
</record>
<record>
- <guid>5FF60DAD-0BDE-4508-8C77-15F0CA5C8DD1</guid>
+ <uid>5FF60DAD-0BDE-4508-8C77-15F0CA5C8DD1</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
</record>
<record>
- <guid>543D28BA-F74F-4D5F-9243-B3E3A61171E5</guid>
+ <uid>543D28BA-F74F-4D5F-9243-B3E3A61171E5</uid>
<enable>true</enable>
<enable-calendar>false</enable-calendar>
+ <enable-addressbook>false</enable-addressbook>
</record>
<record repeat="2">
- <guid>user%02d</guid>
+ <uid>user%02d</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
</record>
<record>
- <guid>9FF60DAD-0BDE-4508-8C77-15F0CA5C8DD1</guid>
+ <uid>9FF60DAD-0BDE-4508-8C77-15F0CA5C8DD1</uid>
<enable>true</enable>
</record>
<record>
- <guid>admin</guid>
+ <uid>admin</uid>
<enable>true</enable>
</record>
<record>
- <guid>grunts</guid>
+ <uid>grunts</uid>
<enable>true</enable>
</record>
<record>
- <guid>right_coast</guid>
+ <uid>right_coast</uid>
<enable>true</enable>
</record>
<record>
- <guid>left_coast</guid>
+ <uid>left_coast</uid>
<enable>true</enable>
</record>
<record>
- <guid>both_coasts</guid>
+ <uid>both_coasts</uid>
<enable>true</enable>
</record>
<record>
- <guid>recursive1_coasts</guid>
+ <uid>recursive1_coasts</uid>
<enable>true</enable>
</record>
<record>
- <guid>recursive2_coasts</guid>
+ <uid>recursive2_coasts</uid>
<enable>true</enable>
</record>
<record>
- <guid>non_calendar_group</guid>
+ <uid>non_calendar_group</uid>
<enable>true</enable>
</record>
<record>
- <guid>mercury</guid>
+ <uid>mercury</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
</record>
<record>
- <guid>gemini</guid>
+ <uid>gemini</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
</record>
<record>
- <guid>apollo</guid>
+ <uid>apollo</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
</record>
<record>
- <guid>orion</guid>
+ <uid>orion</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
</record>
<record>
- <guid>transporter</guid>
+ <uid>transporter</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
</record>
<record>
- <guid>ftlcpu</guid>
+ <uid>ftlcpu</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
</record>
<record>
- <guid>non_calendar_proxy</guid>
+ <uid>non_calendar_proxy</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
</record>
</augments>
Modified: CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/modify/augments.xml
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/modify/augments.xml 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/modify/augments.xml 2010-02-12 22:49:09 UTC (rev 5105)
@@ -20,13 +20,15 @@
<augments>
<record>
- <guid>user01</guid>
+ <uid>user01</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
</record>
<record>
- <guid>user02</guid>
+ <uid>user02</uid>
<enable>false</enable>
<enable-calendar>false</enable-calendar>
+ <enable-addressbook>false</enable-addressbook>
</record>
</augments>
Modified: CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/resources/augments.xml
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/resources/augments.xml 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/resources/augments.xml 2010-02-12 22:49:09 UTC (rev 5105)
@@ -20,25 +20,29 @@
<augments>
<record>
- <guid>user01</guid>
+ <uid>user01</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
</record>
<record>
- <guid>user02</guid>
+ <uid>user02</uid>
<enable>false</enable>
<enable-calendar>false</enable-calendar>
+ <enable-addressbook>false</enable-addressbook>
</record>
<record>
- <guid>resource01</guid>
+ <uid>resource01</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
+ <enable-addressbook>true</enable-addressbook>
<auto-schedule>true</auto-schedule>
</record>
<record>
- <guid>resource02</guid>
+ <uid>resource02</uid>
<enable>false</enable>
<enable-calendar>false</enable-calendar>
+ <enable-addressbook>false</enable-addressbook>
<auto-schedule>false</auto-schedule>
</record>
</augments>
Modified: CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/test_augment.py
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/test_augment.py 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/test_augment.py 2010-02-12 22:49:09 UTC (rev 5105)
@@ -26,32 +26,32 @@
xmlFileDefault = os.path.join(os.path.dirname(__file__), "augments-test-default.xml")
testRecords = (
- {"guid":"D11F03A0-97EA-48AF-9A6C-FAC7F3975766", "enabled":True, "hostedAt":"", "enabledForCalendaring":False, "autoSchedule":False},
- {"guid":"6423F94A-6B76-4A3A-815B-D52CFD77935D", "enabled":True, "hostedAt":"", "enabledForCalendaring":True, "autoSchedule":False},
- {"guid":"5A985493-EE2C-4665-94CF-4DFEA3A89500", "enabled":False, "hostedAt":"", "enabledForCalendaring":False, "autoSchedule":False},
- {"guid":"8B4288F6-CC82-491D-8EF9-642EF4F3E7D0", "enabled":True, "hostedAt":"", "enabledForCalendaring":False, "autoSchedule":False},
- {"guid":"5FF60DAD-0BDE-4508-8C77-15F0CA5C8DD1", "enabled":True, "hostedAt":"00001", "enabledForCalendaring":False, "autoSchedule":False},
- {"guid":"543D28BA-F74F-4D5F-9243-B3E3A61171E5", "enabled":True, "hostedAt":"00002", "enabledForCalendaring":False, "autoSchedule":False},
- {"guid":"6A73326A-F781-47E7-A9F8-AF47364D4152", "enabled":True, "hostedAt":"00002", "enabledForCalendaring":True, "autoSchedule":True},
+ {"uid":"D11F03A0-97EA-48AF-9A6C-FAC7F3975766", "enabled":True, "hostedAt":"", "enabledForCalendaring":False, "enabledForAddressBooks":False, "autoSchedule":False},
+ {"uid":"6423F94A-6B76-4A3A-815B-D52CFD77935D", "enabled":True, "hostedAt":"", "enabledForCalendaring":True, "enabledForAddressBooks":True, "autoSchedule":False},
+ {"uid":"5A985493-EE2C-4665-94CF-4DFEA3A89500", "enabled":False, "hostedAt":"", "enabledForCalendaring":False, "enabledForAddressBooks":False, "autoSchedule":False},
+ {"uid":"8B4288F6-CC82-491D-8EF9-642EF4F3E7D0", "enabled":True, "hostedAt":"", "enabledForCalendaring":False, "enabledForAddressBooks":False, "autoSchedule":False},
+ {"uid":"5FF60DAD-0BDE-4508-8C77-15F0CA5C8DD1", "enabled":True, "hostedAt":"00001", "enabledForCalendaring":False, "enabledForAddressBooks":False, "autoSchedule":False},
+ {"uid":"543D28BA-F74F-4D5F-9243-B3E3A61171E5", "enabled":True, "hostedAt":"00002", "enabledForCalendaring":False, "enabledForAddressBooks":False, "autoSchedule":False},
+ {"uid":"6A73326A-F781-47E7-A9F8-AF47364D4152", "enabled":True, "hostedAt":"00002", "enabledForCalendaring":True, "enabledForAddressBooks":True, "autoSchedule":True},
)
-testRecordDefault = {"guid":"A4318887-F2C7-4A70-9056-B88CC8DB26F1", "enabled":True, "hostedAt":"00001", "enabledForCalendaring":True, "autoSchedule":False}
+testRecordDefault = {"uid":"A4318887-F2C7-4A70-9056-B88CC8DB26F1", "enabled":True, "hostedAt":"00001", "enabledForCalendaring":True, "enabledForAddressBooks":True, "autoSchedule":False}
class AugmentTests(TestCase):
@inlineCallbacks
def _checkRecord(self, db, items):
- record = (yield db.getAugmentRecord(items["guid"]))
+ record = (yield db.getAugmentRecord(items["uid"]))
self.assertTrue(record is not None)
for k,v in items.iteritems():
self.assertEqual(getattr(record, k), v)
@inlineCallbacks
- def _checkNoRecord(self, db, guid):
+ def _checkNoRecord(self, db, uid):
- record = (yield db.getAugmentRecord(guid))
+ record = (yield db.getAugmentRecord(uid))
self.assertTrue(record is None)
class AugmentXMLTests(AugmentTests):
@@ -99,7 +99,7 @@
"""), db)
self.assertRaises(RuntimeError, XMLAugmentsParser, cStringIO.StringIO("""<?xml version="1.0" encoding="utf-8"?>
<record>
- <guid>admin</guid>
+ <uid>admin</uid>
<enable>true</enable>
<foo/>
</record>
@@ -113,8 +113,7 @@
db = AugmentSqliteDB(self.mktemp())
dbxml = AugmentXMLDB((xmlFile,))
- for record in dbxml.db.values():
- yield db.addAugmentRecord(record)
+ yield db.addAugmentRecords(dbxml.db.values())
for item in testRecords:
yield self._checkRecord(db, item)
@@ -127,8 +126,7 @@
db = AugmentSqliteDB(self.mktemp())
dbxml = AugmentXMLDB((xmlFileDefault,))
- for record in dbxml.db.values():
- yield db.addAugmentRecord(record)
+ yield db.addAugmentRecords(dbxml.db.values())
for item in testRecords:
yield self._checkRecord(db, item)
@@ -144,8 +142,7 @@
yield db.clean()
dbxml = AugmentXMLDB((xmlFile,))
- for record in dbxml.db.values():
- yield db.addAugmentRecord(record)
+ yield db.addAugmentRecords(dbxml.db.values())
for item in testRecords:
yield self._checkRecord(db, item)
@@ -159,8 +156,7 @@
yield db.clean()
dbxml = AugmentXMLDB((xmlFileDefault,))
- for record in dbxml.db.values():
- yield db.addAugmentRecord(record)
+ yield db.addAugmentRecords(dbxml.db.values())
for item in testRecords:
yield self._checkRecord(db, item)
Modified: CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/test_cachedirectory.py
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/test_cachedirectory.py 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/test_cachedirectory.py 2010-02-12 22:49:09 UTC (rev 5105)
@@ -68,7 +68,7 @@
)
augmentRecord = AugmentRecord(
- guid = cacheRecord.guid,
+ uid = cacheRecord.guid,
enabled=True,
enabledForCalendaring = True,
)
Modified: CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/test_modify.py
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/test_modify.py 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/test_modify.py 2010-02-12 22:49:09 UTC (rev 5105)
@@ -52,13 +52,19 @@
record = directory.recordWithUID("resource01")
self.assertEquals(record, None)
- directory.createRecord("resources", "resource01", shortNames=("resource01",), uid="resource01")
+ directory.createRecord("resources", guid="resource01",
+ shortNames=("resource01",), uid="resource01",
+ emailAddresses=("res1 at example.com", "res2 at example.com"),
+ comment="Test Comment")
record = directory.recordWithUID("resource01")
self.assertNotEquals(record, None)
- directory.createRecord("resources", "resource02", shortNames=("resource02",), uid="resource02")
+ self.assertEquals(len(record.emailAddresses), 2)
+ self.assertEquals(record.extras['comment'], "Test Comment")
+ directory.createRecord("resources", guid="resource02", shortNames=("resource02",), uid="resource02")
+
record = directory.recordWithUID("resource02")
self.assertNotEquals(record, None)
@@ -74,12 +80,12 @@
record = directory.recordWithUID("resource01")
self.assertEquals(record, None)
- directory.createRecord("resources", "resource01", shortNames=("resource01",), uid="resource01")
+ directory.createRecord("resources", guid="resource01", shortNames=("resource01",), uid="resource01")
record = directory.recordWithUID("resource01")
self.assertNotEquals(record, None)
- directory.destroyRecord("resources", "resource01")
+ directory.destroyRecord("resources", guid="resource01")
record = directory.recordWithUID("resource01")
self.assertEquals(record, None)
@@ -91,17 +97,18 @@
def test_updateRecord(self):
directory = getDirectory()
- directory.createRecord("resources", "resource01",
+ directory.createRecord("resources", guid="resource01",
shortNames=("resource01",), uid="resource01",
fullName="Resource number 1")
record = directory.recordWithUID("resource01")
self.assertEquals(record.fullName, "Resource number 1")
- directory.updateRecord("resources", "resource01",
+ directory.updateRecord("resources", guid="resource01",
shortNames=("resource01", "r01"), uid="resource01",
fullName="Resource #1", firstName="First", lastName="Last",
- emailAddresses=("resource01 at example.com", "r01 at example.com"))
+ emailAddresses=("resource01 at example.com", "r01 at example.com"),
+ comment="Test Comment")
record = directory.recordWithUID("resource01")
self.assertEquals(record.fullName, "Resource #1")
@@ -110,6 +117,7 @@
self.assertEquals(set(record.shortNames), set(["resource01", "r01"]))
self.assertEquals(record.emailAddresses,
set(["resource01 at example.com", "r01 at example.com"]))
+ self.assertEquals(record.extras['comment'], "Test Comment")
# Make sure old records are still there:
record = directory.recordWithUID("location01")
@@ -118,5 +126,5 @@
def test_createDuplicateRecord(self):
directory = getDirectory()
- directory.createRecord("resources", "resource01", shortNames=("resource01",), uid="resource01")
- self.assertRaises(DirectoryError, directory.createRecord, "resources", "resource01", shortNames=("resource01",), uid="resource01")
+ directory.createRecord("resources", guid="resource01", shortNames=("resource01",), uid="resource01")
+ self.assertRaises(DirectoryError, directory.createRecord, "resources", guid="resource01", shortNames=("resource01",), uid="resource01")
Modified: CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/test_xmlfile.py
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/test_xmlfile.py 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/test/test_xmlfile.py 2010-02-12 22:49:09 UTC (rev 5105)
@@ -159,7 +159,7 @@
<!DOCTYPE accounts SYSTEM "accounts.dtd">
<augments>
<record>
- <guid>myoffice</guid>
+ <uid>myoffice</uid>
<enable>true</enable>
<enable-calendar>true</enable-calendar>
<auto-schedule>true</auto-schedule>
@@ -229,6 +229,71 @@
self.assertFalse(service.recordWithShortName(DirectoryService.recordType_groups, "disabled").enabledForCalendaring)
+ def test_readExtras(self):
+ service = self.service()
+
+ self.xmlFile().open("w").write(
+"""<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE accounts SYSTEM "accounts.dtd">
+<accounts realm="Test Realm">
+ <location>
+ <uid>my office</uid>
+ <guid>myoffice</guid>
+ <name>My Office</name>
+ <extras>
+ <comment>This is the comment</comment>
+ <capacity>40</capacity>
+ </extras>
+ </location>
+</accounts>
+"""
+ )
+
+ record = service.recordWithShortName(
+ DirectoryService.recordType_locations, "my office")
+ self.assertEquals(record.guid, "myoffice")
+ self.assertEquals(record.extras["comment"], "This is the comment")
+ self.assertEquals(record.extras["capacity"], "40")
+
+ def test_writeExtras(self):
+ service = self.service()
+
+ service.createRecord(DirectoryService.recordType_locations, "newguid",
+ shortNames=("New office",),
+ fullName="My New Office",
+ address="1 Infinite Loop, Cupertino, CA",
+ capacity="10",
+ comment="Test comment",
+ )
+
+ record = service.recordWithShortName(
+ DirectoryService.recordType_locations, "New office")
+ self.assertEquals(record.extras["comment"], "Test comment")
+ self.assertEquals(record.extras["capacity"], "10")
+
+
+ service.updateRecord(DirectoryService.recordType_locations, "newguid",
+ shortNames=("New office",),
+ fullName="My Newer Office",
+ address="2 Infinite Loop, Cupertino, CA",
+ capacity="20",
+ comment="Test comment updated",
+ )
+
+ record = service.recordWithShortName(
+ DirectoryService.recordType_locations, "New office")
+ self.assertEquals(record.fullName, "My Newer Office")
+ self.assertEquals(record.extras["address"], "2 Infinite Loop, Cupertino, CA")
+ self.assertEquals(record.extras["comment"], "Test comment updated")
+ self.assertEquals(record.extras["capacity"], "20")
+
+ service.destroyRecord(DirectoryService.recordType_locations, "newguid")
+
+ record = service.recordWithShortName(
+ DirectoryService.recordType_locations, "New office")
+ self.assertEquals(record, None)
+
+
class XMLFileSubset (XMLFileBase, TestCase):
"""
Test the recordTypes subset feature of XMLFile service.
Modified: CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/xmlaccountsparser.py
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/xmlaccountsparser.py 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/xmlaccountsparser.py 2010-02-12 22:49:09 UTC (rev 5105)
@@ -48,6 +48,7 @@
ELEMENT_EMAIL_ADDRESS = "email-address"
ELEMENT_MEMBERS = "members"
ELEMENT_MEMBER = "member"
+ELEMENT_EXTRAS = "extras"
ATTRIBUTE_REALM = "realm"
ATTRIBUTE_REPEAT = "repeat"
@@ -156,6 +157,7 @@
self.emailAddresses = set()
self.members = set()
self.groups = set()
+ self.extras = {}
def repeat(self, ctr):
"""
@@ -205,6 +207,7 @@
result.lastName = lastName
result.emailAddresses = emailAddresses
result.members = self.members
+ result.extras = self.extras
return result
def parseXML(self, node):
@@ -237,6 +240,8 @@
self.emailAddresses.add(child.firstChild.data.encode("utf-8").lower())
elif child_name == ELEMENT_MEMBERS:
self._parseMembers(child, self.members)
+ elif child_name == ELEMENT_EXTRAS:
+ self._parseExtras(child, self.extras)
else:
raise RuntimeError("Unknown account attribute: %s" % (child_name,))
@@ -252,3 +257,10 @@
recordType = DirectoryService.recordType_users
if child.firstChild is not None:
addto.add((recordType, child.firstChild.data.encode("utf-8")))
+
+ def _parseExtras(self, node, addto):
+ for child in node._get_childNodes():
+ key = child._get_localName()
+ if key:
+ value = child.firstChild.data.encode("utf-8")
+ addto[key.encode("utf-8")] = value
Modified: CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/xmlaugmentsparser.py
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/xmlaugmentsparser.py 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/xmlaugmentsparser.py 2010-02-12 22:49:09 UTC (rev 5105)
@@ -33,11 +33,11 @@
ELEMENT_AUGMENTS = "augments"
ELEMENT_RECORD = "record"
-ELEMENT_GUID = "guid"
+ELEMENT_UID = "uid"
ELEMENT_ENABLE = "enable"
ELEMENT_HOSTEDAT = "hosted-at"
+ELEMENT_ENABLECALENDAR = "enable-calendar"
ELEMENT_ENABLEADDRESSBOOK = "enable-addressbook"
-ELEMENT_ENABLECALENDAR = "enable-calendar"
ELEMENT_AUTOSCHEDULE = "auto-schedule"
ATTRIBUTE_REPEAT = "repeat"
@@ -46,7 +46,7 @@
VALUE_FALSE = "false"
ELEMENT_AUGMENTRECORD_MAP = {
- ELEMENT_GUID: "guid",
+ ELEMENT_UID: "uid",
ELEMENT_ENABLE: "enabled",
ELEMENT_HOSTEDAT: "hostedAt",
ELEMENT_ENABLECALENDAR: "enabledForCalendaring",
@@ -95,23 +95,23 @@
for node in child.getchildren():
if node.tag in (
- ELEMENT_GUID,
+ ELEMENT_UID,
ELEMENT_HOSTEDAT,
):
fields[node.tag] = node.text
elif node.tag in (
ELEMENT_ENABLE,
ELEMENT_ENABLECALENDAR,
+ ELEMENT_ENABLEADDRESSBOOK,
ELEMENT_AUTOSCHEDULE,
- ELEMENT_ENABLEADDRESSBOOK
):
fields[node.tag] = node.text == VALUE_TRUE
else:
log.error("Invalid element '%s' in augment file: '%s'" % (node.tag, self.xmlFile,), raiseException=RuntimeError)
- # Must have at least a guid
- if ELEMENT_GUID not in fields:
- log.error("Invalid record '%s' without a guid in augment file: '%s'" % (child, self.xmlFile,), raiseException=RuntimeError)
+ # Must have at least a uid
+ if ELEMENT_UID not in fields:
+ log.error("Invalid record '%s' without a uid in augment file: '%s'" % (child, self.xmlFile,), raiseException=RuntimeError)
if repeat > 1:
for i in xrange(1, repeat+1):
@@ -137,4 +137,4 @@
actualFields[ELEMENT_AUGMENTRECORD_MAP[k]] = expandCount(v, count)
record = AugmentRecord(**actualFields)
- self.items[record.guid] = record
+ self.items[record.uid] = record
Modified: CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/xmlfile.py
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/xmlfile.py 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/directory/xmlfile.py 2010-02-12 22:49:09 UTC (rev 5105)
@@ -276,6 +276,10 @@
ET.SubElement(element, "last-name").text = principal.lastName
for value in principal.emailAddresses:
ET.SubElement(element, "email-address").text = value
+ if principal.extras:
+ extrasElement = ET.SubElement(element, "extras")
+ for key, value in principal.extras.iteritems():
+ ET.SubElement(extrasElement, key).text = value
return element
@@ -311,7 +315,7 @@
def createRecord(self, recordType, guid=None, shortNames=(), authIDs=set(),
fullName=None, firstName=None, lastName=None, emailAddresses=set(),
- uid=None, password=None, **kwds):
+ uid=None, password=None, **kwargs):
"""
Create and persist a record using the provided information. In this
XML-based implementation, the xml accounts are read in and converted
@@ -341,12 +345,13 @@
xmlPrincipal.firstName = firstName
xmlPrincipal.lastName = lastName
xmlPrincipal.emailAddresses = emailAddresses
+ xmlPrincipal.extras = kwargs
self._addElement(accountsElement, xmlPrincipal)
self._persistRecords(accountsElement)
- def destroyRecord(self, recordType, guid):
+ def destroyRecord(self, recordType, guid=None):
"""
Remove the record matching guid. In this XML-based implementation,
the xml accounts are read in and those not matching the given guid are
@@ -368,9 +373,9 @@
self._persistRecords(accountsElement)
- def updateRecord(self, recordType, guid, shortNames=(), authIDs=set(),
+ def updateRecord(self, recordType, guid=None, shortNames=(), authIDs=set(),
fullName=None, firstName=None, lastName=None, emailAddresses=set(),
- uid=None, password=None, **kwds):
+ uid=None, password=None, **kwargs):
"""
Update the record matching guid. In this XML-based implementation,
the xml accounts are read in and converted to elementtree elements.
@@ -394,6 +399,7 @@
xmlPrincipal.firstName = firstName
xmlPrincipal.lastName = lastName
xmlPrincipal.emailAddresses = emailAddresses
+ xmlPrincipal.extras = kwargs
self._addElement(accountsElement, xmlPrincipal)
else:
self._addElement(accountsElement, xmlPrincipal)
@@ -415,6 +421,7 @@
firstName = xmlPrincipal.firstName,
lastName = xmlPrincipal.lastName,
emailAddresses = xmlPrincipal.emailAddresses,
+ **xmlPrincipal.extras
)
self.password = xmlPrincipal.password
Modified: CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/mail.py
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/mail.py 2010-02-12 22:27:11 UTC (rev 5104)
+++ CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/mail.py 2010-02-12 22:49:09 UTC (rev 5105)
@@ -46,6 +46,7 @@
from twisted.python.reflect import namedClass
from twisted.python.usage import Options, UsageError
from twisted.web import client
+
from twext.web2 import server, responsecode
from twext.web2.channel.http import HTTPFactory
from twext.web2.dav import auth
@@ -53,13 +54,13 @@
from twext.web2.dav.noneprops import NonePropertyStore
from twext.web2.http import Response, HTTPError
from twext.web2.http_headers import MimeType
+from twext.web2.auth.basic import BasicCredentialFactory
from twext.log import Logger, LoggingMixIn
from twistedcaldav import ical, caldavxml
from twistedcaldav import memcachepool
from twistedcaldav.config import config
-from twistedcaldav.directory.digest import QopDigestCredentialFactory
from twistedcaldav.directory.principal import DirectoryPrincipalProvisioningResource
from twistedcaldav.directory.util import NotFilePath
from twistedcaldav.ical import Property
@@ -70,8 +71,6 @@
from twistedcaldav.static import CalDAVFile, deliverSchedulePrivilegeSet
from twistedcaldav.util import AuthorizedHTTPGetter
from twistedcaldav.stdconfig import DEFAULT_CONFIG, DEFAULT_CONFIG_FILE
-from twistedcaldav.sql import AbstractSQLDatabase
-from twistedcaldav.localization import translationTo
from calendarserver.provision.root import RootResource
@@ -605,17 +604,11 @@
portal = Portal(auth.DavRealm())
portal.registerChecker(directory)
realm = directory.realmName or ""
- schemeConfig = config.Authentication.Digest
- digestCredentialFactory = QopDigestCredentialFactory(
- schemeConfig["Algorithm"],
- schemeConfig["Qop"],
- realm,
- )
root.putChild('inbox',
auth.AuthenticationWrapper(
IMIPInvitationInboxResource(root, mailer),
portal,
- (digestCredentialFactory,),
+ (BasicCredentialFactory(realm),),
(auth.IPrincipal,),
)
)
Copied: CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/xmlutil.py (from rev 5104, CalendarServer/trunk/twistedcaldav/xmlutil.py)
===================================================================
--- CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/xmlutil.py (rev 0)
+++ CalendarServer/branches/users/glyph/use-system-twisted/twistedcaldav/xmlutil.py 2010-02-12 22:49:09 UTC (rev 5105)
@@ -0,0 +1,99 @@
+##
+# Copyright (c) 2010 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 xml.etree.ElementTree import Element, ElementTree, SubElement, tostring
+from xml.parsers.expat import ExpatError
+
+# Utilities for working with ElementTree
+
+def readXML(xmlfile, expectedRootTag=None):
+ """
+ Read in XML data from a file and parse into ElementTree. Optionally verify
+ the root node is what we expect.
+
+ @param xmlfile: file to read from
+ @type xmlfile: C{File}
+ @param expectedRootTag: root tag (qname) to test or C{None}
+ @type expectedRootTag: C{str}
+ @return: C{tuple} of C{ElementTree}, C{Element}
+ """
+
+ # Read in XML
+ try:
+ etree = ElementTree(file=xmlfile)
+ except ExpatError, e:
+ ValueError("Unable to parse file '%s' because: %s" % (xmlfile, e,))
+
+ if expectedRootTag:
+ root = etree.getroot()
+ if root.tag != expectedRootTag:
+ ValueError("Ignoring file '%s' because it is not a %s file" % (xmlfile, expectedRootTag,))
+
+ return etree, etree.getroot()
+
+def writeXML(xmlfile, root):
+
+ data = """<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE %s SYSTEM "%s.dtd">
+
+""" % (root.tag, root.tag)
+
+ INDENT = 2
+
+ # Generate indentation
+ def _indentNode(node, level=0):
+
+ if node.text is not None and node.text.strip():
+ return
+ elif len(node.getchildren()):
+ indent = "\n" + " " * (level + 1) * INDENT
+ node.text = indent
+ for child in node.getchildren():
+ child.tail = indent
+ _indentNode(child, level + 1)
+ if len(node.getchildren()):
+ node.getchildren()[-1].tail = "\n" + " " * level * INDENT
+
+ _indentNode(root, 0)
+ data += tostring(root) + "\n"
+
+ with open(xmlfile, "w") as f:
+ f.write(data)
+
+def newElementTreeWithRoot(roottag):
+
+ root = createElement(roottag)
+ etree = ElementTree(root)
+
+ return etree, root
+
+def createElement(tag, text=None):
+
+ child = Element(tag)
+ child.text = text
+ return child
+
+def addSubElement(parent, tag, text=None):
+
+ child = SubElement(parent, tag)
+ child.text = text
+ return child
+
+def changeSubElementText(parent, tag, text):
+
+ child = parent.find(tag)
+ child.text = text
+
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20100212/b80a8871/attachment-0001.html>
More information about the calendarserver-changes
mailing list