View | Details | Raw Unified | Return to bug 15687 | Differences between
and this patch

Collapse All | Expand All

(-)debian/changelog (+115 lines)
 Lines 1-3    Link Here 
1
univention-directory-manager-modules (5.1.14-2) unstable; urgency=low
2
3
  * store correct IPv6 PTR records when adding reverse zone in UDM web
4
    (Bug #15687)
5
6
 -- Kai-Wilhelm Bolte <bolte@univention.de>  Thu, 19 Nov 2009 12:27:32 +0100
7
8
univention-directory-manager-modules (5.1.14-1) unstable; urgency=low
9
10
  * make IPv6 DNS Forward and Reverse Zone show in UDM web (Bug #15687)
11
12
 -- Kai-Wilhelm Bolte <bolte@univention.de>  Tue, 17 Nov 2009 17:40:03 +0100
13
14
univention-directory-manager-modules (5.1.13-1) unstable; urgency=low
15
16
  * merged with trunk v5.0.45-1 (Bug #15687)
17
18
 -- Kai-Wilhelm Bolte <bolte@univention.de>  Fri, 13 Nov 2009 13:49:52 +0100
19
20
univention-directory-manager-modules (5.1.12-2) unstable; urgency=low
21
22
  * udm now stores IPv6 addresses as aAAARecord for forward zones in LDAP
23
    (Bug #15687)
24
25
 -- Kai-Wilhelm Bolte <bolte@univention.de>  Fri, 13 Nov 2009 12:27:41 +0100
26
27
univention-directory-manager-modules (5.1.12-1) unstable; urgency=low
28
29
  * merged with trunk (Bug #15687)
30
31
 -- Kai-Wilhelm Bolte <bolte@univention.de>  Wed,  4 Nov 2009 14:04:51 +0100
32
33
univention-directory-manager-modules (5.1.11-1) unstable; urgency=low
34
35
  * make DNS filters IPv6-capable (Bug #15687)
36
37
 -- Kai-Wilhelm Bolte <bolte@univention.de>  Wed,  4 Nov 2009 11:48:49 +0100
38
39
univention-directory-manager-modules (5.1.10-1) unstable; urgency=low
40
41
  * small bugfixes in syntax check (Bug #15555)
42
43
 -- Kai-Wilhelm Bolte <bolte@univention.de>  Tue, 13 Oct 2009 09:39:47 +0200
44
45
univention-directory-manager-modules (5.1.9-1) unstable; urgency=low
46
47
  * use ipaddr module for syntax check (Bug #15555)
48
  * fixed typos
49
50
 -- Kai-Wilhelm Bolte <bolte@univention.de>  Mon, 12 Oct 2009 14:08:31 +0200
51
52
univention-directory-manager-modules (5.1.8-1) unstable; urgency=low
53
54
  * German translations update in syntax (Bug #15555)
55
56
 -- Kai-Wilhelm Bolte <bolte@univention.de>  Fri,  9 Oct 2009 12:22:16 +0200
57
58
univention-directory-manager-modules (5.1.7-1) unstable; urgency=low
59
60
  * IPv6 forward and reverse zones are now correctly stored in ldap (Bug #15687)
61
  * fixes in DNS syntax check and add another IPv6 syntax check
62
  * first version which uses new ipaddr module
63
64
 -- Kai-Wilhelm Bolte <bolte@univention.de>  Thu,  8 Oct 2009 11:51:26 +0200
65
66
univention-directory-manager-modules (5.1.6-1) unstable; urgency=low
67
68
  * add IPv6 to 'ipAdress' syntax check
69
  * bugfixes in IPv6 DNS-handling (Bug #15687)
70
71
 -- Kai-Wilhelm Bolte <bolte@univention.de>  Mon, 28 Sep 2009 14:42:14 +0200
72
73
univention-directory-manager-modules (5.1.5-1) unstable; urgency=low
74
75
  * add IPv6 syntax check for DNS and some comments (Bug #15687)
76
77
 -- Kai-Wilhelm Bolte <bolte@univention.de>  Tue, 22 Sep 2009 09:19:30 +0200
78
79
univention-directory-manager-modules (5.1.4-1) unstable; urgency=low
80
81
  * alias, forward_zone and ptr_record are now IPv6-ready ( Bug #15687)
82
  * bugfixes in reverse_zone and host_record
83
84
 -- Kai-Wilhelm Bolte <bolte@univention.de>  Mon, 21 Sep 2009 14:09:35 +0200
85
86
univention-directory-manager-modules (5.1.3-1) unstable; urgency=low
87
88
  * udm reverse_zone is now IPv6-ready (Bug #15687)
89
  * add syntax-checking for IPv6-subnets
90
  * nicer code in dns/host_record
91
92
 -- Kai-Wilhelm Bolte <bolte@univention.de>  Fri, 18 Sep 2009 13:26:19 +0200
93
94
univention-directory-manager-modules (5.1.2-1) unstable; urgency=low
95
96
  * removed aaaa in UDM (Bug #15687)
97
  * udm dns/host_record create and modify now handles aRecord and aAAARecord 
98
  attributes in ldap depending on IP address version
99
  * udm dns/host_record modify ... --append and --remove checks also IP address 
100
  version, --set replaces all old entries
101
102
 -- Kai-Wilhelm Bolte <bolte@univention.de>  Mon, 14 Sep 2009 15:54:16 +0200
103
104
univention-directory-manager-modules (5.1.1-1) unstable; urgency=low
105
106
  * add possibility to create AAAA records with UDM: --set aaaa="IPv6-address" (Bug #15687)
107
108
 -- Kai-Wilhelm Bolte <bolte@univention.de>  Fri,  4 Sep 2009 17:32:34 +0200
109
110
univention-directory-manager-modules (5.1.0-1) unstable; urgency=low
111
112
  * add possibility to add IPv6 addresses and check syntax for IPv4 / IPv6 in module computers (Bug #15555)
113
114
 -- Kai-Wilhelm Bolte <bolte@univention.de>  Wed,  2 Sep 2009 11:56:53 +0200
115
1
univention-directory-manager-modules (5.0.45-1) unstable; urgency=low
116
univention-directory-manager-modules (5.0.45-1) unstable; urgency=low
2
117
3
  * fix some more policy translation bugs (Bug: #14815)
118
  * fix some more policy translation bugs (Bug: #14815)
(-)modules/univention/admin/handlers/dns/alias.py (-5 / +12 lines)
 Lines 143-154    Link Here 
143
	
143
	
144
def lookup(co, lo, filter_s, base='', superordinate=None, scope="sub", unique=0, required=0, timeout=-1, sizelimit=0):
144
def lookup(co, lo, filter_s, base='', superordinate=None, scope="sub", unique=0, required=0, timeout=-1, sizelimit=0):
145
145
146
	filter=univention.admin.filter.conjunction('&', [
146
	filter=univention.admin.filter.conjunction('|', [
147
		univention.admin.filter.conjunction('&', [
147
		univention.admin.filter.expression('objectClass', 'dNSZone'),
148
		univention.admin.filter.expression('objectClass', 'dNSZone'),
148
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('relativeDomainName', '@')]),
149
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('relativeDomainName', '@')]),
149
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('zoneName', '*.in-addr.arpa')]),
150
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('zoneName', '*.in-addr.arpa')]),
150
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('ARecord', '*')]),
151
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('ARecord', '*')]),
151
		univention.admin.filter.expression('CNAMERecord', '*')
152
		univention.admin.filter.expression('CNAMERecord', '*')]),
153
		univention.admin.filter.conjunction('&', [
154
		univention.admin.filter.expression('objectClass', 'dNSZone'),
155
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('relativeDomainName', '@')]),
156
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('zoneName', '*.ip6.arpa')]), # IPv6
157
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('AAAARecord', '*')]),
158
		univention.admin.filter.expression('CNAMERecord', '*')])
152
		])
159
		])
153
160
154
	if superordinate:
161
	if superordinate:
 Lines 165-176    Link Here 
165
	return res
172
	return res
166
173
167
def identify(dn, attr, canonical=0):
174
def identify(dn, attr, canonical=0):
168
	
175
	# IPv4 + IPv6
169
	return 'dNSZone' in attr.get('objectClass', []) and\
176
	return 'dNSZone' in attr.get('objectClass', []) and\
170
		'@' not in attr.get('relativeDomainName', []) and\
177
		'@' not in attr.get('relativeDomainName', []) and\
171
		not attr['zoneName'][0].endswith('.in-addr.arpa') and\
178
		not attr['zoneName'][0].endswith('.arpa') and\
172
		'*' in attr.get('CNAMERecord', []) and\
179
		'*' in attr.get('CNAMERecord', []) and\
173
		not '*' in attr.get('ARecord', [])
180
		not ('*' in attr.get('ARecord', []) or '*' in attr.get('AAAARecord', []))
174
181
175
def lookup_alias_filter(lo, filter_s):
182
def lookup_alias_filter(lo, filter_s):
176
	_re=re.compile('(.*)\(dnsAlias=([^=,]+)\)(.*)')
183
	_re=re.compile('(.*)\(dnsAlias=([^=,]+)\)(.*)')
(-)modules/univention/admin/handlers/dns/forward_zone.py (-4 / +10 lines)
 Lines 265-271    Link Here 
265
	def _ldap_modlist(self):
265
	def _ldap_modlist(self):
266
		ml=univention.admin.handlers.simpleLdap._ldap_modlist(self)
266
		ml=univention.admin.handlers.simpleLdap._ldap_modlist(self)
267
		if self.hasChanged(['nameserver', 'contact', 'serial', 'refresh', 'retry', 'expire', 'ttl']):
267
		if self.hasChanged(['nameserver', 'contact', 'serial', 'refresh', 'retry', 'expire', 'ttl']):
268
			ipaddr = re.compile ('^([0-9]{1,3}\.){3}[0-9]{1,3}$') # matches ip addresses - they shouldn't end with a dot!
268
			# match IPv4 OR IPv6 address (incl. IPv4-mapped IPv6), they shouldn't end with a dot
269
			ipaddr = re.compile ('^((0|[3-9][0-9]?|2(?:5[0-5]|[0-4]?[0-9])?|1[0-9]{0,2})(\.(0|[3-9][0-9]?|2(?:5[0-5]|[0-4]?[0-9])?|1[0-9]{0,2})){3})|((?!.*?::.*?::)[0-9a-fA-F]{0,4}(?:(?:(?<!::):|(?<=::))[0-9a-fA-F]{0,4}){5}(?:(?:(?<!::):|(?<=::))(?:[3-9][0-9]?|2(?:5[0-5]|[0-4]?[0-9])?|1[0-9]{0,2}0)(?:\.(?:[3-9][0-9]?|2(?:5[0-5]|[0-4]?[0-9])?|1[0-9]{0,2}|0)){3}|(?:(?:(?<!::):|(?<=::))[0-9a-fA-F]{0,4}){2}))$')
269
			if len (self['nameserver'][0]) > 0 \
270
			if len (self['nameserver'][0]) > 0 \
270
				and ipaddr.match (self['nameserver'][0]) == None \
271
				and ipaddr.match (self['nameserver'][0]) == None \
271
				and self['nameserver'][0].find (':') == -1 \
272
				and self['nameserver'][0].find (':') == -1 \
 Lines 283-292    Link Here 
283
284
284
def lookup(co, lo, filter_s, base='', superordinate=None, scope='sub', unique=0, required=0, timeout=-1, sizelimit=0):
285
def lookup(co, lo, filter_s, base='', superordinate=None, scope='sub', unique=0, required=0, timeout=-1, sizelimit=0):
285
286
286
	filter=univention.admin.filter.conjunction('&', [
287
	filter=univention.admin.filter.conjunction('|', [
288
		univention.admin.filter.conjunction('&', [
287
		univention.admin.filter.expression('objectClass', 'dNSZone'),
289
		univention.admin.filter.expression('objectClass', 'dNSZone'),
288
		univention.admin.filter.expression('relativeDomainName', '@'),
290
		univention.admin.filter.expression('relativeDomainName', '@'),
289
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('zoneName', '*.in-addr.arpa')])
291
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('zoneName', '*.in-addr.arpa')])]),
292
		univention.admin.filter.conjunction('&', [
293
		univention.admin.filter.expression('objectClass', 'dNSZone'),
294
		univention.admin.filter.expression('relativeDomainName', '@'),
295
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('zoneName', '*.ip6.arpa')])]) # IPv6
290
		])
296
		])
291
297
292
	if filter_s:
298
	if filter_s:
 Lines 304-307    Link Here 
304
310
305
	return 'dNSZone' in attr.get('objectClass', []) and\
311
	return 'dNSZone' in attr.get('objectClass', []) and\
306
		['@'] == attr.get('relativeDomainName', []) and\
312
		['@'] == attr.get('relativeDomainName', []) and\
307
		not attr['zoneName'][0].endswith('.in-addr.arpa')
313
		not attr['zoneName'][0].endswith('.arpa') # IPv6 + IPv4
(-)modules/univention/admin/handlers/dns/ptr_record.py (-3 / +8 lines)
 Lines 123-132    Link Here 
