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

_parseaddr.py (11003B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\stdlib\email\_parseaddr.py
      2 __all__ = ['mktime_tz',
      3  'parsedate',
      4  'parsedate_tz',
      5  'quote']
      6 import time
      7 SPACE = ' '
      8 EMPTYSTRING = ''
      9 COMMASPACE = ', '
     10 _monthnames = ['jan',
     11  'feb',
     12  'mar',
     13  'apr',
     14  'may',
     15  'jun',
     16  'jul',
     17  'aug',
     18  'sep',
     19  'oct',
     20  'nov',
     21  'dec',
     22  'january',
     23  'february',
     24  'march',
     25  'april',
     26  'may',
     27  'june',
     28  'july',
     29  'august',
     30  'september',
     31  'october',
     32  'november',
     33  'december']
     34 _daynames = ['mon',
     35  'tue',
     36  'wed',
     37  'thu',
     38  'fri',
     39  'sat',
     40  'sun']
     41 _timezones = {'UT': 0,
     42  'UTC': 0,
     43  'GMT': 0,
     44  'Z': 0,
     45  'AST': -400,
     46  'ADT': -300,
     47  'EST': -500,
     48  'EDT': -400,
     49  'CST': -600,
     50  'CDT': -500,
     51  'MST': -700,
     52  'MDT': -600,
     53  'PST': -800,
     54  'PDT': -700}
     55 
     56 def parsedate_tz(data):
     57     data = data.split()
     58     if data[0].endswith(',') or data[0].lower() in _daynames:
     59         del data[0]
     60     else:
     61         i = data[0].rfind(',')
     62         if i >= 0:
     63             data[0] = data[0][i + 1:]
     64     if len(data) == 3:
     65         stuff = data[0].split('-')
     66         if len(stuff) == 3:
     67             data = stuff + data[1:]
     68     if len(data) == 4:
     69         s = data[3]
     70         i = s.find('+')
     71         if i > 0:
     72             data[3:] = [s[:i], s[i + 1:]]
     73         else:
     74             data.append('')
     75     if len(data) < 5:
     76         return
     77     data = data[:5]
     78     dd, mm, yy, tm, tz = data
     79     mm = mm.lower()
     80     if mm not in _monthnames:
     81         dd, mm = mm, dd.lower()
     82         if mm not in _monthnames:
     83             return
     84     mm = _monthnames.index(mm) + 1
     85     if mm > 12:
     86         mm -= 12
     87     if dd[-1] == ',':
     88         dd = dd[:-1]
     89     i = yy.find(':')
     90     if i > 0:
     91         yy, tm = tm, yy
     92     if yy[-1] == ',':
     93         yy = yy[:-1]
     94     if not yy[0].isdigit():
     95         yy, tz = tz, yy
     96     if tm[-1] == ',':
     97         tm = tm[:-1]
     98     tm = tm.split(':')
     99     if len(tm) == 2:
    100         thh, tmm = tm
    101         tss = '0'
    102     elif len(tm) == 3:
    103         thh, tmm, tss = tm
    104     else:
    105         return
    106     try:
    107         yy = int(yy)
    108         dd = int(dd)
    109         thh = int(thh)
    110         tmm = int(tmm)
    111         tss = int(tss)
    112     except ValueError:
    113         return
    114 
    115     if yy < 100:
    116         if yy > 68:
    117             yy += 1900
    118         else:
    119             yy += 2000
    120     tzoffset = None
    121     tz = tz.upper()
    122     if tz in _timezones:
    123         tzoffset = _timezones[tz]
    124     else:
    125         try:
    126             tzoffset = int(tz)
    127         except ValueError:
    128             pass
    129 
    130     if tzoffset:
    131         if tzoffset < 0:
    132             tzsign = -1
    133             tzoffset = -tzoffset
    134         else:
    135             tzsign = 1
    136         tzoffset = tzsign * (tzoffset // 100 * 3600 + tzoffset % 100 * 60)
    137     return (yy,
    138      mm,
    139      dd,
    140      thh,
    141      tmm,
    142      tss,
    143      0,
    144      1,
    145      -1,
    146      tzoffset)
    147 
    148 
    149 def parsedate(data):
    150     t = parsedate_tz(data)
    151     if isinstance(t, tuple):
    152         return t[:9]
    153     else:
    154         return t
    155 
    156 
    157 def mktime_tz(data):
    158     if data[9] is None:
    159         return time.mktime(data[:8] + (-1,))
    160     else:
    161         t = time.mktime(data[:8] + (0,))
    162         return t - data[9] - time.timezone
    163 
    164 
    165 def quote(str):
    166     return str.replace('\\', '\\\\').replace('"', '\\"')
    167 
    168 
    169 class AddrlistClass():
    170 
    171     def __init__(self, field):
    172         self.specials = '()<>@,:;."[]'
    173         self.pos = 0
    174         self.LWS = ' \t'
    175         self.CR = '\r\n'
    176         self.FWS = self.LWS + self.CR
    177         self.atomends = self.specials + self.LWS + self.CR
    178         self.phraseends = self.atomends.replace('.', '')
    179         self.field = field
    180         self.commentlist = []
    181 
    182     def gotonext(self):
    183         while self.pos < len(self.field):
    184             if self.field[self.pos] in self.LWS + '\n\r':
    185                 self.pos += 1
    186             elif self.field[self.pos] == '(':
    187                 self.commentlist.append(self.getcomment())
    188             else:
    189                 break
    190 
    191     def getaddrlist(self):
    192         result = []
    193         while self.pos < len(self.field):
    194             ad = self.getaddress()
    195             if ad:
    196                 result += ad
    197             else:
    198                 result.append(('', ''))
    199 
    200         return result
    201 
    202     def getaddress(self):
    203         self.commentlist = []
    204         self.gotonext()
    205         oldpos = self.pos
    206         oldcl = self.commentlist
    207         plist = self.getphraselist()
    208         self.gotonext()
    209         returnlist = []
    210         if self.pos >= len(self.field):
    211             if plist:
    212                 returnlist = [(SPACE.join(self.commentlist), plist[0])]
    213         elif self.field[self.pos] in '.@':
    214             self.pos = oldpos
    215             self.commentlist = oldcl
    216             addrspec = self.getaddrspec()
    217             returnlist = [(SPACE.join(self.commentlist), addrspec)]
    218         elif self.field[self.pos] == ':':
    219             returnlist = []
    220             fieldlen = len(self.field)
    221             self.pos += 1
    222             while self.pos < len(self.field):
    223                 self.gotonext()
    224                 if self.pos < fieldlen and self.field[self.pos] == ';':
    225                     self.pos += 1
    226                     break
    227                 returnlist = returnlist + self.getaddress()
    228 
    229         elif self.field[self.pos] == '<':
    230             routeaddr = self.getrouteaddr()
    231             if self.commentlist:
    232                 returnlist = [(SPACE.join(plist) + ' (' + ' '.join(self.commentlist) + ')', routeaddr)]
    233             else:
    234                 returnlist = [(SPACE.join(plist), routeaddr)]
    235         elif plist:
    236             returnlist = [(SPACE.join(self.commentlist), plist[0])]
    237         elif self.field[self.pos] in self.specials:
    238             self.pos += 1
    239         self.gotonext()
    240         if self.pos < len(self.field) and self.field[self.pos] == ',':
    241             self.pos += 1
    242         return returnlist
    243 
    244     def getrouteaddr(self):
    245         if self.field[self.pos] != '<':
    246             return
    247         expectroute = False
    248         self.pos += 1
    249         self.gotonext()
    250         adlist = ''
    251         while self.pos < len(self.field):
    252             if expectroute:
    253                 self.getdomain()
    254                 expectroute = False
    255             elif self.field[self.pos] == '>':
    256                 self.pos += 1
    257                 break
    258             elif self.field[self.pos] == '@':
    259                 self.pos += 1
    260                 expectroute = True
    261             elif self.field[self.pos] == ':':
    262                 self.pos += 1
    263             else:
    264                 adlist = self.getaddrspec()
    265                 self.pos += 1
    266                 break
    267             self.gotonext()
    268 
    269         return adlist
    270 
    271     def getaddrspec(self):
    272         aslist = []
    273         self.gotonext()
    274         while self.pos < len(self.field):
    275             if self.field[self.pos] == '.':
    276                 aslist.append('.')
    277                 self.pos += 1
    278             elif self.field[self.pos] == '"':
    279                 aslist.append('"%s"' % quote(self.getquote()))
    280             elif self.field[self.pos] in self.atomends:
    281                 break
    282             else:
    283                 aslist.append(self.getatom())
    284             self.gotonext()
    285 
    286         if self.pos >= len(self.field) or self.field[self.pos] != '@':
    287             return EMPTYSTRING.join(aslist)
    288         aslist.append('@')
    289         self.pos += 1
    290         self.gotonext()
    291         return EMPTYSTRING.join(aslist) + self.getdomain()
    292 
    293     def getdomain(self):
    294         sdlist = []
    295         while self.pos < len(self.field):
    296             if self.field[self.pos] in self.LWS:
    297                 self.pos += 1
    298             elif self.field[self.pos] == '(':
    299                 self.commentlist.append(self.getcomment())
    300             elif self.field[self.pos] == '[':
    301                 sdlist.append(self.getdomainliteral())
    302             elif self.field[self.pos] == '.':
    303                 self.pos += 1
    304                 sdlist.append('.')
    305             elif self.field[self.pos] in self.atomends:
    306                 break
    307             else:
    308                 sdlist.append(self.getatom())
    309 
    310         return EMPTYSTRING.join(sdlist)
    311 
    312     def getdelimited(self, beginchar, endchars, allowcomments = True):
    313         if self.field[self.pos] != beginchar:
    314             return ''
    315         slist = ['']
    316         quote = False
    317         self.pos += 1
    318         while self.pos < len(self.field):
    319             if quote:
    320                 slist.append(self.field[self.pos])
    321                 quote = False
    322             elif self.field[self.pos] in endchars:
    323                 self.pos += 1
    324                 break
    325             elif allowcomments and self.field[self.pos] == '(':
    326                 slist.append(self.getcomment())
    327                 continue
    328             elif self.field[self.pos] == '\\':
    329                 quote = True
    330             else:
    331                 slist.append(self.field[self.pos])
    332             self.pos += 1
    333 
    334         return EMPTYSTRING.join(slist)
    335 
    336     def getquote(self):
    337         return self.getdelimited('"', '"\r', False)
    338 
    339     def getcomment(self):
    340         return self.getdelimited('(', ')\r', True)
    341 
    342     def getdomainliteral(self):
    343         return '[%s]' % self.getdelimited('[', ']\r', False)
    344 
    345     def getatom(self, atomends = None):
    346         atomlist = ['']
    347         if atomends is None:
    348             atomends = self.atomends
    349         while self.pos < len(self.field):
    350             if self.field[self.pos] in atomends:
    351                 break
    352             else:
    353                 atomlist.append(self.field[self.pos])
    354             self.pos += 1
    355 
    356         return EMPTYSTRING.join(atomlist)
    357 
    358     def getphraselist(self):
    359         plist = []
    360         while self.pos < len(self.field):
    361             if self.field[self.pos] in self.FWS:
    362                 self.pos += 1
    363             elif self.field[self.pos] == '"':
    364                 plist.append(self.getquote())
    365             elif self.field[self.pos] == '(':
    366                 self.commentlist.append(self.getcomment())
    367             elif self.field[self.pos] in self.phraseends:
    368                 break
    369             else:
    370                 plist.append(self.getatom(self.phraseends))
    371 
    372         return plist
    373 
    374 
    375 class AddressList(AddrlistClass):
    376 
    377     def __init__(self, field):
    378         AddrlistClass.__init__(self, field)
    379         if field:
    380             self.addresslist = self.getaddrlist()
    381         else:
    382             self.addresslist = []
    383 
    384     def __len__(self):
    385         return len(self.addresslist)
    386 
    387     def __add__(self, other):
    388         newaddr = AddressList(None)
    389         newaddr.addresslist = self.addresslist[:]
    390         for x in other.addresslist:
    391             if x not in self.addresslist:
    392                 newaddr.addresslist.append(x)
    393 
    394         return newaddr
    395 
    396     def __iadd__(self, other):
    397         for x in other.addresslist:
    398             if x not in self.addresslist:
    399                 self.addresslist.append(x)
    400 
    401         return self
    402 
    403     def __sub__(self, other):
    404         newaddr = AddressList(None)
    405         for x in self.addresslist:
    406             if x not in other.addresslist:
    407                 newaddr.addresslist.append(x)
    408 
    409         return newaddr
    410 
    411     def __isub__(self, other):
    412         for x in other.addresslist:
    413             if x in self.addresslist:
    414                 self.addresslist.remove(x)
    415 
    416         return self
    417 
    418     def __getitem__(self, index):
    419         return self.addresslist[index]