1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 import copy
21 import types
22 import pprint
23
24 import easyLDAP_defaults
25
26 from easyLDAP_exceptions import *
27 from easyLDAP_utils import *
28
30
31 _caching_object = False
32 _last_ldap_cache_history_size = None
33 ldap_cachetree = None
34 ldap_cache_undo_history = []
35 ldap_cache_redo_history = []
36 ldap_cache_history_size = EASY_LDAP['CacheHistorySize']
37 use_cache_history = True
38
39
41 self.clear_cache_stack = self.clear_cache_history
42 self.resize_cache_stack = self.resize_cache_history
43 self.push = self._push_cache_history
44
45
46 - def __init__(self, config_defaults=EASY_LDAP):
47
48 self._method_aliases()
49 self.ldap_cache_undo_history = []
50 self.ldap_cache_redo_history = []
51
52 self._default_cache_history_size = config_defaults['CacheHistorySize']
53
54
55 if self.ldap_cachetree is None:
56 self._caching_object = True
57
58
59 if not self.use_cache_history:
60 self.ldap_cache_history_size = 1
61
62 self.CONFIG=config_defaults
63
64 - def __deepcopy__(self,memo):
65 """Creates a deepcopy of the easyLDAP cache class, especially of the undo/redo stack."""
66 result = self.__class__()
67 memo[id(self)] = result
68 result.ldap_cache_undo_history = copy.deepcopy(self.ldap_cache_undo_history,memo)
69 return result
70
71
73 """
74 thisClass.clear_cache_stack()
75
76 clears the easyLDAP cache. This method can be used to
77 completely change an existing LDAP object or in order to erase
78 the object entirely from the LDAP directory. Changes will,
79 of course, only be synced to the LDAP directory, when the
80 method thisClass.flush_cache() is called.
81 """
82 self.ldap_cache_undo_history = [ self.ldap_cache_undo_history[0] ]
83 self.ldap_cache_redo_history = []
84
85
86 - def resize_cache_history(self,size=None):
87 """
88 thisClass.resize_cache_stack(mySIZE)
89
90 sets a new size for the easyLDAP undo stack. If the new given
91 stack size mySIZE is less than the former one, the undo stack
92 will be reduced with the next thisClass.push() operation.
93 """
94 if not self.use_cache_history:
95 raise easyLDAP_exceptions.CACHEHISTORY_INACTIVE
96
97 if size is None:
98 if self._last_ldap_cache_history_size:
99 size = self._last_ldap_cache_history_size
100 else:
101 size = self._default_cache_history_size
102
103 if (type(size) is types.IntType) and (size > 0):
104 self._last_ldap_cache_history_size = self.ldap_cache_history_size
105 self.ldap_cache_history_size = size
106
107
108 self.ldap_cache_undo_history = self.ldap_cache_undo_history[:self.ldap_cache_history_size]
109 return True
110
111 else:
112 raise easyLDAP_exceptions.CACHEHISTORY_NATURALNUMBER_EXPECTED
113
114
116 """
117 thisClass._push_cache_history()
118
119 copies the current status of the easyLDAP object cache to the
120 redo/undo stack and increases the stack index by one.
121
122 In normal cases calling thisClass.push() should not be necessary
123 as the stack is administered by the class's internal code.
124
125 However, it can be used.
126 """
127
128 if self._caching_object:
129 self.ldap_cache_undo_history = [ copy.deepcopy(self.ldap_cacheobject) ] + self.ldap_cache_undo_history
130 else:
131 self.ldap_cache_undo_history = [ copy.deepcopy(self.ldap_cachetree) ] + self.ldap_cache_undo_history
132
133 self.ldap_cache_undo_history = self.ldap_cache_undo_history[:self.ldap_cache_history_size]
134
135
137 """
138 thisClass.undo()
139
140 undoes the last modification to the easyLDAP object cache.
141 """
142 if len(self.ldap_cache_undo_history) > 1:
143 if self._caching_object:
144 self.ldap_cache_redo_history = [ copy.deepcopy(self.ldap_cacheobject) ] + self.ldap_cache_redo_history
145 self.ldap_cacheobject = self.ldap_cache_undo_history[1]
146 else:
147 self.ldap_cache_redo_history = [ copy.deepcopy(self.ldap_cachetree) ] + self.ldap_cache_redo_history
148 self.ldap_cachetree = self.ldap_cache_undo_history[1]
149 self.ldap_cache_undo_history = self.ldap_cache_undo_history[1:]
150 return True
151
152 else:
153 raise easyLDAP_exceptions.UNDO_IMPOSSIBLE
154
155
157 """
158 thisClass.redo()
159
160 redoes the former modification to the easyLDAP object cache (if any).
161 """
162 if len(self.ldap_cache_redo_history):
163 self._push_cache_history()
164 if self._caching_object:
165 self.ldap_cacheobject = self.ldap_cache_redo_history[0]
166 else:
167 self.ldap_cachetree = self.ldap_cache_redo_history[0]
168 self.ldap_cache_redo_history = self.ldap_cache_redo_history[1:]
169 return True
170
171 else:
172 raise easyLDAP_exceptions.REDO_IMPOSSIBLE
173
178
179
181
182 self.resize_cache_history(size=1)
183 self.use_cache_history = False
184
185
187
188 self.use_cache_history = True
189
190
192
193 self.use_cache_history = False
194
195
197 """An easyLDAP_cacheobject stores and accesses the python-ldap like
198 LDAP object dictionary.
199 """
200
201 ldap_cacheobject = [ [ '', {}, ], ]
202 ldap_cacheobject_dn = ''
203
204 - def __init__(self, ldap_cacheobject, use_cache_history=True, config_defaults=EASY_LDAP):
217
226
227
230
231
233 cacheobject = self.get_cacheobject()
234 for attr in cacheobject[0][1].keys():
235 if attr in EASY_LDAP['ExcludeFromCharsetEncoding']:
236 cacheobject[0][1][attr] = [ '<binary data, not shown>', ]
237 pprint.pprint(cacheobject[0])
238
239
242
243
246
247
250
251
265
266
282
285
295
297 ldap_cacheobject_data = self._get_cacheobject_data()
298
299 if not ignore_case:
300 if ldap_cacheobject_data.has_key(attrdesc):
301 return ldap_cacheobject_data[attrdesc]
302 else:
303 for key in ldap_cacheobject_data.keys():
304 if attrdesc.lower() == key.lower():
305 return ldap_cacheobject_data[key]
306
307 raise easyLDAP_exceptions.ATTRDESC_NOT_SET
308
316
317
319
320 if type(attrdesc) is not types.StringType:
321 raise easyLDAP_exceptions.ATTRIBUTE_NOT_A_STRING
322
323 values = to_list_of_strings(values)
324
325 ldap_cacheobject_data = self._get_cacheobject_data()
326 ldap_cacheobject_data[attrdesc] = values
327 self._set_cacheobject_data(ldap_cacheobject_data)
328
329
331
332 if type(attrdesc) is not types.StringType:
333 raise easyLDAP_exceptions.ATTRIBUTE_NOT_A_STRING
334
335 ldap_cacheobject_data = self._get_cacheobject_data()
336 del ldap_cacheobject_data[attrdesc]
337
338 self._set_cacheobject_data(ldap_cacheobject_data)
339
340
342
343 if type(attrtype) is not types.StringType:
344 raise easyLDAP_exceptions.ATTRIBUTE_NOT_A_STRING
345
346 ldap_cacheobject_data = self._get_cacheobject_data()
347
348 result = {}
349 for attrdesc in ldap_cacheobject_data.keys():
350 if attrdesc.startswith(attrtype):
351 result[attrdesc] = ldap_cacheobject_data[attrdesc]
352
353 return result
354
355
362
363
365
366 if type(attrtype) is not types.StringType:
367 raise easyLDAP_exceptions.ATTRIBUTE_NOT_A_STRING
368
369 ldap_cacheobject_data = self._get_cacheobject_data()
370
371 for attrdesc in ldap_cacheobject_data.keys():
372 if attrdesc.startswith(attrtype):
373 del ldap_cacheobject_data[attrdesc]
374
375 self._set_cacheobject_data(ldap_cacheobject_data)
376
377
391
392
402
403
414
415
417
418 if type(attrdesc) is not types.StringType:
419 raise easyLDAP_exceptions.ATTRIBUTE_NOT_A_STRING
420
421 values = to_list_of_strings(values)
422
423 ldap_cacheobject_data = self._get_cacheobject_data()
424 for value in values:
425 if ignore_case is False:
426 while value in ldap_cacheobject_data[attrdesc]:
427 ldap_cacheobject_data[attrdesc].remove(value)
428 else:
429 while value.lower() in [ icase_val.lower() for icase_val in ldap_cacheobject_data[attrdesc] ]:
430 ldap_cacheobject_data[attrdesc].remove(value)
431
432 if len(ldap_cacheobject_data[attrdesc]) == 0:
433 del ldap_cacheobject_data[attrdesc]
434
435 self._set_cacheobject_data(ldap_cacheobject_data)
436
437
439 """An easyLDAP_cachetree object stores and accesses the python-ldap like
440 LDAP object dictionary.
441 """
442
443 _raw_ldap_data_on_construction = []
444 _last_linear_ldap_cachetree =[]
445 _last_linear_ldap_cachetree_basedn = ''
446 ldap_server_basedn = ''
447 ldap_cachetree_basedn = None
448
449
453
454
455 - def __init__(self, ldap_cachetree_linear_or_recursive, basedn=None, use_cache_history=True, config_defaults=EASY_LDAP):
488
489
491 return len(self.get_cachetree(linear=True, retrieve_data=False))
492
493
501
502
503 - def __call__(self, linear=False, retrieve_data=False):
504 cachetree = self.get_cachetree(linear=linear, retrieve_data=retrieve_data)
505 pprint.pprint(cachetree)
506
507
521
522
528
530 """
531 """
532
533 if type(cachetree) is types.DictType:
534 return True
535
536 return False
537
538
540
541 _cache_tree = {}
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557 _cachetree_basedn = self._get_ldapserver_basedn()
558 try:
559 _ldap_basedn_object = self._find_object_in_raw_ldap_data(_cachetree_basedn)
560 _cache_tree[_cachetree_basedn] = [ easyLDAP_cacheobject(_ldap_basedn_object, use_cache_history=False), {'_ldap_parent_dn': None} ]
561 except easyLDAP_exceptions.NOT_A_PYTHON_LDAPOBJECT:
562 _cache_tree[_cachetree_basedn] = [ None, {'_ldap_parent_dn': None} ]
563
564 for dn, obj_data in [ ( ldap_cacheextract[0].lower(), ldap_cacheextract[1]) for ldap_cacheextract in pyldap_listofobjects ]:
565
566 rel_dn = self.strip_off_dn_from_dn(_cachetree_basedn, dn)
567 if self.is_childdn_of_cachetree_basedn(dn):
568
569 if not rel_dn: continue
570 rel_dn_nodes = rel_dn.split(',')
571 rel_dn_nodes.reverse()
572
573 _recurse_tree = _cache_tree[_cachetree_basedn][1]
574 _recurse_tree_basedn = _cachetree_basedn
575
576
577 if not _recurse_tree.has_key(rel_dn_nodes[0]):
578 try:
579 _recurse_tree[rel_dn_nodes[0]] = [ easyLDAP_cacheobject(self._find_object_in_raw_ldap_data('%s,%s' % (rel_dn_nodes[0], _recurse_tree_basedn)), use_cache_history=False), {'_ldap_parent_dn': _recurse_tree_basedn} ]
580 except easyLDAP_exceptions.NOT_A_PYTHON_LDAPOBJECT:
581 _recurse_tree[rel_dn_nodes[0]] = [ None, {'_ldap_parent_dn': _recurse_tree_basedn} ]
582
583
584 for i, j in zip(iter(rel_dn_nodes[:-1]), iter(rel_dn_nodes[1:])):
585 if not _recurse_tree[i][1].has_key(j):
586 _ldap_object = '%s,%s,%s' % (j, i, _recurse_tree_basedn)
587 _ldap_object = _ldap_object.lstrip(',').rstrip(',')
588 try:
589 _recurse_tree[i][1][j] = [ easyLDAP_cacheobject(self._find_object_in_raw_ldap_data(_ldap_object), use_cache_history=False), { '_ldap_parent_dn': '%s,%s' % (i, _recurse_tree_basedn)} ]
590 except easyLDAP_exceptions.NOT_A_PYTHON_LDAPOBJECT:
591 _recurse_tree[i][1][j] = [ None, {'_ldap_parent_dn': '%s,%s' % (i, _recurse_tree_basedn)} ]
592
593 _recurse_tree_basedn = '%s,%s' % (i, _recurse_tree_basedn)
594 _recurse_tree = _recurse_tree[i][1]
595
596 else:
597 raise easyLDAP_exceptions.DN_NOT_A_CHILD_OF_BASEDN
598
599 return _cache_tree
600
601
603
604 if not ldap_cachetree_recursive.has_key('_ldap_parent_dn'):
605 self._last_linear_ldap_cachetree = []
606
607 for i in [ key for key in ldap_cachetree_recursive.keys() if key != '_ldap_parent_dn' ]:
608
609 if ldap_cachetree_recursive[i][1]['_ldap_parent_dn']:
610
611 dn = '%s,%s' % (i, ldap_cachetree_recursive[i][1]['_ldap_parent_dn'])
612 else:
613
614 dn = i
615
616 if ldap_cachetree_recursive[i][0] is not None:
617 self._last_linear_ldap_cachetree.append((dn,ldap_cachetree_recursive[i][0]))
618
619 if ldap_cachetree_recursive[i][1].keys():
620 self._get_linear_ldap_cachetree(ldap_cachetree_recursive[i][1], recursive_call=True)
621
622 if not recursive_call:
623 return self._last_linear_ldap_cachetree
624
625
630
631
657
658
662
663
674
675
680
681
683 """
684 """
685 return self.is_childdn_of_dn(child_dn, self._get_ldapserver_basedn())
686
687
694
695
696 - def get_cachetree(self, linear=False, retrieve_data=False, hashed=False):
697 """
698 retrieve_data works only on linear operations
699 """
700 if not linear and not hashed:
701 return self.ldap_cachetree
702 else:
703 linear_res = self._get_linear_ldap_cachetree(self.get_cachetree(linear=False, retrieve_data=retrieve_data))
704 if not hashed:
705 if not retrieve_data:
706
707
708
709 return linear_res
710 else:
711
712
713
714 return [ tuple(obj_tuple[1].get_cacheobject()[0]) for obj_tuple in linear_res if obj_tuple[1] != None ]
715 else:
716
717 this_hash = {}
718 if not retrieve_data:
719
720
721
722 for obj_tuple in linear_res:
723 if obj_tuple:
724 this_hash[obj_tuple[0]] = obj_tuple[1]
725 else:
726
727
728
729 for obj_tuple in linear_res:
730 if obj_tuple:
731 this_hash[obj_tuple[0]] = obj_tuple[1].get_cacheobject()[0][1]
732 return this_hash
733
734
736
737 return self.get_cachetree(linear=True, hashed=True, retrieve_data=retrieve_data)
738
739
741
742 return self.get_cachetree(linear=True, retrieve_data=True)
743
744
750
751
760
761
763 """
764 """
765 dn = dn.lower()
766
767 if dn in self.get_cachetree_dnlist():
768 if deepcopy:
769 tree_pyldap = self.get_cachetree_pyldap()
770 return easyLDAP_cachetree([ obj for obj in tree_pyldap if obj[0].endswith(dn) ], basedn=self.ldap_server_basedn, use_cache_history=self.use_cache_history, config_defaults=self.CONFIG)
771 else:
772 subtree = self.ldap_cachetree
773
774 if dn.lower() == self.ldap_cachetree_basedn:
775 return easyLDAP_cachetree(subtree, basedn=self.ldap_server_basedn, use_cache_history=self.use_cache_history, config_defaults=self.CONFIG)
776
777 rev_rdns = split_dn(dn, basedn=self.ldap_cachetree_basedn)
778 rev_rdns.reverse()
779 last_rdn = rev_rdns[0]
780
781 final_tree = { }
782 temp_tree = final_tree
783 for rdn in rev_rdns[1:]:
784 subtree = { rdn: subtree[last_rdn][1][rdn], }
785 temp_tree[last_rdn] = [ None, {'_ldap_parent_dn': last_rdn, rdn: [], } ]
786
787 temp_tree = temp_tree[last_rdn][1]
788 for k in temp_tree.keys():
789 if k != rdn and k != '_ldap_parent_dn':
790 del temp_tree[k]
791
792 last_rdn = rdn
793
794 temp_tree[rdn].append(subtree[rdn][0])
795 temp_tree[rdn].append(subtree[rdn][1])
796
797 return easyLDAP_cachetree(final_tree, basedn=self.ldap_server_basedn, use_cache_history=self.use_cache_history, config_defaults=self.CONFIG)
798 else:
799 raise easyLDAP_exceptions.NO_SUCH_DN_IN_CACHE
800
801
812
813
818
819
823
824
826
827 dn_split = split_dn(dn, basedn=self.ldap_server_basedn)
828 dn_split.reverse()
829 subtree = self.ldap_cachetree[dn_split[0]][1]
830 if len(subtree.keys()) > 1:
831 if len(dn_split) > 1:
832 for rdn in dn_split[1:]:
833 subtree = subtree[rdn][1]
834 if len(subtree.keys()) > 1:
835 return True
836 else:
837 return True
838
839 return False
840
841
843 """
844 get_cacheobject_from_cachetree('DN')
845
846 returns the data of a single cache object from the
847 cached cachetree.
848 """
849 for obj in self.get_cachetree(linear=True, retrieve_data=False):
850 if obj[0] == object_dn.lower():
851 return obj[1]
852 else:
853 raise easyLDAP_exceptions.NO_SUCH_OBJECT_IN_CACHETREE
854
855
856
857
870
871
876
877
903
904
908
909
913
914 if __name__=='__main__':
915 pass
916