Package pyxmpp :: Module xmppstringprep
[hide private]

Source Code for Module pyxmpp.xmppstringprep

  1  # 
  2  # (C) Copyright 2003-2010 Jacek Konieczny <jajcus@jajcus.net> 
  3  # 
  4  # This program is free software; you can redistribute it and/or modify 
  5  # it under the terms of the GNU Lesser General Public License Version 
  6  # 2.1 as published by the Free Software Foundation. 
  7  # 
  8  # This program is distributed in the hope that it will be useful, 
  9  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 10  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 11  # GNU Lesser General Public License for more details. 
 12  # 
 13  # You should have received a copy of the GNU Lesser General Public 
 14  # License along with this program; if not, write to the Free Software 
 15  # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 16  # 
 17  # pylint treats "import stringprep" like depreciated "import string" 
 18  # pylint: disable-msg=W0402 
 19   
 20  """Nodeprep and resourceprep stringprep profiles. 
 21   
 22  Normative reference: 
 23    - `RFC 3920 <http://www.ietf.org/rfc/rfc3920.txt>`__ 
 24  """ 
 25   
 26  __revision__="$Id: xmppstringprep.py,v 1.16 2004/10/07 22:28:04 jajcus Exp $" 
 27  __docformat__="restructuredtext en" 
 28   
 29  import stringprep 
 30  import unicodedata 
 31  from pyxmpp.exceptions import StringprepError 
 32   
