12 import os |
12 import os |
13 import re |
13 import re |
14 import stat |
14 import stat |
15 |
15 |
16 from VirtualMailManager import ENCODING |
16 from VirtualMailManager import ENCODING |
17 from VirtualMailManager.constants import NOT_EXECUTABLE, NO_SUCH_BINARY |
17 from VirtualMailManager.constants import NOT_EXECUTABLE, NO_SUCH_BINARY, \ |
|
18 TYPE_ACCOUNT, TYPE_ALIAS, TYPE_RELOCATED |
18 from VirtualMailManager.errors import VMMError |
19 from VirtualMailManager.errors import VMMError |
19 |
|
20 |
20 |
21 VERSION_RE = re.compile(r'^(\d+)\.(\d+)\.(?:(\d+)|(alpha|beta|rc)(\d+))$') |
21 VERSION_RE = re.compile(r'^(\d+)\.(\d+)\.(?:(\d+)|(alpha|beta|rc)(\d+))$') |
22 |
22 |
23 _version_level = dict(alpha=0xA, beta=0xB, rc=0xC) |
23 _version_level = dict(alpha=0xA, beta=0xB, rc=0xC) |
24 _version_cache = {} |
24 _version_cache = {} |
188 |
188 |
189 def format_domain_default(domaindata): |
189 def format_domain_default(domaindata): |
190 """Format info output when the value displayed is the domain default.""" |
190 """Format info output when the value displayed is the domain default.""" |
191 return _(u'%s [domain default]') % domaindata |
191 return _(u'%s [domain default]') % domaindata |
192 |
192 |
|
193 |
|
194 def search_addresses(dbh, typelimit=None, lpattern=None, llike=False, |
|
195 dpattern=None, dlike=False): |
|
196 """'Search' for addresses by *pattern* in the database. |
|
197 |
|
198 The search is limited by *typelimit*, a bitfield with values TYPE_ACCOUNT, |
|
199 TYPE_ALIAS, TYPE_RELOCATED, or a bitwise OR thereof. If no limit is |
|
200 specified, all types will be searched. |
|
201 |
|
202 *lpattern* may be a local part or a partial local part - starting and/or |
|
203 ending with a '%' sign. When the *lpattern* starts or ends with a '%' sign |
|
204 *llike* has to be `True` to perform a wildcard search. To retrieve all |
|
205 available addresses use the arguments' default values. |
|
206 |
|
207 *dpattern* and *dlike* behave analogously for the domain part of an |
|
208 address, allowing for separate pattern matching: testuser%@example.% |
|
209 |
|
210 The return value of this function is a tuple. The first element is a list |
|
211 of domain IDs sorted alphabetically by the corresponding domain names. The |
|
212 second element is a dictionary indexed by domain ID, holding lists to |
|
213 associated addresses. Each address is itself actually a tuple of address, |
|
214 type, and boolean indicating whether the address stems from an alias |
|
215 domain. |
|
216 """ |
|
217 if typelimit == None: |
|
218 typelimit = TYPE_ACCOUNT | TYPE_ALIAS | TYPE_RELOCATED |
|
219 queries = [] |
|
220 if typelimit & TYPE_ACCOUNT: |
|
221 queries.append('SELECT gid, local_part, %d AS type FROM users' |
|
222 % TYPE_ACCOUNT) |
|
223 if typelimit & TYPE_ALIAS: |
|
224 queries.append('SELECT gid, address as local_part, %d AS type ' |
|
225 'FROM alias' % TYPE_ALIAS) |
|
226 if typelimit & TYPE_RELOCATED: |
|
227 queries.append('SELECT gid, address as local_part, %d AS type ' |
|
228 'FROM relocated' % TYPE_RELOCATED) |
|
229 sql = "SELECT gid, local_part || '@' || domainname AS address, " |
|
230 sql += 'type, NOT is_primary AS from_aliasdomain FROM (' |
|
231 sql += ' UNION '.join(queries) |
|
232 sql += ') a JOIN domain_name USING (gid)' |
|
233 nextkw = 'WHERE' |
|
234 sqlargs = [] |
|
235 for like, field, pattern in ((dlike, 'domainname', dpattern), |
|
236 (llike, 'local_part', lpattern)): |
|
237 if like: |
|
238 match = 'LIKE' |
|
239 else: |
|
240 if not pattern: continue |
|
241 match = '=' |
|
242 sql += ' %s %s %s %%s' % (nextkw, field, match) |
|
243 sqlargs.append(pattern) |
|
244 nextkw = 'AND' |
|
245 sql += ' ORDER BY domainname, local_part' |
|
246 dbc = dbh.cursor() |
|
247 dbc.execute(sql, sqlargs) |
|
248 result = dbc.fetchall() |
|
249 dbc.close() |
|
250 |
|
251 gids = [] |
|
252 daddrs = {} |
|
253 lastgid = None |
|
254 for gid, address, addrtype, aliasdomain in result: |
|
255 if gid != lastgid: |
|
256 gids.append(gid) |
|
257 lastgid = gid |
|
258 daddrs[gid] = [] |
|
259 daddrs[gid].append((address, addrtype, aliasdomain)) |
|
260 return gids, daddrs |
|
261 |
193 del _ |
262 del _ |