123
123
124
def lookup(co, lo, filter_s, base='', superordinate=None,scope="sub", unique=0, required=0, timeout=-1, sizelimit=0):
124
def lookup(co, lo, filter_s, base='', superordinate=None,scope="sub", unique=0, required=0, timeout=-1, sizelimit=0):
125
125
126
	filter=univention.admin.filter.conjunction('&', [
126
	filter=univention.admin.filter.conjunction('|', [
127
		univention.admin.filter.conjunction('&', [
127
		univention.admin.filter.expression('objectClass', 'dNSZone'),
128
		univention.admin.filter.expression('objectClass', 'dNSZone'),
128
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('relativeDomainName', '@')]),
129
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('relativeDomainName', '@')]),
129
		univention.admin.filter.expression('zoneName', '*.in-addr.arpa')
130
		univention.admin.filter.expression('zoneName', '*.in-addr.arpa')]),
131
		univention.admin.filter.conjunction('&', [
132
		univention.admin.filter.expression('objectClass', 'dNSZone'),
133
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('relativeDomainName', '@')]),
134
		univention.admin.filter.expression('zoneName', '*.ip6.arpa')]) # IPv6
130
		])
135
		])
131
136
132
	if superordinate:
137
	if superordinate:
 Lines 146-149    Link Here 
146
151
147
	return 'dNSZone' in attr.get('objectClass', []) and\
152
	return 'dNSZone' in attr.get('objectClass', []) and\
148
		'@' not in attr.get('relativeDomainName', []) and\
153
		'@' not in attr.get('relativeDomainName', []) and\
149
		attr['zoneName'][0].endswith('.in-addr.arpa')
154
		attr['zoneName'][0].endswith('.arpa') # IPv4 + IPv6
(-)modules/univention/admin/handlers/dns/reverse_zone.py (-14 / +39 lines)
 Lines 174-191    Link Here 
174
]
174
]
175
175
176
def mapSubnet(subnet):
176
def mapSubnet(subnet):
177
	q=subnet.split('.')
177
	v=[]
178
	q.reverse()
178
	if ':' in subnet: # IPv6
179
	return string.join(q, '.')+'.in-addr.arpa'
179
		q=subnet.split(':')
180
180
		for t in q:
181
			u=t.zfill(4)
182
			v.append((u))
183
		[v.append('0000') for x in v if len(v) < 4]
184
		v=list(''.join(v))
185
		v.reverse()
186
		return string.join(v, '.')+'.ip6.arpa'
187
	else:
188
		q=subnet.split('.')
189
		q.reverse()
190
		return string.join(q, '.')+'.in-addr.arpa'
191
  
181
def unmapSubnet(zone):
192
def unmapSubnet(zone):
182
	if type(zone) == types.ListType:
193
	if type(zone) == types.ListType:
183
		zone=zone[0]
194
		zone=zone[0]
184
	zone=zone.replace('.in-addr.arpa', '')
185
	q=zone.split('.')
186
	q.reverse()
187
	return string.join(q, '.')
188
195
196
	if zone.find('ip6')!=-1: # IPv6
197
		zone=zone.replace('.ip6.arpa', '')
198
		q=zone.split('.')
199
		q.reverse()
200
		q=[''.join(q[0:4]),''.join(q[4:8]),''.join(q[8:12]),''.join(q[12:16])]
201
		return string.join(q, ':')
202
203
	else:
204
		zone=zone.replace('.in-addr.arpa', '')
205
		q=zone.split('.')
206
		q.reverse()
207
		return string.join(q, '.')
208
189
mapping=univention.admin.mapping.mapping()
209
mapping=univention.admin.mapping.mapping()
190
mapping.register('subnet', 'zoneName', mapSubnet, unmapSubnet)
210
mapping.register('subnet', 'zoneName', mapSubnet, unmapSubnet)
191
mapping.register('zonettl','dNSTTL', None, univention.admin.mapping.ListToString)
211
mapping.register('zonettl','dNSTTL', None, univention.admin.mapping.ListToString)
 Lines 263-273    Link Here 
263
283
264
def lookup(co, lo, filter_s, base='', superordinate=None, scope='sub', unique=0, required=0, timeout=-1, sizelimit=0):
284
def lookup(co, lo, filter_s, base='', superordinate=None, scope='sub', unique=0, required=0, timeout=-1, sizelimit=0):
265
285
266
	filter=univention.admin.filter.conjunction('&', [
286
	filter=univention.admin.filter.conjunction('|', [
267
		univention.admin.filter.expression('objectClass', 'dNSZone'),
287
			univention.admin.filter.conjunction('&', [
268
		univention.admin.filter.expression('relativeDomainName', '@'),
288
			univention.admin.filter.expression('objectClass', 'dNSZone'),
269
		univention.admin.filter.expression('zoneName', '*.in-addr.arpa')
289
			univention.admin.filter.expression('relativeDomainName', '@'),
270
		])
290
			univention.admin.filter.expression('zoneName', '*.in-addr.arpa')]),
291
			univention.admin.filter.conjunction('&', [
292
			univention.admin.filter.expression('objectClass', 'dNSZone'),
293
			univention.admin.filter.expression('relativeDomainName', '@'),
294
			univention.admin.filter.expression('zoneName', '*.ip6.arpa')]) # IPv6
295
			])
271
296
272
	if filter_s:
297
	if filter_s:
273
		filter_p=univention.admin.filter.parse(filter_s)
298
		filter_p=univention.admin.filter.parse(filter_s)
 Lines 283-289    Link Here 
283
308
284
	return 'dNSZone' in attr.get('objectClass', []) and\
309
	return 'dNSZone' in attr.get('objectClass', []) and\
285
		['@'] == attr.get('relativeDomainName', []) and\
310
		['@'] == attr.get('relativeDomainName', []) and\
286
		attr['zoneName'][0].endswith('.in-addr.arpa')
311
		attr['zoneName'][0].endswith('.arpa') # IPv4 + IPv6
287
312
288
def quickDescription(rdn):
313
def quickDescription(rdn):
289
314
(-)modules/univention/admin/handlers/dns/srv_record.py (-3 / +3 lines)
 Lines 163-171    Link Here 
163
	filter=univention.admin.filter.conjunction('&', [
163
	filter=univention.admin.filter.conjunction('&', [
164
		univention.admin.filter.expression('objectClass', 'dNSZone'),
164
		univention.admin.filter.expression('objectClass', 'dNSZone'),
165
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('relativeDomainName', '@')]),
165
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('relativeDomainName', '@')]),
166
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('zoneName', '*.in-addr.arpa')]),
166
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('zoneName', '*.arpa')]),
167
		univention.admin.filter.expression('sRVRecord', '*'),
167
		univention.admin.filter.expression('sRVRecord', '*'),
168
		])
168
		]) # IPv4 + IPv6
169
169
170
	if superordinate:
170
	if superordinate:
171
		filter.expressions.append(univention.admin.filter.expression('zoneName', superordinate.mapping.mapValue('zone', superordinate['zone'])))
171
		filter.expressions.append(univention.admin.filter.expression('zoneName', superordinate.mapping.mapValue('zone', superordinate['zone'])))
 Lines 184-187    Link Here 
184
184
185
	return 'dNSZone' in attr.get('objectClass', []) and\
185
	return 'dNSZone' in attr.get('objectClass', []) and\
186
		'@' not in attr.get('relativeDomainName', []) and\
186
		'@' not in attr.get('relativeDomainName', []) and\
187
		not attr['zoneName'][0].endswith('.in-addr.arpa')
187
		not attr['zoneName'][0].endswith('.arpa') # IPv4 + IPv6
(-)modules/univention/admin/handlers/dns/host_record.py (-6 / +51 lines)
 Lines 129-135    Link Here 
129
129
130
mapping=univention.admin.mapping.mapping()
130
mapping=univention.admin.mapping.mapping()
131
mapping.register('name', 'relativeDomainName', None, univention.admin.mapping.ListToString)
131
mapping.register('name', 'relativeDomainName', None, univention.admin.mapping.ListToString)
132
mapping.register('a', 'aRecord')
133
mapping.register('mx', 'mXRecord', mapMX, unmapMX)
132
mapping.register('mx', 'mXRecord', mapMX, unmapMX)
134
mapping.register('txt', 'tXTRecord')
133
mapping.register('txt', 'tXTRecord')
135
mapping.register('zonettl', 'dNSTTL', None, univention.admin.mapping.ListToString)
134
mapping.register('zonettl', 'dNSTTL', None, univention.admin.mapping.ListToString)
 Lines 158-163    Link Here 
158
157
159
		univention.admin.handlers.simpleLdap.__init__(self, co, lo, position, dn, superordinate)
158
		univention.admin.handlers.simpleLdap.__init__(self, co, lo, position, dn, superordinate)
160
159
160
	def open(self): # IPv6
161
	    univention.admin.handlers.simpleLdap.open(self)
162
	    self.info['a']=[]
163
	    if self.oldattr.has_key('aRecord'):
164
		self.info['a'].extend((self.oldattr.get('aRecord')))
165
	    if self.oldattr.has_key('aAAARecord'):
166
		self.info['a'].extend((self.oldattr.get('aAAARecord')))
167
	    self.save() # safe current state as old state
168
161
	def exists(self):
169
	def exists(self):
162
		return self._exists
170
		return self._exists
163
171
 Lines 170-175    Link Here 
170
			(self.superordinate.mapping.mapName('zone'), self.superordinate.mapping.mapValue('zone', self.superordinate['zone'])),
178
			(self.superordinate.mapping.mapName('zone'), self.superordinate.mapping.mapValue('zone', self.superordinate['zone'])),
171
		]
179
		]
172
180
181
	def _ldap_modlist(self): # IPv6
182
		ml=univention.admin.handlers.simpleLdap._ldap_modlist(self)
183
		old = self.oldinfo.get('a')
184
		new = self.info.get('a')
185
		ao=[]
186
		an=[]
187
		aaaao=[]
188
		aaaan=[]
189
190
		if old != new:
191
			if old:
192
			    for addr in old:
193
					if ':' in addr: # IPv6
194
						aaaao.append((addr))
195
					else:
196
						ao.append((addr))
197
						i=i+1
198
			if new:
199
			    for addr in new:
200
					if ':' in addr: # IPv6
201
						aaaan.append((addr))
202
					else:
203
						an.append((addr))
204
			ml.append(('aRecord', ao, an))
205
			ml.append(('aAAARecord', aaaao, aaaan))
206
		#print 'DEBUG: ml: "%s" ' %ml
207
		return ml
208
173
	def _ldap_post_create(self):
209
	def _ldap_post_create(self):
174
		self._updateZone()
210
		self._updateZone()
175
211
 Lines 182-194    Link Here 
182
218
183
def lookup(co, lo, filter_s, base='', superordinate=None,scope="sub", unique=0, required=0, timeout=-1, sizelimit=0):
219
def lookup(co, lo, filter_s, base='', superordinate=None,scope="sub", unique=0, required=0, timeout=-1, sizelimit=0):
184
220
185
	filter=univention.admin.filter.conjunction('&', [
221
	filter=univention.admin.filter.conjunction('|', [
222
		univention.admin.filter.conjunction('&', [
186
		univention.admin.filter.expression('objectClass', 'dNSZone'),
223
		univention.admin.filter.expression('objectClass', 'dNSZone'),
187
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('relativeDomainName', '@')]),
224
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('relativeDomainName', '@')]),
188
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('zoneName', '*.in-addr.arpa')]),
225
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('zoneName', '*.in-addr.arpa')]),
189
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('CNAMERecord', '*')]),
226
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('CNAMERecord', '*')]),
190
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('SRVRecord', '*')])
227
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('SRVRecord', '*')])]),
191
		])
228
		univention.admin.filter.conjunction('&', [
229
		univention.admin.filter.expression('objectClass', 'dNSZone'),
230
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('relativeDomainName', '@')]),
231
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('zoneName', '*.ip6.arpa')]),
232
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('CNAMERecord', '*')]),
233
		univention.admin.filter.conjunction('!', [univention.admin.filter.expression('SRVRecord', '*')])])
234
		]) # IPv6
192
235
193
	if superordinate:
236
	if superordinate:
194
		filter.expressions.append(univention.admin.filter.expression('zoneName', superordinate.mapping.mapValue('zone', superordinate['zone'])))
237
		filter.expressions.append(univention.admin.filter.expression('zoneName', superordinate.mapping.mapValue('zone', superordinate['zone'])))
 Lines 206-214    Link Here 
206
def identify(dn, attr, canonical=0):
249
def identify(dn, attr, canonical=0):
207
250
208
	univention.debug.debug(univention.debug.ADMIN, univention.debug.INFO, 'ALIAS(host_record) identify DN=%s'% dn)
251
	univention.debug.debug(univention.debug.ADMIN, univention.debug.INFO, 'ALIAS(host_record) identify DN=%s'% dn)
252
	# IPv4 + IPv6
209
	return 'dNSZone' in attr.get('objectClass', []) and\
253
	return 'dNSZone' in attr.get('objectClass', []) and\
210
		'@' not in attr.get('relativeDomainName', []) and\
254
		'@' not in attr.get('relativeDomainName', []) and\
211
		not attr['zoneName'][0].endswith('.in-addr.arpa') and\
255
		not attr['zoneName'][0].endswith('.arpa') and\
212
		'*' not in attr.get('CNAMERecord', []) and\
256
		'*' not in attr.get('CNAMERecord', []) and\
213
		'*' not in attr.get('SRVRecord', []) and\
257
		'*' not in attr.get('SRVRecord', []) and\
214
		('*' in attr.get('ARecord', []) or '*' in attr.get('MXRecord', []) )
