[CalendarServer-changes] [9169] CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav /directory
source_changes at macosforge.org
source_changes at macosforge.org
Mon Apr 23 09:30:07 PDT 2012
Revision: 9169
http://trac.macosforge.org/projects/calendarserver/changeset/9169
Author: gaya at apple.com
Date: 2012-04-23 09:30:05 -0700 (Mon, 23 Apr 2012)
Log Message:
-----------
fix dsFilterFromAddressBookFilter() so that KIND filters work.
Modified Paths:
--------------
CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/ldapdirectorybacker.py
CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/opendirectorybacker.py
CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/xmldirectorybacker.py
Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/ldapdirectorybacker.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/ldapdirectorybacker.py 2012-04-23 16:15:59 UTC (rev 9168)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/ldapdirectorybacker.py 2012-04-23 16:30:05 UTC (rev 9169)
@@ -150,6 +150,7 @@
else:
queryAttributes = []
for prop in propertyNames:
+ #FIXME wrong mapping: Need vCard property to DS Attribute map
searchAttr = ldapAttrToDSAttrMap.get()
if searchAttr:
print("adding attributes %r" % searchAttr)
@@ -300,17 +301,13 @@
constantProperties["KIND"] = kind
- allRecords, filterAttributes, dsFilter = dsFilterFromAddressBookFilter( addressBookFilter, vcardPropToLdapAttrMap, constantProperties=constantProperties );
- self.log_debug("doAddressBookQuery: rdn=%s LDAP allRecords=%s, filterAttributes=%s, query=%s" % (rdn, allRecords, filterAttributes, "None" if dsFilter is None else dsFilter.generate(),))
-
-
- if allRecords:
- dsFilter = None # None expression == all Records
+ filterAttributes, dsFilter = dsFilterFromAddressBookFilter( addressBookFilter, vcardPropToLdapAttrMap, constantProperties=constantProperties );
+ self.log_debug("doAddressBookQuery: rdn=%s query = %s" % (rdn, dsFilter if isinstance(dsFilter, bool) else dsFilter.generate(),))
+
+ if dsFilter:
+ if dsFilter is True:
+ dsFilter = None
- # stop query all
- clear = not allRecords and not dsFilter
-
- if not clear:
queryAttributes = self._ldapAttributesForAddressBookQuery( addressBookQuery, ldapAttrToDSAttrMap )
attributes = filterAttributes + queryAttributes if queryAttributes else None
self.log_debug("doAddressBookQuery: attributes=%s, queryAttributes=%s" % (attributes, queryAttributes,))
Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/opendirectorybacker.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/opendirectorybacker.py 2012-04-23 16:15:59 UTC (rev 9168)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/opendirectorybacker.py 2012-04-23 16:30:05 UTC (rev 9169)
@@ -492,28 +492,26 @@
Get vCards for a given addressBookFilter and addressBookQuery
"""
+ constantProperties = ABDirectoryQueryResult.constantProperties.copy()
+
# TODO: optimization: call dsFilterFromAddressBookFilter with
# KIND as constant so that record type or query can be skipped if addressBookFilter needs a different kind
# Then combine like filters to do the query with an allowed type list
+ # constantProperties["KIND"] = "group"
- allRecords, filterAttributes, dsFilter = dsFilterFromAddressBookFilter( addressBookFilter,
+ filterAttributes, dsFilter = dsFilterFromAddressBookFilter( addressBookFilter,
self.vcardPropToSearchableDSAttrMap,
ABDirectoryQueryResult.vcardPropToDSAttrMap,
- constantProperties=ABDirectoryQueryResult.constantProperties );
- self.log_debug("allRecords = %s, query = %s" % (allRecords, "None" if dsFilter is None else dsFilter.generate(),))
-
- # testing:
- # allRecords = True
+ constantProperties=constantProperties );
+ self.log_debug("query = %s" % (dsFilter if isinstance(dsFilter, bool) else dsFilter.generate(),))
- if allRecords:
- dsFilter = None # None expression == all Records
- clear = not allRecords and not dsFilter
-
results = []
limited = False
-
- if not clear:
+ if dsFilter:
+ if dsFilter is True:
+ dsFilter = None # None means get all records hereafter
+
# change query to ignore system records rather than post filtering
# but this appears to be broken in open directory
'''
@@ -609,24 +607,58 @@
@param vcardPropToSearchableAttrMap: a mapping from vcard properties to searchable query attributes.
@param vcardPropToAttrMap: a mapping from vcard properties to all query attributes. Need for correct expressionAttributes below
@param constantProperties: a mapping of constant properties. A query on a constant property will return all or None
- @return: (needsAllRecords, expressionAttributes, expression) tuple
+ @return: (expressionAttributes, expression) tuple. expression==True means list all results, expression==False means no results
"""
- #TODO: get rid of needsAllRecords: instead should be: expression==None means list all results, expression==False means no results
- #
def propFilterListQuery(filterAllOf, propFilters):
+ def combineExpressionLists(expressionList, allOf, addedExpressions):
+ """
+ deal with the 4-state logic
+ addedExpressions=None means ignore
+ addedExpressions=True means all records
+ addedExpressions=False means no records
+ addedExpressions=[expressionlist] add to expression list
+ """
+ #def explen(exp): return len(exp) if isinstance(exp, list) else 0
+ # log.debug("propFilterListQuery(): allOf=%s, expressionList=%s (%s), addedExpressions=%s (%s)" % (allOf, expressionList, explen(expressionList), addedExpressions, explen(addedExpressions)))
+ if expressionList is None:
+ expressionList = addedExpressions
+ elif addedExpressions is not None:
+ if addedExpressions is True:
+ if not allOf:
+ 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
+ #else expressionList or False is expressionList
+ else:
+ if expressionList is False:
+ if not allOf:
+ 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
+ #else False and addedExpressions is False
+ else:
+ expressionList += addedExpressions
+ #log.debug("propFilterListQuery(): out expressionList=%s (%s)" % (expressionList, explen(expressionList)))
+ return expressionList
+
+
def propFilterExpression(filterAllOf, propFilter):
#print("propFilterExpression")
"""
Create an expression for a single prop-filter element.
@param propFilter: the L{PropertyFilter} element.
- @return: (needsAllRecords, expressionAttributes, expressions) tuple
+ @return: (expressionAttributes, expressions) tuple
"""
def definedExpression( defined, allOf ):
if constant or propFilter.filter_name in ("N" , "FN", "UID", "SOURCE",):
- return (defined, propFilterAttrNames, []) # all records have this property so no records do not have it
+ return (propFilterAttrNames, 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:
@@ -636,7 +668,7 @@
expr = dsquery.expression( dsquery.expression.OR, matchList )
else:
expr = matchList[0]
- return (False, propFilterAttrNames, [dsquery.expression( dsquery.expression.NOT, expr),])
+ return (propFilterAttrNames, [dsquery.expression( dsquery.expression.NOT, expr),])
#end definedExpression()
@@ -644,9 +676,9 @@
#print("andOrExpression(propFilterAllOf=%r, propFilterAttrNames%r, matchList%r)" % (propFilterAllOf, propFilterAttrNames, matchList))
if propFilterAllOf and len(matchList) > 1:
# add OR expression because parent will AND
- return (False, propFilterAttrNames, [dsquery.expression( dsquery.expression.OR, matchList),])
+ return (propFilterAttrNames, [dsquery.expression( dsquery.expression.OR, matchList),])
else:
- return (False, propFilterAttrNames, matchList)
+ return (propFilterAttrNames, matchList)
#end andOrExpression()
@@ -742,9 +774,8 @@
# end getMatchStrings
if constant:
- # do the match right now! Return either all or none.
#FIXME: match is not implemented in twisteddaldav.query.addressbookqueryfilter.TextMatch so use _match for now
- return( textMatchElement._match([constant,]), propFilterAttrNames, [] )
+ return( propFilterAttrNames, textMatchElement._match([constant,]) )
else:
matchStrings = getMatchStrings(propFilter, textMatchElement.text)
@@ -770,11 +801,11 @@
log.debug("Could not decode UID string %r in %r: %r" % (matchString[recordNameStart:], matchString, e,))
else:
if textMatchElement.negate:
- return (False, propFilterAttrNames,
+ return (propFilterAttrNames,
[dsquery.expression(dsquery.expression.NOT, dsquery.match(dsattributes.kDSNAttrRecordName, recordNameQualifier, dsattributes.eDSExact)),]
)
else:
- return (False, propFilterAttrNames,
+ return (propFilterAttrNames,
[dsquery.match(dsattributes.kDSNAttrRecordName, recordNameQualifier, dsattributes.eDSExact),]
)
@@ -800,7 +831,7 @@
expr = dsquery.expression( dsquery.expression.OR, matchList )
else:
expr = matchList[0]
- return (False, propFilterAttrNames, [dsquery.expression( dsquery.expression.NOT, expr),])
+ return (propFilterAttrNames, [dsquery.expression( dsquery.expression.NOT, expr),])
else:
return andOrExpression(propFilterAllOf, matchList)
@@ -831,7 +862,7 @@
if not searchablePropFilterAttrNames and not constant:
# not allAttrNames means propFilter.filter_name is not mapped
# return None to try to match all items if this is the only property filter
- return (None, propFilterAttrNames, [])
+ return (propFilterAttrNames, None)
if propFilter.qualifier and isinstance(propFilter.qualifier, addressbookqueryfilter.IsNotDefined):
return definedExpression(False, filterAllOf)
@@ -852,27 +883,22 @@
return definedExpression(True, filterAllOf)
else:
if propFilterAllOf:
- return (False, propFilterAttrNames, [])
+ return (propFilterAttrNames, False)
# handle text match elements
- propFilterNeedsAllRecords = propFilterAllOf
- propFilterExpressionList = []
+ propFilterExpressions = None
for textMatchElement in textMatchElements:
- textMatchNeedsAllRecords, textMatchExpressionAttributes, textMatchExpression = textMatchElementExpression(propFilterAllOf, textMatchElement)
- if propFilterAllOf:
- propFilterNeedsAllRecords &= textMatchNeedsAllRecords
- else:
- propFilterNeedsAllRecords |= textMatchNeedsAllRecords
- propFilterExpressionList += textMatchExpression
-
-
- if (len(propFilterExpressionList) > 1) and (filterAllOf != propFilterAllOf):
- propFilterExpressions = [dsquery.expression(dsquery.expression.AND if propFilterAllOf else dsquery.expression.OR , list(set(propFilterExpressionList)))] # remove duplicates
- else:
- propFilterExpressions = list(set(propFilterExpressionList))
+ textMatchExpressionAttributes, textMatchExpressions = textMatchElementExpression(propFilterAllOf, textMatchElement)
+ #ignore textMatchExpressionAttributes
+ propFilterExpressions = combineExpressionLists(propFilterExpressions, propFilterAllOf, textMatchExpressions)
+
+ if isinstance(propFilterExpressions, list):
+ propFilterExpressions= list(set(propFilterExpressions))
+ if (len(propFilterExpressions) > 1) and (filterAllOf != propFilterAllOf):
+ propFilterExpressions = [dsquery.expression(dsquery.expression.AND if propFilterAllOf else dsquery.expression.OR , propFilterExpressions)]
- return (propFilterNeedsAllRecords, propFilterAttrNames, propFilterExpressions)
+ return (propFilterAttrNames, propFilterExpressions)
#end propFilterExpression
#print("propFilterListQuery: filterAllOf=%r, propFilters=%r" % (filterAllOf, propFilters,))
@@ -881,37 +907,32 @@
@param filterAllOf: the C{True} if parent filter test is "allof"
@param propFilters: the C{list} of L{ComponentFilter} elements.
- @return: (needsAllRecords, expressionAttributes, expression) tuple
+ @return: (expressionAttributes, expression) tuple
"""
- needsAllRecords = None
attributes = []
- expressions = []
+ expressions = None
for propFilter in propFilters:
- propNeedsAllRecords, propExpressionAttributes, propExpression = propFilterExpression(filterAllOf, propFilter)
- if needsAllRecords is None:
- needsAllRecords = propNeedsAllRecords
- elif propNeedsAllRecords is not None:
- if filterAllOf:
- needsAllRecords &= propNeedsAllRecords
- else:
- needsAllRecords |= propNeedsAllRecords
+ propExpressionAttributes, propExpressions = propFilterExpression(filterAllOf, propFilter)
attributes += propExpressionAttributes
- expressions += propExpression
- # propFilterExpression()'s returned propNeedsAllRecords is only None if a propFilter.filter_name is not not mapped
- # needsAllRecords is None if there was only one propFilter that returned None
- # set needsAllRecords True in the case
- if needsAllRecords is None:
- needsAllRecords = not filterAllOf
+ expressions = combineExpressionLists(expressions, filterAllOf, propExpressions)
+
+ # convert to needsAllRecords to return
+ if isinstance(expressions, list):
+ expressions = list(set(expressions))
+ if len(expressions) > 1:
+ expr = dsquery.expression(dsquery.expression.AND if filterAllOf else dsquery.expression.OR , expressions)
+ elif len(expressions):
+ expr = expressions[0]
+ else:
+ expr = not filterAllOf # empty expression list. should not happen
+ elif expressions is None:
+ expr = expr = not filterAllOf
+ else:
+ # True or False
+ expr = expressions
- if len(expressions) > 1:
- expr = dsquery.expression(dsquery.expression.AND if filterAllOf else dsquery.expression.OR , list(set(expressions))) # remove duplicates
- elif len(expressions):
- expr = expressions[0]
- else:
- expr = None
-
- return (needsAllRecords, list(set(attributes)), expr)
+ return (list(set(attributes)), expr)
#print("dsFilterFromAddressBookFilter")
@@ -920,12 +941,12 @@
# Top-level filter contains zero or more prop-filters
if addressBookFilter:
filterAllOf = addressBookFilter.filter_test == "allof"
- if len(addressBookFilter.children) > 0:
+ if len(addressBookFilter.children):
return propFilterListQuery(filterAllOf, addressBookFilter.children)
else:
- return (filterAllOf, [], [])
+ return ([], not filterAllOf)
else:
- return (False, [], [])
+ return ([], False)
@@ -1103,6 +1124,7 @@
guid = self.firstValueForAttribute(dsattributes.kDS1AttrGeneratedUID)
if not guid:
nameUUIDStr = "".join(self.firstValueForAttribute(dsattributes.kDSNAttrRecordName).encode("base64").split("\n"))
+ #guid = ABDirectoryQueryResult.uidSeparator.join(["00000000", nameUUIDStr,])
guid = ABDirectoryQueryResult.uidSeparator.join(["d9a8e41b", nameUUIDStr,])
self.attributes[dsattributes.kDS1AttrGeneratedUID] = guid
Modified: CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/xmldirectorybacker.py
===================================================================
--- CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/xmldirectorybacker.py 2012-04-23 16:15:59 UTC (rev 9168)
+++ CalendarServer/branches/users/gaya/ldapdirectorybacker/twistedcaldav/directory/xmldirectorybacker.py 2012-04-23 16:30:05 UTC (rev 9169)
@@ -167,18 +167,11 @@
constantProperties["KIND"] = kind
# add KIND as constant so that query can be skipped if addressBookFilter needs a different kind
- allRecords, filterAttributes, dsFilter = dsFilterFromAddressBookFilter( addressBookFilter, vcardPropToDirRecordAttrMap, constantProperties=constantProperties );
- self.log_debug("doAddressBookQuery: queryType=\"%s\" LDAP allRecords=%s, filterAttributes=%s, query=%s" % (queryType, allRecords, filterAttributes, "None" if dsFilter is None else dsFilter.generate(),))
-
-
- if allRecords:
- dsFilter = None # None expression == all Records
-
- # stop query for all
- clear = not allRecords and not dsFilter
-
- if not clear:
-
+ filterAttributes, dsFilter = dsFilterFromAddressBookFilter( addressBookFilter, vcardPropToDirRecordAttrMap, constantProperties=constantProperties );
+ self.log_debug("doAddressBookQuery: rdn=%s query = %s" % (queryType, dsFilter if isinstance(dsFilter, bool) else dsFilter.generate(),))
+
+ if dsFilter:
+
@inlineCallbacks
def recordsForDSFilter(dsFilter, recordType):
@@ -254,7 +247,7 @@
returnValue(result)
# walk the expression tree
- if allRecords:
+ if dsFilter is True:
xmlDirectoryRecords = None
else:
xmlDirectoryRecords = (yield recordsForDSFilter(dsFilter, queryType))
@@ -268,6 +261,7 @@
for xmlDirectoryRecord in xmlDirectoryRecords:
def dsRecordAttributesFromDirectoryRecord( xmlDirectoryRecord ):
+ #FIXME should filter based on request
dsRecordAttributes = {}
for attr in dirRecordAttrToDSAttrMap:
try:
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20120423/fb5928c6/attachment-0001.html>
More information about the calendarserver-changes
mailing list