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

Source Code for Module ldaptor.entryhelpers

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