258
		('*' in attr.get('ARecord', []) or '*' in attr.get('AAAARecord', []) or '*' in attr.get('MXRecord', []) )
259
(-)modules/univention/admin/handlers/__init__.py (-89 / +204 lines)
 Lines 29-34    Link Here 
29
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
29
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
30
30
31
import copy, types, sys, re, string, ldap
31
import copy, types, sys, re, string, ldap
32
import ipaddr # IPv6 address handling
32
import univention.debug
33
import univention.debug
33
import univention.admin.filter
34
import univention.admin.filter
34
import univention.admin.uldap
35
import univention.admin.uldap
 Lines 983-995    Link Here 
983
	# HELPER
984
	# HELPER
984
	def __ip_from_ptr( self, zoneName, relativeDomainName ):
985
	def __ip_from_ptr( self, zoneName, relativeDomainName ):
985
986
986
		zoneName = zoneName.replace(  '.in-addr.arpa', '' ).split( '.' )
987
		if zoneName.find('ip6')!=-1: # IPv6
987
		zoneName.reverse( )
988
			zoneName=zoneName.replace('.ip6.arpa', '').split( '.' )
988
		relativeDomainName = relativeDomainName.split( '.' )
989
			zoneName.reverse( )
989
		relativeDomainName.reverse( )
990
			zoneName=(''.join(zoneName[0:4]) + ':' + ''.join(zoneName[4:8]) + ':' + ''.join(zoneName[8:12]) + ':' + ''.join(zoneName[12:16]))
991
			relativeDomainName = relativeDomainName.split( '.' )
992
			relativeDomainName.reverse( )
993
			relativeDomainName=(''.join(relativeDomainName[0:4]) + ':' + ''.join(relativeDomainName[4:8]) + ':' + ''.join(relativeDomainName[8:12]) + ':' + ''.join(relativeDomainName[12:16]))
994
			return '%s:%s' % ( zoneName, relativeDomainName )
995
		else:
996
			zoneName = zoneName.replace(  '.in-addr.arpa', '' ).split( '.' )
997
			zoneName.reverse( )
998
			relativeDomainName = relativeDomainName.split( '.' )
999
			relativeDomainName.reverse( )
1000
			return '%s.%s' % ( string.join( zoneName, '.' ) , string.join( relativeDomainName, '.' ) )
990
1001
991
		return '%s.%s' % ( string.join( zoneName, '.' ) , string.join( relativeDomainName, '.' ) )
992
993
	def __is_mac( self, mac ):
1002
	def __is_mac( self, mac ):
994
		_re = re.compile( '^[ 0-9a-fA-F ][ 0-9a-fA-F ]??$' )
1003
		_re = re.compile( '^[ 0-9a-fA-F ][ 0-9a-fA-F ]??$' )
995
		m = mac.split( ':' )
1004
		m = mac.split( ':' )
 Lines 1001-1012    Link Here 
1001
		return False
1010
		return False
1002
1011
1003
	def __is_ip( self, ip ):
1012
	def __is_ip( self, ip ):
1004
		_re = re.compile( '^[ 0-9 ]+\.[ 0-9 ]+\.[ 0-9 ]+\.[ 0-9 ]+$' )
1013
		# return True if valid IPv4 (0.0.0.0 is allowed) or IPv6 address
1005
		if _re.match ( ip ):
1014
		try:
1006
			univention.debug.debug( univention.debug.ADMIN, univention.debug.INFO, 'IP[%s]? -> Yes' % ip )
1015
			ipaddr.IPAddress(ip)
1007
			return True
1016
		except ValueError:
1008
		univention.debug.debug( univention.debug.ADMIN, univention.debug.INFO, 'IP[%s]? -> No' % ip )
1017
			univention.debug.debug( univention.debug.ADMIN, univention.debug.INFO, 'IP[%s]? -> No' % ip )
1009
		return False
1018
			return False
1019
		univention.debug.debug( univention.debug.ADMIN, univention.debug.INFO, 'IP[%s]? -> Yes' % ip )
1020
		return True
1010
1021
1011
	def open( self ):
1022
	def open( self ):
1012
		simpleLdap.open( self )
1023
		simpleLdap.open( self )
 Lines 1033-1039    Link Here 
1033
1044
1034
			searchFilter = '(&(objectClass=dNSZone)(relativeDomainName=%s)(!(cNAMERecord=*)))' % self[ 'name' ]
1045
			searchFilter = '(&(objectClass=dNSZone)(relativeDomainName=%s)(!(cNAMERecord=*)))' % self[ 'name' ]
1035
			try:
1046
			try:
1036
				result = self.lo.search( base = tmppos.getBase( ),scope = 'domain', filter = searchFilter, attr = [ 'zoneName', 'aRecord' ], unique = 0 )
1047
				result = self.lo.search( base = tmppos.getBase( ),scope = 'domain', filter = searchFilter, attr = [ 'zoneName', 'aRecord', 'aAAARecord' ], unique = 0 ) # IPv4 + IPv6
1037
1048
1038
				zoneNames = [ ]
1049
				zoneNames = [ ]
1039
1050
 Lines 1041-1046    Link Here 
1041
					for dn, attr in result:
1052
					for dn, attr in result:
1042
						if attr.has_key( 'aRecord' ):
1053
						if attr.has_key( 'aRecord' ):
1043
							zoneNames.append( ( attr[ 'zoneName' ][ 0 ], attr[ 'aRecord' ] ) )
1054
							zoneNames.append( ( attr[ 'zoneName' ][ 0 ], attr[ 'aRecord' ] ) )
1055
						if attr.has_key( 'aAAARecord' ): # IPv6
1056
							zoneNames.append( ( attr[ 'zoneName' ][ 0 ], attr[ 'aAAARecord' ] ) )
1044
1057
1045
				univention.debug.debug( univention.debug.ADMIN, univention.debug.INFO, 'zoneNames: %s' % zoneNames )
1058
				univention.debug.debug( univention.debug.ADMIN, univention.debug.INFO, 'zoneNames: %s' % zoneNames )
1046
1059
 Lines 1208-1214    Link Here 
1208
	def __rename_dns_object( self, position = None, old_name = None, new_name = None ):
1221
	def __rename_dns_object( self, position = None, old_name = None, new_name = None ):
1209
		for dns_line in self[ 'dnsEntryZoneForward' ]:
1222
		for dns_line in self[ 'dnsEntryZoneForward' ]:
1210
			dn, ip = self.__split_dns_line( dns_line )
1223
			dn, ip = self.__split_dns_line( dns_line )
1211
			results = self.lo.searchDn( base = dn, scope = 'domain', filter = 'aRecord=%s' % ip, unique = 0 )
1224
			if ip.find(':')!=-1: # IPv6
1225
				results = self.lo.searchDn( base = dn, scope = 'domain', filter = 'aAAARecord=%s' % ip, unique = 0 )
1226
			else:
1227
				results = self.lo.searchDn( base = dn, scope = 'domain', filter = 'aRecord=%s' % ip, unique = 0 )
1212
			for result in results:
1228
			for result in results:
1213
				object = univention.admin.objects.get( univention.admin.modules.get( 'dns/host_record' ), self.co, self.lo, position = self.position, dn = result )
1229
				object = univention.admin.objects.get( univention.admin.modules.get( 'dns/host_record' ), self.co, self.lo, position = self.position, dn = result )
1214
				object.open( )
1230
				object.open( )
 Lines 1362-1386    Link Here 
1362
		univention.debug.debug( univention.debug.ADMIN, univention.debug.INFO, 'we should create a dns reverse object: zoneDn="%s", name="%s", ip="%s"' % ( zoneDn, name, ip ) )
1378
		univention.debug.debug( univention.debug.ADMIN, univention.debug.INFO, 'we should create a dns reverse object: zoneDn="%s", name="%s", ip="%s"' % ( zoneDn, name, ip ) )
1363
		if name and zoneDn and ip:
1379
		if name and zoneDn and ip:
1364
			univention.debug.debug( univention.debug.ADMIN, univention.debug.INFO, 'dns reverse object: start' )
1380
			univention.debug.debug( univention.debug.ADMIN, univention.debug.INFO, 'dns reverse object: start' )
1365
			subnet = ldap.explode_dn( zoneDn, 1 )[ 0 ].replace( '.in-addr.arpa', '' ).split( '.' )
1381
			if ip.find(':')!=-1: # IPv6, e.g. ip=2001:db8:100::5
1366
			subnet.reverse( )
1382
				subnet = ldap.explode_dn( zoneDn, 1 )[ 0 ].replace( '.ip6.arpa', '' ).split( '.' )
1367
			subnet = string.join( subnet, '.' ) + '.'
1383
				subnet.reverse( )
1368
			ipPart = ip.replace( subnet, '' )
1384
				subnet=[''.join(subnet[0:4]),''.join(subnet[4:8]),''.join(subnet[8:12]),''.join(subnet[12:16])]
1369
			if ipPart == ip:
1385
				subnet = string.join( subnet, ':' ) + ':' # e.g. '2001:0db8:0100:0000:'
1370
				raise univention.admin.uexceptions.missingInformation, _( 'Reverse zone and IP address are incompatible.' )
1386
				ip6=(ipaddr.IPv6Address(ip)).exploded # use Python Module ipaddr to 'explode' IPv6 address
1371
1387
				ipPart = ip6.replace( subnet, '' )# e.g. '0000:0000:0000:0005'
1372
			pointer = string.split( ipPart, '.' )
1388
				if ipPart == ip:
1373
			pointer.reverse( )
1389
					raise univention.admin.uexceptions.missingInformation, _( 'Reverse zone and IP address are incompatible.' )
1374
			ipPart = string.join( pointer, '.' )
1390
				pointer = string.split( ipPart, ':' )
1375
			tmppos = univention.admin.uldap.position( self.position.getDomain( ) )
1391
				pointer=list(''.join(pointer)) # e.g. ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '5']
1376
			# check in which forward zone the ip is set
1392
				pointer.reverse()
1377
			hostname_list = []
1393
				ipPart=string.join(pointer, '.') # e.g. '5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0'
1378
			results = self.lo.search( base = tmppos.getBase( ) , scope = 'domain', attr = [ 'zoneName' ], filter = '(&(relativeDomainName=%s)(aRecord=%s))' % ( name, ip ), unique = 0 )
1394
				tmppos = univention.admin.uldap.position( self.position.getDomain( ) )
1379
			if results:
1395
				# check in which forward zone the ip is set
1380
				for dn,attr in results:
1396
				hostname_list = []
1381
					if attr.has_key( 'zoneName' ):
1397
				results = self.lo.search( base = tmppos.getBase( ) , scope = 'domain', attr = [ 'zoneName' ], filter = '(&(relativeDomainName=%s)(aAAARecord=%s))' % ( name, ip ), unique = 0 ) # IPv6
1382
						if not '%s.%s.' % ( name, attr[ 'zoneName' ][ 0 ] ) in hostname_list:
1398
				if results:
1399
					for dn,attr in results:
1400
						if attr.has_key( 'zoneName' ):
1383
							hostname_list.append( '%s.%s.' % ( name, attr[ 'zoneName' ][ 0 ] ) )
1401
							hostname_list.append( '%s.%s.' % ( name, attr[ 'zoneName' ][ 0 ] ) )
1402
			else:
1403
				subnet = ldap.explode_dn( zoneDn, 1 )[ 0 ].replace( '.in-addr.arpa', '' ).split( '.' )
1404
				subnet.reverse( )
1405
				subnet = string.join( subnet, '.' ) + '.'
1406
				ipPart = ip.replace( subnet, '' )
1407
				if ipPart == ip:
1408
					raise univention.admin.uexceptions.missingInformation, _( 'Reverse zone and IP address are incompatible.' )
1409
				pointer = string.split( ipPart, '.' )
1410
				pointer.reverse( )
1411
				ipPart = string.join( pointer, '.' )
1412
				tmppos = univention.admin.uldap.position( self.position.getDomain( ) )
1413
				# check in which forward zone the ip is set
1414
				hostname_list = []
1415
				results = self.lo.search( base = tmppos.getBase( ) , scope = 'domain', attr = [ 'zoneName' ], filter = '(&(relativeDomainName=%s)(aRecord=%s))' % ( name, ip ), unique = 0 )
1416
				if results:
1417
					for dn,attr in results:
1418
						if attr.has_key( 'zoneName' ):
1419
							if not '%s.%s.' % ( name, attr[ 'zoneName' ][ 0 ] ) in hostname_list:
1420
								hostname_list.append( '%s.%s.' % ( name, attr[ 'zoneName' ][ 0 ] ) )
1384
1421
1385
			if len( hostname_list ) < 1:
1422
			if len( hostname_list ) < 1:
1386
				hostname_list.append ( name )
1423
				hostname_list.append ( name )
 Lines 1463-1477    Link Here 
1463
				base = tmppos.getBase( )
1500
				base = tmppos.getBase( )
1464
			else:
1501
			else:
1465
				base = zoneDn
1502
				base = zoneDn
1466
			results = self.lo.search( base = base, scope = 'domain', attr = [ 'aRecord' ], filter = '(&(relativeDomainName=%s)(aRecord=%s))' % ( name, old_ip ), unique = 0 )
1467
			for dn, attr in results:
1468
				new_ip_list = copy.deepcopy( attr[ 'aRecord' ] )
1469
				new_ip_list.remove( old_ip )
1470
				new_ip_list.append( new_ip )
