Package ldaptor :: Module entryhelpers
[hide private]
[frames] | no frames]

Source Code for Module ldaptor.entryhelpers

  1  from twisted.internet import defer 
  2  from ldaptor import delta, ldapfilter 
  3  from ldaptor.protocols import pureldap 
  4  from ldaptor.protocols.ldap import ldapsyntax, ldaperrors 
  5   
6 -class DiffTreeMixin(object):
7 - def _diffTree_gotMyChildren(self, myChildren, other, result):
8 d = other.children() 9 d.addCallback(self._diffTree_gotBothChildren, myChildren, other, result) 10 return d
11
12 - def _diffTree_gotBothChildren(self, 13 otherChildren, 14 myChildren, 15 other, 16 result):
17 def rdnToChild(rdn, l): 18 r = [x for x in l if x.dn.split()[0] == rdn] 19 assert len(r) == 1 20 return r[0]
21 22 my = set([x.dn.split()[0] for x in myChildren]) 23 his = set([x.dn.split()[0] for x in otherChildren]) 24 25 # differences in common children 26 commonRDN = list(my & his) 27 commonRDN.sort() # for reproducability only 28 d = self._diffTree_commonChildren([ 29 (rdnToChild(rdn, myChildren), rdnToChild(rdn, otherChildren)) 30 for rdn in commonRDN 31 ], result) 32 33 # added children 34 addedRDN = list(his - my) 35 addedRDN.sort() # for reproducability only 36 d2 = self._diffTree_addedChildren([ 37 rdnToChild(rdn, otherChildren) 38 for rdn in addedRDN 39 ], result) 40 d.addCallback(lambda _: d2) 41 42 # deleted children 43 deletedRDN = list(my - his) 44 deletedRDN.sort() # for reproducability only 45 d3 = self._diffTree_deletedChildren([ 46 rdnToChild(rdn, myChildren) 47 for rdn in deletedRDN 48 ], result) 49 d.addCallback(lambda _: d3) 50 51 return d
52
53 - def _diffTree_commonChildren(self, children, result):
54 if not children: 55 return defer.succeed(result) 56 first, rest = children[0], children[1:] 57 a, b = first 58 d = a.diffTree(b, result) 59 d.addCallback(lambda _: self._diffTree_commonChildren(rest, result)) 60 return d
61
62 - def _diffTree_addedChildren(self, children, result):
63 if not children: 64 return result 65 first, rest = children[0], children[1:] 66 67 d = first.subtree() 68 def _gotSubtree(l, result): 69 for c in l: 70 o = delta.AddOp(c) 71 result.append(o) 72 return result
73 d.addCallback(_gotSubtree, result) 74 75 d.addCallback(lambda _: self._diffTree_addedChildren(rest, result)) 76 return d 77
78 - def _diffTree_deletedChildren(self, children, result):
79 if not children: 80 return result 81 first, rest = children[0], children[1:] 82 83 d = first.subtree() 84 def _gotSubtree(l, result): 85 l.reverse() # remove children before their parent 86 for c in l: 87 o = delta.DeleteOp(c) 88 result.append(o) 89 return result
90 d.addCallback(_gotSubtree, result) 91 92 d.addCallback(lambda _: self._diffTree_deletedChildren(rest, result)) 93 return d 94
95 - def diffTree(self, other, result=None):
96 assert self.dn == other.dn, \ 97 ("diffTree arguments must refer to same LDAP tree:" 98 "%r != %r" % (str(self.dn), str(other.dn)) 99 ) 100 if result is None: 101 result = [] 102 103 # differences in root 104 rootDiff = self.diff(other) 105 if rootDiff is not None: 106 result.append(rootDiff) 107 108 d = self.children() 109 d.addCallback(self._diffTree_gotMyChildren, other, result) 110 111 return d
112
113 -class SubtreeFromChildrenMixin(object):
114 - def subtree(self, callback=None):
115 if callback is None: 116 result = [] 117 d = self.subtree(callback=result.append) 118 d.addCallback(lambda _: result) 119 return d 120 else: 121 callback(self) 122 d = self.children() 123 def _processOneChild(_, children, callback): 124 if not children: 125 return None 126 127 c = children.pop() 128 d = c.subtree(callback) 129 d.addCallback(_processOneChild, children, callback)
130 def _gotChildren(children, callback): 131 _processOneChild(None, children, callback)
132 d.addCallback(_gotChildren, callback) 133 return d 134
135 -class MatchMixin(object):
136 - def match(self, filter):
137 if isinstance(filter, pureldap.LDAPFilter_present): 138 return filter.value in self 139 elif isinstance(filter, pureldap.LDAPFilter_equalityMatch): 140 # TODO case insensitivity depends on different attribute syntaxes 141 if (filter.assertionValue.value.lower() in 142 [val.lower() 143 for val in self.get(filter.attributeDesc.value, [])]): 144 return True 145 return False 146 elif isinstance(filter, pureldap.LDAPFilter_substrings): 147 if filter.type not in self: 148 return False 149 possibleMatches = self[filter.type] 150 substrings = filter.substrings[:] 151 152 if (substrings 153 and isinstance(filter.substrings[0], 154 pureldap.LDAPFilter_substrings_initial)): 155 possibleMatches = [ 156 x[len(filter.substrings[0].value):] 157 for x in possibleMatches 158 if x.lower().startswith(filter.substrings[0].value.lower()) 159 ] 160 del substrings[0] 161 162 if (substrings 163 and isinstance(filter.substrings[-1], 164 pureldap.LDAPFilter_substrings_final)): 165 possibleMatches = [ 166 x[:-len(filter.substrings[0].value)] 167 for x in possibleMatches 168 if x.lower().endswith(filter.substrings[-1].value.lower()) 169 ] 170 del substrings[-1] 171 172 while possibleMatches and substrings: 173 assert isinstance(substrings[0], pureldap.LDAPFilter_substrings_any) 174 r = [] 175 for possible in possibleMatches: 176 i = possible.lower().find(substrings[0].value.lower()) 177 if i >= 0: 178 r.append(possible[i:]) 179 possibleMatches = r 180 del substrings[0] 181 if possibleMatches and not substrings: 182 return True 183 return False 184 elif isinstance(filter, pureldap.LDAPFilter_greaterOrEqual): 185 if filter.attributeDesc not in self: 186 return False 187 for value in self[filter.attributeDesc]: 188 if value >= filter.assertionValue: 189 return True 190 return False 191 elif isinstance(filter, pureldap.LDAPFilter_lessOrEqual): 192 if filter.attributeDesc not in self: 193 return False 194 for value in self[filter.attributeDesc]: 195 if value <= filter.assertionValue: 196 return True 197 return False 198 elif isinstance(filter, pureldap.LDAPFilter_and): 199 for filt in filter: 200 if not self.match(filt): 201 return False 202 return True 203 elif isinstance(filter, pureldap.LDAPFilter_or): 204 for filt in filter: 205 if self.match(filt): 206 return True 207 return False 208 elif isinstance(filter, pureldap.LDAPFilter_not): 209 return not self.match(filter.value) 210 else: 211 raise ldapsyntax.MatchNotImplemented, filter
212
213 -class SearchByTreeWalkingMixin(object):
214 - def search(self, 215 filterText=None, 216 filterObject=None, 217 attributes=(), 218 scope=None, 219 derefAliases=None, 220 sizeLimit=0, 221 timeLimit=0, 222 typesOnly=0, 223 callback=None):
224 if filterObject is None and filterText is None: 225 filterObject=pureldap.LDAPFilterMatchAll 226 elif filterObject is None and filterText is not None: 227 filterObject=ldapfilter.parseFilter(filterText) 228 elif filterObject is not None and filterText is None: 229 pass 230 elif filterObject is not None and filterText is not None: 231 f=ldapfilter.parseFilter(filterText) 232 filterObject=pureldap.LDAPFilter_and((f, filterObject)) 233 234 if scope is None: 235 scope = pureldap.LDAP_SCOPE_wholeSubtree 236 if derefAliases is None: 237 derefAliases = pureldap.LDAP_DEREF_neverDerefAliases 238 239 # choose iterator: base/children/subtree 240 if scope == pureldap.LDAP_SCOPE_wholeSubtree: 241 iterator = self.subtree 242 elif scope == pureldap.LDAP_SCOPE_singleLevel: 243 iterator = self.children 244 elif scope == pureldap.LDAP_SCOPE_baseObject: 245 def iterateSelf(callback): 246 callback(self) 247 return defer.succeed(None)
248 iterator = iterateSelf 249 else: 250 raise ldaperrors.LDAPProtocolError, \ 251 'unknown search scope: %r' % scope 252 253 results = [] 254 if callback is None: 255 matchCallback = results.append 256 else: 257 matchCallback = callback 258 259 # gather results, send them 260 def _tryMatch(entry): 261 if entry.match(filterObject): 262 matchCallback(entry)
263 264 d = iterator(callback=_tryMatch) 265 266 if callback is None: 267 return defer.succeed(results) 268 else: 269 return defer.succeed(None) 270