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
12
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
27 commonRDN = list(my & his)
28 commonRDN.sort()
29 d = self._diffTree_commonChildren([
30 (rdnToChild(rdn, myChildren), rdnToChild(rdn, otherChildren))
31 for rdn in commonRDN
32 ], result)
33
34
35 addedRDN = list(his - my)
36 addedRDN.sort()
37 d2 = self._diffTree_addedChildren([
38 rdnToChild(rdn, otherChildren)
39 for rdn in addedRDN
40 ], result)
41 d.addCallback(lambda _: d2)
42
43
44 deletedRDN = list(my - his)
45 deletedRDN.sort()
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
62
74 d.addCallback(_gotSubtree, result)
75
76 d.addCallback(lambda _: self._diffTree_addedChildren(rest, result))
77 return d
78
91 d.addCallback(_gotSubtree, result)
92
93 d.addCallback(lambda _: self._diffTree_deletedChildren(rest, result))
94 return d
95
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
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
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
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
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
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):
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
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