1471
				self.lo.modify( dn, [ ( 'aRecord', attr[ 'aRecord' ],  new_ip_list ) ] )
1472
				if not zoneDn:
1473
					zone = string.join( ldap.explode_dn( dn )[ 1: ], ',' )
1474
1503
1504
			if old_ip.find(':')!=-1: # IPv6
1505
				results = self.lo.search( base = base, scope = 'domain', attr = [ 'aAAARecord' ], filter = '(&(relativeDomainName=%s)(aAAARecord=%s))' % ( name, old_ip ), unique = 0 )
1506
			else:				
1507
				results = self.lo.search( base = base, scope = 'domain', attr = [ 'aRecord' ], filter = '(&(relativeDomainName=%s)(aRecord=%s))' % ( name, old_ip ), unique = 0 )
1508
1509
			if new_ip.find(':')!=-1: # IPv6
1510
				for dn, attr in results:
1511
					new_ip_list = copy.deepcopy( attr[ 'aAAARecord' ] )
1512
					new_ip_list.remove( old_ip )
1513
					new_ip_list.append( new_ip )
1514
					self.lo.modify( dn, [ ( 'aAAARecord', attr[ 'aAAARecord' ],  new_ip_list ) ] )
1515
					if not zoneDn:
1516
						zone = string.join( ldap.explode_dn( dn )[ 1: ], ',' )
1517
			else:
1518
				for dn, attr in results:
1519
					new_ip_list = copy.deepcopy( attr[ 'aRecord' ] )
1520
					new_ip_list.remove( old_ip )
1521
					new_ip_list.append( new_ip )
1522
					self.lo.modify( dn, [ ( 'aRecord', attr[ 'aRecord' ],  new_ip_list ) ] )
1523
					if not zoneDn:
1524
						zone = string.join( ldap.explode_dn( dn )[ 1: ], ',' )
1525
1475
			if zoneDn:
1526
			if zoneDn:
1476
				zone = zoneDn
1527
				zone = zoneDn
1477
1528
 Lines 1485-1518    Link Here 
1485
1536
1486
	def __add_dns_forward_object( self, name, zoneDn, ip ):
1537
	def __add_dns_forward_object( self, name, zoneDn, ip ):
1487
		univention.debug.debug( univention.debug.ADMIN, univention.debug.INFO, 'we should add a dns forward object: zoneDn="%s", name="%s", ip="%s"' % ( zoneDn, name, ip ) )
1538
		univention.debug.debug( univention.debug.ADMIN, univention.debug.INFO, 'we should add a dns forward object: zoneDn="%s", name="%s", ip="%s"' % ( zoneDn, name, ip ) )
1488
		if name and ip and zoneDn:
1539
		if ip.find(':')!=-1: #IPv6
1489
			results = self.lo.search( base = zoneDn, scope = 'domain', attr = [ 'aRecord' ], filter = '(&(relativeDomainName=%s)(!(cNAMERecord=*)))' % ( name ), unique = 0 )
1540
			if name and ip and zoneDn:
1490
			if not results:
1541
				results = self.lo.search( base = zoneDn, scope = 'domain', attr = [ 'aAAARecord' ], filter = '(&(relativeDomainName=%s)(!(cNAMERecord=*)))' % ( name ), unique = 0 )
1491
				try:
1542
				if not results:
1492
					self.lo.add( 'relativeDomainName=%s,%s'% ( name, zoneDn ), [\
1543
					try:
1544
						self.lo.add( 'relativeDomainName=%s,%s'% ( name, zoneDn ), [\
1493
										( 'objectClass', [ 'top', 'dNSZone' ]),\
1545
										( 'objectClass', [ 'top', 'dNSZone' ]),\
1494
										( 'zoneName', univention.admin.uldap.explodeDn( zoneDn, 1 )[ 0 ]),\
1546
										( 'zoneName', univention.admin.uldap.explodeDn( zoneDn, 1 )[ 0 ]),\
1547
										( 'aAAARecord', [ ip ]),\
1548
										( 'relativeDomainName', [ name ])])
1549
					except univention.admin.uexceptions.objectExists:
1550
						raise univention.admin.uexceptions.dnsAliasRecordExists
1551
1552
					# TODO: check if zoneDn really a forwardZone, maybe it is a container under a zone
1553
					zone = univention.admin.handlers.dns.forward_zone.object( self.co, self.lo, self.position, zoneDn )
1554
					zone.open()
1555
					zone.modify()
1556
				else:
1557
					for dn, attr in results:
1558
						if attr.has_key( 'aAAARecord' ):
1559
							new_ip_list = copy.deepcopy( attr[ 'aAAARecord' ] )
1560
							if not ip in new_ip_list:
1561
								new_ip_list.append( ip )
1562
								self.lo.modify( dn, [ ( 'aAAARecord', attr[ 'aAAARecord' ],  new_ip_list ) ] )
1563
						else:
1564
							self.lo.modify( dn, [ ( 'aAAARecord', '' ,  ip ) ] )
1565
			pass
1566
		else:
1567
			if name and ip and zoneDn:
1568
				results = self.lo.search( base = zoneDn, scope = 'domain', attr = [ 'aRecord' ], filter = '(&(relativeDomainName=%s)(!(cNAMERecord=*)))' % ( name ), unique = 0 )
1569
				if not results:
1570
					try:
1571
						self.lo.add( 'relativeDomainName=%s,%s'% ( name, zoneDn ), [\
1572
										( 'objectClass', [ 'top', 'dNSZone' ]),\
1573
										( 'zoneName', univention.admin.uldap.explodeDn( zoneDn, 1 )[ 0 ]),\
1495
										( 'ARecord', [ ip ]),\
1574
										( 'ARecord', [ ip ]),\
1496
										( 'relativeDomainName', [ name ])])
1575
										( 'relativeDomainName', [ name ])])
1497
				except univention.admin.uexceptions.objectExists:
1576
					except univention.admin.uexceptions.objectExists:
1498
					raise univention.admin.uexceptions.dnsAliasRecordExists
1577
						raise univention.admin.uexceptions.dnsAliasRecordExists
1499
1578
1500
				# TODO: check if zoneDn really a forwardZone, maybe it is a container under a zone
1579
					# TODO: check if zoneDn really a forwardZone, maybe it is a container under a zone
1501
				zone = univention.admin.handlers.dns.forward_zone.object( self.co, self.lo, self.position, zoneDn )
1580
					zone = univention.admin.handlers.dns.forward_zone.object( self.co, self.lo, self.position, zoneDn )
1502
				zone.open()
1581
					zone.open()
1503
				zone.modify()
1582
					zone.modify()
1504
			else:
1583
				else:
1505
				for dn, attr in results:
1584
					for dn, attr in results:
1506
					if attr.has_key( 'aRecord' ):
1585
						if attr.has_key( 'aRecord' ):
1507
						new_ip_list = copy.deepcopy( attr[ 'aRecord' ] )
1586
							new_ip_list = copy.deepcopy( attr[ 'aRecord' ] )
1508
						if not ip in new_ip_list:
1587
							if not ip in new_ip_list:
1509
							new_ip_list.append( ip )
1588
								new_ip_list.append( ip )
1510
							self.lo.modify( dn, [ ( 'aRecord', attr[ 'aRecord' ],  new_ip_list ) ] )
1589
								self.lo.modify( dn, [ ( 'aRecord', attr[ 'aRecord' ],  new_ip_list ) ] )
1511
					else:
1590
						else:
1512
						self.lo.modify( dn, [ ( 'aRecord', '' ,  ip ) ] )
1591
							self.lo.modify( dn, [ ( 'aRecord', '' ,  ip ) ] )
1513
		pass
1592
			pass
1514
1593
1515
1516
	def __add_dns_alias_object( self, name, dnsForwardZone, dnsAliasZoneContainer, alias ):
1594
	def __add_dns_alias_object( self, name, dnsForwardZone, dnsAliasZoneContainer, alias ):
1517
		univention.debug.debug( univention.debug.ADMIN, univention.debug.INFO, 'add a dns alias object: name="%s", dnsForwardZone="%s", dnsAliasZoneContainer="%s", alias="%s"' % ( name, dnsForwardZone, dnsAliasZoneContainer, alias ) )
1595
		univention.debug.debug( univention.debug.ADMIN, univention.debug.INFO, 'add a dns alias object: name="%s", dnsForwardZone="%s", dnsAliasZoneContainer="%s", alias="%s"' % ( name, dnsForwardZone, dnsAliasZoneContainer, alias ) )
1518
		if name and dnsForwardZone and dnsAliasZoneContainer and alias:
1596
		if name and dnsForwardZone and dnsAliasZoneContainer and alias:
 Lines 1814-1851    Link Here 
1814
		return ml
1892
		return ml
1815
1893
1816
	def calc_dns_reverse_entry_name(self, sip, reverseDN):
1894
	def calc_dns_reverse_entry_name(self, sip, reverseDN):
1817
		subnet=ldap.explode_dn(reverseDN, 1)[0].replace('.in-addr.arpa','').split('.')
1895
		if sip.find(':')!=-1: # IPv6
1818
		ip=sip.split('.')
1896
			subnet=ldap.explode_dn(reverseDN, 1)[0].replace('.ip6.arpa','').split('.')
1819
		zoneNet=subnet
1897
			ip6=ipaddr.IPv6Address(sip) # use Python Module ipaddr to 'explode' IPv6 address
1820
		zoneNet.reverse()
1898
			ip6=ip6.exploded
1821
		length=len(zoneNet)
1899
			ip6=ip6.split(':')
1822
		count=0
1900
			ip6=list(''.join(ip6))
1823
		match=1
1901
			zoneNet=subnet
1824
		for i in zoneNet:
1902
			zoneNet.reverse()
1825
			if count == length:
1903
			length=len(zoneNet)
1826
				break
1904
			count=0
1905
			match=1
1906
			for i in zoneNet:
1907
				if count == length:
1908
					break
1827
1909
1828
			if not ip[count] == i:
1910
				if not ip6[count] == i:
1829
				match=0
1911
					match=0
1830
			count += 1
1912
				count += 1
1831
1913
1832
		if match == 1:
1914
			if match == 1:
1833
			stop=(4-length)
1915
				stop=(32-length)
1834
			rmIP=''
1916
				rmIP=''
1835
			ip.reverse()
1917
				ip6.reverse()
1918
				count=0
1919
				for i in ip6:
1920
					if count == stop:
1921
						break
1922
					if len(rmIP) > 0:
1923
						rmIP=rmIP+'.'+ip6[count]
1924
					else:
1925
						rmIP=ip6[count]
1926
					count += 1
1927
				return rmIP
1928
			else:
1929
				return 0
1930
1931
		else:
1932
			subnet=ldap.explode_dn(reverseDN, 1)[0].replace('.in-addr.arpa','').split('.')
1933
			ip=sip.split('.')
1934
			zoneNet=subnet
1935
			zoneNet.reverse()
1936
			length=len(zoneNet)
1836
			count=0
1937
			count=0
1837
			for i in ip:
1938
			match=1
1838
				if count == stop:
1939
			for i in zoneNet:
1940
				if count == length:
1839
					break
1941
					break
1840
				if len(rmIP) > 0:
1841
					rmIP=rmIP+'.'+ip[count]
1842
				else:
1843
					rmIP=ip[count]
1844
				count=count+1
1845
			return rmIP
1846
		else:
1847
			return 0
1848
1942
1943
				if not ip[count] == i:
1944
					match=0
1945
				count += 1
1946
1947
			if match == 1:
1948
				stop=(4-length)
1949
				rmIP=''
1950
				ip.reverse()
1951
				count=0
1952
				for i in ip:
1953
					if count == stop:
1954
						break
1955
					if len(rmIP) > 0:
1956
						rmIP=rmIP+'.'+ip[count]
1957
					else:
1958
						rmIP=ip[count]
1959
					count=count+1
1960
				return rmIP # for ip='10.200.2.5' and subnet='2.200.10.in-addr.arpa' -> rmIP='5' ('5.2' for 200.10.in-addr.arpa)
1961
			else:
1962
				return 0
1963
1849
	def _ldap_pre_create(self):
1964
	def _ldap_pre_create(self):
1850
		self.check_common_name_length()
1965
		self.check_common_name_length()
1851
1966
(-)modules/univention/admin/de.po (-177 / +179 lines)
 Lines 6-13    Link Here 
6
msgstr ""
6
msgstr ""
7
"Project-Id-Version: PACKAGE VERSION\n"
7
"Project-Id-Version: PACKAGE VERSION\n"
8
"Report-Msgid-Bugs-To: \n"
8
"Report-Msgid-Bugs-To: \n"
9
"POT-Creation-Date: 2009-08-07 14:05+0200\n"
9
"POT-Creation-Date: 2009-11-04 13:48+0100\n"
10
"PO-Revision-Date: 2009-08-07 10:29+0200\n"
10
"PO-Revision-Date: 2009-11-04 14:01+0100\n"
11
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
11
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12
"Language-Team: LANGUAGE <LL@li.org>\n"
12
"Language-Team: LANGUAGE <LL@li.org>\n"
13
"MIME-Version: 1.0\n"
13
"MIME-Version: 1.0\n"
 Lines 20-42    Link Here 
