NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

idna.py (6254B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\stdlib\encodings\idna.py
      2 import stringprep, re, codecs
      3 from unicodedata import ucd_3_2_0 as unicodedata
      4 dots = re.compile(u'[.\u3002\uff0e\uff61]')
      5 ace_prefix = 'xn--'
      6 uace_prefix = unicode(ace_prefix, 'ascii')
      7 
      8 def nameprep(label):
      9     newlabel = []
     10     for c in label:
     11         if stringprep.in_table_b1(c):
     12             continue
     13         newlabel.append(stringprep.map_table_b2(c))
     14 
     15     label = u''.join(newlabel)
     16     label = unicodedata.normalize('NFKC', label)
     17     for c in label:
     18         if stringprep.in_table_c12(c) or stringprep.in_table_c22(c) or stringprep.in_table_c3(c) or stringprep.in_table_c4(c) or stringprep.in_table_c5(c) or stringprep.in_table_c6(c) or stringprep.in_table_c7(c) or stringprep.in_table_c8(c) or stringprep.in_table_c9(c):
     19             raise UnicodeError('Invalid character %r' % c)
     20 
     21     RandAL = map(stringprep.in_table_d1, label)
     22     for c in RandAL:
     23         if c:
     24             if filter(stringprep.in_table_d2, label):
     25                 raise UnicodeError('Violation of BIDI requirement 2')
     26             if not RandAL[0] or not RandAL[-1]:
     27                 raise UnicodeError('Violation of BIDI requirement 3')
     28 
     29     return label
     30 
     31 
     32 def ToASCII(label):
     33     try:
     34         label = label.encode('ascii')
     35     except UnicodeError:
     36         pass
     37     else:
     38         if 0 < len(label) < 64:
     39             return label
     40         raise UnicodeError('label empty or too long')
     41 
     42     label = nameprep(label)
     43     try:
     44         label = label.encode('ascii')
     45     except UnicodeError:
     46         pass
     47     else:
     48         if 0 < len(label) < 64:
     49             return label
     50         raise UnicodeError('label empty or too long')
     51 
     52     if label.startswith(uace_prefix):
     53         raise UnicodeError('Label starts with ACE prefix')
     54     label = label.encode('punycode')
     55     label = ace_prefix + label
     56     if 0 < len(label) < 64:
     57         return label
     58     raise UnicodeError('label empty or too long')
     59 
     60 
     61 def ToUnicode(label):
     62     if isinstance(label, str):
     63         pure_ascii = True
     64     else:
     65         try:
     66             label = label.encode('ascii')
     67             pure_ascii = True
     68         except UnicodeError:
     69             pure_ascii = False
     70 
     71     if not pure_ascii:
     72         label = nameprep(label)
     73         try:
     74             label = label.encode('ascii')
     75         except UnicodeError:
     76             raise UnicodeError('Invalid character in IDN label')
     77 
     78     if not label.startswith(ace_prefix):
     79         return unicode(label, 'ascii')
     80     label1 = label[len(ace_prefix):]
     81     result = label1.decode('punycode')
     82     label2 = ToASCII(result)
     83     if label.lower() != label2:
     84         raise UnicodeError('IDNA does not round-trip', label, label2)
     85     return result
     86 
     87 
     88 class Codec(codecs.Codec):
     89 
     90     def encode(self, input, errors = 'strict'):
     91         if errors != 'strict':
     92             raise UnicodeError('unsupported error handling ' + errors)
     93         if not input:
     94             return ('', 0)
     95         result = []
     96         labels = dots.split(input)
     97         if labels and len(labels[-1]) == 0:
     98             trailing_dot = '.'
     99             del labels[-1]
    100         else:
    101             trailing_dot = ''
    102         for label in labels:
    103             result.append(ToASCII(label))
    104 
    105         return ('.'.join(result) + trailing_dot, len(input))
    106 
    107     def decode(self, input, errors = 'strict'):
    108         if errors != 'strict':
    109             raise UnicodeError('Unsupported error handling ' + errors)
    110         if not input:
    111             return (u'', 0)
    112         if isinstance(input, unicode):
    113             labels = dots.split(input)
    114         else:
    115             input = str(input)
    116             unicode(input, 'ascii')
    117             labels = input.split('.')
    118         if labels and len(labels[-1]) == 0:
    119             trailing_dot = u'.'
    120             del labels[-1]
    121         else:
    122             trailing_dot = u''
    123         result = []
    124         for label in labels:
    125             result.append(ToUnicode(label))
    126 
    127         return (u'.'.join(result) + trailing_dot, len(input))
    128 
    129 
    130 class IncrementalEncoder(codecs.BufferedIncrementalEncoder):
    131 
    132     def _buffer_encode(self, input, errors, final):
    133         if errors != 'strict':
    134             raise UnicodeError('unsupported error handling ' + errors)
    135         if not input:
    136             return ('', 0)
    137         labels = dots.split(input)
    138         trailing_dot = u''
    139         if labels:
    140             if not labels[-1]:
    141                 trailing_dot = '.'
    142                 del labels[-1]
    143             elif not final:
    144                 del labels[-1]
    145                 if labels:
    146                     trailing_dot = '.'
    147         result = []
    148         size = 0
    149         for label in labels:
    150             result.append(ToASCII(label))
    151             if size:
    152                 size += 1
    153             size += len(label)
    154 
    155         result = '.'.join(result) + trailing_dot
    156         size += len(trailing_dot)
    157         return (result, size)
    158 
    159 
    160 class IncrementalDecoder(codecs.BufferedIncrementalDecoder):
    161 
    162     def _buffer_decode(self, input, errors, final):
    163         if errors != 'strict':
    164             raise UnicodeError('Unsupported error handling ' + errors)
    165         if not input:
    166             return (u'', 0)
    167         if isinstance(input, unicode):
    168             labels = dots.split(input)
    169         else:
    170             input = str(input)
    171             unicode(input, 'ascii')
    172             labels = input.split('.')
    173         trailing_dot = u''
    174         if labels:
    175             if not labels[-1]:
    176                 trailing_dot = u'.'
    177                 del labels[-1]
    178             elif not final:
    179                 del labels[-1]
    180                 if labels:
    181                     trailing_dot = u'.'
    182         result = []
    183         size = 0
    184         for label in labels:
    185             result.append(ToUnicode(label))
    186             if size:
    187                 size += 1
    188             size += len(label)
    189 
    190         result = u'.'.join(result) + trailing_dot
    191         size += len(trailing_dot)
    192         return (result, size)
    193 
    194 
    195 class StreamWriter(Codec, codecs.StreamWriter):
    196     pass
    197 
    198 
    199 class StreamReader(Codec, codecs.StreamReader):
    200     pass
    201 
    202 
    203 def getregentry():
    204     return codecs.CodecInfo(name='idna', encode=Codec().encode, decode=Codec().decode, incrementalencoder=IncrementalEncoder, incrementaldecoder=IncrementalDecoder, streamwriter=StreamWriter, streamreader=StreamReader)