]>
code.delx.au - pymsnt/blob - src/tlib/jabber/xmpp_stringprep.py
1 # -*- test-case-name: twisted.words.test.test_jabberxmppstringprep -*-
3 # Copyright (c) 2001-2005 Twisted Matrix Laboratories.
4 # See LICENSE for details.
8 if sys
.version_info
< (2,3,2):
12 dots
= re
.compile(u
"[\u002E\u3002\uFF0E\uFF61]")
13 def nameprep(self
, label
):
20 warnings
.warn("Accented and non-Western Jabber IDs will not be properly "
21 "case-folded with this version of Python, resulting in "
22 "incorrect protocol-level behavior. It is strongly "
23 "recommended you upgrade to Python 2.3.2 or newer if you "
24 "intend to use Twisted's Jabber support.")
29 from encodings
import idna
36 """ Interface for character lookup classes. """
39 """ Return whether character is in this table. """
42 """ Interface for character mapping classes. """
45 """ Return mapping for character. """
47 class LookupTableFromFunction
:
49 __implements__
= ILookupTable
51 def __init__(self
, in_table_function
):
52 self
.lookup
= in_table_function
56 __implements__
= ILookupTable
58 def __init__(self
, table
):
62 return c
in self
._table
64 class MappingTableFromFunction
:
66 __implements__
= IMappingTable
68 def __init__(self
, map_table_function
):
69 self
.map = map_table_function
71 class EmptyMappingTable
:
73 __implements__
= IMappingTable
75 def __init__(self
, in_table_function
):
76 self
._in
_table
_function
= in_table_function
79 if self
._in
_table
_function
(c
):
85 def __init__(self
, mappings
=[], normalize
=True, prohibiteds
=[],
86 check_unassigneds
=True, check_bidi
=True):
87 self
.mappings
= mappings
88 self
.normalize
= normalize
89 self
.prohibiteds
= prohibiteds
90 self
.do_check_unassigneds
= check_unassigneds
91 self
.do_check_bidi
= check_bidi
93 def prepare(self
, string
):
94 result
= self
.map(string
)
96 result
= unicodedata
.normalize("NFKC", result
)
97 self
.check_prohibiteds(result
)
98 if self
.do_check_unassigneds
:
99 self
.check_unassigneds(result
)
100 if self
.do_check_bidi
:
101 self
.check_bidirectionals(result
)
104 def map(self
, string
):
110 for mapping
in self
.mappings
:
111 result_c
= mapping
.map(c
)
115 if result_c
is not None:
116 result
.append(result_c
)
118 return u
"".join(result
)
120 def check_prohibiteds(self
, string
):
122 for table
in self
.prohibiteds
:
124 raise UnicodeError, "Invalid character %s" % repr(c
)
126 def check_unassigneds(self
, string
):
128 if stringprep
.in_table_a1(c
):
129 raise UnicodeError, "Unassigned code point %s" % repr(c
)
131 def check_bidirectionals(self
, string
):
133 found_RandALCat
= False
136 if stringprep
.in_table_d1(c
):
137 found_RandALCat
= True
138 if stringprep
.in_table_d2(c
):
141 if found_LCat
and found_RandALCat
:
142 raise UnicodeError, "Violation of BIDI Requirement 2"
144 if found_RandALCat
and not (stringprep
.in_table_d1(string
[0]) and
145 stringprep
.in_table_d1(string
[-1])):
146 raise UnicodeError, "Violation of BIDI Requirement 3"
150 """ Implements nameprep on international domain names.
152 STD3ASCIIRules is assumed true in this implementation.
155 # Prohibited characters.
156 prohibiteds
= [unichr(n
) for n
in range(0x00, 0x2c + 1) +
157 range(0x2e, 0x2f + 1) +
158 range(0x3a, 0x40 + 1) +
159 range(0x5b, 0x60 + 1) +
160 range(0x7b, 0x7f + 1) ]
162 def prepare(self
, string
):
165 labels
= idna
.dots
.split(string
)
167 if labels
and len(labels
[-1]) == 0:
174 result
.append(self
.nameprep(label
))
176 return ".".join(result
)+trailing_dot
178 def check_prohibiteds(self
, string
):
180 if c
in self
.prohibiteds
:
181 raise UnicodeError, "Invalid character %s" % repr(c
)
183 def nameprep(self
, label
):
184 label
= idna
.nameprep(label
)
185 self
.check_prohibiteds(label
)
187 raise UnicodeError, "Invalid leading hyphen-minus"
189 raise UnicodeError, "Invalid trailing hyphen-minus"
193 case_map
= MappingTableFromFunction(lambda c
: c
.lower())
194 nodeprep
= Profile(mappings
=[case_map
],
196 prohibiteds
=[LookupTable([u
' ', u
'"', u
'&', u
"'", u
'/',
197 u
':', u
'<', u
'>', u
'@'])],
198 check_unassigneds
=False,
201 resourceprep
= Profile(normalize
=False,
202 check_unassigneds
=False,
206 C_11
= LookupTableFromFunction(stringprep
.in_table_c11
)
207 C_12
= LookupTableFromFunction(stringprep
.in_table_c12
)
208 C_21
= LookupTableFromFunction(stringprep
.in_table_c21
)
209 C_22
= LookupTableFromFunction(stringprep
.in_table_c22
)
210 C_3
= LookupTableFromFunction(stringprep
.in_table_c3
)
211 C_4
= LookupTableFromFunction(stringprep
.in_table_c4
)
212 C_5
= LookupTableFromFunction(stringprep
.in_table_c5
)
213 C_6
= LookupTableFromFunction(stringprep
.in_table_c6
)
214 C_7
= LookupTableFromFunction(stringprep
.in_table_c7
)
215 C_8
= LookupTableFromFunction(stringprep
.in_table_c8
)
216 C_9
= LookupTableFromFunction(stringprep
.in_table_c9
)
218 B_1
= EmptyMappingTable(stringprep
.in_table_b1
)
219 B_2
= MappingTableFromFunction(stringprep
.map_table_b2
)
221 nodeprep
= Profile(mappings
=[B_1
, B_2
],
222 prohibiteds
=[C_11
, C_12
, C_21
, C_22
,
223 C_3
, C_4
, C_5
, C_6
, C_7
, C_8
, C_9
,
224 LookupTable([u
'"', u
'&', u
"'", u
'/',
225 u
':', u
'<', u
'>', u
'@'])])
227 resourceprep
= Profile(mappings
=[B_1
,],
228 prohibiteds
=[C_12
, C_21
, C_22
,
229 C_3
, C_4
, C_5
, C_6
, C_7
, C_8
, C_9
])
231 nameprep
= NamePrep()