20
msgid ": type was %s"
20
msgid ": type was %s"
21
msgstr ": Typ war %s"
21
msgstr ": Typ war %s"
22
22
23
#: modules.py:163 modules.py:346
23
#: modules.py:166 modules.py:353
24
msgid "Custom"
24
msgid "Custom"
25
msgstr "Benutzerdefiniert"
25
msgstr "Benutzerdefiniert"
26
26
27
#: modules.py:832
27
#: modules.py:839
28
msgid "Search"
28
msgid "Search"
29
msgstr "Suchen"
29
msgstr "Suchen"
30
30
31
#: modules.py:832
31
#: modules.py:839
32
msgid "Search object(s)"
32
msgid "Search object(s)"
33
msgstr "Objekt(e) suchen"
33
msgstr "Objekt(e) suchen"
34
34
35
#: modules.py:832
35
#: modules.py:839
36
msgid "Add"
36
msgid "Add"
37
msgstr "Hinzufügen"
37
msgstr "Hinzufügen"
38
38
39
#: modules.py:832
39
#: modules.py:839
40
msgid "Add object(s)"
40
msgid "Add object(s)"
41
msgstr "Objekt(e) hinzufügen"
41
msgstr "Objekt(e) hinzufügen"
42
42
 Lines 181-260    Link Here 
181
msgid "cannot find fqdn of "
181
msgid "cannot find fqdn of "
182
msgstr "FQDN konnte nicht gefunden werden: "
182
msgstr "FQDN konnte nicht gefunden werden: "
183
183
184
#: syntax.py:104
184
#: syntax.py:105
185
msgid "not enough arguments"
185
msgid "not enough arguments"
186
msgstr "Nicht genug Parameter"
186
msgstr "Nicht genug Parameter"
187
187
188
#: syntax.py:108
188
#: syntax.py:109
189
msgid "too many arguments"
189
msgid "too many arguments"
190
msgstr "Zu viele Parameter"
190
msgstr "Zu viele Parameter"
191
191
192
#: syntax.py:118
192
#: syntax.py:119
193
msgid "Invalid syntax"
193
msgid "Invalid syntax"
194
msgstr "Falsche Syntax"
194
msgstr "Falsche Syntax"
195
195
196
#: syntax.py:237
196
#: syntax.py:247
197
msgid "Value must be a number!"
197
msgid "Value must be a number!"
198
msgstr "Der Wert muss eine Zahl sein."
198
msgstr "Der Wert muss eine Zahl sein."
199
199
200
#: syntax.py:249
200
#: syntax.py:259
201
msgid "Value must be 0 or 1"
201
msgid "Value must be 0 or 1"
202
msgstr "Der Wert muss 0 oder 1 sein."
202
msgstr "Der Wert muss 0 oder 1 sein."
203
203
204
#: syntax.py:261
204
#: syntax.py:271
205
msgid ""
205
msgid ""
206
"Value must be an integer followed by one of GB,MB,KB,B or nothing (equals B)!"
206
"Value must be an integer followed by one of GB,MB,KB,B or nothing (equals B)!"
207
msgstr ""
207
msgstr ""
208
"Der Wert muss eine Zahl sein. Optional kann noch eine Einheit mittels GB,MB,"
208
"Der Wert muss eine Zahl sein. Optional kann noch eine Einheit mittels GB,MB,"
209
"KB oder B angegeben werden."
209
"KB oder B angegeben werden."
210
210
211
#: syntax.py:268
211
#: syntax.py:278
212
msgid "Value may not contain whitespace or exclamation mark !"
212
msgid "Value may not contain whitespace or exclamation mark !"
213
msgstr "Der Wert darf keine Leerzeichen oder Ausrufezeichen enthalten."
213
msgstr "Der Wert darf keine Leerzeichen oder Ausrufezeichen enthalten."
214
214
215
#: syntax.py:275
215
#: syntax.py:285
216
msgid "undefined"
216
msgid "undefined"
217
msgstr "nicht definiert"
217
msgstr "nicht definiert"
218
218
219
#: syntax.py:276
219
#: syntax.py:286
220
msgid "mails"
220
msgid "mails"
221
msgstr "Mails"
221
msgstr "Mails"
222
222
223
#: syntax.py:277
223
#: syntax.py:287
224
msgid "events"
224
msgid "events"
225
msgstr "Kalender"
225
msgstr "Kalender"
226
226
227
#: syntax.py:278
227
#: syntax.py:288
228
msgid "contacts"
228
msgid "contacts"
229
msgstr "Kontakte"
229
msgstr "Kontakte"
230
230
231
#: syntax.py:279
231
#: syntax.py:289
232
msgid "tasks"
232
msgid "tasks"
233
msgstr "Aufgaben"
233
msgstr "Aufgaben"
234
234
235
#: syntax.py:280
235
#: syntax.py:290
236
msgid "notes"
236
msgid "notes"
237
msgstr "Notizen"
237
msgstr "Notizen"
238
238
239
#: syntax.py:281
239
#: syntax.py:291
240
msgid "journals"
240
msgid "journals"
241
msgstr "Journal"
241
msgstr "Journal"
242
242
243
#: syntax.py:293 syntax.py:317 syntax.py:380 syntax.py:646 syntax.py:655
243
#: syntax.py:303 syntax.py:327 syntax.py:390
244
#: syntax.py:665
245
msgid "Value may not contain other than numbers, letters and dots!"
244
msgid "Value may not contain other than numbers, letters and dots!"
246
msgstr "Der Wert darf nur Zahlen, Buchstaben und Punkte enthalten."
245
msgstr "Der Wert darf nur Zahlen, Buchstaben und Punkte enthalten."
247
246
248
#: syntax.py:304
247
#: syntax.py:314
249
msgid "Value may not contain other than numbers, letters, dots and spaces!"
248
msgid "Value may not contain other than numbers, letters, dots and spaces!"
250
msgstr ""
249
msgstr ""
251
"Der Wert darf nur Zahlen, Buchstaben, Leerzeichen und Punkte enthalten."
250
"Der Wert darf nur Zahlen, Buchstaben, Leerzeichen und Punkte enthalten."
252
251
253
#: syntax.py:326
252
#: syntax.py:336
254
msgid "Field must only contain ASCII characters!"
253
msgid "Field must only contain ASCII characters!"
255
msgstr "Der Wert darf nur ASCII Buchstaben enthalten!"
254
msgstr "Der Wert darf nur ASCII Buchstaben enthalten!"
256
255
257
#: syntax.py:339
256
#: syntax.py:349
258
msgid ""
257
msgid ""
259
"Value may not contain other than numbers, letters and dots, and may not be "
258
"Value may not contain other than numbers, letters and dots, and may not be "
260
"admin!"
259
"admin!"
 Lines 262-452    Link Here 
262
"Der Wert darf nur Zahlen, Buchstaben und Punkte enthalten. Ausnahme ist die "
261
"Der Wert darf nur Zahlen, Buchstaben und Punkte enthalten. Ausnahme ist die "
263
"Bezeichnug 'admin', die auch nicht verwendet werden darf"
262
"Bezeichnug 'admin', die auch nicht verwendet werden darf"
264
263
265
#: syntax.py:351 syntax.py:368
264
#: syntax.py:361 syntax.py:378
266
msgid ""
265
msgid ""
267
"Username must only contain numbers, letters and dots, and may not be 'admin'!"
266
"Username must only contain numbers, letters and dots, and may not be 'admin'!"
268
msgstr ""
267
msgstr ""
269
"Der Wert darf nur Zahlen, Buchstaben und Punkte enthalten. Ausnahme ist die "
268
"Der Wert darf nur Zahlen, Buchstaben und Punkte enthalten. Ausnahme ist die "
270
"Bezeichnug 'admin', die auch nicht verwendet werden darf"
269
"Bezeichnug 'admin', die auch nicht verwendet werden darf"
271
270
272
#: syntax.py:363
271
#: syntax.py:373
273
msgid "Only the first letter of the username may be uppercase!"
272
msgid "Only the first letter of the username may be uppercase!"
274
msgstr "Nur der erste Buchstabe des Benutzernames darf groß geschrieben sein!"
273
msgstr "Nur der erste Buchstabe des Benutzernames darf groß geschrieben sein!"
275
274
276
#: syntax.py:388
275
#: syntax.py:398
277
msgid ", a path must begin with \"/\"!"
276
msgid ", a path must begin with \"/\"!"
278
msgstr ", eine Pfadangabe muss mit \\\"/\\\" beginnen."
277
msgstr ", eine Pfadangabe muss mit \\\"/\\\" beginnen."
279
278
280
#: syntax.py:392
279
#: syntax.py:402
281
msgid "Value may not contain double quotes (\")!"
280
msgid "Value may not contain double quotes (\")!"
282
msgstr "Der Wert darf kein Anführungszeichen (\") enthalten!"
281
msgstr "Der Wert darf kein Anführungszeichen (\") enthalten!"
283
282
284
#: syntax.py:406
283
#: syntax.py:416
285
msgid "The password is to short, at least 8 characters needed."
284
msgid "The password is to short, at least 8 characters needed."
286
msgstr "Das Passwort ist zu kurz, mindestens 8 Zeichen sind erforderlich."
285
msgstr "Das Passwort ist zu kurz, mindestens 8 Zeichen sind erforderlich."
287
286
288
#: syntax.py:414
287
#: syntax.py:424
289
msgid "Empty password not allowed!"
288
msgid "Empty password not allowed!"
290
msgstr "Ein leeres Passwort ist nicht erlaubt!"
289
msgstr "Ein leeres Passwort ist nicht erlaubt!"
291
290
292
#: syntax.py:427
291
#: syntax.py:437
293
msgid "Not a valid hostname!"
292
msgid "Not a valid hostname!"
294
msgstr "Kein gültiger Hostname"
293
msgstr "Kein gültiger Hostname"
295
294
296
#: syntax.py:441
295
#: syntax.py:451
297
msgid "Not a valid windows hostname!"
296
msgid "Not a valid windows hostname!"
298
msgstr "Kein gültiger Windows-Hostname"
297
msgstr "Kein gültiger Windows-Hostname"
299
298
300
#: syntax.py:453 syntax.py:456
299
#: syntax.py:463
301
msgid "Not a valid IP address!"
300
msgid "Not a valid IP address!"
302
msgstr "Keine gültige IP-Adresse"
301
msgstr "Keine gültige IP-Adresse"
303
302
304
#: syntax.py:484
303
#: syntax.py:491
305
msgid "Not a valid hostname or IP address!"
304
msgid "Not a valid hostname or IP address!"
306
msgstr "Kein gültiger Hostname oder IP-Adresse"
305
msgstr "Kein gültiger Hostname oder IP-Adresse"
307
306
308
#: syntax.py:527
307
#: syntax.py:534
309
msgid "Not a valid netmask!"
308
msgid "Not a valid netmask!"
310
msgstr "Keine gültige Netzwerkmaske."
309
msgstr "Keine gültige Netzwerkmaske."
311
310
312
#: syntax.py:531
311
#: syntax.py:538
313
msgid "First Address"
312
msgid "First Address"
314
msgstr "Erste Adresse"
313
msgstr "Erste Adresse"
315
314
316
#: syntax.py:531
315
#: syntax.py:538
317
msgid "Last Address"
316
msgid "Last Address"
318
msgstr "Letzte Adresse"
317
msgstr "Letzte Adresse"
319
318
320
#: syntax.py:542
319
#: syntax.py:549
321
msgid "tcp"
320
msgid "tcp"
322
msgstr ""
321
msgstr ""
323
322
324
#: syntax.py:542
323
#: syntax.py:549
325
msgid "udp"
324
msgid "udp"
326
msgstr ""
325
msgstr ""
327
326
328
#: syntax.py:554
327
#: syntax.py:561
329
msgid "Not an absolute path!"
328
msgid "Not an absolute path!"
330
msgstr "Keine absolute Pfadangabe"
329
msgstr "Keine absolute Pfadangabe"
331
330
332
#: syntax.py:565 syntax.py:576
331
#: syntax.py:572 syntax.py:583
333
msgid "Not a valid email address!"
332
msgid "Not a valid email address!"
334
msgstr "Keine gültige E-Mail-Adresse"
333
msgstr "Keine gültige E-Mail-Adresse"
335
334
336
#: syntax.py:588
335
#: syntax.py:595
337
msgid ""
336
msgid ""
338
"The given date does not confirm iso8601, example: \"2009-01-01T12:00:00+01:00"
337
"The given date does not confirm iso8601, example: \"2009-01-01T12:00:00+01:00"
339
"\"."
338
"\"."
340
msgstr ""
339
msgstr ""
341
340
342
#: syntax.py:606
341
#: syntax.py:613
343
msgid "Not a valid Date"
342
msgid "Not a valid Date"
344
msgstr "Kein gültiges Datum"
343
msgstr "Kein gültiges Datum"
345
344
346
#: syntax.py:620
345
#: syntax.py:625
347
msgid ""
346
msgid ""
348
"An IP subnet consists of one to three numbers ranging from 0 to 255 "
347
"An IPv4 subnet consists of one to three numbers ranging from 0 to 255 "
349
"separated by dots."
348
"separated by dots, an IPv6 subnet consists of one to four groups of one to "
350
msgstr ""
349
"four hexadecimal digits separated by colons (:)."
351
"Ein IP-Subnetz muss mit ein bis drei Zahlen zwischen 0 und 255 angegeben "
350
msgstr "Ein IPv4-Subnetz muss mit ein bis drei Zahlen zwischen 0 und 255 angegeben werden, die mit einem Punkt getrennt werden, ein IPv6-Subnetz muss mit ein bis vier Gruppen aus ein bis vier hexadezimalen Zeichen angegeben werden, die mit einem Doppelpunkt getrennt werden."
352
"werden, die mit einem Punkt getrennt werden."
353
351
354
#: syntax.py:635
352
#: syntax.py:637
355
msgid ""
353
msgid ""
356
"The name of a reverse zone consists of the reversed subnet address followed "
354
"The name of a reverse zone for IPv4 consists of the reversed subnet address "
357
"by .in-addr.arpa. Example: \"0.168.192.in-addr.arpa\""
355
"followed by .in-addr.arpa (example: \"0.168.192.in-addr.arpa\") or for IPv6 "
358
msgstr ""
356
"in nibble format followed by .ip6.arpa (example: \"0.0.0.0.0.0.1.0.8.b."
359
"Der Name einer Reverse Lookup Zone besteht aus dem inversen Subnetz, gefolgt "
357
"d.0.1.0.0.2.ip6.arpa\")"
360
"von .in-addr.arpa. z.B.: \"0.168.192.in-addr.arpa\""
358
msgstr "Der Name einer IPv4 Reverse Lookup Zone besteht aus dem inversen Subnetz, gefolgt von .in-addr.arpa (z.B.: \"0.168.192.in-addr.arpa\") oder für IPv6 im Nibble Format, gefolgt von .ip6.arpa (z.B. \"0.0.0.0.0.0.1.0.8.b.d.0.1.0.0.2.ip6.arpa\")."
361
359
362
#: syntax.py:643
360
#: syntax.py:645
363
msgid "Missing value!"
361
msgid "Missing value!"
364
msgstr "Fehlender Wert!"
362
msgstr "Fehlender Wert!"
365
363
366
#: syntax.py:671
364
#: syntax.py:648 syntax.py:657 syntax.py:667
365
msgid "Value may not contain other than numbers, letters, dots and colons!"
366
msgstr "Der Wert darf nur Zahlen, Buchstaben, Leerzeichen, Punkte und Doppelpunkte enthalten."
367
368
#: syntax.py:673
367
msgid "Key"
369
msgid "Key"
368
msgstr ""
370
msgstr ""
369
371
370
#: syntax.py:671
372
#: syntax.py:673
371
msgid "Value"
373
msgid "Value"
372
msgstr ""
374
msgstr ""
373
375
374
#: syntax.py:676 syntax.py:686
376
#: syntax.py:678 syntax.py:694
375
msgid "Priority"
377
msgid "Priority"
376
msgstr "Priorität"
378
msgstr "Priorität"
377
379
378
#: syntax.py:676
380
#: syntax.py:678
379
msgid "Mail Server"
381
msgid "Mail Server"
380
msgstr "Mail-Server"
382
msgstr "Mail-Server"
381
383
382
#: syntax.py:681
384
#: syntax.py:683
383
msgid "Service"
385
msgid "Service"
384
msgstr "Dienst"
386
msgstr "Dienst"
385
387
386
#: syntax.py:681
388
#: syntax.py:683
387
msgid "Protocol"
389
msgid "Protocol"
388
msgstr "Protokoll"
390
msgstr "Protokoll"
389
391
390
#: syntax.py:686
392
#: syntax.py:689
393
msgid "Street"
394
msgstr "Straße"
395
396
#: syntax.py:689
397
msgid "Postal code"
398
msgstr "Postleitzahl"
399
400
#: syntax.py:689
401
msgid "City"
402
msgstr "Stadt"
403
404
#: syntax.py:694
391
msgid "Weight"
405
msgid "Weight"
392
msgstr "Gewichtung"
406
msgstr "Gewichtung"
393
407
394
#: syntax.py:686
408
#: syntax.py:694
395
msgid "Port"
409
msgid "Port"
396
msgstr "Port"
410
msgstr "Port"
397
411
398
#: syntax.py:686
412
#: syntax.py:694
399
msgid "Server"
413
msgid "Server"
400
msgstr "Server"
414
msgstr "Server"
401
415
402
#: syntax.py:696
416
#: syntax.py:704
403
msgid "Not a valid time format"
417
msgid "Not a valid time format"
404
msgstr "Keine gültige Zeitangabe"
418
msgstr "Keine gültige Zeitangabe"
405
419
406
#: syntax.py:696
420
#: syntax.py:717
407
msgid "Street"
408
msgstr "Straße"
409
410
#: syntax.py:696
411
msgid "Postal code"
412
msgstr "Postleitzahl"
413
414
#: syntax.py:696
415
msgid "City"
416
msgstr "Stadt"
417
418
#: syntax.py:709
419
msgid "Not a valid time interval"
421
msgid "Not a valid time interval"
420
msgstr "Kein gültiges Zeitintervall"
422
msgstr "Kein gültiges Zeitintervall"
421
423
422
#: syntax.py:715
424
#: syntax.py:723
423
msgid "Ethernet"
425
msgid "Ethernet"
424
msgstr "Ethernet"
426
msgstr "Ethernet"
425
427
426
#: syntax.py:715
428
#: syntax.py:723
427
msgid "FDDI"
429
msgid "FDDI"
428
msgstr "FDDI"
430
msgstr "FDDI"
429
431
430
#: syntax.py:715
432
#: syntax.py:723
431
msgid "Token-Ring"
433
msgid "Token-Ring"
432
msgstr "Token-Ring"
434
msgstr "Token-Ring"
433
435
434
#: syntax.py:724 syntax.py:740
436
#: syntax.py:732 syntax.py:748
435
msgid ""
437
msgid ""
436
"Value must have 6 two digit hexadecimal numbers separated by \"-\" or \":\" !"
438
"Value must have 6 two digit hexadecimal numbers separated by \"-\" or \":\" !"
437
msgstr ""
439
msgstr ""
438
"Der Wert muss 6 mal 2 Hexadezimalwerte beinhalten, die mit einem \"-\" oder "
440
"Der Wert muss 6 mal 2 Hexadezimalwerte beinhalten, die mit einem \"-\" oder "
439
"\":\"getrennt werden"
441
"\":\"getrennt werden"
440
442
441
#: syntax.py:744
443
#: syntax.py:752
442
msgid "Type"
444
msgid "Type"
443
msgstr "Typ"
445
msgstr "Typ"
444
446
445
#: syntax.py:744
447
#: syntax.py:752
446
msgid "Address"
448
msgid "Address"
447
msgstr "Adresse"
449
msgstr "Adresse"
448
450
449
#: syntax.py:757
451
#: syntax.py:765
450
msgid ""
452
msgid ""
451
"Value may not contain other than numbers, letters, underscore (\"_\") and "
453
"Value may not contain other than numbers, letters, underscore (\"_\") and "
452
"minus (\"-\")!"
454
"minus (\"-\")!"
 Lines 454-488    Link Here 
