Package nbxmpp :: Module stringprepare
[hide private]
[frames] | no frames]

Source Code for Module nbxmpp.stringprepare

  1  # -*- coding:utf-8 -*- 
  2  ## src/common/xmpp/stringprepare.py 
  3  ## 
  4  ## Copyright (C) 2001-2005 Twisted Matrix Laboratories 
  5  ## Copyright (C) 2005-2012 Yann Leboulanger <asterix AT lagaule.org> 
  6  ## Copyright (C) 2006 Stefan Bethge <stefan AT lanpartei.de> 
  7  ## Copyright (C) 2007 Jean-Marie Traissard <jim AT lapin.org> 
  8  ## 
  9  ## This file is part of Gajim. 
 10  ## 
 11  ## Gajim is free software; you can redistribute it and/or modify 
 12  ## it under the terms of the GNU General Public License as published 
 13  ## by the Free Software Foundation; version 3 only. 
 14  ## 
 15  ## Gajim is distributed in the hope that it will be useful, 
 16  ## but WITHOUT ANY WARRANTY; without even the implied warranty of 
 17  ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 18  ## GNU General Public License for more details. 
 19  ## 
 20  ## You should have received a copy of the GNU General Public License 
 21  ## along with Gajim. If not, see <http://www.gnu.org/licenses/>. 
 22  ## 
 23   
 24  import stringprep 
 25  import unicodedata 
 26  from encodings import idna 
 27   
28 -class ILookupTable:
29 """ 30 Interface for character lookup classes 31 """ 32
33 - def lookup(self, c):
34 """ 35 Return whether character is in this table 36 """ 37 pass
38
39 -class IMappingTable:
40 """ 41 Interface for character mapping classes 42 """ 43
44 - def map(self, c):
45 """ 46 Return mapping for character 47 """ 48 pass
49
50 -class LookupTableFromFunction:
51 52 __implements__ = ILookupTable 53
54 - def __init__(self, in_table_function):
55 self.lookup = in_table_function
56
57 -class LookupTable:
58 59 __implements__ = ILookupTable 60
61 - def __init__(self, table):
62 self._table = table
63
64 - def lookup(self, c):
65 return c in self._table
66
67 -class MappingTableFromFunction:
68 69 __implements__ = IMappingTable 70
71 - def __init__(self, map_table_function):
72 self.map = map_table_function
73
74 -class EmptyMappingTable:
75 76 __implements__ = IMappingTable 77
78 - def __init__(self, in_table_function):
79 self._in_table_function = in_table_function
80
81 - def map(self, c):
82 if self._in_table_function(c): 83 return None 84 else: 85 return c
86
87 -class Profile:
88 - def __init__(self, mappings=[], normalize=True, prohibiteds=[], 89 check_unassigneds=True, check_bidi=True):
90 self.mappings = mappings 91 self.normalize = normalize 92 self.prohibiteds = prohibiteds 93 self.do_check_unassigneds = check_unassigneds 94 self.do_check_bidi = check_bidi
95
96 - def prepare(self, string):
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
123 - def check_prohibiteds(self, string):
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
129 - def check_unassigneds(self, string):
130 for c in string: 131 if stringprep.in_table_a1(c): 132 raise UnicodeError, "Unassigned code point %s" % repr(c)
133
134 - def check_bidirectionals(self, string):
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
152 -class NamePrep:
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 # Prohibited characters. 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
181 - def prepare(self, string):
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
197 - def check_prohibiteds(self, string):
198 for c in string: 199 if c in self.prohibiteds: 200 raise UnicodeError, "Invalid character %s" % repr(c)
201
202 - def nameprep(self, label):
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