home *** CD-ROM | disk | FTP | other *** search
/ Chip 2006 June / CHIP 2006-06.2.iso / program / freeware / Democracy-0.8.2.exe / xulrunner / python / BitTorrent / btformats.py < prev    next >
Encoding:
Python Source  |  2006-04-10  |  5.2 KB  |  126 lines

  1. # The contents of this file are subject to the BitTorrent Open Source License
  2. # Version 1.0 (the License).  You may not copy or use this file, in either
  3. # source code or executable form, except in compliance with the License.  You
  4. # may obtain a copy of the License at http://www.bittorrent.com/license/.
  5. #
  6. # Software distributed under the License is distributed on an AS IS basis,
  7. # WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the License
  8. # for the specific language governing rights and limitations under the
  9. # License.
  10.  
  11. # Written by Bram Cohen
  12.  
  13. import re
  14.  
  15. from BitTorrent import BTFailure
  16.  
  17. allowed_path_re = re.compile(r'^[^/\\.~][^/\\]*$')
  18.  
  19. ints = (long, int)
  20.  
  21. def check_info(info, check_paths=True):
  22.     if type(info) != dict:
  23.         raise BTFailure, 'bad metainfo - not a dictionary'
  24.     pieces = info.get('pieces')
  25.     if type(pieces) != str or len(pieces) % 20 != 0:
  26.         raise BTFailure, 'bad metainfo - bad pieces key'
  27.     piecelength = info.get('piece length')
  28.     if type(piecelength) not in ints or piecelength <= 0:
  29.         raise BTFailure, 'bad metainfo - illegal piece length'
  30.     name = info.get('name')
  31.     if type(name) != str:
  32.         raise BTFailure, 'bad metainfo - bad name'
  33.     if not allowed_path_re.match(name):
  34.         raise BTFailure, 'name %s disallowed for security reasons' % name
  35.     if info.has_key('files') == info.has_key('length'):
  36.         raise BTFailure, 'single/multiple file mix'
  37.     if info.has_key('length'):
  38.         length = info.get('length')
  39.         if type(length) not in ints or length < 0:
  40.             raise BTFailure, 'bad metainfo - bad length'
  41.     else:
  42.         files = info.get('files')
  43.         if type(files) != list:
  44.             raise BTFailure, 'bad metainfo - "files" is not a list of files'
  45.         for f in files:
  46.             if type(f) != dict:
  47.                 raise BTFailure, 'bad metainfo - bad file value'
  48.             length = f.get('length')
  49.             if type(length) not in ints or length < 0:
  50.                 raise BTFailure, 'bad metainfo - bad length'
  51.             path = f.get('path')
  52.             if type(path) != list or path == []:
  53.                 raise BTFailure, 'bad metainfo - bad path'
  54.             for p in path:
  55.                 if type(p) != str:
  56.                     raise BTFailure, 'bad metainfo - bad path dir'
  57.                 if check_paths and not allowed_path_re.match(p):
  58.                     raise BTFailure, 'path %s disallowed for security reasons' % p
  59.         f = ['/'.join(x['path']) for x in files]
  60.         f.sort()
  61.         i = iter(f)
  62.         try:
  63.             name2 = i.next()
  64.             while True:
  65.                 name1 = name2
  66.                 name2 = i.next()
  67.                 if name2.startswith(name1):
  68.                     if name1 == name2:
  69.                         raise BTFailure, 'bad metainfo - duplicate path'
  70.                     elif name2[len(name1)] == '/':
  71.                         raise BTFailure('bad metainfo - name used as both '
  72.                                         'file and subdirectory name')
  73.         except StopIteration:
  74.             pass
  75.  
  76. def check_message(message, check_paths=True):
  77.     if type(message) != dict:
  78.         raise BTFailure, 'bad metainfo - wrong object type'
  79.     check_info(message.get('info'), check_paths)
  80.     if type(message.get('announce')) != str:
  81.         raise BTFailure, 'bad metainfo - no announce URL string'
  82.  
  83. def check_peers(message):
  84.     if type(message) != dict:
  85.         raise BTFailure
  86.     if message.has_key('failure reason'):
  87.         if type(message['failure reason']) != str:
  88.             raise BTFailure, 'non-text failure reason'
  89.         return
  90.     if message.has_key('warning message'):
  91.         if type(message['warning message']) != str:
  92.             raise BTFailure, 'non-text warning message'
  93.     peers = message.get('peers')
  94.     if type(peers) == list:
  95.         for p in peers:
  96.             if type(p) != dict:
  97.                 raise BTFailure, 'invalid entry in peer list'
  98.             if type(p.get('ip')) != str:
  99.                 raise BTFailure, 'invalid entry in peer list'
  100.             port = p.get('port')
  101.             if type(port) not in ints or p <= 0:
  102.                 raise BTFailure, 'invalid entry in peer list'
  103.             if p.has_key('peer id'):
  104.                 peerid = p.get('peer id')
  105.                 if type(peerid) != str or len(peerid) != 20:
  106.                     raise BTFailure, 'invalid entry in peer list'
  107.     elif type(peers) != str or len(peers) % 6 != 0:
  108.         raise BTFailure, 'invalid peer list'
  109.     interval = message.get('interval', 1)
  110.     if type(interval) not in ints or interval <= 0:
  111.         raise BTFailure, 'invalid announce interval'
  112.     minint = message.get('min interval', 1)
  113.     if type(minint) not in ints or minint <= 0:
  114.         raise BTFailure, 'invalid min announce interval'
  115.     if type(message.get('tracker id', '')) != str:
  116.         raise BTFailure, 'invalid tracker id'
  117.     npeers = message.get('num peers', 0)
  118.     if type(npeers) not in ints or npeers < 0:
  119.         raise BTFailure, 'invalid peer count'
  120.     dpeers = message.get('done peers', 0)
  121.     if type(dpeers) not in ints or dpeers < 0:
  122.         raise BTFailure, 'invalid seed count'
  123.     last = message.get('last', 0)
  124.     if type(last) not in ints or last < 0:
  125.         raise BTFailure, 'invalid "last" entry'
  126.