454
"Der Wert darf nur Zahlen, Buchstaben, Unterstriche (\"_\") und Minuszeichen "
456
"Der Wert darf nur Zahlen, Buchstaben, Unterstriche (\"_\") und Minuszeichen "
455
"(\"-\") enthalten."
457
"(\"-\") enthalten."
456
458
457
#: syntax.py:761
459
#: syntax.py:769
458
msgid "Driver"
460
msgid "Driver"
459
msgstr "Treiber"
461
msgstr "Treiber"
460
462
461
#: syntax.py:761
463
#: syntax.py:769
462
msgid "Description"
464
msgid "Description"
463
msgstr "Beschreibung"
465
msgstr "Beschreibung"
464
466
465
#: syntax.py:785 syntax.py:850
467
#: syntax.py:793 syntax.py:858
466
msgid "Not a valid LDAP DN"
468
msgid "Not a valid LDAP DN"
467
msgstr "Kein gültiger LDAP-DN"
469
msgstr "Kein gültiger LDAP-DN"
468
470
469
#: syntax.py:816
471
#: syntax.py:824
470
msgid "Invitation Policy"
472
msgid "Invitation Policy"
471
msgstr "Richtlinie für Einladungen"
473
msgstr "Richtlinie für Einladungen"
472
474
473
#: syntax.py:823
475
#: syntax.py:831
474
msgid "Shared folder user ACL"
476
msgid "Shared folder user ACL"
475
msgstr "Benutzer ACLs für gemeinsame Ordner"
477
msgstr "Benutzer ACLs für gemeinsame Ordner"
476
478
477
#: syntax.py:828 syntax.py:839
479
#: syntax.py:836 syntax.py:847
478
msgid "Not a valid shared folder ACL"
480
msgid "Not a valid shared folder ACL"
479
msgstr "Keine gültige ACL für gemeinsame Ordner"
481
msgstr "Keine gültige ACL für gemeinsame Ordner"
480
482
481
#: syntax.py:834
483
#: syntax.py:842
482
msgid "Shared folder group ACL"
484
msgid "Shared folder group ACL"
483
msgstr "Gruppen ACLs für gemeinsame Ordner"
485
msgstr "Gruppen ACLs für gemeinsame Ordner"
484
486
485
#: syntax.py:871
487
#: syntax.py:879
486
msgid ""
488
msgid ""
487
"Value consists of two integer numbers separated by an \"x\" (e.g. \"1024x768"
489
"Value consists of two integer numbers separated by an \"x\" (e.g. \"1024x768"
488
"\")"
490
"\")"
 Lines 490-801    Link Here 
