• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt/router/samba-3.5.8/source3/lib/ldb/swig/
1"""Provide a more Pythonic and object-oriented interface to ldb."""
2
3#
4# Swig interface to Samba
5#
6# Copyright (C) Tim Potter 2006
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 3 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, see <http://www.gnu.org/licenses/>.
20#
21
22#
23# Interface notes:
24#
25#   - should an empty dn be represented as None, or an empty string?
26#
27#   - should single-valued attributes be a string, or a list with one
28#     element?
29#
30
31from ldb import *
32
33# Global initialisation
34
35result = ldb_global_init()
36
37if result != 0:
38    raise LdbError, (result, 'ldb_global_init failed')
39
40# Ldb exceptions
41
42class LdbError(Exception):
43    """An exception raised when a ldb error occurs.
44    The exception data is a tuple consisting of the ldb number and a
45    string description of the error."""
46    pass
47
48# Ldb classes
49
50class LdbMessage:
51    """A class representing a ldb message as a Python dictionary."""
52
53    def __init__(self):
54        self.mem_ctx = talloc_init(None)
55        self.msg = ldb_msg_new(self.mem_ctx)
56
57    def __del__(self):
58        if self.mem_ctx is not None:
59            talloc_free(self.mem_ctx)
60            self.mem_ctx = None
61            self.msg = None
62
63    # Make the dn attribute of the object dynamic
64
65    def __getattr__(self, attr):
66        if attr == 'dn':
67            return ldb_dn_linearize(None, self.msg.dn)
68        return self.__dict__[attr]
69
70    def __setattr__(self, attr, value):
71        if attr == 'dn':
72            self.msg.dn = ldb_dn_explode(self.msg, value)
73            if self.msg.dn == None:
74                err = ldb.ERR_INVALID_DN_SYNTAX
75                raise LdbError(err, ldb_strerror(err))
76            return
77        self.__dict__[attr] = value
78
79    # Get and set individual elements
80
81    def __getitem__(self, key):
82
83        elt = ldb_msg_find_element(self.msg, key)
84
85        if elt is None:
86            raise KeyError, "No such attribute '%s'" % key
87
88        return [ldb_val_array_getitem(elt.values, i)
89                for i in range(elt.num_values)]
90
91    def __setitem__(self, key, value):
92        ldb_msg_remove_attr(self.msg, key)
93        if type(value) in (list, tuple):
94            [ldb_msg_add_value(self.msg, key, v) for v in value]
95        else:
96            ldb_msg_add_value(self.msg, key, value)
97
98    # Dictionary interface
99    # TODO: move to iterator based interface
100
101    def len(self):
102        return self.msg.num_elements
103
104    def keys(self):
105        return [ldb_message_element_array_getitem(self.msg.elements, i).name
106                for i in range(self.msg.num_elements)]
107
108    def values(self):
109        return [self[k] for k in self.keys()]
110
111    def items(self):
112        return [(k, self[k]) for k in self.keys()]
113
114    # Misc stuff
115
116    def sanity_check(self):
117        return ldb_msg_sanity_check(self.msg)
118
119class Ldb:
120    """A class representing a binding to a ldb file."""
121
122    def __init__(self, url, flags = 0):
123        """Initialise underlying ldb."""
124
125        self.mem_ctx = talloc_init('mem_ctx for ldb 0x%x' % id(self))
126        self.ldb_ctx = ldb_init(self.mem_ctx)
127
128        result = ldb_connect(self.ldb_ctx, url, flags, None)
129
130        if result != LDB_SUCCESS:
131            raise LdbError, (result, ldb_strerror(result))
132
133    def __del__(self):
134        """Called when the object is to be garbage collected."""
135        self.close()
136
137    def close(self):
138        """Close down a ldb."""
139        if self.mem_ctx is not None:
140            talloc_free(self.mem_ctx)
141            self.mem_ctx = None
142            self.ldb_ctx = None
143
144    def _ldb_call(self, fn, *args):
145        """Call a ldb function with args.  Raise a LdbError exception
146        if the function returns a non-zero return value."""
147
148        result = fn(*args)
149
150        if result != LDB_SUCCESS:
151            raise LdbError, (result, ldb_strerror(result))
152
153    def search(self, expression):
154        """Search a ldb for a given expression."""
155
156        self._ldb_call(ldb_search, self.ldb_ctx, None, LDB_SCOPE_DEFAULT,
157                       expression, None);
158
159        return [LdbMessage(ldb_message_ptr_array_getitem(result.msgs, ndx))
160                for ndx in range(result.count)]
161
162    def delete(self, dn):
163        """Delete a dn."""
164
165        _dn = ldb_dn_explode(self.ldb_ctx, dn)
166
167        self._ldb_call(ldb_delete, self.ldb_ctx, _dn)
168
169    def rename(self, olddn, newdn):
170        """Rename a dn."""
171
172        _olddn = ldb_dn_explode(self.ldb_ctx, olddn)
173        _newdn = ldb_dn_explode(self.ldb_ctx, newdn)
174
175        self._ldb_call(ldb_rename, self.ldb_ctx, _olddn, _newdn)
176
177    def add(self, m):
178        self._ldb_call(ldb_add, self.ldb_ctx, m.msg)
179