33 -class LookupFunction:
34 """Class for looking up RFC 3454 tables using function. 35 36 :Ivariables: 37 - `lookup`: the lookup function."""
38 - def __init__(self,function):
39 """Initialize `LookupFunction` object. 40 41 :Parameters: 42 - `function`: function taking character code as input and returning 43 `bool` value or the mapped for `code`.""" 44 self.lookup=function
45
46 -class LookupTable:
47 """Class for looking up RFC 3454 tables using a dictionary and/or list of ranges."""
48 - def __init__(self,singles,ranges):
49 """Initialize `LookupTable` object. 50 51 :Parameters: 52 - `singles`: dictionary mapping Unicode characters into other Unicode characters. 53 - `ranges`: list of ``((start,end),value)`` tuples mapping codes in range (start,end) 54 to the value.""" 55 self.singles=singles 56 self.ranges=ranges
57
58 - def lookup(self,c):
59 """Do Unicode character lookup. 60 61 :Parameters: 62 - `c`: Unicode character to look up. 63 64 :return: the mapped value.""" 65 if self.singles.has_key(c): 66 return self.singles[c] 67 c=ord(c) 68 for (start,end),value in self.ranges: 69 if c<start: 70 return None 71 if c<=end: 72 return value 73 return None
74 75 A_1=LookupFunction(stringprep.in_table_a1) 76
77 -def b1_mapping(uc):
78 """Do RFC 3454 B.1 table mapping. 79 80 :Parameters: 81 - `uc`: Unicode character to map. 82 83 :returns: u"" if there is `uc` code in the table, `None` otherwise.""" 84 if stringprep.in_table_b1(uc): 85 return u"" 86 else: 87 return None
88 89 B_1=LookupFunction(b1_mapping) 90 B_2=LookupFunction(stringprep.map_table_b2) 91 B_3=LookupFunction(stringprep.map_table_b3) 92 C_1_1=LookupFunction(stringprep.in_table_c11) 93 C_1_2=LookupFunction(stringprep.in_table_c12) 94 C_2_1=LookupFunction(stringprep.in_table_c21) 95 C_2_2=LookupFunction(stringprep.in_table_c22) 96 C_3=LookupFunction(stringprep.in_table_c3) 97 C_4=LookupFunction(stringprep.in_table_c4) 98 C_5=LookupFunction(stringprep.in_table_c5) 99 C_6=LookupFunction(stringprep.in_table_c6) 100 C_7=LookupFunction(stringprep.in_table_c7) 101 C_8=LookupFunction(stringprep.in_table_c8) 102 C_9=LookupFunction(stringprep.in_table_c9) 103 D_1=LookupFunction(stringprep.in_table_d1) 104 D_2=LookupFunction(stringprep.in_table_d2) 105
106 -def nfkc(data):
107 """Do NFKC normalization of Unicode data. 108 109 :Parameters: 110 - `data`: list of Unicode characters or Unicode string. 111 112 :return: normalized Unicode string.""" 113 if type(data) is list: 114 data=u"".join(data) 115 return unicodedata.normalize("NFKC",data)
116
117 -class Profile:
118 """Base class for stringprep profiles.""" 119 cache_items=[]
120 - def __init__(self,unassigned,mapping,normalization,prohibited,bidi=1):
121 """Initialize Profile object. 122 123 :Parameters: 124 - `unassigned`: the lookup table with unassigned codes 125 - `mapping`: the lookup table with character mappings 126 - `normalization`: the normalization function 127 - `prohibited`: the lookup table with prohibited characters 128 - `bidi`: if True then bidirectional checks should be done 129 """ 130 self.unassigned=unassigned 131 self.mapping=mapping 132 self.normalization=normalization 133 self.prohibited=prohibited 134 self.bidi=bidi 135 self.cache={}
136
137 - def prepare(self,data):
138 """Complete string preparation procedure for 'stored' strings. 139 (includes checks for unassigned codes) 140 141 :Parameters: 142 - `data`: Unicode string to prepare. 143 144 :return: prepared string 145 146 :raise StringprepError: if the preparation fails 147 """ 148 r=self.cache.get(data) 149 if r is not None: 150 return r 151 s=self.map(data) 152 if self.normalization: 153 s=self.normalization(s) 154 s=self.prohibit(s) 155 s=self.check_unassigned(s) 156 if self.bidi: 157 s=self.check_bidi(s) 158 if type(s) is list: 159 s=u"".string.join() 160 if len(self.cache_items)>=stringprep_cache_size: 161 remove=self.cache_items[:-stringprep_cache_size/2] 162 for profile,key in remove: 163 try: 164 del profile.cache[key] 165 except KeyError: 166 pass 167 self.cache_items[:]=self.cache_items[-stringprep_cache_size/2:] 168 self.cache_items.append((self,data)) 169 self.cache[data]=s 170 return s
171
172 - def prepare_query(self,s):
173 """Complete string preparation procedure for 'query' strings. 174 (without checks for unassigned codes) 175 176 :Parameters: 177 - `s`: Unicode string to prepare. 178 179 :return: prepared string 180 181 :raise StringprepError: if the preparation fails 182 """ 183 184 s=self.map(s) 185 if self.normalization: 186 s=self.normalization(s) 187 s=self.prohibit(s) 188 if self.bidi: 189 s=self.check_bidi(s) 190 if type(s) is list: 191 s=u"".string.join(s) 192 return s
193
194 - def map(self,s):
195 """Mapping part of string preparation.""" 196 r=[] 197 for c in s: 198 rc=None 199 for t in self.mapping: 200 rc=t.lookup(c) 201 if rc is not None: 202 break 203 if rc is not None: 204 r.append(rc) 205 else: 206 r.append(c) 207 return r
208
209 - def prohibit(self,s):
210 """Checks for prohibited characters.""" 211 for c in s: 212 for t in self.prohibited: 213 if t.lookup(c): 214 raise StringprepError,"Prohibited character: %r" % (c,) 215 return s
216
217 - def check_unassigned(self,s):
218 """Checks for unassigned character codes.""" 219 for c in s: 220 for t in self.unassigned: 221 if t.lookup(c): 222 raise StringprepError,"Unassigned character: %r" % (c,) 223 return s
224
225 - def check_bidi(self,s):
226 """Checks if sting is valid for bidirectional printing.""" 227 has_l=0 228 has_ral=0 229 for c in s: 230 if D_1.lookup(c): 231 has_ral=1 232 elif D_2.lookup(c): 233 has_l=1 234 if has_l and has_ral: 235 raise StringprepError,"Both RandALCat and LCat characters present" 236 if has_l and (D_1.lookup(s[0]) is None or D_1.lookup(s[-1]) is None): 237 raise StringprepError,"The first and the last character must be RandALCat" 238 return s
239 240 nodeprep=Profile( 241 unassigned=(A_1,), 242 mapping=(B_1,B_2), 243 normalization=nfkc, 244 prohibited=(C_1_1,C_1_2,C_2_1,C_2_2,C_3,C_4,C_5,C_6,C_7,C_8,C_9, 245 LookupTable({u'"':True,u'&':True,u"'":True,u"/":True, 246 u":":True,u"<":True,u">":True,u"@":True},()) ), 247 bidi=1) 248 249 resourceprep=Profile( 250 unassigned=(A_1,), 251 mapping=(B_1,), 252 normalization=nfkc, 253 prohibited=(C_1_2,C_2_1,C_2_2,C_3,C_4,C_5,C_6,C_7,C_8,C_9), 254 bidi=1) 255 256 stringprep_cache_size=1000
257 -def set_stringprep_cache_size(size):
258 """Modify stringprep cache size. 259 260 :Parameters: 261 - `size`: new cache size""" 262 global stringprep_cache_size 263 stringprep_cache_size=size 264 if len(Profile.cache_items)>size: 265 remove=Profile.cache_items[:-size] 266 for profile,key in remove: 267 try: 268 del profile.cache[key] 269 except KeyError: 270 pass 271 Profile.cache_items=Profile.cache_items[-size:]
272 273 # vi: sts=4 et sw=4 274