490
"Der Wert muss zwei ganzzahlige Werte mit einem \"x\" dazwischen beinhalten "
492
"Der Wert muss zwei ganzzahlige Werte mit einem \"x\" dazwischen beinhalten "
491
"(z.B. \"1024x768\")"
493
"(z.B. \"1024x768\")"
492
494
493
#: syntax.py:880
495
#: syntax.py:888
494
msgid ""
496
msgid ""
495
"Value consists of two integer numbers separated by a \"-\" (e.g. \"30-70\")"
497
"Value consists of two integer numbers separated by a \"-\" (e.g. \"30-70\")"
496
msgstr ""
498
msgstr ""
497
"Der Wert muss aus zwei durch ein \"-\" getrennte ganzzahlige Werte bestehen "
499
"Der Wert muss aus zwei durch ein \"-\" getrennte ganzzahlige Werte bestehen "
498
"(z.B. \"30-70\")"
500
"(z.B. \"30-70\")"
499
501
500
#: syntax.py:1116
502
#: syntax.py:1203
501
msgid "User ID"
503
msgid "User ID"
502
msgstr "Benutzer-ID"
504
msgstr "Benutzer-ID"
503
505
504
#: syntax.py:1121
506
#: syntax.py:1208
505
msgid "Group ID"
507
msgid "Group ID"
506
msgstr "Gruppen-ID"
508
msgstr "Gruppen-ID"
507
509
508
#: syntax.py:1129
510
#: syntax.py:1216
509
msgid "Windows Terminal Server Hosts"
511
msgid "Windows Terminal Server Hosts"
510
msgstr "Windows Terminalserver"
512
msgstr "Windows Terminalserver"
511
513
512
#: syntax.py:1134
514
#: syntax.py:1221
513
msgid "Linux Terminal Server Hosts"
515
msgid "Linux Terminal Server Hosts"
514
msgstr "Linux Terminalserver"
516
msgstr "Linux Terminalserver"
515
517
516
#: syntax.py:1139
518
#: syntax.py:1226
517
msgid "Authentication Server"
519
msgid "Authentication Server"
518
msgstr "Authentisierungsserver"
520
msgstr "Authentisierungsserver"
519
521
520
#: syntax.py:1144
522
#: syntax.py:1231
521
msgid "File Server"
523
msgid "File Server"
522
msgstr "Fileserver"
524
msgstr "Fileserver"
523
525
524
#: syntax.py:1161 syntax.py:1166
526
#: syntax.py:1248 syntax.py:1253
525
msgid "Primary Group"
527
msgid "Primary Group"
526
msgstr "Primäre Gruppe"
528
msgstr "Primäre Gruppe"
527
529
528
#: syntax.py:1171
530
#: syntax.py:1258
529
msgid "Network"
531
msgid "Network"
530
msgstr "Netzwerk"
532
msgstr "Netzwerk"
531
533
532
#: syntax.py:1177 syntax.py:1192
534
#: syntax.py:1264 syntax.py:1279
533
msgid "DNS Entry"
535
msgid "DNS Entry"
534
msgstr "DNS-Eintrag"
536
msgstr "DNS-Eintrag"
535
537
536
#: syntax.py:1182 syntax.py:1197
538
#: syntax.py:1269 syntax.py:1284
537
msgid "DNS Entry Reverse"
539
msgid "DNS Entry Reverse"
538
msgstr "Reverse Lookup DNS-Eintrag"
540
msgstr "Reverse Lookup DNS-Eintrag"
539
541
540
#: syntax.py:1187 syntax.py:1202
542
#: syntax.py:1274 syntax.py:1289
541
msgid "DHCP Entry"
543
msgid "DHCP Entry"
542
msgstr "DHCP-Eintrag"
544
msgstr "DHCP-Eintrag"
543
545
544
#: syntax.py:1207
546
#: syntax.py:1294
545
msgid "DNS Entry Alias"
547
msgid "DNS Entry Alias"
546
msgstr "Alias DNS-Eintrag"
548
msgstr "Alias DNS-Eintrag"
547
549
548
#: syntax.py:1199
550
#: syntax.py:1305
549
#, python-format
551
#, python-format
550
msgid "Entry does not have dnsEntryAlias Syntax: %s"
552
msgid "Entry does not have dnsEntryAlias Syntax: %s"
551
msgstr "Eintrag hat nicht dnsEntryAlias Syntax: %s"
553
msgstr "Eintrag hat nicht dnsEntryAlias Syntax: %s"
552
554
553
#: syntax.py:1204
555
#: syntax.py:1310
554
msgid "Share"
556
msgid "Share"
555
msgstr "Freigabe"
557
msgstr "Freigabe"
556
558
557
#: syntax.py:1599 syntax.py:1618 syntax.py:1632 syntax.py:1671 syntax.py:1760
559
#: syntax.py:1702 syntax.py:1721 syntax.py:1735 syntax.py:1774 syntax.py:1863
558
msgid "all"
560
msgid "all"
559
msgstr "Alle"
561
msgstr "Alle"
560
562
561
#: syntax.py:1600
563
#: syntax.py:1703
562
msgid "January"
564
msgid "January"
563
msgstr "Januar"
565
msgstr "Januar"
564
566
565
#: syntax.py:1601
567
#: syntax.py:1704
566
msgid "February"
568
msgid "February"
567
msgstr "Februar"
569
msgstr "Februar"
568
570
569
#: syntax.py:1602
571
#: syntax.py:1705
570
msgid "March"
572
msgid "March"
571
msgstr "März"
573
msgstr "März"
572
574
573
#: syntax.py:1603
575
#: syntax.py:1706
574
msgid "April"
576
msgid "April"
575
msgstr "April"
577
msgstr "April"
576
578
577
#: syntax.py:1604
579
#: syntax.py:1707
578
msgid "May"
580
msgid "May"
579
msgstr "Mai"
581
msgstr "Mai"
580
582
581
#: syntax.py:1605
583
#: syntax.py:1708
582
msgid "June"
584
msgid "June"
583
msgstr "Juni"
585
msgstr "Juni"
584
586
585
#: syntax.py:1606
587
#: syntax.py:1709
586
msgid "July"
588
msgid "July"
587
msgstr "Juli"
589
msgstr "Juli"
588
590
589
#: syntax.py:1607
591
#: syntax.py:1710
590
msgid "August"
592
msgid "August"
591
msgstr "August"
593
msgstr "August"
592
594
593
#: syntax.py:1608
595
#: syntax.py:1711
594
msgid "September"
596
msgid "September"
595
msgstr "September"
597
msgstr "September"
596
598
597
#: syntax.py:1609
599
#: syntax.py:1712
598
msgid "October"
600
msgid "October"
599
msgstr "Oktober"
601
msgstr "Oktober"
600
602
601
#: syntax.py:1610
603
#: syntax.py:1713
602
msgid "November"
604
msgid "November"
603
msgstr "November"
605
msgstr "November"
604
606
605
#: syntax.py:1611
607
#: syntax.py:1714
606
msgid "December"
608
msgid "December"
607
msgstr "Dezember"
609
msgstr "Dezember"
608
610
609
#: syntax.py:1619
611
#: syntax.py:1722
610
msgid "Monday"
612
msgid "Monday"
611
msgstr "Montag"
613
msgstr "Montag"
612
614
613
#: syntax.py:1620
615
#: syntax.py:1723
614
msgid "Tuesday"
616
msgid "Tuesday"
615
msgstr "Dienstag"
617
msgstr "Dienstag"
616
618
617
#: syntax.py:1621
619
#: syntax.py:1724
618
msgid "Wednesday"
620
msgid "Wednesday"
619
msgstr "Mittwoch"
621
msgstr "Mittwoch"
620
622
621
#: syntax.py:1622
623
#: syntax.py:1725
622
msgid "Thursday"
624
msgid "Thursday"
623
msgstr "Donnerstag"
625
msgstr "Donnerstag"
624
626
625
#: syntax.py:1623
627
#: syntax.py:1726
626
msgid "Friday"
628
msgid "Friday"
627
msgstr "Freitag"
629
msgstr "Freitag"
628
630
629
#: syntax.py:1624
631
#: syntax.py:1727
630
msgid "Saturday"
632
msgid "Saturday"
631
msgstr "Samstag"
633
msgstr "Samstag"
632
634
633
#: syntax.py:1625
635
#: syntax.py:1728
634
msgid "Sunday"
636
msgid "Sunday"
635
msgstr "Sonntag"
637
msgstr "Sonntag"
636
638
637
#: syntax.py:1820
639
#: syntax.py:1923
638
msgid "Domain Group"
640
msgid "Domain Group"
639
msgstr "Globale Gruppe"
641
msgstr "Globale Gruppe"
640
642
641
#: syntax.py:1821
643
#: syntax.py:1924
642
msgid "Local Group"
644
msgid "Local Group"
643
msgstr "Lokale Gruppe"
645
msgstr "Lokale Gruppe"
644
646
645
#: syntax.py:1822
647
#: syntax.py:1925
646
msgid "Well-Known Group"
648
msgid "Well-Known Group"
647
msgstr "Bekannte Gruppe"
649
msgstr "Bekannte Gruppe"
648
650
649
#: syntax.py:1831 syntax.py:1838 syntax.py:1845
651
#: syntax.py:1934 syntax.py:1941 syntax.py:1948
650
msgid "Soft limit"
652
msgid "Soft limit"
651
msgstr "Soft-Limit"
653
msgstr "Soft-Limit"
652
654
653
#: syntax.py:1831 syntax.py:1838 syntax.py:1845
655
#: syntax.py:1934 syntax.py:1941 syntax.py:1948
654
msgid "Hard limit"
656
msgid "Hard limit"
655
msgstr "Hard-Limit"
657
msgstr "Hard-Limit"
656
658
657
#: syntax.py:1831 syntax.py:1845
659
#: syntax.py:1934 syntax.py:1948
658
msgid "Group"
660
msgid "Group"
659
msgstr "Gruppe"
661
msgstr "Gruppe"
660
662
661
#: syntax.py:1838
663
#: syntax.py:1941
662
msgid "User"
664
msgid "User"
663
msgstr "Benutzer"
665
msgstr "Benutzer"
664
666
665
#: syntax.py:1861
667
#: syntax.py:1964
666
msgid "synchronous"
668
msgid "synchronous"
667
msgstr "synchron"
669
msgstr "synchron"
668
670
669
#: syntax.py:1862
671
#: syntax.py:1965
670
msgid "asynchronous"
672
msgid "asynchronous"
671
msgstr "asynchron"
673
msgstr "asynchron"
672
674
673
#: syntax.py:1873
675
#: syntax.py:1976
674
#, python-format
676
#, python-format
675
msgid "\"%s\" is not a Univention Admin Module."
677
msgid "\"%s\" is not a Univention Admin Module."
676
msgstr "\"%s\" ist kein Univention Admin Modul"
678
msgstr "\"%s\" ist kein Univention Admin Modul"
677
679
678
#: syntax.py:1911
680
#: syntax.py:2014
679
msgid "None"
681
msgid "None"
680
msgstr "Keine"
682
msgstr "Keine"
681
683
682
#: syntax.py:1916
684
#: syntax.py:2019
683
msgid "About"
685
msgid "About"
684
msgstr "Über"
686
msgstr "Über"
685
687
686
#: syntax.py:1916
688
#: syntax.py:2019
687
msgid "Browse"
689
msgid "Browse"
688
msgstr "Navigation"
690
msgstr "Navigation"
689
691
690
#: syntax.py:1916
692
#: syntax.py:2019
691
msgid "Wizards"
693
msgid "Wizards"
692
msgstr "Assistenten"
694
msgstr "Assistenten"
693
695
694
#: syntax.py:1916
696
#: syntax.py:2019
695
msgid "Personal Settings"
697
msgid "Personal Settings"
696
msgstr "Persönliche Einstellungen"
698
msgstr "Persönliche Einstellungen"
697
699
698
#: syntax.py:1930
700
#: syntax.py:2033
699
msgid "No Reboot"
701
msgid "No Reboot"
700
msgstr "Nicht neu starten"
702
msgstr "Nicht neu starten"
701
703
702
#: syntax.py:1931
704
#: syntax.py:2034
703
msgid "Immediately"
705
msgid "Immediately"
704
msgstr "Sofort"
706
msgstr "Sofort"
705
707
706
#: syntax.py:1937
708
#: syntax.py:2040
707
msgid "Groupware Account"
709
msgid "Groupware Account"
708
msgstr "Groupware Konto"
710
msgstr "Groupware Konto"
709
711
710
#: syntax.py:1938
712
#: syntax.py:2041
711
msgid "Kerberos Principal"
713
msgid "Kerberos Principal"
712
msgstr "Kerberos Prinzipal"
714
msgstr "Kerberos Prinzipal"
713
715
714
#: syntax.py:1939
716
#: syntax.py:2042
715
msgid "Personal Information"
717
msgid "Personal Information"
716
msgstr "Persönliche Information"
718
msgstr "Persönliche Information"
717
719
718
#: syntax.py:1940
720
#: syntax.py:2043
719
msgid "Samba Account"
721
msgid "Samba Account"
720
msgstr "Samba Konto"
722
msgstr "Samba Konto"
721
723
722
#: syntax.py:1941
724
#: syntax.py:2044
723
msgid "Posix Account"
725
msgid "Posix Account"
724
msgstr "Posix Konto"
726
msgstr "Posix Konto"
725
727
726
#: syntax.py:1942
728
#: syntax.py:2045
727
msgid "Mail Account"
729
msgid "Mail Account"
728
msgstr "Mail Konto"
730
msgstr "Mail Konto"
729
731
730
#: syntax.py:1950
732
#: syntax.py:2053
731
msgid "Disconnect"
733
msgid "Disconnect"
732
msgstr "Trennen"
734
msgstr "Trennen"
733
735
734
#: syntax.py:1951
736
#: syntax.py:2054
735
msgid "Reset"
737
msgid "Reset"
736
msgstr "Zurücksetzen"
738
msgstr "Zurücksetzen"
737
739
738
#: syntax.py:1959
740
#: syntax.py:2062
739
msgid "All Clients"
741
msgid "All Clients"
740
msgstr "Von jedem Client"
742
msgstr "Von jedem Client"
741
743
742
#: syntax.py:1960
744
#: syntax.py:2063
743
msgid "Previously used Client"
745
msgid "Previously used Client"
744
msgstr "Nur von vorherigem Client"
746
msgstr "Nur von vorherigem Client"
745
747
746
#: syntax.py:1968 syntax.py:1979
748
#: syntax.py:2071 syntax.py:2082
747
msgid "Disabled"
749
msgid "Disabled"
748
msgstr "Deaktiviert"
750
msgstr "Deaktiviert"
749
751
750
#: syntax.py:1969
752
#: syntax.py:2072
751
msgid "Enabled: Input: on, Message: on"
753
msgid "Enabled: Input: on, Message: on"
752
msgstr "Aktiviert: Eingabe: ein, Benachrichtigen: ein"
754
msgstr "Aktiviert: Eingabe: ein, Benachrichtigen: ein"
753
755
754
#: syntax.py:1970
756
#: syntax.py:2073
755
msgid "Enabled: Input: on, Message: off"
757
msgid "Enabled: Input: on, Message: off"
756
msgstr "Aktiviert: Eingabe: an, Benachrichtigen: aus"
758
msgstr "Aktiviert: Eingabe: an, Benachrichtigen: aus"
757
759
758
#: syntax.py:1971
760
#: syntax.py:2074
759
msgid "Enabled: Input: off, Message: on"
761
msgid "Enabled: Input: off, Message: on"
760
msgstr "Aktiviert: Eingabe: aus, Benachrichtigen: an"
762
msgstr "Aktiviert: Eingabe: aus, Benachrichtigen: an"
761
763
762
#: syntax.py:1972
764
#: syntax.py:2075
763
msgid "Enabled: Input: off, Message: off"
765
msgid "Enabled: Input: off, Message: off"
764
msgstr "Aktiviert: Eingabe: aus, Benachrichtigen: aus"
766
msgstr "Aktiviert: Eingabe: aus, Benachrichtigen: aus"
765
767
766
#: syntax.py:1980
768
#: syntax.py:2083
767
msgid "Enabled: Set by Caller"
769
msgid "Enabled: Set by Caller"
768
msgstr ""
770
msgstr ""
769
771
770
#: syntax.py:1981
772
#: syntax.py:2084
771
msgid "Enabled: No Call Back"
773
msgid "Enabled: No Call Back"
772
msgstr ""
774
msgstr ""
773
775
774
#: syntax.py:2064
776
#: syntax.py:2172
775
msgid "NFS-Share"
777
msgid "NFS-Share"
776
msgstr "NFS-Freigabe"
778
msgstr "NFS-Freigabe"
777
779
778
#: syntax.py:2077
780
#: syntax.py:2185
779
msgid "Language code must be in format \"xx_XX\"!"
781
msgid "Language code must be in format \"xx_XX\"!"
780
msgstr "Sprach-Code muss im Format \"xx_XX\" angegeben werden!"
782
msgstr "Sprach-Code muss im Format \"xx_XX\" angegeben werden!"
781
783
782
#: syntax.py:2083 syntax.py:2087 syntax.py:2090 syntax.py:2093
784
#: syntax.py:2191 syntax.py:2195 syntax.py:2198 syntax.py:2201
783
msgid "Language code (e.g. en_US)"
785
msgid "Language code (e.g. en_US)"
784
msgstr "Sprachcode (z.B. de_DE)"
786
msgstr "Sprachcode (z.B. de_DE)"
785
787
786
#: syntax.py:2083
788
#: syntax.py:2191
787
msgid "Text"
789
msgid "Text"
788
msgstr "Text"
790
msgstr "Text"
789
791
790
#: syntax.py:2087
792
#: syntax.py:2195
791
msgid "Translated short description"
793
msgid "Translated short description"
792
msgstr "Übersetzte Kurzbeschreibung"
794
msgstr "Übersetzte Kurzbeschreibung"
793
795
794
#: syntax.py:2090
796
#: syntax.py:2198
795
msgid "Translated long description"
797
msgid "Translated long description"
796
msgstr "Übersetzte Langbeschreibung"
798
msgstr "Übersetzte Langbeschreibung"
797
799
798
#: syntax.py:2093
800
#: syntax.py:2201
799
msgid "Translated tab name"
801
msgid "Translated tab name"
800
msgstr "Übersetzter Karteikartenname"
802
msgstr "Übersetzter Karteikartenname"
801
803
 Lines 880-887    Link Here 
