1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 import stringprep
25 import unicodedata
26 from encodings import idna
27
29 """
30 Interface for character lookup classes
31 """
32
34 """
35 Return whether character is in this table
36 """
37 pass
38
40 """
41 Interface for character mapping classes
42 """
43
45 """
46 Return mapping for character
47 """
48 pass
49
56
58
59 __implements__ = ILookupTable
60
63
65 return c in self._table
66
73
75
76 __implements__ = IMappingTable
77
79 self._in_table_function = in_table_function
80
82 if self._in_table_function(c):
83 return None
84 else:
85 return c
86
88 - def __init__(self, mappings=[], normalize=True, prohibiteds=[],
89 check_unassigneds=True, check_bidi=True):
95
97 result = self.map(string)
98 if self.normalize:
99 result = unicodedata.normalize("NFKC", result)
100 self.check_prohibiteds(result)
101 if self.do_check_unassigneds:
102 self.check_unassigneds(result)
103 if self.do_check_bidi:
104 self.check_bidirectionals(result)
105 return result
106
107 - def map(self, string):
108 result = []
109
110 for c in string:
111 result_c = c
112
113 for mapping in self.mappings:
114 result_c = mapping.map(c)
115 if result_c != c:
116 break
117
118 if result_c is not None:
119 result.append(result_c)
120
121 return u"".join(result)
122
124 for c in string:
125 for table in self.prohibiteds:
126 if table.lookup(c):
127 raise UnicodeError, "Invalid character %s" % repr(c)
128
130 for c in string:
131 if stringprep.in_table_a1(c):
132 raise UnicodeError, "Unassigned code point %s" % repr(c)
133
135 found_LCat = False
136 found_RandALCat = False
137
138 for c in string:
139 if stringprep.in_table_d1(c):
140 found_RandALCat = True
141 if stringprep.in_table_d2(c):
142 found_LCat = True
143
144 if found_LCat and found_RandALCat:
145 raise UnicodeError, "Violation of BIDI Requirement 2"
146
147 if found_RandALCat and not (stringprep.in_table_d1(string[0]) and
148 stringprep.in_table_d1(string[-1])):
149 raise UnicodeError, "Violation of BIDI Requirement 3"
150
151
153 """
154 Implements preparation of internationalized domain names
155
156 This class implements preparing internationalized domain names using the
157 rules defined in RFC 3491, section 4 (Conversion operations).
158
159 We do not perform step 4 since we deal with unicode representations of
160 domain names and do not convert from or to ASCII representations using
161 punycode encoding. When such a conversion is needed, the L{idna} standard
162 library provides the C{ToUnicode()} and C{ToASCII()} functions. Note that
163 L{idna} itself assumes UseSTD3ASCIIRules to be false.
164
165 The following steps are performed by C{prepare()}:
166
167 * Split the domain name in labels at the dots (RFC 3490, 3.1)
168 * Apply nameprep proper on each label (RFC 3491)
169 * Enforce the restrictions on ASCII characters in host names by
170 assuming STD3ASCIIRules to be true. (STD 3)
171 * Rejoin the labels using the label separator U+002E (full stop).
172 """
173
174
175 prohibiteds = [unichr(n) for n in range(0x00, 0x2c + 1) +
176 range(0x2e, 0x2f + 1) +
177 range(0x3a, 0x40 + 1) +
178 range(0x5b, 0x60 + 1) +
179 range(0x7b, 0x7f + 1) ]
180
182 result = []
183
184 labels = idna.dots.split(string)
185
186 if labels and len(labels[-1]) == 0:
187 trailing_dot = '.'
188 del labels[-1]
189 else:
190 trailing_dot = ''
191
192 for label in labels:
193 result.append(self.nameprep(label))
194
195 return ".".join(result)+trailing_dot
196
198 for c in string:
199 if c in self.prohibiteds:
200 raise UnicodeError, "Invalid character %s" % repr(c)
201
203 label = idna.nameprep(label)
204 self.check_prohibiteds(label)
205 if len(label) == 0:
206 raise UnicodeError, "Invalid empty name"
207 if label[0] == '-':
208 raise UnicodeError, "Invalid leading hyphen-minus"
209 if label[-1] == '-':
210 raise UnicodeError, "Invalid trailing hyphen-minus"
211 return label
212
213 C_11 = LookupTableFromFunction(stringprep.in_table_c11)
214 C_12 = LookupTableFromFunction(stringprep.in_table_c12)
215 C_21 = LookupTableFromFunction(stringprep.in_table_c21)
216 C_22 = LookupTableFromFunction(stringprep.in_table_c22)
217 C_3 = LookupTableFromFunction(stringprep.in_table_c3)
218 C_4 = LookupTableFromFunction(stringprep.in_table_c4)
219 C_5 = LookupTableFromFunction(stringprep.in_table_c5)
220 C_6 = LookupTableFromFunction(stringprep.in_table_c6)
221 C_7 = LookupTableFromFunction(stringprep.in_table_c7)
222 C_8 = LookupTableFromFunction(stringprep.in_table_c8)
223 C_9 = LookupTableFromFunction(stringprep.in_table_c9)
224
225 B_1 = EmptyMappingTable(stringprep.in_table_b1)
226 B_2 = MappingTableFromFunction(stringprep.map_table_b2)
227
228 nodeprep = Profile(mappings=[B_1, B_2],
229 prohibiteds=[C_11, C_12, C_21, C_22,
230 C_3, C_4, C_5, C_6, C_7, C_8, C_9,
231 LookupTable([u'"', u'&', u"'", u'/',
232 u':', u'<', u'>', u'@'])])
233
234 resourceprep = Profile(mappings=[B_1,],
235 prohibiteds=[C_12, C_21, C_22,
236 C_3, C_4, C_5, C_6, C_7, C_8, C_9])
237
238 nameprep = NamePrep()
239