[CalendarServer-changes] [11084] CalendarServer/branches/users/gaya/directorybacker/twistedcaldav
source_changes at macosforge.org
source_changes at macosforge.org
Mon Apr 22 14:25:50 PDT 2013
Revision: 11084
http://trac.calendarserver.org//changeset/11084
Author: gaya at apple.com
Date: 2013-04-22 14:25:50 -0700 (Mon, 22 Apr 2013)
Log Message:
-----------
white-space cleaning
Modified Paths:
--------------
CalendarServer/branches/users/gaya/directorybacker/twistedcaldav/directory/ldapdirectorybacker.py
CalendarServer/branches/users/gaya/directorybacker/twistedcaldav/directory/opendirectorybacker.py
CalendarServer/branches/users/gaya/directorybacker/twistedcaldav/directory/xmldirectorybacker.py
CalendarServer/branches/users/gaya/directorybacker/twistedcaldav/query/addressbookqueryfilter.py
CalendarServer/branches/users/gaya/directorybacker/twistedcaldav/stdconfig.py
Modified: CalendarServer/branches/users/gaya/directorybacker/twistedcaldav/directory/ldapdirectorybacker.py
===================================================================
--- CalendarServer/branches/users/gaya/directorybacker/twistedcaldav/directory/ldapdirectorybacker.py 2013-04-22 18:46:28 UTC (rev 11083)
+++ CalendarServer/branches/users/gaya/directorybacker/twistedcaldav/directory/ldapdirectorybacker.py 2013-04-22 21:25:50 UTC (rev 11084)
@@ -42,19 +42,19 @@
self._actuallyConfigure(**params)
def _actuallyConfigure(self, **params):
-
+
self.log_debug("_actuallyConfigure: params=%s" % (params,))
defaults = {
- "recordTypes": (), # for super
+ "recordTypes": (), # for super
"rdnSchema": {
"base": "dc=example,dc=com",
"queries": (
- { #people
+ { #people
"rdn":"ou=people",
- "vcardPropToLdapAttrMap" : { # maps vCard properties to searchable ldap attributes
+ "vcardPropToLdapAttrMap" : { # maps vCard properties to searchable ldap attributes
"FN" : "cn",
},
- "ldapAttrToDSAttrMap" : { # maps ldap attributes to ds attribute types
+ "ldapAttrToDSAttrMap" : { # maps ldap attributes to ds attribute types
"cn" : "dsAttrTypeStandard:RealName",
},
"additionalVCardProps":None,
@@ -62,10 +62,10 @@
),
},
- "removeDuplicateUIDs":True, # remove vCards with duplicate UIDs
- "appleInternalServer":False, # does magic in ABDirectoryQueryResult
- "maxQueryResults":0, # max records returned
- "fakeETag":True, # eTag is fake, otherwise it is md5(all attributes)
+ "removeDuplicateUIDs":True, # remove vCards with duplicate UIDs
+ "appleInternalServer":False, # does magic in ABDirectoryQueryResult
+ "maxQueryResults":0, # max records returned
+ "fakeETag":True, # eTag is fake, otherwise it is md5(all attributes)
}
#params = self.getParams(params, defaults, ignored)
@@ -74,23 +74,23 @@
if not key in params:
params[key] = defaults[key]
return params
-
+
params = addDefaults(params, defaults)
self.log_debug("_actuallyConfigure after addDefaults: params=%s" % (params,))
-
+
# super does not like these extra params
- directoryBackedAddressBook=params["directoryBackedAddressBook"]
+ directoryBackedAddressBook = params["directoryBackedAddressBook"]
del params["directoryBackedAddressBook"]
- appleInternalServer=params["appleInternalServer"]
- del params["appleInternalServer"]
- maxQueryResults=params["maxQueryResults"]
+ appleInternalServer = params["appleInternalServer"]
+ del params["appleInternalServer"]
+ maxQueryResults = params["maxQueryResults"]
del params["maxQueryResults"]
- fakeETag=params["fakeETag"]
+ fakeETag = params["fakeETag"]
del params["fakeETag"]
- removeDuplicateUIDs=params["removeDuplicateUIDs"]
+ removeDuplicateUIDs = params["removeDuplicateUIDs"]
del params["removeDuplicateUIDs"]
-
+
#standardize ds attributes type names
# or we could just require dsAttrTypeStandard: prefix in the plist
rdnSchema = params["rdnSchema"];
@@ -98,69 +98,69 @@
ldapAttrToDSAttrMap = query["ldapAttrToDSAttrMap"]
for ldapAttrName, dsAttrNames in ldapAttrToDSAttrMap.iteritems():
if not isinstance(dsAttrNames, list):
- dsAttrNames = [dsAttrNames,]
-
+ dsAttrNames = [dsAttrNames, ]
+
normalizedDSAttrNames = []
for dsAttrName in dsAttrNames:
if not dsAttrName.startswith("dsAttrTypeStandard:") and not dsAttrName.startswith("dsAttrTypeNative:"):
normalizedDSAttrNames.append("dsAttrTypeStandard:" + dsAttrName)
else:
normalizedDSAttrNames.append(dsAttrName)
-
+
# not needed, but tests code paths
if len(normalizedDSAttrNames) > 1:
ldapAttrToDSAttrMap[ldapAttrName] = normalizedDSAttrNames
else:
ldapAttrToDSAttrMap[ldapAttrName] = normalizedDSAttrNames[0]
-
-
+
+
self.log_debug("_actuallyConfigure after clean: params=%s" % (params,))
-
+
assert directoryBackedAddressBook is not None
self.directoryBackedAddressBook = directoryBackedAddressBook
-
+
self.maxQueryResults = maxQueryResults
-
+
### params for ABDirectoryQueryResult()
self.fakeETag = fakeETag
self.appleInternalServer = appleInternalServer
self.removeDuplicateUIDs = removeDuplicateUIDs
-
+
super(LdapDirectoryBackingService, self).__init__(params)
-
-
+
+
def createCache(self):
succeed(None)
-
+
@inlineCallbacks
- def _getLdapQueryResults(self, base, queryStr, attributes=None, maxResults=0, ldapAttrToDSAttrMap=None, ldapAttrTransforms=None, additionalVCardProps=None, kind=None ):
+ def _getLdapQueryResults(self, base, queryStr, attributes=None, maxResults=0, ldapAttrToDSAttrMap=None, ldapAttrTransforms=None, additionalVCardProps=None, kind=None):
"""
Get a list of ABDirectoryQueryResult for the given query with the given attributes.
query == None gets all records. attribute == None gets ABDirectoryQueryResult.allDSQueryAttributes
"""
limited = False
resultsDictionary = {}
-
+
# can't resist also using a timeout, 1 sec per request result for now
timeout = maxResults
self.log_debug("_getLdapQueryResults: LDAP query base=%s and filter=%s and attributes=%s timeout=%s resultLimit=%s" % (ldap.dn.dn2str(base), queryStr, attributes, timeout, maxResults))
-
+
ldapSearchResult = (yield self.timedSearch(ldap.dn.dn2str(base), ldap.SCOPE_SUBTREE, filterstr=queryStr, attrlist=attributes, timeoutSeconds=timeout, resultLimit=maxResults))
self.log_debug("_getLdapQueryResults: ldapSearchResult=%s" % (ldapSearchResult,))
-
+
if maxResults and len(ldapSearchResult) >= maxResults:
limited = True
- self.log_debug("_getLdapQueryResults: limit (= %d) reached." % (maxResults, ))
+ self.log_debug("_getLdapQueryResults: limit (= %d) reached." % (maxResults,))
for dn, ldapAttributes in ldapSearchResult:
#dn = normalizeDNstr(dn)
result = None
try:
if "dn" not in ldapAttributes:
- ldapAttributes["dn"] = [normalizeDNstr(dn),]
-
+ ldapAttributes["dn"] = [normalizeDNstr(dn), ]
+
# make a dsRecordAttributes dict from the ldap attributes
dsRecordAttributes = {}
for ldapAttributeName, ldapAttributeValues in ldapAttributes.iteritems():
@@ -169,15 +169,15 @@
# get rid of '' values
ldapAttributeValues = [attr for attr in ldapAttributeValues if len(attr)]
-
+
if len(ldapAttributeValues):
-
-
+
+
dsAttributeNames = ldapAttrToDSAttrMap.get(ldapAttributeName)
if dsAttributeNames:
-
+
if ldapAttrTransforms:
-
+
# do value transforms
# need to expand this to cover all cases
# All this does now is to pull part of an ldap string out
@@ -185,8 +185,8 @@
transforms = ldapAttrTransforms.get(ldapAttributeName)
if transforms:
if not isinstance(transforms, list):
- transforms = [transforms,]
-
+ transforms = [transforms, ]
+
transformedValues = []
for ldapAttributeValue in ldapAttributeValues:
transformedValue = ldapAttributeValue
@@ -197,32 +197,32 @@
if transform.lower() == kvPair[0]:
transformedValue = kvPair[1]
break
-
- transformedValues += [transformedValue,]
-
+
+ transformedValues += [transformedValue, ]
+
if (ldapAttributeValues != transformedValues):
self.log_debug("_getLdapQueryResults: %s %s transformed to %s" % (ldapAttributeName, ldapAttributeValues, transformedValues))
ldapAttributeValues = transformedValues
-
-
-
+
+
+
if not isinstance(dsAttributeNames, list):
- dsAttributeNames = [dsAttributeNames,]
-
+ dsAttributeNames = [dsAttributeNames, ]
+
for dsAttributeName in dsAttributeNames:
-
+
# base64 encode binary attributes
if dsAttributeName in ABDirectoryQueryResult.binaryDSAttrNames:
ldapAttributeValues = [attr.encode('base64') for attr in ldapAttributeValues]
-
+
# add to dsRecordAttributes
if dsAttributeName not in dsRecordAttributes:
dsRecordAttributes[dsAttributeName] = list()
-
+
dsRecordAttributes[dsAttributeName] = list(set(dsRecordAttributes[dsAttributeName] + ldapAttributeValues))
self.log_debug("doAddressBookQuery: dsRecordAttributes[%s] = %s" % (dsAttributeName, dsRecordAttributes[dsAttributeName],))
- # get a record for dsRecordAttributes
+ # get a record for dsRecordAttributes
result = ABDirectoryQueryResult(self.directoryBackedAddressBook, dsRecordAttributes, kind=kind, additionalVCardProps=additionalVCardProps, appleInternalServer=self.appleInternalServer)
except:
traceback.print_exc()
@@ -233,21 +233,22 @@
if uid in resultsDictionary:
self.log_info("Record skipped due to duplicate UID: %s" % (dn,))
continue
-
- self.log_debug("VCard text =\n%s" % (result.vCardText(), ))
- resultsDictionary[uid] = result
+ self.log_debug("VCard text =\n%s" % (result.vCardText(),))
+ resultsDictionary[uid] = result
+
self.log_debug("%s results (limited=%s)." % (len(resultsDictionary), limited))
- returnValue((resultsDictionary, limited, ))
+ returnValue((resultsDictionary, limited,))
+
@inlineCallbacks
- def doAddressBookQuery(self, addressBookFilter, addressBookQuery, maxResults ):
+ def doAddressBookQuery(self, addressBookFilter, addressBookQuery, maxResults):
"""
Get vCards for a given addressBookFilter and addressBookQuery
"""
-
+
results = {} if self.removeDuplicateUIDs else []
-
+
#one ldap query for each rnd in queries
for queryMap in self.rdnSchema["queries"]:
@@ -257,28 +258,27 @@
additionalVCardProps = queryMap.get("additionalVCardProps")
ldapAttrTransforms = queryMap.get("ldapAttrTransforms")
kind = queryMap.get("kind", "individual")
-
+
# add constants and KIND
constantProperties = ABDirectoryQueryResult.constantProperties.copy()
if additionalVCardProps:
for key, value in additionalVCardProps.iteritems():
if key not in constantProperties:
constantProperties[key] = value
-
+
# add KIND as constant so that query can be skipped if addressBookFilter needs a different kind
constantProperties["KIND"] = kind
-
- filterPropertyNames, dsFilter = dsFilterFromAddressBookFilter( addressBookFilter, vcardPropToLdapAttrMap, constantProperties=constantProperties );
+ filterPropertyNames, dsFilter = dsFilterFromAddressBookFilter(addressBookFilter, vcardPropToLdapAttrMap, constantProperties=constantProperties);
self.log_debug("doAddressBookQuery: rdn=%s, query=%s, propertyNames=%s" % (rdn, dsFilter if isinstance(dsFilter, bool) else dsFilter.generate(), filterPropertyNames))
if dsFilter:
if dsFilter is True:
dsFilter = None
-
+
# calculate minimum attributes needed for this query
- etagRequested, queryPropNames = propertiesInAddressBookQuery( addressBookQuery )
-
+ etagRequested, queryPropNames = propertiesInAddressBookQuery(addressBookQuery)
+
if (etagRequested and not self.fakeETag) or not queryPropNames:
queryAttributes = ldapAttrToDSAttrMap.keys()
elif queryPropNames:
@@ -291,18 +291,18 @@
if attributes:
queryAttributes += attributes
'''
-
- queryAttributes = ldapAttrToDSAttrMap.keys()
-
+
+ queryAttributes = ldapAttrToDSAttrMap.keys()
+
self.log_debug("doAddressBookQuery: etagRequested=%s, queryPropNames=%s, queryAttributes=%s" % (etagRequested, queryPropNames, queryAttributes,))
-
+
#get all ldap attributes -- for debug
if queryMap.get("getAllAttributes"):
queryAttributes = None
-
- base = ldap.dn.str2dn(rdn) + self.base
-
- queryStr = "(cn=*)" # all results query - should make a param
+
+ base = ldap.dn.str2dn(rdn) + self.base
+
+ queryStr = "(cn=*)" # all results query - should make a param
#add additional filter from config
queryFilter = queryMap.get("filter")
if dsFilter and queryFilter:
@@ -312,64 +312,61 @@
elif dsFilter:
queryStr = dsFilter.generate()
-
# keep trying ldap query till we get results based on filter. Especially when doing "all results" query
remainingMaxResults = maxResults - len(results) if maxResults else 0
maxLdapResults = int(remainingMaxResults * 1.2)
-
+
while True:
- ldapQueryResultsDictionary, ldapQueryLimited = (yield self._getLdapQueryResults(base=base,
- queryStr=queryStr,
- attributes=queryAttributes,
- maxResults=maxLdapResults,
- kind=kind,
- ldapAttrToDSAttrMap=ldapAttrToDSAttrMap,
- ldapAttrTransforms=ldapAttrTransforms,
+ ldapQueryResultsDictionary, ldapQueryLimited = (yield self._getLdapQueryResults(base=base,
+ queryStr=queryStr,
+ attributes=queryAttributes,
+ maxResults=maxLdapResults,
+ kind=kind,
+ ldapAttrToDSAttrMap=ldapAttrToDSAttrMap,
+ ldapAttrTransforms=ldapAttrTransforms,
additionalVCardProps=additionalVCardProps))
-
+
for uid, ldapQueryResult in ldapQueryResultsDictionary.iteritems():
if self.removeDuplicateUIDs and uid in results:
self.log_info("Record skipped due to duplicate UID: %s" % (uid,))
continue
-
+
if not addressBookFilter.match(ldapQueryResult.vCard()):
self.log_debug("doAddressBookQuery did not match filter: %s (%s)" % (ldapQueryResult.vCard().propertyValue("FN"), uid,))
continue
-
+
if self.removeDuplicateUIDs:
results[uid] = ldapQueryResult
else:
- results += [ldapQueryResult,]
+ results += [ldapQueryResult, ]
-
- #no more results
+ # no more results
if not ldapQueryLimited:
break;
-
+
# more than requested results
if maxResults and len(results) >= maxResults:
break
-
+
# more than max report results
if len(results) >= config.MaxQueryWithDataResults:
break
-
+
# more than self limit
if self.maxQueryResults and maxLdapResults >= self.maxQueryResults:
break
-
+
# try again with 2x
maxLdapResults *= 2
if self.maxQueryResults and maxLdapResults > self.maxQueryResults:
maxLdapResults = self.maxQueryResults
-
+
if maxResults and len(results) >= maxResults:
break
-
-
+
limited = maxResults and len(results) >= maxResults
-
- self.log_info("limited %s len(results) %s" % (limited,len(results),))
- returnValue((results.values() if self.removeDuplicateUIDs else results, limited,))
+ self.log_info("limited %s len(results) %s" % (limited, len(results),))
+ returnValue((results.values() if self.removeDuplicateUIDs else results, limited,))
+
Modified: CalendarServer/branches/users/gaya/directorybacker/twistedcaldav/directory/opendirectorybacker.py
===================================================================
--- CalendarServer/branches/users/gaya/directorybacker/twistedcaldav/directory/opendirectorybacker.py 2013-04-22 18:46:28 UTC (rev 11083)
+++ CalendarServer/branches/users/gaya/directorybacker/twistedcaldav/directory/opendirectorybacker.py 2013-04-22 21:25:50 UTC (rev 11084)
@@ -81,15 +81,15 @@
userNode="/Search",
queryGroupRecords=True,
groupNode="/Search",
- maxDSQueryRecords=0, # maximum number of records requested for any ds query
+ maxDSQueryRecords=0, # maximum number of records requested for any ds query
- queryDSLocal=False, #query in DSLocal -- debug
+ queryDSLocal=False, # query in DSLocal -- debug
dsLocalCacheTimeout=30,
ignoreSystemRecords=True,
- fakeETag=True, # eTag is not reliable if True
+ fakeETag=True, # eTag is not reliable if True
- addDSAttrXProperties=False, # add dsattributes to vcards as "X-" attributes
+ addDSAttrXProperties=False, # add dsattributes to vcards as "X-" attributes
appleInternalServer=False,
additionalAttributes=None,
@@ -202,7 +202,7 @@
#get attributes required for needed for valid vCard
requiredAttributes = [attr for prop in ("UID", "FN", "N") for attr in ABDirectoryQueryResult.vcardPropToDSAttrMap[prop]]
- requiredAttributes += [dsattributes.kDS1AttrModificationTimestamp, dsattributes.kDS1AttrCreationTimestamp, ] # for VCardResult DAVPropertyMixIn
+ requiredAttributes += [dsattributes.kDS1AttrModificationTimestamp, dsattributes.kDS1AttrCreationTimestamp, ] # for VCardResult DAVPropertyMixIn
self.requiredAttributes = list(set(requiredAttributes))
self.log_debug("self.requiredAttributes=%s" % (self.requiredAttributes,))
@@ -297,7 +297,7 @@
self.log_error("Open Directory (node=%s) error: %s" % ("/Local/Default", str(ex)))
raise
- for (recordShortName, recordAttributes) in records: #@UnusedVariable
+ for (recordShortName, recordAttributes) in records: #@UnusedVariable
try:
self.log_info("Inspecting record %s" % (recordAttributes,))
@@ -330,7 +330,7 @@
if time.time() > self._nextDSLocalQueryTime:
self._dsLocalResults = generateDSLocalResults()
- # Add jitter/fuzz factor
+ # Add jitter/fuzz factor
self._nextDSLocalQueryTime = time.time() + self.dsLocalCacheTimeout * (random() + 0.5) * 60
return self._dsLocalResults
@@ -353,7 +353,7 @@
resultsDictionary = self._getAllDSLocalResults().copy()
self.log_debug("Adding %s DSLocal results" % len(resultsDictionary.keys()))
- for (recordShortName, recordAttributes) in records: #@UnusedVariable
+ for (recordShortName, recordAttributes) in records: #@UnusedVariable
try:
# fix ds strangeness
@@ -511,7 +511,7 @@
kind = dsRecordTypeToKindMap.get(recordType, "individual")
constantProperties["KIND"] = kind
- filterPropertyNames, dsFilter = dsFilterFromAddressBookFilter(addressBookFilter, #@UnusedVariable
+ filterPropertyNames, dsFilter = dsFilterFromAddressBookFilter(addressBookFilter, #@UnusedVariable
self.vcardPropToSearchableDSAttrMap,
constantProperties=constantProperties);
if not dsFilter is False:
@@ -572,7 +572,7 @@
else:
self.log_debug("doAddressBookQuery: result did not match filter: %s (%s)" % (dsQueryResult.vCard().propertyValue("FN"), dsQueryResult.vCard().propertyValue("UID"),))
- #no more results
+ #no more results
if not dsQueryLimited:
break;
@@ -655,20 +655,20 @@
elif addedExpressions is not None:
if addedExpressions is True:
if not allOf:
- expressionList = True # expressionList or True is True
+ expressionList = True # expressionList or True is True
#else expressionList and True is expressionList
elif addedExpressions is False:
if allOf:
- expressionList = False # expressionList and False is False
+ expressionList = False # expressionList and False is False
#else expressionList or False is expressionList
else:
if expressionList is False:
if not allOf:
- expressionList = addedExpressions # False or addedExpressions is addedExpressions
+ expressionList = addedExpressions # False or addedExpressions is addedExpressions
#else False and addedExpressions is False
elif expressionList is True:
if allOf:
- expressionList = addedExpressions # False or addedExpressions is addedExpressions
+ expressionList = addedExpressions # False or addedExpressions is addedExpressions
#else False and addedExpressions is False
else:
expressionList += addedExpressions
@@ -687,7 +687,7 @@
def definedExpression(defined, allOf):
if constant or propFilter.filter_name in ("N" , "FN", "UID", "SOURCE",):
- return defined # all records have this property so no records do not have it
+ return defined # all records have this property so no records do not have it
else:
matchList = [dsquery.match(attrName, "", dsattributes.eDSStartsWith) for attrName in searchablePropFilterAttrNames]
if defined:
@@ -710,7 +710,7 @@
#end andOrExpression()
- def paramFilterElementExpression(propFilterAllOf, paramFilterElement): #@UnusedVariable
+ def paramFilterElementExpression(propFilterAllOf, paramFilterElement): #@UnusedVariable
params = ABDirectoryQueryResult.vcardPropToParamMap.get(propFilter.filter_name.upper())
defined = params and paramFilterElement.filter_name.upper() in params
@@ -730,8 +730,7 @@
def textMatchElementExpression(propFilterAllOf, textMatchElement):
-
- # pre process text match strings for ds query
+ # pre process text match strings for ds query
def getMatchStrings(propFilter, matchString):
if propFilter.filter_name in ("REV" , "BDAY",):
@@ -827,7 +826,6 @@
return definedExpression(True, propFilterAllOf)
#end textMatchElementExpression()
-
# searchablePropFilterAttrNames are attributes to be used by this propfilter's expression
searchableAttributes = vcardPropToSearchableAttrMap.get(propFilter.filter_name, [])
if isinstance(searchableAttributes, str):
@@ -896,7 +894,7 @@
elif len(expressions):
expr = expressions[0]
else:
- expr = not filterAllOf # empty expression list. should not happen
+ expr = not filterAllOf # empty expression list. should not happen
elif expressions is None:
expr = expr = not filterAllOf
else:
@@ -1045,7 +1043,7 @@
"PHOTO": { "ENCODING": ("B",), "TYPE": ("JPEG",), },
"ADR": { "TYPE": ("WORK", "PREF", "POSTAL", "PARCEL",), },
"LABEL": { "TYPE": ("POSTAL", "PARCEL",)},
- "TEL": { "TYPE": None, }, # None means param can contain can be anything
+ "TEL": { "TYPE": None, }, # None means param can contain can be anything
"EMAIL": { "TYPE": None, },
"KEY": { "ENCODING": ("B",), "TYPE": ("PGPPUBILICKEY", "USERCERTIFICATE", "USERPKCS12DATA", "USERSMIMECERTIFICATE",) },
"URL": { "TYPE": ("WEBLOG", "HOMEPAGE",) },
@@ -1105,7 +1103,7 @@
else:
self.attributes[key] = values
- # find or create guid
+ # find or create guid
guid = self.firstValueForAttribute(dsattributes.kDS1AttrGeneratedUID)
if not guid:
nameUUIDStr = "".join(self.firstValueForAttribute(dsattributes.kDSNAttrRecordName).encode("base64").split("\n"))
@@ -1263,7 +1261,7 @@
paramTypeStrings += ["PREF", ]
parameters = { "TYPE": paramTypeStrings, }
- #special case for IMHandles which the param is the last part of the property like X-AIM or X-JABBER
+ #special case for IMHandles which the param is the last part of the property like X-AIM or X-JABBER
if propertyPrefix:
propertyName = propertyPrefix + paramTypeString
@@ -1303,11 +1301,11 @@
# dsattributes.kDS1AttrMiddleName, #Used for the middle name of user or person record.
# dsattributes.kDSNAttrNameSuffix, # Represents the name suffix of a user or person.
# ie. Jr., Sr., etc.
- # Usually found in user or people records (kDSStdRecordTypeUsers or
+ # Usually found in user or people records (kDSStdRecordTypeUsers or
# dsattributes.kDSStdRecordTypePeople).
# dsattributes.kDSNAttrNamePrefix, # Represents the title prefix of a user or person.
# ie. Mr., Ms., Mrs., Dr., etc.
- # Usually found in user or people records (kDSStdRecordTypeUsers or
+ # Usually found in user or people records (kDSStdRecordTypeUsers or
# dsattributes.kDSStdRecordTypePeople).
# name is required, so make sure we have one
@@ -1333,19 +1331,19 @@
# 3.1.3 NICKNAME Type Definition
# dsattributes.kDSNAttrNickName, # Represents the nickname of a user or person.
- # Usually found in user or people records (kDSStdRecordTypeUsers or
+ # Usually found in user or people records (kDSStdRecordTypeUsers or
# dsattributes.kDSStdRecordTypePeople).
for nickname in self.valuesForAttribute(dsattributes.kDSNAttrNickName):
addUniqueProperty(vcard, Property("NICKNAME", nickname), None, dsattributes.kDSNAttrNickName, nickname)
# 3.1.4 PHOTO Type Definition
- # dsattributes.kDSNAttrJPEGPhoto, # Used to store binary picture data in JPEG format.
- # Usually found in user, people or group records (kDSStdRecordTypeUsers,
+ # dsattributes.kDSNAttrJPEGPhoto, # Used to store binary picture data in JPEG format.
+ # Usually found in user, people or group records (kDSStdRecordTypeUsers,
# dsattributes.kDSStdRecordTypePeople,dsattributes.kDSStdRecordTypeGroups).
- # pyOpenDirectory always returns binary-encoded string
+ # pyOpenDirectory always returns binary-encoded string
for photo in self.valuesForAttribute(dsattributes.kDSNAttrJPEGPhoto):
- photo = "".join("".join(photo.split("\r")).split("\n")) #get rid of line folding: for PHOTO
+ photo = "".join("".join(photo.split("\r")).split("\n")) #get rid of line folding: for PHOTO
addUniqueProperty(vcard, Property("PHOTO", photo, params={"ENCODING": ["b", ], "TYPE": ["JPEG", ], }), None, dsattributes.kDSNAttrJPEGPhoto, photo)
@@ -1419,17 +1417,17 @@
# dsattributes.kDSNAttrPhoneNumber, # Telephone number of a user.
# dsattributes.kDSNAttrMobileNumber, # Represents the mobile numbers of a user or person.
- # Usually found in user or people records (kDSStdRecordTypeUsers or
+ # Usually found in user or people records (kDSStdRecordTypeUsers or
# dsattributes.kDSStdRecordTypePeople).
# dsattributes.kDSNAttrFaxNumber, # Represents the FAX numbers of a user or person.
- # Usually found in user or people records (kDSStdRecordTypeUsers or
+ # Usually found in user or people records (kDSStdRecordTypeUsers or
# kDSStdRecordTypePeople).
# dsattributes.kDSNAttrPagerNumber, # Represents the pager numbers of a user or person.
- # Usually found in user or people records (kDSStdRecordTypeUsers or
+ # Usually found in user or people records (kDSStdRecordTypeUsers or
# dsattributes.kDSStdRecordTypePeople).
# dsattributes.kDSNAttrHomePhoneNumber, # Home telephone number of a user or person.
# dsattributes.kDSNAttrPhoneContacts, # multi-valued attribute that defines a record's custom phone numbers .
- # found in user records (kDSStdRecordTypeUsers).
+ # found in user records (kDSStdRecordTypeUsers).
# Example: home fax:408-555-4444
params = {"TYPE": ["WORK", "PREF", "VOICE", ], }
@@ -1478,7 +1476,7 @@
params = workParams
# dsattributes.kDSNAttrEMailContacts, # multi-valued attribute that defines a record's custom email addresses .
- # found in user records (kDSStdRecordTypeUsers).
+ # found in user records (kDSStdRecordTypeUsers).
# Example: home:johndoe at mymail.com
# check to see if parameters type are open ended. Could be any string
@@ -1555,17 +1553,17 @@
# 3.6.6 SOUND Type Definition
"""
# 3.6.7 UID Type Definition
- # dsattributes.kDS1AttrGeneratedUID, # Used for 36 character (128 bit) unique ID. Usually found in user,
+ # dsattributes.kDS1AttrGeneratedUID, # Used for 36 character (128 bit) unique ID. Usually found in user,
# group, and computer records. An example value is "A579E95E-CDFE-4EBC-B7E7-F2158562170F".
# The standard format contains 32 hex characters and four hyphen characters.
vcard.addProperty(Property("UID", self.firstValueForAttribute(dsattributes.kDS1AttrGeneratedUID)))
- # 3.6.8 URL Type Definition
+ # 3.6.8 URL Type Definition
# dsattributes.kDSNAttrURL, # List of URLs.
# dsattributes.kDS1AttrWeblogURI, # Single-valued attribute that defines the URI of a user's weblog.
- # Usually found in user records (kDSStdRecordTypeUsers).
+ # Usually found in user records (kDSStdRecordTypeUsers).
# Example: http://example.com/blog/jsmith
for url in self.valuesForAttribute(dsattributes.kDS1AttrWeblogURI):
addPropertyAndLabel(groupCount, "weblog", "URL", url, parameters={"TYPE": ["WEBLOG", ]})
@@ -1586,14 +1584,14 @@
# dsattributes.kDSNAttrPGPPublicKey, # Pretty Good Privacy public encryption key.
# dsattributes.kDS1AttrUserCertificate, # Attribute containing the binary of the user's certificate.
# Usually found in user records. The certificate is data which identifies a user.
- # This data is attested to by a known party, and can be independently verified
+ # This data is attested to by a known party, and can be independently verified
# by a third party.
- # dsattributes.kDS1AttrUserPKCS12Data, # Attribute containing binary data in PKCS #12 format.
+ # dsattributes.kDS1AttrUserPKCS12Data, # Attribute containing binary data in PKCS #12 format.
# Usually found in user records. The value can contain keys, certificates,
# and other related information and is encrypted with a passphrase.
# dsattributes.kDS1AttrUserSMIMECertificate,# Attribute containing the binary of the user's SMIME certificate.
# Usually found in user records. The certificate is data which identifies a user.
- # This data is attested to by a known party, and can be independently verified
+ # This data is attested to by a known party, and can be independently verified
# by a third party. SMIME certificates are often used for signed or encrypted
# emails.
@@ -1635,7 +1633,7 @@
# X-ABRELATEDNAMES
# dsattributes.kDSNAttrRelationships, # multi-valued attribute that defines the relationship to the record type .
- # found in user records (kDSStdRecordTypeUsers).
+ # found in user records (kDSStdRecordTypeUsers).
# Example: brother:John
addPropertiesAndLabelsForPrefixedAttribute(groupCount=groupCount, propertyPrefix=None, propertyName="X-ABRELATEDNAMES", defaultLabel="friend",
labelMap={ "FATHER":"_$!<Father>!$_",
@@ -1715,9 +1713,9 @@
source = "http://%s:%s%s" % (config.ServerHostName, config.HTTPPort, uri)
vcard.addProperty(Property("SOURCE", source))
- # in 4.0 spec:
+ # in 4.0 spec:
# 6.1.4. KIND http://tools.ietf.org/html/rfc6350#section-6.1.4
- #
+ #
# see also: http://www.iana.org/assignments/vcard-elements/vcard-elements.xml
#
vcard.addProperty(Property("KIND", self.kind))
@@ -1764,7 +1762,7 @@
if namespace == dav_namespace:
if name == "resourcetype":
- result = davxml.ResourceType.empty #@UndefinedVariable
+ result = davxml.ResourceType.empty #@UndefinedVariable
return result
elif name == "getetag":
result = davxml.GETETag(ETag(hashlib.md5(self.vCardText()).hexdigest()).generate())
@@ -1797,7 +1795,7 @@
creationDateString = self.isoDateStringForDateAttribute(dsattributes.kDS1AttrCreationTimestamp)
if creationDateString:
creationDatetime = parse_date(creationDateString)
- elif self.vCard().hasProperty("REV"): # use modification date property if it exists
+ elif self.vCard().hasProperty("REV"): # use modification date property if it exists
creationDatetime = parse_date(self.vCard().propertyValue("REV"))
else:
creationDatetime = datetime.datetime.utcnow()
@@ -1814,7 +1812,7 @@
return self._directoryBackedAddressBook.readProperty(property, request)
- def listProperties(self, request): #@UnusedVariable
+ def listProperties(self, request): # @UnusedVariable
qnames = set(self.liveProperties())
# Add dynamic live properties that exist
Modified: CalendarServer/branches/users/gaya/directorybacker/twistedcaldav/directory/xmldirectorybacker.py
===================================================================
--- CalendarServer/branches/users/gaya/directorybacker/twistedcaldav/directory/xmldirectorybacker.py 2013-04-22 18:46:28 UTC (rev 11083)
+++ CalendarServer/branches/users/gaya/directorybacker/twistedcaldav/directory/xmldirectorybacker.py 2013-04-22 21:25:50 UTC (rev 11084)
@@ -36,18 +36,18 @@
"""
Directory backer for L{XMLDirectoryService}.
"""
-
+
def __init__(self, params):
self._actuallyConfigure(**params)
def _actuallyConfigure(self, **params):
-
+
self.log_debug("_actuallyConfigure: params=%s" % (params,))
defaults = {
- "recordTypes": (self.recordType_users, self.recordType_groups, ),
+ "recordTypes": (self.recordType_users, self.recordType_groups,),
"rdnSchema": {
- self.recordType_users : {
- "vcardPropToDirRecordAttrMap" : {
+ self.recordType_users : {
+ "vcardPropToDirRecordAttrMap" : {
"FN" : (
"fullName",
"shortNames",
@@ -63,7 +63,7 @@
"EMAIL" : "emailAddresses",
"UID" : "guid",
},
- "dirRecordAttrToDSAttrMap" : {
+ "dirRecordAttrToDSAttrMap" : {
"guid" : dsattributes.kDS1AttrGeneratedUID,
"fullName" : dsattributes.kDS1AttrDistinguishedName,
"firstName" : dsattributes.kDS1AttrFirstName,
@@ -71,8 +71,8 @@
"emailAddresses" : dsattributes.kDSNAttrEMailAddress,
},
},
- self.recordType_groups : {
- "vcardPropToDirRecordAttrMap" : {
+ self.recordType_groups : {
+ "vcardPropToDirRecordAttrMap" : {
"FN" : (
"fullName",
"shortNames",
@@ -89,7 +89,7 @@
"UID" : "guid",
"X-ADDRESSBOOKSERVER-MEMBER" : "members",
},
- "dirRecordAttrToDSAttrMap" : {
+ "dirRecordAttrToDSAttrMap" : {
"guid" : dsattributes.kDS1AttrGeneratedUID,
"fullName" : dsattributes.kDS1AttrDistinguishedName,
"firstName" : dsattributes.kDS1AttrFirstName,
@@ -99,9 +99,9 @@
},
},
},
- "maxQueryResults":0, # max records returned
- "sortResults":True, # sort results by UID
- "implementNot":True, # implement Not query by listing all records and subtracting
+ "maxQueryResults":0, # max records returned
+ "sortResults":True, # sort results by UID
+ "implementNot":True, # implement Not query by listing all records and subtracting
}
#params = self.getParams(params, defaults, ignored)
@@ -110,45 +110,45 @@
if not key in params:
params[key] = defaults[key]
return params
-
+
params = addDefaults(params, defaults)
self.log_debug("_actuallyConfigure after addDefaults: params=%s" % (params,))
-
+
# super does not like these extra params
- directoryBackedAddressBook=params["directoryBackedAddressBook"]
+ directoryBackedAddressBook = params["directoryBackedAddressBook"]
#del params["directoryBackedAddressBook"]
- rdnSchema=params["rdnSchema"]
+ rdnSchema = params["rdnSchema"]
del params["rdnSchema"]
- maxQueryResults=params["maxQueryResults"]
+ maxQueryResults = params["maxQueryResults"]
del params["maxQueryResults"]
- sortResults=params["sortResults"]
+ sortResults = params["sortResults"]
del params["sortResults"]
- implementNot=params["implementNot"]
+ implementNot = params["implementNot"]
del params["implementNot"]
-
-
+
+
assert directoryBackedAddressBook is not None
self.directoryBackedAddressBook = directoryBackedAddressBook
-
+
self.maxQueryResults = maxQueryResults
self.sortResults = sortResults
self.implementNot = implementNot
self.rdnSchema = rdnSchema
-
+
super(XMLDirectoryBackingService, self).__init__(params)
-
-
+
+
def createCache(self):
succeed(None)
-
+
@inlineCallbacks
- def doAddressBookQuery(self, addressBookFilter, addressBookQuery, maxResults ):
+ def doAddressBookQuery(self, addressBookFilter, addressBookQuery, maxResults):
"""
Get vCards for a given addressBookFilter and addressBookQuery
"""
-
+
results = []
limited = False
@@ -157,24 +157,24 @@
queryMap = self.rdnSchema[recordType]
vcardPropToDirRecordAttrMap = queryMap["vcardPropToDirRecordAttrMap"]
dirRecordAttrToDSAttrMap = queryMap["dirRecordAttrToDSAttrMap"]
-
+
kind = {self.recordType_groups:"group",
self.recordType_locations:"location",
self.recordType_resources:"calendarresource",
}.get(recordType, "individual")
-
+
constantProperties = ABDirectoryQueryResult.constantProperties.copy()
constantProperties["KIND"] = kind
# add KIND as constant so that query can be skipped if addressBookFilter needs a different kind
- filterPropertyNames, dsFilter = dsFilterFromAddressBookFilter( addressBookFilter, vcardPropToDirRecordAttrMap, constantProperties=constantProperties );
+ filterPropertyNames, dsFilter = dsFilterFromAddressBookFilter(addressBookFilter, vcardPropToDirRecordAttrMap, constantProperties=constantProperties);
self.log_debug("doAddressBookQuery: rdn=%s, query=%s, propertyNames=%s" % (recordType, dsFilter if isinstance(dsFilter, bool) else dsFilter.generate(), filterPropertyNames))
if dsFilter:
-
+
@inlineCallbacks
def recordsForDSFilter(dsFilter, recordType):
-
+
"""
Athough recordsForDSFilter() exercises the dsFilter expression tree and recordsMatchingFields(),
it make little difference to the result of a addressbook query because of filtering.
@@ -182,13 +182,13 @@
if not isinstance(dsFilter, dsquery.expression):
#change match list into an expression and recurse
- returnValue((yield recordsForDSFilter(dsquery.expression( dsquery.expression.OR, (dsFilter,)), recordType)))
+ returnValue((yield recordsForDSFilter(dsquery.expression(dsquery.expression.OR, (dsFilter,)), recordType)))
else:
#self.log_debug("recordsForDSFilter: dsFilter=%s" % (dsFilter.generate(), ))
dsFilterSubexpressions = dsFilter.subexpressions if isinstance(dsFilter.subexpressions, list) else (dsFilter.subexpressions,)
#self.log_debug("recordsForDSFilter: #subs %s" % (len(dsFilterSubexpressions), ))
-
+
# evaluate matches
matches = [match for match in dsFilterSubexpressions if isinstance(match, dsquery.match)]
fields = []
@@ -200,12 +200,12 @@
dsattributes.eDSContains : "contains",
}.get(match.matchType)
if not xmlMatchType:
- self.log_debug("recordsForDSFilter: match type=%s match not supported" % (match.generate(), ))
- returnValue(None) # match type not supported by recordsMatchingFields()
-
+ self.log_debug("recordsForDSFilter: match type=%s match not supported" % (match.generate(),))
+ returnValue(None) # match type not supported by recordsMatchingFields()
+
fields += ((match.attribute, match.value, True, xmlMatchType,),)
#self.log_debug("recordsForDSFilter: fields=%s" % (fields,))
-
+
# if there were matches, call get records that match
result = None
if len(fields):
@@ -217,10 +217,10 @@
if self.implementNot:
result = (yield self.listRecords(recordType)).difference(result)
else:
- self.log_debug("recordsForDSFilter: NOT expression not supported" % (match.generate(), ))
+ self.log_debug("recordsForDSFilter: NOT expression not supported" % (match.generate(),))
returnValue(None)
-
+
# evaluate subexpressions
subexpressions = [subexpression for subexpression in dsFilterSubexpressions if isinstance(subexpression, dsquery.expression)]
for subexpression in subexpressions:
@@ -229,12 +229,12 @@
#self.log_debug("recordsForDSFilter: subresult=%s" % (subresult,))
if subresult is None:
returnValue(None)
-
+
if dsFilter.operator == dsquery.expression.NOT:
if self.implementNot:
result = (yield self.listRecords(recordType)).difference(subresult)
else:
- self.log_debug("recordsForDSFilter: NOT expression not supported" % (match.generate(), ))
+ self.log_debug("recordsForDSFilter: NOT expression not supported" % (match.generate(),))
returnValue(None)
elif result is None:
result = subresult
@@ -245,9 +245,9 @@
#self.log_debug("recordsForDSFilter: dsFilter=%s returning %s" % (dsFilter.generate(), result, ))
returnValue(result)
-
+
# calculate minimum attributes needed for this query: results unused
- etagRequested, queryPropNames = propertiesInAddressBookQuery( addressBookQuery )
+ etagRequested, queryPropNames = propertiesInAddressBookQuery(addressBookQuery)
self.log_debug("doAddressBookQuery: etagRequested=%s, queryPropNames=%s" % (etagRequested, queryPropNames,))
# walk the expression tree
@@ -255,16 +255,16 @@
xmlDirectoryRecords = None
else:
xmlDirectoryRecords = (yield recordsForDSFilter(dsFilter, recordType))
- self.log_debug("doAddressBookQuery: #xmlDirectoryRecords %s" % (len(xmlDirectoryRecords) if xmlDirectoryRecords is not None else xmlDirectoryRecords, ))
-
+ self.log_debug("doAddressBookQuery: #xmlDirectoryRecords %s" % (len(xmlDirectoryRecords) if xmlDirectoryRecords is not None else xmlDirectoryRecords,))
+
if xmlDirectoryRecords is None:
xmlDirectoryRecords = (yield self.listRecords(recordType))
- self.log_debug("doAddressBookQuery: all #xmlDirectoryRecords %s" % (len(xmlDirectoryRecords), ))
-
-
+ self.log_debug("doAddressBookQuery: all #xmlDirectoryRecords %s" % (len(xmlDirectoryRecords),))
+
+
for xmlDirectoryRecord in xmlDirectoryRecords:
-
- def dsRecordAttributesFromDirectoryRecord( xmlDirectoryRecord ):
+
+ def dsRecordAttributesFromDirectoryRecord(xmlDirectoryRecord):
#FIXME should filter based on request
dsRecordAttributes = {}
for attr in dirRecordAttrToDSAttrMap:
@@ -281,7 +281,7 @@
return dsRecordAttributes
result = None
- dsRecordAttributes = dsRecordAttributesFromDirectoryRecord( xmlDirectoryRecord )
+ dsRecordAttributes = dsRecordAttributesFromDirectoryRecord(xmlDirectoryRecord)
try:
result = ABDirectoryQueryResult(self.directoryBackedAddressBook, dsRecordAttributes, kind=kind)
except:
@@ -294,15 +294,15 @@
else:
# should also filter for duplicate UIDs
self.log_debug("doAddressBookQuery did not match filter: %s (%s)" % (result.vCard().propertyValue("FN"), result.vCard().propertyValue("UID"),))
-
+
if len(results) >= maxResults:
limited = True
break
-
+
#sort results so that CalDAVTester can have consistent results when it uses limits
if self.sortResults:
results = sorted(list(results), key=lambda result:result.vCard().propertyValue("UID"))
- self.log_info("limited %s len(results) %s" % (limited,len(results),))
- returnValue((results, limited,))
+ self.log_info("limited %s len(results) %s" % (limited, len(results),))
+ returnValue((results, limited,))
Modified: CalendarServer/branches/users/gaya/directorybacker/twistedcaldav/query/addressbookqueryfilter.py
===================================================================
--- CalendarServer/branches/users/gaya/directorybacker/twistedcaldav/query/addressbookqueryfilter.py 2013-04-22 18:46:28 UTC (rev 11083)
+++ CalendarServer/branches/users/gaya/directorybacker/twistedcaldav/query/addressbookqueryfilter.py 2013-04-22 21:25:50 UTC (rev 11084)
@@ -55,7 +55,7 @@
filter_test = xml_element.attributes.get("test", "anyof")
if filter_test not in ("anyof", "allof"):
raise ValueError("Test must be only one of anyof, allof")
-
+
self.filter_test = filter_test
self.children = [PropertyFilter(child) for child in xml_element.children]
@@ -65,7 +65,7 @@
Returns True if the given address property matches this filter, False
otherwise. Empty element means always match.
"""
-
+
if len(self.children) > 0:
allof = self.filter_test == "allof"
for propfilter in self.children:
@@ -82,7 +82,7 @@
@return: True if valid, False otherwise
"""
-
+
# Test each property
for propfilter in self.children:
if not propfilter.valid():
@@ -104,7 +104,7 @@
for child in xml_element.children:
qname = child.qname()
-
+
if qname in (
(carddav_namespace, "is-not-defined"),
):
@@ -129,7 +129,7 @@
if qualifier and isinstance(qualifier, IsNotDefined) and (len(filters) != 0) and propfilter_test == "allof":
raise ValueError("When test is allof, no other tests allowed when CardDAV:is-not-defined is present")
-
+
self.propfilter_test = propfilter_test
self.qualifier = qualifier
self.filters = filters
@@ -143,7 +143,7 @@
Returns True if the given address book item (either a property or parameter value)
matches this filter, False otherwise.
"""
-
+
allof = self.propfilter_test == "allof"
if self.qualifier and allof != self.qualifier.match(item):
return not allof
@@ -176,7 +176,7 @@
@return: True if valid, False otherwise
"""
-
+
# No tests
return True
@@ -261,11 +261,11 @@
def _textCompare(s):
# Currently ignores the collation and does caseless matching
s = s.lower()
-
+
if self.match_type == "equals":
return s == test
elif self.match_type == "contains":
- return s.find(test) != -1
+ return s.find(test) != -1
elif self.match_type == "starts-with":
return s.startswith(test)
elif self.match_type == "ends-with":
@@ -283,5 +283,5 @@
else:
if _textCompare(unicode(value, "utf-8")):
return not self.negate
-
+
return self.negate
Modified: CalendarServer/branches/users/gaya/directorybacker/twistedcaldav/stdconfig.py
===================================================================
--- CalendarServer/branches/users/gaya/directorybacker/twistedcaldav/stdconfig.py 2013-04-22 18:46:28 UTC (rev 11083)
+++ CalendarServer/branches/users/gaya/directorybacker/twistedcaldav/stdconfig.py 2013-04-22 21:25:50 UTC (rev 11084)
@@ -208,7 +208,7 @@
},
}
-
+
directoryAddressBookBackingServiceDefaultParams = {
"twistedcaldav.directory.xmldirectorybacker.XMLDirectoryBackingService": {
"xmlFile": "/etc/carddavd/accounts.xml",
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20130422/a0b136ff/attachment-0001.html>
More information about the calendarserver-changes
mailing list