880
"The DNS alias entry for this host should contain the zone name, the alias "
882
"The DNS alias entry for this host should contain the zone name, the alias "
881
"zone container DN and the alias."
883
"zone container DN and the alias."
882
msgstr ""
884
msgstr ""
883
"Der DNS-Alias Eintrag für diesen Rechner sollte den Zonennamen, die LDAP-DN des Alias-Zonencontainers und "
885
"Der DNS-Alias Eintrag für diesen Rechner sollte den Zonennamen, die LDAP-DN "
884
"den Alias-Namen enthalten."
886
"des Alias-Zonencontainers und den Alias-Namen enthalten."
885
887
886
#: uexceptions.py:102
888
#: uexceptions.py:102
887
msgid "Next IP address not found."
889
msgid "Next IP address not found."
 Lines 1075-1081    Link Here 
1075
"Zum Zuweisen von Nagios-Diensten wird ein Eintrag in der DNS Forward Zone "
1077
"Zum Zuweisen von Nagios-Diensten wird ein Eintrag in der DNS Forward Zone "
1076
"benötigt!"
1078
"benötigt!"
1077
1079
1078
#: uexceptions.py:228
1080
#: uexceptions.py:234
1079
msgid ""
1081
msgid ""
1080
"The DNS forward entry could not be created. Please remove existing alias "
1082
"The DNS forward entry could not be created. Please remove existing alias "
1081
"records or comparable DNS objects with the same name as this host from the "
1083
"records or comparable DNS objects with the same name as this host from the "
 Lines 1085-1091    Link Here 
1085
"DNS-Alias Records oder vergleichbare DNS-Objekte mit dem Namen dieses "
1087
"DNS-Alias Records oder vergleichbare DNS-Objekte mit dem Namen dieses "
1086
"Rechners aus der DNS-Forward-Zone entfernt werden."
1088
"Rechners aus der DNS-Forward-Zone entfernt werden."
1087
1089
1088
#: uexceptions.py:231
1090
#: uexceptions.py:237
1089
msgid "Circular group dependency detected: "
1091
msgid "Circular group dependency detected: "
1090
msgstr "Zyklische Gruppen-Abhängigkeit festgestellt: "
1092
msgstr "Zyklische Gruppen-Abhängigkeit festgestellt: "
1091
1093
 Lines 1102-1108    Link Here 
1102
msgid "Authentication failed"
1104
msgid "Authentication failed"
1103
msgstr "Authentisierung fehlgeschlagen"
1105
msgstr "Authentisierung fehlgeschlagen"
1104
1106
1105
#: uldap.py:357
1107
#: uldap.py:361
1106
msgid "Moving childs is not supported."
1108
msgid "Moving childs is not supported."
1107
msgstr "Das Verschieben von Kindsknoten wird nicht unterstützt."
1109
msgstr "Das Verschieben von Kindsknoten wird nicht unterstützt."
1108
1110
(-)modules/univention/admin/syntax.py (-37 / +30 lines)
 Lines 29-34    Link Here 
29
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
29
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
30
30
31
import re, string, types, math, time, operator
31
import re, string, types, math, time, operator
32
import ipaddr # IPv6 address handling
32
import univention.debug
33
import univention.debug
33
import univention.admin.modules
34
import univention.admin.modules
34
import univention.admin.uexceptions
35
import univention.admin.uexceptions
 Lines 451-468    Link Here 
451
452
452
class ipAddress(simple):
453
class ipAddress(simple):
453
	name='ipAddress'
454
	name='ipAddress'
454
	min_length=7
455
	min_length=2
455
	max_length=15
456
	max_length=39
456
	_re = re.compile('^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$')
457
	# match IPv4 (0.0.0.0 is allowed) or IPv6 address (with IPv4-mapped IPv6)
457
458
	def parse(self, text):
458
	def parse(self, text):
459
		if text and self._re.match(text) != None:
459
		if text != None:
460
			for q in text.split('.'):
460
			try:
461
				if int(q) > 255:
461
				ipaddr.IPAddress(text)
462
					raise univention.admin.uexceptions.valueError, _("Not a valid IP address!")
462
			except ValueError:
463
					return
463
				raise univention.admin.uexceptions.valueError, _("Not a valid IP address!")
464
			return text
464
			return text
465
		raise univention.admin.uexceptions.valueError, _("Not a valid IP address!")
466
465
467
class hostOrIP(simple):
466
class hostOrIP(simple):
468
	name='host'
467
	name='host'
 Lines 470-483    Link Here 
470
	max_length=0
469
	max_length=0
471
470
472
	def ipAddress(self, text):
471
	def ipAddress(self, text):
473
		_re = re.compile('(^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$)')
472
		# match IPv4 (0.0.0.0 is allowed) or IPv6 address (incl. IPv4-mapped IPv6)
474
		if text and _re.match(text) != None:
473
		if text != None:
475
			for q in text.split('.'):
474
			try:
476
				if int(q) > 255:
475
				ipaddr.IPAddress(text)
477
					return False
476
			except ValueError:
477
				return False
478
			return True
478
			return True
479
		else:
480
			return False
481
479
482
	def hostName(self, text):
480
	def hostName(self, text):
483
		_re = re.compile("(^[a-zA-Z])(([a-zA-Z0-9-]*)([a-zA-Z0-9]$))?$")
481
		_re = re.compile("(^[a-zA-Z])(([a-zA-Z0-9-]*)([a-zA-Z0-9]$))?$")
 Lines 491-497    Link Here 
491
			return text
489
			return text
492
		else:
490
		else:
493
			raise univention.admin.uexceptions.valueError, _('Not a valid hostname or IP address!')
491
			raise univention.admin.uexceptions.valueError, _('Not a valid hostname or IP address!')
494
492
# TODO: IPv6
495
class netmask(simple):
493
class netmask(simple):
496
	name='netmask'
494
	name='netmask'
497
	min_length=1
495
	min_length=1
 Lines 617-677    Link Here 
617
class reverseLookupSubnet(simple):
615
class reverseLookupSubnet(simple):
618
	name='reverseLookupSubnet'
616
	name='reverseLookupSubnet'
619
	min_length=1
617
	min_length=1
620
	max_length=15
618
	max_length=19
621
	_re = re.compile('^[0-9]+(\.[0-9]+)?(\.[0-9]+)?$')
619
	_re = re.compile('^((0|[3-9][0-9]?|2(?:5[0-5]|[0-4]?[0-9])?|1[0-9]{0,2})(\.(0|[3-9][0-9]?|2(?:5[0-5]|[0-4]?[0-9])?|1[0-9]{0,2})){0,2})$|^([0-9a-fA\
620
-F]{1,4}(?:(?:(?<!::):|(?<=::))[0-9a-fA-F]{0,4}){1,3})$') # IPv4 + IPv6
622
621
623
	def parse(self, text):
622
	def parse(self, text):
624
		if self._re.match(text) != None:
623
		if self._re.match(text) != None:
625
			for q in text.split('.'):
626
				if int(q) > 255:
627
					return
628
			return text
624
			return text
629
		raise univention.admin.uexceptions.valueError,_("An IP subnet consists of one to three numbers ranging from 0 to 255 separated by dots.")
625
		raise univention.admin.uexceptions.valueError,_("An IPv4 subnet consists of one to three numbers ranging from 0 to 255 separated by dots, an IPv6 subnet consists of one to four groups of one to four hexadecimal digits separated by colons (:).")
630
626
631
class reverseLookupZoneName(simple):
627
class reverseLookupZoneName(simple):
632
	name='reverseLookupZoneName'
628
	name='reverseLookupZoneName'
633
	min_length=14
629
	min_length=14
634
	max_length=30 #?
630
	max_length=72 # IPv6
635
	_re=re.compile('^[0-9]+(\.[0-9]+)?(\.[0-9]+)?\.in-addr\.arpa$')
631
	# TODO: check re.compile IPv6
632
	_re = re.compile('^((0|[3-9][0-9]?|2(?:5[0-5]|[0-4]?[0-9])?|1[0-9]{0,2})(\.(0|[3-9][0-9]?|2(?:5[0-5]|[0-4]?[0-9])?|1[0-9]{0,2})){3}\.in-addr\.arpa$)|((?!.*?::.*?::)[0-9a-fA-F]{0,4}(?:(?:(?<!::):|(?<=::))[0-9a-fA-F]{0,4}){5}(?:(?:(?<!::):|(?<=::))(?:[3-9][0-9]?|2(?:5[0-5]|[0-4]?[0-9])?|1[0-9]{0,2}|0)(?:\.(?:[3-9][0-9]?|2(?:5[0-5]|[0-4]?[0-9])?|1[0-9]{0,2}|0)){3}|(?:(?:(?<!::):|(?<=::))[0-9a-fA-F]{0,4}){2})\.ip6\.arpa)$') # IPv6
636
633
637
	def parse(self, text):
634
	def parse(self, text):
638
		if self._re.match(text) != None:
635
		if self._re.match(text) != None:
639
			t=text.replace('in-addr.arpa', '')
640
			for q in t.split('.'):
641
				if int(q) > 255:
642
					return
643
			return text
636
			return text
644
		raise univention.admin.uexceptions.valueError,_("The name of a reverse zone consists of the reversed subnet address followed by .in-addr.arpa. Example: \"0.168.192.in-addr.arpa\"")
637
		raise univention.admin.uexceptions.valueError,_("The name of a reverse zone for IPv4 consists of the reversed subnet address followed by .in-addr.arpa (example: \"0.168.192.in-addr.arpa\") or for IPv6 in nibble format followed by .ip6.arpa (example: \"0.0.0.0.0.0.1.0.8.b.d.0.1.0.0.2.ip6.arpa\")")
645
638
646
class dnsName(simple):
639
class dnsName(simple):
647
	name='dnsName'
640
	name='dnsName'
648
	_re = re.compile('^[a-zA-Z0-9][a-zA-Z0-9._-]*[a-zA-Z0-9.]$')
641
	_re = re.compile('^[a-zA-Z0-9:][a-zA-Z0-9.:_-]*[a-zA-Z0-9.]$') # IPv6
649
642
650
	def parse(self, text):
643
	def parse(self, text):
651
		if text==None:
644
		if text==None:
652
			raise univention.admin.uexceptions.valueError, _("Missing value!")
645
			raise univention.admin.uexceptions.valueError, _("Missing value!")
653
		if self._re.match(text) != None:
646
		if self._re.match(text) != None:
654
			return text
647
			return text
655
		raise univention.admin.uexceptions.valueError, _("Value may not contain other than numbers, letters and dots!")
648
		raise univention.admin.uexceptions.valueError, _("Value may not contain other than numbers, letters, dots and colons!")
656
649
657
class dnsName_umlauts(simple):
650
class dnsName_umlauts(simple):
658
	name='dnsName_umlauts'
651
	name='dnsName_umlauts'
659
	_re = re.compile('(?u)(^\w[\w -.]*\w$)|\w*$')
652
	_re = re.compile('(?u)(^\w[\w -.:]*\w$)|\w*$') # IPv6
660
653
661
	def parse(self, text):
654
	def parse(self, text):
662
		if self._re.match(text) != None:
655
		if self._re.match(text) != None:
663
			return text
656
			return text
664
		raise univention.admin.uexceptions.valueError, _("Value may not contain other than numbers, letters and dots!")
657
		raise univention.admin.uexceptions.valueError, _("Value may not contain other than numbers, letters, dots and colons!")
665
658
666
class dnsNameDot(simple):
659
class dnsNameDot(simple):
667
	name='dnsName'
660
	name='dnsName'
668
	_re = re.compile('^[0-9a-zA-Z.-]+$')
661
	_re = re.compile('^[0-9a-zA-Z.:-]+$') # IPv6
669
662
670
	def parse(self, text):
663
	def parse(self, text):
671
		if self._re.match(text) != None:
664
		if self._re.match(text) != None:
672
			return text
665
			return text
673
666
674
		raise univention.admin.uexceptions.valueError, _("Value may not contain other than numbers, letters and dots!")
667
		raise univention.admin.uexceptions.valueError, _("Value may not contain other than numbers, letters, dots and colons!")
675
668
676
669
677
class keyAndValue(complex):
670
class keyAndValue(complex):

Return to bug 15687